]> git.proxmox.com Git - mirror_qemu.git/blame - hw/qdev.c
qdev: sysbus_get_default must not return a NULL pointer (fix regression)
[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"
2446333c 32#include "blockdev.h"
aae9460e 33
3418bd25
GH
34static int qdev_hotplug = 0;
35
cdaed7c7 36/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 37static BusState *main_system_bus;
4d6ae674 38
0958b4cc 39DeviceInfo *device_info_list;
aae9460e 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. */
074f2fff 46void qdev_register(DeviceInfo *info)
aae9460e 47{
074f2fff 48 assert(info->size >= sizeof(DeviceState));
042f84d0 49 assert(!info->next);
aae9460e 50
042f84d0
GH
51 info->next = device_info_list;
52 device_info_list = info;
aae9460e
PB
53}
54
81ebb98b
GH
55static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
56{
57 DeviceInfo *info;
58
3320e56e 59 /* first check device names */
81ebb98b
GH
60 for (info = device_info_list; info != NULL; info = info->next) {
61 if (bus_info && info->bus_info != bus_info)
62 continue;
63 if (strcmp(info->name, name) != 0)
64 continue;
65 return info;
66 }
3320e56e
GH
67
68 /* failing that check the aliases */
69 for (info = device_info_list; info != NULL; info = info->next) {
70 if (bus_info && info->bus_info != bus_info)
71 continue;
72 if (!info->alias)
73 continue;
74 if (strcmp(info->alias, name) != 0)
75 continue;
76 return info;
77 }
81ebb98b
GH
78 return NULL;
79}
80
0c17542d
MA
81static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
82{
83 DeviceState *dev;
84
85 assert(bus->info == info->bus_info);
86 dev = qemu_mallocz(info->size);
87 dev->info = info;
88 dev->parent_bus = bus;
89 qdev_prop_set_defaults(dev, dev->info->props);
90 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
91 qdev_prop_set_globals(dev);
92 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
93 if (qdev_hotplug) {
94 assert(bus->allow_hotplug);
95 dev->hotplugged = 1;
96 }
4d2ffa08 97 dev->instance_id_alias = -1;
0c17542d
MA
98 dev->state = DEV_STATE_CREATED;
99 return dev;
100}
101
aae9460e
PB
102/* Create a new device. This only initializes the device state structure
103 and allows properties to be set. qdev_init should be called to
104 initialize the actual device emulation. */
02e2da45 105DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e 106{
042f84d0 107 DeviceInfo *info;
aae9460e 108
10c4c98a 109 if (!bus) {
68694897 110 bus = sysbus_get_default();
10c4c98a
GH
111 }
112
81ebb98b 113 info = qdev_find_info(bus->info, name);
042f84d0 114 if (!info) {
10c4c98a 115 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
aae9460e
PB
116 }
117
0c17542d 118 return qdev_create_from_info(bus, info);
aae9460e
PB
119}
120
8a9662ca 121static void qdev_print_devinfo(DeviceInfo *info)
1b524b04 122{
8a9662ca
MA
123 error_printf("name \"%s\", bus %s",
124 info->name, info->bus_info->name);
22f2e344 125 if (info->alias) {
8a9662ca 126 error_printf(", alias \"%s\"", info->alias);
22f2e344
GH
127 }
128 if (info->desc) {
8a9662ca 129 error_printf(", desc \"%s\"", info->desc);
22f2e344
GH
130 }
131 if (info->no_user) {
8a9662ca 132 error_printf(", no-user");
22f2e344 133 }
8a9662ca 134 error_printf("\n");
1b524b04
GH
135}
136
f31d07d1 137static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 138{
f31d07d1
GH
139 DeviceState *dev = opaque;
140
141 if (strcmp(name, "driver") == 0)
142 return 0;
143 if (strcmp(name, "bus") == 0)
144 return 0;
145
3df04ac3 146 if (qdev_prop_parse(dev, name, value) == -1) {
f31d07d1
GH
147 return -1;
148 }
149 return 0;
150}
151
ff952ba2
MA
152int qdev_device_help(QemuOpts *opts)
153{
154 const char *driver;
155 DeviceInfo *info;
08350cf0 156 Property *prop;
ff952ba2
MA
157
158 driver = qemu_opt_get(opts, "driver");
159 if (driver && !strcmp(driver, "?")) {
160 for (info = device_info_list; info != NULL; info = info->next) {
c64eafaf
MA
161 if (info->no_user) {
162 continue; /* not available, don't show */
163 }
8a9662ca 164 qdev_print_devinfo(info);
ff952ba2
MA
165 }
166 return 1;
167 }
168
08350cf0
MA
169 if (!qemu_opt_get(opts, "?")) {
170 return 0;
171 }
172
173 info = qdev_find_info(NULL, driver);
174 if (!info) {
175 return 0;
176 }
177
178 for (prop = info->props; prop && prop->name; prop++) {
036f7166
MA
179 /*
180 * TODO Properties without a parser are just for dirty hacks.
181 * qdev_prop_ptr is the only such PropertyInfo. It's marked
182 * for removal. This conditional should be removed along with
183 * it.
184 */
185 if (!prop->info->parse) {
186 continue; /* no way to set it, don't show */
187 }
8a9662ca 188 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
08350cf0
MA
189 }
190 return 1;
ff952ba2
MA
191}
192
f31d07d1
GH
193DeviceState *qdev_device_add(QemuOpts *opts)
194{
195 const char *driver, *path, *id;
8ffb1bcf
GH
196 DeviceInfo *info;
197 DeviceState *qdev;
198 BusState *bus;
8ffb1bcf 199
f31d07d1
GH
200 driver = qemu_opt_get(opts, "driver");
201 if (!driver) {
0204276b 202 qerror_report(QERR_MISSING_PARAMETER, "driver");
8ffb1bcf
GH
203 return NULL;
204 }
f31d07d1
GH
205
206 /* find driver */
8ffb1bcf 207 info = qdev_find_info(NULL, driver);
c64eafaf 208 if (!info || info->no_user) {
e17ba87c 209 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
0204276b 210 error_printf_unless_qmp("Try with argument '?' for a list.\n");
8ffb1bcf
GH
211 return NULL;
212 }
8ffb1bcf 213
f31d07d1
GH
214 /* find bus */
215 path = qemu_opt_get(opts, "bus");
216 if (path != NULL) {
8ffb1bcf 217 bus = qbus_find(path);
ac8dae67
MA
218 if (!bus) {
219 return NULL;
220 }
221 if (bus->info != info->bus_info) {
0204276b
MA
222 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
223 driver, bus->info->name);
327867b6
MA
224 return NULL;
225 }
8ffb1bcf
GH
226 } else {
227 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
ac8dae67 228 if (!bus) {
0204276b
MA
229 qerror_report(QERR_NO_BUS_FOR_DEVICE,
230 info->name, info->bus_info->name);
ac8dae67
MA
231 return NULL;
232 }
75570088 233 }
3418bd25 234 if (qdev_hotplug && !bus->allow_hotplug) {
0204276b 235 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
3418bd25
GH
236 return NULL;
237 }
8ffb1bcf 238
f31d07d1 239 /* create device, set properties */
0c17542d 240 qdev = qdev_create_from_info(bus, info);
f31d07d1
GH
241 id = qemu_opts_id(opts);
242 if (id) {
243 qdev->id = id;
244 }
245 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
246 qdev_free(qdev);
247 return NULL;
8ffb1bcf 248 }
5c17ca25 249 if (qdev_init(qdev) < 0) {
0204276b 250 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
81a322d4
GH
251 return NULL;
252 }
ef80b466 253 qdev->opts = opts;
8ffb1bcf
GH
254 return qdev;
255}
256
aae9460e
PB
257/* Initialize a device. Device properties should be set before calling
258 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
259 calling this function.
260 On failure, destroy the device and return negative value.
261 Return 0 on success. */
81a322d4 262int qdev_init(DeviceState *dev)
aae9460e 263{
959f733a
GH
264 int rc;
265
131ec1bd 266 assert(dev->state == DEV_STATE_CREATED);
959f733a 267 rc = dev->info->init(dev, dev->info);
18cfeb52
MA
268 if (rc < 0) {
269 qdev_free(dev);
959f733a 270 return rc;
18cfeb52 271 }
4d2ffa08 272 if (dev->info->vmsd) {
0be71e32 273 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
4d2ffa08
JK
274 dev->instance_id_alias,
275 dev->alias_required_for_version);
276 }
131ec1bd 277 dev->state = DEV_STATE_INITIALIZED;
959f733a 278 return 0;
02e2da45
PB
279}
280
4d2ffa08
JK
281void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
282 int required_for_version)
283{
284 assert(dev->state == DEV_STATE_CREATED);
285 dev->instance_id_alias = alias_id;
286 dev->alias_required_for_version = required_for_version;
287}
288
3418bd25
GH
289int qdev_unplug(DeviceState *dev)
290{
291 if (!dev->parent_bus->allow_hotplug) {
cc601cb7 292 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
3418bd25
GH
293 return -1;
294 }
593831de
AS
295 assert(dev->info->unplug != NULL);
296
3418bd25
GH
297 return dev->info->unplug(dev);
298}
299
ec990eb6
AL
300static int qdev_reset_one(DeviceState *dev, void *opaque)
301{
302 if (dev->info->reset) {
303 dev->info->reset(dev);
304 }
305
306 return 0;
307}
308
309BusState *sysbus_get_default(void)
310{
68694897
SW
311 if (!main_system_bus) {
312 main_system_bus = qbus_create(&system_bus_info, NULL,
313 "main-system-bus");
314 }
ec990eb6
AL
315 return main_system_bus;
316}
317
b4694b7c
IY
318static int qbus_reset_one(BusState *bus, void *opaque)
319{
320 if (bus->info->reset) {
321 return bus->info->reset(bus);
322 }
323 return 0;
324}
325
5af0a04b
IY
326void qdev_reset_all(DeviceState *dev)
327{
328 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
329}
330
ec990eb6
AL
331void qbus_reset_all(BusState *bus)
332{
b4694b7c 333 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
ec990eb6
AL
334}
335
3418bd25
GH
336/* can be used as ->unplug() callback for the simple cases */
337int qdev_simple_unplug_cb(DeviceState *dev)
338{
339 /* just zap it */
340 qdev_free(dev);
341 return 0;
342}
343
e23a1b33
MA
344/* Like qdev_init(), but terminate program via hw_error() instead of
345 returning an error value. This is okay during machine creation.
346 Don't use for hotplug, because there callers need to recover from
347 failure. Exception: if you know the device's init() callback can't
348 fail, then qdev_init_nofail() can't fail either, and is therefore
349 usable even then. But relying on the device implementation that
350 way is somewhat unclean, and best avoided. */
351void qdev_init_nofail(DeviceState *dev)
352{
353 DeviceInfo *info = dev->info;
354
bd6c9a61
MA
355 if (qdev_init(dev) < 0) {
356 error_report("Initialization of device %s failed\n", info->name);
357 exit(1);
358 }
e23a1b33
MA
359}
360
02e2da45
PB
361/* Unlink device from bus and free the structure. */
362void qdev_free(DeviceState *dev)
363{
131ec1bd 364 BusState *bus;
d21357df 365 Property *prop;
131ec1bd
GH
366
367 if (dev->state == DEV_STATE_INITIALIZED) {
368 while (dev->num_child_bus) {
369 bus = QLIST_FIRST(&dev->child_bus);
370 qbus_free(bus);
371 }
131ec1bd 372 if (dev->info->vmsd)
0be71e32 373 vmstate_unregister(dev, dev->info->vmsd, dev);
d29275f1
GH
374 if (dev->info->exit)
375 dev->info->exit(dev);
ef80b466
GH
376 if (dev->opts)
377 qemu_opts_del(dev->opts);
131ec1bd 378 }
72cf2d4f 379 QLIST_REMOVE(dev, sibling);
d21357df
MA
380 for (prop = dev->info->props; prop && prop->name; prop++) {
381 if (prop->info->free) {
382 prop->info->free(dev, prop);
383 }
384 }
ccb63de3 385 qemu_free(dev);
aae9460e
PB
386}
387
3418bd25
GH
388void qdev_machine_creation_done(void)
389{
390 /*
391 * ok, initial machine setup is done, starting from now we can
392 * only create hotpluggable devices
393 */
394 qdev_hotplug = 1;
395}
396
aae9460e
PB
397/* Get a character (serial) device interface. */
398CharDriverState *qdev_init_chardev(DeviceState *dev)
399{
400 static int next_serial;
98b19252
AS
401
402 /* FIXME: This function needs to go away: use chardev properties! */
403 return serial_hds[next_serial++];
aae9460e
PB
404}
405
02e2da45 406BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 407{
02e2da45 408 return dev->parent_bus;
aae9460e
PB
409}
410
aae9460e
PB
411void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
412{
413 assert(dev->num_gpio_in == 0);
414 dev->num_gpio_in = n;
415 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
416}
417
418void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
419{
420 assert(dev->num_gpio_out == 0);
421 dev->num_gpio_out = n;
422 dev->gpio_out = pins;
423}
424
425qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
426{
427 assert(n >= 0 && n < dev->num_gpio_in);
428 return dev->gpio_in[n];
429}
430
431void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
432{
433 assert(n >= 0 && n < dev->num_gpio_out);
434 dev->gpio_out[n] = pin;
435}
436
ed16ab5a
GH
437void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
438{
439 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
440 if (nd->vlan)
441 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
442 if (nd->netdev)
443 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
75422b0d 444 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
97b15621
GH
445 qdev_prop_exists(dev, "vectors")) {
446 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
447 }
ed16ab5a
GH
448}
449
aae9460e
PB
450static int next_block_unit[IF_COUNT];
451
452/* Get a block device. This should only be used for single-drive devices
453 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
454 appropriate bus. */
455BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
456{
457 int unit = next_block_unit[type]++;
751c6a17 458 DriveInfo *dinfo;
aae9460e 459
751c6a17
GH
460 dinfo = drive_get(type, 0, unit);
461 return dinfo ? dinfo->bdrv : NULL;
aae9460e 462}
4d6ae674 463
02e2da45 464BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 465{
02e2da45 466 BusState *bus;
4d6ae674 467
72cf2d4f 468 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 469 if (strcmp(name, bus->name) == 0) {
02e2da45 470 return bus;
4d6ae674
PB
471 }
472 }
473 return NULL;
474}
475
81699d8a
AL
476int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
477 qbus_walkerfn *busfn, void *opaque)
478{
479 DeviceState *dev;
480 int err;
481
482 if (busfn) {
483 err = busfn(bus, opaque);
484 if (err) {
485 return err;
486 }
487 }
488
489 QLIST_FOREACH(dev, &bus->children, sibling) {
490 err = qdev_walk_children(dev, devfn, busfn, opaque);
491 if (err < 0) {
492 return err;
493 }
494 }
495
496 return 0;
497}
498
499int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
500 qbus_walkerfn *busfn, void *opaque)
501{
502 BusState *bus;
503 int err;
504
505 if (devfn) {
506 err = devfn(dev, opaque);
507 if (err) {
508 return err;
509 }
510 }
511
512 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
513 err = qbus_walk_children(bus, devfn, busfn, opaque);
514 if (err < 0) {
515 return err;
516 }
517 }
518
519 return 0;
520}
521
8ffb1bcf
GH
522static BusState *qbus_find_recursive(BusState *bus, const char *name,
523 const BusInfo *info)
524{
525 DeviceState *dev;
526 BusState *child, *ret;
527 int match = 1;
528
529 if (name && (strcmp(bus->name, name) != 0)) {
530 match = 0;
531 }
532 if (info && (bus->info != info)) {
533 match = 0;
534 }
535 if (match) {
536 return bus;
537 }
538
72cf2d4f
BS
539 QLIST_FOREACH(dev, &bus->children, sibling) {
540 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
541 ret = qbus_find_recursive(child, name, info);
542 if (ret) {
543 return ret;
544 }
545 }
546 }
547 return NULL;
548}
549
3418bd25
GH
550static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
551{
552 DeviceState *dev, *ret;
553 BusState *child;
554
555 QLIST_FOREACH(dev, &bus->children, sibling) {
556 if (dev->id && strcmp(dev->id, id) == 0)
557 return dev;
558 QLIST_FOREACH(child, &dev->child_bus, sibling) {
559 ret = qdev_find_recursive(child, id);
560 if (ret) {
561 return ret;
562 }
563 }
564 }
565 return NULL;
566}
567
53db16b5 568static void qbus_list_bus(DeviceState *dev)
8ffb1bcf
GH
569{
570 BusState *child;
571 const char *sep = " ";
8ffb1bcf 572
53db16b5
MA
573 error_printf("child busses at \"%s\":",
574 dev->id ? dev->id : dev->info->name);
72cf2d4f 575 QLIST_FOREACH(child, &dev->child_bus, sibling) {
53db16b5 576 error_printf("%s\"%s\"", sep, child->name);
8ffb1bcf
GH
577 sep = ", ";
578 }
53db16b5 579 error_printf("\n");
8ffb1bcf
GH
580}
581
53db16b5 582static void qbus_list_dev(BusState *bus)
8ffb1bcf
GH
583{
584 DeviceState *dev;
585 const char *sep = " ";
8ffb1bcf 586
53db16b5 587 error_printf("devices at \"%s\":", bus->name);
72cf2d4f 588 QLIST_FOREACH(dev, &bus->children, sibling) {
53db16b5 589 error_printf("%s\"%s\"", sep, dev->info->name);
8ffb1bcf 590 if (dev->id)
53db16b5 591 error_printf("/\"%s\"", dev->id);
8ffb1bcf
GH
592 sep = ", ";
593 }
53db16b5 594 error_printf("\n");
8ffb1bcf
GH
595}
596
597static BusState *qbus_find_bus(DeviceState *dev, char *elem)
598{
599 BusState *child;
600
72cf2d4f 601 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
602 if (strcmp(child->name, elem) == 0) {
603 return child;
604 }
605 }
606 return NULL;
607}
608
609static DeviceState *qbus_find_dev(BusState *bus, char *elem)
610{
611 DeviceState *dev;
612
613 /*
614 * try to match in order:
615 * (1) instance id, if present
616 * (2) driver name
617 * (3) driver alias, if present
618 */
72cf2d4f 619 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
620 if (dev->id && strcmp(dev->id, elem) == 0) {
621 return dev;
622 }
623 }
72cf2d4f 624 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
625 if (strcmp(dev->info->name, elem) == 0) {
626 return dev;
627 }
628 }
72cf2d4f 629 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
630 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
631 return dev;
632 }
633 }
634 return NULL;
635}
636
637static BusState *qbus_find(const char *path)
638{
639 DeviceState *dev;
640 BusState *bus;
53db16b5 641 char elem[128];
8ffb1bcf
GH
642 int pos, len;
643
644 /* find start element */
645 if (path[0] == '/') {
646 bus = main_system_bus;
647 pos = 0;
648 } else {
649 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
fc98eb43
MA
650 assert(!path[0]);
651 elem[0] = len = 0;
8ffb1bcf
GH
652 }
653 bus = qbus_find_recursive(main_system_bus, elem, NULL);
654 if (!bus) {
ac8dae67 655 qerror_report(QERR_BUS_NOT_FOUND, elem);
8ffb1bcf
GH
656 return NULL;
657 }
658 pos = len;
659 }
660
661 for (;;) {
fc98eb43
MA
662 assert(path[pos] == '/' || !path[pos]);
663 while (path[pos] == '/') {
664 pos++;
665 }
8ffb1bcf 666 if (path[pos] == '\0') {
8ffb1bcf
GH
667 return bus;
668 }
669
670 /* find device */
fc98eb43
MA
671 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
672 assert(0);
673 elem[0] = len = 0;
8ffb1bcf
GH
674 }
675 pos += len;
676 dev = qbus_find_dev(bus, elem);
677 if (!dev) {
ac8dae67 678 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
8bc27249
MA
679 if (!monitor_cur_is_qmp()) {
680 qbus_list_dev(bus);
681 }
8ffb1bcf
GH
682 return NULL;
683 }
fc98eb43
MA
684
685 assert(path[pos] == '/' || !path[pos]);
686 while (path[pos] == '/') {
687 pos++;
688 }
8ffb1bcf
GH
689 if (path[pos] == '\0') {
690 /* last specified element is a device. If it has exactly
691 * one child bus accept it nevertheless */
692 switch (dev->num_child_bus) {
693 case 0:
ac8dae67 694 qerror_report(QERR_DEVICE_NO_BUS, elem);
8ffb1bcf
GH
695 return NULL;
696 case 1:
72cf2d4f 697 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf 698 default:
ac8dae67 699 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
8bc27249
MA
700 if (!monitor_cur_is_qmp()) {
701 qbus_list_bus(dev);
702 }
8ffb1bcf
GH
703 return NULL;
704 }
705 }
706
707 /* find bus */
fc98eb43
MA
708 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
709 assert(0);
710 elem[0] = len = 0;
8ffb1bcf
GH
711 }
712 pos += len;
713 bus = qbus_find_bus(dev, elem);
714 if (!bus) {
ac8dae67 715 qerror_report(QERR_BUS_NOT_FOUND, elem);
8bc27249
MA
716 if (!monitor_cur_is_qmp()) {
717 qbus_list_bus(dev);
718 }
8ffb1bcf
GH
719 return NULL;
720 }
721 }
722}
723
cd739fb6
GH
724void qbus_create_inplace(BusState *bus, BusInfo *info,
725 DeviceState *parent, const char *name)
02e2da45 726{
d271de9f
GH
727 char *buf;
728 int i,len;
02e2da45 729
10c4c98a 730 bus->info = info;
02e2da45 731 bus->parent = parent;
d271de9f
GH
732
733 if (name) {
734 /* use supplied name */
735 bus->name = qemu_strdup(name);
736 } else if (parent && parent->id) {
737 /* parent device has id -> use it for bus name */
738 len = strlen(parent->id) + 16;
739 buf = qemu_malloc(len);
740 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
741 bus->name = buf;
742 } else {
743 /* no id -> use lowercase bus type for bus name */
744 len = strlen(info->name) + 16;
745 buf = qemu_malloc(len);
746 len = snprintf(buf, len, "%s.%d", info->name,
747 parent ? parent->num_child_bus : 0);
748 for (i = 0; i < len; i++)
bb87ece5 749 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
750 bus->name = buf;
751 }
752
72cf2d4f 753 QLIST_INIT(&bus->children);
02e2da45 754 if (parent) {
72cf2d4f 755 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 756 parent->num_child_bus++;
02e2da45 757 }
cd739fb6
GH
758
759}
760
761BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
762{
763 BusState *bus;
764
765 bus = qemu_mallocz(info->size);
766 bus->qdev_allocated = 1;
767 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
768 return bus;
769}
cae4956e 770
131ec1bd
GH
771void qbus_free(BusState *bus)
772{
773 DeviceState *dev;
774
775 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
776 qdev_free(dev);
777 }
778 if (bus->parent) {
779 QLIST_REMOVE(bus, sibling);
780 bus->parent->num_child_bus--;
781 }
e163ae7b 782 qemu_free((void*)bus->name);
131ec1bd
GH
783 if (bus->qdev_allocated) {
784 qemu_free(bus);
785 }
786}
787
cae4956e
GH
788#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
789static void qbus_print(Monitor *mon, BusState *bus, int indent);
790
ee6847d1
GH
791static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
792 const char *prefix, int indent)
793{
794 char buf[64];
795
796 if (!props)
797 return;
798 while (props->name) {
036f7166
MA
799 /*
800 * TODO Properties without a print method are just for dirty
801 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
802 * marked for removal. The test props->info->print should be
803 * removed along with it.
804 */
ee6847d1
GH
805 if (props->info->print) {
806 props->info->print(dev, props, buf, sizeof(buf));
807 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
808 }
809 props++;
810 }
811}
812
cae4956e
GH
813static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
814{
cae4956e 815 BusState *child;
ccb63de3
GH
816 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
817 dev->id ? dev->id : "");
cae4956e
GH
818 indent += 2;
819 if (dev->num_gpio_in) {
820 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
821 }
822 if (dev->num_gpio_out) {
823 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
824 }
ee6847d1
GH
825 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
826 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
827 if (dev->parent_bus->info->print_dev)
828 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 829 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
830 qbus_print(mon, child, indent);
831 }
832}
833
834static void qbus_print(Monitor *mon, BusState *bus, int indent)
835{
836 struct DeviceState *dev;
837
838 qdev_printf("bus: %s\n", bus->name);
839 indent += 2;
10c4c98a 840 qdev_printf("type %s\n", bus->info->name);
72cf2d4f 841 QLIST_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
842 qdev_print(mon, dev, indent);
843 }
844}
845#undef qdev_printf
846
847void do_info_qtree(Monitor *mon)
848{
849 if (main_system_bus)
850 qbus_print(mon, main_system_bus, 0);
851}
9316d30f 852
f6c64e0e 853void do_info_qdm(Monitor *mon)
9316d30f
GH
854{
855 DeviceInfo *info;
9316d30f
GH
856
857 for (info = device_info_list; info != NULL; info = info->next) {
8a9662ca 858 qdev_print_devinfo(info);
9316d30f
GH
859 }
860}
3418bd25 861
8bc27249 862int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
863{
864 QemuOpts *opts;
865
3329f07b 866 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
8bc27249
MA
867 if (!opts) {
868 return -1;
869 }
870 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
871 qemu_opts_del(opts);
872 return 0;
0f853a38 873 }
8bc27249
MA
874 if (!qdev_device_add(opts)) {
875 qemu_opts_del(opts);
876 return -1;
877 }
878 return 0;
3418bd25
GH
879}
880
17a38eaa 881int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
882{
883 const char *id = qdict_get_str(qdict, "id");
884 DeviceState *dev;
885
886 dev = qdev_find_recursive(main_system_bus, id);
887 if (NULL == dev) {
17a38eaa
MA
888 qerror_report(QERR_DEVICE_NOT_FOUND, id);
889 return -1;
3418bd25 890 }
17a38eaa 891 return qdev_unplug(dev);
3418bd25 892}
1ca4d09a
GN
893
894static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
895{
896 int l = 0;
897
898 if (dev && dev->parent_bus) {
899 char *d;
900 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
901 if (dev->parent_bus->info->get_fw_dev_path) {
902 d = dev->parent_bus->info->get_fw_dev_path(dev);
903 l += snprintf(p + l, size - l, "%s", d);
904 qemu_free(d);
905 } else {
906 l += snprintf(p + l, size - l, "%s", dev->info->name);
907 }
908 }
909 l += snprintf(p + l , size - l, "/");
910
911 return l;
912}
913
914char* qdev_get_fw_dev_path(DeviceState *dev)
915{
916 char path[128];
917 int l;
918
919 l = qdev_get_fw_dev_path_helper(dev, path, 128);
920
921 path[l-1] = '\0';
922
923 return strdup(path);
924}