From a354d9aecc8a622381347c27eb20fa3612967343 Mon Sep 17 00:00:00 2001 From: Benjamin David Lunt <11790532+fysnet@users.noreply.github.com> Date: Tue, 7 Nov 2023 23:16:52 -0700 Subject: [PATCH] fix ISO status change events (#125) This allows you to change the CD-ROM via the Bochs Ribbon, as well as properly "ejecting" a CD from the guest. Before the CD path would change, but the guest (tested with WinXP and DOS as guests) would not see the change. This fix simulates an open tray and then a closed tray for all CD changes. --- bochs/iodev/harddrv.cc | 26 +++++++++++++++++--------- bochs/iodev/harddrv.h | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bochs/iodev/harddrv.cc b/bochs/iodev/harddrv.cc index 395d7ac64..f36bdfe88 100644 --- a/bochs/iodev/harddrv.cc +++ b/bochs/iodev/harddrv.cc @@ -734,7 +734,7 @@ void bx_hard_drive_c::runtime_config(void) for (Bit8u channel=0; channelget_param(pname); @@ -743,7 +743,6 @@ void bx_hard_drive_c::runtime_config(void) if (status == BX_INSERTED) { BX_HD_THIS set_cd_media_status(handle, 1); } - BX_HD_THIS channels[channel].drives[device].status_changed = 0; } } } @@ -1297,10 +1296,21 @@ void bx_hard_drive_c::write(Bit32u address, Bit32u value, unsigned io_len) switch (atapi_command) { case 0x00: // test unit ready - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { - atapi_cmd_nop(controller); - } else { + // For guests that don't use GET_EVENT_STATUS_NOTIFICATION, we actually + // have to simulate a tray open (status_changed == 1) and then a + // try close (status_changed == -1). + if (BX_SELECTED_DRIVE(channel).status_changed == 1) { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + BX_SELECTED_DRIVE(channel).status_changed = -1; + } else if (BX_SELECTED_DRIVE(channel).status_changed == -1) { + atapi_cmd_error(channel, SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 1); + BX_SELECTED_DRIVE(channel).status_changed = 0; + } else { + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { + atapi_cmd_nop(controller); + } else { + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + } } raise_interrupt(channel); break; @@ -1363,6 +1373,8 @@ void bx_hard_drive_c::write(Bit32u address, Bit32u value, unsigned io_len) bx_list_c *base = (bx_list_c*) SIM->get_param(ata_name); SIM->get_param_enum("status", base)->set(BX_EJECTED); bx_gui->update_drive_status_buttons(); + // indicate a status change + BX_SELECTED_DRIVE(channel).status_changed = 1; } raise_interrupt(channel); } else { // Load the disc @@ -3368,10 +3380,6 @@ bool bx_hard_drive_c::set_cd_media_status(Bit32u handle, bool status) BX_HD_THIS channels[channel].drives[device].cdrom.curr_lba = capacity - 1; BX_INFO(("Capacity is %d sectors (%.2f MB)", capacity, (float)capacity / 512.0)); SIM->get_param_enum("status", base)->set(BX_INSERTED); - BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_UNIT_ATTENTION; - BX_SELECTED_DRIVE(channel).sense.asc = ASC_MEDIUM_MAY_HAVE_CHANGED; - BX_SELECTED_DRIVE(channel).sense.ascq = 0; - raise_interrupt(channel); } else { BX_INFO(("Could not locate CD-ROM, continuing with media not present")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; diff --git a/bochs/iodev/harddrv.h b/bochs/iodev/harddrv.h index f61715bb1..135e8a027 100644 --- a/bochs/iodev/harddrv.h +++ b/bochs/iodev/harddrv.h @@ -253,7 +253,7 @@ private: Bit8u model_no[41]; int statusbar_id; Bit8u device_num; // for ATAPI identify & inquiry - bool status_changed; + int status_changed; int seek_timer_index; } drives[2]; unsigned drive_select;