* [Qemu-devel] [PATCH 01/20] qdev: update pci device registration.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 02/20] qdev: replace bus_type enum with bus_info struct Gerd Hoffmann
` (19 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Makes pci_qdev_register take a PCIDeviceInfo struct instead of a bunch
of parameters. Also adds config_read and config_write callbacks to
PCIDeviceInfo, so drivers needing these can be converted to the qdev
device API too.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/e1000.c | 8 +++++++-
hw/eepro100.c | 25 +++++++++++++++++++------
hw/lsi53c895a.c | 8 +++++++-
hw/ne2000.c | 8 +++++++-
hw/pci.c | 24 ++++++++++--------------
hw/pci.h | 10 +++++++++-
hw/pcnet.c | 8 +++++++-
hw/rtl8139.c | 8 +++++++-
hw/versatile_pci.c | 9 +++++++--
hw/virtio-pci.c | 31 +++++++++++++++++++++++--------
10 files changed, 103 insertions(+), 36 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 5f4b123..9276968 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1125,9 +1125,15 @@ static void pci_e1000_init(PCIDevice *pci_dev)
e1000_reset(d);
}
+static PCIDeviceInfo e1000_info = {
+ .qdev.name = "e1000",
+ .qdev.size = sizeof(E1000State),
+ .init = pci_e1000_init,
+};
+
static void e1000_register_devices(void)
{
- pci_qdev_register("e1000", sizeof(E1000State), pci_e1000_init);
+ pci_qdev_register(&e1000_info);
}
device_init(e1000_register_devices)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6f47eaf..d406716 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1792,14 +1792,27 @@ static void pci_i82559er_init(PCIDevice *dev)
nic_init(dev, i82559ER);
}
+static PCIDeviceInfo eepro100_info[] = {
+ {
+ .qdev.name = "i82551",
+ .qdev.size = sizeof(PCIEEPRO100State),
+ .init = pci_i82551_init,
+ },{
+ .qdev.name = "i82557b",
+ .qdev.size = sizeof(PCIEEPRO100State),
+ .init = pci_i82557b_init,
+ },{
+ .qdev.name = "i82559er",
+ .qdev.size = sizeof(PCIEEPRO100State),
+ .init = pci_i82559er_init,
+ },{
+ /* end of list */
+ }
+};
+
static void eepro100_register_devices(void)
{
- pci_qdev_register("i82551", sizeof(PCIEEPRO100State),
- pci_i82551_init);
- pci_qdev_register("i82557b", sizeof(PCIEEPRO100State),
- pci_i82557b_init);
- pci_qdev_register("i82559er", sizeof(PCIEEPRO100State),
- pci_i82559er_init);
+ pci_qdev_register_many(eepro100_info);
}
device_init(eepro100_register_devices)
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 71f8281..516a468 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2035,9 +2035,15 @@ static void lsi_scsi_init(PCIDevice *dev)
scsi_bus_new(&dev->qdev, lsi_scsi_attach);
}
+static PCIDeviceInfo lsi_info = {
+ .qdev.name = "lsi53c895a",
+ .qdev.size = sizeof(LSIState),
+ .init = lsi_scsi_init,
+};
+
static void lsi53c895a_register_devices(void)
{
- pci_qdev_register("lsi53c895a", sizeof(LSIState), lsi_scsi_init);
+ pci_qdev_register(&lsi_info);
}
device_init(lsi53c895a_register_devices);
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 66ae9ab..66ff29d 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -832,9 +832,15 @@ static void pci_ne2000_init(PCIDevice *pci_dev)
register_savevm("ne2000", -1, 3, ne2000_save, ne2000_load, s);
}
+static PCIDeviceInfo ne2000_info = {
+ .qdev.name = "ne2k_pci",
+ .qdev.size = sizeof(PCINE2000State),
+ .init = pci_ne2000_init,
+};
+
static void ne2000_register_devices(void)
{
- pci_qdev_register("ne2k_pci", sizeof(PCINE2000State), pci_ne2000_init);
+ pci_qdev_register(&ne2000_info);
}
device_init(ne2000_register_devices)
diff --git a/hw/pci.c b/hw/pci.c
index f2d7daf..1259515 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -938,11 +938,6 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
return s->bus;
}
-typedef struct {
- DeviceInfo qdev;
- pci_qdev_initfn init;
-} PCIDeviceInfo;
-
static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
{
PCIDevice *pci_dev = (PCIDevice *)qdev;
@@ -953,25 +948,26 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
devfn = qdev_get_prop_int(qdev, "devfn", -1);
pci_dev = do_pci_register_device(pci_dev, bus, "FIXME", devfn,
- NULL, NULL);//FIXME:config_read, config_write);
+ info->config_read, info->config_write);
assert(pci_dev);
info->init(pci_dev);
}
-void pci_qdev_register(const char *name, int size, pci_qdev_initfn init)
+void pci_qdev_register(PCIDeviceInfo *info)
{
- PCIDeviceInfo *info;
-
- info = qemu_mallocz(sizeof(*info));
- info->qdev.name = qemu_strdup(name);
- info->qdev.size = size;
- info->init = init;
info->qdev.init = pci_qdev_init;
info->qdev.bus_type = BUS_TYPE_PCI;
-
qdev_register(&info->qdev);
}
+void pci_qdev_register_many(PCIDeviceInfo *info)
+{
+ while (info->qdev.name) {
+ pci_qdev_register(info);
+ info++;
+ }
+}
+
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
{
DeviceState *dev;
diff --git a/hw/pci.h b/hw/pci.h
index c8625de..4daf86f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -217,7 +217,15 @@ pci_config_set_class(uint8_t *pci_config, uint16_t val)
}
typedef void (*pci_qdev_initfn)(PCIDevice *dev);
-void pci_qdev_register(const char *name, int size, pci_qdev_initfn init);
+typedef struct {
+ DeviceInfo qdev;
+ pci_qdev_initfn init;
+ PCIConfigReadFunc *config_read;
+ PCIConfigWriteFunc *config_write;
+} PCIDeviceInfo;
+
+void pci_qdev_register(PCIDeviceInfo *info);
+void pci_qdev_register_many(PCIDeviceInfo *info);
PCIDevice *pci_create(const char *name, const char *devaddr);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index a184146..4519780 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2143,9 +2143,15 @@ static void lance_init(SysBusDevice *dev)
}
#endif /* TARGET_SPARC */
+static PCIDeviceInfo pcnet_info = {
+ .qdev.name = "pcnet",
+ .qdev.size = sizeof(PCIPCNetState),
+ .init = pci_pcnet_init,
+};
+
static void pcnet_register_devices(void)
{
- pci_qdev_register("pcnet", sizeof(PCIPCNetState), pci_pcnet_init);
+ pci_qdev_register(&pcnet_info);
#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64)
sysbus_register_dev("lance", sizeof(SysBusPCNetState), lance_init);
#endif
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 0a66026..4ce7cb6 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3499,9 +3499,15 @@ static void pci_rtl8139_init(PCIDevice *dev)
#endif /* RTL8139_ONBOARD_TIMER */
}
+static PCIDeviceInfo rtl8139_info = {
+ .qdev.name = "rtl8139",
+ .qdev.size = sizeof(PCIRTL8139State),
+ .init = pci_rtl8139_init,
+};
+
static void rtl8139_register_devices(void)
{
- pci_qdev_register("rtl8139", sizeof(PCIRTL8139State), pci_rtl8139_init);
+ pci_qdev_register(&rtl8139_info);
}
device_init(rtl8139_register_devices)
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index e89add1..5eb2625 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -153,13 +153,18 @@ static void versatile_pci_host_init(PCIDevice *d)
d->config[0x0D] = 0x10; // latency_timer
}
+static PCIDeviceInfo versatile_pci_host_info = {
+ .qdev.name = "versatile_pci_host",
+ .qdev.size = sizeof(PCIDevice),
+ .init = versatile_pci_host_init,
+};
+
static void versatile_pci_register_devices(void)
{
sysbus_register_dev("versatile_pci", sizeof(PCIVPBState), pci_vpb_init);
sysbus_register_dev("realview_pci", sizeof(PCIVPBState),
pci_realview_init);
- pci_qdev_register("versatile_pci_host", sizeof(PCIDevice),
- versatile_pci_host_init);
+ pci_qdev_register(&versatile_pci_host_info);
}
device_init(versatile_pci_register_devices)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index df45036..c77231e 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -336,16 +336,31 @@ static void virtio_balloon_init_pci(PCIDevice *pci_dev)
0x00);
}
+static PCIDeviceInfo virtio_info[] = {
+ {
+ .qdev.name = "virtio-blk-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_blk_init_pci,
+ },{
+ .qdev.name = "virtio-net-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_net_init_pci,
+ },{
+ .qdev.name = "virtio-console-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_console_init_pci,
+ },{
+ .qdev.name = "virtio-balloon-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_balloon_init_pci,
+ },{
+ /* end of list */
+ }
+};
+
static void virtio_pci_register_devices(void)
{
- pci_qdev_register("virtio-blk-pci", sizeof(VirtIOPCIProxy),
- virtio_blk_init_pci);
- pci_qdev_register("virtio-net-pci", sizeof(VirtIOPCIProxy),
- virtio_net_init_pci);
- pci_qdev_register("virtio-console-pci", sizeof(VirtIOPCIProxy),
- virtio_console_init_pci);
- pci_qdev_register("virtio-balloon-pci", sizeof(VirtIOPCIProxy),
- virtio_balloon_init_pci);
+ pci_qdev_register_many(virtio_info);
}
device_init(virtio_pci_register_devices)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 02/20] qdev: replace bus_type enum with bus_info struct.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 01/20] qdev: update pci device registration Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 03/20] qdev: remove DeviceType Gerd Hoffmann
` (18 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
BusInfo is filled with name and size (pretty much like I did for
DeviceInfo as well). There is also a function pointer to print
bus-specific device information to the monitor. sysbus is hooked
up there, I've also added a print function for PCI.
Device creation is slightly modified as well: The device type search
loop now also checks the bus type while scanning the list instead of
complaining thereafter in case of a mismatch. This effectively gives
each bus a private namespace for device names.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/i2c.c | 10 +++++++---
hw/pci.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-----
hw/qdev.c | 58 ++++++++++++++++++++--------------------------------------
hw/qdev.h | 23 +++++++++++------------
hw/ssi.c | 9 +++++++--
hw/sysbus.c | 12 ++++++++++--
6 files changed, 103 insertions(+), 62 deletions(-)
diff --git a/hw/i2c.c b/hw/i2c.c
index 838f40f..98aa7fc 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -17,6 +17,11 @@ struct i2c_bus
int saved_address;
};
+static struct BusInfo i2c_bus_info = {
+ .name = "I2C",
+ .size = sizeof(i2c_bus),
+};
+
static void i2c_bus_save(QEMUFile *f, void *opaque)
{
i2c_bus *bus = (i2c_bus *)opaque;
@@ -44,8 +49,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
{
i2c_bus *bus;
- bus = FROM_QBUS(i2c_bus, qbus_create(BUS_TYPE_I2C, sizeof(i2c_bus),
- parent, name));
+ bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus);
return bus;
}
@@ -156,7 +160,7 @@ void i2c_register_slave(I2CSlaveInfo *info)
{
assert(info->qdev.size >= sizeof(i2c_slave));
info->qdev.init = i2c_slave_qdev_init;
- info->qdev.bus_type = BUS_TYPE_I2C;
+ info->qdev.bus_info = &i2c_bus_info;
qdev_register(&info->qdev);
}
diff --git a/hw/pci.c b/hw/pci.c
index 1259515..c537ed0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -45,7 +45,15 @@ struct PCIBus {
/* The bus IRQ state is the logical OR of the connected devices.
Keep a count of the number of devices with raised IRQs. */
int nirq;
- int irq_count[];
+ int *irq_count;
+};
+
+static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+
+static struct BusInfo pci_bus_info = {
+ .name = "PCI",
+ .size = sizeof(PCIBus),
+ .print = pcibus_dev_print,
};
static void pci_update_mappings(PCIDevice *d);
@@ -109,14 +117,13 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
PCIBus *bus;
static int nbus = 0;
- bus = FROM_QBUS(PCIBus, qbus_create(BUS_TYPE_PCI,
- sizeof(PCIBus) + (nirq * sizeof(int)),
- parent, name));
+ bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name));
bus->set_irq = set_irq;
bus->map_irq = map_irq;
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
bus->nirq = nirq;
+ bus->irq_count = qemu_malloc(nirq * sizeof(bus->irq_count[0]));
bus->next = first_bus;
first_bus = bus;
register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
@@ -956,7 +963,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
void pci_qdev_register(PCIDeviceInfo *info)
{
info->qdev.init = pci_qdev_init;
- info->qdev.bus_type = BUS_TYPE_PCI;
+ info->qdev.bus_info = &pci_bus_info;
qdev_register(&info->qdev);
}
@@ -978,3 +985,39 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
return (PCIDevice *)dev;
}
+
+static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+ PCIDevice *d = (PCIDevice *)dev;
+ const pci_class_desc *desc;
+ char ctxt[64];
+ PCIIORegion *r;
+ int i, class;
+
+ class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+ desc = pci_class_descriptions;
+ while (desc->desc && class != desc->class)
+ desc++;
+ if (desc->desc) {
+ snprintf(ctxt, sizeof(ctxt), "%s", desc->desc);
+ } else {
+ snprintf(ctxt, sizeof(ctxt), "Class %04x", class);
+ }
+
+ monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
+ "pci id %04x:%04x (sub %04x:%04x)\n",
+ indent, "", ctxt,
+ d->bus->bus_num, d->devfn >> 3, d->devfn & 7,
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_ID))));
+ for (i = 0; i < PCI_NUM_REGIONS; i++) {
+ r = &d->io_regions[i];
+ if (!r->size)
+ continue;
+ monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
+ i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
+ r->addr, r->addr + r->size - 1);
+ }
+}
diff --git a/hw/qdev.c b/hw/qdev.c
index 385e709..93e417d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -48,6 +48,7 @@ struct DeviceType {
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
+extern struct BusInfo system_bus_info;
static DeviceType *device_type_list;
@@ -72,31 +73,26 @@ DeviceState *qdev_create(BusState *bus, const char *name)
DeviceType *t;
DeviceState *dev;
- for (t = device_type_list; t; t = t->next) {
- if (strcmp(t->info->name, name) == 0) {
- break;
+ if (!bus) {
+ if (!main_system_bus) {
+ main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
}
+ bus = main_system_bus;
+ }
+
+ for (t = device_type_list; t; t = t->next) {
+ if (t->info->bus_info != bus->info)
+ continue;
+ if (strcmp(t->info->name, name) != 0)
+ continue;
+ break;
}
if (!t) {
- hw_error("Unknown device '%s'\n", name);
+ hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
}
dev = qemu_mallocz(t->info->size);
dev->type = t;
-
- if (!bus) {
- /* ???: This assumes system busses have no additional state. */
- if (!main_system_bus) {
- main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
- NULL, "main-system-bus");
- }
- bus = main_system_bus;
- }
- if (t->info->bus_type != bus->type) {
- /* TODO: Print bus type names. */
- hw_error("Device '%s' on wrong bus type (%d/%d)", name,
- t->info->bus_type, bus->type);
- }
dev->parent_bus = bus;
LIST_INSERT_HEAD(&bus->children, dev, sibling);
return dev;
@@ -320,13 +316,12 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
}
}
-BusState *qbus_create(BusType type, size_t size,
- DeviceState *parent, const char *name)
+BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
{
BusState *bus;
- bus = qemu_mallocz(size);
- bus->type = type;
+ bus = qemu_mallocz(info->size);
+ bus->info = info;
bus->parent = parent;
bus->name = qemu_strdup(name);
LIST_INIT(&bus->children);
@@ -336,14 +331,6 @@ BusState *qbus_create(BusType type, size_t size,
return bus;
}
-static const char *bus_type_names[] = {
- [ BUS_TYPE_SYSTEM ] = "System",
- [ BUS_TYPE_PCI ] = "PCI",
- [ BUS_TYPE_SCSI ] = "SCSI",
- [ BUS_TYPE_I2C ] = "I2C",
- [ BUS_TYPE_SSI ] = "SSI",
-};
-
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
static void qbus_print(Monitor *mon, BusState *bus, int indent);
@@ -377,13 +364,8 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
break;
}
}
- switch (dev->parent_bus->type) {
- case BUS_TYPE_SYSTEM:
- sysbus_dev_print(mon, dev, indent);
- break;
- default:
- break;
- }
+ if (dev->parent_bus->info->print)
+ dev->parent_bus->info->print(mon, dev, indent);
LIST_FOREACH(child, &dev->child_bus, sibling) {
qbus_print(mon, child, indent);
}
@@ -395,7 +377,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent)
qdev_printf("bus: %s\n", bus->name);
indent += 2;
- qdev_printf("type %s\n", bus_type_names[bus->type]);
+ qdev_printf("type %s\n", bus->info->name);
LIST_FOREACH(dev, &bus->children, sibling) {
qdev_print(mon, dev, indent);
}
diff --git a/hw/qdev.h b/hw/qdev.h
index ad10499..8b238d5 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -10,6 +10,8 @@ typedef struct DeviceProperty DeviceProperty;
typedef struct BusState BusState;
+typedef struct BusInfo BusInfo;
+
/* This structure should not be accessed directly. We declare it here
so that it can be embedded in individual device state structures. */
struct DeviceState {
@@ -25,18 +27,17 @@ struct DeviceState {
LIST_ENTRY(DeviceState) sibling;
};
-typedef enum {
- BUS_TYPE_SYSTEM,
- BUS_TYPE_PCI,
- BUS_TYPE_SCSI,
- BUS_TYPE_I2C,
- BUS_TYPE_SSI
-} BusType;
+typedef void (*bus_dev_print)(Monitor *mon, DeviceState *dev, int indent);
+struct BusInfo {
+ const char *name;
+ size_t size;
+ bus_dev_print print;
+};
struct BusState {
DeviceState *parent;
+ BusInfo *info;
const char *name;
- BusType type;
LIST_HEAD(, DeviceState) children;
LIST_ENTRY(BusState) sibling;
};
@@ -84,7 +85,7 @@ struct DeviceInfo {
/* Private to qdev / bus. */
qdev_initfn init;
- BusType bus_type;
+ BusInfo *bus_info;
};
void qdev_register(DeviceInfo *info);
@@ -116,14 +117,12 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
/*** BUS API. ***/
-BusState *qbus_create(BusType type, size_t size,
- DeviceState *parent, const char *name);
+BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
/*** monitor commands ***/
void do_info_qtree(Monitor *mon);
-void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
#endif
diff --git a/hw/ssi.c b/hw/ssi.c
index b0bcf97..a5133be 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -13,6 +13,11 @@ struct SSIBus {
BusState qbus;
};
+static struct BusInfo ssi_bus_info = {
+ .name = "SSI",
+ .size = sizeof(SSIBus),
+};
+
static void ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
{
SSISlaveInfo *info = container_of(base_info, SSISlaveInfo, qdev);
@@ -33,7 +38,7 @@ void ssi_register_slave(SSISlaveInfo *info)
{
assert(info->qdev.size >= sizeof(SSISlave));
info->qdev.init = ssi_slave_init;
- info->qdev.bus_type = BUS_TYPE_SSI;
+ info->qdev.bus_info = &ssi_bus_info;
qdev_register(&info->qdev);
}
@@ -48,7 +53,7 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
{
BusState *bus;
- bus = qbus_create(BUS_TYPE_SSI, sizeof(SSIBus), parent, name);
+ bus = qbus_create(&ssi_bus_info, parent, name);
return FROM_QBUS(SSIBus, bus);
}
diff --git a/hw/sysbus.c b/hw/sysbus.c
index ef3a701..13e563b 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -22,6 +22,14 @@
#include "sysemu.h"
#include "monitor.h"
+static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+
+struct BusInfo system_bus_info = {
+ .name = "System",
+ .size = sizeof(BusState),
+ .print = sysbus_dev_print,
+};
+
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
{
assert(n >= 0 && n < dev->num_irq);
@@ -108,7 +116,7 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base)
void sysbus_register_withprop(SysBusDeviceInfo *info)
{
info->qdev.init = sysbus_device_init;
- info->qdev.bus_type = BUS_TYPE_SYSTEM;
+ info->qdev.bus_info = &system_bus_info;
assert(info->qdev.size >= sizeof(SysBusDevice));
qdev_register(&info->qdev);
@@ -153,7 +161,7 @@ DeviceState *sysbus_create_varargs(const char *name,
return dev;
}
-void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
+static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
SysBusDevice *s = sysbus_from_qdev(dev);
int i;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 03/20] qdev: remove DeviceType
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 01/20] qdev: update pci device registration Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 02/20] qdev: replace bus_type enum with bus_info struct Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 04/20] qdev/core: bus list Gerd Hoffmann
` (17 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
The only purpose DeviceType serves is creating a linked list of
DeviceInfo structs. This removes DeviceType and add a next field to
DeviceInfo instead, so the DeviceInfo structs can be changed that way.
Elimitates a pointless extra level of indirection.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qdev.c | 37 ++++++++++++++-----------------------
hw/qdev.h | 7 +++----
2 files changed, 17 insertions(+), 27 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index 93e417d..3dc7076 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -41,28 +41,19 @@ struct DeviceProperty {
DeviceProperty *next;
};
-struct DeviceType {
- DeviceInfo *info;
- DeviceType *next;
-};
-
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
extern struct BusInfo system_bus_info;
-static DeviceType *device_type_list;
+static DeviceInfo *device_info_list;
/* Register a new device type. */
void qdev_register(DeviceInfo *info)
{
- DeviceType *t;
-
assert(info->size >= sizeof(DeviceState));
- t = qemu_mallocz(sizeof(DeviceType));
- t->next = device_type_list;
- device_type_list = t;
- t->info = info;
+ info->next = device_info_list;
+ device_info_list = info;
}
/* Create a new device. This only initializes the device state structure
@@ -70,7 +61,7 @@ void qdev_register(DeviceInfo *info)
initialize the actual device emulation. */
DeviceState *qdev_create(BusState *bus, const char *name)
{
- DeviceType *t;
+ DeviceInfo *info;
DeviceState *dev;
if (!bus) {
@@ -80,19 +71,19 @@ DeviceState *qdev_create(BusState *bus, const char *name)
bus = main_system_bus;
}
- for (t = device_type_list; t; t = t->next) {
- if (t->info->bus_info != bus->info)
+ for (info = device_info_list; info != NULL; info = info->next) {
+ if (info->bus_info != bus->info)
continue;
- if (strcmp(t->info->name, name) != 0)
+ if (strcmp(info->name, name) != 0)
continue;
break;
}
- if (!t) {
+ if (!info) {
hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
}
- dev = qemu_mallocz(t->info->size);
- dev->type = t;
+ dev = qemu_mallocz(info->size);
+ dev->info = info;
dev->parent_bus = bus;
LIST_INSERT_HEAD(&bus->children, dev, sibling);
return dev;
@@ -103,7 +94,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
calling this function. */
void qdev_init(DeviceState *dev)
{
- dev->type->info->init(dev, dev->type->info);
+ dev->info->init(dev, dev->info);
}
/* Unlink device from bus and free the structure. */
@@ -165,7 +156,7 @@ CharDriverState *qdev_init_chardev(DeviceState *dev)
static int next_serial;
static int next_virtconsole;
/* FIXME: This is a nasty hack that needs to go away. */
- if (strncmp(dev->type->info->name, "virtio", 6) == 0) {
+ if (strncmp(dev->info->name, "virtio", 6) == 0) {
return virtcon_hds[next_virtconsole++];
} else {
return serial_hds[next_serial++];
@@ -338,7 +329,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
{
DeviceProperty *prop;
BusState *child;
- qdev_printf("dev: %s\n", dev->type->info->name);
+ qdev_printf("dev: %s\n", dev->info->name);
indent += 2;
if (dev->num_gpio_in) {
qdev_printf("gpio-in %d\n", dev->num_gpio_in);
@@ -357,7 +348,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
break;
case PROP_TYPE_DEV:
qdev_printf("prop-dev %s %s\n", prop->name,
- ((DeviceState *)prop->value.ptr)->type->info->name);
+ ((DeviceState *)prop->value.ptr)->info->name);
break;
default:
qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
diff --git a/hw/qdev.h b/hw/qdev.h
index 8b238d5..18321b3 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -4,7 +4,7 @@
#include "hw.h"
#include "sys-queue.h"
-typedef struct DeviceType DeviceType;
+typedef struct DeviceInfo DeviceInfo;
typedef struct DeviceProperty DeviceProperty;
@@ -15,7 +15,7 @@ typedef struct BusInfo BusInfo;
/* This structure should not be accessed directly. We declare it here
so that it can be embedded in individual device state structures. */
struct DeviceState {
- DeviceType *type;
+ DeviceInfo *info;
BusState *parent_bus;
DeviceProperty *props;
int num_gpio_out;
@@ -72,8 +72,6 @@ typedef struct {
DevicePropType type;
} DevicePropList;
-typedef struct DeviceInfo DeviceInfo;
-
typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
int unit);
@@ -86,6 +84,7 @@ struct DeviceInfo {
/* Private to qdev / bus. */
qdev_initfn init;
BusInfo *bus_info;
+ struct DeviceInfo *next;
};
void qdev_register(DeviceInfo *info);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 04/20] qdev/core: bus list
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (2 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 03/20] qdev: remove DeviceType Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 05/20] qdev/core: add monitor command to list all drivers Gerd Hoffmann
` (16 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
* maintain a list of busses.
* maintain bus numbers.
* add function to find busses by type / name / number.
* add monitor command to list busses.
Use case for the bus list is hot-plugging devices via monitor, where
qemu needs some way to find the bus specified in the monitor command.
The usb patches in the patch queue make use of this.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qdev.c | 41 ++++++++++++++++++++++++++++++++++++++++-
hw/qdev.h | 5 +++++
monitor.c | 2 ++
3 files changed, 47 insertions(+), 1 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index 3dc7076..1fb73b1 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -306,22 +306,50 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
attach(host, drives_table[index].bdrv, unit);
}
}
+static TAILQ_HEAD(, BusState) buslist = TAILQ_HEAD_INITIALIZER(buslist);
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
{
BusState *bus;
+ char buf[32];
+ int i;
bus = qemu_mallocz(info->size);
bus->info = info;
+ bus->busnr = info->next_busnr++;
bus->parent = parent;
+ if (!name) {
+ /* default name: lowercase(type) + busnr, i.e. "scsi0" */
+ snprintf(buf, sizeof(buf), "%s%d", info->name, bus->busnr);
+ for (i = 0; buf[i]; i++)
+ buf[i] = tolower(buf[i]);
+ name = buf;
+ }
bus->name = qemu_strdup(name);
LIST_INIT(&bus->children);
if (parent) {
LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
}
+ TAILQ_INSERT_TAIL(&buslist, bus, next);
return bus;
}
+BusState *qbus_find(const char *type, const char *name, int busnr)
+{
+ BusState *bus;
+
+ TAILQ_FOREACH(bus, &buslist, next) {
+ if (type && strcmp(type, bus->info->name) != 0)
+ continue;
+ if (name && strcmp(name, bus->name) != 0)
+ continue;
+ if (busnr != -1 && busnr != bus->busnr)
+ continue;
+ return bus;
+ }
+ return NULL;
+}
+
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
static void qbus_print(Monitor *mon, BusState *bus, int indent);
@@ -368,7 +396,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent)
qdev_printf("bus: %s\n", bus->name);
indent += 2;
- qdev_printf("type %s\n", bus->info->name);
+ qdev_printf("type %s, nr %d\n", bus->info->name, bus->busnr);
LIST_FOREACH(dev, &bus->children, sibling) {
qdev_print(mon, dev, indent);
}
@@ -380,3 +408,14 @@ void do_info_qtree(Monitor *mon)
if (main_system_bus)
qbus_print(mon, main_system_bus, 0);
}
+
+void do_info_qbus(Monitor *mon)
+{
+ BusState *bus;
+
+ TAILQ_FOREACH(bus, &buslist, next) {
+ monitor_printf(mon, "%s: type %s, nr %d, parent %s\n",
+ bus->name, bus->info->name, bus->busnr,
+ bus->parent ? bus->parent->info->name : "<none>");
+ }
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 18321b3..c4b04c1 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -32,14 +32,17 @@ struct BusInfo {
const char *name;
size_t size;
bus_dev_print print;
+ int next_busnr;
};
struct BusState {
DeviceState *parent;
BusInfo *info;
+ int busnr;
const char *name;
LIST_HEAD(, DeviceState) children;
LIST_ENTRY(BusState) sibling;
+ TAILQ_ENTRY(BusState) next;
};
/*** Board API. This should go away once we have a machine config file. ***/
@@ -117,11 +120,13 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
/*** BUS API. ***/
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
+BusState *qbus_find(const char *type, const char *name, int busnr);
#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
/*** monitor commands ***/
void do_info_qtree(Monitor *mon);
+void do_info_qbus(Monitor *mon);
#endif
diff --git a/monitor.c b/monitor.c
index 6b45f6c..b1da695 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1741,6 +1741,8 @@ static const mon_cmd_t info_cmds[] = {
"", "show balloon information" },
{ "qtree", "", do_info_qtree,
"", "show device tree" },
+ { "qbus", "", do_info_qbus,
+ "", "show qdev bus list" },
{ NULL, NULL, },
};
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 05/20] qdev/core: add monitor command to list all drivers
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (3 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 04/20] qdev/core: bus list Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 06/20] qdev/pci: misc fixes Gerd Hoffmann
` (15 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qdev.c | 10 ++++++++++
hw/qdev.h | 1 +
monitor.c | 2 ++
3 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index 1fb73b1..768431c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -419,3 +419,13 @@ void do_info_qbus(Monitor *mon)
bus->parent ? bus->parent->info->name : "<none>");
}
}
+
+void do_info_qdrv(Monitor *mon)
+{
+ DeviceInfo *info;
+
+ for (info = device_info_list; info != NULL; info = info->next) {
+ monitor_printf(mon, "name \"%s\", bus %s\n",
+ info->name, info->bus_info->name);
+ }
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index c4b04c1..2f4e4a4 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -128,5 +128,6 @@ BusState *qbus_find(const char *type, const char *name, int busnr);
void do_info_qtree(Monitor *mon);
void do_info_qbus(Monitor *mon);
+void do_info_qdrv(Monitor *mon);
#endif
diff --git a/monitor.c b/monitor.c
index b1da695..b91fef6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1743,6 +1743,8 @@ static const mon_cmd_t info_cmds[] = {
"", "show device tree" },
{ "qbus", "", do_info_qbus,
"", "show qdev bus list" },
+ { "qdrv", "", do_info_qdrv,
+ "", "show qdev driver list" },
{ NULL, NULL, },
};
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 06/20] qdev/pci: misc fixes.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (4 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 05/20] qdev/core: add monitor command to list all drivers Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 07/20] qdev/pci: hook up i440fx Gerd Hoffmann
` (14 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
* use core busnr.
* fix secondary bus setup.
* use base->name instead of "FIXME" for device name.
Yes, the device name is redundant. Only for drivers converted
to qdev already though. Once all drivers are converted we can
and should kill it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/pci.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index c537ed0..5925617 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -115,7 +115,6 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
qemu_irq *pic, int devfn_min, int nirq)
{
PCIBus *bus;
- static int nbus = 0;
bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name));
bus->set_irq = set_irq;
@@ -126,7 +125,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
bus->irq_count = qemu_malloc(nirq * sizeof(bus->irq_count[0]));
bus->next = first_bus;
first_bus = bus;
- register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
+ register_savevm("PCIBUS", bus->qbus.busnr, 1, pcibus_save, pcibus_load, bus);
qemu_register_reset(pci_bus_reset, 0, bus);
return bus;
}
@@ -134,7 +133,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
{
PCIBus *bus;
- bus = qemu_mallocz(sizeof(PCIBus));
+
+ bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, NULL));
bus->map_irq = map_irq;
bus->parent_dev = dev;
bus->next = dev->bus->next;
@@ -954,7 +954,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
devfn = qdev_get_prop_int(qdev, "devfn", -1);
- pci_dev = do_pci_register_device(pci_dev, bus, "FIXME", devfn,
+ pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
info->config_read, info->config_write);
assert(pci_dev);
info->init(pci_dev);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 07/20] qdev/pci: hook up i440fx.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (5 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 06/20] qdev/pci: misc fixes Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 08/20] qdev: convert piix-ide Gerd Hoffmann
` (13 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hook i44fx pcihost into sysbus.
Convert Host bridge and ISA bridge pci devices to qdev.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/pci_host.h | 3 ++
hw/piix_pci.c | 95 +++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 72 insertions(+), 26 deletions(-)
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 757b0e2..48862b5 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -28,6 +28,8 @@
/* debug PCI */
//#define DEBUG_PCI
+#include "sysbus.h"
+
#ifdef DEBUG_PCI
#define PCI_DPRINTF(fmt, ...) \
do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
@@ -36,6 +38,7 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
#endif
typedef struct {
+ SysBusDevice busdev;
uint32_t config_reg;
PCIBus *bus;
} PCIHostState;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 67e6309..1cbc5c3 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -25,6 +25,7 @@
#include "hw.h"
#include "pc.h"
#include "pci.h"
+#include "sysbus.h"
typedef uint32_t pci_addr_t;
#include "pci_host.h"
@@ -169,16 +170,9 @@ static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
return 0;
}
-PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
+static void i440fx_pcihost_initfn(SysBusDevice *dev)
{
- PCIBus *b;
- PCIDevice *d;
- I440FXState *s;
-
- s = qemu_mallocz(sizeof(I440FXState));
- b = pci_register_bus(NULL, "pci",
- piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
- s->bus = b;
+ I440FXState *s = FROM_SYSBUS(I440FXState, dev);
register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
@@ -189,10 +183,10 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+}
- d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
- NULL, i440fx_write_config);
-
+static void i440fx_initfn(PCIDevice *d)
+{
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441);
d->config[0x08] = 0x02; // revision
@@ -202,7 +196,25 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
d->config[0x72] = 0x02; /* SMRAM */
register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
+}
+
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
+{
+ DeviceState *dev;
+ PCIBus *b;
+ PCIDevice *d;
+ I440FXState *s;
+
+ dev = qdev_create(NULL, "i440FX-pcihost");
+ s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
+ b = pci_register_bus(&s->busdev.qdev, NULL,
+ piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
+ s->bus = b;
+ qdev_init(dev);
+
+ d = pci_create_simple(b, 0, "i440FX");
*pi440fx_state = d;
+
return b;
}
@@ -326,49 +338,80 @@ static int piix_load(QEMUFile* f, void *opaque, int version_id)
return pci_device_load(d, f);
}
-int piix3_init(PCIBus *bus, int devfn)
+static void piix3_initfn(PCIDevice *d)
{
- PCIDevice *d;
uint8_t *pci_conf;
- d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
- devfn, NULL, NULL);
register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
- piix3_dev = d;
pci_conf = d->config;
-
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
pci_conf[PCI_HEADER_TYPE] =
PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
+ piix3_dev = d;
piix3_reset(d);
qemu_register_reset(piix3_reset, 0, d);
- return d->devfn;
}
-int piix4_init(PCIBus *bus, int devfn)
+static void piix4_initfn(PCIDevice *d)
{
- PCIDevice *d;
uint8_t *pci_conf;
- d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
- devfn, NULL, NULL);
register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
- piix4_dev = d;
pci_conf = d->config;
-
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
pci_conf[PCI_HEADER_TYPE] =
PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
-
+ piix4_dev = d;
piix4_reset(d);
qemu_register_reset(piix4_reset, 0, d);
+}
+
+int piix3_init(PCIBus *bus, int devfn)
+{
+ PCIDevice *d;
+
+ d = pci_create_simple(bus, devfn, "PIIX3");
return d->devfn;
}
+
+int piix4_init(PCIBus *bus, int devfn)
+{
+ PCIDevice *d;
+
+ d = pci_create_simple(bus, devfn, "PIIX4");
+ return d->devfn;
+}
+
+static PCIDeviceInfo i440fx_info[] = {
+ {
+ .qdev.name = "i440FX",
+ .qdev.size = sizeof(PCIDevice),
+ .init = i440fx_initfn,
+ .config_write = i440fx_write_config,
+ },{
+ .qdev.name = "PIIX3",
+ .qdev.size = sizeof(PCIDevice),
+ .init = piix3_initfn,
+ },{
+ .qdev.name = "PIIX4",
+ .qdev.size = sizeof(PCIDevice),
+ .init = piix4_initfn,
+ },{
+ /* end of list */
+ }
+};
+
+static void i440fx_register(void)
+{
+ sysbus_register_dev("i440FX-pcihost", sizeof(I440FXState), i440fx_pcihost_initfn);
+ pci_qdev_register_many(i440fx_info);
+}
+device_init(i440fx_register);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 08/20] qdev: convert piix-ide.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (6 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 07/20] qdev/pci: hook up i440fx Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 09/20] qdev: convert piix acpi Gerd Hoffmann
` (12 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hook up pci device into qdev.
First step only: no ide bus yet.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/ide.c | 92 +++++++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 61 insertions(+), 31 deletions(-)
diff --git a/hw/ide.c b/hw/ide.c
index f3787f2..3bc75fa 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -3360,20 +3360,11 @@ static void piix3_reset(void *opaque)
pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
}
-/* hd_table must contain 4 block drivers */
-/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
-void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
- qemu_irq *pic)
+static void pci_piix3_ide_initfn(PCIDevice *dev)
{
- PCIIDEState *d;
+ PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
uint8_t *pci_conf;
- int i;
- /* register a function 1 of PIIX3 */
- d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
- sizeof(PCIIDEState),
- devfn,
- NULL, NULL);
d->type = IDE_TYPE_PIIX3;
pci_conf = d->dev.config;
@@ -3389,31 +3380,14 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
pci_register_bar((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, bmdma_map);
- ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
- ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
- ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
- ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
-
- for (i = 0; i < 4; i++)
- if (hd_table[i])
- hd_table[i]->private = &d->dev;
-
register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
}
-/* hd_table must contain 4 block drivers */
-/* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */
-void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
- qemu_irq *pic)
+static void pci_piix4_ide_initfn(PCIDevice *dev)
{
- PCIIDEState *d;
+ PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
uint8_t *pci_conf;
- /* register a function 1 of PIIX4 */
- d = (PCIIDEState *)pci_register_device(bus, "PIIX4 IDE",
- sizeof(PCIIDEState),
- devfn,
- NULL, NULL);
d->type = IDE_TYPE_PIIX4;
pci_conf = d->dev.config;
@@ -3429,13 +3403,69 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
pci_register_bar((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, bmdma_map);
+ register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+ qemu_irq *pic)
+{
+ PCIDevice *dev;
+ PCIIDEState *d;
+ int i;
+
+ dev = pci_create_simple(bus, devfn, "PIIX3 IDE");
+ d = DO_UPCAST(PCIIDEState, dev, dev);
+
+ /* TODO: ide bus */
ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
- register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
+ for (i = 0; i < 4; i++)
+ if (hd_table[i])
+ hd_table[i]->private = &d->dev;
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */
+void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+ qemu_irq *pic)
+{
+ PCIDevice *dev;
+ PCIIDEState *d;
+
+ dev = pci_create_simple(bus, devfn, "PIIX4 IDE");
+ d = DO_UPCAST(PCIIDEState, dev, dev);
+
+ /* TODO: ide bus */
+ ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+ ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+ ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+ ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+}
+
+static PCIDeviceInfo piix_ide_info[] = {
+ {
+ .qdev.name = "PIIX3 IDE",
+ .qdev.size = sizeof(PCIIDEState),
+ .init = pci_piix3_ide_initfn,
+ },{
+ .qdev.name = "PIIX4 IDE",
+ .qdev.size = sizeof(PCIIDEState),
+ .init = pci_piix4_ide_initfn,
+ },{
+ /* end of list */
+ }
+};
+
+static void piix_ide_register(void)
+{
+ pci_qdev_register_many(piix_ide_info);
}
+device_init(piix_ide_register);
#if defined(TARGET_PPC)
/***********************************************************/
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 09/20] qdev: convert piix acpi.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (7 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 08/20] qdev: convert piix-ide Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 10/20] qdev: convert all vga Gerd Hoffmann
` (11 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hook up pci device and smbus into qdev.
TODO: smbus creation is still hardcoded.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/acpi.c | 46 ++++++++++++++++++++++++++++++++++------------
1 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/hw/acpi.c b/hw/acpi.c
index 5928fe7..f76ca0c 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -497,15 +497,11 @@ static void piix4_reset(void *opaque)
}
}
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- qemu_irq sci_irq)
+static void piix4_pm_initfn(PCIDevice *dev)
{
- PIIX4PMState *s;
- uint8_t *pci_conf;
+ PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
+ uint8_t *pci_conf = s->dev.config;
- s = (PIIX4PMState *)pci_register_device(bus,
- "PM", sizeof(PIIX4PMState),
- devfn, NULL, pm_write_config);
pm_state = s;
pci_conf = s->dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
@@ -538,23 +534,49 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
(serial_hds[1] != NULL ? 0x90 : 0);
+ s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
+
+ register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
+
+}
+
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+ qemu_irq sci_irq)
+{
+ PCIDevice *dev;
+ PIIX4PMState *s;
+ uint8_t *pci_conf;
+
+ dev = pci_create_simple(bus, devfn, "PM");
+ s = DO_UPCAST(PIIX4PMState, dev, dev);
+
+ pci_conf = s->dev.config;
pci_conf[0x90] = smb_io_base | 1;
pci_conf[0x91] = smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+ s->smbus = i2c_init_bus(&s->dev.qdev, "i2c");
- s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
-
- register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
-
- s->smbus = i2c_init_bus(NULL, "i2c");
s->irq = sci_irq;
qemu_register_reset(piix4_reset, 0, s);
return s->smbus;
}
+static PCIDeviceInfo acpi_info = {
+ .qdev.name = "PM",
+ .qdev.size = sizeof(PIIX4PMState),
+ .init = piix4_pm_initfn,
+ .config_write = pm_write_config,
+};
+
+static void acpi_register(void)
+{
+ pci_qdev_register(&acpi_info);
+}
+device_init(acpi_register);
+
#if defined(TARGET_I386)
void qemu_system_powerdown(void)
{
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 10/20] qdev: convert all vga
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (8 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 09/20] qdev: convert piix acpi Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 11/20] qdev: convert es1370 Gerd Hoffmann
` (10 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/cirrus_vga.c | 85 ++++++++++++++++++++++++++++++------------------------
hw/vga.c | 66 ++++++++++++++++++++++++++----------------
hw/vmware_vga.c | 26 +++++++++++++----
3 files changed, 108 insertions(+), 69 deletions(-)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 0a12782..19d3fd9 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3301,46 +3301,55 @@ static void pci_cirrus_write_config(PCIDevice *d,
cirrus_update_memory_access(s);
}
+static void pci_cirrus_vga_initfn(PCIDevice *dev)
+{
+ PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
+ CirrusVGAState *s = &d->cirrus_vga;
+ uint8_t *pci_conf = d->dev.config;
+ int device_id = CIRRUS_ID_CLGD5446;
+
+ /* setup VGA */
+ vga_common_init(&s->vga, VGA_RAM_SIZE);
+ cirrus_init_common(s, device_id, 1);
+ s->vga.pci_dev = (PCIDevice *)d;
+ s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
+ s->vga.screen_dump, s->vga.text_update,
+ &s->vga);
+
+ /* setup PCI */
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS);
+ pci_config_set_device_id(pci_conf, device_id);
+ pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
+ pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+
+ /* setup memory space */
+ /* memory #0 LFB */
+ /* memory #1 memory-mapped I/O */
+ /* XXX: s->vga.vram_size must be a power of two */
+ pci_register_bar((PCIDevice *)d, 0, 0x2000000,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
+ if (device_id == CIRRUS_ID_CLGD5446) {
+ pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
+ PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+ }
+ /* XXX: ROM BIOS */
+}
+
void pci_cirrus_vga_init(PCIBus *bus)
{
- PCICirrusVGAState *d;
- uint8_t *pci_conf;
- CirrusVGAState *s;
- int device_id;
-
- device_id = CIRRUS_ID_CLGD5446;
-
- /* setup PCI configuration registers */
- d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
- sizeof(PCICirrusVGAState),
- -1, NULL, pci_cirrus_write_config);
- pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS);
- pci_config_set_device_id(pci_conf, device_id);
- pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
- pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
- pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
-
- /* setup VGA */
- s = &d->cirrus_vga;
- vga_common_init(&s->vga, VGA_RAM_SIZE);
- cirrus_init_common(s, device_id, 1);
-
- s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
- s->vga.screen_dump, s->vga.text_update,
- &s->vga);
+ pci_create_simple(bus, -1, "Cirrus VGA");
+}
- s->vga.pci_dev = (PCIDevice *)d;
+static PCIDeviceInfo cirrus_vga_info = {
+ .qdev.name = "Cirrus VGA",
+ .qdev.size = sizeof(PCICirrusVGAState),
+ .init = pci_cirrus_vga_initfn,
+ .config_write = pci_cirrus_write_config,
+};
- /* setup memory space */
- /* memory #0 LFB */
- /* memory #1 memory-mapped I/O */
- /* XXX: s->vga.vram_size must be a power of two */
- pci_register_bar((PCIDevice *)d, 0, 0x2000000,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
- if (device_id == CIRRUS_ID_CLGD5446) {
- pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
- PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
- }
- /* XXX: ROM BIOS */
+static void cirrus_vga_register(void)
+{
+ pci_qdev_register(&cirrus_vga_info);
}
+device_init(cirrus_vga_register);
diff --git a/hw/vga.c b/hw/vga.c
index 134ad16..063fa5f 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2480,38 +2480,41 @@ static void pci_vga_write_config(PCIDevice *d,
s->map_addr = 0;
}
+static void pci_vga_initfn(PCIDevice *dev)
+{
+ PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
+ VGAState *s = &d->vga_state;
+ uint8_t *pci_conf = d->dev.config;
+
+ // vga + console init
+ vga_common_init(s, VGA_RAM_SIZE);
+ vga_init(s);
+ s->pci_dev = &d->dev;
+ s->ds = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
+
+ // dummy VGA (same as Bochs ID)
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
+ pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+
+ /* XXX: VGA_RAM_SIZE must be a power of two */
+ pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+}
+
int pci_vga_init(PCIBus *bus,
unsigned long vga_bios_offset, int vga_bios_size)
{
+ PCIDevice *dev;
PCIVGAState *d;
VGAState *s;
- uint8_t *pci_conf;
- d = (PCIVGAState *)pci_register_device(bus, "VGA",
- sizeof(PCIVGAState),
- -1, NULL, pci_vga_write_config);
- if (!d)
- return -1;
+ dev = pci_create_simple(bus, -1, "VGA");
+ d = DO_UPCAST(PCIVGAState, dev, dev);
s = &d->vga_state;
- vga_common_init(s, VGA_RAM_SIZE);
- vga_init(s);
-
- s->ds = graphic_console_init(s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
-
- s->pci_dev = &d->dev;
-
- pci_conf = d->dev.config;
- // dummy VGA (same as Bochs ID)
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
- pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
- pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
-
- /* XXX: VGA_RAM_SIZE must be a power of two */
- pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
if (vga_bios_size != 0) {
unsigned int bios_total_size;
s->bios_offset = vga_bios_offset;
@@ -2521,11 +2524,24 @@ int pci_vga_init(PCIBus *bus,
while (bios_total_size < vga_bios_size)
bios_total_size <<= 1;
pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
}
return 0;
}
+static PCIDeviceInfo vga_info = {
+ .qdev.name = "VGA",
+ .qdev.size = sizeof(PCIVGAState),
+ .init = pci_vga_initfn,
+ .config_write = pci_vga_write_config,
+};
+
+static void vga_register(void)
+{
+ pci_qdev_register(&vga_info);
+}
+device_init(vga_register);
+
/********************************************************/
/* vga screen dump */
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index accdac4..5ceebf1 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1210,14 +1210,11 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
iomemtype);
}
-void pci_vmsvga_init(PCIBus *bus)
+static void pci_vmsvga_initfn(PCIDevice *dev)
{
- struct pci_vmsvga_state_s *s;
+ struct pci_vmsvga_state_s *s =
+ DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
- /* Setup PCI configuration */
- s = (struct pci_vmsvga_state_s *)
- pci_register_device(bus, "QEMUware SVGA",
- sizeof(struct pci_vmsvga_state_s), -1, NULL, NULL);
pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
s->card.config[PCI_COMMAND] = 0x07; /* I/O + Memory */
@@ -1240,3 +1237,20 @@ void pci_vmsvga_init(PCIBus *bus)
register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
}
+
+void pci_vmsvga_init(PCIBus *bus)
+{
+ pci_create_simple(bus, -1, "QEMUware SVGA");
+}
+
+static PCIDeviceInfo vmsvga_info = {
+ .qdev.name = "QEMUware SVGA",
+ .qdev.size = sizeof(struct pci_vmsvga_state_s),
+ .init = pci_vmsvga_initfn,
+};
+
+static void vmsvga_register(void)
+{
+ pci_qdev_register(&vmsvga_info);
+}
+device_init(vmsvga_register);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 11/20] qdev: convert es1370.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (9 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 10/20] qdev: convert all vga Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 12/20] qdev: convert ac97 Gerd Hoffmann
` (9 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/es1370.c | 41 ++++++++++++++++++++++-------------------
1 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/hw/es1370.c b/hw/es1370.c
index af2667b..f0f4286 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1005,27 +1005,12 @@ static void es1370_on_reset (void *opaque)
es1370_reset (s);
}
-int es1370_init (PCIBus *bus)
+static void es1370_initfn(PCIDevice *dev)
{
- PCIES1370State *d;
- ES1370State *s;
- uint8_t *c;
-
- if (!bus) {
- dolog ("No PCI bus\n");
- return -1;
- }
-
- d = (PCIES1370State *) pci_register_device (bus, "ES1370",
- sizeof (PCIES1370State),
- -1, NULL, NULL);
-
- if (!d) {
- AUD_log (NULL, "Failed to register PCI device for ES1370\n");
- return -1;
- }
+ PCIES1370State *d = DO_UPCAST(PCIES1370State, dev, dev);
+ ES1370State *s = &d->es1370;
+ uint8_t *c = d->dev.config;
- c = d->dev.config;
pci_config_set_vendor_id (c, PCI_VENDOR_ID_ENSONIQ);
pci_config_set_device_id (c, PCI_DEVICE_ID_ENSONIQ_ES1370);
c[0x07] = 2 << 1;
@@ -1059,5 +1044,23 @@ int es1370_init (PCIBus *bus)
AUD_register_card ("es1370", &s->card);
es1370_reset (s);
+}
+
+int es1370_init (PCIBus *bus)
+{
+ pci_create_simple(bus, -1, "ES1370");
return 0;
}
+
+static PCIDeviceInfo es1370_info = {
+ .qdev.name = "ES1370",
+ .qdev.size = sizeof(PCIES1370State),
+ .init = es1370_initfn,
+};
+
+static void es1370_register(void)
+{
+ pci_qdev_register(&es1370_info);
+}
+device_init(es1370_register);
+
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 12/20] qdev: convert ac97.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (10 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 11/20] qdev: convert es1370 Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 13/20] qdev: convert uhci Gerd Hoffmann
` (8 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/ac97.c | 42 ++++++++++++++++++++++--------------------
1 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/hw/ac97.c b/hw/ac97.c
index b911308..d25ba71 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1308,29 +1308,13 @@ static void ac97_on_reset (void *opaque)
mixer_reset (s);
}
-int ac97_init (PCIBus *bus)
+static void ac97_initfn(PCIDevice *dev)
{
- PCIAC97LinkState *d;
- AC97LinkState *s;
- uint8_t *c;
-
- if (!bus) {
- AUD_log ("ac97", "No PCI bus\n");
- return -1;
- }
-
- d = (PCIAC97LinkState *) pci_register_device (bus, "AC97",
- sizeof (PCIAC97LinkState),
- -1, NULL, NULL);
-
- if (!d) {
- AUD_log ("ac97", "Failed to register PCI device\n");
- return -1;
- }
+ PCIAC97LinkState *d = DO_UPCAST(PCIAC97LinkState, dev, dev);
+ AC97LinkState *s = &d->ac97;
+ uint8_t *c = d->dev.config;
- s = &d->ac97;
s->pci_dev = &d->dev;
- c = d->dev.config;
pci_config_set_vendor_id (c, PCI_VENDOR_ID_INTEL); /* ro */
pci_config_set_device_id (c, PCI_DEVICE_ID_INTEL_82801AA_5); /* ro */
@@ -1372,5 +1356,23 @@ int ac97_init (PCIBus *bus)
qemu_register_reset (ac97_on_reset, 0, s);
AUD_register_card ("ac97", &s->card);
ac97_on_reset (s);
+}
+
+int ac97_init (PCIBus *bus)
+{
+ pci_create_simple(bus, -1, "AC97");
return 0;
}
+
+static PCIDeviceInfo ac97_info = {
+ .qdev.name = "AC97",
+ .qdev.size = sizeof(PCIAC97LinkState),
+ .init = ac97_initfn,
+};
+
+static void ac97_register(void)
+{
+ pci_qdev_register(&ac97_info);
+}
+device_init(ac97_register);
+
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 13/20] qdev: convert uhci.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (11 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 12/20] qdev: convert ac97 Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 14/20] qdev/usb: add usb bus support to qdev, convert drivers Gerd Hoffmann
` (7 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hookup pci device into qdev.
No usb bus yet, see following patches.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-uhci.c | 74 +++++++++++++++++++++++++++++++-------------------------
1 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index ea83bdc..9ec270e 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1070,18 +1070,11 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
}
-void usb_uhci_piix3_init(PCIBus *bus, int devfn)
+static void usb_uhci_common_initfn(UHCIState *s)
{
- UHCIState *s;
- uint8_t *pci_conf;
+ uint8_t *pci_conf = s->dev.config;
int i;
- s = (UHCIState *)pci_register_device(bus,
- "USB-UHCI", sizeof(UHCIState),
- devfn, NULL, NULL);
- pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_2);
pci_conf[0x08] = 0x01; // revision number
pci_conf[0x09] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
@@ -1105,37 +1098,52 @@ void usb_uhci_piix3_init(PCIBus *bus, int devfn)
register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
}
-void usb_uhci_piix4_init(PCIBus *bus, int devfn)
+static void usb_uhci_piix3_initfn(PCIDevice *dev)
{
- UHCIState *s;
- uint8_t *pci_conf;
- int i;
+ UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+ uint8_t *pci_conf = s->dev.config;
+
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_2);
+ usb_uhci_common_initfn(s);
+}
+
+static void usb_uhci_piix4_initfn(PCIDevice *dev)
+{
+ UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+ uint8_t *pci_conf = s->dev.config;
- s = (UHCIState *)pci_register_device(bus,
- "USB-UHCI", sizeof(UHCIState),
- devfn, NULL, NULL);
- pci_conf = s->dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_2);
- pci_conf[0x08] = 0x01; // revision number
- pci_conf[0x09] = 0x00;
- pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
- pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
- pci_conf[0x3d] = 4; // interrupt pin 3
- pci_conf[0x60] = 0x10; // release number
+ usb_uhci_common_initfn(s);
+}
- for(i = 0; i < NB_PORTS; i++) {
- qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
+static PCIDeviceInfo uhci_info[] = {
+ {
+ .qdev.name = "PIIX3 USB-UHCI",
+ .qdev.size = sizeof(UHCIState),
+ .init = usb_uhci_piix3_initfn,
+ },{
+ .qdev.name = "PIIX4 USB-UHCI",
+ .qdev.size = sizeof(UHCIState),
+ .init = usb_uhci_piix4_initfn,
+ },{
+ /* end of list */
}
- s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
+};
- qemu_register_reset(uhci_reset, 0, s);
- uhci_reset(s);
+static void uhci_register(void)
+{
+ pci_qdev_register_many(uhci_info);
+}
+device_init(uhci_register);
- /* Use region 4 for consistency with real hardware. BSD guests seem
- to rely on this. */
- pci_register_bar(&s->dev, 4, 0x20,
- PCI_ADDRESS_SPACE_IO, uhci_map);
+void usb_uhci_piix3_init(PCIBus *bus, int devfn)
+{
+ pci_create_simple(bus, devfn, "PIIX3 USB-UHCI");
+}
- register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
+void usb_uhci_piix4_init(PCIBus *bus, int devfn)
+{
+ pci_create_simple(bus, devfn, "PIIX4 USB-UHCI");
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 14/20] qdev/usb: add usb bus support to qdev, convert drivers.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (12 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 13/20] qdev: convert uhci Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 15/20] qdev/usb: make qemu aware of usb busses Gerd Hoffmann
` (6 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
* Add USBBus.
* Add USBDeviceInfo, move device callbacks here.
* Add usb-qdev helper functions.
* Switch drivers to qdev.
TODO:
* make the rest of qemu aware of usb busses and kill the FIXMEs
added by this patch.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
Makefile | 2 +-
hw/bt-hid.c | 18 +++++-----
hw/usb-bt.c | 37 ++++++++++++++-----
hw/usb-bus.c | 65 ++++++++++++++++++++++++++++++++++
hw/usb-hid.c | 105 ++++++++++++++++++++++++++++++++-----------------------
hw/usb-hub.c | 48 +++++++++++++++----------
hw/usb-msd.c | 44 +++++++++++++++--------
hw/usb-musb.c | 2 +-
hw/usb-net.c | 44 ++++++++++++++++-------
hw/usb-ohci.c | 4 +-
hw/usb-serial.c | 47 ++++++++++++++++--------
hw/usb-uhci.c | 4 ++-
hw/usb-wacom.c | 33 +++++++++++------
hw/usb.c | 16 ++++----
hw/usb.h | 62 ++++++++++++++++++++------------
usb-linux.c | 52 +++++++++++++++++++--------
vl.c | 4 +-
17 files changed, 394 insertions(+), 193 deletions(-)
create mode 100644 hw/usb-bus.c
diff --git a/Makefile b/Makefile
index a06c9bf..e150ab1 100644
--- a/Makefile
+++ b/Makefile
@@ -103,7 +103,7 @@ OBJS+=tmp105.o lm832x.o eeprom93xx.o tsc2005.o
OBJS+=scsi-disk.o cdrom.o
OBJS+=scsi-generic.o
OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-OBJS+=usb-serial.o usb-net.o
+OBJS+=usb-serial.o usb-net.o usb-bus.o
OBJS+=sd.o ssi-sd.o
OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
OBJS+=bt-hci-csr.o
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index af0c3d5..97c8d79 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -112,7 +112,7 @@ static void bt_hid_reset(struct bt_hid_device_s *s)
bt_l2cap_device_done(&s->btdev);
bt_l2cap_device_init(&s->btdev, net);
- s->usbdev->handle_reset(s->usbdev);
+ s->usbdev->info->handle_reset(s->usbdev);
s->proto = BT_HID_PROTO_REPORT;
s->state = bt_state_ready;
s->dataother.len = 0;
@@ -132,7 +132,7 @@ static int bt_hid_out(struct bt_hid_device_s *s)
p.devep = 1;
p.data = s->dataout.buffer;
p.len = s->dataout.len;
- s->dataout.len = s->usbdev->handle_data(s->usbdev, &p);
+ s->dataout.len = s->usbdev->info->handle_data(s->usbdev, &p);
return s->dataout.len;
}
@@ -155,7 +155,7 @@ static int bt_hid_in(struct bt_hid_device_s *s)
p.devep = 1;
p.data = s->datain.buffer;
p.len = sizeof(s->datain.buffer);
- s->datain.len = s->usbdev->handle_data(s->usbdev, &p);
+ s->datain.len = s->usbdev->info->handle_data(s->usbdev, &p);
return s->datain.len;
}
@@ -324,8 +324,8 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
break;
}
s->proto = parameter;
- s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
- NULL);
+ s->usbdev->info->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
+ NULL);
ret = BT_HS_SUCCESSFUL;
break;
@@ -334,7 +334,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
ret = BT_HS_ERR_INVALID_PARAMETER;
break;
}
- s->usbdev->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
+ s->usbdev->info->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
s->control->sdu_out(s->control, 1));
s->control->sdu_submit(s->control);
break;
@@ -347,7 +347,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
/* We don't need to know about the Idle Rate here really,
* so just pass it on to the device. */
- ret = s->usbdev->handle_control(s->usbdev,
+ ret = s->usbdev->info->handle_control(s->usbdev,
SET_IDLE, data[1], 0, 0, NULL) ?
BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
/* XXX: Does this generate a handshake? */
@@ -451,7 +451,7 @@ static void bt_hid_connected_update(struct bt_hid_device_s *hid)
hid->btdev.device.inquiry_scan = !hid->connected;
if (hid->connected && !prev) {
- hid->usbdev->handle_reset(hid->usbdev);
+ hid->usbdev->info->handle_reset(hid->usbdev);
hid->proto = BT_HID_PROTO_REPORT;
}
@@ -519,7 +519,7 @@ static void bt_hid_destroy(struct bt_device_s *dev)
bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
bt_l2cap_device_done(&hid->btdev);
- hid->usbdev->handle_destroy(hid->usbdev);
+ hid->usbdev->info->handle_destroy(hid->usbdev);
qemu_free(hid);
}
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 53ad9a8..f1d237b 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -618,22 +618,22 @@ static void usb_bt_handle_destroy(USBDevice *dev)
qemu_free(s);
}
+static void usb_bt_initfn(USBDevice *dev)
+{
+ struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
+ s->dev.speed = USB_SPEED_HIGH;
+}
+
USBDevice *usb_bt_init(HCIInfo *hci)
{
+ USBDevice *dev;
struct USBBtState *s;
if (!hci)
return NULL;
- s = qemu_mallocz(sizeof(struct USBBtState));
+ dev = usb_create_simple(NULL /* FIXME */, "QEMU BT dongle");
+ s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.opaque = s;
- s->dev.speed = USB_SPEED_HIGH;
- s->dev.handle_packet = usb_generic_handle_packet;
- pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU BT dongle");
-
- s->dev.handle_reset = usb_bt_handle_reset;
- s->dev.handle_control = usb_bt_handle_control;
- s->dev.handle_data = usb_bt_handle_data;
- s->dev.handle_destroy = usb_bt_handle_destroy;
s->hci = hci;
s->hci->opaque = s;
@@ -642,5 +642,22 @@ USBDevice *usb_bt_init(HCIInfo *hci)
usb_bt_handle_reset(&s->dev);
- return &s->dev;
+ return dev;
+}
+
+static struct USBDeviceInfo bt_info = {
+ .qdev.name = "QEMU BT dongle",
+ .qdev.size = sizeof(struct USBBtState),
+ .init = usb_bt_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_bt_handle_reset,
+ .handle_control = usb_bt_handle_control,
+ .handle_data = usb_bt_handle_data,
+ .handle_destroy = usb_bt_handle_destroy,
+};
+
+static void usb_bt_register_devices(void)
+{
+ usb_qdev_register(&bt_info);
}
+device_init(usb_bt_register_devices)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
new file mode 100644
index 0000000..669c1f7
--- /dev/null
+++ b/hw/usb-bus.c
@@ -0,0 +1,65 @@
+#include "hw.h"
+#include "usb.h"
+#include "qdev.h"
+
+static struct BusInfo usb_bus_info = {
+ .name = "USB",
+ .size = sizeof(USBBus),
+};
+static int next_usb_bus = 0;
+static USBBus *usbbus; /* hack alert */
+
+USBBus *usb_bus_new(DeviceState *host)
+{
+ USBBus *bus;
+ char name[32];
+
+ snprintf(name, sizeof(name), "usb%d", next_usb_bus);
+ bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, name));
+ if (!usbbus)
+ usbbus = bus;
+ next_usb_bus++;
+ return bus;
+}
+
+static void usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+ USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
+
+ pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
+ dev->info = info;
+ dev->info->init(dev);
+}
+
+void usb_qdev_register(USBDeviceInfo *info)
+{
+ info->qdev.bus_info = &usb_bus_info;
+ info->qdev.init = usb_qdev_init;
+ qdev_register(&info->qdev);
+}
+
+void usb_qdev_register_many(USBDeviceInfo *info)
+{
+ while (info->qdev.name) {
+ usb_qdev_register(info);
+ info++;
+ }
+}
+
+USBDevice *usb_create_simple(USBBus *bus, const char *name)
+{
+ DeviceState *dev;
+
+#if 1
+ /* temporary stopgap until all usb is properly qdev-ified */
+ if (!bus)
+ bus = usbbus;
+ if (!bus)
+ bus = usb_bus_new(NULL);
+#endif
+
+ dev = qdev_create(&bus->qbus, name);
+ qdev_init(dev);
+ return DO_UPCAST(USBDevice, qdev, dev);
+}
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index c850a91..d4b2e1a 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -846,65 +846,43 @@ static void usb_hid_handle_destroy(USBDevice *dev)
qemu_free(s);
}
-USBDevice *usb_tablet_init(void)
+static void usb_hid_initfn(USBDevice *dev, int kind)
{
- USBHIDState *s;
-
- s = qemu_mallocz(sizeof(USBHIDState));
+ USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
-
- s->dev.handle_reset = usb_mouse_handle_reset;
- s->dev.handle_control = usb_hid_handle_control;
- s->dev.handle_data = usb_hid_handle_data;
- s->dev.handle_destroy = usb_hid_handle_destroy;
- s->kind = USB_TABLET;
+ s->kind = kind;
/* Force poll routine to be run and grab input the first time. */
s->changed = 1;
-
- pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
-
- return (USBDevice *)s;
}
-USBDevice *usb_mouse_init(void)
+static void usb_tablet_initfn(USBDevice *dev)
{
- USBHIDState *s;
+ usb_hid_initfn(dev, USB_TABLET);
+}
- s = qemu_mallocz(sizeof(USBHIDState));
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
+static void usb_mouse_initfn(USBDevice *dev)
+{
+ usb_hid_initfn(dev, USB_MOUSE);
+}
- s->dev.handle_reset = usb_mouse_handle_reset;
- s->dev.handle_control = usb_hid_handle_control;
- s->dev.handle_data = usb_hid_handle_data;
- s->dev.handle_destroy = usb_hid_handle_destroy;
- s->kind = USB_MOUSE;
- /* Force poll routine to be run and grab input the first time. */
- s->changed = 1;
+static void usb_keyboard_initfn(USBDevice *dev)
+{
+ usb_hid_initfn(dev, USB_KEYBOARD);
+}
- pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
+USBDevice *usb_tablet_init(void)
+{
+ return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet");
+}
- return (USBDevice *)s;
+USBDevice *usb_mouse_init(void)
+{
+ return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse");
}
USBDevice *usb_keyboard_init(void)
{
- USBHIDState *s;
-
- s = qemu_mallocz(sizeof(USBHIDState));
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
-
- s->dev.handle_reset = usb_keyboard_handle_reset;
- s->dev.handle_control = usb_hid_handle_control;
- s->dev.handle_data = usb_hid_handle_data;
- s->dev.handle_destroy = usb_hid_handle_destroy;
- s->kind = USB_KEYBOARD;
-
- pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
-
- return (USBDevice *) s;
+ return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
}
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
@@ -914,3 +892,42 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
s->datain_opaque = opaque;
s->datain = datain;
}
+
+static struct USBDeviceInfo hid_info[] = {
+ {
+ .qdev.name = "QEMU USB Tablet",
+ .qdev.size = sizeof(USBHIDState),
+ .init = usb_tablet_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_mouse_handle_reset,
+ .handle_control = usb_hid_handle_control,
+ .handle_data = usb_hid_handle_data,
+ .handle_destroy = usb_hid_handle_destroy,
+ },{
+ .qdev.name = "QEMU USB Mouse",
+ .qdev.size = sizeof(USBHIDState),
+ .init = usb_mouse_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_mouse_handle_reset,
+ .handle_control = usb_hid_handle_control,
+ .handle_data = usb_hid_handle_data,
+ .handle_destroy = usb_hid_handle_destroy,
+ },{
+ .qdev.name = "QEMU USB Keyboard",
+ .qdev.size = sizeof(USBHIDState),
+ .init = usb_keyboard_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_keyboard_handle_reset,
+ .handle_control = usb_hid_handle_control,
+ .handle_data = usb_hid_handle_data,
+ .handle_destroy = usb_hid_handle_destroy,
+ },{
+ /* end of list */
+ }
+};
+
+static void usb_hid_register_devices(void)
+{
+ usb_qdev_register_many(hid_info);
+}
+device_init(usb_hid_register_devices)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 9f26bbe..bd4eb31 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -486,7 +486,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
port = &s->ports[i];
dev = port->port.dev;
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
- ret = dev->handle_packet(dev, p);
+ ret = dev->info->handle_packet(dev, p);
if (ret != USB_RET_NODEV) {
return ret;
}
@@ -521,32 +521,40 @@ static void usb_hub_handle_destroy(USBDevice *dev)
qemu_free(s);
}
-USBDevice *usb_hub_init(int nb_ports)
+static void usb_hub_initfn(USBDevice *dev)
{
- USBHubState *s;
+ USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
USBHubPort *port;
int i;
- if (nb_ports > MAX_PORTS)
- return NULL;
- s = qemu_mallocz(sizeof(USBHubState));
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_hub_handle_packet;
-
- /* generic USB device init */
- s->dev.handle_reset = usb_hub_handle_reset;
- s->dev.handle_control = usb_hub_handle_control;
- s->dev.handle_data = usb_hub_handle_data;
- s->dev.handle_destroy = usb_hub_handle_destroy;
-
- pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
-
- s->nb_ports = nb_ports;
- for(i = 0; i < s->nb_ports; i++) {
+ s->dev.speed = USB_SPEED_FULL,
+ s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
+ for (i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
- return (USBDevice *)s;
}
+
+USBDevice *usb_hub_init(int nb_ports)
+{
+ return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub");
+}
+
+static struct USBDeviceInfo hub_info = {
+ .qdev.name = "QEMU USB Hub",
+ .qdev.size = sizeof(USBHubState),
+ .init = usb_hub_initfn,
+ .handle_packet = usb_hub_handle_packet,
+ .handle_reset = usb_hub_handle_reset,
+ .handle_control = usb_hub_handle_control,
+ .handle_data = usb_hub_handle_data,
+ .handle_destroy = usb_hub_handle_destroy,
+};
+
+static void usb_hub_register_devices(void)
+{
+ usb_qdev_register(&hub_info);
+}
+device_init(usb_hub_register_devices)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 3a3eb4a..535178f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -514,8 +514,16 @@ static void usb_msd_handle_destroy(USBDevice *dev)
qemu_free(s);
}
+static void usb_msd_initfn(USBDevice *dev)
+{
+ MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+ s->dev.speed = USB_SPEED_FULL;
+}
+
USBDevice *usb_msd_init(const char *filename)
{
+ USBDevice *dev;
MSDState *s;
BlockDriverState *bdrv;
BlockDriver *drv = NULL;
@@ -548,30 +556,19 @@ USBDevice *usb_msd_init(const char *filename)
return NULL;
}
- s = qemu_mallocz(sizeof(MSDState));
-
bdrv = bdrv_new("usb");
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
- goto fail;
- s->bs = bdrv;
-
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
-
- s->dev.handle_reset = usb_msd_handle_reset;
- s->dev.handle_control = usb_msd_handle_control;
- s->dev.handle_data = usb_msd_handle_data;
- s->dev.handle_destroy = usb_msd_handle_destroy;
+ return NULL;
+ dev = usb_create_simple(NULL /* FIXME */, "QEMU USB MSD");
+ s = DO_UPCAST(MSDState, dev, dev);
+ s->bs = bdrv;
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
filename);
s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);
usb_msd_handle_reset((USBDevice *)s);
return (USBDevice *)s;
- fail:
- qemu_free(s);
- return NULL;
}
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
@@ -580,3 +577,20 @@ BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
return s->bs;
}
+
+static struct USBDeviceInfo msd_info = {
+ .qdev.name = "QEMU USB MSD",
+ .qdev.size = sizeof(MSDState),
+ .init = usb_msd_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_msd_handle_reset,
+ .handle_control = usb_msd_handle_control,
+ .handle_data = usb_msd_handle_data,
+ .handle_destroy = usb_msd_handle_destroy,
+};
+
+static void usb_msd_register_devices(void)
+{
+ usb_qdev_register(&msd_info);
+}
+device_init(usb_msd_register_devices)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 451bc8d..bf9a555 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -591,7 +591,7 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->packey[dir].complete_opaque = ep;
if (s->port.dev)
- ret = s->port.dev->handle_packet(s->port.dev, &ep->packey[dir]);
+ ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir]);
else
ret = USB_RET_NODEV;
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 0e80ca6..fde814b 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1432,32 +1432,33 @@ static void usb_net_handle_destroy(USBDevice *dev)
qemu_del_vlan_client(s->vc);
}
-USBDevice *usb_net_init(NICInfo *nd)
+static void usb_net_initfn(USBDevice *dev)
{
- USBNetState *s;
-
- s = qemu_mallocz(sizeof(USBNetState));
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
+ USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
- s->dev.handle_reset = usb_net_handle_reset;
- s->dev.handle_control = usb_net_handle_control;
- s->dev.handle_data = usb_net_handle_data;
- s->dev.handle_destroy = usb_net_handle_destroy;
+ s->dev.speed = USB_SPEED_FULL;
s->rndis = 1;
s->rndis_state = RNDIS_UNINITIALIZED;
+ TAILQ_INIT(&s->rndis_resp);
+
s->medium = 0; /* NDIS_MEDIUM_802_3 */
s->speed = 1000000; /* 100MBps, in 100Bps units */
s->media_state = 0; /* NDIS_MEDIA_STATE_CONNECTED */;
s->filter = 0;
s->vendorid = 0x1234;
+}
+
+USBDevice *usb_net_init(NICInfo *nd)
+{
+ USBDevice *dev;
+ USBNetState *s;
+
+ dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface");
+ s = DO_UPCAST(USBNetState, dev, dev);
memcpy(s->mac, nd->macaddr, 6);
- TAILQ_INIT(&s->rndis_resp);
- pstrcpy(s->dev.devname, sizeof(s->dev.devname),
- "QEMU USB Network Interface");
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
usbnet_can_receive,
usbnet_receive,
@@ -1476,3 +1477,20 @@ USBDevice *usb_net_init(NICInfo *nd)
return (USBDevice *) s;
}
+
+static struct USBDeviceInfo net_info = {
+ .qdev.name = "QEMU USB Network Interface",
+ .qdev.size = sizeof(USBNetState),
+ .init = usb_net_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_net_handle_reset,
+ .handle_control = usb_net_handle_control,
+ .handle_data = usb_net_handle_data,
+ .handle_destroy = usb_net_handle_destroy,
+};
+
+static void usb_net_register_devices(void)
+{
+ usb_qdev_register(&net_info);
+}
+device_init(usb_net_register_devices)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c575480..8cc6677 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -755,7 +755,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
ohci->usb_packet.len = len;
ohci->usb_packet.complete_cb = ohci_async_complete_packet;
ohci->usb_packet.complete_opaque = ohci;
- ret = dev->handle_packet(dev, &ohci->usb_packet);
+ ret = dev->info->handle_packet(dev, &ohci->usb_packet);
if (ret != USB_RET_NODEV)
break;
}
@@ -945,7 +945,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
ohci->usb_packet.len = len;
ohci->usb_packet.complete_cb = ohci_async_complete_packet;
ohci->usb_packet.complete_opaque = ohci;
- ret = dev->handle_packet(dev, &ohci->usb_packet);
+ ret = dev->info->handle_packet(dev, &ohci->usb_packet);
if (ret != USB_RET_NODEV)
break;
}
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 19870a5..24de936 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -524,8 +524,15 @@ static void usb_serial_event(void *opaque, int event)
}
}
+static void usb_serial_initfn(USBDevice *dev)
+{
+ USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+ s->dev.speed = USB_SPEED_FULL;
+}
+
USBDevice *usb_serial_init(const char *filename)
{
+ USBDevice *dev;
USBSerialState *s;
CharDriverState *cdrv;
unsigned short vendorid = 0x0403, productid = 0x6001;
@@ -561,32 +568,40 @@ USBDevice *usb_serial_init(const char *filename)
return NULL;
}
filename++;
- s = qemu_mallocz(sizeof(USBSerialState));
snprintf(label, sizeof(label), "usbserial%d", index++);
cdrv = qemu_chr_open(label, filename, NULL);
if (!cdrv)
- goto fail;
- s->cs = cdrv;
- qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
-
- s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
-
- s->dev.handle_reset = usb_serial_handle_reset;
- s->dev.handle_control = usb_serial_handle_control;
- s->dev.handle_data = usb_serial_handle_data;
- s->dev.handle_destroy = usb_serial_handle_destroy;
+ return NULL;
+ dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Serial");
+ s = DO_UPCAST(USBSerialState, dev, dev);
+ s->cs = cdrv;
s->vendorid = vendorid;
s->productid = productid;
-
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
filename);
+ qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read,
+ usb_serial_event, s);
+
usb_serial_handle_reset((USBDevice *)s);
return (USBDevice *)s;
- fail:
- qemu_free(s);
- return NULL;
}
+
+static struct USBDeviceInfo serial_info = {
+ .qdev.name = "QEMU USB Serial",
+ .qdev.size = sizeof(USBSerialState),
+ .init = usb_serial_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_serial_handle_reset,
+ .handle_control = usb_serial_handle_control,
+ .handle_data = usb_serial_handle_data,
+ .handle_destroy = usb_serial_handle_destroy,
+};
+
+static void usb_serial_register_devices(void)
+{
+ usb_qdev_register(&serial_info);
+}
+device_init(usb_serial_register_devices)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 9ec270e..6daeb33 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -122,6 +122,7 @@ typedef struct UHCIPort {
typedef struct UHCIState {
PCIDevice dev;
+ USBBus *bus;
uint16_t cmd; /* cmd register */
uint16_t status;
uint16_t intr; /* interrupt enable register */
@@ -660,7 +661,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
USBDevice *dev = port->port.dev;
if (dev && (port->ctrl & UHCI_PORT_EN))
- ret = dev->handle_packet(dev, p);
+ ret = dev->info->handle_packet(dev, p);
}
dprintf("uhci: packet exit. ret %d len %d\n", ret, p->len);
@@ -1095,6 +1096,7 @@ static void usb_uhci_common_initfn(UHCIState *s)
pci_register_bar(&s->dev, 4, 0x20,
PCI_ADDRESS_SPACE_IO, uhci_map);
+ s->bus = usb_bus_new(&s->dev.qdev);
register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
}
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index eaf0d29..05b317a 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -392,21 +392,30 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
qemu_free(s);
}
-USBDevice *usb_wacom_init(void)
+static void usb_wacom_initfn(USBDevice *dev)
{
- USBWacomState *s;
-
- s = qemu_mallocz(sizeof(USBWacomState));
+ USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
- s->dev.handle_packet = usb_generic_handle_packet;
+}
- s->dev.handle_reset = usb_wacom_handle_reset;
- s->dev.handle_control = usb_wacom_handle_control;
- s->dev.handle_data = usb_wacom_handle_data;
- s->dev.handle_destroy = usb_wacom_handle_destroy;
+USBDevice *usb_wacom_init(void)
+{
+ return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet");
+}
- pstrcpy(s->dev.devname, sizeof(s->dev.devname),
- "QEMU PenPartner Tablet");
+static struct USBDeviceInfo wacom_info = {
+ .qdev.name = "QEMU PenPartner Tablet",
+ .qdev.size = sizeof(USBWacomState),
+ .init = usb_wacom_initfn,
+ .handle_packet = usb_generic_handle_packet,
+ .handle_reset = usb_wacom_handle_reset,
+ .handle_control = usb_wacom_handle_control,
+ .handle_data = usb_wacom_handle_data,
+ .handle_destroy = usb_wacom_handle_destroy,
+};
- return (USBDevice *) s;
+static void usb_wacom_register_devices(void)
+{
+ usb_qdev_register(&wacom_info);
}
+device_init(usb_wacom_register_devices)
diff --git a/hw/usb.c b/hw/usb.c
index c17266d..a326bcf 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -59,8 +59,8 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
if (s->setup_buf[0] & USB_DIR_IN) {
- ret = s->handle_control(s, request, value, index,
- s->setup_len, s->data_buf);
+ ret = s->info->handle_control(s, request, value, index,
+ s->setup_len, s->data_buf);
if (ret < 0)
return ret;
@@ -83,7 +83,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
int ret = 0;
if (p->devep != 0)
- return s->handle_data(s, p);
+ return s->info->handle_data(s, p);
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -93,8 +93,8 @@ static int do_token_in(USBDevice *s, USBPacket *p)
case SETUP_STATE_ACK:
if (!(s->setup_buf[0] & USB_DIR_IN)) {
s->setup_state = SETUP_STATE_IDLE;
- ret = s->handle_control(s, request, value, index,
- s->setup_len, s->data_buf);
+ ret = s->info->handle_control(s, request, value, index,
+ s->setup_len, s->data_buf);
if (ret > 0)
return 0;
return ret;
@@ -126,7 +126,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
static int do_token_out(USBDevice *s, USBPacket *p)
{
if (p->devep != 0)
- return s->handle_data(s, p);
+ return s->info->handle_data(s, p);
switch(s->setup_state) {
case SETUP_STATE_ACK:
@@ -179,7 +179,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
s->remote_wakeup = 0;
s->addr = 0;
s->state = USB_STATE_DEFAULT;
- s->handle_reset(s);
+ s->info->handle_reset(s);
return 0;
}
@@ -225,7 +225,7 @@ void usb_send_msg(USBDevice *dev, int msg)
USBPacket p;
memset(&p, 0, sizeof(p));
p.pid = msg;
- dev->handle_packet(dev, &p);
+ dev->info->handle_packet(dev, &p);
/* This _must_ be synchronous */
}
diff --git a/hw/usb.h b/hw/usb.h
index e9d4bc2..e39d917 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -23,6 +23,7 @@
*/
#include "block.h"
+#include "qdev.h"
#define USB_TOKEN_SETUP 0x2d
#define USB_TOKEN_IN 0x69 /* device -> host */
@@ -116,37 +117,52 @@
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
+typedef struct USBBus USBBus;
typedef struct USBPort USBPort;
typedef struct USBDevice USBDevice;
+typedef struct USBDeviceInfo USBDeviceInfo;
typedef struct USBPacket USBPacket;
/* definition of a USB device */
struct USBDevice {
+ DeviceState qdev;
+ USBDeviceInfo *info;
void *opaque;
- /*
- * Process USB packet.
+ int speed;
+ uint8_t addr;
+ char devname[32];
+
+ int state;
+ uint8_t setup_buf[8];
+ uint8_t data_buf[1024];
+ int remote_wakeup;
+ int setup_state;
+ int setup_len;
+ int setup_index;
+};
+
+struct USBDeviceInfo {
+ DeviceInfo qdev;
+ void (*init)(USBDevice *dev);
+
+ /*
+ * Process USB packet.
* Called by the HC (Host Controller).
*
- * Returns length of the transaction
+ * Returns length of the transaction
* or one of the USB_RET_XXX codes.
- */
+ */
int (*handle_packet)(USBDevice *dev, USBPacket *p);
- /*
+ /*
* Called when device is destroyed.
*/
void (*handle_destroy)(USBDevice *dev);
- int speed;
-
- /* The following fields are used by the generic USB device
- layer. They are here just to avoid creating a new structure
- for them. */
-
/*
* Reset the device
- */
+ */
void (*handle_reset)(USBDevice *dev);
/*
@@ -165,17 +181,6 @@ struct USBDevice {
* Returns length or one of the USB_RET_ codes.
*/
int (*handle_data)(USBDevice *dev, USBPacket *p);
-
- uint8_t addr;
- char devname[32];
-
- int state;
- uint8_t setup_buf[8];
- uint8_t data_buf[1024];
- int remote_wakeup;
- int setup_state;
- int setup_len;
- int setup_index;
};
typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
@@ -297,3 +302,14 @@ MUSBState *musb_init(qemu_irq *irqs);
uint32_t musb_core_intr_get(MUSBState *s);
void musb_core_intr_clear(MUSBState *s, uint32_t mask);
void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
+
+/* usb-bus.c */
+
+struct USBBus {
+ BusState qbus;
+};
+
+USBBus *usb_bus_new(DeviceState *host);
+void usb_qdev_register(USBDeviceInfo *info);
+void usb_qdev_register_many(USBDeviceInfo *info);
+USBDevice *usb_create_simple(USBBus *bus, const char *name);
diff --git a/usb-linux.c b/usb-linux.c
index 67e4acd..3ac7ab3 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -751,7 +751,7 @@ static int usb_host_handle_packet(USBDevice *s, USBPacket *p)
s->remote_wakeup = 0;
s->addr = 0;
s->state = USB_STATE_DEFAULT;
- s->handle_reset(s);
+ s->info->handle_reset(s);
return 0;
}
@@ -881,18 +881,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
return 0;
}
+static void usb_host_initfn(USBDevice *dev)
+{
+}
+
static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *prod_name)
{
int fd = -1, ret;
- USBHostDevice *dev = NULL;
+ USBDevice *d = NULL;
+ USBHostDevice *dev;
struct usbdevfs_connectinfo ci;
char buf[1024];
- dev = qemu_mallocz(sizeof(USBHostDevice));
-
- dev->bus_num = bus_num;
- dev->addr = addr;
-
printf("husb: open device %d.%d\n", bus_num, addr);
if (!usb_host_device_path) {
@@ -908,6 +908,12 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
}
dprintf("husb: opened %s\n", buf);
+ d = usb_create_simple(NULL /* FIXME */, "USB Host Device");
+ dev = DO_UPCAST(USBHostDevice, dev, d);
+
+ dev->bus_num = bus_num;
+ dev->addr = addr;
+
/* read the device description */
dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
if (dev->descr_len <= 0) {
@@ -925,7 +931,6 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
}
#endif
- dev->fd = fd;
/*
* Initial configuration is -1 which makes us claim first
@@ -953,10 +958,6 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
else
dev->dev.speed = USB_SPEED_HIGH;
- dev->dev.handle_packet = usb_host_handle_packet;
- dev->dev.handle_reset = usb_host_handle_reset;
- dev->dev.handle_destroy = usb_host_handle_destroy;
-
if (!prod_name || prod_name[0] == '\0')
snprintf(dev->dev.devname, sizeof(dev->dev.devname),
"host:%d.%d", bus_num, addr);
@@ -972,13 +973,32 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
return (USBDevice *) dev;
fail:
- if (dev)
- qemu_free(dev);
-
- close(fd);
+ if (d)
+ qdev_free(&d->qdev);
+ if (fd != -1)
+ close(fd);
return NULL;
}
+static struct USBDeviceInfo usb_host_dev_info = {
+ .qdev.name = "USB Host Device",
+ .qdev.size = sizeof(USBHostDevice),
+ .init = usb_host_initfn,
+ .handle_packet = usb_host_handle_packet,
+ .handle_reset = usb_host_handle_reset,
+#if 0
+ .handle_control = usb_host_handle_control,
+ .handle_data = usb_host_handle_data,
+#endif
+ .handle_destroy = usb_host_handle_destroy,
+};
+
+static void usb_host_register_devices(void)
+{
+ usb_qdev_register(&usb_host_dev_info);
+}
+device_init(usb_host_register_devices)
+
static int usb_host_auto_add(const char *spec);
static int usb_host_auto_del(const char *spec);
diff --git a/vl.c b/vl.c
index 60a00e1..99090ad 100644
--- a/vl.c
+++ b/vl.c
@@ -2667,7 +2667,7 @@ static void usb_msd_password_cb(void *opaque, int err)
if (!err)
usb_device_add_dev(dev);
else
- dev->handle_destroy(dev);
+ dev->info->handle_destroy(dev);
}
static int usb_device_add(const char *devname, int is_hotplug)
@@ -2753,7 +2753,7 @@ int usb_device_del_addr(int bus_num, int addr)
dev = port->dev;
*lastp = port->next;
usb_attach(port, NULL);
- dev->handle_destroy(dev);
+ dev->info->handle_destroy(dev);
port->next = free_usb_ports;
free_usb_ports = port;
return 0;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 15/20] qdev/usb: make qemu aware of usb busses.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (13 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 14/20] qdev/usb: add usb bus support to qdev, convert drivers Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 16/20] qdev/usb: print usb dev info Gerd Hoffmann
` (5 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move usb code from vl.c to usb-bus.c and make it use the new data
structures added by qdev conversion. qemu usb core should be able
to handle multiple USB busses just fine now (untested though).
Kill some usb_*_init() legacy functions, use usb_create_simple()
instead.
Kill some FIXMEs added by the first qdev/usb patch.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/bt-hid.c | 3 +-
hw/usb-bus.c | 98 +++++++++++++++++++++++++++++----
hw/usb-hid.c | 15 -----
hw/usb-hub.c | 8 +--
hw/usb-musb.c | 4 +-
hw/usb-ohci.c | 4 +-
hw/usb-uhci.c | 4 +-
hw/usb-wacom.c | 5 --
hw/usb.h | 31 ++++++-----
usb-linux.c | 10 ++--
vl.c | 165 +++++++++++++++++++++-----------------------------------
11 files changed, 181 insertions(+), 166 deletions(-)
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index 97c8d79..9b5d34f 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -567,5 +567,6 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
{
- return bt_hid_init(net, usb_keyboard_init(), class_keyboard);
+ USBDevice *dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
+ return bt_hid_init(net, dev, class_keyboard);
}
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 669c1f7..689df9f 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -6,22 +6,25 @@ static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
};
-static int next_usb_bus = 0;
-static USBBus *usbbus; /* hack alert */
USBBus *usb_bus_new(DeviceState *host)
{
USBBus *bus;
- char name[32];
- snprintf(name, sizeof(name), "usb%d", next_usb_bus);
- bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, name));
- if (!usbbus)
- usbbus = bus;
- next_usb_bus++;
+ bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, NULL));
+ TAILQ_INIT(&bus->free);
+ TAILQ_INIT(&bus->used);
return bus;
}
+USBBus *usb_bus_find(int busnr)
+{
+ BusState *qbus = qbus_find("USB", NULL, busnr);
+ if (!qbus)
+ return NULL;
+ return DO_UPCAST(USBBus, qbus, qbus);
+}
+
static void usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
{
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
@@ -53,13 +56,84 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
#if 1
/* temporary stopgap until all usb is properly qdev-ified */
- if (!bus)
- bus = usbbus;
- if (!bus)
- bus = usb_bus_new(NULL);
+ if (!bus) {
+ bus = usb_bus_find(-1);
+ if (!bus)
+ bus = usb_bus_new(NULL);
+ fprintf(stderr, "%s: no bus specified, using \"%s\" for \"%s\"\n",
+ __FUNCTION__, bus->qbus.name, name);
+ }
#endif
dev = qdev_create(&bus->qbus, name);
qdev_init(dev);
return DO_UPCAST(USBDevice, qdev, dev);
}
+
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+ usb_attachfn attach)
+{
+ port->opaque = opaque;
+ port->index = index;
+ port->attach = attach;
+ TAILQ_INSERT_TAIL(&bus->free, port, next);
+ bus->nfree++;
+}
+
+static void do_attach(USBDevice *dev)
+{
+ USBBus *bus = usb_bus_from_device(dev);
+ USBPort *port;
+
+ port = TAILQ_FIRST(&bus->free);
+ TAILQ_REMOVE(&bus->free, port, next);
+ bus->nfree--;
+
+ usb_attach(port, dev);
+
+ TAILQ_INSERT_TAIL(&bus->used, port, next);
+ bus->nused++;
+}
+
+int usb_device_attach(USBDevice *dev)
+{
+ USBBus *bus = usb_bus_from_device(dev);
+ USBDevice *hub;
+
+ if (bus->nfree == 1) {
+ /* Create a new hub and chain it on. */
+ hub = usb_create_simple(bus, "QEMU USB Hub");
+ do_attach(hub);
+ }
+ do_attach(dev);
+ return 0;
+}
+
+int usb_device_delete_addr(int busnr, int addr)
+{
+ USBBus *bus;
+ USBPort *port;
+ USBDevice *dev;
+
+ bus = usb_bus_find(busnr);
+ if (!bus)
+ return -1;
+
+ TAILQ_FOREACH(port, &bus->used, next) {
+ if (port->dev->addr == addr)
+ break;
+ }
+ if (!port)
+ return -1;
+
+ dev = port->dev;
+ TAILQ_REMOVE(&bus->used, port, next);
+ bus->nused--;
+
+ usb_attach(port, NULL);
+ dev->info->handle_destroy(dev);
+
+ TAILQ_INSERT_TAIL(&bus->free, port, next);
+ bus->nfree++;
+ return 0;
+}
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index d4b2e1a..3895643 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -870,21 +870,6 @@ static void usb_keyboard_initfn(USBDevice *dev)
usb_hid_initfn(dev, USB_KEYBOARD);
}
-USBDevice *usb_tablet_init(void)
-{
- return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet");
-}
-
-USBDevice *usb_mouse_init(void)
-{
- return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse");
-}
-
-USBDevice *usb_keyboard_init(void)
-{
- return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
-}
-
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
{
USBHIDState *s = (USBHIDState *)dev;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index bd4eb31..f62e7c4 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -531,17 +531,13 @@ static void usb_hub_initfn(USBDevice *dev)
s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
for (i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
- qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
+ usb_register_port(usb_bus_from_device(dev),
+ &port->port, s, i, usb_hub_attach);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
}
-USBDevice *usb_hub_init(int nb_ports)
-{
- return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub");
-}
-
static struct USBDeviceInfo hub_info = {
.qdev.name = "QEMU USB Hub",
.qdev.size = sizeof(USBHubState),
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index bf9a555..7813675 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -282,6 +282,7 @@ typedef struct {
struct MUSBState {
qemu_irq *irqs;
+ USBBus *bus;
USBPort port;
int idx;
@@ -331,7 +332,8 @@ struct MUSBState {
s->ep[i].epnum = i;
}
- qemu_register_usb_port(&s->port, s, 0, musb_attach);
+ s->bus = usb_bus_new(NULL /* FIXME */);
+ usb_register_port(s->bus, &s->port, s, 0, musb_attach);
return s;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 8cc6677..ba4cb9e 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -66,6 +66,7 @@ enum ohci_type {
};
typedef struct {
+ USBBus *bus;
qemu_irq irq;
enum ohci_type type;
int mem;
@@ -1689,9 +1690,10 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
ohci->irq = irq;
ohci->type = type;
+ ohci->bus = usb_bus_new(NULL /* FIXME */);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
- qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
+ usb_register_port(ohci->bus, &ohci->rhport[i].port, ohci, i, ohci_attach);
}
ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6daeb33..ef72e6f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1083,8 +1083,9 @@ static void usb_uhci_common_initfn(UHCIState *s)
pci_conf[0x3d] = 4; // interrupt pin 3
pci_conf[0x60] = 0x10; // release number
+ s->bus = usb_bus_new(&s->dev.qdev);
for(i = 0; i < NB_PORTS; i++) {
- qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
+ usb_register_port(s->bus, &s->ports[i].port, s, i, uhci_attach);
}
s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
@@ -1096,7 +1097,6 @@ static void usb_uhci_common_initfn(UHCIState *s)
pci_register_bar(&s->dev, 4, 0x20,
PCI_ADDRESS_SPACE_IO, uhci_map);
- s->bus = usb_bus_new(&s->dev.qdev);
register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
}
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 05b317a..65c81e0 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -398,11 +398,6 @@ static void usb_wacom_initfn(USBDevice *dev)
s->dev.speed = USB_SPEED_FULL;
}
-USBDevice *usb_wacom_init(void)
-{
- return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet");
-}
-
static struct USBDeviceInfo wacom_info = {
.qdev.name = "QEMU PenPartner Tablet",
.qdev.size = sizeof(USBWacomState),
diff --git a/hw/usb.h b/hw/usb.h
index e39d917..d68988a 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -24,6 +24,7 @@
#include "block.h"
#include "qdev.h"
+#include "sys-queue.h"
#define USB_TOKEN_SETUP 0x2d
#define USB_TOKEN_IN 0x69 /* device -> host */
@@ -191,7 +192,7 @@ struct USBPort {
usb_attachfn attach;
void *opaque;
int index; /* internal port index, may be used with the opaque */
- struct USBPort *next; /* Used internally by qemu. */
+ TAILQ_ENTRY(USBPort) next;
};
typedef void USBCallback(USBPacket * packet, void *opaque);
@@ -236,25 +237,17 @@ static inline void usb_cancel_packet(USBPacket * p)
p->cancel_cb(p, p->cancel_opaque);
}
-int usb_device_add_dev(USBDevice *dev);
-int usb_device_del_addr(int bus_num, int addr);
void usb_attach(USBPort *port, USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
void usb_send_msg(USBDevice *dev, int msg);
-/* usb hub */
-USBDevice *usb_hub_init(int nb_ports);
-
/* usb-linux.c */
USBDevice *usb_host_device_open(const char *devname);
int usb_host_device_close(const char *devname);
void usb_host_info(Monitor *mon);
/* usb-hid.c */
-USBDevice *usb_mouse_init(void);
-USBDevice *usb_tablet_init(void);
-USBDevice *usb_keyboard_init(void);
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
/* usb-msd.c */
@@ -267,17 +260,11 @@ USBDevice *usb_net_init(NICInfo *nd);
/* usb-bt.c */
USBDevice *usb_bt_init(HCIInfo *hci);
-/* usb-wacom.c */
-USBDevice *usb_wacom_init(void);
-
/* usb-serial.c */
USBDevice *usb_serial_init(const char *filename);
/* usb ports of the VM */
-void qemu_register_usb_port(USBPort *port, void *opaque, int index,
- usb_attachfn attach);
-
#define VM_USB_HUB_SIZE 8
/* usb-musb.c */
@@ -307,9 +294,23 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
struct USBBus {
BusState qbus;
+ int nfree;
+ int nused;
+ TAILQ_HEAD(, USBPort) free;
+ TAILQ_HEAD(, USBPort) used;
};
USBBus *usb_bus_new(DeviceState *host);
+USBBus *usb_bus_find(int busnr);
void usb_qdev_register(USBDeviceInfo *info);
void usb_qdev_register_many(USBDeviceInfo *info);
USBDevice *usb_create_simple(USBBus *bus, const char *name);
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+ usb_attachfn attach);
+int usb_device_attach(USBDevice *dev);
+int usb_device_delete_addr(int busnr, int addr);
+
+static inline USBBus *usb_bus_from_device(USBDevice *d)
+{
+ return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus);
+}
diff --git a/usb-linux.c b/usb-linux.c
index 3ac7ab3..fb3c24b 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -252,7 +252,7 @@ static void async_complete(void *opaque)
if (errno == ENODEV && !s->closing) {
printf("husb: device %d.%d disconnected\n", s->bus_num, s->addr);
- usb_device_del_addr(0, s->dev.addr);
+ usb_device_delete_addr(s->bus_num, s->dev.addr);
return;
}
@@ -1038,16 +1038,16 @@ int usb_host_device_close(const char *devname)
if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name),
devname) < 0)
return -1;
-
+
s = hostdev_find(bus_num, addr);
if (s) {
- usb_device_del_addr(0, s->dev.addr);
+ usb_device_delete_addr(s->bus_num, s->dev.addr);
return 0;
}
return -1;
}
-
+
static int get_tag_value(char *buf, int buf_size,
const char *str, const char *tag,
const char *stopchars)
@@ -1386,7 +1386,7 @@ static int usb_host_auto_scan(void *opaque, int bus_num, int addr,
dev = usb_host_device_open_addr(bus_num, addr, product_name);
if (dev)
- usb_device_add_dev(dev);
+ usb_device_attach(dev);
}
return 0;
diff --git a/vl.c b/vl.c
index 99090ad..7add3d7 100644
--- a/vl.c
+++ b/vl.c
@@ -2620,72 +2620,56 @@ static void numa_add(const char *optarg)
/***********************************************************/
/* USB devices */
-static USBPort *used_usb_ports;
-static USBPort *free_usb_ports;
-
-/* ??? Maybe change this to register a hub to keep track of the topology. */
-void qemu_register_usb_port(USBPort *port, void *opaque, int index,
- usb_attachfn attach)
-{
- port->opaque = opaque;
- port->index = index;
- port->attach = attach;
- port->next = free_usb_ports;
- free_usb_ports = port;
-}
-
-int usb_device_add_dev(USBDevice *dev)
-{
- USBPort *port;
-
- /* Find a USB port to add the device to. */
- port = free_usb_ports;
- if (!port->next) {
- USBDevice *hub;
-
- /* Create a new hub and chain it on. */
- free_usb_ports = NULL;
- port->next = used_usb_ports;
- used_usb_ports = port;
-
- hub = usb_hub_init(VM_USB_HUB_SIZE);
- usb_attach(port, hub);
- port = free_usb_ports;
- }
-
- free_usb_ports = port->next;
- port->next = used_usb_ports;
- used_usb_ports = port;
- usb_attach(port, dev);
- return 0;
-}
-
static void usb_msd_password_cb(void *opaque, int err)
{
USBDevice *dev = opaque;
if (!err)
- usb_device_add_dev(dev);
+ usb_device_attach(dev);
else
dev->info->handle_destroy(dev);
}
+static struct {
+ const char *name;
+ const char *qdev;
+} usbdevs[] = {
+ {
+ .name = "mouse",
+ .qdev = "QEMU USB Mouse",
+ },{
+ .name = "tablet",
+ .qdev = "QEMU USB Tablet",
+ },{
+ .name = "keyboard",
+ .qdev = "QEMU USB Keyboard",
+ },{
+ .name = "wacom-tablet",
+ .qdev = "QEMU PenPartner Tablet",
+ }
+};
+
static int usb_device_add(const char *devname, int is_hotplug)
{
const char *p;
- USBDevice *dev;
+ USBBus *bus = usb_bus_find(-1 /* any */);
+ USBDevice *dev = NULL;
+ int i;
- if (!free_usb_ports)
+ if (!usb_enabled)
return -1;
+ /* simple devices which don't need extra care */
+ for (i = 0; i < ARRAY_SIZE(usbdevs); i++) {
+ if (strcmp(devname, usbdevs[i].name) != 0)
+ continue;
+ dev = usb_create_simple(bus, usbdevs[i].qdev);
+ goto done;
+ }
+
+ /* the other ones */
if (strstart(devname, "host:", &p)) {
dev = usb_host_device_open(p);
- } else if (!strcmp(devname, "mouse")) {
- dev = usb_mouse_init();
- } else if (!strcmp(devname, "tablet")) {
- dev = usb_tablet_init();
- } else if (!strcmp(devname, "keyboard")) {
- dev = usb_keyboard_init();
} else if (strstart(devname, "disk:", &p)) {
BlockDriverState *bs;
@@ -2701,8 +2685,6 @@ static int usb_device_add(const char *devname, int is_hotplug)
return 0;
}
}
- } else if (!strcmp(devname, "wacom-tablet")) {
- dev = usb_wacom_init();
} else if (strstart(devname, "serial:", &p)) {
dev = usb_serial_init(p);
#ifdef CONFIG_BRLAPI
@@ -2725,38 +2707,8 @@ static int usb_device_add(const char *devname, int is_hotplug)
if (!dev)
return -1;
- return usb_device_add_dev(dev);
-}
-
-int usb_device_del_addr(int bus_num, int addr)
-{
- USBPort *port;
- USBPort **lastp;
- USBDevice *dev;
-
- if (!used_usb_ports)
- return -1;
-
- if (bus_num != 0)
- return -1;
-
- lastp = &used_usb_ports;
- port = used_usb_ports;
- while (port && port->dev->addr != addr) {
- lastp = &port->next;
- port = port->next;
- }
-
- if (!port)
- return -1;
-
- dev = port->dev;
- *lastp = port->next;
- usb_attach(port, NULL);
- dev->info->handle_destroy(dev);
- port->next = free_usb_ports;
- free_usb_ports = port;
- return 0;
+done:
+ return usb_device_attach(dev);
}
static int usb_device_del(const char *devname)
@@ -2767,7 +2719,7 @@ static int usb_device_del(const char *devname)
if (strstart(devname, "host:", &p))
return usb_host_device_close(p);
- if (!used_usb_ports)
+ if (!usb_enabled)
return -1;
p = strchr(devname, '.');
@@ -2776,7 +2728,7 @@ static int usb_device_del(const char *devname)
bus_num = strtoul(devname, NULL, 0);
addr = strtoul(p + 1, NULL, 0);
- return usb_device_del_addr(bus_num, addr);
+ return usb_device_delete_addr(bus_num, addr);
}
void do_usb_add(Monitor *mon, const char *devname)
@@ -2791,35 +2743,42 @@ void do_usb_del(Monitor *mon, const char *devname)
void usb_info(Monitor *mon)
{
+ USBBus *bus;
USBDevice *dev;
USBPort *port;
const char *speed_str;
+ int busnr;
if (!usb_enabled) {
monitor_printf(mon, "USB support not enabled\n");
return;
}
- for (port = used_usb_ports; port; port = port->next) {
- dev = port->dev;
- if (!dev)
- continue;
- switch(dev->speed) {
- case USB_SPEED_LOW:
- speed_str = "1.5";
- break;
- case USB_SPEED_FULL:
- speed_str = "12";
- break;
- case USB_SPEED_HIGH:
- speed_str = "480";
- break;
- default:
- speed_str = "?";
+ for (busnr = 0;; busnr++) {
+ bus = usb_bus_find(busnr);
+ if (!bus)
break;
+ TAILQ_FOREACH(port, &bus->used, next) {
+ dev = port->dev;
+ if (!dev)
+ continue;
+ switch(dev->speed) {
+ case USB_SPEED_LOW:
+ speed_str = "1.5";
+ break;
+ case USB_SPEED_FULL:
+ speed_str = "12";
+ break;
+ case USB_SPEED_HIGH:
+ speed_str = "480";
+ break;
+ default:
+ speed_str = "?";
+ break;
+ }
+ monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
+ busnr, dev->addr, speed_str, dev->devname);
}
- monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
- 0, dev->addr, speed_str, dev->devname);
}
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 16/20] qdev/usb: print usb dev info
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (14 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 15/20] qdev/usb: make qemu aware of usb busses Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 17/20] qdev: convert ohci Gerd Hoffmann
` (4 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-bus.c | 26 ++++++++++++++++++++++++++
hw/usb.h | 1 +
vl.c | 17 +----------------
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 689df9f..9f07946 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -1,10 +1,14 @@
#include "hw.h"
#include "usb.h"
#include "qdev.h"
+#include "monitor.h"
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
+ .print = usb_bus_dev_print,
};
USBBus *usb_bus_new(DeviceState *host)
@@ -137,3 +141,25 @@ int usb_device_delete_addr(int busnr, int addr)
bus->nfree++;
return 0;
}
+
+const char *usb_speed(unsigned int speed)
+{
+ static const char *txt[] = {
+ [ USB_SPEED_LOW ] = "1.5",
+ [ USB_SPEED_FULL ] = "12",
+ [ USB_SPEED_HIGH ] = "480",
+ };
+ if (speed >= ARRAY_SIZE(txt))
+ return "?";
+ return txt[speed];
+}
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
+{
+ USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBBus *bus = usb_bus_from_device(dev);
+
+ monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s\n", indent, "",
+ bus->qbus.busnr, dev->addr,
+ usb_speed(dev->speed), dev->devname);
+}
diff --git a/hw/usb.h b/hw/usb.h
index d68988a..3169bc9 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -309,6 +309,7 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
usb_attachfn attach);
int usb_device_attach(USBDevice *dev);
int usb_device_delete_addr(int busnr, int addr);
+const char *usb_speed(unsigned int speed);
static inline USBBus *usb_bus_from_device(USBDevice *d)
{
diff --git a/vl.c b/vl.c
index 7add3d7..0462892 100644
--- a/vl.c
+++ b/vl.c
@@ -2746,7 +2746,6 @@ void usb_info(Monitor *mon)
USBBus *bus;
USBDevice *dev;
USBPort *port;
- const char *speed_str;
int busnr;
if (!usb_enabled) {
@@ -2762,22 +2761,8 @@ void usb_info(Monitor *mon)
dev = port->dev;
if (!dev)
continue;
- switch(dev->speed) {
- case USB_SPEED_LOW:
- speed_str = "1.5";
- break;
- case USB_SPEED_FULL:
- speed_str = "12";
- break;
- case USB_SPEED_HIGH:
- speed_str = "480";
- break;
- default:
- speed_str = "?";
- break;
- }
monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
- busnr, dev->addr, speed_str, dev->devname);
+ busnr, dev->addr, usb_speed(dev->speed), dev->devname);
}
}
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 17/20] qdev: convert ohci.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (15 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 16/20] qdev/usb: print usb dev info Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 18/20] qdev/scsi: add scsi bus support to qdev, convert drivers Gerd Hoffmann
` (3 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hook pci device into qdev.
TODO: convert non-pci ohci adapters.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 42 ++++++++++++++++++++++++++++--------------
1 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index ba4cb9e..613104d 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1661,7 +1661,8 @@ static CPUWriteMemoryFunc *ohci_writefn[3]={
ohci_mem_write
};
-static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
+static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
+ int num_ports, int devfn,
qemu_irq irq, enum ohci_type type,
const char *name, uint32_t localmem_base)
{
@@ -1690,7 +1691,7 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
ohci->irq = irq;
ohci->type = type;
- ohci->bus = usb_bus_new(NULL /* FIXME */);
+ ohci->bus = usb_bus_new(dev);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
usb_register_port(ohci->bus, &ohci->rhport[i].port, ohci, i, ohci_attach);
@@ -1713,16 +1714,9 @@ static void ohci_mapfunc(PCIDevice *pci_dev, int i,
cpu_register_physical_memory(addr, size, ohci->state.mem);
}
-void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
+static void usb_ohci_initfn_pci(struct PCIDevice *dev)
{
- OHCIPCIState *ohci;
-
- ohci = (OHCIPCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci),
- devfn, NULL, NULL);
- if (ohci == NULL) {
- fprintf(stderr, "usb-ohci: Failed to register PCI device\n");
- return;
- }
+ OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
pci_config_set_vendor_id(ohci->pci_dev.config, PCI_VENDOR_ID_APPLE);
pci_config_set_device_id(ohci->pci_dev.config,
@@ -1730,8 +1724,17 @@ void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
ohci->pci_dev.config[0x09] = 0x10; /* OHCI */
pci_config_set_class(ohci->pci_dev.config, PCI_CLASS_SERIAL_USB);
ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
+}
- usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0],
+void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
+{
+ PCIDevice *dev;
+ OHCIPCIState *ohci;
+
+ dev = pci_create_simple(bus, devfn, "OHCI USB");
+ ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
+
+ usb_ohci_init(&ohci->state, &dev->qdev, num_ports, devfn, ohci->pci_dev.irq[0],
OHCI_TYPE_PCI, ohci->pci_dev.name, 0);
pci_register_bar((struct PCIDevice *)ohci, 0, 256,
@@ -1743,7 +1746,7 @@ void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
{
OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
- usb_ohci_init(ohci, num_ports, devfn, irq,
+ usb_ohci_init(ohci, NULL /* FIXME */, num_ports, devfn, irq,
OHCI_TYPE_PXA, "OHCI USB", 0);
cpu_register_physical_memory(base, 0x1000, ohci->mem);
@@ -1754,9 +1757,20 @@ void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
{
OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
- usb_ohci_init(ohci, num_ports, devfn, irq,
+ usb_ohci_init(ohci, NULL /* FIXME */, num_ports, devfn, irq,
OHCI_TYPE_SM501, "OHCI USB", localmem_base);
cpu_register_physical_memory(mmio_base, 0x1000, ohci->mem);
}
+static PCIDeviceInfo ohci_info = {
+ .qdev.name = "OHCI USB",
+ .qdev.size = sizeof(OHCIPCIState),
+ .init = usb_ohci_initfn_pci,
+};
+
+static void ohci_register(void)
+{
+ pci_qdev_register(&ohci_info);
+}
+device_init(ohci_register);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 18/20] qdev/scsi: add scsi bus support to qdev, convert drivers.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (16 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 17/20] qdev: convert ohci Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 19/20] debug/test patch: add ohci controller to pc Gerd Hoffmann
` (2 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
* Add SCSIBus
* Add SCSIDeviceInfo, move device callbacks here.
* add qdev/scsi helper functions.
* convert drivers.
TODO:
* design a better way to link (guest) scsi devs to (host) bdrvs.
* figure whenever we can move bits from lsi / esp scsi host drivers
to scsi-bus.c (attach function?).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
Makefile | 2 +-
hw/esp.c | 28 ++++++++++++----------
hw/lsi53c895a.c | 31 ++++++++++++++-----------
hw/qdev.c | 18 ---------------
hw/qdev.h | 4 ---
hw/scsi-bus.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi-disk.c | 64 ++++++++++++++++++++++++++++++----------------------
hw/scsi-disk.h | 48 +++++++++++++++++++++++++++++++++------
hw/scsi-generic.c | 62 ++++++++++++++++++++++++++++++++-------------------
hw/usb-msd.c | 24 ++++++++++---------
10 files changed, 223 insertions(+), 119 deletions(-)
create mode 100644 hw/scsi-bus.c
diff --git a/Makefile b/Makefile
index e150ab1..3987f49 100644
--- a/Makefile
+++ b/Makefile
@@ -101,7 +101,7 @@ OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
OBJS+=tmp105.o lm832x.o eeprom93xx.o tsc2005.o
OBJS+=scsi-disk.o cdrom.o
-OBJS+=scsi-generic.o
+OBJS+=scsi-generic.o scsi-bus.o
OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
OBJS+=usb-serial.o usb-net.o usb-bus.o
OBJS+=sd.o ssi-sd.o
diff --git a/hw/esp.c b/hw/esp.c
index 3698917..1aa3e1a 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -63,6 +63,7 @@ struct ESPState {
uint8_t ti_buf[TI_BUFSZ];
uint32_t sense;
uint32_t dma;
+ SCSIBus *bus;
SCSIDevice *scsi_dev[ESP_MAX_DEVS];
SCSIDevice *current_dev;
uint8_t cmdbuf[TI_BUFSZ];
@@ -185,7 +186,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
if (s->current_dev) {
/* Started a new command before the old one finished. Cancel it. */
- s->current_dev->cancel_io(s->current_dev, 0);
+ s->current_dev->info->cancel_io(s->current_dev, 0);
s->async_len = 0;
}
@@ -208,7 +209,7 @@ static void do_cmd(ESPState *s, uint8_t *buf)
DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
lun = buf[0] & 7;
- datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
+ datalen = s->current_dev->info->send_command(s->current_dev, 0, &buf[1], lun);
s->ti_size = datalen;
if (datalen != 0) {
s->rregs[ESP_RSTAT] = STAT_TC;
@@ -216,10 +217,10 @@ static void do_cmd(ESPState *s, uint8_t *buf)
s->dma_counter = 0;
if (datalen > 0) {
s->rregs[ESP_RSTAT] |= STAT_DI;
- s->current_dev->read_data(s->current_dev, 0);
+ s->current_dev->info->read_data(s->current_dev, 0);
} else {
s->rregs[ESP_RSTAT] |= STAT_DO;
- s->current_dev->write_data(s->current_dev, 0);
+ s->current_dev->info->write_data(s->current_dev, 0);
}
}
s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
@@ -318,9 +319,9 @@ static void esp_do_dma(ESPState *s)
if (s->async_len == 0) {
if (to_device) {
// ti_size is negative
- s->current_dev->write_data(s->current_dev, 0);
+ s->current_dev->info->write_data(s->current_dev, 0);
} else {
- s->current_dev->read_data(s->current_dev, 0);
+ s->current_dev->info->read_data(s->current_dev, 0);
/* If there is still data to be read from the device then
complete the DMA operation immediately. Otherwise defer
until the scsi layer has completed. */
@@ -334,10 +335,10 @@ static void esp_do_dma(ESPState *s)
}
}
-static void esp_command_complete(void *opaque, int reason, uint32_t tag,
+static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
{
- ESPState *s = (ESPState *)opaque;
+ ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);
if (reason == SCSI_REASON_DONE) {
DPRINTF("SCSI Command complete\n");
@@ -355,7 +356,7 @@ static void esp_command_complete(void *opaque, int reason, uint32_t tag,
} else {
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
s->async_len = arg;
- s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
+ s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);
if (s->dma_left) {
esp_do_dma(s);
} else if (s->dma_counter != 0 && s->ti_size <= 0) {
@@ -634,13 +635,13 @@ static void esp_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
}
if (s->scsi_dev[id]) {
DPRINTF("Destroying device %d\n", id);
- s->scsi_dev[id]->destroy(s->scsi_dev[id]);
+ s->scsi_dev[id]->info->destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
/* Command queueing is not implemented. */
- s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s);
+ s->scsi_dev[id] = scsi_generic_init(s->bus, bd);
if (s->scsi_dev[id] == NULL)
- s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
+ s->scsi_dev[id] = scsi_disk_init(s->bus, bd);
}
void esp_init(target_phys_addr_t espaddr, int it_shift,
@@ -684,7 +685,8 @@ static void esp_init1(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1);
- scsi_bus_new(&dev->qdev, esp_scsi_attach);
+ s->bus = scsi_bus_new(&dev->qdev, 0, esp_scsi_attach, esp_command_complete);
+ scsi_bus_attach_cmdline(s->bus);
}
static void esp_register_devices(void)
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 516a468..1c3d698 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -12,6 +12,7 @@
#include "hw.h"
#include "pci.h"
+#include "scsi.h"
#include "scsi-disk.h"
#include "block_int.h"
@@ -190,6 +191,7 @@ typedef struct {
* 2 if processing DMA from lsi_execute_script.
* 3 if a DMA operation is in progress. */
int waiting;
+ SCSIBus *bus;
SCSIDevice *scsi_dev[LSI_MAX_DEVS];
SCSIDevice *current_dev;
int current_lun;
@@ -508,8 +510,8 @@ static void lsi_do_dma(LSIState *s, int out)
s->dbc -= count;
if (s->dma_buf == NULL) {
- s->dma_buf = s->current_dev->get_buf(s->current_dev,
- s->current_tag);
+ s->dma_buf = s->current_dev->info->get_buf(s->current_dev,
+ s->current_tag);
}
/* ??? Set SFBR to first data byte. */
@@ -523,10 +525,10 @@ static void lsi_do_dma(LSIState *s, int out)
s->dma_buf = NULL;
if (out) {
/* Write the data. */
- s->current_dev->write_data(s->current_dev, s->current_tag);
+ s->current_dev->info->write_data(s->current_dev, s->current_tag);
} else {
/* Request any remaining data. */
- s->current_dev->read_data(s->current_dev, s->current_tag);
+ s->current_dev->info->read_data(s->current_dev, s->current_tag);
}
} else {
s->dma_buf += count;
@@ -630,10 +632,10 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
}
/* Callback to indicate that the SCSI layer has completed a transfer. */
-static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
+static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
{
- LSIState *s = (LSIState *)opaque;
+ LSIState *s = DO_UPCAST(LSIState, pci_dev.qdev, bus->qbus.parent);
int out;
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
@@ -678,14 +680,14 @@ static void lsi_do_command(LSIState *s)
cpu_physical_memory_read(s->dnad, buf, s->dbc);
s->sfbr = buf[0];
s->command_complete = 0;
- n = s->current_dev->send_command(s->current_dev, s->current_tag, buf,
- s->current_lun);
+ n = s->current_dev->info->send_command(s->current_dev, s->current_tag, buf,
+ s->current_lun);
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
- s->current_dev->read_data(s->current_dev, s->current_tag);
+ s->current_dev->info->read_data(s->current_dev, s->current_tag);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
- s->current_dev->write_data(s->current_dev, s->current_tag);
+ s->current_dev->info->write_data(s->current_dev, s->current_tag);
}
if (!s->command_complete) {
@@ -1972,12 +1974,12 @@ void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
}
if (s->scsi_dev[id]) {
DPRINTF("Destroying device %d\n", id);
- s->scsi_dev[id]->destroy(s->scsi_dev[id]);
+ s->scsi_dev[id]->info->destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
- s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
+ s->scsi_dev[id] = scsi_generic_init(s->bus, bd);
if (s->scsi_dev[id] == NULL)
- s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
+ s->scsi_dev[id] = scsi_disk_init(s->bus, bd);
bd->private = &s->pci_dev;
}
@@ -2032,7 +2034,8 @@ static void lsi_scsi_init(PCIDevice *dev)
lsi_soft_reset(s);
- scsi_bus_new(&dev->qdev, lsi_scsi_attach);
+ s->bus = scsi_bus_new(&dev->qdev, 1, lsi_scsi_attach, lsi_command_complete);
+ scsi_bus_attach_cmdline(s->bus);
}
static PCIDeviceInfo lsi_info = {
diff --git a/hw/qdev.c b/hw/qdev.c
index 768431c..b5068ba 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -288,24 +288,6 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
return NULL;
}
-static int next_scsi_bus;
-
-/* Create a scsi bus, and attach devices to it. */
-/* TODO: Actually create a scsi bus for hotplug to use. */
-void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
-{
- int bus = next_scsi_bus++;
- int unit;
- int index;
-
- for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
- index = drive_get_index(IF_SCSI, bus, unit);
- if (index == -1) {
- continue;
- }
- attach(host, drives_table[index].bdrv, unit);
- }
-}
static TAILQ_HEAD(, BusState) buslist = TAILQ_HEAD_INITIALIZER(buslist);
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
diff --git a/hw/qdev.h b/hw/qdev.h
index 2f4e4a4..5a84fbf 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -76,8 +76,6 @@ typedef struct {
} DevicePropList;
typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
-typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
- int unit);
struct DeviceInfo {
const char *name;
@@ -97,8 +95,6 @@ void qdev_register(DeviceInfo *info);
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
-void scsi_bus_new(DeviceState *host, SCSIAttachFn attach);
-
CharDriverState *qdev_init_chardev(DeviceState *dev);
BusState *qdev_get_parent_bus(DeviceState *dev);
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
new file mode 100644
index 0000000..17d3d16
--- /dev/null
+++ b/hw/scsi-bus.c
@@ -0,0 +1,61 @@
+#include "hw.h"
+#include "sysemu.h"
+#include "scsi-disk.h"
+#include "qdev.h"
+
+static struct BusInfo scsi_bus_info = {
+ .name = "SCSI",
+ .size = sizeof(SCSIBus),
+};
+
+/* Create a scsi bus, and attach devices to it. */
+SCSIBus *scsi_bus_new(DeviceState *host, int tcq,
+ SCSIAttachFn attach, scsi_completionfn complete)
+{
+ SCSIBus *bus;
+
+ bus = FROM_QBUS(SCSIBus, qbus_create(&scsi_bus_info, host, NULL));
+ bus->tcq = tcq;
+ bus->attach = attach;
+ bus->complete = complete;
+ return bus;
+}
+
+void scsi_bus_attach_cmdline(SCSIBus *bus)
+{
+ int unit;
+ int index;
+
+ for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
+ index = drive_get_index(IF_SCSI, bus->qbus.busnr, unit);
+ if (index == -1) {
+ continue;
+ }
+ bus->attach(bus->qbus.parent, drives_table[index].bdrv, unit);
+ }
+}
+
+static void scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
+
+ dev->info = info;
+ dev->info->init(dev);
+}
+
+void scsi_qdev_register(SCSIDeviceInfo *info)
+{
+ info->qdev.bus_info = &scsi_bus_info;
+ info->qdev.init = scsi_qdev_init;
+ qdev_register(&info->qdev);
+}
+
+SCSIDevice *scsi_create_simple(SCSIBus *bus, const char *name)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(&bus->qbus, name);
+ qdev_init(dev);
+ return DO_UPCAST(SCSIDevice, qdev, dev);
+}
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a0485db..19b8ebd 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -45,6 +45,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#define SCSI_REQ_STATUS_RETRY 0x01
typedef struct SCSIRequest {
+ SCSIBus *bus;
SCSIDeviceState *dev;
uint32_t tag;
/* ??? We should probably keep track of whether the data transfer is
@@ -68,19 +69,15 @@ struct SCSIDeviceState
int cluster_size;
uint64_t max_lba;
int sense;
- int tcq;
- /* Completion functions may be called from either scsi_{read,write}_data
- or from the AIO completion routines. */
- scsi_completionfn completion;
- void *opaque;
char drive_serial_str[21];
};
/* Global pool of SCSIRequest structures. */
static SCSIRequest *free_requests = NULL;
-static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
if (free_requests) {
@@ -90,6 +87,7 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
r = qemu_malloc(sizeof(SCSIRequest));
r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
}
+ r->bus = scsi_bus_from_device(d);
r->dev = s;
r->tag = tag;
r->sector_count = 0;
@@ -143,7 +141,7 @@ static void scsi_command_complete(SCSIRequest *r, int status, int sense)
s->sense = sense;
tag = r->tag;
scsi_remove_request(r);
- s->completion(s->opaque, SCSI_REASON_DONE, tag, status);
+ r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
}
/* Cancel a pending data transfer. */
@@ -164,17 +162,16 @@ static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
static void scsi_read_complete(void * opaque, int ret)
{
SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIDeviceState *s = r->dev;
if (ret) {
DPRINTF("IO error\n");
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 0);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, 0);
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
return;
}
DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->iov.iov_len);
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
}
/* Read more data from scsi device into buffer. */
@@ -194,7 +191,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
if (r->sector_count == (uint32_t)-1) {
DPRINTF("Read buf_len=%d\n", r->iov.iov_len);
r->sector_count = 0;
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
return;
}
DPRINTF("Read sector_count=%d\n", r->sector_count);
@@ -239,7 +236,6 @@ static int scsi_handle_write_error(SCSIRequest *r, int error)
static void scsi_write_complete(void * opaque, int ret)
{
SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIDeviceState *s = r->dev;
uint32_t len;
uint32_t n;
@@ -262,7 +258,7 @@ static void scsi_write_complete(void * opaque, int ret)
}
r->iov.iov_len = len;
DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
}
}
@@ -364,7 +360,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
/* ??? Tags are not unique for different luns. We only implement a
single lun, so this should not matter. */
- r = scsi_new_request(s, tag);
+ r = scsi_new_request(d, tag);
outbuf = (uint8_t *)r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
@@ -592,7 +588,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[3] = 2; /* Format 2 */
outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
/* Sync data transfer and TCQ. */
- outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
+ outbuf[7] = 0x10 | (r->bus->tcq ? 0x02 : 0);
r->iov.iov_len = len;
break;
case 0x16:
@@ -926,8 +922,7 @@ static void scsi_destroy(SCSIDevice *d)
qemu_free(d);
}
-SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
- scsi_completionfn completion, void *opaque)
+SCSIDevice *scsi_disk_init(SCSIBus *bus, BlockDriverState *bdrv)
{
SCSIDevice *d;
SCSIDeviceState *s;
@@ -935,9 +930,6 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
s->bdrv = bdrv;
- s->tcq = tcq;
- s->completion = completion;
- s->opaque = opaque;
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
s->cluster_size = 4;
} else {
@@ -953,14 +945,32 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
if (strlen(s->drive_serial_str) == 0)
pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
- d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+
+ d = scsi_create_simple(bus, "scsi-disk");
d->state = s;
- d->destroy = scsi_destroy;
- d->send_command = scsi_send_command;
- d->read_data = scsi_read_data;
- d->write_data = scsi_write_data;
- d->cancel_io = scsi_cancel_io;
- d->get_buf = scsi_get_buf;
return d;
}
+
+static void scsi_disk_initfn(SCSIDevice *dev)
+{
+ /* TODO */
+}
+
+static SCSIDeviceInfo scsi_disk_info = {
+ .qdev.name = "scsi-disk",
+ .qdev.size = sizeof(SCSIDevice),
+ .init = scsi_disk_initfn,
+ .destroy = scsi_destroy,
+ .send_command = scsi_send_command,
+ .read_data = scsi_read_data,
+ .write_data = scsi_write_data,
+ .cancel_io = scsi_cancel_io,
+ .get_buf = scsi_get_buf,
+};
+
+static void scsi_disk_register_devices(void)
+{
+ scsi_qdev_register(&scsi_disk_info);
+}
+device_init(scsi_disk_register_devices)
diff --git a/hw/scsi-disk.h b/hw/scsi-disk.h
index f42212b..5b5c0af 100644
--- a/hw/scsi-disk.h
+++ b/hw/scsi-disk.h
@@ -1,20 +1,40 @@
#ifndef SCSI_DISK_H
#define SCSI_DISK_H
+#include "qdev.h"
+
/* scsi-disk.c */
enum scsi_reason {
SCSI_REASON_DONE, /* Command complete. */
SCSI_REASON_DATA /* Transfer complete, more data required. */
};
+typedef struct SCSIBus SCSIBus;
typedef struct SCSIDeviceState SCSIDeviceState;
typedef struct SCSIDevice SCSIDevice;
-typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag,
+typedef struct SCSIDeviceInfo SCSIDeviceInfo;
+typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg);
struct SCSIDevice
{
+ DeviceState qdev;
+ SCSIDeviceInfo *info;
SCSIDeviceState *state;
+};
+
+SCSIDevice *scsi_disk_init(SCSIBus *bus, BlockDriverState *bdrv);
+SCSIDevice *scsi_generic_init(SCSIBus *bus, BlockDriverState *bdrv);
+
+/* cdrom.c */
+int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
+int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
+
+/* scsi-bus.c */
+typedef void (*scsi_qdev_initfn)(SCSIDevice *dev);
+struct SCSIDeviceInfo {
+ DeviceInfo qdev;
+ scsi_qdev_initfn init;
void (*destroy)(SCSIDevice *s);
int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf,
int lun);
@@ -24,13 +44,25 @@ struct SCSIDevice
uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag);
};
-SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
- scsi_completionfn completion, void *opaque);
-SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
- scsi_completionfn completion, void *opaque);
+typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
+ int unit);
+struct SCSIBus {
+ BusState qbus;
-/* cdrom.c */
-int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
-int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
+ int tcq;
+ SCSIAttachFn attach;
+ scsi_completionfn complete;
+};
+
+SCSIBus *scsi_bus_new(DeviceState *host, int tcq,
+ SCSIAttachFn attach, scsi_completionfn complete);
+void scsi_bus_attach_cmdline(SCSIBus *bus);
+void scsi_qdev_register(SCSIDeviceInfo *info);
+SCSIDevice *scsi_create_simple(SCSIBus *bus, const char *name);
+
+static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
+{
+ return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
+}
#endif
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c827c04..a67b668 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -17,8 +17,7 @@
#ifndef __linux__
-SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
- scsi_completionfn completion, void *opaque)
+SCSIDevice *scsi_generic_init(SCSIBus *bus, BlockDriverState *bdrv)
{
return NULL;
}
@@ -63,6 +62,7 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
typedef struct SCSIRequest {
BlockDriverAIOCB *aiocb;
struct SCSIRequest *next;
+ SCSIBus *bus;
SCSIDeviceState *dev;
uint32_t tag;
uint8_t cmd[SCSI_CMD_BUF_SIZE];
@@ -80,8 +80,6 @@ struct SCSIDeviceState
int type;
int blocksize;
int lun;
- scsi_completionfn completion;
- void *opaque;
int driver_status;
uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
uint8_t senselen;
@@ -90,8 +88,9 @@ struct SCSIDeviceState
/* Global pool of SCSIRequest structures. */
static SCSIRequest *free_requests = NULL;
-static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
if (free_requests) {
@@ -102,6 +101,7 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
r->buf = NULL;
r->buflen = 0;
}
+ r->bus = scsi_bus_from_device(d);
r->dev = s;
r->tag = tag;
memset(r->cmd, 0, sizeof(r->cmd));
@@ -178,7 +178,7 @@ static void scsi_command_complete(void *opaque, int ret)
r, r->tag, status);
tag = r->tag;
scsi_remove_request(r);
- s->completion(s->opaque, SCSI_REASON_DONE, tag, status);
+ r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
}
/* Cancel a pending data transfer. */
@@ -225,7 +225,6 @@ static int execute_command(BlockDriverState *bdrv,
static void scsi_read_complete(void * opaque, int ret)
{
SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIDeviceState *s = r->dev;
int len;
if (ret) {
@@ -237,7 +236,7 @@ static void scsi_read_complete(void * opaque, int ret)
DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
r->len = -1;
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
if (len == 0)
scsi_command_complete(r, 0);
}
@@ -275,7 +274,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
r->buf[0], r->buf[1], r->buf[2], r->buf[3],
r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, s->senselen);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, s->senselen);
return;
}
@@ -325,7 +324,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
if (r->len == 0) {
r->len = r->buflen;
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len);
+ r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->len);
return 0;
}
@@ -518,6 +517,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint32_t len=0;
int cmdlen=0;
SCSIRequest *r;
+ SCSIBus *bus;
int ret;
if (s->type == TYPE_TAPE) {
@@ -548,7 +548,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
s->sensebuf[6] = 0x00;
s->senselen = 7;
s->driver_status = SG_ERR_DRIVER_SENSE;
- s->completion(s->opaque, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
+ bus = scsi_bus_from_device(d);
+ bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
return 0;
}
@@ -557,7 +558,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
BADF("Tag 0x%x already in use %p\n", tag, r);
scsi_cancel_io(d, tag);
}
- r = scsi_new_request(s, tag);
+ r = scsi_new_request(d, tag);
memcpy(r->cmd, cmd, cmdlen);
r->cmdlen = cmdlen;
@@ -675,8 +676,7 @@ static void scsi_destroy(SCSIDevice *d)
qemu_free(d);
}
-SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
- scsi_completionfn completion, void *opaque)
+SCSIDevice *scsi_generic_init(SCSIBus *bus, BlockDriverState *bdrv)
{
int sg_version;
SCSIDevice *d;
@@ -704,8 +704,6 @@ SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
s->bdrv = bdrv;
s->requests = NULL;
- s->completion = completion;
- s->opaque = opaque;
s->lun = scsiid.lun;
DPRINTF("LUN %d\n", s->lun);
s->type = scsiid.scsi_type;
@@ -730,15 +728,33 @@ SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
/* define function to manage device */
- d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+ d = scsi_create_simple(bus, "scsi-generic");
d->state = s;
- d->destroy = scsi_destroy;
- d->send_command = scsi_send_command;
- d->read_data = scsi_read_data;
- d->write_data = scsi_write_data;
- d->cancel_io = scsi_cancel_io;
- d->get_buf = scsi_get_buf;
return d;
}
+
+static void scsi_generic_initfn(SCSIDevice *dev)
+{
+ /* TODO */
+}
+
+static SCSIDeviceInfo scsi_generic_info = {
+ .qdev.name = "scsi-generic",
+ .qdev.size = sizeof(SCSIDevice),
+ .init = scsi_generic_initfn,
+ .destroy = scsi_destroy,
+ .send_command = scsi_send_command,
+ .read_data = scsi_read_data,
+ .write_data = scsi_write_data,
+ .cancel_io = scsi_cancel_io,
+ .get_buf = scsi_get_buf,
+};
+
+static void scsi_generic_register_devices(void)
+{
+ scsi_qdev_register(&scsi_generic_info);
+}
+device_init(scsi_generic_register_devices)
+
#endif /* __linux__ */
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 535178f..22a1994 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -44,6 +44,7 @@ typedef struct {
uint32_t residue;
uint32_t tag;
BlockDriverState *bs;
+ SCSIBus *bus;
SCSIDevice *scsi_dev;
int result;
/* For async completion. */
@@ -150,9 +151,9 @@ static void usb_msd_copy_data(MSDState *s)
s->data_len -= len;
if (s->scsi_len == 0) {
if (s->mode == USB_MSDM_DATAIN) {
- s->scsi_dev->read_data(s->scsi_dev, s->tag);
+ s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
} else if (s->mode == USB_MSDM_DATAOUT) {
- s->scsi_dev->write_data(s->scsi_dev, s->tag);
+ s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
}
}
}
@@ -168,10 +169,10 @@ static void usb_msd_send_status(MSDState *s)
memcpy(s->usb_buf, &csw, 13);
}
-static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
+static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
{
- MSDState *s = (MSDState *)opaque;
+ MSDState *s = DO_UPCAST(MSDState, dev.qdev, bus->qbus.parent);
USBPacket *p = s->packet;
if (tag != s->tag) {
@@ -205,7 +206,7 @@ static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
return;
}
s->scsi_len = arg;
- s->scsi_buf = s->scsi_dev->get_buf(s->scsi_dev, tag);
+ s->scsi_buf = s->scsi_dev->info->get_buf(s->scsi_dev, tag);
if (p) {
usb_msd_copy_data(s);
if (s->usb_len == 0) {
@@ -343,7 +344,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
{
MSDState *s = opaque;
- s->scsi_dev->cancel_io(s->scsi_dev, s->tag);
+ s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
s->packet = NULL;
s->scsi_len = 0;
}
@@ -391,14 +392,14 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
s->tag, cbw.flags, cbw.cmd_len, s->data_len);
s->residue = 0;
- s->scsi_dev->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
+ s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
/* ??? Should check that USB and SCSI data transfer
directions match. */
if (s->residue == 0) {
if (s->mode == USB_MSDM_DATAIN) {
- s->scsi_dev->read_data(s->scsi_dev, s->tag);
+ s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
} else if (s->mode == USB_MSDM_DATAOUT) {
- s->scsi_dev->write_data(s->scsi_dev, s->tag);
+ s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
}
}
ret = len;
@@ -509,7 +510,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
{
MSDState *s = (MSDState *)dev;
- s->scsi_dev->destroy(s->scsi_dev);
+ s->scsi_dev->info->destroy(s->scsi_dev);
bdrv_delete(s->bs);
qemu_free(s);
}
@@ -566,7 +567,8 @@ USBDevice *usb_msd_init(const char *filename)
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
filename);
- s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);
+ s->bus = scsi_bus_new(&s->dev.qdev, 0, NULL, usb_msd_command_complete);
+ s->scsi_dev = scsi_disk_init(s->bus, bdrv);
usb_msd_handle_reset((USBDevice *)s);
return (USBDevice *)s;
}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 19/20] debug/test patch: add ohci controller to pc
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (17 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 18/20] qdev/scsi: add scsi bus support to qdev, convert drivers Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-29 12:46 ` [Qemu-devel] [PATCH 20/20] debug/test patch: allow specify busnr for -usbdevice Gerd Hoffmann
2009-06-30 0:56 ` [Qemu-devel] [PATCH 0/20] qdev patches Anthony Liguori
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/pc.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 86e5cfe..98d8ca8 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1121,6 +1121,7 @@ static void pc_init1(ram_addr_t ram_size,
if (pci_enabled && usb_enabled) {
usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
+ usb_ohci_init_pci(pci_bus, 3, -1);
}
if (pci_enabled && acpi_enabled) {
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 20/20] debug/test patch: allow specify busnr for -usbdevice
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (18 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 19/20] debug/test patch: add ohci controller to pc Gerd Hoffmann
@ 2009-06-29 12:46 ` Gerd Hoffmann
2009-06-30 0:56 ` [Qemu-devel] [PATCH 0/20] qdev patches Anthony Liguori
20 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-29 12:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
i.e. -usbdevice tablet,busnr=1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
vl.c | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/vl.c b/vl.c
index 0462892..cfcf437 100644
--- a/vl.c
+++ b/vl.c
@@ -2649,16 +2649,31 @@ static struct {
}
};
-static int usb_device_add(const char *devname, int is_hotplug)
+static int usb_device_add(const char *config, int is_hotplug)
{
const char *p;
- USBBus *bus = usb_bus_find(-1 /* any */);
+ char devname[32], buf[32], *params;
+ int busnr = -1; /* any */
+ USBBus *bus;
USBDevice *dev = NULL;
int i;
if (!usb_enabled)
return -1;
+ pstrcpy(devname, sizeof(devname), config);
+ if ((params = strchr(devname,',')) != NULL) {
+ *params = 0;
+ params++;
+ if (get_param_value(buf, sizeof(buf), "busnr", params))
+ busnr = atoi(buf);
+ }
+
+ bus = usb_bus_find(busnr);
+ if (!bus)
+ return -1;
+ fprintf(stderr, "%s: busnr=%d, bus=%s\n", __FUNCTION__, busnr, bus->qbus.name);
+
/* simple devices which don't need extra care */
for (i = 0; i < ARRAY_SIZE(usbdevs); i++) {
if (strcmp(devname, usbdevs[i].name) != 0)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 0/20] qdev patches.
2009-06-29 12:46 [Qemu-devel] [PATCH 0/20] qdev patches Gerd Hoffmann
` (19 preceding siblings ...)
2009-06-29 12:46 ` [Qemu-devel] [PATCH 20/20] debug/test patch: allow specify busnr for -usbdevice Gerd Hoffmann
@ 2009-06-30 0:56 ` Anthony Liguori
2009-06-30 9:26 ` Gerd Hoffmann
20 siblings, 1 reply; 23+ messages in thread
From: Anthony Liguori @ 2009-06-30 0:56 UTC (permalink / raw)
To: Gerd Hoffmann; +Cc: qemu-devel
Gerd Hoffmann wrote:
> Hi,
>
> This is a respin of my qdev patches. They are rebased to the latest
> master. Addressed review comments, partly by changing code, partly by
> clarifying commit messages.
>
> The first five patches build the groundwork, I'd like to see them
> merged soon.
>
Can you split out the first five into a separate series then? We can
focus on getting those right, merge them, and then pick up the rest.
I just did a large push (it's apparently been an active week) and I was
not brave/eager enough rebase your patches on top of my queue :-)
Regards,
Anthony Liguori
> cheers,
> Gerd
>
>
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread