xemac_polled.c
来自「适合KS8695X」· C语言 代码 · 共 483 行 · 第 1/2 页
C
483 行
* 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.
*
******************************************************************************/
XStatus
XEmac_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 + =
减小字号Ctrl + -
显示快捷键?