From: Peter Maydell <peter.maydell@linaro.org>
To: Anthony Liguori <aliguori@us.ibm.com>, Blue Swirl <blauwirbel@gmail.com>
Cc: qemu-devel@nongnu.org, Paul Brook <paul@codesourcery.com>
Subject: [Qemu-devel] [PATCH 06/17] qdev: Implement (variable length) array properties
Date: Fri, 15 Mar 2013 16:56:28 +0000 [thread overview]
Message-ID: <1363366599-24238-7-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1363366599-24238-1-git-send-email-peter.maydell@linaro.org>
Add support for declaring array properties for qdev devices.
These work by defining an initial static property 'len-arrayname'
which the user of the device should set to the desired size
of the array. When this property is set, memory is allocated
for the array elements, and dynamic properties "arrayname[0]",
"arrayname[1]"... are created so the user of the device can
then set the values of the individual array elements.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/qdev-core.h | 3 ++
hw/qdev-properties.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/qdev-properties.h | 39 +++++++++++++++++++
3 files changed, 146 insertions(+)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 2486f36..547fbc7 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -175,6 +175,9 @@ struct Property {
uint8_t bitnr;
uint8_t qtype;
int64_t defval;
+ int arrayoffset;
+ PropertyInfo *arrayinfo;
+ int arrayfieldsize;
};
struct PropertyInfo {
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0307a78..247ca6c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -779,6 +779,110 @@ PropertyInfo qdev_prop_pci_host_devaddr = {
.set = set_pci_host_devaddr,
};
+/* --- support for array properties --- */
+
+/* Used as an opaque for the object properties we add for each
+ * array element. Note that the struct Property must be first
+ * in the struct so that a pointer to this works as the opaque
+ * for the underlying element's property hooks as well as for
+ * our own release callback.
+ */
+typedef struct {
+ struct Property prop;
+ char *propname;
+ ObjectPropertyRelease *release;
+} ArrayElementProperty;
+
+/* object property release callback for array element properties:
+ * we call the underlying element's property release hook, and
+ * then free the memory we allocated when we added the property.
+ */
+static void array_element_release(Object *obj, const char *name, void *opaque)
+{
+ ArrayElementProperty *p = opaque;
+ if (p->release) {
+ p->release(obj, name, opaque);
+ }
+ g_free(p->propname);
+ g_free(p);
+}
+
+static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ /* Setter for the property which defines the length of a
+ * variable-sized property array. As well as actually setting the
+ * array-length field in the device struct, we have to create the
+ * array itself and dynamically add the corresponding properties.
+ */
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
+ void **arrayptr = (void *)dev + prop->arrayoffset;
+ void *eltptr;
+ const char *arrayname;
+ int i;
+
+ if (dev->realized) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+ if (*alenptr) {
+ error_setg(errp, "array size property %s may not be set more than once",
+ name);
+ return;
+ }
+ visit_type_uint32(v, alenptr, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (!*alenptr) {
+ return;
+ }
+
+ /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
+ * strip it off so we can get the name of the array itself.
+ */
+ assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
+ strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
+ arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
+
+ /* Note that it is the responsibility of the individual device's deinit
+ * to free the array proper.
+ */
+ *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
+ for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
+ char *propname = g_strdup_printf("%s[%d]", arrayname, i);
+ ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
+ arrayprop->release = prop->arrayinfo->release;
+ arrayprop->propname = propname;
+ arrayprop->prop.info = prop->arrayinfo;
+ arrayprop->prop.name = propname;
+ /* This ugly piece of pointer arithmetic sets up the offset so
+ * that when the underlying get/set hooks call qdev_get_prop_ptr
+ * they get the right answer despite the array element not actually
+ * being inside the device struct.
+ */
+ arrayprop->prop.offset = eltptr - (void *)dev;
+ assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
+ object_property_add(obj, propname,
+ arrayprop->prop.info->name,
+ arrayprop->prop.info->get,
+ arrayprop->prop.info->set,
+ array_element_release,
+ arrayprop, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ }
+}
+
+PropertyInfo qdev_prop_arraylen = {
+ .name = "uint32",
+ .get = get_uint32,
+ .set = set_prop_arraylen,
+};
+
/* --- public helpers --- */
static Property *qdev_prop_walk(Property *props, const char *name)
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 0b0465c..c9bb246 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -26,6 +26,7 @@ extern PropertyInfo qdev_prop_vlan;
extern PropertyInfo qdev_prop_pci_devfn;
extern PropertyInfo qdev_prop_blocksize;
extern PropertyInfo qdev_prop_pci_host_devaddr;
+extern PropertyInfo qdev_prop_arraylen;
#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
.name = (_name), \
@@ -51,6 +52,44 @@ extern PropertyInfo qdev_prop_pci_host_devaddr;
.defval = (bool)_defval, \
}
+#define PROP_ARRAY_LEN_PREFIX "len-"
+
+/**
+ * DEFINE_PROP_ARRAY:
+ * @_name: name of the array
+ * @_state: name of the device state structure type
+ * @_field: uint32_t field in @_state to hold the array length
+ * @_arrayfield: field in @_state (of type '@_arraytype *') which
+ * will point to the array
+ * @_arrayprop: PropertyInfo defining what property the array elements have
+ * @_arraytype: C type of the array elements
+ *
+ * Define device properties for a variable-length array _name. A
+ * static property "len-arrayname" is defined. When the device creator
+ * sets this property to the desired length of array, further dynamic
+ * properties "arrayname[0]", "arrayname[1]", ... are defined so the
+ * device creator can set the array element values. Setting the
+ * "len-arrayname" property more than once is an error.
+ *
+ * When the array length is set, the @_field member of the device
+ * struct is set to the array length, and @_arrayfield is set to point
+ * to (zero-initialised) memory allocated for the array. For a zero
+ * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * It is the responsibility of the device deinit code to free the
+ * @_arrayfield memory.
+ */
+#define DEFINE_PROP_ARRAY(_name, _state, _field, \
+ _arrayfield, _arrayprop, _arraytype) { \
+ .name = (PROP_ARRAY_LEN_PREFIX _name), \
+ .info = &(qdev_prop_arraylen), \
+ .offset = offsetof(_state, _field) \
+ + type_check(uint32_t, typeof_field(_state, _field)), \
+ .qtype = QTYPE_QINT, \
+ .arrayinfo = &(_arrayprop), \
+ .arrayfieldsize = sizeof(_arraytype), \
+ .arrayoffset = offsetof(_state, _arrayfield), \
+ }
+
#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) \
--
1.7.9.5
next prev parent reply other threads:[~2013-03-15 17:16 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-15 16:56 [Qemu-devel] [PULL 00/17] arm-devs queue Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 01/17] hw/vexpress: Pass proc_id via VEDBoardInfo Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 02/17] hw/arm_sysctl: Handle SYS_CFGCTRL in a more structured way Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 03/17] hw/arm_sysctl: Implement SYS_CFG_MUXFPGA writes as a no-op Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 04/17] hw/arm_sysctl: Implement SYS_CFG_DVIMODE " Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 05/17] hw/arm_sysctl: Convert from qdev init to instance_init Peter Maydell
2013-03-15 16:56 ` Peter Maydell [this message]
2013-03-15 16:56 ` [Qemu-devel] [PATCH 07/17] hw/arm_sysctl: Implement SYS_CFG_VOLT Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 08/17] hw/vexpress: Pass voltage sensor properties to sysctl device Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 09/17] hw/arm_sysctl: Implement SYS_CFG_OSC function Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 10/17] hw/vexpress: Set reset values for daughterboard oscillators Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 11/17] iov: Factor out hexdumper Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 12/17] pl330: Initial version Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 13/17] xilinx_zynq: added pl330 to machine model Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 14/17] xilinx_spips: Set unused IRQs to NULL Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 15/17] xilinx_spips: Fix bus setup conditional check Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 16/17] xilinx_spips: Add missing dual-bus snoop commands Peter Maydell
2013-03-15 16:56 ` [Qemu-devel] [PATCH 17/17] xilinx_spips: QOM styling fixes Peter Maydell
2013-03-17 20:48 ` [Qemu-devel] [PULL 00/17] arm-devs queue Blue Swirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1363366599-24238-7-git-send-email-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=aliguori@us.ibm.com \
--cc=blauwirbel@gmail.com \
--cc=paul@codesourcery.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).