Commit 1431b6a17e6546569e09bcf8fb7773c925658d8f
1 parent
fd93a799
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>
Showing
5 changed files
with
77 additions
and
19 deletions
hw/qdev.c
| @@ -32,6 +32,7 @@ | @@ -32,6 +32,7 @@ | ||
| 32 | 32 | ||
| 33 | struct DeviceProperty { | 33 | struct DeviceProperty { |
| 34 | const char *name; | 34 | const char *name; |
| 35 | + DevicePropType type; | ||
| 35 | union { | 36 | union { |
| 36 | uint64_t i; | 37 | uint64_t i; |
| 37 | void *ptr; | 38 | void *ptr; |
| @@ -119,13 +120,15 @@ void qdev_free(DeviceState *dev) | @@ -119,13 +120,15 @@ void qdev_free(DeviceState *dev) | ||
| 119 | free(dev); | 120 | free(dev); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | -static DeviceProperty *create_prop(DeviceState *dev, const char *name) | 123 | +static DeviceProperty *create_prop(DeviceState *dev, const char *name, |
| 124 | + DevicePropType type) | ||
| 123 | { | 125 | { |
| 124 | DeviceProperty *prop; | 126 | DeviceProperty *prop; |
| 125 | 127 | ||
| 126 | /* TODO: Check for duplicate properties. */ | 128 | /* TODO: Check for duplicate properties. */ |
| 127 | prop = qemu_mallocz(sizeof(*prop)); | 129 | prop = qemu_mallocz(sizeof(*prop)); |
| 128 | prop->name = qemu_strdup(name); | 130 | prop->name = qemu_strdup(name); |
| 131 | + prop->type = type; | ||
| 129 | prop->next = dev->props; | 132 | prop->next = dev->props; |
| 130 | dev->props = prop; | 133 | dev->props = prop; |
| 131 | 134 | ||
| @@ -136,15 +139,23 @@ void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value) | @@ -136,15 +139,23 @@ void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value) | ||
| 136 | { | 139 | { |
| 137 | DeviceProperty *prop; | 140 | DeviceProperty *prop; |
| 138 | 141 | ||
| 139 | - prop = create_prop(dev, name); | 142 | + prop = create_prop(dev, name, PROP_TYPE_INT); |
| 140 | prop->value.i = value; | 143 | prop->value.i = value; |
| 141 | } | 144 | } |
| 142 | 145 | ||
| 146 | +void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value) | ||
| 147 | +{ | ||
| 148 | + DeviceProperty *prop; | ||
| 149 | + | ||
| 150 | + prop = create_prop(dev, name, PROP_TYPE_DEV); | ||
| 151 | + prop->value.ptr = value; | ||
| 152 | +} | ||
| 153 | + | ||
| 143 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) | 154 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) |
| 144 | { | 155 | { |
| 145 | DeviceProperty *prop; | 156 | DeviceProperty *prop; |
| 146 | 157 | ||
| 147 | - prop = create_prop(dev, name); | 158 | + prop = create_prop(dev, name, PROP_TYPE_INT); |
| 148 | prop->value.ptr = value; | 159 | prop->value.ptr = value; |
| 149 | } | 160 | } |
| 150 | 161 | ||
| @@ -173,12 +184,14 @@ BusState *qdev_get_parent_bus(DeviceState *dev) | @@ -173,12 +184,14 @@ BusState *qdev_get_parent_bus(DeviceState *dev) | ||
| 173 | return dev->parent_bus; | 184 | return dev->parent_bus; |
| 174 | } | 185 | } |
| 175 | 186 | ||
| 176 | -static DeviceProperty *find_prop(DeviceState *dev, const char *name) | 187 | +static DeviceProperty *find_prop(DeviceState *dev, const char *name, |
| 188 | + DevicePropType type) | ||
| 177 | { | 189 | { |
| 178 | DeviceProperty *prop; | 190 | DeviceProperty *prop; |
| 179 | 191 | ||
| 180 | for (prop = dev->props; prop; prop = prop->next) { | 192 | for (prop = dev->props; prop; prop = prop->next) { |
| 181 | if (strcmp(prop->name, name) == 0) { | 193 | if (strcmp(prop->name, name) == 0) { |
| 194 | + assert (prop->type == type); | ||
| 182 | return prop; | 195 | return prop; |
| 183 | } | 196 | } |
| 184 | } | 197 | } |
| @@ -189,9 +202,10 @@ uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def) | @@ -189,9 +202,10 @@ uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def) | ||
| 189 | { | 202 | { |
| 190 | DeviceProperty *prop; | 203 | DeviceProperty *prop; |
| 191 | 204 | ||
| 192 | - prop = find_prop(dev, name); | ||
| 193 | - if (!prop) | 205 | + prop = find_prop(dev, name, PROP_TYPE_INT); |
| 206 | + if (!prop) { | ||
| 194 | return def; | 207 | return def; |
| 208 | + } | ||
| 195 | 209 | ||
| 196 | return prop->value.i; | 210 | return prop->value.i; |
| 197 | } | 211 | } |
| @@ -200,11 +214,22 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name) | @@ -200,11 +214,22 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name) | ||
| 200 | { | 214 | { |
| 201 | DeviceProperty *prop; | 215 | DeviceProperty *prop; |
| 202 | 216 | ||
| 203 | - prop = find_prop(dev, name); | 217 | + prop = find_prop(dev, name, PROP_TYPE_PTR); |
| 204 | assert(prop); | 218 | assert(prop); |
| 205 | return prop->value.ptr; | 219 | return prop->value.ptr; |
| 206 | } | 220 | } |
| 207 | 221 | ||
| 222 | +DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name) | ||
| 223 | +{ | ||
| 224 | + DeviceProperty *prop; | ||
| 225 | + | ||
| 226 | + prop = find_prop(dev, name, PROP_TYPE_DEV); | ||
| 227 | + if (!prop) { | ||
| 228 | + return NULL; | ||
| 229 | + } | ||
| 230 | + return prop->value.ptr; | ||
| 231 | +} | ||
| 232 | + | ||
| 208 | void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) | 233 | void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) |
| 209 | { | 234 | { |
| 210 | assert(dev->num_gpio_in == 0); | 235 | assert(dev->num_gpio_in == 0); |
hw/qdev.h
| @@ -49,6 +49,7 @@ void qdev_free(DeviceState *dev); | @@ -49,6 +49,7 @@ void qdev_free(DeviceState *dev); | ||
| 49 | 49 | ||
| 50 | /* Set properties between creation and init. */ | 50 | /* Set properties between creation and init. */ |
| 51 | void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value); | 51 | void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value); |
| 52 | +void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value); | ||
| 52 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); | 53 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); |
| 53 | void qdev_set_netdev(DeviceState *dev, NICInfo *nd); | 54 | void qdev_set_netdev(DeviceState *dev, NICInfo *nd); |
| 54 | 55 | ||
| @@ -59,6 +60,17 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); | @@ -59,6 +60,17 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); | ||
| 59 | 60 | ||
| 60 | /*** Device API. ***/ | 61 | /*** Device API. ***/ |
| 61 | 62 | ||
| 63 | +typedef enum { | ||
| 64 | + PROP_TYPE_INT, | ||
| 65 | + PROP_TYPE_PTR, | ||
| 66 | + PROP_TYPE_DEV | ||
| 67 | +} DevicePropType; | ||
| 68 | + | ||
| 69 | +typedef struct { | ||
| 70 | + const char *name; | ||
| 71 | + DevicePropType type; | ||
| 72 | +} DevicePropList; | ||
| 73 | + | ||
| 62 | typedef struct DeviceInfo DeviceInfo; | 74 | typedef struct DeviceInfo DeviceInfo; |
| 63 | 75 | ||
| 64 | typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info); | 76 | typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info); |
| @@ -68,6 +80,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, | @@ -68,6 +80,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, | ||
| 68 | struct DeviceInfo { | 80 | struct DeviceInfo { |
| 69 | qdev_initfn init; | 81 | qdev_initfn init; |
| 70 | BusType bus_type; | 82 | BusType bus_type; |
| 83 | + DevicePropList *props; | ||
| 71 | }; | 84 | }; |
| 72 | 85 | ||
| 73 | void qdev_register(const char *name, int size, DeviceInfo *info); | 86 | void qdev_register(const char *name, int size, DeviceInfo *info); |
| @@ -83,6 +96,8 @@ CharDriverState *qdev_init_chardev(DeviceState *dev); | @@ -83,6 +96,8 @@ CharDriverState *qdev_init_chardev(DeviceState *dev); | ||
| 83 | 96 | ||
| 84 | BusState *qdev_get_parent_bus(DeviceState *dev); | 97 | BusState *qdev_get_parent_bus(DeviceState *dev); |
| 85 | uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def); | 98 | uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def); |
| 99 | +DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name); | ||
| 100 | +/* FIXME: Remove opaque pointer properties. */ | ||
| 86 | void *qdev_get_prop_ptr(DeviceState *dev, const char *name); | 101 | void *qdev_get_prop_ptr(DeviceState *dev, const char *name); |
| 87 | 102 | ||
| 88 | /* Convery from a base type to a parent type, with compile time checking. */ | 103 | /* Convery from a base type to a parent type, with compile time checking. */ |
hw/syborg_timer.c
| @@ -226,10 +226,20 @@ static void syborg_timer_init(SysBusDevice *dev) | @@ -226,10 +226,20 @@ static void syborg_timer_init(SysBusDevice *dev) | ||
| 226 | syborg_timer_save, syborg_timer_load, s); | 226 | syborg_timer_save, syborg_timer_load, s); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | +static SysBusDeviceInfo syborg_timer_info = { | ||
| 230 | + .init = syborg_timer_init, | ||
| 231 | + .qdev = { | ||
| 232 | + .props = (DevicePropList[]) { | ||
| 233 | + {.name = "frequency", .type = PROP_TYPE_INT}, | ||
| 234 | + {.name = NULL} | ||
| 235 | + } | ||
| 236 | + } | ||
| 237 | +}; | ||
| 238 | + | ||
| 229 | static void syborg_timer_register_devices(void) | 239 | static void syborg_timer_register_devices(void) |
| 230 | { | 240 | { |
| 231 | - sysbus_register_dev("syborg,timer", sizeof(SyborgTimerState), | ||
| 232 | - syborg_timer_init); | 241 | + sysbus_register_withprop("syborg,timer", sizeof(SyborgTimerState), |
| 242 | + &syborg_timer_info); | ||
| 233 | } | 243 | } |
| 234 | 244 | ||
| 235 | device_init(syborg_timer_register_devices) | 245 | device_init(syborg_timer_register_devices) |
hw/sysbus.c
| @@ -21,11 +21,6 @@ | @@ -21,11 +21,6 @@ | ||
| 21 | #include "sysbus.h" | 21 | #include "sysbus.h" |
| 22 | #include "sysemu.h" | 22 | #include "sysemu.h" |
| 23 | 23 | ||
| 24 | -typedef struct { | ||
| 25 | - DeviceInfo qdev; | ||
| 26 | - sysbus_initfn init; | ||
| 27 | -} SysBusDeviceInfo; | ||
| 28 | - | ||
| 29 | void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) | 24 | void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) |
| 30 | { | 25 | { |
| 31 | assert(n >= 0 && n < dev->num_irq); | 26 | assert(n >= 0 && n < dev->num_irq); |
| @@ -109,12 +104,9 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base) | @@ -109,12 +104,9 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base) | ||
| 109 | info->init(sysbus_from_qdev(dev)); | 104 | info->init(sysbus_from_qdev(dev)); |
| 110 | } | 105 | } |
| 111 | 106 | ||
| 112 | -void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) | 107 | +void sysbus_register_withprop(const char *name, size_t size, |
| 108 | + SysBusDeviceInfo *info) | ||
| 113 | { | 109 | { |
| 114 | - SysBusDeviceInfo *info; | ||
| 115 | - | ||
| 116 | - info = qemu_mallocz(sizeof(*info)); | ||
| 117 | - info->init = init; | ||
| 118 | info->qdev.init = sysbus_device_init; | 110 | info->qdev.init = sysbus_device_init; |
| 119 | info->qdev.bus_type = BUS_TYPE_SYSTEM; | 111 | info->qdev.bus_type = BUS_TYPE_SYSTEM; |
| 120 | 112 | ||
| @@ -122,6 +114,15 @@ void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) | @@ -122,6 +114,15 @@ void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) | ||
| 122 | qdev_register(name, size, &info->qdev); | 114 | qdev_register(name, size, &info->qdev); |
| 123 | } | 115 | } |
| 124 | 116 | ||
| 117 | +void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) | ||
| 118 | +{ | ||
| 119 | + SysBusDeviceInfo *info; | ||
| 120 | + | ||
| 121 | + info = qemu_mallocz(sizeof(*info)); | ||
| 122 | + info->init = init; | ||
| 123 | + sysbus_register_withprop(name, size, info); | ||
| 124 | +} | ||
| 125 | + | ||
| 125 | DeviceState *sysbus_create_varargs(const char *name, | 126 | DeviceState *sysbus_create_varargs(const char *name, |
| 126 | target_phys_addr_t addr, ...) | 127 | target_phys_addr_t addr, ...) |
| 127 | { | 128 | { |
hw/sysbus.h
| @@ -31,7 +31,14 @@ typedef void (*sysbus_initfn)(SysBusDevice *dev); | @@ -31,7 +31,14 @@ typedef void (*sysbus_initfn)(SysBusDevice *dev); | ||
| 31 | #define sysbus_from_qdev(dev) ((SysBusDevice *)(dev)) | 31 | #define sysbus_from_qdev(dev) ((SysBusDevice *)(dev)) |
| 32 | #define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev) | 32 | #define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev) |
| 33 | 33 | ||
| 34 | +typedef struct { | ||
| 35 | + DeviceInfo qdev; | ||
| 36 | + sysbus_initfn init; | ||
| 37 | +} SysBusDeviceInfo; | ||
| 38 | + | ||
| 34 | void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init); | 39 | void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init); |
| 40 | +void sysbus_register_withprop(const char *name, size_t size, | ||
| 41 | + SysBusDeviceInfo *info); | ||
| 35 | void *sysbus_new(void); | 42 | void *sysbus_new(void); |
| 36 | void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc); | 43 | void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc); |
| 37 | void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, | 44 | void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, |