]> git.proxmox.com Git - qemu.git/blame - hw/qdev.c
list MST as pci layer maintainer
[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"
3ced9f7a 32#include "qerror.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
aae9460e
PB
81/* Create a new device. This only initializes the device state structure
82 and allows properties to be set. qdev_init should be called to
83 initialize the actual device emulation. */
02e2da45 84DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e 85{
042f84d0 86 DeviceInfo *info;
aae9460e
PB
87 DeviceState *dev;
88
10c4c98a
GH
89 if (!bus) {
90 if (!main_system_bus) {
91 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
aae9460e 92 }
10c4c98a
GH
93 bus = main_system_bus;
94 }
95
81ebb98b 96 info = qdev_find_info(bus->info, name);
042f84d0 97 if (!info) {
10c4c98a 98 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
aae9460e
PB
99 }
100
042f84d0
GH
101 dev = qemu_mallocz(info->size);
102 dev->info = info;
02e2da45 103 dev->parent_bus = bus;
ee6847d1
GH
104 qdev_prop_set_defaults(dev, dev->info->props);
105 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
458fb679 106 qdev_prop_set_globals(dev);
72cf2d4f 107 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
3418bd25
GH
108 if (qdev_hotplug) {
109 assert(bus->allow_hotplug);
110 dev->hotplugged = 1;
111 }
131ec1bd 112 dev->state = DEV_STATE_CREATED;
aae9460e
PB
113 return dev;
114}
115
1b524b04
GH
116static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
117{
118 int pos = 0;
22f2e344
GH
119 int ret;
120
121 ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
122 info->name, info->bus_info->name);
123 pos += MIN(len-pos,ret);
124 if (info->alias) {
125 ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
126 pos += MIN(len-pos,ret);
127 }
128 if (info->desc) {
129 ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
130 pos += MIN(len-pos,ret);
131 }
132 if (info->no_user) {
133 ret = snprintf(dest+pos, len-pos, ", no-user");
134 pos += MIN(len-pos,ret);
135 }
1b524b04
GH
136 return pos;
137}
138
f31d07d1 139static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 140{
f31d07d1
GH
141 DeviceState *dev = opaque;
142
143 if (strcmp(name, "driver") == 0)
144 return 0;
145 if (strcmp(name, "bus") == 0)
146 return 0;
147
3df04ac3 148 if (qdev_prop_parse(dev, name, value) == -1) {
286c2321
GH
149 qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
150 name, value, dev->info->name);
f31d07d1
GH
151 return -1;
152 }
153 return 0;
154}
155
156DeviceState *qdev_device_add(QemuOpts *opts)
157{
158 const char *driver, *path, *id;
8ffb1bcf
GH
159 DeviceInfo *info;
160 DeviceState *qdev;
161 BusState *bus;
8ffb1bcf 162
f31d07d1
GH
163 driver = qemu_opt_get(opts, "driver");
164 if (!driver) {
286c2321 165 qemu_error("-device: no driver specified\n");
8ffb1bcf
GH
166 return NULL;
167 }
168 if (strcmp(driver, "?") == 0) {
1b524b04 169 char msg[256];
8ffb1bcf 170 for (info = device_info_list; info != NULL; info = info->next) {
1b524b04 171 qdev_print_devinfo(info, msg, sizeof(msg));
286c2321 172 qemu_error("%s\n", msg);
8ffb1bcf
GH
173 }
174 return NULL;
175 }
f31d07d1
GH
176
177 /* find driver */
8ffb1bcf
GH
178 info = qdev_find_info(NULL, driver);
179 if (!info) {
3ced9f7a 180 qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);
8ffb1bcf
GH
181 return NULL;
182 }
183 if (info->no_user) {
286c2321
GH
184 qemu_error("device \"%s\" can't be added via command line\n",
185 info->name);
8ffb1bcf
GH
186 return NULL;
187 }
188
f31d07d1
GH
189 /* find bus */
190 path = qemu_opt_get(opts, "bus");
191 if (path != NULL) {
8ffb1bcf 192 bus = qbus_find(path);
8ffb1bcf
GH
193 } else {
194 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
8ffb1bcf 195 }
75570088
GH
196 if (!bus) {
197 qemu_error("Did not find %s bus for %s\n",
198 path ? path : info->bus_info->name, info->name);
f31d07d1 199 return NULL;
75570088 200 }
3418bd25
GH
201 if (qdev_hotplug && !bus->allow_hotplug) {
202 qemu_error("Bus %s does not support hotplugging\n",
203 bus->name);
204 return NULL;
205 }
8ffb1bcf 206
f31d07d1
GH
207 /* create device, set properties */
208 qdev = qdev_create(bus, driver);
209 id = qemu_opts_id(opts);
210 if (id) {
211 qdev->id = id;
212 }
213 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
214 qdev_free(qdev);
215 return NULL;
8ffb1bcf 216 }
5c17ca25 217 if (qdev_init(qdev) < 0) {
c8cd1fcd 218 qemu_error("Error initializing device %s\n", driver);
81a322d4
GH
219 return NULL;
220 }
ef80b466 221 qdev->opts = opts;
8ffb1bcf
GH
222 return qdev;
223}
224
7f23f812
MT
225static void qdev_reset(void *opaque)
226{
227 DeviceState *dev = opaque;
228 if (dev->info->reset)
229 dev->info->reset(dev);
230}
231
aae9460e
PB
232/* Initialize a device. Device properties should be set before calling
233 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
234 calling this function.
235 On failure, destroy the device and return negative value.
236 Return 0 on success. */
81a322d4 237int qdev_init(DeviceState *dev)
aae9460e 238{
959f733a
GH
239 int rc;
240
131ec1bd 241 assert(dev->state == DEV_STATE_CREATED);
959f733a 242 rc = dev->info->init(dev, dev->info);
18cfeb52
MA
243 if (rc < 0) {
244 qdev_free(dev);
959f733a 245 return rc;
18cfeb52 246 }
7f23f812 247 qemu_register_reset(qdev_reset, dev);
391a079e
GH
248 if (dev->info->vmsd)
249 vmstate_register(-1, dev->info->vmsd, dev);
131ec1bd 250 dev->state = DEV_STATE_INITIALIZED;
959f733a 251 return 0;
02e2da45
PB
252}
253
3418bd25
GH
254int qdev_unplug(DeviceState *dev)
255{
256 if (!dev->parent_bus->allow_hotplug) {
257 qemu_error("Bus %s does not support hotplugging\n",
258 dev->parent_bus->name);
259 return -1;
260 }
593831de
AS
261 assert(dev->info->unplug != NULL);
262
3418bd25
GH
263 return dev->info->unplug(dev);
264}
265
266/* can be used as ->unplug() callback for the simple cases */
267int qdev_simple_unplug_cb(DeviceState *dev)
268{
269 /* just zap it */
270 qdev_free(dev);
271 return 0;
272}
273
e23a1b33
MA
274/* Like qdev_init(), but terminate program via hw_error() instead of
275 returning an error value. This is okay during machine creation.
276 Don't use for hotplug, because there callers need to recover from
277 failure. Exception: if you know the device's init() callback can't
278 fail, then qdev_init_nofail() can't fail either, and is therefore
279 usable even then. But relying on the device implementation that
280 way is somewhat unclean, and best avoided. */
281void qdev_init_nofail(DeviceState *dev)
282{
283 DeviceInfo *info = dev->info;
284
285 if (qdev_init(dev) < 0)
286 hw_error("Initialization of device %s failed\n", info->name);
287}
288
02e2da45
PB
289/* Unlink device from bus and free the structure. */
290void qdev_free(DeviceState *dev)
291{
131ec1bd
GH
292 BusState *bus;
293
294 if (dev->state == DEV_STATE_INITIALIZED) {
295 while (dev->num_child_bus) {
296 bus = QLIST_FIRST(&dev->child_bus);
297 qbus_free(bus);
298 }
131ec1bd
GH
299 if (dev->info->vmsd)
300 vmstate_unregister(dev->info->vmsd, dev);
d29275f1
GH
301 if (dev->info->exit)
302 dev->info->exit(dev);
ef80b466
GH
303 if (dev->opts)
304 qemu_opts_del(dev->opts);
131ec1bd 305 }
7f23f812 306 qemu_unregister_reset(qdev_reset, dev);
72cf2d4f 307 QLIST_REMOVE(dev, sibling);
ccb63de3 308 qemu_free(dev);
aae9460e
PB
309}
310
3418bd25
GH
311void qdev_machine_creation_done(void)
312{
313 /*
314 * ok, initial machine setup is done, starting from now we can
315 * only create hotpluggable devices
316 */
317 qdev_hotplug = 1;
318}
319
aae9460e
PB
320/* Get a character (serial) device interface. */
321CharDriverState *qdev_init_chardev(DeviceState *dev)
322{
323 static int next_serial;
324 static int next_virtconsole;
325 /* FIXME: This is a nasty hack that needs to go away. */
042f84d0 326 if (strncmp(dev->info->name, "virtio", 6) == 0) {
aae9460e
PB
327 return virtcon_hds[next_virtconsole++];
328 } else {
329 return serial_hds[next_serial++];
330 }
331}
332
02e2da45 333BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 334{
02e2da45 335 return dev->parent_bus;
aae9460e
PB
336}
337
aae9460e
PB
338void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
339{
340 assert(dev->num_gpio_in == 0);
341 dev->num_gpio_in = n;
342 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
343}
344
345void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
346{
347 assert(dev->num_gpio_out == 0);
348 dev->num_gpio_out = n;
349 dev->gpio_out = pins;
350}
351
352qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
353{
354 assert(n >= 0 && n < dev->num_gpio_in);
355 return dev->gpio_in[n];
356}
357
358void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
359{
360 assert(n >= 0 && n < dev->num_gpio_out);
361 dev->gpio_out[n] = pin;
362}
363
ed16ab5a
GH
364void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
365{
366 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
367 if (nd->vlan)
368 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
369 if (nd->netdev)
370 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
97b15621
GH
371 if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
372 qdev_prop_exists(dev, "vectors")) {
373 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
374 }
ed16ab5a
GH
375}
376
aae9460e
PB
377static int next_block_unit[IF_COUNT];
378
379/* Get a block device. This should only be used for single-drive devices
380 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
381 appropriate bus. */
382BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
383{
384 int unit = next_block_unit[type]++;
751c6a17 385 DriveInfo *dinfo;
aae9460e 386
751c6a17
GH
387 dinfo = drive_get(type, 0, unit);
388 return dinfo ? dinfo->bdrv : NULL;
aae9460e 389}
4d6ae674 390
02e2da45 391BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 392{
02e2da45 393 BusState *bus;
4d6ae674 394
72cf2d4f 395 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 396 if (strcmp(name, bus->name) == 0) {
02e2da45 397 return bus;
4d6ae674
PB
398 }
399 }
400 return NULL;
401}
402
8ffb1bcf
GH
403static BusState *qbus_find_recursive(BusState *bus, const char *name,
404 const BusInfo *info)
405{
406 DeviceState *dev;
407 BusState *child, *ret;
408 int match = 1;
409
410 if (name && (strcmp(bus->name, name) != 0)) {
411 match = 0;
412 }
413 if (info && (bus->info != info)) {
414 match = 0;
415 }
416 if (match) {
417 return bus;
418 }
419
72cf2d4f
BS
420 QLIST_FOREACH(dev, &bus->children, sibling) {
421 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
422 ret = qbus_find_recursive(child, name, info);
423 if (ret) {
424 return ret;
425 }
426 }
427 }
428 return NULL;
429}
430
3418bd25
GH
431static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
432{
433 DeviceState *dev, *ret;
434 BusState *child;
435
436 QLIST_FOREACH(dev, &bus->children, sibling) {
437 if (dev->id && strcmp(dev->id, id) == 0)
438 return dev;
439 QLIST_FOREACH(child, &dev->child_bus, sibling) {
440 ret = qdev_find_recursive(child, id);
441 if (ret) {
442 return ret;
443 }
444 }
445 }
446 return NULL;
447}
448
8ffb1bcf
GH
449static void qbus_list_bus(DeviceState *dev, char *dest, int len)
450{
451 BusState *child;
452 const char *sep = " ";
453 int pos = 0;
454
455 pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
456 dev->id ? dev->id : dev->info->name);
72cf2d4f 457 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
458 pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
459 sep = ", ";
460 }
461}
462
463static void qbus_list_dev(BusState *bus, char *dest, int len)
464{
465 DeviceState *dev;
466 const char *sep = " ";
467 int pos = 0;
468
469 pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
470 bus->name);
72cf2d4f 471 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
472 pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
473 sep, dev->info->name);
474 if (dev->id)
475 pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
476 sep = ", ";
477 }
478}
479
480static BusState *qbus_find_bus(DeviceState *dev, char *elem)
481{
482 BusState *child;
483
72cf2d4f 484 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
485 if (strcmp(child->name, elem) == 0) {
486 return child;
487 }
488 }
489 return NULL;
490}
491
492static DeviceState *qbus_find_dev(BusState *bus, char *elem)
493{
494 DeviceState *dev;
495
496 /*
497 * try to match in order:
498 * (1) instance id, if present
499 * (2) driver name
500 * (3) driver alias, if present
501 */
72cf2d4f 502 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
503 if (dev->id && strcmp(dev->id, elem) == 0) {
504 return dev;
505 }
506 }
72cf2d4f 507 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
508 if (strcmp(dev->info->name, elem) == 0) {
509 return dev;
510 }
511 }
72cf2d4f 512 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
513 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
514 return dev;
515 }
516 }
517 return NULL;
518}
519
520static BusState *qbus_find(const char *path)
521{
522 DeviceState *dev;
523 BusState *bus;
524 char elem[128], msg[256];
525 int pos, len;
526
527 /* find start element */
528 if (path[0] == '/') {
529 bus = main_system_bus;
530 pos = 0;
531 } else {
532 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
286c2321 533 qemu_error("path parse error (\"%s\")\n", path);
8ffb1bcf
GH
534 return NULL;
535 }
536 bus = qbus_find_recursive(main_system_bus, elem, NULL);
537 if (!bus) {
286c2321 538 qemu_error("bus \"%s\" not found\n", elem);
8ffb1bcf
GH
539 return NULL;
540 }
541 pos = len;
542 }
543
544 for (;;) {
545 if (path[pos] == '\0') {
546 /* we are done */
547 return bus;
548 }
549
550 /* find device */
551 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
286c2321 552 qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
8ffb1bcf
GH
553 return NULL;
554 }
555 pos += len;
556 dev = qbus_find_dev(bus, elem);
557 if (!dev) {
558 qbus_list_dev(bus, msg, sizeof(msg));
286c2321 559 qemu_error("device \"%s\" not found\n%s\n", elem, msg);
8ffb1bcf
GH
560 return NULL;
561 }
562 if (path[pos] == '\0') {
563 /* last specified element is a device. If it has exactly
564 * one child bus accept it nevertheless */
565 switch (dev->num_child_bus) {
566 case 0:
286c2321 567 qemu_error("device has no child bus (%s)\n", path);
8ffb1bcf
GH
568 return NULL;
569 case 1:
72cf2d4f 570 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf
GH
571 default:
572 qbus_list_bus(dev, msg, sizeof(msg));
286c2321
GH
573 qemu_error("device has multiple child busses (%s)\n%s\n",
574 path, msg);
8ffb1bcf
GH
575 return NULL;
576 }
577 }
578
579 /* find bus */
580 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
286c2321 581 qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
8ffb1bcf
GH
582 return NULL;
583 }
584 pos += len;
585 bus = qbus_find_bus(dev, elem);
586 if (!bus) {
587 qbus_list_bus(dev, msg, sizeof(msg));
286c2321 588 qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
8ffb1bcf
GH
589 return NULL;
590 }
591 }
592}
593
cd739fb6
GH
594void qbus_create_inplace(BusState *bus, BusInfo *info,
595 DeviceState *parent, const char *name)
02e2da45 596{
d271de9f
GH
597 char *buf;
598 int i,len;
02e2da45 599
10c4c98a 600 bus->info = info;
02e2da45 601 bus->parent = parent;
d271de9f
GH
602
603 if (name) {
604 /* use supplied name */
605 bus->name = qemu_strdup(name);
606 } else if (parent && parent->id) {
607 /* parent device has id -> use it for bus name */
608 len = strlen(parent->id) + 16;
609 buf = qemu_malloc(len);
610 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
611 bus->name = buf;
612 } else {
613 /* no id -> use lowercase bus type for bus name */
614 len = strlen(info->name) + 16;
615 buf = qemu_malloc(len);
616 len = snprintf(buf, len, "%s.%d", info->name,
617 parent ? parent->num_child_bus : 0);
618 for (i = 0; i < len; i++)
bb87ece5 619 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
620 bus->name = buf;
621 }
622
72cf2d4f 623 QLIST_INIT(&bus->children);
02e2da45 624 if (parent) {
72cf2d4f 625 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 626 parent->num_child_bus++;
02e2da45 627 }
cd739fb6
GH
628
629}
630
631BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
632{
633 BusState *bus;
634
635 bus = qemu_mallocz(info->size);
636 bus->qdev_allocated = 1;
637 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
638 return bus;
639}
cae4956e 640
131ec1bd
GH
641void qbus_free(BusState *bus)
642{
643 DeviceState *dev;
644
645 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
646 qdev_free(dev);
647 }
648 if (bus->parent) {
649 QLIST_REMOVE(bus, sibling);
650 bus->parent->num_child_bus--;
651 }
652 if (bus->qdev_allocated) {
653 qemu_free(bus);
654 }
655}
656
cae4956e
GH
657#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
658static void qbus_print(Monitor *mon, BusState *bus, int indent);
659
ee6847d1
GH
660static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
661 const char *prefix, int indent)
662{
663 char buf[64];
664
665 if (!props)
666 return;
667 while (props->name) {
668 if (props->info->print) {
669 props->info->print(dev, props, buf, sizeof(buf));
670 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
671 }
672 props++;
673 }
674}
675
cae4956e
GH
676static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
677{
cae4956e 678 BusState *child;
ccb63de3
GH
679 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
680 dev->id ? dev->id : "");
cae4956e
GH
681 indent += 2;
682 if (dev->num_gpio_in) {
683 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
684 }
685 if (dev->num_gpio_out) {
686 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
687 }
ee6847d1
GH
688 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
689 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
690 if (dev->parent_bus->info->print_dev)
691 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 692 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
693 qbus_print(mon, child, indent);
694 }
695}
696
697static void qbus_print(Monitor *mon, BusState *bus, int indent)
698{
699 struct DeviceState *dev;
700
701 qdev_printf("bus: %s\n", bus->name);
702 indent += 2;
10c4c98a 703 qdev_printf("type %s\n", bus->info->name);
72cf2d4f 704 QLIST_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
705 qdev_print(mon, dev, indent);
706 }
707}
708#undef qdev_printf
709
710void do_info_qtree(Monitor *mon)
711{
712 if (main_system_bus)
713 qbus_print(mon, main_system_bus, 0);
714}
9316d30f 715
f6c64e0e 716void do_info_qdm(Monitor *mon)
9316d30f
GH
717{
718 DeviceInfo *info;
719 char msg[256];
720
721 for (info = device_info_list; info != NULL; info = info->next) {
722 qdev_print_devinfo(info, msg, sizeof(msg));
723 monitor_printf(mon, "%s\n", msg);
724 }
725}
3418bd25
GH
726
727void do_device_add(Monitor *mon, const QDict *qdict)
728{
729 QemuOpts *opts;
730
731 opts = qemu_opts_parse(&qemu_device_opts,
732 qdict_get_str(qdict, "config"), "driver");
733 if (opts)
734 qdev_device_add(opts);
735}
736
737void do_device_del(Monitor *mon, const QDict *qdict)
738{
739 const char *id = qdict_get_str(qdict, "id");
740 DeviceState *dev;
741
742 dev = qdev_find_recursive(main_system_bus, id);
743 if (NULL == dev) {
744 qemu_error("Device '%s' not found\n", id);
745 return;
746 }
747 qdev_unplug(dev);
748}