📄 pdma3min.c
字号:
The SZ_DID_DMA flag in the softc structure will be set. This informs the driver that data xfers are taking place. NOTE: An opcode argument is passed to this routine mostly for the NCR 53c94. Return: PDMA_SUCCESS all is ready and ok PDMA_FAIL a fatal(?) problem has occured */int pmaz_ba_start( sc, targid, opcode )struct sz_softc *sc; /* pointer to the softc structure */int targid; /* current target ID */int opcode; /* value to start the dma oper in the chip */ { PDMA *pd; /* pointer for the DMA control struct */ ASC_REG *ascaddr; /* pointer for the SCSI chip registers */ DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ DTENT *datp, *datep; /* pointer to DAT table and individual entry */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_start: entry sc=0x%x targ=%d op=0x%x, ",sc, targid, opcode ));#endif /* Initialize local variables. */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */#ifdef PDMADEBUG PRINTD( targid, DETAILDAT, (" dat_index=%d\n", pd->dat_index ));#endif ascaddr = (ASCREG *)sc->sc_scsiaddr; /* get the chip addr */ ioasicp = (DMA_AR *)sc->ioasicp; /* engine address */ pd->opcode = opcode; /* save for later use */ /* Load the information from the dma control structure for buffer 0 into the SCSI chip and DMA engine. */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]);#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) dumpent( datep );#endif if ( datep->length==0 ) /* handle special case of padded xfer */ { ASC_LOADCNTR(ascaddr, sc->sc_siidmacount[targid]); /* load counter */ wbflush(); /* clear write buffer */ sc->sc_asccmd = ASC_DMA | ASC_XPAD ; ascaddr->asc_cmd = sc->sc_asccmd; sc->sc_szflags[ targid ] |= SZ_DID_DMA; wbflush(); /* clear write buffer */ return PDMA_SUCCESS; } if ( datep->addr == 0 ) { printf( "start: Invalid DAT entry.\n" ); dumpent( datep ); } if ( is_local_xfer( pd ) && datep->dir == IOASIC_WRITE ) { pd->pstate = PDMA_ACTIVE; sc->sc_szflags[ targid ] |= SZ_DID_DMA | SZ_PIO_INTR; asc_FIFOsenddata (sc, ASC_XINFO, datep->uadr, datep->length ); } else { setscsictrl( sc, 0 ); if ( dmapload( sc, targid, datep->iadr ) == PDMA_FAIL ) { printf( "pdma_start: Failure return from dmapload\n" ); return PDMA_FAIL; } ssrdmaon( sc, datep->dir ); #ifdef PDMADEBUG PRINTD( targid, REGLOAD, (" start: loading ASC counter (base 0x%x) with length (%d)\n", ascaddr, datep->length ));#endif ASC_LOADCNTR(ascaddr, datep->length); wbflush(); sc->sc_asccmd = pd->opcode; ascaddr->asc_cmd = pd->opcode; wbflush(); /* clear write buffer */ } /* Set the pstate to inform the driver that DMA is in progress. */ pd->pstate = PDMA_ACTIVE; sc->sc_szflags[ targid ] |= SZ_DID_DMA;#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pdma_start: exit\n"));#endif return PDMA_SUCCESS; }/* ---------------------------------------------------------------------- *//*int pdma_cont( sc, targid )Inputs: sz_softc *sc; pointer to the softc structure int targid; current target ID Function: Handle intermediate DMA functions during the transfer. Return: The number of bytes transfered sofar for this DMA operation.*/int pmaz_ba_cont( sc, targid )struct sz_softc *sc; /* pointer to the softc structure */int targid; /* current target ID */ { PDMA *pd; /* pointer for the DMA control struct */ ASC_REG *ascaddr; /* pointer for the SCSI chip registers */ DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ DTENT *datp, *datep; /* pointer to DAT table and individual entry */ char *newbufp; /* buffer pointer for use in DAT table adj. */ int ecount; /* used in DAT table rebuilding */ int tidx; /* temporary index variable in DAT rebuild */ int ffr; /* value for the FIFO flags */ int dbcount; /* number of bytes in IOASIC data buffer */ int tcount; /* corrected count for the ASC counters */ int lcount; /* local count from the transfers */ int tmp1; pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_cont: entry sc:%x targ:%d\n", sc, targid)); PRINTD( targid, ENTRYEXIT, (" dat_index:%d\n", pd->dat_index ));#endif ascaddr = (ASCREG *)sc->sc_scsiaddr;/* get the chip addr */ ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ /* First pull out the DAT table entry corresponding to this xfer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]);#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) dumpent( datep );#endif if ( !(datep->length) ) /* handle special case of padded xfer */ { sc->sc_szflags[ targid ] |= SZ_DID_DMA; PRINTD( targid, PADTRACK, (" cont: padded xfer return: %d bytes\n", pd->targcnt + sc->sc_siidmacount[targid] )); return pd->targcnt + sc->sc_siidmacount[targid]; } /* From the active buffers count and the SCSI chips actual xfer counter register value, calc how much data was transfered. Update the working counter(s) for the return xfer count. So far the SCSI chip counters are all down counters, making the xfer count calc a simple subtaction. The counters in the ASC have to be corrected for the # of bytes left in the FIFO but not transferred when the target changed phase. It should be noted that the 3min system (or possibly the softc struct) exhibits a situation which should not occur; the TC bit in the status register is set but the dma xfer counter is non-zero. */ ssrdmaoff( sc ); /* turn off DMA */ ffr = (int)ascaddr->asc_ffss; /* get the fifo flags count */ ffr &= ASC_FIFO_MSK; /* mask off sequ step bits */ ASC_GETCNTR(ascaddr, tcount); /* get the counter value */ ASC_LOADCNTR(ascaddr, 0); /* JAG - force TC bit off */ wbflush(); dbcount = getdbcount( sc, datep->dir ); /* bytes stuck in IOASIC? */ if ( datep->dir==IOASIC_WRITE ) /* for RDAT bug */ lcount = datep->length - ffr; else lcount = datep->length; if ( (lcount & 1) && dbcount ) /* if odd, then dbcount is off by 1 */ dbcount--; /* RPS 03/28/91 */ if ( is_local_xfer( pd ) ) newbufp = datep->uadr + lcount; else newbufp = datep->addr + lcount; if( pd->iodir == SZ_DMA_READ ) { if ( dbcount ) /* data was left in the IOASIC */ flushdb( sc, dbcount );#ifdef PDMADEBUG if ( scsidebug & DUMPHEX && targid == targmatch ) { if ( lcount > 0x40 ) { dumphex(datep->addr, 0x20 ); dumphex(datep->addr+lcount-0x20, 0x20 ); } else dumphex( datep->addr, lcount ); }#endif /* If the operation is a DMA_IN: check for fragment buffer usage, clean out that data if necessary, then determine if new DAT table entries must be built or modified before continuing */ if ( is_local_xfer( pd )) /* a local buffer was in addr? */ { flush_fragbuf( pd, lcount ); } else /* completed normally */ { if ( IS_KUSEG( datep->addr ) ) panic("pdmacont(2): KUSEG address passwd in!\n" ); else clean_dcache( PHYS_TO_K0( svtophy( datep->addr ) ), datep->length ); datep->completed = 1; /* tag the entry complete */ pd->targcnt += datep->length; /* bump transfer counter */ pd->dat_index++; } /* Load up the IOASIC chip with the address and '94 with the count for the next buffer. */ datep = (DTENT *)&(datp[pd->dat_index]);#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) { PRINTD( targid, DETAILDAT, (" cont: dat index=%d\n", pd->dat_index )); dumpent( datep ); }#endif if ( datep->length != 0 ) { setscsictrl( sc, 0 ); if ( dmapload( sc, targid, datep->iadr ) == PDMA_FAIL ) { printf( "pdma_start: Failure return from dmapload\n" ); return PDMA_FAIL; } ssrdmaon( sc, datep->dir );#ifdef PDMADEBUG PRINTD( targid, REGLOAD, (" cont: loading ASC counter (base 0x%x) with length (%d)\n", ascaddr, datep->length ));#endif ASC_LOADCNTR(ascaddr, datep->length); /* load counter */ wbflush(); /* Start the DMA operation in the ASC. */ sc->sc_asccmd = pd->opcode; ascaddr->asc_cmd = pd->opcode; wbflush(); /* clear write buffer */ /* Set the flag to inform the driver that DMA is in progress. */ sc->sc_szflags[ targid ] |= SZ_DID_DMA; } /* end of (datep->length != 0 ) */ else { /* time to pad out an xfer */ ASC_LOADCNTR(ascaddr, sc->sc_siidmacount[targid]); /* load counter */ wbflush(); /* clear write buffer */ sc->sc_asccmd = ASC_DMA | ASC_XPAD ; ascaddr->asc_cmd = sc->sc_asccmd; sc->sc_szflags[ targid ] |= SZ_DID_DMA; wbflush(); /* clear write buffer */ } } /* end of (pd->iodir == SZ_DMA_READ) */ else { /* Write case now */ datep->completed = 1; /* tag the entry complete */ pd->targcnt += datep->length; /* bump transfer counter */ pd->dat_index++; datep = (DTENT *)&(datp[pd->dat_index]); if ( is_local_xfer( pd ) ) /* is this a fragment? */ { if ( frag_buf_load( pd ) == PDMA_FAIL ) { printf( "pmaz_ba_cont(3min)(12): (WRITE(2)) frag buffer load, dat_addr=0x%x index= %d\n", pd->dat_addr, pd->dat_index ); return( PDMA_FAIL ); } }#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) { PRINTD( targid, DETAILDAT, (" cont: dat index=%d\n", pd->dat_index )); dumpent( datep ); }#endif if ( is_local_xfer( pd ) && datep->dir == IOASIC_WRITE ) { sc->sc_szflags[ targid ] |= SZ_DID_DMA | SZ_PIO_INTR; asc_FIFOsenddata (sc, ASC_XINFO, datep->uadr, datep->length ); } else { if ( datep->length != 0 ) { /* Load addr reg, set the write direction bit. */ setscsictrl( sc, 0 ); if ( dmapload( sc, targid, datep->iadr ) == PDMA_FAIL ) { printf( "pdma_start: Failure return from dmapload\n" ); return PDMA_FAIL; } ssrdmaon( sc, datep->dir );#ifdef PDMADEBUG PRINTD( targid, REGLOAD, (" cont: loading ASC counter (base 0x%x) with length (%d)\n", ascaddr, datep->length ));#endif ASC_LOADCNTR(ascaddr, datep->length); /* load counter */ wbflush(); /* Start the DMA operation in the ASC. */ sc->sc_asccmd = pd->opcode; ascaddr->asc_cmd = pd->opcode; wbflush(); /* clear write buffer */ /* Set the flag to inform the driver that DMA is in progress. */ sc->sc_szflags[ targid ] |= SZ_DID_DMA; } /* end of if ( datep->length != 0 ) */ else { /* time to pad out an xfer */ ASC_LOADCNTR(ascaddr, sc->sc_siidmacount[targid]); /* load counter */ wbflush(); /* clear write buffer */ sc->sc_asccmd = ASC_DMA | ASC_XPAD ; ascaddr->asc_cmd = sc->sc_asccmd; sc->sc_szflags[ targid ] |= SZ_DID_DMA; wbflush(); /* clear write buffer */ } } } /* end of else on (pd->iodir == SZ_DMA_READ) */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_cont: exit\n" ));#endif return pd->targcnt; /* return current progress */ }/* ---------------------------------------------------------------------- *//*int pdma_end( sc, targid )Inputs: sz_softc *sc; pointer to the softc structure int targid; current target ID Function: Handle the completion of the DMA operation. Free up the necessary DMA resources that were allocated in dma_setup(). Handle the final move of the data to user space if the operation was a read.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -