diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-10-01 19:00:53 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-10-01 19:00:53 +0000 |
commit | 28d2048972070870285a1f3bcb1de5a0edeb9da2 (patch) | |
tree | 31e42da56e059c64534e201480c6a4eb2a560e8f /sys/arch/mvme88k | |
parent | 1173b4bd409e7e437a50878107df575f66fd4aa2 (diff) |
More mvme88k code cleaning:
- merge locore_c_routines.c into machdep.c
- split machdep.c into really machdep.c content, and board-specific routines
(memory sizing, early initialization, etc).
No functionnal change.
Diffstat (limited to 'sys/arch/mvme88k')
-rw-r--r-- | sys/arch/mvme88k/conf/files.mvme88k | 12 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/locore.h | 27 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/mvme188.h | 11 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/locore_c_routines.c | 328 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m187_machdep.c | 267 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m188_machdep.c | 422 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m197_machdep.c | 283 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/machdep.c | 1093 |
8 files changed, 1268 insertions, 1175 deletions
diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index c0a48317c71..18df991418c 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.32 2004/07/25 11:06:42 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.33 2004/10/01 19:00:51 miod Exp $ # maxpartitions 16 @@ -63,9 +63,9 @@ device vmes { [addr = -1], [vec = -1], [ipl = 0] } attach vmes at vme device vmel { [addr = -1], [vec = -1], [ipl = 0] } attach vmel at vme -file arch/mvme88k/dev/vme.c vme | vmes | vmel -file arch/mvme88k/dev/vmes.c vmes needs-count -file arch/mvme88k/dev/vmel.c vmel needs-count +file arch/mvme88k/dev/vme.c vme | vmes | vmel +file arch/mvme88k/dev/vmes.c vmes needs-count +file arch/mvme88k/dev/vmel.c vmel needs-count # list of standard files file dev/cons.c @@ -82,8 +82,10 @@ file arch/mvme88k/mvme88k/m88110.c m88110 file arch/mvme88k/mvme88k/disksubr.c file arch/mvme88k/mvme88k/dkbad.c file arch/mvme88k/mvme88k/eh.S -file arch/mvme88k/mvme88k/locore_c_routines.c file arch/mvme88k/mvme88k/machdep.c +file arch/mvme88k/mvme88k/m187_machdep.c mvme187 +file arch/mvme88k/mvme88k/m188_machdep.c mvme188 +file arch/mvme88k/mvme88k/m197_machdep.c mvme197 file arch/mvme88k/mvme88k/mem.c file arch/mvme88k/mvme88k/pmap_bootstrap.c file arch/mvme88k/mvme88k/pmap_table.c diff --git a/sys/arch/mvme88k/include/locore.h b/sys/arch/mvme88k/include/locore.h index 642e77a7c87..dd554aaeafa 100644 --- a/sys/arch/mvme88k/include/locore.h +++ b/sys/arch/mvme88k/include/locore.h @@ -1,10 +1,8 @@ -/* $OpenBSD: locore.h,v 1.24 2004/08/01 17:18:05 miod Exp $ */ +/* $OpenBSD: locore.h,v 1.25 2004/10/01 19:00:51 miod Exp $ */ #ifndef _MACHINE_LOCORE_H_ #define _MACHINE_LOCORE_H_ -#include <uvm/uvm_param.h> - /* * C prototypes for various routines defined in locore_* and friends */ @@ -17,8 +15,7 @@ int badaddr(vaddr_t addr, int size); void set_cpu_number(unsigned number); void doboot(void); -int guarded_access(unsigned char *volatile address, - unsigned len, u_char *vec); +int guarded_access(volatile u_int8_t *, unsigned, u_int8_t *); /* locore_c_routines.c */ @@ -26,25 +23,13 @@ unsigned getipl(void); /* machdep.c */ -void _doboot(void); -vaddr_t get_slave_stack(void); -void slave_pre_main(void); -int slave_main(void); int intr_findvec(int, int, int); -void bugsyscall(void); void myetheraddr(u_char *cp); -void dosoftint(void); -void mvme_bootstrap(void); -void m187_ext_int(u_int v, struct trapframe *eframe); -void m188_reset(void); -void m188_ext_int(u_int v, struct trapframe *eframe); -unsigned int safe_level(unsigned mask, unsigned curlevel); -void m197_ext_int(u_int v, struct trapframe *eframe); + +extern volatile u_int8_t *ivec[8]; /* eh.S */ -struct proc; -void proc_do_uret(struct proc *); void sigsys(void); void sigtrap(void); void stepbpt(void); @@ -56,8 +41,4 @@ void m88110_stepbpt(void); void m88110_userbpt(void); void m88110_syscall_handler(void); -/* process.S */ -void savectx(struct pcb *); -void switch_exit(struct proc *); - #endif /* _MACHINE_LOCORE_H_ */ diff --git a/sys/arch/mvme88k/include/mvme188.h b/sys/arch/mvme88k/include/mvme188.h index f13da69f39f..90fa6ba7a97 100644 --- a/sys/arch/mvme88k/include/mvme188.h +++ b/sys/arch/mvme88k/include/mvme188.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mvme188.h,v 1.19 2004/08/02 08:35:00 miod Exp $ */ +/* $OpenBSD: mvme188.h,v 1.20 2004/10/01 19:00:51 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -363,15 +363,6 @@ #define VME_CMMU_D2 0xfff3f000 #define VME_CMMU_D3 0xfff7f000 -#ifndef _LOCORE - -extern unsigned int m188_curspl[MAX_CPUS]; -extern unsigned int int_mask_val[INT_LEVEL]; -extern unsigned int int_mask_shadow[MAX_CPUS]; -extern unsigned int *volatile int_mask_reg[MAX_CPUS]; - -#endif - #define M188_IACK 0xFFF85000 #define M188_IVEC 0x40 /* vector returned upon MVME188 int */ diff --git a/sys/arch/mvme88k/mvme88k/locore_c_routines.c b/sys/arch/mvme88k/mvme88k/locore_c_routines.c deleted file mode 100644 index ec52fab9bcf..00000000000 --- a/sys/arch/mvme88k/mvme88k/locore_c_routines.c +++ /dev/null @@ -1,328 +0,0 @@ -/* $OpenBSD: locore_c_routines.c,v 1.43 2004/09/30 21:48:57 miod Exp $ */ -/* - * 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 <machine/asm.h> /* END_OF_VECTOR_LIST, etc. */ -#include <machine/asm_macro.h> /* enable/disable interrupts */ -#include <machine/cpu_number.h> /* cpu_number() */ -#include <machine/locore.h> -#include <machine/prom.h> -#include <machine/trap.h> - -#ifdef MVME188 -#include <machine/mvme188.h> -#endif - -typedef struct { - unsigned word_one, word_two; -} m88k_exception_vector_area; - -extern unsigned int *volatile int_mask_reg[MAX_CPUS]; /* in machdep.c */ -extern unsigned master_cpu; /* in cmmu.c */ - -void setlevel(unsigned int); -void vector_init(m88k_exception_vector_area *, unsigned *); - -#define SIGSYS_MAX 501 -#define SIGTRAP_MAX 510 - -#define EMPTY_BR 0xc0000000 /* empty "br" instruction */ -#define NO_OP 0xf4005800 /* "or r0, r0, r0" */ - -#define BRANCH(FROM, TO) \ - (EMPTY_BR | ((unsigned)(TO) - (unsigned)(FROM)) >> 2) - -#define SET_VECTOR(NUM, VALUE) \ - do { \ - vector[NUM].word_one = NO_OP; \ - vector[NUM].word_two = BRANCH(&vector[NUM].word_two, VALUE); \ - } while (0) - -/* - * vector_init(vector, vector_init_list) - * - * This routine sets up the m88k vector table for the running processor. - * It is called with a very little stack, and interrupts disabled, - * so don't call any other functions! - * XXX clean this - nivas - */ -void -vector_init(m88k_exception_vector_area *vector, unsigned *vector_init_list) -{ - unsigned num; - unsigned vec; - extern void bugtrap(void); - extern void m88110_bugtrap(void); - - for (num = 0; (vec = vector_init_list[num]) != END_OF_VECTOR_LIST; - num++) { - if (vec != UNKNOWN_HANDLER) - SET_VECTOR(num, vec); - } - - /* Save BUG vector */ - bugvec[0] = vector[MVMEPROM_VECTOR].word_one; - bugvec[1] = vector[MVMEPROM_VECTOR].word_two; - -#ifdef M88110 - if (CPU_IS88110) { - for (; num <= SIGSYS_MAX; num++) - SET_VECTOR(num, m88110_sigsys); - - for (; num <= SIGTRAP_MAX; num++) - SET_VECTOR(num, m88110_sigtrap); - - SET_VECTOR(450, m88110_syscall_handler); - SET_VECTOR(MVMEPROM_VECTOR, m88110_bugtrap); - SET_VECTOR(504, m88110_stepbpt); - SET_VECTOR(511, m88110_userbpt); - } -#endif -#ifdef M88100 - if (CPU_IS88100) { - for (; num <= SIGSYS_MAX; num++) - SET_VECTOR(num, sigsys); - - for (; num <= SIGTRAP_MAX; num++) - SET_VECTOR(num, sigtrap); - - SET_VECTOR(450, syscall_handler); - SET_VECTOR(MVMEPROM_VECTOR, bugtrap); - SET_VECTOR(504, stepbpt); - SET_VECTOR(511, userbpt); - } -#endif - - /* GCC will by default produce explicit trap 503 for division by zero */ - SET_VECTOR(503, vector_init_list[T_ZERODIV]); - - /* Save new BUG vector */ - sysbugvec[0] = vector[MVMEPROM_VECTOR].word_one; - sysbugvec[1] = vector[MVMEPROM_VECTOR].word_two; -} - -#ifdef MVME188 -#if 0 -unsigned int int_mask_shadow[MAX_CPUS] = {0, 0, 0, 0}; -unsigned int blocked_interrupts_mask; -#endif -unsigned int m188_curspl[MAX_CPUS] = {0, 0, 0, 0}; - -unsigned int int_mask_val[INT_LEVEL] = { - MASK_LVL_0, - MASK_LVL_1, - MASK_LVL_2, - MASK_LVL_3, - MASK_LVL_4, - MASK_LVL_5, - MASK_LVL_6, - MASK_LVL_7 -}; - -/* - * return next safe spl to reenable interrupts. - */ -unsigned int -safe_level(mask, curlevel) - unsigned mask; - unsigned curlevel; -{ - int i; - - for (i = curlevel; i < 8; i++) - if (!(int_mask_val[i] & mask)) - return i; - - panic("safe_level: no safe level for mask 0x%08x level %d found", - mask, curlevel); - /* NOTREACHED */ -} - -void -setlevel(unsigned int level) -{ - unsigned int mask; - int cpu = cpu_number(); - - mask = int_mask_val[level]; - - if (cpu != master_cpu) - mask &= SLAVE_MASK; - -#if 0 - mask &= ISR_SOFTINT_EXCEPT_MASK(cpu); - mask &= ~blocked_interrupts_mask; -#endif - - *int_mask_reg[cpu] = mask; -#if 0 - int_mask_shadow[cpu] = mask; -#endif - m188_curspl[cpu] = level; -} - -#endif /* MVME188 */ - -unsigned -getipl(void) -{ - unsigned curspl; - m88k_psr_type psr; /* processor status register */ - - psr = disable_interrupts_return_psr(); - switch (brdtyp) { -#ifdef MVME188 - case BRD_188: - curspl = m188_curspl[cpu_number()]; - break; -#endif /* MVME188 */ -#if defined(MVME187) || defined(MVME197) - case BRD_187: - case BRD_8120: - case BRD_197: - curspl = *md.intr_mask & 0x07; - break; -#endif /* defined(MVME187) || defined(MVME197) */ - } - set_psr(psr); - return curspl; -} - -unsigned -setipl(unsigned level) -{ - unsigned curspl; - m88k_psr_type psr; /* processor status register */ - -#ifdef DEBUG - if (level > 7) { - printf("setipl: invoked with invalid level %x\n", level); - level &= 0x07; /* and pray it will work */ - } -#endif - - psr = disable_interrupts_return_psr(); - switch (brdtyp) { -#ifdef MVME188 - case BRD_188: - curspl = m188_curspl[cpu_number()]; - setlevel(level); - break; -#endif /* MVME188 */ -#if defined(MVME187) || defined(MVME197) - case BRD_187: - case BRD_8120: - case BRD_197: - curspl = *md.intr_mask & 0x07; - *md.intr_mask = level; - break; -#endif /* defined(MVME187) || defined(MVME197) */ - } - - flush_pipeline(); - - /* The flush pipeline is required to make sure the above write gets - * through the data pipe and to the hardware; otherwise, the next - * bunch of instructions could execute at the wrong spl protection - */ - set_psr(psr); - return curspl; -} - -unsigned -raiseipl(unsigned level) -{ - unsigned curspl; - m88k_psr_type psr; /* processor status register */ - -#ifdef DEBUG - if (level > 7) { - printf("raiseipl: invoked with invalid level %x\n", level); - level &= 0x07; /* and pray it will work */ - } -#endif - - psr = disable_interrupts_return_psr(); - switch (brdtyp) { -#ifdef MVME188 - case BRD_188: - curspl = m188_curspl[cpu_number()]; - if (curspl < level) - setlevel(level); - break; -#endif /* MVME188 */ -#if defined(MVME187) || defined(MVME197) - case BRD_187: - case BRD_8120: - case BRD_197: - curspl = *md.intr_mask & 0x07; - if (curspl < level) - *md.intr_mask = level; - break; -#endif /* defined(MVME187) || defined(MVME197) */ - } - - flush_pipeline(); - - /* The flush pipeline is required to make sure the above write gets - * through the data pipe and to the hardware; otherwise, the next - * bunch of instructions could execute at the wrong spl protection - */ - set_psr(psr); - return curspl; -} - -/* XXX Utterly bogus */ -#if NCPUS > 1 -#include <sys/simplelock.h> -void -simple_lock_init(lkp) - struct simplelock *volatile lkp; -{ - lkp->lock_data = 0; -} - -int -test_and_set(lock) - int *volatile lock; -{ -#if 0 - int oldlock = *lock; - if (*lock == 0) { - *lock = 1; - return 0; - } -#else - return *lock; - *lock = 1; - return 0; -#endif -} -#endif diff --git a/sys/arch/mvme88k/mvme88k/m187_machdep.c b/sys/arch/mvme88k/mvme88k/m187_machdep.c new file mode 100644 index 00000000000..940ba21ee2f --- /dev/null +++ b/sys/arch/mvme88k/mvme88k/m187_machdep.c @@ -0,0 +1,267 @@ +/* $OpenBSD: m187_machdep.c,v 1.1 2004/10/01 19:00:52 miod Exp $ */ +/* + * Copyright (c) 1998, 1999, 2000, 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. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/errno.h> + +#include <machine/asm_macro.h> +#include <machine/cmmu.h> +#include <machine/cpu.h> +#include <machine/locore.h> +#include <machine/reg.h> +#include <machine/trap.h> +#include <machine/m88100.h> +#include <machine/mvme187.h> + +#include <uvm/uvm_extern.h> + +#include <mvme88k/dev/memcreg.h> + +void m187_bootstrap(void); +void m187_ext_int(u_int, struct trapframe *); +vaddr_t m187_memsize(void); +void m187_setupiackvectors(void); +void m187_startup(void); + +vaddr_t obiova; +vaddr_t bugromva; +vaddr_t sramva; + +/* + * Figure out how much memory is available, by querying the memory controllers. + */ +vaddr_t +m187_memsize() +{ + struct memcreg *memc; + vaddr_t x; + + memc = (struct memcreg *)MEM_CTLR; + x = MEMC_MEMCONF_RTOB(memc->memc_memconf); + + memc = (struct memcreg *)(MEM_CTLR + 0x100); + if (!badaddr((vaddr_t)&memc->memc_memconf, 1)) + x += MEMC_MEMCONF_RTOB(memc->memc_memconf); + + return x; +} + +void +m187_startup() +{ + /* + * Grab the SRAM space that we hardwired in pmap_bootstrap + */ + sramva = SRAM_START; + uvm_map(kernel_map, (vaddr_t *)&sramva, SRAM_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (sramva != SRAM_START) + panic("sramva %lx: SRAM not free", sramva); + + /* + * Grab the BUGROM space that we hardwired in pmap_bootstrap + */ + bugromva = BUG187_START; + uvm_map(kernel_map, (vaddr_t *)&bugromva, BUG187_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (bugromva != BUG187_START) + panic("bugromva %lx: BUGROM not free", bugromva); + + /* + * Grab the OBIO space that we hardwired in pmap_bootstrap + */ + obiova = OBIO_START; + uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (obiova != OBIO_START) + panic("obiova %lx: OBIO not free", obiova); +} + +void +m187_setupiackvectors() +{ + u_int8_t *vaddr = (u_int8_t *)M187_IACK; + + ivec[0] = vaddr + 0x03; /* We dont use level 0 */ + ivec[1] = vaddr + 0x07; + ivec[2] = vaddr + 0x0b; + ivec[3] = vaddr + 0x0f; + ivec[4] = vaddr + 0x13; + ivec[5] = vaddr + 0x17; + ivec[6] = vaddr + 0x1b; + ivec[7] = vaddr + 0x1f; +} + +/* + * Device interrupt handler for MVME187 + */ + +void +m187_ext_int(u_int v, struct trapframe *eframe) +{ + int mask, level; + struct intrhand *intr; + intrhand_t *list; + int ret; + u_char vec; + + /* get level and mask */ + mask = *md.intr_mask & 0x07; + level = *md.intr_ipl & 0x07; + +#ifdef DIAGNOSTIC + /* + * It is really bizarre for the mask and level to the be the same. + * pcc2 for 187 blocks all interrupts at and below the mask value, + * so we should not be getting an interrupt at the level that is + * already blocked. I can't explain this case XXX nivas + */ + + if ((mask == level) && level) { + panic("mask == level, %d", level); + } + + /* + * Interrupting level cannot be 0--0 doesn't produce an interrupt. + * Weird! XXX nivas + */ + + if (level == 0) { + panic("Bogons... level %x and mask %x", level, mask); + } +#endif + + uvmexp.intrs++; + + /* generate IACK and get the vector */ + flush_pipeline(); + if (guarded_access(ivec[level], 1, &vec) == EFAULT) { + panic("Unable to get vector for this interrupt (level %x)", level); + } + flush_pipeline(); + flush_pipeline(); + flush_pipeline(); + + /* block interrupts at level or lower */ + setipl(level); + + enable_interrupt(); + + list = &intr_handlers[vec]; + if (SLIST_EMPTY(list)) { + /* increment intr counter */ + intrcnt[M88K_SPUR_IRQ]++; + printf("Spurious interrupt (level %x and vec %x)\n", + level, vec); + } else { +#ifdef DIAGNOSTIC + intr = SLIST_FIRST(list); + if (intr->ih_ipl != level) { + panic("Handler ipl %x not the same as level %x. " + "vec = 0x%x", + intr->ih_ipl, level, vec); + } +#endif + + /* + * Walk through all interrupt handlers in the chain for the + * given vector, calling each handler in turn, till some handler + * returns a value != 0. + */ + + ret = 0; + SLIST_FOREACH(intr, list, ih_link) { + if (intr->ih_wantframe != 0) + ret = (*intr->ih_fn)((void *)eframe); + else + ret = (*intr->ih_fn)(intr->ih_arg); + if (ret != 0) { + intrcnt[level]++; + intr->ih_count.ec_count++; + break; + } + } + + if (ret == 0) { + printf("Unclaimed interrupt (level %x and vec %x)\n", + level, vec); + } + } + + /* + * process any remaining data access exceptions before + * returning to assembler + */ + disable_interrupt(); + if (eframe->tf_dmt0 & DMT_VALID) + m88100_trap(T_DATAFLT, eframe); + + /* + * Restore the mask level to what it was when the interrupt + * was taken. + */ + setipl(mask); +} + +void +m187_bootstrap() +{ + extern struct cmmu_p cmmu8820x; + + cmmu = &cmmu8820x; + md.interrupt_func = &m187_ext_int; + md.intr_mask = (u_char *)M187_IMASK; + md.intr_ipl = (u_char *)M187_ILEVEL; + md.intr_src = NULL; +} diff --git a/sys/arch/mvme88k/mvme88k/m188_machdep.c b/sys/arch/mvme88k/mvme88k/m188_machdep.c new file mode 100644 index 00000000000..15a4643a905 --- /dev/null +++ b/sys/arch/mvme88k/mvme88k/m188_machdep.c @@ -0,0 +1,422 @@ +/* $OpenBSD: m188_machdep.c,v 1.1 2004/10/01 19:00:52 miod Exp $ */ +/* + * Copyright (c) 1998, 1999, 2000, 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. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/errno.h> + +#include <machine/asm_macro.h> +#include <machine/cmmu.h> +#include <machine/cpu.h> +#include <machine/cpu_number.h> +#include <machine/locore.h> +#include <machine/reg.h> +#include <machine/trap.h> + +#include <machine/m88100.h> +#include <machine/mvme188.h> + +#include <uvm/uvm_extern.h> + +#include <mvme88k/dev/sysconreg.h> + +void m188_reset(void); +u_int safe_level(u_int mask, u_int curlevel); +void setlevel(unsigned int); + +void m188_bootstrap(void); +void m188_ext_int(u_int, struct trapframe *); +vaddr_t m188_memsize(void); +void m188_setupiackvectors(void); +void m188_startup(void); + +/* + * *int_mask_reg[CPU] + * Points to the hardware interrupt status register for each CPU. + */ +unsigned int *volatile int_mask_reg[MAX_CPUS] = { + (unsigned int *)IEN0_REG, + (unsigned int *)IEN1_REG, + (unsigned int *)IEN2_REG, + (unsigned int *)IEN3_REG +}; + +unsigned int m188_curspl[MAX_CPUS] = {0, 0, 0, 0}; + +unsigned int int_mask_val[INT_LEVEL] = { + MASK_LVL_0, + MASK_LVL_1, + MASK_LVL_2, + MASK_LVL_3, + MASK_LVL_4, + MASK_LVL_5, + MASK_LVL_6, + MASK_LVL_7 +}; + +vaddr_t utilva; + +/* + * Figure out how much memory is available, by querying the MBus registers. + * + * For every 4MB segment, ask the MBus address decoder which device claimed + * the range. Since memory is packed at low addresses, we will hit all memory + * boards in order until reaching either a VME space or a non-claimed space. + * + * As a safety measure, we never check for more than 256MB - the 188 can + * only have up to 4 memory boards, which theoretically can not be larger + * than 64MB, and I am not aware of third-party larger memory boards. + */ +vaddr_t +m188_memsize() +{ + unsigned int pgnum; + int32_t rmad; + +#define MVME188_MAX_MEMORY ((4 * 64) / 4) /* 4 64MB boards */ + for (pgnum = 0; pgnum < MVME188_MAX_MEMORY; pgnum++) { + *(volatile int32_t *)RMAD_REG = (pgnum << 22); + rmad = *(volatile int32_t *)RMAD_REG; + + if (rmad & 0x04) /* not a memory board */ + break; + } + + return (pgnum << 22); +} + +void +m188_startup() +{ + /* + * Grab the UTIL space that we hardwired in pmap_bootstrap(). + */ + utilva = MVME188_UTILITY; + uvm_map(kernel_map, (vaddr_t *)&utilva, MVME188_UTILITY_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (utilva != MVME188_UTILITY) + panic("utilva %lx: UTILITY area not free", utilva); +} + +void +m188_bootstrap() +{ + extern struct cmmu_p cmmu8820x; + + cmmu = &cmmu8820x; + md.interrupt_func = &m188_ext_int; + md.intr_mask = NULL; + md.intr_ipl = NULL; + md.intr_src = NULL; + + /* clear and disable all interrupts */ + *int_mask_reg[0] = 0; + *int_mask_reg[1] = 0; + *int_mask_reg[2] = 0; + *int_mask_reg[3] = 0; +} + +void +m188_reset() +{ + volatile int cnt; + + *(volatile u_int32_t *)IEN0_REG = 0; + *(volatile u_int32_t *)IEN1_REG = 0; + *(volatile u_int32_t *)IEN2_REG = 0; + *(volatile u_int32_t *)IEN3_REG = 0; + + if ((*(volatile u_int8_t *)GLB1) & M188_SYSCON) { + /* Force a complete VMEbus reset */ + *(volatile u_int32_t *)GLBRES_REG = 1; + } else { + /* Force only a local reset */ + *(volatile u_int8_t *)GLB1 |= M188_LRST; + } + + *(volatile u_int32_t *)UCSR_REG |= 0x2000; /* clear SYSFAIL */ + for (cnt = 0; cnt < 5*1024*1024; cnt++) + ; + *(volatile u_int32_t *)UCSR_REG |= 0x2000; /* clear SYSFAIL */ + + printf("reset failed\n"); +} + +/* + * fill up ivec array with interrupt response vector addresses. + */ +void +m188_setupiackvectors() +{ + u_int8_t *vaddr = (u_int8_t *)M188_IACK; + + ivec[0] = vaddr; /* We dont use level 0 */ + ivec[1] = vaddr + 0x04; + ivec[2] = vaddr + 0x08; + ivec[3] = vaddr + 0x0c; + ivec[4] = vaddr + 0x10; + ivec[5] = vaddr + 0x14; + ivec[6] = vaddr + 0x18; + ivec[7] = vaddr + 0x1c; + ivec[8] = vaddr + 0x20; /* for self inflicted interrupts */ + *ivec[8] = M188_IVEC; /* supply a vector base for m188ih */ +} + +/* + * return next safe spl to reenable interrupts. + */ +u_int +safe_level(u_int mask, u_int curlevel) +{ + int i; + + for (i = curlevel; i < 8; i++) + if (!(int_mask_val[i] & mask)) + return i; + + panic("safe_level: no safe level for mask 0x%08x level %d found", + mask, curlevel); + /* NOTREACHED */ +} + +void +setlevel(unsigned int level) +{ + unsigned int mask; + int cpu = cpu_number(); + + mask = int_mask_val[level]; + + if (cpu != master_cpu) + mask &= SLAVE_MASK; + + *int_mask_reg[cpu] = mask; + m188_curspl[cpu] = level; +} + +/* + * Device interrupt handler for MVME188 + */ + +/* Hard coded vector table for onboard devices. */ +const unsigned int obio_vec[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, SYSCV_SCC, 0, 0, SYSCV_SYSF, SYSCV_TIMER2, 0, 0, + 0, 0, 0, 0, SYSCV_TIMER1, 0, SYSCV_ACF, SYSCV_ABRT +}; + +#define GET_MASK(cpu, val) *int_mask_reg[cpu] & (val) +#define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */ +#define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */ + +void +m188_ext_int(u_int v, struct trapframe *eframe) +{ + int cpu = cpu_number(); + unsigned int cur_mask; + unsigned int level, old_spl; + struct intrhand *intr; + intrhand_t *list; + int ret, intbit; + unsigned vec; + + cur_mask = ISR_GET_CURRENT_MASK(cpu); + old_spl = m188_curspl[cpu]; + eframe->tf_mask = old_spl; + + if (cur_mask == 0) { + /* + * Spurious interrupts - may be caused by debug output clearing + * DUART interrupts. + */ + flush_pipeline(); + goto out; + } + + uvmexp.intrs++; + + /* + * We want to service all interrupts marked in the IST register + * They are all valid because the mask would have prevented them + * from being generated otherwise. We will service them in order of + * priority. + */ + do { + level = safe_level(cur_mask, old_spl); + + if (old_spl >= level) { + int i; + + printf("safe level %d <= old level %d\n", level, old_spl); + printf("cur_mask = 0x%b\n", cur_mask, IST_STRING); + for (i = 0; i < 4; i++) + printf("IEN%d = 0x%b ", i, *int_mask_reg[i], IST_STRING); + printf("\nCPU0 spl %d CPU1 spl %d CPU2 spl %d CPU3 spl %d\n", + m188_curspl[0], m188_curspl[1], + m188_curspl[2], m188_curspl[3]); + for (i = 0; i < 8; i++) + printf("int_mask[%d] = 0x%08x\n", i, int_mask_val[i]); + printf("--CPU %d halted--\n", cpu_number()); + spl7(); + for(;;) ; + } + +#ifdef DEBUG + if (level > 7 || (int)level < 0) { + panic("int level (%x) is not between 0 and 7", level); + } +#endif + + setipl(level); + + /* + * Do not enable interrupts yet if we know, from cur_mask, + * that we have not cleared enough conditions yet. + * For now, only the timer interrupt requires its condition + * to be cleared before interrupts are enabled. + */ + if ((cur_mask & DTI_BIT) == 0) { + enable_interrupt(); + } + + /* generate IACK and get the vector */ + + /* + * This is tricky. If you don't catch all the + * interrupts, you die. Game over. Insert coin... + * XXX smurph + */ + + /* find the first bit set in the current mask */ + intbit = ff1(cur_mask); + if (OBIO_INTERRUPT_MASK & (1 << intbit)) { + vec = SYSCON_VECT + obio_vec[intbit]; + if (vec == 0) { + panic("unknown onboard interrupt: mask = 0x%b", + 1 << intbit, IST_STRING); + } + } else if (HW_FAILURE_MASK & (1 << intbit)) { + vec = SYSCON_VECT + obio_vec[intbit]; + if (vec == 0) { + panic("unknown hardware failure: mask = 0x%b", + 1 << intbit, IST_STRING); + } + } else if (VME_INTERRUPT_MASK & (1 << intbit)) { + if (guarded_access(ivec[level], 4, (u_char *)&vec) == + EFAULT) { + panic("unable to get vector for this vmebus " + "interrupt (level %x)", level); + } + vec &= VME_VECTOR_MASK; + if (vec & VME_BERR_MASK) { + printf("VME vec timeout, vec = %x, mask = 0x%b\n", + vec, 1 << intbit, IST_STRING); + break; + } + if (vec == 0) { + panic("unknown vme interrupt: mask = 0x%b", + 1 << intbit, IST_STRING); + } + } else { + panic("unknown interrupt: level = %d intbit = 0x%x " + "mask = 0x%b", + level, intbit, 1 << intbit, IST_STRING); + } + + list = &intr_handlers[vec]; + if (SLIST_EMPTY(list)) { + /* increment intr counter */ + intrcnt[M88K_SPUR_IRQ]++; + printf("Spurious interrupt: level = %d vec = 0x%x, " + "intbit = %d mask = 0x%b\n", + level, vec, intbit, 1 << intbit, IST_STRING); + } else { + /* + * Walk through all interrupt handlers in the chain + * for the given vector, calling each handler in turn, + * till some handler returns a value != 0. + */ + ret = 0; + SLIST_FOREACH(intr, list, ih_link) { + if (intr->ih_wantframe != 0) + ret = (*intr->ih_fn)((void *)eframe); + else + ret = (*intr->ih_fn)(intr->ih_arg); + if (ret != 0) { + intrcnt[level]++; + intr->ih_count.ec_count++; + break; + } + } + if (ret == 0) { + printf("Unclaimed interrupt: level = %d " + "vec = 0x%x, intbit = %d mask = 0x%b\n", + level, vec, intbit, + 1 << intbit, IST_STRING); + break; + } + } + } while ((cur_mask = ISR_GET_CURRENT_MASK(cpu)) != 0); + + /* + * process any remaining data access exceptions before + * returning to assembler + */ + disable_interrupt(); +out: + if (eframe->tf_dmt0 & DMT_VALID) + m88100_trap(T_DATAFLT, eframe); + + /* + * Restore the mask level to what it was when the interrupt + * was taken. + */ + setipl(eframe->tf_mask); +} diff --git a/sys/arch/mvme88k/mvme88k/m197_machdep.c b/sys/arch/mvme88k/mvme88k/m197_machdep.c new file mode 100644 index 00000000000..223a7301943 --- /dev/null +++ b/sys/arch/mvme88k/mvme88k/m197_machdep.c @@ -0,0 +1,283 @@ +/* $OpenBSD: m197_machdep.c,v 1.1 2004/10/01 19:00:52 miod Exp $ */ +/* + * Copyright (c) 1998, 1999, 2000, 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. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/errno.h> + +#include <machine/asm_macro.h> +#include <machine/cmmu.h> +#include <machine/cpu.h> +#include <machine/locore.h> +#include <machine/reg.h> +#include <machine/trap.h> +#include <machine/mvme197.h> + +#include <uvm/uvm_extern.h> + +#include <mvme88k/dev/busswreg.h> + +void m197_bootstrap(void); +void m197_ext_int(u_int, struct trapframe *); +vaddr_t m197_memsize(void); +void m197_setupiackvectors(void); +void m197_startup(void); + +vaddr_t obiova; +vaddr_t flashva; + +/* + * Figure out how much real memory is available. + * Start looking from the megabyte after the end of the kernel data, + * until we find non-memory. + */ +vaddr_t +m197_memsize() +{ + unsigned int *volatile look; + unsigned int *max; + extern char *end; +#define PATTERN 0x5a5a5a5a +#define STRIDE (4*1024) /* 4k at a time */ +#define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1)) + /* + * count it up. + */ +#define MAXPHYSMEM 0x30000000 /* 768MB */ + max = (void *)MAXPHYSMEM; + for (look = (void *)Roundup(end, STRIDE); look < max; + look = (int *)((unsigned)look + STRIDE)) { + unsigned save; + + /* if can't access, we've reached the end */ + if (badwordaddr((vaddr_t)look)) { +#if defined(DEBUG) + printf("%x\n", look); +#endif + look = (int *)((int)look - STRIDE); + break; + } + + /* + * If we write a value, we expect to read the same value back. + * We'll do this twice, the 2nd time with the opposite bit + * pattern from the first, to make sure we check all bits. + */ + save = *look; + if (*look = PATTERN, *look != PATTERN) + break; + if (*look = ~PATTERN, *look != ~PATTERN) + break; + *look = save; + } + + return (trunc_page((unsigned)look)); +} + +void +m197_startup() +{ + /* + * Grab the FLASH space that we hardwired in pmap_bootstrap + */ + flashva = FLASH_START; + uvm_map(kernel_map, (vaddr_t *)&flashva, FLASH_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (flashva != FLASH_START) + panic("flashva %lx: FLASH not free", flashva); + + /* + * Grab the OBIO space that we hardwired in pmap_bootstrap + */ + obiova = OBIO_START; + uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)); + if (obiova != OBIO_START) + panic("obiova %lx: OBIO not free", obiova); +} + +void +m197_setupiackvectors() +{ + u_int8_t *vaddr = (u_int8_t *)M197_IACK; + + ivec[0] = vaddr + 0x03; /* We dont use level 0 */ + ivec[1] = vaddr + 0x07; + ivec[2] = vaddr + 0x0b; + ivec[3] = vaddr + 0x0f; + ivec[4] = vaddr + 0x13; + ivec[5] = vaddr + 0x17; + ivec[6] = vaddr + 0x1b; + ivec[7] = vaddr + 0x1f; +} + +/* + * Device interrupt handler for MVME197 + */ + +void +m197_ext_int(u_int v, struct trapframe *eframe) +{ + int mask, level, src; + struct intrhand *intr; + intrhand_t *list; + int ret; + u_char vec; + + /* get src and mask */ + mask = *md.intr_mask & 0x07; + src = *md.intr_src; + + if (v == T_NON_MASK) { + /* This is the abort switch */ + level = IPL_NMI; + vec = BS_ABORTVEC; + } else { + /* get level */ + level = *md.intr_ipl & 0x07; + } + +#ifdef DIAGNOSTIC + /* + * Interrupting level cannot be 0--0 doesn't produce an interrupt. + * Weird! XXX nivas + */ + + if (level == 0) { + panic("Bogons... level %x and mask %x", level, mask); + } +#endif + + uvmexp.intrs++; + + if (v != T_NON_MASK) { + /* generate IACK and get the vector */ + flush_pipeline(); + if (guarded_access(ivec[level], 1, &vec) == EFAULT) { + panic("Unable to get vector for this interrupt (level %x)", level); + } + flush_pipeline(); + flush_pipeline(); + flush_pipeline(); + } + + if (v != T_NON_MASK || cold == 0) { + /* block interrupts at level or lower */ + setipl(level); + + enable_interrupt(); + } + + list = &intr_handlers[vec]; + if (SLIST_EMPTY(list)) { + /* increment intr counter */ + intrcnt[M88K_SPUR_IRQ]++; + printf("Spurious interrupt (level %x and vec %x)\n", + level, vec); + } else { +#ifdef DIAGNOSTIC + intr = SLIST_FIRST(list); + if (intr->ih_ipl != level) { + panic("Handler ipl %x not the same as level %x. " + "vec = 0x%x", + intr->ih_ipl, level, vec); + } +#endif + + /* + * Walk through all interrupt handlers in the chain for the + * given vector, calling each handler in turn, till some handler + * returns a value != 0. + */ + + ret = 0; + SLIST_FOREACH(intr, list, ih_link) { + if (intr->ih_wantframe != 0) + ret = (*intr->ih_fn)((void *)eframe); + else + ret = (*intr->ih_fn)(intr->ih_arg); + if (ret != 0) { + intrcnt[level]++; + intr->ih_count.ec_count++; + break; + } + } + + if (ret == 0) { + printf("Unclaimed interrupt (level %x and vec %x)\n", + level, vec); + } + } + + if (v != T_NON_MASK || cold == 0) { + disable_interrupt(); + + /* + * Restore the mask level to what it was when the interrupt + * was taken. + */ + setipl(mask); + } +} + +void +m197_bootstrap() +{ + extern struct cmmu_p cmmu88110; + extern void set_tcfp(void); + + cmmu = &cmmu88110; + md.interrupt_func = &m197_ext_int; + md.intr_mask = (u_char *)M197_IMASK; + md.intr_ipl = (u_char *)M197_ILEVEL; + md.intr_src = (u_char *)M197_ISRC; + set_tcfp(); /* Set Time Critical Floating Point Mode */ +} diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index c156f57099e..8739ff7b87c 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.158 2004/10/01 05:49:01 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.159 2004/10/01 19:00:52 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -68,7 +68,8 @@ #include <net/netisr.h> -#include <machine/asm_macro.h> /* enable/disable interrupts */ +#include <machine/asm.h> +#include <machine/asm_macro.h> #include <machine/bug.h> #include <machine/bugio.h> #include <machine/cmmu.h> @@ -78,30 +79,11 @@ #include <machine/locore.h> #include <machine/reg.h> #include <machine/trap.h> -#ifdef M88100 -#include <machine/m88100.h> /* DMT_VALID */ -#endif -#ifdef MVME187 -#include <machine/mvme187.h> -#endif -#ifdef MVME197 -#include <machine/mvme197.h> -#endif -#ifdef MVME188 -#include <machine/mvme188.h> -#endif #include <dev/cons.h> #include <uvm/uvm_extern.h> -#ifdef MVME188 -#include <mvme88k/dev/sysconreg.h> -#endif -#ifdef MVME197 -#include <mvme88k/dev/busswreg.h> -#endif - #include "ksyms.h" #if DDB #include <machine/db_machdep.h> @@ -109,66 +91,58 @@ #include <ddb/db_interface.h> #endif /* DDB */ +typedef struct { + unsigned word_one, word_two; +} m88k_exception_vector_area; + +caddr_t allocsys(caddr_t); +void bugsyscall(void); +void consinit(void); +void dosoftint(void); +void dumpconf(void); +void dumpsys(void); +int getcpuspeed(struct mvmeprom_brdid *); +vaddr_t get_slave_stack(void); +void identifycpu(void); +void mvme_bootstrap(void); +void savectx(struct pcb *); +void setupiackvectors(void); +void slave_pre_main(void); +int slave_main(void); +void vector_init(m88k_exception_vector_area *, unsigned *); +void _doboot(void); + +#ifdef MVME188 +extern unsigned int m188_curspl[]; /* XXX temporary */ +#endif + +extern void load_u_area(struct proc *); +extern void save_u_area(struct proc *, vaddr_t); +extern void setlevel(unsigned int); + +extern void m187_bootstrap(void); +extern void m187_ext_int(u_int, struct trapframe *); +extern vaddr_t m187_memsize(void); +extern void m187_setupiackvectors(void); +extern void m187_startup(void); +extern void m188_bootstrap(void); +extern void m188_ext_int(u_int, struct trapframe *); +extern vaddr_t m188_memsize(void); +extern void m188_setupiackvectors(void); +extern void m188_startup(void); +extern void m197_bootstrap(void); +extern void m197_ext_int(u_int, struct trapframe *); +extern vaddr_t m197_memsize(void); +extern void m197_setupiackvectors(void); +extern void m197_startup(void); + intrhand_t intr_handlers[NVMEINTR]; vaddr_t interrupt_stack[MAX_CPUS]; /* machine dependent function pointers. */ struct md_p md; -/* prototypes */ -void setupiackvectors(void); -void dumpsys(void); -void consinit(void); -vaddr_t size_memory(void); -vaddr_t memsize187(void); -vaddr_t memsize188(void); -int getcpuspeed(struct mvmeprom_brdid *); -void identifycpu(void); -void save_u_area(struct proc *, vaddr_t); -void load_u_area(struct proc *); -void dumpconf(void); -void m187_ext_int(u_int v, struct trapframe *eframe); -void m188_ext_int(u_int v, struct trapframe *eframe); -void m197_ext_int(u_int v, struct trapframe *eframe); - -unsigned char *volatile ivec[] = { - (unsigned char *)0xFFFE0003, /* not used, no such thing as int 0 */ - (unsigned char *)0xFFFE0007, - (unsigned char *)0xFFFE000B, - (unsigned char *)0xFFFE000F, - (unsigned char *)0xFFFE0013, - (unsigned char *)0xFFFE0017, - (unsigned char *)0xFFFE001B, - (unsigned char *)0xFFFE001F, - (unsigned char *)0x00000000, -}; - -#ifdef MVME188 -/* - * *int_mask_reg[CPU] - * Points to the hardware interrupt status register for each CPU. - */ -unsigned int *volatile int_mask_reg[MAX_CPUS] = { - (unsigned int *)IEN0_REG, - (unsigned int *)IEN1_REG, - (unsigned int *)IEN2_REG, - (unsigned int *)IEN3_REG -}; -#endif - -#if defined(MVME187) || defined(MVME197) -volatile vaddr_t obiova; -#ifdef MVME187 -volatile vaddr_t bugromva; -volatile vaddr_t sramva; -#endif -#ifdef MVME197 -volatile vaddr_t flashva; -#endif -#endif -#ifdef MVME188 -volatile vaddr_t utilva; -#endif +volatile u_int8_t *ivec[8]; int ssir; int want_ast; @@ -195,9 +169,9 @@ struct vm_map *iomap_map; * Declare these as initialized data so we can patch them. */ #ifdef NBUF -int nbuf = NBUF; +int nbuf = NBUF; #else -int nbuf = 0; +int nbuf = 0; #endif #ifndef BUFCACHEPERCENT @@ -205,13 +179,11 @@ int nbuf = 0; #endif #ifdef BUFPAGES -int bufpages = BUFPAGES; +int bufpages = BUFPAGES; #else -int bufpages = 0; +int bufpages = 0; #endif -int bufcachepercent = BUFCACHEPERCENT; - -caddr_t allocsys(caddr_t); +int bufcachepercent = BUFCACHEPERCENT; /* * Info for CTL_HW @@ -255,7 +227,7 @@ struct consdev bootcons = { bootcnputc, bootcnpollc, NULL, - makedev(14,0), + makedev(14, 0), 1 }; @@ -267,7 +239,6 @@ struct consdev bootcons = { void consinit() { - cn_tab = &bootcons; #if defined(DDB) @@ -278,109 +249,6 @@ consinit() #endif } -#ifdef MVME187 -/* - * Figure out how much memory is available, by querying the memory controllers. - */ -#include <mvme88k/dev/memcreg.h> -vaddr_t -memsize187() -{ - struct memcreg *memc; - vaddr_t x; - - memc = (struct memcreg *)MEM_CTLR; - x = MEMC_MEMCONF_RTOB(memc->memc_memconf); - - memc = (struct memcreg *)(MEM_CTLR + 0x100); - if (!badaddr((vaddr_t)&memc->memc_memconf, 1)) - x += MEMC_MEMCONF_RTOB(memc->memc_memconf); - - return x; -} -#endif - -#ifdef MVME188 -/* - * Figure out how much memory is available, by querying the MBus registers. - * - * For every 4MB segment, ask the MBus address decoder which device claimed - * the range. Since memory is packed at low addresses, we will hit all memory - * boards in order until reaching either a VME space or a non-claimed space. - * - * As a safety measure, we never check for more than 256MB - the 188 can - * only have up to 4 memory boards, which theoretically can not be larger - * than 64MB, and I am not aware of third-party larger memory boards. - */ -vaddr_t -memsize188() -{ - unsigned int pgnum; - int32_t rmad; - -#define MVME188_MAX_MEMORY ((4 * 64) / 4) /* 4 64MB boards */ - for (pgnum = 0; pgnum < MVME188_MAX_MEMORY; pgnum++) { - *(volatile int32_t *)RMAD_REG = (pgnum << 22); - rmad = *(volatile int32_t *)RMAD_REG; - - if (rmad & 0x04) /* not a memory board */ - break; - } - - return (pgnum << 22); -} -#endif - -#ifdef MVME197 -/* - * Figure out how much real memory is available. - * Start looking from the megabyte after the end of the kernel data, - * until we find non-memory. - */ -vaddr_t -size_memory() -{ - unsigned int *volatile look; - unsigned int *max; - extern char *end; -#define PATTERN 0x5a5a5a5a -#define STRIDE (4*1024) /* 4k at a time */ -#define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1)) - /* - * count it up. - */ -#define MAXPHYSMEM 0x30000000 /* 768MB */ - max = (void *)MAXPHYSMEM; - for (look = (void *)Roundup(end, STRIDE); look < max; - look = (int *)((unsigned)look + STRIDE)) { - unsigned save; - - /* if can't access, we've reached the end */ - if (badwordaddr((vaddr_t)look)) { -#if defined(DEBUG) - printf("%x\n", look); -#endif - look = (int *)((int)look - STRIDE); - break; - } - - /* - * If we write a value, we expect to read the same value back. - * We'll do this twice, the 2nd time with the opposite bit - * pattern from the first, to make sure we check all bits. - */ - save = *look; - if (*look = PATTERN, *look != PATTERN) - break; - if (*look = ~PATTERN, *look != ~PATTERN) - break; - *look = save; - } - - return (trunc_page((unsigned)look)); -} -#endif - int getcpuspeed(struct mvmeprom_brdid *brdid) { @@ -507,8 +375,8 @@ cpu_startup() * avail_end was pre-decremented in mvme_bootstrap() to compensate. */ for (i = 0; i < btoc(MSGBUFSIZE); i++) - pmap_kenter_pa((paddr_t)msgbufp + i * NBPG, - avail_end + i * NBPG, VM_PROT_READ | VM_PROT_WRITE); + pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE, + avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE); pmap_update(pmap_kernel()); initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE)); @@ -548,77 +416,17 @@ cpu_startup() #ifdef MVME187 case BRD_187: case BRD_8120: - /* - * Grab the SRAM space that we hardwired in pmap_bootstrap - */ - sramva = SRAM_START; - uvm_map(kernel_map, (vaddr_t *)&sramva, SRAM_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (sramva != SRAM_START) - panic("sramva %lx: SRAM not free", sramva); - - /* - * Grab the BUGROM space that we hardwired in pmap_bootstrap - */ - bugromva = BUG187_START; - uvm_map(kernel_map, (vaddr_t *)&bugromva, BUG187_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (bugromva != BUG187_START) - panic("bugromva %lx: BUGROM not free", bugromva); - - /* - * Grab the OBIO space that we hardwired in pmap_bootstrap - */ - obiova = OBIO_START; - uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (obiova != OBIO_START) - panic("obiova %lx: OBIO not free", obiova); - break; -#endif -#ifdef MVME197 - case BRD_197: - /* - * Grab the FLASH space that we hardwired in pmap_bootstrap - */ - flashva = FLASH_START; - uvm_map(kernel_map, (vaddr_t *)&flashva, FLASH_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (flashva != FLASH_START) - panic("flashva %lx: FLASH not free", flashva); - - /* - * Grab the OBIO space that we hardwired in pmap_bootstrap - */ - obiova = OBIO_START; - uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (obiova != OBIO_START) - panic("obiova %lx: OBIO not free", obiova); + m187_startup(); break; #endif #ifdef MVME188 case BRD_188: - /* - * Grab the UTIL space that we hardwired in pmap_bootstrap - */ - utilva = MVME188_UTILITY; - uvm_map(kernel_map, (vaddr_t *)&utilva, MVME188_UTILITY_SIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_NORMAL, 0)); - if (utilva != MVME188_UTILITY) - panic("utilva %lx: UTILITY area not free", utilva); + m188_startup(); + break; +#endif +#ifdef MVME197 + case BRD_197: + m197_startup(); break; #endif } @@ -838,34 +646,6 @@ haltsys: /*NOTREACHED*/ } -#ifdef MVME188 -void -m188_reset() -{ - volatile int cnt; - - *(volatile u_int32_t *)IEN0_REG = 0; - *(volatile u_int32_t *)IEN1_REG = 0; - *(volatile u_int32_t *)IEN2_REG = 0; - *(volatile u_int32_t *)IEN3_REG = 0; - - if ((*(volatile u_int8_t *)GLB1) & M188_SYSCON) { - /* Force a complete VMEbus reset */ - *(volatile u_int32_t *)GLBRES_REG = 1; - } else { - /* Force only a local reset */ - *(volatile u_int8_t *)GLB1 |= M188_LRST; - } - - *(volatile u_int32_t *)UCSR_REG |= 0x2000; /* clear SYSFAIL */ - for (cnt = 0; cnt < 5*1024*1024; cnt++) - ; - *(volatile u_int32_t *)UCSR_REG |= 0x2000; /* clear SYSFAIL */ - - printf("reset failed\n"); -} -#endif /* MVME188 */ - unsigned dumpmag = 0x8fca0101; /* magic number for savecore */ int dumpsize = 0; /* also for savecore */ long dumplo = 0; @@ -1036,71 +816,24 @@ abort: void setupiackvectors() { - u_char *vaddr; -#undef MAP_VEC /* Switching to new virtual addresses XXX smurph */ -#ifdef MAP_VEC - extern vaddr_t iomap_mapin(paddr_t, psize_t, boolean_t); -#endif - /* - * map a page in for phys address 0xfffe0000 (M187) and set the - * addresses for various levels. - */ switch (brdtyp) { #ifdef MVME187 case BRD_187: case BRD_8120: -#ifdef MAP_VEC /* do for MVME188 too */ - vaddr = (u_char *)iomap_mapin(M187_IACK, NBPG, 1); -#else - vaddr = (u_char *)M187_IACK; -#endif + m187_setupiackvectors(); break; -#endif /* MVME187 */ +#endif #ifdef MVME188 case BRD_188: -#ifdef MAP_VEC /* do for MVME188 too */ - vaddr = (u_char *)iomap_mapin(M188_IACK, NBPG, 1); -#else - vaddr = (u_char *)M188_IACK; -#endif - ivec[0] = vaddr; /* We dont use level 0 */ - ivec[1] = vaddr + 0x04; - ivec[2] = vaddr + 0x08; - ivec[3] = vaddr + 0x0c; - ivec[4] = vaddr + 0x10; - ivec[5] = vaddr + 0x14; - ivec[6] = vaddr + 0x18; - ivec[7] = vaddr + 0x1c; - ivec[8] = vaddr + 0x20; /* for self inflicted interrupts */ - *ivec[8] = M188_IVEC; /* supply a vector base for m188ih */ + m188_setupiackvectors(); break; -#endif /* MVME188 */ +#endif #ifdef MVME197 case BRD_197: -#ifdef MAP_VEC /* do for MVME188 too */ - vaddr = (u_char *)iomap_mapin(M197_IACK, NBPG, 1); -#else - vaddr = (u_char *)M197_IACK; -#endif + m197_setupiackvectors(); break; -#endif /* MVME197 */ - } -#ifdef DEBUG - printf("interrupt ACK address mapped at 0x%x\n", vaddr); #endif - -#if defined(MVME187) || defined(MVME197) - if (brdtyp != BRD_188) { - ivec[0] = vaddr + 0x03; /* We dont use level 0 */ - ivec[1] = vaddr + 0x07; - ivec[2] = vaddr + 0x0b; - ivec[3] = vaddr + 0x0f; - ivec[4] = vaddr + 0x13; - ivec[5] = vaddr + 0x17; - ivec[6] = vaddr + 0x1b; - ivec[7] = vaddr + 0x1f; } -#endif } /* gets an interrupt stack for slave processors */ @@ -1124,15 +857,13 @@ get_slave_stack() * Determine CPU number and set it. * * Running on an interrupt stack here; do nothing fancy. - * - * Called from "mvme88k/locore.S" */ void slave_pre_main() { - set_cpu_number(cmmu_cpu_number()); /* Determine cpu number by CMMU */ - splhigh(); - enable_interrupt(); + set_cpu_number(cmmu_cpu_number()); /* Determine cpu number by CMMU */ + splhigh(); + enable_interrupt(); } /* dummy main routine for slave processors */ @@ -1145,7 +876,7 @@ slave_main() } /* - * Search for the first avilable interrupt vector in the range start, end. + * Search for the first available interrupt vector in the range start, end. * This should really only be used by VME devices. */ int @@ -1207,421 +938,6 @@ intr_establish(int vec, struct intrhand *ihand, const char *name) return (0); } -#ifdef MVME188 - -/* - * Device interrupt handler for MVME188 - * - * when we enter, interrupts are disabled; - * when we leave, they should be disabled, - * but they need not be disabled throughout - * the routine. - */ - -/* Hard coded vector table for onboard devices. */ -const unsigned int obio_vec[32] = { - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,SYSCV_SCC,0,0,SYSCV_SYSF,SYSCV_TIMER2,0,0, - 0,0,0,0,SYSCV_TIMER1,0,SYSCV_ACF,SYSCV_ABRT, -}; - -#define GET_MASK(cpu, val) *int_mask_reg[cpu] & (val) -#define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */ -#define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */ - -void -m188_ext_int(u_int v, struct trapframe *eframe) -{ - int cpu = cpu_number(); - unsigned int cur_mask; - unsigned int level, old_spl; - struct intrhand *intr; - intrhand_t *list; - int ret, intbit; - unsigned vec; - - cur_mask = ISR_GET_CURRENT_MASK(cpu); - old_spl = m188_curspl[cpu]; - eframe->tf_mask = old_spl; - - if (cur_mask == 0) { - /* - * Spurious interrupts - may be caused by debug output clearing - * DUART interrupts. - */ - flush_pipeline(); - goto out; - } - - uvmexp.intrs++; - - /* - * We want to service all interrupts marked in the IST register - * They are all valid because the mask would have prevented them - * from being generated otherwise. We will service them in order of - * priority. - */ - do { - level = safe_level(cur_mask, old_spl); - - if (old_spl >= level) { - int i; - - printf("safe level %d <= old level %d\n", level, old_spl); - printf("cur_mask = 0x%b\n", cur_mask, IST_STRING); - for (i = 0; i < 4; i++) - printf("IEN%d = 0x%b ", i, *int_mask_reg[i], IST_STRING); - printf("\nCPU0 spl %d CPU1 spl %d CPU2 spl %d CPU3 spl %d\n", - m188_curspl[0], m188_curspl[1], - m188_curspl[2], m188_curspl[3]); - for (i = 0; i < 8; i++) - printf("int_mask[%d] = 0x%08x\n", i, int_mask_val[i]); - printf("--CPU %d halted--\n", cpu_number()); - spl7(); - for(;;) ; - } - -#ifdef DEBUG - if (level > 7 || (int)level < 0) { - panic("int level (%x) is not between 0 and 7", level); - } -#endif - - setipl(level); - - /* - * Do not enable interrupts yet if we know, from cur_mask, - * that we have not cleared enough conditions yet. - * For now, only the timer interrupt requires its condition - * to be cleared before interrupts are enabled. - */ - if ((cur_mask & DTI_BIT) == 0) { - enable_interrupt(); - } - - /* generate IACK and get the vector */ - - /* - * This is tricky. If you don't catch all the - * interrupts, you die. Game over. Insert coin... - * XXX smurph - */ - - /* find the first bit set in the current mask */ - intbit = ff1(cur_mask); - if (OBIO_INTERRUPT_MASK & (1 << intbit)) { - vec = SYSCON_VECT + obio_vec[intbit]; - if (vec == 0) { - panic("unknown onboard interrupt: mask = 0x%b", - 1 << intbit, IST_STRING); - } - } else if (HW_FAILURE_MASK & (1 << intbit)) { - vec = SYSCON_VECT + obio_vec[intbit]; - if (vec == 0) { - panic("unknown hardware failure: mask = 0x%b", - 1 << intbit, IST_STRING); - } - } else if (VME_INTERRUPT_MASK & (1 << intbit)) { - if (guarded_access(ivec[level], 4, (u_char *)&vec) == - EFAULT) { - panic("unable to get vector for this vmebus " - "interrupt (level %x)", level); - } - vec &= VME_VECTOR_MASK; - if (vec & VME_BERR_MASK) { - printf("VME vec timeout, vec = %x, mask = 0x%b\n", - vec, 1 << intbit, IST_STRING); - break; - } - if (vec == 0) { - panic("unknown vme interrupt: mask = 0x%b", - 1 << intbit, IST_STRING); - } - } else { - panic("unknown interrupt: level = %d intbit = 0x%x " - "mask = 0x%b", - level, intbit, 1 << intbit, IST_STRING); - } - - list = &intr_handlers[vec]; - if (SLIST_EMPTY(list)) { - /* increment intr counter */ - intrcnt[M88K_SPUR_IRQ]++; - printf("Spurious interrupt: level = %d vec = 0x%x, " - "intbit = %d mask = 0x%b\n", - level, vec, intbit, 1 << intbit, IST_STRING); - } else { - /* - * Walk through all interrupt handlers in the chain - * for the given vector, calling each handler in turn, - * till some handler returns a value != 0. - */ - ret = 0; - SLIST_FOREACH(intr, list, ih_link) { - if (intr->ih_wantframe != 0) - ret = (*intr->ih_fn)((void *)eframe); - else - ret = (*intr->ih_fn)(intr->ih_arg); - if (ret != 0) { - intrcnt[level]++; - intr->ih_count.ec_count++; - break; - } - } - if (ret == 0) { - printf("Unclaimed interrupt: level = %d " - "vec = 0x%x, intbit = %d mask = 0x%b\n", - level, vec, intbit, - 1 << intbit, IST_STRING); - break; - } - } - } while ((cur_mask = ISR_GET_CURRENT_MASK(cpu)) != 0); - - /* - * process any remaining data access exceptions before - * returning to assembler - */ - disable_interrupt(); -out: - if (eframe->tf_dmt0 & DMT_VALID) - m88100_trap(T_DATAFLT, eframe); - - /* - * Restore the mask level to what it was when the interrupt - * was taken. - */ - setipl(eframe->tf_mask); -} - -#endif /* MVME188 */ - -/* - * Device interrupt handler for MVME1x7 - * - * when we enter, interrupts are disabled; - * when we leave, they should be disabled, - * but they need not be disabled throughout - * the routine. - */ - -#ifdef MVME187 -void -m187_ext_int(u_int v, struct trapframe *eframe) -{ - int mask, level; - struct intrhand *intr; - intrhand_t *list; - int ret; - u_char vec; - - /* get level and mask */ - mask = *md.intr_mask & 0x07; - level = *md.intr_ipl & 0x07; - -#ifdef DIAGNOSTIC - /* - * It is really bizarre for the mask and level to the be the same. - * pcc2 for 187 blocks all interrupts at and below the mask value, - * so we should not be getting an interrupt at the level that is - * already blocked. I can't explain this case XXX nivas - */ - - if ((mask == level) && level) { - panic("mask == level, %d", level); - } - - /* - * Interrupting level cannot be 0--0 doesn't produce an interrupt. - * Weird! XXX nivas - */ - - if (level == 0) { - panic("Bogons... level %x and mask %x", level, mask); - } -#endif - - uvmexp.intrs++; - - /* generate IACK and get the vector */ - flush_pipeline(); - if (guarded_access(ivec[level], 1, &vec) == EFAULT) { - panic("Unable to get vector for this interrupt (level %x)", level); - } - flush_pipeline(); - flush_pipeline(); - flush_pipeline(); - - /* block interrupts at level or lower */ - setipl(level); - - enable_interrupt(); - - list = &intr_handlers[vec]; - if (SLIST_EMPTY(list)) { - /* increment intr counter */ - intrcnt[M88K_SPUR_IRQ]++; - printf("Spurious interrupt (level %x and vec %x)\n", - level, vec); - } else { -#ifdef DIAGNOSTIC - intr = SLIST_FIRST(list); - if (intr->ih_ipl != level) { - panic("Handler ipl %x not the same as level %x. " - "vec = 0x%x", - intr->ih_ipl, level, vec); - } -#endif - - /* - * Walk through all interrupt handlers in the chain for the - * given vector, calling each handler in turn, till some handler - * returns a value != 0. - */ - - ret = 0; - SLIST_FOREACH(intr, list, ih_link) { - if (intr->ih_wantframe != 0) - ret = (*intr->ih_fn)((void *)eframe); - else - ret = (*intr->ih_fn)(intr->ih_arg); - if (ret != 0) { - intrcnt[level]++; - intr->ih_count.ec_count++; - break; - } - } - - if (ret == 0) { - printf("Unclaimed interrupt (level %x and vec %x)\n", - level, vec); - } - } - - /* - * process any remaining data access exceptions before - * returning to assembler - */ - disable_interrupt(); - if (eframe->tf_dmt0 & DMT_VALID) - m88100_trap(T_DATAFLT, eframe); - - /* - * Restore the mask level to what it was when the interrupt - * was taken. - */ - setipl(mask); -} -#endif /* MVME187 */ - -#ifdef MVME197 -void -m197_ext_int(u_int v, struct trapframe *eframe) -{ - int mask, level, src; - struct intrhand *intr; - intrhand_t *list; - int ret; - u_char vec; - - /* get src and mask */ - mask = *md.intr_mask & 0x07; - src = *md.intr_src; - - if (v == T_NON_MASK) { - /* This is the abort switch */ - level = IPL_NMI; - vec = BS_ABORTVEC; - } else { - /* get level */ - level = *md.intr_ipl & 0x07; - } - -#ifdef DIAGNOSTIC - /* - * Interrupting level cannot be 0--0 doesn't produce an interrupt. - * Weird! XXX nivas - */ - - if (level == 0) { - panic("Bogons... level %x and mask %x", level, mask); - } -#endif - - uvmexp.intrs++; - - if (v != T_NON_MASK) { - /* generate IACK and get the vector */ - flush_pipeline(); - if (guarded_access(ivec[level], 1, &vec) == EFAULT) { - panic("Unable to get vector for this interrupt (level %x)", level); - } - flush_pipeline(); - flush_pipeline(); - flush_pipeline(); - } - - if (v != T_NON_MASK || cold == 0) { - /* block interrupts at level or lower */ - setipl(level); - - enable_interrupt(); - } - - list = &intr_handlers[vec]; - if (SLIST_EMPTY(list)) { - /* increment intr counter */ - intrcnt[M88K_SPUR_IRQ]++; - printf("Spurious interrupt (level %x and vec %x)\n", - level, vec); - } else { -#ifdef DIAGNOSTIC - intr = SLIST_FIRST(list); - if (intr->ih_ipl != level) { - panic("Handler ipl %x not the same as level %x. " - "vec = 0x%x", - intr->ih_ipl, level, vec); - } -#endif - - /* - * Walk through all interrupt handlers in the chain for the - * given vector, calling each handler in turn, till some handler - * returns a value != 0. - */ - - ret = 0; - SLIST_FOREACH(intr, list, ih_link) { - if (intr->ih_wantframe != 0) - ret = (*intr->ih_fn)((void *)eframe); - else - ret = (*intr->ih_fn)(intr->ih_arg); - if (ret != 0) { - intrcnt[level]++; - intr->ih_count.ec_count++; - break; - } - } - - if (ret == 0) { - printf("Unclaimed interrupt (level %x and vec %x)\n", - level, vec); - } - } - - if (v != T_NON_MASK || cold == 0) { - disable_interrupt(); - - /* - * Restore the mask level to what it was when the interrupt - * was taken. - */ - setipl(mask); - } -} -#endif /* MVME197 */ - int cpu_exec_aout_makecmds(p, epp) struct proc *p; @@ -1681,8 +997,6 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) /*NOTREACHED*/ } -/* dummys for now */ - void bugsyscall() { @@ -1743,19 +1057,11 @@ spl0() * Called from locore.S during boot, * this is the first C code that's run. */ - void mvme_bootstrap() { extern int kernelstart; extern struct consdev *cn_tab; -#ifdef MVME197 - extern struct cmmu_p cmmu88110; -#endif -#if defined(MVME187) || defined(MVME188) - extern struct cmmu_p cmmu8820x; -#endif - extern void set_tcfp(void); struct mvmeprom_brdid brdid; @@ -1763,7 +1069,7 @@ mvme_bootstrap() * Must initialize p_addr before autoconfig or * the fault handler will get a NULL reference. * Do this early so that we can take a data or - * instruction fault and survive it. XXX smurph + * instruction fault and survive it. */ proc0.p_addr = proc0paddr; curproc = &proc0; @@ -1772,57 +1078,41 @@ mvme_bootstrap() /* zero out the machine dependent function pointers */ bzero(&md, sizeof(struct md_p)); - buginit(); /* init the bug routines */ + buginit(); bugbrdid(&brdid); brdtyp = brdid.model; /* - * set up interrupt and fp exception handlers - * based on the machine. + * Set up interrupt and fp exception handlers based on the machine. */ switch (brdtyp) { -#ifdef MVME188 - case BRD_188: - cmmu = &cmmu8820x; - md.interrupt_func = &m188_ext_int; - md.intr_mask = NULL; - md.intr_ipl = NULL; - md.intr_src = NULL; - /* clear and disable all interrupts */ - *int_mask_reg[0] = 0; - *int_mask_reg[1] = 0; - *int_mask_reg[2] = 0; - *int_mask_reg[3] = 0; - break; -#endif /* MVME188 */ #ifdef MVME187 case BRD_187: case BRD_8120: - cmmu = &cmmu8820x; - md.interrupt_func = &m187_ext_int; - md.intr_mask = (u_char *)M187_IMASK; - md.intr_ipl = (u_char *)M187_ILEVEL; - md.intr_src = NULL; + m187_bootstrap(); + break; +#endif +#ifdef MVME188 + case BRD_188: + m188_bootstrap(); break; -#endif /* MVME187 */ +#endif #ifdef MVME197 case BRD_197: - cmmu = &cmmu88110; - md.interrupt_func = &m197_ext_int; - md.intr_mask = (u_char *)M197_IMASK; - md.intr_ipl = (u_char *)M197_ILEVEL; - md.intr_src = (u_char *)M197_ISRC; - set_tcfp(); /* Set Time Critical Floating Point Mode */ + m197_bootstrap(); break; -#endif /* MVME197 */ +#endif default: - panic("mvme_bootstrap: Can't determine cpu type."); + panic("Sorry, this kernel does not support MVME%x", brdtyp); } - /* startup fake console driver. It will be replaced by consinit() */ + /* + * Use the BUG as console for now. After autoconf, we'll switch to + * real hardware. + */ cn_tab = &bootcons; - uvmexp.pagesize = NBPG; + uvmexp.pagesize = PAGE_SIZE; uvm_setpagesize(); first_addr = round_page(first_addr); @@ -1830,21 +1120,19 @@ mvme_bootstrap() #ifdef MVME187 case BRD_187: case BRD_8120: - last_addr = memsize187(); + last_addr = m187_memsize(); break; #endif #ifdef MVME188 case BRD_188: - last_addr = memsize188(); + last_addr = m188_memsize(); break; #endif #ifdef MVME197 case BRD_197: - last_addr = size_memory(); + last_addr = m197_memsize(); break; #endif - default: - break; } physmem = btoc(last_addr); @@ -1860,6 +1148,7 @@ mvme_bootstrap() * We will also want to spin up slave CPUs on the long run... */ switch (brdtyp) { +#ifdef MVME188 case BRD_188: printf("CPU%d is master CPU\n", master_cpu); @@ -1871,6 +1160,8 @@ mvme_bootstrap() } #endif break; +#endif +#ifdef MVME197 case BRD_197: /* * In the 197DP case, mention which CPU is the master @@ -1878,23 +1169,33 @@ mvme_bootstrap() * XXX TBD */ break; +#endif +#ifdef MVME187 + default: + break; +#endif } avail_start = first_addr; avail_end = last_addr; + /* * Steal MSGBUFSIZE at the top of physical memory for msgbuf */ avail_end -= round_page(MSGBUFSIZE); #ifdef DEBUG - printf("MVME%x boot: memory from 0x%x to 0x%x\n", brdtyp, avail_start, avail_end); + printf("MVME%x boot: memory from 0x%x to 0x%x\n", + brdtyp, avail_start, avail_end); #endif pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart)); /* * Tell the VM system about available physical memory. - * mvme88k only has one segment. + * + * The mvme88k boards only have one contiguous area, although BUG + * could be set up to configure a non-contiguous scheme; also, we + * might want to register ECC memory separately later on... */ uvm_page_physload(atop(avail_start), atop(avail_end), atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); @@ -1908,7 +1209,7 @@ mvme_bootstrap() load_u_area(&proc0); /* Initialize the "u-area" pages. */ - bzero((caddr_t)UADDR, UPAGES*NBPG); + bzero((caddr_t)UADDR, UPAGES * PAGE_SIZE); #ifdef DEBUG printf("leaving mvme_bootstrap()\n"); #endif @@ -1949,3 +1250,177 @@ bootcnputc(dev, c) bugoutchr('\r'); bugoutchr((char)c); } + +#define SIGSYS_MAX 501 +#define SIGTRAP_MAX 510 + +#define EMPTY_BR 0xc0000000 /* empty "br" instruction */ +#define NO_OP 0xf4005800 /* "or r0, r0, r0" */ + +#define BRANCH(FROM, TO) \ + (EMPTY_BR | ((unsigned)(TO) - (unsigned)(FROM)) >> 2) + +#define SET_VECTOR(NUM, VALUE) \ + do { \ + vector[NUM].word_one = NO_OP; \ + vector[NUM].word_two = BRANCH(&vector[NUM].word_two, VALUE); \ + } while (0) + +/* + * vector_init(vector, vector_init_list) + * + * This routine sets up the m88k vector table for the running processor. + * It is called with a very little stack, and interrupts disabled, + * so don't call any other functions! + */ +void +vector_init(m88k_exception_vector_area *vector, unsigned *vector_init_list) +{ + unsigned num; + unsigned vec; + extern void bugtrap(void); + extern void m88110_bugtrap(void); + + for (num = 0; (vec = vector_init_list[num]) != END_OF_VECTOR_LIST; + num++) { + if (vec != UNKNOWN_HANDLER) + SET_VECTOR(num, vec); + } + + /* Save BUG vector */ + bugvec[0] = vector[MVMEPROM_VECTOR].word_one; + bugvec[1] = vector[MVMEPROM_VECTOR].word_two; + +#ifdef M88110 + if (CPU_IS88110) { + for (; num <= SIGSYS_MAX; num++) + SET_VECTOR(num, m88110_sigsys); + + for (; num <= SIGTRAP_MAX; num++) + SET_VECTOR(num, m88110_sigtrap); + + SET_VECTOR(450, m88110_syscall_handler); + SET_VECTOR(MVMEPROM_VECTOR, m88110_bugtrap); + SET_VECTOR(504, m88110_stepbpt); + SET_VECTOR(511, m88110_userbpt); + } +#endif +#ifdef M88100 + if (CPU_IS88100) { + for (; num <= SIGSYS_MAX; num++) + SET_VECTOR(num, sigsys); + + for (; num <= SIGTRAP_MAX; num++) + SET_VECTOR(num, sigtrap); + + SET_VECTOR(450, syscall_handler); + SET_VECTOR(MVMEPROM_VECTOR, bugtrap); + SET_VECTOR(504, stepbpt); + SET_VECTOR(511, userbpt); + } +#endif + + /* GCC will by default produce explicit trap 503 for division by zero */ + SET_VECTOR(503, vector_init_list[T_ZERODIV]); + + /* Save new BUG vector */ + sysbugvec[0] = vector[MVMEPROM_VECTOR].word_one; + sysbugvec[1] = vector[MVMEPROM_VECTOR].word_two; +} + +unsigned +getipl(void) +{ + unsigned curspl; + m88k_psr_type psr; + + psr = disable_interrupts_return_psr(); + switch (brdtyp) { +#ifdef MVME188 + case BRD_188: + curspl = m188_curspl[cpu_number()]; + break; +#endif /* MVME188 */ +#if defined(MVME187) || defined(MVME197) + case BRD_187: + case BRD_8120: + case BRD_197: + curspl = *md.intr_mask & 0x07; + break; +#endif /* defined(MVME187) || defined(MVME197) */ + } + set_psr(psr); + return curspl; +} + +unsigned +setipl(unsigned level) +{ + unsigned curspl; + m88k_psr_type psr; + + psr = disable_interrupts_return_psr(); + switch (brdtyp) { +#ifdef MVME188 + case BRD_188: + curspl = m188_curspl[cpu_number()]; + setlevel(level); + break; +#endif /* MVME188 */ +#if defined(MVME187) || defined(MVME197) + case BRD_187: + case BRD_8120: + case BRD_197: + curspl = *md.intr_mask & 0x07; + *md.intr_mask = level; + break; +#endif /* defined(MVME187) || defined(MVME197) */ + } + + /* + * The flush pipeline is required to make sure the above write gets + * through the data pipe and to the hardware; otherwise, the next + * bunch of instructions could execute at the wrong spl protection. + */ + flush_pipeline(); + + set_psr(psr); + return curspl; +} + +unsigned +raiseipl(unsigned level) +{ + unsigned curspl; + m88k_psr_type psr; + + psr = disable_interrupts_return_psr(); + switch (brdtyp) { +#ifdef MVME188 + case BRD_188: + curspl = m188_curspl[cpu_number()]; + if (curspl < level) + setlevel(level); + break; +#endif /* MVME188 */ +#if defined(MVME187) || defined(MVME197) + case BRD_187: + case BRD_8120: + case BRD_197: + curspl = *md.intr_mask & 0x07; + if (curspl < level) + *md.intr_mask = level; + break; +#endif /* defined(MVME187) || defined(MVME197) */ + } + + /* + * The flush pipeline is required to make sure the above write gets + * through the data pipe and to the hardware; otherwise, the next + * bunch of instructions could execute at the wrong spl protection. + */ + flush_pipeline(); + + set_psr(psr); + return curspl; +} |