⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixqmgrdispatcher.c

📁 有关ARM开发板上的IXP400网络驱动程序的源码以。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Count the number of leading zero bits in a word, * and return the same value than the CLZ instruction. * * word (in)    return value (out) * 0x80000000   0 * 0x40000000   1 * ,,,          ,,, * 0x00000002   30 * 0x00000001   31 * 0x00000000   32 * * The C version of this function is used as a replacement  * for system not providing the equivalent of the CLZ  * assembly language instruction. * * Note that this version is big-endian */unsigned intixQMgrCountLeadingZeros(UINT32 word){  unsigned int leadingZerosCount = 0;  if (word == 0)  {      return 32;  }  /* search the first bit set by testing the MSB and shifting the input word */  while ((word & 0x80000000) == 0)  {      word <<= 1;      leadingZerosCount++;  }  return leadingZerosCount;}#endif /* not  __XSCALE__ or __linux */voidixQMgrDispatcherLoopGet (IxQMgrDispatcherFuncPtr *qDispatcherFuncPtr){  IxFeatureCtrlProductId productId = 0;  IxFeatureCtrlDeviceId deviceId = 0;    /* Get the device ID for the underlying silicon */  deviceId = ixFeatureCtrlDeviceRead();  /* Get the product ID for the underlying silicon */  productId = ixFeatureCtrlProductIdRead ();  /* IF (IXP42X AND A0 silicon) -> use ixQMgrDispatcherLoopRunA0 */  if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X ==      (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) &&      (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==        (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId)))    {    /*For IXP42X A0 silicon */    *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunA0 ;  }   else /*For IXP42X B0 or IXP46X silicon*/   {     if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixQMgrOrigB0Dispatcher)    {        /* Default for IXP42X B0 and IXP46X silicon */        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0;    }    else     {        /* FeatureCtrl indicated that livelock dispatcher be used */        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0LLP;    }  }}voidixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group){    UINT32 intRegVal;                /* Interrupt reg val */    UINT32 intRegValAfterWrite;      /* Interrupt reg val after writing back */    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */    UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS];  /* Status b4 interrupt write */    UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */    IxQMgrQInfo *currDispatchQInfo;    BOOL statusChangeFlag;    int priorityTableIndex;/* Priority table index */    int qIndex;            /* Current queue being processed */    int endIndex;          /* Index of last queue to process */#ifndef NDEBUG    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 	      (group == IX_QMGR_QUELOW_GROUP));#endif    /* Read Q status registers before interrupt status read/write */    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write);    /* Read the interrupt register */    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);    /* No bit set : nothing to process (the reaminder of the algorithm is    * based on the fact that the interrupt register value contains at    * least one bit set    */    if (intRegVal == 0)     {#ifndef NDEBUG	/* Update statistics */	dispatcherStats.loopRunCnt++;#endif	/* Rebuild the priority table if needed */	if (rebuildTable)	{	    ixQMgrDispatcherReBuildPriorityTable ();	}	return;    }       /* Write it back to clear the interrupt */    ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);    /* Read Q status registers after interrupt status read/write */    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite);     /* get the first queue Id from the interrupt register value */    qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);    /* check if any change occured during hw register modifications */     if (IX_QMGR_QUELOW_GROUP == group)    {	statusChangeFlag = 	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) ||	    (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) ||	    (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) ||	    (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]);    }    else    {	statusChangeFlag = 	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]);	/* Set the queue range based on the queue group to proccess */	qIndex += IX_QMGR_MIN_QUEUPP_QID;    }    if (statusChangeFlag == FALSE)    {	/* check if the interrupt register contains 	 * only 1 bit set (happy day scenario)	 */	currDispatchQInfo = &dispatchQInfo[qIndex];	if (intRegVal == currDispatchQInfo->intRegCheckMask)	{	    /* only 1 queue event triggered a notification *	     * Call the callback function for this queue 	     */	    currDispatchQInfo->callback (qIndex,					 currDispatchQInfo->callbackId);  #ifndef NDEBUG	    /* Update statistics */	    dispatcherStats.queueStats[qIndex].callbackCnt++;#endif	}	else 	{	    /* the event is triggered by more than 1 queue, 	     * the queue search will be starting from the beginning	     * or the middle of the priority table	     *	     * the serach will end when all the bits of the interrupt	     * register are cleared. There is no need to maintain	     * a seperate value and test it at each iteration.	     */	    if (IX_QMGR_QUELOW_GROUP == group)	    {		/* check if any bit related to queues in the first		 * half of the priority table is set		 */		if (intRegVal & lowPriorityTableFirstHalfMask)		{		    priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;		}		else		{		    priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;		}	    }	    else 	    {		/* check if any bit related to queues in the first		 * half of the priority table is set		 */		if (intRegVal & uppPriorityTableFirstHalfMask)		{		    priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;		}		else		{		    priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;		}	    }	    	    /* iterate following the priority table until all the bits 	     * of the interrupt register are cleared.	     */	    do	    {		qIndex = priorityTable[priorityTableIndex++];		currDispatchQInfo = &dispatchQInfo[qIndex];		intRegCheckMask = currDispatchQInfo->intRegCheckMask;				/* If this queue caused this interrupt to be raised */		if (intRegVal & intRegCheckMask)		{		    /* Call the callback function for this queue */		    currDispatchQInfo->callback (qIndex,						 currDispatchQInfo->callbackId);#ifndef NDEBUG		    /* Update statistics */		    dispatcherStats.queueStats[qIndex].callbackCnt++;#endif		    		    /* Clear the interrupt register bit */		    intRegVal &= ~intRegCheckMask;		}	    }	    while(intRegVal);	}    }    else    {    /* A change in queue status occured during the hw interrupt     * register update. To maintain the interrupt consistency, it     * is necessary to iterate through all queues of the queue group.     */    /* Read interrupt status again */    ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite);    if (IX_QMGR_QUELOW_GROUP == group)    {	priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;	endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX;    }    else    {	priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;	endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX;    }    for ( ; priorityTableIndex<=endIndex; priorityTableIndex++)    {	qIndex = priorityTable[priorityTableIndex];	currDispatchQInfo = &dispatchQInfo[qIndex];	intRegCheckMask = currDispatchQInfo->intRegCheckMask;	/* If this queue caused this interrupt to be raised */	if (intRegVal & intRegCheckMask)	{  	    /* Call the callback function for this queue */	    currDispatchQInfo->callback (qIndex,					 currDispatchQInfo->callbackId);#ifndef NDEBUG	    /* Update statistics */	    dispatcherStats.queueStats[qIndex].callbackCnt++;#endif	    	} /* if (intRegVal .. */	/* 	 * If interrupt bit is set in intRegValAfterWrite don't	 * proceed as this will be caught in next interrupt	 */	else if ((intRegValAfterWrite & intRegCheckMask) == 0)	{	    /* Check if an interrupt was lost for this Q */	    if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write,					qStatusWordsAfterWrite,					currDispatchQInfo->statusWordOffset,					currDispatchQInfo->statusCheckValue,					currDispatchQInfo->statusMask))	    {		/* Call the callback function for this queue */		currDispatchQInfo->callback (qIndex, 					     dispatchQInfo[qIndex].callbackId);                 #ifndef NDEBUG		/* Update statistics */		dispatcherStats.queueStats[qIndex].callbackCnt++;		dispatcherStats.queueStats[qIndex].intLostCallbackCnt++;#endif	    } /* if ixQMgrAqmIfQStatusCheck(.. */	} /* else if ((intRegValAfterWrite ... */    } /* for (priorityTableIndex=0 ... */    }    /* Rebuild the priority table if needed */    if (rebuildTable)    {	ixQMgrDispatcherReBuildPriorityTable ();    }#ifndef NDEBUG    /* Update statistics */    dispatcherStats.loopRunCnt++;#endif}voidixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group){    UINT32 intRegVal;                /* Interrupt reg val */    UINT32 intRegValSav;             /* Saved interrupt reg val */    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */    IxQMgrQInfo *currDispatchQInfo;    int priorityTableIndex; /* Priority table index */    int qIndex;             /* Current queue being processed */#ifndef NDEBUG    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||              (group == IX_QMGR_QUELOW_GROUP));    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 	      (group == IX_QMGR_QUELOW_GROUP));#endif    /* Read the interrupt register */    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);    /* save to write back after processing queues */    intRegValSav = intRegVal;    /* The sequence in which we process queues and write back the      * interrupt register depends on whether or not sticky interrupts     * are in use.  If sticky interrupts are enabled, that means that the     * interrupt status won't be cleared until after the queues are processed     * and the queue status bits are updated.  If interrupts are not sticky,     * the interrupt register has to be written back immediately, before processing     * the queues in case new queue status changes occur during processing.     */    if(!stickyEnabled)    {         /* not sticky, write back now */         ixQMgrAqmIfQInterruptRegWrite (group, intRegValSav);    }    /* No queue has interrupt register set */    if (intRegVal != 0)    {            /* get the first queue Id from the interrupt register value */            qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);            if (IX_QMGR_QUEUPP_GROUP == group)            {                /* Set the queue range based on the queue group to proccess */                qIndex += IX_QMGR_MIN_QUEUPP_QID;            }            /* check if the interrupt register contains             * only 1 bit set             * For example:             *                                        intRegVal = 0x0010             *               currDispatchQInfo->intRegCheckMask = 0x0010             *    intRegVal == currDispatchQInfo->intRegCheckMask is TRUE.             */             currDispatchQInfo = &dispatchQInfo[qIndex];             if (intRegVal == currDispatchQInfo->intRegCheckMask)             {                /* only 1 queue event triggered a notification *                 * Call the callback function for this queue                 */                currDispatchQInfo->callback (qIndex,                                     currDispatchQInfo->callbackId);#ifndef NDEBUG                /* Update statistics */                dispatcherStats.queueStats[qIndex].callbackCnt++;#endif             }             else             {                 /* the event is triggered by more than 1 queue,                  * the queue search will be starting from the beginning                  * or the middle of the priority table                  *                  * the serach will end when all the bits of the interrupt                  * register are cleared. There is no need to maintain                  * a seperate value and test it at each iteration.                  */                 if (IX_QMGR_QUELOW_GROUP == group)                 {                     /* check if any bit related to queues in the first                      * half of the priority table is set                      */                     if (intRegVal & lowPriorityTableFirstHalfMask)                     {                         priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;                     }                     else                     {                         priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;                     }                 }                else                 {                     /* check if any bit related to queues in the first                      * half of the priority table is set                      */                     if (intRegVal & uppPriorityTableFirstHalfMask)                     {                         priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;                     }                     else                     {                         priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;                     }                 }                 /* iterate following the priority table until all the bits                  * of the interrupt register are cleared.                  */                 do                 {                     qIndex = priorityTable[priorityTableIndex++];                     currDispatchQInfo = &dispatchQInfo[qIndex];                     intRegCheckMask = currDispatchQInfo->intRegCheckMask;                     /* If this queue caused this interrupt to be raised */                     if (intRegVal & intRegCheckMask)                     {                         /* Call the callback function for this queue */                         currDispatchQInfo->callback (qIndex,                                              currDispatchQInfo->callbackId);#ifndef NDEBUG                         /* Update statistics */                         dispatcherStats.queueStats[qIndex].callbackCnt++;#endif                         /* Clear the interrupt register bit */                         intRegVal &= ~intRegCheckMask;                     }                  }                  while(intRegVal);             } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */             if(stickyEnabled)             {                 /* Write back saved register to clear the interrupt */                 ixQMgrAqmIfQInterruptRegWrite (group, intRegValSav);             }     } /* End of intRegVal != 0 */#ifndef NDEBUG    /* Update statistics */    dispatcherStats.loopRunCnt++;#endif    /* Rebuild the priority table if needed */    if (rebuildTable)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -