summary refs log tree commit diff stats
path: root/hw/ide/atapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ide/atapi.c')
-rw-r--r--hw/ide/atapi.c58
1 files changed, 27 insertions, 31 deletions
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index f38d2896ae..3f909c3a99 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -73,7 +73,7 @@ static void lba_to_msf(uint8_t *buf, int lba)
 
 static inline int media_present(IDEState *s)
 {
-    return (s->nb_sectors > 0);
+    return !s->tray_open && s->nb_sectors > 0;
 }
 
 /* XXX: DVDs that could fit on a CD will be reported as a CD */
@@ -521,7 +521,7 @@ static unsigned int event_status_media(IDEState *s,
     uint8_t event_code, media_status;
 
     media_status = 0;
-    if (s->bs->tray_open) {
+    if (s->tray_open) {
         media_status = MS_TRAY_OPEN;
     } else if (bdrv_is_inserted(s->bs)) {
         media_status = MS_MEDIA_PRESENT;
@@ -788,8 +788,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[12] = 0x71;
             buf[13] = 3 << 5;
             buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
-            if (bdrv_is_locked(s->bs))
+            if (s->tray_locked) {
                 buf[6] |= 1 << 1;
+            }
             buf[15] = 0x00;
             cpu_to_ube16(&buf[16], 706);
             buf[18] = 0;
@@ -831,7 +832,8 @@ static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
 
 static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
 {
-    bdrv_set_locked(s->bs, buf[4] & 1);
+    s->tray_locked = buf[4] & 1;
+    bdrv_lock_medium(s->bs, buf[4] & 1);
     ide_atapi_cmd_ok(s);
 }
 
@@ -903,29 +905,22 @@ static void cmd_seek(IDEState *s, uint8_t* buf)
 
 static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
 {
-    int start, eject, sense, err = 0;
-    start = buf[4] & 1;
-    eject = (buf[4] >> 1) & 1;
-
-    if (eject) {
-        err = bdrv_eject(s->bs, !start);
-    }
-
-    switch (err) {
-    case 0:
-        ide_atapi_cmd_ok(s);
-        break;
-    case -EBUSY:
-        sense = SENSE_NOT_READY;
-        if (bdrv_is_inserted(s->bs)) {
-            sense = SENSE_ILLEGAL_REQUEST;
+    int sense;
+    bool start = buf[4] & 1;
+    bool loej = buf[4] & 2;     /* load on start, eject on !start */
+
+    if (loej) {
+        if (!start && !s->tray_open && s->tray_locked) {
+            sense = bdrv_is_inserted(s->bs)
+                ? SENSE_NOT_READY : SENSE_ILLEGAL_REQUEST;
+            ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
+            return;
         }
-        ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
-        break;
-    default:
-        ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
-        break;
+        bdrv_eject(s->bs, !start);
+        s->tray_open = !start;
     }
+
+    ide_atapi_cmd_ok(s);
 }
 
 static void cmd_mechanism_status(IDEState *s, uint8_t* buf)
@@ -1073,20 +1068,21 @@ static const struct {
     [ 0x03 ] = { cmd_request_sense,                 ALLOW_UA },
     [ 0x12 ] = { cmd_inquiry,                       ALLOW_UA },
     [ 0x1a ] = { cmd_mode_sense, /* (6) */          0 },
-    [ 0x1b ] = { cmd_start_stop_unit,               0 },
+    [ 0x1b ] = { cmd_start_stop_unit,               0 }, /* [1] */
     [ 0x1e ] = { cmd_prevent_allow_medium_removal,  0 },
     [ 0x25 ] = { cmd_read_cdvd_capacity,            CHECK_READY },
-    [ 0x28 ] = { cmd_read, /* (10) */               0 },
+    [ 0x28 ] = { cmd_read, /* (10) */               CHECK_READY },
     [ 0x2b ] = { cmd_seek,                          CHECK_READY },
     [ 0x43 ] = { cmd_read_toc_pma_atip,             CHECK_READY },
     [ 0x46 ] = { cmd_get_configuration,             ALLOW_UA },
     [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA },
     [ 0x5a ] = { cmd_mode_sense, /* (10) */         0 },
-    [ 0xa8 ] = { cmd_read, /* (12) */               0 },
-    [ 0xad ] = { cmd_read_dvd_structure,            0 },
+    [ 0xa8 ] = { cmd_read, /* (12) */               CHECK_READY },
+    [ 0xad ] = { cmd_read_dvd_structure,            CHECK_READY },
     [ 0xbb ] = { cmd_set_speed,                     0 },
     [ 0xbd ] = { cmd_mechanism_status,              0 },
-    [ 0xbe ] = { cmd_read_cd,                       0 },
+    [ 0xbe ] = { cmd_read_cd,                       CHECK_READY },
+    /* [1] handler detects and reports not ready condition itself */
 };
 
 void ide_atapi_cmd(IDEState *s)
@@ -1122,7 +1118,7 @@ void ide_atapi_cmd(IDEState *s)
      * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
      * states rely on this behavior.
      */
-    if (bdrv_is_inserted(s->bs) && s->cdrom_changed) {
+    if (!s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
         ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
 
         s->cdrom_changed = 0;