diff options
Diffstat (limited to 'hw/scsi-disk.c')
-rw-r--r-- | hw/scsi-disk.c | 69 |
1 files changed, 23 insertions, 46 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 38ebe042cb..e266d6fe9a 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -71,7 +71,6 @@ struct SCSIDiskState QEMUBH *bh; char *version; char *serial; - SCSISense sense; }; static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); @@ -97,20 +96,13 @@ static void scsi_free_request(SCSIRequest *req) qemu_vfree(r->iov.iov_base); } -static void scsi_disk_clear_sense(SCSIDiskState *s) +/* Helper function for command completion with sense. */ +static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense) { - memset(&s->sense, 0, sizeof(s->sense)); -} - -/* Helper function for command completion. */ -static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense) -{ - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n", r->req.tag, status, sense.key, sense.asc, sense.ascq); - s->sense = sense; - scsi_req_complete(&r->req, status); + scsi_req_build_sense(&r->req, sense); + scsi_req_complete(&r->req, CHECK_CONDITION); } /* Cancel a pending data transfer. */ @@ -162,7 +154,8 @@ static void scsi_read_data(SCSIRequest *req) } DPRINTF("Read sector_count=%d\n", r->sector_count); if (r->sector_count == 0) { - scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE)); + /* This also clears the sense buffer for REQUEST SENSE. */ + scsi_req_complete(&r->req, GOOD); return; } @@ -210,16 +203,13 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type) } else { switch (error) { case ENOMEM: - scsi_command_complete(r, CHECK_CONDITION, - SENSE_CODE(TARGET_FAILURE)); + scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE)); break; case EINVAL: - scsi_command_complete(r, CHECK_CONDITION, - SENSE_CODE(INVALID_FIELD)); + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); break; default: - scsi_command_complete(r, CHECK_CONDITION, - SENSE_CODE(IO_ERROR)); + scsi_check_condition(r, SENSE_CODE(IO_ERROR)); break; } bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); @@ -245,7 +235,7 @@ static void scsi_write_complete(void * opaque, int ret) r->sector += n; r->sector_count -= n; if (r->sector_count == 0) { - scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE)); + scsi_req_complete(&r->req, GOOD); } else { len = r->sector_count * 512; if (len > SCSI_DMA_BUF_SIZE) { @@ -314,7 +304,7 @@ static void scsi_dma_restart_bh(void *opaque) case SCSI_REQ_STATUS_RETRY_FLUSH: ret = scsi_disk_emulate_command(r, r->iov.iov_base); if (ret == 0) { - scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE)); + scsi_req_complete(&r->req, GOOD); } } } @@ -342,14 +332,6 @@ static uint8_t *scsi_get_buf(SCSIRequest *req) return (uint8_t *)r->iov.iov_base; } -/* Copy sense information into the provided buffer */ -static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len) -{ - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); - - return scsi_build_sense(s->sense, outbuf, len, len > 14); -} - static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); @@ -827,9 +809,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) case REQUEST_SENSE: if (req->cmd.xfer < 4) goto illegal_request; - buflen = scsi_build_sense(s->sense, outbuf, req->cmd.xfer, - req->cmd.xfer > 13); - scsi_disk_clear_sense(s); + buflen = scsi_device_get_sense(&s->qdev, outbuf, req->cmd.xfer, + (req->cmd.buf[1] & 1) == 0); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -960,21 +941,21 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) case VERIFY_10: break; default: - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE)); + scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); return -1; } return buflen; not_ready: if (!bdrv_is_inserted(s->bs)) { - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(NO_MEDIUM)); + scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); } else { - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LUN_NOT_READY)); + scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); } return -1; illegal_request: - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD)); + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); return -1; } @@ -998,7 +979,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) if (scsi_req_parse(&r->req, buf) != 0) { BADF("Unsupported command length, command %x\n", command); - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE)); + scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); return 0; } #ifdef DEBUG_SCSI @@ -1015,8 +996,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) /* Only LUN 0 supported. */ DPRINTF("Unimplemented LUN %d\n", req->lun); if (command != REQUEST_SENSE && command != INQUIRY) { - scsi_command_complete(r, CHECK_CONDITION, - SENSE_CODE(LUN_NOT_SUPPORTED)); + scsi_check_condition(r, SENSE_CODE(LUN_NOT_SUPPORTED)); return 0; } } @@ -1124,17 +1104,17 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) break; default: DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE)); + scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); return 0; fail: - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD)); + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); return 0; illegal_lba: - scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LBA_OUT_OF_RANGE)); + scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE)); return 0; } if (r->sector_count == 0 && r->iov.iov_len == 0) { - scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE)); + scsi_req_complete(&r->req, GOOD); } len = r->sector_count * 512 + r->iov.iov_len; if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { @@ -1266,7 +1246,6 @@ static SCSIDeviceInfo scsi_disk_info[] = { .write_data = scsi_write_data, .cancel_io = scsi_cancel_io, .get_buf = scsi_get_buf, - .get_sense = scsi_get_sense, .qdev.props = (Property[]) { DEFINE_SCSI_DISK_PROPERTIES(), DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), @@ -1287,7 +1266,6 @@ static SCSIDeviceInfo scsi_disk_info[] = { .write_data = scsi_write_data, .cancel_io = scsi_cancel_io, .get_buf = scsi_get_buf, - .get_sense = scsi_get_sense, .qdev.props = (Property[]) { DEFINE_SCSI_DISK_PROPERTIES(), DEFINE_PROP_END_OF_LIST(), @@ -1307,7 +1285,6 @@ static SCSIDeviceInfo scsi_disk_info[] = { .write_data = scsi_write_data, .cancel_io = scsi_cancel_io, .get_buf = scsi_get_buf, - .get_sense = scsi_get_sense, .qdev.props = (Property[]) { DEFINE_SCSI_DISK_PROPERTIES(), DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), |