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