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 | 32 | |
| 33 | 33 | struct DeviceProperty { |
| 34 | 34 | const char *name; |
| 35 | + DevicePropType type; | |
| 35 | 36 | union { |
| 36 | 37 | uint64_t i; |
| 37 | 38 | void *ptr; |
| ... | ... | @@ -119,13 +120,15 @@ void qdev_free(DeviceState *dev) |
| 119 | 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 | 126 | DeviceProperty *prop; |
| 125 | 127 | |
| 126 | 128 | /* TODO: Check for duplicate properties. */ |
| 127 | 129 | prop = qemu_mallocz(sizeof(*prop)); |
| 128 | 130 | prop->name = qemu_strdup(name); |
| 131 | + prop->type = type; | |
| 129 | 132 | prop->next = dev->props; |
| 130 | 133 | dev->props = prop; |
| 131 | 134 | |
| ... | ... | @@ -136,15 +139,23 @@ void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value) |
| 136 | 139 | { |
| 137 | 140 | DeviceProperty *prop; |
| 138 | 141 | |
| 139 | - prop = create_prop(dev, name); | |
| 142 | + prop = create_prop(dev, name, PROP_TYPE_INT); | |
| 140 | 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 | 154 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) |
| 144 | 155 | { |
| 145 | 156 | DeviceProperty *prop; |
| 146 | 157 | |
| 147 | - prop = create_prop(dev, name); | |
| 158 | + prop = create_prop(dev, name, PROP_TYPE_INT); | |
| 148 | 159 | prop->value.ptr = value; |
| 149 | 160 | } |
| 150 | 161 | |
| ... | ... | @@ -173,12 +184,14 @@ BusState *qdev_get_parent_bus(DeviceState *dev) |
| 173 | 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 | 190 | DeviceProperty *prop; |
| 179 | 191 | |
| 180 | 192 | for (prop = dev->props; prop; prop = prop->next) { |
| 181 | 193 | if (strcmp(prop->name, name) == 0) { |
| 194 | + assert (prop->type == type); | |
| 182 | 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 | 202 | { |
| 190 | 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 | 207 | return def; |
| 208 | + } | |
| 195 | 209 | |
| 196 | 210 | return prop->value.i; |
| 197 | 211 | } |
| ... | ... | @@ -200,11 +214,22 @@ void *qdev_get_prop_ptr(DeviceState *dev, const char *name) |
| 200 | 214 | { |
| 201 | 215 | DeviceProperty *prop; |
| 202 | 216 | |
| 203 | - prop = find_prop(dev, name); | |
| 217 | + prop = find_prop(dev, name, PROP_TYPE_PTR); | |
| 204 | 218 | assert(prop); |
| 205 | 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 | 233 | void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) |
| 209 | 234 | { |
| 210 | 235 | assert(dev->num_gpio_in == 0); | ... | ... |
hw/qdev.h
| ... | ... | @@ -49,6 +49,7 @@ void qdev_free(DeviceState *dev); |
| 49 | 49 | |
| 50 | 50 | /* Set properties between creation and init. */ |
| 51 | 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 | 53 | void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); |
| 53 | 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 | 60 | |
| 60 | 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 | 74 | typedef struct DeviceInfo DeviceInfo; |
| 63 | 75 | |
| 64 | 76 | typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info); |
| ... | ... | @@ -68,6 +80,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, |
| 68 | 80 | struct DeviceInfo { |
| 69 | 81 | qdev_initfn init; |
| 70 | 82 | BusType bus_type; |
| 83 | + DevicePropList *props; | |
| 71 | 84 | }; |
| 72 | 85 | |
| 73 | 86 | void qdev_register(const char *name, int size, DeviceInfo *info); |
| ... | ... | @@ -83,6 +96,8 @@ CharDriverState *qdev_init_chardev(DeviceState *dev); |
| 83 | 96 | |
| 84 | 97 | BusState *qdev_get_parent_bus(DeviceState *dev); |
| 85 | 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 | 101 | void *qdev_get_prop_ptr(DeviceState *dev, const char *name); |
| 87 | 102 | |
| 88 | 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 | 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 | 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 | 245 | device_init(syborg_timer_register_devices) | ... | ... |
hw/sysbus.c
| ... | ... | @@ -21,11 +21,6 @@ |
| 21 | 21 | #include "sysbus.h" |
| 22 | 22 | #include "sysemu.h" |
| 23 | 23 | |
| 24 | -typedef struct { | |
| 25 | - DeviceInfo qdev; | |
| 26 | - sysbus_initfn init; | |
| 27 | -} SysBusDeviceInfo; | |
| 28 | - | |
| 29 | 24 | void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) |
| 30 | 25 | { |
| 31 | 26 | assert(n >= 0 && n < dev->num_irq); |
| ... | ... | @@ -109,12 +104,9 @@ static void sysbus_device_init(DeviceState *dev, DeviceInfo *base) |
| 109 | 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 | 110 | info->qdev.init = sysbus_device_init; |
| 119 | 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 | 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 | 126 | DeviceState *sysbus_create_varargs(const char *name, |
| 126 | 127 | target_phys_addr_t addr, ...) |
| 127 | 128 | { | ... | ... |
hw/sysbus.h
| ... | ... | @@ -31,7 +31,14 @@ typedef void (*sysbus_initfn)(SysBusDevice *dev); |
| 31 | 31 | #define sysbus_from_qdev(dev) ((SysBusDevice *)(dev)) |
| 32 | 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 | 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 | 42 | void *sysbus_new(void); |
| 36 | 43 | void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc); |
| 37 | 44 | void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, | ... | ... |