mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
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:
commit
8aca521512
4
exec.c
4
exec.c
@ -2603,8 +2603,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
|
||||
assert(new_block);
|
||||
assert(!new_block->idstr[0]);
|
||||
|
||||
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
||||
char *id = dev->parent_bus->info->get_dev_path(dev);
|
||||
if (dev) {
|
||||
char *id = qdev_get_dev_path(dev);
|
||||
if (id) {
|
||||
snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
|
||||
g_free(id);
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
};
|
||||
|
||||
|
30
hw/i2c.c
30
hw/i2c.c
@ -17,13 +17,18 @@ struct i2c_bus
|
||||
uint8_t saved_address;
|
||||
};
|
||||
|
||||
static struct BusInfo i2c_bus_info = {
|
||||
.name = "I2C",
|
||||
.size = sizeof(i2c_bus),
|
||||
.props = (Property[]) {
|
||||
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
}
|
||||
static Property i2c_props[] = {
|
||||
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
#define TYPE_I2C_BUS "i2c-bus"
|
||||
#define I2C_BUS(obj) OBJECT_CHECK(i2c_bus, (obj), TYPE_I2C_BUS)
|
||||
|
||||
static const TypeInfo i2c_bus_info = {
|
||||
.name = TYPE_I2C_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(i2c_bus),
|
||||
};
|
||||
|
||||
static void i2c_bus_pre_save(void *opaque)
|
||||
@ -61,7 +66,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
|
||||
{
|
||||
i2c_bus *bus;
|
||||
|
||||
bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
|
||||
bus = FROM_QBUS(i2c_bus, qbus_create(TYPE_I2C_BUS, parent, name));
|
||||
vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
|
||||
return bus;
|
||||
}
|
||||
@ -81,11 +86,12 @@ int i2c_bus_busy(i2c_bus *bus)
|
||||
/* TODO: Make this handle multiple masters. */
|
||||
int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
|
||||
{
|
||||
DeviceState *qdev;
|
||||
BusChild *kid;
|
||||
I2CSlave *slave = NULL;
|
||||
I2CSlaveClass *sc;
|
||||
|
||||
QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
|
||||
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
|
||||
DeviceState *qdev = kid->child;
|
||||
I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
|
||||
if (candidate->address == address) {
|
||||
slave = candidate;
|
||||
@ -218,7 +224,8 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = i2c_slave_qdev_init;
|
||||
k->bus_info = &i2c_bus_info;
|
||||
k->bus_type = TYPE_I2C_BUS;
|
||||
k->props = i2c_props;
|
||||
}
|
||||
|
||||
static TypeInfo i2c_slave_type_info = {
|
||||
@ -232,6 +239,7 @@ static TypeInfo i2c_slave_type_info = {
|
||||
|
||||
static void i2c_slave_register_types(void)
|
||||
{
|
||||
type_register_static(&i2c_bus_info);
|
||||
type_register_static(&i2c_slave_type_info);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
23
hw/isa-bus.c
23
hw/isa-bus.c
@ -28,11 +28,19 @@ target_phys_addr_t isa_mem_base = 0;
|
||||
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
||||
static char *isabus_get_fw_dev_path(DeviceState *dev);
|
||||
|
||||
static struct BusInfo isa_bus_info = {
|
||||
.name = "ISA",
|
||||
.size = sizeof(ISABus),
|
||||
.print_dev = isabus_dev_print,
|
||||
.get_fw_dev_path = isabus_get_fw_dev_path,
|
||||
static void isa_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
|
||||
k->print_dev = isabus_dev_print;
|
||||
k->get_fw_dev_path = isabus_get_fw_dev_path;
|
||||
}
|
||||
|
||||
static const TypeInfo isa_bus_info = {
|
||||
.name = TYPE_ISA_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(ISABus),
|
||||
.class_init = isa_bus_class_init,
|
||||
};
|
||||
|
||||
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
|
||||
@ -46,7 +54,7 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL));
|
||||
isabus = FROM_QBUS(ISABus, qbus_create(TYPE_ISA_BUS, dev, NULL));
|
||||
isabus->address_space_io = address_space_io;
|
||||
return isabus;
|
||||
}
|
||||
@ -198,7 +206,7 @@ static void isa_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = isa_qdev_init;
|
||||
k->bus_info = &isa_bus_info;
|
||||
k->bus_type = TYPE_ISA_BUS;
|
||||
}
|
||||
|
||||
static TypeInfo isa_device_type_info = {
|
||||
@ -212,6 +220,7 @@ static TypeInfo isa_device_type_info = {
|
||||
|
||||
static void isabus_register_types(void)
|
||||
{
|
||||
type_register_static(&isa_bus_info);
|
||||
type_register_static(&isabus_bridge_info);
|
||||
type_register_static(&isa_device_type_info);
|
||||
}
|
||||
|
3
hw/isa.h
3
hw/isa.h
@ -17,6 +17,9 @@
|
||||
#define ISA_DEVICE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
|
||||
|
||||
#define TYPE_ISA_BUS "ISA"
|
||||
#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
|
||||
|
||||
typedef struct ISADeviceClass {
|
||||
DeviceClass parent_class;
|
||||
int (*init)(ISADevice *dev);
|
||||
|
@ -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;
|
||||
|
40
hw/m48t59.c
40
hw/m48t59.c
@ -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(),
|
||||
};
|
||||
|
@ -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),\
|
||||
}
|
||||
|
@ -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
|
||||
|
51
hw/pci.c
51
hw/pci.c
@ -46,23 +46,32 @@ static char *pcibus_get_dev_path(DeviceState *dev);
|
||||
static char *pcibus_get_fw_dev_path(DeviceState *dev);
|
||||
static int pcibus_reset(BusState *qbus);
|
||||
|
||||
struct BusInfo pci_bus_info = {
|
||||
.name = "PCI",
|
||||
.size = sizeof(PCIBus),
|
||||
.print_dev = pcibus_dev_print,
|
||||
.get_dev_path = pcibus_get_dev_path,
|
||||
.get_fw_dev_path = pcibus_get_fw_dev_path,
|
||||
.reset = pcibus_reset,
|
||||
.props = (Property[]) {
|
||||
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
|
||||
DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
|
||||
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
|
||||
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
|
||||
QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
|
||||
DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
|
||||
QEMU_PCI_CAP_SERR_BITNR, true),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
}
|
||||
static Property pci_props[] = {
|
||||
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
|
||||
DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
|
||||
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
|
||||
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
|
||||
QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
|
||||
DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
|
||||
QEMU_PCI_CAP_SERR_BITNR, true),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
|
||||
k->print_dev = pcibus_dev_print;
|
||||
k->get_dev_path = pcibus_get_dev_path;
|
||||
k->get_fw_dev_path = pcibus_get_fw_dev_path;
|
||||
k->reset = pcibus_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bus_info = {
|
||||
.name = TYPE_PCI_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(PCIBus),
|
||||
.class_init = pci_bus_class_init,
|
||||
};
|
||||
|
||||
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
|
||||
@ -270,7 +279,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
|
||||
MemoryRegion *address_space_io,
|
||||
uint8_t devfn_min)
|
||||
{
|
||||
qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
|
||||
qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name);
|
||||
assert(PCI_FUNC(devfn_min) == 0);
|
||||
bus->devfn_min = devfn_min;
|
||||
bus->address_space_mem = address_space_mem;
|
||||
@ -291,7 +300,7 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
|
||||
PCIBus *bus;
|
||||
|
||||
bus = g_malloc0(sizeof(*bus));
|
||||
bus->qbus.qdev_allocated = 1;
|
||||
bus->qbus.glib_allocated = true;
|
||||
pci_bus_new_inplace(bus, parent, name, address_space_mem,
|
||||
address_space_io, devfn_min);
|
||||
return bus;
|
||||
@ -2008,7 +2017,8 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
|
||||
k->init = pci_qdev_init;
|
||||
k->unplug = pci_unplug_device;
|
||||
k->exit = pci_unregister_device;
|
||||
k->bus_info = &pci_bus_info;
|
||||
k->bus_type = TYPE_PCI_BUS;
|
||||
k->props = pci_props;
|
||||
}
|
||||
|
||||
static TypeInfo pci_device_type_info = {
|
||||
@ -2022,6 +2032,7 @@ static TypeInfo pci_device_type_info = {
|
||||
|
||||
static void pci_register_types(void)
|
||||
{
|
||||
type_register_static(&pci_bus_info);
|
||||
type_register_static(&pci_device_type_info);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
302
hw/qdev.c
@ -34,10 +34,6 @@ int qdev_hotplug = 0;
|
||||
static bool qdev_hot_added = false;
|
||||
static bool qdev_hot_removed = false;
|
||||
|
||||
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
|
||||
static BusState *main_system_bus;
|
||||
static void main_system_bus_create(void);
|
||||
|
||||
/* Register a new device type. */
|
||||
const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
|
||||
{
|
||||
@ -45,18 +41,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
|
||||
return dc->vmsd;
|
||||
}
|
||||
|
||||
BusInfo *qdev_get_bus_info(DeviceState *dev)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||
return dc->bus_info;
|
||||
}
|
||||
|
||||
Property *qdev_get_props(DeviceState *dev)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||
return dc->props;
|
||||
}
|
||||
|
||||
const char *qdev_fw_name(DeviceState *dev)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||
@ -76,22 +60,48 @@ bool qdev_exists(const char *name)
|
||||
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
|
||||
Error **errp);
|
||||
|
||||
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
|
||||
static void bus_remove_child(BusState *bus, DeviceState *child)
|
||||
{
|
||||
Property *prop;
|
||||
BusChild *kid;
|
||||
|
||||
QTAILQ_FOREACH(kid, &bus->children, sibling) {
|
||||
if (kid->child == child) {
|
||||
char name[32];
|
||||
|
||||
snprintf(name, sizeof(name), "child[%d]", kid->index);
|
||||
QTAILQ_REMOVE(&bus->children, kid, sibling);
|
||||
object_property_del(OBJECT(bus), name, NULL);
|
||||
g_free(kid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bus_add_child(BusState *bus, DeviceState *child)
|
||||
{
|
||||
char name[32];
|
||||
BusChild *kid = g_malloc0(sizeof(*kid));
|
||||
|
||||
if (qdev_hotplug) {
|
||||
assert(bus->allow_hotplug);
|
||||
}
|
||||
|
||||
dev->parent_bus = bus;
|
||||
QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
|
||||
kid->index = bus->max_index++;
|
||||
kid->child = child;
|
||||
|
||||
for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
|
||||
qdev_property_add_legacy(dev, prop, NULL);
|
||||
qdev_property_add_static(dev, prop, NULL);
|
||||
}
|
||||
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
|
||||
QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
|
||||
|
||||
snprintf(name, sizeof(name), "child[%d]", kid->index);
|
||||
object_property_add_link(OBJECT(bus), name,
|
||||
object_get_typename(OBJECT(child)),
|
||||
(Object **)&kid->child,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
|
||||
{
|
||||
dev->parent_bus = bus;
|
||||
bus_add_child(bus, dev);
|
||||
}
|
||||
|
||||
/* Create a new device. This only initializes the device state structure
|
||||
@ -105,7 +115,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
|
||||
if (!dev) {
|
||||
if (bus) {
|
||||
hw_error("Unknown device '%s' for bus '%s'\n", name,
|
||||
bus->info->name);
|
||||
object_get_typename(OBJECT(bus)));
|
||||
} else {
|
||||
hw_error("Unknown device '%s' for default sysbus\n", name);
|
||||
}
|
||||
@ -131,7 +141,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
|
||||
}
|
||||
|
||||
qdev_set_parent_bus(dev, bus);
|
||||
qdev_prop_set_globals(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@ -210,18 +219,11 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BusState *sysbus_get_default(void)
|
||||
{
|
||||
if (!main_system_bus) {
|
||||
main_system_bus_create();
|
||||
}
|
||||
return main_system_bus;
|
||||
}
|
||||
|
||||
static int qbus_reset_one(BusState *bus, void *opaque)
|
||||
{
|
||||
if (bus->info->reset) {
|
||||
return bus->info->reset(bus);
|
||||
BusClass *bc = BUS_GET_CLASS(bus);
|
||||
if (bc->reset) {
|
||||
return bc->reset(bus);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -322,7 +324,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
if (nd->netdev)
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
qdev_prop_exists(dev, "vectors")) {
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
@ -343,7 +345,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
||||
qbus_walkerfn *busfn, void *opaque)
|
||||
{
|
||||
DeviceState *dev;
|
||||
BusChild *kid;
|
||||
int err;
|
||||
|
||||
if (busfn) {
|
||||
@ -353,8 +355,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
||||
}
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(dev, &bus->children, sibling) {
|
||||
err = qdev_walk_children(dev, devfn, busfn, opaque);
|
||||
QTAILQ_FOREACH(kid, &bus->children, sibling) {
|
||||
err = qdev_walk_children(kid->child, devfn, busfn, opaque);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
@ -388,12 +390,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
|
||||
|
||||
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
|
||||
{
|
||||
DeviceState *dev, *ret;
|
||||
BusChild *kid;
|
||||
DeviceState *ret;
|
||||
BusState *child;
|
||||
|
||||
QTAILQ_FOREACH(dev, &bus->children, sibling) {
|
||||
if (dev->id && strcmp(dev->id, id) == 0)
|
||||
QTAILQ_FOREACH(kid, &bus->children, sibling) {
|
||||
DeviceState *dev = kid->child;
|
||||
|
||||
if (dev->id && strcmp(dev->id, id) == 0) {
|
||||
return dev;
|
||||
}
|
||||
|
||||
QLIST_FOREACH(child, &dev->child_bus, sibling) {
|
||||
ret = qdev_find_recursive(child, id);
|
||||
if (ret) {
|
||||
@ -404,84 +411,87 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void qbus_create_inplace(BusState *bus, BusInfo *info,
|
||||
DeviceState *parent, const char *name)
|
||||
static void qbus_realize(BusState *bus)
|
||||
{
|
||||
const char *typename = object_get_typename(OBJECT(bus));
|
||||
char *buf;
|
||||
int i,len;
|
||||
|
||||
bus->info = info;
|
||||
bus->parent = parent;
|
||||
|
||||
if (name) {
|
||||
if (bus->name) {
|
||||
/* use supplied name */
|
||||
bus->name = g_strdup(name);
|
||||
} else if (parent && parent->id) {
|
||||
} else if (bus->parent && bus->parent->id) {
|
||||
/* parent device has id -> use it for bus name */
|
||||
len = strlen(parent->id) + 16;
|
||||
len = strlen(bus->parent->id) + 16;
|
||||
buf = g_malloc(len);
|
||||
snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
|
||||
snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
|
||||
bus->name = buf;
|
||||
} else {
|
||||
/* no id -> use lowercase bus type for bus name */
|
||||
len = strlen(info->name) + 16;
|
||||
len = strlen(typename) + 16;
|
||||
buf = g_malloc(len);
|
||||
len = snprintf(buf, len, "%s.%d", info->name,
|
||||
parent ? parent->num_child_bus : 0);
|
||||
len = snprintf(buf, len, "%s.%d", typename,
|
||||
bus->parent ? bus->parent->num_child_bus : 0);
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i] = qemu_tolower(buf[i]);
|
||||
bus->name = buf;
|
||||
}
|
||||
|
||||
QTAILQ_INIT(&bus->children);
|
||||
if (parent) {
|
||||
QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
|
||||
parent->num_child_bus++;
|
||||
} else if (bus != main_system_bus) {
|
||||
if (bus->parent) {
|
||||
QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
|
||||
bus->parent->num_child_bus++;
|
||||
object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
|
||||
} else if (bus != sysbus_get_default()) {
|
||||
/* TODO: once all bus devices are qdevified,
|
||||
only reset handler for main_system_bus should be registered here. */
|
||||
qemu_register_reset(qbus_reset_all_fn, bus);
|
||||
}
|
||||
}
|
||||
|
||||
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
|
||||
void qbus_create_inplace(BusState *bus, const char *typename,
|
||||
DeviceState *parent, const char *name)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
65
hw/qdev.h
65
hw/qdev.h
@ -17,7 +17,7 @@ typedef struct CompatProperty CompatProperty;
|
||||
|
||||
typedef struct BusState BusState;
|
||||
|
||||
typedef struct BusInfo BusInfo;
|
||||
typedef struct BusClass BusClass;
|
||||
|
||||
enum DevState {
|
||||
DEV_STATE_CREATED = 1,
|
||||
@ -55,7 +55,7 @@ typedef struct DeviceClass {
|
||||
qdev_initfn init;
|
||||
qdev_event unplug;
|
||||
qdev_event exit;
|
||||
BusInfo *bus_info;
|
||||
const char *bus_type;
|
||||
} DeviceClass;
|
||||
|
||||
/* This structure should not be accessed directly. We declare it here
|
||||
@ -74,38 +74,52 @@ struct DeviceState {
|
||||
qemu_irq *gpio_in;
|
||||
QLIST_HEAD(, BusState) child_bus;
|
||||
int num_child_bus;
|
||||
QTAILQ_ENTRY(DeviceState) sibling;
|
||||
int instance_id_alias;
|
||||
int alias_required_for_version;
|
||||
};
|
||||
|
||||
typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
|
||||
typedef char *(*bus_get_dev_path)(DeviceState *dev);
|
||||
/*
|
||||
* This callback is used to create Open Firmware device path in accordance with
|
||||
* OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings
|
||||
* can be found here http://playground.sun.com/1275/bindings/.
|
||||
*/
|
||||
typedef char *(*bus_get_fw_dev_path)(DeviceState *dev);
|
||||
typedef int (qbus_resetfn)(BusState *bus);
|
||||
|
||||
struct BusInfo {
|
||||
const char *name;
|
||||
size_t size;
|
||||
bus_dev_printfn print_dev;
|
||||
bus_get_dev_path get_dev_path;
|
||||
bus_get_fw_dev_path get_fw_dev_path;
|
||||
qbus_resetfn *reset;
|
||||
Property *props;
|
||||
#define TYPE_BUS "bus"
|
||||
#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
|
||||
#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
|
||||
#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
|
||||
|
||||
struct BusClass {
|
||||
ObjectClass parent_class;
|
||||
|
||||
/* FIXME first arg should be BusState */
|
||||
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
|
||||
char *(*get_dev_path)(DeviceState *dev);
|
||||
char *(*get_fw_dev_path)(DeviceState *dev);
|
||||
int (*reset)(BusState *bus);
|
||||
};
|
||||
|
||||
typedef struct BusChild {
|
||||
DeviceState *child;
|
||||
int index;
|
||||
QTAILQ_ENTRY(BusChild) sibling;
|
||||
} BusChild;
|
||||
|
||||
/**
|
||||
* BusState:
|
||||
* @qom_allocated: Indicates whether the object was allocated by QOM.
|
||||
* @glib_allocated: Indicates whether the object was initialized in-place
|
||||
* yet is expected to be freed with g_free().
|
||||
*/
|
||||
struct BusState {
|
||||
Object obj;
|
||||
DeviceState *parent;
|
||||
BusInfo *info;
|
||||
const char *name;
|
||||
int allow_hotplug;
|
||||
int qdev_allocated;
|
||||
QTAILQ_HEAD(ChildrenHead, DeviceState) children;
|
||||
bool qom_allocated;
|
||||
bool glib_allocated;
|
||||
int max_index;
|
||||
QTAILQ_HEAD(ChildrenHead, BusChild) children;
|
||||
QLIST_ENTRY(BusState) sibling;
|
||||
};
|
||||
|
||||
@ -175,9 +189,9 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id);
|
||||
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
|
||||
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
|
||||
|
||||
void qbus_create_inplace(BusState *bus, BusInfo *info,
|
||||
void qbus_create_inplace(BusState *bus, const char *typename,
|
||||
DeviceState *parent, const char *name);
|
||||
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
|
||||
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
|
||||
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
|
||||
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
|
||||
* 0 otherwise. */
|
||||
@ -292,7 +306,6 @@ extern PropertyInfo qdev_prop_blocksize;
|
||||
|
||||
/* Set properties between creation and init. */
|
||||
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
|
||||
int qdev_prop_exists(DeviceState *dev, const char *name);
|
||||
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
|
||||
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
|
||||
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
|
||||
@ -310,7 +323,6 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
|
||||
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
|
||||
/* FIXME: Remove opaque pointer properties. */
|
||||
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
|
||||
void qdev_prop_set_defaults(DeviceState *dev, Property *props);
|
||||
|
||||
void qdev_prop_register_global_list(GlobalProperty *props);
|
||||
void qdev_prop_set_globals(DeviceState *dev);
|
||||
@ -319,9 +331,6 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
||||
|
||||
char *qdev_get_fw_dev_path(DeviceState *dev);
|
||||
|
||||
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
|
||||
extern struct BusInfo system_bus_info;
|
||||
|
||||
/**
|
||||
* @qdev_property_add_static - add a @Property to a device referencing a
|
||||
* field in a struct.
|
||||
@ -347,10 +356,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
|
||||
|
||||
const char *qdev_fw_name(DeviceState *dev);
|
||||
|
||||
BusInfo *qdev_get_bus_info(DeviceState *dev);
|
||||
|
||||
Property *qdev_get_props(DeviceState *dev);
|
||||
|
||||
Object *qdev_get_machine(void);
|
||||
|
||||
/* FIXME: make this a link<> */
|
||||
@ -358,4 +363,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
|
||||
|
||||
extern int qdev_hotplug;
|
||||
|
||||
char *qdev_get_dev_path(DeviceState *dev);
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
29
hw/ssi.c
29
hw/ssi.c
@ -16,9 +16,13 @@ struct SSIBus {
|
||||
BusState qbus;
|
||||
};
|
||||
|
||||
static struct BusInfo ssi_bus_info = {
|
||||
.name = "SSI",
|
||||
.size = sizeof(SSIBus),
|
||||
#define TYPE_SSI_BUS "SSI"
|
||||
#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS)
|
||||
|
||||
static const TypeInfo ssi_bus_info = {
|
||||
.name = TYPE_SSI_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(SSIBus),
|
||||
};
|
||||
|
||||
static int ssi_slave_init(DeviceState *dev)
|
||||
@ -26,10 +30,11 @@ static int ssi_slave_init(DeviceState *dev)
|
||||
SSISlave *s = SSI_SLAVE(dev);
|
||||
SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
|
||||
SSIBus *bus;
|
||||
BusChild *kid;
|
||||
|
||||
bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
|
||||
if (QTAILQ_FIRST(&bus->qbus.children) != dev
|
||||
|| QTAILQ_NEXT(dev, sibling) != NULL) {
|
||||
kid = QTAILQ_FIRST(&bus->qbus.children);
|
||||
if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) {
|
||||
hw_error("Too many devices on SSI bus");
|
||||
}
|
||||
|
||||
@ -40,7 +45,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
dc->init = ssi_slave_init;
|
||||
dc->bus_info = &ssi_bus_info;
|
||||
dc->bus_type = TYPE_SSI_BUS;
|
||||
}
|
||||
|
||||
static TypeInfo ssi_slave_info = {
|
||||
@ -62,26 +67,28 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
|
||||
SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
|
||||
{
|
||||
BusState *bus;
|
||||
bus = qbus_create(&ssi_bus_info, parent, name);
|
||||
bus = qbus_create(TYPE_SSI_BUS, parent, name);
|
||||
return FROM_QBUS(SSIBus, bus);
|
||||
}
|
||||
|
||||
uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
|
||||
{
|
||||
DeviceState *dev;
|
||||
BusChild *kid;
|
||||
SSISlave *slave;
|
||||
SSISlaveClass *ssc;
|
||||
dev = QTAILQ_FIRST(&bus->qbus.children);
|
||||
if (!dev) {
|
||||
|
||||
kid = QTAILQ_FIRST(&bus->qbus.children);
|
||||
if (!kid) {
|
||||
return 0;
|
||||
}
|
||||
slave = SSI_SLAVE(dev);
|
||||
slave = SSI_SLAVE(kid->child);
|
||||
ssc = SSI_SLAVE_GET_CLASS(slave);
|
||||
return ssc->transfer(slave, val);
|
||||
}
|
||||
|
||||
static void ssi_slave_register_types(void)
|
||||
{
|
||||
type_register_static(&ssi_bus_info);
|
||||
type_register_static(&ssi_slave_info);
|
||||
}
|
||||
|
||||
|
45
hw/sysbus.c
45
hw/sysbus.c
@ -24,11 +24,19 @@
|
||||
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
||||
static char *sysbus_get_fw_dev_path(DeviceState *dev);
|
||||
|
||||
struct BusInfo system_bus_info = {
|
||||
.name = "System",
|
||||
.size = sizeof(BusState),
|
||||
.print_dev = sysbus_dev_print,
|
||||
.get_fw_dev_path = sysbus_get_fw_dev_path,
|
||||
static void system_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
|
||||
k->print_dev = sysbus_dev_print;
|
||||
k->get_fw_dev_path = sysbus_get_fw_dev_path;
|
||||
}
|
||||
|
||||
static const TypeInfo system_bus_info = {
|
||||
.name = TYPE_SYSTEM_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(BusState),
|
||||
.class_init = system_bus_class_init,
|
||||
};
|
||||
|
||||
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
||||
@ -244,7 +252,7 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = sysbus_device_init;
|
||||
k->bus_info = &system_bus_info;
|
||||
k->bus_type = TYPE_SYSTEM_BUS;
|
||||
}
|
||||
|
||||
static TypeInfo sysbus_device_type_info = {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
3
hw/usb.h
3
hw/usb.h
@ -421,6 +421,9 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
|
||||
|
||||
/* usb-bus.c */
|
||||
|
||||
#define TYPE_USB_BUS "usb-bus"
|
||||
#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS)
|
||||
|
||||
struct USBBus {
|
||||
BusState qbus;
|
||||
USBBusOps *ops;
|
||||
|
45
hw/usb/bus.c
45
hw/usb/bus.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
158
qom/object.c
158
qom/object.c
@ -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)
|
||||
|
12
savevm.c
12
savevm.c
@ -1248,8 +1248,8 @@ int register_savevm_live(DeviceState *dev,
|
||||
se->is_ram = 1;
|
||||
}
|
||||
|
||||
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
||||
char *id = dev->parent_bus->info->get_dev_path(dev);
|
||||
if (dev) {
|
||||
char *id = qdev_get_dev_path(dev);
|
||||
if (id) {
|
||||
pstrcpy(se->idstr, sizeof(se->idstr), id);
|
||||
pstrcat(se->idstr, sizeof(se->idstr), "/");
|
||||
@ -1292,8 +1292,8 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
|
||||
SaveStateEntry *se, *new_se;
|
||||
char id[256] = "";
|
||||
|
||||
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
||||
char *path = dev->parent_bus->info->get_dev_path(dev);
|
||||
if (dev) {
|
||||
char *path = qdev_get_dev_path(dev);
|
||||
if (path) {
|
||||
pstrcpy(id, sizeof(id), path);
|
||||
pstrcat(id, sizeof(id), "/");
|
||||
@ -1334,8 +1334,8 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
|
||||
se->alias_id = alias_id;
|
||||
se->no_migrate = vmsd->unmigratable;
|
||||
|
||||
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
||||
char *id = dev->parent_bus->info->get_dev_path(dev);
|
||||
if (dev) {
|
||||
char *id = qdev_get_dev_path(dev);
|
||||
if (id) {
|
||||
pstrcpy(se->idstr, sizeof(se->idstr), id);
|
||||
pstrcat(se->idstr, sizeof(se->idstr), "/");
|
||||
|
Loading…
Reference in New Issue
Block a user