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

📄 pdma_ds5000.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
    if( sc->dma_pflags & PDMA_PREFLUSH )    {	for( i = 0; i < PIPE_BUF_NUM; i++ )	{	    (*sc->dma_bzero)		( sc->pdma_rambuff + RAM_ADJUST(sc, pd->pb_offset[i]),		MAX_XFER_SIZE ); 	    wbflush();	    pd->pb_flags[i] = PB_READY;		/* set to ready for data */	}    }   /* If the I/O direction is a READ, load the two pipe buffer counters.  By    definition buffer 0 will take presidence over buffer 1.  Buffer 0    will be filled first the total count will also be decremented. */    if( dir == SZ_DMA_READ )    {	for( i = 0; i < PIPE_BUF_NUM; i++ )	{	    lcount = XFER_BUFCNT( pd->count - pd->usercnt );	/* how much */	    pd->usercnt += lcount;	/* update count for later */	    pd->pb_count[i] = lcount;	/* load the count expected */	    pd->pb_flags[i] = PB_LOADED;/* loaded for a READ :-) */	    if( pd->usercnt == pd->count )	/* stop if no more data */	    {		break;			/* drop out of the for loop */	    }	}    }    else    {      /* If the I/O direction is a WRITE, pre fill the pipe buffers.  By	definition buffer 0 will take presidence over buffer 1.  Buffer 0	will be filled/emptied first. */	for( i = 0; i < PIPE_BUF_NUM; i++ )	{            int len;	    len = lcount = XFER_BUFCNT( pd->count - pd->usercnt );            if( (pd->usercnt + lcount) > sc->sc_b_bcount[targid] )  {	         /* Calc the new len to the end. */	         len = sc->sc_b_bcount[targid] - pd->usercnt;	         /* Zero out the half of the RAM buffer, this will deal with	            the zero fill requirement. */	         (*sc->dma_bzero)		     ( sc->pdma_rambuff + RAM_ADJUST(sc, pd->pb_offset[i]),		       lcount); 	         wbflush();	    }	    /* Move the data to write into the RAM buffer. */	    (*sc->dma_wbcopy)( (pd->data_addr + pd->usercnt),		(sc->pdma_rambuff + RAM_ADJUST( sc, pd->pb_offset[i] )),		len);	    wbflush();	    pd->usercnt += lcount;	/* update user space count */	    pd->pb_count[i] = lcount;	/* load the count for this buffer */	    pd->pb_flags[i] = PB_LOADED;	    	    if( pd->usercnt == pd->count )	/* stop if all data moved */	    {		break;			/* drop out of the for loop */	    }	}    }    return( PDMA_SUCCESS );		/* ready */}/************************************************************************int pdma_start( sc, targid, opcode )Inputs:	sz_softc *sc;		 pointer to the softc structure 	int targid;		 current targit ID 	int opcode;		 value to start the dma oper in the chip Function:	This routine is fairly straight forward.  It is responsible for loading	what ever is necessary into the DMA engine and the SCSI chip.  The 	dma control structure for the target should contain all the information.	The SZ_DID_DMA flag in the softc structure will be set.  This informs	the driver that data xfers are taking place.	    NOTE: Most of the SCSI chips with the RAM buffer use offsets into	    the buffer for the location of the data.  This is the reason for	    storing the offsets instead of pointers.	    NOTE: An opcode argument is passed to this routine mostly for the	    3max/NCR 53c94.  In the SII, 5380 machines the sequence is fairly	    "canned" to start up dma for the data phases.  However the 3max	    plans to use these routines for all information phases.Return:	PDMA_SUCCESS		 all is ready and ok 	PDMA_FAIL		 a fatal(?) problem has occured **************************************************************************/intds5000_start( sc, targid, opcode )    struct sz_softc *sc;	/* pointer to the softc structure */    int targid;			/* current targit 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 *ascar;		/* pointer for the SCSI DMA engine register */	    PRINTD( targid, 0x1,	("ds5000_start entry sc:%x targ:%d op:%x\n", sc, targid, opcode ));    /* Initialize local variables. */    pd = &sc->pdma_ctrl[ targid ];	/* assign the pointer */    ascaddr = (ASCREG *)sc->sc_scsiaddr;/* get the chip addr */    ascar = (DMAAR *)sc->pdma_addrreg;	/* 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. */    ascar->rambuf_dma =			/* load addr reg */	(((pd->iodir == SZ_DMA_WRITE) ? DMA_ASC_WRITE : 0 ) |     		(pd->pb_offset[0] & 0x00ffffff));    wbflush();    ASC_LOADCNTR(ascaddr, pd->pb_count[0]);	/* load counter */    wbflush();    /* Start the DMA operation in the ASC. */    /* NOTE: for the 3max all this will not be necessary, probably just load	passed opcode ?  */    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;    pd->pb_flags[0] = PB_DMA_ACTIVE;    sc->sc_szflags[ targid ] |= SZ_DID_DMA;    return( PDMA_SUCCESS );}/************************************************************************int pdma_cont( sc, targid )Inputs:	sz_softc *sc;		 pointer to the softc structure 	int targid;		 current targit ID Function:	Handle intermediate DMA functions during the transfer.  In the case	of pipe buffers the SCSI chip/Engine will reach terminal count	whenever one of the buffers is filled/emptied.   The active buffer	for a DATA_IN will have the data moved to user space.  For a DMA_OUT	the next buffer will be given to the SCSI chip, and the previous 	buffer will be filled to get ready for the next pdma_cont() call.	    NOTE: An assupmtion is made that for a DMA_OUT the next buffer is	    always ready with valid data, if necessary.	    NOTE: In the CMAX case the SII has a limitation in the data	    counter.  It can only xfer 8k bytes with one DMA operation.  	    This routine would only have to kick start the SII again.    Question:  Is it fair to assume that this routine will only get called	on TC and not phase change?  There is no checking on the current	counter within the SCSI chip.Return:	The number of bytes transfered sofar for this DMA operation.**************************************************************************/intds5000_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 *ascar;		/* pointer for the SCSI DMA engine register */    int	ffr;			/* value for the FIFO flags */    int	tcount;			/* corrected count for the ASC counters */    int lcount;			/* local count from the transfers */    int active;			/* index for the current active pipe buffer */    int next;			/* index for the next active pipe buffer */    PRINTD( targid, 0x1,	("ds5000_cont entry sc:%x targ:%d\n", sc, targid));    pd = &sc->pdma_ctrl[ targid ];	/* assign the pointer */    ascaddr = (ASCREG *)sc->sc_scsiaddr;/* get the chip addr */    ascar = (DMAAR *)sc->pdma_addrreg;	/* engine address */    /* Find the current active buffer in the pipe.  The offset and counts are    needed.  The return value will not be checked. */    get_bindex( pd, &active, &next );	/* scan the buffers for DMA_ACTIVE */    /* Do a quick check to determine there is still data that needs to be     "continued".  If the Target is slow in changing phase from DATA, the    terminal count interrupt will occur before the phase change interrupt.    This routine could be called and later a phase change occurs.  If there is    no more data left to transfer just return the target count.  When the    phase change interrupt finially happens the pdma_end() routine will clean    up. */    if( (pd->targcnt + pd->pb_count[ active ]) == pd->count )    {	PRINTD(targid, 0x1, ("dma_cont: returning (no i/o), targcnt = 0x%x\n",		pd->targcnt));	return( pd->targcnt );			/* nothing done */    }    /* 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.    Q: What if SCSI cntr != 0? [pdma_end should be called ?] */    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();    /* debug - since we only call this routine when the phase is the same AND	   when TC is set, I believe that both of these should be zero. */    if ((tcount != 0) || (ffr != 0))  {	PRINTD(targid, 0x8000, ("ds5000_cont: tcount = %x, ffr = %x\n",		tcount, ffr));	}    if( pd->iodir == SZ_DMA_WRITE )        tcount += ffr;	/* update count by whats in FIFO on writes */    lcount = pd->pb_count[ active ] - tcount;    /* keep track of total number of bytes actually transferred */    sc->sc_ascdmacount[targid] += lcount;    /* Check the direction flag to determine what has to be done with the pipe    buffers. */    if( pd->iodir == SZ_DMA_READ )    {        /* If the operation is a DMA_IN: swap the buffers if there is more data	that has to come in, startup the DMA, and then move the data from the	now idle buffer to user space. */        /* Load up the SCSI chip with the address and count for the next	buffer. */	/* Load addr reg, no need to set the write bit. */	ascar->rambuf_dma = (pd->pb_offset[ next ] & 0x00ffffff);	wbflush();	ASC_LOADCNTR(ascaddr, pd->pb_count[ next ]);	/* load counter */	wbflush();	PRINTD(targid, 0x8000, 	  ("ds5000_cont: (READ) starting new dma %x bytes\n", 		pd->pb_count[next]));        /* 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. */	pd->pb_flags[ next ] = PB_DMA_ACTIVE;	sc->sc_szflags[ targid ] |= SZ_DID_DMA;        /* Switch the "active" pipe buffer from DMA_ACTIVE to CPU_ACTIVE, the	SCSI chip is done with it.  Move the data into user space. */	pd->pb_flags[ active ] = PB_CPU_ACTIVE;	PRINTD(targid, 0x8000,	  ("ds5000_cont: (READ) bcopying %x bytes to user space\n", 		pd->pb_count[active]));	if( pd->pb_count[active] != 0 )	/* don't bother if no data */	{	    (*sc->dma_rbcopy)			/* move the data */		((sc->pdma_rambuff + RAM_ADJUST( sc, pd->pb_offset[ active ] )),		(pd->data_addr + pd->targcnt), pd->pb_count[ active ] );	    wbflush();	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -