From: Anthony Liguori <anthony@codemonkey.ws>
To: Eduardo Habkost <ehabkost@redhat.com>, qemu-devel@nongnu.org
Cc: blauwirbel@gmail.com, "Igor Mammedov" <imammedo@redhat.com>,
riku.voipio@iki.fi, "Andreas Färber" <afaerber@suse.de>,
peter.maydell@linaro.org
Subject: Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
Date: Wed, 17 Oct 2012 13:11:41 -0500 [thread overview]
Message-ID: <87y5j5t1cy.fsf@codemonkey.ws> (raw)
In-Reply-To: <1350414523-8117-12-git-send-email-ehabkost@redhat.com>
Eduardo Habkost <ehabkost@redhat.com> writes:
> The code depends on some functions from qemu-option.o, so add
> qemu-option.o to universal-obj-y to make sure it's included.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Makefile.objs | 3 +
> hw/Makefile.objs | 2 +-
> hw/qdev-core.c | 727 -------------------------------------
> hw/qdev-properties.c | 963 --------------------------------------------------
> qom/Makefile.objs | 2 +-
> qom/qdev-core.c | 727 +++++++++++++++++++++++++++++++++++++
> qom/qdev-properties.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 1695 insertions(+), 1692 deletions(-)
> delete mode 100644 hw/qdev-core.c
> delete mode 100644 hw/qdev-properties.c
> create mode 100644 qom/qdev-core.c
> create mode 100644 qom/qdev-properties.c
Stick the following in your .git/config:
[diff]
renames = true
It's dangerously close to bike-shedding, but i don't think qdev belongs
in qom/. It's not core infrastructure. It's the device base class and
belongs IMHO in hw/.
Regards,
Anthony Liguori
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 74b3542..fcd1336 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -16,6 +16,9 @@ universal-obj-y += $(qobject-obj-y)
> qom-obj-y = qom/
>
> universal-obj-y += $(qom-obj-y)
> +# QOM qdev-core.o requires qemu-option.o:
> +universal-obj-y += qemu-option.o
> +
>
> #######################################################################
> # oslib-obj-y is code depending on the OS (win32 vs posix)
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 70f2014..3ce38d2 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -180,7 +180,7 @@ common-obj-$(CONFIG_SD) += sd.o
> common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
> common-obj-y += bt-hci-csr.o
> common-obj-y += msmouse.o ps2.o
> -common-obj-y += qdev-core.o qdev-properties.o qdev-monitor.o
> +common-obj-y += qdev-monitor.o
> common-obj-y += qdev-system.o qdev-properties-system.o
> common-obj-$(CONFIG_BRLAPI) += baum.o
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> deleted file mode 100644
> index fbb7cb5..0000000
> --- a/hw/qdev-core.c
> +++ /dev/null
> @@ -1,727 +0,0 @@
> -/*
> - * Dynamic device configuration and creation.
> - *
> - * Copyright (c) 2009 CodeSourcery
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -/* The theory here is that it should be possible to create a machine without
> - knowledge of specific devices. Historically board init routines have
> - passed a bunch of arguments to each device, requiring the board know
> - exactly which device it is dealing with. This file provides an abstract
> - API for device configuration and initialization. Devices will generally
> - inherit from a particular bus (e.g. PCI or I2C) rather than
> - this API directly. */
> -
> -#include "hw/qdev.h"
> -#include "sysemu.h"
> -#include "error.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -int qdev_hotplug = 0;
> -static bool qdev_hot_added = false;
> -static bool qdev_hot_removed = false;
> -
> -/* vmstate handling:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> -{
> -}
> -
> -void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> -{
> -}
> -
> -/* reset handler register/unregister:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qbus_register_reset(BusState *bus)
> -{
> -}
> -
> -void GCC_WEAK qbus_unregister_reset(BusState *bus)
> -{
> -}
> -
> -const char *qdev_fw_name(DeviceState *dev)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (dc->fw_name) {
> - return dc->fw_name;
> - }
> -
> - return object_get_typename(OBJECT(dev));
> -}
> -
> -static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> - Error **errp);
> -
> -static void bus_remove_child(BusState *bus, DeviceState *child)
> -{
> - 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);
> - }
> -
> - kid->index = bus->max_index++;
> - kid->child = child;
> -
> - 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);
> -}
> -
> -/* Initialize a device. Device properties should be set before calling
> - this function. IRQs and MMIO regions should be connected/mapped after
> - calling this function.
> - On failure, destroy the device and return negative value.
> - Return 0 on success. */
> -int qdev_init(DeviceState *dev)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> - int rc;
> -
> - assert(dev->state == DEV_STATE_CREATED);
> -
> - rc = dc->init(dev);
> - if (rc < 0) {
> - 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);
> - }
> -
> - qdev_init_vmstate(dev);
> - dev->state = DEV_STATE_INITIALIZED;
> - if (dev->hotplugged) {
> - device_reset(dev);
> - }
> - return 0;
> -}
> -
> -void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> - int required_for_version)
> -{
> - assert(dev->state == DEV_STATE_CREATED);
> - dev->instance_id_alias = alias_id;
> - dev->alias_required_for_version = required_for_version;
> -}
> -
> -void qdev_unplug(DeviceState *dev, Error **errp)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (!dev->parent_bus->allow_hotplug) {
> - error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> - return;
> - }
> - assert(dc->unplug != NULL);
> -
> - qdev_hot_removed = true;
> -
> - if (dc->unplug(dev) < 0) {
> - error_set(errp, QERR_UNDEFINED_ERROR);
> - return;
> - }
> -}
> -
> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> -{
> - device_reset(dev);
> -
> - return 0;
> -}
> -
> -static int qbus_reset_one(BusState *bus, void *opaque)
> -{
> - BusClass *bc = BUS_GET_CLASS(bus);
> - if (bc->reset) {
> - return bc->reset(bus);
> - }
> - return 0;
> -}
> -
> -void qdev_reset_all(DeviceState *dev)
> -{
> - qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -void qbus_reset_all_fn(void *opaque)
> -{
> - BusState *bus = opaque;
> - qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -/* can be used as ->unplug() callback for the simple cases */
> -int qdev_simple_unplug_cb(DeviceState *dev)
> -{
> - /* just zap it */
> - qdev_free(dev);
> - return 0;
> -}
> -
> -
> -/* Like qdev_init(), but terminate program via error_report() instead of
> - returning an error value. This is okay during machine creation.
> - Don't use for hotplug, because there callers need to recover from
> - failure. Exception: if you know the device's init() callback can't
> - fail, then qdev_init_nofail() can't fail either, and is therefore
> - usable even then. But relying on the device implementation that
> - 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", typename);
> - exit(1);
> - }
> -}
> -
> -/* Unlink device from bus and free the structure. */
> -void qdev_free(DeviceState *dev)
> -{
> - object_delete(OBJECT(dev));
> -}
> -
> -void qdev_machine_creation_done(void)
> -{
> - /*
> - * ok, initial machine setup is done, starting from now we can
> - * only create hotpluggable devices
> - */
> - qdev_hotplug = 1;
> -}
> -
> -bool qdev_machine_modified(void)
> -{
> - return qdev_hot_added || qdev_hot_removed;
> -}
> -
> -BusState *qdev_get_parent_bus(DeviceState *dev)
> -{
> - return dev->parent_bus;
> -}
> -
> -BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> -{
> - BusState *bus;
> -
> - QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> - if (strcmp(name, bus->name) == 0) {
> - return bus;
> - }
> - }
> - return NULL;
> -}
> -
> -int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> - qbus_walkerfn *busfn, void *opaque)
> -{
> - BusChild *kid;
> - int err;
> -
> - if (busfn) {
> - err = busfn(bus, opaque);
> - if (err) {
> - return err;
> - }
> - }
> -
> - QTAILQ_FOREACH(kid, &bus->children, sibling) {
> - err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> - if (err < 0) {
> - return err;
> - }
> - }
> -
> - return 0;
> -}
> -
> -int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> - qbus_walkerfn *busfn, void *opaque)
> -{
> - BusState *bus;
> - int err;
> -
> - if (devfn) {
> - err = devfn(dev, opaque);
> - if (err) {
> - return err;
> - }
> - }
> -
> - QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> - err = qbus_walk_children(bus, devfn, busfn, opaque);
> - if (err < 0) {
> - return err;
> - }
> - }
> -
> - return 0;
> -}
> -
> -DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> -{
> - BusChild *kid;
> - DeviceState *ret;
> - BusState *child;
> -
> - 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) {
> - return ret;
> - }
> - }
> - }
> - return NULL;
> -}
> -
> -static void qbus_realize(BusState *bus)
> -{
> - const char *typename = object_get_typename(OBJECT(bus));
> - char *buf;
> - int i,len;
> -
> - if (bus->name) {
> - /* use supplied name */
> - } else if (bus->parent && bus->parent->id) {
> - /* parent device has id -> use it for bus name */
> - len = strlen(bus->parent->id) + 16;
> - buf = g_malloc(len);
> - 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(typename) + 16;
> - buf = g_malloc(len);
> - 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;
> - }
> -
> - 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 {
> - qbus_register_reset(bus);
> - }
> -}
> -
> -void qbus_create_inplace(BusState *bus, const char *typename,
> - DeviceState *parent, const char *name)
> -{
> - object_initialize(bus, typename);
> -
> - bus->parent = parent;
> - bus->name = name ? g_strdup(name) : NULL;
> - qbus_realize(bus);
> -}
> -
> -BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
> -{
> - 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)
> -{
> - if (bus->qom_allocated) {
> - object_delete(OBJECT(bus));
> - } else {
> - object_finalize(OBJECT(bus));
> - if (bus->glib_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)
> -{
> - int l = 0;
> -
> - if (dev && dev->parent_bus) {
> - char *d;
> - l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> - d = bus_get_fw_dev_path(dev->parent_bus, dev);
> - if (d) {
> - l += snprintf(p + l, size - l, "%s", d);
> - g_free(d);
> - } else {
> - l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> - }
> - }
> - l += snprintf(p + l , size - l, "/");
> -
> - return l;
> -}
> -
> -char* qdev_get_fw_dev_path(DeviceState *dev)
> -{
> - char path[128];
> - int l;
> -
> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
> -
> - path[l-1] = '\0';
> -
> - return g_strdup(path);
> -}
> -
> -char *qdev_get_dev_path(DeviceState *dev)
> -{
> - BusClass *bc;
> -
> - if (!dev || !dev->parent_bus) {
> - return NULL;
> - }
> -
> - bc = BUS_GET_CLASS(dev->parent_bus);
> - if (bc->get_dev_path) {
> - return bc->get_dev_path(dev);
> - }
> -
> - return NULL;
> -}
> -
> -/**
> - * Legacy property handling
> - */
> -
> -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];
> - char *ptr = buffer;
> -
> - prop->info->print(dev, prop, buffer, sizeof(buffer));
> - visit_type_str(v, &ptr, name, errp);
> -}
> -
> -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;
> - int ret;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &ptr, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - ret = prop->info->parse(dev, prop, ptr);
> - error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> - g_free(ptr);
> -}
> -
> -/**
> - * @qdev_add_legacy_property - adds a legacy property
> - *
> - * 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 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);
> -
> - 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);
> -}
> -
> -/**
> - * @qdev_property_add_static - add a @Property to a device.
> - *
> - * Static properties access data in a struct. The actual type of the
> - * property and the field depends on the property type.
> - */
> -void qdev_property_add_static(DeviceState *dev, Property *prop,
> - Error **errp)
> -{
> - Error *local_err = NULL;
> - Object *obj = OBJECT(dev);
> -
> - /*
> - * 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;
> - }
> -
> - object_property_add(obj, prop->name, prop->info->name,
> - prop->info->get, prop->info->set,
> - prop->info->release,
> - prop, &local_err);
> -
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (prop->qtype == QTYPE_NONE) {
> - return;
> - }
> -
> - 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);
> - }
> - assert_no_error(local_err);
> -}
> -
> -static void device_initfn(Object *obj)
> -{
> - DeviceState *dev = DEVICE(obj);
> - ObjectClass *class;
> - Property *prop;
> -
> - if (qdev_hotplug) {
> - dev->hotplugged = 1;
> - qdev_hot_added = true;
> - }
> -
> - dev->instance_id_alias = -1;
> - dev->state = DEV_STATE_CREATED;
> -
> - 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);
> - }
> - class = object_class_get_parent(class);
> - } while (class != object_class_by_name(TYPE_DEVICE));
> - qdev_prop_set_globals(dev);
> -
> - object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> - (Object **)&dev->parent_bus, NULL);
> -}
> -
> -/* Unlink device from bus and free the structure. */
> -static void device_finalize(Object *obj)
> -{
> - DeviceState *dev = DEVICE(obj);
> - BusState *bus;
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (dev->state == DEV_STATE_INITIALIZED) {
> - while (dev->num_child_bus) {
> - bus = QLIST_FIRST(&dev->child_bus);
> - qbus_free(bus);
> - }
> - qdev_finalize_vmstate(dev);
> - if (dc->exit) {
> - dc->exit(dev);
> - }
> - if (dev->opts) {
> - qemu_opts_del(dev->opts);
> - }
> - }
> - if (dev->parent_bus) {
> - bus_remove_child(dev->parent_bus, dev);
> - }
> -}
> -
> -static void device_class_base_init(ObjectClass *class, void *data)
> -{
> - DeviceClass *klass = DEVICE_CLASS(class);
> -
> - /* We explicitly look up properties in the superclasses,
> - * so do not propagate them to the subclasses.
> - */
> - klass->props = NULL;
> -}
> -
> -void device_reset(DeviceState *dev)
> -{
> - DeviceClass *klass = DEVICE_GET_CLASS(dev);
> -
> - if (klass->reset) {
> - klass->reset(dev);
> - }
> -}
> -
> -Object *qdev_get_machine(void)
> -{
> - static Object *dev;
> -
> - if (dev == NULL) {
> - dev = container_get(object_get_root(), "/machine");
> - }
> -
> - return dev;
> -}
> -
> -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),
> -};
> -
> -static void qbus_initfn(Object *obj)
> -{
> - BusState *bus = BUS(obj);
> -
> - QTAILQ_INIT(&bus->children);
> -}
> -
> -static void qbus_finalize(Object *obj)
> -{
> - BusState *bus = BUS(obj);
> - BusChild *kid;
> -
> - while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> - DeviceState *dev = kid->child;
> - qdev_free(dev);
> - }
> - if (bus->parent) {
> - QLIST_REMOVE(bus, sibling);
> - bus->parent->num_child_bus--;
> - } else {
> - qbus_unregister_reset(bus);
> - }
> - g_free((char *)bus->name);
> -}
> -
> -static const TypeInfo bus_info = {
> - .name = TYPE_BUS,
> - .parent = TYPE_OBJECT,
> - .instance_size = sizeof(BusState),
> - .abstract = true,
> - .class_size = sizeof(BusClass),
> - .instance_init = qbus_initfn,
> - .instance_finalize = qbus_finalize,
> -};
> -
> -static void qdev_register_types(void)
> -{
> - type_register_static(&bus_info);
> - type_register_static(&device_type_info);
> -}
> -
> -type_init(qdev_register_types)
> diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
> deleted file mode 100644
> index 2e82cb9..0000000
> --- a/hw/qdev-properties.c
> +++ /dev/null
> @@ -1,963 +0,0 @@
> -#include "net.h"
> -#include "hw/qdev.h"
> -#include "qerror.h"
> -#include "blockdev.h"
> -#include "hw/block-common.h"
> -#include "net/hub.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> -{
> - void *ptr = dev;
> - ptr += prop->offset;
> - return ptr;
> -}
> -
> -static void get_enum(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_enum(v, ptr, prop->info->enum_table,
> - prop->info->name, prop->name, errp);
> -}
> -
> -static void set_enum(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_enum(v, ptr, prop->info->enum_table,
> - prop->info->name, prop->name, errp);
> -}
> -
> -/* Bit */
> -
> -static uint32_t qdev_get_prop_mask(Property *prop)
> -{
> - assert(prop->info == &qdev_prop_bit);
> - return 0x1 << prop->bitnr;
> -}
> -
> -static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> -{
> - uint32_t *p = qdev_get_prop_ptr(dev, props);
> - uint32_t mask = qdev_get_prop_mask(props);
> - if (val)
> - *p |= mask;
> - else
> - *p &= ~mask;
> -}
> -
> -static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint32_t *p = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
> -}
> -
> -static void get_bit(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *p = qdev_get_prop_ptr(dev, prop);
> - bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> -
> - visit_type_bool(v, &value, name, errp);
> -}
> -
> -static void set_bit(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - Error *local_err = NULL;
> - bool value;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_bool(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - bit_prop_set(dev, prop, value);
> -}
> -
> -PropertyInfo qdev_prop_bit = {
> - .name = "boolean",
> - .legacy_name = "on/off",
> - .print = print_bit,
> - .get = get_bit,
> - .set = set_bit,
> -};
> -
> -/* --- 8bit integer --- */
> -
> -static void get_uint8(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -static void set_uint8(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint8 = {
> - .name = "uint8",
> - .get = get_uint8,
> - .set = set_uint8,
> -};
> -
> -/* --- 8bit hex value --- */
> -
> -static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoul(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx8, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex8 = {
> - .name = "uint8",
> - .legacy_name = "hex8",
> - .parse = parse_hex8,
> - .print = print_hex8,
> - .get = get_uint8,
> - .set = set_uint8,
> -};
> -
> -/* --- 16bit integer --- */
> -
> -static void get_uint16(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -static void set_uint16(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint16 = {
> - .name = "uint16",
> - .get = get_uint16,
> - .set = set_uint16,
> -};
> -
> -/* --- 32bit integer --- */
> -
> -static void get_uint32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void set_uint32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void get_int32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_int32(v, ptr, name, errp);
> -}
> -
> -static void set_int32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_int32(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint32 = {
> - .name = "uint32",
> - .get = get_uint32,
> - .set = set_uint32,
> -};
> -
> -PropertyInfo qdev_prop_int32 = {
> - .name = "int32",
> - .get = get_int32,
> - .set = set_int32,
> -};
> -
> -/* --- 32bit hex value --- */
> -
> -static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoul(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx32, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex32 = {
> - .name = "uint32",
> - .legacy_name = "hex32",
> - .parse = parse_hex32,
> - .print = print_hex32,
> - .get = get_uint32,
> - .set = set_uint32,
> -};
> -
> -/* --- 64bit integer --- */
> -
> -static void get_uint64(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -static void set_uint64(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint64 = {
> - .name = "uint64",
> - .get = get_uint64,
> - .set = set_uint64,
> -};
> -
> -/* --- 64bit hex value --- */
> -
> -static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoull(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx64, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex64 = {
> - .name = "uint64",
> - .legacy_name = "hex64",
> - .parse = parse_hex64,
> - .print = print_hex64,
> - .get = get_uint64,
> - .set = set_uint64,
> -};
> -
> -/* --- string --- */
> -
> -static void release_string(Object *obj, const char *name, void *opaque)
> -{
> - Property *prop = opaque;
> - g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> -}
> -
> -static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> - if (!*ptr)
> - return snprintf(dest, len, "<null>");
> - return snprintf(dest, len, "\"%s\"", *ptr);
> -}
> -
> -static void get_string(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (!*ptr) {
> - char *str = (char *)"";
> - visit_type_str(v, &str, name, errp);
> - } else {
> - visit_type_str(v, ptr, name, errp);
> - }
> -}
> -
> -static void set_string(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - char *str;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (*ptr) {
> - g_free(*ptr);
> - }
> - *ptr = str;
> -}
> -
> -PropertyInfo qdev_prop_string = {
> - .name = "string",
> - .print = print_string,
> - .release = release_string,
> - .get = get_string,
> - .set = set_string,
> -};
> -
> -/* --- pointer --- */
> -
> -/* Not a proper property, just for dirty hacks. TODO Remove it! */
> -PropertyInfo qdev_prop_ptr = {
> - .name = "ptr",
> -};
> -
> -/* --- mac address --- */
> -
> -/*
> - * accepted syntax versions:
> - * 01:02:03:04:05:06
> - * 01-02-03-04-05-06
> - */
> -static void get_mac(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> - char buffer[2 * 6 + 5 + 1];
> - char *p = buffer;
> -
> - snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> - mac->a[0], mac->a[1], mac->a[2],
> - mac->a[3], mac->a[4], mac->a[5]);
> -
> - visit_type_str(v, &p, name, errp);
> -}
> -
> -static void set_mac(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - int i, pos;
> - char *str, *p;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> - if (!qemu_isxdigit(str[pos]))
> - goto inval;
> - if (!qemu_isxdigit(str[pos+1]))
> - goto inval;
> - if (i == 5) {
> - if (str[pos+2] != '\0')
> - goto inval;
> - } else {
> - if (str[pos+2] != ':' && str[pos+2] != '-')
> - goto inval;
> - }
> - mac->a[i] = strtol(str+pos, &p, 16);
> - }
> - g_free(str);
> - return;
> -
> -inval:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_macaddr = {
> - .name = "macaddr",
> - .get = get_mac,
> - .set = set_mac,
> -};
> -
> -/* --- lost tick policy --- */
> -
> -static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> - [LOST_TICK_DISCARD] = "discard",
> - [LOST_TICK_DELAY] = "delay",
> - [LOST_TICK_MERGE] = "merge",
> - [LOST_TICK_SLEW] = "slew",
> - [LOST_TICK_MAX] = NULL,
> -};
> -
> -QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> -
> -PropertyInfo qdev_prop_losttickpolicy = {
> - .name = "LostTickPolicy",
> - .enum_table = lost_tick_policy_table,
> - .get = get_enum,
> - .set = set_enum,
> -};
> -
> -/* --- BIOS CHS translation */
> -
> -static const char *bios_chs_trans_table[] = {
> - [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> - [BIOS_ATA_TRANSLATION_NONE] = "none",
> - [BIOS_ATA_TRANSLATION_LBA] = "lba",
> -};
> -
> -PropertyInfo qdev_prop_bios_chs_trans = {
> - .name = "bios-chs-trans",
> - .enum_table = bios_chs_trans_table,
> - .get = get_enum,
> - .set = set_enum,
> -};
> -
> -/* --- pci address --- */
> -
> -/*
> - * bus-local address, i.e. "$slot" or "$slot.$fn"
> - */
> -static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> - unsigned int slot, fn, n;
> - Error *local_err = NULL;
> - char *str;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_free(local_err);
> - local_err = NULL;
> - visit_type_int32(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - } else if (value < -1 || value > 255) {
> - error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
> - "pci_devfn");
> - } else {
> - *ptr = value;
> - }
> - return;
> - }
> -
> - if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> - fn = 0;
> - if (sscanf(str, "%x%n", &slot, &n) != 1) {
> - goto invalid;
> - }
> - }
> - if (str[n] != '\0' || fn > 7 || slot > 31) {
> - goto invalid;
> - }
> - *ptr = slot << 3 | fn;
> - g_free(str);
> - return;
> -
> -invalid:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (*ptr == -1) {
> - return snprintf(dest, len, "<unset>");
> - } else {
> - return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> - }
> -}
> -
> -PropertyInfo qdev_prop_pci_devfn = {
> - .name = "int32",
> - .legacy_name = "pci-devfn",
> - .print = print_pci_devfn,
> - .get = get_int32,
> - .set = set_pci_devfn,
> -};
> -
> -/* --- blocksize --- */
> -
> -static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - const int64_t min = 512;
> - const int64_t max = 32768;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint16(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (value < min || value > max) {
> - error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> - dev->id?:"", name, (int64_t)value, min, max);
> - return;
> - }
> -
> - /* We rely on power-of-2 blocksizes for bitmasks */
> - if ((value & (value - 1)) != 0) {
> - error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> - dev->id?:"", name, (int64_t)value);
> - return;
> - }
> -
> - *ptr = value;
> -}
> -
> -PropertyInfo qdev_prop_blocksize = {
> - .name = "blocksize",
> - .get = get_uint16,
> - .set = set_blocksize,
> -};
> -
> -/* --- pci host address --- */
> -
> -static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> - char buffer[] = "xxxx:xx:xx.x";
> - char *p = buffer;
> - int rc = 0;
> -
> - rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> - addr->domain, addr->bus, addr->slot, addr->function);
> - assert(rc == sizeof(buffer) - 1);
> -
> - visit_type_str(v, &p, name, errp);
> -}
> -
> -/*
> - * Parse [<domain>:]<bus>:<slot>.<func>
> - * if <domain> is not supplied, it's assumed to be 0.
> - */
> -static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - char *str, *p;
> - char *e;
> - unsigned long val;
> - unsigned long dom = 0, bus = 0;
> - unsigned int slot = 0, func = 0;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - p = str;
> - val = strtoul(p, &e, 16);
> - if (e == p || *e != ':') {
> - goto inval;
> - }
> - bus = val;
> -
> - p = e + 1;
> - val = strtoul(p, &e, 16);
> - if (e == p) {
> - goto inval;
> - }
> - if (*e == ':') {
> - dom = bus;
> - bus = val;
> - p = e + 1;
> - val = strtoul(p, &e, 16);
> - if (e == p) {
> - goto inval;
> - }
> - }
> - slot = val;
> -
> - if (*e != '.') {
> - goto inval;
> - }
> - p = e + 1;
> - val = strtoul(p, &e, 10);
> - if (e == p) {
> - goto inval;
> - }
> - func = val;
> -
> - if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> - goto inval;
> - }
> -
> - if (*e) {
> - goto inval;
> - }
> -
> - addr->domain = dom;
> - addr->bus = bus;
> - addr->slot = slot;
> - addr->function = func;
> -
> - g_free(str);
> - return;
> -
> -inval:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_pci_host_devaddr = {
> - .name = "pci-host-devaddr",
> - .get = get_pci_host_devaddr,
> - .set = set_pci_host_devaddr,
> -};
> -
> -/* --- public helpers --- */
> -
> -static Property *qdev_prop_walk(Property *props, const char *name)
> -{
> - if (!props)
> - return NULL;
> - while (props->name) {
> - if (strcmp(props->name, name) == 0)
> - return props;
> - props++;
> - }
> - return NULL;
> -}
> -
> -static Property *qdev_prop_find(DeviceState *dev, const char *name)
> -{
> - ObjectClass *class;
> - Property *prop;
> -
> - /* device properties */
> - class = object_get_class(OBJECT(dev));
> - do {
> - prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> - if (prop) {
> - return prop;
> - }
> - class = object_class_get_parent(class);
> - } while (class != object_class_by_name(TYPE_DEVICE));
> -
> - return NULL;
> -}
> -
> -void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> - Property *prop, const char *value)
> -{
> - switch (ret) {
> - case -EEXIST:
> - error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - default:
> - case -EINVAL:
> - error_set(errp, QERR_PROPERTY_VALUE_BAD,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - case -ENOENT:
> - error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - case 0:
> - break;
> - }
> -}
> -
> -int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> -{
> - char *legacy_name;
> - Error *err = NULL;
> -
> - legacy_name = g_strdup_printf("legacy-%s", name);
> - if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> - object_property_parse(OBJECT(dev), value, legacy_name, &err);
> - } else {
> - object_property_parse(OBJECT(dev), value, name, &err);
> - }
> - g_free(legacy_name);
> -
> - if (err) {
> - qerror_report_err(err);
> - error_free(err);
> - return -1;
> - }
> - return 0;
> -}
> -
> -void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> -{
> - Error *errp = NULL;
> - object_property_set_bool(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
> -{
> - Error *errp = NULL;
> - object_property_set_str(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
> -{
> - Error *errp = NULL;
> - char str[2 * 6 + 5 + 1];
> - snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> - value[0], value[1], value[2], value[3], value[4], value[5]);
> -
> - object_property_set_str(OBJECT(dev), str, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> -{
> - Property *prop;
> - Error *errp = NULL;
> -
> - prop = qdev_prop_find(dev, name);
> - object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> - name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> -{
> - Property *prop;
> - void **ptr;
> -
> - prop = qdev_prop_find(dev, name);
> - assert(prop && prop->info == &qdev_prop_ptr);
> - ptr = qdev_get_prop_ptr(dev, prop);
> - *ptr = value;
> -}
> -
> -static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
> -
> -void qdev_prop_register_global(GlobalProperty *prop)
> -{
> - QTAILQ_INSERT_TAIL(&global_props, prop, next);
> -}
> -
> -void qdev_prop_register_global_list(GlobalProperty *props)
> -{
> - int i;
> -
> - for (i = 0; props[i].driver != NULL; i++) {
> - qdev_prop_register_global(props+i);
> - }
> -}
> -
> -void qdev_prop_set_globals(DeviceState *dev)
> -{
> - ObjectClass *class = object_get_class(OBJECT(dev));
> -
> - do {
> - GlobalProperty *prop;
> - QTAILQ_FOREACH(prop, &global_props, next) {
> - if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> - continue;
> - }
> - if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> - exit(1);
> - }
> - }
> - class = object_class_get_parent(class);
> - } while (class);
> -}
> -
> diff --git a/qom/Makefile.objs b/qom/Makefile.objs
> index 5ef060a..09ef871 100644
> --- a/qom/Makefile.objs
> +++ b/qom/Makefile.objs
> @@ -1,4 +1,4 @@
> qom-obj-y = object.o container.o qom-qobject.o
> -qom-obj-twice-y = cpu.o
> +qom-obj-twice-y = cpu.o qdev-core.o qdev-properties.o
> common-obj-y = $(qom-obj-twice-y)
> user-obj-y = $(qom-obj-twice-y)
> diff --git a/qom/qdev-core.c b/qom/qdev-core.c
> new file mode 100644
> index 0000000..fbb7cb5
> --- /dev/null
> +++ b/qom/qdev-core.c
> @@ -0,0 +1,727 @@
> +/*
> + * Dynamic device configuration and creation.
> + *
> + * Copyright (c) 2009 CodeSourcery
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/* The theory here is that it should be possible to create a machine without
> + knowledge of specific devices. Historically board init routines have
> + passed a bunch of arguments to each device, requiring the board know
> + exactly which device it is dealing with. This file provides an abstract
> + API for device configuration and initialization. Devices will generally
> + inherit from a particular bus (e.g. PCI or I2C) rather than
> + this API directly. */
> +
> +#include "hw/qdev.h"
> +#include "sysemu.h"
> +#include "error.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +int qdev_hotplug = 0;
> +static bool qdev_hot_added = false;
> +static bool qdev_hot_removed = false;
> +
> +/* vmstate handling:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> +{
> +}
> +
> +void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> +{
> +}
> +
> +/* reset handler register/unregister:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qbus_register_reset(BusState *bus)
> +{
> +}
> +
> +void GCC_WEAK qbus_unregister_reset(BusState *bus)
> +{
> +}
> +
> +const char *qdev_fw_name(DeviceState *dev)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (dc->fw_name) {
> + return dc->fw_name;
> + }
> +
> + return object_get_typename(OBJECT(dev));
> +}
> +
> +static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> + Error **errp);
> +
> +static void bus_remove_child(BusState *bus, DeviceState *child)
> +{
> + 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);
> + }
> +
> + kid->index = bus->max_index++;
> + kid->child = child;
> +
> + 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);
> +}
> +
> +/* Initialize a device. Device properties should be set before calling
> + this function. IRQs and MMIO regions should be connected/mapped after
> + calling this function.
> + On failure, destroy the device and return negative value.
> + Return 0 on success. */
> +int qdev_init(DeviceState *dev)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> + int rc;
> +
> + assert(dev->state == DEV_STATE_CREATED);
> +
> + rc = dc->init(dev);
> + if (rc < 0) {
> + 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);
> + }
> +
> + qdev_init_vmstate(dev);
> + dev->state = DEV_STATE_INITIALIZED;
> + if (dev->hotplugged) {
> + device_reset(dev);
> + }
> + return 0;
> +}
> +
> +void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> + int required_for_version)
> +{
> + assert(dev->state == DEV_STATE_CREATED);
> + dev->instance_id_alias = alias_id;
> + dev->alias_required_for_version = required_for_version;
> +}
> +
> +void qdev_unplug(DeviceState *dev, Error **errp)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (!dev->parent_bus->allow_hotplug) {
> + error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> + return;
> + }
> + assert(dc->unplug != NULL);
> +
> + qdev_hot_removed = true;
> +
> + if (dc->unplug(dev) < 0) {
> + error_set(errp, QERR_UNDEFINED_ERROR);
> + return;
> + }
> +}
> +
> +static int qdev_reset_one(DeviceState *dev, void *opaque)
> +{
> + device_reset(dev);
> +
> + return 0;
> +}
> +
> +static int qbus_reset_one(BusState *bus, void *opaque)
> +{
> + BusClass *bc = BUS_GET_CLASS(bus);
> + if (bc->reset) {
> + return bc->reset(bus);
> + }
> + return 0;
> +}
> +
> +void qdev_reset_all(DeviceState *dev)
> +{
> + qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +void qbus_reset_all_fn(void *opaque)
> +{
> + BusState *bus = opaque;
> + qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +/* can be used as ->unplug() callback for the simple cases */
> +int qdev_simple_unplug_cb(DeviceState *dev)
> +{
> + /* just zap it */
> + qdev_free(dev);
> + return 0;
> +}
> +
> +
> +/* Like qdev_init(), but terminate program via error_report() instead of
> + returning an error value. This is okay during machine creation.
> + Don't use for hotplug, because there callers need to recover from
> + failure. Exception: if you know the device's init() callback can't
> + fail, then qdev_init_nofail() can't fail either, and is therefore
> + usable even then. But relying on the device implementation that
> + 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", typename);
> + exit(1);
> + }
> +}
> +
> +/* Unlink device from bus and free the structure. */
> +void qdev_free(DeviceState *dev)
> +{
> + object_delete(OBJECT(dev));
> +}
> +
> +void qdev_machine_creation_done(void)
> +{
> + /*
> + * ok, initial machine setup is done, starting from now we can
> + * only create hotpluggable devices
> + */
> + qdev_hotplug = 1;
> +}
> +
> +bool qdev_machine_modified(void)
> +{
> + return qdev_hot_added || qdev_hot_removed;
> +}
> +
> +BusState *qdev_get_parent_bus(DeviceState *dev)
> +{
> + return dev->parent_bus;
> +}
> +
> +BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> +{
> + BusState *bus;
> +
> + QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> + if (strcmp(name, bus->name) == 0) {
> + return bus;
> + }
> + }
> + return NULL;
> +}
> +
> +int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> + qbus_walkerfn *busfn, void *opaque)
> +{
> + BusChild *kid;
> + int err;
> +
> + if (busfn) {
> + err = busfn(bus, opaque);
> + if (err) {
> + return err;
> + }
> + }
> +
> + QTAILQ_FOREACH(kid, &bus->children, sibling) {
> + err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> + if (err < 0) {
> + return err;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> + qbus_walkerfn *busfn, void *opaque)
> +{
> + BusState *bus;
> + int err;
> +
> + if (devfn) {
> + err = devfn(dev, opaque);
> + if (err) {
> + return err;
> + }
> + }
> +
> + QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> + err = qbus_walk_children(bus, devfn, busfn, opaque);
> + if (err < 0) {
> + return err;
> + }
> + }
> +
> + return 0;
> +}
> +
> +DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> +{
> + BusChild *kid;
> + DeviceState *ret;
> + BusState *child;
> +
> + 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) {
> + return ret;
> + }
> + }
> + }
> + return NULL;
> +}
> +
> +static void qbus_realize(BusState *bus)
> +{
> + const char *typename = object_get_typename(OBJECT(bus));
> + char *buf;
> + int i,len;
> +
> + if (bus->name) {
> + /* use supplied name */
> + } else if (bus->parent && bus->parent->id) {
> + /* parent device has id -> use it for bus name */
> + len = strlen(bus->parent->id) + 16;
> + buf = g_malloc(len);
> + 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(typename) + 16;
> + buf = g_malloc(len);
> + 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;
> + }
> +
> + 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 {
> + qbus_register_reset(bus);
> + }
> +}
> +
> +void qbus_create_inplace(BusState *bus, const char *typename,
> + DeviceState *parent, const char *name)
> +{
> + object_initialize(bus, typename);
> +
> + bus->parent = parent;
> + bus->name = name ? g_strdup(name) : NULL;
> + qbus_realize(bus);
> +}
> +
> +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
> +{
> + 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)
> +{
> + if (bus->qom_allocated) {
> + object_delete(OBJECT(bus));
> + } else {
> + object_finalize(OBJECT(bus));
> + if (bus->glib_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)
> +{
> + int l = 0;
> +
> + if (dev && dev->parent_bus) {
> + char *d;
> + l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> + d = bus_get_fw_dev_path(dev->parent_bus, dev);
> + if (d) {
> + l += snprintf(p + l, size - l, "%s", d);
> + g_free(d);
> + } else {
> + l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> + }
> + }
> + l += snprintf(p + l , size - l, "/");
> +
> + return l;
> +}
> +
> +char* qdev_get_fw_dev_path(DeviceState *dev)
> +{
> + char path[128];
> + int l;
> +
> + l = qdev_get_fw_dev_path_helper(dev, path, 128);
> +
> + path[l-1] = '\0';
> +
> + return g_strdup(path);
> +}
> +
> +char *qdev_get_dev_path(DeviceState *dev)
> +{
> + BusClass *bc;
> +
> + if (!dev || !dev->parent_bus) {
> + return NULL;
> + }
> +
> + bc = BUS_GET_CLASS(dev->parent_bus);
> + if (bc->get_dev_path) {
> + return bc->get_dev_path(dev);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + * Legacy property handling
> + */
> +
> +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];
> + char *ptr = buffer;
> +
> + prop->info->print(dev, prop, buffer, sizeof(buffer));
> + visit_type_str(v, &ptr, name, errp);
> +}
> +
> +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;
> + int ret;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &ptr, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + ret = prop->info->parse(dev, prop, ptr);
> + error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> + g_free(ptr);
> +}
> +
> +/**
> + * @qdev_add_legacy_property - adds a legacy property
> + *
> + * 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 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);
> +
> + 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);
> +}
> +
> +/**
> + * @qdev_property_add_static - add a @Property to a device.
> + *
> + * Static properties access data in a struct. The actual type of the
> + * property and the field depends on the property type.
> + */
> +void qdev_property_add_static(DeviceState *dev, Property *prop,
> + Error **errp)
> +{
> + Error *local_err = NULL;
> + Object *obj = OBJECT(dev);
> +
> + /*
> + * 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;
> + }
> +
> + object_property_add(obj, prop->name, prop->info->name,
> + prop->info->get, prop->info->set,
> + prop->info->release,
> + prop, &local_err);
> +
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (prop->qtype == QTYPE_NONE) {
> + return;
> + }
> +
> + 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);
> + }
> + assert_no_error(local_err);
> +}
> +
> +static void device_initfn(Object *obj)
> +{
> + DeviceState *dev = DEVICE(obj);
> + ObjectClass *class;
> + Property *prop;
> +
> + if (qdev_hotplug) {
> + dev->hotplugged = 1;
> + qdev_hot_added = true;
> + }
> +
> + dev->instance_id_alias = -1;
> + dev->state = DEV_STATE_CREATED;
> +
> + 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);
> + }
> + class = object_class_get_parent(class);
> + } while (class != object_class_by_name(TYPE_DEVICE));
> + qdev_prop_set_globals(dev);
> +
> + object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> + (Object **)&dev->parent_bus, NULL);
> +}
> +
> +/* Unlink device from bus and free the structure. */
> +static void device_finalize(Object *obj)
> +{
> + DeviceState *dev = DEVICE(obj);
> + BusState *bus;
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (dev->state == DEV_STATE_INITIALIZED) {
> + while (dev->num_child_bus) {
> + bus = QLIST_FIRST(&dev->child_bus);
> + qbus_free(bus);
> + }
> + qdev_finalize_vmstate(dev);
> + if (dc->exit) {
> + dc->exit(dev);
> + }
> + if (dev->opts) {
> + qemu_opts_del(dev->opts);
> + }
> + }
> + if (dev->parent_bus) {
> + bus_remove_child(dev->parent_bus, dev);
> + }
> +}
> +
> +static void device_class_base_init(ObjectClass *class, void *data)
> +{
> + DeviceClass *klass = DEVICE_CLASS(class);
> +
> + /* We explicitly look up properties in the superclasses,
> + * so do not propagate them to the subclasses.
> + */
> + klass->props = NULL;
> +}
> +
> +void device_reset(DeviceState *dev)
> +{
> + DeviceClass *klass = DEVICE_GET_CLASS(dev);
> +
> + if (klass->reset) {
> + klass->reset(dev);
> + }
> +}
> +
> +Object *qdev_get_machine(void)
> +{
> + static Object *dev;
> +
> + if (dev == NULL) {
> + dev = container_get(object_get_root(), "/machine");
> + }
> +
> + return dev;
> +}
> +
> +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),
> +};
> +
> +static void qbus_initfn(Object *obj)
> +{
> + BusState *bus = BUS(obj);
> +
> + QTAILQ_INIT(&bus->children);
> +}
> +
> +static void qbus_finalize(Object *obj)
> +{
> + BusState *bus = BUS(obj);
> + BusChild *kid;
> +
> + while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> + DeviceState *dev = kid->child;
> + qdev_free(dev);
> + }
> + if (bus->parent) {
> + QLIST_REMOVE(bus, sibling);
> + bus->parent->num_child_bus--;
> + } else {
> + qbus_unregister_reset(bus);
> + }
> + g_free((char *)bus->name);
> +}
> +
> +static const TypeInfo bus_info = {
> + .name = TYPE_BUS,
> + .parent = TYPE_OBJECT,
> + .instance_size = sizeof(BusState),
> + .abstract = true,
> + .class_size = sizeof(BusClass),
> + .instance_init = qbus_initfn,
> + .instance_finalize = qbus_finalize,
> +};
> +
> +static void qdev_register_types(void)
> +{
> + type_register_static(&bus_info);
> + type_register_static(&device_type_info);
> +}
> +
> +type_init(qdev_register_types)
> diff --git a/qom/qdev-properties.c b/qom/qdev-properties.c
> new file mode 100644
> index 0000000..2e82cb9
> --- /dev/null
> +++ b/qom/qdev-properties.c
> @@ -0,0 +1,963 @@
> +#include "net.h"
> +#include "hw/qdev.h"
> +#include "qerror.h"
> +#include "blockdev.h"
> +#include "hw/block-common.h"
> +#include "net/hub.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> +{
> + void *ptr = dev;
> + ptr += prop->offset;
> + return ptr;
> +}
> +
> +static void get_enum(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_enum(v, ptr, prop->info->enum_table,
> + prop->info->name, prop->name, errp);
> +}
> +
> +static void set_enum(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_enum(v, ptr, prop->info->enum_table,
> + prop->info->name, prop->name, errp);
> +}
> +
> +/* Bit */
> +
> +static uint32_t qdev_get_prop_mask(Property *prop)
> +{
> + assert(prop->info == &qdev_prop_bit);
> + return 0x1 << prop->bitnr;
> +}
> +
> +static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> +{
> + uint32_t *p = qdev_get_prop_ptr(dev, props);
> + uint32_t mask = qdev_get_prop_mask(props);
> + if (val)
> + *p |= mask;
> + else
> + *p &= ~mask;
> +}
> +
> +static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint32_t *p = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
> +}
> +
> +static void get_bit(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *p = qdev_get_prop_ptr(dev, prop);
> + bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> +
> + visit_type_bool(v, &value, name, errp);
> +}
> +
> +static void set_bit(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + Error *local_err = NULL;
> + bool value;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_bool(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + bit_prop_set(dev, prop, value);
> +}
> +
> +PropertyInfo qdev_prop_bit = {
> + .name = "boolean",
> + .legacy_name = "on/off",
> + .print = print_bit,
> + .get = get_bit,
> + .set = set_bit,
> +};
> +
> +/* --- 8bit integer --- */
> +
> +static void get_uint8(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +static void set_uint8(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint8 = {
> + .name = "uint8",
> + .get = get_uint8,
> + .set = set_uint8,
> +};
> +
> +/* --- 8bit hex value --- */
> +
> +static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoul(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx8, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex8 = {
> + .name = "uint8",
> + .legacy_name = "hex8",
> + .parse = parse_hex8,
> + .print = print_hex8,
> + .get = get_uint8,
> + .set = set_uint8,
> +};
> +
> +/* --- 16bit integer --- */
> +
> +static void get_uint16(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +static void set_uint16(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint16 = {
> + .name = "uint16",
> + .get = get_uint16,
> + .set = set_uint16,
> +};
> +
> +/* --- 32bit integer --- */
> +
> +static void get_uint32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void set_uint32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void get_int32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_int32(v, ptr, name, errp);
> +}
> +
> +static void set_int32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_int32(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint32 = {
> + .name = "uint32",
> + .get = get_uint32,
> + .set = set_uint32,
> +};
> +
> +PropertyInfo qdev_prop_int32 = {
> + .name = "int32",
> + .get = get_int32,
> + .set = set_int32,
> +};
> +
> +/* --- 32bit hex value --- */
> +
> +static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoul(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx32, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex32 = {
> + .name = "uint32",
> + .legacy_name = "hex32",
> + .parse = parse_hex32,
> + .print = print_hex32,
> + .get = get_uint32,
> + .set = set_uint32,
> +};
> +
> +/* --- 64bit integer --- */
> +
> +static void get_uint64(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +static void set_uint64(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint64 = {
> + .name = "uint64",
> + .get = get_uint64,
> + .set = set_uint64,
> +};
> +
> +/* --- 64bit hex value --- */
> +
> +static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoull(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx64, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex64 = {
> + .name = "uint64",
> + .legacy_name = "hex64",
> + .parse = parse_hex64,
> + .print = print_hex64,
> + .get = get_uint64,
> + .set = set_uint64,
> +};
> +
> +/* --- string --- */
> +
> +static void release_string(Object *obj, const char *name, void *opaque)
> +{
> + Property *prop = opaque;
> + g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> +}
> +
> +static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> + if (!*ptr)
> + return snprintf(dest, len, "<null>");
> + return snprintf(dest, len, "\"%s\"", *ptr);
> +}
> +
> +static void get_string(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (!*ptr) {
> + char *str = (char *)"";
> + visit_type_str(v, &str, name, errp);
> + } else {
> + visit_type_str(v, ptr, name, errp);
> + }
> +}
> +
> +static void set_string(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + char *str;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (*ptr) {
> + g_free(*ptr);
> + }
> + *ptr = str;
> +}
> +
> +PropertyInfo qdev_prop_string = {
> + .name = "string",
> + .print = print_string,
> + .release = release_string,
> + .get = get_string,
> + .set = set_string,
> +};
> +
> +/* --- pointer --- */
> +
> +/* Not a proper property, just for dirty hacks. TODO Remove it! */
> +PropertyInfo qdev_prop_ptr = {
> + .name = "ptr",
> +};
> +
> +/* --- mac address --- */
> +
> +/*
> + * accepted syntax versions:
> + * 01:02:03:04:05:06
> + * 01-02-03-04-05-06
> + */
> +static void get_mac(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> + char buffer[2 * 6 + 5 + 1];
> + char *p = buffer;
> +
> + snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> + mac->a[0], mac->a[1], mac->a[2],
> + mac->a[3], mac->a[4], mac->a[5]);
> +
> + visit_type_str(v, &p, name, errp);
> +}
> +
> +static void set_mac(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + int i, pos;
> + char *str, *p;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> + if (!qemu_isxdigit(str[pos]))
> + goto inval;
> + if (!qemu_isxdigit(str[pos+1]))
> + goto inval;
> + if (i == 5) {
> + if (str[pos+2] != '\0')
> + goto inval;
> + } else {
> + if (str[pos+2] != ':' && str[pos+2] != '-')
> + goto inval;
> + }
> + mac->a[i] = strtol(str+pos, &p, 16);
> + }
> + g_free(str);
> + return;
> +
> +inval:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_macaddr = {
> + .name = "macaddr",
> + .get = get_mac,
> + .set = set_mac,
> +};
> +
> +/* --- lost tick policy --- */
> +
> +static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> + [LOST_TICK_DISCARD] = "discard",
> + [LOST_TICK_DELAY] = "delay",
> + [LOST_TICK_MERGE] = "merge",
> + [LOST_TICK_SLEW] = "slew",
> + [LOST_TICK_MAX] = NULL,
> +};
> +
> +QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> +
> +PropertyInfo qdev_prop_losttickpolicy = {
> + .name = "LostTickPolicy",
> + .enum_table = lost_tick_policy_table,
> + .get = get_enum,
> + .set = set_enum,
> +};
> +
> +/* --- BIOS CHS translation */
> +
> +static const char *bios_chs_trans_table[] = {
> + [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> + [BIOS_ATA_TRANSLATION_NONE] = "none",
> + [BIOS_ATA_TRANSLATION_LBA] = "lba",
> +};
> +
> +PropertyInfo qdev_prop_bios_chs_trans = {
> + .name = "bios-chs-trans",
> + .enum_table = bios_chs_trans_table,
> + .get = get_enum,
> + .set = set_enum,
> +};
> +
> +/* --- pci address --- */
> +
> +/*
> + * bus-local address, i.e. "$slot" or "$slot.$fn"
> + */
> +static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> + unsigned int slot, fn, n;
> + Error *local_err = NULL;
> + char *str;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_free(local_err);
> + local_err = NULL;
> + visit_type_int32(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + } else if (value < -1 || value > 255) {
> + error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
> + "pci_devfn");
> + } else {
> + *ptr = value;
> + }
> + return;
> + }
> +
> + if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> + fn = 0;
> + if (sscanf(str, "%x%n", &slot, &n) != 1) {
> + goto invalid;
> + }
> + }
> + if (str[n] != '\0' || fn > 7 || slot > 31) {
> + goto invalid;
> + }
> + *ptr = slot << 3 | fn;
> + g_free(str);
> + return;
> +
> +invalid:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (*ptr == -1) {
> + return snprintf(dest, len, "<unset>");
> + } else {
> + return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> + }
> +}
> +
> +PropertyInfo qdev_prop_pci_devfn = {
> + .name = "int32",
> + .legacy_name = "pci-devfn",
> + .print = print_pci_devfn,
> + .get = get_int32,
> + .set = set_pci_devfn,
> +};
> +
> +/* --- blocksize --- */
> +
> +static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + const int64_t min = 512;
> + const int64_t max = 32768;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint16(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (value < min || value > max) {
> + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> + dev->id?:"", name, (int64_t)value, min, max);
> + return;
> + }
> +
> + /* We rely on power-of-2 blocksizes for bitmasks */
> + if ((value & (value - 1)) != 0) {
> + error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> + dev->id?:"", name, (int64_t)value);
> + return;
> + }
> +
> + *ptr = value;
> +}
> +
> +PropertyInfo qdev_prop_blocksize = {
> + .name = "blocksize",
> + .get = get_uint16,
> + .set = set_blocksize,
> +};
> +
> +/* --- pci host address --- */
> +
> +static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> + char buffer[] = "xxxx:xx:xx.x";
> + char *p = buffer;
> + int rc = 0;
> +
> + rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> + addr->domain, addr->bus, addr->slot, addr->function);
> + assert(rc == sizeof(buffer) - 1);
> +
> + visit_type_str(v, &p, name, errp);
> +}
> +
> +/*
> + * Parse [<domain>:]<bus>:<slot>.<func>
> + * if <domain> is not supplied, it's assumed to be 0.
> + */
> +static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + char *str, *p;
> + char *e;
> + unsigned long val;
> + unsigned long dom = 0, bus = 0;
> + unsigned int slot = 0, func = 0;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + p = str;
> + val = strtoul(p, &e, 16);
> + if (e == p || *e != ':') {
> + goto inval;
> + }
> + bus = val;
> +
> + p = e + 1;
> + val = strtoul(p, &e, 16);
> + if (e == p) {
> + goto inval;
> + }
> + if (*e == ':') {
> + dom = bus;
> + bus = val;
> + p = e + 1;
> + val = strtoul(p, &e, 16);
> + if (e == p) {
> + goto inval;
> + }
> + }
> + slot = val;
> +
> + if (*e != '.') {
> + goto inval;
> + }
> + p = e + 1;
> + val = strtoul(p, &e, 10);
> + if (e == p) {
> + goto inval;
> + }
> + func = val;
> +
> + if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> + goto inval;
> + }
> +
> + if (*e) {
> + goto inval;
> + }
> +
> + addr->domain = dom;
> + addr->bus = bus;
> + addr->slot = slot;
> + addr->function = func;
> +
> + g_free(str);
> + return;
> +
> +inval:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_pci_host_devaddr = {
> + .name = "pci-host-devaddr",
> + .get = get_pci_host_devaddr,
> + .set = set_pci_host_devaddr,
> +};
> +
> +/* --- public helpers --- */
> +
> +static Property *qdev_prop_walk(Property *props, const char *name)
> +{
> + if (!props)
> + return NULL;
> + while (props->name) {
> + if (strcmp(props->name, name) == 0)
> + return props;
> + props++;
> + }
> + return NULL;
> +}
> +
> +static Property *qdev_prop_find(DeviceState *dev, const char *name)
> +{
> + ObjectClass *class;
> + Property *prop;
> +
> + /* device properties */
> + class = object_get_class(OBJECT(dev));
> + do {
> + prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> + if (prop) {
> + return prop;
> + }
> + class = object_class_get_parent(class);
> + } while (class != object_class_by_name(TYPE_DEVICE));
> +
> + return NULL;
> +}
> +
> +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> + Property *prop, const char *value)
> +{
> + switch (ret) {
> + case -EEXIST:
> + error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + default:
> + case -EINVAL:
> + error_set(errp, QERR_PROPERTY_VALUE_BAD,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + case -ENOENT:
> + error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + case 0:
> + break;
> + }
> +}
> +
> +int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> +{
> + char *legacy_name;
> + Error *err = NULL;
> +
> + legacy_name = g_strdup_printf("legacy-%s", name);
> + if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> + object_property_parse(OBJECT(dev), value, legacy_name, &err);
> + } else {
> + object_property_parse(OBJECT(dev), value, name, &err);
> + }
> + g_free(legacy_name);
> +
> + if (err) {
> + qerror_report_err(err);
> + error_free(err);
> + return -1;
> + }
> + return 0;
> +}
> +
> +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> +{
> + Error *errp = NULL;
> + object_property_set_bool(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
> +{
> + Error *errp = NULL;
> + object_property_set_str(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
> +{
> + Error *errp = NULL;
> + char str[2 * 6 + 5 + 1];
> + snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> + value[0], value[1], value[2], value[3], value[4], value[5]);
> +
> + object_property_set_str(OBJECT(dev), str, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> +{
> + Property *prop;
> + Error *errp = NULL;
> +
> + prop = qdev_prop_find(dev, name);
> + object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> + name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> +{
> + Property *prop;
> + void **ptr;
> +
> + prop = qdev_prop_find(dev, name);
> + assert(prop && prop->info == &qdev_prop_ptr);
> + ptr = qdev_get_prop_ptr(dev, prop);
> + *ptr = value;
> +}
> +
> +static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
> +
> +void qdev_prop_register_global(GlobalProperty *prop)
> +{
> + QTAILQ_INSERT_TAIL(&global_props, prop, next);
> +}
> +
> +void qdev_prop_register_global_list(GlobalProperty *props)
> +{
> + int i;
> +
> + for (i = 0; props[i].driver != NULL; i++) {
> + qdev_prop_register_global(props+i);
> + }
> +}
> +
> +void qdev_prop_set_globals(DeviceState *dev)
> +{
> + ObjectClass *class = object_get_class(OBJECT(dev));
> +
> + do {
> + GlobalProperty *prop;
> + QTAILQ_FOREACH(prop, &global_props, next) {
> + if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> + continue;
> + }
> + if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> + exit(1);
> + }
> + }
> + class = object_class_get_parent(class);
> + } while (class);
> +}
> +
> --
> 1.7.11.7
next prev parent reply other threads:[~2012-10-17 18:12 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
2012-10-17 18:06 ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
2012-10-17 18:08 ` Anthony Liguori
2012-10-17 18:32 ` Eduardo Habkost
2012-10-18 14:51 ` Andreas Färber
2012-10-23 14:56 ` Eduardo Habkost
2012-10-24 2:43 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
2012-10-17 18:08 ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
2012-10-17 18:11 ` Anthony Liguori [this message]
2012-10-17 18:18 ` Eduardo Habkost
2012-10-17 19:21 ` Peter Maydell
2012-10-19 16:59 ` Eduardo Habkost
2012-10-22 12:36 ` Igor Mammedov
2012-10-22 12:43 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost
-- strict thread matches above, loose matches on Subject: below --
2012-10-16 1:57 [Qemu-devel] [PATCH v3 00/12] make CPU child of DeviceState and include qdev core in *-user Igor Mammedov
2012-10-16 1:57 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Igor Mammedov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87y5j5t1cy.fsf@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=afaerber@suse.de \
--cc=blauwirbel@gmail.com \
--cc=ehabkost@redhat.com \
--cc=imammedo@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=riku.voipio@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.