- rework data structures to align with generic soft interrupts interface

- shift event counters from locore
This commit is contained in:
gmcgarry 2001-12-08 04:00:22 +00:00
parent 52c6bcd104
commit 6b8f8f10c6
1 changed files with 76 additions and 50 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.c,v 1.19 2001/04/12 18:28:40 thorpej Exp $ */
/* $NetBSD: intr.c,v 1.20 2001/12/08 04:00:22 gmcgarry Exp $ */
/*-
* Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc.
@ -54,31 +54,50 @@
#include <machine/cpu.h>
#include <machine/intr.h>
typedef LIST_HEAD(, isr) isr_list_t;
isr_list_t isr_list[NISR];
/*
* The location and size of the autovectored interrupt portion
* of the vector table.
*/
#define ISRLOC 0x18
#define NISR 8
struct hp300_intr hp300_intr_list[NISR];
static const char *hp300_intr_names[NISR] = {
"spurious",
"lev1",
"lev2",
"lev3",
"lev4",
"lev5",
"clock",
"nmi",
};
u_short hp300_ipls[HP300_NIPLS];
extern int intrcnt[]; /* from locore.s */
void intr_computeipl __P((void));
void netintr __P((void));
void
intr_init()
{
struct hp300_intr *hi;
int i;
/* Initialize the ISR lists. */
for (i = 0; i < NISR; ++i)
LIST_INIT(&isr_list[i]);
for (i = 0; i < NISR; ++i) {
hi = &hp300_intr_list[i];
LIST_INIT(&hi->hi_q);
evcnt_attach_dynamic(&hi->hi_evcnt, EVCNT_TYPE_INTR,
NULL, hp300_intr_names[i], "intr");
}
/* Default interrupt priorities. */
hp300_ipls[HP300_IPL_SOFT] = PSL_S|PSL_IPL1;
hp300_ipls[HP300_IPL_BIO] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_NET] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_TTY] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_IMP] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_VM] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_CLOCK] = PSL_S|PSL_IPL6;
hp300_ipls[HP300_IPL_HIGH] = PSL_S|PSL_IPL7;
}
@ -90,23 +109,23 @@ intr_init()
void
intr_computeipl()
{
struct isr *isr;
struct hp300_intrhand *ih;
int ipl;
/* Start with low values. */
hp300_ipls[HP300_IPL_BIO] =
hp300_ipls[HP300_IPL_NET] =
hp300_ipls[HP300_IPL_TTY] =
hp300_ipls[HP300_IPL_IMP] = PSL_S|PSL_IPL3;
hp300_ipls[HP300_IPL_VM] = PSL_S|PSL_IPL3;
for (ipl = 0; ipl < NISR; ipl++) {
for (isr = isr_list[ipl].lh_first; isr != NULL;
isr = isr->isr_link.le_next) {
for (ih = LIST_FIRST(&hp300_intr_list[ipl].hi_q); ih != NULL;
ih = LIST_NEXT(ih, ih_q)) {
/*
* Bump up the level for a given priority,
* if necessary.
*/
switch (isr->isr_priority) {
switch (ih->ih_priority) {
case IPL_BIO:
if (ipl > PSLTOIPL(hp300_ipls[HP300_IPL_BIO]))
hp300_ipls[HP300_IPL_BIO] =
@ -127,7 +146,7 @@ intr_computeipl()
break;
default:
printf("priority = %d\n", isr->isr_priority);
printf("priority = %d\n", ih->ih_priority);
panic("intr_computeipl: bad priority");
}
}
@ -143,8 +162,8 @@ intr_computeipl()
if (hp300_ipls[HP300_IPL_TTY] < hp300_ipls[HP300_IPL_NET])
hp300_ipls[HP300_IPL_TTY] = hp300_ipls[HP300_IPL_NET];
if (hp300_ipls[HP300_IPL_IMP] < hp300_ipls[HP300_IPL_TTY])
hp300_ipls[HP300_IPL_IMP] = hp300_ipls[HP300_IPL_TTY];
if (hp300_ipls[HP300_IPL_VM] < hp300_ipls[HP300_IPL_TTY])
hp300_ipls[HP300_IPL_VM] = hp300_ipls[HP300_IPL_TTY];
}
void
@ -154,7 +173,7 @@ intr_printlevels()
#ifdef DEBUG
printf("psl: bio = 0x%x, net = 0x%x, tty = 0x%x, imp = 0x%x\n",
hp300_ipls[HP300_IPL_BIO], hp300_ipls[HP300_IPL_NET],
hp300_ipls[HP300_IPL_TTY], hp300_ipls[HP300_IPL_IMP]);
hp300_ipls[HP300_IPL_TTY], hp300_ipls[HP300_IPL_VM]);
#endif
printf("interrupt levels: bio = %d, net = %d, tty = %d\n",
@ -174,21 +193,21 @@ intr_establish(func, arg, ipl, priority)
int ipl;
int priority;
{
struct isr *newisr, *curisr;
isr_list_t *list;
struct hp300_intrhand *newih, *curih;
if ((ipl < 0) || (ipl >= NISR))
panic("intr_establish: bad ipl %d", ipl);
newisr = (struct isr *)malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
if (newisr == NULL)
panic("intr_establish: can't allocate space for isr");
newih = (struct hp300_intrhand *)malloc(sizeof(struct hp300_intrhand),
M_DEVBUF, M_NOWAIT);
if (newih == NULL)
panic("intr_establish: can't allocate space for handler");
/* Fill in the new entry. */
newisr->isr_func = func;
newisr->isr_arg = arg;
newisr->isr_ipl = ipl;
newisr->isr_priority = priority;
newih->ih_fn = func;
newih->ih_arg = arg;
newih->ih_ipl = ipl;
newih->ih_priority = priority;
/*
* Some devices are particularly sensitive to interrupt
@ -204,9 +223,9 @@ intr_establish(func, arg, ipl, priority)
* additional work is necessary; we simply insert ourselves
* at the head of the list.
*/
list = &isr_list[ipl];
if (list->lh_first == NULL) {
LIST_INSERT_HEAD(list, newisr, isr_link);
if (LIST_FIRST(&hp300_intr_list[ipl].hi_q) == NULL) {
hp300_intr_list[ipl].hi_q.lh_first = newih;
goto compute;
}
@ -215,10 +234,12 @@ intr_establish(func, arg, ipl, priority)
* and place ourselves after any ISRs with our current (or
* higher) priority.
*/
for (curisr = list->lh_first; curisr->isr_link.le_next != NULL;
curisr = curisr->isr_link.le_next) {
if (newisr->isr_priority > curisr->isr_priority) {
LIST_INSERT_BEFORE(curisr, newisr, isr_link);
for (curih = LIST_FIRST(&hp300_intr_list[ipl].hi_q);
LIST_NEXT(curih,ih_q) != NULL;
curih = LIST_NEXT(curih,ih_q)) {
if (newih->ih_priority > curih->ih_priority) {
LIST_INSERT_BEFORE(curih, newih, ih_q);
goto compute;
}
}
@ -227,12 +248,12 @@ intr_establish(func, arg, ipl, priority)
* We're the least important entry, it seems. We just go
* on the end.
*/
LIST_INSERT_AFTER(curisr, newisr, isr_link);
LIST_INSERT_AFTER(curih, newih, ih_q);
compute:
/* Compute new interrupt levels. */
intr_computeipl();
return (newisr);
return (newih);
}
/*
@ -242,10 +263,10 @@ void
intr_disestablish(arg)
void *arg;
{
struct isr *isr = arg;
struct hp300_intrhand *ih = arg;
LIST_REMOVE(isr, isr_link);
free(isr, M_DEVBUF);
LIST_REMOVE(ih, ih_q);
free(ih, M_DEVBUF);
intr_computeipl();
}
@ -257,21 +278,21 @@ void
intr_dispatch(evec)
int evec; /* format | vector offset */
{
struct isr *isr;
isr_list_t *list;
struct hp300_intrhand *ih;
struct hp300_intr *list;
int handled, ipl, vec;
static int straycount, unexpected;
vec = (evec & 0xfff) >> 2;
if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR)))
panic("isrdispatch: bad vec 0x%x\n", vec);
panic("intr_dispatch: bad vec 0x%x\n", vec);
ipl = vec - ISRLOC;
intrcnt[ipl]++;
hp300_intr_list[ipl].hi_evcnt.ev_count++;
uvmexp.intrs++;
list = &isr_list[ipl];
if (list->lh_first == NULL) {
list = &hp300_intr_list[ipl];
if (LIST_FIRST(&list->hi_q) == NULL) {
printf("intr_dispatch: ipl %d unexpected\n", ipl);
if (++unexpected > 10)
panic("intr_dispatch: too many unexpected interrupts");
@ -280,8 +301,9 @@ intr_dispatch(evec)
handled = 0;
/* Give all the handlers a chance. */
for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next)
handled |= (*isr->isr_func)(isr->isr_arg);
for (ih = LIST_FIRST(&list->hi_q) ; ih != NULL;
ih = LIST_NEXT(ih, ih_q))
handled |= (*ih->ih_fn)(ih->ih_arg);
if (handled)
straycount = 0;
@ -305,13 +327,17 @@ netintr()
if (isr == 0)
return;
#define DONETISR(bit, fn) do { \
if (isr & (1 << bit)) \
fn(); \
} while(0)
#define DONETISR(bit, fn) do { \
if (isr & (1 << bit)) \
fn(); \
} while(0)
s = splsoftnet();
#include <net/netisr_dispatch.h>
#undef DONETISR
splx(s);
}
}