uboot/board/xilinx/common/xpacket_fifo_v1_00_b.c
<<
>>
Prefs
   1/******************************************************************************
   2*
   3*     Author: Xilinx, Inc.
   4*
   5*
   6*     This program is free software; you can redistribute it and/or modify it
   7*     under the terms of the GNU General Public License as published by the
   8*     Free Software Foundation; either version 2 of the License, or (at your
   9*     option) any later version.
  10*
  11*
  12*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
  13*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
  14*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
  15*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
  16*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
  17*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
  18*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
  19*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
  20*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
  21*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
  22*     FITNESS FOR A PARTICULAR PURPOSE.
  23*
  24*
  25*     Xilinx hardware products are not intended for use in life support
  26*     appliances, devices, or systems. Use in such applications is
  27*     expressly prohibited.
  28*
  29*
  30*     (c) Copyright 2002-2004 Xilinx Inc.
  31*     All rights reserved.
  32*
  33*
  34*     You should have received a copy of the GNU General Public License along
  35*     with this program; if not, write to the Free Software Foundation, Inc.,
  36*     675 Mass Ave, Cambridge, MA 02139, USA.
  37*
  38******************************************************************************/
  39/*****************************************************************************/
  40/*
  41*
  42* @file xpacket_fifo_v1_00_b.c
  43*
  44* Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h
  45* for more information about the component.
  46*
  47* <pre>
  48* MODIFICATION HISTORY:
  49*
  50* Ver   Who  Date     Changes
  51* ----- ---- -------- -----------------------------------------------
  52* 1.00b rpm 03/26/02  First release
  53* </pre>
  54*
  55*****************************************************************************/
  56
  57/***************************** Include Files *********************************/
  58
  59#include "xbasic_types.h"
  60#include "xio.h"
  61#include "xstatus.h"
  62#include "xpacket_fifo_v1_00_b.h"
  63
  64/************************** Constant Definitions *****************************/
  65
  66/* width of a FIFO word */
  67
  68#define XPF_FIFO_WIDTH_BYTE_COUNT       4UL
  69
  70/**************************** Type Definitions *******************************/
  71
  72/***************** Macros (Inline Functions) Definitions *********************/
  73
  74/************************* Variable Definitions ******************************/
  75
  76/************************** Function Prototypes ******************************/
  77
  78/*****************************************************************************/
  79/*
  80*
  81* This function initializes a packet FIFO.  Initialization resets the
  82* FIFO such that it's empty and ready to use.
  83*
  84* @param InstancePtr contains a pointer to the FIFO to operate on.
  85* @param RegBaseAddress contains the base address of the registers for
  86*        the packet FIFO.
  87* @param DataBaseAddress contains the base address of the data for
  88*        the packet FIFO.
  89*
  90* @return
  91*
  92* Always returns XST_SUCCESS.
  93*
  94* @note
  95*
  96* None.
  97*
  98******************************************************************************/
  99XStatus
 100XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr,
 101                            u32 RegBaseAddress, u32 DataBaseAddress)
 102{
 103        /* assert to verify input argument are valid */
 104
 105        XASSERT_NONVOID(InstancePtr != NULL);
 106
 107        /* initialize the component variables to the specified state */
 108
 109        InstancePtr->RegBaseAddress = RegBaseAddress;
 110        InstancePtr->DataBaseAddress = DataBaseAddress;
 111        InstancePtr->IsReady = XCOMPONENT_IS_READY;
 112
 113        /* reset the FIFO such that it's empty and ready to use and indicate the
 114         * initialization was successful, note that the is ready variable must be
 115         * set prior to calling the reset function to prevent an assert
 116         */
 117        XPF_V100B_RESET(InstancePtr);
 118
 119        return XST_SUCCESS;
 120}
 121
 122/*****************************************************************************/
 123/*
 124*
 125* This function performs a self-test on the specified packet FIFO.  The self
 126* test resets the FIFO and reads a register to determine if it is the correct
 127* reset value.  This test is destructive in that any data in the FIFO will
 128* be lost.
 129*
 130* @param InstancePtr is a pointer to the packet FIFO to be operated on.
 131*
 132* @param FifoType specifies the type of FIFO, read or write, for the self test.
 133*        The FIFO type is specified by the values XPF_READ_FIFO_TYPE or
 134*        XPF_WRITE_FIFO_TYPE.
 135*
 136* @return
 137*
 138* XST_SUCCESS is returned if the selftest is successful, or
 139* XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the
 140* occupancy/vacancy count register after a reset does not match the
 141* specified reset value.
 142*
 143* @note
 144*
 145* None.
 146*
 147******************************************************************************/
 148XStatus
 149XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType)
 150{
 151        u32 Register;
 152
 153        /* assert to verify valid input arguments */
 154
 155        XASSERT_NONVOID(InstancePtr != NULL);
 156        XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) ||
 157                        (FifoType == XPF_WRITE_FIFO_TYPE));
 158        XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
 159
 160        /* reset the fifo and then check to make sure the occupancy/vacancy
 161         * register contents are correct for a reset condition
 162         */
 163        XPF_V100B_RESET(InstancePtr);
 164
 165        Register = XIo_In32(InstancePtr->RegBaseAddress +
 166                            XPF_COUNT_STATUS_REG_OFFSET);
 167
 168        /* check the value of the register to ensure that it's correct for the
 169         * specified FIFO type since both FIFO types reset to empty, but a bit
 170         * in the register changes definition based upon FIFO type
 171         */
 172
 173        if (FifoType == XPF_READ_FIFO_TYPE) {
 174                /* check the regiser value for a read FIFO which should be empty */
 175
 176                if (Register != XPF_EMPTY_FULL_MASK) {
 177                        return XST_PFIFO_BAD_REG_VALUE;
 178                }
 179        } else {
 180                /* check the register value for a write FIFO which should not be full
 181                 * on reset
 182                 */
 183                if ((Register & XPF_EMPTY_FULL_MASK) != 0) {
 184                        return XST_PFIFO_BAD_REG_VALUE;
 185                }
 186        }
 187
 188        /* the test was successful */
 189
 190        return XST_SUCCESS;
 191}
 192
 193/*****************************************************************************/
 194/*
 195*
 196* Read data from a FIFO and puts it into a specified buffer. The packet FIFO is
 197* currently 32 bits wide such that an input buffer which is a series of bytes
 198* is filled from the FIFO a word at a time. If the requested byte count is not
 199* a multiple of 32 bit words, it is necessary for this function to format the
 200* remaining 32 bit word from the FIFO into a series of bytes in the buffer.
 201* There may be up to 3 extra bytes which must be extracted from the last word
 202* of the FIFO and put into the buffer.
 203*
 204* @param InstancePtr contains a pointer to the FIFO to operate on.
 205* @param BufferPtr points to the memory buffer to write the data into. This
 206*        buffer must be 32 bit aligned or an alignment exception could be
 207*        generated. Since this buffer is a byte buffer, the data is assumed to
 208*        be endian independent.
 209* @param ByteCount contains the number of bytes to read from the FIFO. This
 210*        number of bytes must be present in the FIFO or an error will be
 211*        returned.
 212*
 213* @return
 214*
 215* XST_SUCCESS indicates the operation was successful.  If the number of
 216* bytes specified by the byte count is not present in the FIFO
 217* XST_PFIFO_LACK_OF_DATA is returned.
 218*
 219* If the function was successful, the specified buffer is modified to contain
 220* the bytes which were removed from the FIFO.
 221*
 222* @note
 223*
 224* Note that the exact number of bytes which are present in the FIFO is
 225* not known by this function.  It can only check for a number of 32 bit
 226* words such that if the byte count specified is incorrect, but is still
 227* possible based on the number of words in the FIFO, up to 3 garbage bytes
 228* may be present at the end of the buffer.
 229* <br><br>
 230* This function assumes that if the device consuming data from the FIFO is
 231* a byte device, the order of the bytes to be consumed is from the most
 232* significant byte to the least significant byte of a 32 bit word removed
 233* from the FIFO.
 234*
 235******************************************************************************/
 236XStatus
 237XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr,
 238                      u8 * BufferPtr, u32 ByteCount)
 239{
 240        u32 FifoCount;
 241        u32 WordCount;
 242        u32 ExtraByteCount;
 243        u32 *WordBuffer = (u32 *) BufferPtr;
 244
 245        /* assert to verify valid input arguments including 32 bit alignment of
 246         * the buffer pointer
 247         */
 248        XASSERT_NONVOID(InstancePtr != NULL);
 249        XASSERT_NONVOID(BufferPtr != NULL);
 250        XASSERT_NONVOID(((u32) BufferPtr &
 251                         (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
 252        XASSERT_NONVOID(ByteCount != 0);
 253        XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
 254
 255        /* get the count of how many 32 bit words are in the FIFO, if there aren't
 256         * enought words to satisfy the request, return an error
 257         */
 258
 259        FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
 260                             XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
 261
 262        if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) {
 263                return XST_PFIFO_LACK_OF_DATA;
 264        }
 265
 266        /* calculate the number of words to read from the FIFO before the word
 267         * containing the extra bytes, and calculate the number of extra bytes
 268         * the extra bytes are defined as those at the end of the buffer when
 269         * the buffer does not end on a 32 bit boundary
 270         */
 271        WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
 272        ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
 273
 274        /* Read the 32 bit words from the FIFO for all the buffer except the
 275         * last word which contains the extra bytes, the following code assumes
 276         * that the buffer is 32 bit aligned, otherwise an alignment exception could
 277         * be generated
 278         */
 279        for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
 280                WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress);
 281        }
 282
 283        /* if there are extra bytes to handle, read the last word from the FIFO
 284         * and insert the extra bytes into the buffer
 285         */
 286        if (ExtraByteCount > 0) {
 287                u32 LastWord;
 288                u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
 289
 290                /* get the last word from the FIFO for the extra bytes */
 291
 292                LastWord = XIo_In32(InstancePtr->DataBaseAddress);
 293
 294                /* one extra byte in the last word, put the byte into the next location
 295                 * of the buffer, bytes in a word of the FIFO are ordered from most
 296                 * significant byte to least
 297                 */
 298                if (ExtraByteCount == 1) {
 299                        ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
 300                }
 301
 302                /* two extra bytes in the last word, put each byte into the next two
 303                 * locations of the buffer
 304                 */
 305                else if (ExtraByteCount == 2) {
 306                        ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
 307                        ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
 308                }
 309                /* three extra bytes in the last word, put each byte into the next three
 310                 * locations of the buffer
 311                 */
 312                else if (ExtraByteCount == 3) {
 313                        ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
 314                        ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
 315                        ExtraBytesBuffer[2] = (u8) (LastWord >> 8);
 316                }
 317        }
 318        return XST_SUCCESS;
 319}
 320
 321/*****************************************************************************/
 322/*
 323*
 324* Write data into a packet FIFO. The packet FIFO is currently 32 bits wide
 325* such that an input buffer which is a series of bytes must be written into the
 326* FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is
 327* necessary for this function to format the remaining bytes into a single 32
 328* bit word to be inserted into the FIFO. This is necessary to avoid any
 329* accesses past the end of the buffer.
 330*
 331* @param InstancePtr contains a pointer to the FIFO to operate on.
 332* @param BufferPtr points to the memory buffer that data is to be read from
 333*        and written into the FIFO. Since this buffer is a byte buffer, the data
 334*        is assumed to be endian independent. This buffer must be 32 bit aligned
 335*        or an alignment exception could be generated.
 336* @param ByteCount contains the number of bytes to read from the buffer and to
 337*        write to the FIFO.
 338*
 339* @return
 340*
 341* XST_SUCCESS is returned if the operation succeeded.  If there is not enough
 342* room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is
 343* returned.
 344*
 345* @note
 346*
 347* This function assumes that if the device inserting data into the FIFO is
 348* a byte device, the order of the bytes in each 32 bit word is from the most
 349* significant byte to the least significant byte.
 350*
 351******************************************************************************/
 352XStatus
 353XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr,
 354                       u8 * BufferPtr, u32 ByteCount)
 355{
 356        u32 FifoCount;
 357        u32 WordCount;
 358        u32 ExtraByteCount;
 359        u32 *WordBuffer = (u32 *) BufferPtr;
 360
 361        /* assert to verify valid input arguments including 32 bit alignment of
 362         * the buffer pointer
 363         */
 364        XASSERT_NONVOID(InstancePtr != NULL);
 365        XASSERT_NONVOID(BufferPtr != NULL);
 366        XASSERT_NONVOID(((u32) BufferPtr &
 367                         (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
 368        XASSERT_NONVOID(ByteCount != 0);
 369        XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
 370
 371        /* get the count of how many words may be inserted into the FIFO */
 372
 373        FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
 374                             XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
 375
 376        /* Calculate the number of 32 bit words required to insert the specified
 377         * number of bytes in the FIFO and determine the number of extra bytes
 378         * if the buffer length is not a multiple of 32 bit words
 379         */
 380
 381        WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
 382        ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
 383
 384        /* take into account the extra bytes in the total word count */
 385
 386        if (ExtraByteCount > 0) {
 387                WordCount++;
 388        }
 389
 390        /* if there's not enough room in the FIFO to hold the specified
 391         * number of bytes, then indicate an error,
 392         */
 393        if (FifoCount < WordCount) {
 394                return XST_PFIFO_NO_ROOM;
 395        }
 396
 397        /* readjust the word count to not take into account the extra bytes */
 398
 399        if (ExtraByteCount > 0) {
 400                WordCount--;
 401        }
 402
 403        /* Write all the bytes of the buffer which can be written as 32 bit
 404         * words into the FIFO, waiting to handle the extra bytes seperately
 405         */
 406        for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
 407                XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]);
 408        }
 409
 410        /* if there are extra bytes to handle, extract them from the buffer
 411         * and create a 32 bit word and write it to the FIFO
 412         */
 413        if (ExtraByteCount > 0) {
 414                u32 LastWord = 0;
 415                u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
 416
 417                /* one extra byte in the buffer, put the byte into the last word
 418                 * to be inserted into the FIFO, perform this processing inline rather
 419                 * than in a loop to help performance
 420                 */
 421                if (ExtraByteCount == 1) {
 422                        LastWord = ExtraBytesBuffer[0] << 24;
 423                }
 424
 425                /* two extra bytes in the buffer, put each byte into the last word
 426                 * to be inserted into the FIFO
 427                 */
 428                else if (ExtraByteCount == 2) {
 429                        LastWord = ExtraBytesBuffer[0] << 24 |
 430                            ExtraBytesBuffer[1] << 16;
 431                }
 432
 433                /* three extra bytes in the buffer, put each byte into the last word
 434                 * to be inserted into the FIFO
 435                 */
 436                else if (ExtraByteCount == 3) {
 437                        LastWord = ExtraBytesBuffer[0] << 24 |
 438                            ExtraBytesBuffer[1] << 16 |
 439                            ExtraBytesBuffer[2] << 8;
 440                }
 441
 442                /* write the last 32 bit word to the FIFO and return with no errors */
 443
 444                XIo_Out32(InstancePtr->DataBaseAddress, LastWord);
 445        }
 446
 447        return XST_SUCCESS;
 448}
 449