Patchwork [02/20,MIPS] cpu: convert to qdev

login
register
mail settings
Submitter Hervé Poussineau
Date Aug. 1, 2010, 5:37 p.m.
Message ID <1280684242-19611-2-git-send-email-hpoussin@reactos.org>
Download mbox | patch
Permalink /patch/60473/
State New
Headers show

Comments

Hervé Poussineau - Aug. 1, 2010, 5:37 p.m.
Add a qdev device representing a whole MIPS CPU, ie the core, the interrupt controller, and the timer.
Export a qdev bus, so other devices can use MIPS CPU interrupts

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/mips_cpudevs.h |    4 ++
 hw/mips_int.c     |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 0 deletions(-)

Patch

diff --git a/hw/mips_cpudevs.h b/hw/mips_cpudevs.h
index db82b41..495b3fd 100644
--- a/hw/mips_cpudevs.h
+++ b/hw/mips_cpudevs.h
@@ -1,5 +1,7 @@ 
 #ifndef HW_MIPS_CPUDEVS_H
 #define HW_MIPS_CPUDEVS_H
+#include "qdev.h"
+
 /* Definitions for MIPS CPU internal devices.  */
 
 /* mips_addr.c */
@@ -8,6 +10,8 @@  uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
 
 /* mips_int.c */
 void cpu_mips_irq_init_cpu(CPUState *env);
+BusState *cpu_mips_init_cpu(const char *model);
+void cpu_mips_register(DeviceInfo *info);
 
 /* mips_timer.c */
 void cpu_mips_clock_init(CPUState *);
diff --git a/hw/mips_int.c b/hw/mips_int.c
index 477f6ab..8e868be 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -22,6 +22,7 @@ 
 
 #include "hw.h"
 #include "mips_cpudevs.h"
+#include "sysbus.h"
 #include "cpu.h"
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
@@ -63,3 +64,83 @@  void cpu_mips_soft_irq(CPUState *env, int irq, int level)
 
     qemu_set_irq(env->irq[irq], level);
 }
+
+typedef struct CPUMIPS
+{
+    SysBusDevice busdev;
+    BusState qbus;
+    char *model;
+    CPUState state;
+} CPUMIPS;
+
+static void cpu_mips_irq_request1(void *opaque, int irq, int level)
+{
+    CPUMIPS *s = FROM_SYSBUS(CPUMIPS, sysbus_from_qdev(opaque));
+    CPUState *env = &s->state;
+    cpu_mips_irq_request(env, irq, level);
+}
+
+static void cpu_device_reset(DeviceState *d)
+{
+    CPUMIPS *s = FROM_SYSBUS(CPUMIPS, sysbus_from_qdev(d));
+    cpu_reset(&s->state);
+}
+
+static struct BusInfo cpu_bus_info = {
+    .name      = "cpu",
+    .size      = 0,
+};
+
+void cpu_mips_register(DeviceInfo *info)
+{
+    info->bus_info = &cpu_bus_info;
+    qdev_register(info);
+}
+
+static int cpu_device_init(SysBusDevice *dev)
+{
+    CPUMIPS* cpu = FROM_SYSBUS(CPUMIPS, dev);
+
+    if (cpu_mips_init_inplace(&cpu->state, cpu->model) < 0)
+        return -1;
+
+    cpu_mips_clock_init(&cpu->state);
+
+    qbus_create_inplace(&cpu->qbus, &cpu_bus_info, &dev->qdev, NULL);
+    qdev_init_gpio_in(cpu->qbus.parent, cpu_mips_irq_request1, 8);
+    return 0;
+}
+
+static SysBusDeviceInfo cpu_device_info = {
+    .qdev.name  = "cpu-mips",
+    .qdev.size  = sizeof(CPUMIPS),
+    .qdev.reset = cpu_device_reset,
+    .init       = cpu_device_init,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_STRING("model", CPUMIPS, model),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void mips_register_devices(void)
+{
+    sysbus_register_withprop(&cpu_device_info);
+}
+
+device_init(mips_register_devices)
+
+BusState *cpu_mips_init_cpu(const char *cpu_model)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "cpu-mips");
+    if (!dev) {
+        return NULL;
+    }
+    qdev_prop_set_string(dev, "model", qemu_strdup(cpu_model));
+    if (qdev_init(dev) < 0) {
+        return NULL;
+    }
+    return &container_of(dev, CPUMIPS, busdev.qdev)->qbus;
+}
+