📄 xemac_polled.c
字号:
* Overrun errors */ if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | XEM_EIR_XMIT_LFIFO_OVER_MASK)) { InstancePtr->Stats.XmitOverrunErrors++; InstancePtr->Stats.FifoErrors++; return XST_FIFO_ERROR; } /* * Underrun errors */ if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { InstancePtr->Stats.XmitUnderrunErrors++; InstancePtr->Stats.FifoErrors++; return XST_FIFO_ERROR; } /* * Clear the interrupt status register of transmit statuses */ XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus & XEM_EIR_XMIT_ALL_MASK); /* * Collision errors are stored in the transmit status register * instead of the interrupt status register */ if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) { InstancePtr->Stats.XmitExcessDeferral++; return XST_EMAC_COLLISION_ERROR; } if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) { InstancePtr->Stats.XmitLateCollisionErrors++; return XST_EMAC_COLLISION_ERROR; } return XST_SUCCESS;}/*****************************************************************************//**** Receive an Ethernet frame in polled mode. The device/driver must be in polled* mode before calling this function. The driver receives the frame directly* from the MAC's packet FIFO. This is a non-blocking receive, in that if there* is no frame ready to be received at the device, the function returns with an* error. The MAC's error status is not checked, so statistics are not updated* for polled receive. The buffer into which the frame will be received must be* word-aligned.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param BufPtr is a pointer to a word-aligned buffer into which the received* Ethernet frame will be copied.* @param ByteCountPtr is both an input and an output parameter. It is a pointer* to a 32-bit word that contains the size of the buffer on entry into the* function and the size the received frame on return from the function.** @return** - XST_SUCCESS if the frame was sent successfully* - XST_DEVICE_IS_STOPPED if the device has not yet been started* - XST_NOT_POLLED if the device is not in polled mode* - XST_NO_DATA if there is no frame to be received from the FIFO* - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for* the frame waiting in the FIFO.** @note** Input buffer must be big enough to hold the largest Ethernet frame. Buffer* must also be 32-bit aligned.** @internal** The EMAC uses FIFOs behind its length and status registers. For this reason,* it is important to keep the length, status, and data FIFOs in sync when* reading or writing to them.*******************************************************************************/XStatusXEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr){ XStatus Result; u32 PktLength; u32 IntrStatus; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(BufPtr != NULL); XASSERT_NONVOID(ByteCountPtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* * Be sure the device is configured for polled mode and it is started */ if (!InstancePtr->IsPolled) { return XST_NOT_POLLED; } if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return XST_DEVICE_IS_STOPPED; } /* * Make sure the buffer is big enough to hold the maximum frame size. * We need to do this because as soon as we read the MAC's packet length * register, which is actually a FIFO, we remove that length from the * FIFO. We do not want to read the length FIFO without also reading the * data FIFO since this would get the FIFOs out of sync. So we have to * make this restriction. */ if (*ByteCountPtr < XEM_MAX_FRAME_SIZE) { return XST_BUFFER_TOO_SMALL; } /* * First check for packet FIFO deadlock and return an error if it has * occurred. A reset by the caller is necessary to correct this problem. */ if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) { InstancePtr->Stats.FifoErrors++; return XST_FIFO_ERROR; } /* * Get the interrupt status to know what happened (whether an error occurred * and/or whether frames have been received successfully). When clearing the * intr status register, clear only statuses that pertain to receive. */ IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus & XEM_EIR_RECV_ALL_MASK); /* * Check receive errors and bump statistics so the caller will have a clue * as to why data may not have been received. We continue on if an error * occurred since there still may be frames that were received successfully. */ if (IntrStatus & (XEM_EIR_RECV_LFIFO_OVER_MASK | XEM_EIR_RECV_DFIFO_OVER_MASK)) { InstancePtr->Stats.RecvOverrunErrors++; InstancePtr->Stats.FifoErrors++; } if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) { InstancePtr->Stats.RecvUnderrunErrors++; InstancePtr->Stats.FifoErrors++; } /* * General receive errors */ if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) { if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) { InstancePtr->Stats.RecvMissedFrameErrors = XIo_In32(InstancePtr->BaseAddress + XEM_RMFC_OFFSET); } if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) { InstancePtr->Stats.RecvCollisionErrors = XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET); } if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) { InstancePtr->Stats.RecvFcsErrors = XIo_In32(InstancePtr->BaseAddress + XEM_RFCSEC_OFFSET); } if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) { InstancePtr->Stats.RecvLengthFieldErrors++; } if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) { InstancePtr->Stats.RecvShortErrors++; } if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) { InstancePtr->Stats.RecvLongErrors++; } if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) { InstancePtr->Stats.RecvAlignmentErrors = XIo_In32(InstancePtr->BaseAddress + XEM_RAEC_OFFSET); } } /* * Before reading from the length FIFO, make sure the length FIFO is not * empty. We could cause an underrun error if we try to read from an * empty FIFO. */ if ((IntrStatus & XEM_EIR_RECV_DONE_MASK) == 0) { return XST_NO_DATA; } /* * Determine, from the MAC, the length of the next packet available * in the data FIFO (there should be a non-zero length here) */ PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET); if (PktLength == 0) { return XST_NO_DATA; } /* * Write the RECV_DONE bit in the status register to clear it. This bit * indicates the RPLR is non-empty, and we know it's set at this point. * We clear it so that subsequent entry into this routine will reflect the * current status. This is done because the non-empty bit is latched in the * IPIF, which means it may indicate a non-empty condition even though * there is something in the FIFO. */ XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK); /* * We assume that the MAC never has a length bigger than the largest * Ethernet frame, so no need to make another check here. */ /* * This is a non-blocking read. The FIFO returns an error if there is * not at least the requested amount of data in the FIFO. */ Result = XPacketFifoV100b_Read(&InstancePtr->RecvFifo, BufPtr, PktLength); if (Result != XST_SUCCESS) { return Result; } InstancePtr->Stats.RecvFrames++; InstancePtr->Stats.RecvBytes += PktLength; *ByteCountPtr = PktLength; return XST_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -