Annotation of qemu/hw/qdev.c, revision 1.1.1.2

1.1       root        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"
1.1.1.2 ! root       32: #include "qerror.h"
        !            33: 
        !            34: static int qdev_hotplug = 0;
1.1       root       35: 
                     36: /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
                     37: static BusState *main_system_bus;
                     38: 
1.1.1.2 ! root       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);
1.1       root       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);
1.1.1.2 ! root      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;
1.1       root      113:     return dev;
                    114: }
                    115: 
1.1.1.2 ! root      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: 
1.1       root      232: /* Initialize a device.  Device properties should be set before calling
                    233:    this function.  IRQs and MMIO regions should be connected/mapped after
1.1.1.2 ! root      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)
1.1       root      282: {
1.1.1.2 ! root      283:     DeviceInfo *info = dev->info;
        !           284: 
        !           285:     if (qdev_init(dev) < 0)
        !           286:         hw_error("Initialization of device %s failed\n", info->name);
1.1       root      287: }
                    288: 
                    289: /* Unlink device from bus and free the structure.  */
                    290: void qdev_free(DeviceState *dev)
                    291: {
1.1.1.2 ! root      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);
1.1       root      308:     qemu_free(dev);
                    309: }
                    310: 
1.1.1.2 ! root      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: 
1.1       root      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: 
1.1.1.2 ! root      364: void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
1.1       root      365: {
1.1.1.2 ! root      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:     }
1.1       root      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]++;
1.1.1.2 ! root      385:     DriveInfo *dinfo;
1.1       root      386: 
1.1.1.2 ! root      387:     dinfo = drive_get(type, 0, unit);
        !           388:     return dinfo ? dinfo->bdrv : NULL;
1.1       root      389: }
                    390: 
                    391: BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
                    392: {
                    393:     BusState *bus;
                    394: 
1.1.1.2 ! root      395:     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
1.1       root      396:         if (strcmp(name, bus->name) == 0) {
                    397:             return bus;
                    398:         }
                    399:     }
                    400:     return NULL;
                    401: }
                    402: 
1.1.1.2 ! root      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;
1.1       root      409: 
1.1.1.2 ! root      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;
1.1       root      429: }
                    430: 
1.1.1.2 ! root      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)
1.1       root      493: {
1.1.1.2 ! root      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;
1.1       root      523:     BusState *bus;
1.1.1.2 ! root      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;
1.1       root      599: 
                    600:     bus->info = info;
                    601:     bus->parent = parent;
1.1.1.2 ! root      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);
1.1       root      624:     if (parent) {
1.1.1.2 ! root      625:         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
        !           626:         parent->num_child_bus++;
1.1       root      627:     }
1.1.1.2 ! root      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);
1.1       root      638:     return bus;
                    639: }
                    640: 
1.1.1.2 ! root      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: 
1.1       root      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);
1.1.1.2 ! root      692:     QLIST_FOREACH(child, &dev->child_bus, sibling) {
1.1       root      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);
1.1.1.2 ! root      704:     QLIST_FOREACH(dev, &bus->children, sibling) {
1.1       root      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: }
1.1.1.2 ! root      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