]>
Commit | Line | Data |
---|---|---|
14b41872 | 1 | #include "sysemu.h" |
1503fff3 | 2 | #include "net.h" |
ee6847d1 GH |
3 | #include "qdev.h" |
4 | ||
5 | void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) | |
6 | { | |
7 | void *ptr = dev; | |
8 | ptr += prop->offset; | |
9 | return ptr; | |
10 | } | |
11 | ||
d2364ee4 MT |
12 | static uint32_t qdev_get_prop_mask(Property *prop) |
13 | { | |
14 | assert(prop->info->type == PROP_TYPE_BIT); | |
15 | return 0x1 << prop->bitnr; | |
16 | } | |
17 | ||
18 | static void bit_prop_set(DeviceState *dev, Property *props, bool val) | |
19 | { | |
20 | uint32_t *p = qdev_get_prop_ptr(dev, props); | |
21 | uint32_t mask = qdev_get_prop_mask(props); | |
22 | if (val) | |
dbd48324 | 23 | *p |= mask; |
d2364ee4 MT |
24 | else |
25 | *p &= ~mask; | |
26 | } | |
27 | ||
28 | static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src) | |
29 | { | |
30 | if (props->info->type == PROP_TYPE_BIT) { | |
31 | bool *defval = src; | |
32 | bit_prop_set(dev, props, *defval); | |
33 | } else { | |
34 | char *dst = qdev_get_prop_ptr(dev, props); | |
35 | memcpy(dst, src, props->info->size); | |
36 | } | |
37 | } | |
38 | ||
39 | /* Bit */ | |
40 | static int parse_bit(DeviceState *dev, Property *prop, const char *str) | |
41 | { | |
42 | if (!strncasecmp(str, "on", 2)) | |
43 | bit_prop_set(dev, prop, true); | |
44 | else if (!strncasecmp(str, "off", 3)) | |
45 | bit_prop_set(dev, prop, false); | |
46 | else | |
6bf38816 | 47 | return -EINVAL; |
d2364ee4 MT |
48 | return 0; |
49 | } | |
50 | ||
51 | static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) | |
52 | { | |
53 | uint8_t *p = qdev_get_prop_ptr(dev, prop); | |
54 | return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off"); | |
55 | } | |
56 | ||
57 | PropertyInfo qdev_prop_bit = { | |
58 | .name = "on/off", | |
59 | .type = PROP_TYPE_BIT, | |
60 | .size = sizeof(uint32_t), | |
61 | .parse = parse_bit, | |
62 | .print = print_bit, | |
63 | }; | |
64 | ||
c7cc172d JQ |
65 | /* --- 8bit integer --- */ |
66 | ||
67 | static int parse_uint8(DeviceState *dev, Property *prop, const char *str) | |
68 | { | |
69 | uint8_t *ptr = qdev_get_prop_ptr(dev, prop); | |
70 | const char *fmt; | |
71 | ||
72 | /* accept both hex and decimal */ | |
73 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx8 : "%" PRIu8; | |
74 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 75 | return -EINVAL; |
c7cc172d JQ |
76 | return 0; |
77 | } | |
78 | ||
79 | static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len) | |
80 | { | |
81 | uint8_t *ptr = qdev_get_prop_ptr(dev, prop); | |
82 | return snprintf(dest, len, "%" PRIu8, *ptr); | |
83 | } | |
84 | ||
85 | PropertyInfo qdev_prop_uint8 = { | |
86 | .name = "uint8", | |
87 | .type = PROP_TYPE_UINT8, | |
88 | .size = sizeof(uint8_t), | |
89 | .parse = parse_uint8, | |
90 | .print = print_uint8, | |
91 | }; | |
92 | ||
ee6847d1 GH |
93 | /* --- 16bit integer --- */ |
94 | ||
95 | static int parse_uint16(DeviceState *dev, Property *prop, const char *str) | |
96 | { | |
97 | uint16_t *ptr = qdev_get_prop_ptr(dev, prop); | |
98 | const char *fmt; | |
99 | ||
100 | /* accept both hex and decimal */ | |
101 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16; | |
102 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 103 | return -EINVAL; |
ee6847d1 GH |
104 | return 0; |
105 | } | |
106 | ||
107 | static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len) | |
108 | { | |
109 | uint16_t *ptr = qdev_get_prop_ptr(dev, prop); | |
110 | return snprintf(dest, len, "%" PRIu16, *ptr); | |
111 | } | |
112 | ||
113 | PropertyInfo qdev_prop_uint16 = { | |
114 | .name = "uint16", | |
115 | .type = PROP_TYPE_UINT16, | |
116 | .size = sizeof(uint16_t), | |
117 | .parse = parse_uint16, | |
118 | .print = print_uint16, | |
119 | }; | |
120 | ||
121 | /* --- 32bit integer --- */ | |
122 | ||
123 | static int parse_uint32(DeviceState *dev, Property *prop, const char *str) | |
124 | { | |
125 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
126 | const char *fmt; | |
127 | ||
128 | /* accept both hex and decimal */ | |
129 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32; | |
130 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 131 | return -EINVAL; |
ee6847d1 GH |
132 | return 0; |
133 | } | |
134 | ||
135 | static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
136 | { | |
137 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
138 | return snprintf(dest, len, "%" PRIu32, *ptr); | |
139 | } | |
140 | ||
141 | PropertyInfo qdev_prop_uint32 = { | |
142 | .name = "uint32", | |
143 | .type = PROP_TYPE_UINT32, | |
144 | .size = sizeof(uint32_t), | |
145 | .parse = parse_uint32, | |
146 | .print = print_uint32, | |
147 | }; | |
148 | ||
316940b0 GH |
149 | static int parse_int32(DeviceState *dev, Property *prop, const char *str) |
150 | { | |
151 | int32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
152 | ||
153 | if (sscanf(str, "%" PRId32, ptr) != 1) | |
6bf38816 | 154 | return -EINVAL; |
316940b0 GH |
155 | return 0; |
156 | } | |
157 | ||
158 | static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
159 | { | |
160 | int32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
161 | return snprintf(dest, len, "%" PRId32, *ptr); | |
162 | } | |
163 | ||
164 | PropertyInfo qdev_prop_int32 = { | |
165 | .name = "int32", | |
166 | .type = PROP_TYPE_INT32, | |
167 | .size = sizeof(int32_t), | |
168 | .parse = parse_int32, | |
169 | .print = print_int32, | |
170 | }; | |
171 | ||
ee6847d1 GH |
172 | /* --- 32bit hex value --- */ |
173 | ||
174 | static int parse_hex32(DeviceState *dev, Property *prop, const char *str) | |
175 | { | |
176 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
177 | ||
178 | if (sscanf(str, "%" PRIx32, ptr) != 1) | |
6bf38816 | 179 | return -EINVAL; |
ee6847d1 GH |
180 | return 0; |
181 | } | |
182 | ||
183 | static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
184 | { | |
185 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
186 | return snprintf(dest, len, "0x%" PRIx32, *ptr); | |
187 | } | |
188 | ||
189 | PropertyInfo qdev_prop_hex32 = { | |
190 | .name = "hex32", | |
191 | .type = PROP_TYPE_UINT32, | |
192 | .size = sizeof(uint32_t), | |
193 | .parse = parse_hex32, | |
194 | .print = print_hex32, | |
195 | }; | |
196 | ||
5a053d1f BS |
197 | /* --- 64bit integer --- */ |
198 | ||
199 | static int parse_uint64(DeviceState *dev, Property *prop, const char *str) | |
200 | { | |
201 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
202 | const char *fmt; | |
203 | ||
204 | /* accept both hex and decimal */ | |
205 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64; | |
206 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 207 | return -EINVAL; |
5a053d1f BS |
208 | return 0; |
209 | } | |
210 | ||
211 | static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len) | |
212 | { | |
213 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
214 | return snprintf(dest, len, "%" PRIu64, *ptr); | |
215 | } | |
216 | ||
217 | PropertyInfo qdev_prop_uint64 = { | |
218 | .name = "uint64", | |
219 | .type = PROP_TYPE_UINT64, | |
220 | .size = sizeof(uint64_t), | |
221 | .parse = parse_uint64, | |
222 | .print = print_uint64, | |
223 | }; | |
224 | ||
225 | /* --- 64bit hex value --- */ | |
226 | ||
227 | static int parse_hex64(DeviceState *dev, Property *prop, const char *str) | |
228 | { | |
229 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
230 | ||
231 | if (sscanf(str, "%" PRIx64, ptr) != 1) | |
6bf38816 | 232 | return -EINVAL; |
5a053d1f BS |
233 | return 0; |
234 | } | |
235 | ||
236 | static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len) | |
237 | { | |
238 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
239 | return snprintf(dest, len, "0x%" PRIx64, *ptr); | |
240 | } | |
241 | ||
242 | PropertyInfo qdev_prop_hex64 = { | |
243 | .name = "hex64", | |
244 | .type = PROP_TYPE_UINT64, | |
245 | .size = sizeof(uint64_t), | |
246 | .parse = parse_hex64, | |
247 | .print = print_hex64, | |
248 | }; | |
249 | ||
59419663 GH |
250 | /* --- string --- */ |
251 | ||
252 | static int parse_string(DeviceState *dev, Property *prop, const char *str) | |
253 | { | |
254 | char **ptr = qdev_get_prop_ptr(dev, prop); | |
255 | ||
256 | if (*ptr) | |
257 | qemu_free(*ptr); | |
258 | *ptr = qemu_strdup(str); | |
259 | return 0; | |
260 | } | |
261 | ||
262 | static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) | |
263 | { | |
264 | char **ptr = qdev_get_prop_ptr(dev, prop); | |
265 | if (!*ptr) | |
266 | return snprintf(dest, len, "<null>"); | |
267 | return snprintf(dest, len, "\"%s\"", *ptr); | |
268 | } | |
269 | ||
270 | PropertyInfo qdev_prop_string = { | |
271 | .name = "string", | |
272 | .type = PROP_TYPE_STRING, | |
273 | .size = sizeof(char*), | |
274 | .parse = parse_string, | |
275 | .print = print_string, | |
276 | }; | |
277 | ||
14b41872 GH |
278 | /* --- drive --- */ |
279 | ||
280 | static int parse_drive(DeviceState *dev, Property *prop, const char *str) | |
281 | { | |
282 | DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); | |
283 | ||
284 | *ptr = drive_get_by_id(str); | |
285 | if (*ptr == NULL) | |
6bf38816 | 286 | return -ENOENT; |
14b41872 GH |
287 | return 0; |
288 | } | |
289 | ||
290 | static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) | |
291 | { | |
292 | DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); | |
41b5e892 | 293 | return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>"); |
14b41872 GH |
294 | } |
295 | ||
296 | PropertyInfo qdev_prop_drive = { | |
297 | .name = "drive", | |
298 | .type = PROP_TYPE_DRIVE, | |
299 | .size = sizeof(DriveInfo*), | |
300 | .parse = parse_drive, | |
301 | .print = print_drive, | |
302 | }; | |
303 | ||
313feaab GH |
304 | /* --- character device --- */ |
305 | ||
06113719 GH |
306 | static int parse_chr(DeviceState *dev, Property *prop, const char *str) |
307 | { | |
308 | CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); | |
309 | ||
310 | *ptr = qemu_chr_find(str); | |
311 | if (*ptr == NULL) | |
6bf38816 | 312 | return -ENOENT; |
06113719 GH |
313 | return 0; |
314 | } | |
315 | ||
313feaab GH |
316 | static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len) |
317 | { | |
318 | CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); | |
bc19fcaa BS |
319 | |
320 | if (*ptr && (*ptr)->label) { | |
321 | return snprintf(dest, len, "%s", (*ptr)->label); | |
322 | } else { | |
323 | return snprintf(dest, len, "<null>"); | |
324 | } | |
313feaab GH |
325 | } |
326 | ||
327 | PropertyInfo qdev_prop_chr = { | |
328 | .name = "chr", | |
329 | .type = PROP_TYPE_CHR, | |
330 | .size = sizeof(CharDriverState*), | |
06113719 | 331 | .parse = parse_chr, |
313feaab GH |
332 | .print = print_chr, |
333 | }; | |
334 | ||
2ef924b4 GH |
335 | /* --- netdev device --- */ |
336 | ||
337 | static int parse_netdev(DeviceState *dev, Property *prop, const char *str) | |
338 | { | |
339 | VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); | |
340 | ||
341 | *ptr = qemu_find_netdev(str); | |
342 | if (*ptr == NULL) | |
6bf38816 | 343 | return -ENOENT; |
27f3f8a3 MA |
344 | if ((*ptr)->peer) { |
345 | return -EEXIST; | |
346 | } | |
2ef924b4 GH |
347 | return 0; |
348 | } | |
349 | ||
350 | static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len) | |
351 | { | |
352 | VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); | |
353 | ||
354 | if (*ptr && (*ptr)->name) { | |
355 | return snprintf(dest, len, "%s", (*ptr)->name); | |
356 | } else { | |
357 | return snprintf(dest, len, "<null>"); | |
358 | } | |
359 | } | |
360 | ||
361 | PropertyInfo qdev_prop_netdev = { | |
362 | .name = "netdev", | |
363 | .type = PROP_TYPE_NETDEV, | |
364 | .size = sizeof(VLANClientState*), | |
365 | .parse = parse_netdev, | |
366 | .print = print_netdev, | |
367 | }; | |
368 | ||
851bec09 GH |
369 | /* --- vlan --- */ |
370 | ||
371 | static int parse_vlan(DeviceState *dev, Property *prop, const char *str) | |
372 | { | |
373 | VLANState **ptr = qdev_get_prop_ptr(dev, prop); | |
374 | int id; | |
375 | ||
376 | if (sscanf(str, "%d", &id) != 1) | |
6bf38816 | 377 | return -EINVAL; |
851bec09 GH |
378 | *ptr = qemu_find_vlan(id, 1); |
379 | if (*ptr == NULL) | |
6bf38816 | 380 | return -ENOENT; |
851bec09 GH |
381 | return 0; |
382 | } | |
383 | ||
384 | static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) | |
385 | { | |
386 | VLANState **ptr = qdev_get_prop_ptr(dev, prop); | |
387 | ||
388 | if (*ptr) { | |
389 | return snprintf(dest, len, "%d", (*ptr)->id); | |
390 | } else { | |
391 | return snprintf(dest, len, "<null>"); | |
392 | } | |
393 | } | |
394 | ||
395 | PropertyInfo qdev_prop_vlan = { | |
396 | .name = "vlan", | |
397 | .type = PROP_TYPE_VLAN, | |
398 | .size = sizeof(VLANClientState*), | |
399 | .parse = parse_vlan, | |
400 | .print = print_vlan, | |
401 | }; | |
402 | ||
ee6847d1 GH |
403 | /* --- pointer --- */ |
404 | ||
036f7166 | 405 | /* Not a proper property, just for dirty hacks. TODO Remove it! */ |
ee6847d1 GH |
406 | PropertyInfo qdev_prop_ptr = { |
407 | .name = "ptr", | |
408 | .type = PROP_TYPE_PTR, | |
409 | .size = sizeof(void*), | |
ee6847d1 GH |
410 | }; |
411 | ||
412 | /* --- mac address --- */ | |
413 | ||
414 | /* | |
415 | * accepted syntax versions: | |
416 | * 01:02:03:04:05:06 | |
417 | * 01-02-03-04-05-06 | |
418 | */ | |
419 | static int parse_mac(DeviceState *dev, Property *prop, const char *str) | |
420 | { | |
1503fff3 | 421 | MACAddr *mac = qdev_get_prop_ptr(dev, prop); |
ee6847d1 GH |
422 | int i, pos; |
423 | char *p; | |
424 | ||
425 | for (i = 0, pos = 0; i < 6; i++, pos += 3) { | |
88e150a5 | 426 | if (!qemu_isxdigit(str[pos])) |
6bf38816 | 427 | return -EINVAL; |
88e150a5 | 428 | if (!qemu_isxdigit(str[pos+1])) |
6bf38816 | 429 | return -EINVAL; |
1503fff3 GH |
430 | if (i == 5) { |
431 | if (str[pos+2] != '\0') | |
6bf38816 | 432 | return -EINVAL; |
1503fff3 GH |
433 | } else { |
434 | if (str[pos+2] != ':' && str[pos+2] != '-') | |
6bf38816 | 435 | return -EINVAL; |
1503fff3 GH |
436 | } |
437 | mac->a[i] = strtol(str+pos, &p, 16); | |
ee6847d1 GH |
438 | } |
439 | return 0; | |
440 | } | |
441 | ||
442 | static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len) | |
443 | { | |
1503fff3 GH |
444 | MACAddr *mac = qdev_get_prop_ptr(dev, prop); |
445 | ||
ee6847d1 | 446 | return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x", |
1503fff3 GH |
447 | mac->a[0], mac->a[1], mac->a[2], |
448 | mac->a[3], mac->a[4], mac->a[5]); | |
ee6847d1 GH |
449 | } |
450 | ||
451 | PropertyInfo qdev_prop_macaddr = { | |
1503fff3 | 452 | .name = "macaddr", |
ee6847d1 | 453 | .type = PROP_TYPE_MACADDR, |
1503fff3 | 454 | .size = sizeof(MACAddr), |
ee6847d1 GH |
455 | .parse = parse_mac, |
456 | .print = print_mac, | |
457 | }; | |
458 | ||
05cb5fe4 GH |
459 | /* --- pci address --- */ |
460 | ||
461 | /* | |
462 | * bus-local address, i.e. "$slot" or "$slot.$fn" | |
463 | */ | |
464 | static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str) | |
465 | { | |
466 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
467 | unsigned int slot, fn, n; | |
468 | ||
469 | if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { | |
470 | fn = 0; | |
471 | if (sscanf(str, "%x%n", &slot, &n) != 1) { | |
6bf38816 | 472 | return -EINVAL; |
05cb5fe4 GH |
473 | } |
474 | } | |
475 | if (str[n] != '\0') | |
6bf38816 | 476 | return -EINVAL; |
05cb5fe4 | 477 | if (fn > 7) |
6bf38816 | 478 | return -EINVAL; |
05cb5fe4 GH |
479 | *ptr = slot << 3 | fn; |
480 | return 0; | |
481 | } | |
482 | ||
483 | static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) | |
484 | { | |
485 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
486 | ||
73538c31 | 487 | if (*ptr == -1) { |
05cb5fe4 GH |
488 | return snprintf(dest, len, "<unset>"); |
489 | } else { | |
490 | return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); | |
491 | } | |
492 | } | |
493 | ||
494 | PropertyInfo qdev_prop_pci_devfn = { | |
495 | .name = "pci-devfn", | |
496 | .type = PROP_TYPE_UINT32, | |
497 | .size = sizeof(uint32_t), | |
498 | .parse = parse_pci_devfn, | |
499 | .print = print_pci_devfn, | |
500 | }; | |
501 | ||
ee6847d1 GH |
502 | /* --- public helpers --- */ |
503 | ||
504 | static Property *qdev_prop_walk(Property *props, const char *name) | |
505 | { | |
506 | if (!props) | |
507 | return NULL; | |
508 | while (props->name) { | |
509 | if (strcmp(props->name, name) == 0) | |
510 | return props; | |
511 | props++; | |
512 | } | |
513 | return NULL; | |
514 | } | |
515 | ||
516 | static Property *qdev_prop_find(DeviceState *dev, const char *name) | |
517 | { | |
518 | Property *prop; | |
519 | ||
520 | /* device properties */ | |
521 | prop = qdev_prop_walk(dev->info->props, name); | |
522 | if (prop) | |
523 | return prop; | |
524 | ||
525 | /* bus properties */ | |
526 | prop = qdev_prop_walk(dev->parent_bus->info->props, name); | |
527 | if (prop) | |
528 | return prop; | |
529 | ||
530 | return NULL; | |
531 | } | |
532 | ||
d8ed79ae GH |
533 | int qdev_prop_exists(DeviceState *dev, const char *name) |
534 | { | |
535 | return qdev_prop_find(dev, name) ? true : false; | |
536 | } | |
537 | ||
ee6847d1 GH |
538 | int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) |
539 | { | |
540 | Property *prop; | |
6bf38816 | 541 | int ret; |
ee6847d1 GH |
542 | |
543 | prop = qdev_prop_find(dev, name); | |
036f7166 MA |
544 | /* |
545 | * TODO Properties without a parse method are just for dirty | |
546 | * hacks. qdev_prop_ptr is the only such PropertyInfo. It's | |
547 | * marked for removal. The test !prop->info->parse should be | |
548 | * removed along with it. | |
549 | */ | |
550 | if (!prop || !prop->info->parse) { | |
fdcfa190 | 551 | qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name); |
ee6847d1 GH |
552 | return -1; |
553 | } | |
6bf38816 MA |
554 | ret = prop->info->parse(dev, prop, value); |
555 | if (ret < 0) { | |
556 | switch (ret) { | |
27f3f8a3 | 557 | case -EEXIST: |
fdcfa190 MA |
558 | qerror_report(QERR_PROPERTY_VALUE_IN_USE, |
559 | dev->info->name, name, value); | |
27f3f8a3 | 560 | break; |
6bf38816 MA |
561 | default: |
562 | case -EINVAL: | |
fdcfa190 MA |
563 | qerror_report(QERR_PROPERTY_VALUE_BAD, |
564 | dev->info->name, name, value); | |
6bf38816 MA |
565 | break; |
566 | case -ENOENT: | |
fdcfa190 MA |
567 | qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND, |
568 | dev->info->name, name, value); | |
6bf38816 MA |
569 | break; |
570 | } | |
9ef5c4bf GH |
571 | return -1; |
572 | } | |
573 | return 0; | |
ee6847d1 GH |
574 | } |
575 | ||
576 | void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type) | |
577 | { | |
578 | Property *prop; | |
ee6847d1 GH |
579 | |
580 | prop = qdev_prop_find(dev, name); | |
581 | if (!prop) { | |
582 | fprintf(stderr, "%s: property \"%s.%s\" not found\n", | |
583 | __FUNCTION__, dev->info->name, name); | |
584 | abort(); | |
585 | } | |
586 | if (prop->info->type != type) { | |
587 | fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n", | |
588 | __FUNCTION__, dev->info->name, name); | |
589 | abort(); | |
590 | } | |
d2364ee4 | 591 | qdev_prop_cpy(dev, prop, src); |
ee6847d1 GH |
592 | } |
593 | ||
c7cc172d JQ |
594 | void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) |
595 | { | |
596 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8); | |
597 | } | |
598 | ||
ee6847d1 GH |
599 | void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) |
600 | { | |
601 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16); | |
602 | } | |
603 | ||
604 | void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) | |
605 | { | |
606 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32); | |
607 | } | |
608 | ||
316940b0 GH |
609 | void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) |
610 | { | |
611 | qdev_prop_set(dev, name, &value, PROP_TYPE_INT32); | |
612 | } | |
613 | ||
5a053d1f BS |
614 | void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) |
615 | { | |
616 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64); | |
617 | } | |
618 | ||
14b41872 GH |
619 | void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value) |
620 | { | |
621 | qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); | |
622 | } | |
623 | ||
313feaab GH |
624 | void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) |
625 | { | |
626 | qdev_prop_set(dev, name, &value, PROP_TYPE_CHR); | |
627 | } | |
628 | ||
2ef924b4 GH |
629 | void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value) |
630 | { | |
631 | qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV); | |
632 | } | |
633 | ||
851bec09 GH |
634 | void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value) |
635 | { | |
636 | qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN); | |
637 | } | |
638 | ||
1503fff3 GH |
639 | void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) |
640 | { | |
641 | qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR); | |
642 | } | |
643 | ||
ee6847d1 GH |
644 | void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) |
645 | { | |
646 | qdev_prop_set(dev, name, &value, PROP_TYPE_PTR); | |
647 | } | |
648 | ||
649 | void qdev_prop_set_defaults(DeviceState *dev, Property *props) | |
650 | { | |
ee6847d1 GH |
651 | if (!props) |
652 | return; | |
653 | while (props->name) { | |
654 | if (props->defval) { | |
d2364ee4 | 655 | qdev_prop_cpy(dev, props, props->defval); |
ee6847d1 GH |
656 | } |
657 | props++; | |
658 | } | |
659 | } | |
660 | ||
458fb679 | 661 | static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); |
b6b61144 | 662 | |
458fb679 | 663 | void qdev_prop_register_global(GlobalProperty *prop) |
b6b61144 | 664 | { |
458fb679 | 665 | QTAILQ_INSERT_TAIL(&global_props, prop, next); |
b6b61144 GH |
666 | } |
667 | ||
458fb679 | 668 | void qdev_prop_register_global_list(GlobalProperty *props) |
b6b61144 | 669 | { |
458fb679 | 670 | int i; |
b6b61144 | 671 | |
458fb679 GH |
672 | for (i = 0; props[i].driver != NULL; i++) { |
673 | qdev_prop_register_global(props+i); | |
b6b61144 | 674 | } |
458fb679 GH |
675 | } |
676 | ||
677 | void qdev_prop_set_globals(DeviceState *dev) | |
678 | { | |
679 | GlobalProperty *prop; | |
680 | ||
681 | QTAILQ_FOREACH(prop, &global_props, next) { | |
07a8de35 GH |
682 | if (strcmp(dev->info->name, prop->driver) != 0 && |
683 | strcmp(dev->info->bus_info->name, prop->driver) != 0) { | |
b6b61144 GH |
684 | continue; |
685 | } | |
686 | if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { | |
9ef5c4bf | 687 | exit(1); |
b6b61144 GH |
688 | } |
689 | } | |
690 | } |