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

📄 ks8695intrctl.c

📁 这是micrel公司宽带路由ARM9芯片的VXWORKS BSP 源代码
💻 C
字号:
/* ks8695IntrCtl.c - KS8695/X/P interrupt controller driver */

/*
modification history
--------------------
11/13/2003  LIQUN RUAN (RLQ) modified for KS8695/X, and shared all the functions with KS8695P
09/15/2003  Ritter Yeh  created 
*/

#include "vxWorks.h"
#include "config.h"
#include "intLib.h"

/*#define	USE_PRIORITY_PENDING_INT*/

/* will check which one is better in terms of performance */
#ifdef	USE_MSB
IMPORT int ffsMsb (UINT32);
#else
IMPORT int ffsLsb (UINT32);
#endif

#define KS8695P_INT_VEC_BASE	(0x0)
#define KS8695_INT_VEC_BASE		(0x0)


/* hardware access methods */

/* Convert level number to vector number */
#define KS8695P_INT_LVL_VEC_MAP(level, vector) \
	((vector) = ((level) + KS8695P_INT_VEC_BASE))

/* Convert pending register value, to a level number */
#define KS8695P_INT_PEND_LVL_MAP(pendReg, level) \
	((level) = (pendReg))

/* driver constants */
#if	!defined(KS8695) || defined(KS8695X)
#define KS8695P_INT_ALL_ENABLED	        0xFF03FFFF	/* KS8695X doesn't have EMAC port as well */
#else
#define KS8695P_INT_ALL_ENABLED	        0xFFFFFFFF
#endif

#define KS8695P_INT_ALL_DISABLED	0

/* Local data */

/* Current interrupt level setting (ks8695pIntLvlChg). */

LOCAL UINT32 ks8695pIntLvlCurrent = KS8695P_INT_ALL_DISABLED; /* all levels disabled*/

/*
 * A mask word.  Bits are set in this word when a specific level
 * is enabled. It is used to mask off individual levels that have
 * not been explicitly enabled.
 */

LOCAL UINT32 ks8695pIntLvlEnabled;	/* will be initialized in ks8695pIntDevInit routine */


/* forward declarations */

STATUS	ks8695pIntLvlVecChk (int*, int*);
STATUS  ks8695pIntLvlVecAck (int, int);
int	ks8695pIntLvlChg (int);
STATUS	ks8695pIntLvlEnable (int);
STATUS	ks8695pIntLvlDisable (int);

/*******************************************************************************
*
* ks8695pIntDevInit - initialize the interrupt controller
*
* This routine will initialize the interrupt controller device, disabling all
* interrupt sources.  It will also connect the device driver specific routines
* into the architecture level hooks.  If the BSP needs to create a wrapper
* routine around any of the arhitecture level routines, it should install the
* pointer to the wrapper routine after calling this routine.
*
*
* RETURNS: OK 
*/

int ks8695pIntDevInit (void)
    {

    /* install the driver routines in the architecture hooks */
    sysIntLvlVecChkRtn	= ks8695pIntLvlVecChk;
    sysIntLvlVecAckRtn	= ks8695pIntLvlVecAck;
    sysIntLvlChgRtn	= ks8695pIntLvlChg;
    sysIntLvlEnableRtn	= ks8695pIntLvlEnable;
    sysIntLvlDisableRtn	= ks8695pIntLvlDisable;

    ks8695pIntLvlEnabled = 0; 	/* all sources disabled */

    KS8695P_REG_WRITE (REG_INT_ENABLE, 0);

    return OK;
    }

/*******************************************************************************
*
* ks8695pIntLvlVecChk - check for and return any pending interrupts
*
*
* RETURNS: OK or ERROR if no interrupt is pending.
*/

STATUS  ks8695pIntLvlVecChk
    (
    int* pLevel,  /* ptr to receive old interrupt level */
    int* pVector  /* ptr to receive current interrupt vector */
    )
    {
    int newLevel;
    UINT32 isr;

    /* Read pending interrupt register and mask undefined bits */

#ifndef	USE_PRIORITY_PENDING_INT
    KS8695P_REG_READ (REG_INT_MASK_STATUS, isr);

    isr &= KS8695P_INT_CSR_MASK;
#else
    KS8695P_REG_READ (REG_IRQ_PEND_PRIORITY, isr);
	/*isr &= KS8695P_INT_CSR_MASK;*/
#endif

    /* If no interrupt is pending, return ERROR */
    if (isr == 0) {
#ifdef	USE_PRIORITY_PENDING_INT
		KS8695P_REG_READ (REG_INT_MASK_STATUS, isr);
		isr &= KS8695P_INT_CSR_MASK;
		if (0 == isr) 
#endif
		return ERROR;
	}

    /* find first bit set in ISR, starting from highest-numbered bit */
#ifdef	USE_MSB
    if (newLevel = ffsMsb (isr), newLevel == 0)
#else
    if (newLevel = ffsLsb (isr), newLevel == 0)
#endif
		return ERROR;

    --newLevel;		/* ffsMsb returns numbers from 1, not 0 */

    /* fetch, or compute the interrupt vector number */
    KS8695P_INT_LVL_VEC_MAP (newLevel, *pVector);

    /* Disable interrupt */
    KS8695P_REG_BIT_CLR (REG_INT_ENABLE,(1 << newLevel));

    return OK;
    }

/*******************************************************************************
*
* ks8695pIntLvlVecAck - acknowledge the current interrupt
*
* Acknowledge the current interrupt cycle.  The level and vector values are
* those generated during the ks8695pIntLvlVecChk() routine for this interrupt
* cycle.  The basic action is to reset the current interrupt and return
* the interrupt level to its previous setting.  
* RETURNS: OK or ERROR if a hardware fault is detected.
* ARGSUSED
*/

STATUS  ks8695pIntLvlVecAck
    (
    int level,	/* old interrupt level to be restored */
    int vector	/* current interrupt vector, if needed */
    )
    {

    return OK;
    }

/*******************************************************************************
*
* ks8695pIntLvlChg - change the interrupt level value
*
* This routine implements the overall interrupt setting.  All levels
* up to and including the specifed level are disabled.  All levels above
* the specified level will be enabled, but only if they were specifically
* enabled by the ks8695pIntLvlEnable() routine.
*
*
* RETURNS: Previous interrupt level.
*/

int  ks8695pIntLvlChg
    (
    int level	/* new interrupt level */
    )
    {

    if (level >= 0 && level < KS8695P_INT_NUM_LEVELS)
	{
        ks8695pIntLvlCurrent = level;
		return level;
	}

    return ks8695pIntLvlCurrent;
    }

/*******************************************************************************
*
* ks8695pIntLvlEnable - enable a single interrupt level
*
* Enable a specific interrupt level.  
*
* RETURNS: OK or ERROR if the specified level cannot be enabled.
*/

STATUS  ks8695pIntLvlEnable
    (
    int level  /* level to be enabled */
    )
    {
    int key;

    if (level < 0 || level >= KS8695P_INT_NUM_LEVELS)
		return ERROR;

    /* set bit in enable mask */
    key = intLock ();
    ks8695pIntLvlEnabled |= (1 << level);
    KS8695P_REG_WRITE (REG_INT_ENABLE, ks8695pIntLvlEnabled); 
    intUnlock (key);

    return OK;
    }

/*******************************************************************************
*
* ks8695pIntLvlDisable - disable a single interrupt level
*
* Disable a specific interrupt level.  
*
* RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
*/

STATUS  ks8695pIntLvlDisable
    (
    int level  /* level to be disabled */
    )
    {
    int key;

    if (level < 0 || level >= KS8695P_INT_NUM_LEVELS)
		return ERROR;

    /* clear bit in enable mask */

    key = intLock ();
    ks8695pIntLvlEnabled &= ~(1 << level);
    KS8695P_REG_WRITE (REG_INT_ENABLE, ks8695pIntLvlEnabled);    
    intUnlock (key);

    return OK;
    }

⌨️ 快捷键说明

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