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