static int sbus_find_intrmap(struct sbus_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr) { bus_addr_t intrclr, intrmap; int i; if (ino > SBUS_MAX_INO) { device_printf(sc->sc_dev, "out of range INO %d requested\n", ino); return (0); } if ((ino & INTMAP_OBIO_MASK) == 0) { intrmap = SBR_SLOT0_INT_MAP + INTSLOT(ino) * 8; intrclr = SBR_SLOT0_INT_CLR + (INTSLOT(ino) * 8 * 8) + (INTPRI(ino) * 8); } else { intrclr = 0; for (i = 0, intrmap = SBR_SCSI_INT_MAP; intrmap <= SBR_RESERVED_INT_MAP; intrmap += 8, i++) { if (INTVEC(SYSIO_READ8(sc, intrmap)) == INTMAP_VEC(sc->sc_ign, ino)) { intrclr = SBR_SCSI_INT_CLR + i * 8; break; } } if (intrclr == 0) return (0); } if (intrmapptr != NULL) *intrmapptr = intrmap; if (intrclrptr != NULL) *intrclrptr = intrclr; return (1); }
static int sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_intr_t *intr, void *arg, void **cookiep) { struct sbus_softc *sc; struct sbus_clr *scl; bus_addr_t intrmapptr, intrclrptr, intrptr; u_int64_t intrmap; u_int32_t inr, slot; int error, i; long vec = rman_get_start(ires); sc = (struct sbus_softc *)device_get_softc(dev); scl = (struct sbus_clr *)malloc(sizeof(*scl), M_DEVBUF, M_NOWAIT); if (scl == NULL) return (NULL); intrptr = intrmapptr = intrclrptr = 0; intrmap = 0; inr = INTVEC(vec); if ((inr & INTMAP_OBIO_MASK) == 0) { /* * We're in an SBUS slot, register the map and clear * intr registers. */ slot = INTSLOT(vec); intrmapptr = SBR_SLOT0_INT_MAP + slot * 8; intrclrptr = SBR_SLOT0_INT_CLR + (slot * 8 * 8) + (INTPRI(vec) * 8); /* Enable the interrupt, insert IGN. */ intrmap = inr | sc->sc_ign; } else { intrptr = SBR_SCSI_INT_MAP; /* Insert IGN */ inr |= sc->sc_ign; for (i = 0; intrptr <= SBR_RESERVED_INT_MAP && INTVEC(intrmap = SYSIO_READ8(sc, intrptr)) != INTVEC(inr); intrptr += 8, i++) ; if (INTVEC(intrmap) == INTVEC(inr)) { /* Register the map and clear intr registers */ intrmapptr = intrptr; intrclrptr = SBR_SCSI_INT_CLR + i * 8; /* Enable the interrupt */ } else panic("sbus_setup_intr: IRQ not found!"); } scl->scl_sc = sc; scl->scl_arg = arg; scl->scl_handler = intr; scl->scl_clr = intrclrptr; /* Disable the interrupt while we fiddle with it */ SYSIO_WRITE8(sc, intrmapptr, intrmap); error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, sbus_intr_stub, scl, cookiep); if (error != 0) { free(scl, M_DEVBUF); return (error); } scl->scl_cookie = *cookiep; *cookiep = scl; /* * Clear the interrupt, it might have been triggered before it was * set up. */ SYSIO_WRITE8(sc, intrclrptr, 0); /* * Enable the interrupt and program the target module now we have the * handler installed. */ SYSIO_WRITE8(sc, intrmapptr, INTMAP_ENABLE(intrmap, PCPU_GET(mid))); return (error); }