* [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
` (10 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
From: Anthony Liguori <aliguori@us.ibm.com>
Header file dependency is a frickin' nightmare right now. cpu.h tends to get
included in our 'include everything' header files but qdev also needs to include
those headers mainly for qdev-properties since it knows about CharDriverState
and friends.
We can solve this for now by splitting out qdev.h along the same lines that we
previously split the C file. Then cpu.h just needs to include qdev-core.h
hw/qdev.h is split into following new headers:
hw/qdev-core.h
hw/qdev-properties.h
hw/qdev-monitor.h
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
[ehabkost: re-add DEFINE_PROP_PCI_HOST_DEVADDR, that was removed on the
original patch (by mistake, I guess)]
[ehabkost: kill qdev_prop_set_vlan() declaration]
[ehabkost: moved get_fw_dev_path() comment to the original location
(I don't know why it was moved)]
[ehabkost: removed qdev_exists() declaration]
[ehabkost: keep using 'QemuOpts' instead of 'struct QemuOpts', as
qdev-core.h includes qemu-option.h]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message)
Detailed changelog:
Changes v1 (from Anthony) -> v2 (from Eduardo):
- re-add DEFINE_PROP_PCI_HOST_DEVADDR, that was removed on the original
patch (by mistake, I guess)
- kill qdev_prop_set_vlan() declaration
Changes v2 -> v3 (from Eduardo):
- moved get_fw_dev_path() comment to the original location (I don't
know why it was moved)
- removed qdev_exists() declaration
- keep using 'QemuOpts' instead of 'struct QemuOpts', as qdev-core.h
includes qemu-option.h
Changes v3 -> v4 (from Eduardo):
- Edited commit message to include additional information
---
hw/irq.h | 2 +
hw/mc146818rtc.c | 1 +
hw/qdev-addr.c | 1 +
hw/qdev-core.h | 238 +++++++++++++++++++++++++++++++++
hw/qdev-monitor.h | 16 +++
hw/qdev-properties.c | 1 +
hw/qdev-properties.h | 130 ++++++++++++++++++
hw/qdev.c | 1 +
hw/qdev.h | 370 +--------------------------------------------------
9 files changed, 394 insertions(+), 366 deletions(-)
create mode 100644 hw/qdev-core.h
create mode 100644 hw/qdev-monitor.h
create mode 100644 hw/qdev-properties.h
diff --git a/hw/irq.h b/hw/irq.h
index e640c10..610e6b7 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,6 +3,8 @@
/* Generic IRQ/GPIO pin infrastructure. */
+typedef struct IRQState *qemu_irq;
+
typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
void qemu_set_irq(qemu_irq irq, int level);
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 332a77d..4bf8808 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -25,6 +25,7 @@
#include "qemu-timer.h"
#include "sysemu.h"
#include "mc146818rtc.h"
+#include "qapi/qapi-visit-core.h"
#ifdef TARGET_I386
#include "apic.h"
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index b711b6b..5b5d38f 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -1,6 +1,7 @@
#include "qdev.h"
#include "qdev-addr.h"
#include "targphys.h"
+#include "qapi/qapi-visit-core.h"
/* --- target physical address --- */
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
new file mode 100644
index 0000000..fce9e22
--- /dev/null
+++ b/hw/qdev-core.h
@@ -0,0 +1,238 @@
+#ifndef QDEV_CORE_H
+#define QDEV_CORE_H
+
+#include "qemu-queue.h"
+#include "qemu-option.h"
+#include "qemu/object.h"
+#include "hw/irq.h"
+#include "error.h"
+
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
+
+typedef struct CompatProperty CompatProperty;
+
+typedef struct BusState BusState;
+
+typedef struct BusClass BusClass;
+
+enum DevState {
+ DEV_STATE_CREATED = 1,
+ DEV_STATE_INITIALIZED,
+};
+
+enum {
+ DEV_NVECTORS_UNSPECIFIED = -1,
+};
+
+#define TYPE_DEVICE "device"
+#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
+#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
+#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+
+typedef int (*qdev_initfn)(DeviceState *dev);
+typedef int (*qdev_event)(DeviceState *dev);
+typedef void (*qdev_resetfn)(DeviceState *dev);
+
+struct VMStateDescription;
+
+typedef struct DeviceClass {
+ ObjectClass parent_class;
+
+ const char *fw_name;
+ const char *desc;
+ Property *props;
+ int no_user;
+
+ /* callbacks */
+ void (*reset)(DeviceState *dev);
+
+ /* device state */
+ const struct VMStateDescription *vmsd;
+
+ /* Private to qdev / bus. */
+ qdev_initfn init;
+ qdev_event unplug;
+ qdev_event exit;
+ const char *bus_type;
+} DeviceClass;
+
+/* This structure should not be accessed directly. We declare it here
+ so that it can be embedded in individual device state structures. */
+struct DeviceState {
+ Object parent_obj;
+
+ const char *id;
+ enum DevState state;
+ QemuOpts *opts;
+ int hotplugged;
+ BusState *parent_bus;
+ int num_gpio_out;
+ qemu_irq *gpio_out;
+ int num_gpio_in;
+ qemu_irq *gpio_in;
+ QLIST_HEAD(, BusState) child_bus;
+ int num_child_bus;
+ int instance_id_alias;
+ int alias_required_for_version;
+};
+
+#define TYPE_BUS "bus"
+#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
+#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
+#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+
+struct BusClass {
+ ObjectClass parent_class;
+
+ /* FIXME first arg should be BusState */
+ void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
+ char *(*get_dev_path)(DeviceState *dev);
+ /*
+ * This callback is used to create Open Firmware device path in accordance
+ * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
+ * bindings can be found at http://playground.sun.com/1275/bindings/.
+ */
+ char *(*get_fw_dev_path)(DeviceState *dev);
+ int (*reset)(BusState *bus);
+};
+
+typedef struct BusChild {
+ DeviceState *child;
+ int index;
+ QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
+/**
+ * BusState:
+ * @qom_allocated: Indicates whether the object was allocated by QOM.
+ * @glib_allocated: Indicates whether the object was initialized in-place
+ * yet is expected to be freed with g_free().
+ */
+struct BusState {
+ Object obj;
+ DeviceState *parent;
+ const char *name;
+ int allow_hotplug;
+ bool qom_allocated;
+ bool glib_allocated;
+ int max_index;
+ QTAILQ_HEAD(ChildrenHead, BusChild) children;
+ QLIST_ENTRY(BusState) sibling;
+};
+
+struct Property {
+ const char *name;
+ PropertyInfo *info;
+ int offset;
+ uint8_t bitnr;
+ uint8_t qtype;
+ int64_t defval;
+};
+
+struct PropertyInfo {
+ const char *name;
+ const char *legacy_name;
+ const char **enum_table;
+ int (*parse)(DeviceState *dev, Property *prop, const char *str);
+ int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+ ObjectPropertyAccessor *get;
+ ObjectPropertyAccessor *set;
+ ObjectPropertyRelease *release;
+};
+
+typedef struct GlobalProperty {
+ const char *driver;
+ const char *property;
+ const char *value;
+ QTAILQ_ENTRY(GlobalProperty) next;
+} GlobalProperty;
+
+/*** Board API. This should go away once we have a machine config file. ***/
+
+DeviceState *qdev_create(BusState *bus, const char *name);
+DeviceState *qdev_try_create(BusState *bus, const char *name);
+int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
+void qdev_init_nofail(DeviceState *dev);
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+ int required_for_version);
+void qdev_unplug(DeviceState *dev, Error **errp);
+void qdev_free(DeviceState *dev);
+int qdev_simple_unplug_cb(DeviceState *dev);
+void qdev_machine_creation_done(void);
+bool qdev_machine_modified(void);
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
+void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
+
+BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
+
+/*** Device API. ***/
+
+/* Register device properties. */
+/* GPIO inputs also double as IRQ sinks. */
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
+
+BusState *qdev_get_parent_bus(DeviceState *dev);
+
+/*** BUS API. ***/
+
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
+/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
+typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
+typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
+
+void qbus_create_inplace(BusState *bus, const char *typename,
+ DeviceState *parent, const char *name);
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
+/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
+ * < 0 if either devfn or busfn terminate walk somewhere in cursion,
+ * 0 otherwise. */
+int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
+ qbus_walkerfn *busfn, void *opaque);
+int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
+ qbus_walkerfn *busfn, void *opaque);
+void qdev_reset_all(DeviceState *dev);
+void qbus_reset_all_fn(void *opaque);
+
+void qbus_free(BusState *bus);
+
+#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
+
+/* This should go away once we get rid of the NULL bus hack */
+BusState *sysbus_get_default(void);
+
+char *qdev_get_fw_dev_path(DeviceState *dev);
+
+/**
+ * @qdev_machine_init
+ *
+ * Initialize platform devices before machine init. This is a hack until full
+ * support for composition is added.
+ */
+void qdev_machine_init(void);
+
+/**
+ * @device_reset
+ *
+ * Reset a single device (by calling the reset method).
+ */
+void device_reset(DeviceState *dev);
+
+const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
+
+const char *qdev_fw_name(DeviceState *dev);
+
+Object *qdev_get_machine(void);
+
+/* FIXME: make this a link<> */
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+
+extern int qdev_hotplug;
+
+char *qdev_get_dev_path(DeviceState *dev);
+
+#endif
diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h
new file mode 100644
index 0000000..220ceba
--- /dev/null
+++ b/hw/qdev-monitor.h
@@ -0,0 +1,16 @@
+#ifndef QEMU_QDEV_MONITOR_H
+#define QEMU_QDEV_MONITOR_H
+
+#include "qdev-core.h"
+#include "monitor.h"
+
+/*** monitor commands ***/
+
+void do_info_qtree(Monitor *mon);
+void do_info_qdm(Monitor *mon);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int qdev_device_help(QemuOpts *opts);
+DeviceState *qdev_device_add(QemuOpts *opts);
+
+#endif
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 8aca0d4..81d901c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -4,6 +4,7 @@
#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)
{
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
new file mode 100644
index 0000000..5b046ab
--- /dev/null
+++ b/hw/qdev-properties.h
@@ -0,0 +1,130 @@
+#ifndef QEMU_QDEV_PROPERTIES_H
+#define QEMU_QDEV_PROPERTIES_H
+
+#include "qdev-core.h"
+
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_bit;
+extern PropertyInfo qdev_prop_uint8;
+extern PropertyInfo qdev_prop_uint16;
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_int32;
+extern PropertyInfo qdev_prop_uint64;
+extern PropertyInfo qdev_prop_hex8;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_hex64;
+extern PropertyInfo qdev_prop_string;
+extern PropertyInfo qdev_prop_chr;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_macaddr;
+extern PropertyInfo qdev_prop_losttickpolicy;
+extern PropertyInfo qdev_prop_bios_chs_trans;
+extern PropertyInfo qdev_prop_drive;
+extern PropertyInfo qdev_prop_netdev;
+extern PropertyInfo qdev_prop_vlan;
+extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_blocksize;
+extern PropertyInfo qdev_prop_pci_host_devaddr;
+
+#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
+ .name = (_name), \
+ .info = &(_prop), \
+ .offset = offsetof(_state, _field) \
+ + type_check(_type,typeof_field(_state, _field)), \
+ }
+#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+ .name = (_name), \
+ .info = &(_prop), \
+ .offset = offsetof(_state, _field) \
+ + type_check(_type,typeof_field(_state, _field)), \
+ .qtype = QTYPE_QINT, \
+ .defval = (_type)_defval, \
+ }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
+ .name = (_name), \
+ .info = &(qdev_prop_bit), \
+ .bitnr = (_bit), \
+ .offset = offsetof(_state, _field) \
+ + type_check(uint32_t,typeof_field(_state, _field)), \
+ .qtype = QTYPE_QBOOL, \
+ .defval = (bool)_defval, \
+ }
+
+#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
+#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
+#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
+#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
+
+#define DEFINE_PROP_PTR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
+#define DEFINE_PROP_CHR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
+#define DEFINE_PROP_STRING(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
+#define DEFINE_PROP_NETDEV(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
+#define DEFINE_PROP_VLAN(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
+#define DEFINE_PROP_DRIVE(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
+#define DEFINE_PROP_MACADDR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+ LostTickPolicy)
+#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
+#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
+#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+
+#define DEFINE_PROP_END_OF_LIST() \
+ {}
+
+/* Set properties between creation and init. */
+void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
+void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
+void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
+int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
+void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
+/* FIXME: Remove opaque pointer properties. */
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+
+void qdev_prop_register_global_list(GlobalProperty *props);
+void qdev_prop_set_globals(DeviceState *dev);
+void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
+ Property *prop, const char *value);
+
+/**
+ * @qdev_property_add_static - add a @Property to a device referencing a
+ * field in a struct.
+ */
+void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
+
+#endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 9b9aba3..7ddcd24 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,6 +29,7 @@
#include "qdev.h"
#include "sysemu.h"
#include "error.h"
+#include "qapi/qapi-visit-core.h"
int qdev_hotplug = 0;
static bool qdev_hot_added = false;
diff --git a/hw/qdev.h b/hw/qdev.h
index c6ac636..365b8d6 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -1,371 +1,9 @@
#ifndef QDEV_H
#define QDEV_H
-#include "hw.h"
-#include "qemu-queue.h"
-#include "qemu-char.h"
-#include "qemu-option.h"
-#include "qapi/qapi-visit-core.h"
-#include "qemu/object.h"
-#include "error.h"
-
-typedef struct Property Property;
-
-typedef struct PropertyInfo PropertyInfo;
-
-typedef struct CompatProperty CompatProperty;
-
-typedef struct BusState BusState;
-
-typedef struct BusClass BusClass;
-
-enum DevState {
- DEV_STATE_CREATED = 1,
- DEV_STATE_INITIALIZED,
-};
-
-enum {
- DEV_NVECTORS_UNSPECIFIED = -1,
-};
-
-#define TYPE_DEVICE "device"
-#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
-#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
-#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
-
-typedef int (*qdev_initfn)(DeviceState *dev);
-typedef int (*qdev_event)(DeviceState *dev);
-typedef void (*qdev_resetfn)(DeviceState *dev);
-
-typedef struct DeviceClass {
- ObjectClass parent_class;
-
- const char *fw_name;
- const char *desc;
- Property *props;
- int no_user;
-
- /* callbacks */
- void (*reset)(DeviceState *dev);
-
- /* device state */
- const VMStateDescription *vmsd;
-
- /* Private to qdev / bus. */
- qdev_initfn init;
- qdev_event unplug;
- qdev_event exit;
- const char *bus_type;
-} DeviceClass;
-
-/* This structure should not be accessed directly. We declare it here
- so that it can be embedded in individual device state structures. */
-struct DeviceState {
- Object parent_obj;
-
- const char *id;
- enum DevState state;
- QemuOpts *opts;
- int hotplugged;
- BusState *parent_bus;
- int num_gpio_out;
- qemu_irq *gpio_out;
- int num_gpio_in;
- qemu_irq *gpio_in;
- QLIST_HEAD(, BusState) child_bus;
- int num_child_bus;
- int instance_id_alias;
- int alias_required_for_version;
-};
-
-#define TYPE_BUS "bus"
-#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
-#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
-#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
-
-struct BusClass {
- ObjectClass parent_class;
-
- /* FIXME first arg should be BusState */
- void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
- char *(*get_dev_path)(DeviceState *dev);
- /*
- * This callback is used to create Open Firmware device path in accordance
- * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
- * bindings can be found at http://playground.sun.com/1275/bindings/.
- */
- char *(*get_fw_dev_path)(DeviceState *dev);
- int (*reset)(BusState *bus);
-};
-
-typedef struct BusChild {
- DeviceState *child;
- int index;
- QTAILQ_ENTRY(BusChild) sibling;
-} BusChild;
-
-/**
- * BusState:
- * @qom_allocated: Indicates whether the object was allocated by QOM.
- * @glib_allocated: Indicates whether the object was initialized in-place
- * yet is expected to be freed with g_free().
- */
-struct BusState {
- Object obj;
- DeviceState *parent;
- const char *name;
- int allow_hotplug;
- bool qom_allocated;
- bool glib_allocated;
- int max_index;
- QTAILQ_HEAD(ChildrenHead, BusChild) children;
- QLIST_ENTRY(BusState) sibling;
-};
-
-struct Property {
- const char *name;
- PropertyInfo *info;
- int offset;
- uint8_t bitnr;
- uint8_t qtype;
- int64_t defval;
-};
-
-struct PropertyInfo {
- const char *name;
- const char *legacy_name;
- const char **enum_table;
- int (*parse)(DeviceState *dev, Property *prop, const char *str);
- int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
- ObjectPropertyAccessor *get;
- ObjectPropertyAccessor *set;
- ObjectPropertyRelease *release;
-};
-
-typedef struct GlobalProperty {
- const char *driver;
- const char *property;
- const char *value;
- QTAILQ_ENTRY(GlobalProperty) next;
-} GlobalProperty;
-
-/*** Board API. This should go away once we have a machine config file. ***/
-
-DeviceState *qdev_create(BusState *bus, const char *name);
-DeviceState *qdev_try_create(BusState *bus, const char *name);
-int qdev_device_help(QemuOpts *opts);
-DeviceState *qdev_device_add(QemuOpts *opts);
-int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
-void qdev_init_nofail(DeviceState *dev);
-void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
- int required_for_version);
-void qdev_unplug(DeviceState *dev, Error **errp);
-void qdev_free(DeviceState *dev);
-int qdev_simple_unplug_cb(DeviceState *dev);
-void qdev_machine_creation_done(void);
-bool qdev_machine_modified(void);
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
-void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
-
-BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
-
-/*** Device API. ***/
-
-/* Register device properties. */
-/* GPIO inputs also double as IRQ sinks. */
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
-
-BusState *qdev_get_parent_bus(DeviceState *dev);
-
-/*** BUS API. ***/
-
-DeviceState *qdev_find_recursive(BusState *bus, const char *id);
-
-/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
-typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
-typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
-
-void qbus_create_inplace(BusState *bus, const char *typename,
- DeviceState *parent, const char *name);
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
-/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
- * < 0 if either devfn or busfn terminate walk somewhere in cursion,
- * 0 otherwise. */
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
-void qdev_reset_all(DeviceState *dev);
-void qbus_reset_all_fn(void *opaque);
-
-void qbus_free(BusState *bus);
-
-#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
-
-/* This should go away once we get rid of the NULL bus hack */
-BusState *sysbus_get_default(void);
-
-/*** monitor commands ***/
-
-void do_info_qtree(Monitor *mon);
-void do_info_qdm(Monitor *mon);
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
-/*** qdev-properties.c ***/
-
-extern PropertyInfo qdev_prop_bit;
-extern PropertyInfo qdev_prop_uint8;
-extern PropertyInfo qdev_prop_uint16;
-extern PropertyInfo qdev_prop_uint32;
-extern PropertyInfo qdev_prop_int32;
-extern PropertyInfo qdev_prop_uint64;
-extern PropertyInfo qdev_prop_hex8;
-extern PropertyInfo qdev_prop_hex32;
-extern PropertyInfo qdev_prop_hex64;
-extern PropertyInfo qdev_prop_string;
-extern PropertyInfo qdev_prop_chr;
-extern PropertyInfo qdev_prop_ptr;
-extern PropertyInfo qdev_prop_macaddr;
-extern PropertyInfo qdev_prop_losttickpolicy;
-extern PropertyInfo qdev_prop_bios_chs_trans;
-extern PropertyInfo qdev_prop_drive;
-extern PropertyInfo qdev_prop_netdev;
-extern PropertyInfo qdev_prop_vlan;
-extern PropertyInfo qdev_prop_pci_devfn;
-extern PropertyInfo qdev_prop_blocksize;
-extern PropertyInfo qdev_prop_pci_host_devaddr;
-
-#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type,typeof_field(_state, _field)), \
- }
-#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type,typeof_field(_state, _field)), \
- .qtype = QTYPE_QINT, \
- .defval = (_type)_defval, \
- }
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
- .name = (_name), \
- .info = &(qdev_prop_bit), \
- .bitnr = (_bit), \
- .offset = offsetof(_state, _field) \
- + type_check(uint32_t,typeof_field(_state, _field)), \
- .qtype = QTYPE_QBOOL, \
- .defval = (bool)_defval, \
- }
-
-#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
-#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
-#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
-#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
-#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
-#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
-#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
-#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
-#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
-
-#define DEFINE_PROP_PTR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
-#define DEFINE_PROP_CHR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
-#define DEFINE_PROP_STRING(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
-#define DEFINE_PROP_NETDEV(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
-#define DEFINE_PROP_VLAN(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
-#define DEFINE_PROP_DRIVE(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
-#define DEFINE_PROP_MACADDR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
-#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
- LostTickPolicy)
-#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
-#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
-#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
-
-#define DEFINE_PROP_END_OF_LIST() \
- {}
-
-/* Set properties between creation and init. */
-void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
-int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
-void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
-void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
-void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
-void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
-void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
-void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
-void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
-/* FIXME: Remove opaque pointer properties. */
-void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
-
-void qdev_prop_register_global_list(GlobalProperty *props);
-void qdev_prop_set_globals(DeviceState *dev);
-void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
- Property *prop, const char *value);
-
-char *qdev_get_fw_dev_path(DeviceState *dev);
-
-/**
- * @qdev_property_add_static - add a @Property to a device referencing a
- * field in a struct.
- */
-void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
-
-/**
- * @qdev_machine_init
- *
- * Initialize platform devices before machine init. This is a hack until full
- * support for composition is added.
- */
-void qdev_machine_init(void);
-
-/**
- * @device_reset
- *
- * Reset a single device (by calling the reset method).
- */
-void device_reset(DeviceState *dev);
-
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
-
-const char *qdev_fw_name(DeviceState *dev);
-
-Object *qdev_get_machine(void);
-
-/* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
-
-extern int qdev_hotplug;
-
-char *qdev_get_dev_path(DeviceState *dev);
+#include "hw/hw.h"
+#include "qdev-core.h"
+#include "qdev-properties.h"
+#include "qdev-monitor.h"
#endif
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
` (9 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
From: Igor Mammedov <imammedo@redhat.com>
needed to prevent build breakage when CPU becomes a child of DeviceState
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: include <stdbool.h> too]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
scripts/qapi-types.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 1b84834..6bc2391 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -273,7 +273,8 @@ fdecl.write(mcgen('''
#ifndef %(guard)s
#define %(guard)s
-#include "qemu-common.h"
+#include <stdbool.h>
+#include <stdint.h>
''',
guard=guardname(h_file)))
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-*
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
` (8 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
This change should help on two things:
- Allowing DeviceState to be used by *-user;
- Writing qdev unit tests without pulling too many dependencies.
Note that there are two parts that depend on code compiled only on
qemu-system-*, but are still inside qdev.c:
- vmstate handling
- reset function registration.
Those two parts will be handled later, by moving that code to
qdev-system.c but keeping weak symbols for *-user.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
[imammedo: keep qdev_get_child_bus() in hw/qdev.c]
[imammedo: put qdev_set_nic_properties() in hw/qdev-properties-system.c]
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: updated the qdev_init_gpio_in() code on qdev-system.c to current
version]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
hw/Makefile.objs | 1 +
hw/qdev-properties-system.c | 340 ++++++++++++++++++++++++++++++++++++++++++++
hw/qdev-properties.c | 320 +----------------------------------------
hw/qdev-properties.h | 1 +
hw/qdev-system.c | 68 +++++++++
hw/qdev.c | 80 -----------
6 files changed, 411 insertions(+), 399 deletions(-)
create mode 100644 hw/qdev-properties-system.c
create mode 100644 hw/qdev-system.c
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 854faa9..16f23c0 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -181,6 +181,7 @@ 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.o qdev-properties.o qdev-monitor.o
+common-obj-y += qdev-system.o qdev-properties-system.o
common-obj-$(CONFIG_BRLAPI) += baum.o
# xen backend driver support
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
new file mode 100644
index 0000000..e3a21db
--- /dev/null
+++ b/hw/qdev-properties-system.c
@@ -0,0 +1,340 @@
+#include "net.h"
+#include "qdev.h"
+#include "qerror.h"
+#include "blockdev.h"
+#include "hw/block-common.h"
+#include "net/hub.h"
+#include "qapi/qapi-visit-core.h"
+
+static void get_pointer(Object *obj, Visitor *v, Property *prop,
+ const char *(*print)(void *ptr),
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ void **ptr = qdev_get_prop_ptr(dev, prop);
+ char *p;
+
+ p = (char *) (*ptr ? print(*ptr) : "");
+ visit_type_str(v, &p, name, errp);
+}
+
+static void set_pointer(Object *obj, Visitor *v, Property *prop,
+ int (*parse)(DeviceState *dev, const char *str,
+ void **ptr),
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Error *local_err = NULL;
+ void **ptr = qdev_get_prop_ptr(dev, prop);
+ char *str;
+ int ret;
+
+ 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 (!*str) {
+ g_free(str);
+ *ptr = NULL;
+ return;
+ }
+ ret = parse(dev, str, ptr);
+ error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
+ g_free(str);
+}
+
+/* --- drive --- */
+
+static int parse_drive(DeviceState *dev, const char *str, void **ptr)
+{
+ BlockDriverState *bs;
+
+ bs = bdrv_find(str);
+ if (bs == NULL)
+ return -ENOENT;
+ if (bdrv_attach_dev(bs, dev) < 0)
+ return -EEXIST;
+ *ptr = bs;
+ return 0;
+}
+
+static void release_drive(Object *obj, const char *name, void *opaque)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (*ptr) {
+ bdrv_detach_dev(*ptr, dev);
+ blockdev_auto_del(*ptr);
+ }
+}
+
+static const char *print_drive(void *ptr)
+{
+ return bdrv_get_device_name(ptr);
+}
+
+static void get_drive(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ get_pointer(obj, v, opaque, print_drive, name, errp);
+}
+
+static void set_drive(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_drive, name, errp);
+}
+
+PropertyInfo qdev_prop_drive = {
+ .name = "drive",
+ .get = get_drive,
+ .set = set_drive,
+ .release = release_drive,
+};
+
+/* --- character device --- */
+
+static int parse_chr(DeviceState *dev, const char *str, void **ptr)
+{
+ CharDriverState *chr = qemu_chr_find(str);
+ if (chr == NULL) {
+ return -ENOENT;
+ }
+ if (chr->avail_connections < 1) {
+ return -EEXIST;
+ }
+ *ptr = chr;
+ --chr->avail_connections;
+ return 0;
+}
+
+static void release_chr(Object *obj, const char *name, void *opaque)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (*ptr) {
+ qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
+ }
+}
+
+
+static const char *print_chr(void *ptr)
+{
+ CharDriverState *chr = ptr;
+
+ return chr->label ? chr->label : "";
+}
+
+static void get_chr(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ get_pointer(obj, v, opaque, print_chr, name, errp);
+}
+
+static void set_chr(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_chr, name, errp);
+}
+
+PropertyInfo qdev_prop_chr = {
+ .name = "chr",
+ .get = get_chr,
+ .set = set_chr,
+ .release = release_chr,
+};
+
+/* --- netdev device --- */
+
+static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
+{
+ NetClientState *netdev = qemu_find_netdev(str);
+
+ if (netdev == NULL) {
+ return -ENOENT;
+ }
+ if (netdev->peer) {
+ return -EEXIST;
+ }
+ *ptr = netdev;
+ return 0;
+}
+
+static const char *print_netdev(void *ptr)
+{
+ NetClientState *netdev = ptr;
+
+ return netdev->name ? netdev->name : "";
+}
+
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ get_pointer(obj, v, opaque, print_netdev, name, errp);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_netdev, name, errp);
+}
+
+PropertyInfo qdev_prop_netdev = {
+ .name = "netdev",
+ .get = get_netdev,
+ .set = set_netdev,
+};
+
+void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
+{
+ qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
+ if (nd->netdev)
+ qdev_prop_set_netdev(dev, "netdev", nd->netdev);
+ if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
+ object_property_find(OBJECT(dev), "vectors", NULL)) {
+ qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
+ }
+ nd->instantiated = 1;
+}
+
+/* --- vlan --- */
+
+static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+ NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (*ptr) {
+ int id;
+ if (!net_hub_id_for_client(*ptr, &id)) {
+ return snprintf(dest, len, "%d", id);
+ }
+ }
+
+ return snprintf(dest, len, "<null>");
+}
+
+static void get_vlan(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+ int32_t id = -1;
+
+ if (*ptr) {
+ int hub_id;
+ if (!net_hub_id_for_client(*ptr, &hub_id)) {
+ id = hub_id;
+ }
+ }
+
+ visit_type_int32(v, &id, name, errp);
+}
+
+static void set_vlan(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+ Error *local_err = NULL;
+ int32_t id;
+ NetClientState *hubport;
+
+ if (dev->state != DEV_STATE_CREATED) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_int32(v, &id, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ if (id == -1) {
+ *ptr = NULL;
+ return;
+ }
+
+ hubport = net_hub_port_find(id);
+ if (!hubport) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+ name, prop->info->name);
+ return;
+ }
+ *ptr = hubport;
+}
+
+PropertyInfo qdev_prop_vlan = {
+ .name = "vlan",
+ .print = print_vlan,
+ .get = get_vlan,
+ .set = set_vlan,
+};
+
+
+int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
+{
+ Error *errp = NULL;
+ const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
+ object_property_set_str(OBJECT(dev), bdrv_name,
+ name, &errp);
+ if (errp) {
+ qerror_report_err(errp);
+ error_free(errp);
+ return -1;
+ }
+ return 0;
+}
+
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
+{
+ if (qdev_prop_set_drive(dev, name, value) < 0) {
+ exit(1);
+ }
+}
+
+void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
+{
+ Error *errp = NULL;
+ assert(!value || value->label);
+ object_property_set_str(OBJECT(dev),
+ value ? value->label : "", name, &errp);
+ assert_no_error(errp);
+}
+
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
+{
+ Error *errp = NULL;
+ assert(!value || value->name);
+ object_property_set_str(OBJECT(dev),
+ value ? value->name : "", name, &errp);
+ assert_no_error(errp);
+}
+
+static int qdev_add_one_global(QemuOpts *opts, void *opaque)
+{
+ GlobalProperty *g;
+
+ g = g_malloc0(sizeof(*g));
+ g->driver = qemu_opt_get(opts, "driver");
+ g->property = qemu_opt_get(opts, "property");
+ g->value = qemu_opt_get(opts, "value");
+ qdev_prop_register_global(g);
+ return 0;
+}
+
+void qemu_add_globals(void)
+{
+ qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
+}
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 81d901c..917d986 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
return ptr;
}
-static void get_pointer(Object *obj, Visitor *v, Property *prop,
- const char *(*print)(void *ptr),
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- void **ptr = qdev_get_prop_ptr(dev, prop);
- char *p;
-
- p = (char *) (*ptr ? print(*ptr) : "");
- visit_type_str(v, &p, name, errp);
-}
-
-static void set_pointer(Object *obj, Visitor *v, Property *prop,
- int (*parse)(DeviceState *dev, const char *str,
- void **ptr),
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Error *local_err = NULL;
- void **ptr = qdev_get_prop_ptr(dev, prop);
- char *str;
- int ret;
-
- 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 (!*str) {
- g_free(str);
- *ptr = NULL;
- return;
- }
- ret = parse(dev, str, ptr);
- error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
- g_free(str);
-}
-
static void get_enum(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -476,227 +433,6 @@ PropertyInfo qdev_prop_string = {
.set = set_string,
};
-/* --- drive --- */
-
-static int parse_drive(DeviceState *dev, const char *str, void **ptr)
-{
- BlockDriverState *bs;
-
- bs = bdrv_find(str);
- if (bs == NULL)
- return -ENOENT;
- if (bdrv_attach_dev(bs, dev) < 0)
- return -EEXIST;
- *ptr = bs;
- return 0;
-}
-
-static void release_drive(Object *obj, const char *name, void *opaque)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-
- if (*ptr) {
- bdrv_detach_dev(*ptr, dev);
- blockdev_auto_del(*ptr);
- }
-}
-
-static const char *print_drive(void *ptr)
-{
- return bdrv_get_device_name(ptr);
-}
-
-static void get_drive(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- get_pointer(obj, v, opaque, print_drive, name, errp);
-}
-
-static void set_drive(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- set_pointer(obj, v, opaque, parse_drive, name, errp);
-}
-
-PropertyInfo qdev_prop_drive = {
- .name = "drive",
- .get = get_drive,
- .set = set_drive,
- .release = release_drive,
-};
-
-/* --- character device --- */
-
-static int parse_chr(DeviceState *dev, const char *str, void **ptr)
-{
- CharDriverState *chr = qemu_chr_find(str);
- if (chr == NULL) {
- return -ENOENT;
- }
- if (chr->avail_connections < 1) {
- return -EEXIST;
- }
- *ptr = chr;
- --chr->avail_connections;
- return 0;
-}
-
-static void release_chr(Object *obj, const char *name, void *opaque)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-
- if (*ptr) {
- qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
- }
-}
-
-
-static const char *print_chr(void *ptr)
-{
- CharDriverState *chr = ptr;
-
- return chr->label ? chr->label : "";
-}
-
-static void get_chr(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- get_pointer(obj, v, opaque, print_chr, name, errp);
-}
-
-static void set_chr(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- set_pointer(obj, v, opaque, parse_chr, name, errp);
-}
-
-PropertyInfo qdev_prop_chr = {
- .name = "chr",
- .get = get_chr,
- .set = set_chr,
- .release = release_chr,
-};
-
-/* --- netdev device --- */
-
-static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
-{
- NetClientState *netdev = qemu_find_netdev(str);
-
- if (netdev == NULL) {
- return -ENOENT;
- }
- if (netdev->peer) {
- return -EEXIST;
- }
- *ptr = netdev;
- return 0;
-}
-
-static const char *print_netdev(void *ptr)
-{
- NetClientState *netdev = ptr;
-
- return netdev->name ? netdev->name : "";
-}
-
-static void get_netdev(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- get_pointer(obj, v, opaque, print_netdev, name, errp);
-}
-
-static void set_netdev(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- set_pointer(obj, v, opaque, parse_netdev, name, errp);
-}
-
-PropertyInfo qdev_prop_netdev = {
- .name = "netdev",
- .get = get_netdev,
- .set = set_netdev,
-};
-
-/* --- vlan --- */
-
-static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
-
- if (*ptr) {
- int id;
- if (!net_hub_id_for_client(*ptr, &id)) {
- return snprintf(dest, len, "%d", id);
- }
- }
-
- return snprintf(dest, len, "<null>");
-}
-
-static void get_vlan(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
- int32_t id = -1;
-
- if (*ptr) {
- int hub_id;
- if (!net_hub_id_for_client(*ptr, &hub_id)) {
- id = hub_id;
- }
- }
-
- visit_type_int32(v, &id, name, errp);
-}
-
-static void set_vlan(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- int32_t id;
- NetClientState *hubport;
-
- if (dev->state != DEV_STATE_CREATED) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_int32(v, &id, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (id == -1) {
- *ptr = NULL;
- return;
- }
-
- hubport = net_hub_port_find(id);
- if (!hubport) {
- error_set(errp, QERR_INVALID_PARAMETER_VALUE,
- name, prop->info->name);
- return;
- }
- *ptr = hubport;
-}
-
-PropertyInfo qdev_prop_vlan = {
- .name = "vlan",
- .print = print_vlan,
- .get = get_vlan,
- .set = set_vlan,
-};
-
/* --- pointer --- */
/* Not a proper property, just for dirty hacks. TODO Remove it! */
@@ -1158,44 +894,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
assert_no_error(errp);
}
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
-{
- Error *errp = NULL;
- const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
- object_property_set_str(OBJECT(dev), bdrv_name,
- name, &errp);
- if (errp) {
- qerror_report_err(errp);
- error_free(errp);
- return -1;
- }
- return 0;
-}
-
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
-{
- if (qdev_prop_set_drive(dev, name, value) < 0) {
- exit(1);
- }
-}
-void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
-{
- Error *errp = NULL;
- assert(!value || value->label);
- object_property_set_str(OBJECT(dev),
- value ? value->label : "", name, &errp);
- assert_no_error(errp);
-}
-
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
-{
- Error *errp = NULL;
- assert(!value || value->name);
- object_property_set_str(OBJECT(dev),
- value ? value->name : "", name, &errp);
- assert_no_error(errp);
-}
-
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
{
Error *errp = NULL;
@@ -1231,7 +929,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
-static void qdev_prop_register_global(GlobalProperty *prop)
+void qdev_prop_register_global(GlobalProperty *prop)
{
QTAILQ_INSERT_TAIL(&global_props, prop, next);
}
@@ -1263,19 +961,3 @@ void qdev_prop_set_globals(DeviceState *dev)
} while (class);
}
-static int qdev_add_one_global(QemuOpts *opts, void *opaque)
-{
- GlobalProperty *g;
-
- g = g_malloc0(sizeof(*g));
- g->driver = qemu_opt_get(opts, "driver");
- g->property = qemu_opt_get(opts, "property");
- g->value = qemu_opt_get(opts, "value");
- qdev_prop_register_global(g);
- return 0;
-}
-
-void qemu_add_globals(void)
-{
- qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
-}
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 5b046ab..ddcf774 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
/* FIXME: Remove opaque pointer properties. */
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+void qdev_prop_register_global(GlobalProperty *prop);
void qdev_prop_register_global_list(GlobalProperty *props);
void qdev_prop_set_globals(DeviceState *dev);
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
new file mode 100644
index 0000000..93feaee
--- /dev/null
+++ b/hw/qdev-system.c
@@ -0,0 +1,68 @@
+#include "qdev.h"
+
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
+{
+ dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
+ dev, n);
+ dev->num_gpio_in += n;
+}
+
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
+{
+ assert(dev->num_gpio_out == 0);
+ dev->num_gpio_out = n;
+ dev->gpio_out = pins;
+}
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
+{
+ assert(n >= 0 && n < dev->num_gpio_in);
+ return dev->gpio_in[n];
+}
+
+void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
+{
+ assert(n >= 0 && n < dev->num_gpio_out);
+ dev->gpio_out[n] = pin;
+}
+
+/* Create a new device. This only initializes the device state structure
+ and allows properties to be set. qdev_init should be called to
+ initialize the actual device emulation. */
+DeviceState *qdev_create(BusState *bus, const char *name)
+{
+ DeviceState *dev;
+
+ dev = qdev_try_create(bus, name);
+ if (!dev) {
+ if (bus) {
+ hw_error("Unknown device '%s' for bus '%s'\n", name,
+ object_get_typename(OBJECT(bus)));
+ } else {
+ hw_error("Unknown device '%s' for default sysbus\n", name);
+ }
+ }
+
+ return dev;
+}
+
+DeviceState *qdev_try_create(BusState *bus, const char *type)
+{
+ DeviceState *dev;
+
+ if (object_class_by_name(type) == NULL) {
+ return NULL;
+ }
+ dev = DEVICE(object_new(type));
+ if (!dev) {
+ return NULL;
+ }
+
+ if (!bus) {
+ bus = sysbus_get_default();
+ }
+
+ qdev_set_parent_bus(dev, bus);
+
+ return dev;
+}
diff --git a/hw/qdev.c b/hw/qdev.c
index 7ddcd24..ee19dd5 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -25,7 +25,6 @@
inherit from a particular bus (e.g. PCI or I2C) rather than
this API directly. */
-#include "net.h"
#include "qdev.h"
#include "sysemu.h"
#include "error.h"
@@ -99,47 +98,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
bus_add_child(bus, dev);
}
-/* Create a new device. This only initializes the device state structure
- and allows properties to be set. qdev_init should be called to
- initialize the actual device emulation. */
-DeviceState *qdev_create(BusState *bus, const char *name)
-{
- DeviceState *dev;
-
- dev = qdev_try_create(bus, name);
- if (!dev) {
- if (bus) {
- hw_error("Unknown device '%s' for bus '%s'\n", name,
- object_get_typename(OBJECT(bus)));
- } else {
- hw_error("Unknown device '%s' for default sysbus\n", name);
- }
- }
-
- return dev;
-}
-
-DeviceState *qdev_try_create(BusState *bus, const char *type)
-{
- DeviceState *dev;
-
- if (object_class_by_name(type) == NULL) {
- return NULL;
- }
- dev = DEVICE(object_new(type));
- if (!dev) {
- return NULL;
- }
-
- if (!bus) {
- bus = sysbus_get_default();
- }
-
- qdev_set_parent_bus(dev, bus);
-
- return 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.
@@ -284,44 +242,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
return dev->parent_bus;
}
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
-{
- dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
- dev, n);
- dev->num_gpio_in += n;
-}
-
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
-{
- assert(dev->num_gpio_out == 0);
- dev->num_gpio_out = n;
- dev->gpio_out = pins;
-}
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
-{
- assert(n >= 0 && n < dev->num_gpio_in);
- return dev->gpio_in[n];
-}
-
-void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
-{
- assert(n >= 0 && n < dev->num_gpio_out);
- dev->gpio_out[n] = pin;
-}
-
-void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
-{
- qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
- if (nd->netdev)
- qdev_prop_set_netdev(dev, "netdev", nd->netdev);
- if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
- object_property_find(OBJECT(dev), "vectors", NULL)) {
- qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
- }
- nd->instantiated = 1;
-}
-
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
{
BusState *bus;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (2 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
` (7 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
Just to make clear that it's the qdev core code, corresponding to
qdev-core.h.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/Makefile.objs | 2 +-
hw/qdev-core.c | 716 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/qdev.c | 716 -------------------------------------------------------
3 files changed, 717 insertions(+), 717 deletions(-)
create mode 100644 hw/qdev-core.c
delete mode 100644 hw/qdev.c
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 16f23c0..70f2014 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.o qdev-properties.o qdev-monitor.o
+common-obj-y += qdev-core.o qdev-properties.o 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
new file mode 100644
index 0000000..ee19dd5
--- /dev/null
+++ b/hw/qdev-core.c
@@ -0,0 +1,716 @@
+/*
+ * 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 "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;
+
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ return dc->vmsd;
+}
+
+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);
+ }
+
+ if (qdev_get_vmsd(dev)) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+ dev->instance_id_alias,
+ dev->alias_required_for_version);
+ }
+ 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 if (bus != sysbus_get_default()) {
+ /* TODO: once all bus devices are qdevified,
+ only reset handler for main_system_bus should be registered here. */
+ qemu_register_reset(qbus_reset_all_fn, bus);
+ }
+}
+
+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);
+ }
+ if (qdev_get_vmsd(dev)) {
+ vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+ }
+ if (dc->exit) {
+ dc->exit(dev);
+ }
+ if (dev->opts) {
+ qemu_opts_del(dev->opts);
+ }
+ }
+ 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 {
+ assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+ qemu_unregister_reset(qbus_reset_all_fn, bus);
+ }
+ g_free((char *)bus->name);
+}
+
+static 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.c b/hw/qdev.c
deleted file mode 100644
index ee19dd5..0000000
--- a/hw/qdev.c
+++ /dev/null
@@ -1,716 +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 "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;
-
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
-{
- DeviceClass *dc = DEVICE_GET_CLASS(dev);
- return dc->vmsd;
-}
-
-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);
- }
-
- if (qdev_get_vmsd(dev)) {
- vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
- dev->instance_id_alias,
- dev->alias_required_for_version);
- }
- 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 if (bus != sysbus_get_default()) {
- /* TODO: once all bus devices are qdevified,
- only reset handler for main_system_bus should be registered here. */
- qemu_register_reset(qbus_reset_all_fn, bus);
- }
-}
-
-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);
- }
- if (qdev_get_vmsd(dev)) {
- vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
- }
- if (dc->exit) {
- dc->exit(dev);
- }
- if (dev->opts) {
- qemu_opts_del(dev->opts);
- }
- }
- 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 {
- assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
- qemu_unregister_reset(qbus_reset_all_fn, bus);
- }
- g_free((char *)bus->name);
-}
-
-static 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)
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (3 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-17 18:06 ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
` (6 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
Those functions will eventually be moved somewhere else, and won't get
included on *-user.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/qdev-core.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index ee19dd5..92c3021 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -40,6 +40,22 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
return dc->vmsd;
}
+static void qdev_init_vmstate(DeviceState *dev)
+{
+ if (qdev_get_vmsd(dev)) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+ dev->instance_id_alias,
+ dev->alias_required_for_version);
+ }
+}
+
+static void qdev_finalize_vmstate(DeviceState *dev)
+{
+ if (qdev_get_vmsd(dev)) {
+ vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+ }
+}
+
const char *qdev_fw_name(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -126,11 +142,7 @@ int qdev_init(DeviceState *dev)
g_free(name);
}
- if (qdev_get_vmsd(dev)) {
- vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
- dev->instance_id_alias,
- dev->alias_required_for_version);
- }
+ qdev_init_vmstate(dev);
dev->state = DEV_STATE_INITIALIZED;
if (dev->hotplugged) {
device_reset(dev);
@@ -615,9 +627,7 @@ static void device_finalize(Object *obj)
bus = QLIST_FIRST(&dev->child_bus);
qbus_free(bus);
}
- if (qdev_get_vmsd(dev)) {
- vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
- }
+ qdev_finalize_vmstate(dev);
if (dc->exit) {
dc->exit(dev);
}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions
2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
@ 2012-10-17 18:06 ` Anthony Liguori
0 siblings, 0 replies; 27+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:06 UTC (permalink / raw)
To: Eduardo Habkost, qemu-devel
Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
peter.maydell
Eduardo Habkost <ehabkost@redhat.com> writes:
> Those functions will eventually be moved somewhere else, and won't get
> included on *-user.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> hw/qdev-core.c | 26 ++++++++++++++++++--------
> 1 file changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> index ee19dd5..92c3021 100644
> --- a/hw/qdev-core.c
> +++ b/hw/qdev-core.c
> @@ -40,6 +40,22 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
> return dc->vmsd;
> }
>
> +static void qdev_init_vmstate(DeviceState *dev)
> +{
> + if (qdev_get_vmsd(dev)) {
> + vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
> + dev->instance_id_alias,
> + dev->alias_required_for_version);
> + }
> +}
> +
> +static void qdev_finalize_vmstate(DeviceState *dev)
> +{
> + if (qdev_get_vmsd(dev)) {
> + vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> + }
> +}
> +
You're stubbing at the wrong level. The place to implement stubs ought
to be vmstate_register/vmstate_unregister.
Regards,
Anthony Liguori
> const char *qdev_fw_name(DeviceState *dev)
> {
> DeviceClass *dc = DEVICE_GET_CLASS(dev);
> @@ -126,11 +142,7 @@ int qdev_init(DeviceState *dev)
> g_free(name);
> }
>
> - if (qdev_get_vmsd(dev)) {
> - vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
> - dev->instance_id_alias,
> - dev->alias_required_for_version);
> - }
> + qdev_init_vmstate(dev);
> dev->state = DEV_STATE_INITIALIZED;
> if (dev->hotplugged) {
> device_reset(dev);
> @@ -615,9 +627,7 @@ static void device_finalize(Object *obj)
> bus = QLIST_FIRST(&dev->child_bus);
> qbus_free(bus);
> }
> - if (qdev_get_vmsd(dev)) {
> - vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> - }
> + qdev_finalize_vmstate(dev);
> if (dc->exit) {
> dc->exit(dev);
> }
> --
> 1.7.11.7
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (4 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
` (5 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
Add GCC_WEAK symbols to qdev-core.c, so that qdev-core.o can be used
without qdev-system.o (i.e. by *-user).
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
- Add GCC_WEAK_DECL to function declarations
---
hw/qdev-core.c | 23 +++++++----------------
hw/qdev-core.h | 2 ++
hw/qdev-system.c | 22 ++++++++++++++++++++++
3 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index 92c3021..af0af52 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -34,26 +34,17 @@ int qdev_hotplug = 0;
static bool qdev_hot_added = false;
static bool qdev_hot_removed = false;
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
-{
- DeviceClass *dc = DEVICE_GET_CLASS(dev);
- return dc->vmsd;
-}
-
-static void qdev_init_vmstate(DeviceState *dev)
+/* 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)
{
- if (qdev_get_vmsd(dev)) {
- vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
- dev->instance_id_alias,
- dev->alias_required_for_version);
- }
}
-static void qdev_finalize_vmstate(DeviceState *dev)
+void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
{
- if (qdev_get_vmsd(dev)) {
- vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
- }
}
const char *qdev_fw_name(DeviceState *dev)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fce9e22..89c54d5 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -223,6 +223,8 @@ void qdev_machine_init(void);
void device_reset(DeviceState *dev);
const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
+void GCC_WEAK_DECL qdev_init_vmstate(DeviceState *dev);
+void GCC_WEAK_DECL qdev_finalize_vmstate(DeviceState *dev);
const char *qdev_fw_name(DeviceState *dev);
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
index 93feaee..0c00ab3 100644
--- a/hw/qdev-system.c
+++ b/hw/qdev-system.c
@@ -66,3 +66,25 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
return dev;
}
+
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ return dc->vmsd;
+}
+
+void qdev_init_vmstate(DeviceState *dev)
+{
+ if (qdev_get_vmsd(dev)) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+ dev->instance_id_alias,
+ dev->alias_required_for_version);
+ }
+}
+
+void qdev_finalize_vmstate(DeviceState *dev)
+{
+ if (qdev_get_vmsd(dev)) {
+ vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+ }
+}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (5 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-17 18:08 ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
` (4 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
The reset register/unregister code is specific to qemu-system-*, so
isolate it so it can be moved to qdev-system.c.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/qdev-core.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index af0af52..a105679 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
{
}
+static void qbus_register_reset(BusState *bus)
+{
+ if (bus != sysbus_get_default()) {
+ /* TODO: once all bus devices are qdevified,
+ only reset handler for main_system_bus should be registered here. */
+ qemu_register_reset(qbus_reset_all_fn, bus);
+ }
+}
+
+static void qbus_unregister_reset(BusState *bus)
+{
+ assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+ qemu_unregister_reset(qbus_reset_all_fn, bus);
+}
+
const char *qdev_fw_name(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
bus->parent->num_child_bus++;
object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
- } else if (bus != sysbus_get_default()) {
- /* TODO: once all bus devices are qdevified,
- only reset handler for main_system_bus should be registered here. */
- qemu_register_reset(qbus_reset_all_fn, bus);
+ } else {
+ qbus_register_reset(bus);
}
}
@@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
QLIST_REMOVE(bus, sibling);
bus->parent->num_child_bus--;
} else {
- assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
- qemu_unregister_reset(qbus_reset_all_fn, bus);
+ qbus_unregister_reset(bus);
}
g_free((char *)bus->name);
}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
@ 2012-10-17 18:08 ` Anthony Liguori
2012-10-17 18:32 ` Eduardo Habkost
2012-10-23 14:56 ` Eduardo Habkost
0 siblings, 2 replies; 27+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:08 UTC (permalink / raw)
To: Eduardo Habkost, qemu-devel
Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
peter.maydell
Eduardo Habkost <ehabkost@redhat.com> writes:
> The reset register/unregister code is specific to qemu-system-*, so
> isolate it so it can be moved to qdev-system.c.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> hw/qdev-core.c | 24 ++++++++++++++++++------
> 1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> index af0af52..a105679 100644
> --- a/hw/qdev-core.c
> +++ b/hw/qdev-core.c
> @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> {
> }
>
> +static void qbus_register_reset(BusState *bus)
> +{
> + if (bus != sysbus_get_default()) {
> + /* TODO: once all bus devices are qdevified,
> + only reset handler for main_system_bus should be registered here. */
> + qemu_register_reset(qbus_reset_all_fn, bus);
> + }
> +}
> +
> +static void qbus_unregister_reset(BusState *bus)
> +{
> + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> + qemu_unregister_reset(qbus_reset_all_fn, bus);
> +}
> +
Again, I'd suggest stubbing out qemu_[un]register_reset instead of
trying to cope with it's users.
Regards,
Anthony Liguori
> const char *qdev_fw_name(DeviceState *dev)
> {
> DeviceClass *dc = DEVICE_GET_CLASS(dev);
> @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> bus->parent->num_child_bus++;
> object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> - } else if (bus != sysbus_get_default()) {
> - /* TODO: once all bus devices are qdevified,
> - only reset handler for main_system_bus should be registered here. */
> - qemu_register_reset(qbus_reset_all_fn, bus);
> + } else {
> + qbus_register_reset(bus);
> }
> }
>
> @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> QLIST_REMOVE(bus, sibling);
> bus->parent->num_child_bus--;
> } else {
> - assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> - qemu_unregister_reset(qbus_reset_all_fn, bus);
> + qbus_unregister_reset(bus);
> }
> g_free((char *)bus->name);
> }
> --
> 1.7.11.7
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-17 18:08 ` Anthony Liguori
@ 2012-10-17 18:32 ` Eduardo Habkost
2012-10-18 14:51 ` Andreas Färber
2012-10-23 14:56 ` Eduardo Habkost
1 sibling, 1 reply; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-17 18:32 UTC (permalink / raw)
To: Anthony Liguori
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Igor Mammedov, Andreas Färber
On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
>
> > The reset register/unregister code is specific to qemu-system-*, so
> > isolate it so it can be moved to qdev-system.c.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > hw/qdev-core.c | 24 ++++++++++++++++++------
> > 1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > index af0af52..a105679 100644
> > --- a/hw/qdev-core.c
> > +++ b/hw/qdev-core.c
> > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> > {
> > }
> >
> > +static void qbus_register_reset(BusState *bus)
> > +{
> > + if (bus != sysbus_get_default()) {
> > + /* TODO: once all bus devices are qdevified,
> > + only reset handler for main_system_bus should be registered here. */
> > + qemu_register_reset(qbus_reset_all_fn, bus);
> > + }
> > +}
> > +
> > +static void qbus_unregister_reset(BusState *bus)
> > +{
> > + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > + qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +}
> > +
>
> Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> trying to cope with it's users.
I agree on the vmstate case (the other patch), but on this case this
would require implementing a sysbus_get_default() stub as well. Skipping
the whole check for sysbus_get_default() on *-user looks like the right
thing to do, to me.
Anyway, I am actually wondering if we really need to include the qbus
code on *-user. Do you think *-user will eventually use BusState objects
too, or it will use only DeviceState objects in the foreseeable future?
>
> Regards,
>
> Anthony Liguori
>
> > const char *qdev_fw_name(DeviceState *dev)
> > {
> > DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> > QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> > bus->parent->num_child_bus++;
> > object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> > - } else if (bus != sysbus_get_default()) {
> > - /* TODO: once all bus devices are qdevified,
> > - only reset handler for main_system_bus should be registered here. */
> > - qemu_register_reset(qbus_reset_all_fn, bus);
> > + } else {
> > + qbus_register_reset(bus);
> > }
> > }
> >
> > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> > QLIST_REMOVE(bus, sibling);
> > bus->parent->num_child_bus--;
> > } else {
> > - assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > - qemu_unregister_reset(qbus_reset_all_fn, bus);
> > + qbus_unregister_reset(bus);
> > }
> > g_free((char *)bus->name);
> > }
> > --
> > 1.7.11.7
--
Eduardo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-17 18:32 ` Eduardo Habkost
@ 2012-10-18 14:51 ` Andreas Färber
0 siblings, 0 replies; 27+ messages in thread
From: Andreas Färber @ 2012-10-18 14:51 UTC (permalink / raw)
To: Eduardo Habkost
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Anthony Liguori, Igor Mammedov
Am 17.10.2012 20:32, schrieb Eduardo Habkost:
> Anyway, I am actually wondering if we really need to include the qbus
> code on *-user. Do you think *-user will eventually use BusState objects
> too, or it will use only DeviceState objects in the foreseeable future?
My understanding is that we want DeviceState as a consistent parent and
its static properties mechanisms. Most of it, including BusState, is
going to be unused. At runtime *-user only needs the TCG fields in
CPUArchState plus the name -> object mapping mechanisms of the day for
initialization.
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-17 18:08 ` Anthony Liguori
2012-10-17 18:32 ` Eduardo Habkost
@ 2012-10-23 14:56 ` Eduardo Habkost
2012-10-24 2:43 ` Eduardo Habkost
1 sibling, 1 reply; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-23 14:56 UTC (permalink / raw)
To: Anthony Liguori
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Igor Mammedov, Andreas Färber
On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
>
> > The reset register/unregister code is specific to qemu-system-*, so
> > isolate it so it can be moved to qdev-system.c.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > hw/qdev-core.c | 24 ++++++++++++++++++------
> > 1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > index af0af52..a105679 100644
> > --- a/hw/qdev-core.c
> > +++ b/hw/qdev-core.c
> > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> > {
> > }
> >
> > +static void qbus_register_reset(BusState *bus)
> > +{
> > + if (bus != sysbus_get_default()) {
> > + /* TODO: once all bus devices are qdevified,
> > + only reset handler for main_system_bus should be registered here. */
> > + qemu_register_reset(qbus_reset_all_fn, bus);
> > + }
> > +}
> > +
> > +static void qbus_unregister_reset(BusState *bus)
> > +{
> > + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > + qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +}
> > +
>
> Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> trying to cope with it's users.
I was going to implement it the way you suggested. But then I noticed
that I _ *-user will need to request the devices to be reset once, too
(even if the only devices available are the CPU objects).
On the next version, I will move the reset-function list from vl.c to
qdev-core.c. Code that uses qdev will need to take care of calling
qemu_devices_reset() eventually (qemu-system does that on vl.c *-user
will need to that somewhere else).
>
> Regards,
>
> Anthony Liguori
>
> > const char *qdev_fw_name(DeviceState *dev)
> > {
> > DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> > QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> > bus->parent->num_child_bus++;
> > object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> > - } else if (bus != sysbus_get_default()) {
> > - /* TODO: once all bus devices are qdevified,
> > - only reset handler for main_system_bus should be registered here. */
> > - qemu_register_reset(qbus_reset_all_fn, bus);
> > + } else {
> > + qbus_register_reset(bus);
> > }
> > }
> >
> > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> > QLIST_REMOVE(bus, sibling);
> > bus->parent->num_child_bus--;
> > } else {
> > - assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > - qemu_unregister_reset(qbus_reset_all_fn, bus);
> > + qbus_unregister_reset(bus);
> > }
> > g_free((char *)bus->name);
> > }
> > --
> > 1.7.11.7
>
--
Eduardo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
2012-10-23 14:56 ` Eduardo Habkost
@ 2012-10-24 2:43 ` Eduardo Habkost
0 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-24 2:43 UTC (permalink / raw)
To: Anthony Liguori
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Igor Mammedov, Andreas Färber
On Tue, Oct 23, 2012 at 12:56:18PM -0200, Eduardo Habkost wrote:
> On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> > Eduardo Habkost <ehabkost@redhat.com> writes:
> >
> > > The reset register/unregister code is specific to qemu-system-*, so
> > > isolate it so it can be moved to qdev-system.c.
> > >
> > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > > ---
> > > hw/qdev-core.c | 24 ++++++++++++++++++------
> > > 1 file changed, 18 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > > index af0af52..a105679 100644
> > > --- a/hw/qdev-core.c
> > > +++ b/hw/qdev-core.c
> > > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> > > {
> > > }
> > >
> > > +static void qbus_register_reset(BusState *bus)
> > > +{
> > > + if (bus != sysbus_get_default()) {
> > > + /* TODO: once all bus devices are qdevified,
> > > + only reset handler for main_system_bus should be registered here. */
> > > + qemu_register_reset(qbus_reset_all_fn, bus);
> > > + }
> > > +}
> > > +
> > > +static void qbus_unregister_reset(BusState *bus)
> > > +{
> > > + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > > + qemu_unregister_reset(qbus_reset_all_fn, bus);
> > > +}
> > > +
> >
> > Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> > trying to cope with it's users.
>
> I was going to implement it the way you suggested. But then I noticed
> that I _ *-user will need to request the devices to be reset once, too
> (even if the only devices available are the CPU objects).
>
> On the next version, I will move the reset-function list from vl.c to
> qdev-core.c. Code that uses qdev will need to take care of calling
> qemu_devices_reset() eventually (qemu-system does that on vl.c *-user
> will need to that somewhere else).
I don't usually reply to myself to correct typos, but the message above
was almost impossible to parse. So, rewriting it:
I was going to implement it the way you suggested. But then I noticed
that *-user will need to request the devices to be reset once, too
(even if the only devices available are the CPU objects).
On the next version, I will move the reset-function list from vl.c to
qdev-core.c. Code that uses qdev will need to take care of calling
qemu_devices_reset() eventually (qemu-system does that on vl.c, and
*-user will need to that somewhere else).
>
> >
> > Regards,
> >
> > Anthony Liguori
> >
> > > const char *qdev_fw_name(DeviceState *dev)
> > > {
> > > DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> > > QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> > > bus->parent->num_child_bus++;
> > > object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> > > - } else if (bus != sysbus_get_default()) {
> > > - /* TODO: once all bus devices are qdevified,
> > > - only reset handler for main_system_bus should be registered here. */
> > > - qemu_register_reset(qbus_reset_all_fn, bus);
> > > + } else {
> > > + qbus_register_reset(bus);
> > > }
> > > }
> > >
> > > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> > > QLIST_REMOVE(bus, sibling);
> > > bus->parent->num_child_bus--;
> > > } else {
> > > - assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > > - qemu_unregister_reset(qbus_reset_all_fn, bus);
> > > + qbus_unregister_reset(bus);
> > > }
> > > g_free((char *)bus->name);
> > > }
> > > --
> > > 1.7.11.7
> >
>
> --
> Eduardo
>
--
Eduardo
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (6 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
` (3 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
Also, add weak symbols that will be used if qdev-system.o is not
compiled in (i.e. on *-user).
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
- Add GCC_WEAK_DECL to function declarations
---
hw/qdev-core.c | 16 +++++++---------
hw/qdev-core.h | 3 +++
hw/qdev-system.c | 15 +++++++++++++++
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index a105679..a756e07 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -47,19 +47,17 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
{
}
-static void qbus_register_reset(BusState *bus)
+/* 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)
{
- if (bus != sysbus_get_default()) {
- /* TODO: once all bus devices are qdevified,
- only reset handler for main_system_bus should be registered here. */
- qemu_register_reset(qbus_reset_all_fn, bus);
- }
}
-static void qbus_unregister_reset(BusState *bus)
+void GCC_WEAK qbus_unregister_reset(BusState *bus)
{
- assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
- qemu_unregister_reset(qbus_reset_all_fn, bus);
}
const char *qdev_fw_name(DeviceState *dev)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 89c54d5..e030fff 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -226,6 +226,9 @@ const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
void GCC_WEAK_DECL qdev_init_vmstate(DeviceState *dev);
void GCC_WEAK_DECL qdev_finalize_vmstate(DeviceState *dev);
+void GCC_WEAK_DECL qbus_register_reset(BusState *bus);
+void GCC_WEAK_DECL qbus_unregister_reset(BusState *bus);
+
const char *qdev_fw_name(DeviceState *dev);
Object *qdev_get_machine(void);
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
index 0c00ab3..21074a0 100644
--- a/hw/qdev-system.c
+++ b/hw/qdev-system.c
@@ -88,3 +88,18 @@ void qdev_finalize_vmstate(DeviceState *dev)
vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
}
}
+
+void qbus_register_reset(BusState *bus)
+{
+ if (bus != sysbus_get_default()) {
+ /* TODO: once all bus devices are qdevified,
+ only reset handler for main_system_bus should be registered here. */
+ qemu_register_reset(qbus_reset_all_fn, bus);
+ }
+}
+
+void qbus_unregister_reset(BusState *bus)
+{
+ assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+ qemu_unregister_reset(qbus_reset_all_fn, bus);
+}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (7 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-17 18:08 ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
` (2 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
From: Igor Mammedov <imammedo@redhat.com>
it's necessary for making CPU child of DEVICE without
causing circular header deps.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
Changes v2 -> v3:
imammedo: sysemu.h doesn't need irq.h since 013c2f150
---
hw/arm-misc.h | 1 +
hw/bt.h | 2 ++
hw/devices.h | 2 ++
hw/omap.h | 1 +
hw/soc_dma.h | 1 +
hw/xen.h | 1 +
qemu-common.h | 1 -
7 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index bdd8fec..b13aa59 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -12,6 +12,7 @@
#define ARM_MISC_H 1
#include "memory.h"
+#include "hw/irq.h"
/* The CPU is also modeled as an interrupt controller. */
#define ARM_PIC_CPU_IRQ 0
diff --git a/hw/bt.h b/hw/bt.h
index a48b8d4..ebf6a37 100644
--- a/hw/bt.h
+++ b/hw/bt.h
@@ -23,6 +23,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "hw/irq.h"
+
/* BD Address */
typedef struct {
uint8_t b[6];
diff --git a/hw/devices.h b/hw/devices.h
index 1a55c1e..c60bcab 100644
--- a/hw/devices.h
+++ b/hw/devices.h
@@ -1,6 +1,8 @@
#ifndef QEMU_DEVICES_H
#define QEMU_DEVICES_H
+#include "hw/irq.h"
+
/* ??? Not all users of this file can include cpu-common.h. */
struct MemoryRegion;
diff --git a/hw/omap.h b/hw/omap.h
index 413851b..8b08462 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -19,6 +19,7 @@
#ifndef hw_omap_h
#include "memory.h"
# define hw_omap_h "omap.h"
+#include "hw/irq.h"
# define OMAP_EMIFS_BASE 0x00000000
# define OMAP2_Q0_BASE 0x00000000
diff --git a/hw/soc_dma.h b/hw/soc_dma.h
index 904b26c..e386ace 100644
--- a/hw/soc_dma.h
+++ b/hw/soc_dma.h
@@ -19,6 +19,7 @@
*/
#include "memory.h"
+#include "hw/irq.h"
struct soc_dma_s;
struct soc_dma_ch_s;
diff --git a/hw/xen.h b/hw/xen.h
index d14e92d..e3cca7f 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -8,6 +8,7 @@
*/
#include <inttypes.h>
+#include "hw/irq.h"
#include "qemu-common.h"
/* xen-machine.c */
diff --git a/qemu-common.h b/qemu-common.h
index b54612b..95585b8 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -286,7 +286,6 @@ typedef struct PCIEPort PCIEPort;
typedef struct PCIESlot PCIESlot;
typedef struct MSIMessage MSIMessage;
typedef struct SerialState SerialState;
-typedef struct IRQState *qemu_irq;
typedef struct PCMCIACardState PCMCIACardState;
typedef struct MouseTransformInfo MouseTransformInfo;
typedef struct uWireSlave uWireSlave;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h
2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
@ 2012-10-17 18:08 ` Anthony Liguori
0 siblings, 0 replies; 27+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:08 UTC (permalink / raw)
To: Eduardo Habkost, qemu-devel
Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
peter.maydell
Eduardo Habkost <ehabkost@redhat.com> writes:
> From: Igor Mammedov <imammedo@redhat.com>
>
> it's necessary for making CPU child of DEVICE without
> causing circular header deps.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Regards,
Anthony Liguori
> ---
> Changes v2 -> v3:
> imammedo: sysemu.h doesn't need irq.h since 013c2f150
> ---
> hw/arm-misc.h | 1 +
> hw/bt.h | 2 ++
> hw/devices.h | 2 ++
> hw/omap.h | 1 +
> hw/soc_dma.h | 1 +
> hw/xen.h | 1 +
> qemu-common.h | 1 -
> 7 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/hw/arm-misc.h b/hw/arm-misc.h
> index bdd8fec..b13aa59 100644
> --- a/hw/arm-misc.h
> +++ b/hw/arm-misc.h
> @@ -12,6 +12,7 @@
> #define ARM_MISC_H 1
>
> #include "memory.h"
> +#include "hw/irq.h"
>
> /* The CPU is also modeled as an interrupt controller. */
> #define ARM_PIC_CPU_IRQ 0
> diff --git a/hw/bt.h b/hw/bt.h
> index a48b8d4..ebf6a37 100644
> --- a/hw/bt.h
> +++ b/hw/bt.h
> @@ -23,6 +23,8 @@
> * along with this program; if not, see <http://www.gnu.org/licenses/>.
> */
>
> +#include "hw/irq.h"
> +
> /* BD Address */
> typedef struct {
> uint8_t b[6];
> diff --git a/hw/devices.h b/hw/devices.h
> index 1a55c1e..c60bcab 100644
> --- a/hw/devices.h
> +++ b/hw/devices.h
> @@ -1,6 +1,8 @@
> #ifndef QEMU_DEVICES_H
> #define QEMU_DEVICES_H
>
> +#include "hw/irq.h"
> +
> /* ??? Not all users of this file can include cpu-common.h. */
> struct MemoryRegion;
>
> diff --git a/hw/omap.h b/hw/omap.h
> index 413851b..8b08462 100644
> --- a/hw/omap.h
> +++ b/hw/omap.h
> @@ -19,6 +19,7 @@
> #ifndef hw_omap_h
> #include "memory.h"
> # define hw_omap_h "omap.h"
> +#include "hw/irq.h"
>
> # define OMAP_EMIFS_BASE 0x00000000
> # define OMAP2_Q0_BASE 0x00000000
> diff --git a/hw/soc_dma.h b/hw/soc_dma.h
> index 904b26c..e386ace 100644
> --- a/hw/soc_dma.h
> +++ b/hw/soc_dma.h
> @@ -19,6 +19,7 @@
> */
>
> #include "memory.h"
> +#include "hw/irq.h"
>
> struct soc_dma_s;
> struct soc_dma_ch_s;
> diff --git a/hw/xen.h b/hw/xen.h
> index d14e92d..e3cca7f 100644
> --- a/hw/xen.h
> +++ b/hw/xen.h
> @@ -8,6 +8,7 @@
> */
> #include <inttypes.h>
>
> +#include "hw/irq.h"
> #include "qemu-common.h"
>
> /* xen-machine.c */
> diff --git a/qemu-common.h b/qemu-common.h
> index b54612b..95585b8 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -286,7 +286,6 @@ typedef struct PCIEPort PCIEPort;
> typedef struct PCIESlot PCIESlot;
> typedef struct MSIMessage MSIMessage;
> typedef struct SerialState SerialState;
> -typedef struct IRQState *qemu_irq;
> typedef struct PCMCIACardState PCMCIACardState;
> typedef struct MouseTransformInfo MouseTransformInfo;
> typedef struct uWireSlave uWireSlave;
> --
> 1.7.11.7
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (8 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
This way, the files can be moved to the qom/ directory as-is.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/qdev-core.c | 2 +-
hw/qdev-properties.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index a756e07..fbb7cb5 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -25,7 +25,7 @@
inherit from a particular bus (e.g. PCI or I2C) rather than
this API directly. */
-#include "qdev.h"
+#include "hw/qdev.h"
#include "sysemu.h"
#include "error.h"
#include "qapi/qapi-visit-core.h"
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 917d986..2e82cb9 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,5 +1,5 @@
#include "net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
#include "qerror.h"
#include "blockdev.h"
#include "hw/block-common.h"
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (9 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
2012-10-17 18:11 ` Anthony Liguori
2012-10-22 12:36 ` Igor Mammedov
2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost
11 siblings, 2 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
The code depends on some functions from qemu-option.o, so add
qemu-option.o to universal-obj-y to make sure it's included.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Makefile.objs | 3 +
hw/Makefile.objs | 2 +-
hw/qdev-core.c | 727 -------------------------------------
hw/qdev-properties.c | 963 --------------------------------------------------
qom/Makefile.objs | 2 +-
qom/qdev-core.c | 727 +++++++++++++++++++++++++++++++++++++
qom/qdev-properties.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 1695 insertions(+), 1692 deletions(-)
delete mode 100644 hw/qdev-core.c
delete mode 100644 hw/qdev-properties.c
create mode 100644 qom/qdev-core.c
create mode 100644 qom/qdev-properties.c
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
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
@ 2012-10-17 18:11 ` Anthony Liguori
2012-10-17 18:18 ` Eduardo Habkost
2012-10-17 19:21 ` Peter Maydell
2012-10-22 12:36 ` Igor Mammedov
1 sibling, 2 replies; 27+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:11 UTC (permalink / raw)
To: Eduardo Habkost, qemu-devel
Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
peter.maydell
Eduardo Habkost <ehabkost@redhat.com> writes:
> The code depends on some functions from qemu-option.o, so add
> qemu-option.o to universal-obj-y to make sure it's included.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Makefile.objs | 3 +
> hw/Makefile.objs | 2 +-
> hw/qdev-core.c | 727 -------------------------------------
> hw/qdev-properties.c | 963 --------------------------------------------------
> qom/Makefile.objs | 2 +-
> qom/qdev-core.c | 727 +++++++++++++++++++++++++++++++++++++
> qom/qdev-properties.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 1695 insertions(+), 1692 deletions(-)
> delete mode 100644 hw/qdev-core.c
> delete mode 100644 hw/qdev-properties.c
> create mode 100644 qom/qdev-core.c
> create mode 100644 qom/qdev-properties.c
Stick the following in your .git/config:
[diff]
renames = true
It's dangerously close to bike-shedding, but i don't think qdev belongs
in qom/. It's not core infrastructure. It's the device base class and
belongs IMHO in hw/.
Regards,
Anthony Liguori
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 74b3542..fcd1336 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -16,6 +16,9 @@ universal-obj-y += $(qobject-obj-y)
> qom-obj-y = qom/
>
> universal-obj-y += $(qom-obj-y)
> +# QOM qdev-core.o requires qemu-option.o:
> +universal-obj-y += qemu-option.o
> +
>
> #######################################################################
> # oslib-obj-y is code depending on the OS (win32 vs posix)
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 70f2014..3ce38d2 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -180,7 +180,7 @@ common-obj-$(CONFIG_SD) += sd.o
> common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
> common-obj-y += bt-hci-csr.o
> common-obj-y += msmouse.o ps2.o
> -common-obj-y += qdev-core.o qdev-properties.o qdev-monitor.o
> +common-obj-y += qdev-monitor.o
> common-obj-y += qdev-system.o qdev-properties-system.o
> common-obj-$(CONFIG_BRLAPI) += baum.o
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> deleted file mode 100644
> index fbb7cb5..0000000
> --- a/hw/qdev-core.c
> +++ /dev/null
> @@ -1,727 +0,0 @@
> -/*
> - * Dynamic device configuration and creation.
> - *
> - * Copyright (c) 2009 CodeSourcery
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -/* The theory here is that it should be possible to create a machine without
> - knowledge of specific devices. Historically board init routines have
> - passed a bunch of arguments to each device, requiring the board know
> - exactly which device it is dealing with. This file provides an abstract
> - API for device configuration and initialization. Devices will generally
> - inherit from a particular bus (e.g. PCI or I2C) rather than
> - this API directly. */
> -
> -#include "hw/qdev.h"
> -#include "sysemu.h"
> -#include "error.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -int qdev_hotplug = 0;
> -static bool qdev_hot_added = false;
> -static bool qdev_hot_removed = false;
> -
> -/* vmstate handling:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> -{
> -}
> -
> -void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> -{
> -}
> -
> -/* reset handler register/unregister:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qbus_register_reset(BusState *bus)
> -{
> -}
> -
> -void GCC_WEAK qbus_unregister_reset(BusState *bus)
> -{
> -}
> -
> -const char *qdev_fw_name(DeviceState *dev)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (dc->fw_name) {
> - return dc->fw_name;
> - }
> -
> - return object_get_typename(OBJECT(dev));
> -}
> -
> -static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> - Error **errp);
> -
> -static void bus_remove_child(BusState *bus, DeviceState *child)
> -{
> - BusChild *kid;
> -
> - QTAILQ_FOREACH(kid, &bus->children, sibling) {
> - if (kid->child == child) {
> - char name[32];
> -
> - snprintf(name, sizeof(name), "child[%d]", kid->index);
> - QTAILQ_REMOVE(&bus->children, kid, sibling);
> - object_property_del(OBJECT(bus), name, NULL);
> - g_free(kid);
> - return;
> - }
> - }
> -}
> -
> -static void bus_add_child(BusState *bus, DeviceState *child)
> -{
> - char name[32];
> - BusChild *kid = g_malloc0(sizeof(*kid));
> -
> - if (qdev_hotplug) {
> - assert(bus->allow_hotplug);
> - }
> -
> - kid->index = bus->max_index++;
> - kid->child = child;
> -
> - QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
> -
> - snprintf(name, sizeof(name), "child[%d]", kid->index);
> - object_property_add_link(OBJECT(bus), name,
> - object_get_typename(OBJECT(child)),
> - (Object **)&kid->child,
> - NULL);
> -}
> -
> -void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
> -{
> - dev->parent_bus = bus;
> - bus_add_child(bus, dev);
> -}
> -
> -/* Initialize a device. Device properties should be set before calling
> - this function. IRQs and MMIO regions should be connected/mapped after
> - calling this function.
> - On failure, destroy the device and return negative value.
> - Return 0 on success. */
> -int qdev_init(DeviceState *dev)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> - int rc;
> -
> - assert(dev->state == DEV_STATE_CREATED);
> -
> - rc = dc->init(dev);
> - if (rc < 0) {
> - qdev_free(dev);
> - return rc;
> - }
> -
> - if (!OBJECT(dev)->parent) {
> - static int unattached_count = 0;
> - gchar *name = g_strdup_printf("device[%d]", unattached_count++);
> -
> - object_property_add_child(container_get(qdev_get_machine(),
> - "/unattached"),
> - name, OBJECT(dev), NULL);
> - g_free(name);
> - }
> -
> - qdev_init_vmstate(dev);
> - dev->state = DEV_STATE_INITIALIZED;
> - if (dev->hotplugged) {
> - device_reset(dev);
> - }
> - return 0;
> -}
> -
> -void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> - int required_for_version)
> -{
> - assert(dev->state == DEV_STATE_CREATED);
> - dev->instance_id_alias = alias_id;
> - dev->alias_required_for_version = required_for_version;
> -}
> -
> -void qdev_unplug(DeviceState *dev, Error **errp)
> -{
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (!dev->parent_bus->allow_hotplug) {
> - error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> - return;
> - }
> - assert(dc->unplug != NULL);
> -
> - qdev_hot_removed = true;
> -
> - if (dc->unplug(dev) < 0) {
> - error_set(errp, QERR_UNDEFINED_ERROR);
> - return;
> - }
> -}
> -
> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> -{
> - device_reset(dev);
> -
> - return 0;
> -}
> -
> -static int qbus_reset_one(BusState *bus, void *opaque)
> -{
> - BusClass *bc = BUS_GET_CLASS(bus);
> - if (bc->reset) {
> - return bc->reset(bus);
> - }
> - return 0;
> -}
> -
> -void qdev_reset_all(DeviceState *dev)
> -{
> - qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -void qbus_reset_all_fn(void *opaque)
> -{
> - BusState *bus = opaque;
> - qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -/* can be used as ->unplug() callback for the simple cases */
> -int qdev_simple_unplug_cb(DeviceState *dev)
> -{
> - /* just zap it */
> - qdev_free(dev);
> - return 0;
> -}
> -
> -
> -/* Like qdev_init(), but terminate program via error_report() instead of
> - returning an error value. This is okay during machine creation.
> - Don't use for hotplug, because there callers need to recover from
> - failure. Exception: if you know the device's init() callback can't
> - fail, then qdev_init_nofail() can't fail either, and is therefore
> - usable even then. But relying on the device implementation that
> - way is somewhat unclean, and best avoided. */
> -void qdev_init_nofail(DeviceState *dev)
> -{
> - const char *typename = object_get_typename(OBJECT(dev));
> -
> - if (qdev_init(dev) < 0) {
> - error_report("Initialization of device %s failed", typename);
> - exit(1);
> - }
> -}
> -
> -/* Unlink device from bus and free the structure. */
> -void qdev_free(DeviceState *dev)
> -{
> - object_delete(OBJECT(dev));
> -}
> -
> -void qdev_machine_creation_done(void)
> -{
> - /*
> - * ok, initial machine setup is done, starting from now we can
> - * only create hotpluggable devices
> - */
> - qdev_hotplug = 1;
> -}
> -
> -bool qdev_machine_modified(void)
> -{
> - return qdev_hot_added || qdev_hot_removed;
> -}
> -
> -BusState *qdev_get_parent_bus(DeviceState *dev)
> -{
> - return dev->parent_bus;
> -}
> -
> -BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> -{
> - BusState *bus;
> -
> - QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> - if (strcmp(name, bus->name) == 0) {
> - return bus;
> - }
> - }
> - return NULL;
> -}
> -
> -int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> - qbus_walkerfn *busfn, void *opaque)
> -{
> - BusChild *kid;
> - int err;
> -
> - if (busfn) {
> - err = busfn(bus, opaque);
> - if (err) {
> - return err;
> - }
> - }
> -
> - QTAILQ_FOREACH(kid, &bus->children, sibling) {
> - err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> - if (err < 0) {
> - return err;
> - }
> - }
> -
> - return 0;
> -}
> -
> -int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> - qbus_walkerfn *busfn, void *opaque)
> -{
> - BusState *bus;
> - int err;
> -
> - if (devfn) {
> - err = devfn(dev, opaque);
> - if (err) {
> - return err;
> - }
> - }
> -
> - QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> - err = qbus_walk_children(bus, devfn, busfn, opaque);
> - if (err < 0) {
> - return err;
> - }
> - }
> -
> - return 0;
> -}
> -
> -DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> -{
> - BusChild *kid;
> - DeviceState *ret;
> - BusState *child;
> -
> - QTAILQ_FOREACH(kid, &bus->children, sibling) {
> - DeviceState *dev = kid->child;
> -
> - if (dev->id && strcmp(dev->id, id) == 0) {
> - return dev;
> - }
> -
> - QLIST_FOREACH(child, &dev->child_bus, sibling) {
> - ret = qdev_find_recursive(child, id);
> - if (ret) {
> - return ret;
> - }
> - }
> - }
> - return NULL;
> -}
> -
> -static void qbus_realize(BusState *bus)
> -{
> - const char *typename = object_get_typename(OBJECT(bus));
> - char *buf;
> - int i,len;
> -
> - if (bus->name) {
> - /* use supplied name */
> - } else if (bus->parent && bus->parent->id) {
> - /* parent device has id -> use it for bus name */
> - len = strlen(bus->parent->id) + 16;
> - buf = g_malloc(len);
> - snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
> - bus->name = buf;
> - } else {
> - /* no id -> use lowercase bus type for bus name */
> - len = strlen(typename) + 16;
> - buf = g_malloc(len);
> - len = snprintf(buf, len, "%s.%d", typename,
> - bus->parent ? bus->parent->num_child_bus : 0);
> - for (i = 0; i < len; i++)
> - buf[i] = qemu_tolower(buf[i]);
> - bus->name = buf;
> - }
> -
> - if (bus->parent) {
> - QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> - bus->parent->num_child_bus++;
> - object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> - } else {
> - qbus_register_reset(bus);
> - }
> -}
> -
> -void qbus_create_inplace(BusState *bus, const char *typename,
> - DeviceState *parent, const char *name)
> -{
> - object_initialize(bus, typename);
> -
> - bus->parent = parent;
> - bus->name = name ? g_strdup(name) : NULL;
> - qbus_realize(bus);
> -}
> -
> -BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
> -{
> - BusState *bus;
> -
> - bus = BUS(object_new(typename));
> - bus->qom_allocated = true;
> -
> - bus->parent = parent;
> - bus->name = name ? g_strdup(name) : NULL;
> - qbus_realize(bus);
> -
> - return bus;
> -}
> -
> -void qbus_free(BusState *bus)
> -{
> - if (bus->qom_allocated) {
> - object_delete(OBJECT(bus));
> - } else {
> - object_finalize(OBJECT(bus));
> - if (bus->glib_allocated) {
> - g_free(bus);
> - }
> - }
> -}
> -
> -static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
> -{
> - BusClass *bc = BUS_GET_CLASS(bus);
> -
> - if (bc->get_fw_dev_path) {
> - return bc->get_fw_dev_path(dev);
> - }
> -
> - return NULL;
> -}
> -
> -static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> -{
> - int l = 0;
> -
> - if (dev && dev->parent_bus) {
> - char *d;
> - l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> - d = bus_get_fw_dev_path(dev->parent_bus, dev);
> - if (d) {
> - l += snprintf(p + l, size - l, "%s", d);
> - g_free(d);
> - } else {
> - l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> - }
> - }
> - l += snprintf(p + l , size - l, "/");
> -
> - return l;
> -}
> -
> -char* qdev_get_fw_dev_path(DeviceState *dev)
> -{
> - char path[128];
> - int l;
> -
> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
> -
> - path[l-1] = '\0';
> -
> - return g_strdup(path);
> -}
> -
> -char *qdev_get_dev_path(DeviceState *dev)
> -{
> - BusClass *bc;
> -
> - if (!dev || !dev->parent_bus) {
> - return NULL;
> - }
> -
> - bc = BUS_GET_CLASS(dev->parent_bus);
> - if (bc->get_dev_path) {
> - return bc->get_dev_path(dev);
> - }
> -
> - return NULL;
> -}
> -
> -/**
> - * Legacy property handling
> - */
> -
> -static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> -
> - char buffer[1024];
> - char *ptr = buffer;
> -
> - prop->info->print(dev, prop, buffer, sizeof(buffer));
> - visit_type_str(v, &ptr, name, errp);
> -}
> -
> -static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - Error *local_err = NULL;
> - char *ptr = NULL;
> - int ret;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &ptr, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - ret = prop->info->parse(dev, prop, ptr);
> - error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> - g_free(ptr);
> -}
> -
> -/**
> - * @qdev_add_legacy_property - adds a legacy property
> - *
> - * Do not use this is new code! Properties added through this interface will
> - * be given names and types in the "legacy" namespace.
> - *
> - * Legacy properties are string versions of other OOM properties. The format
> - * of the string depends on the property type.
> - */
> -void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> - Error **errp)
> -{
> - gchar *name, *type;
> -
> - /* Register pointer properties as legacy properties */
> - if (!prop->info->print && !prop->info->parse &&
> - (prop->info->set || prop->info->get)) {
> - return;
> - }
> -
> - name = g_strdup_printf("legacy-%s", prop->name);
> - type = g_strdup_printf("legacy<%s>",
> - prop->info->legacy_name ?: prop->info->name);
> -
> - object_property_add(OBJECT(dev), name, type,
> - prop->info->print ? qdev_get_legacy_property : prop->info->get,
> - prop->info->parse ? qdev_set_legacy_property : prop->info->set,
> - NULL,
> - prop, errp);
> -
> - g_free(type);
> - g_free(name);
> -}
> -
> -/**
> - * @qdev_property_add_static - add a @Property to a device.
> - *
> - * Static properties access data in a struct. The actual type of the
> - * property and the field depends on the property type.
> - */
> -void qdev_property_add_static(DeviceState *dev, Property *prop,
> - Error **errp)
> -{
> - Error *local_err = NULL;
> - Object *obj = OBJECT(dev);
> -
> - /*
> - * TODO qdev_prop_ptr does not have getters or setters. It must
> - * go now that it can be replaced with links. The test should be
> - * removed along with it: all static properties are read/write.
> - */
> - if (!prop->info->get && !prop->info->set) {
> - return;
> - }
> -
> - object_property_add(obj, prop->name, prop->info->name,
> - prop->info->get, prop->info->set,
> - prop->info->release,
> - prop, &local_err);
> -
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (prop->qtype == QTYPE_NONE) {
> - return;
> - }
> -
> - if (prop->qtype == QTYPE_QBOOL) {
> - object_property_set_bool(obj, prop->defval, prop->name, &local_err);
> - } else if (prop->info->enum_table) {
> - object_property_set_str(obj, prop->info->enum_table[prop->defval],
> - prop->name, &local_err);
> - } else if (prop->qtype == QTYPE_QINT) {
> - object_property_set_int(obj, prop->defval, prop->name, &local_err);
> - }
> - assert_no_error(local_err);
> -}
> -
> -static void device_initfn(Object *obj)
> -{
> - DeviceState *dev = DEVICE(obj);
> - ObjectClass *class;
> - Property *prop;
> -
> - if (qdev_hotplug) {
> - dev->hotplugged = 1;
> - qdev_hot_added = true;
> - }
> -
> - dev->instance_id_alias = -1;
> - dev->state = DEV_STATE_CREATED;
> -
> - class = object_get_class(OBJECT(dev));
> - do {
> - for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> - qdev_property_add_legacy(dev, prop, NULL);
> - qdev_property_add_static(dev, prop, NULL);
> - }
> - class = object_class_get_parent(class);
> - } while (class != object_class_by_name(TYPE_DEVICE));
> - qdev_prop_set_globals(dev);
> -
> - object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> - (Object **)&dev->parent_bus, NULL);
> -}
> -
> -/* Unlink device from bus and free the structure. */
> -static void device_finalize(Object *obj)
> -{
> - DeviceState *dev = DEVICE(obj);
> - BusState *bus;
> - DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> - if (dev->state == DEV_STATE_INITIALIZED) {
> - while (dev->num_child_bus) {
> - bus = QLIST_FIRST(&dev->child_bus);
> - qbus_free(bus);
> - }
> - qdev_finalize_vmstate(dev);
> - if (dc->exit) {
> - dc->exit(dev);
> - }
> - if (dev->opts) {
> - qemu_opts_del(dev->opts);
> - }
> - }
> - if (dev->parent_bus) {
> - bus_remove_child(dev->parent_bus, dev);
> - }
> -}
> -
> -static void device_class_base_init(ObjectClass *class, void *data)
> -{
> - DeviceClass *klass = DEVICE_CLASS(class);
> -
> - /* We explicitly look up properties in the superclasses,
> - * so do not propagate them to the subclasses.
> - */
> - klass->props = NULL;
> -}
> -
> -void device_reset(DeviceState *dev)
> -{
> - DeviceClass *klass = DEVICE_GET_CLASS(dev);
> -
> - if (klass->reset) {
> - klass->reset(dev);
> - }
> -}
> -
> -Object *qdev_get_machine(void)
> -{
> - static Object *dev;
> -
> - if (dev == NULL) {
> - dev = container_get(object_get_root(), "/machine");
> - }
> -
> - return dev;
> -}
> -
> -static TypeInfo device_type_info = {
> - .name = TYPE_DEVICE,
> - .parent = TYPE_OBJECT,
> - .instance_size = sizeof(DeviceState),
> - .instance_init = device_initfn,
> - .instance_finalize = device_finalize,
> - .class_base_init = device_class_base_init,
> - .abstract = true,
> - .class_size = sizeof(DeviceClass),
> -};
> -
> -static void qbus_initfn(Object *obj)
> -{
> - BusState *bus = BUS(obj);
> -
> - QTAILQ_INIT(&bus->children);
> -}
> -
> -static void qbus_finalize(Object *obj)
> -{
> - BusState *bus = BUS(obj);
> - BusChild *kid;
> -
> - while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> - DeviceState *dev = kid->child;
> - qdev_free(dev);
> - }
> - if (bus->parent) {
> - QLIST_REMOVE(bus, sibling);
> - bus->parent->num_child_bus--;
> - } else {
> - qbus_unregister_reset(bus);
> - }
> - g_free((char *)bus->name);
> -}
> -
> -static const TypeInfo bus_info = {
> - .name = TYPE_BUS,
> - .parent = TYPE_OBJECT,
> - .instance_size = sizeof(BusState),
> - .abstract = true,
> - .class_size = sizeof(BusClass),
> - .instance_init = qbus_initfn,
> - .instance_finalize = qbus_finalize,
> -};
> -
> -static void qdev_register_types(void)
> -{
> - type_register_static(&bus_info);
> - type_register_static(&device_type_info);
> -}
> -
> -type_init(qdev_register_types)
> diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
> deleted file mode 100644
> index 2e82cb9..0000000
> --- a/hw/qdev-properties.c
> +++ /dev/null
> @@ -1,963 +0,0 @@
> -#include "net.h"
> -#include "hw/qdev.h"
> -#include "qerror.h"
> -#include "blockdev.h"
> -#include "hw/block-common.h"
> -#include "net/hub.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> -{
> - void *ptr = dev;
> - ptr += prop->offset;
> - return ptr;
> -}
> -
> -static void get_enum(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_enum(v, ptr, prop->info->enum_table,
> - prop->info->name, prop->name, errp);
> -}
> -
> -static void set_enum(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_enum(v, ptr, prop->info->enum_table,
> - prop->info->name, prop->name, errp);
> -}
> -
> -/* Bit */
> -
> -static uint32_t qdev_get_prop_mask(Property *prop)
> -{
> - assert(prop->info == &qdev_prop_bit);
> - return 0x1 << prop->bitnr;
> -}
> -
> -static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> -{
> - uint32_t *p = qdev_get_prop_ptr(dev, props);
> - uint32_t mask = qdev_get_prop_mask(props);
> - if (val)
> - *p |= mask;
> - else
> - *p &= ~mask;
> -}
> -
> -static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint32_t *p = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
> -}
> -
> -static void get_bit(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *p = qdev_get_prop_ptr(dev, prop);
> - bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> -
> - visit_type_bool(v, &value, name, errp);
> -}
> -
> -static void set_bit(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - Error *local_err = NULL;
> - bool value;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_bool(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - bit_prop_set(dev, prop, value);
> -}
> -
> -PropertyInfo qdev_prop_bit = {
> - .name = "boolean",
> - .legacy_name = "on/off",
> - .print = print_bit,
> - .get = get_bit,
> - .set = set_bit,
> -};
> -
> -/* --- 8bit integer --- */
> -
> -static void get_uint8(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -static void set_uint8(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint8 = {
> - .name = "uint8",
> - .get = get_uint8,
> - .set = set_uint8,
> -};
> -
> -/* --- 8bit hex value --- */
> -
> -static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoul(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx8, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex8 = {
> - .name = "uint8",
> - .legacy_name = "hex8",
> - .parse = parse_hex8,
> - .print = print_hex8,
> - .get = get_uint8,
> - .set = set_uint8,
> -};
> -
> -/* --- 16bit integer --- */
> -
> -static void get_uint16(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -static void set_uint16(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint16 = {
> - .name = "uint16",
> - .get = get_uint16,
> - .set = set_uint16,
> -};
> -
> -/* --- 32bit integer --- */
> -
> -static void get_uint32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void set_uint32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void get_int32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_int32(v, ptr, name, errp);
> -}
> -
> -static void set_int32(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_int32(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint32 = {
> - .name = "uint32",
> - .get = get_uint32,
> - .set = set_uint32,
> -};
> -
> -PropertyInfo qdev_prop_int32 = {
> - .name = "int32",
> - .get = get_int32,
> - .set = set_int32,
> -};
> -
> -/* --- 32bit hex value --- */
> -
> -static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoul(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx32, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex32 = {
> - .name = "uint32",
> - .legacy_name = "hex32",
> - .parse = parse_hex32,
> - .print = print_hex32,
> - .get = get_uint32,
> - .set = set_uint32,
> -};
> -
> -/* --- 64bit integer --- */
> -
> -static void get_uint64(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -static void set_uint64(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint64 = {
> - .name = "uint64",
> - .get = get_uint64,
> - .set = set_uint64,
> -};
> -
> -/* --- 64bit hex value --- */
> -
> -static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> -{
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> - char *end;
> -
> - if (str[0] != '0' || str[1] != 'x') {
> - return -EINVAL;
> - }
> -
> - *ptr = strtoull(str, &end, 16);
> - if ((*end != '\0') || (end == str)) {
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> - return snprintf(dest, len, "0x%" PRIx64, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex64 = {
> - .name = "uint64",
> - .legacy_name = "hex64",
> - .parse = parse_hex64,
> - .print = print_hex64,
> - .get = get_uint64,
> - .set = set_uint64,
> -};
> -
> -/* --- string --- */
> -
> -static void release_string(Object *obj, const char *name, void *opaque)
> -{
> - Property *prop = opaque;
> - g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> -}
> -
> -static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> - if (!*ptr)
> - return snprintf(dest, len, "<null>");
> - return snprintf(dest, len, "\"%s\"", *ptr);
> -}
> -
> -static void get_string(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (!*ptr) {
> - char *str = (char *)"";
> - visit_type_str(v, &str, name, errp);
> - } else {
> - visit_type_str(v, ptr, name, errp);
> - }
> -}
> -
> -static void set_string(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - char **ptr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - char *str;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (*ptr) {
> - g_free(*ptr);
> - }
> - *ptr = str;
> -}
> -
> -PropertyInfo qdev_prop_string = {
> - .name = "string",
> - .print = print_string,
> - .release = release_string,
> - .get = get_string,
> - .set = set_string,
> -};
> -
> -/* --- pointer --- */
> -
> -/* Not a proper property, just for dirty hacks. TODO Remove it! */
> -PropertyInfo qdev_prop_ptr = {
> - .name = "ptr",
> -};
> -
> -/* --- mac address --- */
> -
> -/*
> - * accepted syntax versions:
> - * 01:02:03:04:05:06
> - * 01-02-03-04-05-06
> - */
> -static void get_mac(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> - char buffer[2 * 6 + 5 + 1];
> - char *p = buffer;
> -
> - snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> - mac->a[0], mac->a[1], mac->a[2],
> - mac->a[3], mac->a[4], mac->a[5]);
> -
> - visit_type_str(v, &p, name, errp);
> -}
> -
> -static void set_mac(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - int i, pos;
> - char *str, *p;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> - if (!qemu_isxdigit(str[pos]))
> - goto inval;
> - if (!qemu_isxdigit(str[pos+1]))
> - goto inval;
> - if (i == 5) {
> - if (str[pos+2] != '\0')
> - goto inval;
> - } else {
> - if (str[pos+2] != ':' && str[pos+2] != '-')
> - goto inval;
> - }
> - mac->a[i] = strtol(str+pos, &p, 16);
> - }
> - g_free(str);
> - return;
> -
> -inval:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_macaddr = {
> - .name = "macaddr",
> - .get = get_mac,
> - .set = set_mac,
> -};
> -
> -/* --- lost tick policy --- */
> -
> -static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> - [LOST_TICK_DISCARD] = "discard",
> - [LOST_TICK_DELAY] = "delay",
> - [LOST_TICK_MERGE] = "merge",
> - [LOST_TICK_SLEW] = "slew",
> - [LOST_TICK_MAX] = NULL,
> -};
> -
> -QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> -
> -PropertyInfo qdev_prop_losttickpolicy = {
> - .name = "LostTickPolicy",
> - .enum_table = lost_tick_policy_table,
> - .get = get_enum,
> - .set = set_enum,
> -};
> -
> -/* --- BIOS CHS translation */
> -
> -static const char *bios_chs_trans_table[] = {
> - [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> - [BIOS_ATA_TRANSLATION_NONE] = "none",
> - [BIOS_ATA_TRANSLATION_LBA] = "lba",
> -};
> -
> -PropertyInfo qdev_prop_bios_chs_trans = {
> - .name = "bios-chs-trans",
> - .enum_table = bios_chs_trans_table,
> - .get = get_enum,
> - .set = set_enum,
> -};
> -
> -/* --- pci address --- */
> -
> -/*
> - * bus-local address, i.e. "$slot" or "$slot.$fn"
> - */
> -static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> - unsigned int slot, fn, n;
> - Error *local_err = NULL;
> - char *str;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_free(local_err);
> - local_err = NULL;
> - visit_type_int32(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - } else if (value < -1 || value > 255) {
> - error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
> - "pci_devfn");
> - } else {
> - *ptr = value;
> - }
> - return;
> - }
> -
> - if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> - fn = 0;
> - if (sscanf(str, "%x%n", &slot, &n) != 1) {
> - goto invalid;
> - }
> - }
> - if (str[n] != '\0' || fn > 7 || slot > 31) {
> - goto invalid;
> - }
> - *ptr = slot << 3 | fn;
> - g_free(str);
> - return;
> -
> -invalid:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
> -{
> - int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> - if (*ptr == -1) {
> - return snprintf(dest, len, "<unset>");
> - } else {
> - return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> - }
> -}
> -
> -PropertyInfo qdev_prop_pci_devfn = {
> - .name = "int32",
> - .legacy_name = "pci-devfn",
> - .print = print_pci_devfn,
> - .get = get_int32,
> - .set = set_pci_devfn,
> -};
> -
> -/* --- blocksize --- */
> -
> -static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - const int64_t min = 512;
> - const int64_t max = 32768;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_uint16(v, &value, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> - if (value < min || value > max) {
> - error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> - dev->id?:"", name, (int64_t)value, min, max);
> - return;
> - }
> -
> - /* We rely on power-of-2 blocksizes for bitmasks */
> - if ((value & (value - 1)) != 0) {
> - error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> - dev->id?:"", name, (int64_t)value);
> - return;
> - }
> -
> - *ptr = value;
> -}
> -
> -PropertyInfo qdev_prop_blocksize = {
> - .name = "blocksize",
> - .get = get_uint16,
> - .set = set_blocksize,
> -};
> -
> -/* --- pci host address --- */
> -
> -static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> - char buffer[] = "xxxx:xx:xx.x";
> - char *p = buffer;
> - int rc = 0;
> -
> - rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> - addr->domain, addr->bus, addr->slot, addr->function);
> - assert(rc == sizeof(buffer) - 1);
> -
> - visit_type_str(v, &p, name, errp);
> -}
> -
> -/*
> - * Parse [<domain>:]<bus>:<slot>.<func>
> - * if <domain> is not supplied, it's assumed to be 0.
> - */
> -static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> - const char *name, Error **errp)
> -{
> - DeviceState *dev = DEVICE(obj);
> - Property *prop = opaque;
> - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> - Error *local_err = NULL;
> - char *str, *p;
> - char *e;
> - unsigned long val;
> - unsigned long dom = 0, bus = 0;
> - unsigned int slot = 0, func = 0;
> -
> - if (dev->state != DEV_STATE_CREATED) {
> - error_set(errp, QERR_PERMISSION_DENIED);
> - return;
> - }
> -
> - visit_type_str(v, &str, name, &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - p = str;
> - val = strtoul(p, &e, 16);
> - if (e == p || *e != ':') {
> - goto inval;
> - }
> - bus = val;
> -
> - p = e + 1;
> - val = strtoul(p, &e, 16);
> - if (e == p) {
> - goto inval;
> - }
> - if (*e == ':') {
> - dom = bus;
> - bus = val;
> - p = e + 1;
> - val = strtoul(p, &e, 16);
> - if (e == p) {
> - goto inval;
> - }
> - }
> - slot = val;
> -
> - if (*e != '.') {
> - goto inval;
> - }
> - p = e + 1;
> - val = strtoul(p, &e, 10);
> - if (e == p) {
> - goto inval;
> - }
> - func = val;
> -
> - if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> - goto inval;
> - }
> -
> - if (*e) {
> - goto inval;
> - }
> -
> - addr->domain = dom;
> - addr->bus = bus;
> - addr->slot = slot;
> - addr->function = func;
> -
> - g_free(str);
> - return;
> -
> -inval:
> - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> - g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_pci_host_devaddr = {
> - .name = "pci-host-devaddr",
> - .get = get_pci_host_devaddr,
> - .set = set_pci_host_devaddr,
> -};
> -
> -/* --- public helpers --- */
> -
> -static Property *qdev_prop_walk(Property *props, const char *name)
> -{
> - if (!props)
> - return NULL;
> - while (props->name) {
> - if (strcmp(props->name, name) == 0)
> - return props;
> - props++;
> - }
> - return NULL;
> -}
> -
> -static Property *qdev_prop_find(DeviceState *dev, const char *name)
> -{
> - ObjectClass *class;
> - Property *prop;
> -
> - /* device properties */
> - class = object_get_class(OBJECT(dev));
> - do {
> - prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> - if (prop) {
> - return prop;
> - }
> - class = object_class_get_parent(class);
> - } while (class != object_class_by_name(TYPE_DEVICE));
> -
> - return NULL;
> -}
> -
> -void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> - Property *prop, const char *value)
> -{
> - switch (ret) {
> - case -EEXIST:
> - error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - default:
> - case -EINVAL:
> - error_set(errp, QERR_PROPERTY_VALUE_BAD,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - case -ENOENT:
> - error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
> - object_get_typename(OBJECT(dev)), prop->name, value);
> - break;
> - case 0:
> - break;
> - }
> -}
> -
> -int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> -{
> - char *legacy_name;
> - Error *err = NULL;
> -
> - legacy_name = g_strdup_printf("legacy-%s", name);
> - if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> - object_property_parse(OBJECT(dev), value, legacy_name, &err);
> - } else {
> - object_property_parse(OBJECT(dev), value, name, &err);
> - }
> - g_free(legacy_name);
> -
> - if (err) {
> - qerror_report_err(err);
> - error_free(err);
> - return -1;
> - }
> - return 0;
> -}
> -
> -void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> -{
> - Error *errp = NULL;
> - object_property_set_bool(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> -{
> - Error *errp = NULL;
> - object_property_set_int(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
> -{
> - Error *errp = NULL;
> - object_property_set_str(OBJECT(dev), value, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
> -{
> - Error *errp = NULL;
> - char str[2 * 6 + 5 + 1];
> - snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> - value[0], value[1], value[2], value[3], value[4], value[5]);
> -
> - object_property_set_str(OBJECT(dev), str, name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> -{
> - Property *prop;
> - Error *errp = NULL;
> -
> - prop = qdev_prop_find(dev, name);
> - object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> - name, &errp);
> - assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> -{
> - Property *prop;
> - void **ptr;
> -
> - prop = qdev_prop_find(dev, name);
> - assert(prop && prop->info == &qdev_prop_ptr);
> - ptr = qdev_get_prop_ptr(dev, prop);
> - *ptr = value;
> -}
> -
> -static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
> -
> -void qdev_prop_register_global(GlobalProperty *prop)
> -{
> - QTAILQ_INSERT_TAIL(&global_props, prop, next);
> -}
> -
> -void qdev_prop_register_global_list(GlobalProperty *props)
> -{
> - int i;
> -
> - for (i = 0; props[i].driver != NULL; i++) {
> - qdev_prop_register_global(props+i);
> - }
> -}
> -
> -void qdev_prop_set_globals(DeviceState *dev)
> -{
> - ObjectClass *class = object_get_class(OBJECT(dev));
> -
> - do {
> - GlobalProperty *prop;
> - QTAILQ_FOREACH(prop, &global_props, next) {
> - if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> - continue;
> - }
> - if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> - exit(1);
> - }
> - }
> - class = object_class_get_parent(class);
> - } while (class);
> -}
> -
> diff --git a/qom/Makefile.objs b/qom/Makefile.objs
> index 5ef060a..09ef871 100644
> --- a/qom/Makefile.objs
> +++ b/qom/Makefile.objs
> @@ -1,4 +1,4 @@
> qom-obj-y = object.o container.o qom-qobject.o
> -qom-obj-twice-y = cpu.o
> +qom-obj-twice-y = cpu.o qdev-core.o qdev-properties.o
> common-obj-y = $(qom-obj-twice-y)
> user-obj-y = $(qom-obj-twice-y)
> diff --git a/qom/qdev-core.c b/qom/qdev-core.c
> new file mode 100644
> index 0000000..fbb7cb5
> --- /dev/null
> +++ b/qom/qdev-core.c
> @@ -0,0 +1,727 @@
> +/*
> + * Dynamic device configuration and creation.
> + *
> + * Copyright (c) 2009 CodeSourcery
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/* The theory here is that it should be possible to create a machine without
> + knowledge of specific devices. Historically board init routines have
> + passed a bunch of arguments to each device, requiring the board know
> + exactly which device it is dealing with. This file provides an abstract
> + API for device configuration and initialization. Devices will generally
> + inherit from a particular bus (e.g. PCI or I2C) rather than
> + this API directly. */
> +
> +#include "hw/qdev.h"
> +#include "sysemu.h"
> +#include "error.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +int qdev_hotplug = 0;
> +static bool qdev_hot_added = false;
> +static bool qdev_hot_removed = false;
> +
> +/* vmstate handling:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> +{
> +}
> +
> +void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> +{
> +}
> +
> +/* reset handler register/unregister:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qbus_register_reset(BusState *bus)
> +{
> +}
> +
> +void GCC_WEAK qbus_unregister_reset(BusState *bus)
> +{
> +}
> +
> +const char *qdev_fw_name(DeviceState *dev)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (dc->fw_name) {
> + return dc->fw_name;
> + }
> +
> + return object_get_typename(OBJECT(dev));
> +}
> +
> +static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> + Error **errp);
> +
> +static void bus_remove_child(BusState *bus, DeviceState *child)
> +{
> + BusChild *kid;
> +
> + QTAILQ_FOREACH(kid, &bus->children, sibling) {
> + if (kid->child == child) {
> + char name[32];
> +
> + snprintf(name, sizeof(name), "child[%d]", kid->index);
> + QTAILQ_REMOVE(&bus->children, kid, sibling);
> + object_property_del(OBJECT(bus), name, NULL);
> + g_free(kid);
> + return;
> + }
> + }
> +}
> +
> +static void bus_add_child(BusState *bus, DeviceState *child)
> +{
> + char name[32];
> + BusChild *kid = g_malloc0(sizeof(*kid));
> +
> + if (qdev_hotplug) {
> + assert(bus->allow_hotplug);
> + }
> +
> + kid->index = bus->max_index++;
> + kid->child = child;
> +
> + QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
> +
> + snprintf(name, sizeof(name), "child[%d]", kid->index);
> + object_property_add_link(OBJECT(bus), name,
> + object_get_typename(OBJECT(child)),
> + (Object **)&kid->child,
> + NULL);
> +}
> +
> +void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
> +{
> + dev->parent_bus = bus;
> + bus_add_child(bus, dev);
> +}
> +
> +/* Initialize a device. Device properties should be set before calling
> + this function. IRQs and MMIO regions should be connected/mapped after
> + calling this function.
> + On failure, destroy the device and return negative value.
> + Return 0 on success. */
> +int qdev_init(DeviceState *dev)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> + int rc;
> +
> + assert(dev->state == DEV_STATE_CREATED);
> +
> + rc = dc->init(dev);
> + if (rc < 0) {
> + qdev_free(dev);
> + return rc;
> + }
> +
> + if (!OBJECT(dev)->parent) {
> + static int unattached_count = 0;
> + gchar *name = g_strdup_printf("device[%d]", unattached_count++);
> +
> + object_property_add_child(container_get(qdev_get_machine(),
> + "/unattached"),
> + name, OBJECT(dev), NULL);
> + g_free(name);
> + }
> +
> + qdev_init_vmstate(dev);
> + dev->state = DEV_STATE_INITIALIZED;
> + if (dev->hotplugged) {
> + device_reset(dev);
> + }
> + return 0;
> +}
> +
> +void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> + int required_for_version)
> +{
> + assert(dev->state == DEV_STATE_CREATED);
> + dev->instance_id_alias = alias_id;
> + dev->alias_required_for_version = required_for_version;
> +}
> +
> +void qdev_unplug(DeviceState *dev, Error **errp)
> +{
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (!dev->parent_bus->allow_hotplug) {
> + error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> + return;
> + }
> + assert(dc->unplug != NULL);
> +
> + qdev_hot_removed = true;
> +
> + if (dc->unplug(dev) < 0) {
> + error_set(errp, QERR_UNDEFINED_ERROR);
> + return;
> + }
> +}
> +
> +static int qdev_reset_one(DeviceState *dev, void *opaque)
> +{
> + device_reset(dev);
> +
> + return 0;
> +}
> +
> +static int qbus_reset_one(BusState *bus, void *opaque)
> +{
> + BusClass *bc = BUS_GET_CLASS(bus);
> + if (bc->reset) {
> + return bc->reset(bus);
> + }
> + return 0;
> +}
> +
> +void qdev_reset_all(DeviceState *dev)
> +{
> + qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +void qbus_reset_all_fn(void *opaque)
> +{
> + BusState *bus = opaque;
> + qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +/* can be used as ->unplug() callback for the simple cases */
> +int qdev_simple_unplug_cb(DeviceState *dev)
> +{
> + /* just zap it */
> + qdev_free(dev);
> + return 0;
> +}
> +
> +
> +/* Like qdev_init(), but terminate program via error_report() instead of
> + returning an error value. This is okay during machine creation.
> + Don't use for hotplug, because there callers need to recover from
> + failure. Exception: if you know the device's init() callback can't
> + fail, then qdev_init_nofail() can't fail either, and is therefore
> + usable even then. But relying on the device implementation that
> + way is somewhat unclean, and best avoided. */
> +void qdev_init_nofail(DeviceState *dev)
> +{
> + const char *typename = object_get_typename(OBJECT(dev));
> +
> + if (qdev_init(dev) < 0) {
> + error_report("Initialization of device %s failed", typename);
> + exit(1);
> + }
> +}
> +
> +/* Unlink device from bus and free the structure. */
> +void qdev_free(DeviceState *dev)
> +{
> + object_delete(OBJECT(dev));
> +}
> +
> +void qdev_machine_creation_done(void)
> +{
> + /*
> + * ok, initial machine setup is done, starting from now we can
> + * only create hotpluggable devices
> + */
> + qdev_hotplug = 1;
> +}
> +
> +bool qdev_machine_modified(void)
> +{
> + return qdev_hot_added || qdev_hot_removed;
> +}
> +
> +BusState *qdev_get_parent_bus(DeviceState *dev)
> +{
> + return dev->parent_bus;
> +}
> +
> +BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> +{
> + BusState *bus;
> +
> + QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> + if (strcmp(name, bus->name) == 0) {
> + return bus;
> + }
> + }
> + return NULL;
> +}
> +
> +int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> + qbus_walkerfn *busfn, void *opaque)
> +{
> + BusChild *kid;
> + int err;
> +
> + if (busfn) {
> + err = busfn(bus, opaque);
> + if (err) {
> + return err;
> + }
> + }
> +
> + QTAILQ_FOREACH(kid, &bus->children, sibling) {
> + err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> + if (err < 0) {
> + return err;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> + qbus_walkerfn *busfn, void *opaque)
> +{
> + BusState *bus;
> + int err;
> +
> + if (devfn) {
> + err = devfn(dev, opaque);
> + if (err) {
> + return err;
> + }
> + }
> +
> + QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> + err = qbus_walk_children(bus, devfn, busfn, opaque);
> + if (err < 0) {
> + return err;
> + }
> + }
> +
> + return 0;
> +}
> +
> +DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> +{
> + BusChild *kid;
> + DeviceState *ret;
> + BusState *child;
> +
> + QTAILQ_FOREACH(kid, &bus->children, sibling) {
> + DeviceState *dev = kid->child;
> +
> + if (dev->id && strcmp(dev->id, id) == 0) {
> + return dev;
> + }
> +
> + QLIST_FOREACH(child, &dev->child_bus, sibling) {
> + ret = qdev_find_recursive(child, id);
> + if (ret) {
> + return ret;
> + }
> + }
> + }
> + return NULL;
> +}
> +
> +static void qbus_realize(BusState *bus)
> +{
> + const char *typename = object_get_typename(OBJECT(bus));
> + char *buf;
> + int i,len;
> +
> + if (bus->name) {
> + /* use supplied name */
> + } else if (bus->parent && bus->parent->id) {
> + /* parent device has id -> use it for bus name */
> + len = strlen(bus->parent->id) + 16;
> + buf = g_malloc(len);
> + snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
> + bus->name = buf;
> + } else {
> + /* no id -> use lowercase bus type for bus name */
> + len = strlen(typename) + 16;
> + buf = g_malloc(len);
> + len = snprintf(buf, len, "%s.%d", typename,
> + bus->parent ? bus->parent->num_child_bus : 0);
> + for (i = 0; i < len; i++)
> + buf[i] = qemu_tolower(buf[i]);
> + bus->name = buf;
> + }
> +
> + if (bus->parent) {
> + QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> + bus->parent->num_child_bus++;
> + object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> + } else {
> + qbus_register_reset(bus);
> + }
> +}
> +
> +void qbus_create_inplace(BusState *bus, const char *typename,
> + DeviceState *parent, const char *name)
> +{
> + object_initialize(bus, typename);
> +
> + bus->parent = parent;
> + bus->name = name ? g_strdup(name) : NULL;
> + qbus_realize(bus);
> +}
> +
> +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
> +{
> + BusState *bus;
> +
> + bus = BUS(object_new(typename));
> + bus->qom_allocated = true;
> +
> + bus->parent = parent;
> + bus->name = name ? g_strdup(name) : NULL;
> + qbus_realize(bus);
> +
> + return bus;
> +}
> +
> +void qbus_free(BusState *bus)
> +{
> + if (bus->qom_allocated) {
> + object_delete(OBJECT(bus));
> + } else {
> + object_finalize(OBJECT(bus));
> + if (bus->glib_allocated) {
> + g_free(bus);
> + }
> + }
> +}
> +
> +static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
> +{
> + BusClass *bc = BUS_GET_CLASS(bus);
> +
> + if (bc->get_fw_dev_path) {
> + return bc->get_fw_dev_path(dev);
> + }
> +
> + return NULL;
> +}
> +
> +static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> +{
> + int l = 0;
> +
> + if (dev && dev->parent_bus) {
> + char *d;
> + l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> + d = bus_get_fw_dev_path(dev->parent_bus, dev);
> + if (d) {
> + l += snprintf(p + l, size - l, "%s", d);
> + g_free(d);
> + } else {
> + l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> + }
> + }
> + l += snprintf(p + l , size - l, "/");
> +
> + return l;
> +}
> +
> +char* qdev_get_fw_dev_path(DeviceState *dev)
> +{
> + char path[128];
> + int l;
> +
> + l = qdev_get_fw_dev_path_helper(dev, path, 128);
> +
> + path[l-1] = '\0';
> +
> + return g_strdup(path);
> +}
> +
> +char *qdev_get_dev_path(DeviceState *dev)
> +{
> + BusClass *bc;
> +
> + if (!dev || !dev->parent_bus) {
> + return NULL;
> + }
> +
> + bc = BUS_GET_CLASS(dev->parent_bus);
> + if (bc->get_dev_path) {
> + return bc->get_dev_path(dev);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + * Legacy property handling
> + */
> +
> +static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> +
> + char buffer[1024];
> + char *ptr = buffer;
> +
> + prop->info->print(dev, prop, buffer, sizeof(buffer));
> + visit_type_str(v, &ptr, name, errp);
> +}
> +
> +static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + Error *local_err = NULL;
> + char *ptr = NULL;
> + int ret;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &ptr, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + ret = prop->info->parse(dev, prop, ptr);
> + error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> + g_free(ptr);
> +}
> +
> +/**
> + * @qdev_add_legacy_property - adds a legacy property
> + *
> + * Do not use this is new code! Properties added through this interface will
> + * be given names and types in the "legacy" namespace.
> + *
> + * Legacy properties are string versions of other OOM properties. The format
> + * of the string depends on the property type.
> + */
> +void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> + Error **errp)
> +{
> + gchar *name, *type;
> +
> + /* Register pointer properties as legacy properties */
> + if (!prop->info->print && !prop->info->parse &&
> + (prop->info->set || prop->info->get)) {
> + return;
> + }
> +
> + name = g_strdup_printf("legacy-%s", prop->name);
> + type = g_strdup_printf("legacy<%s>",
> + prop->info->legacy_name ?: prop->info->name);
> +
> + object_property_add(OBJECT(dev), name, type,
> + prop->info->print ? qdev_get_legacy_property : prop->info->get,
> + prop->info->parse ? qdev_set_legacy_property : prop->info->set,
> + NULL,
> + prop, errp);
> +
> + g_free(type);
> + g_free(name);
> +}
> +
> +/**
> + * @qdev_property_add_static - add a @Property to a device.
> + *
> + * Static properties access data in a struct. The actual type of the
> + * property and the field depends on the property type.
> + */
> +void qdev_property_add_static(DeviceState *dev, Property *prop,
> + Error **errp)
> +{
> + Error *local_err = NULL;
> + Object *obj = OBJECT(dev);
> +
> + /*
> + * TODO qdev_prop_ptr does not have getters or setters. It must
> + * go now that it can be replaced with links. The test should be
> + * removed along with it: all static properties are read/write.
> + */
> + if (!prop->info->get && !prop->info->set) {
> + return;
> + }
> +
> + object_property_add(obj, prop->name, prop->info->name,
> + prop->info->get, prop->info->set,
> + prop->info->release,
> + prop, &local_err);
> +
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (prop->qtype == QTYPE_NONE) {
> + return;
> + }
> +
> + if (prop->qtype == QTYPE_QBOOL) {
> + object_property_set_bool(obj, prop->defval, prop->name, &local_err);
> + } else if (prop->info->enum_table) {
> + object_property_set_str(obj, prop->info->enum_table[prop->defval],
> + prop->name, &local_err);
> + } else if (prop->qtype == QTYPE_QINT) {
> + object_property_set_int(obj, prop->defval, prop->name, &local_err);
> + }
> + assert_no_error(local_err);
> +}
> +
> +static void device_initfn(Object *obj)
> +{
> + DeviceState *dev = DEVICE(obj);
> + ObjectClass *class;
> + Property *prop;
> +
> + if (qdev_hotplug) {
> + dev->hotplugged = 1;
> + qdev_hot_added = true;
> + }
> +
> + dev->instance_id_alias = -1;
> + dev->state = DEV_STATE_CREATED;
> +
> + class = object_get_class(OBJECT(dev));
> + do {
> + for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> + qdev_property_add_legacy(dev, prop, NULL);
> + qdev_property_add_static(dev, prop, NULL);
> + }
> + class = object_class_get_parent(class);
> + } while (class != object_class_by_name(TYPE_DEVICE));
> + qdev_prop_set_globals(dev);
> +
> + object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> + (Object **)&dev->parent_bus, NULL);
> +}
> +
> +/* Unlink device from bus and free the structure. */
> +static void device_finalize(Object *obj)
> +{
> + DeviceState *dev = DEVICE(obj);
> + BusState *bus;
> + DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> + if (dev->state == DEV_STATE_INITIALIZED) {
> + while (dev->num_child_bus) {
> + bus = QLIST_FIRST(&dev->child_bus);
> + qbus_free(bus);
> + }
> + qdev_finalize_vmstate(dev);
> + if (dc->exit) {
> + dc->exit(dev);
> + }
> + if (dev->opts) {
> + qemu_opts_del(dev->opts);
> + }
> + }
> + if (dev->parent_bus) {
> + bus_remove_child(dev->parent_bus, dev);
> + }
> +}
> +
> +static void device_class_base_init(ObjectClass *class, void *data)
> +{
> + DeviceClass *klass = DEVICE_CLASS(class);
> +
> + /* We explicitly look up properties in the superclasses,
> + * so do not propagate them to the subclasses.
> + */
> + klass->props = NULL;
> +}
> +
> +void device_reset(DeviceState *dev)
> +{
> + DeviceClass *klass = DEVICE_GET_CLASS(dev);
> +
> + if (klass->reset) {
> + klass->reset(dev);
> + }
> +}
> +
> +Object *qdev_get_machine(void)
> +{
> + static Object *dev;
> +
> + if (dev == NULL) {
> + dev = container_get(object_get_root(), "/machine");
> + }
> +
> + return dev;
> +}
> +
> +static TypeInfo device_type_info = {
> + .name = TYPE_DEVICE,
> + .parent = TYPE_OBJECT,
> + .instance_size = sizeof(DeviceState),
> + .instance_init = device_initfn,
> + .instance_finalize = device_finalize,
> + .class_base_init = device_class_base_init,
> + .abstract = true,
> + .class_size = sizeof(DeviceClass),
> +};
> +
> +static void qbus_initfn(Object *obj)
> +{
> + BusState *bus = BUS(obj);
> +
> + QTAILQ_INIT(&bus->children);
> +}
> +
> +static void qbus_finalize(Object *obj)
> +{
> + BusState *bus = BUS(obj);
> + BusChild *kid;
> +
> + while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> + DeviceState *dev = kid->child;
> + qdev_free(dev);
> + }
> + if (bus->parent) {
> + QLIST_REMOVE(bus, sibling);
> + bus->parent->num_child_bus--;
> + } else {
> + qbus_unregister_reset(bus);
> + }
> + g_free((char *)bus->name);
> +}
> +
> +static const TypeInfo bus_info = {
> + .name = TYPE_BUS,
> + .parent = TYPE_OBJECT,
> + .instance_size = sizeof(BusState),
> + .abstract = true,
> + .class_size = sizeof(BusClass),
> + .instance_init = qbus_initfn,
> + .instance_finalize = qbus_finalize,
> +};
> +
> +static void qdev_register_types(void)
> +{
> + type_register_static(&bus_info);
> + type_register_static(&device_type_info);
> +}
> +
> +type_init(qdev_register_types)
> diff --git a/qom/qdev-properties.c b/qom/qdev-properties.c
> new file mode 100644
> index 0000000..2e82cb9
> --- /dev/null
> +++ b/qom/qdev-properties.c
> @@ -0,0 +1,963 @@
> +#include "net.h"
> +#include "hw/qdev.h"
> +#include "qerror.h"
> +#include "blockdev.h"
> +#include "hw/block-common.h"
> +#include "net/hub.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> +{
> + void *ptr = dev;
> + ptr += prop->offset;
> + return ptr;
> +}
> +
> +static void get_enum(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_enum(v, ptr, prop->info->enum_table,
> + prop->info->name, prop->name, errp);
> +}
> +
> +static void set_enum(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_enum(v, ptr, prop->info->enum_table,
> + prop->info->name, prop->name, errp);
> +}
> +
> +/* Bit */
> +
> +static uint32_t qdev_get_prop_mask(Property *prop)
> +{
> + assert(prop->info == &qdev_prop_bit);
> + return 0x1 << prop->bitnr;
> +}
> +
> +static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> +{
> + uint32_t *p = qdev_get_prop_ptr(dev, props);
> + uint32_t mask = qdev_get_prop_mask(props);
> + if (val)
> + *p |= mask;
> + else
> + *p &= ~mask;
> +}
> +
> +static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint32_t *p = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
> +}
> +
> +static void get_bit(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *p = qdev_get_prop_ptr(dev, prop);
> + bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> +
> + visit_type_bool(v, &value, name, errp);
> +}
> +
> +static void set_bit(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + Error *local_err = NULL;
> + bool value;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_bool(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + bit_prop_set(dev, prop, value);
> +}
> +
> +PropertyInfo qdev_prop_bit = {
> + .name = "boolean",
> + .legacy_name = "on/off",
> + .print = print_bit,
> + .get = get_bit,
> + .set = set_bit,
> +};
> +
> +/* --- 8bit integer --- */
> +
> +static void get_uint8(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +static void set_uint8(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint8 = {
> + .name = "uint8",
> + .get = get_uint8,
> + .set = set_uint8,
> +};
> +
> +/* --- 8bit hex value --- */
> +
> +static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoul(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx8, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex8 = {
> + .name = "uint8",
> + .legacy_name = "hex8",
> + .parse = parse_hex8,
> + .print = print_hex8,
> + .get = get_uint8,
> + .set = set_uint8,
> +};
> +
> +/* --- 16bit integer --- */
> +
> +static void get_uint16(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +static void set_uint16(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint16 = {
> + .name = "uint16",
> + .get = get_uint16,
> + .set = set_uint16,
> +};
> +
> +/* --- 32bit integer --- */
> +
> +static void get_uint32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void set_uint32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void get_int32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_int32(v, ptr, name, errp);
> +}
> +
> +static void set_int32(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_int32(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint32 = {
> + .name = "uint32",
> + .get = get_uint32,
> + .set = set_uint32,
> +};
> +
> +PropertyInfo qdev_prop_int32 = {
> + .name = "int32",
> + .get = get_int32,
> + .set = set_int32,
> +};
> +
> +/* --- 32bit hex value --- */
> +
> +static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoul(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx32, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex32 = {
> + .name = "uint32",
> + .legacy_name = "hex32",
> + .parse = parse_hex32,
> + .print = print_hex32,
> + .get = get_uint32,
> + .set = set_uint32,
> +};
> +
> +/* --- 64bit integer --- */
> +
> +static void get_uint64(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +static void set_uint64(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint64 = {
> + .name = "uint64",
> + .get = get_uint64,
> + .set = set_uint64,
> +};
> +
> +/* --- 64bit hex value --- */
> +
> +static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> +{
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> + char *end;
> +
> + if (str[0] != '0' || str[1] != 'x') {
> + return -EINVAL;
> + }
> +
> + *ptr = strtoull(str, &end, 16);
> + if ((*end != '\0') || (end == str)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> + return snprintf(dest, len, "0x%" PRIx64, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex64 = {
> + .name = "uint64",
> + .legacy_name = "hex64",
> + .parse = parse_hex64,
> + .print = print_hex64,
> + .get = get_uint64,
> + .set = set_uint64,
> +};
> +
> +/* --- string --- */
> +
> +static void release_string(Object *obj, const char *name, void *opaque)
> +{
> + Property *prop = opaque;
> + g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> +}
> +
> +static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> + if (!*ptr)
> + return snprintf(dest, len, "<null>");
> + return snprintf(dest, len, "\"%s\"", *ptr);
> +}
> +
> +static void get_string(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (!*ptr) {
> + char *str = (char *)"";
> + visit_type_str(v, &str, name, errp);
> + } else {
> + visit_type_str(v, ptr, name, errp);
> + }
> +}
> +
> +static void set_string(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + char **ptr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + char *str;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (*ptr) {
> + g_free(*ptr);
> + }
> + *ptr = str;
> +}
> +
> +PropertyInfo qdev_prop_string = {
> + .name = "string",
> + .print = print_string,
> + .release = release_string,
> + .get = get_string,
> + .set = set_string,
> +};
> +
> +/* --- pointer --- */
> +
> +/* Not a proper property, just for dirty hacks. TODO Remove it! */
> +PropertyInfo qdev_prop_ptr = {
> + .name = "ptr",
> +};
> +
> +/* --- mac address --- */
> +
> +/*
> + * accepted syntax versions:
> + * 01:02:03:04:05:06
> + * 01-02-03-04-05-06
> + */
> +static void get_mac(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> + char buffer[2 * 6 + 5 + 1];
> + char *p = buffer;
> +
> + snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> + mac->a[0], mac->a[1], mac->a[2],
> + mac->a[3], mac->a[4], mac->a[5]);
> +
> + visit_type_str(v, &p, name, errp);
> +}
> +
> +static void set_mac(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + int i, pos;
> + char *str, *p;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> + if (!qemu_isxdigit(str[pos]))
> + goto inval;
> + if (!qemu_isxdigit(str[pos+1]))
> + goto inval;
> + if (i == 5) {
> + if (str[pos+2] != '\0')
> + goto inval;
> + } else {
> + if (str[pos+2] != ':' && str[pos+2] != '-')
> + goto inval;
> + }
> + mac->a[i] = strtol(str+pos, &p, 16);
> + }
> + g_free(str);
> + return;
> +
> +inval:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_macaddr = {
> + .name = "macaddr",
> + .get = get_mac,
> + .set = set_mac,
> +};
> +
> +/* --- lost tick policy --- */
> +
> +static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> + [LOST_TICK_DISCARD] = "discard",
> + [LOST_TICK_DELAY] = "delay",
> + [LOST_TICK_MERGE] = "merge",
> + [LOST_TICK_SLEW] = "slew",
> + [LOST_TICK_MAX] = NULL,
> +};
> +
> +QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> +
> +PropertyInfo qdev_prop_losttickpolicy = {
> + .name = "LostTickPolicy",
> + .enum_table = lost_tick_policy_table,
> + .get = get_enum,
> + .set = set_enum,
> +};
> +
> +/* --- BIOS CHS translation */
> +
> +static const char *bios_chs_trans_table[] = {
> + [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> + [BIOS_ATA_TRANSLATION_NONE] = "none",
> + [BIOS_ATA_TRANSLATION_LBA] = "lba",
> +};
> +
> +PropertyInfo qdev_prop_bios_chs_trans = {
> + .name = "bios-chs-trans",
> + .enum_table = bios_chs_trans_table,
> + .get = get_enum,
> + .set = set_enum,
> +};
> +
> +/* --- pci address --- */
> +
> +/*
> + * bus-local address, i.e. "$slot" or "$slot.$fn"
> + */
> +static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> + unsigned int slot, fn, n;
> + Error *local_err = NULL;
> + char *str;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_free(local_err);
> + local_err = NULL;
> + visit_type_int32(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + } else if (value < -1 || value > 255) {
> + error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
> + "pci_devfn");
> + } else {
> + *ptr = value;
> + }
> + return;
> + }
> +
> + if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> + fn = 0;
> + if (sscanf(str, "%x%n", &slot, &n) != 1) {
> + goto invalid;
> + }
> + }
> + if (str[n] != '\0' || fn > 7 || slot > 31) {
> + goto invalid;
> + }
> + *ptr = slot << 3 | fn;
> + g_free(str);
> + return;
> +
> +invalid:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
> +{
> + int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> + if (*ptr == -1) {
> + return snprintf(dest, len, "<unset>");
> + } else {
> + return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> + }
> +}
> +
> +PropertyInfo qdev_prop_pci_devfn = {
> + .name = "int32",
> + .legacy_name = "pci-devfn",
> + .print = print_pci_devfn,
> + .get = get_int32,
> + .set = set_pci_devfn,
> +};
> +
> +/* --- blocksize --- */
> +
> +static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + const int64_t min = 512;
> + const int64_t max = 32768;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_uint16(v, &value, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + if (value < min || value > max) {
> + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> + dev->id?:"", name, (int64_t)value, min, max);
> + return;
> + }
> +
> + /* We rely on power-of-2 blocksizes for bitmasks */
> + if ((value & (value - 1)) != 0) {
> + error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> + dev->id?:"", name, (int64_t)value);
> + return;
> + }
> +
> + *ptr = value;
> +}
> +
> +PropertyInfo qdev_prop_blocksize = {
> + .name = "blocksize",
> + .get = get_uint16,
> + .set = set_blocksize,
> +};
> +
> +/* --- pci host address --- */
> +
> +static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> + char buffer[] = "xxxx:xx:xx.x";
> + char *p = buffer;
> + int rc = 0;
> +
> + rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> + addr->domain, addr->bus, addr->slot, addr->function);
> + assert(rc == sizeof(buffer) - 1);
> +
> + visit_type_str(v, &p, name, errp);
> +}
> +
> +/*
> + * Parse [<domain>:]<bus>:<slot>.<func>
> + * if <domain> is not supplied, it's assumed to be 0.
> + */
> +static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + DeviceState *dev = DEVICE(obj);
> + Property *prop = opaque;
> + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> + Error *local_err = NULL;
> + char *str, *p;
> + char *e;
> + unsigned long val;
> + unsigned long dom = 0, bus = 0;
> + unsigned int slot = 0, func = 0;
> +
> + if (dev->state != DEV_STATE_CREATED) {
> + error_set(errp, QERR_PERMISSION_DENIED);
> + return;
> + }
> +
> + visit_type_str(v, &str, name, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + p = str;
> + val = strtoul(p, &e, 16);
> + if (e == p || *e != ':') {
> + goto inval;
> + }
> + bus = val;
> +
> + p = e + 1;
> + val = strtoul(p, &e, 16);
> + if (e == p) {
> + goto inval;
> + }
> + if (*e == ':') {
> + dom = bus;
> + bus = val;
> + p = e + 1;
> + val = strtoul(p, &e, 16);
> + if (e == p) {
> + goto inval;
> + }
> + }
> + slot = val;
> +
> + if (*e != '.') {
> + goto inval;
> + }
> + p = e + 1;
> + val = strtoul(p, &e, 10);
> + if (e == p) {
> + goto inval;
> + }
> + func = val;
> +
> + if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> + goto inval;
> + }
> +
> + if (*e) {
> + goto inval;
> + }
> +
> + addr->domain = dom;
> + addr->bus = bus;
> + addr->slot = slot;
> + addr->function = func;
> +
> + g_free(str);
> + return;
> +
> +inval:
> + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> + g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_pci_host_devaddr = {
> + .name = "pci-host-devaddr",
> + .get = get_pci_host_devaddr,
> + .set = set_pci_host_devaddr,
> +};
> +
> +/* --- public helpers --- */
> +
> +static Property *qdev_prop_walk(Property *props, const char *name)
> +{
> + if (!props)
> + return NULL;
> + while (props->name) {
> + if (strcmp(props->name, name) == 0)
> + return props;
> + props++;
> + }
> + return NULL;
> +}
> +
> +static Property *qdev_prop_find(DeviceState *dev, const char *name)
> +{
> + ObjectClass *class;
> + Property *prop;
> +
> + /* device properties */
> + class = object_get_class(OBJECT(dev));
> + do {
> + prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> + if (prop) {
> + return prop;
> + }
> + class = object_class_get_parent(class);
> + } while (class != object_class_by_name(TYPE_DEVICE));
> +
> + return NULL;
> +}
> +
> +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> + Property *prop, const char *value)
> +{
> + switch (ret) {
> + case -EEXIST:
> + error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + default:
> + case -EINVAL:
> + error_set(errp, QERR_PROPERTY_VALUE_BAD,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + case -ENOENT:
> + error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
> + object_get_typename(OBJECT(dev)), prop->name, value);
> + break;
> + case 0:
> + break;
> + }
> +}
> +
> +int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> +{
> + char *legacy_name;
> + Error *err = NULL;
> +
> + legacy_name = g_strdup_printf("legacy-%s", name);
> + if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> + object_property_parse(OBJECT(dev), value, legacy_name, &err);
> + } else {
> + object_property_parse(OBJECT(dev), value, name, &err);
> + }
> + g_free(legacy_name);
> +
> + if (err) {
> + qerror_report_err(err);
> + error_free(err);
> + return -1;
> + }
> + return 0;
> +}
> +
> +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> +{
> + Error *errp = NULL;
> + object_property_set_bool(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> +{
> + Error *errp = NULL;
> + object_property_set_int(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
> +{
> + Error *errp = NULL;
> + object_property_set_str(OBJECT(dev), value, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
> +{
> + Error *errp = NULL;
> + char str[2 * 6 + 5 + 1];
> + snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> + value[0], value[1], value[2], value[3], value[4], value[5]);
> +
> + object_property_set_str(OBJECT(dev), str, name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> +{
> + Property *prop;
> + Error *errp = NULL;
> +
> + prop = qdev_prop_find(dev, name);
> + object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> + name, &errp);
> + assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> +{
> + Property *prop;
> + void **ptr;
> +
> + prop = qdev_prop_find(dev, name);
> + assert(prop && prop->info == &qdev_prop_ptr);
> + ptr = qdev_get_prop_ptr(dev, prop);
> + *ptr = value;
> +}
> +
> +static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
> +
> +void qdev_prop_register_global(GlobalProperty *prop)
> +{
> + QTAILQ_INSERT_TAIL(&global_props, prop, next);
> +}
> +
> +void qdev_prop_register_global_list(GlobalProperty *props)
> +{
> + int i;
> +
> + for (i = 0; props[i].driver != NULL; i++) {
> + qdev_prop_register_global(props+i);
> + }
> +}
> +
> +void qdev_prop_set_globals(DeviceState *dev)
> +{
> + ObjectClass *class = object_get_class(OBJECT(dev));
> +
> + do {
> + GlobalProperty *prop;
> + QTAILQ_FOREACH(prop, &global_props, next) {
> + if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> + continue;
> + }
> + if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> + exit(1);
> + }
> + }
> + class = object_class_get_parent(class);
> + } while (class);
> +}
> +
> --
> 1.7.11.7
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-17 18:11 ` Anthony Liguori
@ 2012-10-17 18:18 ` Eduardo Habkost
2012-10-17 19:21 ` Peter Maydell
1 sibling, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-17 18:18 UTC (permalink / raw)
To: Anthony Liguori
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Igor Mammedov, Andreas Färber
On Wed, Oct 17, 2012 at 01:11:41PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
>
> > The code depends on some functions from qemu-option.o, so add
> > qemu-option.o to universal-obj-y to make sure it's included.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > Makefile.objs | 3 +
> > hw/Makefile.objs | 2 +-
> > hw/qdev-core.c | 727 -------------------------------------
> > hw/qdev-properties.c | 963 --------------------------------------------------
> > qom/Makefile.objs | 2 +-
> > qom/qdev-core.c | 727 +++++++++++++++++++++++++++++++++++++
> > qom/qdev-properties.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > 7 files changed, 1695 insertions(+), 1692 deletions(-)
> > delete mode 100644 hw/qdev-core.c
> > delete mode 100644 hw/qdev-properties.c
> > create mode 100644 qom/qdev-core.c
> > create mode 100644 qom/qdev-properties.c
>
> Stick the following in your .git/config:
>
> [diff]
> renames = true
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
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-17 18:11 ` Anthony Liguori
2012-10-17 18:18 ` Eduardo Habkost
@ 2012-10-17 19:21 ` Peter Maydell
2012-10-19 16:59 ` Eduardo Habkost
1 sibling, 1 reply; 27+ messages in thread
From: Peter Maydell @ 2012-10-17 19:21 UTC (permalink / raw)
To: Anthony Liguori
Cc: Eduardo Habkost, riku.voipio, qemu-devel, blauwirbel,
Igor Mammedov, Andreas Färber
On 17 October 2012 19:11, Anthony Liguori <anthony@codemonkey.ws> wrote:
> 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/.
"-user emulators don't get anything from hw/" is one of those semi
arbitrary but easily definable lines that I'd prefer it if we didn't
break. (Although IIRC there was a directory-renaming proposal recently
which maybe defines some different lines instead.)
-- PMM
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-17 19:21 ` Peter Maydell
@ 2012-10-19 16:59 ` Eduardo Habkost
0 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-19 16:59 UTC (permalink / raw)
To: Peter Maydell
Cc: riku.voipio, qemu-devel, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
On Wed, Oct 17, 2012 at 08:21:17PM +0100, Peter Maydell wrote:
> On 17 October 2012 19:11, Anthony Liguori <anthony@codemonkey.ws> wrote:
> > 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/.
>
> "-user emulators don't get anything from hw/" is one of those semi
> arbitrary but easily definable lines that I'd prefer it if we didn't
> break. (Although IIRC there was a directory-renaming proposal recently
> which maybe defines some different lines instead.)
I just rememberd another reason for moving qdev-core to qom: the CPU
class itself (that's going to be a child of DeviceState) is already
inside qom. Keeping qdev-core it on hw/ would mean having a qom->hw->qom
dependency chain (qom/cpu.c -> hw/qdev.c -> qom/object.c).
So, by now I am keeping the proposed patch as-is (moving qdev-core to
qom/).
--
Eduardo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
2012-10-17 18:11 ` Anthony Liguori
@ 2012-10-22 12:36 ` Igor Mammedov
2012-10-22 12:43 ` Eduardo Habkost
1 sibling, 1 reply; 27+ messages in thread
From: Igor Mammedov @ 2012-10-22 12:36 UTC (permalink / raw)
To: Eduardo Habkost
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Anthony Liguori, Andreas Färber
On Tue, 16 Oct 2012 16:08:42 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
[...]
> 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
[...]
> +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);
> +}
> +
^^^ git complains "whitespace line at EOF"
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-22 12:36 ` Igor Mammedov
@ 2012-10-22 12:43 ` Eduardo Habkost
0 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-22 12:43 UTC (permalink / raw)
To: Igor Mammedov
Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
Anthony Liguori, Andreas Färber
On Mon, Oct 22, 2012 at 02:36:01PM +0200, Igor Mammedov wrote:
> On Tue, 16 Oct 2012 16:08:42 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> [...]
> > 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
> [...]
> > +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);
> > +}
> > +
> ^^^ git complains "whitespace line at EOF"
I will fix it on the next version. Thanks.
--
Eduardo
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
` (10 preceding siblings ...)
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
11 siblings, 0 replies; 27+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
Igor Mammedov, Andreas Färber
From: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: change CPU type declaration to hae TYPE_DEVICE as parent]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
include/qemu/cpu.h | 6 +++---
qom/cpu.c | 3 ++-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h
index ad706a6..ac44057 100644
--- a/include/qemu/cpu.h
+++ b/include/qemu/cpu.h
@@ -20,7 +20,7 @@
#ifndef QEMU_CPU_H
#define QEMU_CPU_H
-#include "qemu/object.h"
+#include "hw/qdev-core.h"
#include "qemu-thread.h"
/**
@@ -46,7 +46,7 @@ typedef struct CPUState CPUState;
*/
typedef struct CPUClass {
/*< private >*/
- ObjectClass parent_class;
+ DeviceClass parent_class;
/*< public >*/
void (*reset)(CPUState *cpu);
@@ -59,7 +59,7 @@ typedef struct CPUClass {
*/
struct CPUState {
/*< private >*/
- Object parent_obj;
+ DeviceState parent_obj;
/*< public >*/
struct QemuThread *thread;
diff --git a/qom/cpu.c b/qom/cpu.c
index 5b36046..f59db7d 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -20,6 +20,7 @@
#include "qemu/cpu.h"
#include "qemu-common.h"
+#include "hw/qdev-core.h"
void cpu_reset(CPUState *cpu)
{
@@ -43,7 +44,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
static TypeInfo cpu_type_info = {
.name = TYPE_CPU,
- .parent = TYPE_OBJECT,
+ .parent = TYPE_DEVICE,
.instance_size = sizeof(CPUState),
.abstract = true,
.class_size = sizeof(CPUClass),
--
1.7.11.7
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
2012-10-16 1:57 [Qemu-devel] [PATCH v3 00/12] make CPU child of DeviceState and include qdev core in *-user Igor Mammedov
@ 2012-10-16 1:57 ` Igor Mammedov
0 siblings, 0 replies; 27+ messages in thread
From: Igor Mammedov @ 2012-10-16 1:57 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, aliguori, afaerber, ehabkost
From: Eduardo Habkost <ehabkost@redhat.com>
The code depends on some functions from qemu-option.o, so add
qemu-option.o to universal-obj-y to make sure it's included.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Makefile.objs | 3 +
hw/Makefile.objs | 2 +-
hw/qdev-core.c | 727 -------------------------------------
hw/qdev-properties.c | 963 --------------------------------------------------
qom/Makefile.objs | 2 +-
qom/qdev-core.c | 727 +++++++++++++++++++++++++++++++++++++
qom/qdev-properties.c | 963 ++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 1695 insertions(+), 1692 deletions(-)
delete mode 100644 hw/qdev-core.c
delete mode 100644 hw/qdev-properties.c
create mode 100644 qom/qdev-core.c
create mode 100644 qom/qdev-properties.c
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
^ permalink raw reply related [flat|nested] 27+ messages in thread