Subject: Re: sharing mips softintr code (Re: generic soft interrupt patch)
To: None <simonb@wasabisystems.com, port-mips@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-arc
Date: 04/28/2003 21:13:09
In article <030428190330.M0110392@mirage.ceres.dti.ne.jp>
I wrote:

> In article <20030428092759.44A1953E7F@thoreau.thistledown.com.au>
> simonb@wasabisystems.com wrote:
> 
> > It'd be nice if we could move all softintr support to somewhere under
> > sys/arch/mips.  Most of arc_trap.c should (with these patches) now be
> > the same as at least the algor, evbmips, mipsco and pmax interrupt.c
> > and the sbmips and sgimips softintr.c.
> 
> Yes, we should share softintr code among all mips ports,
> but I wonder how to migrate to shared code..

Ok, I've made a new patch for arc and newsmips with shared
mips/mips/softintr.c and mips/include/softintr.h
for a start point (works on both NEC-JC94 and NWS-5000).

I'm wondering if _IPL_NSOFT should be MD or not,
but I think all IPL_* and spl*() definitions could
be moved into MI <mips/intr.h> eventually so that
ipl_si_to_sr[] can be moved from machdep.c to mips/softintr.c.

Comments?
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

Index: arc/arc/arc_trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/arc_trap.c,v
retrieving revision 1.24
diff -u -r1.24 arc_trap.c
--- arc/arc/arc_trap.c	2003/04/27 17:13:01	1.24
+++ arc/arc/arc_trap.c	2003/04/28 12:07:33
@@ -46,6 +46,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -133,15 +134,14 @@
 	u_int32_t pc;
 	u_int32_t ipending;		/* pending interrupts & enable mask */
 {
-#if defined(MIPS3) && defined(MIPS_INT_MASK_CLOCK)
-	if ((ipending & MIPS_INT_MASK_CLOCK) && CPUISMIPS3) {
+
+	if (ipending & MIPS_INT_MASK_CLOCK) {
 		/*
 		 *  Writing a value to the Compare register,
 		 *  as a side effect, clears the timer interrupt request.
 		 */
 		mips3_cp0_compare_write(mips3_cp0_count_read());
 	}
-#endif
 
 	uvmexp.intrs++;
 	/* real device interrupt */
@@ -149,30 +149,12 @@
 		_splset(arc_hardware_intr(status, cause, pc, ipending));
 	}
 
-#if defined(MIPS1) && defined(INT_MASK_FPU)
-	if ((ipending & INT_MASK_FPU) && CPUISMIPS1) {
-		intrcnt[FPU_INTR]++;
-		if (!USERMODE(status))
-			panic("kernel used FPU: PC %x, CR %x, SR %x",
-			    pc, cause, status);
-#if !defined(SOFTFLOAT)
-		MachFPInterrupt(status, cause, pc, curlwp->l_md.md_regs);
-#endif
-	}
-#endif
+	/* software interrupts */
+	ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0);
+	if (ipending == 0)
+		return;
 
-	/* 'softnet' interrupt */
-	if (ipending & MIPS_SOFT_INT_MASK_1) {
-		clearsoftnet();
-		uvmexp.softs++;
-		netintr();
-	}
+	_clrsoftintr(ipending);
 
-	/* 'softclock' interrupt */
-	if (ipending & MIPS_SOFT_INT_MASK_0) {
-		clearsoftclock();
-		uvmexp.softs++;
-		intrcnt[SOFTCLOCK_INTR]++;
-		softclock(NULL);
-	}
+	softintr_dispatch(ipending);
 }
Index: arc/arc/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/autoconf.c,v
retrieving revision 1.18
diff -u -r1.18 autoconf.c
--- arc/arc/autoconf.c	2002/09/27 02:24:09	1.18
+++ arc/arc/autoconf.c	2003/04/28 12:07:34
@@ -91,6 +91,9 @@
 void
 cpu_configure()
 {
+
+	softintr_init();
+
 	(void)splhigh();	/* To be really sure.. */
 	if (config_rootfound("mainbus", "mainbus") == NULL)
 		panic("no mainbus found");
Index: arc/arc/c_magnum.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/c_magnum.c,v
retrieving revision 1.3
diff -u -r1.3 c_magnum.c
--- arc/arc/c_magnum.c	2003/04/27 11:33:36	1.3
+++ arc/arc/c_magnum.c	2003/04/28 12:07:34
@@ -80,6 +80,54 @@
 	timer_magnum_init,
 };
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+static const u_int32_t magnum_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3,		/* IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3,		/* IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3,		/* IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* IPL_{CLOCK,HIGH} */
+};
+
 int
 timer_magnum_intr(mask, cf)
 	u_int mask;
@@ -189,12 +237,7 @@
 	/*
 	 * Initialize interrupt priority
 	 */
-	splvec.splnet = MIPS_INT_MASK_SPL3;
-	splvec.splbio = MIPS_INT_MASK_SPL3;
-	splvec.splvm = MIPS_INT_MASK_SPL3;
-	splvec.spltty = MIPS_INT_MASK_SPL3;
-	splvec.splclock = MIPS_INT_MASK_SPL5;
-	splvec.splstatclock = MIPS_INT_MASK_SPL5;
+	ipl_sr_bits = magnum_ipl_sr_bits;
 
 	/*
 	 * Disable all interrupts. New masks will be set up
Index: arc/arc/c_nec_eisa.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/c_nec_eisa.c,v
retrieving revision 1.5
diff -u -r1.5 c_nec_eisa.c
--- arc/arc/c_nec_eisa.c	2003/01/31 22:07:52	1.5
+++ arc/arc/c_nec_eisa.c	2003/04/28 12:07:34
@@ -73,6 +73,51 @@
 	isabr_nec_eisa_intr_status,
 };
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+static const u_int32_t nec_eisa_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* IPL_{CLOCK,HIGH} */
+};
+
 int
 isabr_nec_eisa_intr_status()
 {
@@ -131,12 +176,7 @@
 	/*
 	 * Initialize interrupt priority
 	 */
-	splvec.splnet = MIPS_INT_MASK_SPL2;
-	splvec.splbio = MIPS_INT_MASK_SPL2;
-	splvec.splvm = MIPS_INT_MASK_SPL2;
-	splvec.spltty = MIPS_INT_MASK_SPL2;
-	splvec.splclock = MIPS_INT_MASK_SPL5;
-	splvec.splstatclock = MIPS_INT_MASK_SPL5;
+	ipl_sr_bits = nec_eisa_ipl_sr_bits;
 
 	/*
 	 * Disable all interrupts. New masks will be set up
Index: arc/arc/c_nec_pci.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/c_nec_pci.c,v
retrieving revision 1.4
diff -u -r1.4 c_nec_pci.c
--- arc/arc/c_nec_pci.c	2003/01/19 10:06:12	1.4
+++ arc/arc/c_nec_pci.c	2003/04/28 12:07:34
@@ -98,6 +98,51 @@
 	{ mc_nec_pci_read, mc_nec_pci_write }
 };
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+static const u_int32_t nec_pci_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* IPL_{CLOCK,HIGH} */
+};
+
 u_int
 mc_nec_pci_read(sc, reg)
 	struct mcclock_softc *sc;
@@ -194,12 +239,7 @@
 	/*
 	 * Initialize interrupt priority
 	 */
-	splvec.splnet = MIPS_INT_MASK_SPL2;
-	splvec.splbio = MIPS_INT_MASK_SPL2;
-	splvec.splvm = MIPS_INT_MASK_SPL2;
-	splvec.spltty = MIPS_INT_MASK_SPL2;
-	splvec.splclock = MIPS_INT_MASK_SPL5;
-	splvec.splstatclock = MIPS_INT_MASK_SPL5;
+	ipl_sr_bits = nec_pci_ipl_sr_bits;
 
 	/*
 	 * Disable all interrupts. New masks will be set up
Index: arc/arc/locore_machdep.S
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/locore_machdep.S,v
retrieving revision 1.8
diff -u -r1.8 locore_machdep.S
--- arc/arc/locore_machdep.S	2000/06/09 05:07:32	1.8
+++ arc/arc/locore_machdep.S	2003/04/28 12:07:35
@@ -392,19 +392,14 @@
 
 
 /*
- * Interrupt counters for vmstat.
+ * Symbols that vmstat -i wants, even though they're not used.
  */
 	.data
 	.globl _C_LABEL(intrcnt)
 	.globl _C_LABEL(eintrcnt)
 	.globl _C_LABEL(intrnames)
 	.globl _C_LABEL(eintrnames)
-_C_LABEL(intrnames):
-	.asciiz	"softclock"
-	.asciiz	"softnet"
-	.asciiz	"fpu"
-_C_LABEL(eintrnames):
-	.align	3
 _C_LABEL(intrcnt):
-	.word	0,0,0
 _C_LABEL(eintrcnt):
+_C_LABEL(intrnames):
+_C_LABEL(eintrnames):
Index: arc/arc/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/machdep.c,v
retrieving revision 1.77
diff -u -r1.77 machdep.c
--- arc/arc/machdep.c	2003/04/27 17:05:56	1.77
+++ arc/arc/machdep.c	2003/04/28 12:07:35
@@ -180,13 +180,12 @@
  */
 int	safepri = MIPS3_PSL_LOWIPL;
 
-struct splvec	splvec = {			/* XXX will go XXX */
-	MIPS_INT_MASK_SPLHIGH, /* splbio */
-	MIPS_INT_MASK_SPLHIGH, /* splnet */
-	MIPS_INT_MASK_SPLHIGH, /* spltty */
-	MIPS_INT_MASK_SPLHIGH, /* splvm */
-	MIPS_INT_MASK_SPLHIGH, /* splclock */
-	MIPS_INT_MASK_SPLHIGH, /* splstatclock */
+const u_int32_t *ipl_sr_bits;
+const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+	MIPS_SOFT_INT_MASK_1,			/* IPL_SOFTNET */
+	MIPS_SOFT_INT_MASK_1,			/* IPL_SOFTSERIAL */
 };
 
 extern char kernel_text[], edata[], end[];
Index: arc/arc/p_dti_arcstation.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/p_dti_arcstation.c,v
retrieving revision 1.1
diff -u -r1.1 p_dti_arcstation.c
--- arc/arc/p_dti_arcstation.c	2001/06/13 15:27:17	1.1
+++ arc/arc/p_dti_arcstation.c	2003/04/28 12:07:36
@@ -95,6 +95,61 @@
 	arc_set_intr,
 };
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+/* XXX see comments in p_dti_arcstation_init() */
+static const u_int32_t dti_arcstation_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{CLOCK,HIGH} */
+};
+
 #if NPC_ISA > 0 || NOPMS_ISA > 0
 /*
  * platform-dependent pccons configuration
@@ -202,6 +257,7 @@
 	 * or
 	 *	- use MIP3_INTERNAL_TIMER_INTERRUPT for clock
 	 */
+	ipl_sr_bits = dti_arcstation_ipl_sr_bits;
 
 	/*
 	 * common configuration for DTI platforms
Index: arc/arc/p_dti_tyne.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/p_dti_tyne.c,v
retrieving revision 1.1
diff -u -r1.1 p_dti_tyne.c
--- arc/arc/p_dti_tyne.c	2001/06/13 15:27:18	1.1
+++ arc/arc/p_dti_tyne.c	2003/04/28 12:07:36
@@ -97,6 +97,61 @@
 	arc_set_intr,
 };
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+/* XXX see comments in p_dti_tyne_init() */
+static const u_int32_t dti_tyne_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{CLOCK,HIGH} */
+};
+
 #if NPC_ISA > 0 || NOPMS_ISA > 0
 /*
  * platform-dependent pccons configuration
@@ -199,6 +254,7 @@
 	 * or
 	 *	- use MIP3_INTERNAL_TIMER_INTERRUPT for clock
 	 */
+	ipl_sr_bits = dti_tyne_ipl_sr_bits;
 
 	/*
 	 * common configuration for DTI platforms
Index: arc/arc/p_sni_rm200pci.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/p_sni_rm200pci.c,v
retrieving revision 1.1
diff -u -r1.1 p_sni_rm200pci.c
--- arc/arc/p_sni_rm200pci.c	2001/06/13 15:36:44	1.1
+++ arc/arc/p_sni_rm200pci.c	2003/04/28 12:07:36
@@ -79,6 +79,61 @@
 };
 
 /*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+/* XXX lack of hardware info for sni_rm200pci */
+static const u_int32_t sni_rm200pci_ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2|
+		MIPS_INT_MASK_3|
+		MIPS_INT_MASK_4|
+		MIPS_INT_MASK_5,		/* XXX IPL_{CLOCK,HIGH} */
+};
+
+/*
  * critial i/o space, interrupt, and other chipset related initialization.
  */
 void
@@ -109,6 +164,7 @@
 	/*
 	 * Initialize interrupt priority
 	 */
+	ipl_sr_bits = sni_rm200pci_ipl_sr_bits;
 }
 
 void
Index: arc/conf/files.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/files.arc,v
retrieving revision 1.42
diff -u -r1.42 files.arc
--- arc/conf/files.arc	2003/04/06 09:55:50	1.42
+++ arc/conf/files.arc	2003/04/28 12:07:36
@@ -80,6 +80,9 @@
 
 file	arch/arc/arc/arcbios.c
 
+# XXX should be in mips/conf/files.mips
+file	arch/mips/mips/softintr.c
+
 ##
 ##	Machine-independent ATAPI drivers
 ##
Index: arc/conf/std.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/std.arc,v
retrieving revision 1.14
diff -u -r1.14 std.arc
--- arc/conf/std.arc	2003/04/28 05:03:44	1.14
+++ arc/conf/std.arc	2003/04/28 12:07:36
@@ -18,6 +18,4 @@
 
 options 	MIPS3_L2CACHE_ABSENT	# may not have L2 cache
 
-options 	__NO_SOFT_SERIAL_INTERRUPT	# for "com" driver
-
 makeoptions	DEFTEXTADDR="0x80200000"
Index: arc/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/include/intr.h,v
retrieving revision 1.10
diff -u -r1.10 intr.h
--- arc/include/intr.h	2001/06/13 15:08:06	1.10
+++ arc/include/intr.h	2003/04/28 12:07:36
@@ -1,8 +1,12 @@
 /*	$NetBSD: intr.h,v 1.10 2001/06/13 15:08:06 soda Exp $	*/
 
-/*
- * Copyright (c) 1998 Jonathan Stone.  All rights reserved.
+/*-
+ * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
  *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -13,38 +17,58 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed by Jonathan Stone for
- *      the NetBSD Project.
- * 4. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _ARC_INTR_H_
 #define _ARC_INTR_H_
 
 #define IPL_NONE	0	/* disable only this interrupt */
-#define IPL_BIO		1	/* disable block I/O interrupts */
-#define IPL_NET		2	/* disable network interrupts */
-#define IPL_TTY		3	/* disable terminal interrupts */
-#define IPL_IMP		4	/* memory allocation */
-#define IPL_CLOCK	5	/* disable clock interrupts */
-#define IPL_STATCLOCK	6	/* disable profiling interrupts */
-#if 0 /* XXX */
+
+#define IPL_SOFT	1	/* generic software interrupts (SI 0) */
+#define IPL_SOFTCLOCK	2	/* clock software interrupts (SI 0) */
+#define IPL_SOFTNET	3	/* network software interrupts (SI 1) */
+#define IPL_SOFTSERIAL	4	/* serial software interrupts (SI 1) */
+
+#define IPL_BIO		5	/* disable block I/O interrupts */
+#define IPL_NET		6	/* disable network interrupts */
+#define IPL_TTY		7	/* disable terminal interrupts */
 #define IPL_SERIAL	7	/* disable serial hardware interrupts */
-#endif
+#define IPL_CLOCK	8	/* disable clock interrupts */
+#define IPL_STATCLOCK	8	/* disable profiling interrupts */
 #define IPL_HIGH	8	/* disable all interrupts */
-#define NIPL		9
+
+#define _IPL_NSOFT	4
+#define _IPL_N		9
+
+#define _IPL_SI0_FIRST	IPL_SOFT
+#define _IPL_SI0_LAST	IPL_SOFTCLOCK
+
+#define _IPL_SI1_FIRST	IPL_SOFTNET
+#define _IPL_SI1_LAST	IPL_SOFTSERIAL
+
+#define IPL_SOFTNAMES {							\
+	"misc",								\
+	"clock",							\
+	"net",								\
+	"serial",							\
+}
 
 /* Interrupt sharing types. */
 #define IST_NONE	0	/* none */
@@ -52,86 +76,45 @@
 #define IST_EDGE	2	/* edge-triggered */
 #define IST_LEVEL	3	/* level-triggered */
 
-/* Soft interrupt masks. */
-/* XXX - revisit here */
-#define SIR_CLOCK	31
-#define SIR_NET		30
-#define SIR_CLOCKMASK	((1 << SIR_CLOCK))
-#define SIR_NETMASK	((1 << SIR_NET) | SIR_CLOCKMASK)
-#define SIR_ALLMASK	(SIR_CLOCKMASK | SIR_NETMASK)
-
 #ifdef _KERNEL
 #ifndef _LOCORE
-
-#include <mips/cpuregs.h>
 
-extern int _splraise __P((int));
-extern int _spllower __P((int));
-extern int _splset __P((int));
-extern int _splget __P((void));
-extern void _splnone __P((void));
-extern void _setsoftintr __P((int));
-extern void _clrsoftintr __P((int));
-
-#define setsoftclock()	_setsoftintr(MIPS_SOFT_INT_MASK_0)
-#define setsoftnet()	_setsoftintr(MIPS_SOFT_INT_MASK_1)
-#define clearsoftclock() _clrsoftintr(MIPS_SOFT_INT_MASK_0)
-#define clearsoftnet()	_clrsoftintr(MIPS_SOFT_INT_MASK_1)
+extern const u_int32_t *ipl_sr_bits;
 
-/*
- * nesting interrupt masks.
- */
-#define MIPS_INT_MASK_SPL_SOFT0	MIPS_SOFT_INT_MASK_0
-#define MIPS_INT_MASK_SPL_SOFT1	(MIPS_SOFT_INT_MASK_1|MIPS_INT_MASK_SPL_SOFT0)
-#define MIPS_INT_MASK_SPL0	(MIPS_INT_MASK_0|MIPS_INT_MASK_SPL_SOFT1)
-#define MIPS_INT_MASK_SPL1	(MIPS_INT_MASK_1|MIPS_INT_MASK_SPL0)
-#define MIPS_INT_MASK_SPL2	(MIPS_INT_MASK_2|MIPS_INT_MASK_SPL1)
-#define MIPS_INT_MASK_SPL3	(MIPS_INT_MASK_3|MIPS_INT_MASK_SPL2)
-#define MIPS_INT_MASK_SPL4	(MIPS_INT_MASK_4|MIPS_INT_MASK_SPL3)
-#define MIPS_INT_MASK_SPL5	(MIPS_INT_MASK_5|MIPS_INT_MASK_SPL4)
-#define MIPS_INT_MASK_SPLHIGH	MIPS_INT_MASK_SPL5
+extern int _splraise(int);
+extern int _spllower(int);
+extern int _splset(int);
+extern int _splget(void);
+extern void _splnone(void);
+extern void _setsoftintr(int);
+extern void _clrsoftintr(int);
 
+#define splhigh()	_splraise(ipl_sr_bits[IPL_HIGH])
 #define spl0()		(void)_spllower(0)
 #define splx(s)		(void)_splset(s)
-#define splbio()	(_splraise(splvec.splbio))
-#define splnet()	(_splraise(splvec.splnet))
-#define spltty()	(_splraise(splvec.spltty))
-#define splvm()		(_splraise(splvec.splvm))
-#define splclock()	(_splraise(splvec.splclock))
-#define splstatclock()	(_splraise(splvec.splstatclock))
-#define splhigh()	_splraise(MIPS_INT_MASK_SPLHIGH)
-
-#define splsoftclock()	_splraise(MIPS_INT_MASK_SPL_SOFT0)
-#define splsoftnet()	_splraise(MIPS_INT_MASK_SPL_SOFT1)
-#define spllowersoftclock() _spllower(MIPS_INT_MASK_SPL_SOFT0)
+#define splbio()	_splraise(ipl_sr_bits[IPL_BIO])
+#define splnet()	_splraise(ipl_sr_bits[IPL_NET])
+#define spltty()	_splraise(ipl_sr_bits[IPL_TTY])
+#define splserial()	_splraise(ipl_sr_bits[IPL_SERIAL])
+#define splvm()		spltty()
+#define splclock()	_splraise(ipl_sr_bits[IPL_CLOCK])
+#define splstatclock()	splclock()
 
-#define	splsched()	splhigh()
-#define	spllock()	splhigh()
+#define splsched()	splclock()
+#define spllock()	splhigh()
 #define spllpt()	spltty()		/* lpt driver */
 
-struct splvec {
-	int	splbio;
-	int	splnet;
-	int	spltty;
-	int	splvm;
-	int	splclock;
-	int	splstatclock;
-};
-extern struct splvec splvec;
+#define splsoft()	_splraise(ipl_sr_bits[IPL_SOFT])
+#define splsoftclock()	_splraise(ipl_sr_bits[IPL_SOFTCLOCK])
+#define splsoftnet()	_splraise(ipl_sr_bits[IPL_SOFTNET])
+#define splsoftserial()	_splraise(ipl_sr_bits[IPL_SOFTSERIAL])
 
-/*
- * Index into intrcnt[], which is defined in locore
- */
-#define SOFTCLOCK_INTR	0
-#define SOFTNET_INTR	1
-#define FPU_INTR	2
-extern u_long intrcnt[];
+#define spllowersoftclock() _spllower(ipl_sr_bits[IPL_SOFTCLOCK])
 
-struct clockframe;
-void arc_set_intr __P((int, int(*)(u_int, struct clockframe *), int));
+#include <mips/softintr.h>
 
-/* XXX - revisit here */
-int imask[NIPL];
+struct clockframe;
+void arc_set_intr(int, int(*)(u_int, struct clockframe *), int);
 
 #endif /* !_LOCORE */
 #endif /* _KERNEL */
Index: arc/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/include/types.h,v
retrieving revision 1.13
diff -u -r1.13 types.h
--- arc/include/types.h	2002/03/05 16:12:36	1.13
+++ arc/include/types.h	2003/04/28 12:07:36
@@ -6,6 +6,7 @@
 
 #include <mips/types.h>
 
+#define	__HAVE_GENERIC_SOFT_INTERRUPTS
 #define	__HAVE_DEVICE_REGISTER
 #define	__HAVE_NWSCONS
 
Index: arc/isa/isabus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/isa/isabus.c,v
retrieving revision 1.19
diff -u -r1.19 isabus.c
--- arc/isa/isabus.c	2003/04/27 17:05:58	1.19
+++ arc/isa/isabus.c	2003/04/28 12:07:37
@@ -133,6 +133,7 @@
 int	fakeintr __P((void *a));
 
 struct isabr_config *isabr_conf = NULL;
+u_int32_t imask[_IPL_N];	/* XXX */
 
 void
 isabrattach(sc)
@@ -217,39 +218,47 @@
 	}
 
 	/* Then figure out which IRQs use each level. */
-	for (level = 0; level < 5; level++) {
+	for (level = 0; level < _IPL_N; level++) {
 		int irqs = 0;
 		for (irq = 0; irq < ICU_LEN; irq++)
 			if (intrlevel[irq] & (1 << level))
 				irqs |= 1 << irq;
-		imask[level] = irqs | SIR_ALLMASK;
+		imask[level] = irqs;
 	}
 
-	/*
-	 * There are tty, network and disk drivers that use free() at interrupt
-	 * time, so imp > (tty | net | bio).
-	 */
-	imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
+	imask[IPL_NONE] = 0;
+
+	imask[IPL_SOFT] |= imask[IPL_NONE];
+	imask[IPL_SOFTCLOCK] |= imask[IPL_SOFT];
+	imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
+	imask[IPL_SOFTSERIAL] |= imask[IPL_SOFTNET];
 
 	/*
 	 * Enforce a hierarchy that gives slow devices a better chance at not
 	 * dropping data.
 	 */
-	imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
+	imask[IPL_BIO] |= imask[IPL_SOFTSERIAL];
 	imask[IPL_NET] |= imask[IPL_BIO];
+	imask[IPL_TTY] |= imask[IPL_NET];
+
+	/*
+	 * Since run queues may be manipulated by both the statclock and tty,
+	 * network, and diskdrivers, clock > tty.
+	 */
+	imask[IPL_CLOCK] |= imask[IPL_TTY];
+	imask[IPL_STATCLOCK] |= imask[IPL_CLOCK];
 
 	/*
-	 * These are pseudo-levels.
+	 * IPL_HIGH must block everything that can manipulate a run queue.
 	 */
-	imask[IPL_NONE] = 0x00000000;
-	imask[IPL_HIGH] = 0xffffffff;
+	imask[IPL_HIGH] |= imask[IPL_STATCLOCK];
 
 	/* And eventually calculate the complete masks. */
 	for (irq = 0; irq < ICU_LEN; irq++) {
 		int irqs = 1 << irq;
 		for (q = intrhand[irq]; q; q = q->ih_next)
 			irqs |= imask[q->ih_level];
-		intrmask[irq] = irqs | SIR_ALLMASK;
+		intrmask[irq] = irqs;
 	}
 
 	/* Lastly, determine which IRQs are actually in use. */
Index: newsmips/apbus/apbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/apbus/apbus.c,v
retrieving revision 1.13
diff -u -r1.13 apbus.c
--- newsmips/apbus/apbus.c	2003/04/19 14:56:05	1.13
+++ newsmips/apbus/apbus.c	2003/04/28 12:07:38
@@ -38,6 +38,7 @@
 #include <machine/autoconf.h>
 #define _NEWSMIPS_BUS_DMA_PRIVATE
 #include <machine/bus.h>
+#include <machine/intr.h>
 #include <newsmips/apbus/apbusvar.h>
 
 static int  apbusmatch (struct device *, struct cfdata *, void *);
@@ -71,21 +72,8 @@
 CFATTACH_DECL(ap, sizeof(struct apbus_softc),
     apbusmatch, apbusattach, NULL, NULL);
 
-#define	APBUS_DEVNAMELEN	16
-
-struct ap_intrhand {
-	struct ap_intrhand *ai_next;
-	int ai_mask;
-	int ai_priority;
-	int (*ai_func) (void*);		/* function */
-	void *ai_aux;			/* softc */
-	char ai_name[APBUS_DEVNAMELEN];
-	int ai_ctlno;
-};
-
 #define	NLEVEL	2
-
-static struct ap_intrhand *apintr[NLEVEL];
+static struct newsmips_intr apintr_tab[NLEVEL];
 
 static int
 apbusmatch(parent, cfdata, aux)
@@ -111,6 +99,8 @@
 	struct apbus_attach_args child;
 	struct apbus_dev *apdev;
 	struct apbus_ctl *apctl;
+	struct newsmips_intr *ip;
+	int i;
 
 	*(volatile u_int *)(NEWS5000_APBUS_INTST) = 0xffffffff;
 	*(volatile u_int *)(NEWS5000_APBUS_INTMSK) = 0xffffffff;
@@ -119,6 +109,11 @@
 
 	printf("\n");
 
+	for (i = 0; i < NLEVEL; i++) {
+		ip = &apintr_tab[i];
+		LIST_INIT(&ip->intr_q);
+	}
+
 	/*
 	 * get first ap-device
 	 */
@@ -202,13 +197,16 @@
 	int level;
 	int stat;
 {
-	int nintr = 0;
-	struct ap_intrhand *ai;
-
-	for (ai = apintr[level]; ai != NULL; ai = ai->ai_next) {
-		if (ai->ai_mask & stat) {
-			nintr += (*ai->ai_func)(ai->ai_aux);
-		}
+	struct newsmips_intr *ip;
+	struct newsmips_intrhand *ih;
+	int nintr;
+
+	ip = &apintr_tab[level];
+
+	nintr = 0;
+	LIST_FOREACH(ih, &ip->intr_q, ih_q) {
+		if (ih->ih_mask & stat)
+			nintr += (*ih->ih_func)(ih->ih_arg);
 	}
 	return nintr;
 }
@@ -217,45 +215,58 @@
  * register device interrupt routine
  */
 void *
-apbus_intr_establish(level, mask, priority, func, aux, name, ctlno)
+apbus_intr_establish(level, mask, priority, func, arg, name, ctlno)
 	int level;
 	int mask;
 	int priority;
 	int (*func) (void *);
-	void *aux;
+	void *arg;
 	char *name;
 	int ctlno;
 {
-	struct ap_intrhand *ai, **aip;
-	volatile unsigned int *inten0 = (volatile unsigned int *)NEWS5000_INTEN0;
-	volatile unsigned int *inten1 = (volatile unsigned int *)NEWS5000_INTEN1;
+	struct newsmips_intr *ip;
+	struct newsmips_intrhand *ih, *curih;
+	volatile u_int32_t *inten0, *inten1;
+
+	ip = &apintr_tab[level];
 
-	ai = malloc(sizeof(*ai), M_DEVBUF, M_NOWAIT);
-	if (ai == NULL)
+	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
+	if (ih == NULL)
 		panic("apbus_intr_establish: can't malloc handler info");
-	ai->ai_mask = mask;
-	ai->ai_priority = priority;
-	ai->ai_func = func;
-	ai->ai_aux = aux;
-	strncpy(ai->ai_name, name, APBUS_DEVNAMELEN-1);
-	ai->ai_ctlno = ctlno;
-
-	for (aip = &apintr[level]; *aip != NULL; aip = &(*aip)->ai_next) {
-		if ((*aip)->ai_priority < priority)
-			break;
+	ih->ih_mask = mask;
+	ih->ih_priority = priority;
+	ih->ih_func = func;
+	ih->ih_arg = arg;
+
+	if (LIST_EMPTY(&ip->intr_q)) {
+		LIST_INSERT_HEAD(&ip->intr_q, ih, ih_q);
+		goto done;
 	}
-	ai->ai_next = *aip;
-	*aip = ai;
+
+	for (curih = LIST_FIRST(&ip->intr_q);
+	    LIST_NEXT(curih, ih_q) != NULL;
+	    curih = LIST_NEXT(curih, ih_q)) {
+		if (ih->ih_priority > curih->ih_priority) {
+			LIST_INSERT_BEFORE(curih, ih, ih_q);
+			goto done;
+		}
+	}
+
+	LIST_INSERT_AFTER(curih, ih, ih_q);
+
+ done:
 	switch (level) {
 	case 0:
+		inten0 = (volatile u_int32_t *)NEWS5000_INTEN0;
 		*inten0 |= mask;
 		break;
 	case 1:
+		inten1 = (volatile u_int32_t *)NEWS5000_INTEN1;
 		*inten1 |= mask;
 		break;
 	}
 
-	return (void *)ai;
+	return (void *)ih;
 }
 
 static void
Index: newsmips/apbus/zs_ap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/apbus/zs_ap.c,v
retrieving revision 1.13
diff -u -r1.13 zs_ap.c
--- newsmips/apbus/zs_ap.c	2003/04/26 18:43:19	1.13
+++ newsmips/apbus/zs_ap.c	2003/04/28 12:07:39
@@ -311,6 +311,7 @@
 	if (!didintr) {
 		didintr = 1;
 
+		zsc->zsc_si = softintr_establish(IPL_SOFTSERIAL, zssoft, zsc);
 		apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
 				     NEWS5000_INT1_SCC,
 				     0, /* priority */
Index: newsmips/conf/files.newsmips
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/conf/files.newsmips,v
retrieving revision 1.21
diff -u -r1.21 files.newsmips
--- newsmips/conf/files.newsmips	2002/10/26 13:50:38	1.21
+++ newsmips/conf/files.newsmips	2003/04/28 12:07:39
@@ -98,6 +98,9 @@
 file dev/clock_subr.c
 file dev/cons.c
 
+# XXX should be in mips/conf/files.mips
+file arch/mips/mips/softintr.c
+
 #
 # Machine-independent SCSI driver.
 #
Index: newsmips/dev/hb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/dev/hb.c,v
retrieving revision 1.10
diff -u -r1.10 hb.c
--- newsmips/dev/hb.c	2003/01/01 01:55:42	1.10
+++ newsmips/dev/hb.c	2003/04/28 12:07:39
@@ -3,8 +3,10 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/malloc.h>
 
 #include <machine/autoconf.h>
+#include <machine/intr.h>
 
 static int	hb_match __P((struct device *, struct cfdata *, void *));
 static void	hb_attach __P((struct device *, struct device *, void *));
@@ -17,13 +19,8 @@
 
 extern struct cfdriver hb_cd;
 
-struct intrhand {
-	int (*func) __P((void *));
-	void *arg;
-};
-
-#define NHBINTR	4
-struct intrhand hb_intrhand[6][NHBINTR];
+#define NLEVEL	4
+static struct newsmips_intr hbintr_tab[NLEVEL];
 
 static int
 hb_match(parent, cf, aux)
@@ -46,8 +43,16 @@
 	void *aux;
 {
 	struct confargs *ca = aux;
+	struct newsmips_intr *ip;
+	int i;
 
 	printf("\n");
+
+	for (i = 0; i < NLEVEL; i++) {
+		ip = &hbintr_tab[i];
+		LIST_INIT(&ip->intr_q);
+	}
+
 	config_search(hb_search, self, ca);
 }
 
@@ -90,50 +95,53 @@
 }
 
 void *
-hb_intr_establish(irq, level, func, arg)
-	int irq, level;
+hb_intr_establish(level, priority, func, arg)
+	int level, priority;
 	int (*func) __P((void *));
 	void *arg;
 {
-	struct intrhand *ih = hb_intrhand[irq];
-	int i;
+	struct newsmips_intr *ip;
+	struct newsmips_intrhand *ih, *curih;
+
+	ip = &hbintr_tab[level];
 
-	for (i = NHBINTR; i > 0; i--) {
-		if (ih->func == NULL)
-			goto found;
-		ih++;
+	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
+	if (ih == NULL)
+		panic("hb_intr_establish: malloc failed");
+
+	ih->ih_func = func;
+	ih->ih_arg = arg;
+	ih->ih_priority = priority;
+	if (LIST_EMPTY(&ip->intr_q)) {
+		LIST_INSERT_HEAD(&ip->intr_q, ih, ih_q);
+		goto done;
 	}
-	panic("hb_intr_establish: no room");
 
-found:
-	ih->func = func;
-	ih->arg = arg;
-
-#ifdef HB_DEBUG
-	for (irq = 0; irq <= 2; irq++) {
-		for (i = 0; i < NHBINTR; i++) {
-			printf("%p(%p) ",
-			       hb_intrhand[irq][i].func,
-			       hb_intrhand[irq][i].arg);
+	for (curih = LIST_FIRST(&ip->intr_q);
+	    LIST_NEXT(curih, ih_q) != NULL;
+	    curih = LIST_NEXT(curih, ih_q)) {
+		if (ih->ih_priority > curih->ih_priority) {
+			LIST_INSERT_BEFORE(curih, ih, ih_q);
+			goto done;
 		}
-		printf("\n");
 	}
-#endif
 
+	LIST_INSERT_AFTER(curih, ih, ih_q);
+
+ done:
 	return ih;
 }
 
 void
-hb_intr_dispatch(irq)
-	int irq;
+hb_intr_dispatch(level)
+	int level;
 {
-	struct intrhand *ih;
-	int i;
+	struct newsmips_intr *ip;
+	struct newsmips_intrhand *ih;
+
+	ip = &hbintr_tab[level];
 
-	ih = hb_intrhand[irq];
-	for (i = NHBINTR; i > 0; i--) {
-		if (ih->func)
-			(*ih->func)(ih->arg);
-		ih++;
+	LIST_FOREACH(ih, &ip->intr_q, ih_q) {
+		(*ih->ih_func)(ih->ih_arg);
 	}
 }
Index: newsmips/dev/zs.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/dev/zs.c,v
retrieving revision 1.17
diff -u -r1.17 zs.c
--- newsmips/dev/zs.c	2003/04/26 18:43:20	1.17
+++ newsmips/dev/zs.c	2003/04/28 12:07:39
@@ -84,8 +84,6 @@
 	return UNCONF;
 }
 
-static volatile int zssoftpending;
-
 /*
  * Our ZS chips all share a common, autovectored interrupt,
  * so we have to look at all of them on each interrupt.
@@ -97,20 +95,16 @@
 	struct zsc_softc *zsc;
 	int unit, rval, softreq;
 
-	rval = softreq = 0;
+	rval = 0;
 	for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
 		zsc = zsc_cd.cd_devs[unit];
 		if (zsc == NULL)
 			continue;
 		rval |= zsc_intr_hard(zsc);
-		softreq |= zsc->zsc_cs[0]->cs_softreq;
+		softreq =  zsc->zsc_cs[0]->cs_softreq;
 		softreq |= zsc->zsc_cs[1]->cs_softreq;
-	}
-
-	/* We are at splzs here, so no need to lock. */
-	if (softreq && (zssoftpending == 0)) {
-		zssoftpending = 1;
-		setsoftserial();
+		if (softreq)
+			softintr_schedule(zsc->zsc_si);
 	}
 
 	return rval;
@@ -126,19 +120,6 @@
 	struct zsc_softc *zsc;
 	int s, unit;
 
-	/* This is not the only ISR on this IPL. */
-	if (zssoftpending == 0)
-		return;
-
-	/*
-	 * The soft intr. bit will be set by zshard only if
-	 * the variable zssoftpending is zero.  The order of
-	 * these next two statements prevents our clearing
-	 * the soft intr bit just after zshard has set it.
-	 */
-	/* clearsoftnet(); */
-	zssoftpending = 0;
-
 	/* Make sure we call the tty layer at spltty. */
 	s = spltty();
 	for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
@@ -214,7 +195,7 @@
 	 * Therefore, NEVER set the HFC bit, and instead use the
 	 * status interrupt to detect CTS changes.
 	 */
-	s = splzs();
+	s = splserial();
 	cs->cs_rr0_pps = 0;
 	if ((cflag & (CLOCAL | MDMBUF)) != 0) {
 		cs->cs_rr0_dcd = 0;
Index: newsmips/dev/zs_hb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/dev/zs_hb.c,v
retrieving revision 1.11
diff -u -r1.11 zs_hb.c
--- newsmips/dev/zs_hb.c	2003/04/26 18:43:20	1.11
+++ newsmips/dev/zs_hb.c	2003/04/28 12:07:39
@@ -295,6 +295,7 @@
 	if (!didintr) {
 		didintr = 1;
 
+		zsc->zsc_si = softintr_establish(IPL_SOFTSERIAL, zssoft, zsc);
 		hb_intr_establish(intlevel, IPL_SERIAL, zshard_hb, NULL);
 	}
 	/* XXX; evcnt_attach() ? */
Index: newsmips/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/include/intr.h,v
retrieving revision 1.11
diff -u -r1.11 intr.h
--- newsmips/include/intr.h	2001/04/13 23:30:02	1.11
+++ newsmips/include/intr.h	2003/04/28 12:07:40
@@ -1,7 +1,11 @@
 /*	$NetBSD: intr.h,v 1.11 2001/04/13 23:30:02 thorpej Exp $	*/
 
-/*
- * Copyright (c) 1998 Jonathan Stone.  All rights reserved.
+/*-
+ * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -13,39 +17,66 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed by Jonathan Stone for
- *      the NetBSD Project.
- * 4. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _MACHINE_INTR_H_
 #define _MACHINE_INTR_H_
 
 #define IPL_NONE	0	/* disable only this interrupt */
-#define IPL_BIO		1	/* disable block I/O interrupts */
-#define IPL_NET		2	/* disable network interrupts */
-#define IPL_TTY		3	/* disable terminal interrupts */
-#define IPL_CLOCK	4	/* disable clock interrupts */
-#define IPL_STATCLOCK	5	/* disable profiling interrupts */
-#define IPL_SERIAL	6	/* disable serial hardware interrupts */
-#define IPL_HIGH	7	/* disable all interrupts */
 
+#define IPL_SOFT	1	/* generic software interrupts (SI 0) */
+#define IPL_SOFTCLOCK	2	/* clock software interrupts (SI 0) */
+#define IPL_SOFTNET	3	/* network software interrupts (SI 1) */
+#define IPL_SOFTSERIAL	4	/* serial software interrupts (SI 1) */
+
+#define IPL_BIO		5	/* disable block I/O interrupts */
+#define IPL_NET		6	/* disable network interrupts */
+#define IPL_TTY		7	/* disable terminal interrupts */
+#define IPL_SERIAL	7	/* disable serial hardware interrupts */
+#define IPL_CLOCK	8	/* disable clock interrupts */
+#define IPL_STATCLOCK	8	/* disable profiling interrupts */
+#define IPL_HIGH	8	/* disable all interrupts */
+
+#define _IPL_NSOFT	4
+#define _IPL_N		9
+
+#define _IPL_SI0_FIRST	IPL_SOFT
+#define _IPL_SI0_LAST	IPL_SOFTCLOCK
+
+#define _IPL_SI1_FIRST	IPL_SOFTNET
+#define _IPL_SI1_LAST	IPL_SOFTSERIAL
+
+#define IPL_SOFTNAMES {							\
+	"misc",								\
+	"clock",							\
+	"net",								\
+	"serial",							\
+}
+
 #ifdef _KERNEL
 #ifndef _LOCORE
-#include <mips/cpuregs.h>
 
+#include <sys/device.h>
+
+extern const u_int32_t ipl_sr_bits[_IPL_N];
+
 extern int _splraise __P((int));
 extern int _spllower __P((int));
 extern int _splset __P((int));
@@ -54,81 +85,73 @@
 extern void _setsoftintr __P((int));
 extern void _clrsoftintr __P((int));
 
-/*
- * software simulated interrupt
- */
-#define SIR_NET		0x01
-#define SIR_SERIAL	0x02
-
-#define setsoft(x)	do {			\
-	extern u_int ssir;			\
-	int s;					\
-						\
-	s = splhigh();				\
-	ssir |= (x);				\
-	_setsoftintr(MIPS_SOFT_INT_MASK_1);	\
-	splx(s);				\
-} while (0)
-
-#define setsoftclock()	_setsoftintr(MIPS_SOFT_INT_MASK_0)
-#define setsoftnet()	setsoft(SIR_NET)
-#define setsoftserial()	setsoft(SIR_SERIAL)
-
-/*
- * nesting interrupt masks.
- */
-#define MIPS_INT_MASK_SPL_SOFT0	MIPS_SOFT_INT_MASK_0
-#define MIPS_INT_MASK_SPL_SOFT1	(MIPS_SOFT_INT_MASK_1|MIPS_INT_MASK_SPL_SOFT0)
-#define MIPS_INT_MASK_SPL0	(MIPS_INT_MASK_0|MIPS_INT_MASK_SPL_SOFT1)
-#define MIPS_INT_MASK_SPL1	(MIPS_INT_MASK_1|MIPS_INT_MASK_SPL0)
-#define MIPS_INT_MASK_SPL2	(MIPS_INT_MASK_2|MIPS_INT_MASK_SPL1)
-#define MIPS_INT_MASK_SPL3	(MIPS_INT_MASK_3|MIPS_INT_MASK_SPL2)
-#define MIPS_INT_MASK_SPL4	(MIPS_INT_MASK_4|MIPS_INT_MASK_SPL3)
-#define MIPS_INT_MASK_SPL5	(MIPS_INT_MASK_5|MIPS_INT_MASK_SPL4)
-
+#define splhigh()	_splraise(ipl_sr_bits[IPL_HIGH])
 #define spl0()		(void)_spllower(0)
 #define splx(s)		(void)_splset(s)
-#define splbio()	_splraise(MIPS_INT_MASK_SPL0)
-#define splnet()	_splraise(MIPS_INT_MASK_SPL1)
-#define spltty()	_splraise(MIPS_INT_MASK_SPL1)
-#define splvm()		_splraise(MIPS_INT_MASK_SPL1)
-#define splclock()	_splraise(MIPS_INT_MASK_SPL2)
-#define splstatclock()	_splraise(MIPS_INT_MASK_SPL2)
-#define splhigh()	_splraise(MIPS_INT_MASK_SPL2)
-#define	splsched()	splhigh()
-#define	spllock()	splhigh()
-
-#define splsoftclock()	_splraise(MIPS_INT_MASK_SPL_SOFT0)
-#define splsoftnet()	_splraise(MIPS_INT_MASK_SPL_SOFT1)
-#define spllowersoftclock() _spllower(MIPS_INT_MASK_SPL_SOFT0)
+#define splbio()	_splraise(ipl_sr_bits[IPL_BIO])
+#define splnet()	_splraise(ipl_sr_bits[IPL_NET])
+#define spltty()	_splraise(ipl_sr_bits[IPL_TTY])
+#define splserial()	_splraise(ipl_sr_bits[IPL_SERIAL])
+#define splvm()		spltty()
+#define splclock()	_splraise(ipl_sr_bits[IPL_CLOCK])
+#define splstatclock()	splclock()
+
+#define splsched()	splclock()
+#define spllock()	splhigh()
+
+#define splsoft()	_splraise(ipl_sr_bits[IPL_SOFT])
+#define splsoftclock()	_splraise(ipl_sr_bits[IPL_SOFTCLOCK])
+#define splsoftnet()	_splraise(ipl_sr_bits[IPL_SOFTNET])
+#define splsoftserial()	_splraise(ipl_sr_bits[IPL_SOFTSERIAL])
+
+#define spllowersoftclock() _spllower(ipl_sr_bits[IPL_SOFTCLOCK])
+
+struct newsmips_intrhand {
+	LIST_ENTRY(newsmips_intrhand) ih_q;
+	struct evcnt intr_count;
+	int (*ih_func)(void *);
+	void *ih_arg;
+	u_int ih_level;
+	u_int ih_mask;
+	u_int ih_priority;
+};
+
+struct newsmips_intr {
+	LIST_HEAD(,newsmips_intrhand) intr_q;
+};
+
+#include <mips/softintr.h>
 
 /*
  * Index into intrcnt[], which is defined in locore
  */
-#define SOFTCLOCK_INTR	0
-#define SOFTNET_INTR	1
-#define SERIAL0_INTR	2
-#define SERIAL1_INTR	3
-#define SERIAL2_INTR	4
-#define LANCE_INTR	5
-#define SCSI_INTR	6
-#define ERROR_INTR	7
-#define HARDCLOCK_INTR	8
-#define FPU_INTR	9
-#define SLOT1_INTR	10
-#define SLOT2_INTR	11
-#define SLOT3_INTR	12
-#define FLOPPY_INTR	13
-#define STRAY_INTR	14
+#define SERIAL0_INTR	0
+#define SERIAL1_INTR	1
+#define SERIAL2_INTR	2
+#define LANCE_INTR	3
+#define SCSI_INTR	4
+#define ERROR_INTR	5
+#define HARDCLOCK_INTR	6
+#define FPU_INTR	7
+#define SLOT1_INTR	8
+#define SLOT2_INTR	9
+#define SLOT3_INTR	10
+#define FLOPPY_INTR	11
+#define STRAY_INTR	12
 
 extern u_int intrcnt[];
 
 /* handle i/o device interrupts */
-extern void news3400_intr __P((u_int, u_int, u_int, u_int));
-extern void news5000_intr __P((u_int, u_int, u_int, u_int));
+#ifdef news3400
+void news3400_intr __P((u_int, u_int, u_int, u_int));
+#endif
+#ifdef news5000
+void news5000_intr __P((u_int, u_int, u_int, u_int));
+#endif
+void (*hardware_intr) __P((u_int, u_int, u_int, u_int));
 
-extern void (*enable_intr) __P((void));
-extern void (*disable_intr) __P((void));
+void (*enable_intr) __P((void));
+void (*disable_intr) __P((void));
 
 #endif /* !_LOCORE */
 #endif /* _KERNEL */
Index: newsmips/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/include/types.h,v
retrieving revision 1.5
diff -u -r1.5 types.h
--- newsmips/include/types.h	2002/08/05 02:13:15	1.5
+++ newsmips/include/types.h	2003/04/28 12:07:40
@@ -3,6 +3,7 @@
 #include <mips/types.h>
 
 #define	__BROKEN_CONFIG_UNIT_USAGE
+#define	__HAVE_GENERIC_SOFT_INTERRUPTS
 
 /* MIPS specific options */
 #define	__HAVE_BOOTINFO_H
Index: newsmips/include/z8530var.h
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/include/z8530var.h,v
retrieving revision 1.4
diff -u -r1.4 z8530var.h
--- newsmips/include/z8530var.h	2003/04/26 18:43:20	1.4
+++ newsmips/include/z8530var.h	2003/04/28 12:07:40
@@ -52,6 +52,7 @@
 	struct	zs_chanstate *zsc_cs[2];	/* channel A and B soft state */
 	/* Machine-dependent part follows... */
 	struct zs_chanstate  zsc_cs_store[2];
+	void *zsc_si;			/* softinterrupt handle */
 };
 
 /*
@@ -76,6 +77,4 @@
 int zs_get_speed __P((struct zs_chanstate *));
 void (*zs_delay) __P((void));
 
-/* Zilog Serial hardware interrupts (level 1) */
-#define splzs		cpu_spl1
-extern int splzs(void);
+#define splzs()		splserial()
Index: newsmips/newsmips/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/newsmips/autoconf.c,v
retrieving revision 1.16
diff -u -r1.16 autoconf.c
--- newsmips/newsmips/autoconf.c	2002/09/25 22:21:15	1.16
+++ newsmips/newsmips/autoconf.c	2003/04/28 12:07:40
@@ -98,6 +98,7 @@
 	/*
 	 * Kick off autoconfiguration
 	 */
+	softintr_init();
 	_splnone();	/* enable all interrupts */
 	splhigh();	/* ...then disable device interrupts */
 
Index: newsmips/newsmips/locore_machdep.S
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/newsmips/locore_machdep.S,v
retrieving revision 1.9
diff -u -r1.9 locore_machdep.S
--- newsmips/newsmips/locore_machdep.S	2003/04/26 18:40:00	1.9
+++ newsmips/newsmips/locore_machdep.S	2003/04/28 12:07:40
@@ -226,8 +226,6 @@
 	.globl _C_LABEL(intrnames)
 	.globl _C_LABEL(eintrnames)
 _C_LABEL(intrnames):
-	.asciiz	"softclock"
-	.asciiz	"softnet"
 	.asciiz	"serial0"
 	.asciiz	"serial1"
 	.asciiz	"serial2"
@@ -246,7 +244,7 @@
 _C_LABEL(eintrnames):
 	.align	2
 _C_LABEL(intrcnt):
-	.word	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0
+	.word	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0
 _C_LABEL(eintrcnt):
 	.word	0	# This shouldn't be needed but with 4.4bsd's as, the eintrcnt
 			#  label ends end up in a different section otherwise.
Index: newsmips/newsmips/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/newsmips/newsmips/machdep.c,v
retrieving revision 1.69
diff -u -r1.69 machdep.c
--- newsmips/newsmips/machdep.c	2003/04/26 18:50:19	1.69
+++ newsmips/newsmips/machdep.c	2003/04/28 12:07:41
@@ -78,6 +78,7 @@
 #include <ufs/mfs/mfs_extern.h>		/* mfs_initminiroot() */
 
 #include <machine/cpu.h>
+#include <machine/intr.h>
 #include <machine/reg.h>
 #include <machine/psl.h>
 #include <machine/pte.h>
@@ -129,13 +130,8 @@
 int mem_cluster_cnt;
 
 struct idrom idrom;
-void (*enable_intr) __P((void));
-void (*disable_intr) __P((void));
 void (*readmicrotime) __P((struct timeval *tvp));
 
-static void (*hardware_intr) __P((u_int, u_int, u_int, u_int));
-u_int ssir;
-
 /*
  *  Local functions.
  */
@@ -159,6 +155,51 @@
  */
 int safepri = MIPS3_PSL_LOWIPL;		/* XXX */
 
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given interrupt priority level.
+ */
+const u_int32_t ipl_sr_bits[_IPL_N] = {
+	0,					/* IPL_NONE */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTNET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1,		/* IPL_SOFTSERIAL */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0,		/* IPL_BIO */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1,		/* IPL_NET */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1,		/* IPL_{TTY,SERIAL} */
+
+	MIPS_SOFT_INT_MASK_0|
+		MIPS_SOFT_INT_MASK_1|
+		MIPS_INT_MASK_0|
+		MIPS_INT_MASK_1|
+		MIPS_INT_MASK_2,		/* IPL_{CLOCK,HIGH} */
+};
+
+const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFT */
+	MIPS_SOFT_INT_MASK_0,			/* IPL_SOFTCLOCK */
+	MIPS_SOFT_INT_MASK_1,			/* IPL_SOFTNET */
+	MIPS_SOFT_INT_MASK_1,			/* IPL_SOFTSERIAL */
+};
+
 extern struct user *proc0paddr;
 extern u_long bootdev;
 extern char edata[], end[];
@@ -651,10 +692,6 @@
 	DELAY(n);
 }
 
-#include "zsc.h"
-
-int zssoft __P((void));
-
 void
 cpu_intr(status, cause, pc, ipending)
 	u_int32_t status;
@@ -662,39 +699,18 @@
 	u_int32_t pc;
 	u_int32_t ipending;
 {
+
 	uvmexp.intrs++;
 
 	/* device interrupts */
 	(*hardware_intr)(status, cause, pc, ipending);
 
-	/* software simulated interrupt */
-	if ((ipending & MIPS_SOFT_INT_MASK_1) ||
-	    (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
-
-#define DO_SIR(bit, fn)						\
-	do {							\
-		if (n & (bit)) {				\
-			uvmexp.softs++;				\
-			fn;					\
-		}						\
-	} while (0)
-
-		unsigned n;
-		n = ssir; ssir = 0;
-		_clrsoftintr(MIPS_SOFT_INT_MASK_1);
+	/* software interrupts */
+	ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0);
+	if (ipending == 0)
+		return;
 
-#if NZSC > 0
-		DO_SIR(SIR_SERIAL, zssoft());
-#endif
-		DO_SIR(SIR_NET, netintr());
-#undef DO_SIR
-	}
+	_clrsoftintr(ipending);
 
-	/* 'softclock' interrupt */
-	if (ipending & MIPS_SOFT_INT_MASK_0) {
-		_clrsoftintr(MIPS_SOFT_INT_MASK_0);
-		uvmexp.softs++;
-		intrcnt[SOFTCLOCK_INTR]++;
-		softclock(NULL);
-	}
+	softintr_dispatch(ipending);
 }
--- /dev/null	2003-04-28 20:00:22.000000000 +0900
+++ mips/include/softintr.h	2003-04-28 19:26:48.000000000 +0900
@@ -0,0 +1,99 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MIPS_SOFTINTR_H_
+#define _MIPS_SOFTINTR_H_
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+
+#include <sys/device.h>
+#include <sys/lock.h>
+
+extern const u_int32_t ipl_si_to_sr[_IPL_NSOFT];
+
+#define setsoft(x)							\
+do {									\
+	_setsoftintr(ipl_si_to_sr[(x) - IPL_SOFT]);			\
+} while (/*CONSTCOND*/0)
+
+struct mips_soft_intrhand {
+	TAILQ_ENTRY(mips_soft_intrhand) sih_q;
+	struct mips_soft_intr *sih_intrhead;
+	void (*sih_func)(void *);
+	void *sih_arg;
+	int sih_pending;
+};
+
+struct mips_soft_intr {
+	TAILQ_HEAD(,mips_soft_intrhand) softintr_q;
+	struct evcnt softintr_evcnt;
+	struct simplelock softintr_slock;
+	unsigned long softintr_ipl;
+};
+
+void softintr_init(void);
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_disestablish(void *);
+void softintr_dispatch(u_int32_t);
+
+#define softintr_schedule(arg)						\
+do {									\
+	struct mips_soft_intrhand *__sih = (arg);			\
+	struct mips_soft_intr *__msi = __sih->sih_intrhead;		\
+	int __s;							\
+									\
+	__s = splhigh();						\
+	simple_lock(&__msi->softintr_slock);				\
+	if (__sih->sih_pending == 0) {					\
+		TAILQ_INSERT_TAIL(&__msi->softintr_q, __sih, sih_q);	\
+		__sih->sih_pending = 1;					\
+		setsoft(__msi->softintr_ipl);				\
+	}								\
+	simple_unlock(&__msi->softintr_slock);				\
+	splx(__s);							\
+} while (/*CONSTCOND*/0)
+
+/* XXX For legacy software interrupts. */
+extern struct mips_soft_intrhand *softnet_intrhand;
+
+#define setsoftnet()	softintr_schedule(softnet_intrhand)
+
+#endif /* !_LOCORE */
+#endif /* _KERNEL */
+#endif /* _MIPS_SOFTINTR_H_ */
--- /dev/null	2003-04-28 20:00:22.000000000 +0900
+++ mips/mips/softintr.c	2003-04-28 20:41:55.000000000 +0900
@@ -0,0 +1,172 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <net/netisr.h>			/* Legacy softnet support */
+
+#include <machine/intr.h>
+
+/* XXX For legacy software interrupts. */
+struct mips_soft_intrhand *softnet_intrhand;
+
+struct mips_soft_intr mips_soft_intrs[_IPL_NSOFT];
+
+/*
+ * softintr_init:
+ *
+ *	Initialize the software interrupt system.
+ */
+void
+softintr_init(void)
+{
+	static const char *softintr_names[] = IPL_SOFTNAMES;
+	struct mips_soft_intr *msi;
+	int i;
+
+	for (i = 0; i < _IPL_NSOFT; i++) {
+		msi = &mips_soft_intrs[i];
+		TAILQ_INIT(&msi->softintr_q);
+		msi->softintr_ipl = IPL_SOFT + i;
+		evcnt_attach_dynamic(&msi->softintr_evcnt, EVCNT_TYPE_INTR,
+		    NULL, "soft", softintr_names[i]);
+	}
+
+	/* XXX Establish legacy soft interrupt handlers. */
+	softnet_intrhand = softintr_establish(IPL_SOFTNET,
+	    (void (*)(void *))netintr, NULL);
+
+	KASSERT(softnet_intrhand != NULL);
+}
+
+/*
+ * softintr_establish:		[interface]
+ *
+ *	Register a software interrupt handler.
+ */
+void *
+softintr_establish(int ipl, void (*func)(void *), void *arg)
+{
+	struct mips_soft_intr *msi;
+	struct mips_soft_intrhand *sih;
+
+	if (__predict_false(ipl >= (IPL_SOFT + _IPL_NSOFT) ||
+			    ipl < IPL_SOFT))
+		panic("softintr_establish");
+
+	msi = &mips_soft_intrs[ipl - IPL_SOFT];
+
+	sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
+	if (__predict_true(sih != NULL)) {
+		sih->sih_intrhead = msi;
+		sih->sih_func = func;
+		sih->sih_arg = arg;
+		sih->sih_pending = 0;
+	}
+	return sih;
+}
+
+/*
+ * softintr_disestablish:	[interface]
+ *
+ *	Unregister a software interrupt handler.
+ */
+void
+softintr_disestablish(void *arg)
+{
+	struct mips_soft_intrhand *sih = arg;
+	struct mips_soft_intr *msi = sih->sih_intrhead;
+	int s;
+
+	s = splhigh();
+	if (sih->sih_pending) {
+		TAILQ_REMOVE(&msi->softintr_q, sih, sih_q);
+		sih->sih_pending = 0;
+	}
+	splx(s);
+
+	free(sih, M_DEVBUF);
+}
+
+/*
+ * softintr_dispatch:
+ *
+ *	Process pending software interrupts.
+ *
+ *	Called at splsoft()
+ */
+void
+softintr_dispatch(ipending)
+	u_int32_t ipending;
+{
+	struct mips_soft_intr *msi;
+	struct mips_soft_intrhand *sih;
+	int i, s;
+
+	for (i = _IPL_NSOFT - 1; i >= 0; i--) {
+		if ((ipending & ipl_si_to_sr[i]) == 0)
+			continue;
+
+		msi = &mips_soft_intrs[i];
+
+		if (TAILQ_FIRST(&msi->softintr_q) != NULL)
+			msi->softintr_evcnt.ev_count++;
+
+		for (;;) {
+			s = splhigh();
+
+			sih = TAILQ_FIRST(&msi->softintr_q);
+			if (sih != NULL) {
+				TAILQ_REMOVE(&msi->softintr_q, sih, sih_q);
+				sih->sih_pending = 0;
+			}
+
+			splx(s);
+
+			if (sih == NULL)
+				break;
+
+			uvmexp.softs++;
+			(*sih->sih_func)(sih->sih_arg);
+		}
+	}
+}