summaryrefslogtreecommitdiffstats
path: root/arch/arm/cpu/ixp/npe/IxQMgrQAccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu/ixp/npe/IxQMgrQAccess.c')
-rw-r--r--arch/arm/cpu/ixp/npe/IxQMgrQAccess.c796
1 files changed, 796 insertions, 0 deletions
diff --git a/arch/arm/cpu/ixp/npe/IxQMgrQAccess.c b/arch/arm/cpu/ixp/npe/IxQMgrQAccess.c
new file mode 100644
index 0000000000..8885736246
--- /dev/null
+++ b/arch/arm/cpu/ixp/npe/IxQMgrQAccess.c
@@ -0,0 +1,796 @@
+/**
+ * @file IxQMgrQAccess.c
+ *
+ * @author Intel Corporation
+ * @date 30-Oct-2001
+ *
+ * @brief This file contains functions for putting entries on a queue and
+ * removing entries from a queue.
+ *
+ *
+ * @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 "IxQMgr.h"
+ */
+#ifndef IXQMGR_H
+# define IXQMGRQACCESS_C
+#else
+# error
+#endif
+
+/*
+ * System defined include files.
+ */
+
+/*
+ * User defined include files.
+ */
+#include "IxQMgr.h"
+#include "IxQMgrAqmIf_p.h"
+#include "IxQMgrQAccess_p.h"
+#include "IxQMgrQCfg_p.h"
+#include "IxQMgrDefines_p.h"
+
+/*
+ * Global variables and extern definitions
+ */
+extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+
+/*
+ * Function definitions.
+ */
+void
+ixQMgrQAccessInit (void)
+{
+}
+
+IX_STATUS
+ixQMgrQReadWithChecks (IxQMgrQId qId,
+ UINT32 *entry)
+{
+ IxQMgrQEntrySizeInWords entrySizeInWords;
+ IxQMgrQInlinedReadWriteInfo *infoPtr;
+
+ if (NULL == entry)
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ /* Check QId */
+ if (!ixQMgrQIsConfigured(qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+
+ /* Get the q entry size in words */
+ entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
+
+ ixQMgrAqmIfQPop (qId, entrySizeInWords, entry);
+
+ /* reset the current read count if the counter wrapped around
+ * (unsigned arithmetic)
+ */
+ infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ if (infoPtr->qReadCount-- > infoPtr->qSizeInEntries)
+ {
+ infoPtr->qReadCount = 0;
+ }
+
+ /* Check if underflow occurred on the read */
+ if (ixQMgrAqmIfUnderflowCheck (qId))
+ {
+ return IX_QMGR_Q_UNDERFLOW;
+ }
+
+ return IX_SUCCESS;
+}
+
+/* this function reads the remaining of the q entry
+ * for queues configured with many words.
+ * (the first word of the entry is already read
+ * in the inlined function and the entry pointer already
+ * incremented
+ */
+IX_STATUS
+ixQMgrQReadMWordsMinus1 (IxQMgrQId qId,
+ UINT32 *entry)
+{
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ UINT32 entrySize = infoPtr->qEntrySizeInWords;
+ volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
+
+ while (--entrySize)
+ {
+ /* read the entry and accumulate the result */
+ *(++entry) = IX_OSAL_READ_LONG(++qAccRegAddr);
+ }
+ /* underflow is available for lower queues only */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ /* get the queue status */
+ UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
+
+ /* check the underflow status */
+ if (status & infoPtr->qUflowStatBitMask)
+ {
+ /* the queue is empty
+ * clear the underflow status bit if it was set
+ */
+ IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
+ status & ~infoPtr->qUflowStatBitMask);
+ return IX_QMGR_Q_UNDERFLOW;
+ }
+ }
+ return IX_SUCCESS;
+}
+
+IX_STATUS
+ixQMgrQWriteWithChecks (IxQMgrQId qId,
+ UINT32 *entry)
+{
+ IxQMgrQEntrySizeInWords entrySizeInWords;
+ IxQMgrQInlinedReadWriteInfo *infoPtr;
+
+ if (NULL == entry)
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ /* Check QId */
+ if (!ixQMgrQIsConfigured(qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+
+ /* Get the q entry size in words */
+ entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
+
+ ixQMgrAqmIfQPush (qId, entrySizeInWords, entry);
+
+ /* reset the current read count if the counter wrapped around
+ * (unsigned arithmetic)
+ */
+ infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ if (infoPtr->qWriteCount++ >= infoPtr->qSizeInEntries)
+ {
+ infoPtr->qWriteCount = infoPtr->qSizeInEntries;
+ }
+
+ /* Check if overflow occurred on the write*/
+ if (ixQMgrAqmIfOverflowCheck (qId))
+ {
+ return IX_QMGR_Q_OVERFLOW;
+ }
+
+ return IX_SUCCESS;
+}
+
+IX_STATUS
+ixQMgrQPeek (IxQMgrQId qId,
+ unsigned int entryIndex,
+ UINT32 *entry)
+{
+ unsigned int numEntries;
+
+#ifndef NDEBUG
+ if ((NULL == entry) || (entryIndex >= IX_QMGR_Q_SIZE_INVALID))
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ if (!ixQMgrQIsConfigured(qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+#endif
+
+ if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
+ {
+ return IX_FAIL;
+ }
+
+ if (entryIndex >= numEntries) /* entryIndex starts at 0 */
+ {
+ return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
+ }
+
+ return ixQMgrAqmIfQPeek (qId, entryIndex, entry);
+}
+
+IX_STATUS
+ixQMgrQPoke (IxQMgrQId qId,
+ unsigned entryIndex,
+ UINT32 *entry)
+{
+ unsigned int numEntries;
+
+#ifndef NDEBUG
+ if ((NULL == entry) || (entryIndex > 128))
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ if (!ixQMgrQIsConfigured(qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+#endif
+
+ if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
+ {
+ return IX_FAIL;
+ }
+
+ if (numEntries < (entryIndex + 1)) /* entryIndex starts at 0 */
+ {
+ return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
+ }
+
+ return ixQMgrAqmIfQPoke (qId, entryIndex, entry);
+}
+
+IX_STATUS
+ixQMgrQStatusGetWithChecks (IxQMgrQId qId,
+ IxQMgrQStatus *qStatus)
+{
+ if (NULL == qStatus)
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ if (!ixQMgrQIsConfigured (qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+
+ ixQMgrAqmIfQueStatRead (qId, qStatus);
+
+ return IX_SUCCESS;
+}
+
+IX_STATUS
+ixQMgrQNumEntriesGet (IxQMgrQId qId,
+ unsigned *numEntriesPtr)
+{
+ UINT32 qPtrs;
+ UINT32 qStatus;
+ unsigned numEntries;
+ IxQMgrQInlinedReadWriteInfo *infoPtr;
+
+
+#ifndef NDEBUG
+ if (NULL == numEntriesPtr)
+ {
+ return IX_QMGR_PARAMETER_ERROR;
+ }
+
+ /* Check QId */
+ if (!ixQMgrQIsConfigured(qId))
+ {
+ return IX_QMGR_Q_NOT_CONFIGURED;
+ }
+#endif
+
+ /* get fast access data */
+ infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+
+ /* get snapshot */
+ qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
+
+ /* Mod subtraction of pointers to get number of words in Q. */
+ numEntries = (qPtrs - (qPtrs >> 7)) & 0x7f;
+
+ if (numEntries == 0)
+ {
+ /*
+ * Could mean either full or empty queue
+ * so look at status
+ */
+ ixQMgrAqmIfQueStatRead (qId, &qStatus);
+
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ if (qStatus & IX_QMGR_Q_STATUS_E_BIT_MASK)
+ {
+ /* Empty */
+ *numEntriesPtr = 0;
+ }
+ else if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
+ {
+ /* Full */
+ *numEntriesPtr = infoPtr->qSizeInEntries;
+ }
+ else
+ {
+ /*
+ * Queue status and read/write pointers are volatile.
+ * The queue state has changed since we took the
+ * snapshot of the read and write pointers.
+ * Client can retry if they wish
+ */
+ *numEntriesPtr = 0;
+ return IX_QMGR_WARNING;
+ }
+ }
+ else /* It is an upper queue which does not have an empty status bit maintained */
+ {
+ if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
+ {
+ /* The queue is Full at the time of snapshot. */
+ *numEntriesPtr = infoPtr->qSizeInEntries;
+ }
+ else
+ {
+ /* The queue is either empty, either moving,
+ * Client can retry if they wish
+ */
+ *numEntriesPtr = 0;
+ return IX_QMGR_WARNING;
+ }
+ }
+ }
+ else
+ {
+ *numEntriesPtr = (numEntries / infoPtr->qEntrySizeInWords) & (infoPtr->qSizeInEntries - 1);
+ }
+
+ return IX_SUCCESS;
+}
+
+#if defined(__wince) && defined(NO_INLINE_APIS)
+
+PUBLIC IX_STATUS
+ixQMgrQRead (IxQMgrQId qId,
+ UINT32 *entryPtr)
+{
+ extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ UINT32 entry, entrySize;
+
+ /* get a new entry */
+ entrySize = infoPtr->qEntrySizeInWords;
+ entry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
+
+ if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
+ {
+ *entryPtr = entry;
+ /* process the remaining part of the entry */
+ return ixQMgrQReadMWordsMinus1(qId, entryPtr);
+ }
+
+ /* underflow is available for lower queues only */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ /* the counter of queue entries is decremented. In happy
+ * day scenario there are many entries in the queue
+ * and the counter does not reach zero.
+ */
+ if (infoPtr->qReadCount-- == 0)
+ {
+ /* There is maybe no entry in the queue
+ * qReadCount is now negative, but will be corrected before
+ * the function returns.
+ */
+ UINT32 qPtrs; /* queue internal pointers */
+
+ /* when a queue is empty, the hw guarantees to return
+ * a null value. If the value is not null, the queue is
+ * not empty.
+ */
+ if (entry == 0)
+ {
+ /* get the queue status */
+ UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
+
+ /* check the underflow status */
+ if (status & infoPtr->qUflowStatBitMask)
+ {
+ /* the queue is empty
+ * clear the underflow status bit if it was set
+ */
+ IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
+ status & ~infoPtr->qUflowStatBitMask);
+ *entryPtr = 0;
+ infoPtr->qReadCount = 0;
+ return IX_QMGR_Q_UNDERFLOW;
+ }
+ }
+ /* store the result */
+ *entryPtr = entry;
+
+ /* No underflow occured : someone is filling the queue
+ * or the queue contains null entries.
+ * The current counter needs to be
+ * updated from the current number of entries in the queue
+ */
+
+ /* get snapshot of queue pointers */
+ qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
+
+ /* Mod subtraction of pointers to get number of words in Q. */
+ qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
+
+ if (qPtrs == 0)
+ {
+ /* no entry in the queue */
+ infoPtr->qReadCount = 0;
+ }
+ else
+ {
+ /* convert the number of words inside the queue
+ * to a number of entries
+ */
+ infoPtr->qReadCount = qPtrs & (infoPtr->qSizeInEntries - 1);
+ }
+ return IX_SUCCESS;
+ }
+ }
+ *entryPtr = entry;
+ return IX_SUCCESS;
+}
+
+PUBLIC IX_STATUS
+ixQMgrQBurstRead (IxQMgrQId qId,
+ UINT32 numEntries,
+ UINT32 *entries)
+{
+ extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ UINT32 nullCheckEntry;
+
+ if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
+ {
+ volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
+
+ /* the code is optimized to take care of data dependencies:
+ * Durig a read, there are a few cycles needed to get the
+ * read complete. During these cycles, it is poossible to
+ * do some CPU, e.g. increment pointers and decrement
+ * counters.
+ */
+
+ /* fetch a queue entry */
+ nullCheckEntry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
+
+ /* iterate the specified number of queue entries */
+ while (--numEntries)
+ {
+ /* check the result of the previous read */
+ if (nullCheckEntry == 0)
+ {
+ /* if we read a NULL entry, stop. We have underflowed */
+ break;
+ }
+ else
+ {
+ /* write the entry */
+ *entries = nullCheckEntry;
+ /* fetch next entry */
+ nullCheckEntry = IX_OSAL_READ_LONG(qAccRegAddr);
+ /* increment the write address */
+ entries++;
+ }
+ }
+ /* write the pre-fetched entry */
+ *entries = nullCheckEntry;
+ }
+ else
+ {
+ IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
+ /* read the specified number of queue entries */
+ nullCheckEntry = 0;
+ while (numEntries--)
+ {
+ int i;
+
+ for (i = 0; i < entrySizeInWords; i++)
+ {
+ *entries = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr + i);
+ nullCheckEntry |= *entries++;
+ }
+
+ /* if we read a NULL entry, stop. We have underflowed */
+ if (nullCheckEntry == 0)
+ {
+ break;
+ }
+ nullCheckEntry = 0;
+ }
+ }
+
+ /* reset the current read count : next access to the read function
+ * will force a underflow status check
+ */
+ infoPtr->qWriteCount = 0;
+
+ /* Check if underflow occurred on the read */
+ if (nullCheckEntry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ /* get the queue status */
+ UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
+
+ if (status & infoPtr->qUflowStatBitMask)
+ {
+ /* clear the underflow status bit if it was set */
+ IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
+ status & ~infoPtr->qUflowStatBitMask);
+ return IX_QMGR_Q_UNDERFLOW;
+ }
+ }
+
+ return IX_SUCCESS;
+}
+
+PUBLIC IX_STATUS
+ixQMgrQWrite (IxQMgrQId qId,
+ UINT32 *entry)
+{
+ extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ UINT32 entrySize;
+
+ /* write the entry */
+ IX_OSAL_WRITE_LONG(infoPtr->qAccRegAddr, *entry);
+ entrySize = infoPtr->qEntrySizeInWords;
+
+ if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
+ {
+ /* process the remaining part of the entry */
+ volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
+ while (--entrySize)
+ {
+ ++entry;
+ IX_OSAL_WRITE_LONG(++qAccRegAddr, *entry);
+ }
+ entrySize = infoPtr->qEntrySizeInWords;
+ }
+
+ /* overflow is available for lower queues only */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ UINT32 qSize = infoPtr->qSizeInEntries;
+ /* increment the current number of entries in the queue
+ * and check for overflow
+ */
+ if (infoPtr->qWriteCount++ == qSize)
+ {
+ /* the queue may have overflow */
+ UINT32 qPtrs; /* queue internal pointers */
+
+ /* get the queue status */
+ UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
+
+ /* read the status twice because the status may
+ * not be immediately ready after the write operation
+ */
+ if ((status & infoPtr->qOflowStatBitMask) ||
+ ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
+ & infoPtr->qOflowStatBitMask))
+ {
+ /* the queue is full, clear the overflow status
+ * bit if it was set
+ */
+ IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
+ status & ~infoPtr->qOflowStatBitMask);
+ infoPtr->qWriteCount = infoPtr->qSizeInEntries;
+ return IX_QMGR_Q_OVERFLOW;
+ }
+ /* No overflow occured : someone is draining the queue
+ * and the current counter needs to be
+ * updated from the current number of entries in the queue
+ */
+
+ /* get q pointer snapshot */
+ qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
+
+ /* Mod subtraction of pointers to get number of words in Q. */
+ qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
+
+ if (qPtrs == 0)
+ {
+ /* the queue may be full at the time of the
+ * snapshot. Next access will check
+ * the overflow status again.
+ */
+ infoPtr->qWriteCount = qSize;
+ }
+ else
+ {
+ /* convert the number of words to a number of entries */
+ if (entrySize == IX_QMGR_Q_ENTRY_SIZE1)
+ {
+ infoPtr->qWriteCount = qPtrs & (qSize - 1);
+ }
+ else
+ {
+ infoPtr->qWriteCount = (qPtrs / entrySize) & (qSize - 1);
+ }
+ }
+ }
+ }
+ return IX_SUCCESS;
+}
+
+PUBLIC IX_STATUS
+ixQMgrQBurstWrite (IxQMgrQId qId,
+ unsigned numEntries,
+ UINT32 *entries)
+{
+ extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ UINT32 status;
+
+ /* update the current write count */
+ infoPtr->qWriteCount += numEntries;
+
+ if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
+ {
+ volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
+ while (numEntries--)
+ {
+ IX_OSAL_WRITE_LONG(qAccRegAddr, *entries);
+ entries++;
+ }
+ }
+ else
+ {
+ IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
+ int i;
+
+ /* write each queue entry */
+ while (numEntries--)
+ {
+ /* write the queueEntrySize number of words for each entry */
+ for (i = 0; i < entrySizeInWords; i++)
+ {
+ IX_OSAL_WRITE_LONG((infoPtr->qAccRegAddr + i), *entries);
+ entries++;
+ }
+ }
+ }
+
+ /* check if the write count overflows */
+ if (infoPtr->qWriteCount > infoPtr->qSizeInEntries)
+ {
+ /* reset the current write count */
+ infoPtr->qWriteCount = infoPtr->qSizeInEntries;
+ }
+
+ /* Check if overflow occurred on the write operation */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ /* get the queue status */
+ status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
+
+ /* read the status twice because the status may
+ * not be ready at the time of the write
+ */
+ if ((status & infoPtr->qOflowStatBitMask) ||
+ ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
+ & infoPtr->qOflowStatBitMask))
+ {
+ /* clear the underflow status bit if it was set */
+ IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
+ status & ~infoPtr->qOflowStatBitMask);
+ return IX_QMGR_Q_OVERFLOW;
+ }
+ }
+
+ return IX_SUCCESS;
+}
+
+PUBLIC IX_STATUS
+ixQMgrQStatusGet (IxQMgrQId qId,
+ IxQMgrQStatus *qStatus)
+{
+ /* read the status of a queue in the range 0-31 */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ {
+ extern UINT32 ixQMgrAqmIfQueLowStatRegAddr[];
+ extern UINT32 ixQMgrAqmIfQueLowStatBitsOffset[];
+ extern UINT32 ixQMgrAqmIfQueLowStatBitsMask;
+ extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
+ IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
+ volatile UINT32 *lowStatRegAddr = (UINT32*)ixQMgrAqmIfQueLowStatRegAddr[qId];
+ volatile UINT32 *qUOStatRegAddr = infoPtr->qUOStatRegAddr;
+
+ UINT32 lowStatBitsOffset = ixQMgrAqmIfQueLowStatBitsOffset[qId];
+ UINT32 lowStatBitsMask = ixQMgrAqmIfQueLowStatBitsMask;
+ UINT32 underflowBitMask = infoPtr->qUflowStatBitMask;
+ UINT32 overflowBitMask = infoPtr->qOflowStatBitMask;
+
+ /* read the status register for this queue */
+ *qStatus = IX_OSAL_READ_LONG(lowStatRegAddr);
+ /* mask out the status bits relevant only to this queue */
+ *qStatus = (*qStatus >> lowStatBitsOffset) & lowStatBitsMask;
+
+ /* Check if the queue has overflowed */
+ if (IX_OSAL_READ_LONG(qUOStatRegAddr) & overflowBitMask)
+ {
+ /* clear the overflow status bit if it was set */
+ IX_OSAL_WRITE_LONG(qUOStatRegAddr,
+ (IX_OSAL_READ_LONG(qUOStatRegAddr) &
+ ~overflowBitMask));
+ *qStatus |= IX_QMGR_Q_STATUS_OF_BIT_MASK;
+ }
+
+ /* Check if the queue has underflowed */
+ if (IX_OSAL_READ_LONG(qUOStatRegAddr) & underflowBitMask)
+ {
+ /* clear the underflow status bit if it was set */
+ IX_OSAL_WRITE_LONG(qUOStatRegAddr,
+ (IX_OSAL_READ_LONG(qUOStatRegAddr) &
+ ~underflowBitMask));
+ *qStatus |= IX_QMGR_Q_STATUS_UF_BIT_MASK;
+ }
+ }
+ else /* read status of a queue in the range 32-63 */
+ {
+ extern UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
+ extern UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
+ extern UINT32 ixQMgrAqmIfQueUppStat0BitMask[];
+ extern UINT32 ixQMgrAqmIfQueUppStat1BitMask[];
+
+ volatile UINT32 *qNearEmptyStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat0RegAddr;
+ volatile UINT32 *qFullStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat1RegAddr;
+ int maskIndex = qId - IX_QMGR_MIN_QUEUPP_QID;
+ UINT32 qNearEmptyStatBitMask = ixQMgrAqmIfQueUppStat0BitMask[maskIndex];
+ UINT32 qFullStatBitMask = ixQMgrAqmIfQueUppStat1BitMask[maskIndex];
+
+ /* Reset the status bits */
+ *qStatus = 0;
+
+ /* Check if the queue is nearly empty */
+ if (IX_OSAL_READ_LONG(qNearEmptyStatRegAddr) & qNearEmptyStatBitMask)
+ {
+ *qStatus |= IX_QMGR_Q_STATUS_NE_BIT_MASK;
+ }
+
+ /* Check if the queue is full */
+ if (IX_OSAL_READ_LONG(qFullStatRegAddr) & qFullStatBitMask)
+ {
+ *qStatus |= IX_QMGR_Q_STATUS_F_BIT_MASK;
+ }
+ }
+ return IX_SUCCESS;
+}
+#endif /* def NO_INLINE_APIS */
OpenPOWER on IntegriCloud