diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-01-19 11:57:07 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-01-19 11:57:07 +0000 |
commit | f1fcb6851aba6dd9838886dc179717a11e344a1c (patch) | |
tree | d605d864fbb944916231dfe272899b3583bd12ef | |
parent | c114af1639d26cbcbc06132bae95f9906206ded3 (diff) | |
parent | 41da32471183d7ca4756ad3ed8bb11c1d0c37a32 (diff) | |
download | qemu-f1fcb6851aba6dd9838886dc179717a11e344a1c.zip qemu-f1fcb6851aba6dd9838886dc179717a11e344a1c.tar.gz qemu-f1fcb6851aba6dd9838886dc179717a11e344a1c.tar.bz2 |
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-19' into staging
* Refactor next-cube interrupt and register handling into a proper QOM device
# gpg: Signature made Tue 19 Jan 2021 08:15:39 GMT
# gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg: issuer "huth@tuxfamily.org"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg: aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5
* remotes/huth-gitlab/tags/pull-request-2021-01-19:
hw/m68k/next-cube: Add missing header comment to next-cube.h
hw/m68k/next-cube: Add vmstate for NeXTPC device
hw/m68k/next-cube: Remove unused fields from NeXTState
hw/m68k/next-cube: Move rtc into NeXTPC struct
hw/m68k/next-cube: Make next_irq GPIO inputs to NEXT_PC device
hw/m68k/next-cube: Move int_status and int_mask to NeXTPC struct
hw/m68k/next-cube: Make next_irq take NeXTPC* as its opaque
hw/m68k/next-cube: Move scr_ops into NeXTPC device
hw/m68k/next-cube: Move mmio_ops into NeXTPC device
hw/m68k/next-cube: Move register/interrupt functionality into a device
hw/m68k/next-cube: Make next_irq() function static
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/m68k/next-cube.c | 239 | ||||
-rw-r--r-- | include/hw/m68k/next-cube.h | 15 |
2 files changed, 169 insertions, 85 deletions
diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c index 37bc35d..92b45d7 100644 --- a/hw/m68k/next-cube.c +++ b/hw/m68k/next-cube.c @@ -28,6 +28,7 @@ #include "qapi/error.h" #include "ui/console.h" #include "target/m68k/cpu.h" +#include "migration/vmstate.h" /* #define DEBUG_NEXT */ #ifdef DEBUG_NEXT @@ -73,19 +74,27 @@ typedef struct NextRtc { struct NeXTState { MachineState parent; - uint32_t int_mask; - uint32_t int_status; - - uint8_t scsi_csr_1; - uint8_t scsi_csr_2; next_dma dma[10]; - qemu_irq *scsi_irq; - qemu_irq scsi_dma; - qemu_irq scsi_reset; - qemu_irq *fd_irq; +}; + +#define TYPE_NEXT_PC "next-pc" +OBJECT_DECLARE_SIMPLE_TYPE(NeXTPC, NEXT_PC) + +/* NeXT Peripheral Controller */ +struct NeXTPC { + SysBusDevice parent_obj; + + M68kCPU *cpu; + + MemoryRegion mmiomem; + MemoryRegion scrmem; uint32_t scr1; uint32_t scr2; + uint8_t scsi_csr_1; + uint8_t scsi_csr_2; + uint32_t int_mask; + uint32_t int_status; NextRtc rtc; }; @@ -110,7 +119,7 @@ static const uint8_t rtc_ram2[32] = { #define SCR2_RTDATA 0x4 #define SCR2_TOBCD(x) (((x / 10) << 4) + (x % 10)) -static void nextscr2_write(NeXTState *s, uint32_t val, int size) +static void nextscr2_write(NeXTPC *s, uint32_t val, int size) { static int led; static int phase; @@ -244,7 +253,7 @@ static void nextscr2_write(NeXTState *s, uint32_t val, int size) old_scr2 = scr2_2; } -static uint32_t mmio_readb(NeXTState *s, hwaddr addr) +static uint32_t mmio_readb(NeXTPC *s, hwaddr addr) { switch (addr) { case 0xc000: @@ -274,7 +283,7 @@ static uint32_t mmio_readb(NeXTState *s, hwaddr addr) } } -static uint32_t mmio_readw(NeXTState *s, hwaddr addr) +static uint32_t mmio_readw(NeXTPC *s, hwaddr addr) { switch (addr) { default: @@ -283,7 +292,7 @@ static uint32_t mmio_readw(NeXTState *s, hwaddr addr) } } -static uint32_t mmio_readl(NeXTState *s, hwaddr addr) +static uint32_t mmio_readl(NeXTPC *s, hwaddr addr) { switch (addr) { case 0x7000: @@ -306,7 +315,7 @@ static uint32_t mmio_readl(NeXTState *s, hwaddr addr) } } -static void mmio_writeb(NeXTState *s, hwaddr addr, uint32_t val) +static void mmio_writeb(NeXTPC *s, hwaddr addr, uint32_t val) { switch (addr) { case 0xd003: @@ -318,12 +327,12 @@ static void mmio_writeb(NeXTState *s, hwaddr addr, uint32_t val) } -static void mmio_writew(NeXTState *s, hwaddr addr, uint32_t val) +static void mmio_writew(NeXTPC *s, hwaddr addr, uint32_t val) { DPRINTF("MMIO Write W\n"); } -static void mmio_writel(NeXTState *s, hwaddr addr, uint32_t val) +static void mmio_writel(NeXTPC *s, hwaddr addr, uint32_t val) { switch (addr) { case 0x7000: @@ -348,15 +357,15 @@ static void mmio_writel(NeXTState *s, hwaddr addr, uint32_t val) static uint64_t mmio_readfn(void *opaque, hwaddr addr, unsigned size) { - NeXTState *ns = NEXT_MACHINE(opaque); + NeXTPC *s = NEXT_PC(opaque); switch (size) { case 1: - return mmio_readb(ns, addr); + return mmio_readb(s, addr); case 2: - return mmio_readw(ns, addr); + return mmio_readw(s, addr); case 4: - return mmio_readl(ns, addr); + return mmio_readl(s, addr); default: g_assert_not_reached(); } @@ -365,17 +374,17 @@ static uint64_t mmio_readfn(void *opaque, hwaddr addr, unsigned size) static void mmio_writefn(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - NeXTState *ns = NEXT_MACHINE(opaque); + NeXTPC *s = NEXT_PC(opaque); switch (size) { case 1: - mmio_writeb(ns, addr, value); + mmio_writeb(s, addr, value); break; case 2: - mmio_writew(ns, addr, value); + mmio_writew(s, addr, value); break; case 4: - mmio_writel(ns, addr, value); + mmio_writel(s, addr, value); break; default: g_assert_not_reached(); @@ -390,7 +399,7 @@ static const MemoryRegionOps mmio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint32_t scr_readb(NeXTState *s, hwaddr addr) +static uint32_t scr_readb(NeXTPC *s, hwaddr addr) { switch (addr) { case 0x14108: @@ -424,13 +433,13 @@ static uint32_t scr_readb(NeXTState *s, hwaddr addr) } } -static uint32_t scr_readw(NeXTState *s, hwaddr addr) +static uint32_t scr_readw(NeXTPC *s, hwaddr addr) { DPRINTF("BMAP Read W @ %x\n", (unsigned int)addr); return 0; } -static uint32_t scr_readl(NeXTState *s, hwaddr addr) +static uint32_t scr_readl(NeXTPC *s, hwaddr addr) { DPRINTF("BMAP Read L @ %x\n", (unsigned int)addr); return 0; @@ -443,7 +452,7 @@ static uint32_t scr_readl(NeXTState *s, hwaddr addr) #define SCSICSR_CPUDMA 0x10 /* if set, dma enabled */ #define SCSICSR_INTMASK 0x20 /* if set, interrupt enabled */ -static void scr_writeb(NeXTState *s, hwaddr addr, uint32_t value) +static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value) { switch (addr) { case 0x14108: @@ -521,27 +530,27 @@ static void scr_writeb(NeXTState *s, hwaddr addr, uint32_t value) } } -static void scr_writew(NeXTState *s, hwaddr addr, uint32_t value) +static void scr_writew(NeXTPC *s, hwaddr addr, uint32_t value) { DPRINTF("BMAP Write W @ %x with %x\n", (unsigned int)addr, value); } -static void scr_writel(NeXTState *s, hwaddr addr, uint32_t value) +static void scr_writel(NeXTPC *s, hwaddr addr, uint32_t value) { DPRINTF("BMAP Write L @ %x with %x\n", (unsigned int)addr, value); } static uint64_t scr_readfn(void *opaque, hwaddr addr, unsigned size) { - NeXTState *ns = NEXT_MACHINE(opaque); + NeXTPC *s = NEXT_PC(opaque); switch (size) { case 1: - return scr_readb(ns, addr); + return scr_readb(s, addr); case 2: - return scr_readw(ns, addr); + return scr_readw(s, addr); case 4: - return scr_readl(ns, addr); + return scr_readl(s, addr); default: g_assert_not_reached(); } @@ -550,17 +559,17 @@ static uint64_t scr_readfn(void *opaque, hwaddr addr, unsigned size) static void scr_writefn(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - NeXTState *ns = NEXT_MACHINE(opaque); + NeXTPC *s = NEXT_PC(opaque); switch (size) { case 1: - scr_writeb(ns, addr, value); + scr_writeb(s, addr, value); break; case 2: - scr_writew(ns, addr, value); + scr_writew(s, addr, value); break; case 4: - scr_writel(ns, addr, value); + scr_writel(s, addr, value); break; default: g_assert_not_reached(); @@ -720,15 +729,11 @@ static const MemoryRegionOps dma_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -/* - * TODO: set the shift numbers as values in the enum, so the first switch - * will not be needed - */ -void next_irq(void *opaque, int number, int level) +static void next_irq(void *opaque, int number, int level) { - M68kCPU *cpu = opaque; + NeXTPC *s = NEXT_PC(opaque); + M68kCPU *cpu = s->cpu; int shift = 0; - NeXTState *ns = NEXT_MACHINE(qdev_get_machine()); /* first switch sets interupt status */ /* DPRINTF("IRQ %i\n",number); */ @@ -783,14 +788,14 @@ void next_irq(void *opaque, int number, int level) * this HAS to be wrong, the interrupt handlers in mach and together * int_status and int_mask and return if there is a hit */ - if (ns->int_mask & (1 << shift)) { + if (s->int_mask & (1 << shift)) { DPRINTF("%x interrupt masked @ %x\n", 1 << shift, cpu->env.pc); /* return; */ } /* second switch triggers the correct interrupt */ if (level) { - ns->int_status |= 1 << shift; + s->int_status |= 1 << shift; switch (number) { /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */ @@ -819,24 +824,13 @@ void next_irq(void *opaque, int number, int level) break; } } else { - ns->int_status &= ~(1 << shift); + s->int_status &= ~(1 << shift); cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); } } -static void next_serial_irq(void *opaque, int n, int level) -{ - /* DPRINTF("SCC IRQ NUM %i\n",n); */ - if (n) { - next_irq(opaque, NEXT_SCC_DMA_I, level); - } else { - next_irq(opaque, NEXT_SCC_I, level); - } -} - -static void next_escc_init(M68kCPU *cpu) +static void next_escc_init(DeviceState *pcdev) { - qemu_irq *ser_irq = qemu_allocate_irqs(next_serial_irq, cpu, 2); DeviceState *dev; SysBusDevice *s; @@ -852,25 +846,113 @@ static void next_escc_init(M68kCPU *cpu) s = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(s, &error_fatal); - sysbus_connect_irq(s, 0, ser_irq[0]); - sysbus_connect_irq(s, 1, ser_irq[1]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(pcdev, NEXT_SCC_I)); + sysbus_connect_irq(s, 1, qdev_get_gpio_in(pcdev, NEXT_SCC_DMA_I)); sysbus_mmio_map(s, 0, 0x2118000); } +static void next_pc_reset(DeviceState *dev) +{ + NeXTPC *s = NEXT_PC(dev); + + /* Set internal registers to initial values */ + /* 0x0000XX00 << vital bits */ + s->scr1 = 0x00011102; + s->scr2 = 0x00ff0c80; + + s->rtc.status = 0x90; + + /* Load RTC RAM - TODO: provide possibility to load contents from file */ + memcpy(s->rtc.ram, rtc_ram2, 32); +} + +static void next_pc_realize(DeviceState *dev, Error **errp) +{ + NeXTPC *s = NEXT_PC(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + qdev_init_gpio_in(dev, next_irq, NEXT_NUM_IRQS); + + memory_region_init_io(&s->mmiomem, OBJECT(s), &mmio_ops, s, + "next.mmio", 0xD0000); + memory_region_init_io(&s->scrmem, OBJECT(s), &scr_ops, s, + "next.scr", 0x20000); + sysbus_init_mmio(sbd, &s->mmiomem); + sysbus_init_mmio(sbd, &s->scrmem); +} + +/* + * If the m68k CPU implemented its inbound irq lines as GPIO lines + * rather than via the m68k_set_irq_level() function we would not need + * this cpu link property and could instead provide outbound IRQ lines + * that the board could wire up to the CPU. + */ +static Property next_pc_properties[] = { + DEFINE_PROP_LINK("cpu", NeXTPC, cpu, TYPE_M68K_CPU, M68kCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription next_rtc_vmstate = { + .name = "next-rtc", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(ram, NextRtc, 32), + VMSTATE_UINT8(command, NextRtc), + VMSTATE_UINT8(value, NextRtc), + VMSTATE_UINT8(status, NextRtc), + VMSTATE_UINT8(control, NextRtc), + VMSTATE_UINT8(retval, NextRtc), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription next_pc_vmstate = { + .name = "next-pc", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(scr1, NeXTPC), + VMSTATE_UINT32(scr2, NeXTPC), + VMSTATE_UINT32(int_mask, NeXTPC), + VMSTATE_UINT32(int_status, NeXTPC), + VMSTATE_UINT8(scsi_csr_1, NeXTPC), + VMSTATE_UINT8(scsi_csr_2, NeXTPC), + VMSTATE_STRUCT(rtc, NeXTPC, 0, next_rtc_vmstate, NextRtc), + VMSTATE_END_OF_LIST() + }, +}; + +static void next_pc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "NeXT Peripheral Controller"; + dc->realize = next_pc_realize; + dc->reset = next_pc_reset; + device_class_set_props(dc, next_pc_properties); + dc->vmsd = &next_pc_vmstate; +} + +static const TypeInfo next_pc_info = { + .name = TYPE_NEXT_PC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NeXTPC), + .class_init = next_pc_class_init, +}; + static void next_cube_init(MachineState *machine) { M68kCPU *cpu; CPUM68KState *env; MemoryRegion *rom = g_new(MemoryRegion, 1); - MemoryRegion *mmiomem = g_new(MemoryRegion, 1); - MemoryRegion *scrmem = g_new(MemoryRegion, 1); MemoryRegion *dmamem = g_new(MemoryRegion, 1); MemoryRegion *bmapm1 = g_new(MemoryRegion, 1); MemoryRegion *bmapm2 = g_new(MemoryRegion, 1); MemoryRegion *sysmem = get_system_memory(); const char *bios_name = machine->firmware ?: ROM_FILE; - NeXTState *ns = NEXT_MACHINE(machine); DeviceState *dev; + DeviceState *pcdev; /* Initialize the cpu core */ cpu = M68K_CPU(cpu_create(machine->cpu_type)); @@ -884,14 +966,10 @@ static void next_cube_init(MachineState *machine) env->vbr = 0; env->sr = 0x2700; - /* Set internal registers to initial values */ - /* 0x0000XX00 << vital bits */ - ns->scr1 = 0x00011102; - ns->scr2 = 0x00ff0c80; - ns->rtc.status = 0x90; - - /* Load RTC RAM - TODO: provide possibility to load contents from file */ - memcpy(ns->rtc.ram, rtc_ram2, 32); + /* Peripheral Controller */ + pcdev = qdev_new(TYPE_NEXT_PC); + object_property_set_link(OBJECT(pcdev), "cpu", OBJECT(cpu), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pcdev), &error_fatal); /* 64MB RAM starting at 0x04000000 */ memory_region_add_subregion(sysmem, 0x04000000, machine->ram); @@ -902,9 +980,10 @@ static void next_cube_init(MachineState *machine) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0B000000); /* MMIO */ - memory_region_init_io(mmiomem, NULL, &mmio_ops, machine, "next.mmio", - 0xD0000); - memory_region_add_subregion(sysmem, 0x02000000, mmiomem); + sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 0, 0x02000000); + + /* BMAP IO - acts as a catch-all for now */ + sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02100000); /* BMAP memory */ memory_region_init_ram_shared_nomigrate(bmapm1, NULL, "next.bmapmem", 64, @@ -914,11 +993,6 @@ static void next_cube_init(MachineState *machine) memory_region_init_alias(bmapm2, NULL, "next.bmapmem2", bmapm1, 0x0, 64); memory_region_add_subregion(sysmem, 0x820c0000, bmapm2); - /* BMAP IO - acts as a catch-all for now */ - memory_region_init_io(scrmem, NULL, &scr_ops, machine, "next.scr", - 0x20000); - memory_region_add_subregion(sysmem, 0x02100000, scrmem); - /* KBD */ dev = qdev_new(TYPE_NEXTKBD); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -946,7 +1020,7 @@ static void next_cube_init(MachineState *machine) } /* Serial */ - next_escc_init(cpu); + next_escc_init(pcdev); /* TODO: */ /* Network */ @@ -978,6 +1052,7 @@ static const TypeInfo next_typeinfo = { static void next_register_type(void) { type_register_static(&next_typeinfo); + type_register_static(&next_pc_info); } type_init(next_register_type) diff --git a/include/hw/m68k/next-cube.h b/include/hw/m68k/next-cube.h index a3be2b3..4357728 100644 --- a/include/hw/m68k/next-cube.h +++ b/include/hw/m68k/next-cube.h @@ -1,3 +1,13 @@ +/* + * NeXT Cube + * + * Copyright (c) 2011 Bryce Lanham + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + */ #ifndef NEXT_CUBE_H #define NEXT_CUBE_H @@ -39,9 +49,8 @@ enum next_irqs { NEXT_ENRX_DMA_I, NEXT_SCSI_DMA_I, NEXT_SCC_DMA_I, - NEXT_SND_I + NEXT_SND_I, + NEXT_NUM_IRQS }; -void next_irq(void *opaque, int number, int level); - #endif /* NEXT_CUBE_H */ |