| /****************************************************************************** |
| * |
| * Author: Xilinx, Inc. |
| * |
| * |
| * 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. |
| * |
| * |
| * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A |
| * COURTESY TO YOU. 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 THIRD PARTY 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. |
| * |
| * |
| * Xilinx hardware products are not intended for use in life support |
| * appliances, devices, or systems. Use in such applications is |
| * expressly prohibited. |
| * |
| * |
| * (c) Copyright 2002-2004 Xilinx Inc. |
| * All rights reserved. |
| * |
| * |
| * 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., |
| * 675 Mass Ave, Cambridge, MA 02139, USA. |
| * |
| ******************************************************************************/ |
| /*****************************************************************************/ |
| /* |
| * |
| * @file xpacket_fifo_v1_00_b.c |
| * |
| * Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h |
| * for more information about the component. |
| * |
| * <pre> |
| * MODIFICATION HISTORY: |
| * |
| * Ver Who Date Changes |
| * ----- ---- -------- ----------------------------------------------- |
| * 1.00b rpm 03/26/02 First release |
| * </pre> |
| * |
| *****************************************************************************/ |
| |
| /***************************** Include Files *********************************/ |
| |
| #include "xbasic_types.h" |
| #include "xio.h" |
| #include "xstatus.h" |
| #include "xpacket_fifo_v1_00_b.h" |
| |
| /************************** Constant Definitions *****************************/ |
| |
| /* width of a FIFO word */ |
| |
| #define XPF_FIFO_WIDTH_BYTE_COUNT 4UL |
| |
| /**************************** Type Definitions *******************************/ |
| |
| /***************** Macros (Inline Functions) Definitions *********************/ |
| |
| /************************* Variable Definitions ******************************/ |
| |
| /************************** Function Prototypes ******************************/ |
| |
| /*****************************************************************************/ |
| /* |
| * |
| * This function initializes a packet FIFO. Initialization resets the |
| * FIFO such that it's empty and ready to use. |
| * |
| * @param InstancePtr contains a pointer to the FIFO to operate on. |
| * @param RegBaseAddress contains the base address of the registers for |
| * the packet FIFO. |
| * @param DataBaseAddress contains the base address of the data for |
| * the packet FIFO. |
| * |
| * @return |
| * |
| * Always returns XST_SUCCESS. |
| * |
| * @note |
| * |
| * None. |
| * |
| ******************************************************************************/ |
| XStatus |
| XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr, |
| u32 RegBaseAddress, u32 DataBaseAddress) |
| { |
| /* assert to verify input argument are valid */ |
| |
| XASSERT_NONVOID(InstancePtr != NULL); |
| |
| /* initialize the component variables to the specified state */ |
| |
| InstancePtr->RegBaseAddress = RegBaseAddress; |
| InstancePtr->DataBaseAddress = DataBaseAddress; |
| InstancePtr->IsReady = XCOMPONENT_IS_READY; |
| |
| /* reset the FIFO such that it's empty and ready to use and indicate the |
| * initialization was successful, note that the is ready variable must be |
| * set prior to calling the reset function to prevent an assert |
| */ |
| XPF_V100B_RESET(InstancePtr); |
| |
| return XST_SUCCESS; |
| } |
| |
| /*****************************************************************************/ |
| /* |
| * |
| * This function performs a self-test on the specified packet FIFO. The self |
| * test resets the FIFO and reads a register to determine if it is the correct |
| * reset value. This test is destructive in that any data in the FIFO will |
| * be lost. |
| * |
| * @param InstancePtr is a pointer to the packet FIFO to be operated on. |
| * |
| * @param FifoType specifies the type of FIFO, read or write, for the self test. |
| * The FIFO type is specified by the values XPF_READ_FIFO_TYPE or |
| * XPF_WRITE_FIFO_TYPE. |
| * |
| * @return |
| * |
| * XST_SUCCESS is returned if the selftest is successful, or |
| * XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the |
| * occupancy/vacancy count register after a reset does not match the |
| * specified reset value. |
| * |
| * @note |
| * |
| * None. |
| * |
| ******************************************************************************/ |
| XStatus |
| XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType) |
| { |
| u32 Register; |
| |
| /* assert to verify valid input arguments */ |
| |
| XASSERT_NONVOID(InstancePtr != NULL); |
| XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) || |
| (FifoType == XPF_WRITE_FIFO_TYPE)); |
| XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); |
| |
| /* reset the fifo and then check to make sure the occupancy/vacancy |
| * register contents are correct for a reset condition |
| */ |
| XPF_V100B_RESET(InstancePtr); |
| |
| Register = XIo_In32(InstancePtr->RegBaseAddress + |
| XPF_COUNT_STATUS_REG_OFFSET); |
| |
| /* check the value of the register to ensure that it's correct for the |
| * specified FIFO type since both FIFO types reset to empty, but a bit |
| * in the register changes definition based upon FIFO type |
| */ |
| |
| if (FifoType == XPF_READ_FIFO_TYPE) { |
| /* check the regiser value for a read FIFO which should be empty */ |
| |
| if (Register != XPF_EMPTY_FULL_MASK) { |
| return XST_PFIFO_BAD_REG_VALUE; |
| } |
| } else { |
| /* check the register value for a write FIFO which should not be full |
| * on reset |
| */ |
| if ((Register & XPF_EMPTY_FULL_MASK) != 0) { |
| return XST_PFIFO_BAD_REG_VALUE; |
| } |
| } |
| |
| /* the test was successful */ |
| |
| return XST_SUCCESS; |
| } |
| |
| /*****************************************************************************/ |
| /* |
| * |
| * Read data from a FIFO and puts it into a specified buffer. The packet FIFO is |
| * currently 32 bits wide such that an input buffer which is a series of bytes |
| * is filled from the FIFO a word at a time. If the requested byte count is not |
| * a multiple of 32 bit words, it is necessary for this function to format the |
| * remaining 32 bit word from the FIFO into a series of bytes in the buffer. |
| * There may be up to 3 extra bytes which must be extracted from the last word |
| * of the FIFO and put into the buffer. |
| * |
| * @param InstancePtr contains a pointer to the FIFO to operate on. |
| * @param BufferPtr points to the memory buffer to write the data into. This |
| * buffer must be 32 bit aligned or an alignment exception could be |
| * generated. Since this buffer is a byte buffer, the data is assumed to |
| * be endian independent. |
| * @param ByteCount contains the number of bytes to read from the FIFO. This |
| * number of bytes must be present in the FIFO or an error will be |
| * returned. |
| * |
| * @return |
| * |
| * XST_SUCCESS indicates the operation was successful. If the number of |
| * bytes specified by the byte count is not present in the FIFO |
| * XST_PFIFO_LACK_OF_DATA is returned. |
| * |
| * If the function was successful, the specified buffer is modified to contain |
| * the bytes which were removed from the FIFO. |
| * |
| * @note |
| * |
| * Note that the exact number of bytes which are present in the FIFO is |
| * not known by this function. It can only check for a number of 32 bit |
| * words such that if the byte count specified is incorrect, but is still |
| * possible based on the number of words in the FIFO, up to 3 garbage bytes |
| * may be present at the end of the buffer. |
| * <br><br> |
| * This function assumes that if the device consuming data from the FIFO is |
| * a byte device, the order of the bytes to be consumed is from the most |
| * significant byte to the least significant byte of a 32 bit word removed |
| * from the FIFO. |
| * |
| ******************************************************************************/ |
| XStatus |
| XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr, |
| u8 * BufferPtr, u32 ByteCount) |
| { |
| u32 FifoCount; |
| u32 WordCount; |
| u32 ExtraByteCount; |
| u32 *WordBuffer = (u32 *) BufferPtr; |
| |
| /* assert to verify valid input arguments including 32 bit alignment of |
| * the buffer pointer |
| */ |
| XASSERT_NONVOID(InstancePtr != NULL); |
| XASSERT_NONVOID(BufferPtr != NULL); |
| XASSERT_NONVOID(((u32) BufferPtr & |
| (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0); |
| XASSERT_NONVOID(ByteCount != 0); |
| XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); |
| |
| /* get the count of how many 32 bit words are in the FIFO, if there aren't |
| * enought words to satisfy the request, return an error |
| */ |
| |
| FifoCount = XIo_In32(InstancePtr->RegBaseAddress + |
| XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; |
| |
| if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) { |
| return XST_PFIFO_LACK_OF_DATA; |
| } |
| |
| /* calculate the number of words to read from the FIFO before the word |
| * containing the extra bytes, and calculate the number of extra bytes |
| * the extra bytes are defined as those at the end of the buffer when |
| * the buffer does not end on a 32 bit boundary |
| */ |
| WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT; |
| ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT; |
| |
| /* Read the 32 bit words from the FIFO for all the buffer except the |
| * last word which contains the extra bytes, the following code assumes |
| * that the buffer is 32 bit aligned, otherwise an alignment exception could |
| * be generated |
| */ |
| for (FifoCount = 0; FifoCount < WordCount; FifoCount++) { |
| WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress); |
| } |
| |
| /* if there are extra bytes to handle, read the last word from the FIFO |
| * and insert the extra bytes into the buffer |
| */ |
| if (ExtraByteCount > 0) { |
| u32 LastWord; |
| u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount); |
| |
| /* get the last word from the FIFO for the extra bytes */ |
| |
| LastWord = XIo_In32(InstancePtr->DataBaseAddress); |
| |
| /* one extra byte in the last word, put the byte into the next location |
| * of the buffer, bytes in a word of the FIFO are ordered from most |
| * significant byte to least |
| */ |
| if (ExtraByteCount == 1) { |
| ExtraBytesBuffer[0] = (u8) (LastWord >> 24); |
| } |
| |
| /* two extra bytes in the last word, put each byte into the next two |
| * locations of the buffer |
| */ |
| else if (ExtraByteCount == 2) { |
| ExtraBytesBuffer[0] = (u8) (LastWord >> 24); |
| ExtraBytesBuffer[1] = (u8) (LastWord >> 16); |
| } |
| /* three extra bytes in the last word, put each byte into the next three |
| * locations of the buffer |
| */ |
| else if (ExtraByteCount == 3) { |
| ExtraBytesBuffer[0] = (u8) (LastWord >> 24); |
| ExtraBytesBuffer[1] = (u8) (LastWord >> 16); |
| ExtraBytesBuffer[2] = (u8) (LastWord >> 8); |
| } |
| } |
| return XST_SUCCESS; |
| } |
| |
| /*****************************************************************************/ |
| /* |
| * |
| * Write data into a packet FIFO. The packet FIFO is currently 32 bits wide |
| * such that an input buffer which is a series of bytes must be written into the |
| * FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is |
| * necessary for this function to format the remaining bytes into a single 32 |
| * bit word to be inserted into the FIFO. This is necessary to avoid any |
| * accesses past the end of the buffer. |
| * |
| * @param InstancePtr contains a pointer to the FIFO to operate on. |
| * @param BufferPtr points to the memory buffer that data is to be read from |
| * and written into the FIFO. Since this buffer is a byte buffer, the data |
| * is assumed to be endian independent. This buffer must be 32 bit aligned |
| * or an alignment exception could be generated. |
| * @param ByteCount contains the number of bytes to read from the buffer and to |
| * write to the FIFO. |
| * |
| * @return |
| * |
| * XST_SUCCESS is returned if the operation succeeded. If there is not enough |
| * room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is |
| * returned. |
| * |
| * @note |
| * |
| * This function assumes that if the device inserting data into the FIFO is |
| * a byte device, the order of the bytes in each 32 bit word is from the most |
| * significant byte to the least significant byte. |
| * |
| ******************************************************************************/ |
| XStatus |
| XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr, |
| u8 * BufferPtr, u32 ByteCount) |
| { |
| u32 FifoCount; |
| u32 WordCount; |
| u32 ExtraByteCount; |
| u32 *WordBuffer = (u32 *) BufferPtr; |
| |
| /* assert to verify valid input arguments including 32 bit alignment of |
| * the buffer pointer |
| */ |
| XASSERT_NONVOID(InstancePtr != NULL); |
| XASSERT_NONVOID(BufferPtr != NULL); |
| XASSERT_NONVOID(((u32) BufferPtr & |
| (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0); |
| XASSERT_NONVOID(ByteCount != 0); |
| XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); |
| |
| /* get the count of how many words may be inserted into the FIFO */ |
| |
| FifoCount = XIo_In32(InstancePtr->RegBaseAddress + |
| XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; |
| |
| /* Calculate the number of 32 bit words required to insert the specified |
| * number of bytes in the FIFO and determine the number of extra bytes |
| * if the buffer length is not a multiple of 32 bit words |
| */ |
| |
| WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT; |
| ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT; |
| |
| /* take into account the extra bytes in the total word count */ |
| |
| if (ExtraByteCount > 0) { |
| WordCount++; |
| } |
| |
| /* if there's not enough room in the FIFO to hold the specified |
| * number of bytes, then indicate an error, |
| */ |
| if (FifoCount < WordCount) { |
| return XST_PFIFO_NO_ROOM; |
| } |
| |
| /* readjust the word count to not take into account the extra bytes */ |
| |
| if (ExtraByteCount > 0) { |
| WordCount--; |
| } |
| |
| /* Write all the bytes of the buffer which can be written as 32 bit |
| * words into the FIFO, waiting to handle the extra bytes seperately |
| */ |
| for (FifoCount = 0; FifoCount < WordCount; FifoCount++) { |
| XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]); |
| } |
| |
| /* if there are extra bytes to handle, extract them from the buffer |
| * and create a 32 bit word and write it to the FIFO |
| */ |
| if (ExtraByteCount > 0) { |
| u32 LastWord = 0; |
| u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount); |
| |
| /* one extra byte in the buffer, put the byte into the last word |
| * to be inserted into the FIFO, perform this processing inline rather |
| * than in a loop to help performance |
| */ |
| if (ExtraByteCount == 1) { |
| LastWord = ExtraBytesBuffer[0] << 24; |
| } |
| |
| /* two extra bytes in the buffer, put each byte into the last word |
| * to be inserted into the FIFO |
| */ |
| else if (ExtraByteCount == 2) { |
| LastWord = ExtraBytesBuffer[0] << 24 | |
| ExtraBytesBuffer[1] << 16; |
| } |
| |
| /* three extra bytes in the buffer, put each byte into the last word |
| * to be inserted into the FIFO |
| */ |
| else if (ExtraByteCount == 3) { |
| LastWord = ExtraBytesBuffer[0] << 24 | |
| ExtraBytesBuffer[1] << 16 | |
| ExtraBytesBuffer[2] << 8; |
| } |
| |
| /* write the last 32 bit word to the FIFO and return with no errors */ |
| |
| XIo_Out32(InstancePtr->DataBaseAddress, LastWord); |
| } |
| |
| return XST_SUCCESS; |
| } |