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