Statistics
| Branch: | Revision:

root / hw / scsi-bus.c @ dd4239d6

History | View | Annotate | Download (2.9 kB)

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