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 {
|
struct DeviceProperty {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
DevicePropType type;
|
||||||
union {
|
union {
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
@ -119,13 +120,15 @@ void qdev_free(DeviceState *dev)
|
||||||
free(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;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
/* TODO: Check for duplicate properties. */
|
/* TODO: Check for duplicate properties. */
|
||||||
prop = qemu_mallocz(sizeof(*prop));
|
prop = qemu_mallocz(sizeof(*prop));
|
||||||
prop->name = qemu_strdup(name);
|
prop->name = qemu_strdup(name);
|
||||||
|
prop->type = type;
|
||||||
prop->next = dev->props;
|
prop->next = dev->props;
|
||||||
dev->props = prop;
|
dev->props = prop;
|
||||||
|
|
||||||
|
@ -136,15 +139,23 @@ void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
|
||||||
{
|
{
|
||||||
DeviceProperty *prop;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
prop = create_prop(dev, name);
|
prop = create_prop(dev, name, PROP_TYPE_INT);
|
||||||
prop->value.i = value;
|
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)
|
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
|
||||||
{
|
{
|
||||||
DeviceProperty *prop;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
prop = create_prop(dev, name);
|
prop = create_prop(dev, name, PROP_TYPE_INT);
|
||||||
prop->value.ptr = value;
|
prop->value.ptr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,12 +184,14 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
|
||||||
return dev->parent_bus;
|
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;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
for (prop = dev->props; prop; prop = prop->next) {
|
for (prop = dev->props; prop; prop = prop->next) {
|
||||||
if (strcmp(prop->name, name) == 0) {
|
if (strcmp(prop->name, name) == 0) {
|
||||||
|
assert (prop->type == type);
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,9 +202,10 @@ uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
|
||||||
{
|
{
|
||||||
DeviceProperty *prop;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
prop = find_prop(dev, name);
|
prop = find_prop(dev, name, PROP_TYPE_INT);
|
||||||
if (!prop)
|
if (!prop) {
|
||||||
return def;
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
return prop->value.i;
|
return prop->value.i;
|
||||||
}
|
}
|
||||||
|
@ -200,11 +214,22 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
|
||||||
{
|
{
|
||||||
DeviceProperty *prop;
|
DeviceProperty *prop;
|
||||||
|
|
||||||
prop = find_prop(dev, name);
|
prop = find_prop(dev, name, PROP_TYPE_PTR);
|
||||||
assert(prop);
|
assert(prop);
|
||||||
return prop->value.ptr;
|
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)
|
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||||
{
|
{
|
||||||
assert(dev->num_gpio_in == 0);
|
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. */
|
/* Set properties between creation and init. */
|
||||||
void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value);
|
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_prop_ptr(DeviceState *dev, const char *name, void *value);
|
||||||
void qdev_set_netdev(DeviceState *dev, NICInfo *nd);
|
void qdev_set_netdev(DeviceState *dev, NICInfo *nd);
|
||||||
|
|
||||||
|
@ -59,6 +60,17 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
|
||||||
|
|
||||||
/*** Device API. ***/
|
/*** 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 struct DeviceInfo DeviceInfo;
|
||||||
|
|
||||||
typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
|
typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
|
||||||
|
@ -68,6 +80,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
|
||||||
struct DeviceInfo {
|
struct DeviceInfo {
|
||||||
qdev_initfn init;
|
qdev_initfn init;
|
||||||
BusType bus_type;
|
BusType bus_type;
|
||||||
|
DevicePropList *props;
|
||||||
};
|
};
|
||||||
|
|
||||||
void qdev_register(const char *name, int size, DeviceInfo *info);
|
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);
|
BusState *qdev_get_parent_bus(DeviceState *dev);
|
||||||
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def);
|
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);
|
void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
|
||||||
|
|
||||||
/* Convery from a base type to a parent type, with compile time checking. */
|
/* 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);
|
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)
|
static void syborg_timer_register_devices(void)
|
||||||
{
|
{
|
||||||
sysbus_register_dev("syborg,timer", sizeof(SyborgTimerState),
|
sysbus_register_withprop("syborg,timer", sizeof(SyborgTimerState),
|
||||||
syborg_timer_init);
|
&syborg_timer_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_init(syborg_timer_register_devices)
|
device_init(syborg_timer_register_devices)
|
||||||
|
|
21
hw/sysbus.c
21
hw/sysbus.c
|
@ -21,11 +21,6 @@
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DeviceInfo qdev;
|
|
||||||
sysbus_initfn init;
|
|
||||||
} SysBusDeviceInfo;
|
|
||||||
|
|
||||||
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
||||||
{
|
{
|
||||||
assert(n >= 0 && n < dev->num_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));
|
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)
|
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
|
||||||
{
|
{
|
||||||
SysBusDeviceInfo *info;
|
SysBusDeviceInfo *info;
|
||||||
|
|
||||||
info = qemu_mallocz(sizeof(*info));
|
info = qemu_mallocz(sizeof(*info));
|
||||||
info->init = init;
|
info->init = init;
|
||||||
info->qdev.init = sysbus_device_init;
|
sysbus_register_withprop(name, size, info);
|
||||||
info->qdev.bus_type = BUS_TYPE_SYSTEM;
|
|
||||||
|
|
||||||
assert(size >= sizeof(SysBusDevice));
|
|
||||||
qdev_register(name, size, &info->qdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceState *sysbus_create_varargs(const char *name,
|
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 sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
|
||||||
#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, 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_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_new(void);
|
||||||
void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc);
|
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,
|
void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
|
||||||
|
|
Loading…
Reference in a new issue