summaryrefslogtreecommitdiffstats
path: root/hw/scsi-disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/scsi-disk.c')
-rw-r--r--hw/scsi-disk.c69
1 files changed, 23 insertions, 46 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 38ebe04..e266d6f 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),
OpenPOWER on IntegriCloud