2 * @file IxQMgrQAccess.c
4 * @author Intel Corporation
7 * @brief This file contains functions for putting entries on a queue and
8 * removing entries from a queue.
12 * IXP400 SW Release version 2.0
14 * -- Copyright Notice --
17 * Copyright 2001-2005, Intel Corporation.
18 * All rights reserved.
21 * SPDX-License-Identifier: BSD-3-Clause
23 * -- End of Copyright Notice --
27 * Inlines are compiled as function when this is defined.
28 * N.B. Must be placed before #include of "IxQMgr.h"
31 # define IXQMGRQACCESS_C
37 * System defined include files.
41 * User defined include files.
44 #include "IxQMgrAqmIf_p.h"
45 #include "IxQMgrQAccess_p.h"
46 #include "IxQMgrQCfg_p.h"
47 #include "IxQMgrDefines_p.h"
50 * Global variables and extern definitions
52 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
55 * Function definitions.
58 ixQMgrQAccessInit (void)
63 ixQMgrQReadWithChecks (IxQMgrQId qId,
66 IxQMgrQEntrySizeInWords entrySizeInWords;
67 IxQMgrQInlinedReadWriteInfo *infoPtr;
71 return IX_QMGR_PARAMETER_ERROR;
75 if (!ixQMgrQIsConfigured(qId))
77 return IX_QMGR_Q_NOT_CONFIGURED;
80 /* Get the q entry size in words */
81 entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
83 ixQMgrAqmIfQPop (qId, entrySizeInWords, entry);
85 /* reset the current read count if the counter wrapped around
86 * (unsigned arithmetic)
88 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
89 if (infoPtr->qReadCount-- > infoPtr->qSizeInEntries)
91 infoPtr->qReadCount = 0;
94 /* Check if underflow occurred on the read */
95 if (ixQMgrAqmIfUnderflowCheck (qId))
97 return IX_QMGR_Q_UNDERFLOW;
103 /* this function reads the remaining of the q entry
104 * for queues configured with many words.
105 * (the first word of the entry is already read
106 * in the inlined function and the entry pointer already
110 ixQMgrQReadMWordsMinus1 (IxQMgrQId qId,
113 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
114 UINT32 entrySize = infoPtr->qEntrySizeInWords;
115 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
119 /* read the entry and accumulate the result */
120 *(++entry) = IX_OSAL_READ_LONG(++qAccRegAddr);
122 /* underflow is available for lower queues only */
123 if (qId < IX_QMGR_MIN_QUEUPP_QID)
125 /* get the queue status */
126 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
128 /* check the underflow status */
129 if (status & infoPtr->qUflowStatBitMask)
131 /* the queue is empty
132 * clear the underflow status bit if it was set
134 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
135 status & ~infoPtr->qUflowStatBitMask);
136 return IX_QMGR_Q_UNDERFLOW;
143 ixQMgrQWriteWithChecks (IxQMgrQId qId,
146 IxQMgrQEntrySizeInWords entrySizeInWords;
147 IxQMgrQInlinedReadWriteInfo *infoPtr;
151 return IX_QMGR_PARAMETER_ERROR;
155 if (!ixQMgrQIsConfigured(qId))
157 return IX_QMGR_Q_NOT_CONFIGURED;
160 /* Get the q entry size in words */
161 entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
163 ixQMgrAqmIfQPush (qId, entrySizeInWords, entry);
165 /* reset the current read count if the counter wrapped around
166 * (unsigned arithmetic)
168 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
169 if (infoPtr->qWriteCount++ >= infoPtr->qSizeInEntries)
171 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
174 /* Check if overflow occurred on the write*/
175 if (ixQMgrAqmIfOverflowCheck (qId))
177 return IX_QMGR_Q_OVERFLOW;
184 ixQMgrQPeek (IxQMgrQId qId,
185 unsigned int entryIndex,
188 unsigned int numEntries;
191 if ((NULL == entry) || (entryIndex >= IX_QMGR_Q_SIZE_INVALID))
193 return IX_QMGR_PARAMETER_ERROR;
196 if (!ixQMgrQIsConfigured(qId))
198 return IX_QMGR_Q_NOT_CONFIGURED;
202 if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
207 if (entryIndex >= numEntries) /* entryIndex starts at 0 */
209 return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
212 return ixQMgrAqmIfQPeek (qId, entryIndex, entry);
216 ixQMgrQPoke (IxQMgrQId qId,
220 unsigned int numEntries;
223 if ((NULL == entry) || (entryIndex > 128))
225 return IX_QMGR_PARAMETER_ERROR;
228 if (!ixQMgrQIsConfigured(qId))
230 return IX_QMGR_Q_NOT_CONFIGURED;
234 if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
239 if (numEntries < (entryIndex + 1)) /* entryIndex starts at 0 */
241 return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
244 return ixQMgrAqmIfQPoke (qId, entryIndex, entry);
248 ixQMgrQStatusGetWithChecks (IxQMgrQId qId,
249 IxQMgrQStatus *qStatus)
253 return IX_QMGR_PARAMETER_ERROR;
256 if (!ixQMgrQIsConfigured (qId))
258 return IX_QMGR_Q_NOT_CONFIGURED;
261 ixQMgrAqmIfQueStatRead (qId, qStatus);
267 ixQMgrQNumEntriesGet (IxQMgrQId qId,
268 unsigned *numEntriesPtr)
273 IxQMgrQInlinedReadWriteInfo *infoPtr;
277 if (NULL == numEntriesPtr)
279 return IX_QMGR_PARAMETER_ERROR;
283 if (!ixQMgrQIsConfigured(qId))
285 return IX_QMGR_Q_NOT_CONFIGURED;
289 /* get fast access data */
290 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
293 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
295 /* Mod subtraction of pointers to get number of words in Q. */
296 numEntries = (qPtrs - (qPtrs >> 7)) & 0x7f;
301 * Could mean either full or empty queue
304 ixQMgrAqmIfQueStatRead (qId, &qStatus);
306 if (qId < IX_QMGR_MIN_QUEUPP_QID)
308 if (qStatus & IX_QMGR_Q_STATUS_E_BIT_MASK)
313 else if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
316 *numEntriesPtr = infoPtr->qSizeInEntries;
321 * Queue status and read/write pointers are volatile.
322 * The queue state has changed since we took the
323 * snapshot of the read and write pointers.
324 * Client can retry if they wish
327 return IX_QMGR_WARNING;
330 else /* It is an upper queue which does not have an empty status bit maintained */
332 if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
334 /* The queue is Full at the time of snapshot. */
335 *numEntriesPtr = infoPtr->qSizeInEntries;
339 /* The queue is either empty, either moving,
340 * Client can retry if they wish
343 return IX_QMGR_WARNING;
349 *numEntriesPtr = (numEntries / infoPtr->qEntrySizeInWords) & (infoPtr->qSizeInEntries - 1);
355 #if defined(__wince) && defined(NO_INLINE_APIS)
358 ixQMgrQRead (IxQMgrQId qId,
361 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
362 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
363 UINT32 entry, entrySize;
365 /* get a new entry */
366 entrySize = infoPtr->qEntrySizeInWords;
367 entry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
369 if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
372 /* process the remaining part of the entry */
373 return ixQMgrQReadMWordsMinus1(qId, entryPtr);
376 /* underflow is available for lower queues only */
377 if (qId < IX_QMGR_MIN_QUEUPP_QID)
379 /* the counter of queue entries is decremented. In happy
380 * day scenario there are many entries in the queue
381 * and the counter does not reach zero.
383 if (infoPtr->qReadCount-- == 0)
385 /* There is maybe no entry in the queue
386 * qReadCount is now negative, but will be corrected before
387 * the function returns.
389 UINT32 qPtrs; /* queue internal pointers */
391 /* when a queue is empty, the hw guarantees to return
392 * a null value. If the value is not null, the queue is
397 /* get the queue status */
398 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
400 /* check the underflow status */
401 if (status & infoPtr->qUflowStatBitMask)
403 /* the queue is empty
404 * clear the underflow status bit if it was set
406 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
407 status & ~infoPtr->qUflowStatBitMask);
409 infoPtr->qReadCount = 0;
410 return IX_QMGR_Q_UNDERFLOW;
413 /* store the result */
416 /* No underflow occured : someone is filling the queue
417 * or the queue contains null entries.
418 * The current counter needs to be
419 * updated from the current number of entries in the queue
422 /* get snapshot of queue pointers */
423 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
425 /* Mod subtraction of pointers to get number of words in Q. */
426 qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
430 /* no entry in the queue */
431 infoPtr->qReadCount = 0;
435 /* convert the number of words inside the queue
436 * to a number of entries
438 infoPtr->qReadCount = qPtrs & (infoPtr->qSizeInEntries - 1);
448 ixQMgrQBurstRead (IxQMgrQId qId,
452 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
453 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
454 UINT32 nullCheckEntry;
456 if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
458 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
460 /* the code is optimized to take care of data dependencies:
461 * Durig a read, there are a few cycles needed to get the
462 * read complete. During these cycles, it is poossible to
463 * do some CPU, e.g. increment pointers and decrement
467 /* fetch a queue entry */
468 nullCheckEntry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
470 /* iterate the specified number of queue entries */
473 /* check the result of the previous read */
474 if (nullCheckEntry == 0)
476 /* if we read a NULL entry, stop. We have underflowed */
481 /* write the entry */
482 *entries = nullCheckEntry;
483 /* fetch next entry */
484 nullCheckEntry = IX_OSAL_READ_LONG(qAccRegAddr);
485 /* increment the write address */
489 /* write the pre-fetched entry */
490 *entries = nullCheckEntry;
494 IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
495 /* read the specified number of queue entries */
501 for (i = 0; i < entrySizeInWords; i++)
503 *entries = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr + i);
504 nullCheckEntry |= *entries++;
507 /* if we read a NULL entry, stop. We have underflowed */
508 if (nullCheckEntry == 0)
516 /* reset the current read count : next access to the read function
517 * will force a underflow status check
519 infoPtr->qWriteCount = 0;
521 /* Check if underflow occurred on the read */
522 if (nullCheckEntry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID)
524 /* get the queue status */
525 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
527 if (status & infoPtr->qUflowStatBitMask)
529 /* clear the underflow status bit if it was set */
530 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
531 status & ~infoPtr->qUflowStatBitMask);
532 return IX_QMGR_Q_UNDERFLOW;
540 ixQMgrQWrite (IxQMgrQId qId,
543 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
544 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
547 /* write the entry */
548 IX_OSAL_WRITE_LONG(infoPtr->qAccRegAddr, *entry);
549 entrySize = infoPtr->qEntrySizeInWords;
551 if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
553 /* process the remaining part of the entry */
554 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
558 IX_OSAL_WRITE_LONG(++qAccRegAddr, *entry);
560 entrySize = infoPtr->qEntrySizeInWords;
563 /* overflow is available for lower queues only */
564 if (qId < IX_QMGR_MIN_QUEUPP_QID)
566 UINT32 qSize = infoPtr->qSizeInEntries;
567 /* increment the current number of entries in the queue
568 * and check for overflow
570 if (infoPtr->qWriteCount++ == qSize)
572 /* the queue may have overflow */
573 UINT32 qPtrs; /* queue internal pointers */
575 /* get the queue status */
576 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
578 /* read the status twice because the status may
579 * not be immediately ready after the write operation
581 if ((status & infoPtr->qOflowStatBitMask) ||
582 ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
583 & infoPtr->qOflowStatBitMask))
585 /* the queue is full, clear the overflow status
588 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
589 status & ~infoPtr->qOflowStatBitMask);
590 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
591 return IX_QMGR_Q_OVERFLOW;
593 /* No overflow occured : someone is draining the queue
594 * and the current counter needs to be
595 * updated from the current number of entries in the queue
598 /* get q pointer snapshot */
599 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
601 /* Mod subtraction of pointers to get number of words in Q. */
602 qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
606 /* the queue may be full at the time of the
607 * snapshot. Next access will check
608 * the overflow status again.
610 infoPtr->qWriteCount = qSize;
614 /* convert the number of words to a number of entries */
615 if (entrySize == IX_QMGR_Q_ENTRY_SIZE1)
617 infoPtr->qWriteCount = qPtrs & (qSize - 1);
621 infoPtr->qWriteCount = (qPtrs / entrySize) & (qSize - 1);
630 ixQMgrQBurstWrite (IxQMgrQId qId,
634 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
635 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
638 /* update the current write count */
639 infoPtr->qWriteCount += numEntries;
641 if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
643 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
646 IX_OSAL_WRITE_LONG(qAccRegAddr, *entries);
652 IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
655 /* write each queue entry */
658 /* write the queueEntrySize number of words for each entry */
659 for (i = 0; i < entrySizeInWords; i++)
661 IX_OSAL_WRITE_LONG((infoPtr->qAccRegAddr + i), *entries);
667 /* check if the write count overflows */
668 if (infoPtr->qWriteCount > infoPtr->qSizeInEntries)
670 /* reset the current write count */
671 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
674 /* Check if overflow occurred on the write operation */
675 if (qId < IX_QMGR_MIN_QUEUPP_QID)
677 /* get the queue status */
678 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
680 /* read the status twice because the status may
681 * not be ready at the time of the write
683 if ((status & infoPtr->qOflowStatBitMask) ||
684 ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
685 & infoPtr->qOflowStatBitMask))
687 /* clear the underflow status bit if it was set */
688 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
689 status & ~infoPtr->qOflowStatBitMask);
690 return IX_QMGR_Q_OVERFLOW;
698 ixQMgrQStatusGet (IxQMgrQId qId,
699 IxQMgrQStatus *qStatus)
701 /* read the status of a queue in the range 0-31 */
702 if (qId < IX_QMGR_MIN_QUEUPP_QID)
704 extern UINT32 ixQMgrAqmIfQueLowStatRegAddr[];
705 extern UINT32 ixQMgrAqmIfQueLowStatBitsOffset[];
706 extern UINT32 ixQMgrAqmIfQueLowStatBitsMask;
707 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
708 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
709 volatile UINT32 *lowStatRegAddr = (UINT32*)ixQMgrAqmIfQueLowStatRegAddr[qId];
710 volatile UINT32 *qUOStatRegAddr = infoPtr->qUOStatRegAddr;
712 UINT32 lowStatBitsOffset = ixQMgrAqmIfQueLowStatBitsOffset[qId];
713 UINT32 lowStatBitsMask = ixQMgrAqmIfQueLowStatBitsMask;
714 UINT32 underflowBitMask = infoPtr->qUflowStatBitMask;
715 UINT32 overflowBitMask = infoPtr->qOflowStatBitMask;
717 /* read the status register for this queue */
718 *qStatus = IX_OSAL_READ_LONG(lowStatRegAddr);
719 /* mask out the status bits relevant only to this queue */
720 *qStatus = (*qStatus >> lowStatBitsOffset) & lowStatBitsMask;
722 /* Check if the queue has overflowed */
723 if (IX_OSAL_READ_LONG(qUOStatRegAddr) & overflowBitMask)
725 /* clear the overflow status bit if it was set */
726 IX_OSAL_WRITE_LONG(qUOStatRegAddr,
727 (IX_OSAL_READ_LONG(qUOStatRegAddr) &
729 *qStatus |= IX_QMGR_Q_STATUS_OF_BIT_MASK;
732 /* Check if the queue has underflowed */
733 if (IX_OSAL_READ_LONG(qUOStatRegAddr) & underflowBitMask)
735 /* clear the underflow status bit if it was set */
736 IX_OSAL_WRITE_LONG(qUOStatRegAddr,
737 (IX_OSAL_READ_LONG(qUOStatRegAddr) &
739 *qStatus |= IX_QMGR_Q_STATUS_UF_BIT_MASK;
742 else /* read status of a queue in the range 32-63 */
744 extern UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
745 extern UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
746 extern UINT32 ixQMgrAqmIfQueUppStat0BitMask[];
747 extern UINT32 ixQMgrAqmIfQueUppStat1BitMask[];
749 volatile UINT32 *qNearEmptyStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat0RegAddr;
750 volatile UINT32 *qFullStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat1RegAddr;
751 int maskIndex = qId - IX_QMGR_MIN_QUEUPP_QID;
752 UINT32 qNearEmptyStatBitMask = ixQMgrAqmIfQueUppStat0BitMask[maskIndex];
753 UINT32 qFullStatBitMask = ixQMgrAqmIfQueUppStat1BitMask[maskIndex];
755 /* Reset the status bits */
758 /* Check if the queue is nearly empty */
759 if (IX_OSAL_READ_LONG(qNearEmptyStatRegAddr) & qNearEmptyStatBitMask)
761 *qStatus |= IX_QMGR_Q_STATUS_NE_BIT_MASK;
764 /* Check if the queue is full */
765 if (IX_OSAL_READ_LONG(qFullStatRegAddr) & qFullStatBitMask)
767 *qStatus |= IX_QMGR_Q_STATUS_F_BIT_MASK;
772 #endif /* def NO_INLINE_APIS */