|  | /****************************************************************************** | 
|  | * | 
|  | *     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; | 
|  | } |