Patchwork [26/28] pci: convert to QEMU Object Model

login
register
mail settings
Submitter Anthony Liguori
Date Jan. 24, 2012, 7:33 p.m.
Message ID <1327433600-7403-27-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/137643/
State New
Headers show

Comments

Anthony Liguori - Jan. 24, 2012, 7:33 p.m.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 hw/9pfs/virtio-9p-device.c |   43 ++++++----
 hw/ac97.c                  |   39 +++++----
 hw/acpi_piix4.c            |   59 +++++++------
 hw/apb_pci.c               |   54 ++++++++-----
 hw/bonito.c                |   30 ++++---
 hw/cirrus_vga.c            |   33 +++++---
 hw/dec_pci.c               |   57 ++++++++-----
 hw/e1000.c                 |   43 ++++++----
 hw/eepro100.c              |  200 +++++++++++++++++++++++++++----------------
 hw/es1370.c                |   31 ++++---
 hw/grackle_pci.c           |   25 ++++--
 hw/gt64xxx.c               |   23 ++++--
 hw/i82378.c                |   31 ++++---
 hw/ide/cmd646.c            |   36 +++++---
 hw/ide/ich.c               |   31 ++++---
 hw/ide/piix.c              |   79 +++++++++++-------
 hw/ide/via.c               |   27 ++++--
 hw/intel-hda.c             |   56 ++++++++----
 hw/ioh3420.c               |   59 +++++++------
 hw/ivshmem.c               |   47 ++++++----
 hw/lsi53c895a.c            |   31 ++++---
 hw/macio.c                 |   19 +++--
 hw/ne2000.c                |   35 +++++---
 hw/pci.c                   |  123 ++++++++++++---------------
 hw/pci.h                   |   80 +++++++++---------
 hw/pci_bridge.c            |    2 +-
 hw/pcie.c                  |    2 +-
 hw/pcnet-pci.c             |   39 +++++----
 hw/piix4.c                 |   30 ++++---
 hw/piix_pci.c              |   95 +++++++++++++--------
 hw/ppc4xx_pci.c            |   21 +++--
 hw/ppce500_pci.c           |   21 +++--
 hw/prep_pci.c              |   33 ++++----
 hw/qdev.c                  |    1 +
 hw/qxl.c                   |   62 ++++++++-----
 hw/rtl8139.c               |   41 ++++++----
 hw/sh_pci.c                |   19 +++--
 hw/spapr_pci.c             |   15 +++-
 hw/sun4u.c                 |   23 ++++--
 hw/unin_pci.c              |   92 +++++++++++++-------
 hw/usb-ehci.c              |   54 ++++++++-----
 hw/usb-ohci.c              |   37 +++++---
 hw/usb-uhci.c              |  168 +++++++++++++++++++++++--------------
 hw/usb-xhci.c              |   33 +++++---
 hw/versatile_pci.c         |   22 +++--
 hw/vga-pci.c               |   27 ++++---
 hw/virtio-pci.c            |  188 ++++++++++++++++++++++++-----------------
 hw/vmware_vga.c            |   34 +++++---
 hw/vt82c686.c              |  120 ++++++++++++++++----------
 hw/wdt_i6300esb.c          |   33 +++++---
 hw/xen_platform.c          |   34 +++++---
 hw/xio3130_downstream.c    |   59 +++++++------
 hw/xio3130_upstream.c      |   53 +++++++-----
 53 files changed, 1599 insertions(+), 1050 deletions(-)
Michael S. Tsirkin - Jan. 25, 2012, 12:41 p.m.
On Tue, Jan 24, 2012 at 01:33:18PM -0600, Anthony Liguori wrote:
> diff --git a/hw/ac97.c b/hw/ac97.c
> index 03be99b..33b85f5 100644
> --- a/hw/ac97.c
> +++ b/hw/ac97.c
> @@ -1344,21 +1344,30 @@ int ac97_init (PCIBus *bus)
>      return 0;
>  }
>  
> -static PCIDeviceInfo ac97_info = {
> -    .qdev.name    = "AC97",
> -    .qdev.desc    = "Intel 82801AA AC97 Audio",
> -    .qdev.size    = sizeof (AC97LinkState),
> -    .qdev.vmsd    = &vmstate_ac97,
> -    .init         = ac97_initfn,
> -    .exit         = ac97_exitfn,
> -    .vendor_id    = PCI_VENDOR_ID_INTEL,
> -    .device_id    = PCI_DEVICE_ID_INTEL_82801AA_5,
> -    .revision     = 0x01,
> -    .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
> -    .qdev.props   = (Property[]) {
> -        DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
> -        DEFINE_PROP_END_OF_LIST(),
> -    }
> +static Property ac97_properties[] = {
> +    DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void ac97_class_init(ObjectClass *klass, void *data)
> +{
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> +    k->init = ac97_initfn;
> +    k->exit = ac97_exitfn;
> +    k->vendor_id = PCI_VENDOR_ID_INTEL;
> +    k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
> +    k->revision = 0x01;
> +    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
> +}
> +
> +static DeviceInfo ac97_info = {
> +    .name = "AC97",
> +    .desc = "Intel 82801AA AC97 Audio",
> +    .size = sizeof (AC97LinkState),
> +    .vmsd = &vmstate_ac97,
> +    .props = ac97_properties,
> +    .class_init = ac97_class_init,
>  };
>  
>  static void ac97_register (void)

So I have a question on this: the whole reason
we moved class, vendor id etc away from device init
functions to a table was to make it possible
to perform queries, like list all available sound device
types, or sort devices based on type, based on these tables.

Another purpose was to remove the manually written description/name,
embedding pci id database in qemu instead, and performing
lookups based on device/vendor id.

We never got these patches but it sounds like a genuinely useful
functionality.

Is this no longer possible?
Anthony Liguori - Jan. 25, 2012, 1:34 p.m.
On 01/25/2012 06:41 AM, Michael S. Tsirkin wrote:
> On Tue, Jan 24, 2012 at 01:33:18PM -0600, Anthony Liguori wrote:
>> diff --git a/hw/ac97.c b/hw/ac97.c
>> index 03be99b..33b85f5 100644
>> --- a/hw/ac97.c
>> +++ b/hw/ac97.c
>> @@ -1344,21 +1344,30 @@ int ac97_init (PCIBus *bus)
>>       return 0;
>>   }
>>
>> -static PCIDeviceInfo ac97_info = {
>> -    .qdev.name    = "AC97",
>> -    .qdev.desc    = "Intel 82801AA AC97 Audio",
>> -    .qdev.size    = sizeof (AC97LinkState),
>> -    .qdev.vmsd    =&vmstate_ac97,
>> -    .init         = ac97_initfn,
>> -    .exit         = ac97_exitfn,
>> -    .vendor_id    = PCI_VENDOR_ID_INTEL,
>> -    .device_id    = PCI_DEVICE_ID_INTEL_82801AA_5,
>> -    .revision     = 0x01,
>> -    .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
>> -    .qdev.props   = (Property[]) {
>> -        DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
>> -        DEFINE_PROP_END_OF_LIST(),
>> -    }
>> +static Property ac97_properties[] = {
>> +    DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
>> +    DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void ac97_class_init(ObjectClass *klass, void *data)
>> +{
>> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>> +
>> +    k->init = ac97_initfn;
>> +    k->exit = ac97_exitfn;
>> +    k->vendor_id = PCI_VENDOR_ID_INTEL;
>> +    k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
>> +    k->revision = 0x01;
>> +    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
>> +}
>> +
>> +static DeviceInfo ac97_info = {
>> +    .name = "AC97",
>> +    .desc = "Intel 82801AA AC97 Audio",
>> +    .size = sizeof (AC97LinkState),
>> +    .vmsd =&vmstate_ac97,
>> +    .props = ac97_properties,
>> +    .class_init = ac97_class_init,
>>   };
>>
>>   static void ac97_register (void)
>
> So I have a question on this: the whole reason
> we moved class, vendor id etc away from device init
> functions to a table was to make it possible
> to perform queries, like list all available sound device
> types, or sort devices based on type, based on these tables.
>
> Another purpose was to remove the manually written description/name,
> embedding pci id database in qemu instead, and performing
> lookups based on device/vendor id.
>
> We never got these patches but it sounds like a genuinely useful
> functionality.
>
> Is this no longer possible?

There is one class instance per type.  It's initialized lazily but the types are 
always known.  IOW, ac97_class_init() is called once on the global 
PCIDeviceClass object, most likely very early during init.

These class objects can be searched and interacted with independently of any 
existing object.  What you're after is:

static void show_pci_device(ObjectClass *klass, void *opaque)
{
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);

     printf("Device %s is %02x:%02x\n",
            object_class_get_name(klass), pc->vendor_id, pc->device_id);
}

{
     ...
     object_class_foreach(show_pci_device, TYPE_PCI_DEVICE, false, NULL);
}

Regards,

Anthony Liguori

Patch

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 1325f2f..aded048 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -163,23 +163,32 @@  static int virtio_9p_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
-static PCIDeviceInfo virtio_9p_info = {
-    .qdev.name = "virtio-9p-pci",
-    .qdev.size = sizeof(VirtIOPCIProxy),
-    .init      = virtio_9p_init_pci,
-    .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id = 0x1009,
-    .revision  = VIRTIO_PCI_ABI_VERSION,
-    .class_id  = 0x2,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-        DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-        DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
-        DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
-        DEFINE_PROP_END_OF_LIST(),
-    },
-    .qdev.reset = virtio_pci_reset,
+static Property virtio_9p_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_9p_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_9p_init_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = 0x1009;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = 0x2;
+}
+
+static DeviceInfo virtio_9p_info = {
+    .name = "virtio-9p-pci",
+    .size = sizeof(VirtIOPCIProxy),
+    .props = virtio_9p_properties,
+    .class_init = virtio_9p_class_init,
+    .reset = virtio_pci_reset,
 };
 
 static void virtio_9p_register_devices(void)
diff --git a/hw/ac97.c b/hw/ac97.c
index 03be99b..33b85f5 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1344,21 +1344,30 @@  int ac97_init (PCIBus *bus)
     return 0;
 }
 
-static PCIDeviceInfo ac97_info = {
-    .qdev.name    = "AC97",
-    .qdev.desc    = "Intel 82801AA AC97 Audio",
-    .qdev.size    = sizeof (AC97LinkState),
-    .qdev.vmsd    = &vmstate_ac97,
-    .init         = ac97_initfn,
-    .exit         = ac97_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801AA_5,
-    .revision     = 0x01,
-    .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
-    .qdev.props   = (Property[]) {
-        DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property ac97_properties[] = {
+    DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ac97_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = ac97_initfn;
+    k->exit = ac97_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+}
+
+static DeviceInfo ac97_info = {
+    .name = "AC97",
+    .desc = "Intel 82801AA AC97 Audio",
+    .size = sizeof (AC97LinkState),
+    .vmsd = &vmstate_ac97,
+    .props = ac97_properties,
+    .class_init = ac97_class_init,
 };
 
 static void ac97_register (void)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 4d0b390..9058a7c 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -280,11 +280,11 @@  static void piix4_update_hotplug(PIIX4PMState *s)
     s->pci0_hotplug_enable = ~0;
 
     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
-        PCIDeviceInfo *info = container_of(qdev_get_info(qdev), PCIDeviceInfo, qdev);
-        PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+        PCIDevice *pdev = PCI_DEVICE(qdev);
+        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
         int slot = PCI_SLOT(pdev->devfn);
 
-        if (info->no_hotplug) {
+        if (pc->no_hotplug) {
             s->pci0_hotplug_enable &= ~(1 << slot);
         }
     }
@@ -396,23 +396,32 @@  i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     return s->smb.smbus;
 }
 
-static PCIDeviceInfo piix4_pm_info = {
-    .qdev.name          = "PIIX4_PM",
-    .qdev.desc          = "PM",
-    .qdev.size          = sizeof(PIIX4PMState),
-    .qdev.vmsd          = &vmstate_acpi,
-    .qdev.no_user       = 1,
-    .no_hotplug         = 1,
-    .init               = piix4_pm_initfn,
-    .config_write       = pm_write_config,
-    .vendor_id          = PCI_VENDOR_ID_INTEL,
-    .device_id          = PCI_DEVICE_ID_INTEL_82371AB_3,
-    .revision           = 0x03,
-    .class_id           = PCI_CLASS_BRIDGE_OTHER,
-    .qdev.props         = (Property[]) {
-        DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property piix4_pm_properties[] = {
+    DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void piix4_pm_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = piix4_pm_initfn;
+    k->config_write = pm_write_config;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static DeviceInfo piix4_pm_info = {
+    .name = "PIIX4_PM",
+    .desc = "PM",
+    .size = sizeof(PIIX4PMState),
+    .vmsd = &vmstate_acpi,
+    .no_user = 1,
+    .props = piix4_pm_properties,
+    .class_init = piix4_pm_class_init,
 };
 
 static void piix4_pm_register(void)
@@ -485,14 +494,12 @@  static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 {
     BusState *bus = opaque;
     DeviceState *qdev, *next;
-    PCIDevice *dev;
-    PCIDeviceInfo *info;
     int slot = ffs(val) - 1;
 
     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
-        dev = DO_UPCAST(PCIDevice, qdev, qdev);
-        info = container_of(qdev_get_info(qdev), PCIDeviceInfo, qdev);
-        if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
+        PCIDevice *dev = PCI_DEVICE(qdev);
+        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+        if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) {
             qdev_free(qdev);
         }
     }
@@ -553,7 +560,7 @@  static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 {
     int slot = PCI_SLOT(dev->devfn);
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
-                                DO_UPCAST(PCIDevice, qdev, qdev));
+                                PCI_DEVICE(qdev));
 
     /* Don't send event when device is enabled during qemu machine creation:
      * it is present on boot, no hotplug event is necessary. We do send an
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 3a1b111..70cfc77 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -436,14 +436,21 @@  static int pbm_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo pbm_pci_host_info = {
-    .qdev.name = "pbm",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = pbm_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_SUN,
-    .device_id = PCI_DEVICE_ID_SUN_SABRE,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
-    .is_bridge = 1,
+static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pbm_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    k->is_bridge = 1;
+}
+
+static DeviceInfo pbm_pci_host_info = {
+    .name = "pbm",
+    .size = sizeof(PCIDevice),
+    .class_init = pbm_pci_host_class_init,
 };
 
 static SysBusDeviceInfo pbm_host_info = {
@@ -453,18 +460,25 @@  static SysBusDeviceInfo pbm_host_info = {
     .init = pci_pbm_init_device,
 };
 
-static PCIDeviceInfo pbm_pci_bridge_info = {
-    .qdev.name = "pbm-bridge",
-    .qdev.size = sizeof(PCIBridge),
-    .qdev.vmsd = &vmstate_pci_device,
-    .qdev.reset = pci_bridge_reset,
-    .init = apb_pci_bridge_initfn,
-    .exit = pci_bridge_exitfn,
-    .vendor_id = PCI_VENDOR_ID_SUN,
-    .device_id = PCI_DEVICE_ID_SUN_SIMBA,
-    .revision = 0x11,
-    .config_write = pci_bridge_write_config,
-    .is_bridge = 1,
+static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = apb_pci_bridge_initfn;
+    k->exit = pci_bridge_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
+    k->revision = 0x11;
+    k->config_write = pci_bridge_write_config;
+    k->is_bridge = 1;
+}
+
+static DeviceInfo pbm_pci_bridge_info = {
+    .name = "pbm-bridge",
+    .size = sizeof(PCIBridge),
+    .vmsd = &vmstate_pci_device,
+    .reset = pci_bridge_reset,
+    .class_init = pbm_pci_bridge_class_init,
 };
 
 static void pbm_register_devices(void)
diff --git a/hw/bonito.c b/hw/bonito.c
index f2c7837..23384ec 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -766,18 +766,24 @@  PCIBus *bonito_init(qemu_irq *pic)
     return b;
 }
 
-static PCIDeviceInfo bonito_info = {
-    .qdev.name    = "Bonito",
-    .qdev.desc    = "Host bridge",
-    .qdev.size    = sizeof(PCIBonitoState),
-    .qdev.vmsd    = &vmstate_bonito,
-    .qdev.no_user = 1,
-    .init         = bonito_initfn,
-    /*Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined"*/
-    .vendor_id    = 0xdf53,
-    .device_id    = 0x00d5,
-    .revision     = 0x01,
-    .class_id     = PCI_CLASS_BRIDGE_HOST,
+static void bonito_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = bonito_initfn;
+    k->vendor_id = 0xdf53;
+    k->device_id = 0x00d5;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo bonito_info = {
+    .name = "Bonito",
+    .desc = "Host bridge",
+    .size = sizeof(PCIBonitoState),
+    .vmsd = &vmstate_bonito,
+    .no_user = 1,
+    .class_init = bonito_class_init,
 };
 
 static SysBusDeviceInfo bonito_pcihost_info = {
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 1d0aadf..3fac2ee 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2935,8 +2935,8 @@  static int pci_cirrus_vga_initfn(PCIDevice *dev)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
      CirrusVGAState *s = &d->cirrus_vga;
-     PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, qdev_get_info(&dev->qdev));
-     int16_t device_id = info->device_id;
+     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+     int16_t device_id = pc->device_id;
 
      /* setup VGA */
      vga_common_init(&s->vga, VGA_RAM_SIZE);
@@ -2970,17 +2970,24 @@  DeviceState *pci_cirrus_vga_init(PCIBus *bus)
     return &pci_create_simple(bus, -1, "cirrus-vga")->qdev;
 }
 
-static PCIDeviceInfo cirrus_vga_info = {
-    .qdev.name    = "cirrus-vga",
-    .qdev.desc    = "Cirrus CLGD 54xx VGA",
-    .qdev.size    = sizeof(PCICirrusVGAState),
-    .qdev.vmsd    = &vmstate_pci_cirrus_vga,
-    .no_hotplug   = 1,
-    .init         = pci_cirrus_vga_initfn,
-    .romfile      = VGABIOS_CIRRUS_FILENAME,
-    .vendor_id    = PCI_VENDOR_ID_CIRRUS,
-    .device_id    = CIRRUS_ID_CLGD5446,
-    .class_id     = PCI_CLASS_DISPLAY_VGA,
+static void cirrus_vga_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_cirrus_vga_initfn;
+    k->romfile = VGABIOS_CIRRUS_FILENAME;
+    k->vendor_id = PCI_VENDOR_ID_CIRRUS;
+    k->device_id = CIRRUS_ID_CLGD5446;
+    k->class_id = PCI_CLASS_DISPLAY_VGA;
+}
+
+static DeviceInfo cirrus_vga_info = {
+    .name = "cirrus-vga",
+    .desc = "Cirrus CLGD 54xx VGA",
+    .size = sizeof(PCICirrusVGAState),
+    .vmsd = &vmstate_pci_cirrus_vga,
+    .class_init = cirrus_vga_class_init,
 };
 
 static void cirrus_vga_register(void)
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 08d4e06..7c3f50e 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -50,18 +50,25 @@  static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
     return irq_num;
 }
 
-static PCIDeviceInfo dec_21154_pci_bridge_info = {
-    .qdev.name = "dec-21154-p2p-bridge",
-    .qdev.desc = "DEC 21154 PCI-PCI bridge",
-    .qdev.size = sizeof(PCIBridge),
-    .qdev.vmsd = &vmstate_pci_device,
-    .qdev.reset = pci_bridge_reset,
-    .init = pci_bridge_initfn,
-    .exit = pci_bridge_exitfn,
-    .vendor_id = PCI_VENDOR_ID_DEC,
-    .device_id = PCI_DEVICE_ID_DEC_21154,
-    .config_write = pci_bridge_write_config,
-    .is_bridge = 1,
+static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_bridge_initfn;
+    k->exit = pci_bridge_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_DEC;
+    k->device_id = PCI_DEVICE_ID_DEC_21154;
+    k->config_write = pci_bridge_write_config;
+    k->is_bridge = 1;
+}
+
+static DeviceInfo dec_21154_pci_bridge_info = {
+    .name = "dec-21154-p2p-bridge",
+    .desc = "DEC 21154 PCI-PCI bridge",
+    .size = sizeof(PCIBridge),
+    .vmsd = &vmstate_pci_device,
+    .reset = pci_bridge_reset,
+    .class_init = dec_21154_pci_bridge_class_init,
 };
 
 PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
@@ -98,21 +105,29 @@  static int dec_21154_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo dec_21154_pci_host_info = {
-    .qdev.name = "dec-21154",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = dec_21154_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_DEC,
-    .device_id = PCI_DEVICE_ID_DEC_21154,
-    .revision = 0x02,
-    .class_id = PCI_CLASS_BRIDGE_PCI,
-    .is_bridge  = 1,
+static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = dec_21154_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_DEC;
+    k->device_id = PCI_DEVICE_ID_DEC_21154;
+    k->revision = 0x02;
+    k->class_id = PCI_CLASS_BRIDGE_PCI;
+    k->is_bridge = 1;
+}
+
+static DeviceInfo dec_21154_pci_host_info = {
+    .name = "dec-21154",
+    .size = sizeof(PCIDevice),
+    .class_init = dec_21154_pci_host_class_init,
 };
 
 static void dec_register_devices(void)
 {
     sysbus_register_dev("dec-21154", sizeof(DECState),
                         pci_dec_21154_init_device);
+
     pci_qdev_register(&dec_21154_pci_host_info);
     pci_qdev_register(&dec_21154_pci_bridge_info);
 }
diff --git a/hw/e1000.c b/hw/e1000.c
index 6bab54e..c5d3ecb 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1192,23 +1192,32 @@  static void qdev_e1000_reset(DeviceState *dev)
     e1000_reset(d);
 }
 
-static PCIDeviceInfo e1000_info = {
-    .qdev.name  = "e1000",
-    .qdev.desc  = "Intel Gigabit Ethernet",
-    .qdev.size  = sizeof(E1000State),
-    .qdev.reset = qdev_e1000_reset,
-    .qdev.vmsd  = &vmstate_e1000,
-    .init       = pci_e1000_init,
-    .exit       = pci_e1000_uninit,
-    .romfile    = "pxe-e1000.rom",
-    .vendor_id  = PCI_VENDOR_ID_INTEL,
-    .device_id  = E1000_DEVID,
-    .revision   = 0x03,
-    .class_id   = PCI_CLASS_NETWORK_ETHERNET,
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(E1000State, conf),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property e1000_properties[] = {
+    DEFINE_NIC_PROPERTIES(E1000State, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void e1000_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_e1000_init;
+    k->exit = pci_e1000_uninit;
+    k->romfile = "pxe-e1000.rom";
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = E1000_DEVID;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+}
+
+static DeviceInfo e1000_info = {
+    .name = "e1000",
+    .desc = "Intel Gigabit Ethernet",
+    .size = sizeof(E1000State),
+    .reset = qdev_e1000_reset,
+    .vmsd = &vmstate_e1000,
+    .props = e1000_properties,
+    .class_init = e1000_class_init,
 };
 
 static void e1000_register_devices(void)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index f0059c6..9f6d333 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -128,7 +128,13 @@ 
 #define DRVR_INT        0x0200  /* Driver generated interrupt. */
 
 typedef struct {
-    PCIDeviceInfo pci;
+    DeviceInfo qdev;
+
+    uint16_t device_id;
+    uint8_t revision;
+    uint16_t subsystem_vendor_id;
+    uint16_t subsystem_id;
+
     uint32_t device;
     uint8_t stats_size;
     bool has_extended_tcb_support;
@@ -318,6 +324,8 @@  static const uint16_t eepro100_mdi_mask[] = {
 
 #define POLYNOMIAL 0x04c11db6
 
+static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
+
 /* From FreeBSD */
 /* XXX: optimize */
 static unsigned compute_mcast_idx(const uint8_t * ep)
@@ -487,8 +495,9 @@  static void eepro100_fcp_interrupt(EEPRO100State * s)
 }
 #endif
 
-static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
+static void e100_pci_reset(EEPRO100State * s)
 {
+    E100PCIDeviceInfo *info = eepro100_get_class(s);
     uint32_t device = s->device;
     uint8_t *pci_conf = s->dev.config;
 
@@ -508,8 +517,8 @@  static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
     /* Maximum Latency */
     pci_set_byte(pci_conf + PCI_MAX_LAT, 0x18);
 
-    s->stats_size = e100_device->stats_size;
-    s->has_extended_tcb_support = e100_device->has_extended_tcb_support;
+    s->stats_size = info->stats_size;
+    s->has_extended_tcb_support = info->has_extended_tcb_support;
 
     switch (device) {
     case i82550:
@@ -558,7 +567,7 @@  static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
     }
     assert(s->stats_size > 0 && s->stats_size <= sizeof(s->statistics));
 
-    if (e100_device->power_management) {
+    if (info->power_management) {
         /* Power Management Capabilities */
         int cfg_offset = 0xdc;
         int r = pci_add_capability(&s->dev, PCI_CAP_ID_PM,
@@ -1847,14 +1856,13 @@  static NetClientInfo net_eepro100_info = {
 static int e100_nic_init(PCIDevice *pci_dev)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
-    E100PCIDeviceInfo *e100_device = DO_UPCAST(E100PCIDeviceInfo, pci.qdev,
-                                               qdev_get_info(&pci_dev->qdev));
+    E100PCIDeviceInfo *info = eepro100_get_class(s);
 
     TRACE(OTHER, logout("\n"));
 
-    s->device = e100_device->device;
+    s->device = info->device;
 
-    e100_pci_reset(s, e100_device);
+    e100_pci_reset(s);
 
     /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
      * i82559 and later support 64 or 256 word EEPROM. */
@@ -1897,136 +1905,182 @@  static int e100_nic_init(PCIDevice *pci_dev)
 
 static E100PCIDeviceInfo e100_devices[] = {
     {
-        .pci.qdev.name = "i82550",
-        .pci.qdev.desc = "Intel i82550 Ethernet",
+        .qdev.name = "i82550",
+        .qdev.desc = "Intel i82550 Ethernet",
         .device = i82550,
         /* TODO: check device id. */
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
         /* Revision ID: 0x0c, 0x0d, 0x0e. */
-        .pci.revision = 0x0e,
+        .revision = 0x0e,
         /* TODO: check size of statistical counters. */
         .stats_size = 80,
         /* TODO: check extended tcb support. */
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82551",
-        .pci.qdev.desc = "Intel i82551 Ethernet",
+        .qdev.name = "i82551",
+        .qdev.desc = "Intel i82551 Ethernet",
         .device = i82551,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
         /* Revision ID: 0x0f, 0x10. */
-        .pci.revision = 0x0f,
+        .revision = 0x0f,
         /* TODO: check size of statistical counters. */
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82557a",
-        .pci.qdev.desc = "Intel i82557A Ethernet",
+        .qdev.name = "i82557a",
+        .qdev.desc = "Intel i82557A Ethernet",
         .device = i82557A,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x01,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x01,
         .power_management = false,
     },{
-        .pci.qdev.name = "i82557b",
-        .pci.qdev.desc = "Intel i82557B Ethernet",
+        .qdev.name = "i82557b",
+        .qdev.desc = "Intel i82557B Ethernet",
         .device = i82557B,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x02,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x02,
         .power_management = false,
     },{
-        .pci.qdev.name = "i82557c",
-        .pci.qdev.desc = "Intel i82557C Ethernet",
+        .qdev.name = "i82557c",
+        .qdev.desc = "Intel i82557C Ethernet",
         .device = i82557C,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x03,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x03,
         .power_management = false,
     },{
-        .pci.qdev.name = "i82558a",
-        .pci.qdev.desc = "Intel i82558A Ethernet",
+        .qdev.name = "i82558a",
+        .qdev.desc = "Intel i82558A Ethernet",
         .device = i82558A,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x04,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x04,
         .stats_size = 76,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82558b",
-        .pci.qdev.desc = "Intel i82558B Ethernet",
+        .qdev.name = "i82558b",
+        .qdev.desc = "Intel i82558B Ethernet",
         .device = i82558B,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x05,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x05,
         .stats_size = 76,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82559a",
-        .pci.qdev.desc = "Intel i82559A Ethernet",
+        .qdev.name = "i82559a",
+        .qdev.desc = "Intel i82559A Ethernet",
         .device = i82559A,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x06,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x06,
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82559b",
-        .pci.qdev.desc = "Intel i82559B Ethernet",
+        .qdev.name = "i82559b",
+        .qdev.desc = "Intel i82559B Ethernet",
         .device = i82559B,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
-        .pci.revision = 0x07,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
+        .revision = 0x07,
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82559c",
-        .pci.qdev.desc = "Intel i82559C Ethernet",
+        .qdev.name = "i82559c",
+        .qdev.desc = "Intel i82559C Ethernet",
         .device = i82559C,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+        .device_id = PCI_DEVICE_ID_INTEL_82557,
 #if 0
-        .pci.revision = 0x08,
+        .revision = 0x08,
 #endif
         /* TODO: Windows wants revision id 0x0c. */
-        .pci.revision = 0x0c,
+        .revision = 0x0c,
 #if EEPROM_SIZE > 0
-        .pci.subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
-        .pci.subsystem_id = 0x0040,
+        .subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
+        .subsystem_id = 0x0040,
 #endif
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82559er",
-        .pci.qdev.desc = "Intel i82559ER Ethernet",
+        .qdev.name = "i82559er",
+        .qdev.desc = "Intel i82559ER Ethernet",
         .device = i82559ER,
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
-        .pci.revision = 0x09,
+        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
+        .revision = 0x09,
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
-        .pci.qdev.name = "i82562",
-        .pci.qdev.desc = "Intel i82562 Ethernet",
+        .qdev.name = "i82562",
+        .qdev.desc = "Intel i82562 Ethernet",
         .device = i82562,
         /* TODO: check device id. */
-        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
         /* TODO: wrong revision id. */
-        .pci.revision = 0x0e,
+        .revision = 0x0e,
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     },{
         /* Toshiba Tecra 8200. */
-        .pci.qdev.name = "i82801",
-        .pci.qdev.desc = "Intel i82801 Ethernet",
+        .qdev.name = "i82801",
+        .qdev.desc = "Intel i82801 Ethernet",
         .device = i82801,
-        .pci.device_id = 0x2449,
-        .pci.revision = 0x03,
+        .device_id = 0x2449,
+        .revision = 0x03,
         .stats_size = 80,
         .has_extended_tcb_support = true,
         .power_management = true,
     }
 };
 
+static E100PCIDeviceInfo *eepro100_get_class_by_name(const char *typename)
+{
+    E100PCIDeviceInfo *info = NULL;
+    int i;
+
+    /* This is admittedly awkward but also temporary.  QOM allows for
+     * parameterized typing and for subclassing both of which would suitable
+     * handle what's going on here.  But class_data is already being used as
+     * a stop-gap hack to allow incremental qdev conversion so we cannot use it
+     * right now.  Once we merge the final QOM series, we can come back here and
+     * do this in a much more elegant fashion.
+     */
+    for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
+        if (strcmp(e100_devices[i].qdev.name, typename) == 0) {
+            info = &e100_devices[i];
+            break;
+        }
+    }
+    assert(info != NULL);
+
+    return info;
+}
+
+static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
+{
+    return eepro100_get_class_by_name(object_get_typename(OBJECT(s)));
+}
+
+static void eepro100_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    E100PCIDeviceInfo *info;
+
+    info = eepro100_get_class_by_name(object_class_get_name(klass));
+
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+    k->romfile = "pxe-eepro100.rom";
+    k->init = e100_nic_init;
+    k->exit = pci_nic_uninit;
+    k->device_id = info->device_id;
+    k->revision = info->revision;
+    k->subsystem_vendor_id = info->subsystem_vendor_id;
+    k->subsystem_id = info->subsystem_id;
+}
+
 static Property e100_properties[] = {
     DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
     DEFINE_PROP_END_OF_LIST(),
@@ -2036,17 +2090,13 @@  static void eepro100_register_devices(void)
 {
     size_t i;
     for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
-        PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
-        /* We use the same rom file for all device ids.
-           QEMU fixes the device id during rom load. */
-        pci_dev->vendor_id = PCI_VENDOR_ID_INTEL;
-        pci_dev->class_id = PCI_CLASS_NETWORK_ETHERNET;
-        pci_dev->romfile = "pxe-eepro100.rom";
-        pci_dev->init = e100_nic_init;
-        pci_dev->exit = pci_nic_uninit;
-        pci_dev->qdev.props = e100_properties;
-        pci_dev->qdev.size = sizeof(EEPRO100State);
-        pci_qdev_register(pci_dev);
+        DeviceInfo *info = &e100_devices[i].qdev;
+
+        info->class_init = eepro100_class_init;
+        info->size = sizeof(EEPRO100State);
+        info->props = e100_properties;
+        
+        pci_qdev_register(info);
     }
 }
 
diff --git a/hw/es1370.c b/hw/es1370.c
index 3527eb6..205bed7 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1031,18 +1031,25 @@  int es1370_init (PCIBus *bus)
     return 0;
 }
 
-static PCIDeviceInfo es1370_info = {
-    .qdev.name    = "ES1370",
-    .qdev.desc    = "ENSONIQ AudioPCI ES1370",
-    .qdev.size    = sizeof (ES1370State),
-    .qdev.vmsd    = &vmstate_es1370,
-    .init         = es1370_initfn,
-    .exit         = es1370_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_ENSONIQ,
-    .device_id    = PCI_DEVICE_ID_ENSONIQ_ES1370,
-    .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
-    .subsystem_vendor_id = 0x4942,
-    .subsystem_id = 0x4c4c,
+static void es1370_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = es1370_initfn;
+    k->exit = es1370_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_ENSONIQ;
+    k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370;
+    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+    k->subsystem_vendor_id = 0x4942;
+    k->subsystem_id = 0x4c4c;
+}
+
+static DeviceInfo es1370_info = {
+    .name = "ES1370",
+    .desc = "ENSONIQ AudioPCI ES1370",
+    .size = sizeof (ES1370State),
+    .vmsd = &vmstate_es1370,
+    .class_init = es1370_class_init,
 };
 
 static void es1370_register (void)
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index be10a6d..a790f97 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -121,15 +121,22 @@  static int grackle_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo grackle_pci_info = {
-    .qdev.name = "grackle",
-    .qdev.size = sizeof(PCIDevice),
-    .qdev.no_user = 1,
-    .init      = grackle_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_MOTOROLA,
-    .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
-    .revision  = 0x00,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void grackle_pci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = grackle_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo grackle_pci_info = {
+    .name = "grackle",
+    .size = sizeof(PCIDevice),
+    .no_user = 1,
+    .class_init = grackle_pci_class_init,
 };
 
 static SysBusDeviceInfo grackle_pci_host_info = {
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 432683a..9fc51f2 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1136,14 +1136,21 @@  static int gt64120_pci_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo gt64120_pci_info = {
-    .qdev.name = "gt64120_pci",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = gt64120_pci_init,
-    .vendor_id = PCI_VENDOR_ID_MARVELL,
-    .device_id = PCI_DEVICE_ID_MARVELL_GT6412X,
-    .revision  = 0x10,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void gt64120_pci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = gt64120_pci_init;
+    k->vendor_id = PCI_VENDOR_ID_MARVELL;
+    k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X;
+    k->revision = 0x10;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo gt64120_pci_info = {
+    .name = "gt64120_pci",
+    .size = sizeof(PCIDevice),
+    .class_init = gt64120_pci_class_init,
 };
 
 static void gt64120_pci_register_devices(void)
diff --git a/hw/i82378.c b/hw/i82378.c
index 95ae274..99b453a 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -238,18 +238,25 @@  static int pci_i82378_init(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo pci_i82378_info = {
-    .init = pci_i82378_init,
-    .qdev.name = "i82378",
-    .qdev.size = sizeof(PCIi82378State),
-    .qdev.vmsd = &vmstate_pci_i82378,
-    .vendor_id = PCI_VENDOR_ID_INTEL,
-    .device_id = PCI_DEVICE_ID_INTEL_82378,
-    .revision = 0x03,
-    .class_id = PCI_CLASS_BRIDGE_ISA,
-    .subsystem_vendor_id = 0x0,
-    .subsystem_id = 0x0,
-    .qdev.props = (Property[]) {
+static void pci_i82378_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_i82378_init;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82378;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_BRIDGE_ISA;
+    k->subsystem_vendor_id = 0x0;
+    k->subsystem_id = 0x0;
+}
+
+static DeviceInfo pci_i82378_info = {
+    .name = "i82378",
+    .size = sizeof(PCIi82378State),
+    .vmsd = &vmstate_pci_i82378,
+    .class_init = pci_i82378_class_init,
+    .props = (Property[]) {
         DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
         DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
         DEFINE_PROP_END_OF_LIST()
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 99e7e6f..9c673bb 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -325,20 +325,28 @@  void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
     pci_ide_create_devs(dev, hd_table);
 }
 
-static PCIDeviceInfo cmd646_ide_info = {
-    .qdev.name    = "cmd646-ide",
-    .qdev.size    = sizeof(PCIIDEState),
-    .init         = pci_cmd646_ide_initfn,
-    .exit         = pci_cmd646_ide_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_CMD,
-    .device_id    = PCI_DEVICE_ID_CMD_646,
-    /* IDE controller revision */
-    .revision     = 0x07,
-    .class_id     = PCI_CLASS_STORAGE_IDE,
-    .qdev.props   = (Property[]) {
-        DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property cmd646_ide_properties[] = {
+    DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void cmd646_ide_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_cmd646_ide_initfn;
+    k->exit = pci_cmd646_ide_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_CMD;
+    k->device_id = PCI_DEVICE_ID_CMD_646;
+    k->revision = 0x07;
+    k->class_id = PCI_CLASS_STORAGE_IDE;
+}
+
+static DeviceInfo cmd646_ide_info = {
+    .name = "cmd646-ide",
+    .size = sizeof(PCIIDEState),
+    .props = cmd646_ide_properties,
+    .class_init = cmd646_ide_class_init,
 };
 
 static void cmd646_ide_register(void)
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index e6421e2..1cae9f1 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -146,18 +146,25 @@  static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr,
     msi_write_config(pci, addr, val, len);
 }
 
-static PCIDeviceInfo ich_ahci_info = {
-    .qdev.name    = "ich9-ahci",
-    .qdev.alias   = "ahci",
-    .qdev.size    = sizeof(AHCIPCIState),
-    .qdev.vmsd    = &vmstate_ahci,
-    .init         = pci_ich9_ahci_init,
-    .exit         = pci_ich9_uninit,
-    .config_write = pci_ich9_write_config,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801IR,
-    .revision     = 0x02,
-    .class_id     = PCI_CLASS_STORAGE_SATA,
+static void ich_ahci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ich9_ahci_init;
+    k->exit = pci_ich9_uninit;
+    k->config_write = pci_ich9_write_config;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
+    k->revision = 0x02;
+    k->class_id = PCI_CLASS_STORAGE_SATA;
+}
+
+static DeviceInfo ich_ahci_info = {
+    .name = "ich9-ahci",
+    .alias = "ahci",
+    .size = sizeof(AHCIPCIState),
+    .vmsd = &vmstate_ahci,
+    .class_init = ich_ahci_class_init,
 };
 
 static void ich_ahci_register(void)
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 91b77a2..832a507 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -237,39 +237,60 @@  PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
     return dev;
 }
 
-static PCIDeviceInfo piix3_ide_info = {
-    .qdev.name    = "piix3-ide",
-    .qdev.size    = sizeof(PCIIDEState),
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = pci_piix_ide_initfn,
-    .exit         = pci_piix_ide_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
-    .class_id     = PCI_CLASS_STORAGE_IDE,
+static void piix3_ide_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_piix_ide_initfn;
+    k->exit = pci_piix_ide_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
+    k->class_id = PCI_CLASS_STORAGE_IDE;
+}
+
+static DeviceInfo piix3_ide_info = {
+    .name = "piix3-ide",
+    .size = sizeof(PCIIDEState),
+    .no_user = 1,
+    .class_init = piix3_ide_class_init,
 };
 
-static PCIDeviceInfo piix3_ide_xen_info = {
-    .qdev.name    = "piix3-ide-xen",
-    .qdev.size    = sizeof(PCIIDEState),
-    .qdev.no_user = 1,
-    .qdev.unplug  = pci_piix3_xen_ide_unplug,
-    .init         = pci_piix_ide_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
-    .class_id     = PCI_CLASS_STORAGE_IDE,
+static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_piix_ide_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
+    k->class_id = PCI_CLASS_STORAGE_IDE;
+}
+
+static DeviceInfo piix3_ide_xen_info = {
+    .name = "piix3-ide-xen",
+    .size = sizeof(PCIIDEState),
+    .no_user = 1,
+    .class_init = piix3_ide_xen_class_init,
+    .unplug = pci_piix3_xen_ide_unplug,
 };
 
-static PCIDeviceInfo piix4_ide_info = {
-    .qdev.name    = "piix4-ide",
-    .qdev.size    = sizeof(PCIIDEState),
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = pci_piix_ide_initfn,
-    .exit         = pci_piix_ide_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82371AB,
-    .class_id     = PCI_CLASS_STORAGE_IDE,
+static void piix4_ide_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_piix_ide_initfn;
+    k->exit = pci_piix_ide_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
+    k->class_id = PCI_CLASS_STORAGE_IDE;
+}
+
+static DeviceInfo piix4_ide_info = {
+    .name = "piix4-ide",
+    .size = sizeof(PCIIDEState),
+    .no_user = 1,
+    .class_init = piix4_ide_class_init,
 };
 
 static void piix_ide_register(void)
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 4ea2064..ef70864 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -213,16 +213,23 @@  void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
     pci_ide_create_devs(dev, hd_table);
 }
 
-static PCIDeviceInfo via_ide_info = {
-    .qdev.name    = "via-ide",
-    .qdev.size    = sizeof(PCIIDEState),
-    .qdev.no_user = 1,
-    .init         = vt82c686b_ide_initfn,
-    .exit         = vt82c686b_ide_exitfn,
-    .vendor_id    = PCI_VENDOR_ID_VIA,
-    .device_id    = PCI_DEVICE_ID_VIA_IDE,
-    .revision     = 0x06,
-    .class_id     = PCI_CLASS_STORAGE_IDE,
+static void via_ide_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = vt82c686b_ide_initfn;
+    k->exit = vt82c686b_ide_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_IDE;
+    k->revision = 0x06;
+    k->class_id = PCI_CLASS_STORAGE_IDE;
+}
+
+static DeviceInfo via_ide_info = {
+    .name = "via-ide",
+    .size = sizeof(PCIIDEState),
+    .no_user = 1,
+    .class_init = via_ide_class_init,
 };
 
 static void via_ide_register(void)
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index f727c22..f062133 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -79,7 +79,7 @@  void hda_codec_register(DeviceInfo *info)
     info->init = hda_codec_dev_init;
     info->exit = hda_codec_dev_exit;
     info->bus_info = &hda_codec_bus_info;
-    qdev_register(info);
+    qdev_register_subclass(info, TYPE_HDA_CODEC_DEVICE);
 }
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
@@ -1247,29 +1247,47 @@  static const VMStateDescription vmstate_intel_hda = {
     }
 };
 
-static PCIDeviceInfo intel_hda_info = {
-    .qdev.name    = "intel-hda",
-    .qdev.desc    = "Intel HD Audio Controller",
-    .qdev.size    = sizeof(IntelHDAState),
-    .qdev.vmsd    = &vmstate_intel_hda,
-    .qdev.reset   = intel_hda_reset,
-    .init         = intel_hda_init,
-    .exit         = intel_hda_exit,
-    .config_write = intel_hda_write_config,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = 0x2668,
-    .revision     = 1,
-    .class_id     = PCI_CLASS_MULTIMEDIA_HD_AUDIO,
-    .qdev.props   = (Property[]) {
-        DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
-        DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property intel_hda_properties[] = {
+    DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
+    DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void intel_hda_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = intel_hda_init;
+    k->exit = intel_hda_exit;
+    k->config_write = intel_hda_write_config;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = 0x2668;
+    k->revision = 1;
+    k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
+}
+
+static DeviceInfo intel_hda_info = {
+    .name = "intel-hda",
+    .desc = "Intel HD Audio Controller",
+    .size = sizeof(IntelHDAState),
+    .vmsd = &vmstate_intel_hda,
+    .reset = intel_hda_reset,
+    .props = intel_hda_properties,
+    .class_init = intel_hda_class_init,
+};
+
+static TypeInfo hda_codec_device_type_info = {
+    .name = TYPE_HDA_CODEC_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(HDACodecDevice),
+    .abstract = true,
+    .class_size = sizeof(HDACodecDeviceClass),
 };
 
 static void intel_hda_register(void)
 {
     pci_qdev_register(&intel_hda_info);
+    type_register_static(&hda_codec_device_type_info);
 }
 device_init(intel_hda_register);
 
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index a6bfbb9..6cfafb3 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -80,7 +80,7 @@  static void ioh3420_write_config(PCIDevice *d,
 
 static void ioh3420_reset(DeviceState *qdev)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    PCIDevice *d = PCI_DEVICE(qdev);
     msi_reset(d);
     ioh3420_aer_vector_update(d);
     pcie_cap_root_reset(d);
@@ -201,31 +201,38 @@  static const VMStateDescription vmstate_ioh3420 = {
     }
 };
 
-static PCIDeviceInfo ioh3420_info = {
-    .qdev.name = "ioh3420",
-    .qdev.desc = "Intel IOH device id 3420 PCIE Root Port",
-    .qdev.size = sizeof(PCIESlot),
-    .qdev.reset = ioh3420_reset,
-    .qdev.vmsd = &vmstate_ioh3420,
-
-    .is_express = 1,
-    .is_bridge = 1,
-    .config_write = ioh3420_write_config,
-    .init = ioh3420_initfn,
-    .exit = ioh3420_exitfn,
-    .vendor_id = PCI_VENDOR_ID_INTEL,
-    .device_id = PCI_DEVICE_ID_IOH_EPORT,
-    .revision = PCI_DEVICE_ID_IOH_REV,
-
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
-        DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
-        DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-        DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
-                           port.br.dev.exp.aer_log.log_max,
-                           PCIE_AER_LOG_MAX_DEFAULT),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property ioh3420_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+    port.br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ioh3420_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = ioh3420_write_config;
+    k->init = ioh3420_initfn;
+    k->exit = ioh3420_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_IOH_EPORT;
+    k->revision = PCI_DEVICE_ID_IOH_REV;
+}
+
+static DeviceInfo ioh3420_info = {
+    .name = "ioh3420",
+    .desc = "Intel IOH device id 3420 PCIE Root Port",
+    .size = sizeof(PCIESlot),
+    .reset = ioh3420_reset,
+    .vmsd = &vmstate_ioh3420,
+    .props = ioh3420_properties,
+    .class_init = ioh3420_class_init,
 };
 
 static void ioh3420_register(void)
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index bec2e0b..e2880be 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -766,25 +766,34 @@  static int pci_ivshmem_uninit(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo ivshmem_info = {
-    .qdev.name  = "ivshmem",
-    .qdev.size  = sizeof(IVShmemState),
-    .qdev.reset = ivshmem_reset,
-    .init       = pci_ivshmem_init,
-    .exit       = pci_ivshmem_uninit,
-    .vendor_id  = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id  = 0x1110,
-    .class_id   = PCI_CLASS_MEMORY_RAM,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
-        DEFINE_PROP_STRING("size", IVShmemState, sizearg),
-        DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1),
-        DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, false),
-        DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true),
-        DEFINE_PROP_STRING("shm", IVShmemState, shmobj),
-        DEFINE_PROP_STRING("role", IVShmemState, role),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property ivshmem_properties[] = {
+    DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
+    DEFINE_PROP_STRING("size", IVShmemState, sizearg),
+    DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1),
+    DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, false),
+    DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true),
+    DEFINE_PROP_STRING("shm", IVShmemState, shmobj),
+    DEFINE_PROP_STRING("role", IVShmemState, role),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ivshmem_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ivshmem_init;
+    k->exit = pci_ivshmem_uninit;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = 0x1110;
+    k->class_id = PCI_CLASS_MEMORY_RAM;
+}
+
+static DeviceInfo ivshmem_info = {
+    .name = "ivshmem",
+    .size = sizeof(IVShmemState),
+    .reset = ivshmem_reset,
+    .props = ivshmem_properties,
+    .class_init = ivshmem_class_init,
 };
 
 static void ivshmem_register_devices(void)
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 3a87171..3571588 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2120,18 +2120,25 @@  static int lsi_scsi_init(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo lsi_info = {
-    .qdev.name  = "lsi53c895a",
-    .qdev.alias = "lsi",
-    .qdev.size  = sizeof(LSIState),
-    .qdev.reset = lsi_scsi_reset,
-    .qdev.vmsd  = &vmstate_lsi_scsi,
-    .init       = lsi_scsi_init,
-    .exit       = lsi_scsi_uninit,
-    .vendor_id  = PCI_VENDOR_ID_LSI_LOGIC,
-    .device_id  = PCI_DEVICE_ID_LSI_53C895A,
-    .class_id   = PCI_CLASS_STORAGE_SCSI,
-    .subsystem_id = 0x1000,
+static void lsi_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = lsi_scsi_init;
+    k->exit = lsi_scsi_uninit;
+    k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
+    k->device_id = PCI_DEVICE_ID_LSI_53C895A;
+    k->class_id = PCI_CLASS_STORAGE_SCSI;
+    k->subsystem_id = 0x1000;
+}
+
+static DeviceInfo lsi_info = {
+    .name = "lsi53c895a",
+    .alias = "lsi",
+    .size = sizeof(LSIState),
+    .reset = lsi_scsi_reset,
+    .vmsd = &vmstate_lsi_scsi,
+    .class_init = lsi_class_init,
 };
 
 static void lsi53c895a_register_devices(void)
diff --git a/hw/macio.c b/hw/macio.c
index 357e0ea..ae9db08 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -81,12 +81,19 @@  static int macio_initfn(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo macio_info = {
-    .qdev.name = "macio",
-    .qdev.size = sizeof(MacIOState),
-    .init = macio_initfn,
-    .vendor_id = PCI_VENDOR_ID_APPLE,
-    .class_id = PCI_CLASS_OTHERS << 8,
+static void macio_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = macio_initfn;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->class_id = PCI_CLASS_OTHERS << 8;
+}
+
+static DeviceInfo macio_info = {
+    .name = "macio",
+    .size = sizeof(MacIOState),
+    .class_init = macio_class_init,
 };
 
 static void macio_register(void)
diff --git a/hw/ne2000.c b/hw/ne2000.c
index b44eab1..138479a 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -786,19 +786,28 @@  static int pci_ne2000_exit(PCIDevice *pci_dev)
     return 0;
 }
 
-static PCIDeviceInfo ne2000_info = {
-    .qdev.name  = "ne2k_pci",
-    .qdev.size  = sizeof(PCINE2000State),
-    .qdev.vmsd  = &vmstate_pci_ne2000,
-    .init       = pci_ne2000_init,
-    .exit       = pci_ne2000_exit,
-    .vendor_id  = PCI_VENDOR_ID_REALTEK,
-    .device_id  = PCI_DEVICE_ID_REALTEK_8029,
-    .class_id   = PCI_CLASS_NETWORK_ETHERNET,
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property ne2000_properties[] = {
+    DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ne2000_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ne2000_init;
+    k->exit = pci_ne2000_exit;
+    k->vendor_id = PCI_VENDOR_ID_REALTEK;
+    k->device_id = PCI_DEVICE_ID_REALTEK_8029;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+}
+
+static DeviceInfo ne2000_info = {
+    .name = "ne2k_pci",
+    .size = sizeof(PCINE2000State),
+    .vmsd = &vmstate_pci_ne2000,
+    .props = ne2000_properties,
+    .class_init = ne2000_class_init,
 };
 
 static void ne2000_register_devices(void)
diff --git a/hw/pci.c b/hw/pci.c
index 516da08..6a0b1f5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -89,7 +89,6 @@  static const VMStateDescription vmstate_pcibus = {
         VMSTATE_END_OF_LIST()
     }
 };
-
 static int pci_bar(PCIDevice *d, int reg)
 {
     uint8_t type;
@@ -730,11 +729,11 @@  static void pci_config_free(PCIDevice *pci_dev)
 
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
-                                         const char *name, int devfn,
-                                         const PCIDeviceInfo *info)
+                                         const char *name, int devfn)
 {
-    PCIConfigReadFunc *config_read = info->config_read;
-    PCIConfigWriteFunc *config_write = info->config_write;
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+    PCIConfigReadFunc *config_read = pc->config_read;
+    PCIConfigWriteFunc *config_write = pc->config_write;
 
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
@@ -756,29 +755,29 @@  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->irq_state = 0;
     pci_config_alloc(pci_dev);
 
-    pci_config_set_vendor_id(pci_dev->config, info->vendor_id);
-    pci_config_set_device_id(pci_dev->config, info->device_id);
-    pci_config_set_revision(pci_dev->config, info->revision);
-    pci_config_set_class(pci_dev->config, info->class_id);
+    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);
+    pci_config_set_device_id(pci_dev->config, pc->device_id);
+    pci_config_set_revision(pci_dev->config, pc->revision);
+    pci_config_set_class(pci_dev->config, pc->class_id);
 
-    if (!info->is_bridge) {
-        if (info->subsystem_vendor_id || info->subsystem_id) {
+    if (!pc->is_bridge) {
+        if (pc->subsystem_vendor_id || pc->subsystem_id) {
             pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
-                         info->subsystem_vendor_id);
+                         pc->subsystem_vendor_id);
             pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
-                         info->subsystem_id);
+                         pc->subsystem_id);
         } else {
             pci_set_default_subsystem_id(pci_dev);
         }
     } else {
         /* subsystem_vendor_id/subsystem_id are only for header type 0 */
-        assert(!info->subsystem_vendor_id);
-        assert(!info->subsystem_id);
+        assert(!pc->subsystem_vendor_id);
+        assert(!pc->subsystem_id);
     }
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
     pci_init_w1cmask(pci_dev);
-    if (info->is_bridge) {
+    if (pc->is_bridge) {
         pci_init_wmask_bridge(pci_dev);
     }
     if (pci_init_multifunction(bus, pci_dev)) {
@@ -805,26 +804,6 @@  static void do_pci_unregister_device(PCIDevice *pci_dev)
     pci_config_free(pci_dev);
 }
 
-/* TODO: obsolete. eliminate this once all pci devices are qdevifed. */
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
-                               int instance_size, int devfn,
-                               PCIConfigReadFunc *config_read,
-                               PCIConfigWriteFunc *config_write)
-{
-    PCIDevice *pci_dev;
-    PCIDeviceInfo info = {
-        .config_read = config_read,
-        .config_write = config_write,
-    };
-
-    pci_dev = g_malloc0(instance_size);
-    pci_dev = do_pci_register_device(pci_dev, bus, name, devfn, &info);
-    if (pci_dev == NULL) {
-        hw_error("PCI: can't register device\n");
-    }
-    return pci_dev;
-}
-
 static void pci_unregister_io_regions(PCIDevice *pci_dev)
 {
     PCIIORegion *r;
@@ -840,12 +819,12 @@  static void pci_unregister_io_regions(PCIDevice *pci_dev)
 
 static int pci_unregister_device(DeviceState *dev)
 {
-    PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
-    PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, qdev_get_info(dev));
+    PCIDevice *pci_dev = PCI_DEVICE(dev);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
     int ret = 0;
 
-    if (info->exit)
-        ret = info->exit(pci_dev);
+    if (pc->exit)
+        ret = pc->exit(pci_dev);
     if (ret)
         return ret;
 
@@ -1477,28 +1456,27 @@  PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     PCIDevice *pci_dev = (PCIDevice *)qdev;
-    PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
     PCIBus *bus;
     int rc;
     bool is_default_rom;
 
     /* initialize cap_present for pci_is_express() and pci_config_size() */
-    if (info->is_express) {
+    if (pc->is_express) {
         pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
     }
 
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
-    pci_dev = do_pci_register_device(pci_dev, bus, base->name,
-                                     pci_dev->devfn, info);
+    pci_dev = do_pci_register_device(pci_dev, bus, base->name, pci_dev->devfn);
     if (pci_dev == NULL)
         return -1;
-    if (qdev->hotplugged && info->no_hotplug) {
+    if (qdev->hotplugged && pc->no_hotplug) {
         qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev)));
         do_pci_unregister_device(pci_dev);
         return -1;
     }
-    if (info->init) {
-        rc = info->init(pci_dev);
+    if (pc->init) {
+        rc = pc->init(pci_dev);
         if (rc != 0) {
             do_pci_unregister_device(pci_dev);
             return rc;
@@ -1507,8 +1485,8 @@  static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 
     /* rom loading */
     is_default_rom = false;
-    if (pci_dev->romfile == NULL && info->romfile != NULL) {
-        pci_dev->romfile = g_strdup(info->romfile);
+    if (pci_dev->romfile == NULL && pc->romfile != NULL) {
+        pci_dev->romfile = g_strdup(pc->romfile);
         is_default_rom = true;
     }
     pci_add_option_rom(pci_dev, is_default_rom);
@@ -1530,10 +1508,10 @@  static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 
 static int pci_unplug_device(DeviceState *qdev)
 {
-    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
-    PCIDeviceInfo *info = container_of(qdev_get_info(qdev), PCIDeviceInfo, qdev);
+    PCIDevice *dev = PCI_DEVICE(qdev);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
 
-    if (info->no_hotplug) {
+    if (pc->no_hotplug) {
         qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
         return -1;
     }
@@ -1541,23 +1519,15 @@  static int pci_unplug_device(DeviceState *qdev)
                              PCI_HOTPLUG_DISABLED);
 }
 
-void pci_qdev_register(PCIDeviceInfo *info)
-{
-    info->qdev.init = pci_qdev_init;
-    if (!info->qdev.unplug) {
-        info->qdev.unplug = pci_unplug_device;
-    }
-    info->qdev.exit = pci_unregister_device;
-    info->qdev.bus_info = &pci_bus_info;
-    qdev_register(&info->qdev);
-}
-
-void pci_qdev_register_many(PCIDeviceInfo *info)
+void pci_qdev_register(DeviceInfo *info)
 {
-    while (info->qdev.name) {
-        pci_qdev_register(info);
-        info++;
+    info->init = pci_qdev_init;
+    if (!info->unplug) {
+        info->unplug = pci_unplug_device;
     }
+    info->exit = pci_unregister_device;
+    info->bus_info = &pci_bus_info;
+    qdev_register_subclass(info, TYPE_PCI_DEVICE);
 }
 
 PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
@@ -1568,7 +1538,7 @@  PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
     dev = qdev_create(&bus->qbus, name);
     qdev_prop_set_uint32(dev, "addr", devfn);
     qdev_prop_set_bit(dev, "multifunction", multifunction);
-    return DO_UPCAST(PCIDevice, qdev, dev);
+    return PCI_DEVICE(dev);
 }
 
 PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
@@ -1985,7 +1955,7 @@  static int pci_qdev_find_recursive(PCIBus *bus,
     /* roughly check if given qdev is pci device */
     if (qdev_get_info(qdev)->init == &pci_qdev_init &&
         qdev->parent_bus->info == &pci_bus_info) {
-        *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+        *pdev = PCI_DEVICE(qdev);
         return 0;
     }
     return -EINVAL;
@@ -2019,3 +1989,18 @@  MemoryRegion *pci_address_space_io(PCIDevice *dev)
 {
     return dev->bus->address_space_io;
 }
+
+static TypeInfo pci_device_type_info = {
+    .name = TYPE_PCI_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .abstract = true,
+    .class_size = sizeof(PCIDeviceClass),
+};
+
+static void pci_register_devices(void)
+{
+    type_register_static(&pci_device_type_info);
+}
+
+device_init(pci_register_devices);
diff --git a/hw/pci.h b/hw/pci.h
index 5501d95..09b2324 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -127,6 +127,46 @@  enum {
     QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
 };
 
+#define TYPE_PCI_DEVICE "pci-device"
+#define PCI_DEVICE(obj) \
+     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
+
+typedef struct PCIDeviceClass {
+    DeviceClass parent_class;
+
+    int (*init)(PCIDevice *dev);
+    PCIUnregisterFunc *exit;
+    PCIConfigReadFunc *config_read;
+    PCIConfigWriteFunc *config_write;
+
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint8_t revision;
+    uint16_t class_id;
+    uint16_t subsystem_vendor_id;       /* only for header type = 0 */
+    uint16_t subsystem_id;              /* only for header type = 0 */
+
+    /*
+     * pci-to-pci bridge or normal device.
+     * This doesn't mean pci host switch.
+     * When card bus bridge is supported, this would be enhanced.
+     */
+    int is_bridge;
+
+    /* pcie stuff */
+    int is_express;   /* is this device pci express? */
+
+    /* device isn't hot-pluggable */
+    int no_hotplug;
+
+    /* rom bar */
+    const char *romfile;
+} PCIDeviceClass;
+
 struct PCIDevice {
     DeviceState qdev;
     /* PCI config space */
@@ -196,11 +236,6 @@  struct PCIDevice {
     uint32_t rom_bar;
 };
 
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
-                               int instance_size, int devfn,
-                               PCIConfigReadFunc *config_read,
-                               PCIConfigWriteFunc *config_write);
-
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                       uint8_t attr, MemoryRegion *memory);
 pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
@@ -429,40 +464,7 @@  pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
     return val & mask;
 }
 
-typedef int (*pci_qdev_initfn)(PCIDevice *dev);
-typedef struct {
-    DeviceInfo qdev;
-    pci_qdev_initfn init;
-    PCIUnregisterFunc *exit;
-    PCIConfigReadFunc *config_read;
-    PCIConfigWriteFunc *config_write;
-
-    uint16_t vendor_id;
-    uint16_t device_id;
-    uint8_t revision;
-    uint16_t class_id;
-    uint16_t subsystem_vendor_id;       /* only for header type = 0 */
-    uint16_t subsystem_id;              /* only for header type = 0 */
-
-    /*
-     * pci-to-pci bridge or normal device.
-     * This doesn't mean pci host switch.
-     * When card bus bridge is supported, this would be enhanced.
-     */
-    int is_bridge;
-
-    /* pcie stuff */
-    int is_express;   /* is this device pci express? */
-
-    /* device isn't hot-pluggable */
-    int no_hotplug;
-
-    /* rom bar */
-    const char *romfile;
-} PCIDeviceInfo;
-
-void pci_qdev_register(PCIDeviceInfo *info);
-void pci_qdev_register_many(PCIDeviceInfo *info);
+void pci_qdev_register(DeviceInfo *info);
 
 PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
                                     const char *name);
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index 650d165..1ed4339 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -294,7 +294,7 @@  void pci_bridge_reset_reg(PCIDevice *dev)
 /* default reset function for PCI-to-PCI bridge */
 void pci_bridge_reset(DeviceState *qdev)
 {
-    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+    PCIDevice *dev = PCI_DEVICE(qdev);
     pci_bridge_reset_reg(dev);
 }
 
diff --git a/hw/pcie.c b/hw/pcie.c
index 5c9eb2f..7c92f19 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -203,7 +203,7 @@  static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
 static int pcie_cap_slot_hotplug(DeviceState *qdev,
                                  PCIDevice *pci_dev, PCIHotplugState state)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    PCIDevice *d = PCI_DEVICE(qdev);
     uint8_t *exp_cap = d->config + d->exp.exp_cap;
     uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
 
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 4e164da..be3bd79 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -348,21 +348,30 @@  static void pci_reset(DeviceState *dev)
     pcnet_h_reset(&d->state);
 }
 
-static PCIDeviceInfo pcnet_info = {
-    .qdev.name  = "pcnet",
-    .qdev.size  = sizeof(PCIPCNetState),
-    .qdev.reset = pci_reset,
-    .qdev.vmsd  = &vmstate_pci_pcnet,
-    .init       = pci_pcnet_init,
-    .exit       = pci_pcnet_uninit,
-    .vendor_id  = PCI_VENDOR_ID_AMD,
-    .device_id  = PCI_DEVICE_ID_AMD_LANCE,
-    .revision   = 0x10,
-    .class_id   = PCI_CLASS_NETWORK_ETHERNET,
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property pcnet_properties[] = {
+    DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pcnet_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_pcnet_init;
+    k->exit = pci_pcnet_uninit;
+    k->vendor_id = PCI_VENDOR_ID_AMD;
+    k->device_id = PCI_DEVICE_ID_AMD_LANCE;
+    k->revision = 0x10;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+}
+
+static DeviceInfo pcnet_info = {
+    .name = "pcnet",
+    .size = sizeof(PCIPCNetState),
+    .reset = pci_reset,
+    .vmsd = &vmstate_pci_pcnet,
+    .props = pcnet_properties,
+    .class_init = pcnet_class_init,
 };
 
 static void pci_pcnet_register_devices(void)
diff --git a/hw/piix4.c b/hw/piix4.c
index 130dfd1..88be535 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -102,18 +102,24 @@  int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
     return d->devfn;
 }
 
-static PCIDeviceInfo piix4_info = {
-    .qdev.name    = "PIIX4",
-    .qdev.desc    = "ISA bridge",
-    .qdev.size    = sizeof(PIIX4State),
-    .qdev.vmsd    = &vmstate_piix4,
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = piix4_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    /* 82371AB/EB/MB PIIX4 PCI-to-ISA bridge */
-    .device_id    = PCI_DEVICE_ID_INTEL_82371AB_0,
-    .class_id     = PCI_CLASS_BRIDGE_ISA,
+static void piix4_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = piix4_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
+    k->class_id = PCI_CLASS_BRIDGE_ISA;
+}
+
+static DeviceInfo piix4_info = {
+    .name = "PIIX4",
+    .desc = "ISA bridge",
+    .size = sizeof(PIIX4State),
+    .vmsd = &vmstate_piix4,
+    .no_user = 1,
+    .class_init = piix4_class_init,
 };
 
 static void piix4_register(void)
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 5cbeed5..787db4e 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -502,47 +502,68 @@  static int piix3_initfn(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo i440fx_info = {
-    .qdev.name    = "i440FX",
-    .qdev.desc    = "Host bridge",
-    .qdev.size    = sizeof(PCII440FXState),
-    .qdev.vmsd    = &vmstate_i440fx,
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = i440fx_initfn,
-    .config_write = i440fx_write_config,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82441,
-    .revision     = 0x02,
-    .class_id     = PCI_CLASS_BRIDGE_HOST,
+static void piix3_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug   = 1;
+    k->init         = piix3_initfn;
+    k->config_write = piix3_write_config;
+    k->vendor_id    = PCI_VENDOR_ID_INTEL;
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    k->class_id     = PCI_CLASS_BRIDGE_ISA;
+}
+
+static DeviceInfo piix3_info = {
+    .name    = "PIIX3",
+    .desc    = "ISA bridge",
+    .size    = sizeof(PIIX3State),
+    .vmsd    = &vmstate_piix3,
+    .no_user = 1,
+    .class_init = piix3_class_init,
 };
 
-static PCIDeviceInfo piix3_info = {
-    .qdev.name    = "PIIX3",
-    .qdev.desc    = "ISA bridge",
-    .qdev.size    = sizeof(PIIX3State),
-    .qdev.vmsd    = &vmstate_piix3,
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = piix3_initfn,
-    .config_write = piix3_write_config,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
-    .class_id     = PCI_CLASS_BRIDGE_ISA,
+static void piix3_xen_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug   = 1;
+    k->init         = piix3_initfn;
+    k->config_write = piix3_write_config_xen;
+    k->vendor_id    = PCI_VENDOR_ID_INTEL;
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    k->class_id     = PCI_CLASS_BRIDGE_ISA;
 };
 
-static PCIDeviceInfo piix3_xen_info = {
-    .qdev.name    = "PIIX3-xen",
-    .qdev.desc    = "ISA bridge",
-    .qdev.size    = sizeof(PIIX3State),
-    .qdev.vmsd    = &vmstate_piix3,
-    .qdev.no_user = 1,
-    .no_hotplug   = 1,
-    .init         = piix3_initfn,
-    .config_write = piix3_write_config_xen,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
-    .class_id     = PCI_CLASS_BRIDGE_ISA,
+static DeviceInfo piix3_xen_info = {
+    .name    = "PIIX3-xen",
+    .desc    = "ISA bridge",
+    .size    = sizeof(PIIX3State),
+    .vmsd    = &vmstate_piix3,
+    .no_user = 1,
+    .class_init = piix3_xen_class_init,
+};
+
+static void i440fx_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = i440fx_initfn;
+    k->config_write = i440fx_write_config;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82441;
+    k->revision = 0x02;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo i440fx_info = {
+    .name = "i440FX",
+    .desc = "Host bridge",
+    .size = sizeof(PCII440FXState),
+    .vmsd = &vmstate_i440fx,
+    .no_user = 1,
+    .class_init = i440fx_class_init,
 };
 
 static SysBusDeviceInfo i440fx_pcihost_info = {
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 26de007..b38840e 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -366,13 +366,20 @@  static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo ppc4xx_host_bridge_info = {
-    .qdev.name    = "ppc4xx-host-bridge",
-    .qdev.desc    = "Host bridge",
-    .qdev.size    = sizeof(PCIDevice),
-    .vendor_id    = PCI_VENDOR_ID_IBM,
-    .device_id    = PCI_DEVICE_ID_IBM_440GX,
-    .class_id     = PCI_CLASS_BRIDGE_OTHER,
+static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->vendor_id    = PCI_VENDOR_ID_IBM;
+    k->device_id    = PCI_DEVICE_ID_IBM_440GX;
+    k->class_id     = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static DeviceInfo ppc4xx_host_bridge_info = {
+    .name    = "ppc4xx-host-bridge",
+    .desc    = "Host bridge",
+    .size    = sizeof(PCIDevice),
+    .class_init = ppc4xx_host_bridge_class_init,
 };
 
 static SysBusDeviceInfo ppc4xx_pcihost_info = {
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index b606206..bc783bf 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -339,13 +339,20 @@  static int e500_pcihost_initfn(SysBusDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo e500_host_bridge_info = {
-    .qdev.name    = "e500-host-bridge",
-    .qdev.desc    = "Host bridge",
-    .qdev.size    = sizeof(PCIDevice),
-    .vendor_id    = PCI_VENDOR_ID_FREESCALE,
-    .device_id    = PCI_DEVICE_ID_MPC8533E,
-    .class_id     = PCI_CLASS_PROCESSOR_POWERPC,
+static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->vendor_id = PCI_VENDOR_ID_FREESCALE;
+    k->device_id = PCI_DEVICE_ID_MPC8533E;
+    k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
+}
+
+static DeviceInfo e500_host_bridge_info = {
+    .name = "e500-host-bridge",
+    .desc = "Host bridge",
+    .size = sizeof(PCIDevice),
+    .class_init = e500_host_bridge_class_init,
 };
 
 static SysBusDeviceInfo e500_pcihost_info = {
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 4961eed..4ff1049 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -134,21 +134,24 @@  static const VMStateDescription vmstate_raven = {
     },
 };
 
-static PCIDeviceInfo raven_info = {
-    .qdev.name = "raven",
-    .qdev.desc = "PReP Host Bridge - Motorola Raven",
-    .qdev.size = sizeof(RavenPCIState),
-    .qdev.vmsd = &vmstate_raven,
-    .qdev.no_user = 1,
-    .no_hotplug = 1,
-    .init = raven_init,
-    .vendor_id = PCI_VENDOR_ID_MOTOROLA,
-    .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
-    .revision = 0x00,
-    .class_id = PCI_CLASS_BRIDGE_HOST,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_END_OF_LIST()
-    },
+static void raven_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = raven_init;
+    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+    k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
+    k->revision = 0x00;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo raven_info = {
+    .name = "raven",
+    .desc = "PReP Host Bridge - Motorola Raven",
+    .size = sizeof(RavenPCIState),
+    .vmsd = &vmstate_raven,
+    .no_user = 1,
+    .class_init = raven_class_init,
 };
 
 static SysBusDeviceInfo raven_pcihost_info = {
diff --git a/hw/qdev.c b/hw/qdev.c
index 81996bb..a8c24de 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -119,6 +119,7 @@  bool qdev_exists(const char *name)
 {
     return !!qdev_find_info(NULL, name);
 }
+
 static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                      Error **errp);
 
diff --git a/hw/qxl.c b/hw/qxl.c
index 2a716bf..7aa7d19 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1827,32 +1827,46 @@  static Property qxl_properties[] = {
         DEFINE_PROP_END_OF_LIST(),
 };
 
-static PCIDeviceInfo qxl_primary_info = {
-    .qdev.name    = "qxl-vga",
-    .qdev.desc    = "Spice QXL GPU (primary, vga compatible)",
-    .qdev.size    = sizeof(PCIQXLDevice),
-    .qdev.reset   = qxl_reset_handler,
-    .qdev.vmsd    = &qxl_vmstate,
-    .no_hotplug   = 1,
-    .init         = qxl_init_primary,
-    .romfile      = "vgabios-qxl.bin",
-    .vendor_id    = REDHAT_PCI_VENDOR_ID,
-    .device_id    = QXL_DEVICE_ID_STABLE,
-    .class_id     = PCI_CLASS_DISPLAY_VGA,
-    .qdev.props   = qxl_properties,
+static void qxl_primary_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = qxl_init_primary;
+    k->romfile = "vgabios-qxl.bin";
+    k->vendor_id = REDHAT_PCI_VENDOR_ID;
+    k->device_id = QXL_DEVICE_ID_STABLE;
+    k->class_id = PCI_CLASS_DISPLAY_VGA;
+}
+
+static DeviceInfo qxl_primary_info = {
+    .name = "qxl-vga",
+    .desc = "Spice QXL GPU (primary, vga compatible)",
+    .size = sizeof(PCIQXLDevice),
+    .reset = qxl_reset_handler,
+    .vmsd = &qxl_vmstate,
+    .props = qxl_properties,
+    .class_init = qxl_primary_class_init,
 };
 
-static PCIDeviceInfo qxl_secondary_info = {
-    .qdev.name    = "qxl",
-    .qdev.desc    = "Spice QXL GPU (secondary)",
-    .qdev.size    = sizeof(PCIQXLDevice),
-    .qdev.reset   = qxl_reset_handler,
-    .qdev.vmsd    = &qxl_vmstate,
-    .init         = qxl_init_secondary,
-    .vendor_id    = REDHAT_PCI_VENDOR_ID,
-    .device_id    = QXL_DEVICE_ID_STABLE,
-    .class_id     = PCI_CLASS_DISPLAY_OTHER,
-    .qdev.props   = qxl_properties,
+static void qxl_secondary_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = qxl_init_secondary;
+    k->vendor_id = REDHAT_PCI_VENDOR_ID;
+    k->device_id = QXL_DEVICE_ID_STABLE;
+    k->class_id = PCI_CLASS_DISPLAY_OTHER;
+}
+
+static DeviceInfo qxl_secondary_info = {
+    .name = "qxl",
+    .desc = "Spice QXL GPU (secondary)",
+    .size = sizeof(PCIQXLDevice),
+    .reset = qxl_reset_handler,
+    .vmsd = &qxl_vmstate,
+    .props = qxl_properties,
+    .class_init = qxl_secondary_class_init,
 };
 
 static void qxl_register(void)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 2b55c7f..15dec9b 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3494,22 +3494,31 @@  static int pci_rtl8139_init(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo rtl8139_info = {
-    .qdev.name  = "rtl8139",
-    .qdev.size  = sizeof(RTL8139State),
-    .qdev.reset = rtl8139_reset,
-    .qdev.vmsd  = &vmstate_rtl8139,
-    .init       = pci_rtl8139_init,
-    .exit       = pci_rtl8139_uninit,
-    .romfile    = "pxe-rtl8139.rom",
-    .vendor_id  = PCI_VENDOR_ID_REALTEK,
-    .device_id  = PCI_DEVICE_ID_REALTEK_8139,
-    .revision   = RTL8139_PCI_REVID, /* >=0x20 is for 8139C+ */
-    .class_id   = PCI_CLASS_NETWORK_ETHERNET,
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(RTL8139State, conf),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property rtl8139_properties[] = {
+    DEFINE_NIC_PROPERTIES(RTL8139State, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rtl8139_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_rtl8139_init;
+    k->exit = pci_rtl8139_uninit;
+    k->romfile = "pxe-rtl8139.rom";
+    k->vendor_id = PCI_VENDOR_ID_REALTEK;
+    k->device_id = PCI_DEVICE_ID_REALTEK_8139;
+    k->revision = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+}
+
+static DeviceInfo rtl8139_info = {
+    .name = "rtl8139",
+    .size = sizeof(RTL8139State),
+    .reset = rtl8139_reset,
+    .vmsd = &vmstate_rtl8139,
+    .props = rtl8139_properties,
+    .class_init = rtl8139_class_init,
 };
 
 static void rtl8139_register_devices(void)
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index d4d028d..baeab9e 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -147,12 +147,19 @@  static int sh_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo sh_pci_host_info = {
-    .qdev.name = "sh_pci_host",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = sh_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_HITACHI,
-    .device_id = PCI_DEVICE_ID_HITACHI_SH7751R,
+static void sh_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = sh_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_HITACHI;
+    k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
+}
+
+static DeviceInfo sh_pci_host_info = {
+    .name = "sh_pci_host",
+    .size = sizeof(PCIDevice),
+    .class_init = sh_pci_host_class_init,
 };
 
 static void sh_pci_register_devices(void)
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 2c95faa..8a39f8f 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -214,10 +214,17 @@  static int spapr_main_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo spapr_main_pci_host_info = {
-    .qdev.name = "spapr-pci-host-bridge",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = spapr_main_pci_host_init,
+static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = spapr_main_pci_host_init;
+}
+
+static DeviceInfo spapr_main_pci_host_info = {
+    .name = "spapr-pci-host-bridge",
+    .size = sizeof(PCIDevice),
+    .class_init = spapr_main_pci_host_class_init,
 };
 
 static void spapr_register_devices(void)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 2dc3d04..6d9fdf6 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -562,14 +562,21 @@  pci_ebus_init1(PCIDevice *pci_dev)
     return 0;
 }
 
-static PCIDeviceInfo ebus_info = {
-    .qdev.name = "ebus",
-    .qdev.size = sizeof(EbusState),
-    .init = pci_ebus_init1,
-    .vendor_id = PCI_VENDOR_ID_SUN,
-    .device_id = PCI_DEVICE_ID_SUN_EBUS,
-    .revision = 0x01,
-    .class_id = PCI_CLASS_BRIDGE_OTHER,
+static void ebus_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ebus_init1;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_EBUS;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static DeviceInfo ebus_info = {
+    .name = "ebus",
+    .size = sizeof(EbusState),
+    .class_init = ebus_class_init,
 };
 
 static void pci_ebus_register(void)
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 6a10013..6a148e0 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -339,44 +339,72 @@  static int unin_internal_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo unin_main_pci_host_info = {
-    .qdev.name = "uni-north-pci",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = unin_main_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_APPLE,
-    .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
-    .revision  = 0x00,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_main_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo unin_main_pci_host_info = {
+    .name = "uni-north-pci",
+    .size = sizeof(PCIDevice),
+    .class_init = unin_main_pci_host_class_init,
 };
 
-static PCIDeviceInfo u3_agp_pci_host_info = {
-    .qdev.name = "u3-agp",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = u3_agp_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_APPLE,
-    .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
-    .revision  = 0x00,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = u3_agp_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo u3_agp_pci_host_info = {
+    .name = "u3-agp",
+    .size = sizeof(PCIDevice),
+    .class_init = u3_agp_pci_host_class_init,
 };
 
-static PCIDeviceInfo unin_agp_pci_host_info = {
-    .qdev.name = "uni-north-agp",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = unin_agp_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_APPLE,
-    .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
-    .revision  = 0x00,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_agp_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo unin_agp_pci_host_info = {
+    .name = "uni-north-agp",
+    .size = sizeof(PCIDevice),
+    .class_init = unin_agp_pci_host_class_init,
 };
 
-static PCIDeviceInfo unin_internal_pci_host_info = {
-    .qdev.name = "uni-north-internal-pci",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = unin_internal_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_APPLE,
-    .device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI,
-    .revision  = 0x00,
-    .class_id  = PCI_CLASS_BRIDGE_HOST,
+static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_internal_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static DeviceInfo unin_internal_pci_host_info = {
+    .name = "uni-north-internal-pci",
+    .size = sizeof(PCIDevice),
+    .class_init = unin_internal_pci_host_class_init,
 };
 
 static SysBusDeviceInfo sysbus_unin_pci_host_info = {
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 63fc3c7..8baff1d 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2263,28 +2263,42 @@  static Property ehci_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static PCIDeviceInfo ehci_info = {
-    .qdev.name    = "usb-ehci",
-    .qdev.size    = sizeof(EHCIState),
-    .qdev.vmsd    = &vmstate_ehci,
-    .init         = usb_ehci_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
-    .revision     = 0x10,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = ehci_properties,
+static void ehci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ehci_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */
+    k->revision = 0x10;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ehci_info = {
+    .name = "usb-ehci",
+    .size = sizeof(EHCIState),
+    .vmsd = &vmstate_ehci,
+    .props = ehci_properties,
+    .class_init = ehci_class_init,
 };
 
-static PCIDeviceInfo ich9_ehci_info = {
-    .qdev.name    = "ich9-usb-ehci1",
-    .qdev.size    = sizeof(EHCIState),
-    .qdev.vmsd    = &vmstate_ehci,
-    .init         = usb_ehci_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
-    .revision     = 0x03,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = ehci_properties,
+static void ich9_ehci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ehci_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ich9_ehci_info = {
+    .name = "ich9-usb-ehci1",
+    .size = sizeof(EHCIState),
+    .vmsd = &vmstate_ehci,
+    .props = ehci_properties,
+    .class_init = ich9_ehci_class_init,
 };
 
 static int usb_ehci_initfn(PCIDevice *dev)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 2df6a6e..b9b37d5 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1836,20 +1836,29 @@  static int ohci_init_pxa(SysBusDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo ohci_pci_info = {
-    .qdev.name    = "pci-ohci",
-    .qdev.desc    = "Apple USB Controller",
-    .qdev.size    = sizeof(OHCIPCIState),
-    .init         = usb_ohci_initfn_pci,
-    .vendor_id    = PCI_VENDOR_ID_APPLE,
-    .device_id    = PCI_DEVICE_ID_APPLE_IPID_USB,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = (Property[]) {
-        DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
-        DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
-        DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property ohci_pci_properties[] = {
+    DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
+    DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
+    DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ohci_pci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ohci_initfn_pci;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ohci_pci_info = {
+    .name = "pci-ohci",
+    .desc = "Apple USB Controller",
+    .size = sizeof(OHCIPCIState),
+    .props = ohci_pci_properties,
+    .class_init = ohci_pci_class_init,
 };
 
 static SysBusDeviceInfo ohci_sysbus_info = {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 1821063..e20d7c4 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1192,79 +1192,121 @@  static Property uhci_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static PCIDeviceInfo piix3_uhci_info = {
-        .qdev.name    = "piix3-usb-uhci",
-        .qdev.size    = sizeof(UHCIState),
-        .qdev.vmsd    = &vmstate_uhci,
-        .init         = usb_uhci_common_initfn,
-        .exit         = usb_uhci_exit,
-        .vendor_id    = PCI_VENDOR_ID_INTEL,
-        .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
-        .revision     = 0x01,
-        .class_id     = PCI_CLASS_SERIAL_USB,
-        .qdev.props   = uhci_properties,
+static void piix3_uhci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo piix3_uhci_info = {
+    .name = "piix3-usb-uhci",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = piix3_uhci_class_init,
 };
 
-static PCIDeviceInfo piix4_uhci_info = {
-        .qdev.name    = "piix4-usb-uhci",
-        .qdev.size    = sizeof(UHCIState),
-        .qdev.vmsd    = &vmstate_uhci,
-        .init         = usb_uhci_common_initfn,
-        .exit         = usb_uhci_exit,
-        .vendor_id    = PCI_VENDOR_ID_INTEL,
-        .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
-        .revision     = 0x01,
-        .class_id     = PCI_CLASS_SERIAL_USB,
-        .qdev.props   = uhci_properties,
+static void piix4_uhci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo piix4_uhci_info = {
+    .name = "piix4-usb-uhci",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = piix4_uhci_class_init,
 };
 
-static PCIDeviceInfo vt82c686b_uhci_info = {
-    .qdev.name    = "vt82c686b-usb-uhci",
-    .qdev.size    = sizeof(UHCIState),
-    .qdev.vmsd    = &vmstate_uhci,
-    .init         = usb_uhci_vt82c686b_initfn,
-    .exit         = usb_uhci_exit,
-    .vendor_id    = PCI_VENDOR_ID_VIA,
-    .device_id    = PCI_DEVICE_ID_VIA_UHCI,
-    .revision     = 0x01,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = uhci_properties,
+static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_vt82c686b_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_UHCI;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo vt82c686b_uhci_info = {
+    .name = "vt82c686b-usb-uhci",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = vt82c686b_uhci_class_init,
 };
 
-static PCIDeviceInfo ich9_uhci1_info = {
-    .qdev.name    = "ich9-usb-uhci1",
-    .qdev.size    = sizeof(UHCIState),
-    .qdev.vmsd    = &vmstate_uhci,
-    .init         = usb_uhci_common_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI1,
-    .revision     = 0x03,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = uhci_properties,
+static void ich9_uhci1_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ich9_uhci1_info = {
+    .name = "ich9-usb-uhci1",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = ich9_uhci1_class_init,
 };
 
-static PCIDeviceInfo ich9_uhci2_info = {
-    .qdev.name    = "ich9-usb-uhci2",
-    .qdev.size    = sizeof(UHCIState),
-    .qdev.vmsd    = &vmstate_uhci,
-    .init         = usb_uhci_common_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI2,
-    .revision     = 0x03,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = uhci_properties,
+static void ich9_uhci2_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ich9_uhci2_info = {
+    .name = "ich9-usb-uhci2",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = ich9_uhci2_class_init,
 };
 
-static PCIDeviceInfo ich9_uhci3_info = {
-    .qdev.name    = "ich9-usb-uhci3",
-    .qdev.size    = sizeof(UHCIState),
-    .qdev.vmsd    = &vmstate_uhci,
-    .init         = usb_uhci_common_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI3,
-    .revision     = 0x03,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = uhci_properties,
+static void ich9_uhci3_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static DeviceInfo ich9_uhci3_info = {
+    .name = "ich9-usb-uhci3",
+    .size = sizeof(UHCIState),
+    .vmsd = &vmstate_uhci,
+    .props = uhci_properties,
+    .class_init = ich9_uhci3_class_init,
 };
 
 static void uhci_register(void)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 95bf010..fba2de3 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2724,19 +2724,26 @@  static const VMStateDescription vmstate_xhci = {
     .unmigratable = 1,
 };
 
-static PCIDeviceInfo xhci_info = {
-    .qdev.name    = "nec-usb-xhci",
-    .qdev.alias   = "xhci",
-    .qdev.size    = sizeof(XHCIState),
-    .qdev.vmsd    = &vmstate_xhci,
-    .init         = usb_xhci_initfn,
-    .vendor_id    = PCI_VENDOR_ID_NEC,
-    .device_id    = PCI_DEVICE_ID_NEC_UPD720200,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .revision     = 0x03,
-    .is_express   = 1,
-    .config_write = xhci_write_config,
-    .qdev.props   = (Property[]) {
+static void xhci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init         = usb_xhci_initfn;
+    k->vendor_id    = PCI_VENDOR_ID_NEC;
+    k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
+    k->class_id     = PCI_CLASS_SERIAL_USB;
+    k->revision     = 0x03;
+    k->is_express   = 1;
+    k->config_write = xhci_write_config;
+}
+
+static DeviceInfo xhci_info = {
+    .name    = "nec-usb-xhci",
+    .alias   = "xhci",
+    .size    = sizeof(XHCIState),
+    .vmsd    = &vmstate_xhci,
+    .class_init   = xhci_class_init,
+    .props   = (Property[]) {
         DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
         DEFINE_PROP_END_OF_LIST(),
     }
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index a285f7f..0eb7d32 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -109,14 +109,20 @@  static int versatile_pci_host_init(PCIDevice *d)
     return 0;
 }
 
-static PCIDeviceInfo versatile_pci_host_info = {
-    .qdev.name = "versatile_pci_host",
-    .qdev.size = sizeof(PCIDevice),
-    .init      = versatile_pci_host_init,
-    .vendor_id = PCI_VENDOR_ID_XILINX,
-    /* Both boards have the same device ID.  Oh well.  */
-    .device_id = PCI_DEVICE_ID_XILINX_XC2VP30,
-    .class_id  = PCI_CLASS_PROCESSOR_CO,
+static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = versatile_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_XILINX;
+    k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
+    k->class_id = PCI_CLASS_PROCESSOR_CO;
+}
+
+static DeviceInfo versatile_pci_host_info = {
+    .name = "versatile_pci_host",
+    .size = sizeof(PCIDevice),
+    .class_init = versatile_pci_host_class_init,
 };
 
 static void versatile_pci_register_devices(void)
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index a75dbf3..ef9f8a5 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -75,18 +75,23 @@  DeviceState *pci_vga_init(PCIBus *bus)
     return &pci_create_simple(bus, -1, "VGA")->qdev;
 }
 
-static PCIDeviceInfo vga_info = {
-    .qdev.name    = "VGA",
-    .qdev.size    = sizeof(PCIVGAState),
-    .qdev.vmsd    = &vmstate_vga_pci,
-    .no_hotplug   = 1,
-    .init         = pci_vga_initfn,
-    .romfile      = "vgabios-stdvga.bin",
+static void vga_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_vga_initfn;
+    k->romfile = "vgabios-stdvga.bin";
+    k->vendor_id = PCI_VENDOR_ID_QEMU;
+    k->device_id = PCI_DEVICE_ID_QEMU_VGA;
+    k->class_id = PCI_CLASS_DISPLAY_VGA;
+}
 
-    /* dummy VGA (same as Bochs ID) */
-    .vendor_id    = PCI_VENDOR_ID_QEMU,
-    .device_id    = PCI_DEVICE_ID_QEMU_VGA,
-    .class_id     = PCI_CLASS_DISPLAY_VGA,
+static DeviceInfo vga_info = {
+    .name = "VGA",
+    .size = sizeof(PCIVGAState),
+    .vmsd = &vmstate_vga_pci,
+    .class_init = vga_class_init,
 };
 
 static void vga_register(void)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 72b53af..126fb08 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -806,88 +806,124 @@  static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
     return virtio_exit_pci(pci_dev);
 }
 
-static PCIDeviceInfo virtio_blk_info = {
-    .qdev.name = "virtio-blk-pci",
-    .qdev.alias = "virtio-blk",
-    .qdev.size = sizeof(VirtIOPCIProxy),
-    .init      = virtio_blk_init_pci,
-    .exit      = virtio_blk_exit_pci,
-    .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
-    .revision  = VIRTIO_PCI_ABI_VERSION,
-    .class_id  = PCI_CLASS_STORAGE_SCSI,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-        DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
-        DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
-        DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-        DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
-        DEFINE_PROP_END_OF_LIST(),
-    },
-    .qdev.reset = virtio_pci_reset,
+static Property virtio_blk_properties[] = {
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
+    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static PCIDeviceInfo virtio_net_info = {
-    .qdev.name  = "virtio-net-pci",
-    .qdev.alias = "virtio-net",
-    .qdev.size  = sizeof(VirtIOPCIProxy),
-    .init       = virtio_net_init_pci,
-    .exit       = virtio_net_exit_pci,
-    .romfile    = "pxe-virtio.rom",
-    .vendor_id  = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id  = PCI_DEVICE_ID_VIRTIO_NET,
-    .revision   = VIRTIO_PCI_ABI_VERSION,
-    .class_id   = PCI_CLASS_NETWORK_ETHERNET,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
-        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
-        DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
-        DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
-        DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
-        DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
-        DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
-        DEFINE_PROP_END_OF_LIST(),
-    },
-    .qdev.reset = virtio_pci_reset,
+static void virtio_blk_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_blk_init_pci;
+    k->exit = virtio_blk_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_STORAGE_SCSI;
+}
+
+static DeviceInfo virtio_blk_info = {
+    .name = "virtio-blk-pci",
+    .alias = "virtio-blk",
+    .size = sizeof(VirtIOPCIProxy),
+    .props = virtio_blk_properties,
+    .reset = virtio_pci_reset,
+    .class_init = virtio_blk_class_init,
+};
+
+static Property virtio_net_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
+    DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
+    DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
+    DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_net_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_net_init_pci;
+    k->exit = virtio_net_exit_pci;
+    k->romfile = "pxe-virtio.rom";
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+}
+
+static DeviceInfo virtio_net_info = {
+    .name = "virtio-net-pci",
+    .alias = "virtio-net",
+    .size = sizeof(VirtIOPCIProxy),
+    .props = virtio_net_properties,
+    .reset = virtio_pci_reset,
+    .class_init = virtio_net_class_init,
 };
 
-static PCIDeviceInfo virtio_serial_info = {
-    .qdev.name = "virtio-serial-pci",
-    .qdev.alias = "virtio-serial",
-    .qdev.size = sizeof(VirtIOPCIProxy),
-    .init      = virtio_serial_init_pci,
-    .exit      = virtio_serial_exit_pci,
-    .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
-    .revision  = VIRTIO_PCI_ABI_VERSION,
-    .class_id  = PCI_CLASS_COMMUNICATION_OTHER,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
-        DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-        DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-        DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
-        DEFINE_PROP_END_OF_LIST(),
-    },
-    .qdev.reset = virtio_pci_reset,
+static Property virtio_serial_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static PCIDeviceInfo virtio_balloon_info = {
-    .qdev.name = "virtio-balloon-pci",
-    .qdev.alias = "virtio-balloon",
-    .qdev.size = sizeof(VirtIOPCIProxy),
-    .init      = virtio_balloon_init_pci,
-    .exit      = virtio_balloon_exit_pci,
-    .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
-    .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
-    .revision  = VIRTIO_PCI_ABI_VERSION,
-    .class_id  = PCI_CLASS_MEMORY_RAM,
-    .qdev.props = (Property[]) {
-        DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-        DEFINE_PROP_END_OF_LIST(),
-    },
-    .qdev.reset = virtio_pci_reset,
+static void virtio_serial_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_serial_init_pci;
+    k->exit = virtio_serial_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+}
+
+static DeviceInfo virtio_serial_info = {
+    .name = "virtio-serial-pci",
+    .alias = "virtio-serial",
+    .size = sizeof(VirtIOPCIProxy),
+    .props = virtio_serial_properties,
+    .reset = virtio_pci_reset,
+    .class_init = virtio_serial_class_init,
+};
+
+static Property virtio_balloon_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_balloon_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_balloon_init_pci;
+    k->exit = virtio_balloon_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_MEMORY_RAM;
+}
+
+static DeviceInfo virtio_balloon_info = {
+    .name = "virtio-balloon-pci",
+    .alias = "virtio-balloon",
+    .size = sizeof(VirtIOPCIProxy),
+    .props = virtio_balloon_properties,
+    .reset = virtio_pci_reset,
+    .class_init = virtio_balloon_class_init,
 };
 
 static void virtio_pci_register_devices(void)
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index b1885c3..e7bbf7c 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1199,20 +1199,26 @@  static int pci_vmsvga_initfn(PCIDevice *dev)
     return 0;
 }
 
-static PCIDeviceInfo vmsvga_info = {
-    .qdev.name    = "vmware-svga",
-    .qdev.size    = sizeof(struct pci_vmsvga_state_s),
-    .qdev.vmsd    = &vmstate_vmware_vga,
-    .qdev.reset   = vmsvga_reset,
-    .no_hotplug   = 1,
-    .init         = pci_vmsvga_initfn,
-    .romfile      = "vgabios-vmware.bin",
-
-    .vendor_id    =  PCI_VENDOR_ID_VMWARE,
-    .device_id    = SVGA_PCI_DEVICE_ID,
-    .class_id     = PCI_CLASS_DISPLAY_VGA,
-    .subsystem_vendor_id = PCI_VENDOR_ID_VMWARE,
-    .subsystem_id = SVGA_PCI_DEVICE_ID,
+static void vmsvga_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = pci_vmsvga_initfn;
+    k->romfile = "vgabios-vmware.bin";
+    k->vendor_id = PCI_VENDOR_ID_VMWARE;
+    k->device_id = SVGA_PCI_DEVICE_ID;
+    k->class_id = PCI_CLASS_DISPLAY_VGA;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
+    k->subsystem_id = SVGA_PCI_DEVICE_ID;
+}
+
+static DeviceInfo vmsvga_info = {
+    .name = "vmware-svga",
+    .size = sizeof(struct pci_vmsvga_state_s),
+    .vmsd = &vmstate_vmware_vga,
+    .reset = vmsvga_reset,
+    .class_init = vmsvga_class_init,
 };
 
 static void vmsvga_register(void)
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 7fb88a5..72be4fd 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -346,15 +346,22 @@  void vt82c686b_ac97_init(PCIBus *bus, int devfn)
     qdev_init_nofail(&dev->qdev);
 }
 
-static PCIDeviceInfo via_ac97_info = {
-    .qdev.name          = "VT82C686B_AC97",
-    .qdev.desc          = "AC97",
-    .qdev.size          = sizeof(VT686AC97State),
-    .init               = vt82c686b_ac97_initfn,
-    .vendor_id          = PCI_VENDOR_ID_VIA,
-    .device_id          = PCI_DEVICE_ID_VIA_AC97,
-    .revision           = 0x50,
-    .class_id           = PCI_CLASS_MULTIMEDIA_AUDIO,
+static void via_ac97_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = vt82c686b_ac97_initfn;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_AC97;
+    k->revision = 0x50;
+    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+}
+
+static DeviceInfo via_ac97_info = {
+    .name = "VT82C686B_AC97",
+    .desc = "AC97",
+    .size = sizeof(VT686AC97State),
+    .class_init = via_ac97_class_init,
 };
 
 static void vt82c686b_ac97_register(void)
@@ -385,15 +392,22 @@  void vt82c686b_mc97_init(PCIBus *bus, int devfn)
     qdev_init_nofail(&dev->qdev);
 }
 
-static PCIDeviceInfo via_mc97_info = {
-    .qdev.name          = "VT82C686B_MC97",
-    .qdev.desc          = "MC97",
-    .qdev.size          = sizeof(VT686MC97State),
-    .init               = vt82c686b_mc97_initfn,
-    .vendor_id          = PCI_VENDOR_ID_VIA,
-    .device_id          = PCI_DEVICE_ID_VIA_MC97,
-    .class_id           = PCI_CLASS_COMMUNICATION_OTHER,
-    .revision           = 0x30,
+static void via_mc97_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = vt82c686b_mc97_initfn;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_MC97;
+    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+    k->revision = 0x30;
+}
+
+static DeviceInfo via_mc97_info = {
+    .name = "VT82C686B_MC97",
+    .desc = "MC97",
+    .size = sizeof(VT686MC97State),
+    .class_init = via_mc97_class_init,
 };
 
 static void vt82c686b_mc97_register(void)
@@ -451,21 +465,30 @@  i2c_bus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     return s->smb.smbus;
 }
 
-static PCIDeviceInfo via_pm_info = {
-    .qdev.name          = "VT82C686B_PM",
-    .qdev.desc          = "PM",
-    .qdev.size          = sizeof(VT686PMState),
-    .qdev.vmsd          = &vmstate_acpi,
-    .init               = vt82c686b_pm_initfn,
-    .config_write       = pm_write_config,
-    .vendor_id          = PCI_VENDOR_ID_VIA,
-    .device_id          = PCI_DEVICE_ID_VIA_ACPI,
-    .class_id           = PCI_CLASS_BRIDGE_OTHER,
-    .revision           = 0x40,
-    .qdev.props         = (Property[]) {
-        DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property via_pm_properties[] = {
+    DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void via_pm_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = vt82c686b_pm_initfn;
+    k->config_write = pm_write_config;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_ACPI;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+    k->revision = 0x40;
+}
+
+static DeviceInfo via_pm_info = {
+    .name = "VT82C686B_PM",
+    .desc = "PM",
+    .size = sizeof(VT686PMState),
+    .vmsd = &vmstate_acpi,
+    .props = via_pm_properties,
+    .class_init = via_pm_class_init,
 };
 
 static void vt82c686b_pm_register(void)
@@ -519,18 +542,25 @@  ISABus *vt82c686b_init(PCIBus *bus, int devfn)
     return DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&d->qdev, "isa.0"));
 }
 
-static PCIDeviceInfo via_info = {
-    .qdev.name    = "VT82C686B",
-    .qdev.desc    = "ISA bridge",
-    .qdev.size    = sizeof(VT82C686BState),
-    .qdev.vmsd    = &vmstate_via,
-    .qdev.no_user = 1,
-    .init         = vt82c686b_initfn,
-    .config_write = vt82c686b_write_config,
-    .vendor_id    = PCI_VENDOR_ID_VIA,
-    .device_id    = PCI_DEVICE_ID_VIA_ISA_BRIDGE,
-    .class_id     = PCI_CLASS_BRIDGE_ISA,
-    .revision     = 0x40,
+static void via_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = vt82c686b_initfn;
+    k->config_write = vt82c686b_write_config;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE;
+    k->class_id = PCI_CLASS_BRIDGE_ISA;
+    k->revision = 0x40;
+}
+
+static DeviceInfo via_info = {
+    .name = "VT82C686B",
+    .desc = "ISA bridge",
+    .size = sizeof(VT82C686BState),
+    .vmsd = &vmstate_via,
+    .no_user = 1,
+    .class_init = via_class_init,
 };
 
 static void vt82c686b_register(void)
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 20d8673..a6ceff8 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -143,7 +143,7 @@  static void i6300esb_disable_timer(I6300State *d)
 
 static void i6300esb_reset(DeviceState *dev)
 {
-    PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
+    PCIDevice *pdev = PCI_DEVICE(dev);
     I6300State *d = DO_UPCAST(I6300State, dev, pdev);
 
     i6300esb_debug("I6300State = %p\n", d);
@@ -425,18 +425,25 @@  static WatchdogTimerModel model = {
     .wdt_description = "Intel 6300ESB",
 };
 
-static PCIDeviceInfo i6300esb_info = {
-    .qdev.name    = "i6300esb",
-    .qdev.size    = sizeof(I6300State),
-    .qdev.vmsd    = &vmstate_i6300esb,
-    .qdev.reset   = i6300esb_reset,
-    .config_read  = i6300esb_config_read,
-    .config_write = i6300esb_config_write,
-    .init         = i6300esb_init,
-    .exit         = i6300esb_exit,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_ESB_9,
-    .class_id     = PCI_CLASS_SYSTEM_OTHER,
+static void i6300esb_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->config_read = i6300esb_config_read;
+    k->config_write = i6300esb_config_write;
+    k->init = i6300esb_init;
+    k->exit = i6300esb_exit;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_ESB_9;
+    k->class_id = PCI_CLASS_SYSTEM_OTHER;
+}
+
+static DeviceInfo i6300esb_info = {
+    .name = "i6300esb",
+    .size = sizeof(I6300State),
+    .vmsd = &vmstate_i6300esb,
+    .reset = i6300esb_reset,
+    .class_init = i6300esb_class_init,
 };
 
 static void i6300esb_register_devices(void)
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index e62eaef..40687fb 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -372,20 +372,26 @@  static void platform_reset(DeviceState *dev)
     platform_fixed_ioport_reset(s);
 }
 
-static PCIDeviceInfo xen_platform_info = {
-    .init = xen_platform_initfn,
-    .qdev.name = "xen-platform",
-    .qdev.desc = "XEN platform pci device",
-    .qdev.size = sizeof(PCIXenPlatformState),
-    .qdev.vmsd = &vmstate_xen_platform,
-    .qdev.reset = platform_reset,
-
-    .vendor_id    =  PCI_VENDOR_ID_XEN,
-    .device_id    = PCI_DEVICE_ID_XEN_PLATFORM,
-    .class_id     = PCI_CLASS_OTHERS << 8 | 0x80,
-    .subsystem_vendor_id = PCI_VENDOR_ID_XEN,
-    .subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
-    .revision = 1,
+static void xen_platform_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = xen_platform_initfn;
+    k->vendor_id = PCI_VENDOR_ID_XEN;
+    k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
+    k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->revision = 1;
+}
+
+static DeviceInfo xen_platform_info = {
+    .name = "xen-platform",
+    .desc = "XEN platform pci device",
+    .size = sizeof(PCIXenPlatformState),
+    .vmsd = &vmstate_xen_platform,
+    .reset = platform_reset,
+    .class_init = xen_platform_class_init,
 };
 
 static void xen_platform_register(void)
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index d3c387d..6d625cb 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -47,7 +47,7 @@  static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
 
 static void xio3130_downstream_reset(DeviceState *qdev)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    PCIDevice *d = PCI_DEVICE(qdev);
     msi_reset(d);
     pcie_cap_deverr_reset(d);
     pcie_cap_slot_reset(d);
@@ -167,31 +167,38 @@  static const VMStateDescription vmstate_xio3130_downstream = {
     }
 };
 
-static PCIDeviceInfo xio3130_downstream_info = {
-    .qdev.name = "xio3130-downstream",
-    .qdev.desc = "TI X3130 Downstream Port of PCI Express Switch",
-    .qdev.size = sizeof(PCIESlot),
-    .qdev.reset = xio3130_downstream_reset,
-    .qdev.vmsd = &vmstate_xio3130_downstream,
-
-    .is_express = 1,
-    .is_bridge = 1,
-    .config_write = xio3130_downstream_write_config,
-    .init = xio3130_downstream_initfn,
-    .exit = xio3130_downstream_exitfn,
-    .vendor_id = PCI_VENDOR_ID_TI,
-    .device_id = PCI_DEVICE_ID_TI_XIO3130D,
-    .revision = XIO3130_REVISION,
-
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
-        DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
-        DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-        DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
-                           port.br.dev.exp.aer_log.log_max,
-                           PCIE_AER_LOG_MAX_DEFAULT),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property xio3130_downstream_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+    port.br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = xio3130_downstream_write_config;
+    k->init = xio3130_downstream_initfn;
+    k->exit = xio3130_downstream_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_TI;
+    k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
+    k->revision = XIO3130_REVISION;
+}
+
+static DeviceInfo xio3130_downstream_info = {
+    .name = "xio3130-downstream",
+    .desc = "TI X3130 Downstream Port of PCI Express Switch",
+    .size = sizeof(PCIESlot),
+    .reset = xio3130_downstream_reset,
+    .vmsd = &vmstate_xio3130_downstream,
+    .props = xio3130_downstream_properties,
+    .class_init = xio3130_downstream_class_init,
 };
 
 static void xio3130_downstream_register(void)
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 8283695..ec4c5e3 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -46,7 +46,7 @@  static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address,
 
 static void xio3130_upstream_reset(DeviceState *qdev)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    PCIDevice *d = PCI_DEVICE(qdev);
     msi_reset(d);
     pci_bridge_reset(qdev);
     pcie_cap_deverr_reset(d);
@@ -144,28 +144,35 @@  static const VMStateDescription vmstate_xio3130_upstream = {
     }
 };
 
-static PCIDeviceInfo xio3130_upstream_info = {
-    .qdev.name = "x3130-upstream",
-    .qdev.desc = "TI X3130 Upstream Port of PCI Express Switch",
-    .qdev.size = sizeof(PCIEPort),
-    .qdev.reset = xio3130_upstream_reset,
-    .qdev.vmsd = &vmstate_xio3130_upstream,
-
-    .is_express = 1,
-    .is_bridge = 1,
-    .config_write = xio3130_upstream_write_config,
-    .init = xio3130_upstream_initfn,
-    .exit = xio3130_upstream_exitfn,
-    .vendor_id = PCI_VENDOR_ID_TI,
-    .device_id = PCI_DEVICE_ID_TI_XIO3130U,
-    .revision = XIO3130_REVISION,
-
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
-        DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
-                           PCIE_AER_LOG_MAX_DEFAULT),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property xio3130_upstream_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = xio3130_upstream_write_config;
+    k->init = xio3130_upstream_initfn;
+    k->exit = xio3130_upstream_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_TI;
+    k->device_id = PCI_DEVICE_ID_TI_XIO3130U;
+    k->revision = XIO3130_REVISION;
+}
+
+static DeviceInfo xio3130_upstream_info = {
+    .name = "x3130-upstream",
+    .desc = "TI X3130 Upstream Port of PCI Express Switch",
+    .size = sizeof(PCIEPort),
+    .reset = xio3130_upstream_reset,
+    .vmsd = &vmstate_xio3130_upstream,
+    .props = xio3130_upstream_properties,
+    .class_init = xio3130_upstream_class_init,
 };
 
 static void xio3130_upstream_register(void)