diff --git a/hw/i2c.c b/hw/i2c.c index cb10b1dec6..af5979e65d 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -25,7 +25,6 @@ static Property i2c_props[] = { static struct BusInfo i2c_bus_info = { .name = "I2C", .size = sizeof(i2c_bus), - .props = i2c_props, }; static void i2c_bus_pre_save(void *opaque) @@ -221,6 +220,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->props = i2c_props; } static TypeInfo i2c_slave_type_info = { diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b67df3d1e6..a91e878ca2 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -36,7 +36,6 @@ static struct BusInfo ide_bus_info = { .name = "IDE", .size = sizeof(IDEBus), .get_fw_dev_path = idebus_get_fw_dev_path, - .props = ide_props, }; void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id) @@ -251,6 +250,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->props = ide_props; } static TypeInfo ide_device_type_info = { diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 0994f6b2a5..e2bd41eb66 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -37,7 +37,6 @@ static Property hda_props[] = { static struct BusInfo hda_codec_bus_info = { .name = "HDA", .size = sizeof(HDACodecBus), - .props = hda_props, }; void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, @@ -1278,6 +1277,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data) k->init = hda_codec_dev_init; k->exit = hda_codec_dev_exit; k->bus_info = &hda_codec_bus_info; + k->props = hda_props; } static TypeInfo hda_codec_device_type_info = { diff --git a/hw/pc_piix.c b/hw/pc_piix.c index f49b0aaf89..d68f77a9c0 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -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),\ } diff --git a/hw/pci.c b/hw/pci.c index 377039ec99..09ce4e7698 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -62,7 +62,6 @@ struct BusInfo pci_bus_info = { .get_dev_path = pcibus_get_dev_path, .get_fw_dev_path = pcibus_get_fw_dev_path, .reset = pcibus_reset, - .props = pci_props, }; static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); @@ -2003,6 +2002,7 @@ static void pci_device_class_init(ObjectClass *klass, void *data) k->unplug = pci_unplug_device; k->exit = pci_unregister_device; k->bus_info = &pci_bus_info; + k->props = pci_props; } static TypeInfo pci_device_type_info = { diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index b01ef0600e..b608eb443f 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -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; } @@ -482,7 +473,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,7 +492,7 @@ 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 : ""); g_free(value); } @@ -509,6 +500,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, 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,8 +511,11 @@ 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); + 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)); if (dev->parent_bus->info->print_dev) dev->parent_bus->info->print_dev(mon, dev, indent); QLIST_FOREACH(child, &dev->child_bus, sibling) { diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 9ae318717e..04e8326108 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -915,17 +915,18 @@ 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; } @@ -1145,17 +1146,20 @@ void qdev_prop_register_global_list(GlobalProperty *props) void qdev_prop_set_globals(DeviceState *dev) { - GlobalProperty *prop; + ObjectClass *class = object_get_class(OBJECT(dev)); - 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; + 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) diff --git a/hw/qdev.c b/hw/qdev.c index a9a9f891da..f239902291 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -45,18 +45,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); @@ -78,20 +66,12 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop, void qdev_set_parent_bus(DeviceState *dev, BusState *bus) { - Property *prop; - if (qdev_hotplug) { assert(bus->allow_hotplug); } dev->parent_bus = bus; QTAILQ_INSERT_HEAD(&bus->children, dev, sibling); - - 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); } /* Create a new device. This only initializes the device state structure @@ -618,6 +598,7 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); + ObjectClass *class; Property *prop; if (qdev_hotplug) { @@ -628,12 +609,15 @@ 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); - } - - qdev_prop_set_defaults(dev, qdev_get_props(dev)); + 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); + } + qdev_prop_set_defaults(dev, DEVICE_CLASS(class)->props); + class = object_class_get_parent(class); + } while (class != object_class_by_name(TYPE_DEVICE)); } /* Unlink device from bus and free the structure. */ @@ -661,6 +645,16 @@ static void device_finalize(Object *obj) QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling); } +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) { DeviceClass *klass = DEVICE_GET_CLASS(dev); @@ -687,6 +681,7 @@ 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), }; diff --git a/hw/qdev.h b/hw/qdev.h index 5386b165bc..5f62f80d35 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -96,7 +96,6 @@ struct BusInfo { bus_get_dev_path get_dev_path; bus_get_fw_dev_path get_fw_dev_path; qbus_resetfn *reset; - Property *props; }; struct BusState { @@ -347,10 +346,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<> */ diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 3423b6c834..a1d75b9cc7 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -24,7 +24,6 @@ static struct BusInfo scsi_bus_info = { .size = sizeof(SCSIBus), .get_dev_path = scsibus_get_dev_path, .get_fw_dev_path = scsibus_get_fw_dev_path, - .props = scsi_props, }; static int next_scsi_bus; @@ -1601,6 +1600,7 @@ static void scsi_device_class_init(ObjectClass *klass, void *data) 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 = { diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index ab4362a230..cf849529dc 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -57,7 +57,6 @@ static Property spapr_vio_props[] = { static struct BusInfo spapr_vio_bus_info = { .name = "spapr-vio", .size = sizeof(VIOsPAPRBus), - .props = spapr_vio_props, }; VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) @@ -797,6 +796,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data) k->init = spapr_vio_busdev_init; k->reset = spapr_vio_busdev_reset; k->bus_info = &spapr_vio_bus_info; + k->props = spapr_vio_props; } static TypeInfo spapr_vio_type_info = { diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 3faf4cb2ee..64887d5ecb 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -24,7 +24,6 @@ static struct BusInfo usb_bus_info = { .print_dev = usb_bus_dev_print, .get_dev_path = usb_get_dev_path, .get_fw_dev_path = usb_get_fw_dev_path, - .props = usb_props, }; static int next_usb_bus = 0; @@ -583,6 +582,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data) 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 = { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 357b7e8a3e..a4ab6e589a 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1063,7 +1063,6 @@ static Property ccid_props[] = { static struct BusInfo ccid_bus_info = { .name = "ccid-bus", .size = sizeof(CCIDBus), - .props = ccid_props, }; void ccid_card_send_apdu_to_guest(CCIDCardState *card, @@ -1347,6 +1346,7 @@ static void ccid_card_class_init(ObjectClass *klass, void *data) k->bus_info = &ccid_bus_info; k->init = ccid_card_init; k->exit = ccid_card_exit; + k->props = ccid_props; } static TypeInfo ccid_card_type_info = { diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index ccdbdb3add..d47d870594 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -738,7 +738,6 @@ static struct BusInfo virtser_bus_info = { .name = "virtio-serial-bus", .size = sizeof(VirtIOSerialBus), .print_dev = virtser_bus_dev_print, - .props = virtser_props, }; static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) @@ -985,6 +984,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) k->bus_info = &virtser_bus_info; k->exit = virtser_port_qdev_exit; k->unplug = qdev_simple_unplug_cb; + k->props = virtser_props; } static TypeInfo virtio_serial_port_type_info = {