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()
  ...
This commit is contained in:
Anthony Liguori 2012-06-18 10:35:16 -05:00
commit 8aca521512
41 changed files with 869 additions and 503 deletions

4
exec.c
View File

@ -2603,8 +2603,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
assert(new_block);
assert(!new_block->idstr[0]);
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
char *id = dev->parent_bus->info->get_dev_path(dev);
if (dev) {
char *id = qdev_get_dev_path(dev);
if (id) {
snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
g_free(id);

View File

@ -284,7 +284,7 @@ static const VMStateDescription vmstate_acpi = {
static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
{
DeviceState *qdev, *next;
BusChild *kid, *next;
BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
int slot = ffs(slots) - 1;
bool slot_free = true;
@ -292,7 +292,8 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
/* Mark request as complete */
s->pci0_status.down &= ~(1U << slot);
QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
DeviceState *qdev = kid->child;
PCIDevice *dev = PCI_DEVICE(qdev);
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
if (PCI_SLOT(dev->devfn) == slot) {
@ -313,7 +314,7 @@ static void piix4_update_hotplug(PIIX4PMState *s)
{
PCIDevice *dev = &s->dev;
BusState *bus = qdev_get_parent_bus(&dev->qdev);
DeviceState *qdev, *next;
BusChild *kid, *next;
/* Execute any pending removes during reset */
while (s->pci0_status.down) {
@ -323,7 +324,8 @@ static void piix4_update_hotplug(PIIX4PMState *s)
s->pci0_hotplug_enable = ~0;
s->pci0_slot_device_present = 0;
QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
DeviceState *qdev = kid->child;
PCIDevice *pdev = PCI_DEVICE(qdev);
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
int slot = PCI_SLOT(pdev->devfn);

View File

@ -161,7 +161,7 @@ static int l2x0_priv_init(SysBusDevice *dev)
}
static Property l2x0_properties[] = {
DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100),
DEFINE_PROP_UINT32("cache-type", l2x0_state, cache_type, 0x1c100100),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -17,13 +17,18 @@ struct i2c_bus
uint8_t saved_address;
};
static struct BusInfo i2c_bus_info = {
.name = "I2C",
.size = sizeof(i2c_bus),
.props = (Property[]) {
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
DEFINE_PROP_END_OF_LIST(),
}
static Property i2c_props[] = {
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
DEFINE_PROP_END_OF_LIST(),
};
#define TYPE_I2C_BUS "i2c-bus"
#define I2C_BUS(obj) OBJECT_CHECK(i2c_bus, (obj), TYPE_I2C_BUS)
static const TypeInfo i2c_bus_info = {
.name = TYPE_I2C_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(i2c_bus),
};
static void i2c_bus_pre_save(void *opaque)
@ -61,7 +66,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
{
i2c_bus *bus;
bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
bus = FROM_QBUS(i2c_bus, qbus_create(TYPE_I2C_BUS, parent, name));
vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
return bus;
}
@ -81,11 +86,12 @@ int i2c_bus_busy(i2c_bus *bus)
/* TODO: Make this handle multiple masters. */
int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
{
DeviceState *qdev;
BusChild *kid;
I2CSlave *slave = NULL;
I2CSlaveClass *sc;
QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
if (candidate->address == address) {
slave = candidate;
@ -218,7 +224,8 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = i2c_slave_qdev_init;
k->bus_info = &i2c_bus_info;
k->bus_type = TYPE_I2C_BUS;
k->props = i2c_props;
}
static TypeInfo i2c_slave_type_info = {
@ -232,6 +239,7 @@ static TypeInfo i2c_slave_type_info = {
static void i2c_slave_register_types(void)
{
type_register_static(&i2c_bus_info);
type_register_static(&i2c_slave_type_info);
}

View File

@ -25,6 +25,9 @@ typedef struct IDEState IDEState;
typedef struct IDEDMA IDEDMA;
typedef struct IDEDMAOps IDEDMAOps;
#define TYPE_IDE_BUS "IDE"
#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02

View File

@ -27,19 +27,28 @@
static char *idebus_get_fw_dev_path(DeviceState *dev);
static struct BusInfo ide_bus_info = {
.name = "IDE",
.size = sizeof(IDEBus),
.get_fw_dev_path = idebus_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
DEFINE_PROP_END_OF_LIST(),
},
static Property ide_props[] = {
DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
DEFINE_PROP_END_OF_LIST(),
};
static void ide_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->get_fw_dev_path = idebus_get_fw_dev_path;
}
static const TypeInfo ide_bus_info = {
.name = TYPE_IDE_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(IDEBus),
.class_init = ide_bus_class_init,
};
void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id)
{
qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL);
qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL);
idebus->bus_id = bus_id;
}
@ -248,7 +257,8 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = ide_qdev_init;
k->bus_info = &ide_bus_info;
k->bus_type = TYPE_IDE_BUS;
k->props = ide_props;
}
static TypeInfo ide_device_type_info = {
@ -262,6 +272,7 @@ static TypeInfo ide_device_type_info = {
static void ide_register_types(void)
{
type_register_static(&ide_bus_info);
type_register_static(&ide_hd_info);
type_register_static(&ide_cd_info);
type_register_static(&ide_drive_info);

View File

@ -29,20 +29,22 @@
/* --------------------------------------------------------------------- */
/* hda bus */
static struct BusInfo hda_codec_bus_info = {
.name = "HDA",
.size = sizeof(HDACodecBus),
.props = (Property[]) {
DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1),
DEFINE_PROP_END_OF_LIST()
}
static Property hda_props[] = {
DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1),
DEFINE_PROP_END_OF_LIST()
};
static const TypeInfo hda_codec_bus_info = {
.name = TYPE_HDA_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(HDACodecBus),
};
void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus,
hda_codec_response_func response,
hda_codec_xfer_func xfer)
{
qbus_create_inplace(&bus->qbus, &hda_codec_bus_info, dev, NULL);
qbus_create_inplace(&bus->qbus, TYPE_HDA_BUS, dev, NULL);
bus->response = response;
bus->xfer = xfer;
}
@ -76,10 +78,11 @@ static int hda_codec_dev_exit(DeviceState *qdev)
HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
{
DeviceState *qdev;
BusChild *kid;
HDACodecDevice *cdev;
QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (cdev->cad == cad) {
return cdev;
@ -481,10 +484,11 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st)
static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output)
{
DeviceState *qdev;
BusChild *kid;
HDACodecDevice *cdev;
QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
DeviceState *qdev = kid->child;
HDACodecDeviceClass *cdc;
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
@ -1103,15 +1107,16 @@ static const MemoryRegionOps intel_hda_mmio_ops = {
static void intel_hda_reset(DeviceState *dev)
{
BusChild *kid;
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev);
DeviceState *qdev;
HDACodecDevice *cdev;
intel_hda_regs_reset(d);
d->wall_base_ns = qemu_get_clock_ns(vm_clock);
/* reset codecs */
QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
DeviceState *qdev = kid->child;
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
device_reset(DEVICE(cdev));
d->state_sts |= (1 << cdev->cad);
@ -1263,7 +1268,8 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
DeviceClass *k = DEVICE_CLASS(klass);
k->init = hda_codec_dev_init;
k->exit = hda_codec_dev_exit;
k->bus_info = &hda_codec_bus_info;
k->bus_type = TYPE_HDA_BUS;
k->props = hda_props;
}
static TypeInfo hda_codec_device_type_info = {
@ -1277,6 +1283,7 @@ static TypeInfo hda_codec_device_type_info = {
static void intel_hda_register_types(void)
{
type_register_static(&hda_codec_bus_info);
type_register_static(&intel_hda_info);
type_register_static(&hda_codec_device_type_info);
}

View File

@ -14,6 +14,9 @@
#define HDA_CODEC_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE)
#define TYPE_HDA_BUS "HDA"
#define HDA_BUS(obj) OBJECT_CHECK(HDACodecBus, (obj), TYPE_HDA_BUS)
typedef struct HDACodecBus HDACodecBus;
typedef struct HDACodecDevice HDACodecDevice;

View File

@ -28,11 +28,19 @@ target_phys_addr_t isa_mem_base = 0;
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *isabus_get_fw_dev_path(DeviceState *dev);
static struct BusInfo isa_bus_info = {
.name = "ISA",
.size = sizeof(ISABus),
.print_dev = isabus_dev_print,
.get_fw_dev_path = isabus_get_fw_dev_path,
static void isa_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->print_dev = isabus_dev_print;
k->get_fw_dev_path = isabus_get_fw_dev_path;
}
static const TypeInfo isa_bus_info = {
.name = TYPE_ISA_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(ISABus),
.class_init = isa_bus_class_init,
};
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
@ -46,7 +54,7 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
qdev_init_nofail(dev);
}
isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL));
isabus = FROM_QBUS(ISABus, qbus_create(TYPE_ISA_BUS, dev, NULL));
isabus->address_space_io = address_space_io;
return isabus;
}
@ -198,7 +206,7 @@ static void isa_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = isa_qdev_init;
k->bus_info = &isa_bus_info;
k->bus_type = TYPE_ISA_BUS;
}
static TypeInfo isa_device_type_info = {
@ -212,6 +220,7 @@ static TypeInfo isa_device_type_info = {
static void isabus_register_types(void)
{
type_register_static(&isa_bus_info);
type_register_static(&isabus_bridge_info);
type_register_static(&isa_device_type_info);
}

View File

@ -17,6 +17,9 @@
#define ISA_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
#define TYPE_ISA_BUS "ISA"
#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
typedef struct ISADeviceClass {
DeviceClass parent_class;
int (*init)(ISADevice *dev);

View File

@ -1677,9 +1677,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
}
if (val & LSI_SCNTL1_RST) {
if (!(s->sstat0 & LSI_SSTAT0_RST)) {
DeviceState *dev;
BusChild *kid;
QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
DeviceState *dev = kid->child;
device_reset(dev);
}
s->sstat0 |= LSI_SSTAT0_RST;

View File

@ -65,7 +65,7 @@ struct M48t59State {
/* NVRAM storage */
uint8_t *buffer;
/* Model parameters */
uint32_t type; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
/* NVRAM storage */
uint16_t addr;
uint8_t lock;
@ -197,10 +197,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
/* check for NVRAM access */
if ((NVRAM->type == 2 && addr < 0x7f8) ||
(NVRAM->type == 8 && addr < 0x1ff8) ||
(NVRAM->type == 59 && addr < 0x1ff0))
if ((NVRAM->model == 2 && addr < 0x7f8) ||
(NVRAM->model == 8 && addr < 0x1ff8) ||
(NVRAM->model == 59 && addr < 0x1ff0)) {
goto do_write;
}
/* TOD access */
switch (addr) {
@ -334,10 +335,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
tmp = from_bcd(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
if (NVRAM->type == 8)
if (NVRAM->model == 8) {
tm.tm_year = from_bcd(val) + 68; // Base year is 1968
else
} else {
tm.tm_year = from_bcd(val);
}
set_time(NVRAM, &tm);
}
break;
@ -362,10 +364,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
uint32_t retval = 0xFF;
/* check for NVRAM access */
if ((NVRAM->type == 2 && addr < 0x078f) ||
(NVRAM->type == 8 && addr < 0x1ff8) ||
(NVRAM->type == 59 && addr < 0x1ff0))
if ((NVRAM->model == 2 && addr < 0x078f) ||
(NVRAM->model == 8 && addr < 0x1ff8) ||
(NVRAM->model == 59 && addr < 0x1ff0)) {
goto do_read;
}
/* TOD access */
switch (addr) {
@ -439,10 +442,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
case 0x07FF:
/* year */
get_time(NVRAM, &tm);
if (NVRAM->type == 8)
if (NVRAM->model == 8) {
retval = to_bcd(tm.tm_year - 68); // Base year is 1968
else
} else {
retval = to_bcd(tm.tm_year);
}
break;
default:
/* Check lock registers state */
@ -633,7 +637,7 @@ static const MemoryRegionOps m48t59_io_ops = {
/* Initialisation routine */
M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
uint32_t io_base, uint16_t size, int type)
uint32_t io_base, uint16_t size, int model)
{
DeviceState *dev;
SysBusDevice *s;
@ -641,7 +645,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
M48t59State *state;
dev = qdev_create(NULL, "m48t59");
qdev_prop_set_uint32(dev, "type", type);
qdev_prop_set_uint32(dev, "model", model);
qdev_prop_set_uint32(dev, "size", size);
qdev_prop_set_uint32(dev, "io_base", io_base);
qdev_init_nofail(dev);
@ -661,14 +665,14 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
}
M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
int type)
int model)
{
M48t59ISAState *d;
ISADevice *dev;
M48t59State *s;
dev = isa_create(bus, "m48t59_isa");
qdev_prop_set_uint32(&dev->qdev, "type", type);
qdev_prop_set_uint32(&dev->qdev, "model", model);
qdev_prop_set_uint32(&dev->qdev, "size", size);
qdev_prop_set_uint32(&dev->qdev, "io_base", io_base);
qdev_init_nofail(&dev->qdev);
@ -686,7 +690,7 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
static void m48t59_init_common(M48t59State *s)
{
s->buffer = g_malloc0(s->size);
if (s->type == 59) {
if (s->model == 59) {
s->alrm_timer = qemu_new_timer_ns(rtc_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s);
}
@ -722,7 +726,7 @@ static int m48t59_init1(SysBusDevice *dev)
static Property m48t59_isa_properties[] = {
DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1),
DEFINE_PROP_UINT32("type", M48t59ISAState, state.type, -1),
DEFINE_PROP_UINT32("model", M48t59ISAState, state.model, -1),
DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base, 0),
DEFINE_PROP_END_OF_LIST(),
};
@ -746,7 +750,7 @@ static TypeInfo m48t59_isa_info = {
static Property m48t59_properties[] = {
DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1),
DEFINE_PROP_UINT32("type", M48t59SysBusState, state.type, -1),
DEFINE_PROP_UINT32("model", M48t59SysBusState, state.model, -1),
DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base, 0),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -29,6 +29,7 @@
#include "apic.h"
#include "pci.h"
#include "pci_ids.h"
#include "usb.h"
#include "net.h"
#include "boards.h"
#include "ide.h"
@ -374,7 +375,7 @@ static QEMUMachine pc_machine_v1_1 = {
.property = "vapic",\
.value = "off",\
},{\
.driver = "USB",\
.driver = TYPE_USB_DEVICE,\
.property = "full-path",\
.value = "no",\
}
@ -447,7 +448,7 @@ static QEMUMachine pc_machine_v0_14 = {
#define PC_COMPAT_0_13 \
PC_COMPAT_0_14,\
{\
.driver = "PCI",\
.driver = TYPE_PCI_DEVICE,\
.property = "command_serr_enable",\
.value = "off",\
},{\
@ -519,7 +520,7 @@ static QEMUMachine pc_machine_v0_12 = {
.property = "vectors",\
.value = stringify(0),\
},{\
.driver = "PCI",\
.driver = TYPE_PCI_DEVICE,\
.property = "rombar",\
.value = stringify(0),\
}

View File

@ -80,11 +80,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
SCSIBus *scsibus;
SCSIDevice *scsidev;
scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus));
if (!scsibus || strcmp(scsibus->qbus.info->name, "SCSI") != 0) {
error_report("Device is not a SCSI adapter");
return -1;
}
scsibus = SCSI_BUS(QLIST_FIRST(&adapter->child_bus));
/*
* drive_init() tries to find a default for dinfo->unit. Doesn't

View File

@ -46,23 +46,32 @@ static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
static int pcibus_reset(BusState *qbus);
struct BusInfo pci_bus_info = {
.name = "PCI",
.size = sizeof(PCIBus),
.print_dev = pcibus_dev_print,
.get_dev_path = pcibus_get_dev_path,
.get_fw_dev_path = pcibus_get_fw_dev_path,
.reset = pcibus_reset,
.props = (Property[]) {
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
QEMU_PCI_CAP_SERR_BITNR, true),
DEFINE_PROP_END_OF_LIST()
}
static Property pci_props[] = {
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
QEMU_PCI_CAP_SERR_BITNR, true),
DEFINE_PROP_END_OF_LIST()
};
static void pci_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->print_dev = pcibus_dev_print;
k->get_dev_path = pcibus_get_dev_path;
k->get_fw_dev_path = pcibus_get_fw_dev_path;
k->reset = pcibus_reset;
}
static const TypeInfo pci_bus_info = {
.name = TYPE_PCI_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(PCIBus),
.class_init = pci_bus_class_init,
};
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
@ -270,7 +279,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
MemoryRegion *address_space_io,
uint8_t devfn_min)
{
qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name);
assert(PCI_FUNC(devfn_min) == 0);
bus->devfn_min = devfn_min;
bus->address_space_mem = address_space_mem;
@ -291,7 +300,7 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
PCIBus *bus;
bus = g_malloc0(sizeof(*bus));
bus->qbus.qdev_allocated = 1;
bus->qbus.glib_allocated = true;
pci_bus_new_inplace(bus, parent, name, address_space_mem,
address_space_io, devfn_min);
return bus;
@ -2008,7 +2017,8 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
k->init = pci_qdev_init;
k->unplug = pci_unplug_device;
k->exit = pci_unregister_device;
k->bus_info = &pci_bus_info;
k->bus_type = TYPE_PCI_BUS;
k->props = pci_props;
}
static TypeInfo pci_device_type_info = {
@ -2022,6 +2032,7 @@ static TypeInfo pci_device_type_info = {
static void pci_register_types(void)
{
type_register_static(&pci_bus_info);
type_register_static(&pci_device_type_info);
}

View File

@ -318,7 +318,7 @@ int pci_bridge_initfn(PCIDevice *dev)
br->bus_name = dev->qdev.id;
}
qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
br->bus_name);
sec_bus->parent_dev = dev;
sec_bus->map_irq = br->map_irq;

View File

@ -12,7 +12,8 @@
* Use accessor function in pci.h, pci_bridge.h
*/
extern struct BusInfo pci_bus_info;
#define TYPE_PCI_BUS "PCI"
#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
struct PCIBus {
BusState qbus;

View File

@ -75,8 +75,8 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
}
error_printf("name \"%s\"", object_class_get_name(klass));
if (dc->bus_info) {
error_printf(", bus %s", dc->bus_info->name);
if (dc->bus_type) {
error_printf(", bus %s", dc->bus_type);
}
if (qdev_class_has_alias(dc)) {
error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
@ -123,7 +123,6 @@ int qdev_device_help(QemuOpts *opts)
const char *driver;
Property *prop;
ObjectClass *klass;
DeviceClass *info;
driver = qemu_opt_get(opts, "driver");
if (driver && !strcmp(driver, "?")) {
@ -149,30 +148,22 @@ int qdev_device_help(QemuOpts *opts)
if (!klass) {
return 0;
}
info = DEVICE_CLASS(klass);
for (prop = info->props; prop && prop->name; prop++) {
/*
* TODO Properties without a parser are just for dirty hacks.
* qdev_prop_ptr is the only such PropertyInfo. It's marked
* for removal. This conditional should be removed along with
* it.
*/
if (!prop->info->set) {
continue; /* no way to set it, don't show */
}
error_printf("%s.%s=%s\n", driver, prop->name,
prop->info->legacy_name ?: prop->info->name);
}
if (info->bus_info) {
for (prop = info->bus_info->props; prop && prop->name; prop++) {
do {
for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
/*
* TODO Properties without a parser are just for dirty hacks.
* qdev_prop_ptr is the only such PropertyInfo. It's marked
* for removal. This conditional should be removed along with
* it.
*/
if (!prop->info->set) {
continue; /* no way to set it, don't show */
}
error_printf("%s.%s=%s\n", driver, prop->name,
prop->info->legacy_name ?: prop->info->name);
}
}
klass = object_class_get_parent(klass);
} while (klass != object_class_by_name(TYPE_DEVICE));
return 1;
}
@ -214,11 +205,12 @@ static void qbus_list_bus(DeviceState *dev)
static void qbus_list_dev(BusState *bus)
{
DeviceState *dev;
BusChild *kid;
const char *sep = " ";
error_printf("devices at \"%s\":", bus->name);
QTAILQ_FOREACH(dev, &bus->children, sibling) {
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
if (dev->id)
error_printf("/\"%s\"", dev->id);
@ -241,7 +233,7 @@ static BusState *qbus_find_bus(DeviceState *dev, char *elem)
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
{
DeviceState *dev;
BusChild *kid;
/*
* try to match in order:
@ -249,17 +241,20 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
* (2) driver name
* (3) driver alias, if present
*/
QTAILQ_FOREACH(dev, &bus->children, sibling) {
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
if (dev->id && strcmp(dev->id, elem) == 0) {
return dev;
}
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
return dev;
}
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
DeviceClass *dc = DEVICE_GET_CLASS(dev);
if (qdev_class_has_alias(dc) &&
@ -271,25 +266,27 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
}
static BusState *qbus_find_recursive(BusState *bus, const char *name,
const BusInfo *info)
const char *bus_typename)
{
DeviceState *dev;
BusChild *kid;
BusState *child, *ret;
int match = 1;
if (name && (strcmp(bus->name, name) != 0)) {
match = 0;
}
if (info && (bus->info != info)) {
if (bus_typename &&
(strcmp(object_get_typename(OBJECT(bus)), bus_typename) != 0)) {
match = 0;
}
if (match) {
return bus;
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
QLIST_FOREACH(child, &dev->child_bus, sibling) {
ret = qbus_find_recursive(child, name, info);
ret = qbus_find_recursive(child, name, bus_typename);
if (ret) {
return ret;
}
@ -424,16 +421,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
if (!bus) {
return NULL;
}
if (bus->info != k->bus_info) {
if (strcmp(object_get_typename(OBJECT(bus)), k->bus_type) != 0) {
qerror_report(QERR_BAD_BUS_FOR_DEVICE,
driver, bus->info->name);
driver, object_get_typename(OBJECT(bus)));
return NULL;
}
} else {
bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info);
bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
if (!bus) {
qerror_report(QERR_NO_BUS_FOR_DEVICE,
driver, k->bus_info->name);
driver, k->bus_type);
return NULL;
}
}
@ -449,7 +446,6 @@ DeviceState *qdev_device_add(QemuOpts *opts)
/* create device, set properties */
qdev = DEVICE(object_new(driver));
qdev_set_parent_bus(qdev, bus);
qdev_prop_set_globals(qdev);
id = qemu_opts_id(opts);
if (id) {
@ -482,7 +478,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
static void qbus_print(Monitor *mon, BusState *bus, int indent);
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
const char *prefix, int indent)
int indent)
{
if (!props)
return;
@ -501,14 +497,24 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
error_free(err);
continue;
}
qdev_printf("%s-prop: %s = %s\n", prefix, props->name,
qdev_printf("%s = %s\n", props->name,
value && *value ? value : "<null>");
g_free(value);
}
}
static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
{
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->print_dev) {
bc->print_dev(mon, dev, indent);
}
}
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
{
ObjectClass *class;
BusState *child;
qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
dev->id ? dev->id : "");
@ -519,10 +525,12 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
if (dev->num_gpio_out) {
qdev_printf("gpio-out %d\n", dev->num_gpio_out);
}
qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
if (dev->parent_bus->info->print_dev)
dev->parent_bus->info->print_dev(mon, dev, indent);
class = object_get_class(OBJECT(dev));
do {
qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
bus_print_dev(dev->parent_bus, mon, dev, indent + 2);
QLIST_FOREACH(child, &dev->child_bus, sibling) {
qbus_print(mon, child, indent);
}
@ -530,12 +538,13 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
static void qbus_print(Monitor *mon, BusState *bus, int indent)
{
struct DeviceState *dev;
BusChild *kid;
qdev_printf("bus: %s\n", bus->name);
indent += 2;
qdev_printf("type %s\n", bus->info->name);
QTAILQ_FOREACH(dev, &bus->children, sibling) {
qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
qdev_print(mon, dev, indent);
}
}

View File

@ -915,26 +915,22 @@ static Property *qdev_prop_walk(Property *props, const char *name)
static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
ObjectClass *class;
Property *prop;
/* device properties */
prop = qdev_prop_walk(qdev_get_props(dev), name);
if (prop)
return prop;
/* bus properties */
prop = qdev_prop_walk(dev->parent_bus->info->props, name);
if (prop)
return prop;
class = object_get_class(OBJECT(dev));
do {
prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
if (prop) {
return prop;
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
return NULL;
}
int qdev_prop_exists(DeviceState *dev, const char *name)
{
return qdev_prop_find(dev, name) ? true : false;
}
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
Property *prop, const char *value)
{
@ -1105,28 +1101,6 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
*ptr = value;
}
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
{
Object *obj = OBJECT(dev);
if (!props)
return;
for (; props->name; props++) {
Error *errp = NULL;
if (props->qtype == QTYPE_NONE) {
continue;
}
if (props->qtype == QTYPE_QBOOL) {
object_property_set_bool(obj, props->defval, props->name, &errp);
} else if (props->info->enum_table) {
object_property_set_str(obj, props->info->enum_table[props->defval],
props->name, &errp);
} else if (props->qtype == QTYPE_QINT) {
object_property_set_int(obj, props->defval, props->name, &errp);
}
assert_no_error(errp);
}
}
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
static void qdev_prop_register_global(GlobalProperty *prop)
@ -1145,17 +1119,20 @@ void qdev_prop_register_global_list(GlobalProperty *props)
void qdev_prop_set_globals(DeviceState *dev)
{
GlobalProperty *prop;
ObjectClass *class = object_get_class(OBJECT(dev));
QTAILQ_FOREACH(prop, &global_props, next) {
if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
continue;
do {
GlobalProperty *prop;
QTAILQ_FOREACH(prop, &global_props, next) {
if (strcmp(object_class_get_name(class), prop->driver) != 0) {
continue;
}
if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
exit(1);
}
}
if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
exit(1);
}
}
class = object_class_get_parent(class);
} while (class);
}
static int qdev_add_one_global(QemuOpts *opts, void *opaque)

302
hw/qdev.c
View File

@ -34,10 +34,6 @@ int qdev_hotplug = 0;
static bool qdev_hot_added = false;
static bool qdev_hot_removed = false;
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
static void main_system_bus_create(void);
/* Register a new device type. */
const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
{
@ -45,18 +41,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
return dc->vmsd;
}
BusInfo *qdev_get_bus_info(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
return dc->bus_info;
}
Property *qdev_get_props(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
return dc->props;
}
const char *qdev_fw_name(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@ -76,22 +60,48 @@ bool qdev_exists(const char *name)
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
Error **errp);
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
static void bus_remove_child(BusState *bus, DeviceState *child)
{
Property *prop;
BusChild *kid;
QTAILQ_FOREACH(kid, &bus->children, sibling) {
if (kid->child == child) {
char name[32];
snprintf(name, sizeof(name), "child[%d]", kid->index);
QTAILQ_REMOVE(&bus->children, kid, sibling);
object_property_del(OBJECT(bus), name, NULL);
g_free(kid);
return;
}
}
}
static void bus_add_child(BusState *bus, DeviceState *child)
{
char name[32];
BusChild *kid = g_malloc0(sizeof(*kid));
if (qdev_hotplug) {
assert(bus->allow_hotplug);
}
dev->parent_bus = bus;
QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
kid->index = bus->max_index++;
kid->child = child;
for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
snprintf(name, sizeof(name), "child[%d]", kid->index);
object_property_add_link(OBJECT(bus), name,
object_get_typename(OBJECT(child)),
(Object **)&kid->child,
NULL);
}
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
{
dev->parent_bus = bus;
bus_add_child(bus, dev);
}
/* Create a new device. This only initializes the device state structure
@ -105,7 +115,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
if (!dev) {
if (bus) {
hw_error("Unknown device '%s' for bus '%s'\n", name,
bus->info->name);
object_get_typename(OBJECT(bus)));
} else {
hw_error("Unknown device '%s' for default sysbus\n", name);
}
@ -131,7 +141,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
}
qdev_set_parent_bus(dev, bus);
qdev_prop_set_globals(dev);
return dev;
}
@ -210,18 +219,11 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
return 0;
}
BusState *sysbus_get_default(void)
{
if (!main_system_bus) {
main_system_bus_create();
}
return main_system_bus;
}
static int qbus_reset_one(BusState *bus, void *opaque)
{
if (bus->info->reset) {
return bus->info->reset(bus);
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->reset) {
return bc->reset(bus);
}
return 0;
}
@ -322,7 +324,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
if (nd->netdev)
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
qdev_prop_exists(dev, "vectors")) {
object_property_find(OBJECT(dev), "vectors", NULL)) {
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
}
nd->instantiated = 1;
@ -343,7 +345,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
qbus_walkerfn *busfn, void *opaque)
{
DeviceState *dev;
BusChild *kid;
int err;
if (busfn) {
@ -353,8 +355,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
}
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
err = qdev_walk_children(dev, devfn, busfn, opaque);
QTAILQ_FOREACH(kid, &bus->children, sibling) {
err = qdev_walk_children(kid->child, devfn, busfn, opaque);
if (err < 0) {
return err;
}
@ -388,12 +390,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
{
DeviceState *dev, *ret;
BusChild *kid;
DeviceState *ret;
BusState *child;
QTAILQ_FOREACH(dev, &bus->children, sibling) {
if (dev->id && strcmp(dev->id, id) == 0)
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
if (dev->id && strcmp(dev->id, id) == 0) {
return dev;
}
QLIST_FOREACH(child, &dev->child_bus, sibling) {
ret = qdev_find_recursive(child, id);
if (ret) {
@ -404,84 +411,87 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
return NULL;
}
void qbus_create_inplace(BusState *bus, BusInfo *info,
DeviceState *parent, const char *name)
static void qbus_realize(BusState *bus)
{
const char *typename = object_get_typename(OBJECT(bus));
char *buf;
int i,len;
bus->info = info;
bus->parent = parent;
if (name) {
if (bus->name) {
/* use supplied name */
bus->name = g_strdup(name);
} else if (parent && parent->id) {
} else if (bus->parent && bus->parent->id) {
/* parent device has id -> use it for bus name */
len = strlen(parent->id) + 16;
len = strlen(bus->parent->id) + 16;
buf = g_malloc(len);
snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
bus->name = buf;
} else {
/* no id -> use lowercase bus type for bus name */
len = strlen(info->name) + 16;
len = strlen(typename) + 16;
buf = g_malloc(len);
len = snprintf(buf, len, "%s.%d", info->name,
parent ? parent->num_child_bus : 0);
len = snprintf(buf, len, "%s.%d", typename,
bus->parent ? bus->parent->num_child_bus : 0);
for (i = 0; i < len; i++)
buf[i] = qemu_tolower(buf[i]);
bus->name = buf;
}
QTAILQ_INIT(&bus->children);
if (parent) {
QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
parent->num_child_bus++;
} else if (bus != main_system_bus) {
if (bus->parent) {
QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
bus->parent->num_child_bus++;
object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
} else if (bus != sysbus_get_default()) {
/* TODO: once all bus devices are qdevified,
only reset handler for main_system_bus should be registered here. */
qemu_register_reset(qbus_reset_all_fn, bus);
}
}
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
void qbus_create_inplace(BusState *bus, const char *typename,
DeviceState *parent, const char *name)
{
object_initialize(bus, typename);
bus->parent = parent;
bus->name = name ? g_strdup(name) : NULL;
qbus_realize(bus);
}
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
{
BusState *bus;
bus = g_malloc0(info->size);
bus->qdev_allocated = 1;
qbus_create_inplace(bus, info, parent, name);
return bus;
}
bus = BUS(object_new(typename));
bus->qom_allocated = true;
static void main_system_bus_create(void)
{
/* assign main_system_bus before qbus_create_inplace()
* in order to make "if (bus != main_system_bus)" work */
main_system_bus = g_malloc0(system_bus_info.size);
main_system_bus->qdev_allocated = 1;
qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
"main-system-bus");
bus->parent = parent;
bus->name = name ? g_strdup(name) : NULL;
qbus_realize(bus);
return bus;
}
void qbus_free(BusState *bus)
{
DeviceState *dev;
while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
qdev_free(dev);
}
if (bus->parent) {
QLIST_REMOVE(bus, sibling);
bus->parent->num_child_bus--;
if (bus->qom_allocated) {
object_delete(OBJECT(bus));
} else {
assert(bus != main_system_bus); /* main_system_bus is never freed */
qemu_unregister_reset(qbus_reset_all_fn, bus);
object_finalize(OBJECT(bus));
if (bus->glib_allocated) {
g_free(bus);
}
}
g_free((void*)bus->name);
if (bus->qdev_allocated) {
g_free(bus);
}
static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
{
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->get_fw_dev_path) {
return bc->get_fw_dev_path(dev);
}
return NULL;
}
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
@ -491,8 +501,8 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
if (dev && dev->parent_bus) {
char *d;
l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
if (dev->parent_bus->info->get_fw_dev_path) {
d = dev->parent_bus->info->get_fw_dev_path(dev);
d = bus_get_fw_dev_path(dev->parent_bus, dev);
if (d) {
l += snprintf(p + l, size - l, "%s", d);
g_free(d);
} else {
@ -516,9 +526,20 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
return strdup(path);
}
static char *qdev_get_type(Object *obj, Error **errp)
char *qdev_get_dev_path(DeviceState *dev)
{
return g_strdup(object_get_typename(obj));
BusClass *bc;
if (!dev || !dev->parent_bus) {
return NULL;
}
bc = BUS_GET_CLASS(dev->parent_bus);
if (bc->get_dev_path) {
return bc->get_dev_path(dev);
}
return NULL;
}
/**
@ -606,6 +627,9 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
void qdev_property_add_static(DeviceState *dev, Property *prop,
Error **errp)
{
Error *local_err = NULL;
Object *obj = OBJECT(dev);
/*
* TODO qdev_prop_ptr does not have getters or setters. It must
* go now that it can be replaced with links. The test should be
@ -615,15 +639,34 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
return;
}
object_property_add(OBJECT(dev), prop->name, prop->info->name,
object_property_add(obj, prop->name, prop->info->name,
prop->info->get, prop->info->set,
prop->info->release,
prop, errp);
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (prop->qtype == QTYPE_NONE) {
return;
}
if (prop->qtype == QTYPE_QBOOL) {
object_property_set_bool(obj, prop->defval, prop->name, &local_err);
} else if (prop->info->enum_table) {
object_property_set_str(obj, prop->info->enum_table[prop->defval],
prop->name, &local_err);
} else if (prop->qtype == QTYPE_QINT) {
object_property_set_int(obj, prop->defval, prop->name, &local_err);
}
assert_no_error(local_err);
}
static void device_initfn(Object *obj)
{
DeviceState *dev = DEVICE(obj);
ObjectClass *class;
Property *prop;
if (qdev_hotplug) {
@ -634,13 +677,18 @@ static void device_initfn(Object *obj)
dev->instance_id_alias = -1;
dev->state = DEV_STATE_CREATED;
for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
class = object_get_class(OBJECT(dev));
do {
for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
qdev_prop_set_globals(dev);
object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
qdev_prop_set_defaults(dev, qdev_get_props(dev));
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
(Object **)&dev->parent_bus, NULL);
}
/* Unlink device from bus and free the structure. */
@ -665,7 +713,19 @@ static void device_finalize(Object *obj)
qemu_opts_del(dev->opts);
}
}
QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
if (dev->parent_bus) {
bus_remove_child(dev->parent_bus, dev);
}
}
static void device_class_base_init(ObjectClass *class, void *data)
{
DeviceClass *klass = DEVICE_CLASS(class);
/* We explicitly look up properties in the superclasses,
* so do not propagate them to the subclasses.
*/
klass->props = NULL;
}
void device_reset(DeviceState *dev)
@ -694,12 +754,50 @@ static TypeInfo device_type_info = {
.instance_size = sizeof(DeviceState),
.instance_init = device_initfn,
.instance_finalize = device_finalize,
.class_base_init = device_class_base_init,
.abstract = true,
.class_size = sizeof(DeviceClass),
};
static void qbus_initfn(Object *obj)
{
BusState *bus = BUS(obj);
QTAILQ_INIT(&bus->children);
}
static void qbus_finalize(Object *obj)
{
BusState *bus = BUS(obj);
BusChild *kid;
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child;
qdev_free(dev);
}
if (bus->parent) {
QLIST_REMOVE(bus, sibling);
bus->parent->num_child_bus--;
} else {
assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
qemu_unregister_reset(qbus_reset_all_fn, bus);
}
g_free((char *)bus->name);
}
static const TypeInfo bus_info = {
.name = TYPE_BUS,
.parent = TYPE_OBJECT,
.instance_size = sizeof(BusState),
.abstract = true,
.class_size = sizeof(BusClass),
.instance_init = qbus_initfn,
.instance_finalize = qbus_finalize,
};
static void qdev_register_types(void)
{
type_register_static(&bus_info);
type_register_static(&device_type_info);
}

View File

@ -17,7 +17,7 @@ typedef struct CompatProperty CompatProperty;
typedef struct BusState BusState;
typedef struct BusInfo BusInfo;
typedef struct BusClass BusClass;
enum DevState {
DEV_STATE_CREATED = 1,
@ -55,7 +55,7 @@ typedef struct DeviceClass {
qdev_initfn init;
qdev_event unplug;
qdev_event exit;
BusInfo *bus_info;
const char *bus_type;
} DeviceClass;
/* This structure should not be accessed directly. We declare it here
@ -74,38 +74,52 @@ struct DeviceState {
qemu_irq *gpio_in;
QLIST_HEAD(, BusState) child_bus;
int num_child_bus;
QTAILQ_ENTRY(DeviceState) sibling;
int instance_id_alias;
int alias_required_for_version;
};
typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
typedef char *(*bus_get_dev_path)(DeviceState *dev);
/*
* This callback is used to create Open Firmware device path in accordance with
* OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings
* can be found here http://playground.sun.com/1275/bindings/.
*/
typedef char *(*bus_get_fw_dev_path)(DeviceState *dev);
typedef int (qbus_resetfn)(BusState *bus);
struct BusInfo {
const char *name;
size_t size;
bus_dev_printfn print_dev;
bus_get_dev_path get_dev_path;
bus_get_fw_dev_path get_fw_dev_path;
qbus_resetfn *reset;
Property *props;
#define TYPE_BUS "bus"
#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
struct BusClass {
ObjectClass parent_class;
/* FIXME first arg should be BusState */
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
char *(*get_dev_path)(DeviceState *dev);
char *(*get_fw_dev_path)(DeviceState *dev);
int (*reset)(BusState *bus);
};
typedef struct BusChild {
DeviceState *child;
int index;
QTAILQ_ENTRY(BusChild) sibling;
} BusChild;
/**
* BusState:
* @qom_allocated: Indicates whether the object was allocated by QOM.
* @glib_allocated: Indicates whether the object was initialized in-place
* yet is expected to be freed with g_free().
*/
struct BusState {
Object obj;
DeviceState *parent;
BusInfo *info;
const char *name;
int allow_hotplug;
int qdev_allocated;
QTAILQ_HEAD(ChildrenHead, DeviceState) children;
bool qom_allocated;
bool glib_allocated;
int max_index;
QTAILQ_HEAD(ChildrenHead, BusChild) children;
QLIST_ENTRY(BusState) sibling;
};
@ -175,9 +189,9 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id);
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
void qbus_create_inplace(BusState *bus, BusInfo *info,
void qbus_create_inplace(BusState *bus, const char *typename,
DeviceState *parent, const char *name);
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
* 0 otherwise. */
@ -292,7 +306,6 @@ extern PropertyInfo qdev_prop_blocksize;
/* Set properties between creation and init. */
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
int qdev_prop_exists(DeviceState *dev, const char *name);
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
@ -310,7 +323,6 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
/* FIXME: Remove opaque pointer properties. */
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
void qdev_prop_set_defaults(DeviceState *dev, Property *props);
void qdev_prop_register_global_list(GlobalProperty *props);
void qdev_prop_set_globals(DeviceState *dev);
@ -319,9 +331,6 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
char *qdev_get_fw_dev_path(DeviceState *dev);
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
extern struct BusInfo system_bus_info;
/**
* @qdev_property_add_static - add a @Property to a device referencing a
* field in a struct.
@ -347,10 +356,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
const char *qdev_fw_name(DeviceState *dev);
BusInfo *qdev_get_bus_info(DeviceState *dev);
Property *qdev_get_props(DeviceState *dev);
Object *qdev_get_machine(void);
/* FIXME: make this a link<> */
@ -358,4 +363,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
extern int qdev_hotplug;
char *qdev_get_dev_path(DeviceState *dev);
#endif

View File

@ -45,9 +45,10 @@
#define VIRTIO_EXT_CODE 0x2603
struct BusInfo s390_virtio_bus_info = {
.name = "s390-virtio",
.size = sizeof(VirtIOS390Bus),
static const TypeInfo s390_virtio_bus_info = {
.name = TYPE_S390_VIRTIO_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(VirtIOS390Bus),
};
static const VirtIOBindings virtio_s390_bindings;
@ -92,7 +93,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
/* Create bus on bridge device */
_bus = qbus_create(&s390_virtio_bus_info, dev, "s390-virtio");
_bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio");
bus = DO_UPCAST(VirtIOS390Bus, bus, _bus);
bus->dev_page = *ram_size;
@ -314,20 +315,20 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
ram_addr_t mem,
int *vq_num)
{
VirtIOS390Device *_dev;
DeviceState *dev;
BusChild *kid;
int i;
QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
_dev = (VirtIOS390Device *)dev;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
if (!virtio_queue_get_addr(_dev->vdev, i))
if (!virtio_queue_get_addr(dev->vdev, i))
break;
if (virtio_queue_get_addr(_dev->vdev, i) == mem) {
if (virtio_queue_get_addr(dev->vdev, i) == mem) {
if (vq_num) {
*vq_num = i;
}
return _dev;
return dev;
}
}
}
@ -338,13 +339,12 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
/* Find a device by device descriptor location */
VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
{
VirtIOS390Device *_dev;
DeviceState *dev;
BusChild *kid;
QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
_dev = (VirtIOS390Device *)dev;
if (_dev->dev_offs == mem) {
return _dev;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
if (dev->dev_offs == mem) {
return dev;
}
}
@ -460,7 +460,7 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->init = s390_virtio_busdev_init;
dc->bus_info = &s390_virtio_bus_info;
dc->bus_type = TYPE_S390_VIRTIO_BUS;
dc->unplug = qdev_simple_unplug_cb;
}
@ -521,6 +521,7 @@ static TypeInfo s390_virtio_bridge_info = {
static void s390_virtio_register_types(void)
{
type_register_static(&s390_virtio_bus_info);
type_register_static(&virtio_s390_device_info);
type_register_static(&s390_virtio_serial);
type_register_static(&s390_virtio_blk);

View File

@ -52,6 +52,10 @@
#define VIRTIO_S390_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE)
#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus"
#define S390_VIRTIO_BUS(obj) \
OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS)
typedef struct VirtIOS390Device VirtIOS390Device;
typedef struct VirtIOS390DeviceClass {

View File

@ -12,17 +12,26 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev);
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
static void scsi_req_dequeue(SCSIRequest *req);
static struct BusInfo scsi_bus_info = {
.name = "SCSI",
.size = sizeof(SCSIBus),
.get_dev_path = scsibus_get_dev_path,
.get_fw_dev_path = scsibus_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
DEFINE_PROP_END_OF_LIST(),
},
static Property scsi_props[] = {
DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
DEFINE_PROP_END_OF_LIST(),
};
static void scsi_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->get_dev_path = scsibus_get_dev_path;
k->get_fw_dev_path = scsibus_get_fw_dev_path;
}
static const TypeInfo scsi_bus_info = {
.name = TYPE_SCSI_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(SCSIBus),
.class_init = scsi_bus_class_init,
};
static int next_scsi_bus;
@ -65,7 +74,7 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s)
/* Create a scsi bus, and attach devices to it. */
void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
{
qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, NULL);
bus->busnr = next_scsi_bus++;
bus->info = info;
bus->qbus.allow_hotplug = 1;
@ -205,7 +214,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
if (bootindex >= 0) {
qdev_prop_set_int32(dev, "bootindex", bootindex);
}
if (qdev_prop_exists(dev, "removable")) {
if (object_property_find(OBJECT(dev), "removable", NULL)) {
qdev_prop_set_bit(dev, "removable", removable);
}
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
@ -306,7 +315,7 @@ static void store_lun(uint8_t *outbuf, int lun)
static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
{
DeviceState *qdev;
BusChild *kid;
int i, len, n;
int channel, id;
bool found_lun0;
@ -321,7 +330,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
id = r->req.dev->id;
found_lun0 = false;
n = 0;
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
@ -343,7 +353,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
memset(r->buf, 0, len);
stl_be_p(&r->buf, n);
i = found_lun0 ? 8 : 16;
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
@ -1452,12 +1463,10 @@ static char *scsibus_get_dev_path(DeviceState *dev)
{
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
DeviceState *hba = dev->parent_bus->parent;
char *id = NULL;
char *id;
char *path;
if (hba && hba->parent_bus && hba->parent_bus->info->get_dev_path) {
id = hba->parent_bus->info->get_dev_path(hba);
}
id = qdev_get_dev_path(hba);
if (id) {
path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
} else {
@ -1480,10 +1489,11 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
{
DeviceState *qdev;
BusChild *kid;
SCSIDevice *target_dev = NULL;
QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) {
DeviceState *qdev = kid->child;
SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
@ -1595,10 +1605,11 @@ const VMStateDescription vmstate_scsi_device = {
static void scsi_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->bus_info = &scsi_bus_info;
k->bus_type = TYPE_SCSI_BUS;
k->init = scsi_qdev_init;
k->unplug = qdev_simple_unplug_cb;
k->exit = scsi_qdev_exit;
k->props = scsi_props;
}
static TypeInfo scsi_device_type_info = {
@ -1612,6 +1623,7 @@ static TypeInfo scsi_device_type_info = {
static void scsi_register_types(void)
{
type_register_static(&scsi_bus_info);
type_register_static(&scsi_device_type_info);
}

View File

@ -136,6 +136,9 @@ struct SCSIBusInfo {
void *(*load_request)(QEMUFile *f, SCSIRequest *req);
};
#define TYPE_SCSI_BUS "SCSI"
#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
struct SCSIBus {
BusState qbus;
int busnr;

View File

@ -35,17 +35,18 @@
static PCIDevice *find_dev(sPAPREnvironment *spapr,
uint64_t buid, uint32_t config_addr)
{
DeviceState *qdev;
int devfn = (config_addr >> 8) & 0xFF;
sPAPRPHBState *phb;
QLIST_FOREACH(phb, &spapr->phbs, list) {
BusChild *kid;
if (phb->buid != buid) {
continue;
}
QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
PCIDevice *dev = (PCIDevice *)qdev;
QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
PCIDevice *dev = (PCIDevice *)kid->child;
if (dev->devfn == devfn) {
return dev;
}

View File

@ -49,22 +49,24 @@
do { } while (0)
#endif
static struct BusInfo spapr_vio_bus_info = {
.name = "spapr-vio",
.size = sizeof(VIOsPAPRBus),
.props = (Property[]) {
DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
DEFINE_PROP_END_OF_LIST(),
},
static Property spapr_vio_props[] = {
DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
DEFINE_PROP_END_OF_LIST(),
};
static const TypeInfo spapr_vio_bus_info = {
.name = TYPE_SPAPR_VIO_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(VIOsPAPRBus),
};
VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
{
DeviceState *qdev;
BusChild *kid;
VIOsPAPRDevice *dev = NULL;
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)kid->child;
if (dev->reg == reg) {
return dev;
}
@ -604,7 +606,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
uint32_t nret, target_ulong rets)
{
VIOsPAPRBus *bus = spapr->vio_bus;
DeviceState *qdev;
BusChild *kid;
VIOsPAPRDevice *dev = NULL;
if (nargs != 0) {
@ -612,8 +614,8 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
return;
}
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)kid->child;
spapr_vio_quiesce_one(dev);
}
@ -623,7 +625,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
{
VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
DeviceState *qdev;
BusChild *kid;
VIOsPAPRDevice *other;
/*
@ -631,8 +633,8 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
* using the requested address. We have to open code this because
* the given dev might already be in the list.
*/
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
if (other != dev && other->reg == dev->reg) {
return other;
@ -742,7 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
/* Create bus on bridge device */
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
bus->next_reg = 0x1000;
@ -794,7 +796,8 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
DeviceClass *k = DEVICE_CLASS(klass);
k->init = spapr_vio_busdev_init;
k->reset = spapr_vio_busdev_reset;
k->bus_info = &spapr_vio_bus_info;
k->bus_type = TYPE_SPAPR_VIO_BUS;
k->props = spapr_vio_props;
}
static TypeInfo spapr_vio_type_info = {
@ -808,6 +811,7 @@ static TypeInfo spapr_vio_type_info = {
static void spapr_vio_register_types(void)
{
type_register_static(&spapr_vio_bus_info);
type_register_static(&spapr_vio_bridge_info);
type_register_static(&spapr_vio_type_info);
}
@ -836,19 +840,20 @@ static int compare_reg(const void *p1, const void *p2)
int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
{
DeviceState *qdev, **qdevs;
BusChild *kid;
int i, num, ret = 0;
/* Count qdevs on the bus list */
num = 0;
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
num++;
}
/* Copy out into an array of pointers */
qdevs = g_malloc(sizeof(qdev) * num);
num = 0;
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
qdevs[num++] = qdev;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
qdevs[num++] = kid->child;
}
/* Sort the array */

View File

@ -40,6 +40,9 @@ enum VIOsPAPR_TCEAccess {
#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(VIOsPAPRBus, (obj), TYPE_SPAPR_VIO_BUS)
struct VIOsPAPRDevice;
typedef struct VIOsPAPR_RTCE {

View File

@ -160,7 +160,7 @@ static TypeInfo spapr_vty_info = {
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
{
VIOsPAPRDevice *sdev, *selected;
DeviceState *iter;
BusChild *kid;
/*
* To avoid the console bouncing around we want one VTY to be
@ -169,7 +169,9 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
*/
selected = NULL;
QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
DeviceState *iter = kid->child;
/* Only look at VTY devices */
if (!object_dynamic_cast(OBJECT(iter), "spapr-vty")) {
continue;

View File

@ -16,9 +16,13 @@ struct SSIBus {
BusState qbus;
};
static struct BusInfo ssi_bus_info = {
.name = "SSI",
.size = sizeof(SSIBus),
#define TYPE_SSI_BUS "SSI"
#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS)
static const TypeInfo ssi_bus_info = {
.name = TYPE_SSI_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(SSIBus),
};
static int ssi_slave_init(DeviceState *dev)
@ -26,10 +30,11 @@ static int ssi_slave_init(DeviceState *dev)
SSISlave *s = SSI_SLAVE(dev);
SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
SSIBus *bus;
BusChild *kid;
bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
if (QTAILQ_FIRST(&bus->qbus.children) != dev
|| QTAILQ_NEXT(dev, sibling) != NULL) {
kid = QTAILQ_FIRST(&bus->qbus.children);
if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) {
hw_error("Too many devices on SSI bus");
}
@ -40,7 +45,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->init = ssi_slave_init;
dc->bus_info = &ssi_bus_info;
dc->bus_type = TYPE_SSI_BUS;
}
static TypeInfo ssi_slave_info = {
@ -62,26 +67,28 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
{
BusState *bus;
bus = qbus_create(&ssi_bus_info, parent, name);
bus = qbus_create(TYPE_SSI_BUS, parent, name);
return FROM_QBUS(SSIBus, bus);
}
uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
{
DeviceState *dev;
BusChild *kid;
SSISlave *slave;
SSISlaveClass *ssc;
dev = QTAILQ_FIRST(&bus->qbus.children);
if (!dev) {
kid = QTAILQ_FIRST(&bus->qbus.children);
if (!kid) {
return 0;
}
slave = SSI_SLAVE(dev);
slave = SSI_SLAVE(kid->child);
ssc = SSI_SLAVE_GET_CLASS(slave);
return ssc->transfer(slave, val);
}
static void ssi_slave_register_types(void)
{
type_register_static(&ssi_bus_info);
type_register_static(&ssi_slave_info);
}

View File

@ -24,11 +24,19 @@
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *sysbus_get_fw_dev_path(DeviceState *dev);
struct BusInfo system_bus_info = {
.name = "System",
.size = sizeof(BusState),
.print_dev = sysbus_dev_print,
.get_fw_dev_path = sysbus_get_fw_dev_path,
static void system_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->print_dev = sysbus_dev_print;
k->get_fw_dev_path = sysbus_get_fw_dev_path;
}
static const TypeInfo system_bus_info = {
.name = TYPE_SYSTEM_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(BusState),
.class_init = system_bus_class_init,
};
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
@ -244,7 +252,7 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = sysbus_device_init;
k->bus_info = &system_bus_info;
k->bus_type = TYPE_SYSTEM_BUS;
}
static TypeInfo sysbus_device_type_info = {
@ -256,8 +264,33 @@ static TypeInfo sysbus_device_type_info = {
.class_init = sysbus_device_class_init,
};
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
static void main_system_bus_create(void)
{
/* assign main_system_bus before qbus_create_inplace()
* in order to make "if (bus != sysbus_get_default())" work */
main_system_bus = g_malloc0(system_bus_info.instance_size);
qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL,
"main-system-bus");
main_system_bus->glib_allocated = true;
object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
"sysbus", OBJECT(main_system_bus), NULL);
}
BusState *sysbus_get_default(void)
{
if (!main_system_bus) {
main_system_bus_create();
}
return main_system_bus;
}
static void sysbus_register_types(void)
{
type_register_static(&system_bus_info);
type_register_static(&sysbus_device_type_info);
}

View File

@ -10,6 +10,9 @@
#define QDEV_MAX_PIO 32
#define QDEV_MAX_IRQ 512
#define TYPE_SYSTEM_BUS "System"
#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
typedef struct SysBusDevice SysBusDevice;
#define TYPE_SYS_BUS_DEVICE "sys-bus-device"

View File

@ -421,6 +421,9 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
/* usb-bus.c */
#define TYPE_USB_BUS "usb-bus"
#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS)
struct USBBus {
BusState qbus;
USBBusOps *ops;

View File

@ -11,19 +11,29 @@ static char *usb_get_dev_path(DeviceState *dev);
static char *usb_get_fw_dev_path(DeviceState *qdev);
static int usb_qdev_exit(DeviceState *qdev);
static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
.print_dev = usb_bus_dev_print,
.get_dev_path = usb_get_dev_path,
.get_fw_dev_path = usb_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_STRING("port", USBDevice, port_path),
DEFINE_PROP_BIT("full-path", USBDevice, flags,
USB_DEV_FLAG_FULL_PATH, true),
DEFINE_PROP_END_OF_LIST()
},
static Property usb_props[] = {
DEFINE_PROP_STRING("port", USBDevice, port_path),
DEFINE_PROP_BIT("full-path", USBDevice, flags,
USB_DEV_FLAG_FULL_PATH, true),
DEFINE_PROP_END_OF_LIST()
};
static void usb_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->print_dev = usb_bus_dev_print;
k->get_dev_path = usb_get_dev_path;
k->get_fw_dev_path = usb_get_fw_dev_path;
}
static const TypeInfo usb_bus_info = {
.name = TYPE_USB_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(USBBus),
.class_init = usb_bus_class_init,
};
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@ -45,7 +55,7 @@ const VMStateDescription vmstate_usb_device = {
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
{
qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
qbus_create_inplace(&bus->qbus, TYPE_USB_BUS, host, NULL);
bus->ops = ops;
bus->busnr = next_usb_bus++;
bus->qbus.allow_hotplug = 1; /* Yes, we can */
@ -465,9 +475,8 @@ static char *usb_get_dev_path(DeviceState *qdev)
DeviceState *hcd = qdev->parent_bus->parent;
char *id = NULL;
if ((dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) &&
hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
id = hcd->parent_bus->info->get_dev_path(hcd);
if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
id = qdev_get_dev_path(hcd);
}
if (id) {
char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
@ -576,10 +585,11 @@ USBDevice *usbdevice_create(const char *cmdline)
static void usb_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->bus_info = &usb_bus_info;
k->bus_type = TYPE_USB_BUS;
k->init = usb_qdev_init;
k->unplug = qdev_simple_unplug_cb;
k->exit = usb_qdev_exit;
k->props = usb_props;
}
static TypeInfo usb_device_type_info = {
@ -593,6 +603,7 @@ static TypeInfo usb_device_type_info = {
static void usb_register_types(void)
{
type_register_static(&usb_bus_info);
type_register_static(&usb_device_type_info);
}

View File

@ -432,12 +432,13 @@ void usb_desc_create_serial(USBDevice *dev)
const USBDesc *desc = usb_device_get_usb_desc(dev);
int index = desc->id.iSerialNumber;
char serial[64];
char *path;
int dst;
assert(index != 0 && desc->str[index] != NULL);
dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
char *path = hcd->parent_bus->info->get_dev_path(hcd);
path = qdev_get_dev_path(hcd);
if (path) {
dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
}
dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);

View File

@ -1055,13 +1055,18 @@ static Answer *ccid_peek_next_answer(USBCCIDState *s)
: &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
}
static struct BusInfo ccid_bus_info = {
.name = "ccid-bus",
.size = sizeof(CCIDBus),
.props = (Property[]) {
DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
DEFINE_PROP_END_OF_LIST(),
}
static Property ccid_props[] = {
DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
DEFINE_PROP_END_OF_LIST(),
};
#define TYPE_CCID_BUS "ccid-bus"
#define CCID_BUS(obj) OBJECT_CHECK(CCIDBus, (obj), TYPE_CCID_BUS)
static const TypeInfo ccid_bus_info = {
.name = TYPE_CCID_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(CCIDBus),
};
void ccid_card_send_apdu_to_guest(CCIDCardState *card,
@ -1191,7 +1196,7 @@ static int ccid_initfn(USBDevice *dev)
usb_desc_create_serial(dev);
usb_desc_init(dev);
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
s->bus.qbus.allow_hotplug = 1;
s->card = NULL;
@ -1342,9 +1347,10 @@ static TypeInfo ccid_info = {
static void ccid_card_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->bus_info = &ccid_bus_info;
k->bus_type = TYPE_CCID_BUS;
k->init = ccid_card_init;
k->exit = ccid_card_exit;
k->props = ccid_props;
}
static TypeInfo ccid_card_type_info = {
@ -1358,6 +1364,7 @@ static TypeInfo ccid_card_type_info = {
static void ccid_register_types(void)
{
type_register_static(&ccid_bus_info);
type_register_static(&ccid_card_type_info);
type_register_static(&ccid_info);
usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);

View File

@ -275,7 +275,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
{
SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
SCSIRequest *r, *next;
DeviceState *qdev;
BusChild *kid;
int target;
/* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
@ -346,8 +346,8 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
target = req->req.tmf->lun[1];
s->resetting++;
QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
d = DO_UPCAST(SCSIDevice, qdev, qdev);
QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
d = DO_UPCAST(SCSIDevice, qdev, kid->child);
if (d->channel == 0 && d->id == target) {
qdev_reset_all(&d->qdev);
}

View File

@ -728,15 +728,27 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static struct BusInfo virtser_bus_info = {
.name = "virtio-serial-bus",
.size = sizeof(VirtIOSerialBus),
.print_dev = virtser_bus_dev_print,
.props = (Property[]) {
DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
DEFINE_PROP_END_OF_LIST()
}
static Property virtser_props[] = {
DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
DEFINE_PROP_END_OF_LIST()
};
#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
#define VIRTIO_SERIAL_BUS(obj) \
OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)
static void virtser_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
k->print_dev = virtser_bus_dev_print;
}
static const TypeInfo virtser_bus_info = {
.name = TYPE_VIRTIO_SERIAL_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(VirtIOSerialBus),
.class_init = virtser_bus_class_init,
};
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
@ -904,7 +916,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
qbus_create_inplace(&vser->bus.qbus, &virtser_bus_info, dev, NULL);
qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, dev, NULL);
vser->bus.qbus.allow_hotplug = 1;
vser->bus.vser = vser;
QTAILQ_INIT(&vser->ports);
@ -980,9 +992,10 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = virtser_port_qdev_init;
k->bus_info = &virtser_bus_info;
k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
k->exit = virtser_port_qdev_exit;
k->unplug = qdev_simple_unplug_cb;
k->props = virtser_props;
}
static TypeInfo virtio_serial_port_type_info = {
@ -996,6 +1009,7 @@ static TypeInfo virtio_serial_port_type_info = {
static void virtio_serial_register_types(void)
{
type_register_static(&virtser_bus_info);
type_register_static(&virtio_serial_port_type_info);
}

View File

@ -33,7 +33,7 @@ typedef struct TypeInfo TypeInfo;
typedef struct InterfaceClass InterfaceClass;
typedef struct InterfaceInfo InterfaceInfo;
#define TYPE_OBJECT NULL
#define TYPE_OBJECT "object"
/**
* SECTION:object.h
@ -291,10 +291,15 @@ struct Object
* has occurred to allow a class to set its default virtual method pointers.
* This is also the function to use to override virtual methods from a parent
* class.
* @class_base_init: This function is called for all base classes after all
* parent class initialization has occurred, but before the class itself
* is initialized. This is the function to use to undo the effects of
* memcpy from the parent class to the descendents.
* @class_finalize: This function is called during class destruction and is
* meant to release and dynamic parameters allocated by @class_init.
* @class_data: Data to pass to the @class_init and @class_finalize functions.
* This can be useful when building dynamic classes.
* @class_data: Data to pass to the @class_init, @class_base_init and
* @class_finalize functions. This can be useful when building dynamic
* classes.
* @interfaces: The list of interfaces associated with this type. This
* should point to a static array that's terminated with a zero filled
* element.
@ -312,6 +317,7 @@ struct TypeInfo
size_t class_size;
void (*class_init)(ObjectClass *klass, void *data);
void (*class_base_init)(ObjectClass *klass, void *data);
void (*class_finalize)(ObjectClass *klass, void *data);
void *class_data;
@ -521,8 +527,6 @@ const char *object_get_typename(Object *obj);
*/
Type type_register_static(const TypeInfo *info);
#define type_register_static_alias(info, name) do { } while (0)
/**
* type_register:
* @info: The #TypeInfo of the new type
@ -547,6 +551,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *klass,
ObjectClass *object_class_dynamic_cast(ObjectClass *klass,
const char *typename);
/**
* object_class_get_parent:
* @klass: The class to obtain the parent for.
*
* Returns: The parent for @klass or %NULL if none.
*/
ObjectClass *object_class_get_parent(ObjectClass *klass);
/**
* object_class_get_name:
* @klass: The class to obtain the QOM typename for.
@ -623,6 +635,17 @@ void object_property_add(Object *obj, const char *name, const char *type,
void object_property_del(Object *obj, const char *name, struct Error **errp);
/**
* object_property_find:
* @obj: the object
* @name: the name of the property
* @errp: returns an error if this function fails
*
* Look up a property for an object and return its #ObjectProperty if found.
*/
ObjectProperty *object_property_find(Object *obj, const char *name,
struct Error **errp);
void object_unparent(Object *obj);
/**
@ -909,6 +932,20 @@ void object_property_add_str(Object *obj, const char *name,
void (*set)(Object *, const char *, struct Error **),
struct Error **errp);
/**
* object_child_foreach:
* @obj: the object whose children will be navigated
* @fn: the iterator function to be called
* @opaque: an opaque value that will be passed to the iterator
*
* Call @fn passing each child of @obj and @opaque to it, until @fn returns
* non-zero.
*
* Returns: The last value returned by @fn, or 0 if there is no child.
*/
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
void *opaque);
/**
* container_get:
* @root: root of the #path, e.g., object_get_root()

View File

@ -45,6 +45,7 @@ struct TypeImpl
size_t instance_size;
void (*class_init)(ObjectClass *klass, void *data);
void (*class_base_init)(ObjectClass *klass, void *data);
void (*class_finalize)(ObjectClass *klass, void *data);
void *class_data;
@ -94,7 +95,7 @@ static TypeImpl *type_table_lookup(const char *name)
return g_hash_table_lookup(type_table_get(), name);
}
TypeImpl *type_register(const TypeInfo *info)
static TypeImpl *type_register_internal(const TypeInfo *info)
{
TypeImpl *ti = g_malloc0(sizeof(*ti));
@ -112,6 +113,7 @@ TypeImpl *type_register(const TypeInfo *info)
ti->instance_size = info->instance_size;
ti->class_init = info->class_init;
ti->class_base_init = info->class_base_init;
ti->class_finalize = info->class_finalize;
ti->class_data = info->class_data;
@ -135,6 +137,12 @@ TypeImpl *type_register(const TypeInfo *info)
return ti;
}
TypeImpl *type_register(const TypeInfo *info)
{
assert(info->parent);
return type_register_internal(info);
}
TypeImpl *type_register_static(const TypeInfo *info)
{
return type_register(info);
@ -202,13 +210,13 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
info.name = name;
iface->type = type_register(&info);
iface->type = type_register_internal(&info);
g_free(name);
}
static void type_initialize(TypeImpl *ti)
{
size_t class_size = sizeof(ObjectClass);
TypeImpl *parent;
int i;
if (ti->class) {
@ -219,22 +227,23 @@ static void type_initialize(TypeImpl *ti)
ti->instance_size = type_object_get_size(ti);
ti->class = g_malloc0(ti->class_size);
ti->class->type = ti;
if (type_has_parent(ti)) {
TypeImpl *parent = type_get_parent(ti);
parent = type_get_parent(ti);
if (parent) {
type_initialize(parent);
class_size = parent->class_size;
g_assert(parent->class_size <= ti->class_size);
memcpy((void *)ti->class + sizeof(ObjectClass),
(void *)parent->class + sizeof(ObjectClass),
parent->class_size - sizeof(ObjectClass));
memcpy(ti->class, parent->class, parent->class_size);
}
memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
ti->class->type = ti;
while (parent) {
if (parent->class_base_init) {
parent->class_base_init(ti->class, ti->class_data);
}
parent = type_get_parent(parent);
}
for (i = 0; i < ti->num_interfaces; i++) {
type_class_interface_init(ti, &ti->interfaces[i]);
@ -296,6 +305,16 @@ void object_initialize(void *data, const char *typename)
object_initialize_with_type(data, type);
}
static inline bool object_property_is_child(ObjectProperty *prop)
{
return strstart(prop->type, "child<", NULL);
}
static inline bool object_property_is_link(ObjectProperty *prop)
{
return strstart(prop->type, "link<", NULL);
}
static void object_property_del_all(Object *obj)
{
while (!QTAILQ_EMPTY(&obj->properties)) {
@ -318,7 +337,7 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
ObjectProperty *prop;
QTAILQ_FOREACH(prop, &obj->properties, node) {
if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
if (object_property_is_child(prop) && prop->opaque == child) {
object_property_del(obj, prop->name, errp);
break;
}
@ -458,19 +477,6 @@ Object *object_dynamic_cast(Object *obj, const char *typename)
}
static void register_types(void)
{
static TypeInfo interface_info = {
.name = TYPE_INTERFACE,
.instance_size = sizeof(Interface),
.abstract = true,
};
type_interface = type_register_static(&interface_info);
}
type_init(register_types)
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
{
Object *inst;
@ -545,6 +551,19 @@ ObjectClass *object_class_by_name(const char *typename)
return type->class;
}
ObjectClass *object_class_get_parent(ObjectClass *class)
{
TypeImpl *type = type_get_parent(class->type);
if (!type) {
return NULL;
}
type_initialize(type);
return type->class;
}
typedef struct OCFData
{
void (*fn)(ObjectClass *klass, void *opaque);
@ -584,6 +603,23 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
}
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
void *opaque)
{
ObjectProperty *prop;
int ret = 0;
QTAILQ_FOREACH(prop, &obj->properties, node) {
if (object_property_is_child(prop)) {
ret = fn(prop->opaque, opaque);
if (ret != 0) {
break;
}
}
}
return ret;
}
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
{
GSList **list = opaque;
@ -636,7 +672,8 @@ void object_property_add(Object *obj, const char *name, const char *type,
QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
}
static ObjectProperty *object_property_find(Object *obj, const char *name)
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp)
{
ObjectProperty *prop;
@ -646,17 +683,23 @@ static ObjectProperty *object_property_find(Object *obj, const char *name)
}
}
error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return NULL;
}
void object_property_del(Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
return;
}
if (prop->release) {
prop->release(obj, name, prop->opaque);
}
QTAILQ_REMOVE(&obj->properties, prop, node);
prop->release(obj, prop->name, prop->opaque);
g_free(prop->name);
g_free(prop->type);
g_free(prop);
@ -665,10 +708,8 @@ void object_property_del(Object *obj, const char *name, Error **errp)
void object_property_get(Object *obj, Visitor *v, const char *name,
Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return;
}
@ -682,10 +723,8 @@ void object_property_get(Object *obj, Visitor *v, const char *name,
void object_property_set(Object *obj, Visitor *v, const char *name,
Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return;
}
@ -838,10 +877,8 @@ char *object_property_print(Object *obj, const char *name,
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return NULL;
}
@ -995,7 +1032,7 @@ gchar *object_get_canonical_path(Object *obj)
g_assert(obj->parent != NULL);
QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
if (!strstart(prop->type, "child<", NULL)) {
if (!object_property_is_child(prop)) {
continue;
}
@ -1024,14 +1061,14 @@ gchar *object_get_canonical_path(Object *obj)
Object *object_resolve_path_component(Object *parent, gchar *part)
{
ObjectProperty *prop = object_property_find(parent, part);
ObjectProperty *prop = object_property_find(parent, part, NULL);
if (prop == NULL) {
return NULL;
}
if (strstart(prop->type, "link<", NULL)) {
if (object_property_is_link(prop)) {
return *(Object **)prop->opaque;
} else if (strstart(prop->type, "child<", NULL)) {
} else if (object_property_is_child(prop)) {
return prop->opaque;
} else {
return NULL;
@ -1074,7 +1111,7 @@ static Object *object_resolve_partial_path(Object *parent,
QTAILQ_FOREACH(prop, &parent->properties, node) {
Object *found;
if (!strstart(prop->type, "child<", NULL)) {
if (!object_property_is_child(prop)) {
continue;
}
@ -1194,3 +1231,34 @@ void object_property_add_str(Object *obj, const char *name,
property_release_str,
prop, errp);
}
static char *qdev_get_type(Object *obj, Error **errp)
{
return g_strdup(object_get_typename(obj));
}
static void object_instance_init(Object *obj)
{
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
}
static void register_types(void)
{
static TypeInfo interface_info = {
.name = TYPE_INTERFACE,
.instance_size = sizeof(Interface),
.abstract = true,
};
static TypeInfo object_info = {
.name = TYPE_OBJECT,
.instance_size = sizeof(Object),
.instance_init = object_instance_init,
.abstract = true,
};
type_interface = type_register_internal(&interface_info);
type_register_internal(&object_info);
}
type_init(register_types)

View File

@ -1248,8 +1248,8 @@ int register_savevm_live(DeviceState *dev,
se->is_ram = 1;
}
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
char *id = dev->parent_bus->info->get_dev_path(dev);
if (dev) {
char *id = qdev_get_dev_path(dev);
if (id) {
pstrcpy(se->idstr, sizeof(se->idstr), id);
pstrcat(se->idstr, sizeof(se->idstr), "/");
@ -1292,8 +1292,8 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
SaveStateEntry *se, *new_se;
char id[256] = "";
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
char *path = dev->parent_bus->info->get_dev_path(dev);
if (dev) {
char *path = qdev_get_dev_path(dev);
if (path) {
pstrcpy(id, sizeof(id), path);
pstrcat(id, sizeof(id), "/");
@ -1334,8 +1334,8 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
se->alias_id = alias_id;
se->no_migrate = vmsd->unmigratable;
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
char *id = dev->parent_bus->info->get_dev_path(dev);
if (dev) {
char *id = qdev_get_dev_path(dev);
if (id) {
pstrcpy(se->idstr, sizeof(se->idstr), id);
pstrcat(se->idstr, sizeof(se->idstr), "/");