449 lines
15 KiB
C
449 lines
15 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* 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;
|
||
|
}
|