📄 xtemac_fifo.c
字号:
return(XST_DEVICE_IS_STOPPED); } /* If the receive length FIFO is empty, then there's no packet waiting */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (!(RegIPISR & XTE_IPXR_RECV_DONE_MASK)) { return(XST_NO_DATA); } /* Get the length */ *ByteCountPtr = XTemac_mGetIpifReg(XTE_RPLR_OFFSET); /* The IPXR_RECV_DONE_MASK status bit is tied to the RSR register. To clear * this condition, read from the RSR (which has no information) then write * to the IPISR register to ack the status. */ RegRSR = XTemac_mGetIpifReg(XTE_RSR_OFFSET); XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_RECV_DONE_MASK); /* Return sucess */ return(XST_SUCCESS);}/******************************************************************************//** * Copy data from the receive packet FIFO into a user buffer. The number of * bytes to copy is derived from XTemac_FifoRecv(). The packet data may be * copied out of the FIFO all at once or with multiple calls to this function. * The latter method supports systems that keep packet data in non-contiguous * memory regions. For example: * <pre> * if (XTemac_FifoRecv(Tptr, &PacketLength) == XST_SUCCESS) * { * if (PacketLength > 14) * { * HeaderLength = 14; * PayloadLength = PacketLength - HeaderLength; * * Status = XTemac_FifoRead(Tptr, UserHeaderBuf, HeaderLength, * XTE_PARTIAL_PACKET); * Status |= XTemac_FifoRead(Tptr, UserPayloadBuf, PayloadLength, * XTE_END_OF_PACKET); * * if (Status != XST_SUCCESS) * { * // handle error * } * } * } * </pre> * * If the user's buffer is not aligned on a 4 byte boundary, then the transfer * may take longer to complete. * * @param InstancePtr is a pointer to the instance to be worked on. * @param BufPtr is the user buffer that will recieve packet data from the FIFO. * The buffer may be on any alignment. * @param ByteCount is the number of bytes to transfer * @param Eop specifies whether the last byte read is the last byte of a packet. * If set to XTE_END_OF_PACKET, then any partial bytes being buffered by * the driver at the end of the transfer are discarded. These discarded * bytes are filler provided by the hardware and have no meaning. If set * to XTE_PARTIAL_PACKET, then more packet data is expected to be read * through more calls to this function. Failure to use this parameter * properly will result in undefined filler bytes being copied into * BufPtr. * * @return * - XST_SUCCESS if the data was transferred to the user buffer * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_NO_DATA if there was not enough data in the packet FIFO to satisfy the * request. * * @note * Do not attempt to read more than one packets worth of data at a time with * this function. ******************************************************************************/XStatus XTemac_FifoRead(XTemac *InstancePtr, void *BufPtr, u32 ByteCount, int Eop){ XStatus Status; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(!((Eop != XTE_END_OF_PACKET) && (Eop != XTE_PARTIAL_PACKET))); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return(XST_DEVICE_IS_STOPPED); } /* Transfer the data using the best/fastest method */ Status = InstancePtr->RecvFifo.XferFn(&InstancePtr->RecvFifo, BufPtr, ByteCount, Eop); /* Return correct status */ if (Status == XST_NO_DATA) { return(XST_NO_DATA); } else { return(XST_SUCCESS); }}/******************************************************************************//** * Retrieve the number of free bytes in the packet FIFOs. * * For the transmit packet FIFO, the number returned is the number of bytes * that can be written by XTemac_FifoWrite(). If a non-zero number is returned, * then at least 1 packet of that size can be transmitted. * * For the receive packet FIFO, the number returned is the number of bytes that * can arrive from an external Ethernet device. This number does not reflect * the state of the receive length FIFO. If this FIFO is full, then arriving * packets will get dropped by the HW if there is no place to store the length. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction selects which packet FIFO to examine. If XTE_SEND, then * the transmit packet FIFO is selected. If XTE_RECV, then the receive * packet FIFO is selected. * * @return * Number of bytes available in the selected packet FIFO. * ******************************************************************************/u32 XTemac_FifoGetFreeBytes(XTemac *InstancePtr, u32 Direction){ u32 RegIPISR; u32 Count; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(!(Direction & ~(XTE_SEND | XTE_RECV))); /* For the send direction, even though there may be room in the * packet FIFO, the length FIFO may be full. When this is the case, * another packet cannot be transmiited so return 0. */ if (Direction == XTE_SEND) { /* Check length FIFO */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { return(0); } /* Get FIFO entries */ Count = XPF_V200A_GET_COUNT(&InstancePtr->SendFifo.Fifo); } /* Handle receive direction */ else { Count = XPF_V200A_COUNT_MASK - XPF_V200A_GET_COUNT(&InstancePtr->RecvFifo.Fifo); } /* Multiply free entries by the width of the packet FIFO to arrive at * bytes */ return(Count * InstancePtr->RecvFifo.Width);}/******************************************************************************//** * Query the device for the latest transmit status for FIFO direct frame * transfer mode. This function should be used for polled mode operation only. * * @param InstancePtr is a pointer to the instance to be worked on. * @param SendStatusPtr is the contents of the XTE_TSR_OFFSET register when the * return code is XST_FAILURE. Otherwise 0 is returned. * * @return * - XST_NO_DATA if a transmit status is not currently available. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_NOT_POLLED if the device has not been set to polled mode. * - XST_SUCCESS if a transmit status was found and indicates that there was * no error. * - XST_FIFO_ERROR if the transmit length or transmit status FIFOs error has * been detected. If this error is returned, then the device must be reset * before this function will return a valid transmit status indication. * - XST_PFIFO_ERROR if the transmit packet FIFO is deadlocked. If this error * is returned, then the device must be reset before this function will * return a valid transmit status indication * - XST_IPIF_ERROR if there has been a data phase timeout or transaction error * in the IPIF. This is a fatal error. * * @note * When XST_FAILURE is returned with the XTE_TSR_PFIFOU_MASK bit set in the * SendStatusPtr parameter, then an attempt was made to transmit more data than * was present in the packet FIFO. No reset is required in this situation. * ******************************************************************************/XStatus XTemac_FifoQuerySendStatus(XTemac *InstancePtr, u32 *SendStatusPtr){ u32 RegDISR; u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(SendStatusPtr != NULL); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return(XST_DEVICE_IS_STOPPED); } /* Have to be in polled mode to use this function */ if (!(InstancePtr->Options & XTE_POLLED_OPTION)) { return(XST_NOT_POLLED); } /* Make sure send packet FIFO isn't deadlocked */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); if (RegDISR & XTE_DXR_SEND_FIFO_MASK) { XTemac_mBumpStats(TxPktFifoErrors, 1); return(XST_PFIFO_ERROR); } /* Make sure no IPIF errors are present */ if (RegDISR & (XTE_DXR_TERR_MASK | XTE_DXR_DPTO_MASK)) { XTemac_mBumpStats(IpifErrors, 1); return(XST_IPIF_ERROR); } /* Read the IPISR * If any errors are detetected, try to clear and return error */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_ERROR_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_XMIT_ERROR_MASK); XTemac_mBumpStats(FifoErrors, 1); return(XST_FIFO_ERROR); } /* No FIFO errors, so see of a transmit has completed */ if (!(RegIPISR & XTE_IPXR_XMIT_DONE_MASK)) { return(XST_NO_DATA); } /* Transmit has completed, get the status, ack the condition */ *SendStatusPtr = XTemac_mGetIpifReg(XTE_TSR_OFFSET); XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_XMIT_DONE_MASK); /* no errors to report */ return(XST_SUCCESS);}/******************************************************************************//** * Query the device for the latest receive status for FIFO direct frame * transfer mode. This function should be used for polled mode operation only. * * @param InstancePtr is a pointer to the instance to be worked on. * * @return * - XST_SUCCESS if a frame has been received and no receive error was detected. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_NO_DATA if no frame has been received and no receive related error has * been detected. * - XST_NOT_POLLED if the device has not been set to polled mode. * - XST_DATA_LOST if the device reports that it dropped a receive frame. This * is not a serious problem but may indicate that frames are arriving faster * than the system can process them. * - XST_FIFO_ERROR if an error was detected with the receive length FIFO. If * this error is returned, then the device must be reset before any new frame * can be received. * - XST_PFIFO_ERROR if the receive packet FIFO is deadlocked. If this error is * returned, then the device must be reset before any new frame can be * received. * - XST_IPIF_ERROR if there has been a data phase timeout or transaction error * in the IPIF. This is a fatal error. * * @note * In situations where simultaneously a frame has been received for which an * XST_SUCCESS can be returned and a dropped frame for which an XST_DATA_LOST * can be returned, then this function will give priority to XST_SUCCESS so the * user can receive the frame. ******************************************************************************/XStatus XTemac_FifoQueryRecvStatus(XTemac *InstancePtr){ u32 RegDISR; u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return(XST_DEVICE_IS_STOPPED); } /* Have to be in polled mode to use this function */ if (!(InstancePtr->Options & XTE_POLLED_OPTION)) { return(XST_NOT_POLLED); } /* Read the DISR */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); /* Make sure recv packet FIFO isn't deadlocked */ if (RegDISR & XTE_DXR_RECV_FIFO_MASK) { XTemac_mBumpStats(RxPktFifoErrors, 1); return(XST_PFIFO_ERROR); } /* Make sure no IPIF errors are present */ if (RegDISR & (XTE_DXR_TERR_MASK | XTE_DXR_DPTO_MASK)) { XTemac_mBumpStats(IpifErrors, 1); return(XST_IPIF_ERROR); } /* Read the IPISR */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); /* Check for other recv related FIFO errors */ if (RegIPISR & (XTE_IPXR_RECV_ERROR_MASK - XTE_IPXR_RECV_DROPPED_MASK)) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_RECV_ERROR_MASK); XTemac_mBumpStats(FifoErrors, 1); return(XST_FIFO_ERROR); } /* See if a frame has been received */ if (RegIPISR & XTE_IPXR_RECV_DONE_MASK) { return(XST_SUCCESS); } /* If option to detect recv reject errors is set, check for rejected * receive frames. If one is detected, clear it and return error. */ if (InstancePtr->Options & XTE_REPORT_RXERR_OPTION) { if (RegIPISR & XTE_IPXR_RECV_DROPPED_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_RECV_DROPPED_MASK); return(XST_DATA_LOST); } } /* No frame has been received and no errors detected */ return(XST_NO_DATA);}/******************************************************************************** Algorithm to write to a 64 bit wide transmit packet FIFO through the holding* buffer.** @param FPtr is a pointer to a Temac FIFO instance to worked on.* @param BufPtr is the source buffer address on any alignment* @param ByteCount is the number of bytes to transfer* @param Eop specifies whether the last byte written is the last byte of the* packet.** @return XST_SUCCESS*******************************************************************************/static XStatus Write_64(XTemac_PacketFifo *Fptr, void *BufPtr, u32 ByteCount, int Eop){ unsigned BufAlignment = (unsigned)BufPtr & 3; unsigned PartialBytes; unsigned HoldAlignment = mHold_GetIndex(Fptr); /* Case 1: Buffer aligned on 4-byte boundary and Hold is empty * * 1. Write all bytes using the fastest transfer method */ if ((BufAlignment == 0) && (mHoldS_IsEmpty(Fptr))) { Write64_Aligned(Fptr, (u32*)BufPtr, ByteCount); } /* Case 2: Buffer and Hold are byte aligned with each other * * 1. Transfer enough bytes from the buffer to the Hold to trigger a flush * to the FIFO. * * 2. The state of the buffer and Hold are as described by Case 1 so * write remaining bytes using the fastest transfer method */ else if (BufAlignment == (HoldAlignment % PFIFO_64BIT_WIDTH_BYTES)) { PartialBytes = PFIFO_64BIT_WIDTH_BYTES - HoldAlignment; if (ByteCount < PartialBytes) { PartialBytes = ByteCount; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -