]> Git Repo - qemu.git/blobdiff - hw/qdev.c
savevm: Factorize ram globals reset in its own function
[qemu.git] / hw / qdev.c
index 0692a21fbd1b09a252af95c2d8f4a7f98852d7c4..9b9aba376b1f194f29c9215b5869fdfcba54dd10 100644 (file)
--- a/hw/qdev.c
+++ b/hw/qdev.c
 #include "net.h"
 #include "qdev.h"
 #include "sysemu.h"
+#include "error.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
 static bool qdev_hot_removed = false;
 
-/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
-static BusState *main_system_bus;
-static void main_system_bus_create(void);
-
-/* Register a new device type.  */
 const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     return dc->vmsd;
 }
 
-BusInfo *qdev_get_bus_info(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->bus_info;
-}
-
-Property *qdev_get_props(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->props;
-}
-
 const char *qdev_fw_name(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -67,30 +51,51 @@ const char *qdev_fw_name(DeviceState *dev)
     return object_get_typename(OBJECT(dev));
 }
 
-bool qdev_exists(const char *name)
-{
-    return !!object_class_by_name(name);
-}
-
 static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                      Error **errp);
 
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+static void bus_remove_child(BusState *bus, DeviceState *child)
 {
-    Property *prop;
+    BusChild *kid;
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        if (kid->child == child) {
+            char name[32];
+
+            snprintf(name, sizeof(name), "child[%d]", kid->index);
+            QTAILQ_REMOVE(&bus->children, kid, sibling);
+            object_property_del(OBJECT(bus), name, NULL);
+            g_free(kid);
+            return;
+        }
+    }
+}
+
+static void bus_add_child(BusState *bus, DeviceState *child)
+{
+    char name[32];
+    BusChild *kid = g_malloc0(sizeof(*kid));
 
     if (qdev_hotplug) {
         assert(bus->allow_hotplug);
     }
 
-    dev->parent_bus = bus;
-    QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
+    kid->index = bus->max_index++;
+    kid->child = child;
 
-    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
-    for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
-        qdev_property_add_legacy(dev, prop, NULL);
-        qdev_property_add_static(dev, prop, NULL);
-    }
+    QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
+
+    snprintf(name, sizeof(name), "child[%d]", kid->index);
+    object_property_add_link(OBJECT(bus), name,
+                             object_get_typename(OBJECT(child)),
+                             (Object **)&kid->child,
+                             NULL);
+}
+
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+{
+    dev->parent_bus = bus;
+    bus_add_child(bus, dev);
 }
 
 /* Create a new device.  This only initializes the device state structure
@@ -104,7 +109,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     if (!dev) {
         if (bus) {
             hw_error("Unknown device '%s' for bus '%s'\n", name,
-                     bus->info->name);
+                     object_get_typename(OBJECT(bus)));
         } else {
             hw_error("Unknown device '%s' for default sysbus\n", name);
         }
@@ -113,11 +118,14 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     return dev;
 }
 
-DeviceState *qdev_try_create(BusState *bus, const char *name)
+DeviceState *qdev_try_create(BusState *bus, const char *type)
 {
     DeviceState *dev;
 
-    dev = DEVICE(object_new(name));
+    if (object_class_by_name(type) == NULL) {
+        return NULL;
+    }
+    dev = DEVICE(object_new(type));
     if (!dev) {
         return NULL;
     }
@@ -127,7 +135,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *name)
     }
 
     qdev_set_parent_bus(dev, bus);
-    qdev_prop_set_globals(dev);
 
     return dev;
 }
@@ -149,6 +156,17 @@ int qdev_init(DeviceState *dev)
         qdev_free(dev);
         return rc;
     }
+
+    if (!OBJECT(dev)->parent) {
+        static int unattached_count = 0;
+        gchar *name = g_strdup_printf("device[%d]", unattached_count++);
+
+        object_property_add_child(container_get(qdev_get_machine(),
+                                                "/unattached"),
+                                  name, OBJECT(dev), NULL);
+        g_free(name);
+    }
+
     if (qdev_get_vmsd(dev)) {
         vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
                                        dev->instance_id_alias,
@@ -169,19 +187,22 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
     dev->alias_required_for_version = required_for_version;
 }
 
-int qdev_unplug(DeviceState *dev)
+void qdev_unplug(DeviceState *dev, Error **errp)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
     if (!dev->parent_bus->allow_hotplug) {
-        qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
-        return -1;
+        error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
+        return;
     }
     assert(dc->unplug != NULL);
 
     qdev_hot_removed = true;
 
-    return dc->unplug(dev);
+    if (dc->unplug(dev) < 0) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
+    }
 }
 
 static int qdev_reset_one(DeviceState *dev, void *opaque)
@@ -191,18 +212,11 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
     return 0;
 }
 
-BusState *sysbus_get_default(void)
-{
-    if (!main_system_bus) {
-        main_system_bus_create();
-    }
-    return main_system_bus;
-}
-
 static int qbus_reset_one(BusState *bus, void *opaque)
 {
-    if (bus->info->reset) {
-        return bus->info->reset(bus);
+    BusClass *bc = BUS_GET_CLASS(bus);
+    if (bc->reset) {
+        return bc->reset(bus);
     }
     return 0;
 }
@@ -236,89 +250,17 @@ int qdev_simple_unplug_cb(DeviceState *dev)
    way is somewhat unclean, and best avoided.  */
 void qdev_init_nofail(DeviceState *dev)
 {
+    const char *typename = object_get_typename(OBJECT(dev));
+
     if (qdev_init(dev) < 0) {
-        error_report("Initialization of device %s failed",
-                     object_get_typename(OBJECT(dev)));
+        error_report("Initialization of device %s failed", typename);
         exit(1);
     }
 }
 
-static void qdev_property_del_all(DeviceState *dev)
-{
-    while (!QTAILQ_EMPTY(&dev->properties)) {
-        DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
-
-        QTAILQ_REMOVE(&dev->properties, prop, node);
-
-        if (prop->release) {
-            prop->release(dev, prop->name, prop->opaque);
-        }
-
-        g_free(prop->name);
-        g_free(prop->type);
-        g_free(prop);
-    }
-}
-
-static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
-{
-    DeviceProperty *prop;
-
-    QTAILQ_FOREACH(prop, &dev->properties, node) {
-        if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
-            break;
-        }
-    }
-
-    g_assert(prop != NULL);
-
-    QTAILQ_REMOVE(&dev->properties, prop, node);
-
-    if (prop->release) {
-        prop->release(dev, prop->name, prop->opaque);
-    }
-
-    g_free(prop->name);
-    g_free(prop->type);
-    g_free(prop);
-}
-
 /* Unlink device from bus and free the structure.  */
 void qdev_free(DeviceState *dev)
 {
-    BusState *bus;
-    Property *prop;
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
-    qdev_property_del_all(dev);
-
-    if (dev->state == DEV_STATE_INITIALIZED) {
-        while (dev->num_child_bus) {
-            bus = QLIST_FIRST(&dev->child_bus);
-            qbus_free(bus);
-        }
-        if (qdev_get_vmsd(dev)) {
-            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
-        }
-        if (dc->exit) {
-            dc->exit(dev);
-        }
-        if (dev->opts) {
-            qemu_opts_del(dev->opts);
-        }
-    }
-    QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
-    for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
-        if (prop->info->free) {
-            prop->info->free(dev, prop);
-        }
-    }
-    if (dev->parent) {
-        qdev_property_del_child(dev->parent, dev, NULL);
-    }
-    if (dev->ref != 0) {
-        qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
-    }
     object_delete(OBJECT(dev));
 }
 
@@ -343,9 +285,9 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
 
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
 {
-    assert(dev->num_gpio_in == 0);
-    dev->num_gpio_in = n;
-    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
+    dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
+                                        dev, n);
+    dev->num_gpio_in += n;
 }
 
 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
@@ -370,12 +312,10 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
 {
     qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
-    if (nd->vlan)
-        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
     if (nd->netdev)
         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
-        qdev_prop_exists(dev, "vectors")) {
+        object_property_find(OBJECT(dev), "vectors", NULL)) {
         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
     }
     nd->instantiated = 1;
@@ -396,7 +336,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
 int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque)
 {
-    DeviceState *dev;
+    BusChild *kid;
     int err;
 
     if (busfn) {
@@ -406,8 +346,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
         }
     }
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
-        err = qdev_walk_children(dev, devfn, busfn, opaque);
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        err = qdev_walk_children(kid->child, devfn, busfn, opaque);
         if (err < 0) {
             return err;
         }
@@ -441,12 +381,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
 
 DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {
-    DeviceState *dev, *ret;
+    BusChild *kid;
+    DeviceState *ret;
     BusState *child;
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
-        if (dev->id && strcmp(dev->id, id) == 0)
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+
+        if (dev->id && strcmp(dev->id, id) == 0) {
             return dev;
+        }
+
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
             ret = qdev_find_recursive(child, id);
             if (ret) {
@@ -457,84 +402,87 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
     return NULL;
 }
 
-void qbus_create_inplace(BusState *bus, BusInfo *info,
-                         DeviceState *parent, const char *name)
+static void qbus_realize(BusState *bus)
 {
+    const char *typename = object_get_typename(OBJECT(bus));
     char *buf;
     int i,len;
 
-    bus->info = info;
-    bus->parent = parent;
-
-    if (name) {
+    if (bus->name) {
         /* use supplied name */
-        bus->name = g_strdup(name);
-    } else if (parent && parent->id) {
+    } else if (bus->parent && bus->parent->id) {
         /* parent device has id -> use it for bus name */
-        len = strlen(parent->id) + 16;
+        len = strlen(bus->parent->id) + 16;
         buf = g_malloc(len);
-        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
+        snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
         bus->name = buf;
     } else {
         /* no id -> use lowercase bus type for bus name */
-        len = strlen(info->name) + 16;
+        len = strlen(typename) + 16;
         buf = g_malloc(len);
-        len = snprintf(buf, len, "%s.%d", info->name,
-                       parent ? parent->num_child_bus : 0);
+        len = snprintf(buf, len, "%s.%d", typename,
+                       bus->parent ? bus->parent->num_child_bus : 0);
         for (i = 0; i < len; i++)
             buf[i] = qemu_tolower(buf[i]);
         bus->name = buf;
     }
 
-    QTAILQ_INIT(&bus->children);
-    if (parent) {
-        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
-        parent->num_child_bus++;
-    } else if (bus != main_system_bus) {
+    if (bus->parent) {
+        QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
+        bus->parent->num_child_bus++;
+        object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
+    } else if (bus != sysbus_get_default()) {
         /* TODO: once all bus devices are qdevified,
            only reset handler for main_system_bus should be registered here. */
         qemu_register_reset(qbus_reset_all_fn, bus);
     }
 }
 
-BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
+void qbus_create_inplace(BusState *bus, const char *typename,
+                         DeviceState *parent, const char *name)
 {
-    BusState *bus;
+    object_initialize(bus, typename);
 
-    bus = g_malloc0(info->size);
-    bus->qdev_allocated = 1;
-    qbus_create_inplace(bus, info, parent, name);
-    return bus;
+    bus->parent = parent;
+    bus->name = name ? g_strdup(name) : NULL;
+    qbus_realize(bus);
 }
 
-static void main_system_bus_create(void)
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
 {
-    /* assign main_system_bus before qbus_create_inplace()
-     * in order to make "if (bus != main_system_bus)" work */
-    main_system_bus = g_malloc0(system_bus_info.size);
-    main_system_bus->qdev_allocated = 1;
-    qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
-                        "main-system-bus");
+    BusState *bus;
+
+    bus = BUS(object_new(typename));
+    bus->qom_allocated = true;
+
+    bus->parent = parent;
+    bus->name = name ? g_strdup(name) : NULL;
+    qbus_realize(bus);
+
+    return bus;
 }
 
 void qbus_free(BusState *bus)
 {
-    DeviceState *dev;
-
-    while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
-        qdev_free(dev);
-    }
-    if (bus->parent) {
-        QLIST_REMOVE(bus, sibling);
-        bus->parent->num_child_bus--;
+    if (bus->qom_allocated) {
+        object_delete(OBJECT(bus));
     } else {
-        assert(bus != main_system_bus); /* main_system_bus is never freed */
-        qemu_unregister_reset(qbus_reset_all_fn, bus);
+        object_finalize(OBJECT(bus));
+        if (bus->glib_allocated) {
+            g_free(bus);
+        }
     }
-    g_free((void*)bus->name);
-    if (bus->qdev_allocated) {
-        g_free(bus);
+}
+
+static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->get_fw_dev_path) {
+        return bc->get_fw_dev_path(dev);
     }
+
+    return NULL;
 }
 
 static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
@@ -544,8 +492,8 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
     if (dev && dev->parent_bus) {
         char *d;
         l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
-        if (dev->parent_bus->info->get_fw_dev_path) {
-            d = dev->parent_bus->info->get_fw_dev_path(dev);
+        d = bus_get_fw_dev_path(dev->parent_bus, dev);
+        if (d) {
             l += snprintf(p + l, size - l, "%s", d);
             g_free(d);
         } else {
@@ -566,109 +514,33 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
 
     path[l-1] = '\0';
 
-    return strdup(path);
-}
-
-char *qdev_get_type(DeviceState *dev, Error **errp)
-{
-    return g_strdup(object_get_typename(OBJECT(dev)));
-}
-
-void qdev_ref(DeviceState *dev)
-{
-    dev->ref++;
-}
-
-void qdev_unref(DeviceState *dev)
-{
-    g_assert(dev->ref > 0);
-    dev->ref--;
-}
-
-void qdev_property_add(DeviceState *dev, const char *name, const char *type,
-                       DevicePropertyAccessor *get, DevicePropertyAccessor *set,
-                       DevicePropertyRelease *release,
-                       void *opaque, Error **errp)
-{
-    DeviceProperty *prop = g_malloc0(sizeof(*prop));
-
-    prop->name = g_strdup(name);
-    prop->type = g_strdup(type);
-
-    prop->get = get;
-    prop->set = set;
-    prop->release = release;
-    prop->opaque = opaque;
-
-    QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
-}
-
-static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
-{
-    DeviceProperty *prop;
-
-    QTAILQ_FOREACH(prop, &dev->properties, node) {
-        if (strcmp(prop->name, name) == 0) {
-            return prop;
-        }
-    }
-
-    return NULL;
+    return g_strdup(path);
 }
 
-void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
-                       Error **errp)
+char *qdev_get_dev_path(DeviceState *dev)
 {
-    DeviceProperty *prop = qdev_property_find(dev, name);
+    BusClass *bc;
 
-    if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
-        return;
-    }
-
-    if (!prop->get) {
-        error_set(errp, QERR_PERMISSION_DENIED);
-    } else {
-        prop->get(dev, v, prop->opaque, name, errp);
-    }
-}
-
-void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
-                       Error **errp)
-{
-    DeviceProperty *prop = qdev_property_find(dev, name);
-
-    if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
-        return;
+    if (!dev || !dev->parent_bus) {
+        return NULL;
     }
 
-    if (!prop->set) {
-        error_set(errp, QERR_PERMISSION_DENIED);
-    } else {
-        prop->set(dev, v, prop->opaque, name, errp);
+    bc = BUS_GET_CLASS(dev->parent_bus);
+    if (bc->get_dev_path) {
+        return bc->get_dev_path(dev);
     }
-}
 
-const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
-{
-    DeviceProperty *prop = qdev_property_find(dev, name);
-
-    if (prop == NULL) {
-        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
-        return NULL;
-    }
-
-    return prop->type;
+    return NULL;
 }
 
 /**
  * Legacy property handling
  */
 
-static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
                                      const char *name, Error **errp)
 {
+    DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
 
     char buffer[1024];
@@ -678,9 +550,10 @@ static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
     visit_type_str(v, &ptr, name, errp);
 }
 
-static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
                                      const char *name, Error **errp)
 {
+    DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
     Error *local_err = NULL;
     char *ptr = NULL;
@@ -708,23 +581,29 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
  * Do not use this is new code!  Properties added through this interface will
  * be given names and types in the "legacy" namespace.
  *
- * Legacy properties are always processed as strings.  The format of the string
- * depends on the property type.
+ * Legacy properties are string versions of other OOM properties.  The format
+ * of the string depends on the property type.
  */
 void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                               Error **errp)
 {
     gchar *name, *type;
 
+    /* Register pointer properties as legacy properties */
+    if (!prop->info->print && !prop->info->parse &&
+        (prop->info->set || prop->info->get)) {
+        return;
+    }
+
     name = g_strdup_printf("legacy-%s", prop->name);
     type = g_strdup_printf("legacy<%s>",
                            prop->info->legacy_name ?: prop->info->name);
 
-    qdev_property_add(dev, name, type,
-                      prop->info->print ? qdev_get_legacy_property : NULL,
-                      prop->info->parse ? qdev_set_legacy_property : NULL,
-                      NULL,
-                      prop, errp);
+    object_property_add(OBJECT(dev), name, type,
+                        prop->info->print ? qdev_get_legacy_property : prop->info->get,
+                        prop->info->parse ? qdev_set_legacy_property : prop->info->set,
+                        NULL,
+                        prop, errp);
 
     g_free(type);
     g_free(name);
@@ -739,379 +618,178 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 void qdev_property_add_static(DeviceState *dev, Property *prop,
                               Error **errp)
 {
-    qdev_property_add(dev, prop->name, prop->info->name,
-                      prop->info->get, prop->info->set,
-                      NULL,
-                      prop, errp);
-}
-
-DeviceState *qdev_get_root(void)
-{
-    static DeviceState *qdev_root;
-
-    if (!qdev_root) {
-        qdev_root = qdev_create(NULL, "container");
-        qdev_init_nofail(qdev_root);
-    }
-
-    return qdev_root;
-}
-
-static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
-                                    const char *name, Error **errp)
-{
-    DeviceState *child = opaque;
-    gchar *path;
-
-    path = qdev_get_canonical_path(child);
-    visit_type_str(v, &path, name, errp);
-    g_free(path);
-}
-
-static void qdev_release_child_property(DeviceState *dev, const char *name,
-                                        void *opaque)
-{
-    DeviceState *child = opaque;
-
-    qdev_unref(child);
-}
-
-void qdev_property_add_child(DeviceState *dev, const char *name,
-                             DeviceState *child, Error **errp)
-{
-    gchar *type;
-
-    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
-
-    qdev_property_add(dev, name, type, qdev_get_child_property,
-                      NULL, qdev_release_child_property,
-                      child, errp);
-
-    qdev_ref(child);
-    g_assert(child->parent == NULL);
-    child->parent = dev;
-
-    g_free(type);
-}
-
-static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
-                                   const char *name, Error **errp)
-{
-    DeviceState **child = opaque;
-    gchar *path;
+    Error *local_err = NULL;
+    Object *obj = OBJECT(dev);
 
-    if (*child) {
-        path = qdev_get_canonical_path(*child);
-        visit_type_str(v, &path, name, errp);
-        g_free(path);
-    } else {
-        path = (gchar *)"";
-        visit_type_str(v, &path, name, errp);
+    /*
+     * TODO qdev_prop_ptr does not have getters or setters.  It must
+     * go now that it can be replaced with links.  The test should be
+     * removed along with it: all static properties are read/write.
+     */
+    if (!prop->info->get && !prop->info->set) {
+        return;
     }
-}
-
-static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
-                                   const char *name, Error **errp)
-{
-    DeviceState **child = opaque;
-    bool ambiguous = false;
-    const char *type;
-    char *path;
 
-    type = qdev_property_get_type(dev, name, NULL);
+    object_property_add(obj, prop->name, prop->info->name,
+                        prop->info->get, prop->info->set,
+                        prop->info->release,
+                        prop, &local_err);
 
-    visit_type_str(v, &path, name, errp);
-
-    if (*child) {
-        qdev_unref(*child);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
     }
-
-    if (strcmp(path, "") != 0) {
-        DeviceState *target;
-
-        target = qdev_resolve_path(path, &ambiguous);
-        if (target) {
-            gchar *target_type;
-
-            target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
-            if (strcmp(target_type, type) == 0) {
-                *child = target;
-                qdev_ref(target);
-            } else {
-                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
-            }
-
-            g_free(target_type);
-        } else {
-            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
-        }
-    } else {
-        *child = NULL;
+    if (prop->qtype == QTYPE_NONE) {
+        return;
     }
 
-    g_free(path);
-}
-
-void qdev_property_add_link(DeviceState *dev, const char *name,
-                            const char *type, DeviceState **child,
-                            Error **errp)
-{
-    gchar *full_type;
-
-    full_type = g_strdup_printf("link<%s>", type);
-
-    qdev_property_add(dev, name, full_type,
-                      qdev_get_link_property,
-                      qdev_set_link_property,
-                      NULL, child, errp);
-
-    g_free(full_type);
-}
-
-gchar *qdev_get_canonical_path(DeviceState *dev)
-{
-    DeviceState *root = qdev_get_root();
-    char *newpath = NULL, *path = NULL;
-
-    while (dev != root) {
-        DeviceProperty *prop = NULL;
-
-        g_assert(dev->parent != NULL);
-
-        QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
-            if (!strstart(prop->type, "child<", NULL)) {
-                continue;
-            }
-
-            if (prop->opaque == dev) {
-                if (path) {
-                    newpath = g_strdup_printf("%s/%s", prop->name, path);
-                    g_free(path);
-                    path = newpath;
-                } else {
-                    path = g_strdup(prop->name);
-                }
-                break;
-            }
-        }
-
-        g_assert(prop != NULL);
-
-        dev = dev->parent;
+    if (prop->qtype == QTYPE_QBOOL) {
+        object_property_set_bool(obj, prop->defval, prop->name, &local_err);
+    } else if (prop->info->enum_table) {
+        object_property_set_str(obj, prop->info->enum_table[prop->defval],
+                                prop->name, &local_err);
+    } else if (prop->qtype == QTYPE_QINT) {
+        object_property_set_int(obj, prop->defval, prop->name, &local_err);
     }
-
-    newpath = g_strdup_printf("/%s", path);
-    g_free(path);
-
-    return newpath;
+    assert_no_error(local_err);
 }
 
-static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
-                                          gchar **parts,
-                                          int index)
+static void device_initfn(Object *obj)
 {
-    DeviceProperty *prop;
-    DeviceState *child;
-
-    if (parts[index] == NULL) {
-        return parent;
-    }
+    DeviceState *dev = DEVICE(obj);
+    ObjectClass *class;
+    Property *prop;
 
-    if (strcmp(parts[index], "") == 0) {
-        return qdev_resolve_abs_path(parent, parts, index + 1);
+    if (qdev_hotplug) {
+        dev->hotplugged = 1;
+        qdev_hot_added = true;
     }
 
-    prop = qdev_property_find(parent, parts[index]);
-    if (prop == NULL) {
-        return NULL;
-    }
+    dev->instance_id_alias = -1;
+    dev->state = DEV_STATE_CREATED;
 
-    child = NULL;
-    if (strstart(prop->type, "link<", NULL)) {
-        DeviceState **pchild = prop->opaque;
-        if (*pchild) {
-            child = *pchild;
+    class = object_get_class(OBJECT(dev));
+    do {
+        for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
+            qdev_property_add_legacy(dev, prop, NULL);
+            qdev_property_add_static(dev, prop, NULL);
         }
-    } else if (strstart(prop->type, "child<", NULL)) {
-        child = prop->opaque;
-    }
-
-    if (!child) {
-        return NULL;
-    }
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+    qdev_prop_set_globals(dev);
 
-    return qdev_resolve_abs_path(child, parts, index + 1);
+    object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
+                             (Object **)&dev->parent_bus, NULL);
 }
 
-static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
-                                              gchar **parts,
-                                              bool *ambiguous)
+/* Unlink device from bus and free the structure.  */
+static void device_finalize(Object *obj)
 {
-    DeviceState *dev;
-    DeviceProperty *prop;
-
-    dev = qdev_resolve_abs_path(parent, parts, 0);
-
-    QTAILQ_FOREACH(prop, &parent->properties, node) {
-        DeviceState *found;
+    DeviceState *dev = DEVICE(obj);
+    BusState *bus;
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
-        if (!strstart(prop->type, "child<", NULL)) {
-            continue;
+    if (dev->state == DEV_STATE_INITIALIZED) {
+        while (dev->num_child_bus) {
+            bus = QLIST_FIRST(&dev->child_bus);
+            qbus_free(bus);
         }
-
-        found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
-        if (found) {
-            if (dev) {
-                if (ambiguous) {
-                    *ambiguous = true;
-                }
-                return NULL;
-            }
-            dev = found;
+        if (qdev_get_vmsd(dev)) {
+            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
         }
-
-        if (ambiguous && *ambiguous) {
-            return NULL;
+        if (dc->exit) {
+            dc->exit(dev);
+        }
+        if (dev->opts) {
+            qemu_opts_del(dev->opts);
         }
     }
-
-    return dev;
+    if (dev->parent_bus) {
+        bus_remove_child(dev->parent_bus, dev);
+    }
 }
 
-DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
+static void device_class_base_init(ObjectClass *class, void *data)
 {
-    bool partial_path = true;
-    DeviceState *dev;
-    gchar **parts;
-
-    parts = g_strsplit(path, "/", 0);
-    if (parts == NULL || parts[0] == NULL) {
-        g_strfreev(parts);
-        return qdev_get_root();
-    }
+    DeviceClass *klass = DEVICE_CLASS(class);
 
-    if (strcmp(parts[0], "") == 0) {
-        partial_path = false;
-    }
-
-    if (partial_path) {
-        if (ambiguous) {
-            *ambiguous = false;
-        }
-        dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
-    } else {
-        dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
-    }
-
-    g_strfreev(parts);
-
-    return dev;
+    /* We explicitly look up properties in the superclasses,
+     * so do not propagate them to the subclasses.
+     */
+    klass->props = NULL;
 }
 
-typedef struct StringProperty
-{
-    char *(*get)(DeviceState *, Error **);
-    void (*set)(DeviceState *, const char *, Error **);
-} StringProperty;
-
-static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
-                                  const char *name, Error **errp)
+void device_reset(DeviceState *dev)
 {
-    StringProperty *prop = opaque;
-    char *value;
+    DeviceClass *klass = DEVICE_GET_CLASS(dev);
 
-    value = prop->get(dev, errp);
-    if (value) {
-        visit_type_str(v, &value, name, errp);
-        g_free(value);
+    if (klass->reset) {
+        klass->reset(dev);
     }
 }
 
-static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
-                                  const char *name, Error **errp)
+Object *qdev_get_machine(void)
 {
-    StringProperty *prop = opaque;
-    char *value;
-    Error *local_err = NULL;
+    static Object *dev;
 
-    visit_type_str(v, &value, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
+    if (dev == NULL) {
+        dev = container_get(object_get_root(), "/machine");
     }
 
-    prop->set(dev, value, errp);
-    g_free(value);
+    return dev;
 }
 
-static void qdev_property_release_str(DeviceState *dev, const char *name,
-                                      void *opaque)
-{
-    StringProperty *prop = opaque;
-    g_free(prop);
-}
+static TypeInfo device_type_info = {
+    .name = TYPE_DEVICE,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(DeviceState),
+    .instance_init = device_initfn,
+    .instance_finalize = device_finalize,
+    .class_base_init = device_class_base_init,
+    .abstract = true,
+    .class_size = sizeof(DeviceClass),
+};
 
-void qdev_property_add_str(DeviceState *dev, const char *name,
-                           char *(*get)(DeviceState *, Error **),
-                           void (*set)(DeviceState *, const char *, Error **),
-                           Error **errp)
+static void qbus_initfn(Object *obj)
 {
-    StringProperty *prop = g_malloc0(sizeof(*prop));
+    BusState *bus = BUS(obj);
 
-    prop->get = get;
-    prop->set = set;
-
-    qdev_property_add(dev, name, "string",
-                      get ? qdev_property_get_str : NULL,
-                      set ? qdev_property_set_str : NULL,
-                      qdev_property_release_str,
-                      prop, errp);
+    QTAILQ_INIT(&bus->children);
 }
 
-static void device_initfn(Object *obj)
+static void qbus_finalize(Object *obj)
 {
-    DeviceState *dev = DEVICE(obj);
-    Property *prop;
-
-    if (qdev_hotplug) {
-        dev->hotplugged = 1;
-        qdev_hot_added = true;
-    }
-
-    dev->instance_id_alias = -1;
-    QTAILQ_INIT(&dev->properties);
-    dev->state = DEV_STATE_CREATED;
+    BusState *bus = BUS(obj);
+    BusChild *kid;
 
-    qdev_prop_set_defaults(dev, qdev_get_props(dev));
-    for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
-        qdev_property_add_legacy(dev, prop, NULL);
-        qdev_property_add_static(dev, prop, NULL);
+    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
+        DeviceState *dev = kid->child;
+        qdev_free(dev);
     }
-
-    qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
-}
-
-void device_reset(DeviceState *dev)
-{
-    DeviceClass *klass = DEVICE_GET_CLASS(dev);
-
-    if (klass->reset) {
-        klass->reset(dev);
+    if (bus->parent) {
+        QLIST_REMOVE(bus, sibling);
+        bus->parent->num_child_bus--;
+    } else {
+        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+        qemu_unregister_reset(qbus_reset_all_fn, bus);
     }
+    g_free((char *)bus->name);
 }
 
-static TypeInfo device_type_info = {
-    .name = TYPE_DEVICE,
+static const TypeInfo bus_info = {
+    .name = TYPE_BUS,
     .parent = TYPE_OBJECT,
-    .instance_size = sizeof(DeviceState),
-    .instance_init = device_initfn,
+    .instance_size = sizeof(BusState),
     .abstract = true,
-    .class_size = sizeof(DeviceClass),
+    .class_size = sizeof(BusClass),
+    .instance_init = qbus_initfn,
+    .instance_finalize = qbus_finalize,
 };
 
-static void init_qdev(void)
+static void qdev_register_types(void)
 {
+    type_register_static(&bus_info);
     type_register_static(&device_type_info);
 }
 
-device_init(init_qdev);
+type_init(qdev_register_types)
This page took 0.063859 seconds and 4 git commands to generate.