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