uboot/arch/arm/cpu/ixp/npe/IxQMgrAqmIf.c
<<
>>
Prefs
   1/* 
   2 * @file:    IxQMgrAqmIf.c
   3 *
   4 * @author Intel Corporation
   5 * @date     30-Oct-2001
   6 *
   7 * @brief    This component provides a set of functions for
   8 * perfoming I/O on the AQM hardware.
   9 * 
  10 * Design Notes: 
  11 *              These functions are intended to be as fast as possible
  12 * and as a result perform NO PARAMETER CHECKING.
  13 *
  14 * 
  15 * @par
  16 * IXP400 SW Release version 2.0
  17 * 
  18 * -- Copyright Notice --
  19 * 
  20 * @par
  21 * Copyright 2001-2005, Intel Corporation.
  22 * All rights reserved.
  23 * 
  24 * @par
  25 * Redistribution and use in source and binary forms, with or without
  26 * modification, are permitted provided that the following conditions
  27 * are met:
  28 * 1. Redistributions of source code must retain the above copyright
  29 *    notice, this list of conditions and the following disclaimer.
  30 * 2. Redistributions in binary form must reproduce the above copyright
  31 *    notice, this list of conditions and the following disclaimer in the
  32 *    documentation and/or other materials provided with the distribution.
  33 * 3. Neither the name of the Intel Corporation nor the names of its contributors
  34 *    may be used to endorse or promote products derived from this software
  35 *    without specific prior written permission.
  36 * 
  37 * @par
  38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  39 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  41 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  48 * SUCH DAMAGE.
  49 * 
  50 * @par
  51 * -- End of Copyright Notice --
  52*/
  53
  54/*
  55 * Inlines are compiled as function when this is defined.
  56 * N.B. Must be placed before #include of "IxQMgrAqmIf_p.h
  57 */
  58#ifndef IXQMGRAQMIF_P_H
  59#    define IXQMGRAQMIF_C
  60#else
  61#    error
  62#endif
  63
  64/*
  65 * User defined include files.
  66 */
  67#include "IxOsal.h"
  68#include "IxQMgr.h"
  69#include "IxQMgrAqmIf_p.h"
  70#include "IxQMgrLog_p.h"
  71
  72
  73/*
  74 * #defines and macros used in this file.
  75 */
  76
  77/* These defines are the bit offsets of the various fields of
  78 * the queue configuration register
  79 */
  80#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET       0x00
  81#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET       0x07
  82#define IX_QMGR_Q_CONFIG_BADDR_OFFSET       0x0E
  83#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET       0x16
  84#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET       0x18
  85#define IX_QMGR_Q_CONFIG_NE_OFFSET          0x1A
  86#define IX_QMGR_Q_CONFIG_NF_OFFSET          0x1D
  87
  88#define IX_QMGR_BASE_ADDR_16_WORD_ALIGN     0x40
  89#define IX_QMGR_BASE_ADDR_16_WORD_SHIFT     0x6
  90
  91#define IX_QMGR_NE_NF_CLEAR_MASK            0x03FFFFFF
  92#define IX_QMGR_NE_MASK                     0x7
  93#define IX_QMGR_NF_MASK                     0x7
  94#define IX_QMGR_SIZE_MASK                   0x3
  95#define IX_QMGR_ENTRY_SIZE_MASK             0x3
  96#define IX_QMGR_BADDR_MASK                  0x003FC000
  97#define IX_QMGR_RDPTR_MASK                  0x7F
  98#define IX_QMGR_WRPTR_MASK                  0x7F
  99#define IX_QMGR_RDWRPTR_MASK                0x00003FFF
 100
 101#define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000
 102
 103/* Base address of AQM SRAM */
 104#define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \
 105((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE))
 106
 107/* Min buffer size used for generating buffer size in QUECONFIG */
 108#define IX_QMGR_MIN_BUFFER_SIZE 16
 109
 110/* Reset values of QMgr hardware registers */
 111#define IX_QMGR_QUELOWSTAT_RESET_VALUE    0x33333333
 112#define IX_QMGR_QUEUOSTAT_RESET_VALUE     0x00000000
 113#define IX_QMGR_QUEUPPSTAT0_RESET_VALUE   0xFFFFFFFF
 114#define IX_QMGR_QUEUPPSTAT1_RESET_VALUE   0x00000000
 115#define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000
 116#define IX_QMGR_QUEIEREG_RESET_VALUE      0x00000000
 117#define IX_QMGR_QINTREG_RESET_VALUE       0xFFFFFFFF
 118#define IX_QMGR_QUECONFIG_RESET_VALUE     0x00000000
 119
 120#define IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS IX_OSAL_IXP400_QMGR_PHYS_BASE
 121
 122#define IX_QMGR_QUELOWSTAT_BITS_PER_Q (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)
 123
 124#define IX_QMGR_QUELOWSTAT_QID_MASK 0x7
 125#define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\
 126        (((qId) * IX_QMGR_NUM_BYTES_PER_WORD) +\
 127                  IX_QMGR_QUECONFIG_BASE_OFFSET)
 128
 129#define IX_QMGR_ENTRY1_OFFSET 0
 130#define IX_QMGR_ENTRY2_OFFSET 1
 131#define IX_QMGR_ENTRY4_OFFSET 3
 132
 133/*
 134 * Variable declarations global to this file. Externs are followed by
 135 * statics.
 136 */
 137UINT32 aqmBaseAddress = 0;
 138/* Store addresses and bit-masks for certain queue access and status registers.
 139 * This is to facilitate inlining of QRead, QWrite and QStatusGet functions
 140 * in IxQMgr,h
 141 */
 142extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
 143UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES];
 144UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID];
 145UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID];
 146UINT32 ixQMgrAqmIfQueLowStatBitsMask;
 147UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
 148UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
 149UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID];
 150UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID];
 151
 152/* 
 153 * Fast mutexes, one for each queue, used to protect peek & poke functions
 154 */
 155IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES];
 156
 157/*
 158 * Function prototypes
 159 */
 160PRIVATE unsigned
 161watermarkToAqmWatermark (IxQMgrWMLevel watermark );
 162
 163PRIVATE unsigned
 164entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize);
 165
 166PRIVATE unsigned
 167bufferSizeToAqmBufferSize (unsigned bufferSizeInWords);
 168
 169PRIVATE void
 170ixQMgrAqmIfRegistersReset (void);
 171
 172PRIVATE void
 173ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
 174                            UINT32 configRegWord,
 175                            unsigned int qEntrySizeInwords,
 176                            unsigned int qSizeInWords,
 177                            UINT32 **address);
 178/*
 179 * Function definitions
 180 */
 181void
 182ixQMgrAqmIfInit (void)
 183{
 184    UINT32 aqmVirtualAddr;
 185    int i;
 186
 187    /* The value of aqmBaseAddress depends on the logical address
 188     * assigned by the MMU.
 189     */
 190    aqmVirtualAddr =
 191        (UINT32) IX_OSAL_MEM_MAP(IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS,
 192                                    IX_OSAL_IXP400_QMGR_MAP_SIZE);
 193    IX_OSAL_ASSERT (aqmVirtualAddr);
 194    
 195    ixQMgrAqmIfBaseAddressSet (aqmVirtualAddr);
 196
 197    ixQMgrAqmIfRegistersReset ();
 198
 199    for (i = 0; i< IX_QMGR_MAX_NUM_QUEUES; i++)
 200    {
 201        ixOsalFastMutexInit(&ixQMgrAqmIfPeekPokeFastMutex[i]);
 202
 203        /********************************************************************
 204         * Register addresses and bit masks are calculated and stored here to
 205         * facilitate inlining of QRead, QWrite and QStatusGet functions in
 206         * IxQMgr.h.
 207         * These calculations are normally performed dynamically in inlined
 208         * functions in IxQMgrAqmIf_p.h, and their semantics are reused here.
 209         */
 210
 211        /* AQM Queue access reg addresses, per queue */
 212        ixQMgrAqmIfQueAccRegAddr[i] = 
 213            (UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
 214        ixQMgrQInlinedReadWriteInfo[i].qAccRegAddr = 
 215            (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
 216
 217
 218        ixQMgrQInlinedReadWriteInfo[i].qConfigRegAddr = 
 219            (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(i));
 220
 221        /* AQM Queue lower-group (0-31), only */
 222        if (i < IX_QMGR_MIN_QUEUPP_QID)
 223        {
 224            /* AQM Q underflow/overflow status register addresses, per queue */
 225            ixQMgrQInlinedReadWriteInfo[i].qUOStatRegAddr = 
 226                (volatile UINT32 *)(aqmBaseAddress +
 227                IX_QMGR_QUEUOSTAT0_OFFSET +
 228                ((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) *
 229                 IX_QMGR_NUM_BYTES_PER_WORD));
 230
 231            /* AQM Q underflow status bit masks for status register per queue */
 232            ixQMgrQInlinedReadWriteInfo[i].qUflowStatBitMask = 
 233                (IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) <<
 234                ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
 235                 (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
 236
 237            /* AQM Q overflow status bit masks for status register, per queue */
 238            ixQMgrQInlinedReadWriteInfo[i].qOflowStatBitMask = 
 239                (IX_QMGR_OVERFLOW_BIT_OFFSET + 1) <<
 240                ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
 241                 (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
 242
 243            /* AQM Q lower-group (0-31) status register addresses, per queue */
 244            ixQMgrAqmIfQueLowStatRegAddr[i] = aqmBaseAddress +
 245                IX_QMGR_QUELOWSTAT0_OFFSET +
 246                ((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
 247                 IX_QMGR_NUM_BYTES_PER_WORD);
 248
 249            /* AQM Q lower-group (0-31) status register bit offset */
 250            ixQMgrAqmIfQueLowStatBitsOffset[i] =
 251                (i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) * 
 252                (BITS_PER_WORD / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD);
 253        }
 254        else /* AQM Q upper-group (32-63), only */
 255        {
 256            /* AQM Q upper-group (32-63) Nearly Empty status reg bit masks */
 257            ixQMgrAqmIfQueUppStat0BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
 258                (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
 259
 260            /* AQM Q upper-group (32-63) Full status register bit masks */
 261            ixQMgrAqmIfQueUppStat1BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
 262                (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
 263        }
 264    }
 265
 266    /* AQM Q lower-group (0-31) status register bit mask */
 267    ixQMgrAqmIfQueLowStatBitsMask = (1 <<
 268                                    (BITS_PER_WORD /
 269                                     IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1;
 270
 271    /* AQM Q upper-group (32-63) Nearly Empty status register address */
 272    ixQMgrAqmIfQueUppStat0RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET;
 273    
 274    /* AQM Q upper-group (32-63) Full status register address */
 275    ixQMgrAqmIfQueUppStat1RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET;
 276}
 277
 278/*
 279 * Uninitialise the AqmIf module by unmapping memory, etc
 280 */
 281void
 282ixQMgrAqmIfUninit (void)
 283{
 284    UINT32 virtAddr;
 285
 286    ixQMgrAqmIfBaseAddressGet (&virtAddr);
 287    IX_OSAL_MEM_UNMAP (virtAddr);
 288    ixQMgrAqmIfBaseAddressSet (0);
 289}
 290
 291/*
 292 * Set the the logical base address of AQM
 293 */
 294void
 295ixQMgrAqmIfBaseAddressSet (UINT32 address)
 296{
 297    aqmBaseAddress = address;
 298}
 299
 300/*
 301 * Get the logical base address of AQM
 302 */
 303void
 304ixQMgrAqmIfBaseAddressGet (UINT32 *address)
 305{
 306    *address = aqmBaseAddress;
 307}
 308
 309/*
 310 * Get the logical base address of AQM SRAM
 311 */
 312void
 313ixQMgrAqmIfSramBaseAddressGet (UINT32 *address)
 314{
 315    *address = aqmBaseAddress                +
 316        IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET;
 317}
 318
 319/*
 320 * This function will write the status bits of a queue
 321 * specified by qId.
 322 */
 323void
 324ixQMgrAqmIfQRegisterBitsWrite (IxQMgrQId qId, 
 325                               UINT32 registerBaseAddrOffset,
 326                               unsigned queuesPerRegWord,
 327                               UINT32 value)
 328{
 329    volatile UINT32 *registerAddress;
 330    UINT32 registerWord;
 331    UINT32 statusBitsMask;
 332    UINT32 bitsPerQueue;
 333
 334    bitsPerQueue = BITS_PER_WORD / queuesPerRegWord;
 335
 336    /*
 337     * Calculate the registerAddress
 338     * multiple queues split accross registers
 339     */
 340    registerAddress = (UINT32*)(aqmBaseAddress +
 341                                registerBaseAddrOffset +
 342                                ((qId / queuesPerRegWord) *
 343                                 IX_QMGR_NUM_BYTES_PER_WORD));    
 344
 345    /* Read the current data */
 346    ixQMgrAqmIfWordRead (registerAddress, &registerWord);
 347
 348
 349    if( (registerBaseAddrOffset == IX_QMGR_INT0SRCSELREG0_OFFSET) &&
 350        (qId == IX_QMGR_QUEUE_0) )
 351    {
 352      statusBitsMask = 0x7 ;   
 353
 354      /* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3  */
 355      value &=  0x7 ;        
 356    }
 357    else
 358    {     
 359      /* Calculate the mask for the status bits for this queue. */
 360      statusBitsMask = ((1 << bitsPerQueue) - 1);
 361      statusBitsMask <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
 362
 363      /* Mask out bits in value that would overwrite other q data */
 364      value <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
 365      value &= statusBitsMask;
 366    }
 367
 368    /* Mask out bits to write to */
 369    registerWord &= ~statusBitsMask;
 370    
 371
 372    /* Set the write bits */
 373    registerWord |= value;
 374
 375    /*
 376     * Write the data
 377     */
 378    ixQMgrAqmIfWordWrite (registerAddress, registerWord);
 379}
 380
 381/*
 382 * This function generates the parameters that can be used to
 383 * check if a Qs status matches the specified source select.
 384 * It calculates which status word to check (statusWordOffset),
 385 * the value to check the status against (checkValue) and the
 386 * mask (mask) to mask out all but the bits to check in the status word.
 387 */
 388void
 389ixQMgrAqmIfQStatusCheckValsCalc (IxQMgrQId qId,
 390                                 IxQMgrSourceId srcSel,
 391                                 unsigned int *statusWordOffset,
 392                                 UINT32 *checkValue,
 393                                 UINT32 *mask)
 394{
 395    UINT32 shiftVal;
 396   
 397    if (qId < IX_QMGR_MIN_QUEUPP_QID)
 398    {
 399        switch (srcSel)
 400        {
 401            case IX_QMGR_Q_SOURCE_ID_E:
 402                *checkValue = IX_QMGR_Q_STATUS_E_BIT_MASK;
 403                *mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
 404                break;
 405            case IX_QMGR_Q_SOURCE_ID_NE:
 406                *checkValue = IX_QMGR_Q_STATUS_NE_BIT_MASK;
 407                *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
 408                break;
 409            case IX_QMGR_Q_SOURCE_ID_NF:
 410                *checkValue = IX_QMGR_Q_STATUS_NF_BIT_MASK;
 411                *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
 412                break;
 413            case IX_QMGR_Q_SOURCE_ID_F:
 414                *checkValue = IX_QMGR_Q_STATUS_F_BIT_MASK;
 415                *mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
 416                break;
 417            case IX_QMGR_Q_SOURCE_ID_NOT_E:
 418                *checkValue = 0;
 419                *mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
 420                break;
 421            case IX_QMGR_Q_SOURCE_ID_NOT_NE:
 422                *checkValue = 0;
 423                *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
 424                break;
 425            case IX_QMGR_Q_SOURCE_ID_NOT_NF:
 426                *checkValue = 0;
 427                *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
 428                break;
 429            case IX_QMGR_Q_SOURCE_ID_NOT_F:
 430                *checkValue = 0;
 431                *mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
 432                break;
 433            default:
 434                /* Should never hit */
 435                IX_OSAL_ASSERT(0);
 436                break;
 437        }
 438
 439        /* One nibble of status per queue so need to shift the
 440         * check value and mask out to the correct position.
 441         */
 442        shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) * 
 443            IX_QMGR_QUELOWSTAT_BITS_PER_Q;
 444
 445        /* Calculate the which status word to check from the qId,
 446         * 8 Qs status per word
 447         */
 448        *statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD;
 449
 450        *checkValue <<= shiftVal;
 451        *mask <<= shiftVal;
 452    }
 453    else
 454    {
 455        /* One status word */
 456        *statusWordOffset = 0;
 457        /* Single bits per queue and int source bit hardwired  NE,
 458         * Qs start at 32.
 459         */
 460        *mask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID);
 461        *checkValue = *mask;
 462    }
 463}
 464
 465void
 466ixQMgrAqmIfQInterruptEnable (IxQMgrQId qId)
 467{
 468    volatile UINT32 *registerAddress;
 469    UINT32 registerWord;
 470    UINT32 actualBitOffset;
 471    
 472    if (qId < IX_QMGR_MIN_QUEUPP_QID)
 473    {    
 474        registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
 475    }
 476    else
 477    {
 478        registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
 479    }
 480
 481    actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
 482
 483    ixQMgrAqmIfWordRead (registerAddress, &registerWord);
 484    ixQMgrAqmIfWordWrite (registerAddress, (registerWord | actualBitOffset));
 485}
 486
 487void
 488ixQMgrAqmIfQInterruptDisable (IxQMgrQId qId)
 489{
 490    volatile UINT32 *registerAddress;
 491    UINT32 registerWord;
 492    UINT32 actualBitOffset;
 493
 494    if (qId < IX_QMGR_MIN_QUEUPP_QID)
 495    {    
 496        registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
 497    }
 498    else
 499    {
 500        registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
 501    }
 502
 503    actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
 504
 505    ixQMgrAqmIfWordRead (registerAddress, &registerWord);
 506    ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset));
 507}
 508
 509void
 510ixQMgrAqmIfQueCfgWrite (IxQMgrQId qId,
 511                       IxQMgrQSizeInWords qSizeInWords,
 512                       IxQMgrQEntrySizeInWords entrySizeInWords,
 513                       UINT32 freeSRAMAddress)
 514{
 515    volatile UINT32 *cfgAddress = NULL;
 516    UINT32 qCfg = 0;
 517    UINT32 baseAddress = 0;
 518    unsigned aqmEntrySize = 0;
 519    unsigned aqmBufferSize = 0;
 520
 521    /* Build config register */
 522    aqmEntrySize = entrySizeToAqmEntrySize (entrySizeInWords);
 523    qCfg |= (aqmEntrySize&IX_QMGR_ENTRY_SIZE_MASK) <<
 524        IX_QMGR_Q_CONFIG_ESIZE_OFFSET;
 525
 526    aqmBufferSize = bufferSizeToAqmBufferSize (qSizeInWords);
 527    qCfg |= (aqmBufferSize&IX_QMGR_SIZE_MASK) << IX_QMGR_Q_CONFIG_BSIZE_OFFSET;
 528
 529    /* baseAddress, calculated relative to aqmBaseAddress and start address  */
 530    baseAddress = freeSRAMAddress -
 531        (aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
 532                   
 533    /* Verify base address aligned to a 16 word boundary */
 534    if ((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) != 0)
 535    {
 536        IX_QMGR_LOG_ERROR0("ixQMgrAqmIfQueCfgWrite () address is not on 16 word boundary\n");
 537    }
 538    /* Now convert it to a 16 word pointer as required by QUECONFIG register */
 539    baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
 540    
 541    
 542    qCfg |= (baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET);
 543
 544
 545    cfgAddress = (UINT32*)(aqmBaseAddress +
 546                        IX_QMGR_Q_CONFIG_ADDR_GET(qId));
 547
 548
 549    /* NOTE: High and Low watermarks are set to zero */
 550    ixQMgrAqmIfWordWrite (cfgAddress, qCfg);
 551}
 552
 553void
 554ixQMgrAqmIfQueCfgRead (IxQMgrQId qId,
 555                       unsigned int numEntries,
 556                       UINT32 *baseAddress,
 557                       unsigned int *ne,
 558                       unsigned int *nf,
 559                       UINT32 *readPtr,
 560                       UINT32 *writePtr)
 561{
 562    UINT32 qcfg;
 563    UINT32 *cfgAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
 564    unsigned int qEntrySizeInwords;
 565    unsigned int qSizeInWords;
 566    UINT32 *readPtr_ = NULL;
 567        
 568    /* Read the queue configuration register */
 569    ixQMgrAqmIfWordRead (cfgAddress, &qcfg);
 570    
 571    /* Extract the base address */
 572    *baseAddress = (UINT32)((qcfg & IX_QMGR_BADDR_MASK) >>
 573                            (IX_QMGR_Q_CONFIG_BADDR_OFFSET));
 574
 575    /* Base address is a 16 word pointer from the start of AQM SRAM.
 576     * Convert to absolute word address.
 577     */
 578    *baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
 579    *baseAddress += (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET;
 580
 581    /*
 582     * Extract the watermarks. 0->0 entries, 1->1 entries, 2->2 entries, 3->4 entries......
 583     * If ne > 0 ==> neInEntries = 2^(ne - 1)
 584     * If ne == 0 ==> neInEntries = 0
 585     * The same applies.
 586     */
 587    *ne = ((qcfg) >> (IX_QMGR_Q_CONFIG_NE_OFFSET)) & IX_QMGR_NE_MASK;
 588    *nf = ((qcfg) >> (IX_QMGR_Q_CONFIG_NF_OFFSET)) & IX_QMGR_NF_MASK;
 589
 590    if (0 != *ne)
 591    {
 592        *ne = 1 << (*ne - 1);   
 593    }
 594    if (0 != *nf)
 595    {
 596        *nf = 1 << (*nf - 1);
 597    }
 598
 599    /* Get the queue entry size in words */
 600    qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
 601
 602    /* Get the queue size in words */
 603    qSizeInWords = ixQMgrQSizeInWordsGet (qId);
 604
 605    ixQMgrAqmIfEntryAddressGet (0/* Entry 0. i.e the readPtr*/,
 606                                qcfg,
 607                                qEntrySizeInwords,
 608                                qSizeInWords,
 609                                &readPtr_);
 610    *readPtr = (UINT32)readPtr_;
 611    *readPtr -= (UINT32)aqmBaseAddress;/* Offset, not absolute address */
 612
 613    *writePtr = (qcfg >> IX_QMGR_Q_CONFIG_WRPTR_OFFSET) & IX_QMGR_WRPTR_MASK;
 614    *writePtr = *baseAddress + (*writePtr * (IX_QMGR_NUM_BYTES_PER_WORD));
 615    return;
 616}
 617
 618unsigned
 619ixQMgrAqmIfLog2 (unsigned number)
 620{
 621    unsigned count = 0;
 622
 623    /*
 624     * N.B. this function will return 0
 625     * for ixQMgrAqmIfLog2 (0)
 626     */
 627    while (number/2)
 628    {
 629        number /=2;
 630        count++;        
 631    }
 632
 633    return count;
 634}
 635
 636void ixQMgrAqmIfIntSrcSelReg0Bit3Set (void)
 637{
 638
 639    volatile UINT32 *registerAddress;
 640    UINT32 registerWord; 
 641
 642    /*
 643     * Calculate the registerAddress
 644     * multiple queues split accross registers
 645     */
 646    registerAddress = (UINT32*)(aqmBaseAddress +
 647                                IX_QMGR_INT0SRCSELREG0_OFFSET);    
 648
 649    /* Read the current data */
 650    ixQMgrAqmIfWordRead (registerAddress, &registerWord);
 651
 652    /* Set the write bits */
 653    registerWord |= (1<<IX_QMGR_INT0SRCSELREG0_BIT3) ;
 654
 655    /*
 656     * Write the data
 657     */
 658    ixQMgrAqmIfWordWrite (registerAddress, registerWord);
 659}  
 660
 661
 662void
 663ixQMgrAqmIfIntSrcSelWrite (IxQMgrQId qId,
 664                          IxQMgrSourceId sourceId)
 665{
 666    ixQMgrAqmIfQRegisterBitsWrite (qId,
 667                                   IX_QMGR_INT0SRCSELREG0_OFFSET,
 668                                   IX_QMGR_INTSRC_NUM_QUE_PER_WORD,
 669                                   sourceId);
 670}
 671
 672
 673
 674void
 675ixQMgrAqmIfWatermarkSet (IxQMgrQId qId,
 676                        unsigned ne,
 677                        unsigned nf)
 678{
 679    volatile UINT32 *address = 0;
 680    UINT32 value = 0;
 681    unsigned aqmNeWatermark = 0;
 682    unsigned aqmNfWatermark = 0;
 683
 684    address = (UINT32*)(aqmBaseAddress +
 685                     IX_QMGR_Q_CONFIG_ADDR_GET(qId));
 686
 687    aqmNeWatermark = watermarkToAqmWatermark (ne);
 688    aqmNfWatermark = watermarkToAqmWatermark (nf);
 689
 690    /* Read the current watermarks */
 691    ixQMgrAqmIfWordRead (address, &value);
 692
 693    /* Clear out the old watermarks */
 694    value &=  IX_QMGR_NE_NF_CLEAR_MASK;
 695    
 696    /* Generate the value to write */
 697    value |= (aqmNeWatermark << IX_QMGR_Q_CONFIG_NE_OFFSET) |
 698        (aqmNfWatermark << IX_QMGR_Q_CONFIG_NF_OFFSET); 
 699
 700    ixQMgrAqmIfWordWrite (address, value);
 701
 702}
 703
 704PRIVATE void
 705ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
 706                            UINT32 configRegWord,
 707                            unsigned int qEntrySizeInwords,
 708                            unsigned int qSizeInWords,
 709                            UINT32 **address)
 710{
 711    UINT32 readPtr;
 712    UINT32 baseAddress;
 713    UINT32 *topOfAqmSram;
 714
 715    topOfAqmSram = ((UINT32 *)aqmBaseAddress + IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS);
 716
 717    /* Extract the base address */
 718    baseAddress = (UINT32)((configRegWord & IX_QMGR_BADDR_MASK) >>
 719                           (IX_QMGR_Q_CONFIG_BADDR_OFFSET));
 720
 721    /* Base address is a 16 word pointer from the start of AQM SRAM.
 722     * Convert to absolute word address.
 723     */
 724    baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
 725    baseAddress += ((UINT32)aqmBaseAddress + (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET);
 726
 727    /* Extract the read pointer. Read pointer is a word pointer */
 728    readPtr = (UINT32)((configRegWord >>
 729                        IX_QMGR_Q_CONFIG_RDPTR_OFFSET)&IX_QMGR_RDPTR_MASK);
 730
 731    /* Read/Write pointers(word pointers)  are offsets from the queue buffer space base address.
 732     * Calculate the absolute read pointer address. NOTE: Queues are circular buffers.
 733     */
 734    readPtr  = (readPtr + (entryIndex * qEntrySizeInwords)) & (qSizeInWords - 1); /* Mask by queue size */
 735    *address = (UINT32 *)(baseAddress + (readPtr * (IX_QMGR_NUM_BYTES_PER_WORD)));
 736
 737    switch (qEntrySizeInwords)
 738    {
 739        case IX_QMGR_Q_ENTRY_SIZE1:
 740            IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY1_OFFSET) < topOfAqmSram);      
 741            break;
 742        case IX_QMGR_Q_ENTRY_SIZE2:
 743            IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY2_OFFSET) < topOfAqmSram);
 744            break;
 745        case IX_QMGR_Q_ENTRY_SIZE4:
 746            IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY4_OFFSET) < topOfAqmSram);
 747            break;
 748        default:
 749            IX_QMGR_LOG_ERROR0("Invalid Q Entry size passed to ixQMgrAqmIfEntryAddressGet");
 750            break;
 751    }
 752    
 753}
 754
 755IX_STATUS
 756ixQMgrAqmIfQPeek (IxQMgrQId qId,
 757                  unsigned int entryIndex,
 758                  unsigned int *entry)
 759{
 760    UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
 761    UINT32 *entryAddress = NULL;
 762    UINT32 configRegWordOnEntry;
 763    UINT32 configRegWordOnExit;
 764    unsigned int qEntrySizeInwords;
 765    unsigned int qSizeInWords;
 766
 767    /* Get the queue entry size in words */
 768    qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
 769
 770    /* Get the queue size in words */
 771    qSizeInWords = ixQMgrQSizeInWordsGet (qId);
 772
 773    /* Read the config register */
 774    ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
 775
 776    /* Get the entry address */
 777    ixQMgrAqmIfEntryAddressGet (entryIndex,
 778                                configRegWordOnEntry,
 779                                qEntrySizeInwords,
 780                                qSizeInWords,
 781                                &entryAddress);
 782
 783    /* Get the lock or return busy */
 784    if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
 785    {
 786        return IX_FAIL;
 787    }
 788
 789    while(qEntrySizeInwords--)
 790    {
 791        ixQMgrAqmIfWordRead (entryAddress++, entry++);
 792    }
 793
 794    /* Release the lock */
 795    ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
 796
 797    /* Read the config register */
 798    ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
 799
 800    /* Check that the read and write pointers have not changed */
 801    if (configRegWordOnEntry != configRegWordOnExit)
 802    {
 803        return IX_FAIL;
 804    }
 805
 806    return IX_SUCCESS;
 807}
 808
 809IX_STATUS
 810ixQMgrAqmIfQPoke (IxQMgrQId qId,
 811                  unsigned entryIndex,
 812                  unsigned int *entry)
 813{
 814    UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
 815    UINT32 *entryAddress = NULL;
 816    UINT32 configRegWordOnEntry;
 817    UINT32 configRegWordOnExit;
 818    unsigned int qEntrySizeInwords;
 819    unsigned int qSizeInWords;
 820    
 821    /* Get the queue entry size in words */
 822    qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
 823
 824    /* Get the queue size in words */
 825    qSizeInWords = ixQMgrQSizeInWordsGet (qId);
 826
 827    /* Read the config register */
 828    ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
 829
 830    /* Get the entry address */
 831    ixQMgrAqmIfEntryAddressGet (entryIndex,
 832                                configRegWordOnEntry,
 833                                qEntrySizeInwords,
 834                                qSizeInWords,
 835                                &entryAddress);
 836
 837    /* Get the lock or return busy */
 838    if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
 839    {
 840        return IX_FAIL;
 841    }
 842
 843    /* Else read the entry directly from SRAM. This will not move the read pointer */
 844    while(qEntrySizeInwords--)
 845    {
 846        ixQMgrAqmIfWordWrite (entryAddress++, *entry++);
 847    }
 848
 849    /* Release the lock */
 850    ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
 851
 852    /* Read the config register */
 853    ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
 854
 855    /* Check that the read and write pointers have not changed */
 856    if (configRegWordOnEntry != configRegWordOnExit)
 857    {
 858        return IX_FAIL;
 859    }
 860
 861    return IX_SUCCESS;
 862}
 863
 864PRIVATE unsigned
 865watermarkToAqmWatermark (IxQMgrWMLevel watermark )
 866{
 867    unsigned aqmWatermark = 0;
 868
 869    /*
 870     * Watermarks 0("000"),1("001"),2("010"),4("011"),
 871     * 8("100"),16("101"),32("110"),64("111")
 872     */
 873    aqmWatermark = ixQMgrAqmIfLog2 (watermark * 2);
 874    
 875    return aqmWatermark;
 876}
 877
 878PRIVATE unsigned
 879entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize)
 880{
 881    /* entrySize  1("00"),2("01"),4("10") */
 882    return (ixQMgrAqmIfLog2 (entrySize));
 883}
 884
 885PRIVATE unsigned
 886bufferSizeToAqmBufferSize (unsigned bufferSizeInWords)
 887{
 888    /* bufferSize 16("00"),32("01),64("10"),128("11") */
 889    return (ixQMgrAqmIfLog2 (bufferSizeInWords / IX_QMGR_MIN_BUFFER_SIZE));
 890}
 891
 892/*
 893 * Reset AQM registers to default values.
 894 */
 895PRIVATE void
 896ixQMgrAqmIfRegistersReset (void)
 897{
 898    volatile UINT32 *qConfigWordAddress = NULL;
 899    unsigned int i;
 900
 901    /*
 902     * Need to initialize AQM hardware registers to an initial
 903     * value as init may have been called as a result of a soft
 904     * reset. i.e. soft reset does not reset hardware registers.
 905     */
 906
 907    /* Reset queues 0..31 status registers 0..3 */
 908    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT0_OFFSET), 
 909                         IX_QMGR_QUELOWSTAT_RESET_VALUE);
 910    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT1_OFFSET), 
 911                         IX_QMGR_QUELOWSTAT_RESET_VALUE);
 912    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT2_OFFSET), 
 913                         IX_QMGR_QUELOWSTAT_RESET_VALUE);
 914    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT3_OFFSET), 
 915                         IX_QMGR_QUELOWSTAT_RESET_VALUE);
 916
 917    /* Reset underflow/overflow status registers 0..1 */
 918    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT0_OFFSET), 
 919                         IX_QMGR_QUEUOSTAT_RESET_VALUE);
 920    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT1_OFFSET), 
 921                         IX_QMGR_QUEUOSTAT_RESET_VALUE);
 922    
 923    /* Reset queues 32..63 nearly empty status registers */
 924    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET),
 925                         IX_QMGR_QUEUPPSTAT0_RESET_VALUE);
 926
 927    /* Reset queues 32..63 full status registers */
 928    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET),
 929                         IX_QMGR_QUEUPPSTAT1_RESET_VALUE);
 930
 931    /* Reset int0 status flag source select registers 0..3 */
 932    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG0_OFFSET),
 933                         IX_QMGR_INT0SRCSELREG_RESET_VALUE);
 934    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG1_OFFSET),
 935                         IX_QMGR_INT0SRCSELREG_RESET_VALUE);
 936    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG2_OFFSET),
 937                         IX_QMGR_INT0SRCSELREG_RESET_VALUE);
 938    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG3_OFFSET),
 939                         IX_QMGR_INT0SRCSELREG_RESET_VALUE);
 940         
 941    /* Reset queue interrupt enable register 0..1 */
 942    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET),
 943                         IX_QMGR_QUEIEREG_RESET_VALUE);
 944    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET),
 945                         IX_QMGR_QUEIEREG_RESET_VALUE);
 946
 947    /* Reset queue interrupt register 0..1 */
 948    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG0_OFFSET),
 949                         IX_QMGR_QINTREG_RESET_VALUE);
 950    ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG1_OFFSET),
 951                         IX_QMGR_QINTREG_RESET_VALUE);
 952
 953    /* Reset queue configuration words 0..63 */
 954    qConfigWordAddress = (UINT32 *)(aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
 955    for (i = 0; i < (IX_QMGR_QUECONFIG_SIZE / sizeof(UINT32)); i++)
 956    {
 957        ixQMgrAqmIfWordWrite(qConfigWordAddress,
 958                             IX_QMGR_QUECONFIG_RESET_VALUE);
 959        /* Next word */
 960        qConfigWordAddress++;
 961    }
 962}
 963
 964