📄 pdma3min.c
字号:
Return: The number of bytes transfered over the entire DMA operation.*/int pmaz_ba_end( 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 */ DTENT *datp, *datep; /* pointer to DAT table and individual entry */ 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 i; /* buffer loop counter */ int tmp1; DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */ ioasicp = (DMAAR *)sc->ioasicp; /* engine address */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_end: entry sc=0x%x targ=%d\n", sc, targid)); PRINTD( targid, DETAILDAT, (" dat_index=%d\n", pd->dat_index ));#endif ascaddr = (ASCREG *)sc->sc_scsiaddr;/* get the chip addr */ /* 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. */ 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(); /* Pull out the DAT table entry corresponding to this xfer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]); dbcount = getdbcount( sc, datep->dir ); /* bytes stuck in IOASIC? */ datep->completed = 1; /* tag the entry complete */ if ( !datep->length ) /* take care of empty last DAT */ { sc->sc_szflags[ targid ] &= ~SZ_DID_DMA; /* DID_DMA is done */ sc->sc_szflags[ targid ] &= ~SZ_PIO_INTR; /* DID_DMA is done */ pd->pstate = PDMA_IDLE; /* all done */ return( pd->targcnt + sc->sc_siidmacount[targid] ); }#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) dumpent( datep );#endif if ( (sc->sc_asc_sr&ASC_TC) && (tcount != 0) ) /* shouldn't happen */ { if ( datep->dir == IOASIC_WRITE ) tcount = 0; } lcount = datep->length; /* Assume all transferred */ if ( sc->sc_asc_sr & ASC_TC ) /* terminal count is not set? */ tcount = 0; else lcount -= tcount; /* then subtract remainder */ if ( datep->dir == IOASIC_WRITE ) /* in the case of writes... */ lcount -= ffr; /* don't forget the fifo flags reg */ /* If the last operation was a SZ_DMA_READ, move the data to user space. */ if ( (lcount & 1) && dbcount ) /* if odd, then dbcount is off by 1 */ dbcount--; /* RPS 03/28/91 */ 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, 0x20 ); }#endif if ( is_local_xfer( pd )) /* a local buffer was in addr? */ { /* MOVE THE FRAGMENT BUFFER BYTES TO USER BUFFER HERE */ if( lcount != 0 ) /* don't bother if no data */ { /* Change this to a flush_frag_buf() */ flush_fragbuf( pd, lcount ); wbflush(); pd->targcnt += lcount; /* update target count */ } } else { clean_dcache( PHYS_TO_K0( svtophy( datep->addr ) ), datep->length ); pd->targcnt += datep->length - tcount; } } /* end of if read */ else { /* write case */ pd->targcnt += lcount; /* update target count */ } /* Clean up after ourselves. Clear the SZ_DID_DMA flag. */ sc->sc_szflags[ targid ] &= ~SZ_DID_DMA; /* DID_DMA is done */ sc->sc_szflags[ targid ] &= ~SZ_PIO_INTR; /* DID_DMA is done */ pd->pstate = PDMA_IDLE; /* all done */ /* Return the accumulated working count to the driver. No checking has been done to verify that all the data has been transfered. */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_end: exit\n"));#endif return( pd->targcnt ); }int pmaz_ba_flush( sc, targid )struct sz_softc *sc; /* pointer to the softc structure */int targid; /* current targit ID */ { PDMA *pd; /* pointer for the DMA control struct */ DTENT *datp, *datep; /* pointer to DAT table and individual entry */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_flush: enter, target= %d, dat_index=%d\n", targid, pd->dat_addr ));#endif /* Pull out the DAT table entry corresponding to this xfer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]); if ( datep->dir == IOASIC_READ ) { (*sc->dma_rbcopy) /* move the data */ ( datep->addr, datep->uadr, datep->length ); } return( PDMA_SUCCESS ); /* all done */ }/* ---------------------------------------------------------------------- *//* Support routines. *//* ---------------------------------------------------------------------- *//* Dumps the contents of the PDMA structure to the console. */intdump_pdma( pd ) PDMA *pd;{ int i; printf( "Dumping pd: 0x%x\n", pd ); printf( " pstate 0x%x ", pd->pstate ); printf( " pflags 0x%x ", pd->pflags ); printf( " iodir 0x%x\n", pd->iodir ); printf( " dat_addr : 0x%x\n", pd->dat_addr ); printf( " dat_index : 0x%x\n", pd->dat_index ); printf( " data_addr : 0x%x\n", pd->data_addr ); printf( " usercnt : 0x%x\n", pd->usercnt ); printf( " targcnt : 0x%x\n", pd->targcnt ); printf( " opcode : 0x%x\n", pd->opcode ); }int frag_buf_load( pd )PDMA *pd; { DTENT *datp, *datep; /* pointer to DAT table and individual entry */ char *sadr, *dadr; /* Pull out the DAT table entry corresponding to this xfer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]); bcopy( datep->uadr, datep->addr, datep->length ); return PDMA_SUCCESS; }flushfifo( sc )struct sz_softc *sc; { ASC_REG *ascaddr; ascaddr = (ASCREG *)sc->sc_scsiaddr; /* get the chip addr */ ascaddr->asc_cmd = ASC_FLUSH; wbflush(); /* clear write buffer */ } ioasicint( sc, targid, cntlr )struct sz_softc *sc;int targid;int cntlr; { unsigned **dmap; /* pointer to IOASIC DMA Ptr. reg. */ unsigned long *sir; unsigned long sirp, resetval; int retval; ASC_REG *ascaddr = ASC_REG_ADDR; DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ caddr_t pa; struct tc_memerr_status status; ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ sir = (unsigned long *) ( (unsigned) ioasicp + SIR_O ); resetval = 0xffffffff; sirp = *sir; retval = 1; if ( sirp & SCSI_DBPL ) /* has the DMA buffer pointer */ { /* been loaded? */ resetval &= ~SCSI_DBPL; } if ( sirp & SCSI_OERR ) /* has an overrun error occurred? */ { resetval &= ~SCSI_OERR; } if ( sirp & SCSI_MERR ) /* memory read error? */ { dmap = (unsigned **) ( ( (unsigned) ioasicp ) + IOA_S_DMAP_O ); pa = (char *) backcvt( (void *)*dmap ); /* Calc. the user buf address */ printf("scsi%d: dma memory read error \n", cntlr); status.pa = pa; status.va = 0; status.log = TC_LOG_MEMERR; status.blocksize = 4; tc_isolate_memerr(&status); resetval &= ~SCSI_MERR; }#ifdef NOTNEEDED if ( sirp & SCSI_DRDY ) { retval = 0; printf("ioasicint: Unexpected 53C94 data ready interrupt.\n" ); resetval &= ~SCSI_DRDY; }#endif if ( sirp & SCSI_C94 ) { retval = 0; /* go through '94 code */ resetval &= ~SCSI_C94; } *sir = resetval; return retval; }int is_local_xfer( p )PDMA *p; /* pointer for the DMA control struct */ { int i; DTENT *t, *e; t = (DTENT *) p->dat_addr; /* grab the address of a table */ i = p->dat_index; /* and the index into the table */ e = &t[i]; if ( e->uadr ) /* if user buffer address is defined, */ { /* then a local fragment buffer is being */ return 1; /* used. */ } else /* Yes, this could be a ?: statement but I */ { /* detest those */ return 0; } }dumptbl( tent )DTENT *tent; { int k; int so = 0; printf( "Table dump\n" ); for( k = 0; k < DATTBL_SIZ; k++ ) { printf( " index:%d ", k ); if ( !dumpent( &(tent[k]) ) && so ) k = DATTBL_SIZ; else so = 1; } }dumpent( tent )DTENT *tent; { printf( "len=%d addr=0x%x uadr=0x%x iadr=0x%x, ", tent->length, tent->addr, tent->uadr, tent->iadr ); if ( !tent->completed ) printf( "not "); printf( "completed, " ); if ( tent->dir == IOASIC_READ ) printf( "read\n" ); else if ( tent->dir == IOASIC_WRITE ) printf( "write\n" ); else cprintf( "unknown\n" ); return( tent->length ); } blddatent( tent, ecount, addr, uadr, dir )DTENT *tent; unsigned long ecount; char *addr, *uadr;int dir; { if ( !tent ) return( PDMA_FAIL ); tent->length = ecount; tent->addr = addr; tent->uadr = uadr; tent->completed = 0; if ( dir == SZ_DMA_READ ) dir = IOASIC_READ; else if ( dir == SZ_DMA_WRITE ) dir = IOASIC_WRITE; else dir = IOASIC_UNDEF; tent->dir = dir; if ( addr ) { tent->iadr = (unsigned *) ioa_addrcvt( addr ); if ( tent->iadr == 0 ) { dumpent( tent ); return( PDMA_FAIL ); } } else tent->iadr = 0; return( PDMA_SUCCESS ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -