Esempio n. 1
0
int
osiop_mvme68k_intr(void *arg)
{
	struct osiop_softc *sc = arg;
	u_int8_t istat;

	if (sc->sc_flags & OSIOP_INTSOFF)
		return 0;

	istat = osiop_read_1(sc, OSIOP_ISTAT);
	if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0)
		return 0;

	/*
	 * 53c710 manual recommends reading dstat and sstat0 at least
	 * 12 clk cycles apart if reading as bytes (which is what
	 * pcc2 permits). Stick in a 1us delay between accessing dstat and
	 * sstat0 below.
	 *
	 * save interrupt status, DMA status, and SCSI status 0
	 * (may need to deal with stacked interrupts?)
	 */
	sc->sc_istat = istat;
	sc->sc_sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
	DELAY(25);
	sc->sc_dstat = osiop_read_1(sc, OSIOP_DSTAT);

	osiop_intr(sc);

	return 1;
}
static int
osiop_pcctwo_intr(void *arg)
{
	struct osiop_pcctwo_softc *sc = arg;
	u_char istat;

	/*
	 * Catch any errors which can happen when the SIOP is
	 * local bus master...
	 */
	istat = pcc2_reg_read(sys_pcctwo, PCC2REG_SCSI_ERR_STATUS);
	if ((istat & PCCTWO_ERR_SR_MASK) != 0) {
		printf("%s: Local bus error: 0x%02x\n",
		    device_xname(sc->sc_osiop.sc_dev), istat);
		istat |= PCCTWO_ERR_SR_SCLR;
		pcc2_reg_write(sys_pcctwo, PCC2REG_SCSI_ERR_STATUS, istat);
	}

	/* This is potentially nasty, since the IRQ is level triggered... */
	if (sc->sc_osiop.sc_flags & OSIOP_INTSOFF)
		return (0);

	istat = osiop_read_1(&sc->sc_osiop, OSIOP_ISTAT);

	if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0)
		return (0);

	/* Save interrupt details for the back-end interrupt handler */
	sc->sc_osiop.sc_sstat0 = osiop_read_1(&sc->sc_osiop, OSIOP_SSTAT0);
	sc->sc_osiop.sc_istat = istat;
	sc->sc_osiop.sc_dstat = osiop_read_1(&sc->sc_osiop, OSIOP_DSTAT);

	/* Deal with the interrupt */
	osiop_intr(&sc->sc_osiop);

	return (1);
}