aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2009-06-05 15:52:04 +0100
committerPaul Brook <paul@codesourcery.com>2009-06-05 15:52:04 +0100
commit1431b6a17e6546569e09bcf8fb7773c925658d8f (patch)
tree83669665d82278a27b12d34d2fc1847944e784de /hw
parentfd93a79999c728dd1f30bb2e726ce12bdf704e6d (diff)
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>
Diffstat (limited to 'hw')
-rw-r--r--hw/qdev.c39
-rw-r--r--hw/qdev.h15
-rw-r--r--hw/syborg_timer.c14
-rw-r--r--hw/sysbus.c21
-rw-r--r--hw/sysbus.h7
5 files changed, 77 insertions, 19 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index cedb7728a9..a7025da9a7 100644
--- a/hw/qdev.c
+++ b/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);
diff --git a/hw/qdev.h b/hw/qdev.h
index b3cc3eceb6..5de0573fdb 100644
--- a/hw/qdev.h
+++ b/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. */
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index a84ad8602e..b833330e5b 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -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)
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 13d81f541f..a1843088e3 100644
--- a/hw/sysbus.c
+++ b/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,12 +104,9 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base)
info->init(sysbus_from_qdev(dev));
}
-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)
{
- SysBusDeviceInfo *info;
-
- info = qemu_mallocz(sizeof(*info));
- info->init = init;
info->qdev.init = sysbus_device_init;
info->qdev.bus_type = BUS_TYPE_SYSTEM;
@@ -122,6 +114,15 @@ void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
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;
+ sysbus_register_withprop(name, size, info);
+}
+
DeviceState *sysbus_create_varargs(const char *name,
target_phys_addr_t addr, ...)
{
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 44ed792d2d..2973661667 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -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,