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 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. Neither the name of the Intel Corporation nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
35 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * -- End of Copyright Notice --
51 * Inlines are compiled as function when this is defined.
52 * N.B. Must be placed before #include of "IxQMgr.h"
55 # define IXQMGRQACCESS_C
61 * System defined include files.
65 * User defined include files.
68 #include "IxQMgrAqmIf_p.h"
69 #include "IxQMgrQAccess_p.h"
70 #include "IxQMgrQCfg_p.h"
71 #include "IxQMgrDefines_p.h"
74 * Global variables and extern definitions
76 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
79 * Function definitions.
82 ixQMgrQAccessInit (void)
87 ixQMgrQReadWithChecks (IxQMgrQId qId,
90 IxQMgrQEntrySizeInWords entrySizeInWords;
91 IxQMgrQInlinedReadWriteInfo *infoPtr;
95 return IX_QMGR_PARAMETER_ERROR;
99 if (!ixQMgrQIsConfigured(qId))
101 return IX_QMGR_Q_NOT_CONFIGURED;
104 /* Get the q entry size in words */
105 entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
107 ixQMgrAqmIfQPop (qId, entrySizeInWords, entry);
109 /* reset the current read count if the counter wrapped around
110 * (unsigned arithmetic)
112 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
113 if (infoPtr->qReadCount-- > infoPtr->qSizeInEntries)
115 infoPtr->qReadCount = 0;
118 /* Check if underflow occurred on the read */
119 if (ixQMgrAqmIfUnderflowCheck (qId))
121 return IX_QMGR_Q_UNDERFLOW;
127 /* this function reads the remaining of the q entry
128 * for queues configured with many words.
129 * (the first word of the entry is already read
130 * in the inlined function and the entry pointer already
134 ixQMgrQReadMWordsMinus1 (IxQMgrQId qId,
137 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
138 UINT32 entrySize = infoPtr->qEntrySizeInWords;
139 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
143 /* read the entry and accumulate the result */
144 *(++entry) = IX_OSAL_READ_LONG(++qAccRegAddr);
146 /* underflow is available for lower queues only */
147 if (qId < IX_QMGR_MIN_QUEUPP_QID)
149 /* get the queue status */
150 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
152 /* check the underflow status */
153 if (status & infoPtr->qUflowStatBitMask)
155 /* the queue is empty
156 * clear the underflow status bit if it was set
158 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
159 status & ~infoPtr->qUflowStatBitMask);
160 return IX_QMGR_Q_UNDERFLOW;
167 ixQMgrQWriteWithChecks (IxQMgrQId qId,
170 IxQMgrQEntrySizeInWords entrySizeInWords;
171 IxQMgrQInlinedReadWriteInfo *infoPtr;
175 return IX_QMGR_PARAMETER_ERROR;
179 if (!ixQMgrQIsConfigured(qId))
181 return IX_QMGR_Q_NOT_CONFIGURED;
184 /* Get the q entry size in words */
185 entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
187 ixQMgrAqmIfQPush (qId, entrySizeInWords, entry);
189 /* reset the current read count if the counter wrapped around
190 * (unsigned arithmetic)
192 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
193 if (infoPtr->qWriteCount++ >= infoPtr->qSizeInEntries)
195 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
198 /* Check if overflow occurred on the write*/
199 if (ixQMgrAqmIfOverflowCheck (qId))
201 return IX_QMGR_Q_OVERFLOW;
208 ixQMgrQPeek (IxQMgrQId qId,
209 unsigned int entryIndex,
212 unsigned int numEntries;
215 if ((NULL == entry) || (entryIndex >= IX_QMGR_Q_SIZE_INVALID))
217 return IX_QMGR_PARAMETER_ERROR;
220 if (!ixQMgrQIsConfigured(qId))
222 return IX_QMGR_Q_NOT_CONFIGURED;
226 if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
231 if (entryIndex >= numEntries) /* entryIndex starts at 0 */
233 return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
236 return ixQMgrAqmIfQPeek (qId, entryIndex, entry);
240 ixQMgrQPoke (IxQMgrQId qId,
244 unsigned int numEntries;
247 if ((NULL == entry) || (entryIndex > 128))
249 return IX_QMGR_PARAMETER_ERROR;
252 if (!ixQMgrQIsConfigured(qId))
254 return IX_QMGR_Q_NOT_CONFIGURED;
258 if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
263 if (numEntries < (entryIndex + 1)) /* entryIndex starts at 0 */
265 return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
268 return ixQMgrAqmIfQPoke (qId, entryIndex, entry);
272 ixQMgrQStatusGetWithChecks (IxQMgrQId qId,
273 IxQMgrQStatus *qStatus)
277 return IX_QMGR_PARAMETER_ERROR;
280 if (!ixQMgrQIsConfigured (qId))
282 return IX_QMGR_Q_NOT_CONFIGURED;
285 ixQMgrAqmIfQueStatRead (qId, qStatus);
291 ixQMgrQNumEntriesGet (IxQMgrQId qId,
292 unsigned *numEntriesPtr)
297 IxQMgrQInlinedReadWriteInfo *infoPtr;
301 if (NULL == numEntriesPtr)
303 return IX_QMGR_PARAMETER_ERROR;
307 if (!ixQMgrQIsConfigured(qId))
309 return IX_QMGR_Q_NOT_CONFIGURED;
313 /* get fast access data */
314 infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
317 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
319 /* Mod subtraction of pointers to get number of words in Q. */
320 numEntries = (qPtrs - (qPtrs >> 7)) & 0x7f;
325 * Could mean either full or empty queue
328 ixQMgrAqmIfQueStatRead (qId, &qStatus);
330 if (qId < IX_QMGR_MIN_QUEUPP_QID)
332 if (qStatus & IX_QMGR_Q_STATUS_E_BIT_MASK)
337 else if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
340 *numEntriesPtr = infoPtr->qSizeInEntries;
345 * Queue status and read/write pointers are volatile.
346 * The queue state has changed since we took the
347 * snapshot of the read and write pointers.
348 * Client can retry if they wish
351 return IX_QMGR_WARNING;
354 else /* It is an upper queue which does not have an empty status bit maintained */
356 if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
358 /* The queue is Full at the time of snapshot. */
359 *numEntriesPtr = infoPtr->qSizeInEntries;
363 /* The queue is either empty, either moving,
364 * Client can retry if they wish
367 return IX_QMGR_WARNING;
373 *numEntriesPtr = (numEntries / infoPtr->qEntrySizeInWords) & (infoPtr->qSizeInEntries - 1);
379 #if defined(__wince) && defined(NO_INLINE_APIS)
382 ixQMgrQRead (IxQMgrQId qId,
385 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
386 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
387 UINT32 entry, entrySize;
389 /* get a new entry */
390 entrySize = infoPtr->qEntrySizeInWords;
391 entry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
393 if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
396 /* process the remaining part of the entry */
397 return ixQMgrQReadMWordsMinus1(qId, entryPtr);
400 /* underflow is available for lower queues only */
401 if (qId < IX_QMGR_MIN_QUEUPP_QID)
403 /* the counter of queue entries is decremented. In happy
404 * day scenario there are many entries in the queue
405 * and the counter does not reach zero.
407 if (infoPtr->qReadCount-- == 0)
409 /* There is maybe no entry in the queue
410 * qReadCount is now negative, but will be corrected before
411 * the function returns.
413 UINT32 qPtrs; /* queue internal pointers */
415 /* when a queue is empty, the hw guarantees to return
416 * a null value. If the value is not null, the queue is
421 /* get the queue status */
422 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
424 /* check the underflow status */
425 if (status & infoPtr->qUflowStatBitMask)
427 /* the queue is empty
428 * clear the underflow status bit if it was set
430 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
431 status & ~infoPtr->qUflowStatBitMask);
433 infoPtr->qReadCount = 0;
434 return IX_QMGR_Q_UNDERFLOW;
437 /* store the result */
440 /* No underflow occured : someone is filling the queue
441 * or the queue contains null entries.
442 * The current counter needs to be
443 * updated from the current number of entries in the queue
446 /* get snapshot of queue pointers */
447 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
449 /* Mod subtraction of pointers to get number of words in Q. */
450 qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
454 /* no entry in the queue */
455 infoPtr->qReadCount = 0;
459 /* convert the number of words inside the queue
460 * to a number of entries
462 infoPtr->qReadCount = qPtrs & (infoPtr->qSizeInEntries - 1);
472 ixQMgrQBurstRead (IxQMgrQId qId,
476 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
477 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
478 UINT32 nullCheckEntry;
480 if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
482 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
484 /* the code is optimized to take care of data dependencies:
485 * Durig a read, there are a few cycles needed to get the
486 * read complete. During these cycles, it is poossible to
487 * do some CPU, e.g. increment pointers and decrement
491 /* fetch a queue entry */
492 nullCheckEntry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
494 /* iterate the specified number of queue entries */
497 /* check the result of the previous read */
498 if (nullCheckEntry == 0)
500 /* if we read a NULL entry, stop. We have underflowed */
505 /* write the entry */
506 *entries = nullCheckEntry;
507 /* fetch next entry */
508 nullCheckEntry = IX_OSAL_READ_LONG(qAccRegAddr);
509 /* increment the write address */
513 /* write the pre-fetched entry */
514 *entries = nullCheckEntry;
518 IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
519 /* read the specified number of queue entries */
525 for (i = 0; i < entrySizeInWords; i++)
527 *entries = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr + i);
528 nullCheckEntry |= *entries++;
531 /* if we read a NULL entry, stop. We have underflowed */
532 if (nullCheckEntry == 0)
540 /* reset the current read count : next access to the read function
541 * will force a underflow status check
543 infoPtr->qWriteCount = 0;
545 /* Check if underflow occurred on the read */
546 if (nullCheckEntry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID)
548 /* get the queue status */
549 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
551 if (status & infoPtr->qUflowStatBitMask)
553 /* clear the underflow status bit if it was set */
554 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
555 status & ~infoPtr->qUflowStatBitMask);
556 return IX_QMGR_Q_UNDERFLOW;
564 ixQMgrQWrite (IxQMgrQId qId,
567 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
568 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
571 /* write the entry */
572 IX_OSAL_WRITE_LONG(infoPtr->qAccRegAddr, *entry);
573 entrySize = infoPtr->qEntrySizeInWords;
575 if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
577 /* process the remaining part of the entry */
578 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
582 IX_OSAL_WRITE_LONG(++qAccRegAddr, *entry);
584 entrySize = infoPtr->qEntrySizeInWords;
587 /* overflow is available for lower queues only */
588 if (qId < IX_QMGR_MIN_QUEUPP_QID)
590 UINT32 qSize = infoPtr->qSizeInEntries;
591 /* increment the current number of entries in the queue
592 * and check for overflow
594 if (infoPtr->qWriteCount++ == qSize)
596 /* the queue may have overflow */
597 UINT32 qPtrs; /* queue internal pointers */
599 /* get the queue status */
600 UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
602 /* read the status twice because the status may
603 * not be immediately ready after the write operation
605 if ((status & infoPtr->qOflowStatBitMask) ||
606 ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
607 & infoPtr->qOflowStatBitMask))
609 /* the queue is full, clear the overflow status
612 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
613 status & ~infoPtr->qOflowStatBitMask);
614 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
615 return IX_QMGR_Q_OVERFLOW;
617 /* No overflow occured : someone is draining the queue
618 * and the current counter needs to be
619 * updated from the current number of entries in the queue
622 /* get q pointer snapshot */
623 qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
625 /* Mod subtraction of pointers to get number of words in Q. */
626 qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
630 /* the queue may be full at the time of the
631 * snapshot. Next access will check
632 * the overflow status again.
634 infoPtr->qWriteCount = qSize;
638 /* convert the number of words to a number of entries */
639 if (entrySize == IX_QMGR_Q_ENTRY_SIZE1)
641 infoPtr->qWriteCount = qPtrs & (qSize - 1);
645 infoPtr->qWriteCount = (qPtrs / entrySize) & (qSize - 1);
654 ixQMgrQBurstWrite (IxQMgrQId qId,
658 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
659 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
662 /* update the current write count */
663 infoPtr->qWriteCount += numEntries;
665 if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
667 volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
670 IX_OSAL_WRITE_LONG(qAccRegAddr, *entries);
676 IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
679 /* write each queue entry */
682 /* write the queueEntrySize number of words for each entry */
683 for (i = 0; i < entrySizeInWords; i++)
685 IX_OSAL_WRITE_LONG((infoPtr->qAccRegAddr + i), *entries);
691 /* check if the write count overflows */
692 if (infoPtr->qWriteCount > infoPtr->qSizeInEntries)
694 /* reset the current write count */
695 infoPtr->qWriteCount = infoPtr->qSizeInEntries;
698 /* Check if overflow occurred on the write operation */
699 if (qId < IX_QMGR_MIN_QUEUPP_QID)
701 /* get the queue status */
702 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
704 /* read the status twice because the status may
705 * not be ready at the time of the write
707 if ((status & infoPtr->qOflowStatBitMask) ||
708 ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
709 & infoPtr->qOflowStatBitMask))
711 /* clear the underflow status bit if it was set */
712 IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
713 status & ~infoPtr->qOflowStatBitMask);
714 return IX_QMGR_Q_OVERFLOW;
722 ixQMgrQStatusGet (IxQMgrQId qId,
723 IxQMgrQStatus *qStatus)
725 /* read the status of a queue in the range 0-31 */
726 if (qId < IX_QMGR_MIN_QUEUPP_QID)
728 extern UINT32 ixQMgrAqmIfQueLowStatRegAddr[];
729 extern UINT32 ixQMgrAqmIfQueLowStatBitsOffset[];
730 extern UINT32 ixQMgrAqmIfQueLowStatBitsMask;
731 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
732 IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
733 volatile UINT32 *lowStatRegAddr = (UINT32*)ixQMgrAqmIfQueLowStatRegAddr[qId];
734 volatile UINT32 *qUOStatRegAddr = infoPtr->qUOStatRegAddr;
736 UINT32 lowStatBitsOffset = ixQMgrAqmIfQueLowStatBitsOffset[qId];
737 UINT32 lowStatBitsMask = ixQMgrAqmIfQueLowStatBitsMask;
738 UINT32 underflowBitMask = infoPtr->qUflowStatBitMask;
739 UINT32 overflowBitMask = infoPtr->qOflowStatBitMask;
741 /* read the status register for this queue */
742 *qStatus = IX_OSAL_READ_LONG(lowStatRegAddr);
743 /* mask out the status bits relevant only to this queue */
744 *qStatus = (*qStatus >> lowStatBitsOffset) & lowStatBitsMask;
746 /* Check if the queue has overflowed */
747 if (IX_OSAL_READ_LONG(qUOStatRegAddr) & overflowBitMask)
749 /* clear the overflow status bit if it was set */
750 IX_OSAL_WRITE_LONG(qUOStatRegAddr,
751 (IX_OSAL_READ_LONG(qUOStatRegAddr) &
753 *qStatus |= IX_QMGR_Q_STATUS_OF_BIT_MASK;
756 /* Check if the queue has underflowed */
757 if (IX_OSAL_READ_LONG(qUOStatRegAddr) & underflowBitMask)
759 /* clear the underflow status bit if it was set */
760 IX_OSAL_WRITE_LONG(qUOStatRegAddr,
761 (IX_OSAL_READ_LONG(qUOStatRegAddr) &
763 *qStatus |= IX_QMGR_Q_STATUS_UF_BIT_MASK;
766 else /* read status of a queue in the range 32-63 */
768 extern UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
769 extern UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
770 extern UINT32 ixQMgrAqmIfQueUppStat0BitMask[];
771 extern UINT32 ixQMgrAqmIfQueUppStat1BitMask[];
773 volatile UINT32 *qNearEmptyStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat0RegAddr;
774 volatile UINT32 *qFullStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat1RegAddr;
775 int maskIndex = qId - IX_QMGR_MIN_QUEUPP_QID;
776 UINT32 qNearEmptyStatBitMask = ixQMgrAqmIfQueUppStat0BitMask[maskIndex];
777 UINT32 qFullStatBitMask = ixQMgrAqmIfQueUppStat1BitMask[maskIndex];
779 /* Reset the status bits */
782 /* Check if the queue is nearly empty */
783 if (IX_OSAL_READ_LONG(qNearEmptyStatRegAddr) & qNearEmptyStatBitMask)
785 *qStatus |= IX_QMGR_Q_STATUS_NE_BIT_MASK;
788 /* Check if the queue is full */
789 if (IX_OSAL_READ_LONG(qFullStatRegAddr) & qFullStatBitMask)
791 *qStatus |= IX_QMGR_Q_STATUS_F_BIT_MASK;
796 #endif /* def NO_INLINE_APIS */