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

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"
1.1.1.7 ! root       31: #include "error.h"
1.1.1.2   root       32: 
1.1.1.7 ! root       33: int qdev_hotplug = 0;
1.1.1.4   root       34: static bool qdev_hot_added = false;
                     35: static bool qdev_hot_removed = false;
1.1       root       36: 
                     37: /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
                     38: static BusState *main_system_bus;
1.1.1.6   root       39: static void main_system_bus_create(void);
1.1       root       40: 
                     41: /* Register a new device type.  */
1.1.1.7 ! root       42: const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
        !            43: {
        !            44:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
        !            45:     return dc->vmsd;
        !            46: }
        !            47: 
        !            48: BusInfo *qdev_get_bus_info(DeviceState *dev)
1.1       root       49: {
1.1.1.7 ! root       50:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
        !            51:     return dc->bus_info;
        !            52: }
1.1       root       53: 
1.1.1.7 ! root       54: Property *qdev_get_props(DeviceState *dev)
        !            55: {
        !            56:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
        !            57:     return dc->props;
1.1       root       58: }
                     59: 
1.1.1.7 ! root       60: const char *qdev_fw_name(DeviceState *dev)
1.1       root       61: {
1.1.1.7 ! root       62:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
1.1       root       63: 
1.1.1.7 ! root       64:     if (dc->fw_name) {
        !            65:         return dc->fw_name;
1.1       root       66:     }
                     67: 
1.1.1.7 ! root       68:     return object_get_typename(OBJECT(dev));
1.1       root       69: }
                     70: 
1.1.1.7 ! root       71: bool qdev_exists(const char *name)
1.1.1.3   root       72: {
1.1.1.7 ! root       73:     return !!object_class_by_name(name);
        !            74: }
        !            75: 
        !            76: static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
        !            77:                                      Error **errp);
        !            78: 
        !            79: void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
        !            80: {
        !            81:     Property *prop;
1.1.1.3   root       82: 
                     83:     if (qdev_hotplug) {
                     84:         assert(bus->allow_hotplug);
                     85:     }
1.1.1.7 ! root       86: 
        !            87:     dev->parent_bus = bus;
        !            88:     QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
        !            89: 
        !            90:     for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
        !            91:         qdev_property_add_legacy(dev, prop, NULL);
        !            92:         qdev_property_add_static(dev, prop, NULL);
        !            93:     }
        !            94:     qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
1.1.1.3   root       95: }
                     96: 
1.1       root       97: /* Create a new device.  This only initializes the device state structure
                     98:    and allows properties to be set.  qdev_init should be called to
                     99:    initialize the actual device emulation.  */
                    100: DeviceState *qdev_create(BusState *bus, const char *name)
                    101: {
1.1.1.5   root      102:     DeviceState *dev;
                    103: 
                    104:     dev = qdev_try_create(bus, name);
                    105:     if (!dev) {
1.1.1.6   root      106:         if (bus) {
                    107:             hw_error("Unknown device '%s' for bus '%s'\n", name,
                    108:                      bus->info->name);
                    109:         } else {
                    110:             hw_error("Unknown device '%s' for default sysbus\n", name);
                    111:         }
1.1.1.5   root      112:     }
                    113: 
                    114:     return dev;
                    115: }
                    116: 
1.1.1.7 ! root      117: DeviceState *qdev_try_create(BusState *bus, const char *type)
1.1.1.5   root      118: {
1.1.1.7 ! root      119:     DeviceState *dev;
1.1       root      120: 
1.1.1.7 ! root      121:     if (object_class_by_name(type) == NULL) {
1.1.1.5   root      122:         return NULL;
1.1       root      123:     }
1.1.1.7 ! root      124:     dev = DEVICE(object_new(type));
        !           125:     if (!dev) {
1.1.1.2   root      126:         return NULL;
                    127:     }
                    128: 
1.1.1.7 ! root      129:     if (!bus) {
        !           130:         bus = sysbus_get_default();
1.1.1.2   root      131:     }
                    132: 
1.1.1.7 ! root      133:     qdev_set_parent_bus(dev, bus);
        !           134:     qdev_prop_set_globals(dev);
1.1.1.2   root      135: 
1.1.1.7 ! root      136:     return dev;
1.1.1.2   root      137: }
                    138: 
1.1       root      139: /* Initialize a device.  Device properties should be set before calling
                    140:    this function.  IRQs and MMIO regions should be connected/mapped after
1.1.1.2   root      141:    calling this function.
                    142:    On failure, destroy the device and return negative value.
                    143:    Return 0 on success.  */
                    144: int qdev_init(DeviceState *dev)
                    145: {
1.1.1.7 ! root      146:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
1.1.1.2   root      147:     int rc;
                    148: 
                    149:     assert(dev->state == DEV_STATE_CREATED);
1.1.1.7 ! root      150: 
        !           151:     rc = dc->init(dev);
1.1.1.2   root      152:     if (rc < 0) {
1.1.1.7 ! root      153:         object_unparent(OBJECT(dev));
1.1.1.2   root      154:         qdev_free(dev);
                    155:         return rc;
                    156:     }
1.1.1.7 ! root      157: 
        !           158:     if (!OBJECT(dev)->parent) {
        !           159:         static int unattached_count = 0;
        !           160:         gchar *name = g_strdup_printf("device[%d]", unattached_count++);
        !           161: 
        !           162:         object_property_add_child(container_get(qdev_get_machine(),
        !           163:                                                 "/unattached"),
        !           164:                                   name, OBJECT(dev), NULL);
        !           165:         g_free(name);
        !           166:     }
        !           167: 
        !           168:     if (qdev_get_vmsd(dev)) {
        !           169:         vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
1.1.1.3   root      170:                                        dev->instance_id_alias,
                    171:                                        dev->alias_required_for_version);
                    172:     }
1.1.1.2   root      173:     dev->state = DEV_STATE_INITIALIZED;
1.1.1.7 ! root      174:     if (dev->hotplugged) {
        !           175:         device_reset(dev);
1.1.1.6   root      176:     }
1.1.1.2   root      177:     return 0;
                    178: }
                    179: 
1.1.1.3   root      180: void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
                    181:                                  int required_for_version)
                    182: {
                    183:     assert(dev->state == DEV_STATE_CREATED);
                    184:     dev->instance_id_alias = alias_id;
                    185:     dev->alias_required_for_version = required_for_version;
                    186: }
                    187: 
1.1.1.7 ! root      188: void qdev_unplug(DeviceState *dev, Error **errp)
1.1.1.2   root      189: {
1.1.1.7 ! root      190:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
        !           191: 
1.1.1.2   root      192:     if (!dev->parent_bus->allow_hotplug) {
1.1.1.7 ! root      193:         error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
        !           194:         return;
1.1.1.2   root      195:     }
1.1.1.7 ! root      196:     assert(dc->unplug != NULL);
1.1.1.2   root      197: 
1.1.1.4   root      198:     qdev_hot_removed = true;
                    199: 
1.1.1.7 ! root      200:     if (dc->unplug(dev) < 0) {
        !           201:         error_set(errp, QERR_UNDEFINED_ERROR);
        !           202:         return;
        !           203:     }
1.1.1.2   root      204: }
                    205: 
1.1.1.4   root      206: static int qdev_reset_one(DeviceState *dev, void *opaque)
                    207: {
1.1.1.7 ! root      208:     device_reset(dev);
1.1.1.4   root      209: 
                    210:     return 0;
                    211: }
                    212: 
                    213: BusState *sysbus_get_default(void)
                    214: {
                    215:     if (!main_system_bus) {
1.1.1.6   root      216:         main_system_bus_create();
1.1.1.4   root      217:     }
                    218:     return main_system_bus;
                    219: }
                    220: 
                    221: static int qbus_reset_one(BusState *bus, void *opaque)
                    222: {
                    223:     if (bus->info->reset) {
                    224:         return bus->info->reset(bus);
                    225:     }
                    226:     return 0;
                    227: }
                    228: 
                    229: void qdev_reset_all(DeviceState *dev)
                    230: {
                    231:     qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
                    232: }
                    233: 
                    234: void qbus_reset_all_fn(void *opaque)
                    235: {
                    236:     BusState *bus = opaque;
                    237:     qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
                    238: }
                    239: 
1.1.1.2   root      240: /* can be used as ->unplug() callback for the simple cases */
                    241: int qdev_simple_unplug_cb(DeviceState *dev)
                    242: {
                    243:     /* just zap it */
1.1.1.7 ! root      244:     object_unparent(OBJECT(dev));
1.1.1.2   root      245:     qdev_free(dev);
                    246:     return 0;
                    247: }
                    248: 
1.1.1.5   root      249: 
                    250: /* Like qdev_init(), but terminate program via error_report() instead of
1.1.1.2   root      251:    returning an error value.  This is okay during machine creation.
                    252:    Don't use for hotplug, because there callers need to recover from
                    253:    failure.  Exception: if you know the device's init() callback can't
                    254:    fail, then qdev_init_nofail() can't fail either, and is therefore
                    255:    usable even then.  But relying on the device implementation that
                    256:    way is somewhat unclean, and best avoided.  */
                    257: void qdev_init_nofail(DeviceState *dev)
1.1       root      258: {
1.1.1.3   root      259:     if (qdev_init(dev) < 0) {
1.1.1.7 ! root      260:         error_report("Initialization of device %s failed",
        !           261:                      object_get_typename(OBJECT(dev)));
1.1.1.3   root      262:         exit(1);
                    263:     }
1.1       root      264: }
                    265: 
                    266: /* Unlink device from bus and free the structure.  */
                    267: void qdev_free(DeviceState *dev)
                    268: {
1.1.1.7 ! root      269:     object_delete(OBJECT(dev));
1.1       root      270: }
                    271: 
1.1.1.2   root      272: void qdev_machine_creation_done(void)
                    273: {
                    274:     /*
                    275:      * ok, initial machine setup is done, starting from now we can
                    276:      * only create hotpluggable devices
                    277:      */
                    278:     qdev_hotplug = 1;
                    279: }
                    280: 
1.1.1.4   root      281: bool qdev_machine_modified(void)
                    282: {
                    283:     return qdev_hot_added || qdev_hot_removed;
                    284: }
                    285: 
1.1       root      286: BusState *qdev_get_parent_bus(DeviceState *dev)
                    287: {
                    288:     return dev->parent_bus;
                    289: }
                    290: 
                    291: void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
                    292: {
                    293:     assert(dev->num_gpio_in == 0);
                    294:     dev->num_gpio_in = n;
                    295:     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
                    296: }
                    297: 
                    298: void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
                    299: {
                    300:     assert(dev->num_gpio_out == 0);
                    301:     dev->num_gpio_out = n;
                    302:     dev->gpio_out = pins;
                    303: }
                    304: 
                    305: qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
                    306: {
                    307:     assert(n >= 0 && n < dev->num_gpio_in);
                    308:     return dev->gpio_in[n];
                    309: }
                    310: 
                    311: void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
                    312: {
                    313:     assert(n >= 0 && n < dev->num_gpio_out);
                    314:     dev->gpio_out[n] = pin;
                    315: }
                    316: 
1.1.1.2   root      317: void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
1.1       root      318: {
1.1.1.5   root      319:     qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
1.1.1.2   root      320:     if (nd->vlan)
                    321:         qdev_prop_set_vlan(dev, "vlan", nd->vlan);
                    322:     if (nd->netdev)
                    323:         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
1.1.1.3   root      324:     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
1.1.1.2   root      325:         qdev_prop_exists(dev, "vectors")) {
                    326:         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
                    327:     }
1.1.1.5   root      328:     nd->instantiated = 1;
1.1       root      329: }
                    330: 
1.1.1.4   root      331: BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
                    332: {
                    333:     BusState *bus;
1.1       root      334: 
1.1.1.4   root      335:     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
                    336:         if (strcmp(name, bus->name) == 0) {
                    337:             return bus;
                    338:         }
                    339:     }
                    340:     return NULL;
                    341: }
                    342: 
                    343: int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                    344:                        qbus_walkerfn *busfn, void *opaque)
1.1       root      345: {
1.1.1.4   root      346:     DeviceState *dev;
                    347:     int err;
1.1       root      348: 
1.1.1.4   root      349:     if (busfn) {
                    350:         err = busfn(bus, opaque);
                    351:         if (err) {
                    352:             return err;
                    353:         }
                    354:     }
                    355: 
1.1.1.6   root      356:     QTAILQ_FOREACH(dev, &bus->children, sibling) {
1.1.1.4   root      357:         err = qdev_walk_children(dev, devfn, busfn, opaque);
                    358:         if (err < 0) {
                    359:             return err;
                    360:         }
                    361:     }
                    362: 
                    363:     return 0;
1.1       root      364: }
                    365: 
1.1.1.4   root      366: int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                    367:                        qbus_walkerfn *busfn, void *opaque)
1.1       root      368: {
                    369:     BusState *bus;
1.1.1.4   root      370:     int err;
                    371: 
                    372:     if (devfn) {
                    373:         err = devfn(dev, opaque);
                    374:         if (err) {
                    375:             return err;
                    376:         }
                    377:     }
1.1       root      378: 
1.1.1.2   root      379:     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
1.1.1.4   root      380:         err = qbus_walk_children(bus, devfn, busfn, opaque);
                    381:         if (err < 0) {
                    382:             return err;
1.1       root      383:         }
                    384:     }
1.1.1.4   root      385: 
                    386:     return 0;
1.1       root      387: }
                    388: 
1.1.1.4   root      389: DeviceState *qdev_find_recursive(BusState *bus, const char *id)
1.1.1.2   root      390: {
                    391:     DeviceState *dev, *ret;
                    392:     BusState *child;
                    393: 
1.1.1.6   root      394:     QTAILQ_FOREACH(dev, &bus->children, sibling) {
1.1.1.2   root      395:         if (dev->id && strcmp(dev->id, id) == 0)
                    396:             return dev;
                    397:         QLIST_FOREACH(child, &dev->child_bus, sibling) {
                    398:             ret = qdev_find_recursive(child, id);
                    399:             if (ret) {
                    400:                 return ret;
                    401:             }
                    402:         }
                    403:     }
                    404:     return NULL;
                    405: }
                    406: 
                    407: void qbus_create_inplace(BusState *bus, BusInfo *info,
                    408:                          DeviceState *parent, const char *name)
                    409: {
                    410:     char *buf;
                    411:     int i,len;
1.1       root      412: 
                    413:     bus->info = info;
                    414:     bus->parent = parent;
1.1.1.2   root      415: 
                    416:     if (name) {
                    417:         /* use supplied name */
1.1.1.6   root      418:         bus->name = g_strdup(name);
1.1.1.2   root      419:     } else if (parent && parent->id) {
                    420:         /* parent device has id -> use it for bus name */
                    421:         len = strlen(parent->id) + 16;
1.1.1.6   root      422:         buf = g_malloc(len);
1.1.1.2   root      423:         snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
                    424:         bus->name = buf;
                    425:     } else {
                    426:         /* no id -> use lowercase bus type for bus name */
                    427:         len = strlen(info->name) + 16;
1.1.1.6   root      428:         buf = g_malloc(len);
1.1.1.2   root      429:         len = snprintf(buf, len, "%s.%d", info->name,
                    430:                        parent ? parent->num_child_bus : 0);
                    431:         for (i = 0; i < len; i++)
                    432:             buf[i] = qemu_tolower(buf[i]);
                    433:         bus->name = buf;
                    434:     }
                    435: 
1.1.1.6   root      436:     QTAILQ_INIT(&bus->children);
1.1       root      437:     if (parent) {
1.1.1.2   root      438:         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
                    439:         parent->num_child_bus++;
1.1.1.4   root      440:     } else if (bus != main_system_bus) {
                    441:         /* TODO: once all bus devices are qdevified,
                    442:            only reset handler for main_system_bus should be registered here. */
                    443:         qemu_register_reset(qbus_reset_all_fn, bus);
1.1       root      444:     }
1.1.1.2   root      445: }
                    446: 
                    447: BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
                    448: {
                    449:     BusState *bus;
                    450: 
1.1.1.6   root      451:     bus = g_malloc0(info->size);
1.1.1.2   root      452:     bus->qdev_allocated = 1;
                    453:     qbus_create_inplace(bus, info, parent, name);
1.1       root      454:     return bus;
                    455: }
                    456: 
1.1.1.6   root      457: static void main_system_bus_create(void)
                    458: {
                    459:     /* assign main_system_bus before qbus_create_inplace()
                    460:      * in order to make "if (bus != main_system_bus)" work */
                    461:     main_system_bus = g_malloc0(system_bus_info.size);
                    462:     main_system_bus->qdev_allocated = 1;
                    463:     qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
                    464:                         "main-system-bus");
                    465: }
                    466: 
1.1.1.2   root      467: void qbus_free(BusState *bus)
                    468: {
                    469:     DeviceState *dev;
                    470: 
1.1.1.6   root      471:     while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
1.1.1.2   root      472:         qdev_free(dev);
                    473:     }
                    474:     if (bus->parent) {
                    475:         QLIST_REMOVE(bus, sibling);
                    476:         bus->parent->num_child_bus--;
1.1.1.4   root      477:     } else {
                    478:         assert(bus != main_system_bus); /* main_system_bus is never freed */
                    479:         qemu_unregister_reset(qbus_reset_all_fn, bus);
1.1.1.2   root      480:     }
1.1.1.6   root      481:     g_free((void*)bus->name);
1.1.1.2   root      482:     if (bus->qdev_allocated) {
1.1.1.6   root      483:         g_free(bus);
1.1.1.2   root      484:     }
                    485: }
                    486: 
1.1.1.7 ! root      487: static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1.1       root      488: {
1.1.1.7 ! root      489:     int l = 0;
1.1       root      490: 
1.1.1.7 ! root      491:     if (dev && dev->parent_bus) {
        !           492:         char *d;
        !           493:         l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
        !           494:         if (dev->parent_bus->info->get_fw_dev_path) {
        !           495:             d = dev->parent_bus->info->get_fw_dev_path(dev);
        !           496:             l += snprintf(p + l, size - l, "%s", d);
        !           497:             g_free(d);
        !           498:         } else {
        !           499:             l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
1.1       root      500:         }
                    501:     }
1.1.1.7 ! root      502:     l += snprintf(p + l , size - l, "/");
1.1       root      503: 
1.1.1.7 ! root      504:     return l;
1.1       root      505: }
                    506: 
1.1.1.7 ! root      507: char* qdev_get_fw_dev_path(DeviceState *dev)
1.1       root      508: {
1.1.1.7 ! root      509:     char path[128];
        !           510:     int l;
1.1       root      511: 
1.1.1.7 ! root      512:     l = qdev_get_fw_dev_path_helper(dev, path, 128);
        !           513: 
        !           514:     path[l-1] = '\0';
        !           515: 
        !           516:     return strdup(path);
1.1       root      517: }
                    518: 
1.1.1.7 ! root      519: static char *qdev_get_type(Object *obj, Error **errp)
1.1       root      520: {
1.1.1.7 ! root      521:     return g_strdup(object_get_typename(obj));
1.1       root      522: }
1.1.1.2   root      523: 
1.1.1.7 ! root      524: /**
        !           525:  * Legacy property handling
        !           526:  */
        !           527: 
        !           528: static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
        !           529:                                      const char *name, Error **errp)
1.1.1.2   root      530: {
1.1.1.7 ! root      531:     DeviceState *dev = DEVICE(obj);
        !           532:     Property *prop = opaque;
1.1.1.2   root      533: 
1.1.1.7 ! root      534:     char buffer[1024];
        !           535:     char *ptr = buffer;
        !           536: 
        !           537:     prop->info->print(dev, prop, buffer, sizeof(buffer));
        !           538:     visit_type_str(v, &ptr, name, errp);
1.1.1.2   root      539: }
                    540: 
1.1.1.7 ! root      541: static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
        !           542:                                      const char *name, Error **errp)
1.1.1.2   root      543: {
1.1.1.7 ! root      544:     DeviceState *dev = DEVICE(obj);
        !           545:     Property *prop = opaque;
        !           546:     Error *local_err = NULL;
        !           547:     char *ptr = NULL;
        !           548:     int ret;
1.1.1.2   root      549: 
1.1.1.7 ! root      550:     if (dev->state != DEV_STATE_CREATED) {
        !           551:         error_set(errp, QERR_PERMISSION_DENIED);
        !           552:         return;
1.1.1.3   root      553:     }
1.1.1.7 ! root      554: 
        !           555:     visit_type_str(v, &ptr, name, &local_err);
        !           556:     if (local_err) {
        !           557:         error_propagate(errp, local_err);
        !           558:         return;
1.1.1.3   root      559:     }
1.1.1.7 ! root      560: 
        !           561:     ret = prop->info->parse(dev, prop, ptr);
        !           562:     error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
        !           563:     g_free(ptr);
        !           564: }
        !           565: 
        !           566: /**
        !           567:  * @qdev_add_legacy_property - adds a legacy property
        !           568:  *
        !           569:  * Do not use this is new code!  Properties added through this interface will
        !           570:  * be given names and types in the "legacy" namespace.
        !           571:  *
        !           572:  * Legacy properties are string versions of other OOM properties.  The format
        !           573:  * of the string depends on the property type.
        !           574:  */
        !           575: void qdev_property_add_legacy(DeviceState *dev, Property *prop,
        !           576:                               Error **errp)
        !           577: {
        !           578:     gchar *name, *type;
        !           579: 
        !           580:     /* Register pointer properties as legacy properties */
        !           581:     if (!prop->info->print && !prop->info->parse &&
        !           582:         (prop->info->set || prop->info->get)) {
        !           583:         return;
1.1.1.3   root      584:     }
1.1.1.7 ! root      585: 
        !           586:     name = g_strdup_printf("legacy-%s", prop->name);
        !           587:     type = g_strdup_printf("legacy<%s>",
        !           588:                            prop->info->legacy_name ?: prop->info->name);
        !           589: 
        !           590:     object_property_add(OBJECT(dev), name, type,
        !           591:                         prop->info->print ? qdev_get_legacy_property : prop->info->get,
        !           592:                         prop->info->parse ? qdev_set_legacy_property : prop->info->set,
        !           593:                         NULL,
        !           594:                         prop, errp);
        !           595: 
        !           596:     g_free(type);
        !           597:     g_free(name);
        !           598: }
        !           599: 
        !           600: /**
        !           601:  * @qdev_property_add_static - add a @Property to a device.
        !           602:  *
        !           603:  * Static properties access data in a struct.  The actual type of the
        !           604:  * property and the field depends on the property type.
        !           605:  */
        !           606: void qdev_property_add_static(DeviceState *dev, Property *prop,
        !           607:                               Error **errp)
        !           608: {
        !           609:     /*
        !           610:      * TODO qdev_prop_ptr does not have getters or setters.  It must
        !           611:      * go now that it can be replaced with links.  The test should be
        !           612:      * removed along with it: all static properties are read/write.
        !           613:      */
        !           614:     if (!prop->info->get && !prop->info->set) {
        !           615:         return;
        !           616:     }
        !           617: 
        !           618:     object_property_add(OBJECT(dev), prop->name, prop->info->name,
        !           619:                         prop->info->get, prop->info->set,
        !           620:                         prop->info->release,
        !           621:                         prop, errp);
1.1.1.2   root      622: }
                    623: 
1.1.1.7 ! root      624: static void device_initfn(Object *obj)
1.1.1.2   root      625: {
1.1.1.7 ! root      626:     DeviceState *dev = DEVICE(obj);
        !           627:     Property *prop;
        !           628: 
        !           629:     if (qdev_hotplug) {
        !           630:         dev->hotplugged = 1;
        !           631:         qdev_hot_added = true;
        !           632:     }
        !           633: 
        !           634:     dev->instance_id_alias = -1;
        !           635:     dev->state = DEV_STATE_CREATED;
1.1.1.2   root      636: 
1.1.1.7 ! root      637:     for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
        !           638:         qdev_property_add_legacy(dev, prop, NULL);
        !           639:         qdev_property_add_static(dev, prop, NULL);
1.1.1.2   root      640:     }
1.1.1.7 ! root      641: 
        !           642:     object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
        !           643:     qdev_prop_set_defaults(dev, qdev_get_props(dev));
1.1.1.2   root      644: }
1.1.1.4   root      645: 
1.1.1.7 ! root      646: /* Unlink device from bus and free the structure.  */
        !           647: static void device_finalize(Object *obj)
1.1.1.4   root      648: {
1.1.1.7 ! root      649:     DeviceState *dev = DEVICE(obj);
        !           650:     BusState *bus;
        !           651:     DeviceClass *dc = DEVICE_GET_CLASS(dev);
1.1.1.4   root      652: 
1.1.1.7 ! root      653:     if (dev->state == DEV_STATE_INITIALIZED) {
        !           654:         while (dev->num_child_bus) {
        !           655:             bus = QLIST_FIRST(&dev->child_bus);
        !           656:             qbus_free(bus);
        !           657:         }
        !           658:         if (qdev_get_vmsd(dev)) {
        !           659:             vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
        !           660:         }
        !           661:         if (dc->exit) {
        !           662:             dc->exit(dev);
        !           663:         }
        !           664:         if (dev->opts) {
        !           665:             qemu_opts_del(dev->opts);
1.1.1.4   root      666:         }
                    667:     }
1.1.1.7 ! root      668:     QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
        !           669: }
1.1.1.4   root      670: 
1.1.1.7 ! root      671: void device_reset(DeviceState *dev)
        !           672: {
        !           673:     DeviceClass *klass = DEVICE_GET_CLASS(dev);
        !           674: 
        !           675:     if (klass->reset) {
        !           676:         klass->reset(dev);
        !           677:     }
1.1.1.4   root      678: }
                    679: 
1.1.1.7 ! root      680: Object *qdev_get_machine(void)
1.1.1.4   root      681: {
1.1.1.7 ! root      682:     static Object *dev;
1.1.1.4   root      683: 
1.1.1.7 ! root      684:     if (dev == NULL) {
        !           685:         dev = container_get(object_get_root(), "/machine");
        !           686:     }
1.1.1.4   root      687: 
1.1.1.7 ! root      688:     return dev;
        !           689: }
1.1.1.4   root      690: 
1.1.1.7 ! root      691: static TypeInfo device_type_info = {
        !           692:     .name = TYPE_DEVICE,
        !           693:     .parent = TYPE_OBJECT,
        !           694:     .instance_size = sizeof(DeviceState),
        !           695:     .instance_init = device_initfn,
        !           696:     .instance_finalize = device_finalize,
        !           697:     .abstract = true,
        !           698:     .class_size = sizeof(DeviceClass),
        !           699: };
        !           700: 
        !           701: static void qdev_register_types(void)
        !           702: {
        !           703:     type_register_static(&device_type_info);
1.1.1.4   root      704: }
1.1.1.7 ! root      705: 
        !           706: type_init(qdev_register_types)

unix.superglobalmegacorp.com