eepro100: convert to memory API
[qemu/mdroth.git] / hw / qdev.c
blob6819537648f22694a9d14e1379b309706c0dd546
1 /*
2 * Dynamic device configuration and creation.
4 * Copyright (c) 2009 CodeSourcery
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.
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.
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/>.
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. */
28 #include "net.h"
29 #include "qdev.h"
30 #include "sysemu.h"
31 #include "monitor.h"
33 static int qdev_hotplug = 0;
34 static bool qdev_hot_added = false;
35 static bool qdev_hot_removed = false;
37 /* This is a nasty hack to allow passing a NULL bus to qdev_create. */
38 static BusState *main_system_bus;
39 static void main_system_bus_create(void);
41 DeviceInfo *device_info_list;
43 static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 const BusInfo *info);
45 static BusState *qbus_find(const char *path);
47 /* Register a new device type. */
48 void qdev_register(DeviceInfo *info)
50 assert(info->size >= sizeof(DeviceState));
51 assert(!info->next);
53 info->next = device_info_list;
54 device_info_list = info;
57 static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
59 DeviceInfo *info;
61 /* first check device names */
62 for (info = device_info_list; info != NULL; info = info->next) {
63 if (bus_info && info->bus_info != bus_info)
64 continue;
65 if (strcmp(info->name, name) != 0)
66 continue;
67 return info;
70 /* failing that check the aliases */
71 for (info = device_info_list; info != NULL; info = info->next) {
72 if (bus_info && info->bus_info != bus_info)
73 continue;
74 if (!info->alias)
75 continue;
76 if (strcmp(info->alias, name) != 0)
77 continue;
78 return info;
80 return NULL;
83 static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
85 DeviceState *dev;
87 assert(bus->info == info->bus_info);
88 dev = qemu_mallocz(info->size);
89 dev->info = info;
90 dev->parent_bus = bus;
91 qdev_prop_set_defaults(dev, dev->info->props);
92 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
93 qdev_prop_set_globals(dev);
94 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
95 if (qdev_hotplug) {
96 assert(bus->allow_hotplug);
97 dev->hotplugged = 1;
98 qdev_hot_added = true;
100 dev->instance_id_alias = -1;
101 dev->state = DEV_STATE_CREATED;
102 return dev;
105 /* Create a new device. This only initializes the device state structure
106 and allows properties to be set. qdev_init should be called to
107 initialize the actual device emulation. */
108 DeviceState *qdev_create(BusState *bus, const char *name)
110 DeviceState *dev;
112 dev = qdev_try_create(bus, name);
113 if (!dev) {
114 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
117 return dev;
120 DeviceState *qdev_try_create(BusState *bus, const char *name)
122 DeviceInfo *info;
124 if (!bus) {
125 bus = sysbus_get_default();
128 info = qdev_find_info(bus->info, name);
129 if (!info) {
130 return NULL;
133 return qdev_create_from_info(bus, info);
136 static void qdev_print_devinfo(DeviceInfo *info)
138 error_printf("name \"%s\", bus %s",
139 info->name, info->bus_info->name);
140 if (info->alias) {
141 error_printf(", alias \"%s\"", info->alias);
143 if (info->desc) {
144 error_printf(", desc \"%s\"", info->desc);
146 if (info->no_user) {
147 error_printf(", no-user");
149 error_printf("\n");
152 static int set_property(const char *name, const char *value, void *opaque)
154 DeviceState *dev = opaque;
156 if (strcmp(name, "driver") == 0)
157 return 0;
158 if (strcmp(name, "bus") == 0)
159 return 0;
161 if (qdev_prop_parse(dev, name, value) == -1) {
162 return -1;
164 return 0;
167 int qdev_device_help(QemuOpts *opts)
169 const char *driver;
170 DeviceInfo *info;
171 Property *prop;
173 driver = qemu_opt_get(opts, "driver");
174 if (driver && !strcmp(driver, "?")) {
175 for (info = device_info_list; info != NULL; info = info->next) {
176 if (info->no_user) {
177 continue; /* not available, don't show */
179 qdev_print_devinfo(info);
181 return 1;
184 if (!qemu_opt_get(opts, "?")) {
185 return 0;
188 info = qdev_find_info(NULL, driver);
189 if (!info) {
190 return 0;
193 for (prop = info->props; prop && prop->name; prop++) {
195 * TODO Properties without a parser are just for dirty hacks.
196 * qdev_prop_ptr is the only such PropertyInfo. It's marked
197 * for removal. This conditional should be removed along with
198 * it.
200 if (!prop->info->parse) {
201 continue; /* no way to set it, don't show */
203 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
205 return 1;
208 DeviceState *qdev_device_add(QemuOpts *opts)
210 const char *driver, *path, *id;
211 DeviceInfo *info;
212 DeviceState *qdev;
213 BusState *bus;
215 driver = qemu_opt_get(opts, "driver");
216 if (!driver) {
217 qerror_report(QERR_MISSING_PARAMETER, "driver");
218 return NULL;
221 /* find driver */
222 info = qdev_find_info(NULL, driver);
223 if (!info || info->no_user) {
224 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
225 error_printf_unless_qmp("Try with argument '?' for a list.\n");
226 return NULL;
229 /* find bus */
230 path = qemu_opt_get(opts, "bus");
231 if (path != NULL) {
232 bus = qbus_find(path);
233 if (!bus) {
234 return NULL;
236 if (bus->info != info->bus_info) {
237 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
238 driver, bus->info->name);
239 return NULL;
241 } else {
242 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
243 if (!bus) {
244 qerror_report(QERR_NO_BUS_FOR_DEVICE,
245 info->name, info->bus_info->name);
246 return NULL;
249 if (qdev_hotplug && !bus->allow_hotplug) {
250 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
251 return NULL;
254 /* create device, set properties */
255 qdev = qdev_create_from_info(bus, info);
256 id = qemu_opts_id(opts);
257 if (id) {
258 qdev->id = id;
260 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
261 qdev_free(qdev);
262 return NULL;
264 if (qdev_init(qdev) < 0) {
265 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
266 return NULL;
268 qdev->opts = opts;
269 return qdev;
272 /* Initialize a device. Device properties should be set before calling
273 this function. IRQs and MMIO regions should be connected/mapped after
274 calling this function.
275 On failure, destroy the device and return negative value.
276 Return 0 on success. */
277 int qdev_init(DeviceState *dev)
279 int rc;
281 assert(dev->state == DEV_STATE_CREATED);
282 rc = dev->info->init(dev, dev->info);
283 if (rc < 0) {
284 qdev_free(dev);
285 return rc;
287 if (dev->info->vmsd) {
288 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
289 dev->instance_id_alias,
290 dev->alias_required_for_version);
292 dev->state = DEV_STATE_INITIALIZED;
293 if (dev->hotplugged && dev->info->reset) {
294 dev->info->reset(dev);
296 return 0;
299 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
300 int required_for_version)
302 assert(dev->state == DEV_STATE_CREATED);
303 dev->instance_id_alias = alias_id;
304 dev->alias_required_for_version = required_for_version;
307 int qdev_unplug(DeviceState *dev)
309 if (!dev->parent_bus->allow_hotplug) {
310 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
311 return -1;
313 assert(dev->info->unplug != NULL);
315 qdev_hot_removed = true;
317 return dev->info->unplug(dev);
320 static int qdev_reset_one(DeviceState *dev, void *opaque)
322 if (dev->info->reset) {
323 dev->info->reset(dev);
326 return 0;
329 BusState *sysbus_get_default(void)
331 if (!main_system_bus) {
332 main_system_bus_create();
334 return main_system_bus;
337 static int qbus_reset_one(BusState *bus, void *opaque)
339 if (bus->info->reset) {
340 return bus->info->reset(bus);
342 return 0;
345 void qdev_reset_all(DeviceState *dev)
347 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
350 void qbus_reset_all_fn(void *opaque)
352 BusState *bus = opaque;
353 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
356 /* can be used as ->unplug() callback for the simple cases */
357 int qdev_simple_unplug_cb(DeviceState *dev)
359 /* just zap it */
360 qdev_free(dev);
361 return 0;
365 /* Like qdev_init(), but terminate program via error_report() instead of
366 returning an error value. This is okay during machine creation.
367 Don't use for hotplug, because there callers need to recover from
368 failure. Exception: if you know the device's init() callback can't
369 fail, then qdev_init_nofail() can't fail either, and is therefore
370 usable even then. But relying on the device implementation that
371 way is somewhat unclean, and best avoided. */
372 void qdev_init_nofail(DeviceState *dev)
374 DeviceInfo *info = dev->info;
376 if (qdev_init(dev) < 0) {
377 error_report("Initialization of device %s failed", info->name);
378 exit(1);
382 /* Unlink device from bus and free the structure. */
383 void qdev_free(DeviceState *dev)
385 BusState *bus;
386 Property *prop;
388 if (dev->state == DEV_STATE_INITIALIZED) {
389 while (dev->num_child_bus) {
390 bus = QLIST_FIRST(&dev->child_bus);
391 qbus_free(bus);
393 if (dev->info->vmsd)
394 vmstate_unregister(dev, dev->info->vmsd, dev);
395 if (dev->info->exit)
396 dev->info->exit(dev);
397 if (dev->opts)
398 qemu_opts_del(dev->opts);
400 QLIST_REMOVE(dev, sibling);
401 for (prop = dev->info->props; prop && prop->name; prop++) {
402 if (prop->info->free) {
403 prop->info->free(dev, prop);
406 qemu_free(dev);
409 void qdev_machine_creation_done(void)
412 * ok, initial machine setup is done, starting from now we can
413 * only create hotpluggable devices
415 qdev_hotplug = 1;
418 bool qdev_machine_modified(void)
420 return qdev_hot_added || qdev_hot_removed;
423 /* Get a character (serial) device interface. */
424 CharDriverState *qdev_init_chardev(DeviceState *dev)
426 static int next_serial;
428 /* FIXME: This function needs to go away: use chardev properties! */
429 return serial_hds[next_serial++];
432 BusState *qdev_get_parent_bus(DeviceState *dev)
434 return dev->parent_bus;
437 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
439 assert(dev->num_gpio_in == 0);
440 dev->num_gpio_in = n;
441 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
444 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
446 assert(dev->num_gpio_out == 0);
447 dev->num_gpio_out = n;
448 dev->gpio_out = pins;
451 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
453 assert(n >= 0 && n < dev->num_gpio_in);
454 return dev->gpio_in[n];
457 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
459 assert(n >= 0 && n < dev->num_gpio_out);
460 dev->gpio_out[n] = pin;
463 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
465 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
466 if (nd->vlan)
467 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
468 if (nd->netdev)
469 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
470 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
471 qdev_prop_exists(dev, "vectors")) {
472 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
474 nd->instantiated = 1;
477 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
479 BusState *bus;
481 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
482 if (strcmp(name, bus->name) == 0) {
483 return bus;
486 return NULL;
489 int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
490 qbus_walkerfn *busfn, void *opaque)
492 DeviceState *dev;
493 int err;
495 if (busfn) {
496 err = busfn(bus, opaque);
497 if (err) {
498 return err;
502 QLIST_FOREACH(dev, &bus->children, sibling) {
503 err = qdev_walk_children(dev, devfn, busfn, opaque);
504 if (err < 0) {
505 return err;
509 return 0;
512 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
513 qbus_walkerfn *busfn, void *opaque)
515 BusState *bus;
516 int err;
518 if (devfn) {
519 err = devfn(dev, opaque);
520 if (err) {
521 return err;
525 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
526 err = qbus_walk_children(bus, devfn, busfn, opaque);
527 if (err < 0) {
528 return err;
532 return 0;
535 static BusState *qbus_find_recursive(BusState *bus, const char *name,
536 const BusInfo *info)
538 DeviceState *dev;
539 BusState *child, *ret;
540 int match = 1;
542 if (name && (strcmp(bus->name, name) != 0)) {
543 match = 0;
545 if (info && (bus->info != info)) {
546 match = 0;
548 if (match) {
549 return bus;
552 QLIST_FOREACH(dev, &bus->children, sibling) {
553 QLIST_FOREACH(child, &dev->child_bus, sibling) {
554 ret = qbus_find_recursive(child, name, info);
555 if (ret) {
556 return ret;
560 return NULL;
563 DeviceState *qdev_find_recursive(BusState *bus, const char *id)
565 DeviceState *dev, *ret;
566 BusState *child;
568 QLIST_FOREACH(dev, &bus->children, sibling) {
569 if (dev->id && strcmp(dev->id, id) == 0)
570 return dev;
571 QLIST_FOREACH(child, &dev->child_bus, sibling) {
572 ret = qdev_find_recursive(child, id);
573 if (ret) {
574 return ret;
578 return NULL;
581 static void qbus_list_bus(DeviceState *dev)
583 BusState *child;
584 const char *sep = " ";
586 error_printf("child busses at \"%s\":",
587 dev->id ? dev->id : dev->info->name);
588 QLIST_FOREACH(child, &dev->child_bus, sibling) {
589 error_printf("%s\"%s\"", sep, child->name);
590 sep = ", ";
592 error_printf("\n");
595 static void qbus_list_dev(BusState *bus)
597 DeviceState *dev;
598 const char *sep = " ";
600 error_printf("devices at \"%s\":", bus->name);
601 QLIST_FOREACH(dev, &bus->children, sibling) {
602 error_printf("%s\"%s\"", sep, dev->info->name);
603 if (dev->id)
604 error_printf("/\"%s\"", dev->id);
605 sep = ", ";
607 error_printf("\n");
610 static BusState *qbus_find_bus(DeviceState *dev, char *elem)
612 BusState *child;
614 QLIST_FOREACH(child, &dev->child_bus, sibling) {
615 if (strcmp(child->name, elem) == 0) {
616 return child;
619 return NULL;
622 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
624 DeviceState *dev;
627 * try to match in order:
628 * (1) instance id, if present
629 * (2) driver name
630 * (3) driver alias, if present
632 QLIST_FOREACH(dev, &bus->children, sibling) {
633 if (dev->id && strcmp(dev->id, elem) == 0) {
634 return dev;
637 QLIST_FOREACH(dev, &bus->children, sibling) {
638 if (strcmp(dev->info->name, elem) == 0) {
639 return dev;
642 QLIST_FOREACH(dev, &bus->children, sibling) {
643 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
644 return dev;
647 return NULL;
650 static BusState *qbus_find(const char *path)
652 DeviceState *dev;
653 BusState *bus;
654 char elem[128];
655 int pos, len;
657 /* find start element */
658 if (path[0] == '/') {
659 bus = main_system_bus;
660 pos = 0;
661 } else {
662 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
663 assert(!path[0]);
664 elem[0] = len = 0;
666 bus = qbus_find_recursive(main_system_bus, elem, NULL);
667 if (!bus) {
668 qerror_report(QERR_BUS_NOT_FOUND, elem);
669 return NULL;
671 pos = len;
674 for (;;) {
675 assert(path[pos] == '/' || !path[pos]);
676 while (path[pos] == '/') {
677 pos++;
679 if (path[pos] == '\0') {
680 return bus;
683 /* find device */
684 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
685 assert(0);
686 elem[0] = len = 0;
688 pos += len;
689 dev = qbus_find_dev(bus, elem);
690 if (!dev) {
691 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
692 if (!monitor_cur_is_qmp()) {
693 qbus_list_dev(bus);
695 return NULL;
698 assert(path[pos] == '/' || !path[pos]);
699 while (path[pos] == '/') {
700 pos++;
702 if (path[pos] == '\0') {
703 /* last specified element is a device. If it has exactly
704 * one child bus accept it nevertheless */
705 switch (dev->num_child_bus) {
706 case 0:
707 qerror_report(QERR_DEVICE_NO_BUS, elem);
708 return NULL;
709 case 1:
710 return QLIST_FIRST(&dev->child_bus);
711 default:
712 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
713 if (!monitor_cur_is_qmp()) {
714 qbus_list_bus(dev);
716 return NULL;
720 /* find bus */
721 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
722 assert(0);
723 elem[0] = len = 0;
725 pos += len;
726 bus = qbus_find_bus(dev, elem);
727 if (!bus) {
728 qerror_report(QERR_BUS_NOT_FOUND, elem);
729 if (!monitor_cur_is_qmp()) {
730 qbus_list_bus(dev);
732 return NULL;
737 void qbus_create_inplace(BusState *bus, BusInfo *info,
738 DeviceState *parent, const char *name)
740 char *buf;
741 int i,len;
743 bus->info = info;
744 bus->parent = parent;
746 if (name) {
747 /* use supplied name */
748 bus->name = qemu_strdup(name);
749 } else if (parent && parent->id) {
750 /* parent device has id -> use it for bus name */
751 len = strlen(parent->id) + 16;
752 buf = qemu_malloc(len);
753 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
754 bus->name = buf;
755 } else {
756 /* no id -> use lowercase bus type for bus name */
757 len = strlen(info->name) + 16;
758 buf = qemu_malloc(len);
759 len = snprintf(buf, len, "%s.%d", info->name,
760 parent ? parent->num_child_bus : 0);
761 for (i = 0; i < len; i++)
762 buf[i] = qemu_tolower(buf[i]);
763 bus->name = buf;
766 QLIST_INIT(&bus->children);
767 if (parent) {
768 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
769 parent->num_child_bus++;
770 } else if (bus != main_system_bus) {
771 /* TODO: once all bus devices are qdevified,
772 only reset handler for main_system_bus should be registered here. */
773 qemu_register_reset(qbus_reset_all_fn, bus);
777 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
779 BusState *bus;
781 bus = qemu_mallocz(info->size);
782 bus->qdev_allocated = 1;
783 qbus_create_inplace(bus, info, parent, name);
784 return bus;
787 static void main_system_bus_create(void)
789 /* assign main_system_bus before qbus_create_inplace()
790 * in order to make "if (bus != main_system_bus)" work */
791 main_system_bus = qemu_mallocz(system_bus_info.size);
792 main_system_bus->qdev_allocated = 1;
793 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
794 "main-system-bus");
797 void qbus_free(BusState *bus)
799 DeviceState *dev;
801 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
802 qdev_free(dev);
804 if (bus->parent) {
805 QLIST_REMOVE(bus, sibling);
806 bus->parent->num_child_bus--;
807 } else {
808 assert(bus != main_system_bus); /* main_system_bus is never freed */
809 qemu_unregister_reset(qbus_reset_all_fn, bus);
811 qemu_free((void*)bus->name);
812 if (bus->qdev_allocated) {
813 qemu_free(bus);
817 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
818 static void qbus_print(Monitor *mon, BusState *bus, int indent);
820 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
821 const char *prefix, int indent)
823 char buf[64];
825 if (!props)
826 return;
827 while (props->name) {
829 * TODO Properties without a print method are just for dirty
830 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
831 * marked for removal. The test props->info->print should be
832 * removed along with it.
834 if (props->info->print) {
835 props->info->print(dev, props, buf, sizeof(buf));
836 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
838 props++;
842 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
844 BusState *child;
845 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
846 dev->id ? dev->id : "");
847 indent += 2;
848 if (dev->num_gpio_in) {
849 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
851 if (dev->num_gpio_out) {
852 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
854 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
855 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
856 if (dev->parent_bus->info->print_dev)
857 dev->parent_bus->info->print_dev(mon, dev, indent);
858 QLIST_FOREACH(child, &dev->child_bus, sibling) {
859 qbus_print(mon, child, indent);
863 static void qbus_print(Monitor *mon, BusState *bus, int indent)
865 struct DeviceState *dev;
867 qdev_printf("bus: %s\n", bus->name);
868 indent += 2;
869 qdev_printf("type %s\n", bus->info->name);
870 QLIST_FOREACH(dev, &bus->children, sibling) {
871 qdev_print(mon, dev, indent);
874 #undef qdev_printf
876 void do_info_qtree(Monitor *mon)
878 if (main_system_bus)
879 qbus_print(mon, main_system_bus, 0);
882 void do_info_qdm(Monitor *mon)
884 DeviceInfo *info;
886 for (info = device_info_list; info != NULL; info = info->next) {
887 qdev_print_devinfo(info);
891 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
893 QemuOpts *opts;
895 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
896 if (!opts) {
897 return -1;
899 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
900 qemu_opts_del(opts);
901 return 0;
903 if (!qdev_device_add(opts)) {
904 qemu_opts_del(opts);
905 return -1;
907 return 0;
910 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
912 const char *id = qdict_get_str(qdict, "id");
913 DeviceState *dev;
915 dev = qdev_find_recursive(main_system_bus, id);
916 if (NULL == dev) {
917 qerror_report(QERR_DEVICE_NOT_FOUND, id);
918 return -1;
920 return qdev_unplug(dev);
923 static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
925 int l = 0;
927 if (dev && dev->parent_bus) {
928 char *d;
929 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
930 if (dev->parent_bus->info->get_fw_dev_path) {
931 d = dev->parent_bus->info->get_fw_dev_path(dev);
932 l += snprintf(p + l, size - l, "%s", d);
933 qemu_free(d);
934 } else {
935 l += snprintf(p + l, size - l, "%s", dev->info->name);
938 l += snprintf(p + l , size - l, "/");
940 return l;
943 char* qdev_get_fw_dev_path(DeviceState *dev)
945 char path[128];
946 int l;
948 l = qdev_get_fw_dev_path_helper(dev, path, 128);
950 path[l-1] = '\0';
952 return strdup(path);