Patchwork [RFC,V1,07/14] fdt_generic_qdev: first revision

login
register
mail settings
Submitter Peter A. G. Crosthwaite
Date Aug. 25, 2011, 6:41 a.m.
Message ID <1314254480-22438-8-git-send-email-peter.crosthwaite@petalogix.com>
Download mbox | patch
Permalink /patch/111476/
State New
Headers show

Comments

Peter A. G. Crosthwaite - Aug. 25, 2011, 6:41 a.m.
Support for setting up qdev models for use by the fdt-generic framwork. A
single fdt init function is shared by all qdev models and the qdev model
registers a handler function that maps fdt properties to qdev properties.
Support for basic interrupt controllers and nics is there.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.objs         |    1 +
 hw/fdt_generic_qdev.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/fdt_generic_qdev.h |   46 ++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+), 0 deletions(-)
 create mode 100644 hw/fdt_generic_qdev.c
 create mode 100644 hw/fdt_generic_qdev.h

Patch

diff --git a/Makefile.objs b/Makefile.objs
index 9fd18ff..9d5100a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -222,6 +222,7 @@  hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
 
 hw-obj-$(CONFIG_FDT) += fdt_generic.o
 hw-obj-$(CONFIG_FDT) += fdt_generic_util.o
+hw-obj-$(CONFIG_FDT) += fdt_generic_qdev.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/hw/fdt_generic_qdev.c b/hw/fdt_generic_qdev.c
new file mode 100644
index 0000000..53b32ab
--- /dev/null
+++ b/hw/fdt_generic_qdev.c
@@ -0,0 +1,75 @@ 
+#include "fdt_generic_qdev.h"
+#include "fdt_generic_util.h"
+#include "net.h"
+
+#define D(a)
+
+int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, void *opaque)
+{
+    int err;
+    qemu_irq irq;
+    target_phys_addr_t base;
+    DeviceState *dev;
+    FDTQDevOps *ops = opaque;
+    struct FDTQDevPropMapping *props =
+        (ops && ops->map) ? ops->map(node_path, fdti) : NULL;
+    struct FDTQDevPropMapping *propsi;
+
+    /* create the device */
+    if (!ops || !ops->dev_name) {
+        return 1;
+    }
+    dev = qdev_create(NULL, ops->dev_name);
+    D(fprintf(stderr, "FDT: Creating QDEV model %s %s %d\n",
+        ops->dev_name, ops->is_nic ? "(nic)" : "", ops->is_intc);)
+    /* connect nic if appropriate */
+    if (ops->is_nic) {
+        qemu_check_nic_model(&nd_table[0], ops->dev_name);
+        qdev_set_nic_properties(dev, &nd_table[0]);
+    }
+    /* connect custom properties */
+    for (propsi = props; propsi && propsi->name; propsi++) {
+        enum PropertyType type;
+        if (!qdev_prop_get_type(dev, propsi->name, &type)) {
+            qdev_prop_set(dev, propsi->name, &propsi->src, type);
+            D(fprintf(stderr, "\tFDT: setting qdev prop %s %d (u32) %p (p)\n",
+                propsi->name, propsi->src.u32, propsi->src.p);)
+        }
+        if (propsi->freesrc) {
+            g_free(propsi->src.p);
+        }
+    }
+    qdev_init_nofail(dev);
+    /* map slave attachment */
+    base = qemu_devtree_getprop(fdti->fdt, NULL, node_path, "reg", 0, 0);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    /* connect irq */
+    {
+        char irq_info[1024];
+        /* FIXME: add support for multiple IRQs */
+        irq = fdt_get_irq_info(fdti, node_path, 0, &err, irq_info);
+        /* INTCs inferr their top level, if no IRQ connection specified */
+        if (err && ops->is_intc) {
+            irq = fdti->irq_base[0];
+            err = 0;
+        }
+        if (!err) {
+            sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+            fprintf(stderr, "FDT: (%s) connected irq %s\n", ops->dev_name, irq_info);
+        }
+    }
+    /* create interrupt controller connections if appropriate */
+    if (ops->is_intc) {
+        int i;
+        qemu_irq *irqs = g_malloc0(sizeof(*irqs) * ops->is_intc);
+        for (i = 0; i < ops->is_intc; i++) {
+            irqs[i] = qdev_get_gpio_in(dev, i);
+        }
+        fdt_init_set_opaque(fdti, node_path, irqs);
+    }
+
+    if (props) {
+        g_free(props);
+    }
+    return 0;
+}
diff --git a/hw/fdt_generic_qdev.h b/hw/fdt_generic_qdev.h
new file mode 100644
index 0000000..fe140b3
--- /dev/null
+++ b/hw/fdt_generic_qdev.h
@@ -0,0 +1,46 @@ 
+#ifndef FDT_GENERIC_QDEV_H
+#define FDT_GENERIC_QDEV_H
+
+#include "fdt_generic.h"
+#include "qdev.h"
+
+typedef struct FDTQDevPropMapping {
+    const char *name;
+    union {
+        /* TODO: add support for structure type QDEV props */
+        uint8_t u8;
+        uint16_t u16;
+        uint32_t u32;
+        void *p;
+    } src;
+    int freesrc;
+} FDTQDevPropMapping;
+
+typedef FDTQDevPropMapping* (*FDTQDevMapFn)(char *, FDTMachineInfo *);
+
+typedef struct FDTQDevOps {
+    const char *dev_name;
+    /* TODO: implement */
+    const int *irq_map;
+    const int is_nic;
+    /* FIXME: Add mechanism for dynamically chnginging number of intc IRQs */
+    const int is_intc;
+    FDTQDevMapFn map;
+} FDTQDevOps;
+
+/* FDT init functions for qdev models */
+
+int fdt_init_qdev(char *, FDTMachineInfo *, void *);
+
+/* statically register a FDTQDevMapFn as being associate with a compatibility */
+
+#define fdt_qdev_register_compatibility_n(ops, compat, n) \
+static void __attribute__((constructor)) \
+function ## n ## _register_imp (void) { \
+    add_to_compat_table(fdt_init_qdev, compat, ops); \
+}
+
+#define fdt_qdev_register_compatibility(ops, compat) \
+fdt_qdev_register_compatibility_n(ops, compat, 0);
+
+#endif /* FDT_GENERIC_QDEV_H */