Statistics
| Branch: | Revision:

root / hw / scsi-bus.c @ 3f66aa9c

History | View | Annotate | Download (2.9 kB)

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
    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
}