- pass slot number to sbus_get_intr() as a new argument.
- in sbus_get_intr(), if we are not an onboard device (ie, sbus card), encode the slot number into the sbi_pri so that we can later extract it and use it to find the interrupt map & clear registers for this device. - remove "intr" support as it is really pre-sun4u only. - don't "pause" for so long in sbus interrupt debug messages.. with the slot number being passed back from sbus_get_intr(), the FS/BE card in an ultra2 now appears to get interrupts and gets beyond waiting for the scsibus probe!
This commit is contained in:
parent
36e75e7449
commit
ca66e6b619
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: sbus.c,v 1.21 1999/11/13 00:32:16 thorpej Exp $ */
|
/* $NetBSD: sbus.c,v 1.22 1999/11/25 05:03:53 mrg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -139,7 +139,7 @@ void sbusreset __P((int));
|
||||||
static bus_space_tag_t sbus_alloc_bustag __P((struct sbus_softc *));
|
static bus_space_tag_t sbus_alloc_bustag __P((struct sbus_softc *));
|
||||||
static bus_dma_tag_t sbus_alloc_dmatag __P((struct sbus_softc *));
|
static bus_dma_tag_t sbus_alloc_dmatag __P((struct sbus_softc *));
|
||||||
static int sbus_get_intr __P((struct sbus_softc *, int,
|
static int sbus_get_intr __P((struct sbus_softc *, int,
|
||||||
struct sbus_intr **, int *));
|
struct sbus_intr **, int *, int));
|
||||||
static int sbus_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t,
|
static int sbus_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t,
|
||||||
int, bus_space_handle_t *));
|
int, bus_space_handle_t *));
|
||||||
static int _sbus_bus_map __P((
|
static int _sbus_bus_map __P((
|
||||||
|
@ -233,7 +233,7 @@ sbus_print(args, busname)
|
||||||
printf("%s at %s", sa->sa_name, busname);
|
printf("%s at %s", sa->sa_name, busname);
|
||||||
printf(" slot %ld offset 0x%lx", (long)sa->sa_slot,
|
printf(" slot %ld offset 0x%lx", (long)sa->sa_slot,
|
||||||
(u_long)sa->sa_offset);
|
(u_long)sa->sa_offset);
|
||||||
for (i=0; i<sa->sa_nintr; i++) {
|
for (i = 0; i < sa->sa_nintr; i++) {
|
||||||
struct sbus_intr *sbi = &sa->sa_intr[i];
|
struct sbus_intr *sbi = &sa->sa_intr[i];
|
||||||
|
|
||||||
printf(" vector %lx ipl %ld",
|
printf(" vector %lx ipl %ld",
|
||||||
|
@ -387,7 +387,8 @@ sbus_setup_attach_args(sc, bustag, dmatag, node, bp, sa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sbus_get_intr(sc, node, &sa->sa_intr, &sa->sa_nintr)) != 0)
|
if ((error = sbus_get_intr(sc, node, &sa->sa_intr, &sa->sa_nintr,
|
||||||
|
sa->sa_slot)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
error = getprop(node, "address", sizeof(u_int32_t),
|
error = getprop(node, "address", sizeof(u_int32_t),
|
||||||
|
@ -544,14 +545,15 @@ sbusreset(sbus)
|
||||||
* Get interrupt attributes for an Sbus device.
|
* Get interrupt attributes for an Sbus device.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
sbus_get_intr(sc, node, ipp, np)
|
sbus_get_intr(sc, node, ipp, np, slot)
|
||||||
struct sbus_softc *sc;
|
struct sbus_softc *sc;
|
||||||
int node;
|
int node;
|
||||||
struct sbus_intr **ipp;
|
struct sbus_intr **ipp;
|
||||||
int *np;
|
int *np;
|
||||||
|
int slot;
|
||||||
{
|
{
|
||||||
int *ipl;
|
int *ipl;
|
||||||
int i, n, error;
|
int n, i;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -559,28 +561,40 @@ sbus_get_intr(sc, node, ipp, np)
|
||||||
*/
|
*/
|
||||||
ipl = NULL;
|
ipl = NULL;
|
||||||
if (getprop(node, "interrupts", sizeof(int), np, (void **)&ipl) == 0) {
|
if (getprop(node, "interrupts", sizeof(int), np, (void **)&ipl) == 0) {
|
||||||
/* Change format to an `struct sbus_intr' array */
|
|
||||||
struct sbus_intr *ip;
|
struct sbus_intr *ip;
|
||||||
|
int pri;
|
||||||
|
|
||||||
/* Default to interrupt level 2 -- otherwise unused */
|
/* Default to interrupt level 2 -- otherwise unused */
|
||||||
int pri = INTLEVENCODE(2);
|
pri = INTLEVENCODE(2);
|
||||||
|
|
||||||
|
/* Change format to an `struct sbus_intr' array */
|
||||||
ip = malloc(*np * sizeof(struct sbus_intr), M_DEVBUF, M_NOWAIT);
|
ip = malloc(*np * sizeof(struct sbus_intr), M_DEVBUF, M_NOWAIT);
|
||||||
if (ip == NULL)
|
if (ip == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
/* Now things get ugly. We need to take this value which is
|
|
||||||
|
/*
|
||||||
|
* Now things get ugly. We need to take this value which is
|
||||||
* the interrupt vector number and encode the IPL into it
|
* the interrupt vector number and encode the IPL into it
|
||||||
* somehow. Luckily, the interrupt vector has lots of free
|
* somehow. Luckily, the interrupt vector has lots of free
|
||||||
* space and we can easily stuff the IPL in there for a while.
|
* space and we can easily stuff the IPL in there for a while.
|
||||||
*/
|
*/
|
||||||
getpropstringA(node, "device_type", buf);
|
getpropstringA(node, "device_type", buf);
|
||||||
if (!buf[0]) {
|
if (!buf[0])
|
||||||
getpropstringA(node, "name", buf);
|
getpropstringA(node, "name", buf);
|
||||||
}
|
|
||||||
for (i=0; intrmap[i].in_class; i++) {
|
for (i = 0; intrmap[i].in_class; i++)
|
||||||
if (strcmp(intrmap[i].in_class, buf) == 0) {
|
if (strcmp(intrmap[i].in_class, buf) == 0) {
|
||||||
pri = INTLEVENCODE(intrmap[i].in_lev);
|
pri = INTLEVENCODE(intrmap[i].in_lev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
* Sbus card devices need the slot number encoded into
|
||||||
|
* the vector as this is generally not done.
|
||||||
|
*/
|
||||||
|
if ((ipl[0] & INTMAP_OBIO) == 0)
|
||||||
|
pri |= slot << 3;
|
||||||
|
|
||||||
for (n = 0; n < *np; n++) {
|
for (n = 0; n < *np; n++) {
|
||||||
/*
|
/*
|
||||||
* We encode vector and priority into sbi_pri so we
|
* We encode vector and priority into sbi_pri so we
|
||||||
|
@ -589,41 +603,15 @@ sbus_get_intr(sc, node, ipp, np)
|
||||||
* of an integer level.
|
* of an integer level.
|
||||||
* Stuff the real vector in sbi_vec.
|
* Stuff the real vector in sbi_vec.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ip[n].sbi_pri = pri|ipl[n];
|
ip[n].sbi_pri = pri|ipl[n];
|
||||||
ip[n].sbi_vec = ipl[n];
|
ip[n].sbi_vec = ipl[n];
|
||||||
}
|
}
|
||||||
free(ipl, M_DEVBUF);
|
free(ipl, M_DEVBUF);
|
||||||
*ipp = ip;
|
*ipp = ip;
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We really don't support the following */
|
return (0);
|
||||||
/* printf("\nWARNING: sbus_get_intr() \"interrupts\" not found -- using \"intr\"\n"); */
|
|
||||||
/* And some devices don't even have interrupts */
|
|
||||||
/*
|
|
||||||
* Fall back on `intr' property.
|
|
||||||
*/
|
|
||||||
*ipp = NULL;
|
|
||||||
error = getprop(node, "intr", sizeof(struct sbus_intr),
|
|
||||||
np, (void **)ipp);
|
|
||||||
switch (error) {
|
|
||||||
case 0:
|
|
||||||
for (n = *np; n-- > 0;) {
|
|
||||||
/*
|
|
||||||
* Move the interrupt vector into place.
|
|
||||||
* We could remap the level, but the SBUS priorities
|
|
||||||
* are probably good enough.
|
|
||||||
*/
|
|
||||||
(*ipp)[n].sbi_vec = (*ipp)[n].sbi_pri;
|
|
||||||
(*ipp)[n].sbi_pri |= INTLEVENCODE((*ipp)[n].sbi_pri);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ENOENT:
|
|
||||||
error = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -666,18 +654,20 @@ sbus_intr_establish(t, level, flags, handler, arg)
|
||||||
if ((vec & INTMAP_OBIO) == 0) {
|
if ((vec & INTMAP_OBIO) == 0) {
|
||||||
/* We're in an SBUS slot */
|
/* We're in an SBUS slot */
|
||||||
/* Register the map and clear intr registers */
|
/* Register the map and clear intr registers */
|
||||||
|
|
||||||
|
int slot = INTSLOT(level);
|
||||||
|
|
||||||
|
ih->ih_map = &(&sc->sc_sysio->sbus_slot0_int)[slot];
|
||||||
|
ih->ih_clr = &sc->sc_sysio->sbus0_clr_int[vec];
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sbusdebug & SDB_INTR) {
|
if (sbusdebug & SDB_INTR) {
|
||||||
int64_t *intrptr = &(&sc->sc_sysio->sbus_slot0_int)[INTSLOT(vec)];
|
int64_t intrmap = *ih->ih_map;
|
||||||
int64_t intrmap = *intrptr;
|
|
||||||
|
|
||||||
printf("Found SBUS %lx IRQ as %llx in slot %ld\n",
|
printf("Found SBUS %lx IRQ as %llx in slot %d\n",
|
||||||
(long)vec, (long)intrmap,
|
(long)vec, (long long)intrmap, slot);
|
||||||
(long)INTSLOT(vec));
|
printf("\tmap addr %p clr addr %p\n", ih->ih_map, ih->ih_clr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ih->ih_map = &(&sc->sc_sysio->sbus_slot0_int)[INTSLOT(vec)];
|
|
||||||
ih->ih_clr = &sc->sc_sysio->sbus0_clr_int[INTVEC(vec)];
|
|
||||||
/* Enable the interrupt */
|
/* Enable the interrupt */
|
||||||
vec |= INTMAP_V;
|
vec |= INTMAP_V;
|
||||||
/* Insert IGN */
|
/* Insert IGN */
|
||||||
|
@ -690,10 +680,10 @@ sbus_intr_establish(t, level, flags, handler, arg)
|
||||||
|
|
||||||
/* Insert IGN */
|
/* Insert IGN */
|
||||||
vec |= sc->sc_ign;
|
vec |= sc->sc_ign;
|
||||||
for (i=0;
|
for (i = 0; &intrptr[i] <=
|
||||||
&intrptr[i] <= (int64_t *)&sc->sc_sysio->reserved_int_map &&
|
(int64_t *)&sc->sc_sysio->reserved_int_map &&
|
||||||
INTVEC(intrmap=intrptr[i]) != INTVEC(vec);
|
INTVEC(intrmap = intrptr[i]) != INTVEC(vec); i++)
|
||||||
i++);
|
;
|
||||||
if (INTVEC(intrmap) == INTVEC(vec)) {
|
if (INTVEC(intrmap) == INTVEC(vec)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sbusdebug & SDB_INTR)
|
if (sbusdebug & SDB_INTR)
|
||||||
|
@ -711,7 +701,7 @@ sbus_intr_establish(t, level, flags, handler, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sbusdebug & SDB_INTR) { long i; for (i=0; i<1400000000; i++); }
|
if (sbusdebug & SDB_INTR) { long i; for (i=0; i<400000000; i++); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ih->ih_fun = handler;
|
ih->ih_fun = handler;
|
||||||
|
|
Loading…
Reference in New Issue