aboutsummaryrefslogtreecommitdiff
path: root/hw/qdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/qdev.c')
-rw-r--r--hw/qdev.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index 3bc9166814..49d26a28b3 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -45,6 +45,17 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
static BusState *qbus_find(const char *path);
/* Register a new device type. */
+static void qdev_subclass_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->info = data;
+}
+
+DeviceInfo *qdev_get_info(DeviceState *dev)
+{
+ return DEVICE_GET_CLASS(dev)->info;
+}
+
void qdev_register(DeviceInfo *info)
{
TypeInfo type_info = {};
@@ -55,6 +66,8 @@ void qdev_register(DeviceInfo *info)
type_info.name = info->name;
type_info.parent = TYPE_DEVICE;
type_info.instance_size = info->size;
+ type_info.class_init = qdev_subclass_init;
+ type_info.class_data = info;
type_register_static(&type_info);
@@ -102,9 +115,8 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
assert(bus->info == info->bus_info);
dev = DEVICE(object_new(info->name));
- dev->info = info;
dev->parent_bus = bus;
- qdev_prop_set_defaults(dev, dev->info->props);
+ qdev_prop_set_defaults(dev, qdev_get_info(dev)->props);
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
qdev_prop_set_globals(dev);
QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
@@ -117,12 +129,12 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
QTAILQ_INIT(&dev->properties);
dev->state = DEV_STATE_CREATED;
- for (prop = dev->info->props; prop && prop->name; prop++) {
+ for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
- for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
+ for (prop = qdev_get_info(dev)->bus_info->props; prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
@@ -355,19 +367,19 @@ int qdev_init(DeviceState *dev)
int rc;
assert(dev->state == DEV_STATE_CREATED);
- rc = dev->info->init(dev, dev->info);
+ rc = qdev_get_info(dev)->init(dev, qdev_get_info(dev));
if (rc < 0) {
qdev_free(dev);
return rc;
}
- if (dev->info->vmsd) {
- vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
+ if (qdev_get_info(dev)->vmsd) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_info(dev)->vmsd, dev,
dev->instance_id_alias,
dev->alias_required_for_version);
}
dev->state = DEV_STATE_INITIALIZED;
- if (dev->hotplugged && dev->info->reset) {
- dev->info->reset(dev);
+ if (dev->hotplugged && qdev_get_info(dev)->reset) {
+ qdev_get_info(dev)->reset(dev);
}
return 0;
}
@@ -386,17 +398,17 @@ int qdev_unplug(DeviceState *dev)
qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
return -1;
}
- assert(dev->info->unplug != NULL);
+ assert(qdev_get_info(dev)->unplug != NULL);
qdev_hot_removed = true;
- return dev->info->unplug(dev);
+ return qdev_get_info(dev)->unplug(dev);
}
static int qdev_reset_one(DeviceState *dev, void *opaque)
{
- if (dev->info->reset) {
- dev->info->reset(dev);
+ if (qdev_get_info(dev)->reset) {
+ qdev_get_info(dev)->reset(dev);
}
return 0;
@@ -447,7 +459,7 @@ int qdev_simple_unplug_cb(DeviceState *dev)
way is somewhat unclean, and best avoided. */
void qdev_init_nofail(DeviceState *dev)
{
- DeviceInfo *info = dev->info;
+ DeviceInfo *info = qdev_get_info(dev);
if (qdev_init(dev) < 0) {
error_report("Initialization of device %s failed", info->name);
@@ -508,15 +520,15 @@ void qdev_free(DeviceState *dev)
bus = QLIST_FIRST(&dev->child_bus);
qbus_free(bus);
}
- if (dev->info->vmsd)
- vmstate_unregister(dev, dev->info->vmsd, dev);
- if (dev->info->exit)
- dev->info->exit(dev);
+ if (qdev_get_info(dev)->vmsd)
+ vmstate_unregister(dev, qdev_get_info(dev)->vmsd, dev);
+ if (qdev_get_info(dev)->exit)
+ qdev_get_info(dev)->exit(dev);
if (dev->opts)
qemu_opts_del(dev->opts);
}
QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
- for (prop = dev->info->props; prop && prop->name; prop++) {
+ for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
if (prop->info->free) {
prop->info->free(dev, prop);
}
@@ -708,7 +720,7 @@ static void qbus_list_bus(DeviceState *dev)
const char *sep = " ";
error_printf("child busses at \"%s\":",
- dev->id ? dev->id : dev->info->name);
+ dev->id ? dev->id : qdev_get_info(dev)->name);
QLIST_FOREACH(child, &dev->child_bus, sibling) {
error_printf("%s\"%s\"", sep, child->name);
sep = ", ";
@@ -723,7 +735,7 @@ static void qbus_list_dev(BusState *bus)
error_printf("devices at \"%s\":", bus->name);
QTAILQ_FOREACH(dev, &bus->children, sibling) {
- error_printf("%s\"%s\"", sep, dev->info->name);
+ error_printf("%s\"%s\"", sep, qdev_get_info(dev)->name);
if (dev->id)
error_printf("/\"%s\"", dev->id);
sep = ", ";
@@ -759,12 +771,12 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
}
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (strcmp(dev->info->name, elem) == 0) {
+ if (strcmp(qdev_get_info(dev)->name, elem) == 0) {
return dev;
}
}
QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
+ if (qdev_get_info(dev)->alias && strcmp(qdev_get_info(dev)->alias, elem) == 0) {
return dev;
}
}
@@ -966,7 +978,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
{
BusState *child;
- qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
+ qdev_printf("dev: %s, id \"%s\"\n", qdev_get_info(dev)->name,
dev->id ? dev->id : "");
indent += 2;
if (dev->num_gpio_in) {
@@ -975,7 +987,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
if (dev->num_gpio_out) {
qdev_printf("gpio-out %d\n", dev->num_gpio_out);
}
- qdev_print_props(mon, dev, dev->info->props, "dev", indent);
+ qdev_print_props(mon, dev, qdev_get_info(dev)->props, "dev", indent);
qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
if (dev->parent_bus->info->print_dev)
dev->parent_bus->info->print_dev(mon, dev, indent);
@@ -1056,7 +1068,7 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
l += snprintf(p + l, size - l, "%s", d);
g_free(d);
} else {
- l += snprintf(p + l, size - l, "%s", dev->info->name);
+ l += snprintf(p + l, size - l, "%s", qdev_get_info(dev)->name);
}
}
l += snprintf(p + l , size - l, "/");
@@ -1078,7 +1090,7 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
char *qdev_get_type(DeviceState *dev, Error **errp)
{
- return g_strdup(dev->info->name);
+ return g_strdup(qdev_get_info(dev)->name);
}
void qdev_ref(DeviceState *dev)
@@ -1288,7 +1300,7 @@ void qdev_property_add_child(DeviceState *dev, const char *name,
{
gchar *type;
- type = g_strdup_printf("child<%s>", child->info->name);
+ type = g_strdup_printf("child<%s>", qdev_get_info(child)->name);
qdev_property_add(dev, name, type, qdev_get_child_property,
NULL, qdev_release_child_property,
@@ -1340,7 +1352,7 @@ static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
if (target) {
gchar *target_type;
- target_type = g_strdup_printf("link<%s>", target->info->name);
+ target_type = g_strdup_printf("link<%s>", qdev_get_info(target)->name);
if (strcmp(target_type, type) == 0) {
*child = target;
qdev_ref(target);