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, |