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