Patchwork [1/4] Add 'raid' interface class

login
register
mail settings
Submitter Hannes Reinecke
Date Oct. 27, 2009, 3:28 p.m.
Message ID <20091027152842.001C33967A@ochil.suse.de>
Download mbox | patch
Permalink /patch/36998/
State New
Headers show

Comments

Hannes Reinecke - Oct. 27, 2009, 3:28 p.m.
This patch adds a 'raid' interface class. It is basically a clone
of the existing 'scsi' interface, only allowing up to 128 disks.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/pc.c          |    5 +++++
 hw/pci-hotplug.c |    1 +
 hw/scsi-disk.c   |   17 +++++++++++++++++
 hw/scsi-disk.h   |   20 +++++++++++++++++++-
 qemu-config.c    |    2 +-
 sysemu.h         |    3 ++-
 vl.c             |    8 ++++++--
 7 files changed, 51 insertions(+), 5 deletions(-)

Patch

diff --git a/hw/pc.c b/hw/pc.c
index 83012a9..26aad4c 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1345,6 +1345,11 @@  static void pc_init1(ram_addr_t ram_size,
 	for (bus = 0; bus <= max_bus; bus++) {
             pci_create_simple(pci_bus, -1, "lsi53c895a");
         }
+
+	max_bus = drive_get_max_bus(IF_RAID);
+	for (bus = 0; bus <= max_bus; bus++) {
+	    pci_create_simple(pci_bus, -1, "megasas");
+	}
     }
 
     if (extboot_drive) {
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 410fa3f..855a1ad 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -85,6 +85,7 @@  void drive_hot_add(Monitor *mon, const QDict *qdict)
 
     switch (type) {
     case IF_SCSI:
+    case IF_RAID:
         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
         }
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2a9268a..68b4e83 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -41,6 +41,7 @@  do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 
 #define SCSI_DMA_BUF_SIZE    131072
 #define SCSI_MAX_INQUIRY_LEN 256
+#define SCSI_SENSE_LEN 18
 
 #define SCSI_REQ_STATUS_RETRY 0x01
 
@@ -136,6 +137,22 @@  static SCSIRequest *scsi_find_request(SCSIDiskState *s, uint32_t tag)
     return r;
 }
 
+/* Helper function to build a sense block */
+int32_t scsi_build_sense(uint8_t *sense_buf, uint32_t sense)
+{
+    memset(sense_buf, 0, SCSI_SENSE_LEN);
+    if (!sense)
+       return 0;
+
+    sense_buf[0] = 0xf0; /* current, fixed format */
+    sense_buf[2] = (sense >> 16) & 0x0F;
+    sense_buf[7] = 10;
+    sense_buf[12] = (sense >> 8 ) & 0xFF;
+    sense_buf[13] = sense & 0xFF;
+
+    return SCSI_SENSE_LEN;
+}
+
 /* Helper function for command completion.  */
 static void scsi_command_complete(SCSIRequest *r, int status, int sense)
 {
diff --git a/hw/scsi-disk.h b/hw/scsi-disk.h
index b6b6c12..5b54272 100644
--- a/hw/scsi-disk.h
+++ b/hw/scsi-disk.h
@@ -9,6 +9,23 @@  enum scsi_reason {
     SCSI_REASON_DATA  /* Transfer complete, more data required.  */
 };
 
+/* LUN not ready, Manual intervention required */
+#define SENSE_LUN_NOT_READY 0x020403
+/* Hardware error, I/O process terminated */
+#define SENSE_IO_ERROR 0x040006
+/* Hardware error, I_T Nexus loss occured */
+#define SENSE_TAG_NOT_FOUND 0x042907
+/* Hardware error, internal target failure */
+#define SENSE_TARGET_FAILURE 0x044400
+/* Illegal request, invalid command operation code */
+#define SENSE_INVALID_OPCODE 0x052000
+/* Illegal request, LBA out of range */
+#define SENSE_LBA_OUT_OF_RANGE 0x052100
+/* Illegal request, Invalid field in CDB */
+#define SENSE_INVALID_FIELD 0x052400
+/* Illegal request, LUN not supported */
+#define SENSE_LUN_NOT_SUPPORTED 0x052500
+
 typedef struct SCSIBus SCSIBus;
 typedef struct SCSIDevice SCSIDevice;
 typedef struct SCSIDeviceInfo SCSIDeviceInfo;
@@ -49,7 +66,7 @@  struct SCSIBus {
     int tcq, ndev;
     scsi_completionfn complete;
 
-    SCSIDevice *devs[8];
+    SCSIDevice *devs[128];
 };
 
 void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
@@ -63,5 +80,6 @@  static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit);
 void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
+int32_t scsi_build_sense(uint8_t *sense_buf, uint32_t sense);
 
 #endif
diff --git a/qemu-config.c b/qemu-config.c
index 4fb7898..8d7a137 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -18,7 +18,7 @@  QemuOptsList qemu_drive_opts = {
         },{
             .name = "if",
             .type = QEMU_OPT_STRING,
-            .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
+            .help = "interface (ide, scsi, raid, sd, mtd, floppy, pflash, virtio)",
         },{
             .name = "index",
             .type = QEMU_OPT_NUMBER,
diff --git a/sysemu.h b/sysemu.h
index 2ef3797..8ed0b8c 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -159,7 +159,7 @@  extern unsigned int nb_prom_envs;
 
 typedef enum {
     IF_NONE,
-    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+    IF_IDE, IF_SCSI, IF_RAID, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
     IF_COUNT
 } BlockInterfaceType;
 
@@ -185,6 +185,7 @@  typedef struct DriveInfo {
 
 #define MAX_IDE_DEVS	2
 #define MAX_SCSI_DEVS	7
+#define MAX_RAID_DEVS	128
 #define MAX_DRIVES 32
 
 extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
diff --git a/vl.c b/vl.c
index 5dc7b2b..404afc3 100644
--- a/vl.c
+++ b/vl.c
@@ -2065,6 +2065,9 @@  DriveInfo *drive_init(QemuOpts *opts, void *opaque,
         } else if (!strcmp(buf, "scsi")) {
 	    type = IF_SCSI;
             max_devs = MAX_SCSI_DEVS;
+        } else if (!strcmp(buf, "raid")) {
+	    type = IF_RAID;
+            max_devs = MAX_RAID_DEVS;
         } else if (!strcmp(buf, "floppy")) {
 	    type = IF_FLOPPY;
             max_devs = 0;
@@ -2190,7 +2193,7 @@  DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
     onerror = BLOCK_ERR_STOP_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
-        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
+        if (type != IF_IDE && type != IF_SCSI && type != IF_RAID && type != IF_VIRTIO) {
             fprintf(stderr, "werror is no supported by this format\n");
             return NULL;
         }
@@ -2273,7 +2276,7 @@  DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     } else {
         /* no id supplied -> create one */
         dinfo->id = qemu_mallocz(32);
-        if (type == IF_IDE || type == IF_SCSI)
+        if (type == IF_IDE || type == IF_SCSI || type == IF_RAID)
             mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
         if (max_devs)
             snprintf(dinfo->id, 32, "%s%i%s%i",
@@ -2299,6 +2302,7 @@  DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     switch(type) {
     case IF_IDE:
     case IF_SCSI:
+    case IF_RAID:
     case IF_XEN:
     case IF_NONE:
         switch(media) {