Split trap handler into mips-generic and port-specific functions:
* Delete pmax-specific functions and declarations from trap.c * Delete mips-geeneric functions and declaratinos from pmax_trap.c * Rename the function pointer used to handle hardware interrupts to "mips_hardware_intr". Define it in trap.c. Change references elsewhere, including machdep.c. Verified to boot on a 5000/200.
This commit is contained in:
parent
458024d39d
commit
97f32908b1
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trap.c,v 1.32 1996/03/25 05:55:30 jonathan Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.33 1996/03/25 06:44:17 jonathan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
@ -67,30 +67,19 @@
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
||||
/* XXX */
|
||||
#include <pmax/pmax/clockreg.h>
|
||||
#include <pmax/pmax/kn01.h>
|
||||
#include <pmax/pmax/kn02.h>
|
||||
#include <pmax/pmax/kmin.h>
|
||||
#include <pmax/pmax/maxine.h>
|
||||
#include <pmax/pmax/kn03.h>
|
||||
#include <pmax/pmax/asic.h>
|
||||
#include <pmax/pmax/turbochannel.h>
|
||||
|
||||
#include <pmax/stand/dec_prom.h>
|
||||
|
||||
#include "asc.h"
|
||||
#include "sii.h"
|
||||
#include "le.h"
|
||||
#include "dc.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <pmax/pmax/trap.h>
|
||||
|
||||
struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */
|
||||
|
||||
/*
|
||||
* Port-specific hardware interrupt handler
|
||||
*/
|
||||
|
||||
int (*mips_hardware_intr) __P((u_int mask, u_int pc, u_int status,
|
||||
u_int cause)) =
|
||||
( int (*) __P((u_int, u_int, u_int, u_int)) ) 0;
|
||||
|
||||
/*
|
||||
* Exception-handling functions, called via machExceptionTable from locore
|
||||
*/
|
||||
@ -193,6 +182,13 @@ void trapDump __P((char * msg));
|
||||
void cpu_getregs __P((int *regs));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Other forward declarations.
|
||||
*/
|
||||
u_int MachEmulateBranch __P((unsigned *regsPtr,
|
||||
unsigned instPC,
|
||||
unsigned fpcCSR,
|
||||
int allowNonBranch));
|
||||
|
||||
/* extern functions used but not declared elsewhere */
|
||||
extern void MachFPInterrupt __P((u_int status, u_int cause, u_int pc));
|
||||
@ -221,34 +217,6 @@ extern int main __P((void*));
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
|
||||
static void pmax_errintr __P((void));
|
||||
static void kn02_errintr __P((void)), kn02ba_errintr __P((void));
|
||||
|
||||
#ifdef DS5000_240
|
||||
static void kn03_errintr __P ((void));
|
||||
extern u_long kn03_tc3_imask;
|
||||
|
||||
/*
|
||||
* IOASIC 40ns bus-cycle counter, used as hi-resolution clock:
|
||||
* may also be present on (some) XINE, 3min hardware, but not tested there.
|
||||
*/
|
||||
extern u_long ioasic_base; /* Base address of I/O asic */
|
||||
u_long latched_cycle_cnt; /*
|
||||
* IOASIC cycle counter, latched on every
|
||||
* interrupt from RTC chip (64Hz).
|
||||
*/
|
||||
#endif /*DS5000_240*/
|
||||
|
||||
static unsigned kn02ba_recover_erradr __P((u_int phys, u_int mer));
|
||||
extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
|
||||
extern u_long kmin_tc3_imask, xine_tc3_imask;
|
||||
extern const struct callback *callv;
|
||||
|
||||
int (*pmax_hardware_intr) __P((u_int mask, u_int pc, u_int status,
|
||||
u_int cause)) =
|
||||
( int (*) __P((u_int, u_int, u_int, u_int)) ) 0;
|
||||
|
||||
extern volatile struct chiptime *Mach_clock_addr;
|
||||
extern u_long kernelfaults;
|
||||
u_long kernelfaults = 0;
|
||||
@ -869,7 +837,7 @@ out:
|
||||
* Note: curproc might be NULL.
|
||||
*/
|
||||
void
|
||||
interrupt(statusReg, causeReg, pc)
|
||||
interrupt(statusReg, causeReg, pc /* XXX what, args */ )
|
||||
unsigned statusReg; /* status register at time of the exception */
|
||||
unsigned causeReg; /* cause register at time of exception */
|
||||
unsigned pc; /* program counter where to continue */
|
||||
@ -883,7 +851,7 @@ interrupt(statusReg, causeReg, pc)
|
||||
trp->vadr = 0;
|
||||
trp->pc = pc;
|
||||
trp->ra = 0;
|
||||
trp->sp = (int)&args;
|
||||
trp->sp = /* (int)&args */ 0; /* XXX pass args in */
|
||||
trp->code = 0;
|
||||
if (++trp == &trapdebug[TRAPSIZE])
|
||||
trp = trapdebug;
|
||||
@ -891,8 +859,8 @@ interrupt(statusReg, causeReg, pc)
|
||||
|
||||
cnt.v_intr++;
|
||||
mask = causeReg & statusReg; /* pending interrupts & enable mask */
|
||||
if (pmax_hardware_intr)
|
||||
splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg));
|
||||
if (mips_hardware_intr)
|
||||
splx((*mips_hardware_intr)(mask, pc, statusReg, causeReg));
|
||||
if (mask & MACH_INT_MASK_5) {
|
||||
intrcnt[FPU_INTR]++;
|
||||
if (!USERMODE(statusReg)) {
|
||||
@ -950,568 +918,6 @@ interrupt(statusReg, causeReg, pc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle pmax (DECstation 2100/3100) interrupts.
|
||||
*/
|
||||
int
|
||||
kn01_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
extern struct cfdriver sii_cd;
|
||||
extern struct cfdriver le_cd;
|
||||
extern struct cfdriver dc_cd;
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
|
||||
/* keep clock interrupts enabled */
|
||||
causeReg &= ~MACH_INT_MASK_3;
|
||||
}
|
||||
/* Re-enable clock interrupts */
|
||||
splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);
|
||||
#if NSII > 0
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
intrcnt[SCSI_INTR]++;
|
||||
siiintr(sii_cd.cd_devs[0]);
|
||||
}
|
||||
#endif
|
||||
#if NLE > 0
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
|
||||
/*
|
||||
* tty interrupts were disabled by the splx() call
|
||||
* that re-enables clock interrupts. A slip or ppp driver
|
||||
* manipulating if queues should have called splimp(),
|
||||
* which would mask out MACH_INT_MASK_1.
|
||||
*/
|
||||
leintr(le_cd.cd_devs[0]);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
#endif
|
||||
#if NDC > 0
|
||||
if (mask & MACH_INT_MASK_2) {
|
||||
dcintr(dc_cd.cd_devs[0]);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
#endif
|
||||
if (mask & MACH_INT_MASK_4) {
|
||||
pmax_errintr();
|
||||
intrcnt[ERROR_INTR]++;
|
||||
}
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle hardware interrupts for the KN02. (DECstation 5000/200)
|
||||
* Returns spl value.
|
||||
*/
|
||||
int
|
||||
kn02_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register unsigned i, m;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
register unsigned csr;
|
||||
int temp;
|
||||
struct clockframe cf;
|
||||
static int warned = 0;
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
|
||||
if ((csr & KN02_CSR_PSWARN) && !warned) {
|
||||
warned = 1;
|
||||
printf("WARNING: power supply is overheating!\n");
|
||||
} else if (warned && !(csr & KN02_CSR_PSWARN)) {
|
||||
warned = 0;
|
||||
printf("WARNING: power supply is OK again\n");
|
||||
}
|
||||
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
|
||||
/* keep clock interrupts enabled */
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* Re-enable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
static int intr_map[8] = { SLOT0_INTR, SLOT1_INTR, SLOT2_INTR,
|
||||
/* these two bits reserved */
|
||||
STRAY_INTR, STRAY_INTR,
|
||||
SCSI_INTR, LANCE_INTR,
|
||||
SERIAL0_INTR };
|
||||
|
||||
csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
|
||||
m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;
|
||||
#if 0
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
|
||||
(csr & ~(KN02_CSR_WRESERVED | 0xFF)) |
|
||||
(m << KN02_CSR_IOINTEN_SHIFT);
|
||||
#endif
|
||||
for (i = 0; m; i++, m >>= 1) {
|
||||
if (!(m & 1))
|
||||
continue;
|
||||
intrcnt[intr_map[i]]++;
|
||||
if (tc_slot_info[i].intr)
|
||||
(*tc_slot_info[i].intr)(tc_slot_info[i].sc);
|
||||
else
|
||||
printf("spurious interrupt %d\n", i);
|
||||
}
|
||||
#if 0
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
|
||||
csr & ~(KN02_CSR_WRESERVED | 0xFF);
|
||||
#endif
|
||||
}
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intrcnt[ERROR_INTR]++;
|
||||
kn02_errintr();
|
||||
}
|
||||
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3min hardware interrupts. (DECstation 5000/1xx)
|
||||
*/
|
||||
int
|
||||
kmin_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp =
|
||||
(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK);
|
||||
volatile u_int *intrp =
|
||||
(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR);
|
||||
unsigned int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
static int user_warned = 0;
|
||||
|
||||
old_mask = *imaskp & kmin_tc3_imask;
|
||||
*imaskp = kmin_tc3_imask |
|
||||
(KMIN_IM0 & ~(KN03_INTR_TC_0|KN03_INTR_TC_1|KN03_INTR_TC_2));
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intr = *intrp;
|
||||
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if (intr & KMIN_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & KMIN_INTR_LANCE_READ_E)
|
||||
*intrp &= ~KMIN_INTR_LANCE_READ_E;
|
||||
|
||||
if (intr & KMIN_INTR_TIMEOUT)
|
||||
kn02ba_errintr();
|
||||
|
||||
if (intr & KMIN_INTR_CLOCK) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCC_0) &&
|
||||
tc_slot_info[KMIN_SCC0_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCC0_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCC0_SLOT].sc);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCC_1) &&
|
||||
tc_slot_info[KMIN_SCC1_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCC1_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCC1_SLOT].sc);
|
||||
intrcnt[SERIAL1_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCSI) &&
|
||||
tc_slot_info[KMIN_SCSI_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCSI_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCSI_SLOT].sc);
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_LANCE) &&
|
||||
tc_slot_info[KMIN_LANCE_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_LANCE_SLOT].intr))
|
||||
(tc_slot_info[KMIN_LANCE_SLOT].sc);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
|
||||
if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
|
||||
printf("%s\n", "Power supply ok now.");
|
||||
user_warned = 0;
|
||||
}
|
||||
if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
|
||||
user_warned++;
|
||||
printf("%s\n", "Power supply overheating");
|
||||
}
|
||||
}
|
||||
if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr) {
|
||||
(*tc_slot_info[0].intr)(tc_slot_info[0].sc);
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
|
||||
if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr) {
|
||||
(*tc_slot_info[1].intr)(tc_slot_info[1].sc);
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr) {
|
||||
(*tc_slot_info[2].intr)(tc_slot_info[2].sc);
|
||||
intrcnt[SLOT2_INTR]++;
|
||||
}
|
||||
|
||||
#if 0 /*XXX*/
|
||||
if (mask & (MACH_INT_MASK_2|MACH_INT_MASK_1|MACH_INT_MASK_0))
|
||||
printf("kmin: slot intr, mask 0x%x\n",
|
||||
mask &
|
||||
(MACH_INT_MASK_2|MACH_INT_MASK_1|MACH_INT_MASK_0));
|
||||
#endif
|
||||
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maxine hardware interrupts. (Personal DECstation 5000/xx)
|
||||
*/
|
||||
int
|
||||
xine_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK);
|
||||
volatile u_int *intrp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
|
||||
u_int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
|
||||
old_mask = *imaskp & xine_tc3_imask;
|
||||
*imaskp = xine_tc3_imask;
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* reenable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intr = *intrp;
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if ((intr & XINE_INTR_SCC_0)) {
|
||||
if (tc_slot_info[XINE_SCC0_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_SCC0_SLOT].intr))
|
||||
(tc_slot_info[XINE_SCC0_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle scc interrupt\n");
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~XINE_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & XINE_INTR_LANCE_READ_E)
|
||||
*intrp &= ~XINE_INTR_LANCE_READ_E;
|
||||
|
||||
if (intr & XINE_INTR_DTOP_RX) {
|
||||
if (tc_slot_info[XINE_DTOP_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_DTOP_SLOT].intr))
|
||||
(tc_slot_info[XINE_DTOP_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle dtop interrupt\n");
|
||||
intrcnt[DTOP_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_FLOPPY) {
|
||||
if (tc_slot_info[XINE_FLOPPY_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_FLOPPY_SLOT].intr))
|
||||
(tc_slot_info[XINE_FLOPPY_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle floppy interrupt\n");
|
||||
intrcnt[FLOPPY_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_TC_0) {
|
||||
if (tc_slot_info[0].intr)
|
||||
(*(tc_slot_info[0].intr))
|
||||
(tc_slot_info[0].sc);
|
||||
else
|
||||
printf ("can't handle tc0 interrupt\n");
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_TC_1) {
|
||||
if (tc_slot_info[1].intr)
|
||||
(*(tc_slot_info[1].intr))
|
||||
(tc_slot_info[1].sc);
|
||||
else
|
||||
printf ("can't handle tc1 interrupt\n");
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_ISDN) {
|
||||
if (tc_slot_info[XINE_ISDN_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_ISDN_SLOT].intr))
|
||||
(tc_slot_info[XINE_ISDN_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle isdn interrupt\n");
|
||||
intrcnt[ISDN_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_SCSI) {
|
||||
if (tc_slot_info[XINE_SCSI_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_SCSI_SLOT].intr))
|
||||
(tc_slot_info[XINE_SCSI_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle scsi interrupt\n");
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_LANCE) {
|
||||
if (tc_slot_info[XINE_LANCE_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_LANCE_SLOT].intr))
|
||||
(tc_slot_info[XINE_LANCE_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle lance interrupt\n");
|
||||
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
}
|
||||
if (mask & MACH_INT_MASK_2)
|
||||
kn02ba_errintr();
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
#ifdef DS5000_240
|
||||
/*
|
||||
* 3Max+ hardware interrupts. (DECstation 5000/240) UNTESTED!!
|
||||
*/
|
||||
int
|
||||
kn03_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(KN03_REG_IMSK);
|
||||
volatile u_int *intrp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(KN03_REG_INTR);
|
||||
u_int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
static int user_warned = 0;
|
||||
register u_long old_buscycle = latched_cycle_cnt;
|
||||
|
||||
old_mask = *imaskp & kn03_tc3_imask;
|
||||
*imaskp = kn03_tc3_imask;
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
latched_cycle_cnt = *(u_long*)(IOASIC_REG_CTR(ioasic_base));
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
old_buscycle = latched_cycle_cnt - old_buscycle;
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* reenable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
|
||||
/*
|
||||
* Check for late clock interrupts (allow 10% slop). Be careful
|
||||
* to do so only after calling hardclock(), due to logging cost.
|
||||
* Even then, logging dropped ticks just causes more clock
|
||||
* ticks to be missed.
|
||||
*/
|
||||
#ifdef notdef
|
||||
if ((mask & MACH_INT_MASK_1) && old_buscycle > (tick+49) * 25) {
|
||||
extern int msgbufmapped;
|
||||
if(msgbufmapped && 0)
|
||||
addlog("kn03: clock intr %d usec late\n",
|
||||
old_buscycle/25);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* IOCTL asic DMA-related interrupts should be checked here,
|
||||
* and DMA pointers serviced as soon as possible.
|
||||
*/
|
||||
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
intr = *intrp;
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if (intr & KN03_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~KN03_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* DMA and non-DMA interrupts from the IOCTl asic all use the
|
||||
* single interrupt request line from the IOCTL asic.
|
||||
* Disabling IOASIC interrupts while servicing network or
|
||||
* disk-driver interrupts causes DMA overruns. NON-dma IOASIC
|
||||
* interrupts should be disabled in the ioasic, and
|
||||
* interrupts from the IOASIC itself should be re-enabled.
|
||||
* DMA interrupts can then be serviced whilst still servicing
|
||||
* non-DMA interrupts from ioctl devices or TC options.
|
||||
*/
|
||||
|
||||
if (intr & (KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & KN03_INTR_LANCE_READ_E)
|
||||
*intrp &= ~KN03_INTR_LANCE_READ_E;
|
||||
|
||||
if ((intr & KN03_INTR_SCC_0) &&
|
||||
tc_slot_info[KN03_SCC0_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCC0_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCC0_SLOT].sc);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_SCC_1) &&
|
||||
tc_slot_info[KN03_SCC1_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCC1_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCC1_SLOT].sc);
|
||||
intrcnt[SERIAL1_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_TC_0) &&
|
||||
tc_slot_info[0].intr) {
|
||||
(*(tc_slot_info[0].intr))
|
||||
(tc_slot_info[0].sc);
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_0)
|
||||
printf ("can't handle tc0 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_TC_1) &&
|
||||
tc_slot_info[1].intr) {
|
||||
(*(tc_slot_info[1].intr))
|
||||
(tc_slot_info[1].sc);
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_1)
|
||||
printf ("can't handle tc1 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_TC_2) &&
|
||||
tc_slot_info[2].intr) {
|
||||
(*(tc_slot_info[2].intr))
|
||||
(tc_slot_info[2].sc);
|
||||
intrcnt[SLOT2_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_2)
|
||||
printf ("can't handle tc2 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_SCSI) &&
|
||||
tc_slot_info[KN03_SCSI_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCSI_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCSI_SLOT].sc);
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_LANCE) &&
|
||||
tc_slot_info[KN03_LANCE_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_LANCE_SLOT].intr))
|
||||
(tc_slot_info[KN03_LANCE_SLOT].sc);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
|
||||
if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) {
|
||||
printf("%s\n", "Power supply ok now.");
|
||||
user_warned = 0;
|
||||
}
|
||||
if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) {
|
||||
user_warned++;
|
||||
printf("%s\n", "Power supply overheating");
|
||||
}
|
||||
}
|
||||
if (mask & MACH_INT_MASK_3)
|
||||
kn03_errintr();
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
#endif /* DS5000_240 */
|
||||
|
||||
/*
|
||||
* This is called from MachUserIntr() if astpending is set.
|
||||
@ -1586,173 +992,6 @@ trapDump(msg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* MemErrorInterrupts --
|
||||
* pmax_errintr - for the DS2100/DS3100
|
||||
* kn02_errintr - for the DS5000/200
|
||||
* kn02ba_errintr - for the DS5000/1xx and DS5000/xx
|
||||
*
|
||||
* Handler an interrupt for the control register.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
pmax_errintr()
|
||||
{
|
||||
volatile u_short *sysCSRPtr =
|
||||
(u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);
|
||||
u_short csr;
|
||||
|
||||
csr = *sysCSRPtr;
|
||||
|
||||
if (csr & KN01_CSR_MERR) {
|
||||
printf("Memory error at 0x%x\n",
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
|
||||
panic("Mem error interrupt");
|
||||
}
|
||||
*sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
kn02_errintr()
|
||||
{
|
||||
u_int erradr, chksyn, physadr;
|
||||
int i;
|
||||
|
||||
erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR);
|
||||
chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN);
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
|
||||
if (!(erradr & KN02_ERR_VALID))
|
||||
return;
|
||||
/* extract the physical word address and compensate for pipelining */
|
||||
physadr = erradr & KN02_ERR_ADDRESS;
|
||||
if (!(erradr & KN02_ERR_WRITE))
|
||||
physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
|
||||
physadr <<= 2;
|
||||
printf("%s memory %s %s error at 0x%08x\n",
|
||||
(erradr & KN02_ERR_CPU) ? "CPU" : "DMA",
|
||||
(erradr & KN02_ERR_WRITE) ? "write" : "read",
|
||||
(erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout",
|
||||
physadr);
|
||||
if (erradr & KN02_ERR_ECCERR) {
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
printf("ECC 0x%08x\n", chksyn);
|
||||
|
||||
/* check for a corrected, single bit, read error */
|
||||
if (!(erradr & KN02_ERR_WRITE)) {
|
||||
if (physadr & 0x4) {
|
||||
/* check high word */
|
||||
if (chksyn & KN02_ECC_SNGHI)
|
||||
return;
|
||||
} else {
|
||||
/* check low word */
|
||||
if (chksyn & KN02_ECC_SNGLO)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("Mem error interrupt");
|
||||
}
|
||||
|
||||
#ifdef DS5000_240
|
||||
static void
|
||||
kn03_errintr()
|
||||
{
|
||||
u_int erradr, errsyn, physadr;
|
||||
int i;
|
||||
|
||||
erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR);
|
||||
errsyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRSYN);
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
|
||||
if (!(erradr & KN03_ERR_VALID))
|
||||
return;
|
||||
/* extract the physical word address and compensate for pipelining */
|
||||
physadr = erradr & KN03_ERR_ADDRESS;
|
||||
if (!(erradr & KN03_ERR_WRITE))
|
||||
physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
|
||||
physadr <<= 2;
|
||||
printf("%s memory %s %s error at 0x%08x",
|
||||
(erradr & KN03_ERR_CPU) ? "CPU" : "DMA",
|
||||
(erradr & KN03_ERR_WRITE) ? "write" : "read",
|
||||
(erradr & KN03_ERR_ECCERR) ? "ECC" : "timeout",
|
||||
physadr);
|
||||
if (erradr & KN03_ERR_ECCERR) {
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRSYN) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
printf(" ECC 0x%08x\n", errsyn);
|
||||
|
||||
/* check for a corrected, single bit, read error */
|
||||
if (!(erradr & KN03_ERR_WRITE)) {
|
||||
if (physadr & 0x4) {
|
||||
/* check high word */
|
||||
if (errsyn & KN03_ECC_SNGHI)
|
||||
return;
|
||||
} else {
|
||||
/* check low word */
|
||||
if (errsyn & KN03_ECC_SNGLO)
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
printf("\n");
|
||||
printf("panic(\"Mem error interrupt\");\n");
|
||||
}
|
||||
#endif /* DS5000_240 */
|
||||
|
||||
static void
|
||||
kn02ba_errintr()
|
||||
{
|
||||
register int mer, adr, siz;
|
||||
static int errintr_cnt = 0;
|
||||
|
||||
siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);
|
||||
mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);
|
||||
adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);
|
||||
|
||||
/* clear interrupt bit */
|
||||
*(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
|
||||
|
||||
errintr_cnt++;
|
||||
printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,
|
||||
"Bad memory chip at phys ",
|
||||
kn02ba_recover_erradr(adr, mer),
|
||||
mer, siz, adr);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
kn02ba_recover_erradr(phys, mer)
|
||||
register unsigned phys, mer;
|
||||
{
|
||||
/* phys holds bits 28:2, mer knows which byte */
|
||||
switch (mer & KMIN_MER_LASTBYTE) {
|
||||
case KMIN_LASTB31:
|
||||
mer = 3; break;
|
||||
case KMIN_LASTB23:
|
||||
mer = 2; break;
|
||||
case KMIN_LASTB15:
|
||||
mer = 1; break;
|
||||
case KMIN_LASTB07:
|
||||
mer = 0; break;
|
||||
}
|
||||
return ((phys & KMIN_AER_ADDR_MASK) | mer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* forward declaration
|
||||
*/
|
||||
@ -1997,7 +1236,7 @@ cpu_singlestep(p)
|
||||
uio.uio_rw = UIO_WRITE;
|
||||
uio.uio_procp = curproc;
|
||||
i = procfs_domem(curproc, p, NULL, &uio);
|
||||
machFlushCache(); /* XXX memory barrier followed by flush icache? */
|
||||
MachFlushCache(); /* XXX memory barrier followed by flush icache? */
|
||||
|
||||
if (i < 0)
|
||||
return (EFAULT);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: machdep.c,v 1.46 1996/03/23 04:35:03 jonathan Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.47 1996/03/25 06:44:22 jonathan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
@ -164,7 +164,7 @@ extern void (*tc_enable_interrupt) __P ((u_int slotno,
|
||||
void (*tc_enable_interrupt) __P ((u_int slotno,
|
||||
int (*handler) __P ((void *sc)),
|
||||
void *sc, int onoff));
|
||||
extern int (*pmax_hardware_intr)();
|
||||
extern int (*mips_hardware_intr)();
|
||||
|
||||
int kn02_intr(), kmin_intr(), xine_intr();
|
||||
|
||||
@ -403,7 +403,7 @@ mach_init(argc, argv, code, cv)
|
||||
/*
|
||||
* Set up interrupt handling and I/O addresses.
|
||||
*/
|
||||
pmax_hardware_intr = kn01_intr;
|
||||
mips_hardware_intr = kn01_intr;
|
||||
tc_enable_interrupt = kn01_enable_intr; /*XXX*/
|
||||
Mach_splbio = Mach_spl0;
|
||||
Mach_splnet = Mach_spl1;
|
||||
@ -424,7 +424,7 @@ mach_init(argc, argv, code, cv)
|
||||
/*
|
||||
* Set up interrupt handling and I/O addresses.
|
||||
*/
|
||||
pmax_hardware_intr = kn230_intr;
|
||||
mips_hardware_intr = kn230_intr;
|
||||
tc_enable_interrupt = kn01_enable_intr; /*XXX*/
|
||||
Mach_splbio = Mach_spl0;
|
||||
Mach_splnet = Mach_spl1;
|
||||
@ -456,7 +456,7 @@ mach_init(argc, argv, code, cv)
|
||||
i = *csr_addr;
|
||||
*csr_addr = (i & ~(KN02_CSR_WRESERVED | KN02_CSR_IOINTEN)) |
|
||||
KN02_CSR_CORRECT | 0xff;
|
||||
pmax_hardware_intr = kn02_intr;
|
||||
mips_hardware_intr = kn02_intr;
|
||||
tc_enable_interrupt = kn02_enable_intr;
|
||||
Mach_splbio = Mach_spl0;
|
||||
Mach_splnet = Mach_spl0;
|
||||
@ -479,7 +479,7 @@ mach_init(argc, argv, code, cv)
|
||||
tc_slot_phys_base[1] = KMIN_PHYS_TC_1_START;
|
||||
tc_slot_phys_base[2] = KMIN_PHYS_TC_2_START;
|
||||
ioasic_base = MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
|
||||
pmax_hardware_intr = kmin_intr;
|
||||
mips_hardware_intr = kmin_intr;
|
||||
tc_enable_interrupt = kmin_enable_intr;
|
||||
kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN |
|
||||
KMIN_INTR_TIMEOUT);
|
||||
@ -523,7 +523,7 @@ mach_init(argc, argv, code, cv)
|
||||
tc_slot_phys_base[0] = XINE_PHYS_TC_0_START;
|
||||
tc_slot_phys_base[1] = XINE_PHYS_TC_1_START;
|
||||
ioasic_base = MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
|
||||
pmax_hardware_intr = xine_intr;
|
||||
mips_hardware_intr = xine_intr;
|
||||
tc_enable_interrupt = xine_enable_intr;
|
||||
Mach_splbio = Mach_spl3;
|
||||
Mach_splnet = Mach_spl3;
|
||||
@ -555,7 +555,7 @@ mach_init(argc, argv, code, cv)
|
||||
tc_slot_phys_base[1] = KN03_PHYS_TC_1_START;
|
||||
tc_slot_phys_base[2] = KN03_PHYS_TC_2_START;
|
||||
ioasic_base = MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC);
|
||||
pmax_hardware_intr = kn03_intr;
|
||||
mips_hardware_intr = kn03_intr;
|
||||
tc_enable_interrupt = kn03_enable_intr;
|
||||
Mach_reset_addr =
|
||||
(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trap.c,v 1.32 1996/03/25 05:55:30 jonathan Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.33 1996/03/25 06:44:17 jonathan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
@ -67,30 +67,19 @@
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
||||
/* XXX */
|
||||
#include <pmax/pmax/clockreg.h>
|
||||
#include <pmax/pmax/kn01.h>
|
||||
#include <pmax/pmax/kn02.h>
|
||||
#include <pmax/pmax/kmin.h>
|
||||
#include <pmax/pmax/maxine.h>
|
||||
#include <pmax/pmax/kn03.h>
|
||||
#include <pmax/pmax/asic.h>
|
||||
#include <pmax/pmax/turbochannel.h>
|
||||
|
||||
#include <pmax/stand/dec_prom.h>
|
||||
|
||||
#include "asc.h"
|
||||
#include "sii.h"
|
||||
#include "le.h"
|
||||
#include "dc.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <pmax/pmax/trap.h>
|
||||
|
||||
struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */
|
||||
|
||||
/*
|
||||
* Port-specific hardware interrupt handler
|
||||
*/
|
||||
|
||||
int (*mips_hardware_intr) __P((u_int mask, u_int pc, u_int status,
|
||||
u_int cause)) =
|
||||
( int (*) __P((u_int, u_int, u_int, u_int)) ) 0;
|
||||
|
||||
/*
|
||||
* Exception-handling functions, called via machExceptionTable from locore
|
||||
*/
|
||||
@ -193,6 +182,13 @@ void trapDump __P((char * msg));
|
||||
void cpu_getregs __P((int *regs));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Other forward declarations.
|
||||
*/
|
||||
u_int MachEmulateBranch __P((unsigned *regsPtr,
|
||||
unsigned instPC,
|
||||
unsigned fpcCSR,
|
||||
int allowNonBranch));
|
||||
|
||||
/* extern functions used but not declared elsewhere */
|
||||
extern void MachFPInterrupt __P((u_int status, u_int cause, u_int pc));
|
||||
@ -221,34 +217,6 @@ extern int main __P((void*));
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
|
||||
static void pmax_errintr __P((void));
|
||||
static void kn02_errintr __P((void)), kn02ba_errintr __P((void));
|
||||
|
||||
#ifdef DS5000_240
|
||||
static void kn03_errintr __P ((void));
|
||||
extern u_long kn03_tc3_imask;
|
||||
|
||||
/*
|
||||
* IOASIC 40ns bus-cycle counter, used as hi-resolution clock:
|
||||
* may also be present on (some) XINE, 3min hardware, but not tested there.
|
||||
*/
|
||||
extern u_long ioasic_base; /* Base address of I/O asic */
|
||||
u_long latched_cycle_cnt; /*
|
||||
* IOASIC cycle counter, latched on every
|
||||
* interrupt from RTC chip (64Hz).
|
||||
*/
|
||||
#endif /*DS5000_240*/
|
||||
|
||||
static unsigned kn02ba_recover_erradr __P((u_int phys, u_int mer));
|
||||
extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
|
||||
extern u_long kmin_tc3_imask, xine_tc3_imask;
|
||||
extern const struct callback *callv;
|
||||
|
||||
int (*pmax_hardware_intr) __P((u_int mask, u_int pc, u_int status,
|
||||
u_int cause)) =
|
||||
( int (*) __P((u_int, u_int, u_int, u_int)) ) 0;
|
||||
|
||||
extern volatile struct chiptime *Mach_clock_addr;
|
||||
extern u_long kernelfaults;
|
||||
u_long kernelfaults = 0;
|
||||
@ -869,7 +837,7 @@ out:
|
||||
* Note: curproc might be NULL.
|
||||
*/
|
||||
void
|
||||
interrupt(statusReg, causeReg, pc)
|
||||
interrupt(statusReg, causeReg, pc /* XXX what, args */ )
|
||||
unsigned statusReg; /* status register at time of the exception */
|
||||
unsigned causeReg; /* cause register at time of exception */
|
||||
unsigned pc; /* program counter where to continue */
|
||||
@ -883,7 +851,7 @@ interrupt(statusReg, causeReg, pc)
|
||||
trp->vadr = 0;
|
||||
trp->pc = pc;
|
||||
trp->ra = 0;
|
||||
trp->sp = (int)&args;
|
||||
trp->sp = /* (int)&args */ 0; /* XXX pass args in */
|
||||
trp->code = 0;
|
||||
if (++trp == &trapdebug[TRAPSIZE])
|
||||
trp = trapdebug;
|
||||
@ -891,8 +859,8 @@ interrupt(statusReg, causeReg, pc)
|
||||
|
||||
cnt.v_intr++;
|
||||
mask = causeReg & statusReg; /* pending interrupts & enable mask */
|
||||
if (pmax_hardware_intr)
|
||||
splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg));
|
||||
if (mips_hardware_intr)
|
||||
splx((*mips_hardware_intr)(mask, pc, statusReg, causeReg));
|
||||
if (mask & MACH_INT_MASK_5) {
|
||||
intrcnt[FPU_INTR]++;
|
||||
if (!USERMODE(statusReg)) {
|
||||
@ -950,568 +918,6 @@ interrupt(statusReg, causeReg, pc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle pmax (DECstation 2100/3100) interrupts.
|
||||
*/
|
||||
int
|
||||
kn01_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
extern struct cfdriver sii_cd;
|
||||
extern struct cfdriver le_cd;
|
||||
extern struct cfdriver dc_cd;
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
|
||||
/* keep clock interrupts enabled */
|
||||
causeReg &= ~MACH_INT_MASK_3;
|
||||
}
|
||||
/* Re-enable clock interrupts */
|
||||
splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);
|
||||
#if NSII > 0
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
intrcnt[SCSI_INTR]++;
|
||||
siiintr(sii_cd.cd_devs[0]);
|
||||
}
|
||||
#endif
|
||||
#if NLE > 0
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
|
||||
/*
|
||||
* tty interrupts were disabled by the splx() call
|
||||
* that re-enables clock interrupts. A slip or ppp driver
|
||||
* manipulating if queues should have called splimp(),
|
||||
* which would mask out MACH_INT_MASK_1.
|
||||
*/
|
||||
leintr(le_cd.cd_devs[0]);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
#endif
|
||||
#if NDC > 0
|
||||
if (mask & MACH_INT_MASK_2) {
|
||||
dcintr(dc_cd.cd_devs[0]);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
#endif
|
||||
if (mask & MACH_INT_MASK_4) {
|
||||
pmax_errintr();
|
||||
intrcnt[ERROR_INTR]++;
|
||||
}
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle hardware interrupts for the KN02. (DECstation 5000/200)
|
||||
* Returns spl value.
|
||||
*/
|
||||
int
|
||||
kn02_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register unsigned i, m;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
register unsigned csr;
|
||||
int temp;
|
||||
struct clockframe cf;
|
||||
static int warned = 0;
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
|
||||
if ((csr & KN02_CSR_PSWARN) && !warned) {
|
||||
warned = 1;
|
||||
printf("WARNING: power supply is overheating!\n");
|
||||
} else if (warned && !(csr & KN02_CSR_PSWARN)) {
|
||||
warned = 0;
|
||||
printf("WARNING: power supply is OK again\n");
|
||||
}
|
||||
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
|
||||
/* keep clock interrupts enabled */
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* Re-enable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
static int intr_map[8] = { SLOT0_INTR, SLOT1_INTR, SLOT2_INTR,
|
||||
/* these two bits reserved */
|
||||
STRAY_INTR, STRAY_INTR,
|
||||
SCSI_INTR, LANCE_INTR,
|
||||
SERIAL0_INTR };
|
||||
|
||||
csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
|
||||
m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;
|
||||
#if 0
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
|
||||
(csr & ~(KN02_CSR_WRESERVED | 0xFF)) |
|
||||
(m << KN02_CSR_IOINTEN_SHIFT);
|
||||
#endif
|
||||
for (i = 0; m; i++, m >>= 1) {
|
||||
if (!(m & 1))
|
||||
continue;
|
||||
intrcnt[intr_map[i]]++;
|
||||
if (tc_slot_info[i].intr)
|
||||
(*tc_slot_info[i].intr)(tc_slot_info[i].sc);
|
||||
else
|
||||
printf("spurious interrupt %d\n", i);
|
||||
}
|
||||
#if 0
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
|
||||
csr & ~(KN02_CSR_WRESERVED | 0xFF);
|
||||
#endif
|
||||
}
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intrcnt[ERROR_INTR]++;
|
||||
kn02_errintr();
|
||||
}
|
||||
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3min hardware interrupts. (DECstation 5000/1xx)
|
||||
*/
|
||||
int
|
||||
kmin_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp =
|
||||
(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK);
|
||||
volatile u_int *intrp =
|
||||
(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR);
|
||||
unsigned int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
static int user_warned = 0;
|
||||
|
||||
old_mask = *imaskp & kmin_tc3_imask;
|
||||
*imaskp = kmin_tc3_imask |
|
||||
(KMIN_IM0 & ~(KN03_INTR_TC_0|KN03_INTR_TC_1|KN03_INTR_TC_2));
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intr = *intrp;
|
||||
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if (intr & KMIN_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & KMIN_INTR_LANCE_READ_E)
|
||||
*intrp &= ~KMIN_INTR_LANCE_READ_E;
|
||||
|
||||
if (intr & KMIN_INTR_TIMEOUT)
|
||||
kn02ba_errintr();
|
||||
|
||||
if (intr & KMIN_INTR_CLOCK) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCC_0) &&
|
||||
tc_slot_info[KMIN_SCC0_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCC0_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCC0_SLOT].sc);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCC_1) &&
|
||||
tc_slot_info[KMIN_SCC1_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCC1_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCC1_SLOT].sc);
|
||||
intrcnt[SERIAL1_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_SCSI) &&
|
||||
tc_slot_info[KMIN_SCSI_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_SCSI_SLOT].intr))
|
||||
(tc_slot_info[KMIN_SCSI_SLOT].sc);
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KMIN_INTR_LANCE) &&
|
||||
tc_slot_info[KMIN_LANCE_SLOT].intr) {
|
||||
(*(tc_slot_info[KMIN_LANCE_SLOT].intr))
|
||||
(tc_slot_info[KMIN_LANCE_SLOT].sc);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
|
||||
if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
|
||||
printf("%s\n", "Power supply ok now.");
|
||||
user_warned = 0;
|
||||
}
|
||||
if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
|
||||
user_warned++;
|
||||
printf("%s\n", "Power supply overheating");
|
||||
}
|
||||
}
|
||||
if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr) {
|
||||
(*tc_slot_info[0].intr)(tc_slot_info[0].sc);
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
|
||||
if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr) {
|
||||
(*tc_slot_info[1].intr)(tc_slot_info[1].sc);
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr) {
|
||||
(*tc_slot_info[2].intr)(tc_slot_info[2].sc);
|
||||
intrcnt[SLOT2_INTR]++;
|
||||
}
|
||||
|
||||
#if 0 /*XXX*/
|
||||
if (mask & (MACH_INT_MASK_2|MACH_INT_MASK_1|MACH_INT_MASK_0))
|
||||
printf("kmin: slot intr, mask 0x%x\n",
|
||||
mask &
|
||||
(MACH_INT_MASK_2|MACH_INT_MASK_1|MACH_INT_MASK_0));
|
||||
#endif
|
||||
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maxine hardware interrupts. (Personal DECstation 5000/xx)
|
||||
*/
|
||||
int
|
||||
xine_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK);
|
||||
volatile u_int *intrp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
|
||||
u_int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
|
||||
old_mask = *imaskp & xine_tc3_imask;
|
||||
*imaskp = xine_tc3_imask;
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* reenable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
|
||||
if (mask & MACH_INT_MASK_3) {
|
||||
intr = *intrp;
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if ((intr & XINE_INTR_SCC_0)) {
|
||||
if (tc_slot_info[XINE_SCC0_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_SCC0_SLOT].intr))
|
||||
(tc_slot_info[XINE_SCC0_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle scc interrupt\n");
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~XINE_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & XINE_INTR_LANCE_READ_E)
|
||||
*intrp &= ~XINE_INTR_LANCE_READ_E;
|
||||
|
||||
if (intr & XINE_INTR_DTOP_RX) {
|
||||
if (tc_slot_info[XINE_DTOP_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_DTOP_SLOT].intr))
|
||||
(tc_slot_info[XINE_DTOP_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle dtop interrupt\n");
|
||||
intrcnt[DTOP_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_FLOPPY) {
|
||||
if (tc_slot_info[XINE_FLOPPY_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_FLOPPY_SLOT].intr))
|
||||
(tc_slot_info[XINE_FLOPPY_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle floppy interrupt\n");
|
||||
intrcnt[FLOPPY_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_TC_0) {
|
||||
if (tc_slot_info[0].intr)
|
||||
(*(tc_slot_info[0].intr))
|
||||
(tc_slot_info[0].sc);
|
||||
else
|
||||
printf ("can't handle tc0 interrupt\n");
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_TC_1) {
|
||||
if (tc_slot_info[1].intr)
|
||||
(*(tc_slot_info[1].intr))
|
||||
(tc_slot_info[1].sc);
|
||||
else
|
||||
printf ("can't handle tc1 interrupt\n");
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_ISDN) {
|
||||
if (tc_slot_info[XINE_ISDN_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_ISDN_SLOT].intr))
|
||||
(tc_slot_info[XINE_ISDN_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle isdn interrupt\n");
|
||||
intrcnt[ISDN_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_SCSI) {
|
||||
if (tc_slot_info[XINE_SCSI_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_SCSI_SLOT].intr))
|
||||
(tc_slot_info[XINE_SCSI_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle scsi interrupt\n");
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if (intr & XINE_INTR_LANCE) {
|
||||
if (tc_slot_info[XINE_LANCE_SLOT].intr)
|
||||
(*(tc_slot_info[XINE_LANCE_SLOT].intr))
|
||||
(tc_slot_info[XINE_LANCE_SLOT].sc);
|
||||
else
|
||||
printf ("can't handle lance interrupt\n");
|
||||
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
}
|
||||
if (mask & MACH_INT_MASK_2)
|
||||
kn02ba_errintr();
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
|
||||
#ifdef DS5000_240
|
||||
/*
|
||||
* 3Max+ hardware interrupts. (DECstation 5000/240) UNTESTED!!
|
||||
*/
|
||||
int
|
||||
kn03_intr(mask, pc, statusReg, causeReg)
|
||||
unsigned mask;
|
||||
unsigned pc;
|
||||
unsigned statusReg;
|
||||
unsigned causeReg;
|
||||
{
|
||||
register u_int intr;
|
||||
register volatile struct chiptime *c = Mach_clock_addr;
|
||||
volatile u_int *imaskp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(KN03_REG_IMSK);
|
||||
volatile u_int *intrp = (volatile u_int *)
|
||||
MACH_PHYS_TO_UNCACHED(KN03_REG_INTR);
|
||||
u_int old_mask;
|
||||
struct clockframe cf;
|
||||
int temp;
|
||||
static int user_warned = 0;
|
||||
register u_long old_buscycle = latched_cycle_cnt;
|
||||
|
||||
old_mask = *imaskp & kn03_tc3_imask;
|
||||
*imaskp = kn03_tc3_imask;
|
||||
|
||||
if (mask & MACH_INT_MASK_4)
|
||||
(*callv->_halt)((int *)0, 0);
|
||||
|
||||
/* handle clock interrupts ASAP */
|
||||
if (mask & MACH_INT_MASK_1) {
|
||||
temp = c->regc; /* XXX clear interrupt bits */
|
||||
cf.pc = pc;
|
||||
cf.sr = statusReg;
|
||||
latched_cycle_cnt = *(u_long*)(IOASIC_REG_CTR(ioasic_base));
|
||||
hardclock(&cf);
|
||||
intrcnt[HARDCLOCK]++;
|
||||
old_buscycle = latched_cycle_cnt - old_buscycle;
|
||||
causeReg &= ~MACH_INT_MASK_1;
|
||||
}
|
||||
/* reenable clock interrupts */
|
||||
splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
|
||||
|
||||
/*
|
||||
* Check for late clock interrupts (allow 10% slop). Be careful
|
||||
* to do so only after calling hardclock(), due to logging cost.
|
||||
* Even then, logging dropped ticks just causes more clock
|
||||
* ticks to be missed.
|
||||
*/
|
||||
#ifdef notdef
|
||||
if ((mask & MACH_INT_MASK_1) && old_buscycle > (tick+49) * 25) {
|
||||
extern int msgbufmapped;
|
||||
if(msgbufmapped && 0)
|
||||
addlog("kn03: clock intr %d usec late\n",
|
||||
old_buscycle/25);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* IOCTL asic DMA-related interrupts should be checked here,
|
||||
* and DMA pointers serviced as soon as possible.
|
||||
*/
|
||||
|
||||
if (mask & MACH_INT_MASK_0) {
|
||||
intr = *intrp;
|
||||
/* masked interrupts are still observable */
|
||||
intr &= old_mask;
|
||||
|
||||
if (intr & KN03_INTR_SCSI_PTR_LOAD) {
|
||||
*intrp &= ~KN03_INTR_SCSI_PTR_LOAD;
|
||||
#ifdef notdef
|
||||
asc_dma_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* DMA and non-DMA interrupts from the IOCTl asic all use the
|
||||
* single interrupt request line from the IOCTL asic.
|
||||
* Disabling IOASIC interrupts while servicing network or
|
||||
* disk-driver interrupts causes DMA overruns. NON-dma IOASIC
|
||||
* interrupts should be disabled in the ioasic, and
|
||||
* interrupts from the IOASIC itself should be re-enabled.
|
||||
* DMA interrupts can then be serviced whilst still servicing
|
||||
* non-DMA interrupts from ioctl devices or TC options.
|
||||
*/
|
||||
|
||||
if (intr & (KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E))
|
||||
*intrp &= ~(KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
|
||||
|
||||
if (intr & KN03_INTR_LANCE_READ_E)
|
||||
*intrp &= ~KN03_INTR_LANCE_READ_E;
|
||||
|
||||
if ((intr & KN03_INTR_SCC_0) &&
|
||||
tc_slot_info[KN03_SCC0_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCC0_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCC0_SLOT].sc);
|
||||
intrcnt[SERIAL0_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_SCC_1) &&
|
||||
tc_slot_info[KN03_SCC1_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCC1_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCC1_SLOT].sc);
|
||||
intrcnt[SERIAL1_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_TC_0) &&
|
||||
tc_slot_info[0].intr) {
|
||||
(*(tc_slot_info[0].intr))
|
||||
(tc_slot_info[0].sc);
|
||||
intrcnt[SLOT0_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_0)
|
||||
printf ("can't handle tc0 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_TC_1) &&
|
||||
tc_slot_info[1].intr) {
|
||||
(*(tc_slot_info[1].intr))
|
||||
(tc_slot_info[1].sc);
|
||||
intrcnt[SLOT1_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_1)
|
||||
printf ("can't handle tc1 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_TC_2) &&
|
||||
tc_slot_info[2].intr) {
|
||||
(*(tc_slot_info[2].intr))
|
||||
(tc_slot_info[2].sc);
|
||||
intrcnt[SLOT2_INTR]++;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (intr & KN03_INTR_TC_2)
|
||||
printf ("can't handle tc2 interrupt\n");
|
||||
#endif /*DIAGNOSTIC*/
|
||||
|
||||
if ((intr & KN03_INTR_SCSI) &&
|
||||
tc_slot_info[KN03_SCSI_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_SCSI_SLOT].intr))
|
||||
(tc_slot_info[KN03_SCSI_SLOT].sc);
|
||||
intrcnt[SCSI_INTR]++;
|
||||
}
|
||||
|
||||
if ((intr & KN03_INTR_LANCE) &&
|
||||
tc_slot_info[KN03_LANCE_SLOT].intr) {
|
||||
(*(tc_slot_info[KN03_LANCE_SLOT].intr))
|
||||
(tc_slot_info[KN03_LANCE_SLOT].sc);
|
||||
intrcnt[LANCE_INTR]++;
|
||||
}
|
||||
|
||||
if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) {
|
||||
printf("%s\n", "Power supply ok now.");
|
||||
user_warned = 0;
|
||||
}
|
||||
if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) {
|
||||
user_warned++;
|
||||
printf("%s\n", "Power supply overheating");
|
||||
}
|
||||
}
|
||||
if (mask & MACH_INT_MASK_3)
|
||||
kn03_errintr();
|
||||
return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
|
||||
MACH_SR_INT_ENA_CUR);
|
||||
}
|
||||
#endif /* DS5000_240 */
|
||||
|
||||
/*
|
||||
* This is called from MachUserIntr() if astpending is set.
|
||||
@ -1586,173 +992,6 @@ trapDump(msg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* MemErrorInterrupts --
|
||||
* pmax_errintr - for the DS2100/DS3100
|
||||
* kn02_errintr - for the DS5000/200
|
||||
* kn02ba_errintr - for the DS5000/1xx and DS5000/xx
|
||||
*
|
||||
* Handler an interrupt for the control register.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
pmax_errintr()
|
||||
{
|
||||
volatile u_short *sysCSRPtr =
|
||||
(u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);
|
||||
u_short csr;
|
||||
|
||||
csr = *sysCSRPtr;
|
||||
|
||||
if (csr & KN01_CSR_MERR) {
|
||||
printf("Memory error at 0x%x\n",
|
||||
*(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
|
||||
panic("Mem error interrupt");
|
||||
}
|
||||
*sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
kn02_errintr()
|
||||
{
|
||||
u_int erradr, chksyn, physadr;
|
||||
int i;
|
||||
|
||||
erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR);
|
||||
chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN);
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
|
||||
if (!(erradr & KN02_ERR_VALID))
|
||||
return;
|
||||
/* extract the physical word address and compensate for pipelining */
|
||||
physadr = erradr & KN02_ERR_ADDRESS;
|
||||
if (!(erradr & KN02_ERR_WRITE))
|
||||
physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
|
||||
physadr <<= 2;
|
||||
printf("%s memory %s %s error at 0x%08x\n",
|
||||
(erradr & KN02_ERR_CPU) ? "CPU" : "DMA",
|
||||
(erradr & KN02_ERR_WRITE) ? "write" : "read",
|
||||
(erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout",
|
||||
physadr);
|
||||
if (erradr & KN02_ERR_ECCERR) {
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
printf("ECC 0x%08x\n", chksyn);
|
||||
|
||||
/* check for a corrected, single bit, read error */
|
||||
if (!(erradr & KN02_ERR_WRITE)) {
|
||||
if (physadr & 0x4) {
|
||||
/* check high word */
|
||||
if (chksyn & KN02_ECC_SNGHI)
|
||||
return;
|
||||
} else {
|
||||
/* check low word */
|
||||
if (chksyn & KN02_ECC_SNGLO)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("Mem error interrupt");
|
||||
}
|
||||
|
||||
#ifdef DS5000_240
|
||||
static void
|
||||
kn03_errintr()
|
||||
{
|
||||
u_int erradr, errsyn, physadr;
|
||||
int i;
|
||||
|
||||
erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR);
|
||||
errsyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRSYN);
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
|
||||
if (!(erradr & KN03_ERR_VALID))
|
||||
return;
|
||||
/* extract the physical word address and compensate for pipelining */
|
||||
physadr = erradr & KN03_ERR_ADDRESS;
|
||||
if (!(erradr & KN03_ERR_WRITE))
|
||||
physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
|
||||
physadr <<= 2;
|
||||
printf("%s memory %s %s error at 0x%08x",
|
||||
(erradr & KN03_ERR_CPU) ? "CPU" : "DMA",
|
||||
(erradr & KN03_ERR_WRITE) ? "write" : "read",
|
||||
(erradr & KN03_ERR_ECCERR) ? "ECC" : "timeout",
|
||||
physadr);
|
||||
if (erradr & KN03_ERR_ECCERR) {
|
||||
*(u_int *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRSYN) = 0;
|
||||
MachEmptyWriteBuffer();
|
||||
printf(" ECC 0x%08x\n", errsyn);
|
||||
|
||||
/* check for a corrected, single bit, read error */
|
||||
if (!(erradr & KN03_ERR_WRITE)) {
|
||||
if (physadr & 0x4) {
|
||||
/* check high word */
|
||||
if (errsyn & KN03_ECC_SNGHI)
|
||||
return;
|
||||
} else {
|
||||
/* check low word */
|
||||
if (errsyn & KN03_ECC_SNGLO)
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
printf("\n");
|
||||
printf("panic(\"Mem error interrupt\");\n");
|
||||
}
|
||||
#endif /* DS5000_240 */
|
||||
|
||||
static void
|
||||
kn02ba_errintr()
|
||||
{
|
||||
register int mer, adr, siz;
|
||||
static int errintr_cnt = 0;
|
||||
|
||||
siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);
|
||||
mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);
|
||||
adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);
|
||||
|
||||
/* clear interrupt bit */
|
||||
*(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
|
||||
|
||||
errintr_cnt++;
|
||||
printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,
|
||||
"Bad memory chip at phys ",
|
||||
kn02ba_recover_erradr(adr, mer),
|
||||
mer, siz, adr);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
kn02ba_recover_erradr(phys, mer)
|
||||
register unsigned phys, mer;
|
||||
{
|
||||
/* phys holds bits 28:2, mer knows which byte */
|
||||
switch (mer & KMIN_MER_LASTBYTE) {
|
||||
case KMIN_LASTB31:
|
||||
mer = 3; break;
|
||||
case KMIN_LASTB23:
|
||||
mer = 2; break;
|
||||
case KMIN_LASTB15:
|
||||
mer = 1; break;
|
||||
case KMIN_LASTB07:
|
||||
mer = 0; break;
|
||||
}
|
||||
return ((phys & KMIN_AER_ADDR_MASK) | mer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* forward declaration
|
||||
*/
|
||||
@ -1997,7 +1236,7 @@ cpu_singlestep(p)
|
||||
uio.uio_rw = UIO_WRITE;
|
||||
uio.uio_procp = curproc;
|
||||
i = procfs_domem(curproc, p, NULL, &uio);
|
||||
machFlushCache(); /* XXX memory barrier followed by flush icache? */
|
||||
MachFlushCache(); /* XXX memory barrier followed by flush icache? */
|
||||
|
||||
if (i < 0)
|
||||
return (EFAULT);
|
||||
|
Loading…
Reference in New Issue
Block a user