qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RfC PATCH] qdev: rework device properties.


From: Gerd Hoffmann
Subject: [Qemu-devel] [RfC PATCH] qdev: rework device properties.
Date: Tue, 30 Jun 2009 13:31:43 +0200

Early RfC patch.  Not functional yet.  Just for comments right now.

Overall plan:
 * drop property lists. The properties are saved directly in the
   device state structs instead.
 * drop qdev_get_prop* functions, not needed any more.
 * replace qdev_set_prop* functions by qdev_prop_{parse,set*}.

Done:
 * added code to handle properties.

Todo:
 * convert all the device drivers.
 * actually drop the old functions.

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 Makefile             |    2 +-
 hw/qdev-properties.c |  166 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c            |   80 ++----------------------
 hw/qdev.h            |   44 +++++++++-----
 hw/syborg_timer.c    |   10 ++-
 5 files changed, 208 insertions(+), 94 deletions(-)
 create mode 100644 hw/qdev-properties.c

diff --git a/Makefile b/Makefile
index 918e927..af5b190 100644
--- a/Makefile
+++ b/Makefile
@@ -108,7 +108,7 @@ obj-y += bt-hci-csr.o
 obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
 obj-y += qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
 obj-y += msmouse.o ps2.o
-obj-y += qdev.o ssi.o
+obj-y += qdev.o qdev-properties.o ssi.o
 
 obj-$(CONFIG_BRLAPI) += baum.o
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
new file mode 100644
index 0000000..fc8cb9f
--- /dev/null
+++ b/hw/qdev-properties.c
@@ -0,0 +1,166 @@
+#include "qdev.h"
+
+static void *qdev_prop_ptr(DeviceState *dev, Property *prop)
+{
+    void *ptr = dev;
+    ptr += prop->offset;
+    return ptr;
+}
+
+/* --- 32bit integer --- */
+
+static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = qdev_prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIu32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t 
len)
+{
+    uint32_t *ptr = qdev_prop_ptr(dev, prop);
+    return snprintf(dest, len, "%" PRIu32, *ptr);
+}
+
+PropertyInfo qdev_prop_uint32 = {
+    .name  = "uint32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_uint32,
+    .print = print_uint32,
+};
+
+/* --- 32bit hex value --- */
+
+static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = qdev_prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIx32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t 
len)
+{
+    uint32_t *ptr = qdev_prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x%" PRIx32, *ptr);
+}
+
+PropertyInfo qdev_prop_hex32 = {
+    .name  = "hex32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_hex32,
+    .print = print_hex32,
+};
+
+/* --- mac address --- */
+
+/*
+ * accepted syntax versions:
+ *   01:02:03:04:05:06
+ *   01-02-03-04-05-06
+ */
+static int parse_mac(DeviceState *dev, Property *prop, const char *str)
+{
+    uint8_t *mac = qdev_prop_ptr(dev, prop);
+    int i, pos;
+    char *p;
+
+    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
+        if (!isxdigit(str[pos]))
+            return -1;
+        if (!isxdigit(str[pos+1]))
+            return -1;
+        if (i == 5 && str[pos+2] != '\0')
+            return -1;
+        if (str[pos+2] != ':' && str[pos+2] != '-')
+            return -1;
+        mac[i] = strtol(str+pos, &p, 16);
+    }
+    return 0;
+}
+
+static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint8_t *mac = qdev_prop_ptr(dev, prop);
+    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
+                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+PropertyInfo qdev_prop_mac = {
+    .name  = "mac",
+    .size  = 6,
+    .parse = parse_mac,
+    .print = print_mac,
+};
+
+/* --- public helpers --- */
+
+static Property *qdev_prop_find(DeviceState *dev, const char *name)
+{
+    Property *props;
+
+    /* device properties */
+    props = dev->info->props;
+    while (props->name) {
+        if (strcmp(props->name, name) == 0)
+            return props;
+        props++;
+    }
+
+    /* bus properties */
+    props = dev->info->props;
+    while (props->name) {
+        if (strcmp(props->name, name) == 0)
+            return props;
+        props++;
+    }
+
+    return NULL;
+}
+
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
+{
+    Property *prop;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (!prop->info->parse) {
+        fprintf(stderr, "property \"%s.%s\" has no parser\n",
+                dev->info->name, name);
+        return -1;
+    }
+    return prop->info->parse(dev, prop, value);
+}
+
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size)
+{
+    Property *prop;
+    void *dst;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (prop->info->size != size) {
+        fprintf(stderr, "property \"%s.%s\" size mismatch (%zd / %zd)\n",
+                dev->info->name, name, prop->info->size, size);
+        return -1;
+    }
+    dst = qdev_prop_ptr(dev, prop);
+    memcpy(dst, src, size);
+    return 0;
+}
+
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
+{
+    return qdev_prop_set(dev, name, &value, sizeof(value));
+}
diff --git a/hw/qdev.c b/hw/qdev.c
index 8d19cbe..ab23cd2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -31,16 +31,6 @@
 #include "sysemu.h"
 #include "monitor.h"
 
-struct DeviceProperty {
-    const char *name;
-    DevicePropType type;
-    union {
-        uint64_t i;
-        void *ptr;
-    } value;
-    DeviceProperty *next;
-};
-
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 static BusState *main_system_bus;
 extern struct BusInfo system_bus_info;
@@ -112,52 +102,22 @@ void qdev_free(DeviceState *dev)
     free(dev);
 }
 
-static DeviceProperty *create_prop(DeviceState *dev, const char *name,
-                                   DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    /* TODO: Check for duplicate properties.  */
-    prop = qemu_mallocz(sizeof(*prop));
-    prop->name = qemu_strdup(name);
-    prop->type = type;
-    prop->next = dev->props;
-    dev->props = prop;
-
-    return prop;
-}
-
 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
 {
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_INT);
-    prop->value.i = value;
 }
 
 void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
 {
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_DEV);
-    prop->value.ptr = value;
 }
 
 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
 {
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_PTR);
-    prop->value.ptr = value;
 }
 
 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
 {
-    assert(!dev->nd);
-    dev->nd = nd;
 }
 
-
 /* Get a character (serial) device interface.  */
 CharDriverState *qdev_init_chardev(DeviceState *dev)
 {
@@ -176,50 +136,19 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
     return dev->parent_bus;
 }
 
-static DeviceProperty *find_prop(DeviceState *dev, const char *name,
-                                 DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    for (prop = dev->props; prop; prop = prop->next) {
-        if (strcmp(prop->name, name) == 0) {
-            assert (prop->type == type);
-            return prop;
-        }
-    }
-    return NULL;
-}
-
 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
 {
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_INT);
-    if (!prop) {
-        return def;
-    }
-
-    return prop->value.i;
+    return def;
 }
 
 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
 {
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_PTR);
-    assert(prop);
-    return prop->value.ptr;
+    return NULL;
 }
 
 DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
 {
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_DEV);
-    if (!prop) {
-        return NULL;
-    }
-    return prop->value.ptr;
+    return NULL;
 }
 
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
@@ -345,7 +274,6 @@ static void qbus_print(Monitor *mon, BusState *bus, int 
indent);
 
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 {
-    DeviceProperty *prop;
     BusState *child;
     qdev_printf("dev: %s\n", dev->info->name);
     indent += 2;
@@ -355,6 +283,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
     if (dev->num_gpio_out) {
         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
     }
+#if 0
     for (prop = dev->props; prop; prop = prop->next) {
         switch (prop->type) {
         case PROP_TYPE_INT:
@@ -373,6 +302,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int 
indent)
             break;
         }
     }
+#endif
     if (dev->parent_bus->info->print)
         dev->parent_bus->info->print(mon, dev, indent);
     LIST_FOREACH(child, &dev->child_bus, sibling) {
diff --git a/hw/qdev.h b/hw/qdev.h
index 2dbf414..c7a8d18 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -4,9 +4,11 @@
 #include "hw.h"
 #include "sys-queue.h"
 
-typedef struct DeviceInfo DeviceInfo;
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
 
-typedef struct DeviceProperty DeviceProperty;
+typedef struct DeviceInfo DeviceInfo;
 
 typedef struct BusState BusState;
 
@@ -17,7 +19,6 @@ typedef struct BusInfo BusInfo;
 struct DeviceState {
     DeviceInfo *info;
     BusState *parent_bus;
-    DeviceProperty *props;
     int num_gpio_out;
     qemu_irq *gpio_out;
     int num_gpio_in;
@@ -31,6 +32,7 @@ typedef void (*bus_dev_print)(Monitor *mon, DeviceState *dev, 
int indent);
 struct BusInfo {
     const char *name;
     size_t size;
+    Property *props;
     bus_dev_print print;
     int next_busnr;
 };
@@ -45,6 +47,19 @@ struct BusState {
     TAILQ_ENTRY(BusState) next;
 };
 
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+};
+
+struct PropertyInfo {
+    const char *name;
+    size_t size;
+    int (*parse)(DeviceState *dev, Property *prop, const char *str);
+    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+};
+
 /*** Board API.  This should go away once we have a machine config file.  ***/
 
 DeviceState *qdev_create(BusState *bus, const char *name);
@@ -64,23 +79,12 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char 
*name);
 
 /*** Device API.  ***/
 
-typedef enum {
-    PROP_TYPE_INT,
-    PROP_TYPE_PTR,
-    PROP_TYPE_DEV
-} DevicePropType;
-
-typedef struct {
-    const char *name;
-    DevicePropType type;
-} DevicePropList;
-
 typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
 
 struct DeviceInfo {
     const char *name;
     size_t size;
-    DevicePropList *props;
+    Property *props;
 
     /* Private to qdev / bus.  */
     qdev_initfn init;
@@ -129,4 +133,14 @@ void do_info_qdrv(Monitor *mon);
 /* helper for "-${bus}device ?" */
 void do_list_qdrv(BusInfo *bus);
 
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_mac;
+
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size);
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+
 #endif
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 4f5e3a1..f3d00d8 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -230,9 +230,13 @@ static SysBusDeviceInfo syborg_timer_info = {
     .init = syborg_timer_init,
     .qdev.name  = "syborg,timer",
     .qdev.size  = sizeof(SyborgTimerState),
-    .qdev.props = (DevicePropList[]) {
-        {.name = "frequency", .type = PROP_TYPE_INT},
-        {.name = NULL}
+    .qdev.props = (Property[]) {
+        {
+            .name   = "frequency",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgTimerState, freq),
+        },
+        {/* end of list */}
     }
 };
 
-- 
1.6.2.5





reply via email to

[Prev in Thread] Current Thread [Next in Thread]