📄 xemac_intr_dma.c
字号:
break; } /* Bump statistics */ InstancePtr->Stats.RecvBytes += XBufDescriptor_GetLength(BdPtr); /* Have all BDs been read for this packet */ if (XBufDescriptor_IsLastStatus(BdPtr)) { /* * Decrement the packet count register to reflect the fact * we just processed a packet */ XDmaChannel_DecrementPktCount(&InstancePtr->RecvChannel); /* Bump statistics */ InstancePtr->Stats.RecvFrames++; /* Test loop exit condition */ if (--PacketsLeft == 0) { break; } } /* Get the next buffer descriptor in the list */ Result = XDmaChannel_GetDescriptor(&InstancePtr->RecvChannel, &BdPtr); } /* while */ /* * Check for error that occurred inside the while loop, and break * out of the for loop if there was one so other interrupts can * be serviced. */ if (Result == XST_SUCCESS) { /* * Make the callback to the upper layers, passing it the first * descriptor in the first packet and the number of descriptors * in the list. */ InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef, BdHeadPtr, NumBds); } } /* if (PacketsLeft) */ /* * If the interrupt was an end-ack, check the descriptor list again to * see if it is empty. If not, go ahead and restart the scatter-gather * channel. This is to fix a possible race condition where, on receive, * the driver attempted to start a scatter-gather channel that was * already started, which resulted in no action from the XDmaChannel * component. But, just after the XDmaChannel component saw that the * hardware was already started, the hardware stopped because it * reached the end of the list. In that case, this interrupt is * generated and we can restart the hardware here. */ if (IntrStatus & XDC_IXR_SG_END_MASK) { /* * Ignore the return status since we know the list exists and we * don't care if the list is empty or the channel is already started. */ (void)XDmaChannel_SgStart(&InstancePtr->RecvChannel); } } /* * All interrupts are handled (except the error below) so acknowledge * (clear) the interrupts by writing the value read above back to the status * register. The packet count interrupt must be acknowledged after the * decrement, otherwise it will come right back. We clear the interrupts * before we handle the error interrupt because the ErrorHandler should * result in a reset, which clears the interrupt status register. So we * don't want to toggle the interrupt back on by writing the interrupt * status register with an old value after a reset. */ XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus); /* * Check for DMA errors and call the error callback function if an error * occurred (DMA bus or timeout error), which should result in a reset of * the device by the upper layer software. */ if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { InstancePtr->Stats.DmaErrors++; InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); }}/*****************************************************************************//*** Handle an interrupt from the DMA send 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* - Decrement the packet counter by one* - Call the scatter-gather receive callback function* 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 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 void HandleDmaSendIntr(XEmac *InstancePtr){ XStatus Result; Xuint32 IntrStatus; Xuint32 NumBds; Xuint32 PacketsLeft; Xuint32 XmitStatus; int PacketStart; XBufDescriptor *BdHeadPtr; XBufDescriptor *BdPtr; /* * Read the interrupt status */ IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel); /* * For packet threshold or wait bound interrupt, process descriptors. Also * process descriptors on a SG end acknowledgement, which means the end of * the descriptor list has been reached by the hardware. For transmit, * this is a normal condition during times of light traffic. In fact, the * wait bound interrupt may be masked for transmit since the end-ack would * always occur before the wait bound expires. */ if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { /* Get the number of packets that need processing */ PacketsLeft = XDmaChannel_GetPktCount(&InstancePtr->SendChannel); if (PacketsLeft) { /* Get the buffer descriptor at the head of the list */ Result = XDmaChannel_GetDescriptor(&InstancePtr->SendChannel, &BdHeadPtr); BdPtr = BdHeadPtr; NumBds = 0; PacketStart = 1; /* Loop until all packets have been pulled or an error occurs */ while(1) { NumBds++; /* * 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 loop to service * other interrupts. */ if (Result != XST_SUCCESS) { InstancePtr->ErrorHandler(InstancePtr->ErrorRef, Result); break; } /* Bump statistics */ InstancePtr->Stats.XmitBytes += XBufDescriptor_GetLength(BdPtr); /* If 1st BD in a packet, then check xmit status */ if (PacketStart) { XmitStatus = XBufDescriptor_GetDeviceStatus(BdPtr); if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) { InstancePtr->Stats.XmitExcessDeferral++; } if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) { InstancePtr->Stats.XmitLateCollisionErrors++; } PacketStart = 0; } /* Have all BDs been read for this packet */ if (XBufDescriptor_IsLastStatus(BdPtr)) { /* * Decrement the packet count register to reflect the fact * we just processed a packet */ XDmaChannel_DecrementPktCount(&InstancePtr->SendChannel); (InstancePtr->SendChannel).ActivePacketCount--; /* Bump statistics */ InstancePtr->Stats.XmitFrames++; /* Test loop exit condition */ if (--PacketsLeft == 0) { break; } /* Next BD will mark the beginning of a new packet */ PacketStart = 1; } /* Get the next buffer descriptor in the list */ Result = XDmaChannel_GetDescriptor(&InstancePtr->SendChannel, &BdPtr); } /* while */ /* * Check for error that occurred inside the while loop, and break * out of the for loop if there was one so other interrupts can * be serviced. */ if (Result == XST_SUCCESS) { /* * Make the callback to the upper layers, passing it the first * descriptor in the first packet and the number of descriptors * in the list. */ InstancePtr->SgSendHandler(InstancePtr->SgSendRef, BdHeadPtr, NumBds); } } /* if (PacketsLeft) */ /* * If the interrupt was an end-ack, check the descriptor list again to * see if it is empty. If not, go ahead and restart the scatter-gather * channel. This is to fix a possible race condition where, on transmit, * the driver attempted to start a scatter-gather channel that was * already started, which resulted in no action from the XDmaChannel * component. But, just after the XDmaChannel component saw that the * hardware was already started, the hardware stopped because it * reached the end of the list. In that case, this interrupt is * generated and we can restart the hardware here. */ if ((IntrStatus & XDC_IXR_SG_END_MASK) && ((InstancePtr->SendChannel).ActivePacketCount > 0) && ((InstancePtr->SendChannel).Committed == XTRUE)) { /* * Ignore the return status since we know the list exists and we * don't care if the list is empty or the channel is already started. */ (void)XDmaChannel_SgStart(&InstancePtr->SendChannel); (InstancePtr->SendChannel).Committed = XFALSE; } } /* * All interrupts are handled (except the error below) so acknowledge * (clear) the interrupts by writing the value read above back to the status * register. The packet count interrupt must be acknowledged after the * decrement, otherwise it will come right back. We clear the interrupts * before we handle the error interrupt because the ErrorHandler should * result in a reset, which clears the interrupt status register. So we * don't want to toggle the interrupt back on by writing the interrupt * status register with an old value after a reset. */ XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus); /* * Check for DMA errors and call the error callback function if an error * occurred (DMA bus or timeout error), which should result in a reset of * the device by the upper layer software. */ if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { InstancePtr->Stats.DmaErrors++; InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); }}/*****************************************************************************//*** Handle an interrupt from the Ethernet MAC when configured with scatter-gather* DMA. The only interrupts handled in this case are errors.** @param InstancePtr is a pointer to the XEmac instance to be worked on.** @return** None.** @note** None.*******************************************************************************/static void HandleEmacDmaIntr(XEmac *InstancePtr){ Xuint32 IntrStatus; /* * When configured with DMA, the EMAC generates interrupts only when errors * occur. We clear the interrupts immediately so that any latched status * interrupt bits will reflect the true status of the device, and so any * pulsed interrupts (non-status) generated during the Isr will not be lost. */ IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus); /* * Check the MAC for errors */ XEmac_CheckEmacError(InstancePtr, IntrStatus);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -