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

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

unix.superglobalmegacorp.com