aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-07-16 11:04:37 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-29 17:36:38 +0200
commit33cbb2c546594685131e771e2e0972418b9d0301 (patch)
treeb3469354072b13c584bfc2cba81303425cab0b47
parent3e7e180ab3f970a4e5b64b5fafd57c48c98ee560 (diff)
virtio-scsi: implement parse_cdb
Enable passthrough of vendor-specific commands. Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--hw/scsi/virtio-scsi.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 0eb069ae9b..2dd92552e0 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -406,6 +406,30 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
virtio_scsi_complete_cmd_req(req);
}
+static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
+ uint8_t *buf, void *hba_private)
+{
+ VirtIOSCSIReq *req = hba_private;
+
+ if (cmd->len == 0) {
+ cmd->len = MIN(VIRTIO_SCSI_CDB_SIZE, SCSI_CMD_BUF_SIZE);
+ memcpy(cmd->buf, buf, cmd->len);
+ }
+
+ /* Extract the direction and mode directly from the request, for
+ * host device passthrough.
+ */
+ cmd->xfer = req->qsgl.size;
+ if (cmd->xfer == 0) {
+ cmd->mode = SCSI_XFER_NONE;
+ } else if (iov_size(req->elem.in_sg, req->elem.in_num) > req->resp_size) {
+ cmd->mode = SCSI_XFER_FROM_DEV;
+ } else {
+ cmd->mode = SCSI_XFER_TO_DEV;
+ }
+ return 0;
+}
+
static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
{
VirtIOSCSIReq *req = r->hba_private;
@@ -658,6 +682,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
.change = virtio_scsi_change,
.hotplug = virtio_scsi_hotplug,
.hot_unplug = virtio_scsi_hot_unplug,
+ .parse_cdb = virtio_scsi_parse_cdb,
.get_sg_list = virtio_scsi_get_sg_list,
.save_request = virtio_scsi_save_request,
.load_request = virtio_scsi_load_request,