Patchwork [RFC,v2,04/13] scsi: let a SCSIDevice have children devices

login
register
mail settings
Submitter Paolo Bonzini
Date June 6, 2011, 4:04 p.m.
Message ID <1307376262-1255-5-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/98954/
State New
Headers show

Comments

Paolo Bonzini - June 6, 2011, 4:04 p.m.
This provides the infrastructure for simple devices to pick LUNs.
Of course, this will not do anything until there is a device that
can report the existence of those LUNs.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c        |    4 +++-
 hw/lsi53c895a.c |    2 +-
 hw/scsi-bus.c   |   15 +++++++++++++++
 hw/scsi.h       |    3 +++
 4 files changed, 22 insertions(+), 2 deletions(-)

Patch

diff --git a/hw/esp.c b/hw/esp.c
index e47dfec..a821a0a 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -239,12 +239,14 @@  static uint32_t get_cmd(ESPState *s, uint8_t *buf)
 
 static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
 {
+    SCSIDevice *dev;
     int32_t datalen;
     int lun;
 
     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
     lun = busid & 7;
-    s->current_req = scsi_req_new(s->current_dev, &s->busdev.qdev, 0, lun);
+    dev = scsi_find_lun(s->current_dev, lun, buf);
+    s->current_req = scsi_req_new(dev, &s->busdev.qdev, 0, lun);
     datalen = scsi_req_enqueue(s->current_req, buf);
     s->ti_size = datalen;
     if (datalen != 0) {
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 96b19f9..a908324 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -780,7 +780,7 @@  static void lsi_do_command(LSIState *s)
     s->command_complete = 0;
 
     id = (s->select_tag >> 8) & 0xf;
-    dev = s->bus.devs[id];
+    dev = scsi_find_lun(s->bus.devs[id], s->current_lun, buf);
     if (!dev) {
         lsi_bad_selection(s, id);
         return;
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 24e91bf..b44f308 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -745,6 +745,21 @@  static char *scsibus_get_fw_dev_path(DeviceState *dev)
     return strdup(path);
 }
 
+/* Simplified walk of the SCSI bus hierarchy, for devices that only support
+   one bus and only flat-space LUNs (typically 3-bit ones!).  */
+SCSIDevice *scsi_find_lun(SCSIDevice *sdev, int lun, uint8_t *cdb)
+{
+    SCSIBus *sbus = sdev->children;
+    if (!sbus ||
+        lun < 0 ||
+        (lun == 0 && cdb[0] == REPORT_LUNS) ||
+        lun >= sbus->ndev || sbus->devs[lun] == NULL) {
+        return sdev;
+    } else {
+        return sbus->devs[lun];
+    }
+}
+
 /* Decode the bus and level parts of a LUN, as defined in the SCSI architecture
    model.  If false is returned, the LUN could not be parsed.  If true
    is return, "*bus" and "*target" identify the next two steps in the
diff --git a/hw/scsi.h b/hw/scsi.h
index fa3ca9b..8d5737b 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -59,6 +59,7 @@  struct SCSIDevice
     uint32_t id;
     BlockConf conf;
     SCSIDeviceInfo *info;
+    SCSIBus *children;
     QTAILQ_HEAD(, SCSIRequest) requests;
     int blocksize;
     int type;
@@ -152,7 +153,9 @@  extern const struct SCSISense sense_code_LUN_FAILURE;
 
 int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
 int scsi_sense_valid(SCSISense sense);
+
 SCSIDevice *scsi_decode_lun(SCSIBus *sbus, uint64_t sam_lun, int *lun);
+SCSIDevice *scsi_find_lun(SCSIDevice *sdev, int lun, uint8_t *cdb);
 
 SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, DeviceState *initiator,
                             uint32_t tag, uint32_t lun);