aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-07-16 10:39:05 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-29 17:36:25 +0200
commitff34c32ccc29fc23c11f0ef6c86257e23f9e3266 (patch)
tree60023eae3693f494576d6d96dd1716d956888926 /hw/scsi
parent769998a1dbf338a0cdeab2acf8ef605bcf635e01 (diff)
scsi-bus: introduce parse_cdb in SCSIDeviceClass and SCSIBusInfo
These callbacks will let devices do their own request parsing, or defer it to the bus. If the bus does not provide an implementation, in turn, fall back to the default parsing routine. Swap the first two arguments to scsi_req_parse, and rename it to scsi_req_parse_cdb, for consistency. Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi')
-rw-r--r--hw/scsi/scsi-bus.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ca4e9f37ee..d97d18a048 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -9,7 +9,7 @@
static char *scsibus_get_dev_path(DeviceState *dev);
static char *scsibus_get_fw_dev_path(DeviceState *dev);
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
+static int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf);
static void scsi_req_dequeue(SCSIRequest *req);
static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
static void scsi_target_free_buf(SCSIRequest *req);
@@ -54,6 +54,20 @@ static void scsi_device_destroy(SCSIDevice *s)
}
}
+int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
+ void *hba_private)
+{
+ SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
+ int rc;
+
+ assert(cmd->len == 0);
+ rc = scsi_req_parse_cdb(dev, cmd, buf);
+ if (bus->info->parse_cdb) {
+ rc = bus->info->parse_cdb(dev, cmd, buf, hba_private);
+ }
+ return rc;
+}
+
static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun,
uint8_t *buf, void *hba_private)
{
@@ -562,6 +576,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
{
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
const SCSIReqOps *ops;
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(d);
SCSIRequest *req;
SCSICommand cmd = { .len = 0 };
int ret;
@@ -587,7 +602,12 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
ops = NULL;
}
- ret = scsi_req_parse(&cmd, d, buf);
+ if (ops != NULL || !sc->parse_cdb) {
+ ret = scsi_req_parse_cdb(d, &cmd, buf);
+ } else {
+ ret = sc->parse_cdb(d, &cmd, buf, hba_private);
+ }
+
if (ret != 0) {
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
@@ -1190,7 +1210,7 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
return lba;
}
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
+static int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
{
int rc;