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 <hpous...@reactos.org> --- hw/mips_cpudevs.h | 4 ++ hw/mips_int.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 0 deletions(-) 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; +} + -- 1.7.1.GIT