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

📄 sa150xintrctl.c

📁 操作系统vxworks平台下中断控制器设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 2 页
字号:
    int key;    int bit;    UINT32 val;    sa150xIntrCtlDetails *p;    if (level < 0 ||	level >= SA150X_INT_NUM_LEVELS)	return ERROR;    bit = 1 << (level % 32);    p = &sa150xIntrCtl[level / 32];    key = intIFLock ();		/* disable IRQ and FIQ */    /* configure destination - note: must not retry write (locks up) */    SA150X_INT_REG_READ (SA150X_INT_DESTINATION (p->base), val);    val &= ~bit;		/* clear bit for this interrupt */#ifdef SA150X_INT_HANDLE_1501_DESTINATION    if (features & SA150X_INT_DESTINATION_FIQ)	val |= bit & (bit ^ p->destModifier);    else	val |= bit & (0 ^ p->destModifier);#else    if (features & SA150X_INT_DESTINATION_FIQ)	val |= bit;#endif    SA150X_INT_REG_WRITE (SA150X_INT_DESTINATION (p->base), val);    /* configure polarity */    SA150X_INT_REG_READ (SA150X_INT_POLARITY (p->base), val);    if (features & SA150X_INT_POLARITY_POSITIVE)	val &= ~bit;    else	val |= bit;#ifdef SA150X_INT_RETRY_WRITES    SA150X_INT_REG_WRITE_RETRY (SA150X_INT_POLARITY (p->base), val);#else    SA150X_INT_REG_WRITE (SA150X_INT_POLARITY (p->base), val);#endif    intIFUnlock (key);		/* restore IRQ and FIQ */    /* clear any pending interrupt */    SA150X_INT_REG_WRITE (SA150X_INT_CLEAR (p->base), bit);    /*     * if level interrupt, and source register (which takes account of     * polarity) indicates that interrupt is still active, set request     */    if (features & SA150X_INT_TYPE_LEVEL)	{	SA150X_INT_REG_READ (SA150X_INT_SOURCE (p->base), val);	if (val & bit)	    SA150X_INT_REG_WRITE (SA150X_INT_SET (p->base), bit);	}    return OK;    }/********************************************************************************* sa150xIntLvlVecChk - check for and return any pending interrupts** This routine interrogates the hardware to determine the highest priority* interrupt pending.  It returns the vector associated with that interrupt, and* also the interrupt priority level prior to the interrupt (not the* level of the interrupt).  The current interrupt priority level is then* raised to the level of the current interrupt so that only higher priority* interrupts will be accepted until this interrupt is finished.** This routine must be called with CPU interrupts disabled.** The return value ERROR indicates that no pending interrupt was found and* that the level and vector values were not returned.** RETURNS: OK or ERROR if no interrupt is pending.*/STATUS  sa150xIntLvlVecChk    (    int* pLevel,  /* ptr to receive old interrupt level */    int* pVector  /* ptr to receive current interrupt vector */    )    {    int newLevel;    sa150xIntrCtlDetails *p;    UINT32 isr, bit;    UINT32 *priPtr;    int ctl;    int bitNum;#ifdef SA150X_INT_RETRY_READS    int ok;#define TRIES 2#endif    /* initialise vars to stop compiler warnings */    p = 0;    bit = 0;    SA150X_INT_DEBUG(0x00, 0);#ifdef SA150X_INT_CACHE_IRQ_REQUEST    /* mark all cached requests as invalid */    for (ctl = 0; ctl < SA150X_INT_NUM_CONTROLLERS; ++ctl)	sa150xIntrCtl[ctl].requestsValid = FALSE;#endif    if (priPtr = sa150xIntLvlPriMap, priPtr == 0)	bitNum = -1;    else	{	/* service interrupts according to priority specified in map */	while (bitNum = *priPtr++, bitNum != -1)	    {	    /*	     * bitNum = interrupt bit from priority map - convert it to	     * a bit position in a specific controller	     * Note: UINT32 cast of bitNum is an optimisation(!)	     */	    ctl = (UINT32)bitNum / 32;	    bit = 1 << ((UINT32)bitNum % 32);	    p = &sa150xIntrCtl[ctl];#ifdef SA150X_INT_CACHE_IRQ_REQUEST	    if (p->requestsValid)		{		isr = p->irqRequests;		SA150X_INT_DEBUG(0x81, ctl);		}	    else		{#endif		/* read pending interrupt register for this controller */		SA150X_INT_DEBUG(0x80, ctl);		SA150X_INT_REQ_REG_READ (SA150X_INT_IRQ_REQUEST (p->base), isr,					 ~p->enabledIrqs, TRIES, ok);#ifdef SA150X_INT_RETRY_READS		if (ok)#endif#ifdef SA150X_INT_CACHE_IRQ_REQUEST		    {		    p->requestsValid = TRUE;		    p->irqRequests = isr;		    }#ifdef SA150X_INT_RETRY_READS		else		    {		    isr = 0;		    SA150X_INT_DEBUG(0x83, bitNum);		    }#endif		}#endif	/* SA150X_INT_CACHE_IRQ_REQUEST */	    if (isr & bit)		{		SA150X_INT_DEBUG(0x82, bitNum);		break;		}	    }	}    /*     * If priority scan didn't find anything, look for any bit set in any     * controller, starting with the lowest-numbered bit     */    if (bitNum == -1)	for (ctl = 0; ctl < SA150X_INT_NUM_CONTROLLERS; ++ctl)	    {	    p = &sa150xIntrCtl[ctl];#ifdef SA150X_INT_CACHE_IRQ_REQUEST	    if (p->requestsValid)		{		isr = p->irqRequests;		SA150X_INT_DEBUG(0x91, ctl);		}	    else		{#endif		/* read pending interrupt register for this controller */		SA150X_INT_DEBUG(0x90, ctl);		SA150X_INT_REQ_REG_READ (SA150X_INT_IRQ_REQUEST (p->base), isr,					 ~p->enabledIrqs, TRIES, ok);#ifdef SA150X_INT_RETRY_READS		if (ok)#endif#ifdef SA150X_INT_CACHE_IRQ_REQUEST		    {		    p->requestsValid = TRUE;		    p->irqRequests = isr;		    }#ifdef SA150X_INT_RETRY_READS		else		    {		    isr = 0;		    SA150X_INT_DEBUG(0x93, ctl);		    }#endif		}#endif	/* SA150X_INT_CACHE_IRQ_REQUEST */	    /* find lowest bit set */	    bitNum = ffsLsb (isr) - 1;	/* ffsLsb returns 1..n, not 0..n-1 */	    if (bitNum != -1)		{		bit = 1 << bitNum;		bitNum += ctl * 32;		SA150X_INT_DEBUG(0x92, bitNum);		break;		}	    }    /* If no interrupt is pending, return ERROR */    if (bitNum == -1)	{	SA150X_INT_DEBUG(0xEE, 0xEE);	return ERROR;	}    /*     * bitNum is the bit that is interrupting (0..SA150X_INT_NUM_LEVELS-1)     * ctl is the controller number (0..SA150X_INT_NUM_CONTROLLERS-1)     * bit is the bit within that controller     * p-> sa150xIntrCtl structure for this controller     *     * clear the interrupt     */    SA150X_INT_REG_WRITE (SA150X_INT_CLEAR (p->base), bit);    /* map the interrupting device to an interrupt level number */    newLevel = sa150xIntLvlMap[bitNum];    /* change to new interrupt level, returning previous level to caller */    *pLevel = sa150xIntLvlChg (newLevel);    /* fetch, or compute the interrupt vector number */    SA150X_INT_LVL_VEC_MAP (bitNum, *pVector);    SA150X_INT_DEBUG(0xEE, 0x00);    return OK;    }/********************************************************************************* sa150xIntLvlVecAck - acknowledge the current interrupt** Acknowledge the current interrupt cycle.  The level and vector values are* those generated during the sa150xIntLvlVecChk() routine for this interrupt* cycle.  The basic action is to return the interrupt level to its previous* setting.  Note that the SA150X interrupt controller does not need an* acknowledge cycle and that the interrupt has already been cleared in* sa150xIntLvlVecChk().** RETURNS: OK or ERROR if a hardware fault is detected.* ARGSUSED*/STATUS  sa150xIntLvlVecAck    (    int level,	/* old interrupt level to be restored */    int vector	/* current interrupt vector, if needed */    )    {    SA150X_INT_DEBUG(0xFF, vector);    /* restore the previous interrupt level */    sa150xIntLvlChg (level);    return OK;    }/********************************************************************************* sa150xIntLvlChg - change the interrupt level value** This routine implements the overall interrupt setting.  All levels* up to and including the specified level are disabled.  All levels above* the specified level will be enabled, but only if they were specifically* enabled by the sa150xIntLvlEnable() routine.** The specific priority level SA150X_INT_NUM_LEVELS is valid and represents* all levels enabled.** RETURNS: Previous interrupt level.*/int  sa150xIntLvlChg    (    int level	/* new interrupt level */    )    {    int oldLevel;    int i, m;    sa150xIntrCtlDetails *p;    int key;    oldLevel = sa150xIntLvlCurrent;    if (level >= 0 &&        level <= SA150X_INT_NUM_LEVELS)	{	/* change current interrupt level */	sa150xIntLvlCurrent = level;	}    /* Activate the enabled interrupts */    m = sa150xIntLvlCurrent * SA150X_INT_NUM_CONTROLLERS;    for (i = 0; i < SA150X_INT_NUM_CONTROLLERS; ++i)	{	p = &sa150xIntrCtl[i];	key = intIFLock ();		/* disable IRQ and FIQ */#ifdef SA150X_INT_RETRY_WRITES	SA150X_INT_REG_WRITE_RETRY (SA150X_INT_ENABLE (p->base),				    (sa150xIntLvlMask[m + i] & p->enabledIrqs) |				    p->enabledFiqs);#else	SA150X_INT_REG_WRITE (SA150X_INT_ENABLE (p->base),			      (sa150xIntLvlMask[m + i] & p->enabledIrqs) |			      p->enabledFiqs);#endif	intIFUnlock (key);	}    return oldLevel;    }/********************************************************************************* sa150xIntLvlEnable - enable a single interrupt level** Enable a specific interrupt level.  The enabled level will be allowed* to generate an interrupt when the overall interrupt level is set to* enable interrupts of this priority (as configured by* sa150xIntLvlPriMap).  Without being enabled, the interrupt is blocked* regardless of the overall interrupt level setting.** RETURNS: OK or ERROR if the specified level cannot be enabled.*/STATUS  sa150xIntLvlEnable    (    int level  /* level to be enabled */    )    {    int key;    if (level < 0 ||	level >= SA150X_INT_NUM_LEVELS)	return ERROR;    /* set bit in enable mask */    key = intIFLock ();		/* disable IRQ and FIQ */    sa150xIntrCtl[level / 32].enabledIrqs |= (1 << (level % 32));    intIFUnlock (key);    sa150xIntLvlChg (-1);	/* reset current mask */    return OK;    }/********************************************************************************* sa150xIntLvlDisable - disable a single interrupt level** Disable a specific interrupt level.  The disabled level is prevented* from generating an interrupt even if the overall interrupt level is set* to enable interrupts of this priority (as configured by* sa150xIntLvlPriMap).** RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.*/STATUS  sa150xIntLvlDisable    (    int level  /* level to be disabled */    )    {    int key;    if (level < 0 ||	level >= SA150X_INT_NUM_LEVELS)	return ERROR;    /* clear bit in enable mask */    key = intIFLock ();		/* disable IRQ and FIQ */    sa150xIntrCtl[level / 32].enabledIrqs &= ~(1 << (level % 32));    intIFUnlock (key);    sa150xIntLvlChg (-1);	/* reset current mask */    return OK;    }/********************************************************************************* sa150xIntFiqEnable - enable a single FIQ interrupt** Enable a specific FIQ interrupt. Unlike an enable IRQ interrupt, an* enabled FIQ interrupt will be always be allowed to interrupt,* irrespective of the overall interrupt level.** RETURNS: OK or ERROR if the specified level cannot be enabled.*/STATUS  sa150xIntFiqEnable    (    int level  /* level to be enabled */    )    {    int key;    if (level < 0 ||	level >= SA150X_INT_NUM_LEVELS)	return ERROR;    /* set bit in enable mask */    key = intIFLock ();		/* disable IRQ and FIQ */    sa150xIntrCtl[level / 32].enabledFiqs |= (1 << (level % 32));    intIFUnlock (key);    sa150xIntLvlChg (-1);	/* reset current mask */    return OK;    }/********************************************************************************* sa150xIntFiqDisable - disable a single FIQ interrupt** Disable a specific FIQ interrupt.  The disabled level is prevented* from generating an interrupt.** RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.*/STATUS  sa150xIntFiqDisable    (    int level  /* level to be disabled */    )    {    int key;    if (level < 0 ||	level >= SA150X_INT_NUM_LEVELS)	return ERROR;    /* clear bit in enable mask */    key = intIFLock ();		/* disable IRQ and FIQ */    sa150xIntrCtl[level / 32].enabledFiqs &= ~(1 << (level % 32));    intIFUnlock (key);    sa150xIntLvlChg (-1);	/* reset current mask */    return OK;    }

⌨️ 快捷键说明

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