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