diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2009-07-15 13:43:31 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-07-16 17:28:51 -0500 |
commit | ee6847d19be16c789b8bd4e553b7cd6701ba1245 (patch) | |
tree | 41845b3b1e8740ce97daf0582e124c6b6e0a6873 /hw/qdev.c | |
parent | f114784f69ec3b9af342148025de14dbd1b429a5 (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.c | 141 |
1 files changed, 20 insertions, 121 deletions
@@ -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) { |