[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
From: |
Eduardo Habkost |
Subject: |
Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too |
Date: |
Wed, 17 Oct 2012 15:18:55 -0300 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Wed, Oct 17, 2012 at 01:11:41PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <address@hidden> 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 <address@hidden>
> > ---
> > 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
Done.
>
> 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/.
I don't mind keeping it on hw/, either. I was unsure wheter to move it,
or if it would be OK for *-user to start including files from the hw/
directory.
If nobody complains, I will change the patches to keep the files on
"hw/" on the next version of the series.
>
> 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
--
Eduardo
- [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions, (continued)
- [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-*, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h, Eduardo Habkost, 2012/10/16
- [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too, Eduardo Habkost, 2012/10/16
- Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too, Igor Mammedov, 2012/10/22