Interrupt overhaul:
- Allocate interrupt handles dynamically from a pool(9) to reduce the number of TLB misses during interrupt dispatch. - Fully support evcnt(9) in all interrupt dispatchers.
This commit is contained in:
parent
041aef4bee
commit
89612efe30
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: superio.c,v 1.9 2002/10/02 05:33:54 thorpej Exp $ */
|
||||
/* $NetBSD: superio.c,v 1.10 2002/10/14 14:19:29 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -59,6 +59,7 @@
|
|||
#include <dev/ic/smc91cxxreg.h>
|
||||
|
||||
#if NCOM > 0
|
||||
#include <evbsh5/evbsh5/machdep.h>
|
||||
#include <evbsh5/dev/sysfpgareg.h>
|
||||
#endif
|
||||
|
||||
|
@ -571,8 +572,12 @@ isa_attach_hook(struct device *parent, struct device *self,
|
|||
const struct evcnt *
|
||||
isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
|
||||
{
|
||||
int inum, dummy;
|
||||
|
||||
return (sysfpga_intr_evcnt(SYSFPGA_IGROUP_SUPERIO));
|
||||
if ((inum = superio_isa_irq_to_inum(irq, &dummy)) < 0)
|
||||
return (NULL);
|
||||
|
||||
return (sysfpga_intr_evcnt(SYSFPGA_IGROUP_SUPERIO, inum));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -668,8 +673,8 @@ superio_console_tag(bus_space_tag_t bt, int port,
|
|||
bus_addr_t base;
|
||||
u_int8_t reg;
|
||||
|
||||
if (bus_space_map(bt, SYSFPGA_OFFSET_SUPERIO, SUPERIO_REG_SZ, 0,
|
||||
&sc.sc_bush))
|
||||
if (bus_space_subregion(bt, _evbsh5_bh_sysfpga,
|
||||
SYSFPGA_OFFSET_SUPERIO, SUPERIO_REG_SZ, &sc.sc_bush))
|
||||
return (-1);
|
||||
sc.sc_bust = bt;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sysfpga.c,v 1.11 2002/10/05 12:18:58 scw Exp $ */
|
||||
/* $NetBSD: sysfpga.c,v 1.12 2002/10/14 14:19:29 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -121,14 +121,24 @@ static int sysfpga_intr_handler_irl2(void *);
|
|||
static int sysfpga_intr_handler_irl3(void *);
|
||||
#endif
|
||||
|
||||
static int sysfpga_intr_dispatch(struct sysfpga_softc *,
|
||||
struct sysfpga_ihandler *, int);
|
||||
static int sysfpga_intr_dispatch(const struct sysfpga_ihandler *, int, int);
|
||||
|
||||
|
||||
static const char *sysfpga_cpuclksel[] = {
|
||||
"400/200/100MHz", "400/200/66MHz", "400/200/50MHz", "<invalid>"
|
||||
};
|
||||
|
||||
#if NSUPERIO > 0
|
||||
static const char *sysfpga_superio_intr_names[SYSFPGA_SUPERIO_NINTR] = {
|
||||
"dcd0", "lan", "keyboard", "uart2", "uart1", "lpt", "mouse", "ide"
|
||||
};
|
||||
static struct evcnt sysfpga_superio_intr_events[SYSFPGA_SUPERIO_NINTR];
|
||||
#endif
|
||||
#if NSH5PCI > 0
|
||||
static struct evcnt sysfpga_pci1_intr_events;
|
||||
static struct evcnt sysfpga_pci2_intr_events;
|
||||
#endif
|
||||
|
||||
static struct sysfpga_softc *sysfpga_sc;
|
||||
|
||||
|
||||
|
@ -152,6 +162,10 @@ sysfpgaattach(struct device *parent, struct device *self, void *args)
|
|||
struct sysfpga_attach_args sa;
|
||||
u_int32_t reg;
|
||||
int i;
|
||||
#if (NSUPERIO > 0) || (NSH5PCI > 0)
|
||||
struct evcnt *ev;
|
||||
static const char sysfpga_intr[] = "sysfpga intr";
|
||||
#endif
|
||||
|
||||
sysfpga_sc = sc;
|
||||
|
||||
|
@ -194,6 +208,14 @@ sysfpgaattach(struct device *parent, struct device *self, void *args)
|
|||
|
||||
if (sc->sc_ih[SYSFPGA_IGROUP_SUPERIO] == NULL)
|
||||
panic("sysfpga: failed to register superio isr");
|
||||
|
||||
ev = sh5_intr_evcnt(sc->sc_ih[SYSFPGA_IGROUP_SUPERIO]);
|
||||
for (i = 0; i < SYSFPGA_SUPERIO_NINTR; i++) {
|
||||
evcnt_attach_dynamic(&sysfpga_superio_intr_events[i],
|
||||
EVCNT_TYPE_INTR, ev,
|
||||
(i >= SYSFPGA_SUPERIO_INUM_KBD) ? "isa intr" : sysfpga_intr,
|
||||
sysfpga_superio_intr_names[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NSH5PCI > 0
|
||||
|
@ -203,6 +225,7 @@ sysfpgaattach(struct device *parent, struct device *self, void *args)
|
|||
sc->sc_ih[SYSFPGA_IGROUP_PCI1] =
|
||||
sh5_intr_establish(INTC_INTEVT_IRL2, IST_LEVEL, IPL_SH5PCI,
|
||||
sysfpga_intr_handler_irl2, sc);
|
||||
|
||||
sc->sc_ih[SYSFPGA_IGROUP_PCI2] =
|
||||
sh5_intr_establish(INTC_INTEVT_IRL3, IST_LEVEL, IPL_SH5PCI,
|
||||
sysfpga_intr_handler_irl3, sc);
|
||||
|
@ -210,6 +233,14 @@ sysfpgaattach(struct device *parent, struct device *self, void *args)
|
|||
if (sc->sc_ih[SYSFPGA_IGROUP_PCI1] == NULL ||
|
||||
sc->sc_ih[SYSFPGA_IGROUP_PCI2] == NULL)
|
||||
panic("sysfpga: failed to register pci isr");
|
||||
|
||||
ev = sh5_intr_evcnt(sc->sc_ih[SYSFPGA_IGROUP_PCI1]);
|
||||
evcnt_attach_dynamic(&sysfpga_pci1_intr_events,
|
||||
EVCNT_TYPE_INTR, ev, sysfpga_intr, "pci1");
|
||||
|
||||
ev = sh5_intr_evcnt(sc->sc_ih[SYSFPGA_IGROUP_PCI2]);
|
||||
evcnt_attach_dynamic(&sysfpga_pci2_intr_events,
|
||||
EVCNT_TYPE_INTR, ev, sysfpga_intr, "pci2");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -278,6 +309,7 @@ sysfpga_intr_handler_irl1(void *arg)
|
|||
{
|
||||
struct sysfpga_softc *sc = arg;
|
||||
struct sysfpga_ihandler *ih;
|
||||
struct evcnt *events = sysfpga_superio_intr_events;
|
||||
u_int8_t intsr, intmr;
|
||||
int sr_reg, h = 0;
|
||||
|
||||
|
@ -289,33 +321,47 @@ sysfpga_intr_handler_irl1(void *arg)
|
|||
(intsr &= intmr) != 0;
|
||||
intsr = sysfpga_reg_read(sc, sr_reg)) {
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_UART1))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_UART1)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_UART1);
|
||||
events[SYSFPGA_SUPERIO_INUM_UART1].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_UART2))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_UART2)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_UART2);
|
||||
events[SYSFPGA_SUPERIO_INUM_UART2].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_MOUSE))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
SYSFPGA_SUPERIO_INUM_MOUSE);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_KBD))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
SYSFPGA_SUPERIO_INUM_KBD);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_LAN))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_LAN)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_LAN);
|
||||
events[SYSFPGA_SUPERIO_INUM_LAN].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_IDE))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_MOUSE)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_MOUSE);
|
||||
events[SYSFPGA_SUPERIO_INUM_MOUSE].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_KBD)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_KBD);
|
||||
events[SYSFPGA_SUPERIO_INUM_KBD].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_IDE)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_IDE);
|
||||
events[SYSFPGA_SUPERIO_INUM_IDE].ev_count++;
|
||||
}
|
||||
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_LPT))
|
||||
h |= sysfpga_intr_dispatch(sc, ih,
|
||||
if (intsr & (1 << SYSFPGA_SUPERIO_INUM_LPT)) {
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SUPERIO,
|
||||
SYSFPGA_SUPERIO_INUM_LPT);
|
||||
events[SYSFPGA_SUPERIO_INUM_LPT].ev_count++;
|
||||
}
|
||||
|
||||
if (h == 0)
|
||||
panic("sysfpga: unclaimed IRL1 interrupt: 0x%02x",
|
||||
|
@ -344,20 +390,26 @@ sysfpga_intr_handler_irl2(void *arg)
|
|||
intsr = sysfpga_reg_read(sc, sr_reg)) {
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI1_INTA))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI1_INTA);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI1_INTA);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI1_INTB))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI1_INTB);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI1_INTB);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI1_INTC))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI1_INTC);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI1_INTC);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI1_INTD))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI1_INTD);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI1_INTD);
|
||||
|
||||
if (h == 0)
|
||||
panic("sysfpga: unclaimed IRL2 interrupt: 0x%02x",
|
||||
intsr);
|
||||
|
||||
sysfpga_pci1_intr_events.ev_count++;
|
||||
}
|
||||
|
||||
return (h);
|
||||
|
@ -380,32 +432,42 @@ sysfpga_intr_handler_irl3(void *arg)
|
|||
intsr = sysfpga_reg_read(sc, sr_reg)) {
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTA))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTA);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTA);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTB))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTB);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTB);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTC))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTC);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTC);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTD))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTD);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTD);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_FAL))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_FAL);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_FAL);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_DEG))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_DEG);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_DEG);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTP))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTP);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTP);
|
||||
|
||||
if (intsr & (1 << SYSFPGA_PCI2_INTS))
|
||||
h |= sysfpga_intr_dispatch(sc, ih, SYSFPGA_PCI2_INTS);
|
||||
h |= sysfpga_intr_dispatch(ih, IPL_SH5PCI,
|
||||
SYSFPGA_PCI2_INTS);
|
||||
|
||||
if (h == 0)
|
||||
panic("sysfpga: unclaimed IRL3 interrupt: 0x%02x",
|
||||
intsr);
|
||||
|
||||
sysfpga_pci2_intr_events.ev_count++;
|
||||
}
|
||||
|
||||
return (h);
|
||||
|
@ -413,8 +475,7 @@ sysfpga_intr_handler_irl3(void *arg)
|
|||
#endif
|
||||
|
||||
static int
|
||||
sysfpga_intr_dispatch(struct sysfpga_softc *sc, struct sysfpga_ihandler *ih,
|
||||
int hnum)
|
||||
sysfpga_intr_dispatch(const struct sysfpga_ihandler *ih, int level, int hnum)
|
||||
{
|
||||
int h, s;
|
||||
|
||||
|
@ -429,22 +490,41 @@ sysfpga_intr_dispatch(struct sysfpga_softc *sc, struct sysfpga_ihandler *ih,
|
|||
* This splraise() is fine since sysfpga's interrupt handler
|
||||
* runs at a lower ipl than anything the child drivers could request.
|
||||
*/
|
||||
s = splraise(ih->ih_level);
|
||||
s = (ih->ih_level > level) ? splraise(ih->ih_level) : -1;
|
||||
|
||||
h = (*ih->ih_func)(ih->ih_arg);
|
||||
splx(s);
|
||||
|
||||
if (s >= 0)
|
||||
splx(s);
|
||||
|
||||
return (h);
|
||||
}
|
||||
|
||||
struct evcnt *
|
||||
sysfpga_intr_evcnt(int group)
|
||||
sysfpga_intr_evcnt(int group, int inum)
|
||||
{
|
||||
struct sysfpga_softc *sc = sysfpga_sc;
|
||||
struct evcnt *ev = NULL;
|
||||
|
||||
KDASSERT(group < SYSFPGA_NGROUPS);
|
||||
KDASSERT(sc->sc_ih[group] != NULL);
|
||||
|
||||
return (sh5_intr_evcnt(sc->sc_ih[group]));
|
||||
switch (group) {
|
||||
case SYSFPGA_IGROUP_SUPERIO:
|
||||
KDASSERT(inum >= 0 && inum < SYSFPGA_SUPERIO_NINTR);
|
||||
ev = &sysfpga_superio_intr_events[inum];
|
||||
break;
|
||||
|
||||
case SYSFPGA_IGROUP_PCI1:
|
||||
ev = &sysfpga_pci1_intr_events;
|
||||
break;
|
||||
|
||||
case SYSFPGA_IGROUP_PCI2:
|
||||
ev = &sysfpga_pci2_intr_events;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ev);
|
||||
}
|
||||
|
||||
void *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sysfpgavar.h,v 1.5 2002/10/05 10:59:10 scw Exp $ */
|
||||
/* $NetBSD: sysfpgavar.h,v 1.6 2002/10/14 14:19:29 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -92,9 +92,9 @@ struct sysfpga_attach_args {
|
|||
#define SYSFPGA_PCI2_NINTR 8
|
||||
|
||||
struct evcnt;
|
||||
extern struct evcnt *sysfpga_intr_evcnt(int);
|
||||
extern void *sysfpga_intr_establish(int, int, int, int (*)(void *), void *);
|
||||
extern void sysfpga_intr_disestablish(void *);
|
||||
extern struct evcnt *sysfpga_intr_evcnt(int, int);
|
||||
extern void sysfpga_nmi_clear(void);
|
||||
extern void sysfpga_sreset(void);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore.S,v 1.7 2002/10/08 15:52:02 scw Exp $ */
|
||||
/* $NetBSD: locore.S,v 1.8 2002/10/14 14:19:29 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -381,8 +381,8 @@ GLOBAL(intrnames)
|
|||
.asciz "softclock"
|
||||
.asciz "softnet"
|
||||
.asciz "irq4"
|
||||
.asciz "isa-lan"
|
||||
.asciz "pci"
|
||||
.asciz "irq5"
|
||||
.asciz "irq6"
|
||||
.asciz "irq7"
|
||||
.asciz "irq8"
|
||||
.asciz "irq9"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pci_intr_machdep.c,v 1.1 2002/09/28 11:16:39 scw Exp $ */
|
||||
/* $NetBSD: pci_intr_machdep.c,v 1.2 2002/10/14 14:19:29 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -51,12 +51,13 @@
|
|||
* XXX: Right now, assume no other PCI-PCI bridges are present on the
|
||||
* primary and secondary buses (they would mess up the bus numbers, and
|
||||
* confuse the code). The solution to this will be to scan the bus
|
||||
* heirarchy to check subordinate bus numbers...
|
||||
* hierarchy to check subordinate bus numbers...
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
@ -95,13 +96,11 @@ struct sh5pci_intr_hooks cayman_pci_hooks = {
|
|||
|
||||
struct cayman_intr_softc {
|
||||
void *sc_ct;
|
||||
struct sh5pci_ihead sc_primary[PCI_INTERRUPT_PIN_MAX];
|
||||
struct sh5pci_ihead sc_p1[PCI_INTERRUPT_PIN_MAX];
|
||||
struct sh5pci_ihead sc_p2[PCI_INTERRUPT_PIN_MAX];
|
||||
struct sh5pci_ihead *sc_primary[PCI_INTERRUPT_PIN_MAX];
|
||||
struct sh5pci_ihead *sc_p1[PCI_INTERRUPT_PIN_MAX];
|
||||
struct sh5pci_ihead *sc_p2[PCI_INTERRUPT_PIN_MAX];
|
||||
};
|
||||
|
||||
static struct cayman_intr_softc softc;
|
||||
|
||||
/*
|
||||
* Magick values stuffed into the interrupt line to identify which
|
||||
* interrupt controller the pin is routed to.
|
||||
|
@ -139,10 +138,12 @@ cayman_intr_init(struct sh5_pci_chipset_tag *ct,
|
|||
void **ih_serr, int (*fn_serr)(void *), void *arg_serr,
|
||||
void **ih_err, int (*fn_err)(void *), void *arg_err)
|
||||
{
|
||||
struct cayman_intr_softc *sc = &softc;
|
||||
struct sh5pci_ihead *ih;
|
||||
struct cayman_intr_softc *sc;
|
||||
int i;
|
||||
|
||||
if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Hook the ERR and SERR interrupts from the bridge, if required.
|
||||
*/
|
||||
|
@ -159,45 +160,13 @@ cayman_intr_init(struct sh5_pci_chipset_tag *ct,
|
|||
}
|
||||
|
||||
/*
|
||||
* Initialise the sh5pci_ihead structures for the PCI INT[A-D] pins
|
||||
* Initialise the sh5pci_ihead structures for the PCI INT[A-D] pins.
|
||||
* We lazy-allocate the ihead stuctures as they are required.
|
||||
*/
|
||||
for (i = 0; i < PCI_INTERRUPT_PIN_MAX; i++) {
|
||||
ih = &sc->sc_primary[i];
|
||||
|
||||
SLIST_INIT(&ih->ih_handlers);
|
||||
ih->ih_cookie = NULL;
|
||||
ih->ih_evcnt = NULL;
|
||||
ih->ih_level = 0;
|
||||
switch (i) {
|
||||
case 0: ih->ih_intevt = INTC_INTEVT_PCI_INTA;
|
||||
break;
|
||||
case 1: ih->ih_intevt = INTC_INTEVT_PCI_INTB;
|
||||
break;
|
||||
case 2: ih->ih_intevt = INTC_INTEVT_PCI_INTC;
|
||||
break;
|
||||
case 3: ih->ih_intevt = INTC_INTEVT_PCI_INTD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PCI_INTERRUPT_PIN_MAX; i++) {
|
||||
ih = &sc->sc_p1[i];
|
||||
|
||||
SLIST_INIT(&ih->ih_handlers);
|
||||
ih->ih_cookie = NULL;
|
||||
ih->ih_evcnt = NULL;
|
||||
ih->ih_level = 0;
|
||||
ih->ih_intevt = INTC_INTEVT_IRL2;
|
||||
}
|
||||
|
||||
for (i = 0; i < PCI_INTERRUPT_PIN_MAX; i++) {
|
||||
ih = &sc->sc_p2[i];
|
||||
|
||||
SLIST_INIT(&ih->ih_handlers);
|
||||
ih->ih_cookie = NULL;
|
||||
ih->ih_evcnt = NULL;
|
||||
ih->ih_level = 0;
|
||||
ih->ih_intevt = INTC_INTEVT_IRL3;
|
||||
sc->sc_primary[i] = NULL;
|
||||
sc->sc_p1[i] = NULL;
|
||||
sc->sc_p2[i] = NULL;
|
||||
}
|
||||
|
||||
sc->sc_ct = ct;
|
||||
|
@ -236,70 +205,158 @@ cayman_intr_conf(void *arg, int bus, int dev, int pin, int swiz, int *line)
|
|||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
cayman_intr_map(void *arg, struct pci_attach_args *pa, pci_intr_handle_t *ih)
|
||||
cayman_intr_map(void *arg, struct pci_attach_args *pa, pci_intr_handle_t *hp)
|
||||
{
|
||||
|
||||
*ih = SH5PCI_IH_CREATE(pa->pa_intrline, pa->pa_intrpin, 0);
|
||||
*hp = SH5PCI_IH_CREATE(pa->pa_intrline, pa->pa_intrpin, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct sh5pci_ihead *
|
||||
cayman_intr_ihead(void *arg, pci_intr_handle_t ih)
|
||||
cayman_intr_ihead(void *arg, pci_intr_handle_t handle)
|
||||
{
|
||||
struct cayman_intr_softc *sc = arg;
|
||||
int pin;
|
||||
struct sh5pci_ihead *ih, **ihp;
|
||||
int pin, evt;
|
||||
|
||||
if (SH5PCI_IH_PIN(ih) == PCI_INTERRUPT_PIN_NONE ||
|
||||
SH5PCI_IH_PIN(ih) > PCI_INTERRUPT_PIN_MAX)
|
||||
pin = SH5PCI_IH_PIN(handle);
|
||||
|
||||
if (pin == PCI_INTERRUPT_PIN_NONE || pin > PCI_INTERRUPT_PIN_MAX)
|
||||
return (NULL);
|
||||
|
||||
pin = SH5PCI_IH_PIN(ih) - 1;
|
||||
pin -= 1;
|
||||
|
||||
if (CAYMAN_INTR_IS_PRIMARY(ih))
|
||||
return (&sc->sc_primary[pin]);
|
||||
if (CAYMAN_INTR_IS_PRIMARY(handle)) {
|
||||
ihp = &sc->sc_primary[pin];
|
||||
switch (pin) {
|
||||
case 0: evt = INTC_INTEVT_PCI_INTA;
|
||||
break;
|
||||
case 1: evt = INTC_INTEVT_PCI_INTB;
|
||||
break;
|
||||
case 2: evt = INTC_INTEVT_PCI_INTC;
|
||||
break;
|
||||
case 3: evt = INTC_INTEVT_PCI_INTD;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
if (CAYMAN_INTR_IS_P1(handle)) {
|
||||
ihp = &sc->sc_p1[pin];
|
||||
evt = INTC_INTEVT_IRL2;
|
||||
} else
|
||||
if (CAYMAN_INTR_IS_P2(handle)) {
|
||||
ihp = &sc->sc_p2[pin];
|
||||
evt = INTC_INTEVT_IRL3;
|
||||
} else
|
||||
return (NULL);
|
||||
|
||||
if (CAYMAN_INTR_IS_P1(ih))
|
||||
return (&sc->sc_p1[pin]);
|
||||
if (*ihp)
|
||||
return (*ihp);
|
||||
|
||||
if (CAYMAN_INTR_IS_P2(ih))
|
||||
return (&sc->sc_p2[pin]);
|
||||
if ((ih = sh5_intr_alloc_handle(sizeof(*ih))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (NULL);
|
||||
SLIST_INIT(&ih->ih_handlers);
|
||||
ih->ih_cookie = NULL;
|
||||
ih->ih_evcnt = NULL;
|
||||
ih->ih_level = 0;
|
||||
ih->ih_intevt = evt;
|
||||
*ihp = ih;
|
||||
|
||||
return (ih);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void *
|
||||
cayman_intr_establish(void *arg, pci_intr_handle_t ih,
|
||||
cayman_intr_establish(void *arg, pci_intr_handle_t handle,
|
||||
int level, int (*func)(void *), void *fnarg)
|
||||
{
|
||||
struct sh5pci_ihead *ihead;
|
||||
int inum, group;
|
||||
struct evcnt *evcnt, *parent_evcnt;
|
||||
int pin, inum, group;
|
||||
void *cookie;
|
||||
const char *ename, *gname;
|
||||
|
||||
if ((ihead = cayman_intr_ihead(arg, ih)) == NULL)
|
||||
if ((ihead = cayman_intr_ihead(arg, handle)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (CAYMAN_INTR_IS_PRIMARY(ih)) {
|
||||
return (sh5_intr_establish(ihead->ih_intevt, IST_LEVEL, level,
|
||||
func, fnarg));
|
||||
pin = (SH5PCI_IH_PIN(handle) - 1) & 3;
|
||||
switch (pin) {
|
||||
case 0: ename = "INTA"; break;
|
||||
case 1: ename = "INTB"; break;
|
||||
case 2: ename = "INTC"; break;
|
||||
case 3: ename = "INTD"; break;
|
||||
}
|
||||
|
||||
inum = SH5PCI_IH_LINE(ih) & 0x03;
|
||||
if (CAYMAN_INTR_IS_PRIMARY(handle)) {
|
||||
cookie = sh5_intr_establish(ihead->ih_intevt, IST_LEVEL, level,
|
||||
func, fnarg);
|
||||
parent_evcnt = sh5_intr_evcnt(cookie);
|
||||
gname = "pci0";
|
||||
} else {
|
||||
inum = SH5PCI_IH_LINE(handle) & 0x03;
|
||||
|
||||
if (CAYMAN_INTR_IS_P1(ih))
|
||||
group = SYSFPGA_IGROUP_PCI1;
|
||||
else
|
||||
group = SYSFPGA_IGROUP_PCI2;
|
||||
if (CAYMAN_INTR_IS_P1(handle)) {
|
||||
group = SYSFPGA_IGROUP_PCI1;
|
||||
gname = "pci1";
|
||||
} else {
|
||||
group = SYSFPGA_IGROUP_PCI2;
|
||||
gname = "pci2";
|
||||
}
|
||||
|
||||
return (sysfpga_intr_establish(group, level, inum, func, fnarg));
|
||||
cookie = sysfpga_intr_establish(group, level, inum, func,
|
||||
fnarg);
|
||||
parent_evcnt = sysfpga_intr_evcnt(group, inum);
|
||||
}
|
||||
|
||||
if (ihead->ih_evcnt == NULL &&
|
||||
(evcnt = sh5_intr_alloc_handle(sizeof(*ihead->ih_evcnt))) != NULL) {
|
||||
evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR, parent_evcnt,
|
||||
gname, ename);
|
||||
ihead->ih_evcnt = evcnt;
|
||||
}
|
||||
|
||||
return (cookie);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
cayman_intr_disestablish(void *arg, pci_intr_handle_t ih, void *cookie)
|
||||
cayman_intr_disestablish(void *arg, pci_intr_handle_t handle, void *cookie)
|
||||
{
|
||||
struct cayman_intr_softc *sc = arg;
|
||||
struct sh5pci_ihead **ihp;
|
||||
int pin;
|
||||
|
||||
if (CAYMAN_INTR_IS_PRIMARY(ih))
|
||||
if (CAYMAN_INTR_IS_PRIMARY(handle))
|
||||
sh5_intr_disestablish(cookie);
|
||||
else
|
||||
sysfpga_intr_disestablish(cookie);
|
||||
|
||||
pin = SH5PCI_IH_PIN(handle);
|
||||
|
||||
if (pin == PCI_INTERRUPT_PIN_NONE || pin > PCI_INTERRUPT_PIN_MAX)
|
||||
return; /* XXX: Should probably panic */
|
||||
|
||||
pin -= 1;
|
||||
|
||||
if (CAYMAN_INTR_IS_PRIMARY(handle))
|
||||
ihp = &sc->sc_primary[pin];
|
||||
else
|
||||
if (CAYMAN_INTR_IS_P1(handle))
|
||||
ihp = &sc->sc_p1[pin];
|
||||
else
|
||||
if (CAYMAN_INTR_IS_P2(handle))
|
||||
ihp = &sc->sc_p2[pin];
|
||||
else
|
||||
return; /* XXX: Should probably panic */
|
||||
|
||||
if (*ihp == NULL)
|
||||
return; /* XXX: Should probably panic */
|
||||
|
||||
if ((*ihp)->ih_evcnt) {
|
||||
evcnt_detach((*ihp)->ih_evcnt);
|
||||
sh5_intr_free_handle((*ihp)->ih_evcnt);
|
||||
}
|
||||
|
||||
sh5_intr_free_handle(*ihp);
|
||||
*ihp = NULL;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intc.c,v 1.7 2002/10/02 15:52:36 thorpej Exp $ */
|
||||
/* $NetBSD: intc.c,v 1.8 2002/10/14 14:19:27 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -159,7 +159,7 @@ intcattach(struct device *parent, struct device *self, void *args)
|
|||
intc_reg_write(sc, INTC_REG_ICR_CLEAR, INTC_ICR_CLEAR_IRL_MODE_LEVEL);
|
||||
#endif
|
||||
|
||||
sh5_intr_init(31, intc_enable, intc_disable, sc);
|
||||
sh5_intr_init(intc_enable, intc_disable, sc);
|
||||
|
||||
printf(": Interrupt Controller\n");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intr.h,v 1.4 2002/10/01 21:07:31 scw Exp $ */
|
||||
/* $NetBSD: intr.h,v 1.5 2002/10/14 14:19:28 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -99,8 +99,10 @@ extern struct evcnt *sh5_intr_evcnt(void *);
|
|||
/* Internal use only */
|
||||
extern void softintr_dispatch(u_int, u_int);
|
||||
extern void softintr_init(void);
|
||||
extern void sh5_intr_init(int, void (*)(void *, u_int, int, int),
|
||||
extern void sh5_intr_init(void (*)(void *, u_int, int, int),
|
||||
void (*)(void *, u_int), void *);
|
||||
extern void *sh5_intr_alloc_handle(size_t);
|
||||
extern void sh5_intr_free_handle(void *);
|
||||
extern struct evcnt _sh5_intr_events[];
|
||||
extern void _cpu_intr_set(u_int);
|
||||
extern void _cpu_intr_resume(u_int);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sh5_pci.c,v 1.6 2002/10/04 10:22:24 scw Exp $ */
|
||||
/* $NetBSD: sh5_pci.c,v 1.7 2002/10/14 14:19:28 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -771,13 +771,13 @@ sh5pci_intr_establish(void *arg, pci_intr_handle_t ih,
|
|||
if (ihead == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((ic = malloc(sizeof(*ic), M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
if ((ic = sh5_intr_alloc_handle(sizeof(*ic))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
s = splhigh();
|
||||
if (ihead->ih_cookie != NULL && ihead->ih_level != level) {
|
||||
splx(s);
|
||||
free(ic, M_DEVBUF);
|
||||
sh5_intr_free_handle(ic);
|
||||
printf("sh5pci_intr_establish: shared level mismatch");
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -821,17 +821,19 @@ sh5pci_intr_disestablish(void *arg, void *cookie)
|
|||
SLIST_REMOVE(&ihead->ih_handlers, ic, sh5pci_icookie, ic_next);
|
||||
|
||||
/*
|
||||
* If we're removing the last handler, unhook the interrupt
|
||||
* If we're removing the last handler, unhook the interrupt.
|
||||
*/
|
||||
if (SLIST_EMPTY(&ihead->ih_handlers)) {
|
||||
(*sc->sc_intr->ih_intr_disestablish)(sc->sc_intr_arg,
|
||||
ic->ic_ih, ihead->ih_cookie);
|
||||
ihead->ih_cookie = NULL;
|
||||
ihead->ih_level = 0;
|
||||
/*
|
||||
* Note that ihead is likely to be invalid now if the back-end
|
||||
* does lazy-allocation of the sh5pci_ihead structures...
|
||||
*/
|
||||
}
|
||||
splx(s);
|
||||
|
||||
free(ic, M_DEVBUF);
|
||||
sh5_intr_free_handle(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -845,8 +847,13 @@ sh5pci_intr_dispatch(void *arg)
|
|||
* Call all the handlers registered for a particular interrupt pin
|
||||
* and accumulate their "handled" status.
|
||||
*/
|
||||
SLIST_FOREACH(ic, &ihead->ih_handlers, ic_next)
|
||||
rv |= (*ic->ic_func)(ic->ic_arg);
|
||||
SLIST_FOREACH(ic, &ihead->ih_handlers, ic_next) {
|
||||
if ((*ic->ic_func)(ic->ic_arg)) {
|
||||
if (ihead->ih_evcnt)
|
||||
ihead->ih_evcnt->ev_count++;
|
||||
rv++;
|
||||
}
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: interrupt.c,v 1.5 2002/10/08 15:55:07 scw Exp $ */
|
||||
/* $NetBSD: interrupt.c,v 1.6 2002/10/14 14:19:28 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Wasabi Systems, Inc.
|
||||
|
@ -72,34 +72,49 @@
|
|||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pool.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <uvm/uvm_extern.h> /* uvmexp.intrs */
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/cacheops.h>
|
||||
|
||||
|
||||
/*
|
||||
* INTEVT to intrhand mapper.
|
||||
* SH5 interrupt handlers are tracked using instances of the following
|
||||
* structure.
|
||||
*/
|
||||
static int8_t intevt_to_ih[256];
|
||||
|
||||
struct intrhand {
|
||||
int (*ih_func)(void *);
|
||||
void *ih_arg;
|
||||
int ih_type;
|
||||
int ih_level;
|
||||
u_int ih_intevt;
|
||||
int ih_idx;
|
||||
};
|
||||
|
||||
static struct intrhand *intrhand;
|
||||
static int szintrhand;
|
||||
/*
|
||||
* The list of all possible interrupt handlers, indexed by INTEVT
|
||||
*/
|
||||
static struct intrhand *intrhand[256];
|
||||
|
||||
#define INTEVT_TO_IH_INDEX(x) ((int)((x) >> 5) & 0xff)
|
||||
#define INTEVT_IH(x) (intrhand[INTEVT_TO_IH_INDEX(x)])
|
||||
|
||||
/*
|
||||
* Pool of interrupt handles.
|
||||
* This is used by all native SH5 interrupt drivers. It ensures the
|
||||
* handle is allocated from KSEG0, which avoids taking multiple TLB
|
||||
* before the real interrupt handler is even called.
|
||||
*/
|
||||
static struct pool intrhand_pool;
|
||||
|
||||
/*
|
||||
* By default, each interrupt handle is 64-bytes in size. This allows
|
||||
* some room for future growth.
|
||||
*/
|
||||
#define INTRHAND_SIZE 64
|
||||
|
||||
#define INTEVT_TO_MAP_INDEX(x) ((x) >> 5)
|
||||
#define INTEVT_TO_IH_INDEX(x) intevt_to_ih[INTEVT_TO_MAP_INDEX(x)]
|
||||
#define INTEVT_IH(x) (&intrhand[INTEVT_TO_IH_INDEX(x)])
|
||||
|
||||
static void (*intr_enable)(void *, u_int, int, int);
|
||||
static void (*intr_disable)(void *, u_int);
|
||||
|
@ -109,42 +124,22 @@ struct evcnt _sh5_intr_events[NIPL];
|
|||
extern const char intrnames[]; /* Defined in port-specific code */
|
||||
|
||||
void sh5_intr_dispatch(struct intrframe *);
|
||||
static struct intrhand *alloc_ih(void);
|
||||
static void free_ih(struct intrhand *);
|
||||
static int spurious_interrupt(void *);
|
||||
|
||||
|
||||
/*
|
||||
* SH5 Interrupt support.
|
||||
*/
|
||||
void
|
||||
sh5_intr_init(int nhandles,
|
||||
void (*int_enable)(void *, u_int, int, int),
|
||||
sh5_intr_init(void (*int_enable)(void *, u_int, int, int),
|
||||
void (*int_disable)(void *, u_int),
|
||||
void *arg)
|
||||
{
|
||||
struct intrhand *ih;
|
||||
const char *iname;
|
||||
int i;
|
||||
|
||||
ih = malloc(sizeof(*ih) * (nhandles + 1), M_DEVBUF, M_NOWAIT);
|
||||
if (ih == NULL)
|
||||
panic("sh5_intr_init: Out of memory");
|
||||
pool_init(&intrhand_pool, INTRHAND_SIZE, SH5_CACHELINE_SIZE,
|
||||
0, 0, NULL, NULL);
|
||||
|
||||
memset(ih, 0, sizeof(*ih) * (nhandles + 1));
|
||||
intrhand = ih;
|
||||
szintrhand = nhandles + 1;
|
||||
intr_enable = int_enable;
|
||||
intr_disable = int_disable;
|
||||
intr_arg = arg;
|
||||
|
||||
ih->ih_func = spurious_interrupt;
|
||||
ih->ih_arg = NULL;
|
||||
ih->ih_idx = 0;
|
||||
ih->ih_level = 0;
|
||||
ih->ih_intevt = 0;
|
||||
ih->ih_type = IST_NONE;
|
||||
|
||||
iname = intrnames;
|
||||
for (i = 0; i < NIPL; i++) {
|
||||
evcnt_attach_dynamic(&_sh5_intr_events[i], EVCNT_TYPE_INTR,
|
||||
|
@ -158,11 +153,20 @@ sh5_intr_establish(int intevt, int trigger, int level,
|
|||
int (*ih_func)(void *), void *ih_arg)
|
||||
{
|
||||
struct intrhand *ih;
|
||||
int idx;
|
||||
|
||||
KDASSERT(szintrhand != 0);
|
||||
KDASSERT(intr_enable != NULL);
|
||||
KDASSERT(level > 0 && level < NIPL);
|
||||
|
||||
ih = alloc_ih();
|
||||
idx = INTEVT_TO_IH_INDEX(intevt);
|
||||
KDASSERT(idx < (sizeof(intrhand) / sizeof(struct intrhand *)));
|
||||
|
||||
if (intrhand[idx] != NULL)
|
||||
return (NULL); /* Perhaps panic? */
|
||||
|
||||
if ((ih = sh5_intr_alloc_handle(sizeof(*ih))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ih->ih_func = ih_func;
|
||||
ih->ih_arg = ih_arg;
|
||||
ih->ih_level = level;
|
||||
|
@ -170,7 +174,7 @@ sh5_intr_establish(int intevt, int trigger, int level,
|
|||
ih->ih_type = trigger;
|
||||
|
||||
/* Map interrupt handler */
|
||||
INTEVT_TO_IH_INDEX(intevt) = ih->ih_idx;
|
||||
intrhand[idx] = ih;
|
||||
|
||||
(*intr_enable)(intr_arg, intevt, trigger, level);
|
||||
|
||||
|
@ -181,13 +185,18 @@ void
|
|||
sh5_intr_disestablish(void *cookie)
|
||||
{
|
||||
struct intrhand *ih = cookie;
|
||||
int idx;
|
||||
|
||||
idx = INTEVT_TO_IH_INDEX(ih->ih_intevt);
|
||||
KDASSERT(idx < (sizeof(intrhand) / sizeof(struct intrhand *)));
|
||||
KDASSERT(intrhand[idx] == ih);
|
||||
|
||||
(*intr_disable)(intr_arg, ih->ih_intevt);
|
||||
|
||||
/* Unmap interrupt handler */
|
||||
INTEVT_TO_IH_INDEX(ih->ih_intevt) = 0;
|
||||
intrhand[idx] = NULL;
|
||||
|
||||
free_ih(ih);
|
||||
sh5_intr_free_handle(ih);
|
||||
}
|
||||
|
||||
struct evcnt *
|
||||
|
@ -198,17 +207,43 @@ sh5_intr_evcnt(void *cookie)
|
|||
return (&_sh5_intr_events[ih->ih_level]);
|
||||
}
|
||||
|
||||
void *
|
||||
sh5_intr_alloc_handle(size_t size)
|
||||
{
|
||||
|
||||
if (size > INTRHAND_SIZE)
|
||||
panic("sh5_intr_alloc_handle: size > %d", INTRHAND_SIZE);
|
||||
|
||||
return (pool_get(&intrhand_pool, 0));
|
||||
}
|
||||
|
||||
void
|
||||
sh5_intr_free_handle(void *handle)
|
||||
{
|
||||
|
||||
pool_put(&intrhand_pool, handle);
|
||||
}
|
||||
|
||||
void
|
||||
sh5_intr_dispatch(struct intrframe *fr)
|
||||
{
|
||||
extern u_long intrcnt[];
|
||||
struct intrhand *ih;
|
||||
int idx;
|
||||
|
||||
KDASSERT(INTEVT_TO_MAP_INDEX(fr->if_state.sf_intevt) < 0x100);
|
||||
idx = INTEVT_TO_IH_INDEX(fr->if_state.sf_intevt);
|
||||
KDASSERT(idx < (sizeof(intrhand) / sizeof(struct intrhand *)));
|
||||
|
||||
ih = INTEVT_IH(fr->if_state.sf_intevt);
|
||||
|
||||
KDASSERT(ih->ih_func != NULL);
|
||||
if ((ih = intrhand[idx]) == NULL) {
|
||||
int level;
|
||||
__asm __volatile("getcon sr, %0" : "=r"(level));
|
||||
printf(
|
||||
"sh5_intr_dispatch: spurious level %d irq: intevt 0x%lx\n",
|
||||
(level >> SH5_CONREG_SR_IMASK_SHIFT) &
|
||||
SH5_CONREG_SR_IMASK_MASK,
|
||||
(unsigned long)fr->if_state.sf_intevt);
|
||||
return;
|
||||
}
|
||||
|
||||
_sh5_intr_events[ih->ih_level].ev_count++;
|
||||
intrcnt[ih->ih_level]++;
|
||||
|
@ -221,47 +256,12 @@ sh5_intr_dispatch(struct intrframe *fr)
|
|||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* We don't support Edge or Pulse triggered interrupts at this time */
|
||||
|
||||
printf("sh5_intr_dispatch: Unclaimed %s-triggered interrupt...\n",
|
||||
(ih->ih_type == IST_PULSE) ? "Pulse" : "Edge");
|
||||
printf("sh5_intr_dispatch: INTEVT=0x%x, level=%d\n",
|
||||
(int) fr->if_state.sf_intevt, ih->ih_level);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handle allocator.
|
||||
*/
|
||||
static struct intrhand *
|
||||
alloc_ih()
|
||||
{
|
||||
/* #0 is reserved for unregistered interrupt. */
|
||||
struct intrhand *ih = &intrhand[1];
|
||||
int i;
|
||||
|
||||
for (i = 1; i < szintrhand; i++, ih++)
|
||||
if (ih->ih_idx == 0) { /* no driver use this. */
|
||||
ih->ih_idx = i; /* register myself */
|
||||
return (ih);
|
||||
}
|
||||
|
||||
panic("intc_alloc_ih: Out of interrupt handles!");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
free_ih(struct intrhand *ih)
|
||||
{
|
||||
|
||||
memset(ih, 0, sizeof(*ih));
|
||||
}
|
||||
|
||||
static int
|
||||
spurious_interrupt(void *arg)
|
||||
{
|
||||
struct intrframe *fr = arg;
|
||||
|
||||
printf("Spurious Interrupt: INTEVT=0x%x\n",
|
||||
(int) fr->if_state.sf_intevt);
|
||||
panic("oops");
|
||||
/* NOTREACHED */
|
||||
return (0);
|
||||
printf("sh5_intr_dispatch: INTEVT=0x%lx, level=%d\n",
|
||||
(unsigned long) fr->if_state.sf_intevt, ih->ih_level);
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue