mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
scsi: move sense handling to generic code
With this patch, sense data is stored in the generic data structures for SCSI devices and requests. The SCSI layer takes care of storing sense data in the SCSIDevice for the subsequent REQUEST SENSE command. At the same time, get_sense is removed and scsi_req_get_sense can use an entirely generic implementation. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
682a9b213c
commit
b45ef674f4
5 changed files with 111 additions and 112 deletions
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue