aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi-bus.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-08-31 14:24:04 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-09-09 14:57:19 -0500
commitd52affa7f6b9df3c7d44da0effbdfc8339c43914 (patch)
treef846e1baed7d228519ba95bfd3d915529e7172f9 /hw/scsi-bus.c
parent5b19d9a247c47fe52c4f3d3e844009a689ee6b28 (diff)
qdev/scsi: add scsi bus support to qdev, convert drivers.
* Add SCSIBus. * Add SCSIDeviceInfo, move device callbacks here. * add qdev/scsi helper functions. * convert drivers. Adding scsi disks via -device works now, i.e. you can do: -drive id=sda,if=none,... -device lsi -device scsi-disk,drive=sda legacy command lines (-drive if=scsi,...) continue to work. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/scsi-bus.c')
-rw-r--r--hw/scsi-bus.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
new file mode 100644
index 0000000000..16afa0532a
--- /dev/null
+++ b/hw/scsi-bus.c
@@ -0,0 +1,93 @@
+#include "hw.h"
+#include "sysemu.h"
+#include "scsi-disk.h"
+#include "block.h"
+#include "qdev.h"
+
+static struct BusInfo scsi_bus_info = {
+ .name = "SCSI",
+ .size = sizeof(SCSIBus),
+ .props = (Property[]) {
+ DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+static int next_scsi_bus;
+
+/* Create a scsi bus, and attach devices to it. */
+SCSIBus *scsi_bus_new(DeviceState *host, int tcq, int ndev,
+ scsi_completionfn complete)
+{
+ SCSIBus *bus;
+
+ bus = FROM_QBUS(SCSIBus, qbus_create(&scsi_bus_info, host, NULL));
+ bus->busnr = next_scsi_bus++;
+ bus->tcq = tcq;
+ bus->ndev = ndev;
+ bus->complete = complete;
+ return bus;
+}
+
+static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
+ SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
+
+ if (dev->id == -1) {
+ for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
+ if (bus->devs[dev->id] == NULL)
+ break;
+ }
+ }
+ if (dev->id >= bus->ndev) {
+ qemu_error("bad scsi device id: %d\n", dev->id);
+ goto err;
+ }
+
+ if (bus->devs[dev->id]) {
+ bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
+ }
+ bus->devs[dev->id] = dev;
+
+ dev->info = info;
+ return dev->info->init(dev);
+
+err:
+ return -1;
+}
+
+void scsi_qdev_register(SCSIDeviceInfo *info)
+{
+ info->qdev.bus_info = &scsi_bus_info;
+ info->qdev.init = scsi_qdev_init;
+ qdev_register(&info->qdev);
+}
+
+/* handle legacy '-drive if=scsi,...' cmd line args */
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)
+{
+ const char *driver;
+ DeviceState *dev;
+
+ driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk";
+ dev = qdev_create(&bus->qbus, driver);
+ qdev_prop_set_uint32(dev, "scsi-id", unit);
+ qdev_prop_set_drive(dev, "drive", dinfo);
+ qdev_init(dev);
+ return DO_UPCAST(SCSIDevice, qdev, dev);
+}
+
+void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
+{
+ DriveInfo *dinfo;
+ int unit;
+
+ for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
+ dinfo = drive_get(IF_SCSI, bus->busnr, unit);
+ if (dinfo == NULL) {
+ continue;
+ }
+ scsi_bus_legacy_add_drive(bus, dinfo, unit);
+ }
+}