From: Chris Torek Date: Mon, 13 Jul 1992 15:44:35 +0000 (-0800) Subject: date and time created 92/07/13 00:44:35 by torek X-Git-Tag: BSD-4_4-Snapshot-Development~5767 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/3aa857011d91d949b2bba558cf9d365b8e0676e2 date and time created 92/07/13 00:44:35 by torek SCCS-vsn: sys/sparc/sparc/intr.c 7.1 SCCS-vsn: sys/sparc/sparc/intreg.h 7.1 --- diff --git a/usr/src/sys/sparc/sparc/intr.c b/usr/src/sys/sparc/sparc/intr.c new file mode 100644 index 0000000000..4a3d36a3fd --- /dev/null +++ b/usr/src/sys/sparc/sparc/intr.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * %sccs.include.redist.c% + * + * @(#)intr.c 7.1 (Berkeley) %G% + * + * from: $Header: intr.c,v 1.18 92/07/09 00:47:43 torek Exp $ (LBL) + */ + +#include "sys/param.h" +#include "sys/kernel.h" + +#include "net/netisr.h" + +#include "machine/cpu.h" +#ifdef DIAGNOSTIC +#include "machine/instr.h" +#endif +#include "machine/trap.h" + +#include "clockreg.h" +#include "ctlreg.h" + +/* + * Stray interrupt handler. Clear it if possible. + * If not, and if we get 10 interrupts in 10 seconds, panic. + */ +void +strayintr(fp) + struct clockframe *fp; +{ + static int straytime, nstray; + int timesince; + + printf("stray interrupt ipl %x pc=%x npc=%x psr=%b\n", + fp->ipl, fp->pc, fp->npc, fp->psr, PSR_BITS); + timesince = time.tv_sec - straytime; + straytime = time.tv_sec; + if (timesince <= 10) { + if (++nstray > 9) + panic("crazy interrupts"); + } else { + straytime = time.tv_sec; + nstray = 1; + } +} + +extern int clockintr(); /* level 10 (clock) interrupt code */ +static struct intrhand level10 = { clockintr }; + +extern int statintr(); /* level 14 (statclock) interrupt code */ +static struct intrhand level14 = { statintr }; + +/* + * Level 1 software interrupt (could also be Sbus level 1 interrupt). + * Three possible reasons: + * ROM console input needed + * Network software interrupt + * Soft clock interrupt + */ +int +soft01intr(fp) + void *fp; +{ + extern int rom_console_input; + + if (rom_console_input && cnrom()) + cnrint(); + if (sir.sir_any) { + /* + * XXX this is bogus: should just have a list of + * routines to call, a la timeouts. Mods to + * netisr are not atomic and must be protected (gah). + */ + if (sir.sir_which[SIR_NET]) { + int n, s; + + s = splhigh(); + n = netisr; + netisr = 0; + splx(s); + sir.sir_which[SIR_NET] = 0; +#ifdef INET + if (n & (1 << NETISR_ARP)) + arpintr(); + if (n & (1 << NETISR_IP)) + ipintr(); +#endif +#ifdef NS + if (n & (1 << NETISR_NS)) + nsintr(); +#endif +#ifdef ISO + if (n & (1 << NETISR_ISO)) + clnlintr(); +#endif + } + if (sir.sir_which[SIR_CLOCK]) { + sir.sir_which[SIR_CLOCK] = 0; + softclock(); + } + } + return (1); +} + +static struct intrhand level01 = { soft01intr }; + +/* + * Level 15 interrupts are special, and not vectored here. + * Only `prewired' interrupts appear here; boot-time configured devices + * are attached via intr_establish() below. + */ +struct intrhand *intrhand[15] = { + NULL, /* 0 = error */ + &level01, /* 1 = software level 1 + Sbus */ + NULL, /* 2 = Sbus level 2 */ + NULL, /* 3 = SCSI + DMA + Sbus level 3 */ + NULL, /* 4 = software level 4 (tty softint) */ + NULL, /* 5 = Ethernet + Sbus level 4 */ + NULL, /* 6 = software level 6 (not used) */ + NULL, /* 7 = video + Sbus level 5 */ + NULL, /* 8 = Sbus level 6 */ + NULL, /* 9 = Sbus level 7 */ + &level10, /* 10 = counter 0 = clock */ + NULL, /* 11 = floppy */ + NULL, /* 12 = zs hardware interrupt */ + NULL, /* 13 = audio chip */ + &level14, /* 14 = counter 1 = profiling timer */ +}; + +static int fastvec; /* marks fast vectors (see below) */ +#ifdef DIAGNOSTIC +extern int sparc_interrupt[]; +#endif + +/* + * Attach an interrupt handler to the vector chain for the given level. + * This is not possible if it has been taken away as a fast vector. + */ +void +intr_establish(level, ih) + int level; + struct intrhand *ih; +{ + register struct intrhand **p, *q; +#ifdef DIAGNOSTIC + register struct trapvec *tv; + register int displ; +#endif + int s; + + s = splhigh(); + if (fastvec & (1 << level)) + panic("intr_establish: level %d interrupt tied to fast vector", + level); +#ifdef DIAGNOSTIC + /* double check for legal hardware interrupt */ + if (level != 1 && level != 4 && level != 6) { + tv = &trapbase[T_L1INT - 1 + level]; + displ = &sparc_interrupt[0] - &tv->tv_instr[1]; + /* has to be `mov level,%l3; ba _sparc_interrupt; rdpsr %l0' */ + if (tv->tv_instr[0] != I_MOVi(I_L3, level) || + tv->tv_instr[1] != I_BA(0, displ) || + tv->tv_instr[2] != I_RDPSR(I_L0)) + panic("intr_establish(%d, %x)\n%x %x %x != %x %x %x", + level, ih, + tv->tv_instr[0], tv->tv_instr[1], tv->tv_instr[2], + I_MOVi(I_L3, level), I_BA(0, displ), I_RDPSR(I_L0)); + } +#endif + /* + * This is O(N^2) for long chains, but chains are never long + * and we do want to preserve order. + */ + for (p = &intrhand[level]; (q = *p) != NULL; p = &q->ih_next) + continue; + *p = ih; + ih->ih_next = NULL; + splx(s); +} + +/* + * Like intr_establish, but wires a fast trap vector. Only one such fast + * trap is legal for any interrupt, and it must be a hardware interrupt. + */ +void +intr_fasttrap(level, vec) + int level; + void (*vec) __P((void)); +{ + register struct trapvec *tv; + register u_long hi22, lo10; +#ifdef DIAGNOSTIC + register int displ; /* suspenders, belt, and buttons too */ +#endif + int s; + + tv = &trapbase[T_L1INT - 1 + level]; + hi22 = ((u_long)vec) >> 10; + lo10 = ((u_long)vec) & 0x3ff; + s = splhigh(); + if ((fastvec & (1 << level)) != 0 || intrhand[level] != NULL) + panic("intr_fasttrap: already handling level %d interrupts", + level); +#ifdef DIAGNOSTIC + displ = &sparc_interrupt[0] - &tv->tv_instr[1]; + /* has to be `mov level,%l3; ba _sparc_interrupt; rdpsr %l0' */ + if (tv->tv_instr[0] != I_MOVi(I_L3, level) || + tv->tv_instr[1] != I_BA(0, displ) || + tv->tv_instr[2] != I_RDPSR(I_L0)) + panic("intr_fasttrap(%d, %x)\n%x %x %x != %x %x %x", + level, vec, + tv->tv_instr[0], tv->tv_instr[1], tv->tv_instr[2], + I_MOVi(I_L3, level), I_BA(0, displ), I_RDPSR(I_L0)); +#endif + tv->tv_instr[0] = I_SETHI(I_L3, hi22); /* sethi %hi(vec),%l3 */ + tv->tv_instr[1] = I_JMPLri(I_G0, I_L3, lo10);/* jmpl %l3+%lo(vec),%g0 */ + tv->tv_instr[2] = I_RDPSR(I_L0); /* mov %psr, %l0 */ + fastvec |= 1 << level; + splx(s); +} diff --git a/usr/src/sys/sparc/sparc/intreg.h b/usr/src/sys/sparc/sparc/intreg.h new file mode 100644 index 0000000000..cecd7c7f59 --- /dev/null +++ b/usr/src/sys/sparc/sparc/intreg.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * %sccs.include.redist.c% + * + * @(#)intreg.h 7.1 (Berkeley) %G% + * + * from: $Header: intreg.h,v 1.6 92/06/17 05:22:06 torek Exp $ (LBL) + */ + +/* + * sun4c interrupt enable register. + * + * The register is a single byte. C code must use the ienab_bis and + * ienab_bic functions found in locore.s. + * + * The register's physical address is defined here as the register + * must be mapped early in the boot process (otherwise NMI handling + * will fail). + */ +#define INT_ENABLE_REG_PHYSADR 0xf5000000 /* phys addr in IOspace */ + +/* + * Bits in interrupt enable register. Software interrupt requests must + * be cleared in software. This is done in locore.s. The ALLIE bit must + * be cleared to clear asynchronous memory error (level 15) interrupts. + */ +#define IE_L14 0x80 /* enable level 14 (counter 1) interrupts */ +#define IE_L10 0x20 /* enable level 10 (counter 0) interrupts */ +#define IE_L8 0x10 /* enable level 8 interrupts */ +#define IE_L6 0x08 /* request software level 6 interrupt */ +#define IE_L4 0x04 /* request software level 4 interrupt */ +#define IE_L1 0x02 /* request software level 1 interrupt */ +#define IE_ALLIE 0x01 /* enable interrupts */ + +#ifndef LOCORE +void ienab_bis __P((int bis)); /* set given bits */ +void ienab_bic __P((int bic)); /* clear given bits */ +#endif