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:
jonathan 1996-03-25 06:44:17 +00:00
parent 458024d39d
commit 97f32908b1
4 changed files with 52 additions and 3016 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);