📄 pdma3min.c
字号:
/* blddattbl - Builds a table of DMA buffers suitable for use with the 3min. Users buffer address is broken up both at page boundaries and, when buffer areas are less than 8 bytes in length, fixed buffer areas allocated by the driver are used instead. Inputs: int controller - controller number DTENT *table - A pointer to the table to be filled in. long count - Length of the user's buffer. char *addr - Pointer to the user's buffer. Return: PDMA_FAIL on failure*/blddattbl( controller, pd, count, addr, dir ) int controller; PDMA *pd; /* pointer for the DMA control struct */unsigned long count; char *addr;int dir; { DTENT *table; char *frag; int index = 0; unsigned ecount; int rem; char *eaddr, *uadr; table = (DTENT *) pd->dat_addr; frag = pd->frag_bufp; /* build null 0th entry */ if ( blddatent( &table[index++], NULL, NULL, NULL, NULL ) == PDMA_FAIL ) return( PDMA_FAIL ); while( count ) { if ( !(ecount = caldatent( addr, count )) ) { printf( "blddattbl: Illegal return value (0) from caldatent().\n" ); return( PDMA_FAIL ); } if ( ecount < 8 ) { eaddr = frag; uadr = addr; } else { eaddr = addr; uadr = 0; } if ( blddatent( &(table[index++]), ecount, eaddr, uadr, dir ) ) { printstate |= PANICPRINT; printf("eaddr=0x%x ecount=%d\n ", eaddr, ecount); dumptbl( table ); panic("blddatbl: Invalid IOASIC physical address .\n"); } count -= ecount; addr += ecount; } if ( blddatent( &table[index++], NULL, NULL, NULL, NULL ) == PDMA_FAIL ) return( PDMA_FAIL ); return( PDMA_SUCCESS ); }/* rps - original 4K page params - should use other kernel defines */#define STRPW 0xfffffff8#define PAGS 0x00001000#define SEGMSK 0x00000fff#define FRAGSZ 0x00000008#define FRAGM 0x00000007int caldatent( addr, count )char *addr;long count; { unsigned long rem, rem2; unsigned long ecount; rem = ((unsigned long)addr) & FRAGM; rem2 = ((unsigned long)addr) & SEGMSK; if ( count < FRAGSZ ) ecount = count; else if ( rem ) /* not octabyte aligned? */ ecount = FRAGSZ - rem; else if ( rem2 ) /* not page aligned? */ { ecount = PAGS - rem2; if ( count < ecount ) ecount = ( ( ((unsigned long)addr) + count ) & STRPW ) - ((unsigned long)addr); } else /* a 4k page */ { ecount = PAGS; if ( count < ecount ) ecount = ( ( ((unsigned long)addr) + count ) & STRPW ) - ((unsigned long)addr); } return( ecount ); }flush_fragbuf( pd, lcount )PDMA *pd;unsigned long lcount; { DTENT *datp, *datep; /* pointer to DAT table and individual entry */ char *tp; if ( lcount > 7 ) printf("flush_fragbuf: pd=0x%x, lcount=%d\n", pd, lcount ); /* First pull out the DAT table entry corresponding to this xfer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]); if( lcount > 0 ) /* don't bother if no data */ { bcopy( datep->addr, datep->uadr, lcount ); pd->targcnt += lcount; /* update target count */ datep->length -= lcount; /* adjust DAT entry length */ datep->uadr += lcount; if ( datep->length == 0 ) pd->dat_index++; wbflush(); } }dmapload( sc, targid, addr )struct sz_softc *sc;int targid;unsigned int *addr; { unsigned **dmap; /* pointer to IOASIC DMA Ptr. reg. */ DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ PDMA *pd; DTENT *datp, *datep; /* pointer to DAT table and individual entry */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */ datp = (DTENT *)pd->dat_addr; datep = (DTENT *)&(datp[pd->dat_index]); ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ dmap = (unsigned **) ( ( (unsigned) ioasicp ) + IOA_S_DMAP_O ); if ( addr == 0 ) { printstate |= PANICPRINT; dumptbl( (DTENT *)pd->dat_addr ); printf("dat_index = %d\n", pd->dat_index ); dumpent( datep ); printf( "dmapload: Null IOASIC (SCSI) DMA address pointer.\n" ); return PDMA_FAIL; } *dmap = addr; return PDMA_SUCCESS; }ssrdmaon( sc, dir )struct sz_softc *sc;int dir; { unsigned *ssrp; /* pointer to IOASIC SSR */ DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ ssrp = (unsigned *)((unsigned)ioasicp + SSR_O); if ( dir ) /* read */ *ssrp |= ( SSR_DMADIR | SSR_DMAENB ); else { *ssrp &= ( ~SSR_DMADIR ); *ssrp |= SSR_DMAENB; } wbflush(); }ssrdmaoff( sc )struct sz_softc *sc; { unsigned *ssrp; /* pointer to IOASIC SSR */ DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ unsigned int ssr; ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ ssrp = (unsigned *)((unsigned)ioasicp + SSR_O);#ifdef PDMADEBUG if ( scsidebug & PASS2 && targtmp == targmatch ) { ssr = *ssrp; if ( ssr & SSR_DMAENB ) printf("ssrdmaoff: DMA enabled\n"); else printf("ssrdmaoff: DMA disabled\n"); }#endif *ssrp &= ( ~SSR_DMAENB ); wbflush(); }dumphex( ptr, len )char *ptr;unsigned len; { int i,j,index; printf("\nDump of 0x%x, length %d\n\n", ptr, len ); for( i=0; i<len; i+=16 ) { printf(" %05x: ", i ); for( j=0; j<16; j++ ) { index = i+j; if (index >= len ) break; printf( "%2x ", ptr[index] ); } printf( "\n" ); } }/* ------------------------------------------------------------------------ *//* getdbuffer( sc, bufp ) Copies the IOASIC data buffers into *//* a user buffer. User buffer must be *//* at least 8 bytes long! *//* Inputs: *//* sc Pointer to soft_c structure *//* bufp Pointer to user buffer. *//* *//* Return value: Number of valid data bytes or -1 on *//* error. *//* ------------------------------------------------------------------------ */int getdbuffer( sc, bufp )struct sz_softc *sc;void *bufp; { unsigned long *dbufp, *ubufp; unsigned int *cregp, creg; DMA_AR *ioasicp; /* pointer for the SCSI DMA engine register */ if ( !bufp ) /* check for invalid user address */ return -1; ubufp = (unsigned long *)bufp; /* address user buffer using 32's */ ioasicp = (DMAAR *)sc->ioasicp; /* engine address */ dbufp = (unsigned long *)((unsigned)ioasicp + SCSI_DATA0_O ); *ubufp++ = *dbufp; /* Copy word 1 */ dbufp = (unsigned long *)((unsigned)ioasicp + SCSI_DATA1_O ); *ubufp = *dbufp; /* Copy word 2 */ cregp = (unsigned int *)((unsigned)ioasicp + SCSI_CTRL_O ); creg = *cregp; /* grab the scsi control register */ if ( creg & CREG_DMA_M ) /* DMA operation in progress? */ return 0; /* nothing to read if a write */ creg &= CREG_BUSG_M; /* mask of to byte usage count */#ifdef PDMADEBUGif ( scsidebug & ENTRYEXIT && targtmp == targmatch ) printf( "getdbuffer: exit(%x)\n", creg<<1 );#endif return creg<<1; /* multiply hword's to get bytes */ }/* ------------------------------------------------------------------------ *//* getdbcount( sc, dir ) Returns the number of bytes filled *//* in the IOASIC data buffers. *//* Inputs: *//* sc Pointer to soft_c structure *//* dir IO Direction (IOASIC_READ or _WRITE)*//* *//* Return value: Number of valid data bytes or -1 on *//* error. *//* ------------------------------------------------------------------------ */int getdbcount( sc, dir )struct sz_softc *sc;int dir; { unsigned int *cregp, creg; /* Control pointer and content. */ DMA_AR *ioasicp; /* SCSI DMA engine register */ int bcnt; ioasicp = (DMAAR *)sc->ioasicp; /* Engine address */ cregp = (unsigned int *)((unsigned)ioasicp + SCSI_CTRL_O ); creg = *cregp; /* Grab the scsi control register. */ bcnt = creg & CREG_BUSG_M; /* Mask off to byte usage count. */ if ( dir == IOASIC_WRITE ) /* During writes, the sense of the */ { /* DMA bit is inverted. */ if ( creg & CREG_DMA_M ) /* Buffer not empty? */ return (4-bcnt)<<1; /* IOASIC counts in half-words (16)*/ return 0; /* bcnt is invalid */ } /* We've handled all WRITE cases. */ if ( creg & CREG_DMA_M ) /* DMA in progress? */ return 0;#ifdef PDMADEBUGif ( scsidebug & ENTRYEXIT && targtmp == targmatch ) printf( "getdbcount: exit(%x)\n", bcnt<<1 );#endif return bcnt<<1; /* Multiply hword's to get bytes. */ }voidsetscsictrl( sc, val )struct sz_softc *sc;int val; { unsigned int *cregp, creg; /* Control pointer and content. */ DMA_AR *ioasicp; /* SCSI DMA engine register */ int bcnt; ssrdmaoff( sc ); /* JIC, turn DMA OFF */ ioasicp = (DMAAR *)sc->ioasicp; /* Engine address */ cregp = (unsigned int *)((unsigned)ioasicp + SCSI_CTRL_O ); *cregp = val; wbflush(); }int flushdb( sc, cnt )struct sz_softc *sc;int cnt; { unsigned int *cregp, creg; /* Control pointer and content. */ DMA_AR *ioasicp; /* SCSI DMA engine register */ unsigned int *dmap; /* pointer to IOASIC DMA Ptr. reg. */ char *padr; /* physical address of user buffer */ char lbuf[32]; /* Local data buffer */ int bcnt; ioasicp = (DMAAR *)sc->ioasicp; /* Engine address */ dmap = (unsigned int *) ( (unsigned) ioasicp + IOA_S_DMAP_O ); padr = (char *) backcvt( (void *)*dmap ); /* Calc. the user buf address */ bcnt = getdbuffer( sc, lbuf ); /* grab data bytes */ if ( cnt != bcnt ) { printf("flushdb: input count (%d) doesn't match buffer count (%d)\n", cnt, bcnt ); } bcopy( lbuf, padr, cnt ); return cnt; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -