Don't fail when tray is already open. Signed-off-by: Markus Armbruster <arm...@redhat.com> --- hw/scsi-bus.c | 10 ++++++++++ hw/scsi-disk.c | 15 +++++++++++---- hw/scsi.h | 4 ++++ 3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index ad6a730..169a022 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -440,6 +440,11 @@ const struct SCSISense sense_code_NO_MEDIUM = { .key = NOT_READY, .asc = 0x3a, .ascq = 0x00 }; +/* LUN not ready, medium removal prevented */ +const struct SCSISense sense_code_MEDIUM_REMOVAL_PREVENTED_NR = { + .key = NOT_READY, .asc = 0x53, .ascq = 0x00 +}; + /* Hardware error, internal target failure */ const struct SCSISense sense_code_TARGET_FAILURE = { .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00 @@ -465,6 +470,11 @@ const struct SCSISense sense_code_LUN_NOT_SUPPORTED = { .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00 }; +/* Illegal request, medium removal prevented */ +const struct SCSISense sense_code_MEDIUM_REMOVAL_PREVENTED_ILL = { + .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x00 +}; + /* Command aborted, I/O process terminated */ const struct SCSISense sense_code_IO_ERROR = { .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 97f6d41..b9de4df 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -825,7 +825,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf) return toclen; } -static void scsi_disk_emulate_start_stop(SCSIDiskReq *r) +static int scsi_disk_emulate_start_stop(SCSIDiskReq *r) { SCSIRequest *req = &r->req; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); @@ -833,12 +833,17 @@ static void scsi_disk_emulate_start_stop(SCSIDiskReq *r) bool loej = req->cmd.buf[4] & 2; if (s->drive_kind == SCSI_CD && loej) { - if (!start && s->tray_locked) { - return; + if (!start && !s->tray_open && s->tray_locked) { + scsi_command_complete(r, CHECK_CONDITION, + bdrv_is_inserted(s->bs) + ? SENSE_CODE(MEDIUM_REMOVAL_PREVENTED_ILL) + : SENSE_CODE(MEDIUM_REMOVAL_PREVENTED_NR)); + return -1; } bdrv_eject(s->bs, !start); s->tray_open = !start; } + return 0; } static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) @@ -894,7 +899,9 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) goto illegal_request; break; case START_STOP: - scsi_disk_emulate_start_stop(r); + if (scsi_disk_emulate_start_stop(r) < 0) { + return -1; + } break; case ALLOW_MEDIUM_REMOVAL: s->tray_locked = req->cmd.buf[4] & 1; diff --git a/hw/scsi.h b/hw/scsi.h index c1dca35..f6b6bc1 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -116,6 +116,8 @@ extern const struct SCSISense sense_code_NO_SENSE; extern const struct SCSISense sense_code_LUN_NOT_READY; /* LUN not ready, Medium not present */ extern const struct SCSISense sense_code_NO_MEDIUM; +/* LUN not readt, medium removal prevented */ +extern const struct SCSISense sense_code_MEDIUM_REMOVAL_PREVENTED_NR; /* Hardware error, internal target failure */ extern const struct SCSISense sense_code_TARGET_FAILURE; /* Illegal request, invalid command operation code */ @@ -126,6 +128,8 @@ extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE; extern const struct SCSISense sense_code_INVALID_FIELD; /* Illegal request, LUN not supported */ extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED; +/* Illegal request, medium removal prevented */ +extern const struct SCSISense sense_code_MEDIUM_REMOVAL_PREVENTED_ILL; /* Command aborted, I/O process terminated */ extern const struct SCSISense sense_code_IO_ERROR; /* Command aborted, I_T Nexus loss occurred */ -- 1.7.2.3