📄 xtemac_fifo.c
字号:
/* $Id: *//******************************************************************************** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS* FOR A PARTICULAR PURPOSE.** (c) Copyright 2005-2006 Xilinx Inc.* All rights reserved.* This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License as published by the* Free Software Foundation; either version 2 of the License, or (at your* option) any later version.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************//*****************************************************************************//**** @file xtemac_fifo.c** Functions in this file implement FIFO direct and Simple DMA frame transfer* mode. See xtemac.h for a detailed description of the driver.** <pre>* MODIFICATION HISTORY:** Ver Who Date Changes* ----- ---- -------- -------------------------------------------------------* 1.00a rmm 06/01/05 First release* 1.00b rmm 09/23/05 Fixed void* arithmetic usage, added XST_FIFO_ERROR* return code to send/recv query functions.* 2.00a rmm 11/21/05 Removed XST_FAILURE return code for XTemac_FifoQuery-* SendStatus, removed simple dma code* rmm 06/22/06 Fixed C++ compiler warnings* </pre>******************************************************************************//***************************** Include Files *********************************/#include "xtemac.h"#include "xtemac_i.h"#include "xio.h"/************************** Constant Definitions *****************************/#define PFIFO_64BIT_WIDTH_BYTES 8/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//******************************************************************************* * Primitives that modify the hold structure for XTemac_PacketFifo. All F * parameters refer to a pointer to XTemac_PacketFifo. * * mHold_GetIndex(F) - Get the ByteIndex of Hold * mHold_SetIndex(F,D) - Set the ByteIndex of Hold to D * mHold_Advance(F,D) - Advance the ByteIndex of Hold by D bytes * mHold_CopyIn(F,I,D) - Set Hold[I] to D * mHold_CopyOut(F,I,D) - Set D to Hold[I] * mHoldS_IsFull(F) - Is a write channel Hold full of data * mHoldS_IsEmpty(F) - Is a write channel Hold empty * mHoldS_SetEmpty(F) - Set a write channel Hold empty * mHoldR_IsFull(F) - Is a read channel Hold full of data * mHoldR_IsEmpty(F) - Is a read channel Hold empty * mHoldR_SetEmpty(F) - Set a read channel Hold empty * * @param F - Address to a XTemac_PacketFifo structure * @param SrcPtr - Source data address aligned on 4 byte boundary * ******************************************************************************/#define mHold_GetIndex(F) ((F)->ByteIndex)#define mHold_SetIndex(F, D) ((F)->ByteIndex = (D))#define mHold_Advance(F, D) ((F)->ByteIndex += (D))#define mHold_CopyIn(F, I, D) (*(u8*)(((u8*)(&(F)->Hold[0])) + (I)) = (D))#define mHold_CopyOut(F, I, D) ((D) = (*(u8*)(((u8*)(&(F)->Hold[0])) + (I))))#define mHoldS_IsFull(F) ((F)->ByteIndex >= (F)->Width)#define mHoldS_IsEmpty(F) ((F)->ByteIndex == 0)#define mHoldS_SetEmpty(F) ((F)->ByteIndex = 0)#define mHoldR_IsFull(F) ((F)->ByteIndex == 0)#define mHoldR_IsEmpty(F) ((F)->ByteIndex >= (F)->Width)#define mHoldR_SetEmpty(F) ((F)->ByteIndex = (F)->Width)/******************************************************************************* * Primitive write to 64 bit FIFO. Use two 32-bit wide I/O accesses. * * @param F - Address to a XTemac_PacketFifo structure * @param SrcPtr - Source data address aligned on 4 byte boundary * ******************************************************************************/#define mWriteFifo64(F, SrcPtr) \ { \ register u32 Faddr = F->Fifo.DataBaseAddress; \ XIo_Out32(Faddr, (SrcPtr)[0]); \ XIo_Out32(Faddr + 4, (SrcPtr)[1]); \ }/******************************************************************************* * Primitive read from 64 bit FIFO. Use two 32-bit wide I/O accesses. * * @param F - Address to a XTemac_PacketFifo structure * @param DestPtr - Destination data address aligned on 4 byte boundary * ******************************************************************************/#define mReadFifo64(F, DestPtr) \ (DestPtr)[0] = XIo_In32(F->Fifo.DataBaseAddress); \ (DestPtr)[1] = XIo_In32(F->Fifo.DataBaseAddress + 4);/******************************************************************************* * Primitive to transfer the holding data to the FIFO 64 bits at a time * * @param F - Address to a XTemac_PacketFifo structure * ******************************************************************************/#define mPush64(F) mWriteFifo64(F, &F->Hold[0])/******************************************************************************* * Primitive to tranfer FIFO contents into the holding data 64 bits at a time * * @param F - Address to a XTemac_PacketFifo structure * ******************************************************************************/#define mPop64(F) mReadFifo64(F, &F->Hold[0])/************************** Function Prototypes ******************************//* The following functions will be attached to the FifoRead and FifoWrite * attribute of an instance by XTemac_ConfigureFifoAccess */static XStatus Write_64(XTemac_PacketFifo *Fptr, void *BufPtr, u32 ByteCount, int Eop);static XStatus Read_64(XTemac_PacketFifo *Fptr, void *BufPtr, u32 ByteCount, int Eop);/* 64 bit wide FIFO support functions */static void Write64_Unaligned(XTemac_PacketFifo *F, void *BufPtr, u32 ByteCount);static void Write64_Aligned(XTemac_PacketFifo *F, u32 *BufPtr, u32 ByteCount);static void Read64_Unaligned(XTemac_PacketFifo *F, void *BufPtr, u32 ByteCount);static void Read64_Aligned(XTemac_PacketFifo *F, u32 *BufPtr, u32 ByteCount);/******************************************************************************* * Select the best method for accessing the read and write FIFOs for FIFO direct * frame transfer mode. On the write (transmit) side, the choices are DRE or via * the holding structure. Both methods allow unaligned transfers. On the read * (receive) side, the only choice is the holding structure. * * This function should be called only from XTemac_Initialize(). * * @param InstancePtr is a pointer to the instance to be worked on. * * @return XST_SUCCESS or XST_FAILURE if an error was detected * ******************************************************************************/XStatus XTemac_ConfigureFifoAccess(XTemac *InstancePtr){ XStatus Result; /* Initialize the packet FIFOs */ Result = XPacketFifoV200a_Initialize(&InstancePtr->RecvFifo.Fifo, InstancePtr->BaseAddress + XTE_PFIFO_RXREG_OFFSET, InstancePtr->BaseAddress + XTE_PFIFO_RXDATA_OFFSET); if (Result != XST_SUCCESS) { return(XST_FAILURE); } Result = XPacketFifoV200a_Initialize(&InstancePtr->SendFifo.Fifo, InstancePtr->BaseAddress + XTE_PFIFO_TXREG_OFFSET, InstancePtr->BaseAddress + XTE_PFIFO_TXDATA_OFFSET); if (Result != XST_SUCCESS) { return(XST_FAILURE); } /* Choose an access algorithm. * Note: 64-bit wide FIFO is the only width supported at this time */ InstancePtr->RecvFifo.Width = PFIFO_64BIT_WIDTH_BYTES; InstancePtr->RecvFifo.XferFn = Read_64; InstancePtr->SendFifo.Width = PFIFO_64BIT_WIDTH_BYTES; InstancePtr->SendFifo.XferFn = Write_64; /* Initialize the holds */ mHoldS_SetEmpty(&InstancePtr->SendFifo); mHoldR_SetEmpty(&InstancePtr->RecvFifo); return(XST_SUCCESS);}/******************************************************************************//** * Copy data from a user buffer to the transmit packet FIFO. The data copied * may comprise of single, multiple, or partial packets. The data is not * transmitted until XTemac_FifoSend() is called. * * If the user buffer contains multiple packets, then extra care must be taken. * In this special situation, the end of one packet and the beginning of a new * packet is specified within the user buffer. The beginning of each NEW packet * must begin on a 4 byte alignment. The user is responsible for adding filler * data between packets to acheive this alignment. The amount of filler data * depends on what byte the end of the previous packet falls on. When calling * XTemac_FifoSend() to transmit the packets, DO NOT specify the filler bytes * in the TxByteCount parameter. For example, if a user buffer contains two * complete packets of 15 bytes each with 1 byte of filler between them, then * XTemac_FifoWrite() is called once to write all 31 bytes to the FIFO. * XTemac_FifoSend() is called twice specifying 15 bytes each time to transmit * the packets (the 1 byte of filler data is ignored by the TEMAC). Of course * you could also just call XTemac_FifoWrite() once for each packet. This way, * the driver will manage the filler data. * * 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 buffer containing user data that will be transferred * into the transmit FIFO. The buffer may be on any alignment. * @param ByteCount is the number of bytes to transfer from 1 to the number * of bytes available in the FIFO at the time of invocation. See usage * note for situations when a value of 0 is legal. * @param Eop specifies whether the last byte of BufPtr marks the End Of Packet. * If set to XTE_END_OF_PACKET, then any partial bytes being buffered by * the driver are flushed into the packet FIFO. If set to * XTE_PARTIAL_PACKET, then more packet data is expected to be written * through more calls to this function. Failure to use XTE_END_OF_PACKET * prior to calling XTemac_FifoSend() may cause a packet FIFO underrun. * * @return * - XST_SUCCESS if the data was transferred to the FIFO. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_PFIFO_ERROR if there was a packet FIFO overflow during the transfer. * This is a fatal condition. If this value is returned in polled mode, then * the device must be reset. For interrupt driven modes, an interrupt will be * asserted resulting in a call to the registered error handler which should * handle reset of the device. * - XST_IPIF_ERROR if a data or bus error occurred within the TEMAC's IPIF. * Like the PFIFO error, this is a fatal condition and should be handled * in the same manner. * * @note * Calling this function with ByteCount = 0 will not result in the transfer of * data from BufPtr to the FIFO. However, if at the same time Eop is set to * XTE_END_OF_PACKET, then all data previously written with this function is * guaranteed to be flushed into the packet FIFO and available for transmission * with XTemac_FifoSend(). ******************************************************************************/XStatus XTemac_FifoWrite(XTemac *InstancePtr, void *BufPtr, u32 ByteCount, int Eop){ u32 RegDISR; 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 */ InstancePtr->SendFifo.XferFn(&InstancePtr->SendFifo, BufPtr, ByteCount, Eop); /* Make sure the packet FIFO didn't report an error */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); if (RegDISR & XTE_DXR_SEND_FIFO_MASK) { /* Only bump stats in polled mode. For interrupt driven mode, this stat * is bumped in XTemac_IntrFifoHandler() */ if (InstancePtr->Options & XTE_POLLED_OPTION) { XTemac_mBumpStats(TxPktFifoErrors, 1); } return(XST_PFIFO_ERROR); } /* Verify no IPIF errors */ if (RegDISR & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK)) { /* Only bump stats in polled mode. For interrupt driven mode, this stat * is bumped in XTemac_IntrFifoHandler() */ if (InstancePtr->Options & XTE_POLLED_OPTION) { XTemac_mBumpStats(IpifErrors, 1); } return(XST_IPIF_ERROR); } return(XST_SUCCESS);}/******************************************************************************//** * Initiate a transmit of one packet of data previously written with * XTemac_FifoWrite(). The given length in bytes is written to the transmit * length FIFO. There should be at least this many bytes in the packet FIFO * ready for transmit. * * If FIFO interrupts are enabled (see XTemac_IntrFifoEnable()), then upon * completion of the transmit, the registered XTemac_FifoSendHandler() is * invoked. * * If more bytes that are in the packet FIFO are specified in the TxByteCount * parameter, then a packet FIFO underrun error will result. * * @param InstancePtr is a pointer to the instance to be worked on. * @param TxByteCount is the number of bytes to transmit. Range is 1 to the * total number of bytes available in the packet FIFO to be transmitted. * * @return * - XST_SUCCESS if transmit was initiated. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_FIFO_NO_ROOM if the transmit was not initiated because the transmit * length FIFO was full. This is not a fatal condition. The user may need to * wait for other packets to transmit before this condition clears itself. * ******************************************************************************/XStatus XTemac_FifoSend(XTemac *InstancePtr, u32 TxByteCount){ u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(TxByteCount != 0); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return(XST_DEVICE_IS_STOPPED); } /* See if transmit length FIFO is full. If it is, try to clear the * status. If it the status remains, then return an error */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_XMIT_LFIFO_FULL_MASK); RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { XTemac_mBumpStats(FifoErrors, 1); return(XST_FIFO_NO_ROOM); } } /* Start transmit */ XTemac_mSetIpifReg(XTE_TPLR_OFFSET, TxByteCount); /* Return sucess */ return(XST_SUCCESS);}/******************************************************************************//** * Return the length of a received packet. If a packet is waiting in the * receive packet FIFO, then it may be copied to a user buffer with * XTemac_FifoRead(). * * @param InstancePtr is a pointer to the instance to be worked on. * @param ByteCountPtr is the length of the next received packet if the return * status is XST_SUCCESS. * * @return * - XST_SUCCESS if a packet has been received and a value has been written to * ByteCountPtr. * - XST_DEVICE_IS_STOPPED if the device has been stopped. * - XST_NO_DATA if no packet length is available. ByteCountPtr is not modified. * ******************************************************************************/XStatus XTemac_FifoRecv(XTemac *InstancePtr, u32 *ByteCountPtr){ u32 RegIPISR; volatile u32 RegRSR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(ByteCountPtr != NULL); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -