root / hw / scsi-bus.c @ dd4239d6
History | View | Annotate | Download (2.9 kB)
1 |
#include "hw.h" |
---|---|
2 |
#include "sysemu.h" |
3 |
#include "scsi.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 |
bus->qbus.allow_hotplug = 1;
|
27 |
} |
28 |
|
29 |
static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base) |
30 |
{ |
31 |
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); |
32 |
SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base); |
33 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); |
34 |
int rc = -1; |
35 |
|
36 |
if (dev->id == -1) { |
37 |
for (dev->id = 0; dev->id < bus->ndev; dev->id++) { |
38 |
if (bus->devs[dev->id] == NULL) |
39 |
break;
|
40 |
} |
41 |
} |
42 |
if (dev->id >= bus->ndev) {
|
43 |
qemu_error("bad scsi device id: %d\n", dev->id);
|
44 |
goto err;
|
45 |
} |
46 |
|
47 |
if (bus->devs[dev->id]) {
|
48 |
qdev_free(&bus->devs[dev->id]->qdev); |
49 |
} |
50 |
bus->devs[dev->id] = dev; |
51 |
|
52 |
dev->info = info; |
53 |
rc = dev->info->init(dev); |
54 |
if (rc != 0) { |
55 |
bus->devs[dev->id] = NULL;
|
56 |
} |
57 |
|
58 |
err:
|
59 |
return rc;
|
60 |
} |
61 |
|
62 |
static int scsi_qdev_exit(DeviceState *qdev) |
63 |
{ |
64 |
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); |
65 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); |
66 |
|
67 |
assert(bus->devs[dev->id] != NULL);
|
68 |
if (bus->devs[dev->id]->info->destroy) {
|
69 |
bus->devs[dev->id]->info->destroy(bus->devs[dev->id]); |
70 |
} |
71 |
bus->devs[dev->id] = NULL;
|
72 |
return 0; |
73 |
} |
74 |
|
75 |
void scsi_qdev_register(SCSIDeviceInfo *info)
|
76 |
{ |
77 |
info->qdev.bus_info = &scsi_bus_info; |
78 |
info->qdev.init = scsi_qdev_init; |
79 |
info->qdev.unplug = qdev_simple_unplug_cb; |
80 |
info->qdev.exit = scsi_qdev_exit; |
81 |
qdev_register(&info->qdev); |
82 |
} |
83 |
|
84 |
/* handle legacy '-drive if=scsi,...' cmd line args */
|
85 |
/* FIXME callers should check for failure, but don't */
|
86 |
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)
|
87 |
{ |
88 |
const char *driver; |
89 |
DeviceState *dev; |
90 |
|
91 |
driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk"; |
92 |
dev = qdev_create(&bus->qbus, driver); |
93 |
qdev_prop_set_uint32(dev, "scsi-id", unit);
|
94 |
qdev_prop_set_drive(dev, "drive", dinfo);
|
95 |
if (qdev_init(dev) < 0) |
96 |
return NULL; |
97 |
return DO_UPCAST(SCSIDevice, qdev, dev);
|
98 |
} |
99 |
|
100 |
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
|
101 |
{ |
102 |
DriveInfo *dinfo; |
103 |
int unit;
|
104 |
|
105 |
for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { |
106 |
dinfo = drive_get(IF_SCSI, bus->busnr, unit); |
107 |
if (dinfo == NULL) { |
108 |
continue;
|
109 |
} |
110 |
scsi_bus_legacy_add_drive(bus, dinfo, unit); |
111 |
} |
112 |
} |