source: SVN/rincon/u-boot/cpu/ixp/npe/IxQMgrDispatcher.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 39.9 KB
Line 
1/**
2 * @file    IxQMgrDispatcher.c
3 *
4 * @author Intel Corporation
5 * @date    20-Dec-2001
6 *   
7 * @brief   This file contains the implementation of the Dispatcher sub component
8 *
9 *
10 * @par
11 * IXP400 SW Release version 2.0
12 *
13 * -- Copyright Notice --
14 *
15 * @par
16 * Copyright 2001-2005, Intel Corporation.
17 * All rights reserved.
18 *
19 * @par
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 * 3. Neither the name of the Intel Corporation nor the names of its contributors
29 *    may be used to endorse or promote products derived from this software
30 *    without specific prior written permission.
31 *
32 * @par
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
34 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 *
45 * @par
46 * -- End of Copyright Notice --
47*/
48
49/*
50 * User defined include files.
51 */
52#include "IxQMgr.h"
53#include "IxQMgrAqmIf_p.h"
54#include "IxQMgrQCfg_p.h"
55#include "IxQMgrDispatcher_p.h"
56#include "IxQMgrLog_p.h"
57#include "IxQMgrDefines_p.h"
58#include "IxFeatureCtrl.h"
59#include "IxOsal.h"
60
61
62
63/*
64 * #defines and macros used in this file.
65 */
66
67
68/*
69 * This constant is used to indicate the number of priority levels supported
70 */
71#define IX_QMGR_NUM_PRIORITY_LEVELS 3
72
73/*
74 * This constant is used to set the size of the array of status words
75 */
76#define MAX_Q_STATUS_WORDS      4
77
78/*
79 * This macro is used to check if a given priority is valid
80 */
81#define IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority) \
82(((priority) >= IX_QMGR_Q_PRIORITY_0) && ((priority) <= IX_QMGR_Q_PRIORITY_2))
83
84/*
85 * This macto is used to check that a given interrupt source is valid
86 */
87#define IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel) \
88(((srcSel) >= IX_QMGR_Q_SOURCE_ID_E) && ((srcSel) <= IX_QMGR_Q_SOURCE_ID_NOT_F))
89
90/*
91 * Number of times a dummy callback is called before logging a trace
92 * message
93 */
94#define LOG_THROTTLE_COUNT 1000000
95
96/* Priority tables limits */
97#define IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX (0)
98#define IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX (16)
99#define IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX (31)
100#define IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX (32)
101#define IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX (48)
102#define IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX (63)
103 
104/*
105 * This macro is used to check if a given callback type is valid
106 */
107#define IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type) \
108            (((type) >= IX_QMGR_TYPE_REALTIME_OTHER) && \
109            ((type) <= IX_QMGR_TYPE_REALTIME_SPORADIC))
110
111/*
112 * define max index in lower queue to use in loops
113 */
114#define IX_QMGR_MAX_LOW_QUE_TABLE_INDEX (31)
115
116/*
117 * Typedefs whose scope is limited to this file.
118 */
119
120/*
121 * Information on a queue needed by the Dispatcher
122 */
123typedef struct 
124{
125    IxQMgrCallback callback;       /* Notification callback                  */
126    IxQMgrCallbackId callbackId;   /* Notification callback identifier       */
127    unsigned dummyCallbackCount;   /* Number of times runs of dummy callback */
128    IxQMgrPriority priority;       /* Dispatch priority                      */
129    unsigned int statusWordOffset; /* Offset to the status word to check     */
130    UINT32 statusMask;             /* Status mask                            */   
131    UINT32 statusCheckValue;       /* Status check value                     */
132    UINT32 intRegCheckMask;        /* Interrupt register check mask          */
133} IxQMgrQInfo;
134
135/*
136 * Variable declarations global to this file. Externs are followed by
137 * statics.
138 */
139
140/*
141 * Flag to keep record of what dispatcher set in featureCtrl when ixQMgrInit()
142 * is called. This is needed because it is possible that a client might
143 * change whether the live lock prevention dispatcher is used between
144 * calls to ixQMgrInit() and ixQMgrDispatcherLoopGet().
145 */
146PRIVATE IX_STATUS ixQMgrOrigB0Dispatcher = IX_FEATURE_CTRL_COMPONENT_ENABLED;
147
148/*
149 * keep record of Q types - not in IxQMgrQInfo for performance as
150 * it is only used with ixQMgrDispatcherLoopRunB0LLP()
151 */
152PRIVATE IxQMgrType ixQMgrQTypes[IX_QMGR_MAX_NUM_QUEUES];
153
154/*
155 * This array contains a list of queue identifiers ordered by priority. The table
156 * is split logically between queue identifiers 0-31 and 32-63.
157 */
158static IxQMgrQId priorityTable[IX_QMGR_MAX_NUM_QUEUES];
159
160/*
161 * This flag indicates to the dispatcher that the priority table needs to be rebuilt.
162 */
163static BOOL rebuildTable = FALSE;
164
165/* Dispatcher statistics */
166static IxQMgrDispatcherStats dispatcherStats;
167
168/* Table of queue information */
169static IxQMgrQInfo dispatchQInfo[IX_QMGR_MAX_NUM_QUEUES];
170
171/* Masks use to identify the first queues in the priority tables
172*  when comparing with the interrupt register
173*/
174static unsigned int lowPriorityTableFirstHalfMask;
175static unsigned int uppPriorityTableFirstHalfMask;
176
177/*
178 * Static function prototypes
179 */
180
181/*
182 * This function is the default callback for all queues
183 */
184PRIVATE void
185dummyCallback (IxQMgrQId qId,         
186               IxQMgrCallbackId cbId);
187
188PRIVATE void
189ixQMgrDispatcherReBuildPriorityTable (void);
190
191/*
192 * Function definitions.
193 */
194void
195ixQMgrDispatcherInit (void)
196{
197    int i;
198    IxFeatureCtrlProductId productId = 0;
199    IxFeatureCtrlDeviceId deviceId = 0;
200    BOOL stickyIntSilicon = TRUE; 
201
202    /* Set default priorities */
203    for (i=0; i< IX_QMGR_MAX_NUM_QUEUES; i++)
204    {
205        dispatchQInfo[i].callback = dummyCallback;
206        dispatchQInfo[i].callbackId = 0;
207        dispatchQInfo[i].dummyCallbackCount = 0;
208        dispatchQInfo[i].priority = IX_QMGR_Q_PRIORITY_2;
209        dispatchQInfo[i].statusWordOffset = 0;
210        dispatchQInfo[i].statusCheckValue = 0;
211        dispatchQInfo[i].statusMask = 0; 
212        /*
213         * There are two interrupt registers, 32 bits each. One for the lower
214         * queues(0-31) and one for the upper queues(32-63). Therefore need to
215         * mod by 32 i.e the min upper queue identifier.
216         */
217        dispatchQInfo[i].intRegCheckMask = (1<<(i%(IX_QMGR_MIN_QUEUPP_QID)));
218
219        /*
220         * Set the Q types - will only be used with livelock
221         */
222        ixQMgrQTypes[i] = IX_QMGR_TYPE_REALTIME_OTHER;
223
224        /* Reset queue statistics */
225        dispatcherStats.queueStats[i].callbackCnt = 0;
226        dispatcherStats.queueStats[i].priorityChangeCnt = 0;
227        dispatcherStats.queueStats[i].intNoCallbackCnt = 0;
228        dispatcherStats.queueStats[i].intLostCallbackCnt = 0;
229        dispatcherStats.queueStats[i].notificationEnabled = FALSE;
230        dispatcherStats.queueStats[i].srcSel = 0;
231
232    }
233
234    /* Priority table. Order the table from queue 0 to 63 */
235    ixQMgrDispatcherReBuildPriorityTable();
236
237    /* Reset statistics */
238    dispatcherStats.loopRunCnt = 0;
239
240    /* Get the device ID for the underlying silicon */
241    deviceId = ixFeatureCtrlDeviceRead();
242   
243    /* Get the product ID for the underlying silicon */
244    productId = ixFeatureCtrlProductIdRead();
245
246    /*
247     * Check featureCtrl to see if Livelock prevention is required
248     */
249    ixQMgrOrigB0Dispatcher = ixFeatureCtrlSwConfigurationCheck( 
250                                 IX_FEATURECTRL_ORIGB0_DISPATCHER);
251
252    /*
253     * Check if the silicon supports the sticky interrupt feature.
254     * IF (IXP42X AND A0) -> No sticky interrupt feature supported
255     */
256    if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == 
257        (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) &&
258        (IX_FEATURE_CTRL_SILICON_TYPE_A0 == 
259        (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId))) 
260    {
261       stickyIntSilicon = FALSE;
262    }
263
264    /*
265     * IF user wants livelock prev option AND silicon supports sticky interrupt
266     * feature -> enable the sticky interrupt bit
267     */
268    if ((IX_FEATURE_CTRL_SWCONFIG_DISABLED == ixQMgrOrigB0Dispatcher) &&
269         stickyIntSilicon) 
270    {
271        ixQMgrStickyInterruptRegEnable();
272    }
273}
274
275IX_STATUS
276ixQMgrDispatcherPrioritySet (IxQMgrQId qId,
277                             IxQMgrPriority priority)
278{   
279    int ixQMgrLockKey;
280
281    if (!ixQMgrQIsConfigured(qId))
282    {
283        return IX_QMGR_Q_NOT_CONFIGURED;
284    }
285   
286    if (!IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority))
287    {
288        return IX_QMGR_Q_INVALID_PRIORITY;
289    }
290
291    ixQMgrLockKey = ixOsalIrqLock();
292   
293    /* Change priority */
294    dispatchQInfo[qId].priority = priority;
295    /* Set flag */
296    rebuildTable = TRUE;
297
298    ixOsalIrqUnlock(ixQMgrLockKey);
299
300#ifndef NDEBUG
301    /* Update statistics */
302    dispatcherStats.queueStats[qId].priorityChangeCnt++;
303#endif
304
305    return IX_SUCCESS;
306}
307
308IX_STATUS
309ixQMgrNotificationCallbackSet (IxQMgrQId qId,
310                               IxQMgrCallback callback,
311                               IxQMgrCallbackId callbackId)
312{
313    if (!ixQMgrQIsConfigured(qId))
314    {
315        return IX_QMGR_Q_NOT_CONFIGURED;
316    }
317
318    if (NULL == callback)
319    {
320        /* Reset to dummy callback */
321        dispatchQInfo[qId].callback = dummyCallback;
322        dispatchQInfo[qId].dummyCallbackCount = 0;
323        dispatchQInfo[qId].callbackId = 0;
324    }
325    else 
326    {
327        dispatchQInfo[qId].callback = callback;
328        dispatchQInfo[qId].callbackId = callbackId;
329    }
330
331    return IX_SUCCESS;
332}
333
334IX_STATUS
335ixQMgrNotificationEnable (IxQMgrQId qId, 
336                          IxQMgrSourceId srcSel)
337{
338    IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */
339    IxQMgrQStatus qStatusOnExit; /* to this function               */
340    int ixQMgrLockKey;
341
342#ifndef NDEBUG
343    if (!ixQMgrQIsConfigured (qId))
344    {
345        return IX_QMGR_Q_NOT_CONFIGURED;
346    }
347
348    if ((qId < IX_QMGR_MIN_QUEUPP_QID) &&
349       !IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel))
350    {
351        /* QId 0-31 source id invalid */
352        return IX_QMGR_INVALID_INT_SOURCE_ID;
353    }
354
355    if ((IX_QMGR_Q_SOURCE_ID_NE != srcSel) &&
356        (qId >= IX_QMGR_MIN_QUEUPP_QID))
357    {
358        /*
359         * For queues 32-63 the interrupt source is fixed to the Nearly
360         * Empty status flag and therefore should have a srcSel of NE.
361         */
362        return IX_QMGR_INVALID_INT_SOURCE_ID;
363    }
364#endif
365
366#ifndef NDEBUG
367    dispatcherStats.queueStats[qId].notificationEnabled = TRUE;
368    dispatcherStats.queueStats[qId].srcSel = srcSel;
369#endif
370
371    /* Get the current queue status */
372    ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry);
373 
374    /*
375     * Enabling interrupts results in Read-Modify-Write
376     * so need critical section
377     */
378
379    ixQMgrLockKey = ixOsalIrqLock();
380
381    /* Calculate the checkMask and checkValue for this q */
382    ixQMgrAqmIfQStatusCheckValsCalc (qId,
383                                     srcSel,
384                                     &dispatchQInfo[qId].statusWordOffset,
385                                     &dispatchQInfo[qId].statusCheckValue,
386                                     &dispatchQInfo[qId].statusMask);
387
388
389    /* Set the interupt source is this queue is in the range 0-31 */
390    if (qId < IX_QMGR_MIN_QUEUPP_QID)
391    {
392        ixQMgrAqmIfIntSrcSelWrite (qId, srcSel);
393    }
394
395    /* Enable the interrupt */
396    ixQMgrAqmIfQInterruptEnable (qId);
397
398    ixOsalIrqUnlock(ixQMgrLockKey);
399   
400    /* Get the current queue status */
401    ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit);
402 
403    /* If the status has changed return a warning */
404    if (qStatusOnEntry != qStatusOnExit)
405    {
406        return IX_QMGR_WARNING;
407    }
408   
409    return IX_SUCCESS;
410}
411
412
413IX_STATUS
414ixQMgrNotificationDisable (IxQMgrQId qId)
415{
416    int ixQMgrLockKey;
417
418#ifndef NDEBUG
419    /* Validate parameters */
420    if (!ixQMgrQIsConfigured (qId))
421    {
422        return IX_QMGR_Q_NOT_CONFIGURED;
423    }
424#endif
425 
426    /*
427     * Enabling interrupts results in Read-Modify-Write
428     * so need critical section
429     */
430#ifndef NDEBUG
431    dispatcherStats.queueStats[qId].notificationEnabled = FALSE;
432#endif
433
434    ixQMgrLockKey = ixOsalIrqLock();
435
436    ixQMgrAqmIfQInterruptDisable (qId);
437   
438    ixOsalIrqUnlock(ixQMgrLockKey);
439
440    return IX_SUCCESS;   
441}
442
443void 
444ixQMgrStickyInterruptRegEnable(void)
445{
446 /* Use Aqm If function to set Interrupt Register0 Bit-3 */ 
447 ixQMgrAqmIfIntSrcSelReg0Bit3Set ();   
448}
449
450#if !defined __XSCALE__ || defined __linux
451
452/* Count the number of leading zero bits in a word,
453 * and return the same value than the CLZ instruction.
454 *
455 * word (in)    return value (out)
456 * 0x80000000   0
457 * 0x40000000   1
458 * ,,,          ,,,
459 * 0x00000002   30
460 * 0x00000001   31
461 * 0x00000000   32
462 *
463 * The C version of this function is used as a replacement
464 * for system not providing the equivalent of the CLZ
465 * assembly language instruction.
466 *
467 * Note that this version is big-endian
468 */
469unsigned int
470ixQMgrCountLeadingZeros(UINT32 word)
471{
472  unsigned int leadingZerosCount = 0;
473
474  if (word == 0)
475  {
476      return 32;
477  }
478  /* search the first bit set by testing the MSB and shifting the input word */
479  while ((word & 0x80000000) == 0)
480  {
481      word <<= 1;
482      leadingZerosCount++;
483  }
484  return leadingZerosCount;
485}
486#endif /* not  __XSCALE__ or __linux */
487
488void
489ixQMgrDispatcherLoopGet (IxQMgrDispatcherFuncPtr *qDispatcherFuncPtr)
490{
491  IxFeatureCtrlProductId productId = 0;
492  IxFeatureCtrlDeviceId deviceId = 0;
493 
494  /* Get the device ID for the underlying silicon */
495  deviceId = ixFeatureCtrlDeviceRead();
496
497  /* Get the product ID for the underlying silicon */
498  productId = ixFeatureCtrlProductIdRead ();
499
500  /* IF (IXP42X AND A0 silicon) -> use ixQMgrDispatcherLoopRunA0 */
501  if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X ==
502      (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) &&
503      (IX_FEATURE_CTRL_SILICON_TYPE_A0 == 
504      (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId))) 
505  {
506    /*For IXP42X A0 silicon */
507    *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunA0 ;
508  } 
509  else /*For IXP42X B0 or IXP46X silicon*/ 
510  { 
511    if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixQMgrOrigB0Dispatcher)
512    {
513        /* Default for IXP42X B0 and IXP46X silicon */
514        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0;
515    }
516    else 
517    {
518        /* FeatureCtrl indicated that livelock dispatcher be used */
519        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0LLP;
520    }
521  }
522}
523
524void
525ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group)
526{
527    UINT32 intRegVal;                /* Interrupt reg val */
528    UINT32 intRegValAfterWrite;      /* Interrupt reg val after writing back */
529    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
530    UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS];  /* Status b4 interrupt write */
531    UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */
532    IxQMgrQInfo *currDispatchQInfo;
533    BOOL statusChangeFlag;
534
535    int priorityTableIndex;/* Priority table index */
536    int qIndex;            /* Current queue being processed */
537    int endIndex;          /* Index of last queue to process */
538
539#ifndef NDEBUG
540    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 
541              (group == IX_QMGR_QUELOW_GROUP));
542#endif
543
544    /* Read Q status registers before interrupt status read/write */
545    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write);
546
547    /* Read the interrupt register */
548    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
549
550    /* No bit set : nothing to process (the reaminder of the algorithm is
551    * based on the fact that the interrupt register value contains at
552    * least one bit set
553    */
554    if (intRegVal == 0) 
555    {
556#ifndef NDEBUG
557        /* Update statistics */
558        dispatcherStats.loopRunCnt++;
559#endif
560
561        /* Rebuild the priority table if needed */
562        if (rebuildTable)
563        {
564            ixQMgrDispatcherReBuildPriorityTable ();
565        }
566
567        return;
568    }
569   
570    /* Write it back to clear the interrupt */
571    ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
572
573    /* Read Q status registers after interrupt status read/write */
574    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite);
575 
576    /* get the first queue Id from the interrupt register value */
577    qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
578
579    /* check if any change occured during hw register modifications */ 
580    if (IX_QMGR_QUELOW_GROUP == group)
581    {
582        statusChangeFlag = 
583            (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) ||
584            (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) ||
585            (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) ||
586            (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]);
587    }
588    else
589    {
590        statusChangeFlag = 
591            (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]);
592        /* Set the queue range based on the queue group to proccess */
593        qIndex += IX_QMGR_MIN_QUEUPP_QID;
594    }
595
596    if (statusChangeFlag == FALSE)
597    {
598        /* check if the interrupt register contains
599         * only 1 bit set (happy day scenario)
600         */
601        currDispatchQInfo = &dispatchQInfo[qIndex];
602        if (intRegVal == currDispatchQInfo->intRegCheckMask)
603        {
604            /* only 1 queue event triggered a notification *
605             * Call the callback function for this queue
606             */
607            currDispatchQInfo->callback (qIndex,
608                                         currDispatchQInfo->callbackId); 
609#ifndef NDEBUG
610            /* Update statistics */
611            dispatcherStats.queueStats[qIndex].callbackCnt++;
612#endif
613        }
614        else 
615        {
616            /* the event is triggered by more than 1 queue,
617             * the queue search will be starting from the beginning
618             * or the middle of the priority table
619             *
620             * the serach will end when all the bits of the interrupt
621             * register are cleared. There is no need to maintain
622             * a seperate value and test it at each iteration.
623             */
624            if (IX_QMGR_QUELOW_GROUP == group)
625            {
626                /* check if any bit related to queues in the first
627                 * half of the priority table is set
628                 */
629                if (intRegVal & lowPriorityTableFirstHalfMask)
630                {
631                    priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
632                }
633                else
634                {
635                    priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
636                }
637            }
638            else 
639            {
640                /* check if any bit related to queues in the first
641                 * half of the priority table is set
642                 */
643                if (intRegVal & uppPriorityTableFirstHalfMask)
644                {
645                    priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
646                }
647                else
648                {
649                    priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
650                }
651            }
652           
653            /* iterate following the priority table until all the bits
654             * of the interrupt register are cleared.
655             */
656            do
657            {
658                qIndex = priorityTable[priorityTableIndex++];
659                currDispatchQInfo = &dispatchQInfo[qIndex];
660                intRegCheckMask = currDispatchQInfo->intRegCheckMask;
661               
662                /* If this queue caused this interrupt to be raised */
663                if (intRegVal & intRegCheckMask)
664                {
665                    /* Call the callback function for this queue */
666                    currDispatchQInfo->callback (qIndex,
667                                                 currDispatchQInfo->callbackId);
668#ifndef NDEBUG
669                    /* Update statistics */
670                    dispatcherStats.queueStats[qIndex].callbackCnt++;
671#endif
672                   
673                    /* Clear the interrupt register bit */
674                    intRegVal &= ~intRegCheckMask;
675                }
676            }
677            while(intRegVal);
678        }
679    }
680    else
681    {
682    /* A change in queue status occured during the hw interrupt
683     * register update. To maintain the interrupt consistency, it
684     * is necessary to iterate through all queues of the queue group.
685     */
686
687    /* Read interrupt status again */
688    ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite);
689
690    if (IX_QMGR_QUELOW_GROUP == group)
691    {
692        priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
693        endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX;
694    }
695    else
696    {
697        priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
698        endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX;
699    }
700
701    for ( ; priorityTableIndex<=endIndex; priorityTableIndex++)
702    {
703        qIndex = priorityTable[priorityTableIndex];
704        currDispatchQInfo = &dispatchQInfo[qIndex];
705        intRegCheckMask = currDispatchQInfo->intRegCheckMask;
706
707        /* If this queue caused this interrupt to be raised */
708        if (intRegVal & intRegCheckMask)
709        { 
710            /* Call the callback function for this queue */
711            currDispatchQInfo->callback (qIndex,
712                                         currDispatchQInfo->callbackId);
713#ifndef NDEBUG
714            /* Update statistics */
715            dispatcherStats.queueStats[qIndex].callbackCnt++;
716#endif
717           
718        } /* if (intRegVal .. */
719
720        /*
721         * If interrupt bit is set in intRegValAfterWrite don't
722         * proceed as this will be caught in next interrupt
723         */
724        else if ((intRegValAfterWrite & intRegCheckMask) == 0)
725        {
726            /* Check if an interrupt was lost for this Q */
727            if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write,
728                                        qStatusWordsAfterWrite,
729                                        currDispatchQInfo->statusWordOffset,
730                                        currDispatchQInfo->statusCheckValue,
731                                        currDispatchQInfo->statusMask))
732            {
733                /* Call the callback function for this queue */
734                currDispatchQInfo->callback (qIndex, 
735                                             dispatchQInfo[qIndex].callbackId);                 
736#ifndef NDEBUG
737                /* Update statistics */
738                dispatcherStats.queueStats[qIndex].callbackCnt++;
739                dispatcherStats.queueStats[qIndex].intLostCallbackCnt++;
740#endif
741            } /* if ixQMgrAqmIfQStatusCheck(.. */
742        } /* else if ((intRegValAfterWrite ... */
743    } /* for (priorityTableIndex=0 ... */
744    }
745
746    /* Rebuild the priority table if needed */
747    if (rebuildTable)
748    {
749        ixQMgrDispatcherReBuildPriorityTable ();
750    }
751
752#ifndef NDEBUG
753    /* Update statistics */
754    dispatcherStats.loopRunCnt++;
755#endif
756}
757
758
759
760void
761ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group)
762{
763    UINT32 intRegVal;                /* Interrupt reg val */
764    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
765    IxQMgrQInfo *currDispatchQInfo;
766
767
768    int priorityTableIndex; /* Priority table index */
769    int qIndex;             /* Current queue being processed */
770
771#ifndef NDEBUG
772    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
773              (group == IX_QMGR_QUELOW_GROUP));
774    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 
775              (group == IX_QMGR_QUELOW_GROUP));
776#endif
777
778    /* Read the interrupt register */
779    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
780
781
782    /* No queue has interrupt register set */
783    if (intRegVal != 0)
784    {
785
786            /* Write it back to clear the interrupt */
787            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
788
789            /* get the first queue Id from the interrupt register value */
790            qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
791
792            if (IX_QMGR_QUEUPP_GROUP == group)
793            {
794                /* Set the queue range based on the queue group to proccess */
795                qIndex += IX_QMGR_MIN_QUEUPP_QID;
796            }
797
798            /* check if the interrupt register contains
799             * only 1 bit set
800             * For example:
801             *                                        intRegVal = 0x0010
802             *               currDispatchQInfo->intRegCheckMask = 0x0010
803             *    intRegVal == currDispatchQInfo->intRegCheckMask is TRUE.
804             */
805             currDispatchQInfo = &dispatchQInfo[qIndex];
806             if (intRegVal == currDispatchQInfo->intRegCheckMask)
807             {
808                /* only 1 queue event triggered a notification *
809                 * Call the callback function for this queue
810                 */
811                currDispatchQInfo->callback (qIndex,
812                                     currDispatchQInfo->callbackId);
813#ifndef NDEBUG
814                /* Update statistics */
815                dispatcherStats.queueStats[qIndex].callbackCnt++;
816#endif
817             }
818             else
819             {
820                 /* the event is triggered by more than 1 queue,
821                  * the queue search will be starting from the beginning
822                  * or the middle of the priority table
823                  *
824                  * the serach will end when all the bits of the interrupt
825                  * register are cleared. There is no need to maintain
826                  * a seperate value and test it at each iteration.
827                  */
828                 if (IX_QMGR_QUELOW_GROUP == group)
829                 {
830                     /* check if any bit related to queues in the first
831                      * half of the priority table is set
832                      */
833                     if (intRegVal & lowPriorityTableFirstHalfMask)
834                     {
835                         priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
836                     }
837                     else
838                     {
839                         priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
840                     }
841                 }
842                else
843                 {
844                     /* check if any bit related to queues in the first
845                      * half of the priority table is set
846                      */
847                     if (intRegVal & uppPriorityTableFirstHalfMask)
848                     {
849                         priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
850                     }
851                     else
852                     {
853                         priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
854                     }
855                 }
856
857                 /* iterate following the priority table until all the bits
858                  * of the interrupt register are cleared.
859                  */
860                 do
861                 {
862                     qIndex = priorityTable[priorityTableIndex++];
863                     currDispatchQInfo = &dispatchQInfo[qIndex];
864                     intRegCheckMask = currDispatchQInfo->intRegCheckMask;
865
866                     /* If this queue caused this interrupt to be raised */
867                     if (intRegVal & intRegCheckMask)
868                     {
869                         /* Call the callback function for this queue */
870                         currDispatchQInfo->callback (qIndex,
871                                              currDispatchQInfo->callbackId);
872#ifndef NDEBUG
873                         /* Update statistics */
874                         dispatcherStats.queueStats[qIndex].callbackCnt++;
875#endif
876
877                         /* Clear the interrupt register bit */
878                         intRegVal &= ~intRegCheckMask;
879                     }
880                  }
881                  while(intRegVal);
882             } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
883     } /* End of intRegVal != 0 */
884
885#ifndef NDEBUG
886    /* Update statistics */
887    dispatcherStats.loopRunCnt++;
888#endif
889
890    /* Rebuild the priority table if needed */
891    if (rebuildTable)
892    {
893        ixQMgrDispatcherReBuildPriorityTable ();
894    }
895}
896
897void
898ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group)
899{
900    UINT32 intRegVal =0;                /* Interrupt reg val */
901    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
902    IxQMgrQInfo *currDispatchQInfo;
903
904    int priorityTableIndex; /* Priority table index */
905    int qIndex;             /* Current queue being processed */
906
907    UINT32 intRegValCopy = 0;
908    UINT32 intEnableRegVal = 0;
909    UINT8 i = 0;
910
911#ifndef NDEBUG
912    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
913              (group == IX_QMGR_QUELOW_GROUP));
914#endif
915
916    /* Read the interrupt register */
917    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
918
919    /*
920     * mask any interrupts that are not enabled
921     */
922    ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal);
923    intRegVal &= intEnableRegVal;
924
925    /* No queue has interrupt register set */
926    if (intRegVal != 0)
927    {
928        if (IX_QMGR_QUELOW_GROUP == group)
929        {
930            /*
931             * As the sticky bit is set, the interrupt register will
932             * not clear if write back at this point because the condition
933             * has not been cleared. Take a copy and write back later after
934             * the condition has been cleared
935             */
936            intRegValCopy = intRegVal;
937        }
938        else
939        {
940            /* no sticky for upper Q's, so write back now */
941            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
942        }
943
944        /* get the first queue Id from the interrupt register value */
945        qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
946
947        if (IX_QMGR_QUEUPP_GROUP == group)
948        {
949            /* Set the queue range based on the queue group to proccess */
950            qIndex += IX_QMGR_MIN_QUEUPP_QID;
951        }
952
953        /* check if the interrupt register contains
954        * only 1 bit set
955        * For example:
956        *                                        intRegVal = 0x0010
957        *               currDispatchQInfo->intRegCheckMask = 0x0010
958        *    intRegVal == currDispatchQInfo->intRegCheckMask is TRUE.
959        */
960        currDispatchQInfo = &dispatchQInfo[qIndex];
961        if (intRegVal == currDispatchQInfo->intRegCheckMask)
962        {
963
964            /*
965             * check if Q type periodic -  only lower queues can
966             * have there type set to periodic
967             */
968            if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
969            {
970                /*
971                 * Disable the notifications on any sporadics
972                 */
973                for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
974                {
975                    if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i])
976                    {
977                        ixQMgrNotificationDisable(i);
978#ifndef NDEBUG
979                        /* Update statistics */
980                        dispatcherStats.queueStats[i].disableCount++;
981#endif
982                    }
983                }
984            }
985
986            currDispatchQInfo->callback (qIndex,
987                                         currDispatchQInfo->callbackId);
988#ifndef NDEBUG
989            /* Update statistics */
990            dispatcherStats.queueStats[qIndex].callbackCnt++;
991#endif
992        }
993        else
994        {
995            /* the event is triggered by more than 1 queue,
996            * the queue search will be starting from the beginning
997            * or the middle of the priority table
998            *
999            * the serach will end when all the bits of the interrupt
1000            * register are cleared. There is no need to maintain
1001            * a seperate value and test it at each iteration.
1002            */
1003            if (IX_QMGR_QUELOW_GROUP == group)
1004            {
1005                /* check if any bit related to queues in the first
1006                 * half of the priority table is set
1007                 */
1008                if (intRegVal & lowPriorityTableFirstHalfMask)
1009                {
1010                    priorityTableIndex =
1011                                       IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
1012                }
1013                else
1014                {
1015                    priorityTableIndex =
1016                                       IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
1017                }
1018            }
1019            else
1020            {
1021                /* check if any bit related to queues in the first
1022                 * half of the priority table is set
1023                 */
1024                if (intRegVal & uppPriorityTableFirstHalfMask)
1025                {
1026                    priorityTableIndex =
1027                                       IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
1028                }
1029                else
1030                {
1031                    priorityTableIndex =
1032                                       IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
1033                }
1034            }
1035
1036            /* iterate following the priority table until all the bits
1037             * of the interrupt register are cleared.
1038             */
1039            do
1040            {
1041                qIndex = priorityTable[priorityTableIndex++];
1042                currDispatchQInfo = &dispatchQInfo[qIndex];
1043                intRegCheckMask = currDispatchQInfo->intRegCheckMask;
1044
1045                /* If this queue caused this interrupt to be raised */
1046                if (intRegVal & intRegCheckMask)
1047                {
1048                    /*
1049                     * check if Q type periodic - only lower queues can
1050                     * have there type set to periodic. There can only be one
1051                     * periodic queue, so the sporadics are only disabled once.
1052                     */
1053                    if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
1054                    {
1055                        /*
1056                         * Disable the notifications on any sporadics
1057                         */
1058                        for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
1059                        {
1060                            if (IX_QMGR_TYPE_REALTIME_SPORADIC == 
1061                                    ixQMgrQTypes[i])
1062                            {
1063                                ixQMgrNotificationDisable(i);
1064                                /*
1065                                 * remove from intRegVal as we don't want
1066                                 * to service any sporadics now
1067                                 */
1068                                intRegVal &= ~dispatchQInfo[i].intRegCheckMask;
1069#ifndef NDEBUG
1070                                /* Update statistics */
1071                                dispatcherStats.queueStats[i].disableCount++;
1072#endif
1073                            }
1074                        }
1075                    }
1076
1077                    currDispatchQInfo->callback (qIndex,
1078                                                 currDispatchQInfo->callbackId);
1079#ifndef NDEBUG
1080                    /* Update statistics */
1081                    dispatcherStats.queueStats[qIndex].callbackCnt++;
1082#endif
1083                    /* Clear the interrupt register bit */
1084                    intRegVal &= ~intRegCheckMask;
1085                }
1086            }
1087            while(intRegVal);
1088        } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
1089    } /* End of intRegVal != 0 */
1090
1091#ifndef NDEBUG
1092    /* Update statistics */
1093    dispatcherStats.loopRunCnt++;
1094#endif
1095
1096    if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group))
1097    {
1098        /*
1099         * lower groups (therefore sticky) AND at least one enabled interrupt
1100         * Write back to clear the interrupt
1101         */
1102        ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy);
1103    }
1104
1105    /* Rebuild the priority table if needed */
1106    if (rebuildTable)
1107    {
1108        ixQMgrDispatcherReBuildPriorityTable ();
1109    }
1110}
1111
1112PRIVATE void
1113ixQMgrDispatcherReBuildPriorityTable (void)
1114{
1115    UINT32 qIndex;
1116    UINT32 priority;
1117    int lowQuePriorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
1118    int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
1119
1120    /* Reset the rebuild flag */
1121    rebuildTable = FALSE;
1122
1123    /* initialize the mak used to identify the queues in the first half
1124     * of the priority table
1125     */
1126    lowPriorityTableFirstHalfMask = 0;
1127    uppPriorityTableFirstHalfMask = 0;
1128   
1129    /* For each priority level */
1130    for(priority=0; priority<IX_QMGR_NUM_PRIORITY_LEVELS; priority++)
1131    {
1132        /* Foreach low queue in this priority */
1133        for(qIndex=0; qIndex<IX_QMGR_MIN_QUEUPP_QID; qIndex++)
1134        {
1135            if (dispatchQInfo[qIndex].priority == priority)
1136            { 
1137                /* build the priority table bitmask which match the
1138                 * queues of the first half of the priority table
1139                 */
1140                if (lowQuePriorityTableIndex < IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX) 
1141                {
1142                    lowPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask;
1143                }
1144                /* build the priority table */
1145                priorityTable[lowQuePriorityTableIndex++] = qIndex;
1146            }
1147        }
1148        /* Foreach upp queue */
1149        for(qIndex=IX_QMGR_MIN_QUEUPP_QID; qIndex<=IX_QMGR_MAX_QID; qIndex++)
1150        {
1151            if (dispatchQInfo[qIndex].priority == priority)
1152            {
1153                /* build the priority table bitmask which match the
1154                 * queues of the first half of the priority table
1155                 */
1156                if (uppQuePriorityTableIndex < IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX) 
1157                {
1158                    uppPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask;
1159                }
1160                /* build the priority table */
1161                priorityTable[uppQuePriorityTableIndex++] = qIndex;
1162            }
1163        }
1164    }
1165}
1166
1167IxQMgrDispatcherStats*
1168ixQMgrDispatcherStatsGet (void)
1169{
1170    return &dispatcherStats;
1171}
1172
1173PRIVATE void
1174dummyCallback (IxQMgrQId qId,
1175               IxQMgrCallbackId cbId)
1176{
1177    /* Throttle the trace message */
1178    if ((dispatchQInfo[qId].dummyCallbackCount % LOG_THROTTLE_COUNT) == 0)
1179    {
1180        IX_QMGR_LOG_WARNING2("--> dummyCallback: qId (%d), callbackId (%d)\n",qId,cbId);
1181    }
1182    dispatchQInfo[qId].dummyCallbackCount++;
1183
1184#ifndef NDEBUG
1185    /* Update statistcs */
1186    dispatcherStats.queueStats[qId].intNoCallbackCnt++;
1187#endif
1188}
1189void
1190ixQMgrLLPShow (int resetStats)
1191{
1192#ifndef NDEBUG
1193    UINT8 i = 0;
1194    IxQMgrQInfo *q;
1195    UINT32 intEnableRegVal = 0;
1196
1197    printf ("Livelock statistics are printed on the fly.\n");
1198    printf ("qId Type     EnableCnt DisableCnt IntEnableState Callbacks\n");
1199    printf ("=== ======== ========= ========== ============== =========\n");
1200
1201    for (i=0; i<= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
1202    {
1203        q = &dispatchQInfo[i];
1204
1205        if (ixQMgrQTypes[i] != IX_QMGR_TYPE_REALTIME_OTHER)
1206        {
1207            printf (" %2d ", i);
1208
1209            if (ixQMgrQTypes[i] == IX_QMGR_TYPE_REALTIME_SPORADIC)
1210            {
1211                printf ("Sporadic");
1212            }
1213            else
1214            {
1215                printf ("Periodic");
1216            }
1217
1218           
1219            ixQMgrAqmIfQInterruptEnableRegRead (IX_QMGR_QUELOW_GROUP, 
1220                                                    &intEnableRegVal);
1221               
1222
1223            intEnableRegVal &= dispatchQInfo[i].intRegCheckMask;
1224            intEnableRegVal = intEnableRegVal >> i;
1225
1226            printf (" %10d %10d %10d %10d\n",
1227                    dispatcherStats.queueStats[i].enableCount,
1228                    dispatcherStats.queueStats[i].disableCount,
1229                    intEnableRegVal,
1230                    dispatcherStats.queueStats[i].callbackCnt);
1231
1232            if (resetStats)
1233            {
1234                dispatcherStats.queueStats[i].enableCount =
1235                dispatcherStats.queueStats[i].disableCount = 
1236                dispatcherStats.queueStats[i].callbackCnt = 0;
1237            }
1238        }
1239    }
1240#else
1241    IX_QMGR_LOG0("Livelock Prevention statistics are only collected in debug mode\n");
1242#endif
1243}
1244
1245void
1246ixQMgrPeriodicDone (void)
1247{
1248    UINT32 i = 0;
1249    UINT32 ixQMgrLockKey = 0;
1250
1251    /*
1252     * for the lower queues
1253     */
1254    for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
1255    {
1256        /*
1257         * check for sporadics
1258         */
1259        if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i])
1260        {
1261             /*
1262              * enable any sporadics
1263              */
1264             ixQMgrLockKey = ixOsalIrqLock();
1265             ixQMgrAqmIfQInterruptEnable(i);
1266             ixOsalIrqUnlock(ixQMgrLockKey);
1267#ifndef NDEBUG
1268             /*
1269              * Update statistics
1270              */
1271             dispatcherStats.queueStats[i].enableCount++;
1272             dispatcherStats.queueStats[i].notificationEnabled = TRUE;
1273#endif
1274        }
1275    }
1276}
1277IX_STATUS
1278ixQMgrCallbackTypeSet (IxQMgrQId qId, 
1279                       IxQMgrType type)
1280{
1281    UINT32 ixQMgrLockKey = 0;
1282    IxQMgrType ixQMgrOldType =0;
1283
1284#ifndef NDEBUG
1285    if (!ixQMgrQIsConfigured(qId))
1286    {
1287        return IX_QMGR_Q_NOT_CONFIGURED;
1288    }
1289    if (qId >= IX_QMGR_MIN_QUEUPP_QID)
1290    {
1291        return IX_QMGR_PARAMETER_ERROR;
1292    }
1293    if(!IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type))
1294    {
1295        return IX_QMGR_PARAMETER_ERROR;
1296    }
1297#endif
1298
1299    ixQMgrOldType = ixQMgrQTypes[qId];
1300    ixQMgrQTypes[qId] = type;
1301
1302    /*
1303     * check if Q has been changed from type SPORADIC
1304     */
1305    if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrOldType)
1306    {
1307       /*
1308        * previously Q was a SPORADIC, this means that LLP
1309        * might have had it disabled. enable it now.
1310        */
1311       ixQMgrLockKey = ixOsalIrqLock();
1312       ixQMgrAqmIfQInterruptEnable(qId);
1313       ixOsalIrqUnlock(ixQMgrLockKey);
1314
1315#ifndef NDEBUG
1316       /*
1317        * Update statistics
1318        */
1319       dispatcherStats.queueStats[qId].enableCount++;
1320#endif
1321    }
1322
1323    return IX_SUCCESS;
1324}
1325
1326IX_STATUS
1327ixQMgrCallbackTypeGet (IxQMgrQId qId, 
1328                       IxQMgrType *type)
1329{
1330#ifndef NDEBUG
1331    if (!ixQMgrQIsConfigured(qId))
1332    {
1333        return IX_QMGR_Q_NOT_CONFIGURED;
1334    }
1335    if (qId >= IX_QMGR_MIN_QUEUPP_QID)
1336    {
1337        return IX_QMGR_PARAMETER_ERROR;
1338    }
1339    if(type == NULL)
1340    {
1341         return IX_QMGR_PARAMETER_ERROR;
1342    }
1343#endif
1344
1345    *type = ixQMgrQTypes[qId];
1346    return IX_SUCCESS;
1347}
Note: See TracBrowser for help on using the repository browser.