Signed-off-by: Marek Vasut <marex@denx.de> Cc: Bryan Hundven <bryanhundven@gmail.com> Cc: Michael Schwingen <rincewind@discworld.dascon.de> Cc: Wolfgang Denk <wd@denx.de> Cc: Albert Aribaud <albert.u.boot@aribaud.net> Cc: U-Boot DM <u-boot-dm@lists.denx.de> Cc: Joe Hershberger <joe.hershberger@ni.com>
797 lines
21 KiB
C
797 lines
21 KiB
C
/**
|
|
* @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 */
|