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