Merge remote-tracking branch 'afaerber-or/qom-next-2' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 18 Jun 2012 15:35:16 +0000 (10:35 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 18 Jun 2012 15:35:16 +0000 (10:35 -0500)
* afaerber-or/qom-next-2: (22 commits)
  qom: Push error reporting to object_property_find()
  qdev: Remove qdev_prop_exists()
  qbus: Initialize in standard way
  qbus: Make child devices links
  qdev: Connect busses with their parent devices
  qdev: Convert busses to QEMU Object Model
  qdev: Move SysBus initialization to sysbus.c
  qdev: Use wrapper for qdev_get_path
  qdev: Remove qdev_prop_set_defaults
  qdev: Clean up global properties
  qdev: Move bus properties to abstract superclasses
  qdev: Move bus properties to a separate global
  qdev: Push "type" property up to Object
  arm_l2x0: Rename "type" property to "cache-type"
  m48t59: Rename "type" property to "model"
  qom: Assert that public types have a non-NULL parent field
  qom: Drop type_register_static_alias() macro
  qom: Make Object a type
  qom: Add class_base_init
  qom: Add object_child_foreach()
  ...

41 files changed:
exec.c
hw/acpi_piix4.c
hw/arm_l2x0.c
hw/i2c.c
hw/ide/internal.h
hw/ide/qdev.c
hw/intel-hda.c
hw/intel-hda.h
hw/isa-bus.c
hw/isa.h
hw/lsi53c895a.c
hw/m48t59.c
hw/pc_piix.c
hw/pci-hotplug.c
hw/pci.c
hw/pci_bridge.c
hw/pci_internals.h
hw/qdev-monitor.c
hw/qdev-properties.c
hw/qdev.c
hw/qdev.h
hw/s390-virtio-bus.c
hw/s390-virtio-bus.h
hw/scsi-bus.c
hw/scsi.h
hw/spapr_pci.c
hw/spapr_vio.c
hw/spapr_vio.h
hw/spapr_vty.c
hw/ssi.c
hw/sysbus.c
hw/sysbus.h
hw/usb.h
hw/usb/bus.c
hw/usb/desc.c
hw/usb/dev-smartcard-reader.c
hw/virtio-scsi.c
hw/virtio-serial-bus.c
include/qemu/object.h
qom/object.c
savevm.c

diff --git a/exec.c b/exec.c
index 5c9b7627bfec5b302530c7566600c45da7c10385..b5d688567ea7009c2dbc4b580a227cb54ef91926 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -2603,8 +2603,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
     assert(new_block);
     assert(!new_block->idstr[0]);
 
-    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
-        char *id = dev->parent_bus->info->get_dev_path(dev);
+    if (dev) {
+        char *id = qdev_get_dev_path(dev);
         if (id) {
             snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
             g_free(id);
index 0345490ee095d0184954b8a462eaf3e96fdf36cf..a11c8e7ae05eadfcf67993daa02d58a9c9bab121 100644 (file)
@@ -284,7 +284,7 @@ static const VMStateDescription vmstate_acpi = {
 
 static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
 {
-    DeviceState *qdev, *next;
+    BusChild *kid, *next;
     BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
     int slot = ffs(slots) - 1;
     bool slot_free = true;
@@ -292,7 +292,8 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
     /* Mark request as complete */
     s->pci0_status.down &= ~(1U << slot);
 
-    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+        DeviceState *qdev = kid->child;
         PCIDevice *dev = PCI_DEVICE(qdev);
         PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
         if (PCI_SLOT(dev->devfn) == slot) {
@@ -313,7 +314,7 @@ static void piix4_update_hotplug(PIIX4PMState *s)
 {
     PCIDevice *dev = &s->dev;
     BusState *bus = qdev_get_parent_bus(&dev->qdev);
-    DeviceState *qdev, *next;
+    BusChild *kid, *next;
 
     /* Execute any pending removes during reset */
     while (s->pci0_status.down) {
@@ -323,7 +324,8 @@ static void piix4_update_hotplug(PIIX4PMState *s)
     s->pci0_hotplug_enable = ~0;
     s->pci0_slot_device_present = 0;
 
-    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+        DeviceState *qdev = kid->child;
         PCIDevice *pdev = PCI_DEVICE(qdev);
         PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
         int slot = PCI_SLOT(pdev->devfn);
index 09f290c85fe89e7b055b32a01418707cf3a14a4a..de6a0863d831e820e32def86ef70158c5f2894e1 100644 (file)
@@ -161,7 +161,7 @@ static int l2x0_priv_init(SysBusDevice *dev)
 }
 
 static Property l2x0_properties[] = {
-    DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100),
+    DEFINE_PROP_UINT32("cache-type", l2x0_state, cache_type, 0x1c100100),
     DEFINE_PROP_END_OF_LIST(),
 };
 
index 23dfccba149925bcd9de4f38185b4451240a4652..296bece119b3217de03b40e18cfdda812e3464d2 100644 (file)
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -17,13 +17,18 @@ struct i2c_bus
     uint8_t saved_address;
 };
 
-static struct BusInfo i2c_bus_info = {
-    .name = "I2C",
-    .size = sizeof(i2c_bus),
-    .props = (Property[]) {
-        DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property i2c_props[] = {
+    DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+#define TYPE_I2C_BUS "i2c-bus"
+#define I2C_BUS(obj) OBJECT_CHECK(i2c_bus, (obj), TYPE_I2C_BUS)
+
+static const TypeInfo i2c_bus_info = {
+    .name = TYPE_I2C_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(i2c_bus),
 };
 
 static void i2c_bus_pre_save(void *opaque)
@@ -61,7 +66,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
 {
     i2c_bus *bus;
 
-    bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
+    bus = FROM_QBUS(i2c_bus, qbus_create(TYPE_I2C_BUS, parent, name));
     vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
     return bus;
 }
@@ -81,11 +86,12 @@ int i2c_bus_busy(i2c_bus *bus)
 /* TODO: Make this handle multiple masters.  */
 int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     I2CSlave *slave = NULL;
     I2CSlaveClass *sc;
 
-    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
         if (candidate->address == address) {
             slave = candidate;
@@ -218,7 +224,8 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = i2c_slave_qdev_init;
-    k->bus_info = &i2c_bus_info;
+    k->bus_type = TYPE_I2C_BUS;
+    k->props = i2c_props;
 }
 
 static TypeInfo i2c_slave_type_info = {
@@ -232,6 +239,7 @@ static TypeInfo i2c_slave_type_info = {
 
 static void i2c_slave_register_types(void)
 {
+    type_register_static(&i2c_bus_info);
     type_register_static(&i2c_slave_type_info);
 }
 
index f8a027d0e42313e7d029f99c7880744b11ba4653..1a02f57bf5f959514ef3972a345ea00525135d8b 100644 (file)
@@ -25,6 +25,9 @@ typedef struct IDEState IDEState;
 typedef struct IDEDMA IDEDMA;
 typedef struct IDEDMAOps IDEDMAOps;
 
+#define TYPE_IDE_BUS "IDE"
+#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
+
 /* Bits of HD_STATUS */
 #define ERR_STAT               0x01
 #define INDEX_STAT             0x02
index a46578d685a779b96228dac4c807ed34a3573538..c1223954010ab8fa6812cce8309d0d281004e5f3 100644 (file)
 
 static char *idebus_get_fw_dev_path(DeviceState *dev);
 
-static struct BusInfo ide_bus_info = {
-    .name  = "IDE",
-    .size  = sizeof(IDEBus),
-    .get_fw_dev_path = idebus_get_fw_dev_path,
-    .props = (Property[]) {
-        DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property ide_props[] = {
+    DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ide_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->get_fw_dev_path = idebus_get_fw_dev_path;
+}
+
+static const TypeInfo ide_bus_info = {
+    .name = TYPE_IDE_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(IDEBus),
+    .class_init = ide_bus_class_init,
 };
 
 void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id)
 {
-    qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL);
+    qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL);
     idebus->bus_id = bus_id;
 }
 
@@ -248,7 +257,8 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = ide_qdev_init;
-    k->bus_info = &ide_bus_info;
+    k->bus_type = TYPE_IDE_BUS;
+    k->props = ide_props;
 }
 
 static TypeInfo ide_device_type_info = {
@@ -262,6 +272,7 @@ static TypeInfo ide_device_type_info = {
 
 static void ide_register_types(void)
 {
+    type_register_static(&ide_bus_info);
     type_register_static(&ide_hd_info);
     type_register_static(&ide_cd_info);
     type_register_static(&ide_drive_info);
index 8f3b70bd1474fbf859078064b83d3d1b78ba11ee..31fe1c54f680f17ee2c590553a0178925fee1f45 100644 (file)
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
 
-static struct BusInfo hda_codec_bus_info = {
-    .name      = "HDA",
-    .size      = sizeof(HDACodecBus),
-    .props     = (Property[]) {
-        DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1),
-        DEFINE_PROP_END_OF_LIST()
-    }
+static Property hda_props[] = {
+    DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static const TypeInfo hda_codec_bus_info = {
+    .name = TYPE_HDA_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(HDACodecBus),
 };
 
 void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus,
                         hda_codec_response_func response,
                         hda_codec_xfer_func xfer)
 {
-    qbus_create_inplace(&bus->qbus, &hda_codec_bus_info, dev, NULL);
+    qbus_create_inplace(&bus->qbus, TYPE_HDA_BUS, dev, NULL);
     bus->response = response;
     bus->xfer = xfer;
 }
@@ -76,10 +78,11 @@ static int hda_codec_dev_exit(DeviceState *qdev)
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     HDACodecDevice *cdev;
 
-    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         if (cdev->cad == cad) {
             return cdev;
@@ -481,10 +484,11 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st)
 
 static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     HDACodecDevice *cdev;
 
-    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         HDACodecDeviceClass *cdc;
 
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
@@ -1103,15 +1107,16 @@ static const MemoryRegionOps intel_hda_mmio_ops = {
 
 static void intel_hda_reset(DeviceState *dev)
 {
+    BusChild *kid;
     IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev);
-    DeviceState *qdev;
     HDACodecDevice *cdev;
 
     intel_hda_regs_reset(d);
     d->wall_base_ns = qemu_get_clock_ns(vm_clock);
 
     /* reset codecs */
-    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         device_reset(DEVICE(cdev));
         d->state_sts |= (1 << cdev->cad);
@@ -1263,7 +1268,8 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = hda_codec_dev_init;
     k->exit = hda_codec_dev_exit;
-    k->bus_info = &hda_codec_bus_info;
+    k->bus_type = TYPE_HDA_BUS;
+    k->props = hda_props;
 }
 
 static TypeInfo hda_codec_device_type_info = {
@@ -1277,6 +1283,7 @@ static TypeInfo hda_codec_device_type_info = {
 
 static void intel_hda_register_types(void)
 {
+    type_register_static(&hda_codec_bus_info);
     type_register_static(&intel_hda_info);
     type_register_static(&hda_codec_device_type_info);
 }
index a1cca5b1bb24d2a6fc1d4f7e671a8114a6f9f265..22e0968d50a762ea123192eb7ca446443082e047 100644 (file)
@@ -14,6 +14,9 @@
 #define HDA_CODEC_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE)
 
+#define TYPE_HDA_BUS "HDA"
+#define HDA_BUS(obj) OBJECT_CHECK(HDACodecBus, (obj), TYPE_HDA_BUS)
+
 typedef struct HDACodecBus HDACodecBus;
 typedef struct HDACodecDevice HDACodecDevice;
 
index 5a43f03a7c342bf21ccc0585126bb94ded5d1237..f9b237387ae0abe63a4e98a28ae927e5546442ae 100644 (file)
@@ -28,11 +28,19 @@ target_phys_addr_t isa_mem_base = 0;
 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *isabus_get_fw_dev_path(DeviceState *dev);
 
-static struct BusInfo isa_bus_info = {
-    .name      = "ISA",
-    .size      = sizeof(ISABus),
-    .print_dev = isabus_dev_print,
-    .get_fw_dev_path = isabus_get_fw_dev_path,
+static void isa_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->print_dev = isabus_dev_print;
+    k->get_fw_dev_path = isabus_get_fw_dev_path;
+}
+
+static const TypeInfo isa_bus_info = {
+    .name = TYPE_ISA_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(ISABus),
+    .class_init = isa_bus_class_init,
 };
 
 ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
@@ -46,7 +54,7 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
         qdev_init_nofail(dev);
     }
 
-    isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL));
+    isabus = FROM_QBUS(ISABus, qbus_create(TYPE_ISA_BUS, dev, NULL));
     isabus->address_space_io = address_space_io;
     return isabus;
 }
@@ -198,7 +206,7 @@ static void isa_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = isa_qdev_init;
-    k->bus_info = &isa_bus_info;
+    k->bus_type = TYPE_ISA_BUS;
 }
 
 static TypeInfo isa_device_type_info = {
@@ -212,6 +220,7 @@ static TypeInfo isa_device_type_info = {
 
 static void isabus_register_types(void)
 {
+    type_register_static(&isa_bus_info);
     type_register_static(&isabus_bridge_info);
     type_register_static(&isa_device_type_info);
 }
index 6c6fd7fac98c8aac24809939d9c70ee33c42b696..dc970527ae6eee933056afc87a05f06c8c041bb3 100644 (file)
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -17,6 +17,9 @@
 #define ISA_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
 
+#define TYPE_ISA_BUS "ISA"
+#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
+
 typedef struct ISADeviceClass {
     DeviceClass parent_class;
     int (*init)(ISADevice *dev);
index f022a024473d150643d0eb67d9ac4599f9a9543b..2fe141d24eab3a6bbd5a31c7d327e3951257a836 100644 (file)
@@ -1677,9 +1677,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-                DeviceState *dev;
+                BusChild *kid;
 
-                QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
+                QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+                    DeviceState *dev = kid->child;
                     device_reset(dev);
                 }
                 s->sstat0 |= LSI_SSTAT0_RST;
index 0c50f450ad1eb4206bae6bae40fef8cb603d9096..dd6cb37ba6f6ed5cc73dd72716fb7acf7a7d20c4 100644 (file)
@@ -65,7 +65,7 @@ struct M48t59State {
     /* NVRAM storage */
     uint8_t *buffer;
     /* Model parameters */
-    uint32_t type; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
+    uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
     /* NVRAM storage */
     uint16_t addr;
     uint8_t  lock;
@@ -197,10 +197,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
        NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
 
     /* check for NVRAM access */
-    if ((NVRAM->type == 2 && addr < 0x7f8) ||
-        (NVRAM->type == 8 && addr < 0x1ff8) ||
-        (NVRAM->type == 59 && addr < 0x1ff0))
+    if ((NVRAM->model == 2 && addr < 0x7f8) ||
+        (NVRAM->model == 8 && addr < 0x1ff8) ||
+        (NVRAM->model == 59 && addr < 0x1ff0)) {
         goto do_write;
+    }
 
     /* TOD access */
     switch (addr) {
@@ -334,10 +335,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
        tmp = from_bcd(val);
        if (tmp >= 0 && tmp <= 99) {
            get_time(NVRAM, &tm);
-            if (NVRAM->type == 8)
+            if (NVRAM->model == 8) {
                 tm.tm_year = from_bcd(val) + 68; // Base year is 1968
-            else
+            } else {
                 tm.tm_year = from_bcd(val);
+            }
            set_time(NVRAM, &tm);
        }
         break;
@@ -362,10 +364,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
     uint32_t retval = 0xFF;
 
     /* check for NVRAM access */
-    if ((NVRAM->type == 2 && addr < 0x078f) ||
-        (NVRAM->type == 8 && addr < 0x1ff8) ||
-        (NVRAM->type == 59 && addr < 0x1ff0))
+    if ((NVRAM->model == 2 && addr < 0x078f) ||
+        (NVRAM->model == 8 && addr < 0x1ff8) ||
+        (NVRAM->model == 59 && addr < 0x1ff0)) {
         goto do_read;
+    }
 
     /* TOD access */
     switch (addr) {
@@ -439,10 +442,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
     case 0x07FF:
         /* year */
         get_time(NVRAM, &tm);
-        if (NVRAM->type == 8)
+        if (NVRAM->model == 8) {
             retval = to_bcd(tm.tm_year - 68); // Base year is 1968
-        else
+        } else {
             retval = to_bcd(tm.tm_year);
+        }
         break;
     default:
         /* Check lock registers state */
@@ -633,7 +637,7 @@ static const MemoryRegionOps m48t59_io_ops = {
 
 /* Initialisation routine */
 M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
-                         uint32_t io_base, uint16_t size, int type)
+                         uint32_t io_base, uint16_t size, int model)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -641,7 +645,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
     M48t59State *state;
 
     dev = qdev_create(NULL, "m48t59");
-    qdev_prop_set_uint32(dev, "type", type);
+    qdev_prop_set_uint32(dev, "model", model);
     qdev_prop_set_uint32(dev, "size", size);
     qdev_prop_set_uint32(dev, "io_base", io_base);
     qdev_init_nofail(dev);
@@ -661,14 +665,14 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
 }
 
 M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
-                             int type)
+                             int model)
 {
     M48t59ISAState *d;
     ISADevice *dev;
     M48t59State *s;
 
     dev = isa_create(bus, "m48t59_isa");
-    qdev_prop_set_uint32(&dev->qdev, "type", type);
+    qdev_prop_set_uint32(&dev->qdev, "model", model);
     qdev_prop_set_uint32(&dev->qdev, "size", size);
     qdev_prop_set_uint32(&dev->qdev, "io_base", io_base);
     qdev_init_nofail(&dev->qdev);
@@ -686,7 +690,7 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
 static void m48t59_init_common(M48t59State *s)
 {
     s->buffer = g_malloc0(s->size);
-    if (s->type == 59) {
+    if (s->model == 59) {
         s->alrm_timer = qemu_new_timer_ns(rtc_clock, &alarm_cb, s);
         s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s);
     }
@@ -722,7 +726,7 @@ static int m48t59_init1(SysBusDevice *dev)
 
 static Property m48t59_isa_properties[] = {
     DEFINE_PROP_UINT32("size",    M48t59ISAState, state.size,    -1),
-    DEFINE_PROP_UINT32("type",    M48t59ISAState, state.type,    -1),
+    DEFINE_PROP_UINT32("model",   M48t59ISAState, state.model,   -1),
     DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base,  0),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -746,7 +750,7 @@ static TypeInfo m48t59_isa_info = {
 
 static Property m48t59_properties[] = {
     DEFINE_PROP_UINT32("size",    M48t59SysBusState, state.size,    -1),
-    DEFINE_PROP_UINT32("type",    M48t59SysBusState, state.type,    -1),
+    DEFINE_PROP_UINT32("model",   M48t59SysBusState, state.model,   -1),
     DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base,  0),
     DEFINE_PROP_END_OF_LIST(),
 };
index f49b0aaf89394d09d7a7773bbef0cf9acb15aaa9..d68f77a9c04fb6f48d0819df743f8f6a6753b488 100644 (file)
@@ -29,6 +29,7 @@
 #include "apic.h"
 #include "pci.h"
 #include "pci_ids.h"
+#include "usb.h"
 #include "net.h"
 #include "boards.h"
 #include "ide.h"
@@ -374,7 +375,7 @@ static QEMUMachine pc_machine_v1_1 = {
             .property = "vapic",\
             .value    = "off",\
         },{\
-            .driver   = "USB",\
+            .driver   = TYPE_USB_DEVICE,\
             .property = "full-path",\
             .value    = "no",\
         }
@@ -447,7 +448,7 @@ static QEMUMachine pc_machine_v0_14 = {
 #define PC_COMPAT_0_13 \
         PC_COMPAT_0_14,\
         {\
-            .driver   = "PCI",\
+            .driver   = TYPE_PCI_DEVICE,\
             .property = "command_serr_enable",\
             .value    = "off",\
         },{\
@@ -519,7 +520,7 @@ static QEMUMachine pc_machine_v0_12 = {
             .property = "vectors",\
             .value    = stringify(0),\
         },{\
-            .driver   = "PCI",\
+            .driver   = TYPE_PCI_DEVICE,\
             .property = "rombar",\
             .value    = stringify(0),\
         }
index 61257f457bc5acfe8707d61be421410adb99b4ca..e7fb780a088280b085e742c7547d056cbf167998 100644 (file)
@@ -80,11 +80,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     SCSIBus *scsibus;
     SCSIDevice *scsidev;
 
-    scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus));
-    if (!scsibus || strcmp(scsibus->qbus.info->name, "SCSI") != 0) {
-        error_report("Device is not a SCSI adapter");
-        return -1;
-    }
+    scsibus = SCSI_BUS(QLIST_FIRST(&adapter->child_bus));
 
     /*
      * drive_init() tries to find a default for dinfo->unit.  Doesn't
index 9daa0bfb204b7ac74b7afb8242aa9e1c43428eb9..bdfb3d6540ee654e4ddc0711912b88feab2c5b4f 100644 (file)
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -46,23 +46,32 @@ static char *pcibus_get_dev_path(DeviceState *dev);
 static char *pcibus_get_fw_dev_path(DeviceState *dev);
 static int pcibus_reset(BusState *qbus);
 
-struct BusInfo pci_bus_info = {
-    .name       = "PCI",
-    .size       = sizeof(PCIBus),
-    .print_dev  = pcibus_dev_print,
-    .get_dev_path = pcibus_get_dev_path,
-    .get_fw_dev_path = pcibus_get_fw_dev_path,
-    .reset      = pcibus_reset,
-    .props      = (Property[]) {
-        DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
-        DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
-        DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
-        DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
-                        QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
-        DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
-                        QEMU_PCI_CAP_SERR_BITNR, true),
-        DEFINE_PROP_END_OF_LIST()
-    }
+static Property pci_props[] = {
+    DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
+    DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
+    DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
+    DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
+                    QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
+    DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
+                    QEMU_PCI_CAP_SERR_BITNR, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void pci_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->print_dev = pcibus_dev_print;
+    k->get_dev_path = pcibus_get_dev_path;
+    k->get_fw_dev_path = pcibus_get_fw_dev_path;
+    k->reset = pcibus_reset;
+}
+
+static const TypeInfo pci_bus_info = {
+    .name = TYPE_PCI_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(PCIBus),
+    .class_init = pci_bus_class_init,
 };
 
 static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
@@ -270,7 +279,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min)
 {
-    qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
+    qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
     bus->address_space_mem = address_space_mem;
@@ -291,7 +300,7 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     PCIBus *bus;
 
     bus = g_malloc0(sizeof(*bus));
-    bus->qbus.qdev_allocated = 1;
+    bus->qbus.glib_allocated = true;
     pci_bus_new_inplace(bus, parent, name, address_space_mem,
                         address_space_io, devfn_min);
     return bus;
@@ -2008,7 +2017,8 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
     k->init = pci_qdev_init;
     k->unplug = pci_unplug_device;
     k->exit = pci_unregister_device;
-    k->bus_info = &pci_bus_info;
+    k->bus_type = TYPE_PCI_BUS;
+    k->props = pci_props;
 }
 
 static TypeInfo pci_device_type_info = {
@@ -2022,6 +2032,7 @@ static TypeInfo pci_device_type_info = {
 
 static void pci_register_types(void)
 {
+    type_register_static(&pci_bus_info);
     type_register_static(&pci_device_type_info);
 }
 
index e0832b4a67e92ca1dfab6e416eca85c6080cc42b..0916276c4d4255900ab8a4743dfc64fc85e8802c 100644 (file)
@@ -318,7 +318,7 @@ int pci_bridge_initfn(PCIDevice *dev)
            br->bus_name = dev->qdev.id;
     }
 
-    qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
+    qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
     sec_bus->map_irq = br->map_irq;
index 96690b72d38f770227df4e5cf4ed92f589ee0d07..399c6d475ce93901f2426335ffd0fcb41b0fb89a 100644 (file)
@@ -12,7 +12,8 @@
  * Use accessor function in pci.h, pci_bridge.h
  */
 
-extern struct BusInfo pci_bus_info;
+#define TYPE_PCI_BUS "PCI"
+#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
 
 struct PCIBus {
     BusState qbus;
index b01ef0600e60d22c18f136fa4dde49d6cecff562..17452c8c01c8e1849d8982dccf4be8a039509536 100644 (file)
@@ -75,8 +75,8 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
     }
 
     error_printf("name \"%s\"", object_class_get_name(klass));
-    if (dc->bus_info) {
-        error_printf(", bus %s", dc->bus_info->name);
+    if (dc->bus_type) {
+        error_printf(", bus %s", dc->bus_type);
     }
     if (qdev_class_has_alias(dc)) {
         error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
@@ -123,7 +123,6 @@ int qdev_device_help(QemuOpts *opts)
     const char *driver;
     Property *prop;
     ObjectClass *klass;
-    DeviceClass *info;
 
     driver = qemu_opt_get(opts, "driver");
     if (driver && !strcmp(driver, "?")) {
@@ -149,30 +148,22 @@ int qdev_device_help(QemuOpts *opts)
     if (!klass) {
         return 0;
     }
-    info = DEVICE_CLASS(klass);
-
-    for (prop = info->props; prop && prop->name; prop++) {
-        /*
-         * TODO Properties without a parser are just for dirty hacks.
-         * qdev_prop_ptr is the only such PropertyInfo.  It's marked
-         * for removal.  This conditional should be removed along with
-         * it.
-         */
-        if (!prop->info->set) {
-            continue;           /* no way to set it, don't show */
-        }
-        error_printf("%s.%s=%s\n", driver, prop->name,
-                     prop->info->legacy_name ?: prop->info->name);
-    }
-    if (info->bus_info) {
-        for (prop = info->bus_info->props; prop && prop->name; prop++) {
+    do {
+        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
+            /*
+             * TODO Properties without a parser are just for dirty hacks.
+             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
+             * for removal.  This conditional should be removed along with
+             * it.
+             */
             if (!prop->info->set) {
                 continue;           /* no way to set it, don't show */
             }
             error_printf("%s.%s=%s\n", driver, prop->name,
                          prop->info->legacy_name ?: prop->info->name);
         }
-    }
+        klass = object_class_get_parent(klass);
+    } while (klass != object_class_by_name(TYPE_DEVICE));
     return 1;
 }
 
@@ -214,11 +205,12 @@ static void qbus_list_bus(DeviceState *dev)
 
 static void qbus_list_dev(BusState *bus)
 {
-    DeviceState *dev;
+    BusChild *kid;
     const char *sep = " ";
 
     error_printf("devices at \"%s\":", bus->name);
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
         if (dev->id)
             error_printf("/\"%s\"", dev->id);
@@ -241,7 +233,7 @@ static BusState *qbus_find_bus(DeviceState *dev, char *elem)
 
 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 {
-    DeviceState *dev;
+    BusChild *kid;
 
     /*
      * try to match in order:
@@ -249,17 +241,20 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
      *   (2) driver name
      *   (3) driver alias, if present
      */
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
             return dev;
         }
     }
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
             return dev;
         }
     }
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
         if (qdev_class_has_alias(dc) &&
@@ -271,25 +266,27 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 }
 
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
-                                     const BusInfo *info)
+                                     const char *bus_typename)
 {
-    DeviceState *dev;
+    BusChild *kid;
     BusState *child, *ret;
     int match = 1;
 
     if (name && (strcmp(bus->name, name) != 0)) {
         match = 0;
     }
-    if (info && (bus->info != info)) {
+    if (bus_typename &&
+        (strcmp(object_get_typename(OBJECT(bus)), bus_typename) != 0)) {
         match = 0;
     }
     if (match) {
         return bus;
     }
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qbus_find_recursive(child, name, info);
+            ret = qbus_find_recursive(child, name, bus_typename);
             if (ret) {
                 return ret;
             }
@@ -424,16 +421,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
         if (!bus) {
             return NULL;
         }
-        if (bus->info != k->bus_info) {
+        if (strcmp(object_get_typename(OBJECT(bus)), k->bus_type) != 0) {
             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
-                           driver, bus->info->name);
+                          driver, object_get_typename(OBJECT(bus)));
             return NULL;
         }
     } else {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info);
+        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
         if (!bus) {
             qerror_report(QERR_NO_BUS_FOR_DEVICE,
-                          driver, k->bus_info->name);
+                          driver, k->bus_type);
             return NULL;
         }
     }
@@ -449,7 +446,6 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     /* create device, set properties */
     qdev = DEVICE(object_new(driver));
     qdev_set_parent_bus(qdev, bus);
-    qdev_prop_set_globals(qdev);
 
     id = qemu_opts_id(opts);
     if (id) {
@@ -482,7 +478,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
 static void qbus_print(Monitor *mon, BusState *bus, int indent);
 
 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
-                             const char *prefix, int indent)
+                             int indent)
 {
     if (!props)
         return;
@@ -501,14 +497,24 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
             error_free(err);
             continue;
         }
-        qdev_printf("%s-prop: %s = %s\n", prefix, props->name,
+        qdev_printf("%s = %s\n", props->name,
                     value && *value ? value : "<null>");
         g_free(value);
     }
 }
 
+static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->print_dev) {
+        bc->print_dev(mon, dev, indent);
+    }
+}
+
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 {
+    ObjectClass *class;
     BusState *child;
     qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
                 dev->id ? dev->id : "");
@@ -519,10 +525,12 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
     if (dev->num_gpio_out) {
         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
     }
-    qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
-    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
-    if (dev->parent_bus->info->print_dev)
-        dev->parent_bus->info->print_dev(mon, dev, indent);
+    class = object_get_class(OBJECT(dev));
+    do {
+        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+    bus_print_dev(dev->parent_bus, mon, dev, indent + 2);
     QLIST_FOREACH(child, &dev->child_bus, sibling) {
         qbus_print(mon, child, indent);
     }
@@ -530,12 +538,13 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 
 static void qbus_print(Monitor *mon, BusState *bus, int indent)
 {
-    struct DeviceState *dev;
+    BusChild *kid;
 
     qdev_printf("bus: %s\n", bus->name);
     indent += 2;
-    qdev_printf("type %s\n", bus->info->name);
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         qdev_print(mon, dev, indent);
     }
 }
index 9ae318717e073f744fdfc8bff26ff87912e54064..099a7aa96f9588edb655d35272ad5bce7bcf82ba 100644 (file)
@@ -915,26 +915,22 @@ static Property *qdev_prop_walk(Property *props, const char *name)
 
 static Property *qdev_prop_find(DeviceState *dev, const char *name)
 {
+    ObjectClass *class;
     Property *prop;
 
     /* device properties */
-    prop = qdev_prop_walk(qdev_get_props(dev), name);
-    if (prop)
-        return prop;
-
-    /* bus properties */
-    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
-    if (prop)
-        return prop;
+    class = object_get_class(OBJECT(dev));
+    do {
+        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
+        if (prop) {
+            return prop;
+        }
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
 
     return NULL;
 }
 
-int qdev_prop_exists(DeviceState *dev, const char *name)
-{
-    return qdev_prop_find(dev, name) ? true : false;
-}
-
 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                     Property *prop, const char *value)
 {
@@ -1105,28 +1101,6 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
     *ptr = value;
 }
 
-void qdev_prop_set_defaults(DeviceState *dev, Property *props)
-{
-    Object *obj = OBJECT(dev);
-    if (!props)
-        return;
-    for (; props->name; props++) {
-        Error *errp = NULL;
-        if (props->qtype == QTYPE_NONE) {
-            continue;
-        }
-        if (props->qtype == QTYPE_QBOOL) {
-            object_property_set_bool(obj, props->defval, props->name, &errp);
-        } else if (props->info->enum_table) {
-            object_property_set_str(obj, props->info->enum_table[props->defval],
-                                    props->name, &errp);
-        } else if (props->qtype == QTYPE_QINT) {
-            object_property_set_int(obj, props->defval, props->name, &errp);
-        }
-        assert_no_error(errp);
-    }
-}
-
 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
 
 static void qdev_prop_register_global(GlobalProperty *prop)
@@ -1145,17 +1119,20 @@ void qdev_prop_register_global_list(GlobalProperty *props)
 
 void qdev_prop_set_globals(DeviceState *dev)
 {
-    GlobalProperty *prop;
-
-    QTAILQ_FOREACH(prop, &global_props, next) {
-        if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
-            strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
-            continue;
+    ObjectClass *class = object_get_class(OBJECT(dev));
+
+    do {
+        GlobalProperty *prop;
+        QTAILQ_FOREACH(prop, &global_props, next) {
+            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
+                continue;
+            }
+            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
+                exit(1);
+            }
         }
-        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
-            exit(1);
-        }
-    }
+        class = object_class_get_parent(class);
+    } while (class);
 }
 
 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
index af419b9c1318e1728824984698f1639faea46554..a6c4c02947748bc3d091fe8a3bae2a8dcaf653ac 100644 (file)
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -34,10 +34,6 @@ int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
 static bool qdev_hot_removed = false;
 
-/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
-static BusState *main_system_bus;
-static void main_system_bus_create(void);
-
 /* Register a new device type.  */
 const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
 {
@@ -45,18 +41,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
     return dc->vmsd;
 }
 
-BusInfo *qdev_get_bus_info(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->bus_info;
-}
-
-Property *qdev_get_props(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->props;
-}
-
 const char *qdev_fw_name(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -76,22 +60,48 @@ bool qdev_exists(const char *name)
 static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                      Error **errp);
 
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+static void bus_remove_child(BusState *bus, DeviceState *child)
 {
-    Property *prop;
+    BusChild *kid;
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        if (kid->child == child) {
+            char name[32];
+
+            snprintf(name, sizeof(name), "child[%d]", kid->index);
+            QTAILQ_REMOVE(&bus->children, kid, sibling);
+            object_property_del(OBJECT(bus), name, NULL);
+            g_free(kid);
+            return;
+        }
+    }
+}
+
+static void bus_add_child(BusState *bus, DeviceState *child)
+{
+    char name[32];
+    BusChild *kid = g_malloc0(sizeof(*kid));
 
     if (qdev_hotplug) {
         assert(bus->allow_hotplug);
     }
 
-    dev->parent_bus = bus;
-    QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
+    kid->index = bus->max_index++;
+    kid->child = child;
 
-    for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
-        qdev_property_add_legacy(dev, prop, NULL);
-        qdev_property_add_static(dev, prop, NULL);
-    }
-    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
+    QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
+
+    snprintf(name, sizeof(name), "child[%d]", kid->index);
+    object_property_add_link(OBJECT(bus), name,
+                             object_get_typename(OBJECT(child)),
+                             (Object **)&kid->child,
+                             NULL);
+}
+
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+{
+    dev->parent_bus = bus;
+    bus_add_child(bus, dev);
 }
 
 /* Create a new device.  This only initializes the device state structure
@@ -105,7 +115,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     if (!dev) {
         if (bus) {
             hw_error("Unknown device '%s' for bus '%s'\n", name,
-                     bus->info->name);
+                     object_get_typename(OBJECT(bus)));
         } else {
             hw_error("Unknown device '%s' for default sysbus\n", name);
         }
@@ -131,7 +141,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
     }
 
     qdev_set_parent_bus(dev, bus);
-    qdev_prop_set_globals(dev);
 
     return dev;
 }
@@ -210,18 +219,11 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
     return 0;
 }
 
-BusState *sysbus_get_default(void)
-{
-    if (!main_system_bus) {
-        main_system_bus_create();
-    }
-    return main_system_bus;
-}
-
 static int qbus_reset_one(BusState *bus, void *opaque)
 {
-    if (bus->info->reset) {
-        return bus->info->reset(bus);
+    BusClass *bc = BUS_GET_CLASS(bus);
+    if (bc->reset) {
+        return bc->reset(bus);
     }
     return 0;
 }
@@ -322,7 +324,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
     if (nd->netdev)
         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
-        qdev_prop_exists(dev, "vectors")) {
+        object_property_find(OBJECT(dev), "vectors", NULL)) {
         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
     }
     nd->instantiated = 1;
@@ -343,7 +345,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
 int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque)
 {
-    DeviceState *dev;
+    BusChild *kid;
     int err;
 
     if (busfn) {
@@ -353,8 +355,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
         }
     }
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
-        err = qdev_walk_children(dev, devfn, busfn, opaque);
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        err = qdev_walk_children(kid->child, devfn, busfn, opaque);
         if (err < 0) {
             return err;
         }
@@ -388,12 +390,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
 
 DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {
-    DeviceState *dev, *ret;
+    BusChild *kid;
+    DeviceState *ret;
     BusState *child;
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
-        if (dev->id && strcmp(dev->id, id) == 0)
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+
+        if (dev->id && strcmp(dev->id, id) == 0) {
             return dev;
+        }
+
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
             ret = qdev_find_recursive(child, id);
             if (ret) {
@@ -404,84 +411,87 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
     return NULL;
 }
 
-void qbus_create_inplace(BusState *bus, BusInfo *info,
-                         DeviceState *parent, const char *name)
+static void qbus_realize(BusState *bus)
 {
+    const char *typename = object_get_typename(OBJECT(bus));
     char *buf;
     int i,len;
 
-    bus->info = info;
-    bus->parent = parent;
-
-    if (name) {
+    if (bus->name) {
         /* use supplied name */
-        bus->name = g_strdup(name);
-    } else if (parent && parent->id) {
+    } else if (bus->parent && bus->parent->id) {
         /* parent device has id -> use it for bus name */
-        len = strlen(parent->id) + 16;
+        len = strlen(bus->parent->id) + 16;
         buf = g_malloc(len);
-        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
+        snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
         bus->name = buf;
     } else {
         /* no id -> use lowercase bus type for bus name */
-        len = strlen(info->name) + 16;
+        len = strlen(typename) + 16;
         buf = g_malloc(len);
-        len = snprintf(buf, len, "%s.%d", info->name,
-                       parent ? parent->num_child_bus : 0);
+        len = snprintf(buf, len, "%s.%d", typename,
+                       bus->parent ? bus->parent->num_child_bus : 0);
         for (i = 0; i < len; i++)
             buf[i] = qemu_tolower(buf[i]);
         bus->name = buf;
     }
 
-    QTAILQ_INIT(&bus->children);
-    if (parent) {
-        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
-        parent->num_child_bus++;
-    } else if (bus != main_system_bus) {
+    if (bus->parent) {
+        QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
+        bus->parent->num_child_bus++;
+        object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
+    } else if (bus != sysbus_get_default()) {
         /* TODO: once all bus devices are qdevified,
            only reset handler for main_system_bus should be registered here. */
         qemu_register_reset(qbus_reset_all_fn, bus);
     }
 }
 
-BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
+void qbus_create_inplace(BusState *bus, const char *typename,
+                         DeviceState *parent, const char *name)
 {
-    BusState *bus;
+    object_initialize(bus, typename);
 
-    bus = g_malloc0(info->size);
-    bus->qdev_allocated = 1;
-    qbus_create_inplace(bus, info, parent, name);
-    return bus;
+    bus->parent = parent;
+    bus->name = name ? g_strdup(name) : NULL;
+    qbus_realize(bus);
 }
 
-static void main_system_bus_create(void)
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
 {
-    /* assign main_system_bus before qbus_create_inplace()
-     * in order to make "if (bus != main_system_bus)" work */
-    main_system_bus = g_malloc0(system_bus_info.size);
-    main_system_bus->qdev_allocated = 1;
-    qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
-                        "main-system-bus");
+    BusState *bus;
+
+    bus = BUS(object_new(typename));
+    bus->qom_allocated = true;
+
+    bus->parent = parent;
+    bus->name = name ? g_strdup(name) : NULL;
+    qbus_realize(bus);
+
+    return bus;
 }
 
 void qbus_free(BusState *bus)
 {
-    DeviceState *dev;
-
-    while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
-        qdev_free(dev);
-    }
-    if (bus->parent) {
-        QLIST_REMOVE(bus, sibling);
-        bus->parent->num_child_bus--;
+    if (bus->qom_allocated) {
+        object_delete(OBJECT(bus));
     } else {
-        assert(bus != main_system_bus); /* main_system_bus is never freed */
-        qemu_unregister_reset(qbus_reset_all_fn, bus);
+        object_finalize(OBJECT(bus));
+        if (bus->glib_allocated) {
+            g_free(bus);
+        }
     }
-    g_free((void*)bus->name);
-    if (bus->qdev_allocated) {
-        g_free(bus);
+}
+
+static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->get_fw_dev_path) {
+        return bc->get_fw_dev_path(dev);
     }
+
+    return NULL;
 }
 
 static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
@@ -491,8 +501,8 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
     if (dev && dev->parent_bus) {
         char *d;
         l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
-        if (dev->parent_bus->info->get_fw_dev_path) {
-            d = dev->parent_bus->info->get_fw_dev_path(dev);
+        d = bus_get_fw_dev_path(dev->parent_bus, dev);
+        if (d) {
             l += snprintf(p + l, size - l, "%s", d);
             g_free(d);
         } else {
@@ -516,9 +526,20 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
     return strdup(path);
 }
 
-static char *qdev_get_type(Object *obj, Error **errp)
+char *qdev_get_dev_path(DeviceState *dev)
 {
-    return g_strdup(object_get_typename(obj));
+    BusClass *bc;
+
+    if (!dev || !dev->parent_bus) {
+        return NULL;
+    }
+
+    bc = BUS_GET_CLASS(dev->parent_bus);
+    if (bc->get_dev_path) {
+        return bc->get_dev_path(dev);
+    }
+
+    return NULL;
 }
 
 /**
@@ -606,6 +627,9 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 void qdev_property_add_static(DeviceState *dev, Property *prop,
                               Error **errp)
 {
+    Error *local_err = NULL;
+    Object *obj = OBJECT(dev);
+
     /*
      * TODO qdev_prop_ptr does not have getters or setters.  It must
      * go now that it can be replaced with links.  The test should be
@@ -615,15 +639,34 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
         return;
     }
 
-    object_property_add(OBJECT(dev), prop->name, prop->info->name,
+    object_property_add(obj, prop->name, prop->info->name,
                         prop->info->get, prop->info->set,
                         prop->info->release,
-                        prop, errp);
+                        prop, &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (prop->qtype == QTYPE_NONE) {
+        return;
+    }
+
+    if (prop->qtype == QTYPE_QBOOL) {
+        object_property_set_bool(obj, prop->defval, prop->name, &local_err);
+    } else if (prop->info->enum_table) {
+        object_property_set_str(obj, prop->info->enum_table[prop->defval],
+                                prop->name, &local_err);
+    } else if (prop->qtype == QTYPE_QINT) {
+        object_property_set_int(obj, prop->defval, prop->name, &local_err);
+    }
+    assert_no_error(local_err);
 }
 
 static void device_initfn(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
+    ObjectClass *class;
     Property *prop;
 
     if (qdev_hotplug) {
@@ -634,13 +677,18 @@ static void device_initfn(Object *obj)
     dev->instance_id_alias = -1;
     dev->state = DEV_STATE_CREATED;
 
-    for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
-        qdev_property_add_legacy(dev, prop, NULL);
-        qdev_property_add_static(dev, prop, NULL);
-    }
+    class = object_get_class(OBJECT(dev));
+    do {
+        for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
+            qdev_property_add_legacy(dev, prop, NULL);
+            qdev_property_add_static(dev, prop, NULL);
+        }
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+    qdev_prop_set_globals(dev);
 
-    object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
-    qdev_prop_set_defaults(dev, qdev_get_props(dev));
+    object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
+                             (Object **)&dev->parent_bus, NULL);
 }
 
 /* Unlink device from bus and free the structure.  */
@@ -665,7 +713,19 @@ static void device_finalize(Object *obj)
             qemu_opts_del(dev->opts);
         }
     }
-    QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
+    if (dev->parent_bus) {
+        bus_remove_child(dev->parent_bus, dev);
+    }
+}
+
+static void device_class_base_init(ObjectClass *class, void *data)
+{
+    DeviceClass *klass = DEVICE_CLASS(class);
+
+    /* We explicitly look up properties in the superclasses,
+     * so do not propagate them to the subclasses.
+     */
+    klass->props = NULL;
 }
 
 void device_reset(DeviceState *dev)
@@ -694,12 +754,50 @@ static TypeInfo device_type_info = {
     .instance_size = sizeof(DeviceState),
     .instance_init = device_initfn,
     .instance_finalize = device_finalize,
+    .class_base_init = device_class_base_init,
     .abstract = true,
     .class_size = sizeof(DeviceClass),
 };
 
+static void qbus_initfn(Object *obj)
+{
+    BusState *bus = BUS(obj);
+
+    QTAILQ_INIT(&bus->children);
+}
+
+static void qbus_finalize(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    BusChild *kid;
+
+    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
+        DeviceState *dev = kid->child;
+        qdev_free(dev);
+    }
+    if (bus->parent) {
+        QLIST_REMOVE(bus, sibling);
+        bus->parent->num_child_bus--;
+    } else {
+        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+        qemu_unregister_reset(qbus_reset_all_fn, bus);
+    }
+    g_free((char *)bus->name);
+}
+
+static const TypeInfo bus_info = {
+    .name = TYPE_BUS,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(BusState),
+    .abstract = true,
+    .class_size = sizeof(BusClass),
+    .instance_init = qbus_initfn,
+    .instance_finalize = qbus_finalize,
+};
+
 static void qdev_register_types(void)
 {
+    type_register_static(&bus_info);
     type_register_static(&device_type_info);
 }
 
index 5386b165bcc4d2b7942598ad9d85e97a48827f70..ae1d2812bffb32c7b09e87c6e0b9cd28e328361c 100644 (file)
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -17,7 +17,7 @@ typedef struct CompatProperty CompatProperty;
 
 typedef struct BusState BusState;
 
-typedef struct BusInfo BusInfo;
+typedef struct BusClass BusClass;
 
 enum DevState {
     DEV_STATE_CREATED = 1,
@@ -55,7 +55,7 @@ typedef struct DeviceClass {
     qdev_initfn init;
     qdev_event unplug;
     qdev_event exit;
-    BusInfo *bus_info;
+    const char *bus_type;
 } DeviceClass;
 
 /* This structure should not be accessed directly.  We declare it here
@@ -74,38 +74,52 @@ struct DeviceState {
     qemu_irq *gpio_in;
     QLIST_HEAD(, BusState) child_bus;
     int num_child_bus;
-    QTAILQ_ENTRY(DeviceState) sibling;
     int instance_id_alias;
     int alias_required_for_version;
 };
 
-typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
-typedef char *(*bus_get_dev_path)(DeviceState *dev);
 /*
  * This callback is used to create Open Firmware device path in accordance with
  * OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings
  * can be found here http://playground.sun.com/1275/bindings/.
  */
-typedef char *(*bus_get_fw_dev_path)(DeviceState *dev);
-typedef int (qbus_resetfn)(BusState *bus);
 
-struct BusInfo {
-    const char *name;
-    size_t size;
-    bus_dev_printfn print_dev;
-    bus_get_dev_path get_dev_path;
-    bus_get_fw_dev_path get_fw_dev_path;
-    qbus_resetfn *reset;
-    Property *props;
+#define TYPE_BUS "bus"
+#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
+#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
+#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+
+struct BusClass {
+    ObjectClass parent_class;
+
+    /* FIXME first arg should be BusState */
+    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
+    char *(*get_dev_path)(DeviceState *dev);
+    char *(*get_fw_dev_path)(DeviceState *dev);
+    int (*reset)(BusState *bus);
 };
 
+typedef struct BusChild {
+    DeviceState *child;
+    int index;
+    QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
+/**
+ * BusState:
+ * @qom_allocated: Indicates whether the object was allocated by QOM.
+ * @glib_allocated: Indicates whether the object was initialized in-place
+ * yet is expected to be freed with g_free().
+ */
 struct BusState {
+    Object obj;
     DeviceState *parent;
-    BusInfo *info;
     const char *name;
     int allow_hotplug;
-    int qdev_allocated;
-    QTAILQ_HEAD(ChildrenHead, DeviceState) children;
+    bool qom_allocated;
+    bool glib_allocated;
+    int max_index;
+    QTAILQ_HEAD(ChildrenHead, BusChild) children;
     QLIST_ENTRY(BusState) sibling;
 };
 
@@ -175,9 +189,9 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id);
 typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
 typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
 
-void qbus_create_inplace(BusState *bus, BusInfo *info,
+void qbus_create_inplace(BusState *bus, const char *typename,
                          DeviceState *parent, const char *name);
-BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
 /* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
  *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
  *           0 otherwise. */
@@ -292,7 +306,6 @@ extern PropertyInfo qdev_prop_blocksize;
 
 /* Set properties between creation and init.  */
 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
-int qdev_prop_exists(DeviceState *dev, const char *name);
 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
@@ -310,7 +323,6 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
 /* FIXME: Remove opaque pointer properties.  */
 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
-void qdev_prop_set_defaults(DeviceState *dev, Property *props);
 
 void qdev_prop_register_global_list(GlobalProperty *props);
 void qdev_prop_set_globals(DeviceState *dev);
@@ -319,9 +331,6 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
 
 char *qdev_get_fw_dev_path(DeviceState *dev);
 
-/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
-extern struct BusInfo system_bus_info;
-
 /**
  * @qdev_property_add_static - add a @Property to a device referencing a
  * field in a struct.
@@ -347,10 +356,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
 
 const char *qdev_fw_name(DeviceState *dev);
 
-BusInfo *qdev_get_bus_info(DeviceState *dev);
-
-Property *qdev_get_props(DeviceState *dev);
-
 Object *qdev_get_machine(void);
 
 /* FIXME: make this a link<> */
@@ -358,4 +363,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
 
 extern int qdev_hotplug;
 
+char *qdev_get_dev_path(DeviceState *dev);
+
 #endif
index 23ef35b3bb28b85ed33742a11b75d592ec4ffff6..4d49b96f94af684a0dae2a9c087be6a8ef710264 100644 (file)
 
 #define VIRTIO_EXT_CODE   0x2603
 
-struct BusInfo s390_virtio_bus_info = {
-    .name       = "s390-virtio",
-    .size       = sizeof(VirtIOS390Bus),
+static const TypeInfo s390_virtio_bus_info = {
+    .name = TYPE_S390_VIRTIO_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VirtIOS390Bus),
 };
 
 static const VirtIOBindings virtio_s390_bindings;
@@ -92,7 +93,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
 
     /* Create bus on bridge device */
 
-    _bus = qbus_create(&s390_virtio_bus_info, dev, "s390-virtio");
+    _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio");
     bus = DO_UPCAST(VirtIOS390Bus, bus, _bus);
 
     bus->dev_page = *ram_size;
@@ -314,20 +315,20 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
                                              ram_addr_t mem,
                                              int *vq_num)
 {
-    VirtIOS390Device *_dev;
-    DeviceState *dev;
+    BusChild *kid;
     int i;
 
-    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
-        _dev = (VirtIOS390Device *)dev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
+
         for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
-            if (!virtio_queue_get_addr(_dev->vdev, i))
+            if (!virtio_queue_get_addr(dev->vdev, i))
                 break;
-            if (virtio_queue_get_addr(_dev->vdev, i) == mem) {
+            if (virtio_queue_get_addr(dev->vdev, i) == mem) {
                 if (vq_num) {
                     *vq_num = i;
                 }
-                return _dev;
+                return dev;
             }
         }
     }
@@ -338,13 +339,12 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
 /* Find a device by device descriptor location */
 VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
 {
-    VirtIOS390Device *_dev;
-    DeviceState *dev;
+    BusChild *kid;
 
-    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
-        _dev = (VirtIOS390Device *)dev;
-        if (_dev->dev_offs == mem) {
-            return _dev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
+        if (dev->dev_offs == mem) {
+            return dev;
         }
     }
 
@@ -460,7 +460,7 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->init = s390_virtio_busdev_init;
-    dc->bus_info = &s390_virtio_bus_info;
+    dc->bus_type = TYPE_S390_VIRTIO_BUS;
     dc->unplug = qdev_simple_unplug_cb;
 }
 
@@ -521,6 +521,7 @@ static TypeInfo s390_virtio_bridge_info = {
 
 static void s390_virtio_register_types(void)
 {
+    type_register_static(&s390_virtio_bus_info);
     type_register_static(&virtio_s390_device_info);
     type_register_static(&s390_virtio_serial);
     type_register_static(&s390_virtio_blk);
index 4b99d02298f85d8af2dd6914cc95e1bcec6b60c4..4873134ae9051b18418922992701b28c9f33012c 100644 (file)
 #define VIRTIO_S390_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE)
 
+#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus"
+#define S390_VIRTIO_BUS(obj) \
+     OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS)
+
 typedef struct VirtIOS390Device VirtIOS390Device;
 
 typedef struct VirtIOS390DeviceClass {
index 4a798210ce36ceb55d998cab2da29cab46e29878..187bc903c1cab35ce7e4723518046ac15d7d27a1 100644 (file)
@@ -12,17 +12,26 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev);
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 static void scsi_req_dequeue(SCSIRequest *req);
 
-static struct BusInfo scsi_bus_info = {
-    .name  = "SCSI",
-    .size  = sizeof(SCSIBus),
-    .get_dev_path = scsibus_get_dev_path,
-    .get_fw_dev_path = scsibus_get_fw_dev_path,
-    .props = (Property[]) {
-        DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
-        DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
-        DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property scsi_props[] = {
+    DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
+    DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
+    DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scsi_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->get_dev_path = scsibus_get_dev_path;
+    k->get_fw_dev_path = scsibus_get_fw_dev_path;
+}
+
+static const TypeInfo scsi_bus_info = {
+    .name = TYPE_SCSI_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(SCSIBus),
+    .class_init = scsi_bus_class_init,
 };
 static int next_scsi_bus;
 
@@ -65,7 +74,7 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s)
 /* Create a scsi bus, and attach devices to it.  */
 void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
 {
-    qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
+    qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, NULL);
     bus->busnr = next_scsi_bus++;
     bus->info = info;
     bus->qbus.allow_hotplug = 1;
@@ -205,7 +214,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     if (bootindex >= 0) {
         qdev_prop_set_int32(dev, "bootindex", bootindex);
     }
-    if (qdev_prop_exists(dev, "removable")) {
+    if (object_property_find(OBJECT(dev), "removable", NULL)) {
         qdev_prop_set_bit(dev, "removable", removable);
     }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
@@ -306,7 +315,7 @@ static void store_lun(uint8_t *outbuf, int lun)
 
 static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     int i, len, n;
     int channel, id;
     bool found_lun0;
@@ -321,7 +330,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     id = r->req.dev->id;
     found_lun0 = false;
     n = 0;
-    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
@@ -343,7 +353,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     memset(r->buf, 0, len);
     stl_be_p(&r->buf, n);
     i = found_lun0 ? 8 : 16;
-    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
@@ -1452,12 +1463,10 @@ static char *scsibus_get_dev_path(DeviceState *dev)
 {
     SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
     DeviceState *hba = dev->parent_bus->parent;
-    char *id = NULL;
+    char *id;
     char *path;
 
-    if (hba && hba->parent_bus && hba->parent_bus->info->get_dev_path) {
-        id = hba->parent_bus->info->get_dev_path(hba);
-    }
+    id = qdev_get_dev_path(hba);
     if (id) {
         path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
     } else {
@@ -1480,10 +1489,11 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
 
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     SCSIDevice *target_dev = NULL;
 
-    QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
+    QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
@@ -1595,10 +1605,11 @@ const VMStateDescription vmstate_scsi_device = {
 static void scsi_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
-    k->bus_info = &scsi_bus_info;
+    k->bus_type = TYPE_SCSI_BUS;
     k->init     = scsi_qdev_init;
     k->unplug   = qdev_simple_unplug_cb;
     k->exit     = scsi_qdev_exit;
+    k->props    = scsi_props;
 }
 
 static TypeInfo scsi_device_type_info = {
@@ -1612,6 +1623,7 @@ static TypeInfo scsi_device_type_info = {
 
 static void scsi_register_types(void)
 {
+    type_register_static(&scsi_bus_info);
     type_register_static(&scsi_device_type_info);
 }
 
index 2eb66f7393a8352554577bc6bb0d243e18a0bab9..76f06d41de19228e63a70ec496c9a930aeedc84b 100644 (file)
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -136,6 +136,9 @@ struct SCSIBusInfo {
     void *(*load_request)(QEMUFile *f, SCSIRequest *req);
 };
 
+#define TYPE_SCSI_BUS "SCSI"
+#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
+
 struct SCSIBus {
     BusState qbus;
     int busnr;
index 25b400aa47865d056239e6496e03d304081bf1ca..97d417a99713cb56658c106afd6361f41fcf3198 100644 (file)
 static PCIDevice *find_dev(sPAPREnvironment *spapr,
                            uint64_t buid, uint32_t config_addr)
 {
-    DeviceState *qdev;
     int devfn = (config_addr >> 8) & 0xFF;
     sPAPRPHBState *phb;
 
     QLIST_FOREACH(phb, &spapr->phbs, list) {
+        BusChild *kid;
+
         if (phb->buid != buid) {
             continue;
         }
 
-        QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
-            PCIDevice *dev = (PCIDevice *)qdev;
+        QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
+            PCIDevice *dev = (PCIDevice *)kid->child;
             if (dev->devfn == devfn) {
                 return dev;
             }
index 315ab8091ccc200b8b0991fef6085ff5447782ec..c8271c626c55ce8982da7e205e3d9b8f6af66e79 100644 (file)
     do { } while (0)
 #endif
 
-static struct BusInfo spapr_vio_bus_info = {
-    .name       = "spapr-vio",
-    .size       = sizeof(VIOsPAPRBus),
-    .props = (Property[]) {
-        DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property spapr_vio_props[] = {
+    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const TypeInfo spapr_vio_bus_info = {
+    .name = TYPE_SPAPR_VIO_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VIOsPAPRBus),
 };
 
 VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *dev = NULL;
 
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
         if (dev->reg == reg) {
             return dev;
         }
@@ -604,7 +606,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
                          uint32_t nret, target_ulong rets)
 {
     VIOsPAPRBus *bus = spapr->vio_bus;
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *dev = NULL;
 
     if (nargs != 0) {
@@ -612,8 +614,8 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
         spapr_vio_quiesce_one(dev);
     }
 
@@ -623,7 +625,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
 static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
 {
     VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *other;
 
     /*
@@ -631,8 +633,8 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
      * using the requested address. We have to open code this because
      * the given dev might already be in the list.
      */
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
 
         if (other != dev && other->reg == dev->reg) {
             return other;
@@ -742,7 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
 
     /* Create bus on bridge device */
 
-    qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
+    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
     bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
     bus->next_reg = 0x1000;
 
@@ -794,7 +796,8 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = spapr_vio_busdev_init;
     k->reset = spapr_vio_busdev_reset;
-    k->bus_info = &spapr_vio_bus_info;
+    k->bus_type = TYPE_SPAPR_VIO_BUS;
+    k->props = spapr_vio_props;
 }
 
 static TypeInfo spapr_vio_type_info = {
@@ -808,6 +811,7 @@ static TypeInfo spapr_vio_type_info = {
 
 static void spapr_vio_register_types(void)
 {
+    type_register_static(&spapr_vio_bus_info);
     type_register_static(&spapr_vio_bridge_info);
     type_register_static(&spapr_vio_type_info);
 }
@@ -836,19 +840,20 @@ static int compare_reg(const void *p1, const void *p2)
 int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
 {
     DeviceState *qdev, **qdevs;
+    BusChild *kid;
     int i, num, ret = 0;
 
     /* Count qdevs on the bus list */
     num = 0;
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
         num++;
     }
 
     /* Copy out into an array of pointers */
     qdevs = g_malloc(sizeof(qdev) * num);
     num = 0;
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        qdevs[num++] = qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        qdevs[num++] = kid->child;
     }
 
     /* Sort the array */
index 87816e456d39998ecd6c7475b63e7ba7afe06a4c..2adad77d02759564abca4d4565a45572cc91c085 100644 (file)
@@ -40,6 +40,9 @@ enum VIOsPAPR_TCEAccess {
 #define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
 
+#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
+#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(VIOsPAPRBus, (obj), TYPE_SPAPR_VIO_BUS)
+
 struct VIOsPAPRDevice;
 
 typedef struct VIOsPAPR_RTCE {
index c9674f36a64d0f2cebdba2799c5d03cceb09112b..f340b83237dd11a7dc15eb1ccd6f4c4884c96753 100644 (file)
@@ -160,7 +160,7 @@ static TypeInfo spapr_vty_info = {
 VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
 {
     VIOsPAPRDevice *sdev, *selected;
-    DeviceState *iter;
+    BusChild *kid;
 
     /*
      * To avoid the console bouncing around we want one VTY to be
@@ -169,7 +169,9 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
      */
 
     selected = NULL;
-    QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        DeviceState *iter = kid->child;
+
         /* Only look at VTY devices */
         if (!object_dynamic_cast(OBJECT(iter), "spapr-vty")) {
             continue;
index 8f2d9bc0341c4aee6de9364a36fabfee86aca90a..e5f14a0cefdfdc1b1660f3126fab143754a3ce41 100644 (file)
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -16,9 +16,13 @@ struct SSIBus {
     BusState qbus;
 };
 
-static struct BusInfo ssi_bus_info = {
-    .name = "SSI",
-    .size = sizeof(SSIBus),
+#define TYPE_SSI_BUS "SSI"
+#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS)
+
+static const TypeInfo ssi_bus_info = {
+    .name = TYPE_SSI_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(SSIBus),
 };
 
 static int ssi_slave_init(DeviceState *dev)
@@ -26,10 +30,11 @@ static int ssi_slave_init(DeviceState *dev)
     SSISlave *s = SSI_SLAVE(dev);
     SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
     SSIBus *bus;
+    BusChild *kid;
 
     bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
-    if (QTAILQ_FIRST(&bus->qbus.children) != dev
-        || QTAILQ_NEXT(dev, sibling) != NULL) {
+    kid = QTAILQ_FIRST(&bus->qbus.children);
+    if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) {
         hw_error("Too many devices on SSI bus");
     }
 
@@ -40,7 +45,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     dc->init = ssi_slave_init;
-    dc->bus_info = &ssi_bus_info;
+    dc->bus_type = TYPE_SSI_BUS;
 }
 
 static TypeInfo ssi_slave_info = {
@@ -62,26 +67,28 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
 SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
 {
     BusState *bus;
-    bus = qbus_create(&ssi_bus_info, parent, name);
+    bus = qbus_create(TYPE_SSI_BUS, parent, name);
     return FROM_QBUS(SSIBus, bus);
 }
 
 uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
 {
-    DeviceState *dev;
+    BusChild *kid;
     SSISlave *slave;
     SSISlaveClass *ssc;
-    dev = QTAILQ_FIRST(&bus->qbus.children);
-    if (!dev) {
+
+    kid = QTAILQ_FIRST(&bus->qbus.children);
+    if (!kid) {
         return 0;
     }
-    slave = SSI_SLAVE(dev);
+    slave = SSI_SLAVE(kid->child);
     ssc = SSI_SLAVE_GET_CLASS(slave);
     return ssc->transfer(slave, val);
 }
 
 static void ssi_slave_register_types(void)
 {
+    type_register_static(&ssi_bus_info);
     type_register_static(&ssi_slave_info);
 }
 
index db4efccef40bbf6dca7d32ccd78bec2d2c5e21d0..9d8b1eaf7d8191d08267284f611fd4fafe5eb218 100644 (file)
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *sysbus_get_fw_dev_path(DeviceState *dev);
 
-struct BusInfo system_bus_info = {
-    .name       = "System",
-    .size       = sizeof(BusState),
-    .print_dev  = sysbus_dev_print,
-    .get_fw_dev_path = sysbus_get_fw_dev_path,
+static void system_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->print_dev = sysbus_dev_print;
+    k->get_fw_dev_path = sysbus_get_fw_dev_path;
+}
+
+static const TypeInfo system_bus_info = {
+    .name = TYPE_SYSTEM_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(BusState),
+    .class_init = system_bus_class_init,
 };
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
@@ -244,7 +252,7 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = sysbus_device_init;
-    k->bus_info = &system_bus_info;
+    k->bus_type = TYPE_SYSTEM_BUS;
 }
 
 static TypeInfo sysbus_device_type_info = {
@@ -256,8 +264,33 @@ static TypeInfo sysbus_device_type_info = {
     .class_init = sysbus_device_class_init,
 };
 
+/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
+static BusState *main_system_bus;
+
+static void main_system_bus_create(void)
+{
+    /* assign main_system_bus before qbus_create_inplace()
+     * in order to make "if (bus != sysbus_get_default())" work */
+    main_system_bus = g_malloc0(system_bus_info.instance_size);
+    qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL,
+                        "main-system-bus");
+    main_system_bus->glib_allocated = true;
+    object_property_add_child(container_get(qdev_get_machine(),
+                                            "/unattached"),
+                              "sysbus", OBJECT(main_system_bus), NULL);
+}
+
+BusState *sysbus_get_default(void)
+{
+    if (!main_system_bus) {
+        main_system_bus_create();
+    }
+    return main_system_bus;
+}
+
 static void sysbus_register_types(void)
 {
+    type_register_static(&system_bus_info);
     type_register_static(&sysbus_device_type_info);
 }
 
index 22555cd443bbfb9dc7db1f0df36fe3719015d649..acfbcfba52945115be6dae4a534085d2f912005f 100644 (file)
@@ -10,6 +10,9 @@
 #define QDEV_MAX_PIO 32
 #define QDEV_MAX_IRQ 512
 
+#define TYPE_SYSTEM_BUS "System"
+#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
+
 typedef struct SysBusDevice SysBusDevice;
 
 #define TYPE_SYS_BUS_DEVICE "sys-bus-device"
index ae7ccda18cc08378ce89985280c8ebd82e47c413..2a56fe554f662f47beff1d2433280b212dc5f3a8 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -421,6 +421,9 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
 
 /* usb-bus.c */
 
+#define TYPE_USB_BUS "usb-bus"
+#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS)
+
 struct USBBus {
     BusState qbus;
     USBBusOps *ops;
index 2068640a58bcdf57d9d0f47f411d720c06863fad..f87cc5f443901677b8ce56520c98d85c9affe8ff 100644 (file)
@@ -11,19 +11,29 @@ static char *usb_get_dev_path(DeviceState *dev);
 static char *usb_get_fw_dev_path(DeviceState *qdev);
 static int usb_qdev_exit(DeviceState *qdev);
 
-static struct BusInfo usb_bus_info = {
-    .name      = "USB",
-    .size      = sizeof(USBBus),
-    .print_dev = usb_bus_dev_print,
-    .get_dev_path = usb_get_dev_path,
-    .get_fw_dev_path = usb_get_fw_dev_path,
-    .props      = (Property[]) {
-        DEFINE_PROP_STRING("port", USBDevice, port_path),
-        DEFINE_PROP_BIT("full-path", USBDevice, flags,
-                        USB_DEV_FLAG_FULL_PATH, true),
-        DEFINE_PROP_END_OF_LIST()
-    },
+static Property usb_props[] = {
+    DEFINE_PROP_STRING("port", USBDevice, port_path),
+    DEFINE_PROP_BIT("full-path", USBDevice, flags,
+                    USB_DEV_FLAG_FULL_PATH, true),
+    DEFINE_PROP_END_OF_LIST()
 };
+
+static void usb_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->print_dev = usb_bus_dev_print;
+    k->get_dev_path = usb_get_dev_path;
+    k->get_fw_dev_path = usb_get_fw_dev_path;
+}
+
+static const TypeInfo usb_bus_info = {
+    .name = TYPE_USB_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(USBBus),
+    .class_init = usb_bus_class_init,
+};
+
 static int next_usb_bus = 0;
 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
 
@@ -45,7 +55,7 @@ const VMStateDescription vmstate_usb_device = {
 
 void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
 {
-    qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
+    qbus_create_inplace(&bus->qbus, TYPE_USB_BUS, host, NULL);
     bus->ops = ops;
     bus->busnr = next_usb_bus++;
     bus->qbus.allow_hotplug = 1; /* Yes, we can */
@@ -465,9 +475,8 @@ static char *usb_get_dev_path(DeviceState *qdev)
     DeviceState *hcd = qdev->parent_bus->parent;
     char *id = NULL;
 
-    if ((dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) &&
-        hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
-        id = hcd->parent_bus->info->get_dev_path(hcd);
+    if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
+        id = qdev_get_dev_path(hcd);
     }
     if (id) {
         char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
@@ -576,10 +585,11 @@ USBDevice *usbdevice_create(const char *cmdline)
 static void usb_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
-    k->bus_info = &usb_bus_info;
+    k->bus_type = TYPE_USB_BUS;
     k->init     = usb_qdev_init;
     k->unplug   = qdev_simple_unplug_cb;
     k->exit     = usb_qdev_exit;
+    k->props    = usb_props;
 }
 
 static TypeInfo usb_device_type_info = {
@@ -593,6 +603,7 @@ static TypeInfo usb_device_type_info = {
 
 static void usb_register_types(void)
 {
+    type_register_static(&usb_bus_info);
     type_register_static(&usb_device_type_info);
 }
 
index e8a3c6af3da68f0e95253fbd5fc8f37797c98f00..0a9d3c9f6055b007c25bd6eda38cec442a1b1d98 100644 (file)
@@ -432,12 +432,13 @@ void usb_desc_create_serial(USBDevice *dev)
     const USBDesc *desc = usb_device_get_usb_desc(dev);
     int index = desc->id.iSerialNumber;
     char serial[64];
+    char *path;
     int dst;
 
     assert(index != 0 && desc->str[index] != NULL);
     dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
-    if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
-        char *path = hcd->parent_bus->info->get_dev_path(hcd);
+    path = qdev_get_dev_path(hcd);
+    if (path) {
         dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
     }
     dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
index 3b7604e8b1391387ece8284ff27483fb0e0f56f8..6cf4a1aeaa22bc75e80f1e8b27f2cd07dc7d2b21 100644 (file)
@@ -1055,13 +1055,18 @@ static Answer *ccid_peek_next_answer(USBCCIDState *s)
         : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
 }
 
-static struct BusInfo ccid_bus_info = {
-    .name = "ccid-bus",
-    .size = sizeof(CCIDBus),
-    .props = (Property[]) {
-        DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
+static Property ccid_props[] = {
+    DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+#define TYPE_CCID_BUS "ccid-bus"
+#define CCID_BUS(obj) OBJECT_CHECK(CCIDBus, (obj), TYPE_CCID_BUS)
+
+static const TypeInfo ccid_bus_info = {
+    .name = TYPE_CCID_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(CCIDBus),
 };
 
 void ccid_card_send_apdu_to_guest(CCIDCardState *card,
@@ -1191,7 +1196,7 @@ static int ccid_initfn(USBDevice *dev)
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
-    qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
+    qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
     s->bus.qbus.allow_hotplug = 1;
     s->card = NULL;
@@ -1342,9 +1347,10 @@ static TypeInfo ccid_info = {
 static void ccid_card_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
-    k->bus_info = &ccid_bus_info;
+    k->bus_type = TYPE_CCID_BUS;
     k->init = ccid_card_init;
     k->exit = ccid_card_exit;
+    k->props = ccid_props;
 }
 
 static TypeInfo ccid_card_type_info = {
@@ -1358,6 +1364,7 @@ static TypeInfo ccid_card_type_info = {
 
 static void ccid_register_types(void)
 {
+    type_register_static(&ccid_bus_info);
     type_register_static(&ccid_card_type_info);
     type_register_static(&ccid_info);
     usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
index 5e39ce93c46c345115b01d0db5a96e8f149f19c1..e1a767ea78d4d7285a0a7acfa39e24ee1ab66474 100644 (file)
@@ -275,7 +275,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
     SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
     SCSIRequest *r, *next;
-    DeviceState *qdev;
+    BusChild *kid;
     int target;
 
     /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
@@ -346,8 +346,8 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
     case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
         target = req->req.tmf->lun[1];
         s->resetting++;
-        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
-             d = DO_UPCAST(SCSIDevice, qdev, qdev);
+        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+             d = DO_UPCAST(SCSIDevice, qdev, kid->child);
              if (d->channel == 0 && d->id == target) {
                 qdev_reset_all(&d->qdev);
              }
index 72287d10ce45d378e1515d8d1c7392cb6a8ca986..96382a4ea164a176e5851852110aa788e8293d8a 100644 (file)
@@ -728,15 +728,27 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
 static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
 
-static struct BusInfo virtser_bus_info = {
-    .name      = "virtio-serial-bus",
-    .size      = sizeof(VirtIOSerialBus),
-    .print_dev = virtser_bus_dev_print,
-    .props      = (Property[]) {
-        DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
-        DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
-        DEFINE_PROP_END_OF_LIST()
-    }
+static Property virtser_props[] = {
+    DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
+    DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
+#define VIRTIO_SERIAL_BUS(obj) \
+      OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)
+
+static void virtser_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+    k->print_dev = virtser_bus_dev_print;
+}
+
+static const TypeInfo virtser_bus_info = {
+    .name = TYPE_VIRTIO_SERIAL_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VirtIOSerialBus),
+    .class_init = virtser_bus_class_init,
 };
 
 static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
@@ -904,7 +916,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
 
     /* Spawn a new virtio-serial bus on which the ports will ride as devices */
-    qbus_create_inplace(&vser->bus.qbus, &virtser_bus_info, dev, NULL);
+    qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, dev, NULL);
     vser->bus.qbus.allow_hotplug = 1;
     vser->bus.vser = vser;
     QTAILQ_INIT(&vser->ports);
@@ -980,9 +992,10 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = virtser_port_qdev_init;
-    k->bus_info = &virtser_bus_info;
+    k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
     k->exit = virtser_port_qdev_exit;
     k->unplug = qdev_simple_unplug_cb;
+    k->props = virtser_props;
 }
 
 static TypeInfo virtio_serial_port_type_info = {
@@ -996,6 +1009,7 @@ static TypeInfo virtio_serial_port_type_info = {
 
 static void virtio_serial_register_types(void)
 {
+    type_register_static(&virtser_bus_info);
     type_register_static(&virtio_serial_port_type_info);
 }
 
index d93b77293f10e3eee2bfb37421bb644dcd279b3e..8b17776bb332aa2464a3c7df33d0c86fcab59d99 100644 (file)
@@ -33,7 +33,7 @@ typedef struct TypeInfo TypeInfo;
 typedef struct InterfaceClass InterfaceClass;
 typedef struct InterfaceInfo InterfaceInfo;
 
-#define TYPE_OBJECT NULL
+#define TYPE_OBJECT "object"
 
 /**
  * SECTION:object.h
@@ -291,10 +291,15 @@ struct Object
  *   has occurred to allow a class to set its default virtual method pointers.
  *   This is also the function to use to override virtual methods from a parent
  *   class.
+ * @class_base_init: This function is called for all base classes after all
+ *   parent class initialization has occurred, but before the class itself
+ *   is initialized.  This is the function to use to undo the effects of
+ *   memcpy from the parent class to the descendents.
  * @class_finalize: This function is called during class destruction and is
  *   meant to release and dynamic parameters allocated by @class_init.
- * @class_data: Data to pass to the @class_init and @class_finalize functions.
- *   This can be useful when building dynamic classes.
+ * @class_data: Data to pass to the @class_init, @class_base_init and
+ *   @class_finalize functions.  This can be useful when building dynamic
+ *   classes.
  * @interfaces: The list of interfaces associated with this type.  This
  *   should point to a static array that's terminated with a zero filled
  *   element.
@@ -312,6 +317,7 @@ struct TypeInfo
     size_t class_size;
 
     void (*class_init)(ObjectClass *klass, void *data);
+    void (*class_base_init)(ObjectClass *klass, void *data);
     void (*class_finalize)(ObjectClass *klass, void *data);
     void *class_data;
 
@@ -521,8 +527,6 @@ const char *object_get_typename(Object *obj);
  */
 Type type_register_static(const TypeInfo *info);
 
-#define type_register_static_alias(info, name) do { } while (0)
-
 /**
  * type_register:
  * @info: The #TypeInfo of the new type
@@ -547,6 +551,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *klass,
 ObjectClass *object_class_dynamic_cast(ObjectClass *klass,
                                        const char *typename);
 
+/**
+ * object_class_get_parent:
+ * @klass: The class to obtain the parent for.
+ *
+ * Returns: The parent for @klass or %NULL if none.
+ */
+ObjectClass *object_class_get_parent(ObjectClass *klass);
+
 /**
  * object_class_get_name:
  * @klass: The class to obtain the QOM typename for.
@@ -623,6 +635,17 @@ void object_property_add(Object *obj, const char *name, const char *type,
 
 void object_property_del(Object *obj, const char *name, struct Error **errp);
 
+/**
+ * object_property_find:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Look up a property for an object and return its #ObjectProperty if found.
+ */
+ObjectProperty *object_property_find(Object *obj, const char *name,
+                                     struct Error **errp);
+
 void object_unparent(Object *obj);
 
 /**
@@ -909,6 +932,20 @@ void object_property_add_str(Object *obj, const char *name,
                              void (*set)(Object *, const char *, struct Error **),
                              struct Error **errp);
 
+/**
+ * object_child_foreach:
+ * @obj: the object whose children will be navigated
+ * @fn: the iterator function to be called
+ * @opaque: an opaque value that will be passed to the iterator
+ *
+ * Call @fn passing each child of @obj and @opaque to it, until @fn returns
+ * non-zero.
+ *
+ * Returns: The last value returned by @fn, or 0 if there is no child.
+ */
+int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
+                         void *opaque);
+
 /**
  * container_get:
  * @root: root of the #path, e.g., object_get_root()
index 6f839ad8c950a6dd2b6e75adc3704545660a72b3..00bb3b029cb800b95ca6e0c4a706c72c5bf6135b 100644 (file)
@@ -45,6 +45,7 @@ struct TypeImpl
     size_t instance_size;
 
     void (*class_init)(ObjectClass *klass, void *data);
+    void (*class_base_init)(ObjectClass *klass, void *data);
     void (*class_finalize)(ObjectClass *klass, void *data);
 
     void *class_data;
@@ -94,7 +95,7 @@ static TypeImpl *type_table_lookup(const char *name)
     return g_hash_table_lookup(type_table_get(), name);
 }
 
-TypeImpl *type_register(const TypeInfo *info)
+static TypeImpl *type_register_internal(const TypeInfo *info)
 {
     TypeImpl *ti = g_malloc0(sizeof(*ti));
 
@@ -112,6 +113,7 @@ TypeImpl *type_register(const TypeInfo *info)
     ti->instance_size = info->instance_size;
 
     ti->class_init = info->class_init;
+    ti->class_base_init = info->class_base_init;
     ti->class_finalize = info->class_finalize;
     ti->class_data = info->class_data;
 
@@ -135,6 +137,12 @@ TypeImpl *type_register(const TypeInfo *info)
     return ti;
 }
 
+TypeImpl *type_register(const TypeInfo *info)
+{
+    assert(info->parent);
+    return type_register_internal(info);
+}
+
 TypeImpl *type_register_static(const TypeInfo *info)
 {
     return type_register(info);
@@ -202,13 +210,13 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
     char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
 
     info.name = name;
-    iface->type = type_register(&info);
+    iface->type = type_register_internal(&info);
     g_free(name);
 }
 
 static void type_initialize(TypeImpl *ti)
 {
-    size_t class_size = sizeof(ObjectClass);
+    TypeImpl *parent;
     int i;
 
     if (ti->class) {
@@ -219,22 +227,23 @@ static void type_initialize(TypeImpl *ti)
     ti->instance_size = type_object_get_size(ti);
 
     ti->class = g_malloc0(ti->class_size);
-    ti->class->type = ti;
-
-    if (type_has_parent(ti)) {
-        TypeImpl *parent = type_get_parent(ti);
 
+    parent = type_get_parent(ti);
+    if (parent) {
         type_initialize(parent);
 
-        class_size = parent->class_size;
         g_assert(parent->class_size <= ti->class_size);
-
-        memcpy((void *)ti->class + sizeof(ObjectClass),
-               (void *)parent->class + sizeof(ObjectClass),
-               parent->class_size - sizeof(ObjectClass));
+        memcpy(ti->class, parent->class, parent->class_size);
     }
 
-    memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
+    ti->class->type = ti;
+
+    while (parent) {
+        if (parent->class_base_init) {
+            parent->class_base_init(ti->class, ti->class_data);
+        }
+        parent = type_get_parent(parent);
+    }
 
     for (i = 0; i < ti->num_interfaces; i++) {
         type_class_interface_init(ti, &ti->interfaces[i]);
@@ -296,6 +305,16 @@ void object_initialize(void *data, const char *typename)
     object_initialize_with_type(data, type);
 }
 
+static inline bool object_property_is_child(ObjectProperty *prop)
+{
+    return strstart(prop->type, "child<", NULL);
+}
+
+static inline bool object_property_is_link(ObjectProperty *prop)
+{
+    return strstart(prop->type, "link<", NULL);
+}
+
 static void object_property_del_all(Object *obj)
 {
     while (!QTAILQ_EMPTY(&obj->properties)) {
@@ -318,7 +337,7 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
     ObjectProperty *prop;
 
     QTAILQ_FOREACH(prop, &obj->properties, node) {
-        if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
+        if (object_property_is_child(prop) && prop->opaque == child) {
             object_property_del(obj, prop->name, errp);
             break;
         }
@@ -458,19 +477,6 @@ Object *object_dynamic_cast(Object *obj, const char *typename)
 }
 
 
-static void register_types(void)
-{
-    static TypeInfo interface_info = {
-        .name = TYPE_INTERFACE,
-        .instance_size = sizeof(Interface),
-        .abstract = true,
-    };
-
-    type_interface = type_register_static(&interface_info);
-}
-
-type_init(register_types)
-
 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
 {
     Object *inst;
@@ -545,6 +551,19 @@ ObjectClass *object_class_by_name(const char *typename)
     return type->class;
 }
 
+ObjectClass *object_class_get_parent(ObjectClass *class)
+{
+    TypeImpl *type = type_get_parent(class->type);
+
+    if (!type) {
+        return NULL;
+    }
+
+    type_initialize(type);
+
+    return type->class;
+}
+
 typedef struct OCFData
 {
     void (*fn)(ObjectClass *klass, void *opaque);
@@ -584,6 +603,23 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
 }
 
+int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
+                         void *opaque)
+{
+    ObjectProperty *prop;
+    int ret = 0;
+
+    QTAILQ_FOREACH(prop, &obj->properties, node) {
+        if (object_property_is_child(prop)) {
+            ret = fn(prop->opaque, opaque);
+            if (ret != 0) {
+                break;
+            }
+        }
+    }
+    return ret;
+}
+
 static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
 {
     GSList **list = opaque;
@@ -636,7 +672,8 @@ void object_property_add(Object *obj, const char *name, const char *type,
     QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
 }
 
-static ObjectProperty *object_property_find(Object *obj, const char *name)
+ObjectProperty *object_property_find(Object *obj, const char *name,
+                                     Error **errp)
 {
     ObjectProperty *prop;
 
@@ -646,16 +683,22 @@ static ObjectProperty *object_property_find(Object *obj, const char *name)
         }
     }
 
+    error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
     return NULL;
 }
 
 void object_property_del(Object *obj, const char *name, Error **errp)
 {
-    ObjectProperty *prop = object_property_find(obj, name);
+    ObjectProperty *prop = object_property_find(obj, name, errp);
+    if (prop == NULL) {
+        return;
+    }
 
-    QTAILQ_REMOVE(&obj->properties, prop, node);
+    if (prop->release) {
+        prop->release(obj, name, prop->opaque);
+    }
 
-    prop->release(obj, prop->name, prop->opaque);
+    QTAILQ_REMOVE(&obj->properties, prop, node);
 
     g_free(prop->name);
     g_free(prop->type);
@@ -665,10 +708,8 @@ void object_property_del(Object *obj, const char *name, Error **errp)
 void object_property_get(Object *obj, Visitor *v, const char *name,
                          Error **errp)
 {
-    ObjectProperty *prop = object_property_find(obj, name);
-
+    ObjectProperty *prop = object_property_find(obj, name, errp);
     if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
         return;
     }
 
@@ -682,10 +723,8 @@ void object_property_get(Object *obj, Visitor *v, const char *name,
 void object_property_set(Object *obj, Visitor *v, const char *name,
                          Error **errp)
 {
-    ObjectProperty *prop = object_property_find(obj, name);
-
+    ObjectProperty *prop = object_property_find(obj, name, errp);
     if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
         return;
     }
 
@@ -838,10 +877,8 @@ char *object_property_print(Object *obj, const char *name,
 
 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
 {
-    ObjectProperty *prop = object_property_find(obj, name);
-
+    ObjectProperty *prop = object_property_find(obj, name, errp);
     if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
         return NULL;
     }
 
@@ -995,7 +1032,7 @@ gchar *object_get_canonical_path(Object *obj)
         g_assert(obj->parent != NULL);
 
         QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
-            if (!strstart(prop->type, "child<", NULL)) {
+            if (!object_property_is_child(prop)) {
                 continue;
             }
 
@@ -1024,14 +1061,14 @@ gchar *object_get_canonical_path(Object *obj)
 
 Object *object_resolve_path_component(Object *parent, gchar *part)
 {
-    ObjectProperty *prop = object_property_find(parent, part);
+    ObjectProperty *prop = object_property_find(parent, part, NULL);
     if (prop == NULL) {
         return NULL;
     }
 
-    if (strstart(prop->type, "link<", NULL)) {
+    if (object_property_is_link(prop)) {
         return *(Object **)prop->opaque;
-    } else if (strstart(prop->type, "child<", NULL)) {
+    } else if (object_property_is_child(prop)) {
         return prop->opaque;
     } else {
         return NULL;
@@ -1074,7 +1111,7 @@ static Object *object_resolve_partial_path(Object *parent,
     QTAILQ_FOREACH(prop, &parent->properties, node) {
         Object *found;
 
-        if (!strstart(prop->type, "child<", NULL)) {
+        if (!object_property_is_child(prop)) {
             continue;
         }
 
@@ -1194,3 +1231,34 @@ void object_property_add_str(Object *obj, const char *name,
                         property_release_str,
                         prop, errp);
 }
+
+static char *qdev_get_type(Object *obj, Error **errp)
+{
+    return g_strdup(object_get_typename(obj));
+}
+
+static void object_instance_init(Object *obj)
+{
+    object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
+}
+
+static void register_types(void)
+{
+    static TypeInfo interface_info = {
+        .name = TYPE_INTERFACE,
+        .instance_size = sizeof(Interface),
+        .abstract = true,
+    };
+
+    static TypeInfo object_info = {
+        .name = TYPE_OBJECT,
+        .instance_size = sizeof(Object),
+        .instance_init = object_instance_init,
+        .abstract = true,
+    };
+
+    type_interface = type_register_internal(&interface_info);
+    type_register_internal(&object_info);
+}
+
+type_init(register_types)
index 2b6833d5f59506c8880eaf841aebbc5015d35b31..faa81457d5f657b711f9d8f5ff0b08a173c1001f 100644 (file)
--- a/savevm.c
+++ b/savevm.c
@@ -1248,8 +1248,8 @@ int register_savevm_live(DeviceState *dev,
         se->is_ram = 1;
     }
 
-    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
-        char *id = dev->parent_bus->info->get_dev_path(dev);
+    if (dev) {
+        char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);
             pstrcat(se->idstr, sizeof(se->idstr), "/");
@@ -1292,8 +1292,8 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
     SaveStateEntry *se, *new_se;
     char id[256] = "";
 
-    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
-        char *path = dev->parent_bus->info->get_dev_path(dev);
+    if (dev) {
+        char *path = qdev_get_dev_path(dev);
         if (path) {
             pstrcpy(id, sizeof(id), path);
             pstrcat(id, sizeof(id), "/");
@@ -1334,8 +1334,8 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->alias_id = alias_id;
     se->no_migrate = vmsd->unmigratable;
 
-    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
-        char *id = dev->parent_bus->info->get_dev_path(dev);
+    if (dev) {
+        char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);
             pstrcat(se->idstr, sizeof(se->idstr), "/");