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

📄 mcd_dmaapi.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 3 页
字号:
		    || MCD_chStatus[channel] == MCD_IDLE) {			MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT;			/* This register is selected to know which initiator is			   actually asserted. */			if ((MCD_dmaBar->ptdDebug >> channel) & 0x1)				MCD_chStatus[channel] = MCD_RUNNING;			else				MCD_chStatus[channel] = MCD_IDLE;			/* do not change the status if it is already paused. */		}	}	return MCD_chStatus[channel];}/******************** End of MCD_dmaStatus() ************************//********************************************************************//* Function:    MCD_startDma * Ppurpose:    Starts a particular kind of DMA * Arguments: * srcAddr	- the channel on which to run the DMA * srcIncr	- the address to move data from, or buffer-descriptor address * destAddr	- the amount to increment the source address per transfer * destIncr	- the address to move data to * dmaSize	- the amount to increment the destination address per transfer * xferSize	- the number bytes in of each data movement (1, 2, or 4) * initiator	- what device initiates the DMA * priority	- priority of the DMA * flags	- flags describing the DMA * funcDesc	- description of byte swapping, bit swapping, and CRC actions * srcAddrVirt	- virtual buffer descriptor address TBD * Returns:     MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK */int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr,		 s16 destIncr, u32 dmaSize, u32 xferSize, u32 initiator,		 int priority, u32 flags, u32 funcDesc#ifdef MCD_NEED_ADDR_TRANS		 s8 * srcAddrVirt#endif    ){	int srcRsdIncr, destRsdIncr;	int *cSave;	short xferSizeIncr;	int tcrCount = 0;#ifdef MCD_INCLUDE_EU	u32 *realFuncArray;#endif	if ((channel < 0) || (channel >= NCHANNELS))		return (MCD_CHANNEL_INVALID);	/* tbd - need to determine the proper response to a bad funcDesc when	   not including EU functions, for now, assign a benign funcDesc, but	   maybe should return an error */#ifndef MCD_INCLUDE_EU	funcDesc = MCD_FUNC_NOEU1;#endif#ifdef MCD_DEBUG	printf("startDma:Setting up params\n");#endif	/* Set us up for task-wise priority.  We don't technically need to do	   this on every start, but since the register involved is in the same	   longword as other registers that users are in control of, setting	   it more than once is probably preferable.  That since the	   documentation doesn't seem to be completely consistent about the	   nature of the PTD control register. */	MCD_dmaBar->ptdControl |= (u16) 0x8000;	/* Not sure what we need to keep here rtm TBD */#if 1	/* Calculate additional parameters to the regular DMA calls. */	srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0);	destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0);	xferSizeIncr = (xferSize & 0xffff) | 0x20000000;	/* Remember for each channel which variant is running. */	MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr;	MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr;	MCD_remVariants.remDestIncr[channel] = destIncr;	MCD_remVariants.remSrcIncr[channel] = srcIncr;	MCD_remVariants.remXferSize[channel] = xferSize;#endif	cSave =	    (int *)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET +	    CURRBD;#ifdef MCD_INCLUDE_EU	/* may move this to EU specific calls */	realFuncArray =	    (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00);	/* Modify the LURC's normal and byte-residue-loop functions according	   to parameter. */	realFuncArray[(LURC * 16)] = xferSize == 4 ?	    funcDesc : xferSize == 2 ?	    funcDesc & 0xfffff00f : funcDesc & 0xffff000f;	realFuncArray[(LURC * 16 + 1)] =	    (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL;#endif	/* Write the initiator field in the TCR, and also set the	   initiator-hold bit. Note that,due to a hardware quirk, this could	   collide with an MDE access to the initiator-register file, so we	   have to verify that the write reads back correctly. */	MCD_dmaBar->taskControl[channel] =	    (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;	while (((MCD_dmaBar->taskControl[channel] & 0x1fff) !=		((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM))	       && (tcrCount < 1000)) {		tcrCount++;		/*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020; */		MCD_dmaBar->taskControl[channel] =		    (initiator << 8) | TASK_CTL_HIPRITSKEN |		    TASK_CTL_HLDINITNUM;	}	MCD_dmaBar->priority[channel] = (u8) priority & PRIORITY_PRI_MASK;	/* should be albe to handle this stuff with only one write to ts reg	   - tbd */	if (channel < 8 && channel >= 0) {		MCD_dmaBar->taskSize0 &= ~(0xf << (7 - channel) * 4);		MCD_dmaBar->taskSize0 |=		    (xferSize & 3) << (((7 - channel) * 4) + 2);		MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel) * 4);	} else {		MCD_dmaBar->taskSize1 &= ~(0xf << (15 - channel) * 4);		MCD_dmaBar->taskSize1 |=		    (xferSize & 3) << (((15 - channel) * 4) + 2);		MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel) * 4);	}	/* setup task table flags/options which mostly control the line	   buffers */	MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK;	MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags);	if (flags & MCD_FECTX_DMA) {		/* TDTStart and TDTEnd */		MCD_taskTable[channel].TDTstart =		    MCD_modelTaskTable[TASK_FECTX].TDTstart;		MCD_taskTable[channel].TDTend =		    MCD_modelTaskTable[TASK_FECTX].TDTend;		MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable,				     channel);	} else if (flags & MCD_FECRX_DMA) {		/* TDTStart and TDTEnd */		MCD_taskTable[channel].TDTstart =		    MCD_modelTaskTable[TASK_FECRX].TDTstart;		MCD_taskTable[channel].TDTend =		    MCD_modelTaskTable[TASK_FECRX].TDTend;		MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable,				    channel);	} else if (flags & MCD_SINGLE_DMA) {		/* this buffer descriptor is used for storing off initial		   parameters for later progress query calculation and for the		   DMA to write the resulting checksum. The DMA does not use		   this to determine how to operate, that info is passed with		   the init routine */		MCD_relocBuffDesc[channel].srcAddr = srcAddr;		MCD_relocBuffDesc[channel].destAddr = destAddr;		/* definitely not its final value */		MCD_relocBuffDesc[channel].lastDestAddr = destAddr;		MCD_relocBuffDesc[channel].dmaSize = dmaSize;		MCD_relocBuffDesc[channel].flags = 0;	/* not used */		MCD_relocBuffDesc[channel].csumResult = 0;	/* not used */		MCD_relocBuffDesc[channel].next = 0;	/* not used */		/* Initialize the progress-querying stuff to show no		   progress: */		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[CURRBD + CSAVE_OFFSET] =(u32) & (MCD_relocBuffDesc[channel]);		/* tbd - need to keep the user from trying to call the EU		   routine when MCD_INCLUDE_EU is not defined */		if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) {			/* TDTStart and TDTEnd */			MCD_taskTable[channel].TDTstart =			    MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart;			MCD_taskTable[channel].TDTend =			    MCD_modelTaskTable[TASK_SINGLENOEU].TDTend;			MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr,					       destIncr, dmaSize, xferSizeIncr,					       flags, (int *)					       &(MCD_relocBuffDesc[channel]),					       cSave, MCD_taskTable, channel);		} else {			/* TDTStart and TDTEnd */			MCD_taskTable[channel].TDTstart =			    MCD_modelTaskTable[TASK_SINGLEEU].TDTstart;			MCD_taskTable[channel].TDTend =			    MCD_modelTaskTable[TASK_SINGLEEU].TDTend;			MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr,					     destIncr, dmaSize, xferSizeIncr,					     flags, (int *)					     &(MCD_relocBuffDesc[channel]),					     cSave, MCD_taskTable, channel);		}	} else {		/* chained DMAS */		/* Initialize the progress-querying stuff to show no		   progress: */#if 1		/* (!defined(MCD_NEED_ADDR_TRANS)) */		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[SRCPTR + CSAVE_OFFSET]		    = (int)((MCD_bufDesc *) srcAddr)->srcAddr;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[DESTPTR + CSAVE_OFFSET]		    = (int)((MCD_bufDesc *) srcAddr)->destAddr;#else		/* if using address translation, need the virtual addr of the		   first buffdesc */		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[SRCPTR + CSAVE_OFFSET]		    = (int)((MCD_bufDesc *) srcAddrVirt)->srcAddr;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[DESTPTR + CSAVE_OFFSET]		    = (int)((MCD_bufDesc *) srcAddrVirt)->destAddr;#endif		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;		((volatile int *)MCD_taskTable[channel].		 contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr;		if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) {			/*TDTStart and TDTEnd */			MCD_taskTable[channel].TDTstart =			    MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart;			MCD_taskTable[channel].TDTend =			    MCD_modelTaskTable[TASK_CHAINNOEU].TDTend;			MCD_startDmaChainNoEu((int *)srcAddr, srcIncr,					      destIncr, xferSize,					      xferSizeIncr, cSave,					      MCD_taskTable, channel);		} else {			/*TDTStart and TDTEnd */			MCD_taskTable[channel].TDTstart =			    MCD_modelTaskTable[TASK_CHAINEU].TDTstart;			MCD_taskTable[channel].TDTend =			    MCD_modelTaskTable[TASK_CHAINEU].TDTend;			MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr,					    xferSize, xferSizeIncr, cSave,					    MCD_taskTable, channel);		}	}	MCD_chStatus[channel] = MCD_IDLE;	return (MCD_OK);}/************************ End of MCD_startDma() *********************//********************************************************************//* Function:    MCD_XferProgrQuery * Purpose:     Returns progress of DMA on requested channel * Arguments:   channel - channel to retrieve progress for *              progRep - pointer to user supplied MCD_XferProg struct * Returns:     MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK * * Notes: *  MCD_XferProgrQuery() upon completing or after aborting a DMA, or *  while the DMA is in progress, this function returns the first *  DMA-destination address not (or not yet) used in the DMA. When *  encountering a non-ready buffer descriptor, the information for *  the last completed descriptor is returned. * *  MCD_XferProgQuery() has to avoid the possibility of getting *  partially-updated information in the event that we should happen *  to query DMA progress just as the DMA is updating it. It does that *  by taking advantage of the fact context is not saved frequently for *  the most part. We therefore read it at least twice until we get the *  same information twice in a row. * *  Because a small, but not insignificant, amount of time is required *  to write out the progress-query information, especially upon *  completion of the DMA, it would be wise to guarantee some time lag *  between successive readings of the progress-query information. *//* How many iterations of the loop below to execute to stabilize values */#define STABTIME 0int MCD_XferProgrQuery(int channel, MCD_XferProg * progRep){	MCD_XferProg prevRep;	int again;		/* true if we are to try again to ge				   consistent results */	int i;			/* used as a time-waste counter */	int destDiffBytes;	/* Total no of bytes that we think actually				   got xfered. */	int numIterations;	/* number of iterations */	int bytesNotXfered;	/* bytes that did not get xfered. */	s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr;	int subModVal, addModVal;	/* Mode values to added and subtracted					   from the final destAddr */	if ((channel < 0) || (channel >= NCHANNELS))		return (MCD_CHANNEL_INVALID);	/* Read a trial value for the progress-reporting values */	prevRep.lastSrcAddr =	    (s8 *) ((volatile int *)MCD_taskTable[channel].		    contextSaveSpace)[SRCPTR + CSAVE_OFFSET];	prevRep.lastDestAddr =	    (s8 *) ((volatile int *)MCD_taskTable[channel].		    contextSaveSpace)[DESTPTR + CSAVE_OFFSET];	prevRep.dmaSize =	    ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT +								      CSAVE_OFFSET];	prevRep.currBufDesc =	    (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel].			     contextSaveSpace)[CURRBD + CSAVE_OFFSET];	/* Repeatedly reread those values until they match previous values: */	do {		/* Waste a little bit of time to ensure stability: */		for (i = 0; i < STABTIME; i++) {			/* make sure this loop does something so that it			   doesn't get optimized out */			i += i >> 2;		}		/* Check them again: */		progRep->lastSrcAddr =		    (s8 *) ((volatile int *)MCD_taskTable[channel].			    contextSaveSpace)[SRCPTR + CSAVE_OFFSET];		progRep->lastDestAddr =		    (s8 *) ((volatile int *)MCD_taskTable[channel].			    contextSaveSpace)[DESTPTR + CSAVE_OFFSET];		progRep->dmaSize =		    ((volatile int *)MCD_taskTable[channel].		     contextSaveSpace)[DCOUNT + CSAVE_OFFSET];		progRep->currBufDesc =		    (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel].

⌨️ 快捷键说明

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