]> Git Repo - qemu.git/blob - hw/qdev.c
qbus: fix memory leak in qbus_free()
[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         hw_error("Initialization of device %s failed\n", info->name);
331 }
332
333 /* Unlink device from bus and free the structure.  */
334 void qdev_free(DeviceState *dev)
335 {
336     BusState *bus;
337
338     if (dev->state == DEV_STATE_INITIALIZED) {
339         while (dev->num_child_bus) {
340             bus = QLIST_FIRST(&dev->child_bus);
341             qbus_free(bus);
342         }
343         if (dev->info->vmsd)
344             vmstate_unregister(dev->info->vmsd, dev);
345         if (dev->info->exit)
346             dev->info->exit(dev);
347         if (dev->opts)
348             qemu_opts_del(dev->opts);
349     }
350     qemu_unregister_reset(qdev_reset, dev);
351     QLIST_REMOVE(dev, sibling);
352     qemu_free(dev);
353 }
354
355 void qdev_machine_creation_done(void)
356 {
357     /*
358      * ok, initial machine setup is done, starting from now we can
359      * only create hotpluggable devices
360      */
361     qdev_hotplug = 1;
362 }
363
364 /* Get a character (serial) device interface.  */
365 CharDriverState *qdev_init_chardev(DeviceState *dev)
366 {
367     static int next_serial;
368
369     /* FIXME: This function needs to go away: use chardev properties!  */
370     return serial_hds[next_serial++];
371 }
372
373 BusState *qdev_get_parent_bus(DeviceState *dev)
374 {
375     return dev->parent_bus;
376 }
377
378 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
379 {
380     assert(dev->num_gpio_in == 0);
381     dev->num_gpio_in = n;
382     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
383 }
384
385 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
386 {
387     assert(dev->num_gpio_out == 0);
388     dev->num_gpio_out = n;
389     dev->gpio_out = pins;
390 }
391
392 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
393 {
394     assert(n >= 0 && n < dev->num_gpio_in);
395     return dev->gpio_in[n];
396 }
397
398 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
399 {
400     assert(n >= 0 && n < dev->num_gpio_out);
401     dev->gpio_out[n] = pin;
402 }
403
404 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
405 {
406     qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
407     if (nd->vlan)
408         qdev_prop_set_vlan(dev, "vlan", nd->vlan);
409     if (nd->netdev)
410         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
411     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
412         qdev_prop_exists(dev, "vectors")) {
413         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
414     }
415 }
416
417 static int next_block_unit[IF_COUNT];
418
419 /* Get a block device.  This should only be used for single-drive devices
420    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
421    appropriate bus.  */
422 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
423 {
424     int unit = next_block_unit[type]++;
425     DriveInfo *dinfo;
426
427     dinfo = drive_get(type, 0, unit);
428     return dinfo ? dinfo->bdrv : NULL;
429 }
430
431 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
432 {
433     BusState *bus;
434
435     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
436         if (strcmp(name, bus->name) == 0) {
437             return bus;
438         }
439     }
440     return NULL;
441 }
442
443 static BusState *qbus_find_recursive(BusState *bus, const char *name,
444                                      const BusInfo *info)
445 {
446     DeviceState *dev;
447     BusState *child, *ret;
448     int match = 1;
449
450     if (name && (strcmp(bus->name, name) != 0)) {
451         match = 0;
452     }
453     if (info && (bus->info != info)) {
454         match = 0;
455     }
456     if (match) {
457         return bus;
458     }
459
460     QLIST_FOREACH(dev, &bus->children, sibling) {
461         QLIST_FOREACH(child, &dev->child_bus, sibling) {
462             ret = qbus_find_recursive(child, name, info);
463             if (ret) {
464                 return ret;
465             }
466         }
467     }
468     return NULL;
469 }
470
471 static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
472 {
473     DeviceState *dev, *ret;
474     BusState *child;
475
476     QLIST_FOREACH(dev, &bus->children, sibling) {
477         if (dev->id && strcmp(dev->id, id) == 0)
478             return dev;
479         QLIST_FOREACH(child, &dev->child_bus, sibling) {
480             ret = qdev_find_recursive(child, id);
481             if (ret) {
482                 return ret;
483             }
484         }
485     }
486     return NULL;
487 }
488
489 static void qbus_list_bus(DeviceState *dev)
490 {
491     BusState *child;
492     const char *sep = " ";
493
494     error_printf("child busses at \"%s\":",
495                  dev->id ? dev->id : dev->info->name);
496     QLIST_FOREACH(child, &dev->child_bus, sibling) {
497         error_printf("%s\"%s\"", sep, child->name);
498         sep = ", ";
499     }
500     error_printf("\n");
501 }
502
503 static void qbus_list_dev(BusState *bus)
504 {
505     DeviceState *dev;
506     const char *sep = " ";
507
508     error_printf("devices at \"%s\":", bus->name);
509     QLIST_FOREACH(dev, &bus->children, sibling) {
510         error_printf("%s\"%s\"", sep, dev->info->name);
511         if (dev->id)
512             error_printf("/\"%s\"", dev->id);
513         sep = ", ";
514     }
515     error_printf("\n");
516 }
517
518 static BusState *qbus_find_bus(DeviceState *dev, char *elem)
519 {
520     BusState *child;
521
522     QLIST_FOREACH(child, &dev->child_bus, sibling) {
523         if (strcmp(child->name, elem) == 0) {
524             return child;
525         }
526     }
527     return NULL;
528 }
529
530 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
531 {
532     DeviceState *dev;
533
534     /*
535      * try to match in order:
536      *   (1) instance id, if present
537      *   (2) driver name
538      *   (3) driver alias, if present
539      */
540     QLIST_FOREACH(dev, &bus->children, sibling) {
541         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
542             return dev;
543         }
544     }
545     QLIST_FOREACH(dev, &bus->children, sibling) {
546         if (strcmp(dev->info->name, elem) == 0) {
547             return dev;
548         }
549     }
550     QLIST_FOREACH(dev, &bus->children, sibling) {
551         if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
552             return dev;
553         }
554     }
555     return NULL;
556 }
557
558 static BusState *qbus_find(const char *path)
559 {
560     DeviceState *dev;
561     BusState *bus;
562     char elem[128];
563     int pos, len;
564
565     /* find start element */
566     if (path[0] == '/') {
567         bus = main_system_bus;
568         pos = 0;
569     } else {
570         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
571             assert(!path[0]);
572             elem[0] = len = 0;
573         }
574         bus = qbus_find_recursive(main_system_bus, elem, NULL);
575         if (!bus) {
576             qerror_report(QERR_BUS_NOT_FOUND, elem);
577             return NULL;
578         }
579         pos = len;
580     }
581
582     for (;;) {
583         assert(path[pos] == '/' || !path[pos]);
584         while (path[pos] == '/') {
585             pos++;
586         }
587         if (path[pos] == '\0') {
588             return bus;
589         }
590
591         /* find device */
592         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
593             assert(0);
594             elem[0] = len = 0;
595         }
596         pos += len;
597         dev = qbus_find_dev(bus, elem);
598         if (!dev) {
599             qerror_report(QERR_DEVICE_NOT_FOUND, elem);
600             if (!monitor_cur_is_qmp()) {
601                 qbus_list_dev(bus);
602             }
603             return NULL;
604         }
605
606         assert(path[pos] == '/' || !path[pos]);
607         while (path[pos] == '/') {
608             pos++;
609         }
610         if (path[pos] == '\0') {
611             /* last specified element is a device.  If it has exactly
612              * one child bus accept it nevertheless */
613             switch (dev->num_child_bus) {
614             case 0:
615                 qerror_report(QERR_DEVICE_NO_BUS, elem);
616                 return NULL;
617             case 1:
618                 return QLIST_FIRST(&dev->child_bus);
619             default:
620                 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
621                 if (!monitor_cur_is_qmp()) {
622                     qbus_list_bus(dev);
623                 }
624                 return NULL;
625             }
626         }
627
628         /* find bus */
629         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
630             assert(0);
631             elem[0] = len = 0;
632         }
633         pos += len;
634         bus = qbus_find_bus(dev, elem);
635         if (!bus) {
636             qerror_report(QERR_BUS_NOT_FOUND, elem);
637             if (!monitor_cur_is_qmp()) {
638                 qbus_list_bus(dev);
639             }
640             return NULL;
641         }
642     }
643 }
644
645 void qbus_create_inplace(BusState *bus, BusInfo *info,
646                          DeviceState *parent, const char *name)
647 {
648     char *buf;
649     int i,len;
650
651     bus->info = info;
652     bus->parent = parent;
653
654     if (name) {
655         /* use supplied name */
656         bus->name = qemu_strdup(name);
657     } else if (parent && parent->id) {
658         /* parent device has id -> use it for bus name */
659         len = strlen(parent->id) + 16;
660         buf = qemu_malloc(len);
661         snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
662         bus->name = buf;
663     } else {
664         /* no id -> use lowercase bus type for bus name */
665         len = strlen(info->name) + 16;
666         buf = qemu_malloc(len);
667         len = snprintf(buf, len, "%s.%d", info->name,
668                        parent ? parent->num_child_bus : 0);
669         for (i = 0; i < len; i++)
670             buf[i] = qemu_tolower(buf[i]);
671         bus->name = buf;
672     }
673
674     QLIST_INIT(&bus->children);
675     if (parent) {
676         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
677         parent->num_child_bus++;
678     }
679
680 }
681
682 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
683 {
684     BusState *bus;
685
686     bus = qemu_mallocz(info->size);
687     bus->qdev_allocated = 1;
688     qbus_create_inplace(bus, info, parent, name);
689     return bus;
690 }
691
692 void qbus_free(BusState *bus)
693 {
694     DeviceState *dev;
695
696     while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
697         qdev_free(dev);
698     }
699     if (bus->parent) {
700         QLIST_REMOVE(bus, sibling);
701         bus->parent->num_child_bus--;
702     }
703     qemu_free((void*)bus->name);
704     if (bus->qdev_allocated) {
705         qemu_free(bus);
706     }
707 }
708
709 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
710 static void qbus_print(Monitor *mon, BusState *bus, int indent);
711
712 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
713                              const char *prefix, int indent)
714 {
715     char buf[64];
716
717     if (!props)
718         return;
719     while (props->name) {
720         /*
721          * TODO Properties without a print method are just for dirty
722          * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
723          * marked for removal.  The test props->info->print should be
724          * removed along with it.
725          */
726         if (props->info->print) {
727             props->info->print(dev, props, buf, sizeof(buf));
728             qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
729         }
730         props++;
731     }
732 }
733
734 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
735 {
736     BusState *child;
737     qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
738                 dev->id ? dev->id : "");
739     indent += 2;
740     if (dev->num_gpio_in) {
741         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
742     }
743     if (dev->num_gpio_out) {
744         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
745     }
746     qdev_print_props(mon, dev, dev->info->props, "dev", indent);
747     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
748     if (dev->parent_bus->info->print_dev)
749         dev->parent_bus->info->print_dev(mon, dev, indent);
750     QLIST_FOREACH(child, &dev->child_bus, sibling) {
751         qbus_print(mon, child, indent);
752     }
753 }
754
755 static void qbus_print(Monitor *mon, BusState *bus, int indent)
756 {
757     struct DeviceState *dev;
758
759     qdev_printf("bus: %s\n", bus->name);
760     indent += 2;
761     qdev_printf("type %s\n", bus->info->name);
762     QLIST_FOREACH(dev, &bus->children, sibling) {
763         qdev_print(mon, dev, indent);
764     }
765 }
766 #undef qdev_printf
767
768 void do_info_qtree(Monitor *mon)
769 {
770     if (main_system_bus)
771         qbus_print(mon, main_system_bus, 0);
772 }
773
774 void do_info_qdm(Monitor *mon)
775 {
776     DeviceInfo *info;
777
778     for (info = device_info_list; info != NULL; info = info->next) {
779         qdev_print_devinfo(info);
780     }
781 }
782
783 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
784 {
785     QemuOpts *opts;
786
787     opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
788     if (!opts) {
789         return -1;
790     }
791     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
792         qemu_opts_del(opts);
793         return 0;
794     }
795     if (!qdev_device_add(opts)) {
796         qemu_opts_del(opts);
797         return -1;
798     }
799     return 0;
800 }
801
802 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
803 {
804     const char *id = qdict_get_str(qdict, "id");
805     DeviceState *dev;
806
807     dev = qdev_find_recursive(main_system_bus, id);
808     if (NULL == dev) {
809         qerror_report(QERR_DEVICE_NOT_FOUND, id);
810         return -1;
811     }
812     return qdev_unplug(dev);
813 }
This page took 0.072189 seconds and 4 git commands to generate.