⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdma3min.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -