date and time created 92/07/13 00:44:35 by torek
authorChris Torek <torek@ucbvax.Berkeley.EDU>
Mon, 13 Jul 1992 15:44:35 +0000 (07:44 -0800)
committerChris Torek <torek@ucbvax.Berkeley.EDU>
Mon, 13 Jul 1992 15:44:35 +0000 (07:44 -0800)
SCCS-vsn: sys/sparc/sparc/intr.c 7.1
SCCS-vsn: sys/sparc/sparc/intreg.h 7.1

usr/src/sys/sparc/sparc/intr.c [new file with mode: 0644]
usr/src/sys/sparc/sparc/intreg.h [new file with mode: 0644]

diff --git a/usr/src/sys/sparc/sparc/intr.c b/usr/src/sys/sparc/sparc/intr.c
new file mode 100644 (file)
index 0000000..4a3d36a
--- /dev/null
@@ -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 (file)
index 0000000..cecd7c7
--- /dev/null
@@ -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