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

📄 xemacps_bdring.c

📁 自学ZedBoard:使用IP通过ARM PS访问FPGA(源代码)
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Can't do this function with some of the BDs in use */	if (RingPtr->FreeCnt != RingPtr->AllCnt) {		return (XST_DMA_SG_LIST_ERROR);	}	if ((Direction != XEMACPS_SEND) && (Direction != XEMACPS_RECV)) {		return (XST_INVALID_PARAM);	}	/* Starting from the top of the ring, save BD.Next, overwrite the entire	 * BD with the template, then restore BD.Next	 */	for (i = 0, CurBd = (u32) RingPtr->BaseBdAddr;	     i < RingPtr->AllCnt; i++, CurBd += RingPtr->Separation) {		memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd));		XEMACPS_CACHE_FLUSH(CurBd);	}	CurBd -= RingPtr->Separation;	if (Direction == XEMACPS_RECV) {		XEmacPs_BdSetRxWrap(CurBd);	}	else {		XEmacPs_BdSetTxWrap(CurBd);	}	XEMACPS_CACHE_FLUSH(CurBd);	return (XST_SUCCESS);}/*****************************************************************************//** * Reserve locations in the BD list. The set of returned BDs may be modified * in preparation for future DMA transaction(s). Once the BDs are ready to be * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same * order which they were allocated here. Example: * * <pre> *        NumBd = 2; *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet); * *        if (Status != XST_SUCCESS) *        { *            // Not enough BDs available for the request *        } * *        CurBd = MyBdSet; *        for (i=0; i<NumBd; i++) *        { *            // Prepare CurBd..... * *            // Onto next BD *            CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd); *        } * *        // Give list to hardware *        Status = XEmacPs_BdRingToHw(MyRingPtr, NumBd, MyBdSet); * </pre> * * A more advanced use of this function may allocate multiple sets of BDs. * They must be allocated and given to hardware in the correct sequence: * <pre> *        // Legal *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1); * *        // Legal *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2); *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1); *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2); * *        // Not legal *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2); *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2); *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1); * </pre> * * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal * of the BD set can be done using XEmacPs_BdRingNext() and * XEmacPs_BdRingPrev(). * * @param RingPtr is a pointer to the BD ring instance to be worked on. * @param NumBd is the number of BDs to allocate * @param BdSetPtr is an output parameter, it points to the first BD available *        for modification. * * @return *   - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr *     parameter. *   - XST_FAILURE if there were not enough free BDs to satisfy the request. * * @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. * * @note Do not modify more BDs than the number requested with the NumBd *       parameter. Doing so will lead to data corruption and system *       instability. * *****************************************************************************/int XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, unsigned NumBd,			 XEmacPs_Bd ** BdSetPtr){	/* Enough free BDs available for the request? */	if (RingPtr->FreeCnt < NumBd) {		return (XST_FAILURE);	}	/* Set the return argument and move FreeHead forward */	*BdSetPtr = RingPtr->FreeHead;	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd);	RingPtr->FreeCnt -= NumBd;	RingPtr->PreCnt += NumBd;	return (XST_SUCCESS);}/*****************************************************************************//** * Fully or partially undo an XEmacPs_BdRingAlloc() operation. Use this * function if all the BDs allocated by XEmacPs_BdRingAlloc() could not be * transferred to hardware with XEmacPs_BdRingToHw(). * * This function helps out in situations when an unrelated error occurs after * BDs have been allocated but before they have been given to hardware. * An example of this type of error would be an OS running out of resources. * * This function is not the same as XEmacPs_BdRingFree(). The Free function * returns BDs to the free list after they have been processed by hardware, * while UnAlloc returns them before being processed by hardware. * * There are two scenarios where this function can be used. Full UnAlloc or * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned: * * <pre> *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr); *        ... *    if (Error) *    { *        Status = XEmacPs_BdRingUnAlloc(MyRingPtr, 10, &BdPtr); *    } * </pre> * * A partial UnAlloc means some of the BDs Alloc'd will be returned: * * <pre> *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr); *    BdsLeft = 10; *    CurBdPtr = BdPtr; * *    while (BdsLeft) *    { *       if (Error) *       { *          Status = XEmacPs_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr); *       } * *       CurBdPtr = XEmacPs_BdRingNext(MyRingPtr, CurBdPtr); *       BdsLeft--; *    } * </pre> * * A partial UnAlloc must include the last BD in the list that was Alloc'd. * * @param RingPtr is a pointer to the instance to be worked on. * @param NumBd is the number of BDs to allocate * @param BdSetPtr is an output parameter, it points to the first BD available *        for modification. * * @return *   - XST_SUCCESS if the BDs were unallocated. *   - XST_FAILURE if NumBd parameter was greater that the number of BDs in *     the preprocessing state. * * @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_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, unsigned NumBd,			   XEmacPs_Bd * BdSetPtr){	/* Enough BDs in the free state for the request? */	if (RingPtr->PreCnt < NumBd) {		return (XST_FAILURE);	}	/* Set the return argument and move FreeHead backward */	XEMACPS_RING_SEEKBACK(RingPtr, RingPtr->FreeHead, NumBd);	RingPtr->FreeCnt += NumBd;	RingPtr->PreCnt -= NumBd;	return (XST_SUCCESS);}/*****************************************************************************//** * Enqueue a set of BDs to hardware that were previously allocated by * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes * under hardware control. Any changes made to these BDs after this point will * corrupt the BD list leading to data corruption and system instability. * * The set will be rejected if the last BD of the set does not mark the end of * a packet (see XEmacPs_BdSetLast()). * * @param RingPtr is a pointer to the instance to be worked on. * @param NumBd is the number of BDs in the set. * @param BdSetPtr is the first BD of the set to commit to hardware. * * @return *   - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware. *   - XST_FAILURE if the set of BDs was rejected because the last BD of the set *     did not have its "last" bit set. *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with *     XEmacPs_BdRingAlloc(). * * @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_BdRingToHw(XEmacPs_BdRing * RingPtr, unsigned NumBd,			XEmacPs_Bd * BdSetPtr){	XEmacPs_Bd *CurBdPtr;	unsigned i;	/* if no bds to process, simply return. */	if (0 == NumBd)		return (XST_SUCCESS);	/* Make sure we are in sync with XEmacPs_BdRingAlloc() */	if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {		return (XST_DMA_SG_LIST_ERROR);	}	CurBdPtr = BdSetPtr;	for (i = 0; i < NumBd; i++) {		XEMACPS_CACHE_FLUSH(CurBdPtr);		CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);	}	/* Adjust ring pointers & counters */	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);	RingPtr->PreCnt -= NumBd;	RingPtr->HwTail = CurBdPtr;	RingPtr->HwCnt += NumBd;	return (XST_SUCCESS);}/*****************************************************************************//** * 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_BdRingFromHwTx(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_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1); * *        // Legal *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2); *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1); *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2); * *        // Not legal *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1); *        XEmacPs_BdRingFromHwTx(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_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, unsigned BdLimit,				 XEmacPs_Bd ** BdSetPtr){	XEmacPs_Bd *CurBdPtr;	u32 BdStr = 0;	unsigned BdCount;	unsigned BdPartialCount;	unsigned int Sop = 0;	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);	}	if (BdLimit > RingPtr->HwCnt)		BdLimit = RingPtr->HwCnt;

⌨️ 快捷键说明

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