From 0d936928ef87ca1bb7b41b5b89c400c699a7691c Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 2 May 2012 09:00:20 +0200 Subject: [PATCH] qdev: Convert busses to QEMU Object Model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is far less interesting than it sounds. We simply add an Object to each BusState and then register the types appropriately. Most of the interesting refactoring will follow in the next patches. Since we're changing fundamental type names (BusInfo -> BusClass), it all needs to convert at once. Fortunately, not a lot of code is affected. Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini [AF: Made all new bus TypeInfos static const.] [AF: Made qbus_free() call object_delete(), required {qom,glib}_allocated] Signed-off-by: Andreas Färber --- hw/i2c.c | 15 ++++--- hw/ide/internal.h | 3 ++ hw/ide/qdev.c | 21 +++++++--- hw/intel-hda.c | 12 +++--- hw/intel-hda.h | 3 ++ hw/isa-bus.c | 23 +++++++---- hw/isa.h | 3 ++ hw/pci-hotplug.c | 6 +-- hw/pci.c | 29 +++++++++----- hw/pci_bridge.c | 2 +- hw/pci_internals.h | 3 +- hw/qdev-monitor.c | 33 ++++++++++------ hw/qdev.c | 73 +++++++++++++++++++++++++---------- hw/qdev.h | 46 ++++++++++++---------- hw/s390-virtio-bus.c | 12 +++--- hw/s390-virtio-bus.h | 4 ++ hw/scsi-bus.c | 23 +++++++---- hw/scsi.h | 3 ++ hw/spapr_vio.c | 12 +++--- hw/spapr_vio.h | 3 ++ hw/ssi.c | 15 ++++--- hw/sysbus.c | 27 ++++++++----- hw/sysbus.h | 3 ++ hw/usb.h | 3 ++ hw/usb/bus.c | 25 ++++++++---- hw/usb/dev-smartcard-reader.c | 15 ++++--- hw/virtio-serial-bus.c | 24 +++++++++--- 27 files changed, 299 insertions(+), 142 deletions(-) diff --git a/hw/i2c.c b/hw/i2c.c index af5979e65d..319b249da3 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -22,9 +22,13 @@ static Property i2c_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo i2c_bus_info = { - .name = "I2C", - .size = sizeof(i2c_bus), +#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) @@ -62,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; } @@ -219,7 +223,7 @@ 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; } @@ -234,6 +238,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); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index f8a027d0e4..1a02f57bf5 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -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 diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index a91e878ca2..c122395401 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -32,15 +32,23 @@ static Property ide_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo ide_bus_info = { - .name = "IDE", - .size = sizeof(IDEBus), - .get_fw_dev_path = idebus_get_fw_dev_path, +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; } @@ -249,7 +257,7 @@ 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; } @@ -264,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); diff --git a/hw/intel-hda.c b/hw/intel-hda.c index e2bd41eb66..e343096534 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -34,16 +34,17 @@ static Property hda_props[] = { DEFINE_PROP_END_OF_LIST() }; -static struct BusInfo hda_codec_bus_info = { - .name = "HDA", - .size = sizeof(HDACodecBus), +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; } @@ -1276,7 +1277,7 @@ 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; } @@ -1291,6 +1292,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); } diff --git a/hw/intel-hda.h b/hw/intel-hda.h index a1cca5b1bb..22e0968d50 100644 --- a/hw/intel-hda.h +++ b/hw/intel-hda.h @@ -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; diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 5a43f03a7c..f9b237387a 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -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); } diff --git a/hw/isa.h b/hw/isa.h index f7bc4b5a95..f7ddf23628 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -19,6 +19,9 @@ typedef struct ISADevice ISADevice; #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); diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index 61257f457b..e7fb780a08 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -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 diff --git a/hw/pci.c b/hw/pci.c index 09ce4e7698..d6ce9a54fa 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -55,13 +55,21 @@ static Property pci_props[] = { DEFINE_PROP_END_OF_LIST() }; -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, +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); @@ -266,7 +274,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; @@ -287,7 +295,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; @@ -2001,7 +2009,7 @@ 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; } @@ -2016,6 +2024,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); } diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 866f0b6c52..253e034981 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -324,7 +324,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; diff --git a/hw/pci_internals.h b/hw/pci_internals.h index 96690b72d3..399c6d475c 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -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; diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 390d467e89..691b864c54 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -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)); @@ -262,7 +262,7 @@ 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; BusState *child, *ret; @@ -271,7 +271,8 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, 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) { @@ -280,7 +281,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, QTAILQ_FOREACH(dev, &bus->children, sibling) { 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; } @@ -415,16 +416,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; } } @@ -497,6 +498,15 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, } } +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; @@ -515,8 +525,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent); class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); - if (dev->parent_bus->info->print_dev) - dev->parent_bus->info->print_dev(mon, dev, indent); + bus_print_dev(dev->parent_bus, mon, dev, indent + 2); QLIST_FOREACH(child, &dev->child_bus, sibling) { qbus_print(mon, child, indent); } @@ -528,7 +537,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent) qdev_printf("bus: %s\n", bus->name); indent += 2; - qdev_printf("type %s\n", bus->info->name); + qdev_printf("type %s\n", object_get_typename(OBJECT(bus))); QTAILQ_FOREACH(dev, &bus->children, sibling) { qdev_print(mon, dev, indent); } diff --git a/hw/qdev.c b/hw/qdev.c index 7816a3776a..63012b5252 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -81,7 +81,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); } @@ -186,8 +186,9 @@ static int qdev_reset_one(DeviceState *dev, void *opaque) 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; } @@ -370,13 +371,13 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id) return NULL; } -void qbus_create_inplace(BusState *bus, BusInfo *info, - DeviceState *parent, const char *name) +/* FIXME move this logic into instance_init */ +static void do_qbus_create_inplace(BusState *bus, const char *typename, + DeviceState *parent, const char *name) { char *buf; int i,len; - bus->info = info; bus->parent = parent; if (name) { @@ -390,9 +391,9 @@ void qbus_create_inplace(BusState *bus, BusInfo *info, 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, + len = snprintf(buf, len, "%s.%d", typename, parent ? parent->num_child_bus : 0); for (i = 0; i < len; i++) buf[i] = qemu_tolower(buf[i]); @@ -410,13 +411,20 @@ void qbus_create_inplace(BusState *bus, BusInfo *info, } } -BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name) +void qbus_create_inplace(BusState *bus, const char *typename, + DeviceState *parent, const char *name) +{ + object_initialize(bus, typename); + do_qbus_create_inplace(bus, typename, parent, name); +} + +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) { BusState *bus; - bus = g_malloc0(info->size); - bus->qdev_allocated = 1; - qbus_create_inplace(bus, info, parent, name); + bus = BUS(object_new(typename)); + bus->qom_allocated = true; + do_qbus_create_inplace(bus, typename, parent, name); return bus; } @@ -435,11 +443,27 @@ void qbus_free(BusState *bus) qemu_unregister_reset(qbus_reset_all_fn, bus); } g_free((void*)bus->name); - if (bus->qdev_allocated) { - g_free(bus); + if (bus->qom_allocated) { + object_delete(OBJECT(bus)); + } else { + object_finalize(OBJECT(bus)); + if (bus->glib_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) { int l = 0; @@ -447,8 +471,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 { @@ -474,15 +498,15 @@ char* qdev_get_fw_dev_path(DeviceState *dev) char *qdev_get_dev_path(DeviceState *dev) { - BusInfo *businfo; + BusClass *bc; if (!dev || !dev->parent_bus) { return NULL; } - businfo = dev->parent_bus->info; - if (businfo->get_dev_path) { - return businfo->get_dev_path(dev); + bc = BUS_GET_CLASS(dev->parent_bus); + if (bc->get_dev_path) { + return bc->get_dev_path(dev); } return NULL; @@ -700,8 +724,17 @@ static TypeInfo device_type_info = { .class_size = sizeof(DeviceClass), }; +static const TypeInfo bus_info = { + .name = TYPE_BUS, + .parent = TYPE_OBJECT, + .instance_size = sizeof(BusState), + .abstract = true, + .class_size = sizeof(BusClass), +}; + static void qdev_register_types(void) { + type_register_static(&bus_info); type_register_static(&device_type_info); } diff --git a/hw/qdev.h b/hw/qdev.h index 013ccf2b7a..736271ecef 100644 --- 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 @@ -79,31 +79,40 @@ struct DeviceState { 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; +#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); }; +/** + * 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; + bool qom_allocated; + bool glib_allocated; QTAILQ_HEAD(ChildrenHead, DeviceState) children; QLIST_ENTRY(BusState) sibling; }; @@ -174,9 +183,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. */ @@ -317,9 +326,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. diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 23ef35b3bb..2aec756da1 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -45,9 +45,10 @@ #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; @@ -460,7 +461,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 +522,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); diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h index 4b99d02298..4873134ae9 100644 --- a/hw/s390-virtio-bus.h +++ b/hw/s390-virtio-bus.h @@ -52,6 +52,10 @@ #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 { diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index e79bb54a9d..276c794f47 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -19,11 +19,19 @@ static Property scsi_props[] = { DEFINE_PROP_END_OF_LIST(), }; -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, +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; @@ -66,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; @@ -1594,7 +1602,7 @@ 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; @@ -1612,6 +1620,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); } diff --git a/hw/scsi.h b/hw/scsi.h index 2eb66f7393..76f06d41de 100644 --- 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; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index cf849529dc..b7611ff865 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -54,9 +54,10 @@ static Property spapr_vio_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo spapr_vio_bus_info = { - .name = "spapr-vio", - .size = sizeof(VIOsPAPRBus), +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) @@ -743,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; @@ -795,7 +796,7 @@ 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; } @@ -810,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); } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 87816e456d..2adad77d02 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -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 { diff --git a/hw/ssi.c b/hw/ssi.c index 8f2d9bc034..8db99c29e4 100644 --- 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) @@ -40,7 +44,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,7 +66,7 @@ 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); } @@ -82,6 +86,7 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val) static void ssi_slave_register_types(void) { + type_register_static(&ssi_bus_info); type_register_static(&ssi_slave_info); } diff --git a/hw/sysbus.c b/hw/sysbus.c index fe5c4212ff..2347f510bd 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -24,11 +24,19 @@ 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 = { @@ -263,10 +271,10 @@ 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.size); - main_system_bus->qdev_allocated = 1; - qbus_create_inplace(main_system_bus, &system_bus_info, NULL, + 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; } BusState *sysbus_get_default(void) @@ -279,6 +287,7 @@ BusState *sysbus_get_default(void) static void sysbus_register_types(void) { + type_register_static(&system_bus_info); type_register_static(&sysbus_device_type_info); } diff --git a/hw/sysbus.h b/hw/sysbus.h index 22555cd443..acfbcfba52 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -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" diff --git a/hw/usb.h b/hw/usb.h index ae7ccda18c..2a56fe554f 100644 --- 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; diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 8b08f93389..f87cc5f443 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -18,12 +18,20 @@ static Property usb_props[] = { DEFINE_PROP_END_OF_LIST() }; -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, +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; @@ -47,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 */ @@ -577,7 +585,7 @@ 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; @@ -595,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); } diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index a4ab6e589a..6cf4a1aeaa 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1060,9 +1060,13 @@ static Property ccid_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo ccid_bus_info = { - .name = "ccid-bus", - .size = sizeof(CCIDBus), +#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, @@ -1192,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; @@ -1343,7 +1347,7 @@ 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; @@ -1360,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); diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index d47d870594..96382a4ea1 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -734,10 +734,21 @@ static Property virtser_props[] = { DEFINE_PROP_END_OF_LIST() }; -static struct BusInfo virtser_bus_info = { - .name = "virtio-serial-bus", - .size = sizeof(VirtIOSerialBus), - .print_dev = virtser_bus_dev_print, +#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) @@ -905,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); @@ -981,7 +992,7 @@ 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; @@ -998,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); }