FreeBSD/sys/sparc64/sbus/lsi64854.c
/*
 * Pseudo (chained) interrupt from the esp driver to kick the
 * current running DMA transfer.  Called from ncr53c9x_intr()
 * for now.
 *
 * return 1 if it was a DMA continue.
 */
Pseudo (chained) interrupt from the esp driver to kick the
current running DMA transfer.  Called from ncr53c9x_intr()
for now.

return 1 if it was a DMA continue.
Pseudo ( chained ) interrupt from the esp driver to kick the current running DMA transfer . Called from ncr53c9x_intr () for now . return 1 if it was a DMA continue .
static int
lsi64854_scsi_intr(void *arg)
{
	struct lsi64854_softc *sc = arg;
	struct ncr53c9x_softc *nsc = sc->sc_client;
	bus_dma_tag_t dmat;
	bus_dmamap_t dmam;
	size_t dmasize;
	int lxfer, resid, trans;
	uint32_t csr;
	csr = L64854_GCSR(sc);
	DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
	    bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS));
	if (csr & (D_ERR_PEND | D_SLAVE_ERR)) {
		device_printf(sc->sc_dev, "error: csr=%b\n", csr,
		    DDMACSR_BITS);
		csr &= ~D_EN_DMA;	
		csr |= D_INVALIDATE | D_SLAVE_ERR;
		L64854_SCSR(sc, csr);
		return (-1);
	}
	if (sc->sc_active == 0)
		panic("%s: DMA wasn't active", __func__);
	DMA_DRAIN(sc, 0);
	csr &= ~D_EN_DMA;
	L64854_SCSR(sc, csr);
	sc->sc_active = 0;
	dmasize = sc->sc_dmasize;
	if (dmasize == 0) {
		DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, "
		    "tcm=%d)\n", __func__, NCR_READ_REG(nsc, NCR_TCL) |
		    (NCR_READ_REG(nsc, NCR_TCM) << 8),
		    NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
		return (0);
	}
	resid = 0;
	if ((csr & D_WRITE) == 0 &&
	    (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
		DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
		    resid));
		if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
		    (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
			resid <<= 1;
	}
	if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
		lxfer = nsc->sc_features & NCR_F_LARGEXFER;
		resid += (NCR_READ_REG(nsc, NCR_TCL) |
		    (NCR_READ_REG(nsc, NCR_TCM) << 8) |
		    (lxfer != 0 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
		if (resid == 0 && dmasize == 65536 && lxfer == 0)
			resid = 65536;
	}
	trans = dmasize - resid;
	if (trans < 0) {			
#if 0
		device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
		    dmasize);
#endif
		trans = dmasize;
	}
	DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
	    __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
	    (nsc->sc_features & NCR_F_LARGEXFER) != 0 ?
	    NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid));
	if (dmasize != 0) {
		dmat = sc->sc_buffer_dmat;
		dmam = sc->sc_dmamap;
		bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
		bus_dmamap_unload(dmat, dmam);
	}
	*sc->sc_dmalen -= trans;
	*sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
#if 0	
	if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase)
		return (0);
	dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
	return (1);
#endif
	return (0);
}
static int lsi64854_scsi_intr ( void * arg ) { struct lsi64854_softc * sc = arg ; struct ncr53c9x_softc * nsc = sc -> sc_client ; bus_dma_tag_t dmat ; bus_dmamap_t dmam ; size_t dmasize ; int lxfer , resid , trans ; uint32_t csr ; csr = L64854_GCSR ( sc ) ; DPRINTF ( LDB_SCSI , ( " \n " , __func__ , bus_read_4 ( sc -> sc_res , L64854_REG_ADDR ) , csr , DDMACSR_BITS ) ) ; if ( csr & ( D_ERR_PEND | D_SLAVE_ERR ) ) { device_printf ( sc -> sc_dev , " \n " , csr , DDMACSR_BITS ) ; csr &= ~ D_EN_DMA ; csr |= D_INVALIDATE | D_SLAVE_ERR ; L64854_SCSR ( sc , csr ) ; return ( -1 ) ; } if ( sc -> sc_active == 0 ) panic ( " " , __func__ ) ; DMA_DRAIN ( sc , 0 ) ; csr &= ~ D_EN_DMA ; L64854_SCSR ( sc , csr ) ; sc -> sc_active = 0 ; dmasize = sc -> sc_dmasize ; if ( dmasize == 0 ) { DPRINTF ( LDB_SCSI , ( " " " \n " , __func__ , NCR_READ_REG ( nsc , NCR_TCL ) | ( NCR_READ_REG ( nsc , NCR_TCM ) << 8 ) , NCR_READ_REG ( nsc , NCR_TCL ) , NCR_READ_REG ( nsc , NCR_TCM ) ) ) ; return ( 0 ) ; } resid = 0 ; if ( ( csr & D_WRITE ) == 0 && ( resid = ( NCR_READ_REG ( nsc , NCR_FFLAG ) & NCRFIFO_FF ) ) != 0 ) { DPRINTF ( LDB_SCSI , ( " " , __func__ , resid ) ) ; if ( nsc -> sc_rev == NCR_VARIANT_FAS366 && ( NCR_READ_REG ( nsc , NCR_CFG3 ) & NCRFASCFG3_EWIDE ) ) resid <<= 1 ; } if ( ( nsc -> sc_espstat & NCRSTAT_TC ) == 0 ) { lxfer = nsc -> sc_features & NCR_F_LARGEXFER ; resid += ( NCR_READ_REG ( nsc , NCR_TCL ) | ( NCR_READ_REG ( nsc , NCR_TCM ) << 8 ) | ( lxfer != 0 ? ( NCR_READ_REG ( nsc , NCR_TCH ) << 16 ) : 0 ) ) ; if ( resid == 0 && dmasize == 65536 && lxfer == 0 ) resid = 65536 ; } trans = dmasize - resid ; if ( trans < 0 ) { #if 0 device_printf ( sc -> sc_dev , " \n " , trans , dmasize ) ; #endif trans = dmasize ; } DPRINTF ( LDB_SCSI , ( " \n " , __func__ , NCR_READ_REG ( nsc , NCR_TCL ) , NCR_READ_REG ( nsc , NCR_TCM ) , ( nsc -> sc_features & NCR_F_LARGEXFER ) != 0 ? NCR_READ_REG ( nsc , NCR_TCH ) : 0 , trans , resid ) ) ; if ( dmasize != 0 ) { dmat = sc -> sc_buffer_dmat ; dmam = sc -> sc_dmamap ; bus_dmamap_sync ( dmat , dmam , ( csr & D_WRITE ) != 0 ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE ) ; bus_dmamap_unload ( dmat , dmam ) ; } * sc -> sc_dmalen -= trans ; * sc -> sc_dmaaddr = ( char * ) * sc -> sc_dmaaddr + trans ; #if 0 if ( * sc -> sc_dmalen == 0 || nsc -> sc_phase != nsc -> sc_prevphase ) return ( 0 ) ; dma_start ( sc , sc -> sc_dmaaddr , sc -> sc_dmalen , DMACSR ( sc ) & D_WRITE ) ; return ( 1 ) ; #endif return ( 0 ) ; }
Pseudo (chained) interrupt from the esp driver to kick the
 current running DMA transfer.
Pseudo ( chained ) interrupt from the esp driver to kick the current running DMA transfer .
/* Stop DMA. */ /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ /* This is an "assertion" :) */ /* DMA has stopped */ /* A "Transfer Pad" operation completed. */ /*
	 * If a transfer onto the SCSI bus gets interrupted by the device
	 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
	 * as residual since the NCR53C9X counter registers get decremented
	 * as bytes are clocked into the FIFO.
	 */ /*
		 * "Terminal count" is off, so read the residue
		 * out of the NCR53C9X counter registers.
		 */ /* A transfer of 64k is encoded as TCL=TCM=0. */ /* transferred < 0? */ /*
		 * This situation can happen in perfectly normal operation
		 * if the ESP is reselected while using DMA to select
		 * another target.  As such, don't print the warning.
		 */ /* this is not normal operation just yet */ /* and again */