- Prepare common structures for interrupt handler and share them between

Hyper-bus and AP-bus.
- Use LIST rather than static array for interrupt dispatcher.
This commit is contained in:
tsutsui 2003-05-10 09:46:24 +00:00
parent a85b205894
commit 764da5a461
10 changed files with 140 additions and 97 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: apbus.c,v 1.14 2003/05/03 18:10:53 wiz Exp $ */
/* $NetBSD: apbus.c,v 1.15 2003/05/10 09:46:24 tsutsui Exp $ */
/*-
* Copyright (C) 1999 SHIMIZU Ryo. All rights reserved.
@ -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 @@ struct apbus_softc {
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 @@ apbusattach(parent, self, aux)
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 @@ apbusattach(parent, self, aux)
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 @@ apbus_intr_call(level, stat)
int level;
int stat;
{
int nintr = 0;
struct ap_intrhand *ai;
struct newsmips_intr *ip;
struct newsmips_intrhand *ih;
int nintr;
for (ai = apintr[level]; ai != NULL; ai = ai->ai_next) {
if (ai->ai_mask & stat) {
nintr += (*ai->ai_func)(ai->ai_aux);
}
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 @@ apbus_intr_call(level, stat)
* 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;
ai = malloc(sizeof(*ai), M_DEVBUF, M_NOWAIT);
if (ai == NULL)
ip = &apintr_tab[level];
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;
ih->ih_mask = mask;
ih->ih_priority = priority;
ih->ih_func = func;
ih->ih_arg = arg;
for (aip = &apintr[level]; *aip != NULL; aip = &(*aip)->ai_next) {
if ((*aip)->ai_priority < priority)
break;
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

View File

@ -1,10 +1,12 @@
/* $NetBSD: hb.c,v 1.11 2003/05/09 13:36:40 tsutsui Exp $ */
/* $NetBSD: hb.c,v 1.12 2003/05/10 09:46:25 tsutsui Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <machine/autoconf.h>
#include <machine/intr.h>
#include <newsmips/dev/hbvar.h>
@ -18,13 +20,8 @@ CFATTACH_DECL(hb, sizeof(struct device),
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)
@ -47,9 +44,17 @@ hb_attach(parent, self, aux)
void *aux;
{
struct hb_attach_args ha;
struct newsmips_intr *ip;
int i;
printf("\n");
memset(&ha, 0, sizeof(ha));
for (i = 0; i < NLEVEL; i++) {
ip = &hbintr_tab[i];
LIST_INIT(&ip->intr_q);
}
config_search(hb_search, self, &ha);
}
@ -93,50 +98,58 @@ hb_print(args, name)
}
void *
hb_intr_establish(irq, level, func, arg)
int irq, level;
hb_intr_establish(level, mask, priority, func, arg)
int level, mask, priority;
int (*func) __P((void *));
void *arg;
{
struct intrhand *ih = hb_intrhand[irq];
int i;
struct newsmips_intr *ip;
struct newsmips_intrhand *ih, *curih;
for (i = NHBINTR; i > 0; i--) {
if (ih->func == NULL)
goto found;
ih++;
ip = &hbintr_tab[level];
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_level = level;
ih->ih_mask = mask;
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, stat)
int level;
int stat;
{
struct intrhand *ih;
int i;
struct newsmips_intr *ip;
struct newsmips_intrhand *ih;
ih = hb_intrhand[irq];
for (i = NHBINTR; i > 0; i--) {
if (ih->func)
(*ih->func)(ih->arg);
ih++;
ip = &hbintr_tab[level];
LIST_FOREACH(ih, &ip->intr_q, ih_q) {
if (ih->ih_mask & stat)
(*ih->ih_func)(ih->ih_arg);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hbvar.h,v 1.1 2003/05/09 13:36:40 tsutsui Exp $ */
/* $NetBSD: hbvar.h,v 1.2 2003/05/10 09:46:25 tsutsui Exp $ */
/*
* Copyright (C) 2003 Izumi Tsutsui. All rights reserved.
@ -42,5 +42,5 @@ struct hb_attach_args {
#define hb_badaddr news3400_badaddr
void *hb_intr_establish(int, int, int (*)(void *), void *);
void hb_intr_dispatch(int);
void *hb_intr_establish(int, int, int, int (*)(void *), void *);
void hb_intr_dispatch(int, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_le.c,v 1.10 2003/05/09 13:36:40 tsutsui Exp $ */
/* $NetBSD: if_le.c,v 1.11 2003/05/10 09:46:25 tsutsui Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@ -154,7 +154,7 @@ le_attach(parent, self, aux)
struct le_softc *lesc = (struct le_softc *)self;
struct lance_softc *sc = &lesc->sc_am7990.lsc;
struct hb_attach_args *ha = aux;
int intlevel;
int intlevel, intmask;
u_char *p;
intlevel = ha->ha_level;
@ -169,14 +169,17 @@ le_attach(parent, self, aux)
case LANCE_PORT:
sc->sc_mem = (void *)LANCE_MEMORY;
p = (u_char *)(ETHER_ID+16);
intmask = INTST1_LANCE;
break;
case LANCE_PORT1:
sc->sc_mem = (void *)LANCE_MEMORY1;
p = (u_char *)(ETHER_ID1+16);
intmask = INTST1_SLOT3; /* XXX not tested */
break;
case LANCE_PORT2:
sc->sc_mem = (void *)LANCE_MEMORY2;
p = (u_char *)(ETHER_ID2+16);
intmask = INTST1_SLOT3; /* XXX not tested */
break;
default:
@ -214,5 +217,5 @@ le_attach(parent, self, aux)
sc->sc_hwinit = NULL;
am7990_config(&lesc->sc_am7990);
hb_intr_establish(intlevel, IPL_NET, am7990_intr, sc);
hb_intr_establish(intlevel, intmask, IPL_NET, am7990_intr, sc);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: kb_hb.c,v 1.5 2003/05/09 13:36:40 tsutsui Exp $ */
/* $NetBSD: kb_hb.c,v 1.6 2003/05/10 09:46:25 tsutsui Exp $ */
/*-
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
@ -129,7 +129,7 @@ kb_hb_attach(parent, self, aux)
}
printf("\n");
hb_intr_establish(intr, IPL_TTY, kb_hb_intr, sc);
hb_intr_establish(intr, INTEN0_KBDINT, IPL_TTY, kb_hb_intr, sc);
aa.console = cons;
aa.keymap = &kb_hb_keymapdata;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ms_hb.c,v 1.6 2003/05/10 03:57:28 tsutsui Exp $ */
/* $NetBSD: ms_hb.c,v 1.7 2003/05/10 09:46:25 tsutsui Exp $ */
/*-
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
@ -107,7 +107,7 @@ ms_hb_attach(parent, self, aux)
printf(" level %d\n", intr);
hb_intr_establish(intr, IPL_TTY, ms_hb_intr, sc);
hb_intr_establish(intr, INTEN0_MSINT, IPL_TTY, ms_hb_intr, sc);
aa.accessops = &ms_hb_accessops;
aa.accesscookie = sc;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sc_wrap.c,v 1.23 2003/05/09 13:36:40 tsutsui Exp $ */
/* $NetBSD: sc_wrap.c,v 1.24 2003/05/10 09:46:25 tsutsui Exp $ */
/*
* This driver is slow! Need to rewrite.
@ -125,7 +125,7 @@ cxd1185_attach(parent, self, aux)
cxd1185_init(sc);
DELAY(100000);
hb_intr_establish(intlevel, IPL_BIO, sc_intr, sc);
hb_intr_establish(intlevel, INTEN1_DMA, IPL_BIO, sc_intr, sc);
config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: zs_hb.c,v 1.14 2003/05/10 03:27:33 tsutsui Exp $ */
/* $NetBSD: zs_hb.c,v 1.15 2003/05/10 09:46:25 tsutsui Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@ -296,7 +296,8 @@ zs_hb_attach(parent, self, aux)
if (!didintr) {
didintr = 1;
hb_intr_establish(intlevel, IPL_SERIAL, zshard_hb, NULL);
hb_intr_establish(intlevel, INTST1_SCC, IPL_SERIAL,
zshard_hb, NULL);
}
/* XXX; evcnt_attach() ? */

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.11 2001/04/13 23:30:02 thorpej Exp $ */
/* $NetBSD: intr.h,v 1.12 2003/05/10 09:46:25 tsutsui Exp $ */
/*
* Copyright (c) 1998 Jonathan Stone. All rights reserved.
@ -44,6 +44,7 @@
#ifdef _KERNEL
#ifndef _LOCORE
#include <sys/device.h>
#include <mips/cpuregs.h>
extern int _splraise __P((int));
@ -102,6 +103,20 @@ extern void _clrsoftintr __P((int));
#define splsoftnet() _splraise(MIPS_INT_MASK_SPL_SOFT1)
#define spllowersoftclock() _spllower(MIPS_INT_MASK_SPL_SOFT0)
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;
};
/*
* Index into intrcnt[], which is defined in locore
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: news3400.c,v 1.10 2003/05/09 13:36:42 tsutsui Exp $ */
/* $NetBSD: news3400.c,v 1.11 2003/05/10 09:46:26 tsutsui Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. All rights reserved.
@ -84,7 +84,7 @@ news3400_intr(status, cause, pc, ipending)
}
if (stat)
hb_intr_dispatch(2);
hb_intr_dispatch(2, stat);
cause &= ~MIPS_INT_MASK_2;
}
@ -142,7 +142,7 @@ news3400_level0_intr()
stat = *intst1 & LEVEL0_MASK;
*intclr1 = stat;
hb_intr_dispatch(0);
hb_intr_dispatch(0, stat);
if (stat & INTST1_SLOT1)
intrcnt[SLOT1_INTR]++;
@ -170,7 +170,7 @@ news3400_level1_intr()
stat1 &= saved_inten1;
hb_intr_dispatch(1);
hb_intr_dispatch(1, stat1);
*inten1 = saved_inten1;