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

📄 xemacps_bdring.c

📁 定制简单LED的IP核的设计源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Starting at HwHead, keep moving forward in the list until:	 *  - A BD is encountered with its new/used bit set which means	 *    hardware has not completed processing of that BD.	 *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.	 *  - The number of requested BDs has been processed	 */	while (BdCount < BdLimit) {		/* Read the status */		XEMACPS_CACHE_INVALIDATE(CurBdPtr);		BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);		if ((Sop == 0) && (BdStr & XEMACPS_TXBUF_USED_MASK))			Sop = 1;		if (Sop == 1) {			BdCount++;			BdPartialCount++;		}		/* hardware has processed this BD so check the "last" bit.		 * If it is clear, then there are more BDs for the current		 * packet. Keep a count of these partial packet BDs.		 */		if ((Sop == 1) && (BdStr & XEMACPS_TXBUF_LAST_MASK)) {			Sop = 0;			BdPartialCount = 0;		}		/* Move on to next BD in work group */		CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);	}	/* Subtract off any partial packet BDs found */        BdCount -= BdPartialCount;	/* If BdCount is non-zero then BDs were found to return. Set return	 * parameters, update pointers and counters, return success	 */	if (BdCount > 0) {		*BdSetPtr = RingPtr->HwHead;		RingPtr->HwCnt -= BdCount;		RingPtr->PostCnt += BdCount;		XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);		return (BdCount);	}	else {		*BdSetPtr = NULL;		return (0);	}}/*****************************************************************************//** * Returns a set of BD(s) that have been processed by hardware. The returned * BDs may be examined to determine the outcome of the DMA transaction(s). * Once the BDs have been examined, the user must call XEmacPs_BdRingFree() * in the same order which they were retrieved here. Example: * * <pre> *        NumBd = XEmacPs_BdRingFromHwRx(MyRingPtr, MaxBd, &MyBdSet); * *        if (NumBd == 0) *        { *           // hardware has nothing ready for us yet *        } * *        CurBd = MyBdSet; *        for (i=0; i<NumBd; i++) *        { *           // Examine CurBd for post processing..... * *           // Onto next BD *           CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd); *           } * *           XEmacPs_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return list *        } * </pre> * * A more advanced use of this function may allocate multiple sets of BDs. * They must be retrieved from hardware and freed in the correct sequence: * <pre> *        // Legal *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1); * *        // Legal *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2); *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1); *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2); * *        // Not legal *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2); *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2); *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1); * </pre> * * If hardware has only partially completed a packet spanning multiple BDs, * then none of the BDs for that packet will be included in the results. * * @param RingPtr is a pointer to the instance to be worked on. * @param BdLimit is the maximum number of BDs to return in the set. * @param BdSetPtr is an output parameter, it points to the first BD available *        for examination. * * @return *   The number of BDs processed by hardware. A value of 0 indicates that no *   data is available. No more than BdLimit BDs will be returned. * * @note Treat BDs returned by this function as read-only. * * @note This function should not be preempted by another XEmacPs_Bd function *       call that modifies the BD space. It is the caller's responsibility to *       provide a mutual exclusion mechanism. * *****************************************************************************/unsigned XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, unsigned BdLimit,				 XEmacPs_Bd ** BdSetPtr){	XEmacPs_Bd *CurBdPtr;	u32 BdStr = 0;	unsigned BdCount;	unsigned BdPartialCount;	CurBdPtr = RingPtr->HwHead;	BdCount = 0;	BdPartialCount = 0;	/* If no BDs in work group, then there's nothing to search */	if (RingPtr->HwCnt == 0) {		*BdSetPtr = NULL;		return (0);	}	/* Starting at HwHead, keep moving forward in the list until:	 *  - A BD is encountered with its new/used bit set which means	 *    hardware has completed processing of that BD.	 *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.	 *  - The number of requested BDs has been processed	 */	while (BdCount < BdLimit) {		/* Read the status */		XEMACPS_CACHE_INVALIDATE(CurBdPtr);		BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);		if (!(XEmacPs_BdIsRxNew(CurBdPtr))) {			break;		}		BdCount++;		/* hardware has processed this BD so check the "last" bit. If                 * it is clear, then there are more BDs for the current packet.                 * Keep a count of these partial packet BDs.		 */		if (BdStr & XEMACPS_RXBUF_EOF_MASK) {			BdPartialCount = 0;		}		else {			BdPartialCount++;		}		/* Move on to next BD in work group */		CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);	}	/* Subtract off any partial packet BDs found */	BdCount -= BdPartialCount;	/* If BdCount is non-zero then BDs were found to return. Set return	 * parameters, update pointers and counters, return success	 */	if (BdCount > 0) {		*BdSetPtr = RingPtr->HwHead;		RingPtr->HwCnt -= BdCount;		RingPtr->PostCnt += BdCount;		XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);		return (BdCount);	}	else {		*BdSetPtr = NULL;		return (0);	}}/*****************************************************************************//** * Frees a set of BDs that had been previously retrieved with * XEmacPs_BdRingFromHw(). * * @param RingPtr is a pointer to the instance to be worked on. * @param NumBd is the number of BDs to free. * @param BdSetPtr is the head of a list of BDs returned by * XEmacPs_BdRingFromHw(). * * @return *   - XST_SUCCESS if the set of BDs was freed. *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with *     XEmacPs_BdRingFromHw(). * * @note This function should not be preempted by another XEmacPs_Bd function *       call that modifies the BD space. It is the caller's responsibility to *       provide a mutual exclusion mechanism. * *****************************************************************************/int XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, unsigned NumBd,			XEmacPs_Bd * BdSetPtr){	/* if no bds to process, simply return. */	if (0 == NumBd)		return (XST_SUCCESS);	/* Make sure we are in sync with XEmacPs_BdRingFromHw() */	if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) {		return (XST_DMA_SG_LIST_ERROR);	}	/* Update pointers and counters */	RingPtr->FreeCnt += NumBd;	RingPtr->PostCnt -= NumBd;	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd);	return (XST_SUCCESS);}/*****************************************************************************//** * Check the internal data structures of the BD ring for the provided channel. * The following checks are made: * *   - Is the BD ring linked correctly in physical address space. *   - Do the internal pointers point to BDs in the ring. *   - Do the internal counters add up. * * The channel should be stopped prior to calling this function. * * @param RingPtr is a pointer to the instance to be worked on. * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates *        which direction. * * @return *   - XST_SUCCESS if the set of BDs was freed. *   - XST_DMA_SG_NO_LIST if the list has not been created. *   - XST_IS_STARTED if the channel is not stopped. *   - XST_DMA_SG_LIST_ERROR if a problem is found with the internal data *     structures. If this value is returned, the channel should be reset to *     avoid data corruption or system instability. * * @note This function should not be preempted by another XEmacPs_Bd function *       call that modifies the BD space. It is the caller's responsibility to *       provide a mutual exclusion mechanism. * *****************************************************************************/int XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction){	u32 AddrV, AddrP;	unsigned i;	if ((Direction != XEMACPS_SEND) && (Direction != XEMACPS_RECV)) {		return (XST_INVALID_PARAM);	}	/* Is the list created */	if (RingPtr->AllCnt == 0) {		return (XST_DMA_SG_NO_LIST);	}	/* Can't check if channel is running */	if (RingPtr->RunState == XST_DMA_SG_IS_STARTED) {		return (XST_IS_STARTED);	}	/* RunState doesn't make sense */	else if (RingPtr->RunState != XST_DMA_SG_IS_STOPPED) {		return (XST_DMA_SG_LIST_ERROR);	}	/* Verify internal pointers point to correct memory space */	AddrV = (u32) RingPtr->FreeHead;	if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {		return (XST_DMA_SG_LIST_ERROR);	}	AddrV = (u32) RingPtr->PreHead;	if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {		return (XST_DMA_SG_LIST_ERROR);	}	AddrV = (u32) RingPtr->HwHead;	if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {		return (XST_DMA_SG_LIST_ERROR);	}	AddrV = (u32) RingPtr->HwTail;	if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {		return (XST_DMA_SG_LIST_ERROR);	}	AddrV = (u32) RingPtr->PostHead;	if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {		return (XST_DMA_SG_LIST_ERROR);	}	/* Verify internal counters add up */	if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt +	     RingPtr->PostCnt) != RingPtr->AllCnt) {		return (XST_DMA_SG_LIST_ERROR);	}	/* Verify BDs are linked correctly */	AddrV = RingPtr->BaseBdAddr;	AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation;	for (i = 1; i < RingPtr->AllCnt; i++) {		/* Check BDA for this BD. It should point to next physical addr */		if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) {			return (XST_DMA_SG_LIST_ERROR);		}		/* Move on to next BD */		AddrV += RingPtr->Separation;		AddrP += RingPtr->Separation;	}	/* Last BD should have wrap bit set */	if (XEMACPS_SEND == Direction) {		if (!XEmacPs_BdIsTxWrap(AddrV)) {			return (XST_DMA_SG_LIST_ERROR);		}	}	else {			/* XEMACPS_RECV */		if (!XEmacPs_BdIsRxWrap(AddrV)) {			return (XST_DMA_SG_LIST_ERROR);		}	}	/* No problems found */	return (XST_SUCCESS);}

⌨️ 快捷键说明

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