- 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:
mrg 1999-11-25 05:03:53 +00:00
parent 36e75e7449
commit ca66e6b619
1 changed files with 44 additions and 54 deletions

View File

@ -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;