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