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