qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 4/4] megasas: Add SCSI command emulation


From: Hannes Reinecke
Subject: [Qemu-devel] [PATCH 4/4] megasas: Add SCSI command emulation
Date: Tue, 27 Oct 2009 16:29:07 +0100
User-agent: Heirloom mailx 12.2 01/07/07

Now that we can use SCSI command emulation without using the SCSI
disk abstraction we can easily add it to the megasas HBA.

Signed-off-by: Hannes Reinecke <address@hidden>
---
 hw/megasas.c |   88 +++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/hw/megasas.c b/hw/megasas.c
index a57e8e0..f32b313 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -661,40 +661,55 @@ static int megasas_handle_scsi(MPTState *s, uint8_t fcmd,
     }
     }
 
-    memset(&cmd->hdr, 0, sizeof(struct sg_io_hdr));
-    cmd->hdr.interface_id = 'S';
-    cmd->hdr.cmd_len = cdb_len;
-    cmd->hdr.cmdp = cdb;
-    cmd->hdr.iovec_count = cmd->sge_count;
-    cmd->hdr.dxferp = cmd->iov;
-    for (n = 0; n < cmd->sge_count; n++)
-       cmd->hdr.dxfer_len += cmd->iov[n].iov_len;
-    if (cmd->sge_count) {
-       if (dir)
-           cmd->hdr.dxfer_direction = SG_DXFER_TO_DEV;
-       else
-           cmd->hdr.dxfer_direction = SG_DXFER_FROM_DEV;
-    } else {
-       cmd->hdr.dxfer_direction = SG_DXFER_NONE;
-    }
-    cmd->hdr.sbp = cmd->sense;
-    cmd->hdr.mx_sb_len = cmd->sense_len;
+    if (bdrv_is_sg(cmd->lun->bdrv)) {
+       memset(&cmd->hdr, 0, sizeof(struct sg_io_hdr));
+       cmd->hdr.interface_id = 'S';
+       cmd->hdr.cmd_len = cdb_len;
+       cmd->hdr.cmdp = cdb;
+       cmd->hdr.iovec_count = cmd->sge_count;
+       cmd->hdr.dxferp = cmd->iov;
+       for (n = 0; n < cmd->sge_count; n++)
+           cmd->hdr.dxfer_len += cmd->iov[n].iov_len;
+       if (cmd->sge_count) {
+           if (dir)
+               cmd->hdr.dxfer_direction = SG_DXFER_TO_DEV;
+           else
+               cmd->hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+       } else {
+           cmd->hdr.dxfer_direction = SG_DXFER_NONE;
+       }
+       cmd->hdr.sbp = cmd->sense;
+       cmd->hdr.mx_sb_len = cmd->sense_len;
 
-    ret = bdrv_ioctl(cmd->lun->bdrv, SG_IO, &cmd->hdr);
-    if (ret) {
-       DPRINTF("SCSI pthru dev %x lun %x failed with %d\n",
-               target, lun, errno);
-       sense_len = scsi_build_sense(cmd->sense, SENSE_IO_ERROR);
-       cmd->sge_size = 0;
-       scsi_status = SAM_STAT_CHECK_CONDITION;
-    } else if (cmd->hdr.status) {
-       sense_len = cmd->hdr.sb_len_wr;
-       scsi_status = cmd->hdr.status;
-       cmd->sge_size = cmd->hdr.dxfer_len;
-       scsi_status = SAM_STAT_CHECK_CONDITION;
+       ret = bdrv_ioctl(cmd->lun->bdrv, SG_IO, &cmd->hdr);
+       if (ret) {
+           DPRINTF("SCSI pthru dev %x lun %x failed with %d\n",
+                   target, lun, errno);
+           sense_len = scsi_build_sense(cmd->sense, SENSE_IO_ERROR);
+           cmd->sge_size = 0;
+           scsi_status = SAM_STAT_CHECK_CONDITION;
+       } else if (cmd->hdr.status) {
+           sense_len = cmd->hdr.sb_len_wr;
+           scsi_status = cmd->hdr.status;
+           cmd->sge_size = cmd->hdr.dxfer_len;
+           scsi_status = SAM_STAT_CHECK_CONDITION;
+       } else {
+           sense_len = 0;
+           cmd->sge_size = cmd->hdr.dxfer_len;
+       }
     } else {
-       sense_len = 0;
-       cmd->sge_size = cmd->hdr.dxfer_len;
+       uint32_t sense;
+
+       DPRINTF("Emulate SCSI pthru cmd %x\n", cdb[0]);
+       sense = scsi_emulate_command(cmd->lun->bdrv, 0, cdb,
+                                    cmd->iov[0].iov_len,
+                                    cmd->iov[0].iov_base,
+                                    &cmd->sge_size);
+       sense_len = scsi_build_sense(cmd->sense, sense);
+       if (sense_len)
+           scsi_status = SAM_STAT_CHECK_CONDITION;
+       else
+           scsi_status = SAM_STAT_GOOD;
     }
 out:
     megasas_unmap_sense(cmd, sense_len);
@@ -1105,13 +1120,16 @@ static int megasas_scsi_init(PCIDevice *dev)
            lun->bdrv = NULL;
            continue;
        }
+       bdrv_set_tcq(lun->bdrv, 1);
        /* check if we can use SG_IO */
        ret = bdrv_ioctl(lun->bdrv, SG_IO, &hdr);
        if (ret) {
-           DPRINTF("SCSI cmd passthrough not available on dev %d (error %d)\n",
+           DPRINTF("Using SCSI cmd emulation on dev %d (error %d)\n",
                    unit, ret);
-           lun->sdev = NULL;
-           lun->bdrv = NULL;
+           bdrv_set_sg(lun->bdrv, 0);
+       } else {
+           DPRINTF("Using SCSI cmd passthrough on dev %d\n", unit);
+           bdrv_set_sg(lun->bdrv, 1);
        }
     }
     register_savevm("megasas", -1, 0, megasas_scsi_save, megasas_scsi_load, s);
-- 
1.6.0.2





reply via email to

[Prev in Thread] Current Thread [Next in Thread]