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