@@ -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 *);
@@ -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;
+}
+
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(-)