aboutsummaryrefslogtreecommitdiff
path: root/hw/qdev.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-07-15 13:43:31 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-07-16 17:28:51 -0500
commitee6847d19be16c789b8bd4e553b7cd6701ba1245 (patch)
tree41845b3b1e8740ce97daf0582e124c6b6e0a6873 /hw/qdev.c
parentf114784f69ec3b9af342148025de14dbd1b429a5 (diff)
qdev: rework device properties.
This patch is a major overhaul of the device properties. The properties are saved directly in the device state struct now, the linked list of property values is gone. Advantages: * We don't have to maintain the list with the property values. * The value in the property list and the value actually used by the device can't go out of sync any more (used to happen for the pci.devfn == -1 case) because there is only one place where the value is stored. * A record describing the property is required now, you can't set random properties any more. There are bus-specific and device-specific properties. The former should be used for properties common to all bus drivers. Typical use case is bus addressing, i.e. pci.devfn and i2c.address. Properties have a PropertyInfo struct attached with name, size and function pointers to parse and print properties. A few common property types have PropertyInfos defined in qdev-properties.c. Drivers are free to implement their own very special property parsers if needed. Properties can have default values. If unset they are zero-filled. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/qdev.c')
-rw-r--r--hw/qdev.c141
1 files changed, 20 insertions, 121 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index 1bccf2ff27..64461e7eb2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -30,16 +30,6 @@
#include "sysemu.h"
#include "monitor.h"
-struct DeviceProperty {
- const char *name;
- DevicePropType type;
- union {
- uint64_t i;
- void *ptr;
- } value;
- DeviceProperty *next;
-};
-
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
extern struct BusInfo system_bus_info;
@@ -85,6 +75,8 @@ DeviceState *qdev_create(BusState *bus, const char *name)
dev = qemu_mallocz(info->size);
dev->info = info;
dev->parent_bus = bus;
+ qdev_prop_set_defaults(dev, dev->info->props);
+ qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
LIST_INSERT_HEAD(&bus->children, dev, sibling);
return dev;
}
@@ -104,52 +96,6 @@ void qdev_free(DeviceState *dev)
free(dev);
}
-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;
-
- return prop;
-}
-
-void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
-{
- DeviceProperty *prop;
-
- 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_TYPE_PTR);
- prop->value.ptr = value;
-}
-
-void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
-{
- assert(!dev->nd);
- dev->nd = nd;
-}
-
-
/* Get a character (serial) device interface. */
CharDriverState *qdev_init_chardev(DeviceState *dev)
{
@@ -168,52 +114,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
return dev->parent_bus;
}
-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;
- }
- }
- return NULL;
-}
-
-uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
-{
- DeviceProperty *prop;
-
- prop = find_prop(dev, name, PROP_TYPE_INT);
- if (!prop) {
- return def;
- }
-
- return prop->value.i;
-}
-
-void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
-{
- DeviceProperty *prop;
-
- 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);
@@ -326,9 +226,24 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
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)
+{
+ char buf[64];
+
+ if (!props)
+ return;
+ while (props->name) {
+ if (props->info->print) {
+ props->info->print(dev, props, buf, sizeof(buf));
+ qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
+ }
+ props++;
+ }
+}
+
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
{
- DeviceProperty *prop;
BusState *child;
qdev_printf("dev: %s\n", dev->info->name);
indent += 2;
@@ -338,24 +253,8 @@ 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);
}
- for (prop = dev->props; prop; prop = prop->next) {
- switch (prop->type) {
- case PROP_TYPE_INT:
- qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
- prop->value.i);
- break;
- case PROP_TYPE_PTR:
- qdev_printf("prop-ptr %s\n", prop->name);
- break;
- case PROP_TYPE_DEV:
- qdev_printf("prop-dev %s %s\n", prop->name,
- ((DeviceState *)prop->value.ptr)->info->name);
- break;
- default:
- qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
- break;
- }
- }
+ qdev_print_props(mon, dev, dev->info->props, "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);
LIST_FOREACH(child, &dev->child_bus, sibling) {