summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-04-18 22:04:40 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-04-18 22:04:40 +0000
commita438e324e70ca6e94ae333db346240ab09a6c153 (patch)
treebb39d26c835f463cab516422f6881bd8ac88006e /sys/arch
parent23aedc2af582c445ff84e97ff328d37e54d80eba (diff)
Work in progress support for AViiON models 4600 and 530.
Also features support for {awkw,bast}ard 6:1 CMMU:CPU configurations (4I2D). Tested on model 4605, which runs up to cpu_initclocks(), which is not written for this system family yet. No regression on model 4300.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/aviion/aviion/av400_machdep.c23
-rw-r--r--sys/arch/aviion/aviion/av530_machdep.c583
-rw-r--r--sys/arch/aviion/aviion/eh.S52
-rw-r--r--sys/arch/aviion/aviion/m8820x.c59
-rw-r--r--sys/arch/aviion/conf/GENERIC4
-rw-r--r--sys/arch/aviion/dev/vme.c67
-rw-r--r--sys/arch/aviion/include/av400.h10
-rw-r--r--sys/arch/aviion/include/av530.h191
-rw-r--r--sys/arch/aviion/include/board.h6
-rw-r--r--sys/arch/m88k/include/m8820x.h6
-rw-r--r--sys/arch/m88k/m88k/m8820x_machdep.c57
11 files changed, 974 insertions, 84 deletions
diff --git a/sys/arch/aviion/aviion/av400_machdep.c b/sys/arch/aviion/aviion/av400_machdep.c
index 3948ae39039..8b4502c7bc7 100644
--- a/sys/arch/aviion/aviion/av400_machdep.c
+++ b/sys/arch/aviion/aviion/av400_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: av400_machdep.c,v 1.14 2009/02/16 22:54:59 miod Exp $ */
+/* $OpenBSD: av400_machdep.c,v 1.15 2010/04/18 22:04:37 miod Exp $ */
/*
* Copyright (c) 2006, 2007, Miodrag Vallat.
*
@@ -159,7 +159,7 @@
#include <aviion/dev/sysconvar.h>
#include <aviion/dev/vmevar.h>
-u_int safe_level(u_int mask, u_int curlevel);
+u_int av400_safe_level(u_int, u_int);
const pmap_table_entry
av400_ptable[] = {
@@ -183,7 +183,16 @@ const struct board board_av400 = {
av400_setipl,
av400_raiseipl,
av400_intsrc,
- av400_ptable
+
+ av400_ptable,
+
+ AV400_VME16_BASE,
+ AV400_VME16_START, AV400_VME16_END,
+ AV400_VME24_BASE,
+ AV400_VME24_START, AV400_VME24_END,
+ AV400_VME32_BASE,
+ AV400_VME32_START1, AV400_VME32_END1,
+ AV400_VME32_START2, AV400_VME32_END2
};
/*
@@ -199,7 +208,7 @@ const struct board board_av400 = {
* Note that, on the AV400 design, the interrupt enable registers are
* write-only and read back as 0xffffffff.
*/
-u_int32_t int_mask_reg[] = { 0, 0, 0, 0 };
+static u_int32_t int_mask_reg[] = { 0, 0, 0, 0 };
u_int av400_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH };
@@ -275,7 +284,7 @@ av400_bootstrap()
* while keeping ``mask'' masked.
*/
u_int
-safe_level(u_int mask, u_int curlevel)
+av400_safe_level(u_int mask, u_int curlevel)
{
int i;
@@ -380,7 +389,7 @@ av400_intsrc(int i)
/*
* Provide the interrupt source for a given interrupt status bit.
*/
-const u_int obio_vec[32] = {
+static const u_int obio_vec[32] = {
0, /* SWI0 */
0, /* SWI1 */
0,
@@ -461,7 +470,7 @@ av400_intr(struct trapframe *eframe)
* priority.
*/
do {
- level = safe_level(cur_mask, old_spl);
+ level = av400_safe_level(cur_mask, old_spl);
av400_setipl(level);
if (unmasked == 0) {
diff --git a/sys/arch/aviion/aviion/av530_machdep.c b/sys/arch/aviion/aviion/av530_machdep.c
new file mode 100644
index 00000000000..f965852693c
--- /dev/null
+++ b/sys/arch/aviion/aviion/av530_machdep.c
@@ -0,0 +1,583 @@
+/* $OpenBSD: av530_machdep.c,v 1.1 2010/04/18 22:04:37 miod Exp $ */
+/*
+ * Copyright (c) 2006, 2007, 2010 Miodrag Vallat.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/asm_macro.h>
+#include <machine/board.h>
+#include <machine/bus.h>
+#include <machine/cmmu.h>
+#include <machine/cpu.h>
+#include <machine/trap.h>
+
+#include <machine/m88100.h>
+#include <machine/m8820x.h>
+#include <machine/avcommon.h>
+#include <machine/av530.h>
+#include <machine/prom.h>
+
+#include <aviion/dev/sysconvar.h>
+#include <aviion/dev/vmevar.h>
+
+u_int av530_safe_level(u_int, u_int, u_int);
+
+const pmap_table_entry
+av530_ptable[] = {
+ { AV530_PROM, AV530_PROM, AV530_PROM_SIZE,
+ UVM_PROT_RW, CACHE_INH },
+#if 0 /* mapped by the hardcoded BATC entries */
+ { AV530_UTILITY,AV530_UTILITY, AV530_UTILITY_SIZE,
+ UVM_PROT_RW, CACHE_INHIBIT },
+#endif
+ { 0, 0, (vsize_t)-1, 0, 0 }
+};
+
+const struct board board_av530 = {
+ "530/4600 series",
+ av530_bootstrap,
+ av530_memsize,
+ av530_startup,
+ av530_intr,
+ NULL, /* XXX need PIT clock code */
+ av530_getipl,
+ av530_setipl,
+ av530_raiseipl,
+ av530_intsrc,
+
+ av530_ptable,
+
+ AV530_VME16_BASE,
+ AV530_VME16_START, AV530_VME16_END,
+ AV530_VME24_BASE,
+ AV530_VME24_START, AV530_VME24_END,
+ AV530_VME32_BASE,
+ AV530_VME32_START1, AV530_VME32_END1,
+ AV530_VME32_START2, AV530_VME32_END2
+};
+
+/*
+ * The MVME188 interrupt arbiter has 25 orthogonal interrupt sources.
+ * On the AViiON 530 machines, there are even more interrupt sources in use,
+ * requiring the use of two arbiters.
+ * We fold this model in the 8-level spl model this port uses, enforcing
+ * priorities manually with the interrupt masks.
+ */
+
+/*
+ * Copy of the interrupt enable registers for each CPU.
+ * Note that, on the AV530 design, the interrupt enable registers are
+ * write-only and read back as 0xffffffff.
+ */
+static u_int32_t int_mask_reg[] = { 0, 0, 0, 0 };
+static u_int32_t ext_int_mask_reg[] = { 0, 0, 0, 0 };
+
+u_int av530_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH };
+
+#ifdef MULTIPROCESSOR
+/*
+ * Interrupts allowed on secondary processors.
+ */
+#define SLAVE_MASK 0 /* IRQ_SWI0 | IRQ_SWI1 */
+#define SLAVE_EXMASK 0
+#endif
+
+/*
+ * Figure out how much memory is available, by asking the PROM.
+ */
+vaddr_t
+av530_memsize()
+{
+ vaddr_t memsize0, memsize1;
+
+ memsize0 = scm_memsize(0);
+ memsize1 = scm_memsize(1);
+
+ /*
+ * What we got is the ``top of memory'', i.e. the largest addressable
+ * word address, ending in 0xffc. Round up to a multiple of a page.
+ */
+ memsize0 = round_page(memsize0);
+ memsize1 = round_page(memsize1);
+
+ physmem = atop(memsize0);
+ return (memsize1);
+}
+
+void
+av530_startup()
+{
+}
+
+int32_t cpuid, sysid;
+
+void
+av530_bootstrap()
+{
+ extern struct cmmu_p cmmu8820x;
+ extern u_char hostaddr[6];
+ uint32_t whoami;
+
+ /*
+ * Set up CMMU addresses. We need to access the WHOAMI register
+ * early since addresses differ between the 6:1 and 2:1 designs.
+ */
+ cmmu = &cmmu8820x;
+ whoami = (*(volatile u_int32_t *)AV_WHOAMI & 0xf0) >> 4;
+ switch (whoami) {
+ default: /* 2:1 systems */
+ m8820x_cmmu[0].cmmu_regs = (void *)AV530_CMMU_I0;
+ m8820x_cmmu[1].cmmu_regs = (void *)AV530_CMMU_D0;
+ m8820x_cmmu[2].cmmu_regs = (void *)AV530_CMMU_I1;
+ m8820x_cmmu[3].cmmu_regs = (void *)AV530_CMMU_D1;
+ break;
+ case 3:
+ case 7: /* 6:1 systems */
+ m8820x_cmmu[0].cmmu_regs = (void *)AV530_CMMU6_I0;
+ m8820x_cmmu[1].cmmu_regs = (void *)AV530_CMMU6_D0;
+ m8820x_cmmu[2].cmmu_regs = (void *)AV530_CMMU6_I1;
+ m8820x_cmmu[3].cmmu_regs = (void *)AV530_CMMU6_D1;
+ m8820x_cmmu[4].cmmu_regs = (void *)AV530_CMMU6_I2;
+ m8820x_cmmu[6].cmmu_regs = (void *)AV530_CMMU6_I3;
+
+ m8820x_cmmu[8].cmmu_regs = (void *)AV530_CMMU6_I4;
+ m8820x_cmmu[9].cmmu_regs = (void *)AV530_CMMU6_D2;
+ m8820x_cmmu[10].cmmu_regs = (void *)AV530_CMMU6_I5;
+ m8820x_cmmu[11].cmmu_regs = (void *)AV530_CMMU6_D3;
+ m8820x_cmmu[12].cmmu_regs = (void *)AV530_CMMU6_I6;
+ m8820x_cmmu[14].cmmu_regs = (void *)AV530_CMMU6_I7;
+ break;
+ }
+
+ /* clear and disable all interrupts */
+ *(volatile u_int32_t *)AV_IENALL = 0;
+ *(volatile u_int32_t *)AV_EXIENALL = 0;
+
+ /*
+ * Get all the information we'll need later from the PROM, while
+ * we can still use it.
+ */
+ scm_getenaddr(hostaddr);
+ cpuid = scm_cpuid();
+ sysid = scm_sysid();
+}
+
+/*
+ * Return the next ipl >= ``curlevel'' at which we can reenable interrupts
+ * while keeping ``mask'' masked.
+ */
+u_int
+av530_safe_level(u_int mask, u_int exmask, u_int curlevel)
+{
+ int i;
+
+ for (i = curlevel; i < NIPLS; i++)
+ if ((int_mask_val[i] & mask) == 0 &&
+ (ext_int_mask_val[i] & exmask) == 0)
+ return i;
+
+ return (NIPLS - 1);
+}
+
+u_int
+av530_getipl(void)
+{
+ return av530_curspl[cpu_number()];
+}
+
+u_int
+av530_setipl(u_int level)
+{
+ u_int32_t mask, exmask, curspl, psr;
+ u_int cpu = cpu_number();
+
+ psr = get_psr();
+ set_psr(psr | PSR_IND);
+ curspl = av530_curspl[cpu];
+
+ mask = int_mask_val[level];
+ exmask = ext_int_mask_val[level];
+#ifdef MULTIPROCESSOR
+ if (cpu != master_cpu) {
+ mask &= SLAVE_MASK;
+ exmask &= SLAVE_EXMASK;
+ }
+#endif
+
+ av530_curspl[cpu] = level;
+ *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
+ *(u_int32_t *)AV_EXIEN(cpu) = ext_int_mask_reg[cpu] = exmask;
+ /*
+ * We do not flush the pipeline here, because interrupts are disabled,
+ * and set_psr() will synchronize the pipeline.
+ */
+ set_psr(psr);
+
+ return curspl;
+}
+
+u_int
+av530_raiseipl(u_int level)
+{
+ u_int32_t mask, exmask, curspl, psr;
+ u_int cpu = cpu_number();
+
+ psr = get_psr();
+ set_psr(psr | PSR_IND);
+ curspl = av530_curspl[cpu];
+ if (curspl < level) {
+ mask = int_mask_val[level];
+ exmask = ext_int_mask_val[level];
+#ifdef MULTIPROCESSOR
+ if (cpu != master_cpu) {
+ mask &= SLAVE_MASK;
+ exmask &= SLAVE_EXMASK;
+ }
+#endif
+
+ av530_curspl[cpu] = level;
+ *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
+ *(u_int32_t *)AV_EXIEN(cpu) = ext_int_mask_reg[cpu] = exmask;
+ }
+ /*
+ * We do not flush the pipeline here, because interrupts are disabled,
+ * and set_psr() will synchronize the pipeline.
+ */
+ set_psr(psr);
+
+ return curspl;
+}
+
+/*
+ * Provide the interrupt masks for a given logical interrupt source.
+ */
+u_int64_t
+av530_intsrc(int i)
+{
+ static const u_int32_t intsrc[] = {
+ 0,
+ IRQ_ABORT,
+ IRQ_ACF,
+ IRQ_SF,
+ 0, /* XXX no clock */
+ IRQ_DI,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IRQ_VME1,
+ IRQ_VME2,
+ IRQ_VME3,
+ IRQ_VME4,
+ IRQ_VME5,
+ IRQ_VME6,
+ IRQ_VME7
+ }, ext_intsrc[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ EXIRQ_DUART2,
+ EXIRQ_LAN0,
+ EXIRQ_LAN1,
+ EXIRQ_SCSI0,
+ EXIRQ_SCSI1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+ uint64_t isrc;
+
+ isrc = ext_intsrc[i];
+ isrc = (isrc << 32) | intsrc[i];
+ return isrc;
+}
+
+/*
+ * Provide the interrupt source for a given interrupt status bit.
+ */
+static const u_int obio_vec[32] = {
+ 0, /* SWI0 */
+ 0, /* SWI1 */
+ 0, /* SWI2 */
+ 0, /* SWI3 */
+ INTSRC_VME, /* VME1 */
+ 0,
+ INTSRC_VME, /* VME2 */
+ 0, /* SIGLPI */
+ 0, /* LMI */
+ 0,
+ INTSRC_VME, /* VME3 */
+ 0,
+ INTSRC_VME, /* VME4 */
+ 0,
+ INTSRC_VME, /* VME5 */
+ 0,
+ 0, /* HPI */
+ INTSRC_DUART1, /* DI */
+ 0, /* MEM */
+ INTSRC_VME, /* VME6 */
+ INTSRC_SYSFAIL, /* SF */
+ 0,
+ 0, /* KBD */
+ INTSRC_VME, /* VME7 */
+ 0, /* SWI4 */
+ 0, /* SWI5 */
+ 0, /* SWI6 */
+ 0, /* SWI7 */
+ 0, /* DTI */
+ 0, /* ARBTO */
+ INTSRC_ACFAIL, /* ACF */
+ INTSRC_ABORT /* ABORT */
+};
+static const u_int obio_exvec[32] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* PDMA */
+ 0, /* IOEXP2 */
+ 0,
+ 0, /* IOEXP1 */
+ 0,
+ 0,
+ 0,
+ 0, /* VDMA */
+ INTSRC_DUART2, /* DUART2 */
+ 0, /* ZBUF */
+ 0, /* VIDEO */
+ INTSRC_SCSI2, /* SCSI1 */
+ INTSRC_SCSI1, /* SCSI0 */
+ INTSRC_ETHERNET2, /* LAN1 */
+ INTSRC_ETHERNET1, /* LAN0 */
+ 0, /* SCC */
+ 0, /* DMA0C */
+ 0, /* DMA1C */
+ 0, /* DMA2C */
+ 0, /* DMA3C */
+ 0, /* DMA4C */
+ 0,
+ 0, /* PIT0OF */
+ 0, /* PIT1OF */
+ 0, /* PIT2OF */
+ 0, /* PIT3OF */
+ 0 /* RTCOF */
+};
+
+/*
+ * Device interrupt handler for AV530
+ */
+
+#define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */
+#define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */
+
+void
+av530_intr(struct trapframe *eframe)
+{
+ int cpu = cpu_number();
+ u_int32_t cur_mask, ign_mask;
+ u_int32_t cur_exmask, ign_exmask;
+ u_int level, old_spl;
+ struct intrhand *intr;
+ intrhand_t *list;
+ int ret, intbit;
+ vaddr_t ivec;
+ u_int intsrc, vec;
+ int unmasked = 0;
+ int warn;
+#ifdef DIAGNOSTIC
+ static int problems = 0;
+#endif
+
+ cur_mask = ISR_GET_CURRENT_MASK(cpu);
+ cur_exmask = EXISR_GET_CURRENT_MASK(cpu);
+ ign_mask = 0;
+ ign_exmask = 0;
+ old_spl = eframe->tf_mask;
+
+ if (cur_mask == 0 && cur_exmask == 0) {
+ /*
+ * Spurious interrupts - may be caused by debug output clearing
+ * DUART interrupts.
+ */
+ flush_pipeline();
+ goto out;
+ }
+
+ uvmexp.intrs++;
+
+ /*
+ * We want to service all interrupts marked in the IST register
+ * They are all valid because the mask would have prevented them
+ * from being generated otherwise. We will service them in order of
+ * priority.
+ */
+ for (;;) {
+ cur_mask = ISR_GET_CURRENT_MASK(cpu);
+ cur_exmask = EXISR_GET_CURRENT_MASK(cpu);
+ if ((cur_mask & ~ign_mask) == 0 &&
+ (cur_exmask & ~ign_exmask) == 0)
+ break;
+
+ level = av530_safe_level(cur_mask, cur_exmask, old_spl);
+ av530_setipl(level);
+
+ if (unmasked == 0) {
+ set_psr(get_psr() & ~PSR_IND);
+ unmasked = 1;
+ }
+
+ /* find the first bit set in the current mask */
+ warn = 0;
+ if (cur_mask != 0) {
+ intbit = ff1(cur_mask);
+ intsrc = obio_vec[intbit];
+
+ if (intsrc == 0)
+ panic("%s: unexpected interrupt source"
+ " (bit %d), level %d, mask 0x%b",
+ __func__, intbit, level,
+ cur_mask, IST_STRING);
+ } else {
+ intbit = ff1(cur_exmask);
+ intsrc = obio_exvec[intbit];
+
+ if (intsrc == 0)
+ panic("%s: unexpected extended interrupt source"
+ " (bit %d), level %d, mask 0x%b",
+ __func__, intbit, level,
+ cur_exmask, EXIST_STRING);
+ }
+
+ if (intsrc == INTSRC_VME) {
+ ivec = AV530_VIRQLV + (level << 2);
+ vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK;
+ if (vec & VME_BERR_MASK) {
+ /* no need to dump exmask for vme intr */
+ printf("%s: timeout getting VME "
+ "interrupt vector, "
+ "level %d, mask 0x%b\n",
+ __func__, level,
+ cur_mask, IST_STRING);
+ ign_mask |= 1 << intbit;
+ continue;
+ }
+ list = &vmeintr_handlers[vec];
+ } else {
+ list = &sysconintr_handlers[intsrc];
+ }
+
+ if (SLIST_EMPTY(list)) {
+ warn = 1;
+ } else {
+ /*
+ * Walk through all interrupt handlers in the chain
+ * for the given vector, calling each handler in turn,
+ * until some handler returns a value != 0.
+ */
+ ret = 0;
+ SLIST_FOREACH(intr, list, ih_link) {
+ if (ISSET(intr->ih_flags, INTR_WANTFRAME))
+ ret = (*intr->ih_fn)((void *)eframe);
+ else
+ ret = (*intr->ih_fn)(intr->ih_arg);
+ if (ret != 0) {
+ intr->ih_count.ec_count++;
+ break;
+ }
+ }
+ if (ret == 0)
+ warn = 2;
+ }
+
+ if (warn != 0) {
+ if (cur_mask != 0)
+ ign_mask |= 1 << intbit;
+ else
+ ign_exmask |= 1 << intbit;
+
+ if (intsrc == INTSRC_VME)
+ printf("%s: %s VME interrupt, "
+ "level %d, vec 0x%x, mask 0x%b\n",
+ __func__,
+ warn == 1 ? "spurious" : "unclaimed",
+ level, vec, cur_mask, IST_STRING);
+ else {
+ if (cur_mask != 0)
+ printf("%s: %s interrupt, "
+ "level %d, bit %d, mask 0x%b\n",
+ __func__,
+ warn == 1 ?
+ "spurious" : "unclaimed",
+ level, intbit,
+ cur_mask, IST_STRING);
+ else
+ printf("%s: %s extended interrupt, "
+ "level %d, bit %d, mask 0x%b\n",
+ __func__,
+ warn == 1 ?
+ "spurious" : "unclaimed",
+ level, intbit,
+ cur_exmask, EXIST_STRING);
+ }
+ }
+ }
+
+#ifdef DIAGNOSTIC
+ if (ign_mask != 0 || ign_exmask != 0) {
+ if (++problems >= 10)
+ panic("%s: broken interrupt behaviour", __func__);
+ } else
+ problems = 0;
+#endif
+
+out:
+ /*
+ * process any remaining data access exceptions before
+ * returning to assembler
+ */
+ if (eframe->tf_dmt0 & DMT_VALID)
+ m88100_trap(T_DATAFLT, eframe);
+
+ /*
+ * Disable interrupts before returning to assembler, the spl will
+ * be restored later.
+ */
+ set_psr(get_psr() | PSR_IND);
+}
diff --git a/sys/arch/aviion/aviion/eh.S b/sys/arch/aviion/aviion/eh.S
index 630cc79fbcd..99b0de93575 100644
--- a/sys/arch/aviion/aviion/eh.S
+++ b/sys/arch/aviion/aviion/eh.S
@@ -1,6 +1,6 @@
-/* $OpenBSD: eh.S,v 1.5 2007/12/21 23:56:53 miod Exp $ */
+/* $OpenBSD: eh.S,v 1.6 2010/04/18 22:04:37 miod Exp $ */
/*
- * Copyright (c) 2006, Miodrag Vallat
+ * Copyright (c) 2006, 2010 Miodrag Vallat
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,7 +36,7 @@
#include <m88k/m88k/eh_common.S>
-ENTRY(pfsr_av400_double)
+ENTRY(pfsr_double)
/*
* 4 CMMUs per CPU. Almost as simple as the 2 CMMUs per CPU
* situation...
@@ -68,7 +68,7 @@ ENTRY(pfsr_av400_double)
br.n _ASM_LABEL(pfsr_done)
st TMP3, r31, EF_DPFSR
-ENTRY(pfsr_av400_straight)
+ENTRY(pfsr_straight)
/*
* We have the simple 2 CMMUs per CPU mapping. Pick our couple;
* no need to reset fault status registers in this case.
@@ -80,3 +80,47 @@ ENTRY(pfsr_av400_straight)
ld TMP3, TMP2, r0
br.n _ASM_LABEL(pfsr_done)
st TMP3, r31, EF_DPFSR
+
+ENTRY(pfsr_six)
+ /*
+ * 6 CMMU (2D4I) per CPU.
+ * This is the worst situation. We handle the data CMMU first,
+ * using the cpu_info pointers; and then the instruction CMMU,
+ * relying upon them being set up every 0x1000 bytes in the
+ * address space.
+ */
+ ld TMP2, TMP, CI_PFSR_D0
+ ld TMP3, TMP2, r0
+ extu TMP3, TMP3, 3<16>
+ bcnd ne0, TMP3, 1f
+ st r0, TMP2, r0
+ ld TMP2, TMP, CI_PFSR_D1
+1:
+ ld TMP3, TMP2, r0
+ st r0, TMP2, r0
+ st TMP3, r31, EF_DPFSR
+
+ ld TMP2, TMP, CI_PFSR_I0
+ ld TMP3, TMP2, r0
+ extu TMP3, TMP3, 3<16>
+ bcnd ne0, TMP3, 2f
+ st r0, TMP2, r0
+
+ addu TMP2, TMP2, 0x1000 /* I1 */
+ ld TMP3, TMP2, r0
+ extu TMP3, TMP3, 3<16>
+ bcnd ne0, TMP3, 2f
+ st r0, TMP2, r0
+
+ addu TMP2, TMP2, 0x1000 /* I2 */
+ ld TMP3, TMP2, r0
+ extu TMP3, TMP3, 3<16>
+ bcnd ne0, TMP3, 2f
+ st r0, TMP2, r0
+
+ addu TMP2, TMP2, 0x1000 /* I3 */
+2:
+ ld TMP3, TMP2, r0
+ st r0, TMP2, r0
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP3, r31, EF_IPFSR
diff --git a/sys/arch/aviion/aviion/m8820x.c b/sys/arch/aviion/aviion/m8820x.c
index 79b6392a3fe..f0b6277d075 100644
--- a/sys/arch/aviion/aviion/m8820x.c
+++ b/sys/arch/aviion/aviion/m8820x.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: m8820x.c,v 1.6 2009/04/19 17:56:12 miod Exp $ */
+/* $OpenBSD: m8820x.c,v 1.7 2010/04/18 22:04:37 miod Exp $ */
/*
- * Copyright (c) 2004, 2006, Miodrag Vallat.
+ * Copyright (c) 2004, 2006, 2010 Miodrag Vallat.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,8 +36,9 @@
#include <machine/m8820x.h>
#include <machine/prom.h>
-extern u_int32_t pfsr_av400_straight[];
-extern u_int32_t pfsr_av400_double[];
+extern u_int32_t pfsr_straight[];
+extern u_int32_t pfsr_double[];
+extern u_int32_t pfsr_six[];
/*
* This routine sets up the CPU/CMMU configuration.
@@ -48,7 +49,7 @@ m8820x_setup_board_config()
extern u_int32_t pfsr_save[];
struct m8820x_cmmu *cmmu;
struct scm_cpuconfig scc;
- int type, cpu_num, cmmu_num;
+ int type, cpu_num, cpu_cmmu_num, cmmu_num, cmmu_per_cpu;
volatile u_int *cr;
u_int32_t whoami;
u_int32_t *m8820x_pfsr;
@@ -57,6 +58,9 @@ m8820x_setup_board_config()
* First, find if any CPU0 CMMU is a 88204. If so, we can
* issue the CPUCONFIG system call to get the configuration
* details.
+ * NOTE that this relies upon [0] and [1] to always have
+ * valid CMMU addresses - thankfully this is always the case
+ * on model 530 regardless of the CMMU configuration.
*/
if (badaddr((vaddr_t)m8820x_cmmu[0].cmmu_regs, 4) != 0 ||
badaddr((vaddr_t)m8820x_cmmu[1].cmmu_regs, 4) != 0) {
@@ -110,8 +114,11 @@ hardprobe:
* slots we can ignore, and keep using badaddr() to cope
* with unpopulated slots.
*/
- cmmu = m8820x_cmmu + 7;
- for (max_cmmus = 7; max_cmmus != 0; max_cmmus--, cmmu--) {
+ cmmu = m8820x_cmmu + MAX_CMMUS - 1;
+ for (max_cmmus = MAX_CMMUS - 1; max_cmmus != 0;
+ max_cmmus--, cmmu--) {
+ if (cmmu->cmmu_regs == NULL)
+ continue;
if (badaddr((vaddr_t)cmmu->cmmu_regs, 4) == 0)
break;
}
@@ -122,8 +129,8 @@ hardprobe:
/*
* Deduce our configuration from the WHOAMI register.
*/
- whoami = *(volatile u_int32_t *)AV_WHOAMI;
- switch ((whoami & 0xf0) >> 4) {
+ whoami = (*(volatile u_int32_t *)AV_WHOAMI & 0xf0) >> 4;
+ switch (whoami) {
case 0: /* 4 CPUs, 8 CMMUs */
scc.cpucount = 4;
break;
@@ -135,10 +142,16 @@ hardprobe:
break;
case 3: /* 2 CPUs, 12 CMMUs */
case 7: /* 1 CPU, 6 CMMU */
- printf("MAYDAY, 6:1 CMMU configuration (whoami %x)"
- " but no CPUCONFIG information\n", whoami);
- scm_halt();
- /* NOTREACHED */
+ /*
+ *
+ */
+ ncpusfound = whoami == 7 ? 1 : 2;
+ cmmu_per_cpu = 6;
+ cmmu_shift = 3;
+ max_cmmus = ncpusfound << cmmu_shift;
+ scc.isplit = scc.dsplit = 0; /* XXX unknown */
+ m8820x_pfsr = pfsr_six;
+ goto done;
break;
default:
printf("unrecognized CMMU configuration, whoami %x\n",
@@ -171,13 +184,15 @@ knowledge:
ncpusfound = scc.cpucount;
if (scc.igang == 1) {
cmmu_shift = 1;
- m8820x_pfsr = pfsr_av400_straight;
+ m8820x_pfsr = pfsr_straight;
} else {
cmmu_shift = 2;
- m8820x_pfsr = pfsr_av400_double;
+ m8820x_pfsr = pfsr_double;
}
- max_cmmus = ncpusfound << scc.igang;
+ max_cmmus = ncpusfound << cmmu_shift;
+ cmmu_per_cpu = 1 << cmmu_shift;
+done:
/*
* Now that we know which CMMUs are there, report every association
*/
@@ -189,7 +204,7 @@ knowledge:
cmmu_regs[CMMU_IDR]);
printf("CPU%d is associated to %d MC8820%c CMMUs\n",
- cpu_num, 1 << cmmu_shift,
+ cpu_num, cmmu_per_cpu,
type == M88204_ID ? '4' : '0');
}
}
@@ -201,15 +216,17 @@ knowledge:
if (cmmu_shift > 1) {
for (cmmu_num = 0, cmmu = m8820x_cmmu; cmmu_num < max_cmmus;
cmmu_num++, cmmu++) {
- cpu_num = cmmu_num >> 1; /* CPU view of the CMMU */
+ cpu_cmmu_num = cmmu_num >> 1; /* CPU view of the CMMU */
- if (cmmu_num & 1) {
+ if (CMMU_MODE(cmmu_num) == INST_CMMU) {
/* I0, I1 */
- cmmu->cmmu_addr = cpu_num < 2 ? 0 : scc.isplit;
+ cmmu->cmmu_addr =
+ cpu_cmmu_num < 2 ? 0 : scc.isplit;
cmmu->cmmu_addr_mask = scc.isplit;
} else {
/* D0, D1 */
- cmmu->cmmu_addr = cpu_num < 2 ? 0 : scc.dsplit;
+ cmmu->cmmu_addr =
+ cpu_cmmu_num < 2 ? 0 : scc.dsplit;
cmmu->cmmu_addr_mask = scc.dsplit;
}
}
diff --git a/sys/arch/aviion/conf/GENERIC b/sys/arch/aviion/conf/GENERIC
index 65faae30a96..5b0ba40d1ab 100644
--- a/sys/arch/aviion/conf/GENERIC
+++ b/sys/arch/aviion/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.2 2006/05/20 12:06:51 miod Exp $
+# $OpenBSD: GENERIC,v 1.3 2010/04/18 22:04:39 miod Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -19,7 +19,7 @@ option M88100
# Supported models
option AV400 # 100, 200, 300, 400, 3000, 4000, 4300
-#option AV530 # 4600, 530
+option AV530 # 4600, 530
#option AV5000 # 5000, 6000
#option AV6280 # 6280, 8000-8
diff --git a/sys/arch/aviion/dev/vme.c b/sys/arch/aviion/dev/vme.c
index 456e2e7b9cb..faad62acef2 100644
--- a/sys/arch/aviion/dev/vme.c
+++ b/sys/arch/aviion/dev/vme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vme.c,v 1.4 2007/12/19 22:05:06 miod Exp $ */
+/* $OpenBSD: vme.c,v 1.5 2010/04/18 22:04:39 miod Exp $ */
/*
* Copyright (c) 2006, 2007, Miodrag Vallat.
*
@@ -46,7 +46,6 @@
#include <aviion/dev/vmevar.h>
#include <machine/avcommon.h>
-#include <machine/av400.h> /* XXX */
struct vmesoftc {
struct device sc_dev;
@@ -139,13 +138,13 @@ vmeattach(struct device *parent, struct device *self, void *aux)
* Display VME ranges.
*/
printf("%s: A32 %08x-%08x\n", self->dv_xname,
- AV400_VME32_START1, AV400_VME32_END1);
+ platform->vme32_start1, platform->vme32_end1);
printf("%s: A32 %08x-%08x\n", self->dv_xname,
- AV400_VME32_START2, AV400_VME32_END2);
+ platform->vme32_start2, platform->vme32_end2);
printf("%s: A24 %08x-%08x\n", self->dv_xname,
- AV400_VME24_START, AV400_VME24_END);
+ platform->vme24_start, platform->vme24_end);
printf("%s: A16 %08x-%08x\n", self->dv_xname,
- AV400_VME16_START, AV400_VME16_END);
+ platform->vme16_start, platform->vme16_end);
/* scan for child devices */
config_search(vmescan, self, aux);
@@ -341,16 +340,24 @@ vmeintr_disestablish(u_int vec, struct intrhand *ih)
* bus_space specific functions
*/
+#define ISVMEA32(addr) \
+ (((addr) >= platform->vme32_start1 && (addr) <= platform->vme32_end1) || \
+ ((addr) >= platform->vme32_start2 && (addr) <= platform->vme32_end2))
+#define ISVMEA24(addr) \
+ ((addr) >= platform->vme24_start && (addr) <= platform->vme24_end)
+#define ISVMEA16(addr) \
+ ((addr) >= platform->vme16_start && (addr) <= platform->vme16_end)
+
int
vme16_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
{
struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
- if (AV400_ISVMEA16(addr) && AV400_ISVMEA16(addr + size - 1))
- return (vme_map(sc->sc_ext_a16, addr + AV400_VME16_BASE, addr,
- size, flags, ret));
- else
- return (EINVAL);
+ if (ISVMEA16(addr) && ISVMEA16(addr + size - 1))
+ return vme_map(sc->sc_ext_a16, addr + platform->vme16_base,
+ addr, size, flags, ret);
+
+ return EINVAL;
}
int
@@ -358,11 +365,11 @@ vme24_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
{
struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
- if (AV400_ISVMEA24(addr) && AV400_ISVMEA24(addr + size - 1))
- return (vme_map(sc->sc_ext_a24, addr + AV400_VME24_BASE, addr,
- size, flags, ret));
- else
- return (EINVAL);
+ if (ISVMEA24(addr) && ISVMEA24(addr + size - 1))
+ return vme_map(sc->sc_ext_a24, addr + platform->vme24_base,
+ addr, size, flags, ret);
+
+ return EINVAL;
}
int
@@ -370,11 +377,11 @@ vme32_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
{
struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
- if (AV400_ISVMEA32(addr) && AV400_ISVMEA32(addr + size - 1))
- return (vme_map(sc->sc_ext_a32, addr + AV400_VME32_BASE, addr,
- size, flags, ret));
- else
- return (EINVAL);
+ if (ISVMEA32(addr) && ISVMEA32(addr + size - 1))
+ return vme_map(sc->sc_ext_a32, addr + platform->vme32_base,
+ addr, size, flags, ret);
+
+ return EINVAL;
}
int
@@ -431,7 +438,7 @@ vme16_unmap(bus_space_handle_t handle, bus_size_t size)
if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE)
return;
- pa -= AV400_VME16_BASE;
+ pa -= platform->vme16_base;
return (vme_unmap(sc->sc_ext_a16, pa, (vaddr_t)handle, size));
}
@@ -444,7 +451,7 @@ vme24_unmap(bus_space_handle_t handle, bus_size_t size)
if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE)
return;
- pa -= AV400_VME24_BASE;
+ pa -= platform->vme24_base;
return (vme_unmap(sc->sc_ext_a24, pa, (vaddr_t)handle, size));
}
@@ -457,7 +464,7 @@ vme32_unmap(bus_space_handle_t handle, bus_size_t size)
if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE)
return;
- pa -= AV400_VME32_BASE;
+ pa -= platform->vme32_base;
return (vme_unmap(sc->sc_ext_a32, pa, (vaddr_t)handle, size));
}
@@ -643,19 +650,19 @@ vmemmap(dev_t dev, off_t off, int prot)
switch (awidth) {
case VME_A32:
- if (!AV400_ISVMEA32(pa))
+ if (!ISVMEA32(pa))
return (-1);
- pa += AV400_VME32_BASE;
+ pa += platform->vme32_base;
break;
case VME_A24:
- if (!AV400_ISVMEA24(pa))
+ if (!ISVMEA24(pa))
return (-1);
- pa += AV400_VME24_BASE;
+ pa += platform->vme24_base;
break;
case VME_A16:
- if (!AV400_ISVMEA16(pa))
+ if (!ISVMEA16(pa))
return (-1);
- pa += AV400_VME16_BASE;
+ pa += platform->vme16_base;
break;
}
diff --git a/sys/arch/aviion/include/av400.h b/sys/arch/aviion/include/av400.h
index 5e3e6c6adb6..c7a38af64e3 100644
--- a/sys/arch/aviion/include/av400.h
+++ b/sys/arch/aviion/include/av400.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: av400.h,v 1.5 2007/12/19 22:05:06 miod Exp $ */
+/* $OpenBSD: av400.h,v 1.6 2010/04/18 22:04:39 miod Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
* All rights reserved.
@@ -69,14 +69,6 @@
#define AV400_VME16_START 0x00000000
#define AV400_VME16_END 0x0000ffff
-#define AV400_ISVMEA32(addr) \
- (((addr) >= AV400_VME32_START1 && (addr) < AV400_VME32_END1 + 1U) || \
- ((addr) >= AV400_VME32_START2 && (addr) < AV400_VME32_END2 + 1U))
-#define AV400_ISVMEA24(addr) \
- ((addr) >= AV400_VME24_START && (addr) < AV400_VME24_END + 1U)
-#define AV400_ISVMEA16(addr) \
- ((addr) >= AV400_VME16_START /* && (addr) <= AV400_VME16_END */)
-
/*
* AV400 declarations for hardware level device registers and such.
*/
diff --git a/sys/arch/aviion/include/av530.h b/sys/arch/aviion/include/av530.h
new file mode 100644
index 00000000000..d5bb22b5827
--- /dev/null
+++ b/sys/arch/aviion/include/av530.h
@@ -0,0 +1,191 @@
+/* $OpenBSD: av530.h,v 1.1 2010/04/18 22:04:39 miod Exp $ */
+/*
+ * Copyright (c) 2006, 2010 Miodrag Vallat
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MACHINE_AV530_H__
+#define __MACHINE_AV530_H__
+
+#define AV530_PROM 0xffc00000
+#define AV530_PROM_SIZE 0x00080000
+#define AV530_UTILITY 0xfff00000
+#define AV530_UTILITY_SIZE 0x00100000
+
+/*
+ * AV530 VME mappings
+ */
+
+#define AV530_VME32_BASE 0x00000000
+#define AV530_VME32_START1 0x40000000
+#define AV530_VME32_END1 0x7fffffff
+#define AV530_VME32_START2 0x90000000
+#define AV530_VME32_END2 0xfdffffff
+#define AV530_VME24_BASE 0xfe000000
+#define AV530_VME24_START 0x00000000
+#define AV530_VME24_END 0x00ffffff
+#define AV530_VME16_BASE 0xffff0000
+#define AV530_VME16_START 0x00000000
+#define AV530_VME16_END 0x0000ffff
+
+/*
+ * AV530 declarations for hardware level device registers and such.
+ */
+
+#define AV530_SETSWI 0xfff84080 /* generate soft interrupt */
+#define AV530_CLRSWI 0xfff84084 /* reset soft interrupt */
+
+#define AV530_VIRQLV 0xfff85000
+#define AV530_VIACK1V 0xfff85004
+#define AV530_VIACK2V 0xfff85008
+#define AV530_VIACK3V 0xfff8500c
+#define AV530_VIACK4V 0xfff85010
+#define AV530_VIACK5V 0xfff85014
+#define AV530_VIACK6V 0xfff85018
+#define AV530_VIACK7V 0xfff8501c
+#define AV530_VIRQV 0xfff85020
+
+/*
+ * IEN and IST register bits
+ * See ``Programming System Control and I/O Registers: AViiON 4600 and
+ * 530 series'', section 3 (Interrupts).
+ */
+
+#define IRQ_RESERVED 0x0020aa00 /* all reserved bits */
+#define IRQ_ABORT 0x80000000 /* 31 - Abort */
+#define IRQ_ACF 0x40000000 /* 30 - AC Fail */
+#define IRQ_ARBTO 0x20000000 /* 29 - VME Arbiter Timeout */
+#define IRQ_DTI 0x10000000 /* 28 - DUART Timer Interrupt */
+#define IRQ_SWI7 0x08000000 /* 27 - SW Interrupt level 7 */
+#define IRQ_SWI6 0x04000000 /* 26 - SW Interrupt level 6 */
+#define IRQ_SWI5 0x02000000 /* 25 - SW Interrupt level 5 */
+#define IRQ_SWI4 0x01000000 /* 24 - SW Interrupt level 4 */
+#define IRQ_VME7 0x00800000 /* 23 - VMEBus level 7 */
+#define IRQ_KBD 0x00400000 /* 22 - Keyboard */
+#define IRQ_SF 0x00100000 /* 20 - System Failure */
+#define IRQ_VME6 0x00080000 /* 19 - VMEBus level 6 */
+#define IRQ_MEM 0x00040000 /* 18 - Memory Error */
+#define IRQ_DI 0x00020000 /* 17 - DUART */
+#define IRQ_SIGHPI 0x00010000 /* 16 - SIGHPI */
+#define IRQ_VME5 0x00004000 /* 14 - VMEBus level 5 */
+#define IRQ_VME4 0x00001000 /* 12 - VMEBus level 4 */
+#define IRQ_VME3 0x00000400 /* 10 - VMEBus level 3 */
+#define IRQ_LMI 0x00000100 /* 08 - Location Monitor */
+#define IRQ_SIGLPI 0x00000080 /* 07 - SIGLPI */
+#define IRQ_VME2 0x00000040 /* 06 - VMEBus level 2 */
+#define IRQ_VME1 0x00000010 /* 04 - VMEBus level 1 */
+#define IRQ_SWI3 0x00000008 /* 03 - SW Interrupt level 3 */
+#define IRQ_SWI2 0x00000004 /* 02 - SW Interrupt level 2 */
+#define IRQ_SWI1 0x00000002 /* 01 - SW Interrupt level 1 */
+#define IRQ_SWI0 0x00000001 /* 00 - SW Interrupt level 0 */
+
+#define IST_STRING "\20" \
+ "\40ABRT\37ACF\36ARBTO\35DTI\34SWI7\33SWI6\32SWI5\31SWI4" \
+ "\30IRQ7\27KBD\25SF\24IRQ6\23MEM\22DI\21SIGHPI" \
+ "\17IRQ5\15IRQ4\13IRQ3\11LMI" \
+ "\10SIGLPI\7IRQ2\5IRQ1\4SWI3\3SWI2\2SWI1\1SWI0"
+
+/*
+ * Extended interrupts
+ */
+
+#define AV_EXIEN_BASE 0xfff8e000
+#define AV_EXIEN0 0xfff8e004
+#define AV_EXIEN1 0xfff8e008
+#define AV_EXIEN2 0xfff8e010
+#define AV_EXIEN3 0xfff8e020
+#define AV_EXIENALL 0xfff8e03c
+#define AV_EXIEN(cpu) (AV_EXIEN_BASE + (4 << (cpu)))
+
+#define AV_EXIST 0xfff8e040
+
+#define EXISR_GET_CURRENT_MASK(cpu) \
+ (*(volatile u_int *)AV_EXIST & ext_int_mask_reg[cpu])
+
+/*
+ * EXIEN and EXIST register bits
+ * See ``Programming System control and I/O registers for the 4600 and 530
+ * series'', section 3 (Interrupts).
+ */
+
+#define EXIRQ_RESERVED 0x04000e9f /* all reserved bits */
+#define EXIRQ_RTCOF 0x80000000 /* 31 - RTC Overflow */
+#define EXIRQ_PIT3OF 0x40000000 /* 30 - PIT 3 Overflow */
+#define EXIRQ_PIT2OF 0x20000000 /* 29 - PIT 2 Overflow */
+#define EXIRQ_PIT1OF 0x10000000 /* 28 - PIT 1 Overflow */
+#define EXIRQ_PIT0OF 0x08000000 /* 27 - PIT 0 Overflow */
+#define EXIRQ_DMA4C 0x02000000 /* 25 - DMA4 Channel Complete */
+#define EXIRQ_DMA3C 0x01000000 /* 24 - DMA3 Channel Complete */
+#define EXIRQ_DMA2C 0x00800000 /* 23 - DMA2 Channel Complete */
+#define EXIRQ_DMA1C 0x00400000 /* 22 - DMA1 Channel Complete */
+#define EXIRQ_DMA0C 0x00200000 /* 21 - DMA0 Channel Complete */
+#define EXIRQ_SCC 0x00100000 /* 20 - SCC */
+#define EXIRQ_LAN0 0x00080000 /* 19 - Ethernet 0 */
+#define EXIRQ_LAN1 0x00040000 /* 18 - Ethernet 1 */
+#define EXIRQ_SCSI0 0x00020000 /* 17 - SCSI0 */
+#define EXIRQ_SCSI1 0x00010000 /* 16 - SCSI1 */
+#define EXIRQ_VIDEO 0x00008000 /* 15 - Video */
+#define EXIRQ_ZBUF 0x00004000 /* 14 - Z Buffer */
+#define EXIRQ_DUART2 0x00002000 /* 13 - DUART2 */
+#define EXIRQ_VDMA 0x00001000 /* 12 - VDMA */
+#define EXIRQ_IOEXP1 0x00000100 /* 8 - IO Expansion 1 */
+#define EXIRQ_IOEXP2 0x00000040 /* 6 - IO Expansion 2 */
+#define EXIRQ_PDMA 0x00000020 /* 5 - Parallel Printer DMA */
+
+#define EXIST_STRING "\20" \
+ "\40RTCOF\37PIT3OF\36PIT2OF\35PIT1OF\34PIT0OF\32DMA4\31DMA3" \
+ "\30DMA2\27DMA1\26DMA0\25SCC\24LAN0\23LAN1\22SCSI0\21SCSI1" \
+ "\20VIDEO\17ZBUF\16DUART2\15VDMA\11IOEXP1" \
+ "\7IOEXP2\6PDMA"
+
+#define AV530_SRST 0xfff83100 /* software reset */
+#define SRST_KBD 0x08
+#define SRST_DUART2 0x02
+#define SRST_DUART1 0x01
+#define AV530_IOBRDID0 0xfffcf000
+#define AV530_IOBRDID1 0xfffcf004
+#define AV530_CONFIG 0xfff8fffc
+
+/*
+ * CMMU addresses
+ */
+
+#define AV530_CMMU_D0 0xfff00000
+#define AV530_CMMU_I0 0xfff01000
+#define AV530_CMMU_D1 0xfff02000
+#define AV530_CMMU_I1 0xfff03000
+
+#define AV530_CMMU6_D0 0xfff00000
+#define AV530_CMMU6_D1 0xfff01000
+#define AV530_CMMU6_I0 0xfff04000
+#define AV530_CMMU6_I1 0xfff05000
+#define AV530_CMMU6_I2 0xfff06000
+#define AV530_CMMU6_I3 0xfff07000
+#define AV530_CMMU6_D2 0xfff08000
+#define AV530_CMMU6_D3 0xfff09000
+#define AV530_CMMU6_I4 0xfff0c000
+#define AV530_CMMU6_I5 0xfff0d000
+#define AV530_CMMU6_I6 0xfff0e000
+#define AV530_CMMU6_I7 0xfff0f000
+
+#endif /* __MACHINE_AV530_H__ */
diff --git a/sys/arch/aviion/include/board.h b/sys/arch/aviion/include/board.h
index 21258eadb04..a9975f6ca31 100644
--- a/sys/arch/aviion/include/board.h
+++ b/sys/arch/aviion/include/board.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: board.h,v 1.4 2009/02/16 22:55:03 miod Exp $ */
+/* $OpenBSD: board.h,v 1.5 2010/04/18 22:04:39 miod Exp $ */
/*
* Copyright (c) 2006, 2007, Miodrag Vallat
*
@@ -46,6 +46,10 @@ struct board {
u_int64_t (*intsrc)(int);
pmap_table_t ptable;
+
+ vaddr_t vme16_base, vme16_start, vme16_end;
+ vaddr_t vme24_base, vme24_start, vme24_end;
+ vaddr_t vme32_base, vme32_start1, vme32_end1, vme32_start2, vme32_end2;
};
#define md_interrupt_func(f) platform->intr(f)
diff --git a/sys/arch/m88k/include/m8820x.h b/sys/arch/m88k/include/m8820x.h
index d83ea886484..efb1f28a70e 100644
--- a/sys/arch/m88k/include/m8820x.h
+++ b/sys/arch/m88k/include/m8820x.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: m8820x.h,v 1.7 2006/05/06 16:59:26 miod Exp $ */
+/* $OpenBSD: m8820x.h,v 1.8 2010/04/18 22:04:39 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
*
@@ -198,7 +198,11 @@ struct m8820x_cmmu {
#define DATA_CMMU 0x01 /* odd number */
#define CMMU_MODE(num) ((num) & 1)
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+#define MAX_CMMUS 16 /* maximum cmmus on the board */
+#else
#define MAX_CMMUS 8 /* maximum cmmus on the board */
+#endif
extern struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS];
extern u_int cmmu_shift;
extern u_int max_cmmus;
diff --git a/sys/arch/m88k/m88k/m8820x_machdep.c b/sys/arch/m88k/m88k/m8820x_machdep.c
index 776ef59544f..178382b02ad 100644
--- a/sys/arch/m88k/m88k/m8820x_machdep.c
+++ b/sys/arch/m88k/m88k/m8820x_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m8820x_machdep.c,v 1.38 2009/04/19 17:56:13 miod Exp $ */
+/* $OpenBSD: m8820x_machdep.c,v 1.39 2010/04/18 22:04:39 miod Exp $ */
/*
* Copyright (c) 2004, 2007, Miodrag Vallat.
*
@@ -179,6 +179,10 @@ m8820x_cmmu_set_reg(int reg, u_int val, int flags, int cpu, int mode)
* values there.
*/
for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
if ((flags & MODE_VAL) != 0) {
if (CMMU_MODE(mmu) != mode)
continue;
@@ -201,6 +205,10 @@ m8820x_cmmu_set_cmd(u_int cmd, int flags, int cpu, int mode, vaddr_t addr)
* values there.
*/
for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
if ((flags & MODE_VAL) != 0) {
if (CMMU_MODE(mmu) != mode)
continue;
@@ -234,6 +242,10 @@ m8820x_cmmu_wait(int cpu)
* We scan all related CMMUs and read their status register.
*/
for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
#ifdef DEBUG
if (cmmu->cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
panic("cache flush failed!");
@@ -258,7 +270,7 @@ m8820x_cpu_configuration_print(int main)
int pid = get_cpu_pid();
int proctype = (pid & PID_ARN) >> ARN_SHIFT;
int procvers = (pid & PID_VN) >> VN_SHIFT;
- int mmu, cnt, cpu = cpu_number();
+ int reported, nmmu, mmu, cnt, cpu = cpu_number();
#ifdef M88200_HAS_SPLIT_ADDRESS
int aline, abit, amask;
#endif
@@ -275,15 +287,31 @@ m8820x_cpu_configuration_print(int main)
if (main == 0)
printf(", secondary");
#endif
- printf(", %d CMMU", 1 << cmmu_shift);
+ nmmu = 1 << cmmu_shift;
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ mmu = cpu << cmmu_shift;
+ cmmu = m8820x_cmmu + mmu;
+ for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++)
+ if (cmmu->cmmu_regs == NULL)
+ nmmu--;
+#endif
+ printf(", %d CMMU", nmmu);
mmu = cpu << cmmu_shift;
cmmu = m8820x_cmmu + mmu;
+ reported = 0;
for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
- int idr = cmmu->cmmu_regs[CMMU_IDR];
- int mmuid = CMMU_TYPE(idr);
+ int idr, mmuid;
+
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
- if (mmu % 2 == 0)
+ idr = cmmu->cmmu_regs[CMMU_IDR];
+ mmuid = CMMU_TYPE(idr);
+
+ if (reported++ % 2 == 0)
printf("\ncpu%d: ", cpu);
else
printf(", ");
@@ -320,6 +348,9 @@ m8820x_cpu_configuration_print(int main)
abit);
amask ^= 1 << abit;
}
+ } else if (cmmu_shift != 1) {
+ /* unknown split scheme */
+ printf(" split");
} else
#endif
printf(" full");
@@ -382,8 +413,8 @@ m8820x_initialize_cpu(cpuid_t cpu)
ci = &m88k_cpus[cpu];
switch (cmmu_shift) {
default:
- /* exception code does not use ci_pfsr_* fields */
- break;
+ /* exception code may not use ci_pfsr fields, compute anyway */
+ /* FALLTHROUGH */
case 2:
ci->ci_pfsr_d1 = (u_int)cmmu[3].cmmu_regs + CMMU_PFSR * 4;
ci->ci_pfsr_i1 = (u_int)cmmu[2].cmmu_regs + CMMU_PFSR * 4;
@@ -395,6 +426,10 @@ m8820x_initialize_cpu(cpuid_t cpu)
}
for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, cmmu++) {
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
type = CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]);
/*
@@ -462,6 +497,10 @@ m8820x_shutdown()
cmmu = m8820x_cmmu;
for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
+#ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION
+ if (cmmu->cmmu_regs == NULL)
+ continue;
+#endif
cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] =
((0x00000 << PG_BITS) | CACHE_INH) &
~(CACHE_WT | CACHE_GLOBAL | APR_V);
@@ -555,7 +594,7 @@ m8820x_flush_tlb(cpuid_t cpu, unsigned kernel, vaddr_t vaddr, u_int count)
* of the command we use then).
*
* XXX On systems with more than two CMMUs per CPU, we do not honor the
- * address split - this does not work...
+ * address split - this does not seem to work...
*/
#define trunc_cache_line(a) ((a) & ~(MC88200_CACHE_LINE - 1))