]> git.proxmox.com Git - qemu.git/blame - hw/qdev-properties.c
xilinx_timer: Fixed deadlock issue
[qemu.git] / hw / qdev-properties.c
CommitLineData
1503fff3 1#include "net.h"
ee6847d1 2#include "qdev.h"
9f59b566 3#include "qerror.h"
2446333c 4#include "blockdev.h"
ee6847d1
GH
5
6void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
7{
8 void *ptr = dev;
9 ptr += prop->offset;
10 return ptr;
11}
12
d2364ee4
MT
13static uint32_t qdev_get_prop_mask(Property *prop)
14{
a3d4a1b0 15 assert(prop->info == &qdev_prop_bit);
d2364ee4
MT
16 return 0x1 << prop->bitnr;
17}
18
19static void bit_prop_set(DeviceState *dev, Property *props, bool val)
20{
21 uint32_t *p = qdev_get_prop_ptr(dev, props);
22 uint32_t mask = qdev_get_prop_mask(props);
23 if (val)
dbd48324 24 *p |= mask;
d2364ee4
MT
25 else
26 *p &= ~mask;
27}
28
d2364ee4 29/* Bit */
d2364ee4
MT
30
31static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
32{
5a5e3d55 33 uint32_t *p = qdev_get_prop_ptr(dev, prop);
d2364ee4
MT
34 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
35}
36
57c9fafe 37static void get_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
38 const char *name, Error **errp)
39{
57c9fafe 40 DeviceState *dev = DEVICE(obj);
80e555c2
PB
41 Property *prop = opaque;
42 uint32_t *p = qdev_get_prop_ptr(dev, prop);
43 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
44
45 visit_type_bool(v, &value, name, errp);
46}
47
57c9fafe 48static void set_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
49 const char *name, Error **errp)
50{
57c9fafe 51 DeviceState *dev = DEVICE(obj);
80e555c2
PB
52 Property *prop = opaque;
53 Error *local_err = NULL;
54 bool value;
55
56 if (dev->state != DEV_STATE_CREATED) {
57 error_set(errp, QERR_PERMISSION_DENIED);
58 return;
59 }
60
61 visit_type_bool(v, &value, name, &local_err);
62 if (local_err) {
63 error_propagate(errp, local_err);
64 return;
65 }
66 bit_prop_set(dev, prop, value);
67}
68
d2364ee4 69PropertyInfo qdev_prop_bit = {
cafe5bdb
PB
70 .name = "boolean",
71 .legacy_name = "on/off",
d2364ee4 72 .print = print_bit,
80e555c2
PB
73 .get = get_bit,
74 .set = set_bit,
d2364ee4
MT
75};
76
c7cc172d
JQ
77/* --- 8bit integer --- */
78
c08fb2ac
MR
79static void get_uint8(Object *obj, Visitor *v, void *opaque,
80 const char *name, Error **errp)
80e555c2 81{
57c9fafe 82 DeviceState *dev = DEVICE(obj);
80e555c2 83 Property *prop = opaque;
c08fb2ac 84 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 85
c08fb2ac 86 visit_type_uint8(v, ptr, name, errp);
80e555c2
PB
87}
88
c08fb2ac
MR
89static void set_uint8(Object *obj, Visitor *v, void *opaque,
90 const char *name, Error **errp)
80e555c2 91{
57c9fafe 92 DeviceState *dev = DEVICE(obj);
80e555c2 93 Property *prop = opaque;
27712df9 94 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
95
96 if (dev->state != DEV_STATE_CREATED) {
97 error_set(errp, QERR_PERMISSION_DENIED);
98 return;
99 }
100
27712df9 101 visit_type_uint8(v, ptr, name, errp);
80e555c2
PB
102}
103
c7cc172d
JQ
104PropertyInfo qdev_prop_uint8 = {
105 .name = "uint8",
c08fb2ac
MR
106 .get = get_uint8,
107 .set = set_uint8,
c7cc172d
JQ
108};
109
6835678c
JK
110/* --- 8bit hex value --- */
111
112static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
113{
114 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
115 char *end;
116
97aa6e9b
PB
117 if (str[0] != '0' || str[1] != 'x') {
118 return -EINVAL;
119 }
120
6835678c
JK
121 *ptr = strtoul(str, &end, 16);
122 if ((*end != '\0') || (end == str)) {
123 return -EINVAL;
124 }
125
126 return 0;
127}
128
129static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
130{
131 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
132 return snprintf(dest, len, "0x%" PRIx8, *ptr);
133}
134
135PropertyInfo qdev_prop_hex8 = {
cafe5bdb
PB
136 .name = "uint8",
137 .legacy_name = "hex8",
6835678c
JK
138 .parse = parse_hex8,
139 .print = print_hex8,
c08fb2ac
MR
140 .get = get_uint8,
141 .set = set_uint8,
6835678c
JK
142};
143
ee6847d1
GH
144/* --- 16bit integer --- */
145
c08fb2ac
MR
146static void get_uint16(Object *obj, Visitor *v, void *opaque,
147 const char *name, Error **errp)
80e555c2 148{
57c9fafe 149 DeviceState *dev = DEVICE(obj);
80e555c2 150 Property *prop = opaque;
c08fb2ac 151 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 152
c08fb2ac 153 visit_type_uint16(v, ptr, name, errp);
80e555c2
PB
154}
155
c08fb2ac
MR
156static void set_uint16(Object *obj, Visitor *v, void *opaque,
157 const char *name, Error **errp)
80e555c2 158{
57c9fafe 159 DeviceState *dev = DEVICE(obj);
80e555c2 160 Property *prop = opaque;
27712df9 161 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
162
163 if (dev->state != DEV_STATE_CREATED) {
164 error_set(errp, QERR_PERMISSION_DENIED);
165 return;
166 }
167
27712df9 168 visit_type_uint16(v, ptr, name, errp);
80e555c2
PB
169}
170
ee6847d1
GH
171PropertyInfo qdev_prop_uint16 = {
172 .name = "uint16",
c08fb2ac
MR
173 .get = get_uint16,
174 .set = set_uint16,
ee6847d1
GH
175};
176
177/* --- 32bit integer --- */
178
c08fb2ac
MR
179static void get_uint32(Object *obj, Visitor *v, void *opaque,
180 const char *name, Error **errp)
181{
182 DeviceState *dev = DEVICE(obj);
183 Property *prop = opaque;
27712df9 184 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
c08fb2ac 185
27712df9 186 visit_type_uint32(v, ptr, name, errp);
c08fb2ac
MR
187}
188
189static void set_uint32(Object *obj, Visitor *v, void *opaque,
190 const char *name, Error **errp)
191{
192 DeviceState *dev = DEVICE(obj);
193 Property *prop = opaque;
27712df9 194 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
c08fb2ac
MR
195
196 if (dev->state != DEV_STATE_CREATED) {
197 error_set(errp, QERR_PERMISSION_DENIED);
198 return;
199 }
200
27712df9 201 visit_type_uint32(v, ptr, name, errp);
c08fb2ac
MR
202}
203
57c9fafe 204static void get_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
205 const char *name, Error **errp)
206{
57c9fafe 207 DeviceState *dev = DEVICE(obj);
80e555c2
PB
208 Property *prop = opaque;
209 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 210
c08fb2ac 211 visit_type_int32(v, ptr, name, errp);
80e555c2
PB
212}
213
57c9fafe 214static void set_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
215 const char *name, Error **errp)
216{
57c9fafe 217 DeviceState *dev = DEVICE(obj);
80e555c2 218 Property *prop = opaque;
27712df9 219 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
220
221 if (dev->state != DEV_STATE_CREATED) {
222 error_set(errp, QERR_PERMISSION_DENIED);
223 return;
224 }
225
27712df9 226 visit_type_int32(v, ptr, name, errp);
80e555c2
PB
227}
228
ee6847d1
GH
229PropertyInfo qdev_prop_uint32 = {
230 .name = "uint32",
c08fb2ac
MR
231 .get = get_uint32,
232 .set = set_uint32,
ee6847d1
GH
233};
234
316940b0
GH
235PropertyInfo qdev_prop_int32 = {
236 .name = "int32",
80e555c2
PB
237 .get = get_int32,
238 .set = set_int32,
316940b0
GH
239};
240
ee6847d1
GH
241/* --- 32bit hex value --- */
242
243static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
244{
245 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 246 char *end;
ee6847d1 247
97aa6e9b
PB
248 if (str[0] != '0' || str[1] != 'x') {
249 return -EINVAL;
250 }
251
449041d4
KW
252 *ptr = strtoul(str, &end, 16);
253 if ((*end != '\0') || (end == str)) {
6bf38816 254 return -EINVAL;
449041d4
KW
255 }
256
ee6847d1
GH
257 return 0;
258}
259
260static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
261{
262 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
263 return snprintf(dest, len, "0x%" PRIx32, *ptr);
264}
265
266PropertyInfo qdev_prop_hex32 = {
cafe5bdb
PB
267 .name = "uint32",
268 .legacy_name = "hex32",
ee6847d1
GH
269 .parse = parse_hex32,
270 .print = print_hex32,
c08fb2ac
MR
271 .get = get_uint32,
272 .set = set_uint32,
ee6847d1
GH
273};
274
5a053d1f
BS
275/* --- 64bit integer --- */
276
c08fb2ac
MR
277static void get_uint64(Object *obj, Visitor *v, void *opaque,
278 const char *name, Error **errp)
80e555c2 279{
57c9fafe 280 DeviceState *dev = DEVICE(obj);
80e555c2 281 Property *prop = opaque;
c08fb2ac 282 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 283
c08fb2ac 284 visit_type_uint64(v, ptr, name, errp);
80e555c2
PB
285}
286
c08fb2ac
MR
287static void set_uint64(Object *obj, Visitor *v, void *opaque,
288 const char *name, Error **errp)
80e555c2 289{
57c9fafe 290 DeviceState *dev = DEVICE(obj);
80e555c2 291 Property *prop = opaque;
c08fb2ac 292 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
293
294 if (dev->state != DEV_STATE_CREATED) {
295 error_set(errp, QERR_PERMISSION_DENIED);
296 return;
297 }
298
c08fb2ac 299 visit_type_uint64(v, ptr, name, errp);
80e555c2
PB
300}
301
5a053d1f
BS
302PropertyInfo qdev_prop_uint64 = {
303 .name = "uint64",
c08fb2ac
MR
304 .get = get_uint64,
305 .set = set_uint64,
5a053d1f
BS
306};
307
308/* --- 64bit hex value --- */
309
310static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
311{
312 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 313 char *end;
5a053d1f 314
97aa6e9b
PB
315 if (str[0] != '0' || str[1] != 'x') {
316 return -EINVAL;
317 }
318
449041d4
KW
319 *ptr = strtoull(str, &end, 16);
320 if ((*end != '\0') || (end == str)) {
6bf38816 321 return -EINVAL;
449041d4
KW
322 }
323
5a053d1f
BS
324 return 0;
325}
326
327static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
328{
329 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
330 return snprintf(dest, len, "0x%" PRIx64, *ptr);
331}
332
333PropertyInfo qdev_prop_hex64 = {
cafe5bdb
PB
334 .name = "uint64",
335 .legacy_name = "hex64",
5a053d1f
BS
336 .parse = parse_hex64,
337 .print = print_hex64,
c08fb2ac
MR
338 .get = get_uint64,
339 .set = set_uint64,
5a053d1f
BS
340};
341
59419663
GH
342/* --- string --- */
343
dd0ba250 344static void release_string(Object *obj, const char *name, void *opaque)
d21357df 345{
dd0ba250
PB
346 Property *prop = opaque;
347 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
d21357df
MA
348}
349
59419663
GH
350static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
351{
352 char **ptr = qdev_get_prop_ptr(dev, prop);
353 if (!*ptr)
354 return snprintf(dest, len, "<null>");
355 return snprintf(dest, len, "\"%s\"", *ptr);
356}
357
57c9fafe 358static void get_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
359 const char *name, Error **errp)
360{
57c9fafe 361 DeviceState *dev = DEVICE(obj);
80e555c2
PB
362 Property *prop = opaque;
363 char **ptr = qdev_get_prop_ptr(dev, prop);
364
365 if (!*ptr) {
366 char *str = (char *)"";
367 visit_type_str(v, &str, name, errp);
368 } else {
369 visit_type_str(v, ptr, name, errp);
370 }
371}
372
57c9fafe 373static void set_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
374 const char *name, Error **errp)
375{
57c9fafe 376 DeviceState *dev = DEVICE(obj);
80e555c2
PB
377 Property *prop = opaque;
378 char **ptr = qdev_get_prop_ptr(dev, prop);
379 Error *local_err = NULL;
380 char *str;
381
382 if (dev->state != DEV_STATE_CREATED) {
383 error_set(errp, QERR_PERMISSION_DENIED);
384 return;
385 }
386
387 visit_type_str(v, &str, name, &local_err);
388 if (local_err) {
389 error_propagate(errp, local_err);
390 return;
391 }
80e555c2
PB
392 if (*ptr) {
393 g_free(*ptr);
394 }
395 *ptr = str;
396}
397
59419663
GH
398PropertyInfo qdev_prop_string = {
399 .name = "string",
59419663 400 .print = print_string,
dd0ba250 401 .release = release_string,
80e555c2
PB
402 .get = get_string,
403 .set = set_string,
59419663
GH
404};
405
14b41872
GH
406/* --- drive --- */
407
7b009e5d 408static int parse_drive(DeviceState *dev, const char *str, void **ptr)
14b41872 409{
f8b6cc00 410 BlockDriverState *bs;
14b41872 411
f8b6cc00
MA
412 bs = bdrv_find(str);
413 if (bs == NULL)
6bf38816 414 return -ENOENT;
fa879d62 415 if (bdrv_attach_dev(bs, dev) < 0)
18846dee 416 return -EEXIST;
f8b6cc00 417 *ptr = bs;
14b41872
GH
418 return 0;
419}
420
dd0ba250 421static void release_drive(Object *obj, const char *name, void *opaque)
14bafc54 422{
dd0ba250
PB
423 DeviceState *dev = DEVICE(obj);
424 Property *prop = opaque;
f8b6cc00 425 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
14bafc54
MA
426
427 if (*ptr) {
fa879d62 428 bdrv_detach_dev(*ptr, dev);
f8b6cc00 429 blockdev_auto_del(*ptr);
14bafc54
MA
430 }
431}
432
7b009e5d 433static const char *print_drive(void *ptr)
14b41872 434{
7b009e5d 435 return bdrv_get_device_name(ptr);
14b41872
GH
436}
437
7b009e5d
PB
438static void get_pointer(Object *obj, Visitor *v, Property *prop,
439 const char *(*print)(void *ptr),
440 const char *name, Error **errp)
80e555c2 441{
57c9fafe 442 DeviceState *dev = DEVICE(obj);
80e555c2 443 void **ptr = qdev_get_prop_ptr(dev, prop);
7b009e5d 444 char *p;
80e555c2 445
7b009e5d 446 p = (char *) (*ptr ? print(*ptr) : "");
80e555c2
PB
447 visit_type_str(v, &p, name, errp);
448}
449
7b009e5d
PB
450static void set_pointer(Object *obj, Visitor *v, Property *prop,
451 int (*parse)(DeviceState *dev, const char *str, void **ptr),
80e555c2
PB
452 const char *name, Error **errp)
453{
57c9fafe 454 DeviceState *dev = DEVICE(obj);
80e555c2 455 Error *local_err = NULL;
7b009e5d 456 void **ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
457 char *str;
458 int ret;
459
460 if (dev->state != DEV_STATE_CREATED) {
461 error_set(errp, QERR_PERMISSION_DENIED);
462 return;
463 }
464
465 visit_type_str(v, &str, name, &local_err);
466 if (local_err) {
467 error_propagate(errp, local_err);
468 return;
469 }
470 if (!*str) {
471 g_free(str);
0a54a0ce 472 *ptr = NULL;
80e555c2
PB
473 return;
474 }
7b009e5d 475 ret = parse(dev, str, ptr);
80e555c2
PB
476 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
477 g_free(str);
478}
479
7b009e5d
PB
480static void get_drive(Object *obj, Visitor *v, void *opaque,
481 const char *name, Error **errp)
482{
483 get_pointer(obj, v, opaque, print_drive, name, errp);
484}
485
486static void set_drive(Object *obj, Visitor *v, void *opaque,
487 const char *name, Error **errp)
488{
489 set_pointer(obj, v, opaque, parse_drive, name, errp);
490}
491
14b41872
GH
492PropertyInfo qdev_prop_drive = {
493 .name = "drive",
7b009e5d
PB
494 .get = get_drive,
495 .set = set_drive,
dd0ba250 496 .release = release_drive,
14b41872
GH
497};
498
313feaab
GH
499/* --- character device --- */
500
7b009e5d 501static int parse_chr(DeviceState *dev, const char *str, void **ptr)
06113719 502{
7b009e5d
PB
503 CharDriverState *chr = qemu_chr_find(str);
504 if (chr == NULL) {
6bf38816 505 return -ENOENT;
2d6c1ef4 506 }
7b009e5d 507 if (chr->avail_connections < 1) {
2d6c1ef4
AS
508 return -EEXIST;
509 }
7b009e5d
PB
510 *ptr = chr;
511 --chr->avail_connections;
06113719
GH
512 return 0;
513}
514
dd0ba250 515static void release_chr(Object *obj, const char *name, void *opaque)
a87f3e8b 516{
dd0ba250
PB
517 DeviceState *dev = DEVICE(obj);
518 Property *prop = opaque;
a87f3e8b
AS
519 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
520
521 if (*ptr) {
522 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
523 }
524}
525
526
7b009e5d 527static const char *print_chr(void *ptr)
313feaab 528{
7b009e5d 529 CharDriverState *chr = ptr;
bc19fcaa 530
7b009e5d
PB
531 return chr->label ? chr->label : "";
532}
533
534static void get_chr(Object *obj, Visitor *v, void *opaque,
535 const char *name, Error **errp)
536{
537 get_pointer(obj, v, opaque, print_chr, name, errp);
538}
539
540static void set_chr(Object *obj, Visitor *v, void *opaque,
541 const char *name, Error **errp)
542{
543 set_pointer(obj, v, opaque, parse_chr, name, errp);
313feaab
GH
544}
545
546PropertyInfo qdev_prop_chr = {
547 .name = "chr",
7b009e5d
PB
548 .get = get_chr,
549 .set = set_chr,
dd0ba250 550 .release = release_chr,
313feaab
GH
551};
552
2ef924b4
GH
553/* --- netdev device --- */
554
7b009e5d 555static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
2ef924b4 556{
7b009e5d 557 VLANClientState *netdev = qemu_find_netdev(str);
2ef924b4 558
7b009e5d 559 if (netdev == NULL) {
6bf38816 560 return -ENOENT;
7b009e5d
PB
561 }
562 if (netdev->peer) {
27f3f8a3
MA
563 return -EEXIST;
564 }
7b009e5d 565 *ptr = netdev;
2ef924b4
GH
566 return 0;
567}
568
7b009e5d 569static const char *print_netdev(void *ptr)
2ef924b4 570{
7b009e5d 571 VLANClientState *netdev = ptr;
2ef924b4 572
7b009e5d
PB
573 return netdev->name ? netdev->name : "";
574}
575
576static void get_netdev(Object *obj, Visitor *v, void *opaque,
577 const char *name, Error **errp)
578{
579 get_pointer(obj, v, opaque, print_netdev, name, errp);
580}
581
582static void set_netdev(Object *obj, Visitor *v, void *opaque,
583 const char *name, Error **errp)
584{
585 set_pointer(obj, v, opaque, parse_netdev, name, errp);
2ef924b4
GH
586}
587
588PropertyInfo qdev_prop_netdev = {
589 .name = "netdev",
7b009e5d
PB
590 .get = get_netdev,
591 .set = set_netdev,
2ef924b4
GH
592};
593
851bec09
GH
594/* --- vlan --- */
595
851bec09
GH
596static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
597{
598 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
599
600 if (*ptr) {
601 return snprintf(dest, len, "%d", (*ptr)->id);
602 } else {
603 return snprintf(dest, len, "<null>");
604 }
605}
606
57c9fafe 607static void get_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
608 const char *name, Error **errp)
609{
57c9fafe 610 DeviceState *dev = DEVICE(obj);
80e555c2
PB
611 Property *prop = opaque;
612 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
613 int64_t id;
614
615 id = *ptr ? (*ptr)->id : -1;
c08fb2ac 616 visit_type_int64(v, &id, name, errp);
80e555c2
PB
617}
618
57c9fafe 619static void set_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
620 const char *name, Error **errp)
621{
57c9fafe 622 DeviceState *dev = DEVICE(obj);
80e555c2
PB
623 Property *prop = opaque;
624 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
625 Error *local_err = NULL;
626 int64_t id;
627 VLANState *vlan;
628
629 if (dev->state != DEV_STATE_CREATED) {
630 error_set(errp, QERR_PERMISSION_DENIED);
631 return;
632 }
633
c08fb2ac 634 visit_type_int64(v, &id, name, &local_err);
80e555c2
PB
635 if (local_err) {
636 error_propagate(errp, local_err);
637 return;
638 }
639 if (id == -1) {
640 *ptr = NULL;
641 return;
642 }
643 vlan = qemu_find_vlan(id, 1);
644 if (!vlan) {
645 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
646 name, prop->info->name);
647 return;
648 }
649 *ptr = vlan;
650}
651
851bec09
GH
652PropertyInfo qdev_prop_vlan = {
653 .name = "vlan",
851bec09 654 .print = print_vlan,
80e555c2
PB
655 .get = get_vlan,
656 .set = set_vlan,
851bec09
GH
657};
658
ee6847d1
GH
659/* --- pointer --- */
660
036f7166 661/* Not a proper property, just for dirty hacks. TODO Remove it! */
ee6847d1
GH
662PropertyInfo qdev_prop_ptr = {
663 .name = "ptr",
ee6847d1
GH
664};
665
666/* --- mac address --- */
667
668/*
669 * accepted syntax versions:
670 * 01:02:03:04:05:06
671 * 01-02-03-04-05-06
672 */
e39e5d60
PB
673static void get_mac(Object *obj, Visitor *v, void *opaque,
674 const char *name, Error **errp)
ee6847d1 675{
e39e5d60
PB
676 DeviceState *dev = DEVICE(obj);
677 Property *prop = opaque;
1503fff3 678 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
e39e5d60
PB
679 char buffer[2 * 6 + 5 + 1];
680 char *p = buffer;
681
682 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
683 mac->a[0], mac->a[1], mac->a[2],
684 mac->a[3], mac->a[4], mac->a[5]);
685
686 visit_type_str(v, &p, name, errp);
687}
688
689static void set_mac(Object *obj, Visitor *v, void *opaque,
690 const char *name, Error **errp)
691{
692 DeviceState *dev = DEVICE(obj);
693 Property *prop = opaque;
694 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
695 Error *local_err = NULL;
ee6847d1 696 int i, pos;
e39e5d60
PB
697 char *str, *p;
698
699 if (dev->state != DEV_STATE_CREATED) {
700 error_set(errp, QERR_PERMISSION_DENIED);
701 return;
702 }
703
704 visit_type_str(v, &str, name, &local_err);
705 if (local_err) {
706 error_propagate(errp, local_err);
707 return;
708 }
ee6847d1
GH
709
710 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
88e150a5 711 if (!qemu_isxdigit(str[pos]))
e39e5d60 712 goto inval;
88e150a5 713 if (!qemu_isxdigit(str[pos+1]))
e39e5d60 714 goto inval;
1503fff3
GH
715 if (i == 5) {
716 if (str[pos+2] != '\0')
e39e5d60 717 goto inval;
1503fff3
GH
718 } else {
719 if (str[pos+2] != ':' && str[pos+2] != '-')
e39e5d60 720 goto inval;
1503fff3
GH
721 }
722 mac->a[i] = strtol(str+pos, &p, 16);
ee6847d1 723 }
a3400466 724 g_free(str);
e39e5d60 725 return;
1503fff3 726
e39e5d60
PB
727inval:
728 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
a3400466 729 g_free(str);
ee6847d1
GH
730}
731
732PropertyInfo qdev_prop_macaddr = {
1503fff3 733 .name = "macaddr",
e39e5d60
PB
734 .get = get_mac,
735 .set = set_mac,
ee6847d1
GH
736};
737
4e4fa398
JK
738
739/* --- lost tick policy --- */
740
1ce05125
PB
741static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
742 [LOST_TICK_DISCARD] = "discard",
743 [LOST_TICK_DELAY] = "delay",
744 [LOST_TICK_MERGE] = "merge",
745 [LOST_TICK_SLEW] = "slew",
746 [LOST_TICK_MAX] = NULL,
4e4fa398
JK
747};
748
1ce05125
PB
749QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
750
751static void get_enum(Object *obj, Visitor *v, void *opaque,
752 const char *name, Error **errp)
4e4fa398 753{
1ce05125
PB
754 DeviceState *dev = DEVICE(obj);
755 Property *prop = opaque;
756 int *ptr = qdev_get_prop_ptr(dev, prop);
4e4fa398 757
1ce05125
PB
758 visit_type_enum(v, ptr, prop->info->enum_table,
759 prop->info->name, prop->name, errp);
4e4fa398
JK
760}
761
1ce05125
PB
762static void set_enum(Object *obj, Visitor *v, void *opaque,
763 const char *name, Error **errp)
4e4fa398 764{
1ce05125
PB
765 DeviceState *dev = DEVICE(obj);
766 Property *prop = opaque;
767 int *ptr = qdev_get_prop_ptr(dev, prop);
4e4fa398 768
1ce05125
PB
769 if (dev->state != DEV_STATE_CREATED) {
770 error_set(errp, QERR_PERMISSION_DENIED);
771 return;
772 }
773
774 visit_type_enum(v, ptr, prop->info->enum_table,
775 prop->info->name, prop->name, errp);
4e4fa398
JK
776}
777
778PropertyInfo qdev_prop_losttickpolicy = {
1ce05125 779 .name = "LostTickPolicy",
1ce05125
PB
780 .enum_table = lost_tick_policy_table,
781 .get = get_enum,
782 .set = set_enum,
4e4fa398
JK
783};
784
05cb5fe4
GH
785/* --- pci address --- */
786
787/*
788 * bus-local address, i.e. "$slot" or "$slot.$fn"
789 */
768a9ebe
PB
790static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
791 const char *name, Error **errp)
05cb5fe4 792{
768a9ebe
PB
793 DeviceState *dev = DEVICE(obj);
794 Property *prop = opaque;
27712df9 795 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
05cb5fe4 796 unsigned int slot, fn, n;
768a9ebe 797 Error *local_err = NULL;
a3400466 798 char *str;
768a9ebe
PB
799
800 if (dev->state != DEV_STATE_CREATED) {
801 error_set(errp, QERR_PERMISSION_DENIED);
802 return;
803 }
804
805 visit_type_str(v, &str, name, &local_err);
806 if (local_err) {
5c878008 807 error_free(local_err);
27712df9
PB
808 local_err = NULL;
809 visit_type_int32(v, &value, name, &local_err);
810 if (local_err) {
811 error_propagate(errp, local_err);
812 } else if (value < -1 || value > 255) {
813 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
814 "pci_devfn");
815 } else {
816 *ptr = value;
817 }
818 return;
768a9ebe 819 }
05cb5fe4
GH
820
821 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
822 fn = 0;
823 if (sscanf(str, "%x%n", &slot, &n) != 1) {
768a9ebe 824 goto invalid;
05cb5fe4
GH
825 }
826 }
768a9ebe
PB
827 if (str[n] != '\0' || fn > 7 || slot > 31) {
828 goto invalid;
829 }
05cb5fe4 830 *ptr = slot << 3 | fn;
a3400466 831 g_free(str);
768a9ebe
PB
832 return;
833
834invalid:
835 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
a3400466 836 g_free(str);
05cb5fe4
GH
837}
838
839static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
840{
09f1bbcd 841 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
05cb5fe4 842
73538c31 843 if (*ptr == -1) {
05cb5fe4
GH
844 return snprintf(dest, len, "<unset>");
845 } else {
846 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
847 }
848}
849
850PropertyInfo qdev_prop_pci_devfn = {
b403298a
PB
851 .name = "int32",
852 .legacy_name = "pci-devfn",
05cb5fe4 853 .print = print_pci_devfn,
b403298a 854 .get = get_int32,
768a9ebe 855 .set = set_pci_devfn,
05cb5fe4
GH
856};
857
02fda01c
SH
858/* --- blocksize --- */
859
860static void set_blocksize(Object *obj, Visitor *v, void *opaque,
861 const char *name, Error **errp)
862{
863 DeviceState *dev = DEVICE(obj);
864 Property *prop = opaque;
c08fb2ac 865 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
02fda01c 866 Error *local_err = NULL;
27712df9
PB
867 const int64_t min = 512;
868 const int64_t max = 32768;
02fda01c
SH
869
870 if (dev->state != DEV_STATE_CREATED) {
871 error_set(errp, QERR_PERMISSION_DENIED);
872 return;
873 }
874
c08fb2ac 875 visit_type_uint16(v, &value, name, &local_err);
02fda01c
SH
876 if (local_err) {
877 error_propagate(errp, local_err);
878 return;
879 }
27712df9 880 if (value < min || value > max) {
02fda01c 881 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
27712df9 882 dev->id?:"", name, (int64_t)value, min, max);
02fda01c
SH
883 return;
884 }
885
886 /* We rely on power-of-2 blocksizes for bitmasks */
887 if ((value & (value - 1)) != 0) {
888 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
c08fb2ac 889 dev->id?:"", name, (int64_t)value);
02fda01c
SH
890 return;
891 }
892
893 *ptr = value;
894}
895
896PropertyInfo qdev_prop_blocksize = {
897 .name = "blocksize",
c08fb2ac 898 .get = get_uint16,
02fda01c 899 .set = set_blocksize,
02fda01c
SH
900};
901
ee6847d1
GH
902/* --- public helpers --- */
903
904static Property *qdev_prop_walk(Property *props, const char *name)
905{
906 if (!props)
907 return NULL;
908 while (props->name) {
909 if (strcmp(props->name, name) == 0)
910 return props;
911 props++;
912 }
913 return NULL;
914}
915
916static Property *qdev_prop_find(DeviceState *dev, const char *name)
917{
bce54474 918 ObjectClass *class;
ee6847d1
GH
919 Property *prop;
920
921 /* device properties */
bce54474
PB
922 class = object_get_class(OBJECT(dev));
923 do {
924 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
925 if (prop) {
926 return prop;
927 }
928 class = object_class_get_parent(class);
929 } while (class != object_class_by_name(TYPE_DEVICE));
ee6847d1
GH
930
931 return NULL;
932}
933
7db4c4e8
PB
934void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
935 Property *prop, const char *value)
936{
937 switch (ret) {
938 case -EEXIST:
939 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
f79f2bfc 940 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
941 break;
942 default:
943 case -EINVAL:
944 error_set(errp, QERR_PROPERTY_VALUE_BAD,
f79f2bfc 945 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
946 break;
947 case -ENOENT:
948 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
f79f2bfc 949 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
950 break;
951 case 0:
952 break;
953 }
954}
955
ee6847d1
GH
956int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
957{
d822979b
PB
958 char *legacy_name;
959 Error *err = NULL;
ee6847d1 960
d822979b
PB
961 legacy_name = g_strdup_printf("legacy-%s", name);
962 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
0c96e285 963 object_property_parse(OBJECT(dev), value, legacy_name, &err);
d822979b 964 } else {
0c96e285 965 object_property_parse(OBJECT(dev), value, name, &err);
ee6847d1 966 }
d822979b
PB
967 g_free(legacy_name);
968
969 if (err) {
7db4c4e8
PB
970 qerror_report_err(err);
971 error_free(err);
9ef5c4bf
GH
972 return -1;
973 }
974 return 0;
ee6847d1
GH
975}
976
f4594a3b
IY
977void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
978{
9b170e60
PB
979 Error *errp = NULL;
980 object_property_set_bool(OBJECT(dev), value, name, &errp);
59f971d4 981 assert_no_error(errp);
f4594a3b
IY
982}
983
c7cc172d
JQ
984void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
985{
9b170e60
PB
986 Error *errp = NULL;
987 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 988 assert_no_error(errp);
c7cc172d
JQ
989}
990
ee6847d1
GH
991void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
992{
9b170e60
PB
993 Error *errp = NULL;
994 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 995 assert_no_error(errp);
ee6847d1
GH
996}
997
998void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
999{
9b170e60
PB
1000 Error *errp = NULL;
1001 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1002 assert_no_error(errp);
ee6847d1
GH
1003}
1004
316940b0
GH
1005void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1006{
9b170e60
PB
1007 Error *errp = NULL;
1008 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1009 assert_no_error(errp);
316940b0
GH
1010}
1011
5a053d1f
BS
1012void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1013{
9b170e60
PB
1014 Error *errp = NULL;
1015 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1016 assert_no_error(errp);
5a053d1f
BS
1017}
1018
cc984673
MA
1019void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1020{
9b170e60
PB
1021 Error *errp = NULL;
1022 object_property_set_str(OBJECT(dev), value, name, &errp);
59f971d4 1023 assert_no_error(errp);
cc984673
MA
1024}
1025
18846dee 1026int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
14b41872 1027{
9b170e60 1028 Error *errp = NULL;
0a54a0ce
PB
1029 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1030 object_property_set_str(OBJECT(dev), bdrv_name,
9b170e60
PB
1031 name, &errp);
1032 if (errp) {
1033 qerror_report_err(errp);
1034 error_free(errp);
18846dee
MA
1035 return -1;
1036 }
18846dee 1037 return 0;
14b41872
GH
1038}
1039
18846dee
MA
1040void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1041{
1042 if (qdev_prop_set_drive(dev, name, value) < 0) {
1043 exit(1);
1044 }
1045}
313feaab
GH
1046void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1047{
9b170e60 1048 Error *errp = NULL;
0a54a0ce
PB
1049 assert(!value || value->label);
1050 object_property_set_str(OBJECT(dev),
1051 value ? value->label : "", name, &errp);
59f971d4 1052 assert_no_error(errp);
313feaab
GH
1053}
1054
2ef924b4
GH
1055void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1056{
9b170e60 1057 Error *errp = NULL;
0a54a0ce
PB
1058 assert(!value || value->name);
1059 object_property_set_str(OBJECT(dev),
1060 value ? value->name : "", name, &errp);
59f971d4 1061 assert_no_error(errp);
2ef924b4
GH
1062}
1063
851bec09
GH
1064void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1065{
9b170e60
PB
1066 Error *errp = NULL;
1067 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
59f971d4 1068 assert_no_error(errp);
851bec09
GH
1069}
1070
1503fff3
GH
1071void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1072{
9b170e60
PB
1073 Error *errp = NULL;
1074 char str[2 * 6 + 5 + 1];
1075 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1076 value[0], value[1], value[2], value[3], value[4], value[5]);
1077
1078 object_property_set_str(OBJECT(dev), str, name, &errp);
59f971d4 1079 assert_no_error(errp);
1503fff3
GH
1080}
1081
9b170e60 1082void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
4e4fa398 1083{
9b170e60
PB
1084 Property *prop;
1085 Error *errp = NULL;
1086
1087 prop = qdev_prop_find(dev, name);
1088 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1089 name, &errp);
59f971d4 1090 assert_no_error(errp);
4e4fa398
JK
1091}
1092
ee6847d1
GH
1093void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1094{
7a7aae21
PB
1095 Property *prop;
1096 void **ptr;
1097
1098 prop = qdev_prop_find(dev, name);
1099 assert(prop && prop->info == &qdev_prop_ptr);
1100 ptr = qdev_get_prop_ptr(dev, prop);
1101 *ptr = value;
ee6847d1
GH
1102}
1103
458fb679 1104static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
b6b61144 1105
25920d6a 1106static void qdev_prop_register_global(GlobalProperty *prop)
b6b61144 1107{
458fb679 1108 QTAILQ_INSERT_TAIL(&global_props, prop, next);
b6b61144
GH
1109}
1110
458fb679 1111void qdev_prop_register_global_list(GlobalProperty *props)
b6b61144 1112{
458fb679 1113 int i;
b6b61144 1114
458fb679
GH
1115 for (i = 0; props[i].driver != NULL; i++) {
1116 qdev_prop_register_global(props+i);
b6b61144 1117 }
458fb679
GH
1118}
1119
1120void qdev_prop_set_globals(DeviceState *dev)
1121{
bce54474
PB
1122 ObjectClass *class = object_get_class(OBJECT(dev));
1123
1124 do {
1125 GlobalProperty *prop;
1126 QTAILQ_FOREACH(prop, &global_props, next) {
1127 if (strcmp(object_class_get_name(class), prop->driver) != 0) {
1128 continue;
1129 }
1130 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1131 exit(1);
1132 }
b6b61144 1133 }
bce54474
PB
1134 class = object_class_get_parent(class);
1135 } while (class);
b6b61144 1136}
25920d6a
KW
1137
1138static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1139{
1140 GlobalProperty *g;
1141
7267c094 1142 g = g_malloc0(sizeof(*g));
25920d6a
KW
1143 g->driver = qemu_opt_get(opts, "driver");
1144 g->property = qemu_opt_get(opts, "property");
1145 g->value = qemu_opt_get(opts, "value");
1146 qdev_prop_register_global(g);
1147 return 0;
1148}
1149
1150void qemu_add_globals(void)
1151{
3329f07b 1152 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
25920d6a 1153}