]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ixp/npe/IxQMgrQAccess.c
Big white-space cleanup.
[karo-tx-uboot.git] / cpu / ixp / npe / IxQMgrQAccess.c
1 /**
2  * @file    IxQMgrQAccess.c
3  *
4  * @author Intel Corporation
5  * @date    30-Oct-2001
6  *
7  * @brief   This file contains functions for putting entries on a queue and
8  * removing entries from a queue.
9  *
10  * 
11  * @par
12  * IXP400 SW Release version 2.0
13  * 
14  * -- Copyright Notice --
15  * 
16  * @par
17  * Copyright 2001-2005, Intel Corporation.
18  * All rights reserved.
19  * 
20  * @par
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
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.
32  * 
33  * @par
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
44  * SUCH DAMAGE.
45  * 
46  * @par
47  * -- End of Copyright Notice --
48 */
49
50 /*
51  * Inlines are compiled as function when this is defined.
52  * N.B. Must be placed before #include of "IxQMgr.h"
53  */
54 #ifndef IXQMGR_H
55 #    define IXQMGRQACCESS_C
56 #else
57 #    error
58 #endif
59
60 /*
61  * System defined include files.
62  */
63
64 /*
65  * User defined include files.
66  */
67 #include "IxQMgr.h"
68 #include "IxQMgrAqmIf_p.h"
69 #include "IxQMgrQAccess_p.h"
70 #include "IxQMgrQCfg_p.h"
71 #include "IxQMgrDefines_p.h"
72
73 /*
74  * Global variables and extern definitions
75  */
76 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
77
78 /*
79  * Function definitions.
80  */
81 void
82 ixQMgrQAccessInit (void)
83 {   
84 }
85
86 IX_STATUS
87 ixQMgrQReadWithChecks (IxQMgrQId qId,
88                        UINT32 *entry)
89 {
90     IxQMgrQEntrySizeInWords entrySizeInWords;
91     IxQMgrQInlinedReadWriteInfo *infoPtr;
92
93     if (NULL == entry)
94     {
95         return IX_QMGR_PARAMETER_ERROR;
96     }
97
98     /* Check QId */
99     if (!ixQMgrQIsConfigured(qId))
100     {
101         return IX_QMGR_Q_NOT_CONFIGURED;
102     }
103
104     /* Get the q entry size in words */
105     entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
106
107     ixQMgrAqmIfQPop (qId, entrySizeInWords, entry);         
108
109     /* reset the current read count if the counter wrapped around 
110     * (unsigned arithmetic)
111     */
112     infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
113     if (infoPtr->qReadCount-- > infoPtr->qSizeInEntries)
114     {
115         infoPtr->qReadCount = 0;
116     }
117
118     /* Check if underflow occurred on the read */
119     if (ixQMgrAqmIfUnderflowCheck (qId))
120     {
121         return IX_QMGR_Q_UNDERFLOW;
122     }
123     
124     return IX_SUCCESS;
125 }
126
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
131  * incremented
132  */
133 IX_STATUS
134 ixQMgrQReadMWordsMinus1 (IxQMgrQId qId,
135                          UINT32 *entry)
136 {
137     IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
138     UINT32 entrySize = infoPtr->qEntrySizeInWords;
139     volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
140     
141     while (--entrySize)
142     {
143         /* read the entry and accumulate the result */
144         *(++entry) = IX_OSAL_READ_LONG(++qAccRegAddr);
145     }
146     /* underflow is available for lower queues only */
147     if (qId < IX_QMGR_MIN_QUEUPP_QID)
148     {
149         /* get the queue status */
150         UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
151         
152         /* check the underflow status */
153         if (status & infoPtr->qUflowStatBitMask)
154         {
155             /* the queue is empty 
156              *  clear the underflow status bit if it was set 
157              */
158             IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
159                                  status & ~infoPtr->qUflowStatBitMask);
160             return IX_QMGR_Q_UNDERFLOW;
161         }
162     }
163     return IX_SUCCESS;
164 }
165
166 IX_STATUS
167 ixQMgrQWriteWithChecks (IxQMgrQId qId,
168                         UINT32 *entry)
169 {
170     IxQMgrQEntrySizeInWords entrySizeInWords;
171     IxQMgrQInlinedReadWriteInfo *infoPtr;
172
173     if (NULL == entry)
174     {
175         return IX_QMGR_PARAMETER_ERROR;
176     }
177
178     /* Check QId */
179     if (!ixQMgrQIsConfigured(qId))
180     {
181         return IX_QMGR_Q_NOT_CONFIGURED;
182     }
183
184     /* Get the q entry size in words */
185     entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
186     
187     ixQMgrAqmIfQPush (qId, entrySizeInWords, entry);
188
189     /* reset the current read count if the counter wrapped around 
190     * (unsigned arithmetic)
191     */
192     infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
193     if (infoPtr->qWriteCount++ >= infoPtr->qSizeInEntries)
194     {
195         infoPtr->qWriteCount = infoPtr->qSizeInEntries;
196     }
197
198     /* Check if overflow occurred on the write*/
199     if (ixQMgrAqmIfOverflowCheck (qId))
200     {
201         return IX_QMGR_Q_OVERFLOW;
202     }
203          
204     return IX_SUCCESS;
205 }
206
207 IX_STATUS
208 ixQMgrQPeek (IxQMgrQId qId,
209              unsigned int entryIndex,
210              UINT32 *entry)
211 {
212     unsigned int numEntries;
213
214 #ifndef NDEBUG
215     if ((NULL == entry) || (entryIndex >= IX_QMGR_Q_SIZE_INVALID))
216     {
217         return IX_QMGR_PARAMETER_ERROR;
218     }
219
220     if (!ixQMgrQIsConfigured(qId))
221     {
222         return IX_QMGR_Q_NOT_CONFIGURED;
223     }
224 #endif
225     
226     if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
227     {
228         return IX_FAIL;
229     }
230
231     if (entryIndex >= numEntries) /* entryIndex starts at 0 */
232     {
233         return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
234     }
235
236     return ixQMgrAqmIfQPeek (qId, entryIndex, entry);
237 }
238
239 IX_STATUS
240 ixQMgrQPoke (IxQMgrQId qId,
241              unsigned entryIndex,
242              UINT32 *entry)
243 {
244     unsigned int numEntries;
245
246 #ifndef NDEBUG
247     if ((NULL == entry) || (entryIndex > 128))
248     {
249         return IX_QMGR_PARAMETER_ERROR;
250     }
251
252     if (!ixQMgrQIsConfigured(qId))
253     {
254         return IX_QMGR_Q_NOT_CONFIGURED;
255     }
256 #endif
257         
258     if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
259     {
260         return IX_FAIL;
261     }
262
263     if (numEntries < (entryIndex + 1)) /* entryIndex starts at 0 */
264     {
265         return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
266     }
267
268     return ixQMgrAqmIfQPoke (qId, entryIndex, entry);
269 }
270
271 IX_STATUS
272 ixQMgrQStatusGetWithChecks (IxQMgrQId qId,
273                             IxQMgrQStatus *qStatus)
274 {
275     if (NULL == qStatus)
276     {
277         return IX_QMGR_PARAMETER_ERROR;
278     }
279    
280     if (!ixQMgrQIsConfigured (qId)) 
281     {
282         return IX_QMGR_Q_NOT_CONFIGURED;
283     }
284
285     ixQMgrAqmIfQueStatRead (qId, qStatus);
286
287     return IX_SUCCESS;
288 }
289
290 IX_STATUS
291 ixQMgrQNumEntriesGet (IxQMgrQId qId,
292                       unsigned *numEntriesPtr)
293 {
294     UINT32 qPtrs;
295     UINT32 qStatus;
296     unsigned numEntries;
297     IxQMgrQInlinedReadWriteInfo *infoPtr;
298
299
300 #ifndef NDEBUG
301     if (NULL == numEntriesPtr)
302     {
303         return IX_QMGR_PARAMETER_ERROR;
304     }
305
306     /* Check QId */
307     if (!ixQMgrQIsConfigured(qId))
308     {
309         return IX_QMGR_Q_NOT_CONFIGURED;
310     }
311 #endif
312
313     /* get fast access data */
314     infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
315
316     /* get snapshot */
317     qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
318
319     /* Mod subtraction of pointers to get number of words in Q. */
320     numEntries = (qPtrs - (qPtrs >> 7)) & 0x7f;
321   
322     if (numEntries == 0)
323     {
324         /* 
325          * Could mean either full or empty queue
326          * so look at status
327          */
328         ixQMgrAqmIfQueStatRead (qId, &qStatus);
329
330         if (qId < IX_QMGR_MIN_QUEUPP_QID)
331         {
332             if (qStatus & IX_QMGR_Q_STATUS_E_BIT_MASK)
333             {
334                 /* Empty */
335                 *numEntriesPtr = 0;
336             }
337             else if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
338             {
339                 /* Full */
340                 *numEntriesPtr = infoPtr->qSizeInEntries;
341             }
342             else
343             {       
344                 /* 
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
349                  */
350                 *numEntriesPtr = 0;
351                 return IX_QMGR_WARNING;
352             }
353         }
354         else /* It is an upper queue which does not have an empty status bit maintained */
355         {
356             if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
357             {
358                 /* The queue is Full at the time of snapshot. */
359                 *numEntriesPtr = infoPtr->qSizeInEntries;
360             }
361             else
362             {
363                /* The queue is either empty, either moving,
364                 * Client can retry if they wish
365                 */
366                 *numEntriesPtr = 0;
367                 return IX_QMGR_WARNING;
368             }
369         }
370     }
371     else
372     {
373         *numEntriesPtr = (numEntries / infoPtr->qEntrySizeInWords) & (infoPtr->qSizeInEntries - 1);
374     }
375     
376     return IX_SUCCESS;
377 }
378
379 #if defined(__wince) && defined(NO_INLINE_APIS)
380
381 PUBLIC IX_STATUS
382 ixQMgrQRead (IxQMgrQId qId,
383       UINT32 *entryPtr)
384 {
385     extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
386     IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
387     UINT32 entry, entrySize;
388
389     /* get a new entry */
390     entrySize = infoPtr->qEntrySizeInWords;
391     entry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
392
393     if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
394     { 
395     *entryPtr = entry;
396   /* process the remaining part of the entry */
397    return ixQMgrQReadMWordsMinus1(qId, entryPtr);
398     }
399
400     /* underflow is available for lower queues only */
401     if (qId < IX_QMGR_MIN_QUEUPP_QID)
402     {
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.
406   */
407      if (infoPtr->qReadCount-- == 0)
408  {
409        /* There is maybe no entry in the queue
410       * qReadCount is now negative, but will be corrected before
411       * the function returns.
412          */
413      UINT32 qPtrs; /* queue internal pointers */
414
415      /* when a queue is empty, the hw guarantees to return 
416        * a null value. If the value is not null, the queue is
417       * not empty.
418         */
419      if (entry == 0)
420      {
421        /* get the queue status */
422       UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
423    
424         /* check the underflow status */
425         if (status & infoPtr->qUflowStatBitMask)
426         {
427            /* the queue is empty 
428           *  clear the underflow status bit if it was set 
429             */
430           IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
431                     status & ~infoPtr->qUflowStatBitMask);
432          *entryPtr = 0;
433           infoPtr->qReadCount = 0;
434             return IX_QMGR_Q_UNDERFLOW;
435      }
436        }
437        /* store the result */
438       *entryPtr = entry;
439
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
444        */
445
446      /* get snapshot of queue pointers */
447         qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
448
449        /* Mod subtraction of pointers to get number of words in Q. */
450       qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f; 
451   
452        if (qPtrs == 0)
453      {
454        /* no entry in the queue */
455      infoPtr->qReadCount = 0;
456         }
457        else
458         {
459        /* convert the number of words inside the queue
460       * to a number of entries 
461        */
462      infoPtr->qReadCount = qPtrs & (infoPtr->qSizeInEntries - 1);
463         }
464        return IX_SUCCESS;
465   }
466     }
467     *entryPtr = entry;
468     return IX_SUCCESS;
469 }
470
471 PUBLIC IX_STATUS
472 ixQMgrQBurstRead (IxQMgrQId qId,
473           UINT32 numEntries,
474           UINT32 *entries)
475 {
476     extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
477     IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
478     UINT32 nullCheckEntry;
479
480     if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
481     {
482     volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
483
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 
488    * counters.
489      */
490
491  /* fetch a queue entry */
492    nullCheckEntry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
493
494  /* iterate the specified number of queue entries */ 
495     while (--numEntries)
496     {
497        /* check the result of the previous read */
498      if (nullCheckEntry == 0)
499         {
500        /* if we read a NULL entry, stop. We have underflowed */
501         break;
502       }
503        else
504         {
505        /* write the entry */
506        *entries = nullCheckEntry;
507       /* fetch next entry */
508       nullCheckEntry = IX_OSAL_READ_LONG(qAccRegAddr);
509       /* increment the write address */
510        entries++;
511       }
512    }
513    /* write the pre-fetched entry */
514    *entries = nullCheckEntry;
515     }
516     else
517     {
518     IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
519   /* read the specified number of queue entries */
520     nullCheckEntry = 0;
521  while (numEntries--)
522     {
523        int i;
524
525       for (i = 0; i < entrySizeInWords; i++)
526       {
527        *entries = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr + i);
528        nullCheckEntry |= *entries++;
529        }
530
531        /* if we read a NULL entry, stop. We have underflowed */
532         if (nullCheckEntry == 0)
533         {
534        break;
535       }
536        nullCheckEntry = 0;
537  }
538     }
539
540     /* reset the current read count : next access to the read function 
541      * will force a underflow status check 
542      */
543     infoPtr->qWriteCount = 0;
544
545     /* Check if underflow occurred on the read */
546     if (nullCheckEntry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID)
547     {
548   /* get the queue status */
549   UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
550
551    if (status & infoPtr->qUflowStatBitMask)
552     {
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;
557  }
558     }
559
560     return IX_SUCCESS;
561 }
562
563 PUBLIC IX_STATUS
564 ixQMgrQWrite (IxQMgrQId qId,
565          UINT32 *entry)
566 {
567     extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
568     IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
569     UINT32 entrySize;
570
571     /* write the entry */
572     IX_OSAL_WRITE_LONG(infoPtr->qAccRegAddr, *entry);
573     entrySize = infoPtr->qEntrySizeInWords;
574
575     if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
576     {   
577     /* process the remaining part of the entry */
578    volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
579     while (--entrySize)
580  {
581        ++entry;
582         IX_OSAL_WRITE_LONG(++qAccRegAddr, *entry);
583     }
584    entrySize = infoPtr->qEntrySizeInWords;
585     }
586
587     /* overflow is available for lower queues only */
588     if (qId < IX_QMGR_MIN_QUEUPP_QID)
589     {   
590   UINT32 qSize = infoPtr->qSizeInEntries;
591  /* increment the current number of entries in the queue
592   * and check for overflow 
593    */
594  if (infoPtr->qWriteCount++ == qSize)
595     {
596        /* the queue may have overflow */
597        UINT32 qPtrs; /* queue internal pointers */
598   
599        /* get the queue status */
600       UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
601
602        /* read the status twice because the status may 
603          * not be immediately ready after the write operation
604         */
605      if ((status & infoPtr->qOflowStatBitMask) ||
606         ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
607          & infoPtr->qOflowStatBitMask))
608      {
609        /* the queue is full, clear the overflow status
610       *  bit if it was set 
611        */
612      IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
613                     status & ~infoPtr->qOflowStatBitMask);
614      infoPtr->qWriteCount = infoPtr->qSizeInEntries;
615      return IX_QMGR_Q_OVERFLOW;
616       }
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
620        */
621
622      /* get q pointer snapshot */
623         qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
624
625        /* Mod subtraction of pointers to get number of words in Q. */
626       qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f; 
627
628      if (qPtrs == 0)
629      {
630        /* the queue may be full at the time of the 
631          * snapshot. Next access will check 
632          * the overflow status again.
633         */
634      infoPtr->qWriteCount = qSize;
635        }
636        else 
637        {
638        /* convert the number of words to a number of entries */
639         if (entrySize == IX_QMGR_Q_ENTRY_SIZE1)
640      {
641            infoPtr->qWriteCount = qPtrs & (qSize - 1);
642      }
643        else
644         {
645            infoPtr->qWriteCount = (qPtrs / entrySize) & (qSize - 1);
646        }
647        }
648    }
649     }
650     return IX_SUCCESS;
651 }
652
653 PUBLIC IX_STATUS
654 ixQMgrQBurstWrite (IxQMgrQId qId,
655           unsigned numEntries,
656         UINT32 *entries)
657 {
658     extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
659     IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
660     UINT32 status;
661
662     /* update the current write count */
663     infoPtr->qWriteCount += numEntries;
664
665     if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
666     {
667     volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
668     while (numEntries--)
669     {
670        IX_OSAL_WRITE_LONG(qAccRegAddr, *entries);
671         entries++;
672   }
673     }
674     else
675     {
676  IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
677   int i;
678
679   /* write each queue entry */
680     while (numEntries--)
681     {
682        /* write the queueEntrySize number of words for each entry */
683        for (i = 0; i < entrySizeInWords; i++)
684       {
685        IX_OSAL_WRITE_LONG((infoPtr->qAccRegAddr + i), *entries);
686      entries++;
687       }
688    }
689     }
690
691     /* check if the write count overflows */
692     if (infoPtr->qWriteCount > infoPtr->qSizeInEntries)
693     {
694   /* reset the current write count */
695  infoPtr->qWriteCount = infoPtr->qSizeInEntries;
696     }
697
698     /* Check if overflow occurred on the write operation */
699     if (qId < IX_QMGR_MIN_QUEUPP_QID)
700     {
701    /* get the queue status */
702   status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
703
704   /* read the status twice because the status may 
705      * not be ready at the time of the write
706      */
707  if ((status & infoPtr->qOflowStatBitMask) ||
708         ((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
709          & infoPtr->qOflowStatBitMask))
710  {
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;
715   }
716     }
717
718     return IX_SUCCESS;
719 }
720
721 PUBLIC IX_STATUS
722 ixQMgrQStatusGet (IxQMgrQId qId,
723           IxQMgrQStatus *qStatus)
724 {
725     /* read the status of a queue in the range 0-31 */
726     if (qId < IX_QMGR_MIN_QUEUPP_QID)
727     {
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;
735
736   UINT32 lowStatBitsOffset = ixQMgrAqmIfQueLowStatBitsOffset[qId];
737     UINT32 lowStatBitsMask   = ixQMgrAqmIfQueLowStatBitsMask;
738    UINT32 underflowBitMask  = infoPtr->qUflowStatBitMask;
739   UINT32 overflowBitMask   = infoPtr->qOflowStatBitMask;
740
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;
745
746    /* Check if the queue has overflowed */
747  if (IX_OSAL_READ_LONG(qUOStatRegAddr) & overflowBitMask)
748   {
749        /* clear the overflow status bit if it was set */
750        IX_OSAL_WRITE_LONG(qUOStatRegAddr,
751                  (IX_OSAL_READ_LONG(qUOStatRegAddr) &
752                ~overflowBitMask));
753        *qStatus |= IX_QMGR_Q_STATUS_OF_BIT_MASK;
754    }
755
756    /* Check if the queue has underflowed */
757         if (IX_OSAL_READ_LONG(qUOStatRegAddr) & underflowBitMask)
758  {
759        /* clear the underflow status bit if it was set */
760       IX_OSAL_WRITE_LONG(qUOStatRegAddr,
761                  (IX_OSAL_READ_LONG(qUOStatRegAddr) &
762                ~underflowBitMask));
763       *qStatus |= IX_QMGR_Q_STATUS_UF_BIT_MASK;
764    }
765     }
766     else /* read status of a queue in the range 32-63 */
767     {
768  extern UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
769     extern UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
770     extern UINT32 ixQMgrAqmIfQueUppStat0BitMask[];
771   extern UINT32 ixQMgrAqmIfQueUppStat1BitMask[];
772
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];
778
779     /* Reset the status bits */
780  *qStatus = 0;
781
782    /* Check if the queue is nearly empty */
783     if (IX_OSAL_READ_LONG(qNearEmptyStatRegAddr) & qNearEmptyStatBitMask)
784  {
785        *qStatus |= IX_QMGR_Q_STATUS_NE_BIT_MASK;
786    }
787
788    /* Check if the queue is full */
789     if (IX_OSAL_READ_LONG(qFullStatRegAddr) & qFullStatBitMask)
790    {
791        *qStatus |= IX_QMGR_Q_STATUS_F_BIT_MASK;
792     }
793     }
794     return IX_SUCCESS;
795 }
796 #endif /* def NO_INLINE_APIS */