aboutsummaryrefslogtreecommitdiff
path: root/hw/qdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/qdev.c')
-rw-r--r--hw/qdev.c491
1 files changed, 17 insertions, 474 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index 0692a21fbd..8f13e49170 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -222,6 +222,7 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
+ object_unparent(OBJECT(dev));
qdev_free(dev);
return 0;
}
@@ -243,46 +244,6 @@ void qdev_init_nofail(DeviceState *dev)
}
}
-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)
{
@@ -290,8 +251,6 @@ void qdev_free(DeviceState *dev)
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);
@@ -313,12 +272,6 @@ void qdev_free(DeviceState *dev)
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));
}
@@ -569,106 +522,19 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
return strdup(path);
}
-char *qdev_get_type(DeviceState *dev, Error **errp)
-{
- return g_strdup(object_get_typename(OBJECT(dev)));
-}
-
-void qdev_ref(DeviceState *dev)
+static char *qdev_get_type(Object *obj, Error **errp)
{
- 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;
-}
-
-void qdev_property_get(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 (!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 (!prop->set) {
- error_set(errp, QERR_PERMISSION_DENIED);
- } else {
- prop->set(dev, v, prop->opaque, name, errp);
- }
-}
-
-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 g_strdup(object_get_typename(obj));
}
/**
* 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 +544,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;
@@ -720,11 +587,11 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
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 : NULL,
+ prop->info->parse ? qdev_set_legacy_property : NULL,
+ NULL,
+ prop, errp);
g_free(type);
g_free(name);
@@ -739,333 +606,10 @@ 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;
-
- 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);
- }
-}
-
-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);
-
- visit_type_str(v, &path, name, errp);
-
- if (*child) {
- qdev_unref(*child);
- }
-
- 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;
- }
-
- 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;
- }
-
- newpath = g_strdup_printf("/%s", path);
- g_free(path);
-
- return newpath;
-}
-
-static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
- gchar **parts,
- int index)
-{
- DeviceProperty *prop;
- DeviceState *child;
-
- if (parts[index] == NULL) {
- return parent;
- }
-
- if (strcmp(parts[index], "") == 0) {
- return qdev_resolve_abs_path(parent, parts, index + 1);
- }
-
- prop = qdev_property_find(parent, parts[index]);
- if (prop == NULL) {
- return NULL;
- }
-
- child = NULL;
- if (strstart(prop->type, "link<", NULL)) {
- DeviceState **pchild = prop->opaque;
- if (*pchild) {
- child = *pchild;
- }
- } else if (strstart(prop->type, "child<", NULL)) {
- child = prop->opaque;
- }
-
- if (!child) {
- return NULL;
- }
-
- return qdev_resolve_abs_path(child, parts, index + 1);
-}
-
-static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
- gchar **parts,
- bool *ambiguous)
-{
- DeviceState *dev;
- DeviceProperty *prop;
-
- dev = qdev_resolve_abs_path(parent, parts, 0);
-
- QTAILQ_FOREACH(prop, &parent->properties, node) {
- DeviceState *found;
-
- if (!strstart(prop->type, "child<", NULL)) {
- continue;
- }
-
- found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
- if (found) {
- if (dev) {
- if (ambiguous) {
- *ambiguous = true;
- }
- return NULL;
- }
- dev = found;
- }
-
- if (ambiguous && *ambiguous) {
- return NULL;
- }
- }
-
- return dev;
-}
-
-DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
-{
- 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();
- }
-
- 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;
-}
-
-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)
-{
- StringProperty *prop = opaque;
- char *value;
-
- value = prop->get(dev, errp);
- if (value) {
- visit_type_str(v, &value, name, errp);
- g_free(value);
- }
-}
-
-static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- StringProperty *prop = opaque;
- char *value;
- Error *local_err = NULL;
-
- visit_type_str(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- prop->set(dev, value, errp);
- g_free(value);
-}
-
-static void qdev_property_release_str(DeviceState *dev, const char *name,
- void *opaque)
-{
- StringProperty *prop = opaque;
- g_free(prop);
-}
-
-void qdev_property_add_str(DeviceState *dev, const char *name,
- char *(*get)(DeviceState *, Error **),
- void (*set)(DeviceState *, const char *, Error **),
- Error **errp)
-{
- StringProperty *prop = g_malloc0(sizeof(*prop));
-
- 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);
+ object_property_add(OBJECT(dev), prop->name, prop->info->name,
+ prop->info->get, prop->info->set,
+ NULL,
+ prop, errp);
}
static void device_initfn(Object *obj)
@@ -1079,7 +623,6 @@ static void device_initfn(Object *obj)
}
dev->instance_id_alias = -1;
- QTAILQ_INIT(&dev->properties);
dev->state = DEV_STATE_CREATED;
qdev_prop_set_defaults(dev, qdev_get_props(dev));
@@ -1088,7 +631,7 @@ static void device_initfn(Object *obj)
qdev_property_add_static(dev, prop, NULL);
}
- qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
+ object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
}
void device_reset(DeviceState *dev)