]> git.proxmox.com Git - qemu.git/blob - hw/scsi-bus.c
Implement scsi device destruction
[qemu.git] / hw / scsi-bus.c
1 #include "hw.h"
2 #include "sysemu.h"
3 #include "scsi-disk.h"
4 #include "block.h"
5 #include "qdev.h"
6
7 static struct BusInfo scsi_bus_info = {
8 .name = "SCSI",
9 .size = sizeof(SCSIBus),
10 .props = (Property[]) {
11 DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
12 DEFINE_PROP_END_OF_LIST(),
13 },
14 };
15 static int next_scsi_bus;
16
17 /* Create a scsi bus, and attach devices to it. */
18 void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
19 scsi_completionfn complete)
20 {
21 qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
22 bus->busnr = next_scsi_bus++;
23 bus->tcq = tcq;
24 bus->ndev = ndev;
25 bus->complete = complete;
26 }
27
28 static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
29 {
30 SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
31 SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
32 SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
33 int rc = -1;
34
35 if (dev->id == -1) {
36 for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
37 if (bus->devs[dev->id] == NULL)
38 break;
39 }
40 }
41 if (dev->id >= bus->ndev) {
42 qemu_error("bad scsi device id: %d\n", dev->id);
43 goto err;
44 }
45
46 if (bus->devs[dev->id]) {
47 qdev_free(&bus->devs[dev->id]->qdev);
48 }
49 bus->devs[dev->id] = dev;
50
51 dev->info = info;
52 rc = dev->info->init(dev);
53 if (rc != 0) {
54 bus->devs[dev->id] = NULL;
55 }
56
57 err:
58 return rc;
59 }
60
61 static int scsi_qdev_exit(DeviceState *qdev)
62 {
63 SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
64 SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
65
66 assert(bus->devs[dev->id] != NULL);
67 if (bus->devs[dev->id]->info->destroy) {
68 bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
69 }
70 bus->devs[dev->id] = NULL;
71 return 0;
72 }
73
74 void scsi_qdev_register(SCSIDeviceInfo *info)
75 {
76 info->qdev.bus_info = &scsi_bus_info;
77 info->qdev.init = scsi_qdev_init;
78 info->qdev.exit = scsi_qdev_exit;
79 qdev_register(&info->qdev);
80 }
81
82 /* handle legacy '-drive if=scsi,...' cmd line args */
83 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)
84 {
85 const char *driver;
86 DeviceState *dev;
87
88 driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk";
89 dev = qdev_create(&bus->qbus, driver);
90 qdev_prop_set_uint32(dev, "scsi-id", unit);
91 qdev_prop_set_drive(dev, "drive", dinfo);
92 qdev_init(dev);
93 return DO_UPCAST(SCSIDevice, qdev, dev);
94 }
95
96 void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
97 {
98 DriveInfo *dinfo;
99 int unit;
100
101 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
102 dinfo = drive_get(IF_SCSI, bus->busnr, unit);
103 if (dinfo == NULL) {
104 continue;
105 }
106 scsi_bus_legacy_add_drive(bus, dinfo, unit);
107 }
108 }