File:  [Qemu by Fabrice Bellard] / qemu / hw / qdev.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:37:39 2018 UTC (2 years, 6 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, HEAD
qemu 0.12.0

    1: /*
    2:  *  Dynamic device configuration and creation.
    3:  *
    4:  *  Copyright (c) 2009 CodeSourcery
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library is distributed in the hope that it will be useful,
   12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
   18:  */
   19: 
   20: /* The theory here is that it should be possible to create a machine without
   21:    knowledge of specific devices.  Historically board init routines have
   22:    passed a bunch of arguments to each device, requiring the board know
   23:    exactly which device it is dealing with.  This file provides an abstract
   24:    API for device configuration and initialization.  Devices will generally
   25:    inherit from a particular bus (e.g. PCI or I2C) rather than
   26:    this API directly.  */
   27: 
   28: #include "net.h"
   29: #include "qdev.h"
   30: #include "sysemu.h"
   31: #include "monitor.h"
   32: #include "qerror.h"
   33: 
   34: static int qdev_hotplug = 0;
   35: 
   36: /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
   37: static BusState *main_system_bus;
   38: 
   39: DeviceInfo *device_info_list;
   40: 
   41: static BusState *qbus_find_recursive(BusState *bus, const char *name,
   42:                                      const BusInfo *info);
   43: static BusState *qbus_find(const char *path);
   44: 
   45: /* Register a new device type.  */
   46: void qdev_register(DeviceInfo *info)
   47: {
   48:     assert(info->size >= sizeof(DeviceState));
   49:     assert(!info->next);
   50: 
   51:     info->next = device_info_list;
   52:     device_info_list = info;
   53: }
   54: 
   55: static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
   56: {
   57:     DeviceInfo *info;
   58: 
   59:     /* first check device names */
   60:     for (info = device_info_list; info != NULL; info = info->next) {
   61:         if (bus_info && info->bus_info != bus_info)
   62:             continue;
   63:         if (strcmp(info->name, name) != 0)
   64:             continue;
   65:         return info;
   66:     }
   67: 
   68:     /* failing that check the aliases */
   69:     for (info = device_info_list; info != NULL; info = info->next) {
   70:         if (bus_info && info->bus_info != bus_info)
   71:             continue;
   72:         if (!info->alias)
   73:             continue;
   74:         if (strcmp(info->alias, name) != 0)
   75:             continue;
   76:         return info;
   77:     }
   78:     return NULL;
   79: }
   80: 
   81: /* Create a new device.  This only initializes the device state structure
   82:    and allows properties to be set.  qdev_init should be called to
   83:    initialize the actual device emulation.  */
   84: DeviceState *qdev_create(BusState *bus, const char *name)
   85: {
   86:     DeviceInfo *info;
   87:     DeviceState *dev;
   88: 
   89:     if (!bus) {
   90:         if (!main_system_bus) {
   91:             main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
   92:         }
   93:         bus = main_system_bus;
   94:     }
   95: 
   96:     info = qdev_find_info(bus->info, name);
   97:     if (!info) {
   98:         hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
   99:     }
  100: 
  101:     dev = qemu_mallocz(info->size);
  102:     dev->info = info;
  103:     dev->parent_bus = bus;
  104:     qdev_prop_set_defaults(dev, dev->info->props);
  105:     qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
  106:     qdev_prop_set_globals(dev);
  107:     QLIST_INSERT_HEAD(&bus->children, dev, sibling);
  108:     if (qdev_hotplug) {
  109:         assert(bus->allow_hotplug);
  110:         dev->hotplugged = 1;
  111:     }
  112:     dev->state = DEV_STATE_CREATED;
  113:     return dev;
  114: }
  115: 
  116: static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
  117: {
  118:     int pos = 0;
  119:     int ret;
  120: 
  121:     ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
  122:                    info->name, info->bus_info->name);
  123:     pos += MIN(len-pos,ret);
  124:     if (info->alias) {
  125:         ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
  126:         pos += MIN(len-pos,ret);
  127:     }
  128:     if (info->desc) {
  129:         ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
  130:         pos += MIN(len-pos,ret);
  131:     }
  132:     if (info->no_user) {
  133:         ret = snprintf(dest+pos, len-pos, ", no-user");
  134:         pos += MIN(len-pos,ret);
  135:     }
  136:     return pos;
  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:         qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
  150:                    name, value, dev->info->name);
  151:         return -1;
  152:     }
  153:     return 0;
  154: }
  155: 
  156: DeviceState *qdev_device_add(QemuOpts *opts)
  157: {
  158:     const char *driver, *path, *id;
  159:     DeviceInfo *info;
  160:     DeviceState *qdev;
  161:     BusState *bus;
  162: 
  163:     driver = qemu_opt_get(opts, "driver");
  164:     if (!driver) {
  165:         qemu_error("-device: no driver specified\n");
  166:         return NULL;
  167:     }
  168:     if (strcmp(driver, "?") == 0) {
  169:         char msg[256];
  170:         for (info = device_info_list; info != NULL; info = info->next) {
  171:             qdev_print_devinfo(info, msg, sizeof(msg));
  172:             qemu_error("%s\n", msg);
  173:         }
  174:         return NULL;
  175:     }
  176: 
  177:     /* find driver */
  178:     info = qdev_find_info(NULL, driver);
  179:     if (!info) {
  180:         qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);
  181:         return NULL;
  182:     }
  183:     if (info->no_user) {
  184:         qemu_error("device \"%s\" can't be added via command line\n",
  185:                    info->name);
  186:         return NULL;
  187:     }
  188: 
  189:     /* find bus */
  190:     path = qemu_opt_get(opts, "bus");
  191:     if (path != NULL) {
  192:         bus = qbus_find(path);
  193:     } else {
  194:         bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
  195:     }
  196:     if (!bus) {
  197:         qemu_error("Did not find %s bus for %s\n",
  198:                    path ? path : info->bus_info->name, info->name);
  199:         return NULL;
  200:     }
  201:     if (qdev_hotplug && !bus->allow_hotplug) {
  202:         qemu_error("Bus %s does not support hotplugging\n",
  203:                    bus->name);
  204:         return NULL;
  205:     }
  206: 
  207:     /* create device, set properties */
  208:     qdev = qdev_create(bus, driver);
  209:     id = qemu_opts_id(opts);
  210:     if (id) {
  211:         qdev->id = id;
  212:     }
  213:     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
  214:         qdev_free(qdev);
  215:         return NULL;
  216:     }
  217:     if (qdev_init(qdev) < 0) {
  218:         qemu_error("Error initializing device %s\n", driver);
  219:         return NULL;
  220:     }
  221:     qdev->opts = opts;
  222:     return qdev;
  223: }
  224: 
  225: static void qdev_reset(void *opaque)
  226: {
  227:     DeviceState *dev = opaque;
  228:     if (dev->info->reset)
  229:         dev->info->reset(dev);
  230: }
  231: 
  232: /* Initialize a device.  Device properties should be set before calling
  233:    this function.  IRQs and MMIO regions should be connected/mapped after
  234:    calling this function.
  235:    On failure, destroy the device and return negative value.
  236:    Return 0 on success.  */
  237: int qdev_init(DeviceState *dev)
  238: {
  239:     int rc;
  240: 
  241:     assert(dev->state == DEV_STATE_CREATED);
  242:     rc = dev->info->init(dev, dev->info);
  243:     if (rc < 0) {
  244:         qdev_free(dev);
  245:         return rc;
  246:     }
  247:     qemu_register_reset(qdev_reset, dev);
  248:     if (dev->info->vmsd)
  249:         vmstate_register(-1, dev->info->vmsd, dev);
  250:     dev->state = DEV_STATE_INITIALIZED;
  251:     return 0;
  252: }
  253: 
  254: int qdev_unplug(DeviceState *dev)
  255: {
  256:     if (!dev->parent_bus->allow_hotplug) {
  257:         qemu_error("Bus %s does not support hotplugging\n",
  258:                    dev->parent_bus->name);
  259:         return -1;
  260:     }
  261:     assert(dev->info->unplug != NULL);
  262: 
  263:     return dev->info->unplug(dev);
  264: }
  265: 
  266: /* can be used as ->unplug() callback for the simple cases */
  267: int qdev_simple_unplug_cb(DeviceState *dev)
  268: {
  269:     /* just zap it */
  270:     qdev_free(dev);
  271:     return 0;
  272: }
  273: 
  274: /* Like qdev_init(), but terminate program via hw_error() instead of
  275:    returning an error value.  This is okay during machine creation.
  276:    Don't use for hotplug, because there callers need to recover from
  277:    failure.  Exception: if you know the device's init() callback can't
  278:    fail, then qdev_init_nofail() can't fail either, and is therefore
  279:    usable even then.  But relying on the device implementation that
  280:    way is somewhat unclean, and best avoided.  */
  281: void qdev_init_nofail(DeviceState *dev)
  282: {
  283:     DeviceInfo *info = dev->info;
  284: 
  285:     if (qdev_init(dev) < 0)
  286:         hw_error("Initialization of device %s failed\n", info->name);
  287: }
  288: 
  289: /* Unlink device from bus and free the structure.  */
  290: void qdev_free(DeviceState *dev)
  291: {
  292:     BusState *bus;
  293: 
  294:     if (dev->state == DEV_STATE_INITIALIZED) {
  295:         while (dev->num_child_bus) {
  296:             bus = QLIST_FIRST(&dev->child_bus);
  297:             qbus_free(bus);
  298:         }
  299:         if (dev->info->vmsd)
  300:             vmstate_unregister(dev->info->vmsd, dev);
  301:         if (dev->info->exit)
  302:             dev->info->exit(dev);
  303:         if (dev->opts)
  304:             qemu_opts_del(dev->opts);
  305:     }
  306:     qemu_unregister_reset(qdev_reset, dev);
  307:     QLIST_REMOVE(dev, sibling);
  308:     qemu_free(dev);
  309: }
  310: 
  311: void qdev_machine_creation_done(void)
  312: {
  313:     /*
  314:      * ok, initial machine setup is done, starting from now we can
  315:      * only create hotpluggable devices
  316:      */
  317:     qdev_hotplug = 1;
  318: }
  319: 
  320: /* Get a character (serial) device interface.  */
  321: CharDriverState *qdev_init_chardev(DeviceState *dev)
  322: {
  323:     static int next_serial;
  324:     static int next_virtconsole;
  325:     /* FIXME: This is a nasty hack that needs to go away.  */
  326:     if (strncmp(dev->info->name, "virtio", 6) == 0) {
  327:         return virtcon_hds[next_virtconsole++];
  328:     } else {
  329:         return serial_hds[next_serial++];
  330:     }
  331: }
  332: 
  333: BusState *qdev_get_parent_bus(DeviceState *dev)
  334: {
  335:     return dev->parent_bus;
  336: }
  337: 
  338: void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
  339: {
  340:     assert(dev->num_gpio_in == 0);
  341:     dev->num_gpio_in = n;
  342:     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
  343: }
  344: 
  345: void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
  346: {
  347:     assert(dev->num_gpio_out == 0);
  348:     dev->num_gpio_out = n;
  349:     dev->gpio_out = pins;
  350: }
  351: 
  352: qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
  353: {
  354:     assert(n >= 0 && n < dev->num_gpio_in);
  355:     return dev->gpio_in[n];
  356: }
  357: 
  358: void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
  359: {
  360:     assert(n >= 0 && n < dev->num_gpio_out);
  361:     dev->gpio_out[n] = pin;
  362: }
  363: 
  364: void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
  365: {
  366:     qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
  367:     if (nd->vlan)
  368:         qdev_prop_set_vlan(dev, "vlan", nd->vlan);
  369:     if (nd->netdev)
  370:         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
  371:     if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
  372:         qdev_prop_exists(dev, "vectors")) {
  373:         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
  374:     }
  375: }
  376: 
  377: static int next_block_unit[IF_COUNT];
  378: 
  379: /* Get a block device.  This should only be used for single-drive devices
  380:    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
  381:    appropriate bus.  */
  382: BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
  383: {
  384:     int unit = next_block_unit[type]++;
  385:     DriveInfo *dinfo;
  386: 
  387:     dinfo = drive_get(type, 0, unit);
  388:     return dinfo ? dinfo->bdrv : NULL;
  389: }
  390: 
  391: BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
  392: {
  393:     BusState *bus;
  394: 
  395:     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
  396:         if (strcmp(name, bus->name) == 0) {
  397:             return bus;
  398:         }
  399:     }
  400:     return NULL;
  401: }
  402: 
  403: static BusState *qbus_find_recursive(BusState *bus, const char *name,
  404:                                      const BusInfo *info)
  405: {
  406:     DeviceState *dev;
  407:     BusState *child, *ret;
  408:     int match = 1;
  409: 
  410:     if (name && (strcmp(bus->name, name) != 0)) {
  411:         match = 0;
  412:     }
  413:     if (info && (bus->info != info)) {
  414:         match = 0;
  415:     }
  416:     if (match) {
  417:         return bus;
  418:     }
  419: 
  420:     QLIST_FOREACH(dev, &bus->children, sibling) {
  421:         QLIST_FOREACH(child, &dev->child_bus, sibling) {
  422:             ret = qbus_find_recursive(child, name, info);
  423:             if (ret) {
  424:                 return ret;
  425:             }
  426:         }
  427:     }
  428:     return NULL;
  429: }
  430: 
  431: static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
  432: {
  433:     DeviceState *dev, *ret;
  434:     BusState *child;
  435: 
  436:     QLIST_FOREACH(dev, &bus->children, sibling) {
  437:         if (dev->id && strcmp(dev->id, id) == 0)
  438:             return dev;
  439:         QLIST_FOREACH(child, &dev->child_bus, sibling) {
  440:             ret = qdev_find_recursive(child, id);
  441:             if (ret) {
  442:                 return ret;
  443:             }
  444:         }
  445:     }
  446:     return NULL;
  447: }
  448: 
  449: static void qbus_list_bus(DeviceState *dev, char *dest, int len)
  450: {
  451:     BusState *child;
  452:     const char *sep = " ";
  453:     int pos = 0;
  454: 
  455:     pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
  456:                     dev->id ? dev->id : dev->info->name);
  457:     QLIST_FOREACH(child, &dev->child_bus, sibling) {
  458:         pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
  459:         sep = ", ";
  460:     }
  461: }
  462: 
  463: static void qbus_list_dev(BusState *bus, char *dest, int len)
  464: {
  465:     DeviceState *dev;
  466:     const char *sep = " ";
  467:     int pos = 0;
  468: 
  469:     pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
  470:                     bus->name);
  471:     QLIST_FOREACH(dev, &bus->children, sibling) {
  472:         pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
  473:                         sep, dev->info->name);
  474:         if (dev->id)
  475:             pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
  476:         sep = ", ";
  477:     }
  478: }
  479: 
  480: static BusState *qbus_find_bus(DeviceState *dev, char *elem)
  481: {
  482:     BusState *child;
  483: 
  484:     QLIST_FOREACH(child, &dev->child_bus, sibling) {
  485:         if (strcmp(child->name, elem) == 0) {
  486:             return child;
  487:         }
  488:     }
  489:     return NULL;
  490: }
  491: 
  492: static DeviceState *qbus_find_dev(BusState *bus, char *elem)
  493: {
  494:     DeviceState *dev;
  495: 
  496:     /*
  497:      * try to match in order:
  498:      *   (1) instance id, if present
  499:      *   (2) driver name
  500:      *   (3) driver alias, if present
  501:      */
  502:     QLIST_FOREACH(dev, &bus->children, sibling) {
  503:         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
  504:             return dev;
  505:         }
  506:     }
  507:     QLIST_FOREACH(dev, &bus->children, sibling) {
  508:         if (strcmp(dev->info->name, elem) == 0) {
  509:             return dev;
  510:         }
  511:     }
  512:     QLIST_FOREACH(dev, &bus->children, sibling) {
  513:         if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
  514:             return dev;
  515:         }
  516:     }
  517:     return NULL;
  518: }
  519: 
  520: static BusState *qbus_find(const char *path)
  521: {
  522:     DeviceState *dev;
  523:     BusState *bus;
  524:     char elem[128], msg[256];
  525:     int pos, len;
  526: 
  527:     /* find start element */
  528:     if (path[0] == '/') {
  529:         bus = main_system_bus;
  530:         pos = 0;
  531:     } else {
  532:         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
  533:             qemu_error("path parse error (\"%s\")\n", path);
  534:             return NULL;
  535:         }
  536:         bus = qbus_find_recursive(main_system_bus, elem, NULL);
  537:         if (!bus) {
  538:             qemu_error("bus \"%s\" not found\n", elem);
  539:             return NULL;
  540:         }
  541:         pos = len;
  542:     }
  543: 
  544:     for (;;) {
  545:         if (path[pos] == '\0') {
  546:             /* we are done */
  547:             return bus;
  548:         }
  549: 
  550:         /* find device */
  551:         if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
  552:             qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
  553:             return NULL;
  554:         }
  555:         pos += len;
  556:         dev = qbus_find_dev(bus, elem);
  557:         if (!dev) {
  558:             qbus_list_dev(bus, msg, sizeof(msg));
  559:             qemu_error("device \"%s\" not found\n%s\n", elem, msg);
  560:             return NULL;
  561:         }
  562:         if (path[pos] == '\0') {
  563:             /* last specified element is a device.  If it has exactly
  564:              * one child bus accept it nevertheless */
  565:             switch (dev->num_child_bus) {
  566:             case 0:
  567:                 qemu_error("device has no child bus (%s)\n", path);
  568:                 return NULL;
  569:             case 1:
  570:                 return QLIST_FIRST(&dev->child_bus);
  571:             default:
  572:                 qbus_list_bus(dev, msg, sizeof(msg));
  573:                 qemu_error("device has multiple child busses (%s)\n%s\n",
  574:                            path, msg);
  575:                 return NULL;
  576:             }
  577:         }
  578: 
  579:         /* find bus */
  580:         if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
  581:             qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
  582:             return NULL;
  583:         }
  584:         pos += len;
  585:         bus = qbus_find_bus(dev, elem);
  586:         if (!bus) {
  587:             qbus_list_bus(dev, msg, sizeof(msg));
  588:             qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
  589:             return NULL;
  590:         }
  591:     }
  592: }
  593: 
  594: void qbus_create_inplace(BusState *bus, BusInfo *info,
  595:                          DeviceState *parent, const char *name)
  596: {
  597:     char *buf;
  598:     int i,len;
  599: 
  600:     bus->info = info;
  601:     bus->parent = parent;
  602: 
  603:     if (name) {
  604:         /* use supplied name */
  605:         bus->name = qemu_strdup(name);
  606:     } else if (parent && parent->id) {
  607:         /* parent device has id -> use it for bus name */
  608:         len = strlen(parent->id) + 16;
  609:         buf = qemu_malloc(len);
  610:         snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
  611:         bus->name = buf;
  612:     } else {
  613:         /* no id -> use lowercase bus type for bus name */
  614:         len = strlen(info->name) + 16;
  615:         buf = qemu_malloc(len);
  616:         len = snprintf(buf, len, "%s.%d", info->name,
  617:                        parent ? parent->num_child_bus : 0);
  618:         for (i = 0; i < len; i++)
  619:             buf[i] = qemu_tolower(buf[i]);
  620:         bus->name = buf;
  621:     }
  622: 
  623:     QLIST_INIT(&bus->children);
  624:     if (parent) {
  625:         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
  626:         parent->num_child_bus++;
  627:     }
  628: 
  629: }
  630: 
  631: BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
  632: {
  633:     BusState *bus;
  634: 
  635:     bus = qemu_mallocz(info->size);
  636:     bus->qdev_allocated = 1;
  637:     qbus_create_inplace(bus, info, parent, name);
  638:     return bus;
  639: }
  640: 
  641: void qbus_free(BusState *bus)
  642: {
  643:     DeviceState *dev;
  644: 
  645:     while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
  646:         qdev_free(dev);
  647:     }
  648:     if (bus->parent) {
  649:         QLIST_REMOVE(bus, sibling);
  650:         bus->parent->num_child_bus--;
  651:     }
  652:     if (bus->qdev_allocated) {
  653:         qemu_free(bus);
  654:     }
  655: }
  656: 
  657: #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
  658: static void qbus_print(Monitor *mon, BusState *bus, int indent);
  659: 
  660: static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
  661:                              const char *prefix, int indent)
  662: {
  663:     char buf[64];
  664: 
  665:     if (!props)
  666:         return;
  667:     while (props->name) {
  668:         if (props->info->print) {
  669:             props->info->print(dev, props, buf, sizeof(buf));
  670:             qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
  671:         }
  672:         props++;
  673:     }
  674: }
  675: 
  676: static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
  677: {
  678:     BusState *child;
  679:     qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
  680:                 dev->id ? dev->id : "");
  681:     indent += 2;
  682:     if (dev->num_gpio_in) {
  683:         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
  684:     }
  685:     if (dev->num_gpio_out) {
  686:         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
  687:     }
  688:     qdev_print_props(mon, dev, dev->info->props, "dev", indent);
  689:     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
  690:     if (dev->parent_bus->info->print_dev)
  691:         dev->parent_bus->info->print_dev(mon, dev, indent);
  692:     QLIST_FOREACH(child, &dev->child_bus, sibling) {
  693:         qbus_print(mon, child, indent);
  694:     }
  695: }
  696: 
  697: static void qbus_print(Monitor *mon, BusState *bus, int indent)
  698: {
  699:     struct DeviceState *dev;
  700: 
  701:     qdev_printf("bus: %s\n", bus->name);
  702:     indent += 2;
  703:     qdev_printf("type %s\n", bus->info->name);
  704:     QLIST_FOREACH(dev, &bus->children, sibling) {
  705:         qdev_print(mon, dev, indent);
  706:     }
  707: }
  708: #undef qdev_printf
  709: 
  710: void do_info_qtree(Monitor *mon)
  711: {
  712:     if (main_system_bus)
  713:         qbus_print(mon, main_system_bus, 0);
  714: }
  715: 
  716: void do_info_qdm(Monitor *mon)
  717: {
  718:     DeviceInfo *info;
  719:     char msg[256];
  720: 
  721:     for (info = device_info_list; info != NULL; info = info->next) {
  722:         qdev_print_devinfo(info, msg, sizeof(msg));
  723:         monitor_printf(mon, "%s\n", msg);
  724:     }
  725: }
  726: 
  727: void do_device_add(Monitor *mon, const QDict *qdict)
  728: {
  729:     QemuOpts *opts;
  730: 
  731:     opts = qemu_opts_parse(&qemu_device_opts,
  732:                            qdict_get_str(qdict, "config"), "driver");
  733:     if (opts)
  734:         qdev_device_add(opts);
  735: }
  736: 
  737: void do_device_del(Monitor *mon, const QDict *qdict)
  738: {
  739:     const char *id = qdict_get_str(qdict, "id");
  740:     DeviceState *dev;
  741: 
  742:     dev = qdev_find_recursive(main_system_bus, id);
  743:     if (NULL == dev) {
  744:         qemu_error("Device '%s' not found\n", id);
  745:         return;
  746:     }
  747:     qdev_unplug(dev);
  748: }

unix.superglobalmegacorp.com