nscsi/cd.cpp: Fixed no-disc status for Apple CD drive and implemented eject command. [R. Belmont]

- Dragging a CD into the Trash on MacOS now properly unloads it.
This commit is contained in:
arbee 2024-07-06 09:51:22 -04:00
parent 574e71a61b
commit 152ebf3ade
2 changed files with 42 additions and 10 deletions

View File

@ -83,6 +83,7 @@ nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, device_typ
: nscsi_full_device(mconfig, type, tag, owner, clock)
, image(*this, "image")
, cdda(*this, "cdda")
, m_removal_prevented(false)
, bytes_per_block(bytes_per_sector)
, lba(0)
, cur_sector(0)
@ -549,6 +550,7 @@ void nscsi_cdrom_device::scsi_command()
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
// TODO: support eject prevention
LOG("command %s MEDIUM REMOVAL\n", (scsi_cmdbuf[4] & 0x1) ? "PREVENT" : "ALLOW");
m_removal_prevented = BIT(scsi_cmdbuf[4], 0);
scsi_status_complete(SS_GOOD);
break;
@ -883,11 +885,21 @@ void nscsi_cdrom_apple_device::device_start()
}
/*
The Apple II SCSI Card firmware demands that ASC on a failing TEST_UNIT_READY be either 0x28 or 0xb0.
0x28 is MEDIA_CHANGED, 0xb0 is vendor-specific. If the drive returns the normal 0x3A for disc-not-present,
The Apple II SCSI Card firmware demands that ASC on a failing TEST_UNIT_READY be either 0x28 or 0xB0.
0x28 is MEDIA_CHANGED, 0xB0 is vendor-specific. If the drive returns the normal 0x3A for disc-not-present,
the firmware assumes the drive is broken and retries the TEST_UNIT_READY for 60 seconds before giving up
and booting the machine.
MacOS will see the normal 0x3A disc-not-present and simply disbelieve it and hammer on the drive while
asking the user to format it because it's unreadable. 0xB0 makes it behave as expected.
*/
void nscsi_cdrom_apple_device::return_no_cd()
{
sense(false, SK_NOT_READY, 0xb0);
scsi_status_complete(SS_CHECK_CONDITION);
}
void nscsi_cdrom_apple_device::scsi_command()
{
if (scsi_cmdbuf[0] != 8 && scsi_cmdbuf[0] != 0x28 && scsi_cmdbuf[0] != 0 && scsi_cmdbuf[0] != 0x03)
@ -908,8 +920,7 @@ void nscsi_cdrom_apple_device::scsi_command()
}
else
{
sense(false, SK_NOT_READY, 0xb0);
scsi_status_complete(SS_CHECK_CONDITION);
return_no_cd();
}
break;
@ -1312,15 +1323,33 @@ void nscsi_cdrom_apple_device::scsi_command()
case APPLE_AUDIO_CONTROL:
LOG("command APPLE AUDIO CONTROL, size %d\n", scsi_cmdbuf[8]);
scsi_data_out(3, scsi_cmdbuf[8]);
scsi_status_complete(SS_GOOD);
if (image->exists())
{
scsi_data_out(3, scsi_cmdbuf[8]);
scsi_status_complete(SS_GOOD);
}
else
{
return_no_cd();
}
break;
case APPLE_EJECT:
LOG("command APPLE EJECT\n");
cdda->stop_audio();
m_stopped = true;
scsi_status_complete(SS_GOOD);
if (!m_removal_prevented)
{
cdda->stop_audio();
m_stopped = true;
image->unload();
sense(false, SK_NOT_READY, SK_ASC_MEDIUM_NOT_PRESENT);
scsi_status_complete(SS_GOOD);
}
else
{
LOG("Eject not allowed by PREVENT_ALLOW_MEDIA_REMOVAL\n");
sense(false, SK_ILLEGAL_REQUEST, 0x80); // "Prevent bit is set"
scsi_status_complete(SS_CHECK_CONDITION);
}
break;
case SC_READ_6:

View File

@ -43,9 +43,11 @@ protected:
virtual uint8_t scsi_get_data(int id, int pos) override;
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
void return_no_cd();
virtual void return_no_cd();
static int to_msf(int frame);
bool m_removal_prevented;
private:
static constexpr uint32_t bytes_per_sector = 2048;
@ -133,6 +135,7 @@ protected:
virtual void scsi_command() override;
virtual bool scsi_command_done(uint8_t command, uint8_t length) override;
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
virtual void return_no_cd() override;
private:
bool m_stopped;