예제 #1
0
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);
}
예제 #2
0
파일: sbus.c 프로젝트: MarginC/kame
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);
}