Subject: generic soft interrupt patch
To: None <port-arc@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-arc
Date: 04/28/2003 15:35:17
I've just made a patch to support generic soft interrupt for arc.
It's based on algor port (as newsmips patch) and seems to work
on my NEC-JC94, but I'm not sure if isabus.c fix is correct or not.
(Has anyone tried any ISA device that uses interrupts on arc?)
Note it seems that getty for /dev/tty00 does not work if console isn't
com, but I think old kernels also has the same problem.
cpu_intr() in arc_trap.c should also be rewritten as noted
in arch/arc/TODO file, but it's a future work.
(BTW, we should rename arc_trap.c to interrupt.c like other mips ports?)
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp
Index: 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_trap.c 2003/04/27 17:13:01 1.24
+++ arc/arc_trap.c 2003/04/28 06:03:51
@@ -2,6 +2,42 @@
/* $OpenBSD: trap.c,v 1.22 1999/05/24 23:08:59 jason Exp $ */
/*
+ * 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.
+ */
+
+/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -46,9 +82,12 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <uvm/uvm_extern.h>
+#include <net/netisr.h> /* Legacy softnet support */
+
#include <mips/locore.h>
#include <machine/autoconf.h>
@@ -60,6 +99,20 @@
int arc_hardware_intr __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+/* XXX For legacy software interrupts. */
+struct arc_soft_intrhand *softnet_intrhand;
+
+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 */
+};
+
+struct arc_soft_intr arc_soft_intrs[_IPL_NSOFT];
+
#define MIPS_INT_LEVELS 8
struct {
@@ -133,46 +186,131 @@
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) {
+ struct arc_soft_intr *asi;
+ struct arc_soft_intrhand *sih;
+ int i, s;
+
+ 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 */
if (ipending & INT_MASK_REAL_DEV) {
_splset(arc_hardware_intr(status, cause, pc, ipending));
}
+
+ /* software interrupts */
+ ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0);
+ if (ipending == 0)
+ return;
+
+ _clrsoftintr(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
-
- /* 'softnet' interrupt */
- if (ipending & MIPS_SOFT_INT_MASK_1) {
- clearsoftnet();
- uvmexp.softs++;
- netintr();
- }
-
- /* 'softclock' interrupt */
- if (ipending & MIPS_SOFT_INT_MASK_0) {
- clearsoftclock();
- uvmexp.softs++;
- intrcnt[SOFTCLOCK_INTR]++;
- softclock(NULL);
+ for (i = _IPL_NSOFT - 1; i >= 0; i--) {
+ if ((ipending & ipl_si_to_sr[i]) == 0)
+ continue;
+
+ asi = &arc_soft_intrs[i];
+
+ if (TAILQ_FIRST(&asi->softintr_q) != NULL)
+ asi->softintr_evcnt.ev_count++;
+
+ for (;;) {
+ s = splhigh();
+
+ sih = TAILQ_FIRST(&asi->softintr_q);
+ if (sih != NULL) {
+ TAILQ_REMOVE(&asi->softintr_q, sih, sih_q);
+ sih->sih_pending = 0;
+ }
+
+ splx(s);
+
+ if (sih == NULL)
+ break;
+
+ uvmexp.softs++;
+ (*sih->sih_func)(sih->sih_arg);
+ }
}
+}
+
+/*
+ * softintr_init:
+ *
+ * Initialize the software interrupt system.
+ */
+void
+softintr_init(void)
+{
+ static const char *softintr_names[] = IPL_SOFTNAMES;
+ struct arc_soft_intr *asi;
+ int i;
+
+ for (i = 0; i < _IPL_NSOFT; i++) {
+ asi = &arc_soft_intrs[i];
+ TAILQ_INIT(&asi->softintr_q);
+ asi->softintr_ipl = IPL_SOFT + i;
+ evcnt_attach_dynamic(&asi->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 arc_soft_intr *asi;
+ struct arc_soft_intrhand *sih;
+
+ if (__predict_false(ipl >= (IPL_SOFT + _IPL_NSOFT) || ipl < IPL_SOFT))
+ panic("softintr_establish");
+
+ asi = &arc_soft_intrs[ipl - IPL_SOFT];
+
+ sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
+ if (__predict_true(sih != NULL)) {
+ sih->sih_intrhead = asi;
+ 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 arc_soft_intrhand *sih = arg;
+ struct arc_soft_intr *asi = sih->sih_intrhead;
+ int s;
+
+ s = splhigh();
+ if (sih->sih_pending) {
+ TAILQ_REMOVE(&asi->softintr_q, sih, sih_q);
+ sih->sih_pending = 0;
+ }
+ splx(s);
+
+ free(sih, M_DEVBUF);
}
Index: 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/autoconf.c 2002/09/27 02:24:09 1.18
+++ arc/autoconf.c 2003/04/28 06:03:51
@@ -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/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/c_magnum.c 2003/04/27 11:33:36 1.3
+++ arc/c_magnum.c 2003/04/28 06:03:52
@@ -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/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/c_nec_eisa.c 2003/01/31 22:07:52 1.5
+++ arc/c_nec_eisa.c 2003/04/28 06:03:52
@@ -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/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/c_nec_pci.c 2003/01/19 10:06:12 1.4
+++ arc/c_nec_pci.c 2003/04/28 06:03:53
@@ -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/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/locore_machdep.S 2000/06/09 05:07:32 1.8
+++ arc/locore_machdep.S 2003/04/28 06:03:53
@@ -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/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/machdep.c,v
retrieving revision 1.77
diff -u -r1.77 machdep.c
--- arc/machdep.c 2003/04/27 17:05:56 1.77
+++ arc/machdep.c 2003/04/28 06:03:54
@@ -180,15 +180,6 @@
*/
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 */
-};
-
extern char kernel_text[], edata[], end[];
extern struct user *proc0paddr;
Index: 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/p_dti_arcstation.c 2001/06/13 15:27:17 1.1
+++ arc/p_dti_arcstation.c 2003/04/28 06:03:54
@@ -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/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/p_dti_tyne.c 2001/06/13 15:27:18 1.1
+++ arc/p_dti_tyne.c 2003/04/28 06:03:54
@@ -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/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/p_sni_rm200pci.c 2001/06/13 15:36:44 1.1
+++ arc/p_sni_rm200pci.c 2003/04/28 06:03:55
@@ -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: conf/std.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/std.arc,v
retrieving revision 1.14
diff -u -r1.14 std.arc
--- conf/std.arc 2003/04/28 05:03:44 1.14
+++ conf/std.arc 2003/04/28 06:03:55
@@ -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: include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/include/intr.h,v
retrieving revision 1.10
diff -u -r1.10 intr.h
--- include/intr.h 2001/06/13 15:08:06 1.10
+++ include/intr.h 2003/04/28 06:03:55
@@ -1,7 +1,11 @@
/* $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
@@ -13,125 +17,158 @@
* 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 */
#define IST_PULSE 1 /* pulsed */
#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>
+#include <sys/device.h>
+#include <sys/lock.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;
+extern const u_int32_t ipl_si_to_sr[_IPL_NSOFT];
-/*
- * 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 */
+
+#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])
+
+#define setsoft(x) \
+do { \
+ _setsoftintr(ipl_si_to_sr[(x) - IPL_SOFT]); \
+} while (/*CONSTCOND*/0)
+
+struct arc_soft_intrhand {
+ TAILQ_ENTRY(arc_soft_intrhand) sih_q;
+ struct arc_soft_intr *sih_intrhead;
+ void (*sih_func)(void *);
+ void *sih_arg;
+ int sih_pending;
+};
-struct splvec {
- int splbio;
- int splnet;
- int spltty;
- int splvm;
- int splclock;
- int splstatclock;
+struct arc_soft_intr {
+ TAILQ_HEAD(,arc_soft_intrhand) softintr_q;
+ struct evcnt softintr_evcnt;
+ struct simplelock softintr_slock;
+ unsigned long softintr_ipl;
};
-extern struct splvec splvec;
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_disestablish(void *);
+void softintr_init(void);
+void softintr_dispatch(void);
+
+#define softintr_schedule(arg) \
+do { \
+ struct arc_soft_intrhand *__sih = (arg); \
+ struct arc_soft_intr *__si = __sih->sih_intrhead; \
+ int __s; \
+ \
+ __s = splhigh(); \
+ simple_lock(&__si->softintr_slock); \
+ if (__sih->sih_pending == 0) { \
+ TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \
+ __sih->sih_pending = 1; \
+ setsoft(__si->softintr_ipl); \
+ } \
+ simple_unlock(&__si->softintr_slock); \
+ splx(__s); \
+} while (/*CONSTCOND*/0)
+
+/* XXX For legacy software interrupts. */
+extern struct arc_soft_intrhand *softnet_intrhand;
+
+#define setsoftnet() softintr_schedule(softnet_intrhand)
+
/*
* Index into intrcnt[], which is defined in locore
*/
-#define SOFTCLOCK_INTR 0
-#define SOFTNET_INTR 1
-#define FPU_INTR 2
extern u_long intrcnt[];
struct clockframe;
-void arc_set_intr __P((int, int(*)(u_int, struct clockframe *), int));
-
-/* XXX - revisit here */
-int imask[NIPL];
+void arc_set_intr(int, int(*)(u_int, struct clockframe *), int);
#endif /* !_LOCORE */
#endif /* _KERNEL */
Index: include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/include/types.h,v
retrieving revision 1.13
diff -u -r1.13 types.h
--- include/types.h 2002/03/05 16:12:36 1.13
+++ include/types.h 2003/04/28 06:03:55
@@ -6,6 +6,7 @@
#include <mips/types.h>
+#define __HAVE_GENERIC_SOFT_INTERRUPTS
#define __HAVE_DEVICE_REGISTER
#define __HAVE_NWSCONS
Index: isa/isabus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/isa/isabus.c,v
retrieving revision 1.19
diff -u -r1.19 isabus.c
--- isa/isabus.c 2003/04/27 17:05:58 1.19
+++ isa/isabus.c 2003/04/28 06:03:55
@@ -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. */