]> git.proxmox.com Git - mirror_qemu.git/blame - hw/qdev.c
qom: add new command to search for types
[mirror_qemu.git] / hw / qdev.c
CommitLineData
aae9460e
PB
1/*
2 * Dynamic device configuration and creation.
3 *
4 * Copyright (c) 2009 CodeSourcery
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
aae9460e
PB
18 */
19
20/* The theory here is that it should be possible to create a machine without
21 knowledge of specific devices. Historically board init routines have
22 passed a bunch of arguments to each device, requiring the board know
23 exactly which device it is dealing with. This file provides an abstract
24 API for device configuration and initialization. Devices will generally
25 inherit from a particular bus (e.g. PCI or I2C) rather than
26 this API directly. */
27
9d07d757 28#include "net.h"
aae9460e
PB
29#include "qdev.h"
30#include "sysemu.h"
cae4956e 31#include "monitor.h"
aae9460e 32
3418bd25 33static int qdev_hotplug = 0;
0ac8ef71
AW
34static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
3418bd25 36
cdaed7c7 37/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 38static BusState *main_system_bus;
2da8bb92 39static void main_system_bus_create(void);
4d6ae674 40
8ffb1bcf
GH
41static BusState *qbus_find_recursive(BusState *bus, const char *name,
42 const BusInfo *info);
43static BusState *qbus_find(const char *path);
44
aae9460e 45/* Register a new device type. */
4be9f0d1
AL
46const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
47{
6e008585
AL
48 DeviceClass *dc = DEVICE_GET_CLASS(dev);
49 return dc->vmsd;
4be9f0d1
AL
50}
51
52BusInfo *qdev_get_bus_info(DeviceState *dev)
53{
6e008585
AL
54 DeviceClass *dc = DEVICE_GET_CLASS(dev);
55 return dc->bus_info;
4be9f0d1
AL
56}
57
58Property *qdev_get_props(DeviceState *dev)
59{
6e008585
AL
60 DeviceClass *dc = DEVICE_GET_CLASS(dev);
61 return dc->props;
4be9f0d1
AL
62}
63
6acbe4c6
AL
64/*
65 * Aliases were a bad idea from the start. Let's keep them
66 * from spreading further.
67 */
68typedef struct QDevAlias
69{
70 const char *typename;
71 const char *alias;
72} QDevAlias;
73
74static const QDevAlias qdev_alias_table[] = {
75 { "virtio-blk-pci", "virtio-blk" },
76 { "virtio-net-pci", "virtio-net" },
77 { "virtio-serial-pci", "virtio-serial" },
78 { "virtio-balloon-pci", "virtio-balloon" },
79 { "virtio-blk-s390", "virtio-blk" },
80 { "virtio-net-s390", "virtio-net" },
81 { "virtio-serial-s390", "virtio-serial" },
82 { "lsi53c895a", "lsi" },
83 { "ich9-ahci", "ahci" },
84 { }
85};
86
87static const char *qdev_class_get_alias(DeviceClass *dc)
88{
89 const char *typename = object_class_get_name(OBJECT_CLASS(dc));
90 int i;
91
92 for (i = 0; qdev_alias_table[i].typename; i++) {
93 if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
94 return qdev_alias_table[i].alias;
95 }
96 }
97
98 return NULL;
99}
100
101static bool qdev_class_has_alias(DeviceClass *dc)
102{
103 return (qdev_class_get_alias(dc) != NULL);
104}
105
4be9f0d1
AL
106const char *qdev_fw_name(DeviceState *dev)
107{
6e008585 108 DeviceClass *dc = DEVICE_GET_CLASS(dev);
4be9f0d1 109
6e008585
AL
110 if (dc->fw_name) {
111 return dc->fw_name;
6acbe4c6
AL
112 } else if (qdev_class_has_alias(dc)) {
113 return qdev_class_get_alias(dc);
4be9f0d1
AL
114 }
115
116 return object_get_typename(OBJECT(dev));
117}
118
a369da5f
BS
119bool qdev_exists(const char *name)
120{
212ad111 121 return !!object_class_by_name(name);
a369da5f 122}
40021f08 123
ca2cc788
PB
124static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
125 Error **errp);
126
18b6dade 127static DeviceState *qdev_create_from_info(BusState *bus, const char *typename)
0c17542d
MA
128{
129 DeviceState *dev;
a5296ca9 130 Property *prop;
0c17542d 131
18b6dade 132 dev = DEVICE(object_new(typename));
0c17542d 133 dev->parent_bus = bus;
6e008585 134 qdev_prop_set_defaults(dev, qdev_get_props(dev));
0c17542d
MA
135 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
136 qdev_prop_set_globals(dev);
d8bb00d6 137 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
0c17542d
MA
138 if (qdev_hotplug) {
139 assert(bus->allow_hotplug);
140 dev->hotplugged = 1;
0ac8ef71 141 qdev_hot_added = true;
0c17542d 142 }
4d2ffa08 143 dev->instance_id_alias = -1;
44677ded 144 QTAILQ_INIT(&dev->properties);
0c17542d 145 dev->state = DEV_STATE_CREATED;
a5296ca9 146
6e008585 147 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
a5296ca9 148 qdev_property_add_legacy(dev, prop, NULL);
ca2cc788 149 qdev_property_add_static(dev, prop, NULL);
a5296ca9
AL
150 }
151
6e008585 152 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
a5296ca9 153 qdev_property_add_legacy(dev, prop, NULL);
ca2cc788 154 qdev_property_add_static(dev, prop, NULL);
a5296ca9
AL
155 }
156
cd34d667
AL
157 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
158
0c17542d
MA
159 return dev;
160}
161
aae9460e
PB
162/* Create a new device. This only initializes the device state structure
163 and allows properties to be set. qdev_init should be called to
164 initialize the actual device emulation. */
02e2da45 165DeviceState *qdev_create(BusState *bus, const char *name)
0bcdeda7
BS
166{
167 DeviceState *dev;
168
169 dev = qdev_try_create(bus, name);
170 if (!dev) {
e92714c7
PM
171 if (bus) {
172 hw_error("Unknown device '%s' for bus '%s'\n", name,
173 bus->info->name);
174 } else {
175 hw_error("Unknown device '%s' for default sysbus\n", name);
176 }
0bcdeda7
BS
177 }
178
179 return dev;
180}
181
182DeviceState *qdev_try_create(BusState *bus, const char *name)
aae9460e 183{
10c4c98a 184 if (!bus) {
68694897 185 bus = sysbus_get_default();
10c4c98a
GH
186 }
187
18b6dade 188 return qdev_create_from_info(bus, name);
aae9460e
PB
189}
190
212ad111 191static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
1b524b04 192{
212ad111
AL
193 DeviceClass *dc;
194 bool *show_no_user = opaque;
195
196 dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
197
198 if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
199 return;
22f2e344 200 }
212ad111
AL
201
202 error_printf("name \"%s\"", object_class_get_name(klass));
203 if (dc->bus_info) {
204 error_printf(", bus %s", dc->bus_info->name);
22f2e344 205 }
6acbe4c6
AL
206 if (qdev_class_has_alias(dc)) {
207 error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
212ad111
AL
208 }
209 if (dc->desc) {
210 error_printf(", desc \"%s\"", dc->desc);
211 }
212 if (dc->no_user) {
8a9662ca 213 error_printf(", no-user");
22f2e344 214 }
8a9662ca 215 error_printf("\n");
1b524b04
GH
216}
217
f31d07d1 218static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 219{
f31d07d1
GH
220 DeviceState *dev = opaque;
221
222 if (strcmp(name, "driver") == 0)
223 return 0;
224 if (strcmp(name, "bus") == 0)
225 return 0;
226
3df04ac3 227 if (qdev_prop_parse(dev, name, value) == -1) {
f31d07d1
GH
228 return -1;
229 }
230 return 0;
231}
232
6acbe4c6
AL
233static const char *find_typename_by_alias(const char *alias)
234{
235 int i;
236
237 for (i = 0; qdev_alias_table[i].alias; i++) {
238 if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
239 return qdev_alias_table[i].typename;
240 }
241 }
242
243 return NULL;
244}
245
ff952ba2
MA
246int qdev_device_help(QemuOpts *opts)
247{
248 const char *driver;
08350cf0 249 Property *prop;
212ad111
AL
250 ObjectClass *klass;
251 DeviceClass *info;
ff952ba2
MA
252
253 driver = qemu_opt_get(opts, "driver");
254 if (driver && !strcmp(driver, "?")) {
212ad111
AL
255 bool show_no_user = false;
256 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
ff952ba2
MA
257 return 1;
258 }
259
542379f4 260 if (!driver || !qemu_opt_get(opts, "?")) {
08350cf0
MA
261 return 0;
262 }
263
212ad111 264 klass = object_class_by_name(driver);
6acbe4c6
AL
265 if (!klass) {
266 const char *typename = find_typename_by_alias(driver);
267
268 if (typename) {
269 driver = typename;
270 klass = object_class_by_name(driver);
271 }
272 }
273
212ad111 274 if (!klass) {
08350cf0
MA
275 return 0;
276 }
212ad111 277 info = DEVICE_CLASS(klass);
08350cf0
MA
278
279 for (prop = info->props; prop && prop->name; prop++) {
036f7166
MA
280 /*
281 * TODO Properties without a parser are just for dirty hacks.
282 * qdev_prop_ptr is the only such PropertyInfo. It's marked
283 * for removal. This conditional should be removed along with
284 * it.
285 */
286 if (!prop->info->parse) {
287 continue; /* no way to set it, don't show */
288 }
212ad111 289 error_printf("%s.%s=%s\n", driver, prop->name,
cafe5bdb 290 prop->info->legacy_name ?: prop->info->name);
a8467c7a
GH
291 }
292 for (prop = info->bus_info->props; prop && prop->name; prop++) {
293 if (!prop->info->parse) {
294 continue; /* no way to set it, don't show */
295 }
212ad111 296 error_printf("%s.%s=%s\n", driver, prop->name,
cafe5bdb 297 prop->info->legacy_name ?: prop->info->name);
08350cf0
MA
298 }
299 return 1;
ff952ba2
MA
300}
301
1bdaacb1
AL
302static DeviceState *qdev_get_peripheral(void)
303{
304 static DeviceState *dev;
305
306 if (dev == NULL) {
307 dev = qdev_create(NULL, "container");
308 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
309 qdev_init_nofail(dev);
310 }
311
312 return dev;
313}
314
8eb02831
AL
315static DeviceState *qdev_get_peripheral_anon(void)
316{
317 static DeviceState *dev;
318
319 if (dev == NULL) {
320 dev = qdev_create(NULL, "container");
321 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
322 qdev_init_nofail(dev);
323 }
324
325 return dev;
326}
327
f31d07d1
GH
328DeviceState *qdev_device_add(QemuOpts *opts)
329{
6acbe4c6 330 ObjectClass *obj;
18b6dade 331 DeviceClass *k;
f31d07d1 332 const char *driver, *path, *id;
8ffb1bcf
GH
333 DeviceState *qdev;
334 BusState *bus;
8ffb1bcf 335
f31d07d1
GH
336 driver = qemu_opt_get(opts, "driver");
337 if (!driver) {
0204276b 338 qerror_report(QERR_MISSING_PARAMETER, "driver");
8ffb1bcf
GH
339 return NULL;
340 }
f31d07d1
GH
341
342 /* find driver */
6acbe4c6
AL
343 obj = object_class_by_name(driver);
344 if (!obj) {
345 const char *typename = find_typename_by_alias(driver);
346
347 if (typename) {
348 driver = typename;
349 obj = object_class_by_name(driver);
350 }
351 }
352
353 if (!obj) {
354 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
355 return NULL;
356 }
357
358 k = DEVICE_CLASS(obj);
8ffb1bcf 359
f31d07d1
GH
360 /* find bus */
361 path = qemu_opt_get(opts, "bus");
362 if (path != NULL) {
8ffb1bcf 363 bus = qbus_find(path);
ac8dae67
MA
364 if (!bus) {
365 return NULL;
366 }
18b6dade 367 if (bus->info != k->bus_info) {
0204276b
MA
368 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
369 driver, bus->info->name);
327867b6
MA
370 return NULL;
371 }
8ffb1bcf 372 } else {
18b6dade 373 bus = qbus_find_recursive(main_system_bus, NULL, k->bus_info);
ac8dae67 374 if (!bus) {
0204276b 375 qerror_report(QERR_NO_BUS_FOR_DEVICE,
18b6dade 376 driver, k->bus_info->name);
ac8dae67
MA
377 return NULL;
378 }
75570088 379 }
3418bd25 380 if (qdev_hotplug && !bus->allow_hotplug) {
0204276b 381 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
3418bd25
GH
382 return NULL;
383 }
8ffb1bcf 384
f31d07d1 385 /* create device, set properties */
18b6dade 386 qdev = qdev_create_from_info(bus, driver);
f31d07d1
GH
387 id = qemu_opts_id(opts);
388 if (id) {
389 qdev->id = id;
1bdaacb1 390 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
8eb02831
AL
391 } else {
392 static int anon_count;
393 gchar *name = g_strdup_printf("device[%d]", anon_count++);
394 qdev_property_add_child(qdev_get_peripheral_anon(), name,
395 qdev, NULL);
396 g_free(name);
397 }
f31d07d1
GH
398 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
399 qdev_free(qdev);
400 return NULL;
8ffb1bcf 401 }
5c17ca25 402 if (qdev_init(qdev) < 0) {
0204276b 403 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
81a322d4
GH
404 return NULL;
405 }
ef80b466 406 qdev->opts = opts;
8ffb1bcf
GH
407 return qdev;
408}
409
aae9460e
PB
410/* Initialize a device. Device properties should be set before calling
411 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
412 calling this function.
413 On failure, destroy the device and return negative value.
414 Return 0 on success. */
81a322d4 415int qdev_init(DeviceState *dev)
aae9460e 416{
6e008585 417 DeviceClass *dc = DEVICE_GET_CLASS(dev);
959f733a
GH
418 int rc;
419
131ec1bd 420 assert(dev->state == DEV_STATE_CREATED);
6e008585 421
d307af79 422 rc = dc->init(dev);
18cfeb52
MA
423 if (rc < 0) {
424 qdev_free(dev);
959f733a 425 return rc;
18cfeb52 426 }
6e008585
AL
427 if (qdev_get_vmsd(dev)) {
428 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
4d2ffa08
JK
429 dev->instance_id_alias,
430 dev->alias_required_for_version);
431 }
131ec1bd 432 dev->state = DEV_STATE_INITIALIZED;
94afdadc
AL
433 if (dev->hotplugged) {
434 device_reset(dev);
5ab28c83 435 }
959f733a 436 return 0;
02e2da45
PB
437}
438
4d2ffa08
JK
439void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
440 int required_for_version)
441{
442 assert(dev->state == DEV_STATE_CREATED);
443 dev->instance_id_alias = alias_id;
444 dev->alias_required_for_version = required_for_version;
445}
446
3418bd25
GH
447int qdev_unplug(DeviceState *dev)
448{
6e008585
AL
449 DeviceClass *dc = DEVICE_GET_CLASS(dev);
450
3418bd25 451 if (!dev->parent_bus->allow_hotplug) {
cc601cb7 452 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
3418bd25
GH
453 return -1;
454 }
6e008585 455 assert(dc->unplug != NULL);
593831de 456
0ac8ef71
AW
457 qdev_hot_removed = true;
458
6e008585 459 return dc->unplug(dev);
3418bd25
GH
460}
461
ec990eb6
AL
462static int qdev_reset_one(DeviceState *dev, void *opaque)
463{
94afdadc 464 device_reset(dev);
ec990eb6
AL
465
466 return 0;
467}
468
469BusState *sysbus_get_default(void)
470{
68694897 471 if (!main_system_bus) {
2da8bb92 472 main_system_bus_create();
68694897 473 }
ec990eb6
AL
474 return main_system_bus;
475}
476
b4694b7c
IY
477static int qbus_reset_one(BusState *bus, void *opaque)
478{
479 if (bus->info->reset) {
480 return bus->info->reset(bus);
481 }
482 return 0;
483}
484
5af0a04b
IY
485void qdev_reset_all(DeviceState *dev)
486{
487 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
488}
489
80376c3f
IY
490void qbus_reset_all_fn(void *opaque)
491{
492 BusState *bus = opaque;
f530cce3 493 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
80376c3f
IY
494}
495
3418bd25
GH
496/* can be used as ->unplug() callback for the simple cases */
497int qdev_simple_unplug_cb(DeviceState *dev)
498{
499 /* just zap it */
500 qdev_free(dev);
501 return 0;
502}
503
3b29a101
MT
504
505/* Like qdev_init(), but terminate program via error_report() instead of
e23a1b33
MA
506 returning an error value. This is okay during machine creation.
507 Don't use for hotplug, because there callers need to recover from
508 failure. Exception: if you know the device's init() callback can't
509 fail, then qdev_init_nofail() can't fail either, and is therefore
510 usable even then. But relying on the device implementation that
511 way is somewhat unclean, and best avoided. */
512void qdev_init_nofail(DeviceState *dev)
513{
bd6c9a61 514 if (qdev_init(dev) < 0) {
6e008585
AL
515 error_report("Initialization of device %s failed",
516 object_get_typename(OBJECT(dev)));
bd6c9a61
MA
517 exit(1);
518 }
e23a1b33
MA
519}
520
44677ded
AL
521static void qdev_property_del_all(DeviceState *dev)
522{
523 while (!QTAILQ_EMPTY(&dev->properties)) {
524 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
525
526 QTAILQ_REMOVE(&dev->properties, prop, node);
527
528 if (prop->release) {
529 prop->release(dev, prop->name, prop->opaque);
530 }
531
532 g_free(prop->name);
533 g_free(prop->type);
534 g_free(prop);
535 }
536}
537
024a6fbd
AL
538static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
539{
540 DeviceProperty *prop;
541
542 QTAILQ_FOREACH(prop, &dev->properties, node) {
543 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
544 break;
545 }
546 }
547
548 g_assert(prop != NULL);
549
550 QTAILQ_REMOVE(&dev->properties, prop, node);
551
552 if (prop->release) {
553 prop->release(dev, prop->name, prop->opaque);
554 }
555
556 g_free(prop->name);
557 g_free(prop->type);
558 g_free(prop);
559}
560
02e2da45
PB
561/* Unlink device from bus and free the structure. */
562void qdev_free(DeviceState *dev)
563{
131ec1bd 564 BusState *bus;
d21357df 565 Property *prop;
6e008585 566 DeviceClass *dc = DEVICE_GET_CLASS(dev);
131ec1bd 567
44677ded
AL
568 qdev_property_del_all(dev);
569
131ec1bd
GH
570 if (dev->state == DEV_STATE_INITIALIZED) {
571 while (dev->num_child_bus) {
572 bus = QLIST_FIRST(&dev->child_bus);
573 qbus_free(bus);
574 }
6e008585
AL
575 if (qdev_get_vmsd(dev)) {
576 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
577 }
578 if (dc->exit) {
579 dc->exit(dev);
580 }
581 if (dev->opts) {
ef80b466 582 qemu_opts_del(dev->opts);
6e008585 583 }
131ec1bd 584 }
d8bb00d6 585 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
6e008585 586 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
d21357df
MA
587 if (prop->info->free) {
588 prop->info->free(dev, prop);
589 }
590 }
024a6fbd
AL
591 if (dev->parent) {
592 qdev_property_del_child(dev->parent, dev, NULL);
593 }
594 if (dev->ref != 0) {
595 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
596 }
32fea402 597 object_delete(OBJECT(dev));
aae9460e
PB
598}
599
3418bd25
GH
600void qdev_machine_creation_done(void)
601{
602 /*
603 * ok, initial machine setup is done, starting from now we can
604 * only create hotpluggable devices
605 */
606 qdev_hotplug = 1;
607}
608
0ac8ef71
AW
609bool qdev_machine_modified(void)
610{
611 return qdev_hot_added || qdev_hot_removed;
612}
613
aae9460e
PB
614/* Get a character (serial) device interface. */
615CharDriverState *qdev_init_chardev(DeviceState *dev)
616{
617 static int next_serial;
98b19252
AS
618
619 /* FIXME: This function needs to go away: use chardev properties! */
620 return serial_hds[next_serial++];
aae9460e
PB
621}
622
02e2da45 623BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 624{
02e2da45 625 return dev->parent_bus;
aae9460e
PB
626}
627
aae9460e
PB
628void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
629{
630 assert(dev->num_gpio_in == 0);
631 dev->num_gpio_in = n;
632 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
633}
634
635void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
636{
637 assert(dev->num_gpio_out == 0);
638 dev->num_gpio_out = n;
639 dev->gpio_out = pins;
640}
641
642qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
643{
644 assert(n >= 0 && n < dev->num_gpio_in);
645 return dev->gpio_in[n];
646}
647
648void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
649{
650 assert(n >= 0 && n < dev->num_gpio_out);
651 dev->gpio_out[n] = pin;
652}
653
ed16ab5a
GH
654void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
655{
6eed1856 656 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
ed16ab5a
GH
657 if (nd->vlan)
658 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
659 if (nd->netdev)
660 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
75422b0d 661 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
97b15621
GH
662 qdev_prop_exists(dev, "vectors")) {
663 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
664 }
48e2faf2 665 nd->instantiated = 1;
ed16ab5a
GH
666}
667
02e2da45 668BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 669{
02e2da45 670 BusState *bus;
4d6ae674 671
72cf2d4f 672 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 673 if (strcmp(name, bus->name) == 0) {
02e2da45 674 return bus;
4d6ae674
PB
675 }
676 }
677 return NULL;
678}
679
81699d8a
AL
680int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
681 qbus_walkerfn *busfn, void *opaque)
682{
683 DeviceState *dev;
684 int err;
685
686 if (busfn) {
687 err = busfn(bus, opaque);
688 if (err) {
689 return err;
690 }
691 }
692
d8bb00d6 693 QTAILQ_FOREACH(dev, &bus->children, sibling) {
81699d8a
AL
694 err = qdev_walk_children(dev, devfn, busfn, opaque);
695 if (err < 0) {
696 return err;
697 }
698 }
699
700 return 0;
701}
702
703int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
704 qbus_walkerfn *busfn, void *opaque)
705{
706 BusState *bus;
707 int err;
708
709 if (devfn) {
710 err = devfn(dev, opaque);
711 if (err) {
712 return err;
713 }
714 }
715
716 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
717 err = qbus_walk_children(bus, devfn, busfn, opaque);
718 if (err < 0) {
719 return err;
720 }
721 }
722
723 return 0;
724}
725
8ffb1bcf
GH
726static BusState *qbus_find_recursive(BusState *bus, const char *name,
727 const BusInfo *info)
728{
729 DeviceState *dev;
730 BusState *child, *ret;
731 int match = 1;
732
733 if (name && (strcmp(bus->name, name) != 0)) {
734 match = 0;
735 }
736 if (info && (bus->info != info)) {
737 match = 0;
738 }
739 if (match) {
740 return bus;
741 }
742
d8bb00d6 743 QTAILQ_FOREACH(dev, &bus->children, sibling) {
72cf2d4f 744 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
745 ret = qbus_find_recursive(child, name, info);
746 if (ret) {
747 return ret;
748 }
749 }
750 }
751 return NULL;
752}
753
a2ee6b4f 754DeviceState *qdev_find_recursive(BusState *bus, const char *id)
3418bd25
GH
755{
756 DeviceState *dev, *ret;
757 BusState *child;
758
d8bb00d6 759 QTAILQ_FOREACH(dev, &bus->children, sibling) {
3418bd25
GH
760 if (dev->id && strcmp(dev->id, id) == 0)
761 return dev;
762 QLIST_FOREACH(child, &dev->child_bus, sibling) {
763 ret = qdev_find_recursive(child, id);
764 if (ret) {
765 return ret;
766 }
767 }
768 }
769 return NULL;
770}
771
53db16b5 772static void qbus_list_bus(DeviceState *dev)
8ffb1bcf
GH
773{
774 BusState *child;
775 const char *sep = " ";
8ffb1bcf 776
53db16b5 777 error_printf("child busses at \"%s\":",
f79f2bfc 778 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
72cf2d4f 779 QLIST_FOREACH(child, &dev->child_bus, sibling) {
53db16b5 780 error_printf("%s\"%s\"", sep, child->name);
8ffb1bcf
GH
781 sep = ", ";
782 }
53db16b5 783 error_printf("\n");
8ffb1bcf
GH
784}
785
53db16b5 786static void qbus_list_dev(BusState *bus)
8ffb1bcf
GH
787{
788 DeviceState *dev;
789 const char *sep = " ";
8ffb1bcf 790
53db16b5 791 error_printf("devices at \"%s\":", bus->name);
d8bb00d6 792 QTAILQ_FOREACH(dev, &bus->children, sibling) {
f79f2bfc 793 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
8ffb1bcf 794 if (dev->id)
53db16b5 795 error_printf("/\"%s\"", dev->id);
8ffb1bcf
GH
796 sep = ", ";
797 }
53db16b5 798 error_printf("\n");
8ffb1bcf
GH
799}
800
801static BusState *qbus_find_bus(DeviceState *dev, char *elem)
802{
803 BusState *child;
804
72cf2d4f 805 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
806 if (strcmp(child->name, elem) == 0) {
807 return child;
808 }
809 }
810 return NULL;
811}
812
813static DeviceState *qbus_find_dev(BusState *bus, char *elem)
814{
815 DeviceState *dev;
816
817 /*
818 * try to match in order:
819 * (1) instance id, if present
820 * (2) driver name
821 * (3) driver alias, if present
822 */
d8bb00d6 823 QTAILQ_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
824 if (dev->id && strcmp(dev->id, elem) == 0) {
825 return dev;
826 }
827 }
d8bb00d6 828 QTAILQ_FOREACH(dev, &bus->children, sibling) {
f79f2bfc 829 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
8ffb1bcf
GH
830 return dev;
831 }
832 }
d8bb00d6 833 QTAILQ_FOREACH(dev, &bus->children, sibling) {
6e008585
AL
834 DeviceClass *dc = DEVICE_GET_CLASS(dev);
835
6acbe4c6
AL
836 if (qdev_class_has_alias(dc) &&
837 strcmp(qdev_class_get_alias(dc), elem) == 0) {
8ffb1bcf
GH
838 return dev;
839 }
840 }
841 return NULL;
842}
843
844static BusState *qbus_find(const char *path)
845{
846 DeviceState *dev;
847 BusState *bus;
53db16b5 848 char elem[128];
8ffb1bcf
GH
849 int pos, len;
850
851 /* find start element */
852 if (path[0] == '/') {
853 bus = main_system_bus;
854 pos = 0;
855 } else {
856 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
fc98eb43
MA
857 assert(!path[0]);
858 elem[0] = len = 0;
8ffb1bcf
GH
859 }
860 bus = qbus_find_recursive(main_system_bus, elem, NULL);
861 if (!bus) {
ac8dae67 862 qerror_report(QERR_BUS_NOT_FOUND, elem);
8ffb1bcf
GH
863 return NULL;
864 }
865 pos = len;
866 }
867
868 for (;;) {
fc98eb43
MA
869 assert(path[pos] == '/' || !path[pos]);
870 while (path[pos] == '/') {
871 pos++;
872 }
8ffb1bcf 873 if (path[pos] == '\0') {
8ffb1bcf
GH
874 return bus;
875 }
876
877 /* find device */
fc98eb43
MA
878 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
879 assert(0);
880 elem[0] = len = 0;
8ffb1bcf
GH
881 }
882 pos += len;
883 dev = qbus_find_dev(bus, elem);
884 if (!dev) {
ac8dae67 885 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
8bc27249
MA
886 if (!monitor_cur_is_qmp()) {
887 qbus_list_dev(bus);
888 }
8ffb1bcf
GH
889 return NULL;
890 }
fc98eb43
MA
891
892 assert(path[pos] == '/' || !path[pos]);
893 while (path[pos] == '/') {
894 pos++;
895 }
8ffb1bcf
GH
896 if (path[pos] == '\0') {
897 /* last specified element is a device. If it has exactly
898 * one child bus accept it nevertheless */
899 switch (dev->num_child_bus) {
900 case 0:
ac8dae67 901 qerror_report(QERR_DEVICE_NO_BUS, elem);
8ffb1bcf
GH
902 return NULL;
903 case 1:
72cf2d4f 904 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf 905 default:
ac8dae67 906 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
8bc27249
MA
907 if (!monitor_cur_is_qmp()) {
908 qbus_list_bus(dev);
909 }
8ffb1bcf
GH
910 return NULL;
911 }
912 }
913
914 /* find bus */
fc98eb43
MA
915 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
916 assert(0);
917 elem[0] = len = 0;
8ffb1bcf
GH
918 }
919 pos += len;
920 bus = qbus_find_bus(dev, elem);
921 if (!bus) {
ac8dae67 922 qerror_report(QERR_BUS_NOT_FOUND, elem);
8bc27249
MA
923 if (!monitor_cur_is_qmp()) {
924 qbus_list_bus(dev);
925 }
8ffb1bcf
GH
926 return NULL;
927 }
928 }
929}
930
cd739fb6
GH
931void qbus_create_inplace(BusState *bus, BusInfo *info,
932 DeviceState *parent, const char *name)
02e2da45 933{
d271de9f
GH
934 char *buf;
935 int i,len;
02e2da45 936
10c4c98a 937 bus->info = info;
02e2da45 938 bus->parent = parent;
d271de9f
GH
939
940 if (name) {
941 /* use supplied name */
7267c094 942 bus->name = g_strdup(name);
d271de9f
GH
943 } else if (parent && parent->id) {
944 /* parent device has id -> use it for bus name */
945 len = strlen(parent->id) + 16;
7267c094 946 buf = g_malloc(len);
d271de9f
GH
947 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
948 bus->name = buf;
949 } else {
950 /* no id -> use lowercase bus type for bus name */
951 len = strlen(info->name) + 16;
7267c094 952 buf = g_malloc(len);
d271de9f
GH
953 len = snprintf(buf, len, "%s.%d", info->name,
954 parent ? parent->num_child_bus : 0);
955 for (i = 0; i < len; i++)
bb87ece5 956 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
957 bus->name = buf;
958 }
959
d8bb00d6 960 QTAILQ_INIT(&bus->children);
02e2da45 961 if (parent) {
72cf2d4f 962 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 963 parent->num_child_bus++;
80376c3f
IY
964 } else if (bus != main_system_bus) {
965 /* TODO: once all bus devices are qdevified,
966 only reset handler for main_system_bus should be registered here. */
967 qemu_register_reset(qbus_reset_all_fn, bus);
02e2da45 968 }
cd739fb6
GH
969}
970
971BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
972{
973 BusState *bus;
974
7267c094 975 bus = g_malloc0(info->size);
cd739fb6
GH
976 bus->qdev_allocated = 1;
977 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
978 return bus;
979}
cae4956e 980
2da8bb92
IY
981static void main_system_bus_create(void)
982{
983 /* assign main_system_bus before qbus_create_inplace()
984 * in order to make "if (bus != main_system_bus)" work */
7267c094 985 main_system_bus = g_malloc0(system_bus_info.size);
2da8bb92
IY
986 main_system_bus->qdev_allocated = 1;
987 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
988 "main-system-bus");
989}
990
131ec1bd
GH
991void qbus_free(BusState *bus)
992{
993 DeviceState *dev;
994
d8bb00d6 995 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
131ec1bd
GH
996 qdev_free(dev);
997 }
998 if (bus->parent) {
999 QLIST_REMOVE(bus, sibling);
1000 bus->parent->num_child_bus--;
80376c3f
IY
1001 } else {
1002 assert(bus != main_system_bus); /* main_system_bus is never freed */
1003 qemu_unregister_reset(qbus_reset_all_fn, bus);
131ec1bd 1004 }
7267c094 1005 g_free((void*)bus->name);
131ec1bd 1006 if (bus->qdev_allocated) {
7267c094 1007 g_free(bus);
131ec1bd
GH
1008 }
1009}
1010
cae4956e
GH
1011#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
1012static void qbus_print(Monitor *mon, BusState *bus, int indent);
1013
ee6847d1
GH
1014static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
1015 const char *prefix, int indent)
1016{
1017 char buf[64];
1018
1019 if (!props)
1020 return;
1021 while (props->name) {
036f7166
MA
1022 /*
1023 * TODO Properties without a print method are just for dirty
1024 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1025 * marked for removal. The test props->info->print should be
1026 * removed along with it.
1027 */
ee6847d1
GH
1028 if (props->info->print) {
1029 props->info->print(dev, props, buf, sizeof(buf));
1030 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1031 }
1032 props++;
1033 }
1034}
1035
cae4956e
GH
1036static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1037{
cae4956e 1038 BusState *child;
f79f2bfc 1039 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
ccb63de3 1040 dev->id ? dev->id : "");
cae4956e
GH
1041 indent += 2;
1042 if (dev->num_gpio_in) {
1043 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1044 }
1045 if (dev->num_gpio_out) {
1046 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1047 }
6e008585 1048 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
ee6847d1 1049 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
1050 if (dev->parent_bus->info->print_dev)
1051 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 1052 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
1053 qbus_print(mon, child, indent);
1054 }
1055}
1056
1057static void qbus_print(Monitor *mon, BusState *bus, int indent)
1058{
1059 struct DeviceState *dev;
1060
1061 qdev_printf("bus: %s\n", bus->name);
1062 indent += 2;
10c4c98a 1063 qdev_printf("type %s\n", bus->info->name);
d8bb00d6 1064 QTAILQ_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
1065 qdev_print(mon, dev, indent);
1066 }
1067}
1068#undef qdev_printf
1069
1070void do_info_qtree(Monitor *mon)
1071{
1072 if (main_system_bus)
1073 qbus_print(mon, main_system_bus, 0);
1074}
9316d30f 1075
f6c64e0e 1076void do_info_qdm(Monitor *mon)
9316d30f 1077{
212ad111 1078 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
9316d30f 1079}
3418bd25 1080
8bc27249 1081int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
1082{
1083 QemuOpts *opts;
1084
3329f07b 1085 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
8bc27249
MA
1086 if (!opts) {
1087 return -1;
1088 }
1089 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1090 qemu_opts_del(opts);
1091 return 0;
0f853a38 1092 }
8bc27249
MA
1093 if (!qdev_device_add(opts)) {
1094 qemu_opts_del(opts);
1095 return -1;
1096 }
1097 return 0;
3418bd25
GH
1098}
1099
17a38eaa 1100int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
1101{
1102 const char *id = qdict_get_str(qdict, "id");
1103 DeviceState *dev;
1104
1105 dev = qdev_find_recursive(main_system_bus, id);
1106 if (NULL == dev) {
17a38eaa
MA
1107 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1108 return -1;
3418bd25 1109 }
17a38eaa 1110 return qdev_unplug(dev);
3418bd25 1111}
1ca4d09a
GN
1112
1113static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1114{
1115 int l = 0;
1116
1117 if (dev && dev->parent_bus) {
1118 char *d;
1119 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1120 if (dev->parent_bus->info->get_fw_dev_path) {
1121 d = dev->parent_bus->info->get_fw_dev_path(dev);
1122 l += snprintf(p + l, size - l, "%s", d);
7267c094 1123 g_free(d);
1ca4d09a 1124 } else {
f79f2bfc 1125 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
1ca4d09a
GN
1126 }
1127 }
1128 l += snprintf(p + l , size - l, "/");
1129
1130 return l;
1131}
1132
1133char* qdev_get_fw_dev_path(DeviceState *dev)
1134{
1135 char path[128];
1136 int l;
1137
1138 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1139
1140 path[l-1] = '\0';
1141
1142 return strdup(path);
1143}
85ed303b 1144
cd34d667
AL
1145char *qdev_get_type(DeviceState *dev, Error **errp)
1146{
f79f2bfc 1147 return g_strdup(object_get_typename(OBJECT(dev)));
cd34d667
AL
1148}
1149
85ed303b
AL
1150void qdev_ref(DeviceState *dev)
1151{
1152 dev->ref++;
1153}
1154
1155void qdev_unref(DeviceState *dev)
1156{
1157 g_assert(dev->ref > 0);
1158 dev->ref--;
1159}
44677ded
AL
1160
1161void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1162 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1163 DevicePropertyRelease *release,
1164 void *opaque, Error **errp)
1165{
1166 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1167
1168 prop->name = g_strdup(name);
1169 prop->type = g_strdup(type);
1170
1171 prop->get = get;
1172 prop->set = set;
1173 prop->release = release;
1174 prop->opaque = opaque;
1175
1176 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1177}
1178
1179static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1180{
1181 DeviceProperty *prop;
1182
1183 QTAILQ_FOREACH(prop, &dev->properties, node) {
1184 if (strcmp(prop->name, name) == 0) {
1185 return prop;
1186 }
1187 }
1188
1189 return NULL;
1190}
1191
1192void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1193 Error **errp)
1194{
1195 DeviceProperty *prop = qdev_property_find(dev, name);
1196
1197 if (prop == NULL) {
1198 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1199 return;
1200 }
1201
1202 if (!prop->get) {
1203 error_set(errp, QERR_PERMISSION_DENIED);
1204 } else {
1205 prop->get(dev, v, prop->opaque, name, errp);
1206 }
1207}
1208
1209void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1210 Error **errp)
1211{
1212 DeviceProperty *prop = qdev_property_find(dev, name);
1213
1214 if (prop == NULL) {
1215 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1216 return;
1217 }
1218
1219 if (!prop->set) {
1220 error_set(errp, QERR_PERMISSION_DENIED);
1221 } else {
0d41d9aa 1222 prop->set(dev, v, prop->opaque, name, errp);
44677ded
AL
1223 }
1224}
1225
1226const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1227{
1228 DeviceProperty *prop = qdev_property_find(dev, name);
1229
1230 if (prop == NULL) {
1231 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1232 return NULL;
1233 }
1234
1235 return prop->type;
1236}
a5296ca9
AL
1237
1238/**
1239 * Legacy property handling
1240 */
1241
1242static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1243 const char *name, Error **errp)
1244{
1245 Property *prop = opaque;
1246
e3cb6ba6
PB
1247 char buffer[1024];
1248 char *ptr = buffer;
a5296ca9 1249
e3cb6ba6
PB
1250 prop->info->print(dev, prop, buffer, sizeof(buffer));
1251 visit_type_str(v, &ptr, name, errp);
a5296ca9
AL
1252}
1253
1254static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1255 const char *name, Error **errp)
1256{
1257 Property *prop = opaque;
e3cb6ba6
PB
1258 Error *local_err = NULL;
1259 char *ptr = NULL;
1260 int ret;
a5296ca9
AL
1261
1262 if (dev->state != DEV_STATE_CREATED) {
1263 error_set(errp, QERR_PERMISSION_DENIED);
1264 return;
1265 }
1266
e3cb6ba6
PB
1267 visit_type_str(v, &ptr, name, &local_err);
1268 if (local_err) {
1269 error_propagate(errp, local_err);
1270 return;
1271 }
a5296ca9 1272
e3cb6ba6 1273 ret = prop->info->parse(dev, prop, ptr);
7db4c4e8 1274 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
e3cb6ba6 1275 g_free(ptr);
a5296ca9
AL
1276}
1277
1278/**
1279 * @qdev_add_legacy_property - adds a legacy property
1280 *
1281 * Do not use this is new code! Properties added through this interface will
ca2cc788 1282 * be given names and types in the "legacy" namespace.
a5296ca9
AL
1283 *
1284 * Legacy properties are always processed as strings. The format of the string
1285 * depends on the property type.
1286 */
1287void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1288 Error **errp)
1289{
ca2cc788 1290 gchar *name, *type;
a5296ca9 1291
ca2cc788 1292 name = g_strdup_printf("legacy-%s", prop->name);
cafe5bdb
PB
1293 type = g_strdup_printf("legacy<%s>",
1294 prop->info->legacy_name ?: prop->info->name);
a5296ca9 1295
ca2cc788 1296 qdev_property_add(dev, name, type,
e3cb6ba6
PB
1297 prop->info->print ? qdev_get_legacy_property : NULL,
1298 prop->info->parse ? qdev_set_legacy_property : NULL,
a5296ca9
AL
1299 NULL,
1300 prop, errp);
1301
1302 g_free(type);
ca2cc788
PB
1303 g_free(name);
1304}
1305
1306/**
1307 * @qdev_property_add_static - add a @Property to a device.
1308 *
1309 * Static properties access data in a struct. The actual type of the
1310 * property and the field depends on the property type.
1311 */
1312void qdev_property_add_static(DeviceState *dev, Property *prop,
1313 Error **errp)
1314{
1315 qdev_property_add(dev, prop->name, prop->info->name,
1316 prop->info->get, prop->info->set,
1317 NULL,
1318 prop, errp);
a5296ca9 1319}
a10f07a7
AL
1320
1321DeviceState *qdev_get_root(void)
1322{
1323 static DeviceState *qdev_root;
1324
1325 if (!qdev_root) {
1326 qdev_root = qdev_create(NULL, "container");
1327 qdev_init_nofail(qdev_root);
1328 }
1329
1330 return qdev_root;
1331}
f9fbd2fd 1332
3de1c3e8
AL
1333static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1334 const char *name, Error **errp)
1335{
1336 DeviceState *child = opaque;
1337 gchar *path;
1338
1339 path = qdev_get_canonical_path(child);
1340 visit_type_str(v, &path, name, errp);
1341 g_free(path);
1342}
1343
024a6fbd
AL
1344static void qdev_release_child_property(DeviceState *dev, const char *name,
1345 void *opaque)
1346{
1347 DeviceState *child = opaque;
1348
1349 qdev_unref(child);
1350}
1351
3de1c3e8
AL
1352void qdev_property_add_child(DeviceState *dev, const char *name,
1353 DeviceState *child, Error **errp)
1354{
1355 gchar *type;
1356
f79f2bfc 1357 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
3de1c3e8
AL
1358
1359 qdev_property_add(dev, name, type, qdev_get_child_property,
024a6fbd
AL
1360 NULL, qdev_release_child_property,
1361 child, errp);
3de1c3e8
AL
1362
1363 qdev_ref(child);
b2b6c39a
AL
1364 g_assert(child->parent == NULL);
1365 child->parent = dev;
3de1c3e8
AL
1366
1367 g_free(type);
1368}
1369
83e94fb8
AL
1370static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1371 const char *name, Error **errp)
1372{
1373 DeviceState **child = opaque;
1374 gchar *path;
1375
1376 if (*child) {
1377 path = qdev_get_canonical_path(*child);
1378 visit_type_str(v, &path, name, errp);
1379 g_free(path);
1380 } else {
1381 path = (gchar *)"";
1382 visit_type_str(v, &path, name, errp);
1383 }
1384}
1385
1386static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1387 const char *name, Error **errp)
1388{
1389 DeviceState **child = opaque;
1390 bool ambiguous = false;
1391 const char *type;
1392 char *path;
1393
1394 type = qdev_property_get_type(dev, name, NULL);
1395
1396 visit_type_str(v, &path, name, errp);
1397
1398 if (*child) {
1399 qdev_unref(*child);
1400 }
1401
1402 if (strcmp(path, "") != 0) {
1403 DeviceState *target;
1404
1405 target = qdev_resolve_path(path, &ambiguous);
1406 if (target) {
1407 gchar *target_type;
1408
f79f2bfc 1409 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
83e94fb8
AL
1410 if (strcmp(target_type, type) == 0) {
1411 *child = target;
1412 qdev_ref(target);
1413 } else {
1414 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1415 }
1416
1417 g_free(target_type);
1418 } else {
1419 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1420 }
1421 } else {
1422 *child = NULL;
1423 }
1424
1425 g_free(path);
1426}
1427
1428void qdev_property_add_link(DeviceState *dev, const char *name,
1429 const char *type, DeviceState **child,
1430 Error **errp)
1431{
1432 gchar *full_type;
1433
1434 full_type = g_strdup_printf("link<%s>", type);
1435
1436 qdev_property_add(dev, name, full_type,
1437 qdev_get_link_property,
1438 qdev_set_link_property,
1439 NULL, child, errp);
1440
1441 g_free(full_type);
1442}
1443
b2b6c39a 1444gchar *qdev_get_canonical_path(DeviceState *dev)
f9fbd2fd 1445{
b2b6c39a
AL
1446 DeviceState *root = qdev_get_root();
1447 char *newpath = NULL, *path = NULL;
f9fbd2fd 1448
b2b6c39a
AL
1449 while (dev != root) {
1450 DeviceProperty *prop = NULL;
f9fbd2fd 1451
b2b6c39a 1452 g_assert(dev->parent != NULL);
f9fbd2fd 1453
b2b6c39a
AL
1454 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1455 if (!strstart(prop->type, "child<", NULL)) {
1456 continue;
1457 }
f9fbd2fd 1458
b2b6c39a
AL
1459 if (prop->opaque == dev) {
1460 if (path) {
1461 newpath = g_strdup_printf("%s/%s", prop->name, path);
1462 g_free(path);
1463 path = newpath;
1464 } else {
1465 path = g_strdup(prop->name);
1466 }
1467 break;
1468 }
f9fbd2fd
AL
1469 }
1470
b2b6c39a 1471 g_assert(prop != NULL);
f9fbd2fd 1472
b2b6c39a 1473 dev = dev->parent;
f9fbd2fd
AL
1474 }
1475
f9fbd2fd
AL
1476 newpath = g_strdup_printf("/%s", path);
1477 g_free(path);
1478
1479 return newpath;
1480}
dc45c21f
AL
1481
1482static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1483 gchar **parts,
1484 int index)
1485{
1486 DeviceProperty *prop;
1487 DeviceState *child;
1488
1489 if (parts[index] == NULL) {
1490 return parent;
1491 }
1492
1493 if (strcmp(parts[index], "") == 0) {
1494 return qdev_resolve_abs_path(parent, parts, index + 1);
1495 }
1496
1497 prop = qdev_property_find(parent, parts[index]);
1498 if (prop == NULL) {
1499 return NULL;
1500 }
1501
1502 child = NULL;
1503 if (strstart(prop->type, "link<", NULL)) {
1504 DeviceState **pchild = prop->opaque;
1505 if (*pchild) {
1506 child = *pchild;
1507 }
1508 } else if (strstart(prop->type, "child<", NULL)) {
1509 child = prop->opaque;
1510 }
1511
1512 if (!child) {
1513 return NULL;
1514 }
1515
1516 return qdev_resolve_abs_path(child, parts, index + 1);
1517}
1518
1519static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1520 gchar **parts,
1521 bool *ambiguous)
1522{
1523 DeviceState *dev;
1524 DeviceProperty *prop;
1525
1526 dev = qdev_resolve_abs_path(parent, parts, 0);
1527
1528 QTAILQ_FOREACH(prop, &parent->properties, node) {
1529 DeviceState *found;
1530
1531 if (!strstart(prop->type, "child<", NULL)) {
1532 continue;
1533 }
1534
1535 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1536 if (found) {
1537 if (dev) {
1538 if (ambiguous) {
1539 *ambiguous = true;
1540 }
1541 return NULL;
1542 }
1543 dev = found;
1544 }
1545
1546 if (ambiguous && *ambiguous) {
1547 return NULL;
1548 }
1549 }
1550
1551 return dev;
1552}
1553
1554DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1555{
1556 bool partial_path = true;
1557 DeviceState *dev;
1558 gchar **parts;
1559
1560 parts = g_strsplit(path, "/", 0);
1561 if (parts == NULL || parts[0] == NULL) {
1562 g_strfreev(parts);
1563 return qdev_get_root();
1564 }
1565
1566 if (strcmp(parts[0], "") == 0) {
1567 partial_path = false;
1568 }
1569
1570 if (partial_path) {
1571 if (ambiguous) {
1572 *ambiguous = false;
1573 }
1574 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1575 } else {
1576 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1577 }
1578
1579 g_strfreev(parts);
1580
1581 return dev;
1582}
1583
6a146eba
AL
1584typedef struct StringProperty
1585{
1586 char *(*get)(DeviceState *, Error **);
1587 void (*set)(DeviceState *, const char *, Error **);
1588} StringProperty;
1589
1590static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1591 const char *name, Error **errp)
1592{
1593 StringProperty *prop = opaque;
1594 char *value;
1595
1596 value = prop->get(dev, errp);
1597 if (value) {
1598 visit_type_str(v, &value, name, errp);
1599 g_free(value);
1600 }
1601}
1602
1603static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1604 const char *name, Error **errp)
1605{
1606 StringProperty *prop = opaque;
1607 char *value;
1608 Error *local_err = NULL;
1609
1610 visit_type_str(v, &value, name, &local_err);
1611 if (local_err) {
1612 error_propagate(errp, local_err);
1613 return;
1614 }
1615
1616 prop->set(dev, value, errp);
1617 g_free(value);
1618}
1619
1620static void qdev_property_release_str(DeviceState *dev, const char *name,
1621 void *opaque)
1622{
1623 StringProperty *prop = opaque;
1624 g_free(prop);
1625}
1626
1627void qdev_property_add_str(DeviceState *dev, const char *name,
1628 char *(*get)(DeviceState *, Error **),
1629 void (*set)(DeviceState *, const char *, Error **),
1630 Error **errp)
1631{
1632 StringProperty *prop = g_malloc0(sizeof(*prop));
1633
1634 prop->get = get;
1635 prop->set = set;
1636
1637 qdev_property_add(dev, name, "string",
1638 get ? qdev_property_get_str : NULL,
1639 set ? qdev_property_set_str : NULL,
1640 qdev_property_release_str,
1641 prop, errp);
1642}
1de81d28
AL
1643
1644void qdev_machine_init(void)
1645{
1646 qdev_get_peripheral_anon();
1647 qdev_get_peripheral();
1648}
32fea402 1649
94afdadc
AL
1650void device_reset(DeviceState *dev)
1651{
1652 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1653
1654 if (klass->reset) {
1655 klass->reset(dev);
1656 }
1657}
1658
32fea402
AL
1659static TypeInfo device_type_info = {
1660 .name = TYPE_DEVICE,
1661 .parent = TYPE_OBJECT,
1662 .instance_size = sizeof(DeviceState),
1663 .abstract = true,
1664 .class_size = sizeof(DeviceClass),
1665};
1666
1667static void init_qdev(void)
1668{
1669 type_register_static(&device_type_info);
1670}
1671
1672device_init(init_qdev);