summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/luna88k/luna88k/m8820x.c1411
-rw-r--r--sys/arch/m88k/conf/files.m88k3
-rw-r--r--sys/arch/m88k/include/cmmu.h4
-rw-r--r--sys/arch/m88k/include/m8820x.h28
-rw-r--r--sys/arch/m88k/m88k/cmmu.c4
-rw-r--r--sys/arch/m88k/m88k/m8820x_machdep.c1223
-rw-r--r--sys/arch/mvme88k/include/m8820x.h16
-rw-r--r--sys/arch/mvme88k/mvme88k/m8820x.c1329
8 files changed, 1364 insertions, 2654 deletions
diff --git a/sys/arch/luna88k/luna88k/m8820x.c b/sys/arch/luna88k/luna88k/m8820x.c
index 02f00e3521a..1c5c17a5149 100644
--- a/sys/arch/luna88k/luna88k/m8820x.c
+++ b/sys/arch/luna88k/luna88k/m8820x.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m8820x.c,v 1.4 2004/08/04 15:54:35 miod Exp $ */
+/* $OpenBSD: m8820x.c,v 1.5 2004/08/06 13:23:47 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
*
@@ -83,189 +83,14 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/simplelock.h>
#include <machine/asm_macro.h>
-#include <machine/board.h>
#include <machine/cpu_number.h>
#include <machine/locore.h>
#include <machine/cmmu.h>
#include <machine/m8820x.h>
-
-#include <uvm/uvm_extern.h>
-
-#ifdef DDB
-#include <ddb/db_output.h> /* db_printf() */
-#endif /* DDB */
-
-/*
- * On some versions of the 88200, page size flushes don't work. I am using
- * sledge hammer approach till I find for sure which ones are bad XXX nivas
- */
-#define BROKEN_MMU_MASK
-
-#ifdef DEBUG
-unsigned int m8820x_debuglevel;
-#define dprintf(_X_) \
- do { \
- if (m8820x_debuglevel != 0) { \
- unsigned int psr = disable_interrupts_return_psr(); \
- printf("%d: ", cpu_number()); \
- printf _X_; \
- set_psr(psr); \
- } \
- } while (0)
-#else
-#define dprintf(_X_) do { } while (0)
-#endif
-
-void m8820x_cmmu_init(void);
-void m8820x_setup_board_config(void);
-void m8820x_cpu_configuration_print(int);
-void m8820x_cmmu_shutdown_now(void);
-void m8820x_cmmu_parity_enable(void);
-unsigned m8820x_cmmu_cpu_number(void);
-void m8820x_cmmu_set_sapr(unsigned, unsigned);
-void m8820x_cmmu_set_uapr(unsigned);
-void m8820x_cmmu_flush_tlb(unsigned, unsigned, vaddr_t, vsize_t);
-void m8820x_cmmu_flush_cache(int, paddr_t, psize_t);
-void m8820x_cmmu_flush_inst_cache(int, paddr_t, psize_t);
-void m8820x_cmmu_flush_data_cache(int, paddr_t, psize_t);
-void m8820x_dma_cachectl(vaddr_t, vsize_t, int);
-void m8820x_dma_cachectl_pa(paddr_t, psize_t, int);
-void m8820x_cmmu_dump_config(void);
-void m8820x_cmmu_show_translation(unsigned, unsigned, unsigned, int);
-void m8820x_show_apr(unsigned);
-
-/* This is the function table for the mc8820x CMMUs */
-struct cmmu_p cmmu8820x = {
- m8820x_cmmu_init,
- m8820x_setup_board_config,
- m8820x_cpu_configuration_print,
- m8820x_cmmu_shutdown_now,
- m8820x_cmmu_parity_enable,
- m8820x_cmmu_cpu_number,
- m8820x_cmmu_set_sapr,
- m8820x_cmmu_set_uapr,
- m8820x_cmmu_flush_tlb,
- m8820x_cmmu_flush_cache,
- m8820x_cmmu_flush_inst_cache,
- m8820x_cmmu_flush_data_cache,
- m8820x_dma_cachectl,
- m8820x_dma_cachectl_pa,
-#ifdef DDB
- m8820x_cmmu_dump_config,
- m8820x_cmmu_show_translation,
-#else
- NULL,
- NULL,
-#endif
-#ifdef DEBUG
- m8820x_show_apr,
-#else
- NULL,
-#endif
-};
-
-/*
- * CMMU kernel information
- */
-struct m8820x_cmmu {
- unsigned *volatile cmmu_regs; /* CMMU "base" area */
- unsigned int cmmu_cpu; /* cpu number it is attached to */
- unsigned int cmmu_type;
-#define INST_CMMU 0
-#define DATA_CMMU 1
- unsigned int cmmu_access;
-#define CMMU_ACS_USER 0
-#define CMMU_ACS_SUPER 1
-#define CMMU_ACS_BOTH 2
- unsigned int cmmu_alive;
-#define CMMU_DEAD 0 /* This cmmu is not there */
-#define CMMU_AVAILABLE 1 /* It's there, but which cpu's? */
-#define CMMU_MARRIED 2 /* Know which cpu it belongs to. */
- vaddr_t cmmu_addr; /* address range */
- vaddr_t cmmu_addr_mask; /* address mask */
- int cmmu_addr_match;/* return value of address comparison */
-};
-
-/*
- * Structure for accessing MMUS properly
- */
-
-#define MAX_CMMUS (2 * MAX_CPUS) /* maximum cmmus on the board */
-
-struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS] =
-{
- /* address, cpu, mode, access, alive, addr, mask */
- {(unsigned *volatile)CMMU_I0, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_D0, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_I1, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_D1, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_I2, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_D2, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_I3, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0},
- {(unsigned *volatile)CMMU_D3, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}
-};
-
-struct cpu_cmmu {
- struct m8820x_cmmu *pair[2];
-} cpu_cmmu[MAX_CPUS];
-
-/*
- * CMMU per CPU split strategies
- */
-
-#define CMMU_SPLIT_ADDRESS 0x00
-#define CMMU_SPLIT_SPV 0x01
-#define CMMU_SPLIT_SRAM_SPV 0x02
-#define CMMU_SPLIT_SRAM_ALL 0x03
-
-#define CMMU_SPLIT_MASK 0x03
-
-struct cmmu_strategy {
- int inst;
- int data;
-} cpu_cmmu_strategy[] = {
- /* inst data */
- { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 0 */
- { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 1 */
- { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 2 */
- { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS} /* CPU 3 */
-};
-
-unsigned int cmmu_shift;
-
-/* local prototypes */
-void m8820x_cmmu_set(int, unsigned, int, int, int, int, vaddr_t);
-void m8820x_cmmu_wait(int);
-void m8820x_cmmu_sync_cache(paddr_t, psize_t);
-void m8820x_cmmu_sync_inval_cache(paddr_t, psize_t);
-void m8820x_cmmu_inval_cache(paddr_t, psize_t);
-
-/* Flags passed to m8820x_cmmu_set() */
-#define MODE_VAL 0x01
-#define ACCESS_VAL 0x02
-#define ADDR_VAL 0x04
-
-#ifdef DEBUG
-void
-m8820x_show_apr(value)
- unsigned value;
-{
- printf("table @ 0x%x000", PG_PFNUM(value));
- if (value & CACHE_WT)
- printf(", writethrough");
- if (value & CACHE_GLOBAL)
- printf(", global");
- if (value & CACHE_INH)
- printf(", cache inhibit");
- if (value & APR_V)
- printf(", valid");
- printf("\n");
-}
-#endif
+#include <machine/board.h>
/*
* This routine sets up the CPU/CMMU configuration.
@@ -273,418 +98,66 @@ m8820x_show_apr(value)
void
m8820x_setup_board_config()
{
- int num, cmmu_num;
- unsigned *volatile cr;
+ struct m8820x_cmmu *cmmu;
+ int num;
master_cpu = 0; /* temp to get things going */
- max_cpus = 4;
- max_cmmus = 8;
- cmmu_shift = ff1(max_cmmus / max_cpus);
+ m8820x_cmmu[0].cmmu_regs = (void *)CMMU_I0;
+ m8820x_cmmu[1].cmmu_regs = (void *)CMMU_D0;
+ m8820x_cmmu[2].cmmu_regs = (void *)CMMU_I1;
+ m8820x_cmmu[3].cmmu_regs = (void *)CMMU_D1;
+ m8820x_cmmu[4].cmmu_regs = (void *)CMMU_I2;
+ m8820x_cmmu[5].cmmu_regs = (void *)CMMU_D2;
+ m8820x_cmmu[6].cmmu_regs = (void *)CMMU_I3;
+ m8820x_cmmu[7].cmmu_regs = (void *)CMMU_D3;
+
+ /*
+ * Probe all CMMU address to discover if the CPU slots are populated.
+ */
+ cmmu = m8820x_cmmu;
+ for (max_cmmus = 0; max_cmmus < 8; max_cmmus++, cmmu++) {
+ if (badwordaddr((vaddr_t)cmmu->cmmu_regs) != 0)
+ break;
+ }
+
+ max_cpus = max_cmmus >> 1;
+ max_cmmus = max_cpus << 1;
+ cmmu_shift = 1; /* fixed 2:1 configuration */
+#ifdef DEBUG
/*
- * Probe for available MMUs
+ * Check CMMU type
*/
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
+ for (num = 0; num < max_cmmus; num++) {
+ volatile unsigned *cr = m8820x_cmmu[num].cmmu_regs;
if (badwordaddr((vaddr_t)cr) == 0) {
int type;
type = CMMU_TYPE(cr[CMMU_IDR]);
-#ifdef DIAGNOSTIC
if (type != M88200_ID && type != M88204_ID) {
printf("WARNING: non M8820x circuit found "
"at CMMU address %p\n", cr);
continue; /* will probably die quickly */
}
-#endif
- m8820x_cmmu[cmmu_num].cmmu_alive = CMMU_AVAILABLE;
- dprintf(("m8820x_setup_cmmu_config: CMMU %d found at %p\n",
- cmmu_num, cr));
}
}
+#endif
/*
- * Now that we know which CMMUs are there, let's report on which
- * CPU/CMMU sets seem complete (hopefully all)
+ * Now that we know which CMMUs are there, report every association
*/
for (num = 0; num < max_cpus; num++) {
- int i, type;
+ int type;
- for (i = 0; i < (1 << cmmu_shift); i++) {
- dprintf(("cmmu_init: testing CMMU %d for CPU %d\n",
- (num << cmmu_shift) | i, num));
-#ifdef DIAGNOSTIC
- if (m8820x_cmmu[(num << cmmu_shift) | i].cmmu_alive == CMMU_DEAD) {
- printf("CMMU %d attached to CPU %d is not working\n",
- (num << cmmu_shift) | i, num);
- continue; /* will probably die quickly */
- }
-#endif
- }
cpu_sets[num] = 1; /* This cpu installed... */
type = CMMU_TYPE(m8820x_cmmu[num << cmmu_shift].
cmmu_regs[CMMU_IDR]);
- printf("CPU%d is attached with %d MC%x CMMUs\n",
- num, 1 << cmmu_shift, type == M88204_ID ? 0x88204 : 0x88200);
- }
-
- /*
- * Calculate the CMMU<->CPU connections
- */
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- m8820x_cmmu[cmmu_num].cmmu_cpu =
- (cmmu_num * max_cpus) / max_cmmus;
- dprintf(("m8820x_setup_cmmu_config: CMMU %d connected with CPU %d\n",
- cmmu_num, m8820x_cmmu[cmmu_num].cmmu_cpu));
- }
-
- /*
- * Now set m8820x_cmmu[].cmmu_access and addr
- */
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- /*
- * We don't set up anything for the hardwired configurations.
- */
- m8820x_cmmu[cmmu_num].cmmu_addr = 0;
- m8820x_cmmu[cmmu_num].cmmu_addr_mask = 0;
- m8820x_cmmu[cmmu_num].cmmu_addr_match = 1;
- m8820x_cmmu[cmmu_num].cmmu_access = CMMU_ACS_BOTH;
- }
-}
-
-#ifdef DDB
-
-const char *cmmu_strat_string[] = {
- "address split ",
- "user/spv split",
- "spv SRAM split",
- "all SRAM split"
-};
-
-void
-m8820x_cmmu_dump_config()
-{
- int cmmu_num;
-
- db_printf("Current CPU/CMMU configuration:\n");
-
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- db_printf("CMMU #%d: %s CMMU for CPU %d:\n Strategy: %s\n %s access addr 0x%08lx mask 0x%08lx match %s\n",
- cmmu_num,
- (m8820x_cmmu[cmmu_num].cmmu_type == INST_CMMU) ? "inst" : "data",
- m8820x_cmmu[cmmu_num].cmmu_cpu,
- cmmu_strat_string[(m8820x_cmmu[cmmu_num].cmmu_type == INST_CMMU) ?
- cpu_cmmu_strategy[m8820x_cmmu[cmmu_num].cmmu_cpu].inst :
- cpu_cmmu_strategy[m8820x_cmmu[cmmu_num].cmmu_cpu].data],
- (m8820x_cmmu[cmmu_num].cmmu_access == CMMU_ACS_BOTH) ? "User and spv" :
- ((m8820x_cmmu[cmmu_num].cmmu_access == CMMU_ACS_USER) ? "User " :
- "Supervisor "),
- m8820x_cmmu[cmmu_num].cmmu_addr,
- m8820x_cmmu[cmmu_num].cmmu_addr_mask,
- m8820x_cmmu[cmmu_num].cmmu_addr_match ? "TRUE" : "FALSE");
+ printf("CPU%d is associated to %d MC8820%c CMMUs\n",
+ num, 1 << cmmu_shift, type == M88204_ID ? '4' : '0');
}
}
-#endif /* DDB */
-
-/*
- * This function is called by the MMU module and pokes values
- * into the CMMU's registers.
- */
-void
-m8820x_cmmu_set(reg, val, flags, num, mode, access, addr)
- int reg;
- unsigned val;
- int flags, num, mode, access;
- vaddr_t addr;
-{
- int mmu;
-
- /*
- * We scan all CMMUs to find the matching ones and store the
- * values there.
- */
- for (mmu = num << cmmu_shift;
- mmu < (num + 1) << cmmu_shift; mmu++) {
- if (((flags & MODE_VAL)) &&
- (m8820x_cmmu[mmu].cmmu_type != mode))
- continue;
- if (((flags & ACCESS_VAL)) &&
- (m8820x_cmmu[mmu].cmmu_access != access) &&
- (m8820x_cmmu[mmu].cmmu_access != CMMU_ACS_BOTH))
- continue;
- if (flags & ADDR_VAL) {
- if (((addr & m8820x_cmmu[mmu].cmmu_addr_mask) == m8820x_cmmu[mmu].cmmu_addr)
- != m8820x_cmmu[mmu].cmmu_addr_match) {
- continue;
- }
- }
- m8820x_cmmu[mmu].cmmu_regs[reg] = val;
- }
-}
-
-/*
- * Force a read from the CMMU status register, thereby forcing execution to
- * stop until all pending CMMU operations are finished.
- * This is used by the various cache invalidation functions.
- */
-void
-m8820x_cmmu_wait(int cpu)
-{
- int mmu;
-
- /*
- * We scan all related CMMUs and read their status register.
- */
- for (mmu = cpu << cmmu_shift;
- mmu < (cpu + 1) << cmmu_shift; mmu++) {
-#ifdef DEBUG
- if (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
- panic("cache flush failed!");
- }
-#else
- /* force the read access, but do not issue this statement... */
- __asm__ __volatile__ ("|or r0, r0, %0" ::
- "r" (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR]));
-#endif
- }
-}
-
-const char *mmutypes[8] = {
- "Unknown (0)",
- "Unknown (1)",
- "Unknown (2)",
- "Unknown (3)",
- "Unknown (4)",
- "M88200 (16K)",
- "M88204 (64K)",
- "Unknown (7)"
-};
-
-/*
- * Should only be called after the calling cpus knows its cpu
- * number and master/slave status . Should be called first
- * by the master, before the slaves are started.
-*/
-void
-m8820x_cpu_configuration_print(master)
- int master;
-{
- int pid = read_processor_identification_register();
- int proctype = (pid & 0xff00) >> 8;
- int procvers = (pid & 0xe) >> 1;
- int mmu, cpu = cpu_number();
- struct simplelock print_lock;
-
- if (master)
- simple_lock_init(&print_lock);
-
- simple_lock(&print_lock);
-
- printf("cpu%d: ", cpu);
- if (proctype != 0) {
- printf("unknown model arch 0x%x rev 0x%x\n",
- proctype, procvers);
- simple_unlock(&print_lock);
- return;
- }
-
- printf("M88100 rev 0x%x", procvers);
-#if 0 /* not useful yet */
-#ifdef MVME188
- if (brdtyp == BRD_188)
- printf(", %s", master ? "master" : "slave");
-#endif
-#endif
- printf(", %d CMMU", 1 << cmmu_shift);
-
- for (mmu = cpu << cmmu_shift; mmu < (cpu + 1) << cmmu_shift;
- mmu++) {
- int idr = m8820x_cmmu[mmu].cmmu_regs[CMMU_IDR];
- int mmuid = CMMU_TYPE(idr);
- int access = m8820x_cmmu[mmu].cmmu_access;
-
- if (mmu % 2 == 0)
- printf("\ncpu%d: ", cpu);
- else
- printf(", ");
-
- if (mmutypes[mmuid][0] == 'U')
- printf("unknown model id 0x%x", mmuid);
- else
- printf("%s", mmutypes[mmuid]);
- printf(" rev 0x%x, %s %scache",
- CMMU_VERSION(idr),
- access == CMMU_ACS_BOTH ? "global" :
- (access == CMMU_ACS_USER ? "user" : "sup"),
- m8820x_cmmu[mmu].cmmu_type == INST_CMMU ? "I" : "D");
- }
- printf("\n");
-
-#ifndef ERRATA__XXX_USR
- {
- static int errata_warn = 0;
-
- if (proctype != 0 && procvers < 2) {
- if (!errata_warn++)
- printf("WARNING: M88100 bug workaround code "
- "not enabled.\nPlease recompile the kernel "
- "with option ERRATA__XXX_USR !\n");
- }
- }
-#endif
-
- simple_unlock(&print_lock);
-}
-
-/*
- * CMMU initialization routine
- */
-void
-m8820x_cmmu_init()
-{
- unsigned int line, cmmu_num;
- int cssp, cpu, type;
- u_int32_t apr;
- unsigned *volatile cr;
-
- for (cpu = 0; cpu < max_cpus; cpu++) {
- cpu_cmmu[cpu].pair[INST_CMMU] = 0;
- cpu_cmmu[cpu].pair[DATA_CMMU] = 0;
- }
-
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
- type = CMMU_TYPE(cr[CMMU_IDR]);
-
- cpu_cmmu[m8820x_cmmu[cmmu_num].cmmu_cpu].
- pair[m8820x_cmmu[cmmu_num].cmmu_type] =
- &m8820x_cmmu[cmmu_num];
-
- /*
- * Reset cache
- */
- for (cssp = type == M88204_ID ? 3 : 0;
- cssp >= 0; cssp--)
- for (line = 0; line <= 255; line++) {
- cr[CMMU_SAR] =
- line << MC88200_CACHE_SHIFT;
- cr[CMMU_CSSP(cssp)] =
- CMMU_CSSP_L5 | CMMU_CSSP_L4 |
- CMMU_CSSP_L3 | CMMU_CSSP_L2 |
- CMMU_CSSP_L1 | CMMU_CSSP_L0 |
- CMMU_CSSP_VV(3, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(2, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(1, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(0, CMMU_VV_INVALID);
- }
-
- /*
- * Set the SCTR, SAPR, and UAPR to some known state
- */
- cr[CMMU_SCTR] &=
- ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
- cr[CMMU_SAPR] = cr[CMMU_UAPR] =
- ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL |
- CACHE_INH) & ~APR_V;
-
- cr[CMMU_BWP0] = cr[CMMU_BWP1] =
- cr[CMMU_BWP2] = cr[CMMU_BWP3] =
- cr[CMMU_BWP4] = cr[CMMU_BWP5] =
- cr[CMMU_BWP6] = cr[CMMU_BWP7] = 0;
- cr[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL;
- __asm__ __volatile__ ("|or r0, r0, %0" ::
- "r" (cr[CMMU_SSR]));
- cr[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL;
- cr[CMMU_SCR] = CMMU_FLUSH_USER_ALL;
- }
- }
-
- /*
- * Enable snooping on MVME188 only.
- * Snooping is enabled for instruction cmmus as well so that
- * we can share breakpoints.
- */
-
- for (cpu = 0; cpu < max_cpus; cpu++) {
- if (cpu_sets[cpu] == 0)
- continue;
-
- m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
- DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
- INST_CMMU, 0, 0);
-
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
- ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0);
- m8820x_cmmu_wait(cpu);
- /* Icache gets flushed just below */
- }
-
- /*
- * Enable instruction cache.
- * Data cache can not be enabled at this point, because some device
- * addresses can never be cached, and the no-caching zones are not
- * set up yet.
- */
- for (cpu = 0; cpu < max_cpus; cpu++) {
- if (cpu_sets[cpu] == 0)
- continue;
-
- apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL)
- & ~(CACHE_INH | APR_V);
-
- m8820x_cmmu_set(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
- ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0);
- m8820x_cmmu_wait(cpu);
- }
-}
-
-/*
- * Just before poweroff or reset....
- */
-void
-m8820x_cmmu_shutdown_now()
-{
- unsigned cmmu_num;
- unsigned *volatile cr;
-
- CMMU_LOCK;
- for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++)
- if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
-
- cr[CMMU_SCTR] &=
- ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
- cr[CMMU_SAPR] = cr[CMMU_UAPR] =
- ((0x00000 << PG_BITS) | CACHE_INH) &
- ~(CACHE_WT | CACHE_GLOBAL | APR_V);
- }
- CMMU_UNLOCK;
-}
-
-/*
- * enable parity
- */
-void
-m8820x_cmmu_parity_enable()
-{
- unsigned cmmu_num;
- unsigned *volatile cr;
-
- CMMU_LOCK;
-
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++)
- if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
- cr[CMMU_SCTR] |= CMMU_SCTR_PE;
- }
-
- CMMU_UNLOCK;
-}
/*
* Find out the CPU number from accessing CMMU
@@ -696,34 +169,30 @@ m8820x_cmmu_parity_enable()
unsigned
m8820x_cmmu_cpu_number()
{
- unsigned cmmu_no;
- int i, cpu;
+ unsigned cmmu;
+ u_int i;
CMMU_LOCK;
for (i = 0; i < 10; i++) {
- /* clear CMMU p-bus status registers */
- for (cmmu_no = 0; cmmu_no < MAX_CMMUS; cmmu_no++) {
- if (m8820x_cmmu[cmmu_no].cmmu_alive == CMMU_AVAILABLE &&
- m8820x_cmmu[cmmu_no].cmmu_type == DATA_CMMU)
- m8820x_cmmu[cmmu_no].cmmu_regs[CMMU_PFSR] = 0;
+ /* clear CMMU P-bus status registers */
+ for (cmmu = 0; cmmu < max_cmmus; cmmu++) {
+ if (CMMU_MODE(cmmu) != INST_CMMU)
+ m8820x_cmmu[cmmu].cmmu_regs[CMMU_PFSR] = 0;
}
/* access faulting address */
badwordaddr((vaddr_t)ILLADDRESS);
/* check which CMMU reporting the fault */
- for (cmmu_no = 0; cmmu_no < MAX_CMMUS; cmmu_no++) {
- if (m8820x_cmmu[cmmu_no].cmmu_alive == CMMU_AVAILABLE &&
- m8820x_cmmu[cmmu_no].cmmu_type == DATA_CMMU &&
- CMMU_PFSR_FAULT(m8820x_cmmu[cmmu_no].
+ for (cmmu = 0; cmmu < max_cmmus; cmmu++) {
+ if (CMMU_MODE(cmmu) != INST_CMMU &&
+ CMMU_PFSR_FAULT(m8820x_cmmu[cmmu].
cmmu_regs[CMMU_PFSR]) != CMMU_PFSR_SUCCESS) {
/* clean register, just in case... */
- m8820x_cmmu[cmmu_no].cmmu_regs[CMMU_PFSR] = 0;
- m8820x_cmmu[cmmu_no].cmmu_alive = CMMU_MARRIED;
- cpu = m8820x_cmmu[cmmu_no].cmmu_cpu;
+ m8820x_cmmu[cmmu].cmmu_regs[CMMU_PFSR] = 0;
CMMU_UNLOCK;
- return cpu;
+ return cmmu >> 1;
}
}
}
@@ -731,793 +200,3 @@ m8820x_cmmu_cpu_number()
panic("m8820x_cmmu_cpu_number: could not determine my cpu number");
}
-
-void
-m8820x_cmmu_set_sapr(cpu, ap)
- unsigned cpu, ap;
-{
- CMMU_LOCK;
- m8820x_cmmu_set(CMMU_SAPR, ap, ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0);
- CMMU_UNLOCK;
-}
-
-void
-m8820x_cmmu_set_uapr(ap)
- unsigned ap;
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
- m8820x_cmmu_set(CMMU_UAPR, ap, ACCESS_VAL, cpu, 0, CMMU_ACS_USER, 0);
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * Functions that invalidate TLB entries.
- */
-
-/*
- * flush any tlb
- */
-void
-m8820x_cmmu_flush_tlb(unsigned cpu, unsigned kernel, vaddr_t vaddr,
- vsize_t size)
-{
- int s = splhigh();
-
- CMMU_LOCK;
-
- /*
- * Since segment operations are horribly expensive, don't
- * do any here. Invalidations of up to three pages are performed
- * as page invalidations, otherwise the entire tlb is flushed.
- *
- * Note that this code relies upon size being a multiple of
- * a page and vaddr being page-aligned.
- */
- if (size == PAGE_SIZE) { /* most frequent situation */
- m8820x_cmmu_set(CMMU_SAR, vaddr,
- ADDR_VAL | ACCESS_VAL, cpu, 0,
- kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr);
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
- ADDR_VAL | ACCESS_VAL, cpu, 0,
- kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr);
- } else if (size > 3 * PAGE_SIZE) {
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL,
- ACCESS_VAL, cpu, 0,
- kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, 0);
- } else
- while (size != 0) {
- m8820x_cmmu_set(CMMU_SAR, vaddr,
- ADDR_VAL | ACCESS_VAL, cpu, 0,
- kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr);
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
- ADDR_VAL | ACCESS_VAL, cpu, 0,
- kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr);
-
- size -= PAGE_SIZE;
- vaddr += PAGE_SIZE;
- }
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * Functions that invalidate caches.
- *
- * Cache invalidates require physical addresses. Care must be exercised when
- * using segment invalidates. This implies that the starting physical address
- * plus the segment length should be invalidated. A typical mistake is to
- * extract the first physical page of a segment from a virtual address, and
- * then expecting to invalidate when the pages are not physically contiguous.
- *
- * We don't push Instruction Caches prior to invalidate because they are not
- * snooped and never modified (I guess it doesn't matter then which form
- * of the command we use then).
- */
-
-/*
- * flush both Instruction and Data caches
- */
-void
-m8820x_cmmu_flush_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0,
- cpu, 0, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
- cpu, 0, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, ADDR_VAL,
- cpu, 0, 0, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
- cpu, 0, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, ADDR_VAL,
- cpu, 0, 0, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, 0,
- cpu, 0, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, 0,
- cpu, 0, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0,
- cpu, 0, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * flush Instruction caches
- */
-void
-m8820x_cmmu_flush_inst_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_flush_data_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * sync dcache (and icache too)
- */
-void
-m8820x_cmmu_sync_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_sync_inval_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_inval_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, INST_CMMU, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_dma_cachectl(vaddr_t va, vsize_t size, int op)
-{
- paddr_t pa;
-#if !defined(BROKEN_MMU_MASK)
- psize_t count;
-
- while (size != 0) {
- count = NBPG - (va & PGOFSET);
-
- if (size < count)
- count = size;
-
- if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, count);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, count);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, count);
- break;
- }
- }
-
- va += count;
- size -= count;
- }
-#else
- /* XXX This assumes the space is also physically contiguous */
- if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, size);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, size);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, size);
- break;
- }
- }
-#endif /* !BROKEN_MMU_MASK */
-}
-
-void
-m8820x_dma_cachectl_pa(paddr_t pa, psize_t size, int op)
-{
-#if !defined(BROKEN_MMU_MASK)
- psize_t count;
-
- while (size != 0) {
- count = NBPG - (va & PGOFSET);
-
- if (size < count)
- count = size;
-
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, count);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, count);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, count);
- break;
- }
-
- pa += count;
- size -= count;
- }
-#else
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, size);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, size);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, size);
- break;
- }
-#endif /* !BROKEN_MMU_MASK */
-}
-
-#ifdef DDB
-union ssr {
- unsigned bits;
- struct {
- unsigned :16,
- ce:1,
- be:1,
- :4,
- wt:1,
- sp:1,
- g:1,
- ci:1,
- :1,
- m:1,
- u:1,
- wp:1,
- bh:1,
- v:1;
- } field;
-};
-
-union cssp {
- unsigned bits;
- struct {
- unsigned : 2,
- l: 6,
- d3: 1,
- d2: 1,
- d1: 1,
- d0: 1,
- vv3: 2,
- vv2: 2,
- vv1: 2,
- vv0: 2,
- :12;
- } field;
-};
-
-union batcu {
- unsigned bits;
- struct { /* block address translation register */
- unsigned int
- lba:13, /* logical block address */
- pba:13, /* physical block address */
- s:1, /* supervisor */
- wt:4, /* write through */
- g:1, /* global */
- ci:1, /* cache inhibit */
- wp:1, /* write protect */
- v:1; /* valid */
- } field;
-};
-
- #define VV_EX_UNMOD 0
- #define VV_EX_MOD 1
- #define VV_SHARED_UNMOD 2
- #define VV_INVALID 3
-
- #define D(UNION, LINE) \
- ((LINE) == 3 ? (UNION).field.d3 : \
- ((LINE) == 2 ? (UNION).field.d2 : \
- ((LINE) == 1 ? (UNION).field.d1 : \
- ((LINE) == 0 ? (UNION).field.d0 : ~0))))
- #define VV(UNION, LINE) \
- ((LINE) == 3 ? (UNION).field.vv3 : \
- ((LINE) == 2 ? (UNION).field.vv2 : \
- ((LINE) == 1 ? (UNION).field.vv1 : \
- ((LINE) == 0 ? (UNION).field.vv0 : ~0))))
-
- #undef VEQR_ADDR
- #define VEQR_ADDR 0
-/*
- * Show (for debugging) how the given CMMU translates the given ADDRESS.
- * If cmmu == -1, the data cmmu for the current cpu is used.
- */
-void
-m8820x_cmmu_show_translation(address, supervisor_flag, verbose_flag, cmmu_num)
- unsigned address, supervisor_flag, verbose_flag;
- int cmmu_num;
-{
- /*
- * A virtual address is split into three fields. Two are used as
- * indicies into tables (segment and page), and one is an offset into
- * a page of memory.
- */
- union {
- unsigned bits;
- struct {
- unsigned segment_table_index:SDT_BITS,
- page_table_index:PDT_BITS,
- page_offset:PG_BITS;
- } field;
- } virtual_address;
- u_int32_t value;
-
- if (verbose_flag)
- db_printf("-------------------------------------------\n");
-
-
-
- /****** ACCESS PROPER CMMU or THREAD ***********/
- if (cmmu_num == -1) {
- int cpu = cpu_number();
- if (cpu_cmmu[cpu].pair[DATA_CMMU] == 0) {
- db_printf("ack! can't figure my own data cmmu number.\n");
- return;
- }
- cmmu_num = cpu_cmmu[cpu].pair[DATA_CMMU] - m8820x_cmmu;
- if (verbose_flag)
- db_printf("The data cmmu for cpu#%d is cmmu#%d.\n",
- 0, cmmu_num);
- } else if (cmmu_num < 0 || cmmu_num >= MAX_CMMUS) {
- db_printf("invalid cpu number [%d]... must be in range [0..%d]\n",
- cmmu_num, MAX_CMMUS - 1);
-
- return;
- }
-
- if (m8820x_cmmu[cmmu_num].cmmu_alive == CMMU_DEAD) {
- db_printf("warning: cmmu %d is not alive.\n", cmmu_num);
-#if 0
- return;
-#endif
- }
-
- if (!verbose_flag) {
- if (!(m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE))
- db_printf("WARNING: snooping not enabled for CMMU#%d.\n",
- cmmu_num);
- } else {
- int i;
- for (i = 0; i < MAX_CMMUS; i++)
- if ((i == cmmu_num || m8820x_cmmu[i].cmmu_alive != CMMU_DEAD) &&
- (verbose_flag > 1 || !(m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE))) {
- db_printf("CMMU#%d (cpu %d %s) snooping %s\n", i,
- m8820x_cmmu[i].cmmu_cpu, m8820x_cmmu[i].cmmu_type ? "data" : "inst",
- (m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE) ? "on":"OFF");
- }
- }
-
- if (supervisor_flag)
- value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SAPR];
- else
- value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_UAPR];
-
- /******* SEE WHAT A PROBE SAYS (if not a thread) ***********/
- {
- union ssr ssr;
- unsigned *volatile cmmu_regs = m8820x_cmmu[cmmu_num].cmmu_regs;
- cmmu_regs[CMMU_SAR] = address;
- cmmu_regs[CMMU_SCR] = supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER;
- ssr.bits = cmmu_regs[CMMU_SSR];
- if (verbose_flag > 1)
- db_printf("probe of 0x%08x returns ssr=0x%08x\n",
- address, ssr.bits);
- if (ssr.field.v)
- db_printf("PROBE of 0x%08x returns phys=0x%x",
- address, cmmu_regs[CMMU_SAR]);
- else
- db_printf("PROBE fault at 0x%x", cmmu_regs[CMMU_PFAR]);
- if (ssr.field.ce) db_printf(", copyback err");
- if (ssr.field.be) db_printf(", bus err");
- if (ssr.field.wt) db_printf(", writethrough");
- if (ssr.field.sp) db_printf(", sup prot");
- if (ssr.field.g) db_printf(", global");
- if (ssr.field.ci) db_printf(", cache inhibit");
- if (ssr.field.m) db_printf(", modified");
- if (ssr.field.u) db_printf(", used");
- if (ssr.field.wp) db_printf(", write prot");
- if (ssr.field.bh) db_printf(", BATC");
- db_printf(".\n");
- }
-
- /******* INTERPRET AREA DESCRIPTOR *********/
- {
- if (verbose_flag > 1) {
- db_printf("CMMU#%d", cmmu_num);
- db_printf(" %cAPR is 0x%08x\n",
- supervisor_flag ? 'S' : 'U', value);
- }
- db_printf("CMMU#%d", cmmu_num);
- db_printf(" %cAPR: SegTbl: 0x%x000p",
- supervisor_flag ? 'S' : 'U', PG_PFNUM(value));
- if (value & CACHE_WT)
- db_printf(", WTHRU");
- if (value & CACHE_GLOBAL)
- db_printf(", GLOBAL");
- if (value & CACHE_INH)
- db_printf(", INHIBIT");
- if (value & APR_V)
- db_printf(", VALID");
- db_printf("\n");
-
- /* if not valid, done now */
- if ((value & APR_V) == 0) {
- db_printf("<would report an error, valid bit not set>\n");
-
- return;
- }
-
- value &= PG_FRAME; /* now point to seg page */
- }
-
- /* translate value from physical to virtual */
- if (verbose_flag)
- db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
- value += VEQR_ADDR;
-
- virtual_address.bits = address;
-
- /****** ACCESS SEGMENT TABLE AND INTERPRET SEGMENT DESCRIPTOR *******/
- {
- sdt_entry_t sdt;
- if (verbose_flag)
- db_printf("will follow to entry %d of page at 0x%x...\n",
- virtual_address.field.segment_table_index, value);
- value |= virtual_address.field.segment_table_index *
- sizeof(sdt_entry_t);
-
- if (badwordaddr((vaddr_t)value)) {
- db_printf("ERROR: unable to access page at 0x%08x.\n", value);
- return;
- }
-
- sdt = *(sdt_entry_t *)value;
- if (verbose_flag > 1)
- db_printf("SEG DESC @0x%x is 0x%08x\n", value, sdt);
- db_printf("SEG DESC @0x%x: PgTbl: 0x%x000",
- value, PG_PFNUM(sdt));
- if (sdt & CACHE_WT) db_printf(", WTHRU");
- else db_printf(", !wthru");
- if (sdt & SG_SO) db_printf(", S-PROT");
- else db_printf(", UserOk");
- if (sdt & CACHE_GLOBAL) db_printf(", GLOBAL");
- else db_printf(", !global");
- if (sdt & CACHE_INH) db_printf(", $INHIBIT");
- else db_printf(", $ok");
- if (sdt & SG_PROT) db_printf(", W-PROT");
- else db_printf(", WriteOk");
- if (sdt & SG_V) db_printf(", VALID");
- else db_printf(", !valid");
- db_printf(".\n");
-
- /* if not valid, done now */
- if (!(sdt & SG_V)) {
- db_printf("<would report an error, STD entry not valid>\n");
- return;
- }
-
- value = ptoa(PG_PFNUM(sdt));
- }
-
- /* translate value from physical to virtual */
- if (verbose_flag)
- db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
- value += VEQR_ADDR;
-
- /******* PAGE TABLE *********/
- {
- pt_entry_t pte;
- if (verbose_flag)
- db_printf("will follow to entry %d of page at 0x%x...\n",
- virtual_address.field.page_table_index, value);
- value |= virtual_address.field.page_table_index *
- sizeof(pt_entry_t);
-
- if (badwordaddr((vaddr_t)value)) {
- db_printf("error: unable to access page at 0x%08x.\n", value);
-
- return;
- }
-
- pte = *(pt_entry_t *)value;
- if (verbose_flag > 1)
- db_printf("PAGE DESC @0x%x is 0x%08x.\n", value, pte);
- db_printf("PAGE DESC @0x%x: page @%x000",
- value, PG_PFNUM(pte));
- if (pte & PG_W) db_printf(", WIRE");
- else db_printf(", !wire");
- if (pte & CACHE_WT) db_printf(", WTHRU");
- else db_printf(", !wthru");
- if (pte & PG_SO) db_printf(", S-PROT");
- else db_printf(", UserOk");
- if (pte & CACHE_GLOBAL) db_printf(", GLOBAL");
- else db_printf(", !global");
- if (pte & CACHE_INH) db_printf(", $INHIBIT");
- else db_printf(", $ok");
- if (pte & PG_M) db_printf(", MOD");
- else db_printf(", !mod");
- if (pte & PG_U) db_printf(", USED");
- else db_printf(", !used");
- if (pte & PG_PROT) db_printf(", W-PROT");
- else db_printf(", WriteOk");
- if (pte & PG_V) db_printf(", VALID");
- else db_printf(", !valid");
- db_printf(".\n");
-
- /* if not valid, done now */
- if (!(pte & PG_V)) {
- db_printf("<would report an error, PTE entry not valid>\n");
- return;
- }
-
- value = ptoa(PG_PFNUM(pte));
- if (verbose_flag)
- db_printf("will follow to byte %d of page at 0x%x...\n",
- virtual_address.field.page_offset, value);
- value |= virtual_address.field.page_offset;
-
- if (badwordaddr((vaddr_t)value)) {
- db_printf("error: unable to access page at 0x%08x.\n", value);
- return;
- }
- }
-
- /* translate value from physical to virtual */
- if (verbose_flag)
- db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
- value += VEQR_ADDR;
-
- db_printf("WORD at 0x%x is 0x%08x.\n", value, *(unsigned *)value);
-
-}
-#endif /* DDB */
diff --git a/sys/arch/m88k/conf/files.m88k b/sys/arch/m88k/conf/files.m88k
index a849b4541e8..11232f62b0d 100644
--- a/sys/arch/m88k/conf/files.m88k
+++ b/sys/arch/m88k/conf/files.m88k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.m88k,v 1.6 2004/08/01 17:18:05 miod Exp $
+# $OpenBSD: files.m88k,v 1.7 2004/08/06 13:23:49 miod Exp $
file arch/m88k/m88k/cmmu.c
file arch/m88k/m88k/db_disasm.c ddb
@@ -8,6 +8,7 @@ file arch/m88k/m88k/m88100_fp.S m88100
file arch/m88k/m88k/m88100_machdep.c m88100
file arch/m88k/m88k/m88110_fp.S m88110
file arch/m88k/m88k/m88110_mmu.S m88110
+file arch/m88k/m88k/m8820x_machdep.c m88100
file arch/m88k/m88k/pmap.c
file arch/m88k/m88k/process.S
file arch/m88k/m88k/process_machdep.c
diff --git a/sys/arch/m88k/include/cmmu.h b/sys/arch/m88k/include/cmmu.h
index 8bbaf4b840b..630af8664e7 100644
--- a/sys/arch/m88k/include/cmmu.h
+++ b/sys/arch/m88k/include/cmmu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmmu.h,v 1.4 2004/08/04 15:54:37 miod Exp $ */
+/* $OpenBSD: cmmu.h,v 1.5 2004/08/06 13:23:49 miod Exp $ */
/*
* Mach Operating System
* Copyright (c) 1993-1992 Carnegie Mellon University
@@ -36,7 +36,7 @@
*/
extern unsigned cpu_sets[MAX_CPUS];
extern unsigned master_cpu;
-extern int max_cpus, max_cmmus;
+extern int max_cpus;
/*
* This lock protects the cmmu SAR and SCR's; other ports
diff --git a/sys/arch/m88k/include/m8820x.h b/sys/arch/m88k/include/m8820x.h
index 98ab49f2adc..f37cd64767c 100644
--- a/sys/arch/m88k/include/m8820x.h
+++ b/sys/arch/m88k/include/m8820x.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: m8820x.h,v 1.2 2004/08/04 09:08:19 miod Exp $ */
+/* $OpenBSD: m8820x.h,v 1.3 2004/08/06 13:23:49 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
*
@@ -171,4 +171,30 @@
#define NBSG (1 << (PDT_BITS + PG_BITS)) /* segment size */
+#ifndef _LOCORE
+
+/*
+ * CMMU kernel information
+ */
+struct m8820x_cmmu {
+ volatile u_int32_t *cmmu_regs; /* CMMU "base" area */
+#ifdef M88200_HAS_SPLIT_ADDRESS
+ vaddr_t cmmu_addr; /* address range */
+ vaddr_t cmmu_addr_mask; /* address mask */
+#endif
+};
+
+#define INST_CMMU 0x00 /* even number */
+#define DATA_CMMU 0x01 /* odd number */
+#define CMMU_MODE(num) ((num) & 1)
+
+#define MAX_CMMUS 8 /* maximum cmmus on the board */
+extern struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS];
+extern u_int cmmu_shift;
+extern u_int max_cmmus;
+
+extern void m8820x_setup_board_config(void);
+extern unsigned m8820x_cmmu_cpu_number(void);
+
+#endif /* _LOCORE */
#endif /* __M88K_M8820X_H__ */
diff --git a/sys/arch/m88k/m88k/cmmu.c b/sys/arch/m88k/m88k/cmmu.c
index b82898ca979..30f2d82dde3 100644
--- a/sys/arch/m88k/m88k/cmmu.c
+++ b/sys/arch/m88k/m88k/cmmu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmmu.c,v 1.1 2004/04/29 14:33:27 miod Exp $ */
+/* $OpenBSD: cmmu.c,v 1.2 2004/08/06 13:23:49 miod Exp $ */
/*
* Copyright (c) 1998 Steve Murphree, Jr.
* Copyright (c) 1996 Nivas Madhur
@@ -73,6 +73,6 @@ struct simplelock cmmu_cpu_lock;
unsigned cpu_sets[MAX_CPUS];
unsigned master_cpu = 0;
-int max_cpus, max_cmmus;
+int max_cpus;
struct cmmu_p *cmmu;
diff --git a/sys/arch/m88k/m88k/m8820x_machdep.c b/sys/arch/m88k/m88k/m8820x_machdep.c
new file mode 100644
index 00000000000..30bee9aad77
--- /dev/null
+++ b/sys/arch/m88k/m88k/m8820x_machdep.c
@@ -0,0 +1,1223 @@
+/* $OpenBSD: m8820x_machdep.c,v 1.1 2004/08/06 13:23:49 miod Exp $ */
+/*
+ * Copyright (c) 2004, 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.
+ */
+/*
+ * Copyright (c) 2001 Steve Murphree, Jr.
+ * Copyright (c) 1996 Nivas Madhur
+ * All rights reserved.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Nivas Madhur.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * 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.
+ *
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1991 Carnegie Mellon University
+ * Copyright (c) 1991 OMRON Corporation
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/simplelock.h>
+
+#include <machine/asm_macro.h>
+#include <machine/cpu_number.h>
+#include <machine/locore.h>
+
+#include <machine/cmmu.h>
+#include <machine/m8820x.h>
+
+#include <uvm/uvm_extern.h>
+
+#ifdef DDB
+#include <ddb/db_output.h> /* db_printf() */
+#endif
+
+/*
+ * On some versions of the 88200, page size flushes don't work. I am using
+ * sledge hammer approach till I find for sure which ones are bad XXX nivas
+ */
+#define BROKEN_MMU_MASK
+
+void m8820x_cmmu_init(void);
+void m8820x_cpu_configuration_print(int);
+void m8820x_cmmu_shutdown_now(void);
+void m8820x_cmmu_parity_enable(void);
+void m8820x_cmmu_set_sapr(unsigned, unsigned);
+void m8820x_cmmu_set_uapr(unsigned);
+void m8820x_cmmu_flush_tlb(unsigned, unsigned, vaddr_t, vsize_t);
+void m8820x_cmmu_flush_cache(int, paddr_t, psize_t);
+void m8820x_cmmu_flush_inst_cache(int, paddr_t, psize_t);
+void m8820x_cmmu_flush_data_cache(int, paddr_t, psize_t);
+void m8820x_dma_cachectl(vaddr_t, vsize_t, int);
+void m8820x_dma_cachectl_pa(paddr_t, psize_t, int);
+void m8820x_cmmu_dump_config(void);
+void m8820x_cmmu_show_translation(unsigned, unsigned, unsigned, int);
+void m8820x_show_apr(unsigned);
+
+/* This is the function table for the mc8820x CMMUs */
+struct cmmu_p cmmu8820x = {
+ m8820x_cmmu_init,
+ m8820x_setup_board_config,
+ m8820x_cpu_configuration_print,
+ m8820x_cmmu_shutdown_now,
+ m8820x_cmmu_parity_enable,
+ m8820x_cmmu_cpu_number,
+ m8820x_cmmu_set_sapr,
+ m8820x_cmmu_set_uapr,
+ m8820x_cmmu_flush_tlb,
+ m8820x_cmmu_flush_cache,
+ m8820x_cmmu_flush_inst_cache,
+ m8820x_cmmu_flush_data_cache,
+ m8820x_dma_cachectl,
+ m8820x_dma_cachectl_pa,
+#ifdef DDB
+ m8820x_cmmu_dump_config,
+ m8820x_cmmu_show_translation,
+#else
+ NULL,
+ NULL,
+#endif
+#ifdef DEBUG
+ m8820x_show_apr,
+#else
+ NULL,
+#endif
+};
+
+/*
+ * Systems with more than 2 CMMUs per CPU use programmable split schemes.
+ *
+ * The following schemes are available on MVME188 boards:
+ * - split on A12 address bit (A14 for 88204)
+ * - split on supervisor/user access
+ * - split on SRAM/non-SRAM addresses, with either supervisor-only or all
+ * access to SRAM.
+ *
+ * MVME188 configuration 6, with 4 CMMUs par CPU, also forces a split on
+ * A14 address bit.
+ *
+ * Under OpenBSD, we will only split on A12 and A14 address bits, since we
+ * do not want to waste CMMU resources on the SRAM, and user/supervisor
+ * splits seem less efficient.
+ *
+ * The really nasty part of this choice is in the exception handling code,
+ * when it needs to get error information from up to 4 CMMUs. See eh.S on
+ * mvme88k for the gory details, luna88k is more sane.
+ */
+
+struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS];
+u_int max_cmmus;
+u_int cmmu_shift;
+
+/* local prototypes */
+void m8820x_cmmu_set(int, unsigned, int, int, int, vaddr_t);
+void m8820x_cmmu_wait(int);
+void m8820x_cmmu_sync_cache(paddr_t, psize_t);
+void m8820x_cmmu_sync_inval_cache(paddr_t, psize_t);
+void m8820x_cmmu_inval_cache(paddr_t, psize_t);
+
+/* Flags passed to m8820x_cmmu_set() */
+#define MODE_VAL 0x01
+#define ADDR_VAL 0x02
+
+/*
+ * This function is called by the MMU module and pokes values
+ * into the CMMU's registers.
+ */
+void
+m8820x_cmmu_set(int reg, unsigned val, int flags, int cpu, int mode,
+ vaddr_t addr)
+{
+ struct m8820x_cmmu *cmmu;
+ int mmu, cnt;
+
+ mmu = cpu << cmmu_shift;
+ cmmu = m8820x_cmmu + mmu;
+
+ /*
+ * We scan all CMMUs to find the matching ones and store the
+ * values there.
+ */
+ for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+ if ((flags & MODE_VAL) != 0) {
+ if (CMMU_MODE(mmu) != mode)
+ continue;
+ }
+#ifdef M88200_HAS_SPLIT_ADDRESS
+ if ((flags & ADDR_VAL) != 0) {
+ if (cmmu->cmmu_addr_mask != 0 &&
+ (addr & cmmu->cmmu_addr_mask) != cmmu->cmmu_addr)
+ continue;
+ }
+#endif
+ cmmu->cmmu_regs[reg] = val;
+ }
+}
+
+/*
+ * Force a read from the CMMU status register, thereby forcing execution to
+ * stop until all pending CMMU operations are finished.
+ * This is used by the various cache invalidation functions.
+ */
+void
+m8820x_cmmu_wait(int cpu)
+{
+ struct m8820x_cmmu *cmmu;
+ int mmu, cnt;
+
+ mmu = cpu << cmmu_shift;
+ cmmu = m8820x_cmmu + mmu;
+
+ /*
+ * We scan all related CMMUs and read their status register.
+ */
+ for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+#ifdef DEBUG
+ if (cmmu->cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
+ panic("cache flush failed!");
+ }
+#else
+ /* force the read access, but do not issue this statement... */
+ __asm__ __volatile__ ("|or r0, r0, %0" ::
+ "r" (cmmu->cmmu_regs[CMMU_SSR]));
+#endif
+ }
+}
+
+const char *mmutypes[8] = {
+ "Unknown (0)",
+ "Unknown (1)",
+ "Unknown (2)",
+ "Unknown (3)",
+ "Unknown (4)",
+ "M88200 (16K)",
+ "M88204 (64K)",
+ "Unknown (7)"
+};
+
+/*
+ * Should only be called after the calling cpus knows its cpu
+ * number and master/slave status . Should be called first
+ * by the master, before the slaves are started.
+*/
+void
+m8820x_cpu_configuration_print(int master)
+{
+ struct m8820x_cmmu *cmmu;
+ int pid = read_processor_identification_register();
+ int proctype = (pid & 0xff00) >> 8;
+ int procvers = (pid & 0xe) >> 1;
+ int mmu, cnt, cpu = cpu_number();
+ struct simplelock print_lock;
+
+ if (master)
+ simple_lock_init(&print_lock);
+
+ simple_lock(&print_lock);
+
+ printf("cpu%d: ", cpu);
+ if (proctype != 0) {
+ printf("unknown model arch 0x%x rev 0x%x\n",
+ proctype, procvers);
+ simple_unlock(&print_lock);
+ return;
+ }
+
+ printf("M88100 rev 0x%x", procvers);
+#if 0 /* not useful yet */
+ if (max_cpus > 1)
+ printf(", %s", master ? "master" : "slave");
+#endif
+ printf(", %d CMMU", 1 << cmmu_shift);
+
+ mmu = cpu << cmmu_shift;
+ cmmu = m8820x_cmmu + mmu;
+ for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
+ int idr = cmmu->cmmu_regs[CMMU_IDR];
+ int mmuid = CMMU_TYPE(idr);
+
+ if (mmu % 2 == 0)
+ printf("\ncpu%d: ", cpu);
+ else
+ printf(", ");
+
+ if (mmutypes[mmuid][0] == 'U')
+ printf("unknown model id 0x%x", mmuid);
+ else
+ printf("%s", mmutypes[mmuid]);
+ /* XXX print address lines */
+ printf(" rev 0x%x, %ccache",
+ CMMU_VERSION(idr), CMMU_MODE(mmu) == INST_CMMU ? 'I' : 'D');
+ }
+ printf("\n");
+
+#ifndef ERRATA__XXX_USR
+ {
+ static int errata_warn = 0;
+
+ if (proctype != 0 && procvers < 2) {
+ if (!errata_warn++)
+ printf("WARNING: M88100 bug workaround code "
+ "not enabled.\nPlease recompile the kernel "
+ "with option ERRATA__XXX_USR !\n");
+ }
+ }
+#endif
+
+ simple_unlock(&print_lock);
+}
+
+/*
+ * CMMU initialization routine
+ */
+void
+m8820x_cmmu_init()
+{
+ struct m8820x_cmmu *cmmu;
+ unsigned int line, cmmu_num;
+ int cssp, cpu, type;
+ u_int32_t apr;
+
+ cmmu = m8820x_cmmu;
+ for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
+ type = CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]);
+
+ /*
+ * Reset cache
+ */
+ for (cssp = type == M88204_ID ? 3 : 0; cssp >= 0; cssp--)
+ for (line = 0; line <= 255; line++) {
+ cmmu->cmmu_regs[CMMU_SAR] =
+ line << MC88200_CACHE_SHIFT;
+ cmmu->cmmu_regs[CMMU_CSSP(cssp)] =
+ CMMU_CSSP_L5 | CMMU_CSSP_L4 |
+ CMMU_CSSP_L3 | CMMU_CSSP_L2 |
+ CMMU_CSSP_L1 | CMMU_CSSP_L0 |
+ CMMU_CSSP_VV(3, CMMU_VV_INVALID) |
+ CMMU_CSSP_VV(2, CMMU_VV_INVALID) |
+ CMMU_CSSP_VV(1, CMMU_VV_INVALID) |
+ CMMU_CSSP_VV(0, CMMU_VV_INVALID);
+ }
+
+ /*
+ * Set the SCTR, SAPR, and UAPR to some known state
+ */
+ cmmu->cmmu_regs[CMMU_SCTR] &=
+ ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
+ cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] =
+ ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL |
+ CACHE_INH) & ~APR_V;
+
+ cmmu->cmmu_regs[CMMU_BWP0] = cmmu->cmmu_regs[CMMU_BWP1] =
+ cmmu->cmmu_regs[CMMU_BWP2] = cmmu->cmmu_regs[CMMU_BWP3] =
+ cmmu->cmmu_regs[CMMU_BWP4] = cmmu->cmmu_regs[CMMU_BWP5] =
+ cmmu->cmmu_regs[CMMU_BWP6] = cmmu->cmmu_regs[CMMU_BWP7] = 0;
+ cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL;
+ __asm__ __volatile__ ("|or r0, r0, %0" ::
+ "r" (cmmu->cmmu_regs[CMMU_SSR]));
+ cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL;
+ cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_USER_ALL;
+ }
+
+ /*
+ * Enable snooping on multiprocessor systems.
+ * Snooping is enabled for instruction cmmus as well so that
+ * we can share breakpoints.
+ */
+ if (max_cpus > 1) {
+ for (cpu = 0; cpu < max_cpus; cpu++) {
+#ifdef DIAGNOSTIC
+ if (cpu_sets[cpu] == 0)
+ continue;
+#endif
+
+ m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
+ DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
+ INST_CMMU, 0);
+
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
+ 0, cpu, 0, 0);
+ m8820x_cmmu_wait(cpu);
+ /* Icache gets flushed just below */
+ }
+ }
+
+ /*
+ * Enable instruction cache.
+ * Data cache can not be enabled at this point, because some device
+ * addresses can never be cached, and the no-caching zones are not
+ * set up yet.
+ */
+ for (cpu = 0; cpu < max_cpus; cpu++) {
+#ifdef DIAGNOSTIC
+ if (cpu_sets[cpu] == 0)
+ continue;
+#endif
+
+ apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL)
+ & ~(CACHE_INH | APR_V);
+
+ m8820x_cmmu_set(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
+ 0, cpu, 0, 0);
+ m8820x_cmmu_wait(cpu);
+ }
+}
+
+/*
+ * Just before poweroff or reset....
+ */
+void
+m8820x_cmmu_shutdown_now()
+{
+ unsigned cmmu_num;
+ struct m8820x_cmmu *cmmu;
+
+ CMMU_LOCK;
+ cmmu = m8820x_cmmu;
+ for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
+ cmmu->cmmu_regs[CMMU_SCTR] &=
+ ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
+ cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] =
+ ((0x00000 << PG_BITS) | CACHE_INH) &
+ ~(CACHE_WT | CACHE_GLOBAL | APR_V);
+ }
+ CMMU_UNLOCK;
+}
+
+/*
+ * enable parity
+ */
+void
+m8820x_cmmu_parity_enable()
+{
+ unsigned cmmu_num;
+ struct m8820x_cmmu *cmmu;
+
+ cmmu = m8820x_cmmu;
+ CMMU_LOCK;
+ for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++)
+ cmmu->cmmu_regs[CMMU_SCTR] |= CMMU_SCTR_PE;
+ CMMU_UNLOCK;
+}
+
+void
+m8820x_cmmu_set_sapr(unsigned cpu, unsigned ap)
+{
+ CMMU_LOCK;
+ m8820x_cmmu_set(CMMU_SAPR, ap, 0, cpu, 0, 0);
+ CMMU_UNLOCK;
+}
+
+void
+m8820x_cmmu_set_uapr(unsigned ap)
+{
+ int s = splhigh();
+ int cpu = cpu_number();
+
+ CMMU_LOCK;
+ m8820x_cmmu_set(CMMU_UAPR, ap, 0, cpu, 0, 0);
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+/*
+ * Functions that invalidate TLB entries.
+ */
+
+/*
+ * flush any tlb
+ */
+void
+m8820x_cmmu_flush_tlb(unsigned cpu, unsigned kernel, vaddr_t vaddr,
+ vsize_t size)
+{
+ int s = splhigh();
+
+ CMMU_LOCK;
+
+ /*
+ * Since segment operations are horribly expensive, don't
+ * do any here. Invalidations of up to three pages are performed
+ * as page invalidations, otherwise the entire tlb is flushed.
+ *
+ * Note that this code relies upon size being a multiple of
+ * a page and vaddr being page-aligned.
+ */
+ if (size == PAGE_SIZE) { /* most frequent situation */
+ m8820x_cmmu_set(CMMU_SAR, vaddr,
+ ADDR_VAL, cpu, 0, vaddr);
+ m8820x_cmmu_set(CMMU_SCR,
+ kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
+ ADDR_VAL, cpu, 0, vaddr);
+ } else if (size > 3 * PAGE_SIZE) {
+ m8820x_cmmu_set(CMMU_SCR,
+ kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL,
+ 0, cpu, 0, 0);
+ } else
+ while (size != 0) {
+ m8820x_cmmu_set(CMMU_SAR, vaddr,
+ ADDR_VAL, cpu, 0, vaddr);
+ m8820x_cmmu_set(CMMU_SCR,
+ kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
+ ADDR_VAL, cpu, 0, vaddr);
+
+ size -= PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+/*
+ * Functions that invalidate caches.
+ *
+ * Cache invalidates require physical addresses. Care must be exercised when
+ * using segment invalidates. This implies that the starting physical address
+ * plus the segment length should be invalidated. A typical mistake is to
+ * extract the first physical page of a segment from a virtual address, and
+ * then expecting to invalidate when the pages are not physically contiguous.
+ *
+ * We don't push Instruction Caches prior to invalidate because they are not
+ * snooped and never modified (I guess it doesn't matter then which form
+ * of the command we use then).
+ */
+
+/*
+ * flush both Instruction and Data caches
+ */
+void
+m8820x_cmmu_flush_cache(int cpu, paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0,
+ cpu, 0, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
+ cpu, 0, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, ADDR_VAL,
+ cpu, 0, (unsigned)physaddr);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
+ cpu, 0, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, ADDR_VAL,
+ cpu, 0, (unsigned)physaddr);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, 0,
+ cpu, 0, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, 0,
+ cpu, 0, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0, cpu, 0, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+/*
+ * flush Instruction caches
+ */
+void
+m8820x_cmmu_flush_inst_cache(int cpu, paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+void
+m8820x_cmmu_flush_data_cache(int cpu, paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+/*
+ * sync dcache (and icache too)
+ */
+void
+m8820x_cmmu_sync_cache(paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ int cpu = cpu_number();
+
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_LINE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_LINE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_PAGE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_PAGE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_SEGMENT,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_SEGMENT,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+void
+m8820x_cmmu_sync_inval_cache(paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ int cpu = cpu_number();
+
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+void
+m8820x_cmmu_inval_cache(paddr_t physaddr, psize_t size)
+{
+ int s = splhigh();
+ int cpu = cpu_number();
+
+ CMMU_LOCK;
+
+#if !defined(BROKEN_MMU_MASK)
+ if (size > NBSG) {
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+ } else if (size <= MC88200_CACHE_LINE) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_LINE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_LINE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else if (size <= NBPG) {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_PAGE,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_PAGE,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ } else {
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_SEGMENT,
+ MODE_VAL, cpu, INST_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
+ MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_SEGMENT,
+ MODE_VAL, cpu, DATA_CMMU, 0);
+ }
+#else
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
+ cpu, DATA_CMMU, 0);
+ m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
+ cpu, INST_CMMU, 0);
+#endif /* !BROKEN_MMU_MASK */
+
+ m8820x_cmmu_wait(cpu);
+
+ CMMU_UNLOCK;
+ splx(s);
+}
+
+void
+m8820x_dma_cachectl(vaddr_t va, vsize_t size, int op)
+{
+ paddr_t pa;
+#if !defined(BROKEN_MMU_MASK)
+ psize_t count;
+
+ while (size != 0) {
+ count = NBPG - (va & PGOFSET);
+
+ if (size < count)
+ count = size;
+
+ if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
+ switch (op) {
+ case DMA_CACHE_SYNC:
+ m8820x_cmmu_sync_cache(pa, count);
+ break;
+ case DMA_CACHE_SYNC_INVAL:
+ m8820x_cmmu_sync_inval_cache(pa, count);
+ break;
+ default:
+ m8820x_cmmu_inval_cache(pa, count);
+ break;
+ }
+ }
+
+ va += count;
+ size -= count;
+ }
+#else
+ /* XXX This assumes the space is also physically contiguous */
+ if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
+ switch (op) {
+ case DMA_CACHE_SYNC:
+ m8820x_cmmu_sync_cache(pa, size);
+ break;
+ case DMA_CACHE_SYNC_INVAL:
+ m8820x_cmmu_sync_inval_cache(pa, size);
+ break;
+ default:
+ m8820x_cmmu_inval_cache(pa, size);
+ break;
+ }
+ }
+#endif /* !BROKEN_MMU_MASK */
+}
+
+void
+m8820x_dma_cachectl_pa(paddr_t pa, psize_t size, int op)
+{
+#if !defined(BROKEN_MMU_MASK)
+ psize_t count;
+
+ while (size != 0) {
+ count = NBPG - (va & PGOFSET);
+
+ if (size < count)
+ count = size;
+
+ switch (op) {
+ case DMA_CACHE_SYNC:
+ m8820x_cmmu_sync_cache(pa, count);
+ break;
+ case DMA_CACHE_SYNC_INVAL:
+ m8820x_cmmu_sync_inval_cache(pa, count);
+ break;
+ default:
+ m8820x_cmmu_inval_cache(pa, count);
+ break;
+ }
+
+ pa += count;
+ size -= count;
+ }
+#else
+ switch (op) {
+ case DMA_CACHE_SYNC:
+ m8820x_cmmu_sync_cache(pa, size);
+ break;
+ case DMA_CACHE_SYNC_INVAL:
+ m8820x_cmmu_sync_inval_cache(pa, size);
+ break;
+ default:
+ m8820x_cmmu_inval_cache(pa, size);
+ break;
+ }
+#endif /* !BROKEN_MMU_MASK */
+}
+
+#ifdef DDB
+void
+m8820x_cmmu_dump_config()
+{
+ struct m8820x_cmmu *cmmu;
+ int cmmu_num;
+
+ db_printf("Current CPU/CMMU configuration:\n");
+ cmmu = m8820x_cmmu;
+ for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
+#ifdef M88200_HAS_SPLIT_ADDRESS
+ db_printf("CMMU #%d: %s CMMU for CPU %d, addr 0x%08lx mask 0x%08lx\n",
+ cmmu_num,
+ CMMU_MODE(cmmu_num) == INST_CMMU ? "inst" : "data",
+ cmmu_num >> cmmu_shift,
+ cmmu->cmmu_addr, cmmu->cmmu_addr_mask);
+#else
+ db_printf("CMMU #%d: %s CMMU for CPU %d",
+ cmmu_num,
+ CMMU_MODE(cmmu_num) == INST_CMMU ? "inst" : "data",
+ cmmu_num >> cmmu_shift);
+#endif
+ }
+}
+
+/*
+ * Show (for debugging) how the current CPU translates the given ADDRESS
+ * (as DATA).
+ */
+void
+m8820x_cmmu_show_translation(unsigned address, unsigned supervisor_flag,
+ unsigned verbose_flag, int unused __attribute__ ((unused)))
+{
+ struct m8820x_cmmu *cmmu;
+ int cpu = cpu_number();
+ vaddr_t va = address;
+ int cmmu_num, cnt;
+ u_int32_t value;
+
+ /*
+ * Find the correct data CMMU.
+ */
+ cmmu_num = cpu << cmmu_shift;
+ cmmu = m8820x_cmmu + cmmu_num;
+ for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, cmmu_num++, cmmu++) {
+ if (CMMU_MODE(cmmu_num) == INST_CMMU)
+ continue;
+#ifdef M88200_HAS_SPLIT_ADDRESS
+ if (cmmu->cmmu_addr_mask == 0 ||
+ (va & cmmu->cmmu_addr_mask) ==
+ cmmu->cmmu_addr)
+#endif
+ break;
+ }
+ if (cnt == 0) {
+ db_printf("No matching cmmu for VA %08x\n", address);
+ return;
+ }
+
+ if (verbose_flag != 0)
+ db_printf("VA %08x is managed by CMMU#%d.\n",
+ address, cmmu_num);
+
+ /*
+ * Perform some sanity checks.
+ */
+ if (verbose_flag == 0) {
+ if ((cmmu->cmmu_regs[CMMU_SCTR] &
+ CMMU_SCTR_SE) == 0)
+ db_printf("WARNING: snooping not enabled for CMMU#%d.\n",
+ cmmu_num);
+ } else {
+ int i;
+
+ cmmu = m8820x_cmmu;
+ for (i = 0; i < max_cmmus; i++, cmmu++)
+ if (verbose_flag > 1 ||
+ (cmmu->cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE) == 0) {
+ db_printf("CMMU#%d (cpu %d %s) snooping %s\n",
+ i, i >> cmmu_shift,
+ CMMU_MODE(i) == INST_CMMU ? "inst" : "data",
+ (cmmu->cmmu_regs[CMMU_SCTR] &
+ CMMU_SCTR_SE) ? "on" : "OFF");
+ }
+ cmmu = m8820x_cmmu + cmmu_num;
+ }
+
+ /*
+ * Ask for a CMMU probe and report its result.
+ */
+ {
+ u_int32_t ssr;
+
+ cmmu->cmmu_regs[CMMU_SAR] = address;
+ cmmu->cmmu_regs[CMMU_SCR] =
+ supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER;
+ ssr = cmmu->cmmu_regs[CMMU_SSR];
+
+ switch (verbose_flag) {
+ case 2:
+ db_printf("probe of 0x%08x returns ssr=0x%08x\n",
+ address, ssr);
+ /* FALLTHROUGH */
+ case 1:
+ if (ssr & CMMU_SSR_V)
+ db_printf("PROBE of 0x%08x returns phys=0x%x",
+ address, cmmu->cmmu_regs[CMMU_SAR]);
+ else
+ db_printf("PROBE fault at 0x%x",
+ cmmu->cmmu_regs[CMMU_PFAR]);
+ if (ssr & CMMU_SSR_CE)
+ db_printf(", copyback err");
+ if (ssr & CMMU_SSR_BE)
+ db_printf(", bus err");
+ if (ssr & CACHE_WT)
+ db_printf(", writethrough");
+ if (ssr & CMMU_SSR_SO)
+ db_printf(", sup prot");
+ if (ssr & CACHE_GLOBAL)
+ db_printf(", global");
+ if (ssr & CACHE_INH)
+ db_printf(", cache inhibit");
+ if (ssr & CMMU_SSR_M)
+ db_printf(", modified");
+ if (ssr & CMMU_SSR_U)
+ db_printf(", used");
+ if (ssr & CMMU_SSR_PROT)
+ db_printf(", write prot");
+ if (ssr & CMMU_SSR_BH)
+ db_printf(", BATC");
+ db_printf(".\n");
+ break;
+ }
+ }
+
+ /*
+ * Interpret area descriptor.
+ */
+
+ if (supervisor_flag)
+ value = cmmu->cmmu_regs[CMMU_SAPR];
+ else
+ value = cmmu->cmmu_regs[CMMU_UAPR];
+
+ switch (verbose_flag) {
+ case 2:
+ db_printf("CMMU#%d", cmmu_num);
+ db_printf(" %cAPR is 0x%08x\n",
+ supervisor_flag ? 'S' : 'U', value);
+ /* FALLTHROUGH */
+ case 1:
+ db_printf("CMMU#%d", cmmu_num);
+ db_printf(" %cAPR: SegTbl: 0x%x000p",
+ supervisor_flag ? 'S' : 'U', PG_PFNUM(value));
+ if (value & CACHE_WT)
+ db_printf(", WTHRU");
+ if (value & CACHE_GLOBAL)
+ db_printf(", GLOBAL");
+ if (value & CACHE_INH)
+ db_printf(", INHIBIT");
+ if (value & APR_V)
+ db_printf(", VALID");
+ db_printf("\n");
+ break;
+ }
+
+ if ((value & APR_V) == 0) {
+ db_printf("VA 0x%08x -> apr 0x%08x not valid\n", va, value);
+ return;
+ }
+
+ value &= PG_FRAME; /* now point to seg page */
+
+ /*
+ * Walk segment and page tables to find our page.
+ */
+ {
+ sdt_entry_t sdt;
+
+ if (verbose_flag)
+ db_printf("will follow to entry %d of page at 0x%x...\n",
+ SDTIDX(va), value);
+ value |= SDTIDX(va) * sizeof(sdt_entry_t);
+
+ if (badwordaddr((vaddr_t)value)) {
+ db_printf("VA 0x%08x -> segment table @0x%08x not accessible\n",
+ va, value);
+ return;
+ }
+
+ sdt = *(sdt_entry_t *)value;
+ switch (verbose_flag) {
+ case 2:
+ db_printf("SEG DESC @0x%x is 0x%08x\n", value, sdt);
+ /* FALLTHROUGH */
+ case 1:
+ db_printf("SEG DESC @0x%x: PgTbl: 0x%x000",
+ value, PG_PFNUM(sdt));
+ if (sdt & CACHE_WT)
+ db_printf(", WTHRU");
+ if (sdt & SG_SO)
+ db_printf(", S-PROT");
+ if (sdt & CACHE_GLOBAL)
+ db_printf(", GLOBAL");
+ if (sdt & CACHE_INH)
+ db_printf(", $INHIBIT");
+ if (sdt & SG_PROT)
+ db_printf(", W-PROT");
+ if (sdt & SG_V)
+ db_printf(", VALID");
+ db_printf(".\n");
+ break;
+ }
+
+ if ((sdt & SG_V) == 0) {
+ db_printf("VA 0x%08x -> segment entry 0x%8x @0x%08x not valid\n",
+ va, sdt, value);
+ return;
+ }
+
+ value = ptoa(PG_PFNUM(sdt));
+ }
+
+ {
+ pt_entry_t pte;
+
+ if (verbose_flag)
+ db_printf("will follow to entry %d of page at 0x%x...\n",
+ PDTIDX(va), value);
+ value |= PDTIDX(va) * sizeof(pt_entry_t);
+
+ if (badwordaddr((vaddr_t)value)) {
+ db_printf("VA 0x%08x -> page table entry @0x%08x not accessible\n",
+ va, value);
+ return;
+ }
+
+ pte = *(pt_entry_t *)value;
+ switch (verbose_flag) {
+ case 2:
+ db_printf("PAGE DESC @0x%x is 0x%08x.\n", value, pte);
+ /* FALLTHROUGH */
+ case 1:
+ db_printf("PAGE DESC @0x%x: page @%x000",
+ value, PG_PFNUM(pte));
+ if (pte & PG_W)
+ db_printf(", WIRE");
+ if (pte & CACHE_WT)
+ db_printf(", WTHRU");
+ if (pte & PG_SO)
+ db_printf(", S-PROT");
+ if (pte & CACHE_GLOBAL)
+ db_printf(", GLOBAL");
+ if (pte & CACHE_INH)
+ db_printf(", $INHIBIT");
+ if (pte & PG_M)
+ db_printf(", MOD");
+ if (pte & PG_U)
+ db_printf(", USED");
+ if (pte & PG_PROT)
+ db_printf(", W-PROT");
+ if (pte & PG_V)
+ db_printf(", VALID");
+ db_printf(".\n");
+ break;
+ }
+
+ if ((pte & PG_V) == 0) {
+ db_printf("VA 0x%08x -> page table entry 0x%08x @0x%08x not valid\n",
+ va, pte, value);
+ return;
+ }
+
+ value = ptoa(PG_PFNUM(pte)) | (va & PAGE_MASK);
+ }
+
+ db_printf("VA 0x%08x -> PA 0x%08x\n", va, value);
+}
+#endif /* DDB */
+
+#ifdef DEBUG
+void
+m8820x_show_apr(unsigned value)
+{
+ printf("table @ 0x%x000", PG_PFNUM(value));
+ if (value & CACHE_WT)
+ printf(", writethrough");
+ if (value & CACHE_GLOBAL)
+ printf(", global");
+ if (value & CACHE_INH)
+ printf(", cache inhibit");
+ if (value & APR_V)
+ printf(", valid");
+ printf("\n");
+}
+#endif
diff --git a/sys/arch/mvme88k/include/m8820x.h b/sys/arch/mvme88k/include/m8820x.h
index 4b881800351..1a763f05f48 100644
--- a/sys/arch/mvme88k/include/m8820x.h
+++ b/sys/arch/mvme88k/include/m8820x.h
@@ -1,4 +1,6 @@
-/* $OpenBSD: m8820x.h,v 1.14 2004/08/02 08:35:00 miod Exp $ */
+#ifndef _MVME88K_M8820X_H_
+#define _MVME88K_M8820X_H_
+/* $OpenBSD: m8820x.h,v 1.15 2004/08/06 13:23:49 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
*
@@ -49,7 +51,13 @@
* the rights to redistribute these changes.
*/
-#include <m88k/m8820x.h>
+/*
+ * Code features to enable
+ */
+
+#ifdef MVME188
+#define M88200_HAS_SPLIT_ADDRESS
+#endif
/*
* Address masks for MVME188 CMMU configs
@@ -59,3 +67,7 @@
#define CMMU_A12_MASK (1 << 12)
#define CMMU_A14_MASK (1 << 14)
#define CMMU_SRAM_MASK ((1 << 31) | (1 << 30))
+
+#include <m88k/m8820x.h>
+
+#endif /* _MVME88K_M8820X_H_ */
diff --git a/sys/arch/mvme88k/mvme88k/m8820x.c b/sys/arch/mvme88k/mvme88k/m8820x.c
index 8011a7e5abc..d9172b67905 100644
--- a/sys/arch/mvme88k/mvme88k/m8820x.c
+++ b/sys/arch/mvme88k/mvme88k/m8820x.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m8820x.c,v 1.38 2004/08/04 15:54:38 miod Exp $ */
+/* $OpenBSD: m8820x.c,v 1.39 2004/08/06 13:23:49 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
*
@@ -23,71 +23,15 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * Copyright (c) 2001 Steve Murphree, Jr.
- * Copyright (c) 1996 Nivas Madhur
- * All rights reserved.
- *
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nivas Madhur.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * 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.
- *
- */
-/*
- * Mach Operating System
- * Copyright (c) 1993-1991 Carnegie Mellon University
- * Copyright (c) 1991 OMRON Corporation
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
- * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie the
- * rights to redistribute these changes.
- */
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/simplelock.h>
#include <machine/asm_macro.h>
#include <machine/cpu_number.h>
+#ifdef DEBUG
#include <machine/locore.h>
+#endif
#include <machine/cmmu.h>
#include <machine/m8820x.h>
@@ -98,68 +42,7 @@
#include <machine/mvme188.h>
#endif
-#include <uvm/uvm_extern.h>
-
-#ifdef DDB
-#include <ddb/db_output.h> /* db_printf() */
-#endif
-
-/*
- * On some versions of the 88200, page size flushes don't work. I am using
- * sledge hammer approach till I find for sure which ones are bad XXX nivas
- */
-#define BROKEN_MMU_MASK
-
-u_int max_cmmus;
-
-void m8820x_cmmu_init(void);
-void m8820x_setup_board_config(void);
-void m8820x_cpu_configuration_print(int);
-void m8820x_cmmu_shutdown_now(void);
-void m8820x_cmmu_parity_enable(void);
-unsigned m8820x_cmmu_cpu_number(void);
-void m8820x_cmmu_set_sapr(unsigned, unsigned);
-void m8820x_cmmu_set_uapr(unsigned);
-void m8820x_cmmu_flush_tlb(unsigned, unsigned, vaddr_t, vsize_t);
-void m8820x_cmmu_flush_cache(int, paddr_t, psize_t);
-void m8820x_cmmu_flush_inst_cache(int, paddr_t, psize_t);
-void m8820x_cmmu_flush_data_cache(int, paddr_t, psize_t);
-void m8820x_dma_cachectl(vaddr_t, vsize_t, int);
-void m8820x_dma_cachectl_pa(paddr_t, psize_t, int);
-void m8820x_cmmu_dump_config(void);
-void m8820x_cmmu_show_translation(unsigned, unsigned, unsigned, int);
-void m8820x_show_apr(unsigned);
-
-/* This is the function table for the mc8820x CMMUs */
-struct cmmu_p cmmu8820x = {
- m8820x_cmmu_init,
- m8820x_setup_board_config,
- m8820x_cpu_configuration_print,
- m8820x_cmmu_shutdown_now,
- m8820x_cmmu_parity_enable,
- m8820x_cmmu_cpu_number,
- m8820x_cmmu_set_sapr,
- m8820x_cmmu_set_uapr,
- m8820x_cmmu_flush_tlb,
- m8820x_cmmu_flush_cache,
- m8820x_cmmu_flush_inst_cache,
- m8820x_cmmu_flush_data_cache,
- m8820x_dma_cachectl,
- m8820x_dma_cachectl_pa,
-#ifdef DDB
- m8820x_cmmu_dump_config,
- m8820x_cmmu_show_translation,
-#else
- NULL,
- NULL,
-#endif
-#ifdef DEBUG
- m8820x_show_apr,
-#else
- NULL,
-#endif
-};
-
+#ifdef MVME188
/*
* There are 6 possible MVME188 HYPERmodule configurations:
* - config 0: 4 CPUs, 8 CMMUs
@@ -167,69 +50,8 @@ struct cmmu_p cmmu8820x = {
* - config 2: 1 CPUs, 8 CMMUs
* - config 5: 2 CPUs, 4 CMMUs
* - config 6: 1 CPU, 4 CMMUs
- * - config A: 1 CPU, 2 CMMUs
+ * - config A: 1 CPU, 2 CMMUs (similar in operation to MVME187)
* which can exist either with MC88200 or MC88204 CMMUs.
- *
- * Systems with more than 2 CMMUs per CPU use programmable split schemes,
- * through PCNFA (for code CMMUs) and PCNFB (for data CMMUs) configuration
- * registers.
- *
- * The following schemes are available:
- * - split on A12 address bit (A14 for 88204)
- * - split on supervisor/user access
- * - split on SRAM/non-SRAM addresses, with either supervisor-only or all
- * access to SRAM.
- *
- * Configuration 6, with 4 CMMUs par CPU, also forces a split on A14 address
- * bit.
- *
- * Under OpenBSD, we will only split on A12 and A14 address bits, since we
- * do not want to waste CMMU resources on the SRAM, and user/supervisor
- * splits seem less efficient.
- *
- * The really nasty part of this choice is in the exception handling code,
- * when it needs to get error information from up to 4 CMMUs. See eh.S for
- * the gory details.
- */
-
-/*
- * CMMU kernel information
- */
-struct m8820x_cmmu {
- volatile u_int32_t *cmmu_regs; /* CMMU "base" area */
- unsigned int cmmu_cpu; /* cpu number it is attached to */
- unsigned int cmmu_type;
-#define NO_CMMU 0x00
-#define INST_CMMU 0x01
-#define DATA_CMMU 0x02
- vaddr_t cmmu_addr; /* address range */
- vaddr_t cmmu_addr_mask; /* address mask */
-};
-
-/*
- * Structure for accessing MMUS properly
- */
-
-#define MAX_CMMUS (2 * MAX_CPUS) /* maximum cmmus on the board */
-
-struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS] = {
- /* address, cpu, mode, addr, mask */
- { NULL, -1, INST_CMMU, 0, 0 },
- { NULL, -1, DATA_CMMU, 0, 0 },
- { NULL, -1, INST_CMMU, 0, 0 },
- { NULL, -1, DATA_CMMU, 0, 0 },
- { NULL, -1, INST_CMMU, 0, 0 },
- { NULL, -1, DATA_CMMU, 0, 0 },
- { NULL, -1, INST_CMMU, 0, 0 },
- { NULL, -1, DATA_CMMU, 0, 0 }
-};
-
-unsigned int cmmu_shift;
-
-#ifdef MVME188
-/*
- * The following list describes the different MVME188 configurations
- * which are supported by this code.
*/
const struct board_config {
int ncpus;
@@ -254,45 +76,17 @@ const struct board_config {
};
#endif
-/* local prototypes */
-void m8820x_cmmu_set(int, unsigned, int, int, int, vaddr_t);
-void m8820x_cmmu_wait(int);
-void m8820x_cmmu_sync_cache(paddr_t, psize_t);
-void m8820x_cmmu_sync_inval_cache(paddr_t, psize_t);
-void m8820x_cmmu_inval_cache(paddr_t, psize_t);
-
-/* Flags passed to m8820x_cmmu_set() */
-#define MODE_VAL 0x01
-#define ADDR_VAL 0x02
-
-#ifdef DEBUG
-void
-m8820x_show_apr(unsigned value)
-{
- printf("table @ 0x%x000", PG_PFNUM(value));
- if (value & CACHE_WT)
- printf(", writethrough");
- if (value & CACHE_GLOBAL)
- printf(", global");
- if (value & CACHE_INH)
- printf(", cache inhibit");
- if (value & APR_V)
- printf(", valid");
- printf("\n");
-}
-#endif
-
/*
* This routine sets up the CPU/CMMU configuration.
*/
void
m8820x_setup_board_config()
{
- volatile unsigned *cr;
+ struct m8820x_cmmu *cmmu;
int num, cmmu_num;
int vme188_config;
#ifdef MVME188
- u_int32_t *volatile whoami;
+ u_int32_t whoami;
#endif
master_cpu = 0; /* temp to get things going */
@@ -303,21 +97,16 @@ m8820x_setup_board_config()
/* There is no WHOAMI reg on MVME187 - fake it... */
vme188_config = 0x0a;
m8820x_cmmu[0].cmmu_regs = (void *)SBC_CMMU_I;
- m8820x_cmmu[0].cmmu_cpu = 0;
m8820x_cmmu[1].cmmu_regs = (void *)SBC_CMMU_D;
- m8820x_cmmu[1].cmmu_cpu = 0;
- m8820x_cmmu[2].cmmu_regs = (void *)NULL;
- m8820x_cmmu[3].cmmu_regs = (void *)NULL;
- m8820x_cmmu[4].cmmu_regs = (void *)NULL;
- m8820x_cmmu[5].cmmu_regs = (void *)NULL;
- m8820x_cmmu[6].cmmu_regs = (void *)NULL;
- m8820x_cmmu[7].cmmu_regs = (void *)NULL;
+ max_cpus = 1;
+ max_cmmus = 2;
+ cmmu_shift = 1;
break;
#endif /* MVME187 */
#ifdef MVME188
case BRD_188:
- whoami = (u_int32_t *volatile)MVME188_WHOAMI;
- vme188_config = (*whoami & 0xf0) >> 4;
+ whoami = *(volatile u_int32_t *)MVME188_WHOAMI;
+ vme188_config = (whoami & 0xf0) >> 4;
m8820x_cmmu[0].cmmu_regs = (void *)VME_CMMU_I0;
m8820x_cmmu[1].cmmu_regs = (void *)VME_CMMU_D0;
m8820x_cmmu[2].cmmu_regs = (void *)VME_CMMU_I1;
@@ -326,17 +115,15 @@ m8820x_setup_board_config()
m8820x_cmmu[5].cmmu_regs = (void *)VME_CMMU_D2;
m8820x_cmmu[6].cmmu_regs = (void *)VME_CMMU_I3;
m8820x_cmmu[7].cmmu_regs = (void *)VME_CMMU_D3;
+ max_cpus = bd_config[vme188_config].ncpus;
+ max_cmmus = bd_config[vme188_config].ncmmus;
+ cmmu_shift = ff1(max_cmmus / max_cpus);
break;
#endif /* MVME188 */
}
- max_cpus = bd_config[vme188_config].ncpus;
- max_cmmus = bd_config[vme188_config].ncmmus;
-
- cmmu_shift = ff1(max_cmmus / max_cpus);
-
#ifdef MVME188
- if (bd_config[vme188_config].ncpus > 0) {
+ if (bd_config[vme188_config].ncpus != 0) {
/* 187 has a fixed configuration, no need to print it */
if (brdtyp == BRD_188) {
printf("MVME188 board configuration #%X "
@@ -349,12 +136,12 @@ m8820x_setup_board_config()
}
#endif
-#ifdef DIAGNOSTIC
+#ifdef DEBUG
/*
- * Probe for available MMUs
+ * Check CMMU type
*/
for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
+ volatile unsigned *cr = m8820x_cmmu[cmmu_num].cmmu_regs;
if (badwordaddr((vaddr_t)cr) == 0) {
int type;
@@ -364,14 +151,12 @@ m8820x_setup_board_config()
"at CMMU address %p\n", cr);
continue; /* will probably die quickly */
}
- } else
- m8820x_cmmu[cmmu_num].cmmu_type = NO_CMMU;
+ }
}
#endif
/*
- * Now that we know which CMMUs are there, let's report on which
- * CPU/CMMU sets seem complete (hopefully all)
+ * Now that we know which CMMUs are there, report every association
*/
for (num = 0; num < max_cpus; num++) {
int type;
@@ -380,16 +165,29 @@ m8820x_setup_board_config()
type = CMMU_TYPE(m8820x_cmmu[num << cmmu_shift].
cmmu_regs[CMMU_IDR]);
- printf("CPU%d is attached with %d MC8820%c CMMUs\n",
+ printf("CPU%d is associated to %d MC8820%c CMMUs\n",
num, 1 << cmmu_shift, type == M88204_ID ? '4' : '0');
}
#ifdef MVME188
/*
- * Configure CPU/CMMU strategy into PCNFA and PCNFB board registers.
- * We should theoretically only set these on configurations 1, 2
- * and 6, since the other ones do not have P bus decoders.
+ * Systems with more than 2 CMMUs per CPU use programmable split
+ * schemes, through PCNFA (for code CMMUs) and PCNFB (for data CMMUs)
+ * configuration registers.
+ *
+ * The following schemes are available:
+ * - split on A12 address bit (A14 for 88204)
+ * - split on supervisor/user access
+ * - split on SRAM/non-SRAM addresses, with either supervisor-only or
+ * all access to SRAM.
+ *
+ * Configuration 6, with 4 CMMUs par CPU, also allows a split on A14
+ * address bit.
+ *
+ * Setup the default A12/A14 split here. We should theoretically only
+ * set the PCNFA and PCNFB on configurations 1, 2 and 6, since the
+ * other ones do not have P bus decoders.
* However, is it safe to write them anyways - the values will be
* discarded. Just don't do this on a 187...
*/
@@ -397,20 +195,12 @@ m8820x_setup_board_config()
*(volatile unsigned long *)MVME188_PCNFA = 0;
*(volatile unsigned long *)MVME188_PCNFB = 0;
}
-#endif
-
- /*
- * Calculate the CMMU<->CPU connections
- */
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- m8820x_cmmu[cmmu_num].cmmu_cpu =
- (cmmu_num * max_cpus) / max_cmmus;
- }
/*
* Now set up addressing limits
*/
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
+ for (cmmu_num = 0, cmmu = m8820x_cmmu; cmmu_num < max_cmmus;
+ cmmu_num++, cmmu++) {
num = cmmu_num >> 1; /* CPU view of the CMMU */
switch (cmmu_shift) {
@@ -420,9 +210,8 @@ m8820x_setup_board_config()
* CMMU numbers 0 and 1 match on A14 set,
* 2 and 3 on A14 clear
*/
- m8820x_cmmu[cmmu_num].cmmu_addr |=
- (num < 2 ? CMMU_A14_MASK : 0);
- m8820x_cmmu[cmmu_num].cmmu_addr_mask |= CMMU_A14_MASK;
+ cmmu->cmmu_addr |= (num < 2 ? CMMU_A14_MASK : 0);
+ cmmu->cmmu_addr_mask |= CMMU_A14_MASK;
/* FALLTHROUGH */
case 2:
@@ -431,9 +220,8 @@ m8820x_setup_board_config()
* CMMU numbers 0 and 2 match on A12 set,
* 1 and 3 on A12 clear.
*/
- m8820x_cmmu[cmmu_num].cmmu_addr |=
- (num & 1 ? 0 : CMMU_A12_MASK);
- m8820x_cmmu[cmmu_num].cmmu_addr_mask |= CMMU_A12_MASK;
+ cmmu->cmmu_addr |= (num & 1 ? 0 : CMMU_A12_MASK);
+ cmmu->cmmu_addr_mask |= CMMU_A12_MASK;
break;
case 1:
@@ -441,8 +229,8 @@ m8820x_setup_board_config()
* We don't need to set up anything for the hardwired
* configurations.
*/
- m8820x_cmmu[cmmu_num].cmmu_addr = 0;
- m8820x_cmmu[cmmu_num].cmmu_addr_mask = 0;
+ cmmu->cmmu_addr = 0;
+ cmmu->cmmu_addr_mask = 0;
break;
}
@@ -450,321 +238,12 @@ m8820x_setup_board_config()
* If these CMMUs are 88204, these splitting address lines
* need to be shifted two bits.
*/
- if (CMMU_TYPE(m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_IDR]) ==
- M88204_ID) {
- m8820x_cmmu[cmmu_num].cmmu_addr <<= 2;
- m8820x_cmmu[cmmu_num].cmmu_addr_mask <<= 2;
+ if (CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]) == M88204_ID) {
+ cmmu->cmmu_addr <<= 2;
+ cmmu->cmmu_addr_mask <<= 2;
}
}
-}
-
-#ifdef DDB
-void
-m8820x_cmmu_dump_config()
-{
-#ifdef MVME188
- int cmmu_num;
-
-#ifdef MVME187
- if (brdtyp != BRD_188)
- return;
#endif
-
- db_printf("Current CPU/CMMU configuration:\n");
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- db_printf("CMMU #%d: %s CMMU for CPU %d:\n addr 0x%08lx mask 0x%08lx\n",
- cmmu_num,
- (m8820x_cmmu[cmmu_num].cmmu_type == INST_CMMU) ? "inst" : "data",
- m8820x_cmmu[cmmu_num].cmmu_cpu,
- m8820x_cmmu[cmmu_num].cmmu_addr,
- m8820x_cmmu[cmmu_num].cmmu_addr_mask);
- }
-#endif /* MVME188 */
-}
-#endif /* DDB */
-
-/*
- * This function is called by the MMU module and pokes values
- * into the CMMU's registers.
- */
-void
-m8820x_cmmu_set(int reg, unsigned val, int flags, int cpu, int mode,
- vaddr_t addr)
-{
- int mmu;
-
- /*
- * We scan all CMMUs to find the matching ones and store the
- * values there.
- */
- for (mmu = cpu << cmmu_shift;
- mmu < (cpu + 1) << cmmu_shift; mmu++) {
- if ((flags & MODE_VAL) != 0) {
- if (m8820x_cmmu[mmu].cmmu_type != mode)
- continue;
- }
-#ifdef MVME188
- if ((flags & ADDR_VAL) != 0) {
- if (m8820x_cmmu[mmu].cmmu_addr_mask != 0 &&
- (addr & m8820x_cmmu[mmu].cmmu_addr_mask) !=
- m8820x_cmmu[mmu].cmmu_addr)
- continue;
- }
-#endif
- m8820x_cmmu[mmu].cmmu_regs[reg] = val;
- }
-}
-
-/*
- * Force a read from the CMMU status register, thereby forcing execution to
- * stop until all pending CMMU operations are finished.
- * This is used by the various cache invalidation functions.
- */
-void
-m8820x_cmmu_wait(int cpu)
-{
- int mmu;
-
- /*
- * We scan all related CMMUs and read their status register.
- */
- for (mmu = cpu << cmmu_shift;
- mmu < (cpu + 1) << cmmu_shift; mmu++) {
-#ifdef DEBUG
- if (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
- panic("cache flush failed!");
- }
-#else
- /* force the read access, but do not issue this statement... */
- __asm__ __volatile__ ("|or r0, r0, %0" ::
- "r" (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR]));
-#endif
- }
-}
-
-const char *mmutypes[8] = {
- "Unknown (0)",
- "Unknown (1)",
- "Unknown (2)",
- "Unknown (3)",
- "Unknown (4)",
- "M88200 (16K)",
- "M88204 (64K)",
- "Unknown (7)"
-};
-
-/*
- * Should only be called after the calling cpus knows its cpu
- * number and master/slave status . Should be called first
- * by the master, before the slaves are started.
-*/
-void
-m8820x_cpu_configuration_print(int master)
-{
- int pid = read_processor_identification_register();
- int proctype = (pid & 0xff00) >> 8;
- int procvers = (pid & 0xe) >> 1;
- int mmu, cpu = cpu_number();
- struct simplelock print_lock;
-
- if (master)
- simple_lock_init(&print_lock);
-
- simple_lock(&print_lock);
-
- printf("cpu%d: ", cpu);
- if (proctype != 0) {
- printf("unknown model arch 0x%x rev 0x%x\n",
- proctype, procvers);
- simple_unlock(&print_lock);
- return;
- }
-
- printf("M88100 rev 0x%x", procvers);
-#if 0 /* not useful yet */
-#ifdef MVME188
- if (brdtyp == BRD_188)
- printf(", %s", master ? "master" : "slave");
-#endif
-#endif
- printf(", %d CMMU", 1 << cmmu_shift);
-
- for (mmu = cpu << cmmu_shift; mmu < (cpu + 1) << cmmu_shift;
- mmu++) {
- int idr = m8820x_cmmu[mmu].cmmu_regs[CMMU_IDR];
- int mmuid = CMMU_TYPE(idr);
-
- if (mmu % 2 == 0)
- printf("\ncpu%d: ", cpu);
- else
- printf(", ");
-
- if (mmutypes[mmuid][0] == 'U')
- printf("unknown model id 0x%x", mmuid);
- else
- printf("%s", mmutypes[mmuid]);
- printf(" rev 0x%x, %scache",
- CMMU_VERSION(idr),
- m8820x_cmmu[mmu].cmmu_type == INST_CMMU ? "I" : "D");
- }
- printf("\n");
-
-#ifndef ERRATA__XXX_USR
- {
- static int errata_warn = 0;
-
- if (proctype != 0 && procvers < 2) {
- if (!errata_warn++)
- printf("WARNING: M88100 bug workaround code "
- "not enabled.\nPlease recompile the kernel "
- "with option ERRATA__XXX_USR !\n");
- }
- }
-#endif
-
- simple_unlock(&print_lock);
-}
-
-/*
- * CMMU initialization routine
- */
-void
-m8820x_cmmu_init()
-{
- unsigned int line, cmmu_num;
- int cssp, cpu, type;
- u_int32_t apr;
- volatile unsigned *cr;
-
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
- if (m8820x_cmmu[cmmu_num].cmmu_type != NO_CMMU) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
- type = CMMU_TYPE(cr[CMMU_IDR]);
-
- /*
- * Reset cache
- */
- for (cssp = type == M88204_ID ? 3 : 0;
- cssp >= 0; cssp--)
- for (line = 0; line <= 255; line++) {
- cr[CMMU_SAR] =
- line << MC88200_CACHE_SHIFT;
- cr[CMMU_CSSP(cssp)] =
- CMMU_CSSP_L5 | CMMU_CSSP_L4 |
- CMMU_CSSP_L3 | CMMU_CSSP_L2 |
- CMMU_CSSP_L1 | CMMU_CSSP_L0 |
- CMMU_CSSP_VV(3, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(2, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(1, CMMU_VV_INVALID) |
- CMMU_CSSP_VV(0, CMMU_VV_INVALID);
- }
-
- /*
- * Set the SCTR, SAPR, and UAPR to some known state
- */
- cr[CMMU_SCTR] &=
- ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
- cr[CMMU_SAPR] = cr[CMMU_UAPR] =
- ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL |
- CACHE_INH) & ~APR_V;
-
- cr[CMMU_BWP0] = cr[CMMU_BWP1] =
- cr[CMMU_BWP2] = cr[CMMU_BWP3] =
- cr[CMMU_BWP4] = cr[CMMU_BWP5] =
- cr[CMMU_BWP6] = cr[CMMU_BWP7] = 0;
- cr[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL;
- __asm__ __volatile__ ("|or r0, r0, %0" ::
- "r" (cr[CMMU_SSR]));
- cr[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL;
- cr[CMMU_SCR] = CMMU_FLUSH_USER_ALL;
- }
- }
-
- /*
- * Enable snooping on MVME188 only.
- * Snooping is enabled for instruction cmmus as well so that
- * we can share breakpoints.
- */
-#ifdef MVME188
- if (brdtyp == BRD_188) {
- for (cpu = 0; cpu < max_cpus; cpu++) {
- if (cpu_sets[cpu] == 0)
- continue;
-
- m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
- DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu,
- INST_CMMU, 0);
-
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
- 0, cpu, 0, 0);
- m8820x_cmmu_wait(cpu);
- /* Icache gets flushed just below */
- }
- }
-#endif
-
- /*
- * Enable instruction cache.
- * Data cache can not be enabled at this point, because some device
- * addresses can never be cached, and the no-caching zones are not
- * set up yet.
- */
- for (cpu = 0; cpu < max_cpus; cpu++) {
- if (cpu_sets[cpu] == 0)
- continue;
-
- apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL)
- & ~(CACHE_INH | APR_V);
-
- m8820x_cmmu_set(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL,
- 0, cpu, 0, 0);
- m8820x_cmmu_wait(cpu);
- }
-}
-
-/*
- * Just before poweroff or reset....
- */
-void
-m8820x_cmmu_shutdown_now()
-{
- unsigned cmmu_num;
- volatile unsigned *cr;
-
- CMMU_LOCK;
- for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++)
- if (m8820x_cmmu[cmmu_num].cmmu_type != NO_CMMU) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
-
- cr[CMMU_SCTR] &=
- ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
- cr[CMMU_SAPR] = cr[CMMU_UAPR] =
- ((0x00000 << PG_BITS) | CACHE_INH) &
- ~(CACHE_WT | CACHE_GLOBAL | APR_V);
- }
- CMMU_UNLOCK;
-}
-
-/*
- * enable parity
- */
-void
-m8820x_cmmu_parity_enable()
-{
- unsigned cmmu_num;
- volatile unsigned *cr;
-
- CMMU_LOCK;
-
- for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++)
- if (m8820x_cmmu[cmmu_num].cmmu_type != NO_CMMU) {
- cr = m8820x_cmmu[cmmu_num].cmmu_regs;
- cr[CMMU_SCTR] |= CMMU_SCTR_PE;
- }
-
- CMMU_UNLOCK;
}
/*
@@ -812,713 +291,3 @@ m8820x_cmmu_cpu_number()
panic("can't figure out cpu number from whoami register %x", whoami);
#endif
}
-
-void
-m8820x_cmmu_set_sapr(unsigned cpu, unsigned ap)
-{
- CMMU_LOCK;
- m8820x_cmmu_set(CMMU_SAPR, ap, 0, cpu, 0, 0);
- CMMU_UNLOCK;
-}
-
-void
-m8820x_cmmu_set_uapr(unsigned ap)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
- m8820x_cmmu_set(CMMU_UAPR, ap, 0, cpu, 0, 0);
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * Functions that invalidate TLB entries.
- */
-
-/*
- * flush any tlb
- */
-void
-m8820x_cmmu_flush_tlb(unsigned cpu, unsigned kernel, vaddr_t vaddr,
- vsize_t size)
-{
- int s = splhigh();
-
- CMMU_LOCK;
-
- /*
- * Since segment operations are horribly expensive, don't
- * do any here. Invalidations of up to three pages are performed
- * as page invalidations, otherwise the entire tlb is flushed.
- *
- * Note that this code relies upon size being a multiple of
- * a page and vaddr being page-aligned.
- */
- if (size == PAGE_SIZE) { /* most frequent situation */
- m8820x_cmmu_set(CMMU_SAR, vaddr,
- ADDR_VAL, cpu, 0, vaddr);
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
- ADDR_VAL, cpu, 0, vaddr);
- } else if (size > 3 * PAGE_SIZE) {
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL,
- 0, cpu, 0, 0);
- } else
- while (size != 0) {
- m8820x_cmmu_set(CMMU_SAR, vaddr,
- ADDR_VAL, cpu, 0, vaddr);
- m8820x_cmmu_set(CMMU_SCR,
- kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
- ADDR_VAL, cpu, 0, vaddr);
-
- size -= PAGE_SIZE;
- vaddr += PAGE_SIZE;
- }
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * Functions that invalidate caches.
- *
- * Cache invalidates require physical addresses. Care must be exercised when
- * using segment invalidates. This implies that the starting physical address
- * plus the segment length should be invalidated. A typical mistake is to
- * extract the first physical page of a segment from a virtual address, and
- * then expecting to invalidate when the pages are not physically contiguous.
- *
- * We don't push Instruction Caches prior to invalidate because they are not
- * snooped and never modified (I guess it doesn't matter then which form
- * of the command we use then).
- */
-
-/*
- * flush both Instruction and Data caches
- */
-void
-m8820x_cmmu_flush_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0,
- cpu, 0, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
- cpu, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, ADDR_VAL,
- cpu, 0, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL,
- cpu, 0, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, ADDR_VAL,
- cpu, 0, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, 0,
- cpu, 0, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, 0,
- cpu, 0, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0, cpu, 0, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * flush Instruction caches
- */
-void
-m8820x_cmmu_flush_inst_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_flush_data_cache(int cpu, paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL, cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-/*
- * sync dcache (and icache too)
- */
-void
-m8820x_cmmu_sync_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_sync_inval_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_cmmu_inval_cache(paddr_t physaddr, psize_t size)
-{
- int s = splhigh();
- int cpu = cpu_number();
-
- CMMU_LOCK;
-
-#if !defined(BROKEN_MMU_MASK)
- if (size > NBSG) {
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
- } else if (size <= MC88200_CACHE_LINE) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else if (size <= NBPG) {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE,
- MODE_VAL, cpu, DATA_CMMU, 0);
- } else {
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, INST_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT,
- MODE_VAL, cpu, INST_CMMU, 0);
- m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr,
- MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, (unsigned)physaddr);
- m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT,
- MODE_VAL, cpu, DATA_CMMU, 0);
- }
-#else
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, DATA_CMMU, 0);
- m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL,
- cpu, INST_CMMU, 0);
-#endif /* !BROKEN_MMU_MASK */
-
- m8820x_cmmu_wait(cpu);
-
- CMMU_UNLOCK;
- splx(s);
-}
-
-void
-m8820x_dma_cachectl(vaddr_t va, vsize_t size, int op)
-{
- paddr_t pa;
-#if !defined(BROKEN_MMU_MASK)
- psize_t count;
-
- while (size != 0) {
- count = NBPG - (va & PGOFSET);
-
- if (size < count)
- count = size;
-
- if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, count);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, count);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, count);
- break;
- }
- }
-
- va += count;
- size -= count;
- }
-#else
- /* XXX This assumes the space is also physically contiguous */
- if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) {
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, size);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, size);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, size);
- break;
- }
- }
-#endif /* !BROKEN_MMU_MASK */
-}
-
-void
-m8820x_dma_cachectl_pa(paddr_t pa, psize_t size, int op)
-{
-#if !defined(BROKEN_MMU_MASK)
- psize_t count;
-
- while (size != 0) {
- count = NBPG - (va & PGOFSET);
-
- if (size < count)
- count = size;
-
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, count);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, count);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, count);
- break;
- }
-
- pa += count;
- size -= count;
- }
-#else
- switch (op) {
- case DMA_CACHE_SYNC:
- m8820x_cmmu_sync_cache(pa, size);
- break;
- case DMA_CACHE_SYNC_INVAL:
- m8820x_cmmu_sync_inval_cache(pa, size);
- break;
- default:
- m8820x_cmmu_inval_cache(pa, size);
- break;
- }
-#endif /* !BROKEN_MMU_MASK */
-}
-
-#ifdef DDB
-/*
- * Show (for debugging) how the current CPU translates the given ADDRESS
- * (as DATA).
- */
-void
-m8820x_cmmu_show_translation(unsigned address, unsigned supervisor_flag,
- unsigned verbose_flag, int unused __attribute__ ((unused)))
-{
- int cpu = cpu_number();
- vaddr_t va = address;
- int cmmu_num;
- u_int32_t value;
-
- /*
- * Find the correct data CMMU.
- */
- for (cmmu_num = cpu << cmmu_shift;
- cmmu_num < (cpu + 1) << cmmu_shift; cmmu_num++) {
- if (m8820x_cmmu[cmmu_num].cmmu_type != DATA_CMMU)
- continue;
- if (m8820x_cmmu[cmmu_num].cmmu_addr_mask == 0 ||
- (va & m8820x_cmmu[cmmu_num].cmmu_addr_mask) ==
- m8820x_cmmu[cmmu_num].cmmu_addr)
- break;
- }
- if (cmmu_num == (cpu + 1) << cmmu_shift) {
- db_printf("No matching cmmu for VA %08x\n", address);
- return;
- }
-
- if (verbose_flag != 0)
- db_printf("VA %08x is managed by CMMU#%d.\n",
- address, cmmu_num);
-
- /*
- * Perform some sanity checks.
- */
- if (verbose_flag == 0) {
- if ((m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SCTR] &
- CMMU_SCTR_SE) == 0)
- db_printf("WARNING: snooping not enabled for CMMU#%d.\n",
- cmmu_num);
- } else {
- int i;
-
- for (i = 0; i < max_cmmus; i++)
- if (m8820x_cmmu[i].cmmu_type != NO_CMMU &&
- (verbose_flag > 1 ||
- (m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] &
- CMMU_SCTR_SE) == 0)) {
- db_printf("CMMU#%d (cpu %d %s) snooping %s\n",
- i, m8820x_cmmu[i].cmmu_cpu,
- m8820x_cmmu[i].cmmu_type ? "data" : "inst",
- (m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] &
- CMMU_SCTR_SE) ? "on":"OFF");
- }
- }
-
- /*
- * Ask for a CMMU probe and report its result.
- */
- {
- volatile unsigned *cmmu_regs = m8820x_cmmu[cmmu_num].cmmu_regs;
- u_int32_t ssr;
-
- cmmu_regs[CMMU_SAR] = address;
- cmmu_regs[CMMU_SCR] =
- supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER;
- ssr = cmmu_regs[CMMU_SSR];
-
- switch (verbose_flag) {
- case 2:
- db_printf("probe of 0x%08x returns ssr=0x%08x\n",
- address, ssr);
- /* FALLTHROUGH */
- case 1:
- if (ssr & CMMU_SSR_V)
- db_printf("PROBE of 0x%08x returns phys=0x%x",
- address, cmmu_regs[CMMU_SAR]);
- else
- db_printf("PROBE fault at 0x%x",
- cmmu_regs[CMMU_PFAR]);
- if (ssr & CMMU_SSR_CE)
- db_printf(", copyback err");
- if (ssr & CMMU_SSR_BE)
- db_printf(", bus err");
- if (ssr & CACHE_WT)
- db_printf(", writethrough");
- if (ssr & CMMU_SSR_SO)
- db_printf(", sup prot");
- if (ssr & CACHE_GLOBAL)
- db_printf(", global");
- if (ssr & CACHE_INH)
- db_printf(", cache inhibit");
- if (ssr & CMMU_SSR_M)
- db_printf(", modified");
- if (ssr & CMMU_SSR_U)
- db_printf(", used");
- if (ssr & CMMU_SSR_PROT)
- db_printf(", write prot");
- if (ssr & CMMU_SSR_BH)
- db_printf(", BATC");
- db_printf(".\n");
- break;
- }
- }
-
- /*
- * Interpret area descriptor.
- */
-
- if (supervisor_flag)
- value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SAPR];
- else
- value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_UAPR];
-
- switch (verbose_flag) {
- case 2:
- db_printf("CMMU#%d", cmmu_num);
- db_printf(" %cAPR is 0x%08x\n",
- supervisor_flag ? 'S' : 'U', value);
- /* FALLTHROUGH */
- case 1:
- db_printf("CMMU#%d", cmmu_num);
- db_printf(" %cAPR: SegTbl: 0x%x000p",
- supervisor_flag ? 'S' : 'U', PG_PFNUM(value));
- if (value & CACHE_WT)
- db_printf(", WTHRU");
- if (value & CACHE_GLOBAL)
- db_printf(", GLOBAL");
- if (value & CACHE_INH)
- db_printf(", INHIBIT");
- if (value & APR_V)
- db_printf(", VALID");
- db_printf("\n");
- break;
- }
-
- if ((value & APR_V) == 0) {
- db_printf("VA 0x%08x -> apr 0x%08x not valid\n", va, value);
- return;
- }
-
- value &= PG_FRAME; /* now point to seg page */
-
- /*
- * Walk segment and page tables to find our page.
- */
- {
- sdt_entry_t sdt;
-
- if (verbose_flag)
- db_printf("will follow to entry %d of page at 0x%x...\n",
- SDTIDX(va), value);
- value |= SDTIDX(va) * sizeof(sdt_entry_t);
-
- if (badwordaddr((vaddr_t)value)) {
- db_printf("VA 0x%08x -> segment table @0x%08x not accessible\n",
- va, value);
- return;
- }
-
- sdt = *(sdt_entry_t *)value;
- switch (verbose_flag) {
- case 2:
- db_printf("SEG DESC @0x%x is 0x%08x\n", value, sdt);
- /* FALLTHROUGH */
- case 1:
- db_printf("SEG DESC @0x%x: PgTbl: 0x%x000",
- value, PG_PFNUM(sdt));
- if (sdt & CACHE_WT)
- db_printf(", WTHRU");
- if (sdt & SG_SO)
- db_printf(", S-PROT");
- if (sdt & CACHE_GLOBAL)
- db_printf(", GLOBAL");
- if (sdt & CACHE_INH)
- db_printf(", $INHIBIT");
- if (sdt & SG_PROT)
- db_printf(", W-PROT");
- if (sdt & SG_V)
- db_printf(", VALID");
- db_printf(".\n");
- break;
- }
-
- if ((sdt & SG_V) == 0) {
- db_printf("VA 0x%08x -> segment entry 0x%8x @0x%08x not valid\n",
- va, sdt, value);
- return;
- }
-
- value = ptoa(PG_PFNUM(sdt));
- }
-
- {
- pt_entry_t pte;
-
- if (verbose_flag)
- db_printf("will follow to entry %d of page at 0x%x...\n",
- PDTIDX(va), value);
- value |= PDTIDX(va) * sizeof(pt_entry_t);
-
- if (badwordaddr((vaddr_t)value)) {
- db_printf("VA 0x%08x -> page table entry @0x%08x not accessible\n",
- va, value);
- return;
- }
-
- pte = *(pt_entry_t *)value;
- switch (verbose_flag) {
- case 2:
- db_printf("PAGE DESC @0x%x is 0x%08x.\n", value, pte);
- /* FALLTHROUGH */
- case 1:
- db_printf("PAGE DESC @0x%x: page @%x000",
- value, PG_PFNUM(pte));
- if (pte & PG_W)
- db_printf(", WIRE");
- if (pte & CACHE_WT)
- db_printf(", WTHRU");
- if (pte & PG_SO)
- db_printf(", S-PROT");
- if (pte & CACHE_GLOBAL)
- db_printf(", GLOBAL");
- if (pte & CACHE_INH)
- db_printf(", $INHIBIT");
- if (pte & PG_M)
- db_printf(", MOD");
- if (pte & PG_U)
- db_printf(", USED");
- if (pte & PG_PROT)
- db_printf(", W-PROT");
- if (pte & PG_V)
- db_printf(", VALID");
- db_printf(".\n");
- break;
- }
-
- if ((pte & PG_V) == 0) {
- db_printf("VA 0x%08x -> page table entry 0x%08x @0x%08x not valid\n",
- va, pte, value);
- return;
- }
-
- value = ptoa(PG_PFNUM(pte)) | (va & PAGE_MASK);
- }
-
- db_printf("VA 0x%08x -> PA 0x%08x\n", va, value);
-}
-#endif /* DDB */