提交 8aca5215 编写于 作者: A Anthony Liguori

Merge remote-tracking branch 'afaerber-or/qom-next-2' into staging

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