Re: [PATCH 2/3] q800: add djMEMC memory controller
On 12/12/2019 20:01, Laurent Vivier wrote: > Current implementation is based on GLUE, an early implementation > of the memory controller found in Macintosh II series. > > Quadra 800 uses in fact djMEMC: > > The djMEMC is an Apple custom integrated circuit chip that performs a > variety of functions (RAM management, clock generation, ...). > It receives interrupt requests from various devices, assign priority to > each, and asserts one or more interrupt line to the CPU. > > Signed-off-by: Laurent Vivier > --- > MAINTAINERS | 2 + > hw/m68k/Kconfig | 1 + > hw/m68k/q800.c | 61 -- > hw/misc/Kconfig | 3 + > hw/misc/Makefile.objs| 1 + > hw/misc/djmemc.c | 176 +++ > hw/misc/trace-events | 4 + > include/hw/misc/djmemc.h | 34 > 8 files changed, 237 insertions(+), 45 deletions(-) > create mode 100644 hw/misc/djmemc.c > create mode 100644 include/hw/misc/djmemc.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 5e5e3e52d6..07224a2fa2 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -925,11 +925,13 @@ F: hw/misc/mac_via.c > F: hw/nubus/* > F: hw/display/macfb.c > F: hw/block/swim.c > +F: hw/misc/djmemc.c > F: hw/m68k/bootinfo.h > F: include/hw/misc/mac_via.h > F: include/hw/nubus/* > F: include/hw/display/macfb.h > F: include/hw/block/swim.h > +F: include/hw/misc/djmemc.c > > MicroBlaze Machines > --- > diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig > index c757e7dfa4..bdc43a798a 100644 > --- a/hw/m68k/Kconfig > +++ b/hw/m68k/Kconfig > @@ -22,3 +22,4 @@ config Q800 > select ESCC > select ESP > select DP8393X > +select DJMEMC > diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c > index ef0014f4c4..9ee0cb1141 100644 > --- a/hw/m68k/q800.c > +++ b/hw/m68k/q800.c > @@ -46,6 +46,7 @@ > #include "sysemu/qtest.h" > #include "sysemu/runstate.h" > #include "sysemu/reset.h" > +#include "hw/misc/djmemc.h" > > #define MACROM_ADDR 0x4000 > #define MACROM_SIZE 0x0010 > @@ -68,6 +69,7 @@ > #define SONIC_PROM_BASE (IO_BASE + 0x08000) > #define SONIC_BASE(IO_BASE + 0x0a000) > #define SCC_BASE (IO_BASE + 0x0c000) > +#define DJMEMC_BASE (IO_BASE + 0x0e000) > #define ESP_BASE (IO_BASE + 0x1) > #define ESP_PDMA (IO_BASE + 0x10100) > #define ASC_BASE (IO_BASE + 0x14000) > @@ -85,39 +87,6 @@ > > #define MAC_CLOCK 3686418 > > -/* > - * The GLUE (General Logic Unit) is an Apple custom integrated circuit chip > - * that performs a variety of functions (RAM management, clock generation, > ...). > - * The GLUE chip receives interrupt requests from various devices, > - * assign priority to each, and asserts one or more interrupt line to the > - * CPU. > - */ > - > -typedef struct { > -M68kCPU *cpu; > -uint8_t ipr; > -} GLUEState; > - > -static void GLUE_set_irq(void *opaque, int irq, int level) > -{ > -GLUEState *s = opaque; > -int i; > - > -if (level) { > -s->ipr |= 1 << irq; > -} else { > -s->ipr &= ~(1 << irq); > -} > - > -for (i = 7; i >= 0; i--) { > -if ((s->ipr >> i) & 1) { > -m68k_set_irq_level(s->cpu, i + 1, i + 25); > -return; > -} > -} > -m68k_set_irq_level(s->cpu, 0, 0); > -} > - > static void main_cpu_reset(void *opaque) > { > M68kCPU *cpu = opaque; > @@ -149,6 +118,7 @@ static void q800_init(MachineState *machine) > const char *kernel_cmdline = machine->kernel_cmdline; > hwaddr parameters_base; > CPUState *cs; > +DeviceState *djmemc_dev; > DeviceState *dev; > DeviceState *via_dev; > SysBusESPState *sysbus_esp; > @@ -156,8 +126,6 @@ static void q800_init(MachineState *machine) > SysBusDevice *sysbus; > BusState *adb_bus; > NubusBus *nubus; > -GLUEState *irq; > -qemu_irq *pic; > > linux_boot = (kernel_filename != NULL); > > @@ -191,11 +159,13 @@ static void q800_init(MachineState *machine) > g_free(name); > } > > -/* IRQ Glue */ > +/* djMEMC memory and interrupt controller */ > > -irq = g_new0(GLUEState, 1); > -irq->cpu = cpu; > -pic = qemu_allocate_irqs(GLUE_set_irq, irq, 8); > +djmemc_dev = qdev_create(NULL, TYPE_DJMEMC); > +object_property_set_link(OBJECT(djmemc_dev), OBJECT(cpu), "cpu", > + _abort); > +qdev_init_nofail(djmemc_dev); > +sysbus_mmio_map(SYS_BUS_DEVICE(djmemc_dev), 0, DJMEMC_BASE); > > /* VIA */ > > @@ -203,9 +173,10 @@ static void q800_init(MachineState *machine) > qdev_init_nofail(via_dev); > sysbus = SYS_BUS_DEVICE(via_dev); > sysbus_mmio_map(sysbus, 0, VIA_BASE); > -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]); > -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]); > - > +
Re: [PATCH 2/3] q800: add djMEMC memory controller
On 12/12/19 9:01 PM, Laurent Vivier wrote: Current implementation is based on GLUE, an early implementation of the memory controller found in Macintosh II series. Quadra 800 uses in fact djMEMC: The djMEMC is an Apple custom integrated circuit chip that performs a variety of functions (RAM management, clock generation, ...). It receives interrupt requests from various devices, assign priority to each, and asserts one or more interrupt line to the CPU. Signed-off-by: Laurent Vivier --- MAINTAINERS | 2 + hw/m68k/Kconfig | 1 + hw/m68k/q800.c | 61 -- hw/misc/Kconfig | 3 + hw/misc/Makefile.objs| 1 + hw/misc/djmemc.c | 176 +++ hw/misc/trace-events | 4 + include/hw/misc/djmemc.h | 34 8 files changed, 237 insertions(+), 45 deletions(-) create mode 100644 hw/misc/djmemc.c create mode 100644 include/hw/misc/djmemc.h diff --git a/MAINTAINERS b/MAINTAINERS index 5e5e3e52d6..07224a2fa2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -925,11 +925,13 @@ F: hw/misc/mac_via.c F: hw/nubus/* F: hw/display/macfb.c F: hw/block/swim.c +F: hw/misc/djmemc.c F: hw/m68k/bootinfo.h F: include/hw/misc/mac_via.h F: include/hw/nubus/* F: include/hw/display/macfb.h F: include/hw/block/swim.h +F: include/hw/misc/djmemc.c MicroBlaze Machines --- diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index c757e7dfa4..bdc43a798a 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -22,3 +22,4 @@ config Q800 select ESCC select ESP select DP8393X +select DJMEMC diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index ef0014f4c4..9ee0cb1141 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -46,6 +46,7 @@ #include "sysemu/qtest.h" #include "sysemu/runstate.h" #include "sysemu/reset.h" +#include "hw/misc/djmemc.h" #define MACROM_ADDR 0x4000 #define MACROM_SIZE 0x0010 @@ -68,6 +69,7 @@ #define SONIC_PROM_BASE (IO_BASE + 0x08000) #define SONIC_BASE(IO_BASE + 0x0a000) #define SCC_BASE (IO_BASE + 0x0c000) +#define DJMEMC_BASE (IO_BASE + 0x0e000) #define ESP_BASE (IO_BASE + 0x1) #define ESP_PDMA (IO_BASE + 0x10100) #define ASC_BASE (IO_BASE + 0x14000) @@ -85,39 +87,6 @@ #define MAC_CLOCK 3686418 -/* - * The GLUE (General Logic Unit) is an Apple custom integrated circuit chip - * that performs a variety of functions (RAM management, clock generation, ...). - * The GLUE chip receives interrupt requests from various devices, - * assign priority to each, and asserts one or more interrupt line to the - * CPU. - */ - -typedef struct { -M68kCPU *cpu; -uint8_t ipr; -} GLUEState; - -static void GLUE_set_irq(void *opaque, int irq, int level) -{ -GLUEState *s = opaque; -int i; - -if (level) { -s->ipr |= 1 << irq; -} else { -s->ipr &= ~(1 << irq); -} - -for (i = 7; i >= 0; i--) { -if ((s->ipr >> i) & 1) { -m68k_set_irq_level(s->cpu, i + 1, i + 25); -return; -} -} -m68k_set_irq_level(s->cpu, 0, 0); -} - static void main_cpu_reset(void *opaque) { M68kCPU *cpu = opaque; @@ -149,6 +118,7 @@ static void q800_init(MachineState *machine) const char *kernel_cmdline = machine->kernel_cmdline; hwaddr parameters_base; CPUState *cs; +DeviceState *djmemc_dev; DeviceState *dev; DeviceState *via_dev; SysBusESPState *sysbus_esp; @@ -156,8 +126,6 @@ static void q800_init(MachineState *machine) SysBusDevice *sysbus; BusState *adb_bus; NubusBus *nubus; -GLUEState *irq; -qemu_irq *pic; linux_boot = (kernel_filename != NULL); @@ -191,11 +159,13 @@ static void q800_init(MachineState *machine) g_free(name); } -/* IRQ Glue */ +/* djMEMC memory and interrupt controller */ -irq = g_new0(GLUEState, 1); -irq->cpu = cpu; -pic = qemu_allocate_irqs(GLUE_set_irq, irq, 8); Glad to see you add a QOM INTC and use QDEV API. +djmemc_dev = qdev_create(NULL, TYPE_DJMEMC); +object_property_set_link(OBJECT(djmemc_dev), OBJECT(cpu), "cpu", + _abort); +qdev_init_nofail(djmemc_dev); +sysbus_mmio_map(SYS_BUS_DEVICE(djmemc_dev), 0, DJMEMC_BASE); /* VIA */ @@ -203,9 +173,10 @@ static void q800_init(MachineState *machine) qdev_init_nofail(via_dev); sysbus = SYS_BUS_DEVICE(via_dev); sysbus_mmio_map(sysbus, 0, VIA_BASE); -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]); -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]); - +qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, +qdev_get_gpio_in(djmemc_dev, 0)); +qdev_connect_gpio_out_named(DEVICE(sysbus), +"irq", 1,
Re: [PATCH 2/3] q800: add djMEMC memory controller
On Thu, 12 Dec 2019, Laurent Vivier wrote: Current implementation is based on GLUE, an early implementation of the memory controller found in Macintosh II series. Quadra 800 uses in fact djMEMC: The djMEMC is an Apple custom integrated circuit chip that performs a variety of functions (RAM management, clock generation, ...). It receives interrupt requests from various devices, assign priority to each, and asserts one or more interrupt line to the CPU. Signed-off-by: Laurent Vivier --- MAINTAINERS | 2 + hw/m68k/Kconfig | 1 + hw/m68k/q800.c | 61 -- hw/misc/Kconfig | 3 + hw/misc/Makefile.objs| 1 + hw/misc/djmemc.c | 176 +++ hw/misc/trace-events | 4 + include/hw/misc/djmemc.h | 34 8 files changed, 237 insertions(+), 45 deletions(-) create mode 100644 hw/misc/djmemc.c create mode 100644 include/hw/misc/djmemc.h [...] diff --git a/hw/misc/djmemc.c b/hw/misc/djmemc.c new file mode 100644 index 00..b494e82a60 --- /dev/null +++ b/hw/misc/djmemc.c @@ -0,0 +1,176 @@ +/* + * djMEMC, macintosh memory and interrupt controller + * (Quadra 610/650/800 & Centris 610/650) + * + *https://mac68k.info/wiki/display/mac68k/djMEMC+Information + * + * The djMEMC is an Apple custom integrated circuit chip that performs a + * variety of functions (RAM management, clock generation, ...). + * It receives interrupt requests from various devices, assign priority to + * each, and asserts one or more interrupt line to the CPU. + */ + +#include "qemu/osdep.h" +#include "migration/vmstate.h" +#include "hw/misc/djmemc.h" +#include "hw/qdev-properties.h" +#include "trace.h" + +#define DJMEMC_SIZE 0x2000 + +#define InterleaveConf0 +#define Bank0Conf 1 +#define Bank1Conf 2 +#define Bank2Conf 3 +#define Bank3Conf 4 +#define Bank4Conf 5 +#define Bank5Conf 6 +#define Bank6Conf 7 +#define Bank7Conf 8 +#define Bank8Conf 9 +#define Bank9Conf 10 +#define MemTop11 +#define Config12 +#define Refresh 13 Should this be an enum so the compiler can better verify values and if all cases are handled? Regards, BALATON Zoltan
[PATCH 2/3] q800: add djMEMC memory controller
Current implementation is based on GLUE, an early implementation of the memory controller found in Macintosh II series. Quadra 800 uses in fact djMEMC: The djMEMC is an Apple custom integrated circuit chip that performs a variety of functions (RAM management, clock generation, ...). It receives interrupt requests from various devices, assign priority to each, and asserts one or more interrupt line to the CPU. Signed-off-by: Laurent Vivier --- MAINTAINERS | 2 + hw/m68k/Kconfig | 1 + hw/m68k/q800.c | 61 -- hw/misc/Kconfig | 3 + hw/misc/Makefile.objs| 1 + hw/misc/djmemc.c | 176 +++ hw/misc/trace-events | 4 + include/hw/misc/djmemc.h | 34 8 files changed, 237 insertions(+), 45 deletions(-) create mode 100644 hw/misc/djmemc.c create mode 100644 include/hw/misc/djmemc.h diff --git a/MAINTAINERS b/MAINTAINERS index 5e5e3e52d6..07224a2fa2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -925,11 +925,13 @@ F: hw/misc/mac_via.c F: hw/nubus/* F: hw/display/macfb.c F: hw/block/swim.c +F: hw/misc/djmemc.c F: hw/m68k/bootinfo.h F: include/hw/misc/mac_via.h F: include/hw/nubus/* F: include/hw/display/macfb.h F: include/hw/block/swim.h +F: include/hw/misc/djmemc.c MicroBlaze Machines --- diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index c757e7dfa4..bdc43a798a 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -22,3 +22,4 @@ config Q800 select ESCC select ESP select DP8393X +select DJMEMC diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index ef0014f4c4..9ee0cb1141 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -46,6 +46,7 @@ #include "sysemu/qtest.h" #include "sysemu/runstate.h" #include "sysemu/reset.h" +#include "hw/misc/djmemc.h" #define MACROM_ADDR 0x4000 #define MACROM_SIZE 0x0010 @@ -68,6 +69,7 @@ #define SONIC_PROM_BASE (IO_BASE + 0x08000) #define SONIC_BASE(IO_BASE + 0x0a000) #define SCC_BASE (IO_BASE + 0x0c000) +#define DJMEMC_BASE (IO_BASE + 0x0e000) #define ESP_BASE (IO_BASE + 0x1) #define ESP_PDMA (IO_BASE + 0x10100) #define ASC_BASE (IO_BASE + 0x14000) @@ -85,39 +87,6 @@ #define MAC_CLOCK 3686418 -/* - * The GLUE (General Logic Unit) is an Apple custom integrated circuit chip - * that performs a variety of functions (RAM management, clock generation, ...). - * The GLUE chip receives interrupt requests from various devices, - * assign priority to each, and asserts one or more interrupt line to the - * CPU. - */ - -typedef struct { -M68kCPU *cpu; -uint8_t ipr; -} GLUEState; - -static void GLUE_set_irq(void *opaque, int irq, int level) -{ -GLUEState *s = opaque; -int i; - -if (level) { -s->ipr |= 1 << irq; -} else { -s->ipr &= ~(1 << irq); -} - -for (i = 7; i >= 0; i--) { -if ((s->ipr >> i) & 1) { -m68k_set_irq_level(s->cpu, i + 1, i + 25); -return; -} -} -m68k_set_irq_level(s->cpu, 0, 0); -} - static void main_cpu_reset(void *opaque) { M68kCPU *cpu = opaque; @@ -149,6 +118,7 @@ static void q800_init(MachineState *machine) const char *kernel_cmdline = machine->kernel_cmdline; hwaddr parameters_base; CPUState *cs; +DeviceState *djmemc_dev; DeviceState *dev; DeviceState *via_dev; SysBusESPState *sysbus_esp; @@ -156,8 +126,6 @@ static void q800_init(MachineState *machine) SysBusDevice *sysbus; BusState *adb_bus; NubusBus *nubus; -GLUEState *irq; -qemu_irq *pic; linux_boot = (kernel_filename != NULL); @@ -191,11 +159,13 @@ static void q800_init(MachineState *machine) g_free(name); } -/* IRQ Glue */ +/* djMEMC memory and interrupt controller */ -irq = g_new0(GLUEState, 1); -irq->cpu = cpu; -pic = qemu_allocate_irqs(GLUE_set_irq, irq, 8); +djmemc_dev = qdev_create(NULL, TYPE_DJMEMC); +object_property_set_link(OBJECT(djmemc_dev), OBJECT(cpu), "cpu", + _abort); +qdev_init_nofail(djmemc_dev); +sysbus_mmio_map(SYS_BUS_DEVICE(djmemc_dev), 0, DJMEMC_BASE); /* VIA */ @@ -203,9 +173,10 @@ static void q800_init(MachineState *machine) qdev_init_nofail(via_dev); sysbus = SYS_BUS_DEVICE(via_dev); sysbus_mmio_map(sysbus, 0, VIA_BASE); -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]); -qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]); - +qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, +qdev_get_gpio_in(djmemc_dev, 0)); +qdev_connect_gpio_out_named(DEVICE(sysbus), +"irq", 1, qdev_get_gpio_in(djmemc_dev, 1)); adb_bus = qdev_get_child_bus(via_dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); @@ -244,7 +215,7 @@ static void