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