Record device property types
Record device property types, and provide a list of properties at device registration time. Add a "device" property type that holds a reference to annother device. Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
parent
fd93a79999
commit
1431b6a17e
39
hw/qdev.c
39
hw/qdev.c
@ -32,6 +32,7 @@
|
||||
|
||||
struct DeviceProperty {
|
||||
const char *name;
|
||||
DevicePropType type;
|
||||
union {
|
||||
uint64_t i;
|
||||
void *ptr;
|
||||
@ -119,13 +120,15 @@ void qdev_free(DeviceState *dev)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static DeviceProperty *create_prop(DeviceState *dev, const char *name)
|
||||
static DeviceProperty *create_prop(DeviceState *dev, const char *name,
|
||||
DevicePropType type)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
/* TODO: Check for duplicate properties. */
|
||||
prop = qemu_mallocz(sizeof(*prop));
|
||||
prop->name = qemu_strdup(name);
|
||||
prop->type = type;
|
||||
prop->next = dev->props;
|
||||
dev->props = prop;
|
||||
|
||||
@ -136,15 +139,23 @@ void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = create_prop(dev, name);
|
||||
prop = create_prop(dev, name, PROP_TYPE_INT);
|
||||
prop->value.i = value;
|
||||
}
|
||||
|
||||
void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = create_prop(dev, name, PROP_TYPE_DEV);
|
||||
prop->value.ptr = value;
|
||||
}
|
||||
|
||||
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = create_prop(dev, name);
|
||||
prop = create_prop(dev, name, PROP_TYPE_INT);
|
||||
prop->value.ptr = value;
|
||||
}
|
||||
|
||||
@ -173,12 +184,14 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
|
||||
return dev->parent_bus;
|
||||
}
|
||||
|
||||
static DeviceProperty *find_prop(DeviceState *dev, const char *name)
|
||||
static DeviceProperty *find_prop(DeviceState *dev, const char *name,
|
||||
DevicePropType type)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
for (prop = dev->props; prop; prop = prop->next) {
|
||||
if (strcmp(prop->name, name) == 0) {
|
||||
assert (prop->type == type);
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
@ -189,9 +202,10 @@ uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = find_prop(dev, name);
|
||||
if (!prop)
|
||||
prop = find_prop(dev, name, PROP_TYPE_INT);
|
||||
if (!prop) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return prop->value.i;
|
||||
}
|
||||
@ -200,11 +214,22 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = find_prop(dev, name);
|
||||
prop = find_prop(dev, name, PROP_TYPE_PTR);
|
||||
assert(prop);
|
||||
return prop->value.ptr;
|
||||
}
|
||||
|
||||
DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
|
||||
{
|
||||
DeviceProperty *prop;
|
||||
|
||||
prop = find_prop(dev, name, PROP_TYPE_DEV);
|
||||
if (!prop) {
|
||||
return NULL;
|
||||
}
|
||||
return prop->value.ptr;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||
{
|
||||
assert(dev->num_gpio_in == 0);
|
||||
|
15
hw/qdev.h
15
hw/qdev.h
@ -49,6 +49,7 @@ void qdev_free(DeviceState *dev);
|
||||
|
||||
/* Set properties between creation and init. */
|
||||
void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value);
|
||||
void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value);
|
||||
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value);
|
||||
void qdev_set_netdev(DeviceState *dev, NICInfo *nd);
|
||||
|
||||
@ -59,6 +60,17 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
|
||||
|
||||
/*** Device API. ***/
|
||||
|
||||
typedef enum {
|
||||
PROP_TYPE_INT,
|
||||
PROP_TYPE_PTR,
|
||||
PROP_TYPE_DEV
|
||||
} DevicePropType;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
DevicePropType type;
|
||||
} DevicePropList;
|
||||
|
||||
typedef struct DeviceInfo DeviceInfo;
|
||||
|
||||
typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
|
||||
@ -68,6 +80,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
|
||||
struct DeviceInfo {
|
||||
qdev_initfn init;
|
||||
BusType bus_type;
|
||||
DevicePropList *props;
|
||||
};
|
||||
|
||||
void qdev_register(const char *name, int size, DeviceInfo *info);
|
||||
@ -83,6 +96,8 @@ CharDriverState *qdev_init_chardev(DeviceState *dev);
|
||||
|
||||
BusState *qdev_get_parent_bus(DeviceState *dev);
|
||||
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def);
|
||||
DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name);
|
||||
/* FIXME: Remove opaque pointer properties. */
|
||||
void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
|
||||
|
||||
/* Convery from a base type to a parent type, with compile time checking. */
|
||||
|
@ -226,10 +226,20 @@ static void syborg_timer_init(SysBusDevice *dev)
|
||||
syborg_timer_save, syborg_timer_load, s);
|
||||
}
|
||||
|
||||
static SysBusDeviceInfo syborg_timer_info = {
|
||||
.init = syborg_timer_init,
|
||||
.qdev = {
|
||||
.props = (DevicePropList[]) {
|
||||
{.name = "frequency", .type = PROP_TYPE_INT},
|
||||
{.name = NULL}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void syborg_timer_register_devices(void)
|
||||
{
|
||||
sysbus_register_dev("syborg,timer", sizeof(SyborgTimerState),
|
||||
syborg_timer_init);
|
||||
sysbus_register_withprop("syborg,timer", sizeof(SyborgTimerState),
|
||||
&syborg_timer_info);
|
||||
}
|
||||
|
||||
device_init(syborg_timer_register_devices)
|
||||
|
21
hw/sysbus.c
21
hw/sysbus.c
@ -21,11 +21,6 @@
|
||||
#include "sysbus.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
typedef struct {
|
||||
DeviceInfo qdev;
|
||||
sysbus_initfn init;
|
||||
} SysBusDeviceInfo;
|
||||
|
||||
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
||||
{
|
||||
assert(n >= 0 && n < dev->num_irq);
|
||||
@ -109,17 +104,23 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base)
|
||||
info->init(sysbus_from_qdev(dev));
|
||||
}
|
||||
|
||||
void sysbus_register_withprop(const char *name, size_t size,
|
||||
SysBusDeviceInfo *info)
|
||||
{
|
||||
info->qdev.init = sysbus_device_init;
|
||||
info->qdev.bus_type = BUS_TYPE_SYSTEM;
|
||||
|
||||
assert(size >= sizeof(SysBusDevice));
|
||||
qdev_register(name, size, &info->qdev);
|
||||
}
|
||||
|
||||
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
|
||||
{
|
||||
SysBusDeviceInfo *info;
|
||||
|
||||
info = qemu_mallocz(sizeof(*info));
|
||||
info->init = init;
|
||||
info->qdev.init = sysbus_device_init;
|
||||
info->qdev.bus_type = BUS_TYPE_SYSTEM;
|
||||
|
||||
assert(size >= sizeof(SysBusDevice));
|
||||
qdev_register(name, size, &info->qdev);
|
||||
sysbus_register_withprop(name, size, info);
|
||||
}
|
||||
|
||||
DeviceState *sysbus_create_varargs(const char *name,
|
||||
|
@ -31,7 +31,14 @@ typedef void (*sysbus_initfn)(SysBusDevice *dev);
|
||||
#define sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
|
||||
#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev)
|
||||
|
||||
typedef struct {
|
||||
DeviceInfo qdev;
|
||||
sysbus_initfn init;
|
||||
} SysBusDeviceInfo;
|
||||
|
||||
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
|
||||
void sysbus_register_withprop(const char *name, size_t size,
|
||||
SysBusDeviceInfo *info);
|
||||
void *sysbus_new(void);
|
||||
void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc);
|
||||
void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
|
||||
|
Loading…
Reference in New Issue
Block a user