📄 xemac_intr_dma.c
字号:
case XEM_RECV: *WaitPtr = XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel); break; default: return XST_INVALID_PARAM; } return XST_SUCCESS;}/*****************************************************************************//**** Give the driver the memory space to be used for the scatter-gather DMA* receive descriptor list. This function should only be called once, during* initialization of the Ethernet driver. The memory space must be big enough* to hold some number of descriptors, depending on the needs of the system.* The xemac.h file defines minimum and default numbers of descriptors* which can be used to allocate this memory space.** The memory space must be word-aligned. An assert will occur if asserts are* turned on and the memory is not word-aligned.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param MemoryPtr is a pointer to the word-aligned memory.* @param ByteCount is the length, in bytes, of the memory space.** @return** - XST_SUCCESS if the space was initialized successfully* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA* - XST_DMA_SG_LIST_EXISTS if this list space has already been created** @note** If the device is configured for scatter-gather DMA, this function must be* called AFTER the XEmac_Initialize() function because the DMA channel* components must be initialized before the memory space is set.*******************************************************************************/XStatusXEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount){ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(MemoryPtr != NULL); XASSERT_NONVOID(ByteCount != 0); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); if (!XEmac_mIsSgDma(InstancePtr)) { return XST_NOT_SGDMA; } return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr, ByteCount);}/*****************************************************************************//**** Give the driver the memory space to be used for the scatter-gather DMA* transmit descriptor list. This function should only be called once, during* initialization of the Ethernet driver. The memory space must be big enough* to hold some number of descriptors, depending on the needs of the system.* The xemac.h file defines minimum and default numbers of descriptors* which can be used to allocate this memory space.** The memory space must be word-aligned. An assert will occur if asserts are* turned on and the memory is not word-aligned.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param MemoryPtr is a pointer to the word-aligned memory.* @param ByteCount is the length, in bytes, of the memory space.** @return** - XST_SUCCESS if the space was initialized successfully* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA* - XST_DMA_SG_LIST_EXISTS if this list space has already been created** @note** If the device is configured for scatter-gather DMA, this function must be* called AFTER the XEmac_Initialize() function because the DMA channel* components must be initialized before the memory space is set.*******************************************************************************/XStatusXEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount){ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(MemoryPtr != NULL); XASSERT_NONVOID(ByteCount != 0); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); if (!XEmac_mIsSgDma(InstancePtr)) { return XST_NOT_SGDMA; } return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr, ByteCount);}/*****************************************************************************//**** Set the callback function for handling received frames in scatter-gather DMA* mode. The upper layer software should call this function during* initialization. The callback is called once per frame received. The head of* a descriptor list is passed in along with the number of descriptors in the* list. Before leaving the callback, the upper layer software should attach a* new buffer to each descriptor in the list.** The callback is invoked by the driver within interrupt context, so it needs* to do its job quickly. Sending the received frame up the protocol stack* should be done at task-level. If there are other potentially slow operations* within the callback, these too should be done at task-level.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param CallBackRef is a reference pointer to be passed back to the adapter in* the callback. This helps the adapter correlate the callback to a* particular driver.* @param FuncPtr is the pointer to the callback function.** @return** None.** @note** None.*******************************************************************************/voidXEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef, XEmac_SgHandler FuncPtr){ /* * Asserted IsDmaSg here instead of run-time check because there is really * no ill-effects of setting these when not configured for scatter-gather. */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(FuncPtr != NULL); XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); InstancePtr->SgRecvHandler = FuncPtr; InstancePtr->SgRecvRef = CallBackRef;}/*****************************************************************************//**** Set the callback function for handling confirmation of transmitted frames in* scatter-gather DMA mode. The upper layer software should call this function* during initialization. The callback is called once per frame sent. The head* of a descriptor list is passed in along with the number of descriptors in* the list. The callback is responsible for freeing buffers attached to these* descriptors.** The callback is invoked by the driver within interrupt context, so it needs* to do its job quickly. If there are potentially slow operations within the* callback, these should be done at task-level.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param CallBackRef is a reference pointer to be passed back to the adapter in* the callback. This helps the adapter correlate the callback to a* particular driver.* @param FuncPtr is the pointer to the callback function.** @return** None.** @note** None.*******************************************************************************/voidXEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef, XEmac_SgHandler FuncPtr){ /* * Asserted IsDmaSg here instead of run-time check because there is really * no ill-effects of setting these when not configured for scatter-gather. */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(FuncPtr != NULL); XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); InstancePtr->SgSendHandler = FuncPtr; InstancePtr->SgSendRef = CallBackRef;}/*****************************************************************************//*** Handle an interrupt from the DMA receive channel. DMA interrupts are:** - DMA error. DMA encountered a bus error or timeout. This is a fatal error* that requires reset of the channel. The driver calls the error handler* of the upper layer software with an error code indicating the device should* be reset.* - Packet count threshold reached. For scatter-gather operations, indicates* the threshold for the number of packets not serviced by software has been* reached. The driver behaves as follows:* - Get the value of the packet counter, which tells us how many packets* are ready to be serviced* - For each packet* - For each descriptor, remove it from the scatter-gather list* - Check for the last descriptor in the frame, and if set* - Bump frame statistics* - Call the scatter-gather receive callback function* - Decrement the packet counter by one* Note that there are no receive errors reported in the status word of* the buffer descriptor. If receive errors occur, the MAC drops the* packet, and we only find out about the errors through various error* count registers.* - Packet wait bound reached. For scatter-gather, indicates the time to wait* for the next packet has expired. The driver follows the same logic as when* the packet count threshold interrupt is received.* - Scatter-gather end acknowledge. Hardware has reached the end of the* descriptor list. The driver follows the same logic as when the packet count* threshold interrupt is received. In addition, the driver restarts the DMA* scatter-gather channel in case there are newly inserted descriptors.** @param InstancePtr is a pointer to the XEmac instance to be worked on.** @return** Although the function returns void, there are asynchronous errors that can* be generated (by calling the ErrorHandler) from this function. These are:* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the* DMA channel, but there was not one ready for software.* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal* error that requires reset.** @note** None.*******************************************************************************/static voidHandleDmaRecvIntr(XEmac * InstancePtr){ u32 IntrStatus; /* * Read the interrupt status */ IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel); /* * For packet threshold or wait bound interrupts, process desciptors. Also * process descriptors on a SG end acknowledgement, which means the end of * the descriptor list has been reached by the hardware. For receive, this * is potentially trouble since it means the descriptor list is full, * unless software can process enough packets quickly enough so the * hardware has room to put new packets. */ if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { XStatus Result = XST_SUCCESS; u32 NumFrames; u32 NumProcessed; u32 NumBuffers; u32 NumBytes; u32 IsLast; XBufDescriptor *FirstBdPtr; XBufDescriptor *BdPtr; /* * Get the number of unserviced packets */ NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel); for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) { IsLast = FALSE; FirstBdPtr = NULL; NumBuffers = 0; NumBytes = 0; /* * For each packet, get the descriptor from the list. On the * last one in the frame, make the callback to the upper layer. */ while (!IsLast) { Result = XDmaChannel_GetDescriptor(&InstancePtr-> RecvChannel, &BdPtr); if (Result != XST_SUCCESS) { /* * An error getting a buffer descriptor from the list. * This should not happen, but if it does, report it to * the error callback and break out of the loops to service * other interrupts. */ InstancePtr->ErrorHandler(InstancePtr-> ErrorRef, Result); break; } /* * Keep a pointer to the first descriptor in the list, as it * will be passed to the upper layers in a bit. By the fact * that we received this packet means no errors occurred, so * no need to check the device status word for errors. */ if (FirstBdPtr == NULL) { FirstBdPtr = BdPtr; } NumBytes += XBufDescriptor_GetLength(BdPtr); /* * Check to see if this is the last descriptor in the frame, * and if so, set the IsLast flag to get out of the loop. */ if (XBufDescriptor_IsLastStatus(BdPtr)) { IsLast = TRUE; } /* * Bump the number of buffers in this packet */ NumBuffers++; } /* end while loop */ /* * Check for error that occurred inside the while loop, and break * out of the for loop if there was one so other interrupts can
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -