| /* |
| * @file: IxQMgrAqmIf.c |
| * |
| * @author Intel Corporation |
| * @date 30-Oct-2001 |
| * |
| * @brief This component provides a set of functions for |
| * perfoming I/O on the AQM hardware. |
| * |
| * Design Notes: |
| * These functions are intended to be as fast as possible |
| * and as a result perform NO PARAMETER CHECKING. |
| * |
| * |
| * @par |
| * IXP400 SW Release version 2.0 |
| * |
| * -- Copyright Notice -- |
| * |
| * @par |
| * Copyright 2001-2005, Intel Corporation. |
| * All rights reserved. |
| * |
| * @par |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the Intel Corporation nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * @par |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| * @par |
| * -- End of Copyright Notice -- |
| */ |
| |
| /* |
| * Inlines are compiled as function when this is defined. |
| * N.B. Must be placed before #include of "IxQMgrAqmIf_p.h |
| */ |
| #ifndef IXQMGRAQMIF_P_H |
| # define IXQMGRAQMIF_C |
| #else |
| # error |
| #endif |
| |
| /* |
| * User defined include files. |
| */ |
| #include "IxOsal.h" |
| #include "IxQMgr.h" |
| #include "IxQMgrAqmIf_p.h" |
| #include "IxQMgrLog_p.h" |
| |
| |
| /* |
| * #defines and macros used in this file. |
| */ |
| |
| /* These defines are the bit offsets of the various fields of |
| * the queue configuration register |
| */ |
| #define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0x00 |
| #define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 0x07 |
| #define IX_QMGR_Q_CONFIG_BADDR_OFFSET 0x0E |
| #define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 0x16 |
| #define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 0x18 |
| #define IX_QMGR_Q_CONFIG_NE_OFFSET 0x1A |
| #define IX_QMGR_Q_CONFIG_NF_OFFSET 0x1D |
| |
| #define IX_QMGR_BASE_ADDR_16_WORD_ALIGN 0x40 |
| #define IX_QMGR_BASE_ADDR_16_WORD_SHIFT 0x6 |
| |
| #define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF |
| #define IX_QMGR_NE_MASK 0x7 |
| #define IX_QMGR_NF_MASK 0x7 |
| #define IX_QMGR_SIZE_MASK 0x3 |
| #define IX_QMGR_ENTRY_SIZE_MASK 0x3 |
| #define IX_QMGR_BADDR_MASK 0x003FC000 |
| #define IX_QMGR_RDPTR_MASK 0x7F |
| #define IX_QMGR_WRPTR_MASK 0x7F |
| #define IX_QMGR_RDWRPTR_MASK 0x00003FFF |
| |
| #define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000 |
| |
| /* Base address of AQM SRAM */ |
| #define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \ |
| ((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE)) |
| |
| /* Min buffer size used for generating buffer size in QUECONFIG */ |
| #define IX_QMGR_MIN_BUFFER_SIZE 16 |
| |
| /* Reset values of QMgr hardware registers */ |
| #define IX_QMGR_QUELOWSTAT_RESET_VALUE 0x33333333 |
| #define IX_QMGR_QUEUOSTAT_RESET_VALUE 0x00000000 |
| #define IX_QMGR_QUEUPPSTAT0_RESET_VALUE 0xFFFFFFFF |
| #define IX_QMGR_QUEUPPSTAT1_RESET_VALUE 0x00000000 |
| #define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000 |
| #define IX_QMGR_QUEIEREG_RESET_VALUE 0x00000000 |
| #define IX_QMGR_QINTREG_RESET_VALUE 0xFFFFFFFF |
| #define IX_QMGR_QUECONFIG_RESET_VALUE 0x00000000 |
| |
| #define IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS IX_OSAL_IXP400_QMGR_PHYS_BASE |
| |
| #define IX_QMGR_QUELOWSTAT_BITS_PER_Q (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) |
| |
| #define IX_QMGR_QUELOWSTAT_QID_MASK 0x7 |
| #define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\ |
| (((qId) * IX_QMGR_NUM_BYTES_PER_WORD) +\ |
| IX_QMGR_QUECONFIG_BASE_OFFSET) |
| |
| #define IX_QMGR_ENTRY1_OFFSET 0 |
| #define IX_QMGR_ENTRY2_OFFSET 1 |
| #define IX_QMGR_ENTRY4_OFFSET 3 |
| |
| /* |
| * Variable declarations global to this file. Externs are followed by |
| * statics. |
| */ |
| UINT32 aqmBaseAddress = 0; |
| /* Store addresses and bit-masks for certain queue access and status registers. |
| * This is to facilitate inlining of QRead, QWrite and QStatusGet functions |
| * in IxQMgr,h |
| */ |
| extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[]; |
| UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES]; |
| UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID]; |
| UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID]; |
| UINT32 ixQMgrAqmIfQueLowStatBitsMask; |
| UINT32 ixQMgrAqmIfQueUppStat0RegAddr; |
| UINT32 ixQMgrAqmIfQueUppStat1RegAddr; |
| UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID]; |
| UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID]; |
| |
| /* |
| * Fast mutexes, one for each queue, used to protect peek & poke functions |
| */ |
| IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES]; |
| |
| /* |
| * Function prototypes |
| */ |
| PRIVATE unsigned |
| watermarkToAqmWatermark (IxQMgrWMLevel watermark ); |
| |
| PRIVATE unsigned |
| entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize); |
| |
| PRIVATE unsigned |
| bufferSizeToAqmBufferSize (unsigned bufferSizeInWords); |
| |
| PRIVATE void |
| ixQMgrAqmIfRegistersReset (void); |
| |
| PRIVATE void |
| ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex, |
| UINT32 configRegWord, |
| unsigned int qEntrySizeInwords, |
| unsigned int qSizeInWords, |
| UINT32 **address); |
| /* |
| * Function definitions |
| */ |
| void |
| ixQMgrAqmIfInit (void) |
| { |
| UINT32 aqmVirtualAddr; |
| int i; |
| |
| /* The value of aqmBaseAddress depends on the logical address |
| * assigned by the MMU. |
| */ |
| aqmVirtualAddr = |
| (UINT32) IX_OSAL_MEM_MAP(IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS, |
| IX_OSAL_IXP400_QMGR_MAP_SIZE); |
| IX_OSAL_ASSERT (aqmVirtualAddr); |
| |
| ixQMgrAqmIfBaseAddressSet (aqmVirtualAddr); |
| |
| ixQMgrAqmIfRegistersReset (); |
| |
| for (i = 0; i< IX_QMGR_MAX_NUM_QUEUES; i++) |
| { |
| ixOsalFastMutexInit(&ixQMgrAqmIfPeekPokeFastMutex[i]); |
| |
| /******************************************************************** |
| * Register addresses and bit masks are calculated and stored here to |
| * facilitate inlining of QRead, QWrite and QStatusGet functions in |
| * IxQMgr.h. |
| * These calculations are normally performed dynamically in inlined |
| * functions in IxQMgrAqmIf_p.h, and their semantics are reused here. |
| */ |
| |
| /* AQM Queue access reg addresses, per queue */ |
| ixQMgrAqmIfQueAccRegAddr[i] = |
| (UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i)); |
| ixQMgrQInlinedReadWriteInfo[i].qAccRegAddr = |
| (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i)); |
| |
| |
| ixQMgrQInlinedReadWriteInfo[i].qConfigRegAddr = |
| (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(i)); |
| |
| /* AQM Queue lower-group (0-31), only */ |
| if (i < IX_QMGR_MIN_QUEUPP_QID) |
| { |
| /* AQM Q underflow/overflow status register addresses, per queue */ |
| ixQMgrQInlinedReadWriteInfo[i].qUOStatRegAddr = |
| (volatile UINT32 *)(aqmBaseAddress + |
| IX_QMGR_QUEUOSTAT0_OFFSET + |
| ((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) * |
| IX_QMGR_NUM_BYTES_PER_WORD)); |
| |
| /* AQM Q underflow status bit masks for status register per queue */ |
| ixQMgrQInlinedReadWriteInfo[i].qUflowStatBitMask = |
| (IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) << |
| ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) * |
| (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD)); |
| |
| /* AQM Q overflow status bit masks for status register, per queue */ |
| ixQMgrQInlinedReadWriteInfo[i].qOflowStatBitMask = |
| (IX_QMGR_OVERFLOW_BIT_OFFSET + 1) << |
| ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) * |
| (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD)); |
| |
| /* AQM Q lower-group (0-31) status register addresses, per queue */ |
| ixQMgrAqmIfQueLowStatRegAddr[i] = aqmBaseAddress + |
| IX_QMGR_QUELOWSTAT0_OFFSET + |
| ((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) * |
| IX_QMGR_NUM_BYTES_PER_WORD); |
| |
| /* AQM Q lower-group (0-31) status register bit offset */ |
| ixQMgrAqmIfQueLowStatBitsOffset[i] = |
| (i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) * |
| (BITS_PER_WORD / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD); |
| } |
| else /* AQM Q upper-group (32-63), only */ |
| { |
| /* AQM Q upper-group (32-63) Nearly Empty status reg bit masks */ |
| ixQMgrAqmIfQueUppStat0BitMask[i - IX_QMGR_MIN_QUEUPP_QID] = |
| (1 << (i - IX_QMGR_MIN_QUEUPP_QID)); |
| |
| /* AQM Q upper-group (32-63) Full status register bit masks */ |
| ixQMgrAqmIfQueUppStat1BitMask[i - IX_QMGR_MIN_QUEUPP_QID] = |
| (1 << (i - IX_QMGR_MIN_QUEUPP_QID)); |
| } |
| } |
| |
| /* AQM Q lower-group (0-31) status register bit mask */ |
| ixQMgrAqmIfQueLowStatBitsMask = (1 << |
| (BITS_PER_WORD / |
| IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1; |
| |
| /* AQM Q upper-group (32-63) Nearly Empty status register address */ |
| ixQMgrAqmIfQueUppStat0RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET; |
| |
| /* AQM Q upper-group (32-63) Full status register address */ |
| ixQMgrAqmIfQueUppStat1RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET; |
| } |
| |
| /* |
| * Uninitialise the AqmIf module by unmapping memory, etc |
| */ |
| void |
| ixQMgrAqmIfUninit (void) |
| { |
| UINT32 virtAddr; |
| |
| ixQMgrAqmIfBaseAddressGet (&virtAddr); |
| IX_OSAL_MEM_UNMAP (virtAddr); |
| ixQMgrAqmIfBaseAddressSet (0); |
| } |
| |
| /* |
| * Set the the logical base address of AQM |
| */ |
| void |
| ixQMgrAqmIfBaseAddressSet (UINT32 address) |
| { |
| aqmBaseAddress = address; |
| } |
| |
| /* |
| * Get the logical base address of AQM |
| */ |
| void |
| ixQMgrAqmIfBaseAddressGet (UINT32 *address) |
| { |
| *address = aqmBaseAddress; |
| } |
| |
| /* |
| * Get the logical base address of AQM SRAM |
| */ |
| void |
| ixQMgrAqmIfSramBaseAddressGet (UINT32 *address) |
| { |
| *address = aqmBaseAddress + |
| IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET; |
| } |
| |
| /* |
| * This function will write the status bits of a queue |
| * specified by qId. |
| */ |
| void |
| ixQMgrAqmIfQRegisterBitsWrite (IxQMgrQId qId, |
| UINT32 registerBaseAddrOffset, |
| unsigned queuesPerRegWord, |
| UINT32 value) |
| { |
| volatile UINT32 *registerAddress; |
| UINT32 registerWord; |
| UINT32 statusBitsMask; |
| UINT32 bitsPerQueue; |
| |
| bitsPerQueue = BITS_PER_WORD / queuesPerRegWord; |
| |
| /* |
| * Calculate the registerAddress |
| * multiple queues split accross registers |
| */ |
| registerAddress = (UINT32*)(aqmBaseAddress + |
| registerBaseAddrOffset + |
| ((qId / queuesPerRegWord) * |
| IX_QMGR_NUM_BYTES_PER_WORD)); |
| |
| /* Read the current data */ |
| ixQMgrAqmIfWordRead (registerAddress, ®isterWord); |
| |
| |
| if( (registerBaseAddrOffset == IX_QMGR_INT0SRCSELREG0_OFFSET) && |
| (qId == IX_QMGR_QUEUE_0) ) |
| { |
| statusBitsMask = 0x7 ; |
| |
| /* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3 */ |
| value &= 0x7 ; |
| } |
| else |
| { |
| /* Calculate the mask for the status bits for this queue. */ |
| statusBitsMask = ((1 << bitsPerQueue) - 1); |
| statusBitsMask <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue); |
| |
| /* Mask out bits in value that would overwrite other q data */ |
| value <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue); |
| value &= statusBitsMask; |
| } |
| |
| /* Mask out bits to write to */ |
| registerWord &= ~statusBitsMask; |
| |
| |
| /* Set the write bits */ |
| registerWord |= value; |
| |
| /* |
| * Write the data |
| */ |
| ixQMgrAqmIfWordWrite (registerAddress, registerWord); |
| } |
| |
| /* |
| * This function generates the parameters that can be used to |
| * check if a Qs status matches the specified source select. |
| * It calculates which status word to check (statusWordOffset), |
| * the value to check the status against (checkValue) and the |
| * mask (mask) to mask out all but the bits to check in the status word. |
| */ |
| void |
| ixQMgrAqmIfQStatusCheckValsCalc (IxQMgrQId qId, |
| IxQMgrSourceId srcSel, |
| unsigned int *statusWordOffset, |
| UINT32 *checkValue, |
| UINT32 *mask) |
| { |
| UINT32 shiftVal; |
| |
| if (qId < IX_QMGR_MIN_QUEUPP_QID) |
| { |
| switch (srcSel) |
| { |
| case IX_QMGR_Q_SOURCE_ID_E: |
| *checkValue = IX_QMGR_Q_STATUS_E_BIT_MASK; |
| *mask = IX_QMGR_Q_STATUS_E_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NE: |
| *checkValue = IX_QMGR_Q_STATUS_NE_BIT_MASK; |
| *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NF: |
| *checkValue = IX_QMGR_Q_STATUS_NF_BIT_MASK; |
| *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_F: |
| *checkValue = IX_QMGR_Q_STATUS_F_BIT_MASK; |
| *mask = IX_QMGR_Q_STATUS_F_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NOT_E: |
| *checkValue = 0; |
| *mask = IX_QMGR_Q_STATUS_E_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NOT_NE: |
| *checkValue = 0; |
| *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NOT_NF: |
| *checkValue = 0; |
| *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK; |
| break; |
| case IX_QMGR_Q_SOURCE_ID_NOT_F: |
| *checkValue = 0; |
| *mask = IX_QMGR_Q_STATUS_F_BIT_MASK; |
| break; |
| default: |
| /* Should never hit */ |
| IX_OSAL_ASSERT(0); |
| break; |
| } |
| |
| /* One nibble of status per queue so need to shift the |
| * check value and mask out to the correct position. |
| */ |
| shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) * |
| IX_QMGR_QUELOWSTAT_BITS_PER_Q; |
| |
| /* Calculate the which status word to check from the qId, |
| * 8 Qs status per word |
| */ |
| *statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD; |
| |
| *checkValue <<= shiftVal; |
| *mask <<= shiftVal; |
| } |
| else |
| { |
| /* One status word */ |
| *statusWordOffset = 0; |
| /* Single bits per queue and int source bit hardwired NE, |
| * Qs start at 32. |
| */ |
| *mask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID); |
| *checkValue = *mask; |
| } |
| } |
| |
| void |
| ixQMgrAqmIfQInterruptEnable (IxQMgrQId qId) |
| { |
| volatile UINT32 *registerAddress; |
| UINT32 registerWord; |
| UINT32 actualBitOffset; |
| |
| if (qId < IX_QMGR_MIN_QUEUPP_QID) |
| { |
| registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET); |
| } |
| else |
| { |
| registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET); |
| } |
| |
| actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID); |
| |
| ixQMgrAqmIfWordRead (registerAddress, ®isterWord); |
| ixQMgrAqmIfWordWrite (registerAddress, (registerWord | actualBitOffset)); |
| } |
| |
| void |
| ixQMgrAqmIfQInterruptDisable (IxQMgrQId qId) |
| { |
| volatile UINT32 *registerAddress; |
| UINT32 registerWord; |
| UINT32 actualBitOffset; |
| |
| if (qId < IX_QMGR_MIN_QUEUPP_QID) |
| { |
| registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET); |
| } |
| else |
| { |
| registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET); |
| } |
| |
| actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID); |
| |
| ixQMgrAqmIfWordRead (registerAddress, ®isterWord); |
| ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset)); |
| } |
| |
| void |
| ixQMgrAqmIfQueCfgWrite (IxQMgrQId qId, |
| IxQMgrQSizeInWords qSizeInWords, |
| IxQMgrQEntrySizeInWords entrySizeInWords, |
| UINT32 freeSRAMAddress) |
| { |
| volatile UINT32 *cfgAddress = NULL; |
| UINT32 qCfg = 0; |
| UINT32 baseAddress = 0; |
| unsigned aqmEntrySize = 0; |
| unsigned aqmBufferSize = 0; |
| |
| /* Build config register */ |
| aqmEntrySize = entrySizeToAqmEntrySize (entrySizeInWords); |
| qCfg |= (aqmEntrySize&IX_QMGR_ENTRY_SIZE_MASK) << |
| IX_QMGR_Q_CONFIG_ESIZE_OFFSET; |
| |
| aqmBufferSize = bufferSizeToAqmBufferSize (qSizeInWords); |
| qCfg |= (aqmBufferSize&IX_QMGR_SIZE_MASK) << IX_QMGR_Q_CONFIG_BSIZE_OFFSET; |
| |
| /* baseAddress, calculated relative to aqmBaseAddress and start address */ |
| baseAddress = freeSRAMAddress - |
| (aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET); |
| |
| /* Verify base address aligned to a 16 word boundary */ |
| if ((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) != 0) |
| { |
| IX_QMGR_LOG_ERROR0("ixQMgrAqmIfQueCfgWrite () address is not on 16 word boundary\n"); |
| } |
| /* Now convert it to a 16 word pointer as required by QUECONFIG register */ |
| baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT; |
| |
| |
| qCfg |= (baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET); |
| |
| |
| cfgAddress = (UINT32*)(aqmBaseAddress + |
| IX_QMGR_Q_CONFIG_ADDR_GET(qId)); |
| |
| |
| /* NOTE: High and Low watermarks are set to zero */ |
| ixQMgrAqmIfWordWrite (cfgAddress, qCfg); |
| } |
| |
| void |
| ixQMgrAqmIfQueCfgRead (IxQMgrQId qId, |
| unsigned int numEntries, |
| UINT32 *baseAddress, |
| unsigned int *ne, |
| unsigned int *nf, |
| UINT32 *readPtr, |
| UINT32 *writePtr) |
| { |
| UINT32 qcfg; |
| UINT32 *cfgAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId)); |
| unsigned int qEntrySizeInwords; |
| unsigned int qSizeInWords; |
| UINT32 *readPtr_ = NULL; |
| |
| /* Read the queue configuration register */ |
| ixQMgrAqmIfWordRead (cfgAddress, &qcfg); |
| |
| /* Extract the base address */ |
| *baseAddress = (UINT32)((qcfg & IX_QMGR_BADDR_MASK) >> |
| (IX_QMGR_Q_CONFIG_BADDR_OFFSET)); |
| |
| /* Base address is a 16 word pointer from the start of AQM SRAM. |
| * Convert to absolute word address. |
| */ |
| *baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT; |
| *baseAddress += (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET; |
| |
| /* |
| * Extract the watermarks. 0->0 entries, 1->1 entries, 2->2 entries, 3->4 entries...... |
| * If ne > 0 ==> neInEntries = 2^(ne - 1) |
| * If ne == 0 ==> neInEntries = 0 |
| * The same applies. |
| */ |
| *ne = ((qcfg) >> (IX_QMGR_Q_CONFIG_NE_OFFSET)) & IX_QMGR_NE_MASK; |
| *nf = ((qcfg) >> (IX_QMGR_Q_CONFIG_NF_OFFSET)) & IX_QMGR_NF_MASK; |
| |
| if (0 != *ne) |
| { |
| *ne = 1 << (*ne - 1); |
| } |
| if (0 != *nf) |
| { |
| *nf = 1 << (*nf - 1); |
| } |
| |
| /* Get the queue entry size in words */ |
| qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId); |
| |
| /* Get the queue size in words */ |
| qSizeInWords = ixQMgrQSizeInWordsGet (qId); |
| |
| ixQMgrAqmIfEntryAddressGet (0/* Entry 0. i.e the readPtr*/, |
| qcfg, |
| qEntrySizeInwords, |
| qSizeInWords, |
| &readPtr_); |
| *readPtr = (UINT32)readPtr_; |
| *readPtr -= (UINT32)aqmBaseAddress;/* Offset, not absolute address */ |
| |
| *writePtr = (qcfg >> IX_QMGR_Q_CONFIG_WRPTR_OFFSET) & IX_QMGR_WRPTR_MASK; |
| *writePtr = *baseAddress + (*writePtr * (IX_QMGR_NUM_BYTES_PER_WORD)); |
| return; |
| } |
| |
| unsigned |
| ixQMgrAqmIfLog2 (unsigned number) |
| { |
| unsigned count = 0; |
| |
| /* |
| * N.B. this function will return 0 |
| * for ixQMgrAqmIfLog2 (0) |
| */ |
| while (number/2) |
| { |
| number /=2; |
| count++; |
| } |
| |
| return count; |
| } |
| |
| void ixQMgrAqmIfIntSrcSelReg0Bit3Set (void) |
| { |
| |
| volatile UINT32 *registerAddress; |
| UINT32 registerWord; |
| |
| /* |
| * Calculate the registerAddress |
| * multiple queues split accross registers |
| */ |
| registerAddress = (UINT32*)(aqmBaseAddress + |
| IX_QMGR_INT0SRCSELREG0_OFFSET); |
| |
| /* Read the current data */ |
| ixQMgrAqmIfWordRead (registerAddress, ®isterWord); |
| |
| /* Set the write bits */ |
| registerWord |= (1<<IX_QMGR_INT0SRCSELREG0_BIT3) ; |
| |
| /* |
| * Write the data |
| */ |
| ixQMgrAqmIfWordWrite (registerAddress, registerWord); |
| } |
| |
| |
| void |
| ixQMgrAqmIfIntSrcSelWrite (IxQMgrQId qId, |
| IxQMgrSourceId sourceId) |
| { |
| ixQMgrAqmIfQRegisterBitsWrite (qId, |
| IX_QMGR_INT0SRCSELREG0_OFFSET, |
| IX_QMGR_INTSRC_NUM_QUE_PER_WORD, |
| sourceId); |
| } |
| |
| |
| |
| void |
| ixQMgrAqmIfWatermarkSet (IxQMgrQId qId, |
| unsigned ne, |
| unsigned nf) |
| { |
| volatile UINT32 *address = 0; |
| UINT32 value = 0; |
| unsigned aqmNeWatermark = 0; |
| unsigned aqmNfWatermark = 0; |
| |
| address = (UINT32*)(aqmBaseAddress + |
| IX_QMGR_Q_CONFIG_ADDR_GET(qId)); |
| |
| aqmNeWatermark = watermarkToAqmWatermark (ne); |
| aqmNfWatermark = watermarkToAqmWatermark (nf); |
| |
| /* Read the current watermarks */ |
| ixQMgrAqmIfWordRead (address, &value); |
| |
| /* Clear out the old watermarks */ |
| value &= IX_QMGR_NE_NF_CLEAR_MASK; |
| |
| /* Generate the value to write */ |
| value |= (aqmNeWatermark << IX_QMGR_Q_CONFIG_NE_OFFSET) | |
| (aqmNfWatermark << IX_QMGR_Q_CONFIG_NF_OFFSET); |
| |
| ixQMgrAqmIfWordWrite (address, value); |
| |
| } |
| |
| PRIVATE void |
| ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex, |
| UINT32 configRegWord, |
| unsigned int qEntrySizeInwords, |
| unsigned int qSizeInWords, |
| UINT32 **address) |
| { |
| UINT32 readPtr; |
| UINT32 baseAddress; |
| UINT32 *topOfAqmSram; |
| |
| topOfAqmSram = ((UINT32 *)aqmBaseAddress + IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS); |
| |
| /* Extract the base address */ |
| baseAddress = (UINT32)((configRegWord & IX_QMGR_BADDR_MASK) >> |
| (IX_QMGR_Q_CONFIG_BADDR_OFFSET)); |
| |
| /* Base address is a 16 word pointer from the start of AQM SRAM. |
| * Convert to absolute word address. |
| */ |
| baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT; |
| baseAddress += ((UINT32)aqmBaseAddress + (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET); |
| |
| /* Extract the read pointer. Read pointer is a word pointer */ |
| readPtr = (UINT32)((configRegWord >> |
| IX_QMGR_Q_CONFIG_RDPTR_OFFSET)&IX_QMGR_RDPTR_MASK); |
| |
| /* Read/Write pointers(word pointers) are offsets from the queue buffer space base address. |
| * Calculate the absolute read pointer address. NOTE: Queues are circular buffers. |
| */ |
| readPtr = (readPtr + (entryIndex * qEntrySizeInwords)) & (qSizeInWords - 1); /* Mask by queue size */ |
| *address = (UINT32 *)(baseAddress + (readPtr * (IX_QMGR_NUM_BYTES_PER_WORD))); |
| |
| switch (qEntrySizeInwords) |
| { |
| case IX_QMGR_Q_ENTRY_SIZE1: |
| IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY1_OFFSET) < topOfAqmSram); |
| break; |
| case IX_QMGR_Q_ENTRY_SIZE2: |
| IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY2_OFFSET) < topOfAqmSram); |
| break; |
| case IX_QMGR_Q_ENTRY_SIZE4: |
| IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY4_OFFSET) < topOfAqmSram); |
| break; |
| default: |
| IX_QMGR_LOG_ERROR0("Invalid Q Entry size passed to ixQMgrAqmIfEntryAddressGet"); |
| break; |
| } |
| |
| } |
| |
| IX_STATUS |
| ixQMgrAqmIfQPeek (IxQMgrQId qId, |
| unsigned int entryIndex, |
| unsigned int *entry) |
| { |
| UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId)); |
| UINT32 *entryAddress = NULL; |
| UINT32 configRegWordOnEntry; |
| UINT32 configRegWordOnExit; |
| unsigned int qEntrySizeInwords; |
| unsigned int qSizeInWords; |
| |
| /* Get the queue entry size in words */ |
| qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId); |
| |
| /* Get the queue size in words */ |
| qSizeInWords = ixQMgrQSizeInWordsGet (qId); |
| |
| /* Read the config register */ |
| ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry); |
| |
| /* Get the entry address */ |
| ixQMgrAqmIfEntryAddressGet (entryIndex, |
| configRegWordOnEntry, |
| qEntrySizeInwords, |
| qSizeInWords, |
| &entryAddress); |
| |
| /* Get the lock or return busy */ |
| if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId])) |
| { |
| return IX_FAIL; |
| } |
| |
| while(qEntrySizeInwords--) |
| { |
| ixQMgrAqmIfWordRead (entryAddress++, entry++); |
| } |
| |
| /* Release the lock */ |
| ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]); |
| |
| /* Read the config register */ |
| ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit); |
| |
| /* Check that the read and write pointers have not changed */ |
| if (configRegWordOnEntry != configRegWordOnExit) |
| { |
| return IX_FAIL; |
| } |
| |
| return IX_SUCCESS; |
| } |
| |
| IX_STATUS |
| ixQMgrAqmIfQPoke (IxQMgrQId qId, |
| unsigned entryIndex, |
| unsigned int *entry) |
| { |
| UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId)); |
| UINT32 *entryAddress = NULL; |
| UINT32 configRegWordOnEntry; |
| UINT32 configRegWordOnExit; |
| unsigned int qEntrySizeInwords; |
| unsigned int qSizeInWords; |
| |
| /* Get the queue entry size in words */ |
| qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId); |
| |
| /* Get the queue size in words */ |
| qSizeInWords = ixQMgrQSizeInWordsGet (qId); |
| |
| /* Read the config register */ |
| ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry); |
| |
| /* Get the entry address */ |
| ixQMgrAqmIfEntryAddressGet (entryIndex, |
| configRegWordOnEntry, |
| qEntrySizeInwords, |
| qSizeInWords, |
| &entryAddress); |
| |
| /* Get the lock or return busy */ |
| if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId])) |
| { |
| return IX_FAIL; |
| } |
| |
| /* Else read the entry directly from SRAM. This will not move the read pointer */ |
| while(qEntrySizeInwords--) |
| { |
| ixQMgrAqmIfWordWrite (entryAddress++, *entry++); |
| } |
| |
| /* Release the lock */ |
| ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]); |
| |
| /* Read the config register */ |
| ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit); |
| |
| /* Check that the read and write pointers have not changed */ |
| if (configRegWordOnEntry != configRegWordOnExit) |
| { |
| return IX_FAIL; |
| } |
| |
| return IX_SUCCESS; |
| } |
| |
| PRIVATE unsigned |
| watermarkToAqmWatermark (IxQMgrWMLevel watermark ) |
| { |
| unsigned aqmWatermark = 0; |
| |
| /* |
| * Watermarks 0("000"),1("001"),2("010"),4("011"), |
| * 8("100"),16("101"),32("110"),64("111") |
| */ |
| aqmWatermark = ixQMgrAqmIfLog2 (watermark * 2); |
| |
| return aqmWatermark; |
| } |
| |
| PRIVATE unsigned |
| entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize) |
| { |
| /* entrySize 1("00"),2("01"),4("10") */ |
| return (ixQMgrAqmIfLog2 (entrySize)); |
| } |
| |
| PRIVATE unsigned |
| bufferSizeToAqmBufferSize (unsigned bufferSizeInWords) |
| { |
| /* bufferSize 16("00"),32("01),64("10"),128("11") */ |
| return (ixQMgrAqmIfLog2 (bufferSizeInWords / IX_QMGR_MIN_BUFFER_SIZE)); |
| } |
| |
| /* |
| * Reset AQM registers to default values. |
| */ |
| PRIVATE void |
| ixQMgrAqmIfRegistersReset (void) |
| { |
| volatile UINT32 *qConfigWordAddress = NULL; |
| unsigned int i; |
| |
| /* |
| * Need to initialize AQM hardware registers to an initial |
| * value as init may have been called as a result of a soft |
| * reset. i.e. soft reset does not reset hardware registers. |
| */ |
| |
| /* Reset queues 0..31 status registers 0..3 */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT0_OFFSET), |
| IX_QMGR_QUELOWSTAT_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT1_OFFSET), |
| IX_QMGR_QUELOWSTAT_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT2_OFFSET), |
| IX_QMGR_QUELOWSTAT_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT3_OFFSET), |
| IX_QMGR_QUELOWSTAT_RESET_VALUE); |
| |
| /* Reset underflow/overflow status registers 0..1 */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT0_OFFSET), |
| IX_QMGR_QUEUOSTAT_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT1_OFFSET), |
| IX_QMGR_QUEUOSTAT_RESET_VALUE); |
| |
| /* Reset queues 32..63 nearly empty status registers */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET), |
| IX_QMGR_QUEUPPSTAT0_RESET_VALUE); |
| |
| /* Reset queues 32..63 full status registers */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET), |
| IX_QMGR_QUEUPPSTAT1_RESET_VALUE); |
| |
| /* Reset int0 status flag source select registers 0..3 */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG0_OFFSET), |
| IX_QMGR_INT0SRCSELREG_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG1_OFFSET), |
| IX_QMGR_INT0SRCSELREG_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG2_OFFSET), |
| IX_QMGR_INT0SRCSELREG_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG3_OFFSET), |
| IX_QMGR_INT0SRCSELREG_RESET_VALUE); |
| |
| /* Reset queue interrupt enable register 0..1 */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET), |
| IX_QMGR_QUEIEREG_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET), |
| IX_QMGR_QUEIEREG_RESET_VALUE); |
| |
| /* Reset queue interrupt register 0..1 */ |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG0_OFFSET), |
| IX_QMGR_QINTREG_RESET_VALUE); |
| ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG1_OFFSET), |
| IX_QMGR_QINTREG_RESET_VALUE); |
| |
| /* Reset queue configuration words 0..63 */ |
| qConfigWordAddress = (UINT32 *)(aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET); |
| for (i = 0; i < (IX_QMGR_QUECONFIG_SIZE / sizeof(UINT32)); i++) |
| { |
| ixQMgrAqmIfWordWrite(qConfigWordAddress, |
| IX_QMGR_QUECONFIG_RESET_VALUE); |
| /* Next word */ |
| qConfigWordAddress++; |
| } |
| } |
| |