📄 ks8695intrctl.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 + -