aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/scsi-bus.c')
-rw-r--r--hw/scsi-bus.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index d9d4e18d66..7104e98d59 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -37,12 +37,16 @@ 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);
+ SCSIDevice *olddev;
int rc = -1;
if (dev->id == -1) {
- for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
- if (bus->devs[dev->id] == NULL)
+ int id;
+ for (id = 0; id < bus->info->ndev; id++) {
+ if (!scsi_device_find(bus, id, 0)) {
+ dev->id = id;
break;
+ }
}
}
if (dev->id >= bus->info->ndev) {
@@ -50,17 +54,14 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
goto err;
}
- if (bus->devs[dev->id]) {
- qdev_free(&bus->devs[dev->id]->qdev);
+ olddev = scsi_device_find(bus, dev->id, dev->lun);
+ if (olddev && dev->lun == olddev->lun) {
+ qdev_free(&olddev->qdev);
}
- bus->devs[dev->id] = dev;
dev->info = info;
QTAILQ_INIT(&dev->requests);
rc = dev->info->init(dev);
- if (rc != 0) {
- bus->devs[dev->id] = NULL;
- }
err:
return rc;
@@ -69,13 +70,10 @@ err:
static int scsi_qdev_exit(DeviceState *qdev)
{
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
- assert(bus->devs[dev->id] != NULL);
- if (bus->devs[dev->id]->info->destroy) {
- bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
+ if (dev->info->destroy) {
+ dev->info->destroy(dev);
}
- bus->devs[dev->id] = NULL;
return 0;
}
@@ -1157,19 +1155,28 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
static char *scsibus_get_fw_dev_path(DeviceState *dev)
{
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
- SCSIBus *bus = scsi_bus_from_device(d);
char path[100];
- int i;
- for (i = 0; i < bus->info->ndev; i++) {
- if (bus->devs[i] == d) {
- break;
- }
- }
+ snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
+ 0, d->id, d->lun);
- assert(i != bus->info->ndev);
+ return strdup(path);
+}
+
+SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
+{
+ DeviceState *qdev;
+ SCSIDevice *target_dev = NULL;
- snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
+ QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- return strdup(path);
+ if (dev->id == id) {
+ if (dev->lun == lun) {
+ return dev;
+ }
+ target_dev = dev;
+ }
+ }
+ return target_dev;
}