With the new IPL world, things are easier for us: if we can get the
nell hardware interrupt handler run at IPL_VM, we can call the socket drivers interrupt handler directly. This is always possible on sparc64, but on sparc we might have to fall back to the old softint bounce. Since this uses arbitrary IPLs, we can not use the new softint_* for this - we'll have to use the old sparc_softintr_* functions.
This commit is contained in:
parent
0c0de8072e
commit
258a4b78cf
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: stp4020.c,v 1.52 2007/10/19 12:01:12 ad Exp $ */
|
||||
/* $NetBSD: stp4020.c,v 1.53 2008/01/06 02:29:58 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -41,7 +41,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: stp4020.c,v 1.52 2007/10/19 12:01:12 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: stp4020.c,v 1.53 2008/01/06 02:29:58 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -105,8 +105,10 @@ struct stp4020_socket {
|
|||
int sock; /* Socket number (0 or 1) */
|
||||
int sbus_intno; /* Do we use first (0) or second (1)
|
||||
interrupt? */
|
||||
#ifndef SUN4U
|
||||
int int_enable; /* ICR0 value for interrupt enabled */
|
||||
int int_disable; /* ICR0 value for interrupt disabled */
|
||||
#endif
|
||||
bus_space_tag_t tag; /* socket control io */
|
||||
bus_space_handle_t regs; /* space */
|
||||
bus_space_tag_t pcmciat; /* io space for pcmcia */
|
||||
|
@ -114,7 +116,9 @@ struct stp4020_socket {
|
|||
int (*intrhandler) /* Card driver interrupt handler */
|
||||
(void *);
|
||||
void *intrarg; /* Card interrupt handler argument */
|
||||
#ifndef SUN4U
|
||||
void *softint; /* cookie for the softintr */
|
||||
#endif
|
||||
|
||||
struct {
|
||||
bus_space_handle_t winaddr;/* this window's address */
|
||||
|
@ -131,6 +135,9 @@ struct stp4020_softc {
|
|||
SIMPLEQ_HEAD(, stp4020_event) events; /* Pending events for thread */
|
||||
|
||||
struct stp4020_socket sc_socks[STP4020_NSOCK];
|
||||
#ifndef SUN4U
|
||||
bool sc_use_softint;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -140,7 +147,9 @@ static void stp4020attach(struct device *, struct device *, void *);
|
|||
static int stp4020_intr(void *);
|
||||
static void stp4020_map_window(struct stp4020_socket *h, int win, int speed);
|
||||
static void stp4020_calc_speed(int bus_speed, int ns, int *length, int *cmd_delay);
|
||||
#ifndef SUN4U
|
||||
static void stp4020_intr_dispatch(void *arg);
|
||||
#endif
|
||||
|
||||
CFATTACH_DECL(nell, sizeof(struct stp4020_softc),
|
||||
stp4020match, stp4020attach, NULL, NULL);
|
||||
|
@ -366,13 +375,9 @@ stp4020attach(parent, self, aux)
|
|||
struct sbus_attach_args *sa = aux;
|
||||
struct stp4020_softc *sc = (void *)self;
|
||||
bus_space_tag_t tag;
|
||||
int rev;
|
||||
int i, sbus_intno;
|
||||
int rev, i, sbus_intno, hw_ipl;
|
||||
bus_space_handle_t bh;
|
||||
|
||||
/* lsb of our config flags decides which interrupt we use */
|
||||
sbus_intno = device_cfdata(&sc->sc_dev)->cf_flags & 1;
|
||||
|
||||
/* Transfer bus tags */
|
||||
#ifdef SUN4U
|
||||
tag = sa->sa_bustag;
|
||||
|
@ -390,6 +395,46 @@ stp4020attach(parent, self, aux)
|
|||
tag->sparc_write_8 = stp4020_write_8;
|
||||
#endif /* SUN4U */
|
||||
|
||||
/* check interrupt options, decide if we need a softint */
|
||||
#ifdef SUN4U
|
||||
/*
|
||||
* On sparc64 the hardware interrupt priority does not restrict
|
||||
* the IPL we run our interrupt handler on, so we can always just
|
||||
* use the first interrupt and reqest the handler to run at
|
||||
* IPL_VM.
|
||||
*/
|
||||
sbus_intno = 0;
|
||||
hw_ipl = IPL_VM;
|
||||
#else
|
||||
/*
|
||||
* We need to check if one of the available interrupts has
|
||||
* a priority that allows us to establish a handler at IPL_VM.
|
||||
* If not (hard to imagine), use a soft interrupt.
|
||||
*/
|
||||
sbus_intno = -1;
|
||||
for (i = 0; i < sa->sa_nintr; i++) {
|
||||
struct sbus_softc *bus =
|
||||
(struct sbus_softc *) sa->sa_bustag->cookie;
|
||||
int ipl = bus->sc_intr2ipl[sa->sa_intr[i].oi_pri];
|
||||
if (ipl <= IPL_VM) {
|
||||
sbus_intno = i;
|
||||
sc->sc_use_softint = false;
|
||||
hw_ipl = IPL_VM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sbus_intno == -1) {
|
||||
/*
|
||||
* We have not found a usable hardware interrupt - so
|
||||
* use a softint to bounce to the proper IPL.
|
||||
*/
|
||||
printf("no usable HW interrupt found, using softint\n");
|
||||
sbus_intno = 0;
|
||||
sc->sc_use_softint = true;
|
||||
hw_ipl = IPL_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set up per-socket static initialization */
|
||||
sc->sc_socks[0].sc = sc->sc_socks[1].sc = sc;
|
||||
sc->sc_socks[0].tag = sc->sc_socks[1].tag = sa->sa_bustag;
|
||||
|
@ -460,7 +505,7 @@ stp4020attach(parent, self, aux)
|
|||
if (sa->sa_nintr > sbus_intno) {
|
||||
bus_intr_establish(sa->sa_bustag,
|
||||
sa->sa_intr[sbus_intno].oi_pri,
|
||||
IPL_NONE, stp4020_intr, sc);
|
||||
hw_ipl, stp4020_intr, sc);
|
||||
}
|
||||
|
||||
rev = stp4020_rd_sockctl(&sc->sc_socks[0], STP4020_ISR1_IDX) &
|
||||
|
@ -503,9 +548,11 @@ stp4020_attach_socket(h, speed)
|
|||
/* no interrupt handlers yet */
|
||||
h->intrhandler = NULL;
|
||||
h->intrarg = NULL;
|
||||
#ifndef SUN4U
|
||||
h->softint = NULL;
|
||||
h->int_enable = 0;
|
||||
h->int_disable = 0;
|
||||
#endif
|
||||
|
||||
/* Map all three windows */
|
||||
stp4020_map_window(h, STP_WIN_ATTR, speed);
|
||||
|
@ -623,6 +670,7 @@ stp4020_queue_event(sc, sock, event)
|
|||
wakeup(&sc->events);
|
||||
}
|
||||
|
||||
#ifndef SUN4U
|
||||
/*
|
||||
* Softinterrupt called to invoke the real driver interrupt handler.
|
||||
*/
|
||||
|
@ -641,17 +689,23 @@ stp4020_intr_dispatch(arg)
|
|||
stp4020_wr_sockctl(h, STP4020_ICR0_IDX, h->int_enable);
|
||||
splx(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
stp4020_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct stp4020_softc *sc = arg;
|
||||
int i, s, r = 0, cd_change = 0;
|
||||
#ifndef SUN4U
|
||||
int s;
|
||||
#endif
|
||||
int i, r = 0, cd_change = 0;
|
||||
|
||||
|
||||
#ifndef SUN4U
|
||||
/* protect hardware access by splhigh against softint */
|
||||
s = splhigh();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check each socket for pending requests.
|
||||
|
@ -710,17 +764,21 @@ stp4020_intr(arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
#ifndef SUN4U
|
||||
/*
|
||||
* Schedule softint to invoke driver interrupt
|
||||
* handler
|
||||
*/
|
||||
if (h->softint != NULL)
|
||||
softint_schedule(h->softint);
|
||||
sparc_softintr_schedule(h->softint);
|
||||
/*
|
||||
* Disable this sbus interrupt, until the soft-int
|
||||
* handler had a chance to run
|
||||
*/
|
||||
stp4020_wr_sockctl(h, STP4020_ICR0_IDX, h->int_disable);
|
||||
#else
|
||||
(*h->intrhandler)(h->intrarg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* informational messages */
|
||||
|
@ -762,7 +820,9 @@ stp4020_intr(arg)
|
|||
printf("stp4020[%d]: unhandled interrupt: 0x%x\n", h->sock, v);
|
||||
|
||||
}
|
||||
#ifndef SUN4U
|
||||
splx(s);
|
||||
#endif
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -1022,12 +1082,16 @@ stp4020_chip_socket_settype(pch, type)
|
|||
|STP4020_ICR0_SPKREN;
|
||||
v |= h->sbus_intno ? STP4020_ICR0_IOILVL_SB1
|
||||
: STP4020_ICR0_IOILVL_SB0;
|
||||
#ifndef SUN4U
|
||||
h->int_enable = v;
|
||||
h->int_disable = v & ~STP4020_ICR0_IOIE;
|
||||
#endif
|
||||
DPRINTF(("%s: configuring card for IO useage\n", h->sc->sc_dev.dv_xname));
|
||||
} else {
|
||||
v |= STP4020_ICR0_IFTYPE_MEM;
|
||||
#ifndef SUN4U
|
||||
h->int_enable = h->int_disable = v;
|
||||
#endif
|
||||
DPRINTF(("%s: configuring card for IO useage\n", h->sc->sc_dev.dv_xname));
|
||||
DPRINTF(("%s: configuring card for MEM ONLY useage\n", h->sc->sc_dev.dv_xname));
|
||||
}
|
||||
|
@ -1073,8 +1137,13 @@ stp4020_chip_intr_establish(pch, pf, ipl, handler, arg)
|
|||
|
||||
h->intrhandler = handler;
|
||||
h->intrarg = arg;
|
||||
h->softint = softint_establish(ipl, stp4020_intr_dispatch, h);
|
||||
return h->softint;
|
||||
#ifndef SUN4U
|
||||
if (h->sc->sc_use_softint) {
|
||||
h->softint = sparc_softintr_establish(ipl, stp4020_intr_dispatch, h);
|
||||
return h->softint;
|
||||
}
|
||||
#endif
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1086,10 +1155,12 @@ stp4020_chip_intr_disestablish(pch, ih)
|
|||
|
||||
h->intrhandler = NULL;
|
||||
h->intrarg = NULL;
|
||||
#ifndef SUN4U
|
||||
if (h->softint) {
|
||||
softint_disestablish(h->softint);
|
||||
sparc_softintr_disestablish(h->softint);
|
||||
h->softint = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue