IxQMgrDispatcher.c 40 KB

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