diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2011-08-03 10:49:07 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-08-12 08:27:30 -0500 |
commit | b45ef674f4c403398e75c6be02e27a0bfa813a11 (patch) | |
tree | 5cf3db12f4e69af96866f4b31ea4ff1bb09239b3 /hw/scsi-generic.c | |
parent | 682a9b213ca3c47c4de5b0518c59c2e550299106 (diff) |
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>
Diffstat (limited to 'hw/scsi-generic.c')
-rw-r--r-- | hw/scsi-generic.c | 76 |
1 files changed, 17 insertions, 59 deletions
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 71cbfb0a44..37c598271a 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -61,41 +61,8 @@ struct SCSIGenericState SCSIDevice qdev; BlockDriverState *bs; int lun; - int driver_status; - uint8_t sensebuf[SCSI_SENSE_BUF_SIZE]; - uint8_t senselen; }; -static void scsi_set_sense(SCSIGenericState *s, SCSISense sense) -{ - s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0); - s->driver_status = SG_ERR_DRIVER_SENSE; -} - -static void scsi_clear_sense(SCSIGenericState *s) -{ - memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE); - s->senselen = 0; - s->driver_status = 0; -} - -static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len) -{ - SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev); - int size = SCSI_SENSE_BUF_SIZE; - - if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) { - size = scsi_build_sense(SENSE_CODE(NO_SENSE), s->sensebuf, - SCSI_SENSE_BUF_SIZE, 0); - } - if (size > len) { - size = len; - } - memcpy(outbuf, s->sensebuf, size); - - return size; -} - static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, void *hba_private) { @@ -117,12 +84,10 @@ static void scsi_command_complete(void *opaque, int ret) { int status; SCSIGenericReq *r = (SCSIGenericReq *)opaque; - SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev); r->req.aiocb = NULL; - s->driver_status = r->io_header.driver_status; - if (s->driver_status & SG_ERR_DRIVER_SENSE) - s->senselen = r->io_header.sb_len_wr; + if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) + r->req.sense_len = r->io_header.sb_len_wr; if (ret != 0) { switch (ret) { @@ -131,24 +96,24 @@ static void scsi_command_complete(void *opaque, int ret) break; case -EINVAL: status = CHECK_CONDITION; - scsi_set_sense(s, SENSE_CODE(INVALID_FIELD)); + scsi_req_build_sense(&r->req, SENSE_CODE(INVALID_FIELD)); break; case -ENOMEM: status = CHECK_CONDITION; - scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE)); + scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE)); break; default: status = CHECK_CONDITION; - scsi_set_sense(s, SENSE_CODE(IO_ERROR)); + scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR)); break; } } else { - if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) { + if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) { status = BUSY; BADF("Driver Timeout\n"); } else if (r->io_header.status) { status = r->io_header.status; - } else if (s->driver_status & SG_ERR_DRIVER_SENSE) { + } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) { status = CHECK_CONDITION; } else { status = GOOD; @@ -176,16 +141,14 @@ static int execute_command(BlockDriverState *bdrv, SCSIGenericReq *r, int direction, BlockDriverCompletionFunc *complete) { - SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev); - r->io_header.interface_id = 'S'; r->io_header.dxfer_direction = direction; r->io_header.dxferp = r->buf; r->io_header.dxfer_len = r->buflen; r->io_header.cmdp = r->req.cmd.buf; r->io_header.cmd_len = r->req.cmd.len; - r->io_header.mx_sb_len = sizeof(s->sensebuf); - r->io_header.sbp = s->sensebuf; + r->io_header.mx_sb_len = sizeof(r->req.sense); + r->io_header.sbp = r->req.sense; r->io_header.timeout = MAX_UINT; r->io_header.usr_ptr = r; r->io_header.flags |= SG_FLAG_DIRECT_IO; @@ -234,21 +197,19 @@ static void scsi_read_data(SCSIRequest *req) return; } - if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE) - { - s->senselen = MIN(r->len, s->senselen); - memcpy(r->buf, s->sensebuf, s->senselen); + if (r->req.cmd.buf[0] == REQUEST_SENSE) { r->io_header.driver_status = 0; r->io_header.status = 0; - r->io_header.dxfer_len = s->senselen; + r->io_header.dxfer_len = + scsi_device_get_sense(&s->qdev, r->buf, r->req.cmd.xfer, + (r->req.cmd.buf[1] & 1) == 0); r->len = -1; - DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen); + DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, r->io_header.dxfer_len); DPRINTF("Sense: %d %d %d %d %d %d %d %d\n", r->buf[0], r->buf[1], r->buf[2], r->buf[3], r->buf[4], r->buf[5], r->buf[6], r->buf[7]); - scsi_req_data(&r->req, s->senselen); - /* Clear sensebuf after REQUEST_SENSE */ - scsi_clear_sense(s); + scsi_req_data(&r->req, r->io_header.dxfer_len); + /* The sense buffer is cleared when we return GOOD */ return; } @@ -342,7 +303,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) { DPRINTF("Unimplemented LUN %d\n", req->lun); - scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED)); + scsi_req_build_sense(&r->req, SENSE_CODE(LUN_NOT_SUPPORTED)); scsi_req_complete(&r->req, CHECK_CONDITION); return 0; } @@ -533,8 +494,6 @@ static int scsi_generic_initfn(SCSIDevice *dev) } } DPRINTF("block size %d\n", s->qdev.blocksize); - s->driver_status = 0; - memset(s->sensebuf, 0, sizeof(s->sensebuf)); bdrv_set_removable(s->bs, 0); return 0; } @@ -553,7 +512,6 @@ static SCSIDeviceInfo scsi_generic_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_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf), DEFINE_PROP_END_OF_LIST(), |