All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/10] qdev patches.
@ 2009-06-17 12:59 Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 01/10] qdev: update pci device registration Gerd Hoffmann
                   ` (11 more replies)
  0 siblings, 12 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

This is a respin of my qdev patches.  They are rebased to the latest
master.

The first two patches are almost unmodified since the last time I posted
them, I think they are ready to be merged.  The pci registration patch
addresses the pci config space access issue, which must be fixed because
otherwise some PCI drivers can't be converted to qdev.

The other patches switch over various drivers and busses to qdev.  They
depend on the first two patches.  The conversion work is far from being
completed.  Currently my main focus is on getting all devices into the
qdev tree.  Most drivers are not (yet) in a state where creating them
from a fdt can actually work though.  IMHO the patches are useful
nevertheless.  YMMV, feel free to cherry-pick some of the patches only.

Open issues:
  usb: The way qemu manages usb ports, hubs and busses needs fixing.
       Right now qemu manages ports only.
  scsi: linking host-devs + guest-devs isn't solved yet.
        Needed for bdrv + scsi-disk to complete scsi conversion.
  ide: not even started yet.

The patches can also be pulled from
	git://git.et.redhat.com/qemu-kraxel.git (branch qdev.v4).

Note: the git tree also has the alsa warning fix so the tree actually
builds ...

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 01/10] qdev: update pci device registration.
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 02/10] qdev: replace bus_type enum with bus_info struct Gerd Hoffmann
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 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      |   23 +++++++++++++++++------
 hw/lsi53c895a.c    |    8 +++++++-
 hw/ne2000.c        |    8 +++++++-
 hw/pci.c           |   24 ++++++++----------------
 hw/pci.h           |    9 ++++++++-
 hw/pcnet.c         |    8 +++++++-
 hw/rtl8139.c       |    8 +++++++-
 hw/versatile_pci.c |    9 +++++++--
 hw/virtio-pci.c    |   29 +++++++++++++++++++++--------
 10 files changed, 96 insertions(+), 38 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index cffcbde..6fdef4a 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1133,9 +1133,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, 1);
 }
 
 device_init(e1000_register_devices)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6f47eaf..df08826 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1792,14 +1792,25 @@ 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,
+    }
+};
+
 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(eepro100_info, ARRAY_SIZE(eepro100_info));
 }
 
 device_init(eepro100_register_devices)
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 71f8281..b07424f 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, 1);
 }
 
 device_init(lsi53c895a_register_devices);
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 66ae9ab..cff6053 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, 1);
 }
 
 device_init(ne2000_register_devices)
diff --git a/hw/pci.c b/hw/pci.c
index 0a738db..662f8a4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -899,11 +899,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;
@@ -914,23 +909,20 @@ 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, int count)
 {
-    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;
+    int i;
 
-    qdev_register(&info->qdev);
+    for (i = 0; i < count; i++, info++) {
+        info->qdev.init = pci_qdev_init;
+        info->qdev.bus_type = BUS_TYPE_PCI;
+        qdev_register(&info->qdev);
+    }
 }
 
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
diff --git a/hw/pci.h b/hw/pci.h
index fcca526..ba41867 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -218,7 +218,14 @@ 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, int count);
 
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
diff --git a/hw/pcnet.c b/hw/pcnet.c
index a184146..0e63d1b 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, 1);
 #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 1364606..45bc8c0 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3501,9 +3501,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, 1);
 }
 
 device_init(rtl8139_register_devices)
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index e89add1..92cf1d0 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, 1);
 }
 
 device_init(versatile_pci_register_devices)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 24fe837..231cc52 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -334,16 +334,29 @@ 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,
+    }
+};
+
 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(virtio_info, ARRAY_SIZE(virtio_info));
 }
 
 device_init(virtio_pci_register_devices)
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 02/10] qdev: replace bus_type enum with bus_info struct.
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 01/10] qdev: update pci device registration Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 03/10] qdev: remove DeviceType Gerd Hoffmann
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 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 662f8a4..5f91175 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);
@@ -94,14 +102,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);
@@ -920,7 +927,7 @@ void pci_qdev_register(PCIDeviceInfo *info, int count)
 
     for (i = 0; i < count; i++, 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);
     }
 }
@@ -935,3 +942,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.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 03/10] qdev: remove DeviceType
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 01/10] qdev: update pci device registration Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 02/10] qdev: replace bus_type enum with bus_info struct Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 04/10] qdev/pci: bus name Gerd Hoffmann
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 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.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 04/10] qdev/pci: bus name
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 03/10] qdev: remove DeviceType Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 05/10] qdev: hook up i440fx Gerd Hoffmann
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 5f91175..099658c 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -101,6 +101,12 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 {
     PCIBus *bus;
     static int nbus = 0;
+    char defname[32];
+
+    if (!name) {
+        snprintf(defname, sizeof(defname), "pci%d", nbus);
+        name = defname;
+    }
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name));
     bus->set_irq = set_irq;
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 05/10] qdev: hook up i440fx.
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 04/10] qdev/pci: bus name Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 06/10] qdev: convert piix-ide, first step Gerd Hoffmann
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 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 |   93 +++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 70 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 914a65a..60fa0fa 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;
 }
 
@@ -320,47 +332,76 @@ 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);
-    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);
+}
+
+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,
+    }
+};
+
+static void i440fx_register(void)
+{
+    sysbus_register_dev("i440FX-pcihost", sizeof(I440FXState), i440fx_pcihost_initfn);
+    pci_qdev_register(i440fx_info, ARRAY_SIZE(i440fx_info));
+}
+device_init(i440fx_register);
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 06/10] qdev: convert piix-ide, first step
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 05/10] qdev: hook up i440fx Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 07/10] qdev-ify: piix acpi Gerd Hoffmann
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/ide.c |   90 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/hw/ide.c b/hw/ide.c
index f3787f2..23f213d 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,67 @@ 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,
+    }
+};
+
+static void piix_ide_register(void)
+{
+    pci_qdev_register(piix_ide_info, ARRAY_SIZE(piix_ide_info));
 }
+device_init(piix_ide_register);
 
 #if defined(TARGET_PPC)
 /***********************************************************/
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 07/10] qdev-ify: piix acpi
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 06/10] qdev: convert piix-ide, first step Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 08/10] qdev-ify: uhci Gerd Hoffmann
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


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 fccae69..6b627cb 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, 1);
+}
+device_init(acpi_register);
+
 #if defined(TARGET_I386)
 void qemu_system_powerdown(void)
 {
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 08/10] qdev-ify: uhci
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 07/10] qdev-ify: piix acpi Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 09/10] qdev-ify: usb Gerd Hoffmann
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-uhci.c |   71 +++++++++++++++++++++++++++++++-------------------------
 1 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 00e740b..e3a501c 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1069,18 +1069,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);
@@ -1103,36 +1096,50 @@ 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,
     }
-    s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
+};
 
-    uhci_reset(s);
+static void acpi_register(void)
+{
+    pci_qdev_register(uhci_info, ARRAY_SIZE(uhci_info));
+}
+device_init(acpi_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.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 09/10] qdev-ify: usb
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 08/10] qdev-ify: uhci Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 10/10] qdev-ify: scsi Gerd Hoffmann
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile        |    2 +-
 hw/bt-hid.c     |   18 +++++-----
 hw/usb-bt.c     |   37 ++++++++++++++-----
 hw/usb-bus.c    |   61 ++++++++++++++++++++++++++++++++
 hw/usb-hid.c    |  103 +++++++++++++++++++++++++++++++-----------------------
 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        |   61 ++++++++++++++++++++------------
 usb-linux.c     |   52 +++++++++++++++++++--------
 vl.c            |    4 +-
 17 files changed, 387 insertions(+), 193 deletions(-)
 create mode 100644 hw/usb-bus.c

diff --git a/Makefile b/Makefile
index dabf322..0ecac45 100644
--- a/Makefile
+++ b/Makefile
@@ -102,7 +102,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..33270f4 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, 1);
 }
+device_init(usb_bt_register_devices)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
new file mode 100644
index 0000000..b216d40
--- /dev/null
+++ b/hw/usb-bus.c
@@ -0,0 +1,61 @@
+#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, int count)
+{
+    int i;
+
+    for (i = 0; i < count; i++) {
+        info[i].qdev.bus_info = &usb_bus_info;
+        info[i].qdev.init     = usb_qdev_init;
+        qdev_register(&info[i].qdev);
+    }
+}
+
+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..f8772de 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,40 @@ 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,
+    }
+};
+
+static void usb_hid_register_devices(void)
+{
+    usb_qdev_register(hid_info, ARRAY_SIZE(hid_info));
+}
+device_init(usb_hid_register_devices)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 9f26bbe..f92f7ad 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, 1);
+}
+device_init(usb_hub_register_devices)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 3a3eb4a..a4c53a7 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, 1);
+}
+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..aa19204 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, 1);
+}
+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..d18be89 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, 1);
+}
+device_init(usb_serial_register_devices)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index e3a501c..dc8d2ee 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 */
@@ -659,7 +660,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);
@@ -1093,6 +1094,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..a3113a7 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, 1);
 }
+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..99fd82d 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,13 @@ 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, int count);
+USBDevice *usb_create_simple(USBBus *bus, const char *name);
diff --git a/usb-linux.c b/usb-linux.c
index 67e4acd..02930ef 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, 1);
+}
+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 3242c23..a616efc 100644
--- a/vl.c
+++ b/vl.c
@@ -2655,7 +2655,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)
@@ -2741,7 +2741,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.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH 10/10] qdev-ify: scsi
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 09/10] qdev-ify: usb Gerd Hoffmann
@ 2009-06-17 12:59 ` Gerd Hoffmann
  2009-06-18 14:39 ` [Qemu-devel] Re: [PATCH 0/10] qdev patches Gerd Hoffmann
  2009-06-19 16:26 ` [Qemu-devel] " Paul Brook
  11 siblings, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-17 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile          |    2 +-
 hw/esp.c          |   28 +++++++++++----------
 hw/lsi53c895a.c   |   31 +++++++++++++----------
 hw/qdev.c         |   19 --------------
 hw/qdev.h         |    4 ---
 hw/scsi-bus.c     |   65 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/scsi-disk.c    |   69 ++++++++++++++++++++++++++++++++--------------------
 hw/scsi-disk.h    |   49 +++++++++++++++++++++++++++++++------
 hw/scsi-generic.c |   62 ++++++++++++++++++++++++++++++-----------------
 hw/usb-msd.c      |   24 ++++++++++--------
 10 files changed, 233 insertions(+), 120 deletions(-)
 create mode 100644 hw/scsi-bus.c

diff --git a/Makefile b/Makefile
index 0ecac45..af998d2 100644
--- a/Makefile
+++ b/Makefile
@@ -100,7 +100,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 5fa910c..7127eca 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) {
@@ -636,13 +637,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,
@@ -686,7 +687,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 b07424f..8c48e02 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 3dc7076..c3ceff0 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -288,25 +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);
-   }
-}
-
 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
 {
     BusState *bus;
diff --git a/hw/qdev.h b/hw/qdev.h
index 18321b3..fa0e96b 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -73,8 +73,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;
@@ -94,8 +92,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..31fb5d7
--- /dev/null
+++ b/hw/scsi-bus.c
@@ -0,0 +1,65 @@
+#include "hw.h"
+#include "sysemu.h"
+#include "scsi-disk.h"
+#include "qdev.h"
+
+static struct BusInfo scsi_bus_info = {
+    .name  = "SCSI",
+    .size  = sizeof(SCSIBus),
+};
+static int next_scsi_bus;
+
+/* Create a scsi bus, and attach devices to it.  */
+SCSIBus *scsi_bus_new(DeviceState *host, int tcq,
+                      SCSIAttachFn attach, scsi_completionfn complete)
+{
+    SCSIBus *bus;
+    char name[32];
+
+    snprintf(name, sizeof(name), "scsi%d", next_scsi_bus);
+    bus = FROM_QBUS(SCSIBus, qbus_create(&scsi_bus_info, host, name));
+    bus->busnr = next_scsi_bus++;
+    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->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..c2d610a 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,37 @@ 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));
+
+    if (bus) {
+        d = scsi_create_simple(bus, "scsi-disk");
+    } else {
+        /* temporary until usb is qdev-ified */
+        d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+    }
     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..53e93f9 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,26 @@ 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;
+    int busnr;
 
-/* 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 a4c53a7..8a92815 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.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2009-06-17 12:59 ` [Qemu-devel] [PATCH 10/10] qdev-ify: scsi Gerd Hoffmann
@ 2009-06-18 14:39 ` Gerd Hoffmann
  2009-06-19 15:59   ` Gerd Hoffmann
  2009-06-19 16:26 ` [Qemu-devel] " Paul Brook
  11 siblings, 1 reply; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-18 14:39 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

   Hi,

> The patches can also be pulled from
> 	git://git.et.redhat.com/qemu-kraxel.git (branch qdev.v4).

Updated patch queue pushed to qdev.v5.  Not posting to avoid spamming 
the list too much.  Online viewable via gitweb here:
http://git.et.redhat.com/?p=qemu-kraxel.git;a=shortlog;h=refs/heads/qdev.v5

Changes:
   * bunch of minor fixes and improvements.
   * more verbose commit messages.
   * more usb work, teach qemu about busses, it can deal with more
     than one usb bus now.

enjoy,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-18 14:39 ` [Qemu-devel] Re: [PATCH 0/10] qdev patches Gerd Hoffmann
@ 2009-06-19 15:59   ` Gerd Hoffmann
  2009-06-19 17:51     ` Paul Brook
  0 siblings, 1 reply; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-19 15:59 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

   Hi,

> Updated patch queue pushed to qdev.v5. Not posting to avoid spamming the
> list too much. Online viewable via gitweb here:
> http://git.et.redhat.com/?p=qemu-kraxel.git;a=shortlog;h=refs/heads/qdev.v5

Todays update pushed to qdev.v6.
http://git.et.redhat.com/?p=qemu-kraxel.git;a=shortlog;h=refs/heads/qdev.v6

Changes:

   * Reordered patches:
     - First the patches with the core changes.
     - Then conversion of some PCI drivers.
     - Next USB.
     - Next SCSI.
     - Finally some test patches I've used to play with multiple
       USB busses.
     The core patches are needed for all others.  The usb-related
     patches build on each other and must be applied in order.
     SCSI goes after USB because of usb-storage.  Otherwise the
     patches should be independent on each other.
   * Converted VGA drivers and ac97/es1370 to qdev.
   * Minor tweaks.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH 0/10] qdev patches.
  2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2009-06-18 14:39 ` [Qemu-devel] Re: [PATCH 0/10] qdev patches Gerd Hoffmann
@ 2009-06-19 16:26 ` Paul Brook
  2009-06-26 21:16   ` Markus Armbruster
  11 siblings, 1 reply; 23+ messages in thread
From: Paul Brook @ 2009-06-19 16:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

> The other patches switch over various drivers and busses to qdev.  They
> depend on the first two patches.  The conversion work is far from being
> completed.  Currently my main focus is on getting all devices into the
> qdev tree.  Most drivers are not (yet) in a state where creating them
> from a fdt can actually work though.  IMHO the patches are useful
> nevertheless.  YMMV, feel free to cherry-pick some of the patches only.

I'm not so convinced. I don't see much value in "dummy" conversion that still 
requires use of the old APIs to create devices.

Paul

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-19 15:59   ` Gerd Hoffmann
@ 2009-06-19 17:51     ` Paul Brook
  2009-06-22  9:15       ` Gerd Hoffmann
  2009-06-22 13:45       ` Gerd Hoffmann
  0 siblings, 2 replies; 23+ messages in thread
From: Paul Brook @ 2009-06-19 17:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

On Friday 19 June 2009, Gerd Hoffmann wrote:
>    Hi,
>
> > Updated patch queue pushed to qdev.v5. Not posting to avoid spamming the
> > list too much. Online viewable via gitweb here:
> > http://git.et.redhat.com/?p=qemu-kraxel.git;a=shortlog;h=refs/heads/qdev.
> >v5
>
> Todays update pushed to qdev.v6.
> http://git.et.redhat.com/?p=qemu-kraxel.git;a=shortlog;h=refs/heads/qdev.v6

A few comments on specific patches:

* qdev: update pci device registration

I dislike passing an {array,length} pair. Especially when it requires every 
user to manually get the right length.

* qdev/core: bus list

I don't seen any good reason for this. In fact I think it is a major step 
backwards. A bus is uniquely identified by its name and parent device.

* qdev/pci: misc fixes.

All uses of the second argument to savevm should go away, not introduce new 
ones. I'm unconvinced by the dev->name change. If we're using the same value 
then why does it exist at all?

* qdev/pci: hook up i440fx

i440fx_init should not exist. c.f. versatile_pci.c

* qdev: update pci device registration

This is exactly the sort of fake conversion that I don't like, because you 
still require use of the old hardcoded initialization functions.
Convenience wrappers like smc91c111_init are fine (and will naturally 
disappear when we have a machine config), but you shouldn't be poking directly 
at device state.
In practice there's no way for the user to have more than one set of IDE 
busses, so I don't see much point pretending we allow this. i.e. remove the 
hd_table argument altogether and use drive_get_index directly.

* qdev: convert all vga

Likewise, pci_vga_init needs to go away.

* qdev/scsi: add scsi bus support to qdev, convert drivers

This still feels wrong, probably because you're using the same thing for both 
a parallel scsi bus, and for devices (usb-msd) that incorporate scsi 
functionality directly. The current qemu scsi API is actually a set of point 
to point links with individual devices. All the bus emulation is local to the 
host controller.

* qdev/usb*

I have not looked at these patches.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-19 17:51     ` Paul Brook
@ 2009-06-22  9:15       ` Gerd Hoffmann
  2009-06-22  9:36         ` Avi Kivity
  2009-06-22 14:02         ` Gerd Hoffmann
  2009-06-22 13:45       ` Gerd Hoffmann
  1 sibling, 2 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-22  9:15 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 06/19/09 19:51, Paul Brook wrote:
> * qdev: update pci device registration
>
> I dislike passing an {array,length} pair. Especially when it requires every
> user to manually get the right length.

qemu has a ARRAY_SIZE macro which can be used like this:
(from uhci patch):

     pci_qdev_register(uhci_info, ARRAY_SIZE(uhci_info));

to get the right length, so I don't see this as a problem.

I can create pci_qdev_register_{single,array} macros to hide the length 
parameter.  I can also just drop the length argument and just use 
multiple calls in the (few) places where multiple drivers are registered 
at once.  What do you prefer?

> * qdev/core: bus list
>
> I don't seen any good reason for this. In fact I think it is a major step
> backwards. A bus is uniquely identified by its name and parent device.

For a static device tree you don't need that indeed.  I've added the 
patch recently while hacking usb, the reason is hotplugging devices. 
When adding devices to busses using monitor commands you'll need some 
way to specify the bus and to find it.  This gets the job done without 
having to walk the whole device tree.

> * qdev/pci: misc fixes.
>
> All uses of the second argument to savevm should go away, not introduce new
> ones.

This just maintains current behavior (PCI busses are numbered starting 
zero).

> I'm unconvinced by the dev->name change. If we're using the same value
> then why does it exist at all?

It is redundant indeed.  I've considered dropping it right away, then 
decided to better wait with that step until all PCI drivers are 
converted to qdev.

> * qdev/pci: hook up i440fx
>
> i440fx_init should not exist. c.f. versatile_pci.c

Indeed.  That is the long-term plan, I'm just not there yet.

> * qdev: update pci device registration

Guess this was supposed to say "qdev: convert piix-ide." ?

> This is exactly the sort of fake conversion that I don't like, because you
> still require use of the old hardcoded initialization functions.

I'd prefer to call them "incomplete" instead of "fake".  I know that 
more work needs to be done to get the drivers into shape for a dt-driven 
machine creation.

> Convenience wrappers like smc91c111_init are fine

Yes, that is the plan for all drivers.  So the old, hardcoded way of 
doing things keeps working while we are busy making the dt-driven 
machine creation work.

I'm just not there yet in all cases.  Basically every old *_init() call 
which has more than a single $bus_create_simple(...) call needs more work.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-22  9:15       ` Gerd Hoffmann
@ 2009-06-22  9:36         ` Avi Kivity
  2009-06-22  9:57           ` Gerd Hoffmann
  2009-06-22 14:02         ` Gerd Hoffmann
  1 sibling, 1 reply; 23+ messages in thread
From: Avi Kivity @ 2009-06-22  9:36 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Paul Brook, qemu-devel

On 06/22/2009 12:15 PM, Gerd Hoffmann wrote:
> On 06/19/09 19:51, Paul Brook wrote:
>> * qdev: update pci device registration
>>
>> I dislike passing an {array,length} pair. Especially when it requires 
>> every
>> user to manually get the right length.
>
> qemu has a ARRAY_SIZE macro which can be used like this:
> (from uhci patch):
>
>     pci_qdev_register(uhci_info, ARRAY_SIZE(uhci_info));
>
> to get the right length, so I don't see this as a problem.
>
> I can create pci_qdev_register_{single,array} macros to hide the 
> length parameter.  I can also just drop the length argument and just 
> use multiple calls in the (few) places where multiple drivers are 
> registered at once.  What do you prefer?

There's a third alternative, zero terminating the array.

If most calls register one qdev, I'd prefer pci_qdev_register() and 
pci_qdev_register_many().

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-22  9:36         ` Avi Kivity
@ 2009-06-22  9:57           ` Gerd Hoffmann
  2009-06-22 11:25             ` Gerd Hoffmann
  0 siblings, 1 reply; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-22  9:57 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Paul Brook, qemu-devel

On 06/22/09 11:36, Avi Kivity wrote:
> On 06/22/2009 12:15 PM, Gerd Hoffmann wrote:
>> I can create pci_qdev_register_{single,array} macros to hide the
>> length parameter. I can also just drop the length argument and just
>> use multiple calls in the (few) places where multiple drivers are
>> registered at once. What do you prefer?
>
> There's a third alternative, zero terminating the array.
>
> If most calls register one qdev, I'd prefer pci_qdev_register() and
> pci_qdev_register_many().

Where register() takes a single instance and register_many() a 
zero-terminated array I guess?  Sounds good.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-22  9:57           ` Gerd Hoffmann
@ 2009-06-22 11:25             ` Gerd Hoffmann
  2009-06-22 11:29               ` Avi Kivity
  0 siblings, 1 reply; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-22 11:25 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Paul Brook, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 454 bytes --]

On 06/22/09 11:57, Gerd Hoffmann wrote:
> On 06/22/09 11:36, Avi Kivity wrote:
>> There's a third alternative, zero terminating the array.
>>
>> If most calls register one qdev, I'd prefer pci_qdev_register() and
>> pci_qdev_register_many().
>
> Where register() takes a single instance and register_many() a
> zero-terminated array I guess? Sounds good.

i.e. something like the attached patch (incremental to the whole patch 
series).

cheers,
   Gerd

[-- Attachment #2: rfc.diff --]
[-- Type: text/plain, Size: 8478 bytes --]

diff --git a/hw/ac97.c b/hw/ac97.c
index bcd5ce1..6ae1524 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1373,7 +1373,7 @@ static PCIDeviceInfo ac97_info = {
 
 static void ac97_register(void)
 {
-    pci_qdev_register(&ac97_info, 1);
+    pci_qdev_register(&ac97_info);
 }
 device_init(ac97_register);
 
diff --git a/hw/acpi.c b/hw/acpi.c
index 6b627cb..7562ef3 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -573,7 +573,7 @@ static PCIDeviceInfo acpi_info = {
 
 static void acpi_register(void)
 {
-    pci_qdev_register(&acpi_info, 1);
+    pci_qdev_register(&acpi_info);
 }
 device_init(acpi_register);
 
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 065545e..19d3fd9 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3350,6 +3350,6 @@ static PCIDeviceInfo cirrus_vga_info = {
 
 static void cirrus_vga_register(void)
 {
-    pci_qdev_register(&cirrus_vga_info, 1);
+    pci_qdev_register(&cirrus_vga_info);
 }
 device_init(cirrus_vga_register);
diff --git a/hw/e1000.c b/hw/e1000.c
index 2a9d3d7..9276968 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1133,7 +1133,7 @@ static PCIDeviceInfo e1000_info = {
 
 static void e1000_register_devices(void)
 {
-    pci_qdev_register(&e1000_info, 1);
+    pci_qdev_register(&e1000_info);
 }
 
 device_init(e1000_register_devices)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index df08826..d406716 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1805,12 +1805,14 @@ static PCIDeviceInfo eepro100_info[] = {
         .qdev.name = "i82559er",
         .qdev.size = sizeof(PCIEEPRO100State),
         .init      = pci_i82559er_init,
+    },{
+        /* end of list */
     }
 };
 
 static void eepro100_register_devices(void)
 {
-    pci_qdev_register(eepro100_info, ARRAY_SIZE(eepro100_info));
+    pci_qdev_register_many(eepro100_info);
 }
 
 device_init(eepro100_register_devices)
diff --git a/hw/es1370.c b/hw/es1370.c
index 6bc345d..ec1e540 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1060,7 +1060,7 @@ static PCIDeviceInfo es1370_info = {
 
 static void es1370_register(void)
 {
-    pci_qdev_register(&es1370_info, 1);
+    pci_qdev_register(&es1370_info);
 }
 device_init(es1370_register);
 
diff --git a/hw/ide.c b/hw/ide.c
index 23f213d..3bc75fa 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -3456,12 +3456,14 @@ static PCIDeviceInfo piix_ide_info[] = {
         .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(piix_ide_info, ARRAY_SIZE(piix_ide_info));
+    pci_qdev_register_many(piix_ide_info);
 }
 device_init(piix_ide_register);
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 8c48e02..1c3d698 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2046,7 +2046,7 @@ static PCIDeviceInfo lsi_info = {
 
 static void lsi53c895a_register_devices(void)
 {
-    pci_qdev_register(&lsi_info, 1);
+    pci_qdev_register(&lsi_info);
 }
 
 device_init(lsi53c895a_register_devices);
diff --git a/hw/ne2000.c b/hw/ne2000.c
index cff6053..66ff29d 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -840,7 +840,7 @@ static PCIDeviceInfo ne2000_info = {
 
 static void ne2000_register_devices(void)
 {
-    pci_qdev_register(&ne2000_info, 1);
+    pci_qdev_register(&ne2000_info);
 }
 
 device_init(ne2000_register_devices)
diff --git a/hw/pci.c b/hw/pci.c
index 30cd304..f13b6aa 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -921,14 +921,18 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     info->init(pci_dev);
 }
 
-void pci_qdev_register(PCIDeviceInfo *info, int count)
+void pci_qdev_register(PCIDeviceInfo *info)
 {
-    int i;
+    info->qdev.init = pci_qdev_init;
+    info->qdev.bus_info = &pci_bus_info;
+    qdev_register(&info->qdev);
+}
 
-    for (i = 0; i < count; i++, info++) {
-        info->qdev.init = pci_qdev_init;
-        info->qdev.bus_info = &pci_bus_info;
-        qdev_register(&info->qdev);
+void pci_qdev_register_many(PCIDeviceInfo *info)
+{
+    while (info->qdev.name) {
+        pci_qdev_register(info);
+        info++;
     }
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index ba41867..5f7b301 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -225,7 +225,8 @@ typedef struct {
     PCIConfigWriteFunc *config_write;
 } PCIDeviceInfo;
 
-void pci_qdev_register(PCIDeviceInfo *info, int count);
+void pci_qdev_register(PCIDeviceInfo *info);
+void pci_qdev_register_many(PCIDeviceInfo *info);
 
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 0e63d1b..4519780 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2151,7 +2151,7 @@ static PCIDeviceInfo pcnet_info = {
 
 static void pcnet_register_devices(void)
 {
-    pci_qdev_register(&pcnet_info, 1);
+    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/piix_pci.c b/hw/piix_pci.c
index cd63bf4..1cbc5c3 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -404,12 +404,14 @@ static PCIDeviceInfo i440fx_info[] = {
         .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(i440fx_info, ARRAY_SIZE(i440fx_info));
+    pci_qdev_register_many(i440fx_info);
 }
 device_init(i440fx_register);
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 5e4ae8f..4ce7cb6 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3507,7 +3507,7 @@ static PCIDeviceInfo rtl8139_info = {
 
 static void rtl8139_register_devices(void)
 {
-    pci_qdev_register(&rtl8139_info, 1);
+    pci_qdev_register(&rtl8139_info);
 }
 
 device_init(rtl8139_register_devices)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index d2c8759..613104d 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1771,6 +1771,6 @@ static PCIDeviceInfo ohci_info = {
 
 static void ohci_register(void)
 {
-    pci_qdev_register(&ohci_info, 1);
+    pci_qdev_register(&ohci_info);
 }
 device_init(ohci_register);
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6674290..ef72e6f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,12 +1129,14 @@ static PCIDeviceInfo uhci_info[] = {
         .qdev.name    = "PIIX4 USB-UHCI",
         .qdev.size    = sizeof(UHCIState),
         .init         = usb_uhci_piix4_initfn,
+    },{
+        /* end of list */
     }
 };
 
 static void uhci_register(void)
 {
-    pci_qdev_register(uhci_info, ARRAY_SIZE(uhci_info));
+    pci_qdev_register_many(uhci_info);
 }
 device_init(uhci_register);
 
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 92cf1d0..5eb2625 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -164,7 +164,7 @@ 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_info, 1);
+    pci_qdev_register(&versatile_pci_host_info);
 }
 
 device_init(versatile_pci_register_devices)
diff --git a/hw/vga.c b/hw/vga.c
index a6056c4..063fa5f 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2538,7 +2538,7 @@ static PCIDeviceInfo vga_info = {
 
 static void vga_register(void)
 {
-    pci_qdev_register(&vga_info, 1);
+    pci_qdev_register(&vga_info);
 }
 device_init(vga_register);
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 231cc52..56be2b3 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -351,12 +351,14 @@ static PCIDeviceInfo virtio_info[] = {
         .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_info, ARRAY_SIZE(virtio_info));
+    pci_qdev_register_many(virtio_info);
 }
 
 device_init(virtio_pci_register_devices)
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 7499c95..5ceebf1 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1251,6 +1251,6 @@ static PCIDeviceInfo vmsvga_info = {
 
 static void vmsvga_register(void)
 {
-    pci_qdev_register(&vmsvga_info, 1);
+    pci_qdev_register(&vmsvga_info);
 }
 device_init(vmsvga_register);

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-22 11:25             ` Gerd Hoffmann
@ 2009-06-22 11:29               ` Avi Kivity
  0 siblings, 0 replies; 23+ messages in thread
From: Avi Kivity @ 2009-06-22 11:29 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Paul Brook, qemu-devel

On 06/22/2009 02:25 PM, Gerd Hoffmann wrote:
> On 06/22/09 11:57, Gerd Hoffmann wrote:
>> On 06/22/09 11:36, Avi Kivity wrote:
>>> There's a third alternative, zero terminating the array.
>>>
>>> If most calls register one qdev, I'd prefer pci_qdev_register() and
>>> pci_qdev_register_many().
>>
>> Where register() takes a single instance and register_many() a
>> zero-terminated array I guess? Sounds good.
>
> i.e. something like the attached patch (incremental to the whole patch 
> series).
>

Yes.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-19 17:51     ` Paul Brook
  2009-06-22  9:15       ` Gerd Hoffmann
@ 2009-06-22 13:45       ` Gerd Hoffmann
  1 sibling, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-22 13:45 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

   Hi,

> In practice there's no way for the user to have more than one set of IDE
> busses, so I don't see much point pretending we allow this. i.e. remove the
> hd_table argument altogether and use drive_get_index directly.

I tend to kill the drives_table[] completely.  It mixes host and guest 
state, we need to separate them.

For the host side I think about a linked list built from stripped down 
DriveInfo which contains the hostside info only (BlockDriverState + 
friends) and a name to reference it.

The guest side will link to the host side state using the name, probably 
passed as attribute.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 0/10] qdev patches.
  2009-06-22  9:15       ` Gerd Hoffmann
  2009-06-22  9:36         ` Avi Kivity
@ 2009-06-22 14:02         ` Gerd Hoffmann
  1 sibling, 0 replies; 23+ messages in thread
From: Gerd Hoffmann @ 2009-06-22 14:02 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

   Hi,

>> This is exactly the sort of fake conversion that I don't like, because
>> you
>> still require use of the old hardcoded initialization functions.
>
> I'd prefer to call them "incomplete" instead of "fake". I know that more
> work needs to be done to get the drivers into shape for a dt-driven
> machine creation.

To followup with some more backgroud on that on that:  These are cases 
where additional arguments are passed to the *_init() function.

Partly the reason is irq windup (i.e. passing around qemu_irqs), which 
must be adapted.  Didn't investigate that one yet.  Probably non-trivial 
to the way interrupts work (pic, lapic, ioapic, ...) in PCs.

Partly the arguments carry extra configutation info.  In that case the 
info should probably come as attributes from the the device tree. 
Didn't look (yet) into using attributes, one of the reasons being that 
the API for them is still quite unclear.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH 0/10] qdev patches.
  2009-06-19 16:26 ` [Qemu-devel] " Paul Brook
@ 2009-06-26 21:16   ` Markus Armbruster
  0 siblings, 0 replies; 23+ messages in thread
From: Markus Armbruster @ 2009-06-26 21:16 UTC (permalink / raw)
  To: qemu-devel

Paul Brook <paul@codesourcery.com> writes:

>> The other patches switch over various drivers and busses to qdev.  They
>> depend on the first two patches.  The conversion work is far from being
>> completed.  Currently my main focus is on getting all devices into the
>> qdev tree.  Most drivers are not (yet) in a state where creating them
>> from a fdt can actually work though.  IMHO the patches are useful
>> nevertheless.  YMMV, feel free to cherry-pick some of the patches only.
>
> I'm not so convinced. I don't see much value in "dummy" conversion that still 
> requires use of the old APIs to create devices.

What's wrong with merging an intermediate step, as long as it doesn't
break anything, clearly moves in the right direction, and the developer
can be trusted to go the rest of the way?

Forcing him to keep his substantial patches out of tree until they're
perfectly complete just creates merging & rebasing hassle for him, which
can only slow him down.  Moreover, it keeps his work less visible, and
thus risks duplicated effort.

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2009-06-26 21:17 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-17 12:59 [Qemu-devel] [PATCH 0/10] qdev patches Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 01/10] qdev: update pci device registration Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 02/10] qdev: replace bus_type enum with bus_info struct Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 03/10] qdev: remove DeviceType Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 04/10] qdev/pci: bus name Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 05/10] qdev: hook up i440fx Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 06/10] qdev: convert piix-ide, first step Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 07/10] qdev-ify: piix acpi Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 08/10] qdev-ify: uhci Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 09/10] qdev-ify: usb Gerd Hoffmann
2009-06-17 12:59 ` [Qemu-devel] [PATCH 10/10] qdev-ify: scsi Gerd Hoffmann
2009-06-18 14:39 ` [Qemu-devel] Re: [PATCH 0/10] qdev patches Gerd Hoffmann
2009-06-19 15:59   ` Gerd Hoffmann
2009-06-19 17:51     ` Paul Brook
2009-06-22  9:15       ` Gerd Hoffmann
2009-06-22  9:36         ` Avi Kivity
2009-06-22  9:57           ` Gerd Hoffmann
2009-06-22 11:25             ` Gerd Hoffmann
2009-06-22 11:29               ` Avi Kivity
2009-06-22 14:02         ` Gerd Hoffmann
2009-06-22 13:45       ` Gerd Hoffmann
2009-06-19 16:26 ` [Qemu-devel] " Paul Brook
2009-06-26 21:16   ` Markus Armbruster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.