diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2009-08-31 14:24:04 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-09-09 14:57:19 -0500 |
commit | d52affa7f6b9df3c7d44da0effbdfc8339c43914 (patch) | |
tree | f846e1baed7d228519ba95bfd3d915529e7172f9 /hw/scsi-bus.c | |
parent | 5b19d9a247c47fe52c4f3d3e844009a689ee6b28 (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.c | 93 |
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); + } +} |