📄 ixdp2400intrctl.c
字号:
/* ixp2400IntrCtl.c - interrupt controller driver for IXP2400 *//* Copyright 2001, Wind River Systems, Inc. *//*modification history--------------------.01a,20mar02,vgd created - Adapted from template*//*This module implements the Intel IXP2400 interrupt controller driver.The interrupt controller driver is implemented with 32 interrupt vectors and 32 interrupt levels.These are managed by the intArchLib.The number of interrupts supported by the software is IXP2400_INT_NUM_LEVELS.The actual registers referenced are: IXP2400_IRQ_ENABLE_SET_REG IXP2400_IRQ_ENABLE_CLR_REG IXP2400_IRQ_ENABLE_REGWe assume that config.h or <bsp>.h has defined the above addresses.This driver assumes that the chip is memory-mapped and does directmemory accesses to the registers which are assumed to be 32 bits wide.If a different access method is needed, the BSP can redefine the macros.The BSP will initialize this driver in sysHwInit2(), after initializingthe main interrupt library, usually intLibInit(). The initializationroutine, ixp2400IntDevInit() will setup the interrupt service.All of the functions in this library are global. This allows them tobe used by the BSP if it is necessary to create wrapper routines or toincorporate several drivers together as one.*/#include "vxWorks.h"#include "config.h"#include "intLib.h"/* Convert level number to vector number */#ifndef IXP2400_INUM_TO_IVEC#define IXP2400_INUM_TO_IVEC(level,pvector) (*pvector = (level+IXP2400_INT_VEC_BASE))#endif/*done with defines that need to go into ixdp2400.h*//* Local data */LOCAL UINT32 ixp2400LvlCurrent = 0; LOCAL UINT32 ixp2400LvlEnabled = 0; /* forward declarations */STATUS ixp2400IntLvlVecChk (int*, int*);STATUS ixp2400IntLvlVecAck (int, int);int ixp2400IntLvlChg (int);STATUS ixp2400IntLvlEnable (int);STATUS ixp2400IntLvlDisable (int);/******************************************************************************** ixp2400IntDevInit - 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 or ERROR */int ixp2400IntDevInit (void) { FAST int key; /* install the driver routines in the architecture hooks */ sysIntLvlVecChkRtn = ixp2400IntLvlVecChk; sysIntLvlVecAckRtn = ixp2400IntLvlVecAck; sysIntLvlChgRtn = ixp2400IntLvlChg; sysIntLvlEnableRtn = ixp2400IntLvlEnable; sysIntLvlDisableRtn = ixp2400IntLvlDisable; /* Mask all the interrupts */ key = intLock (); IXP2400_REG_WRITE(IXP2400_IRQ_ENABLE_CLR_REG,0xFFFFFFFF); /*mask all interrupts*/ intUnlock (key); return OK; }/********************************************************************************* ixp2400IntLvlVecChk - 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 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 ixp2400IntLvlVecChk ( int* pLevel, /* ptr to receive old interrupt level */ int* pVector /* ptr to receive current interrupt vector */ ) { int newlevel=-1, i; FAST int key; UINT32 isr; key=intLock(); /* read the IRQ status register */ IXP2400_REG_READ (IXP2400_IRQ_STATUS_REG, isr); intUnlock (key); if (isr == 0) /*no pending interrupt*/ return ERROR; else /*IRQ interrupt*/ { for(i=0;i<IXP2400_INT_NUM_LEVELS;i++) { if(isr & (1 << i)) { newlevel = i; break; } } } /*change interrupt level*/ *pLevel = ixp2400IntLvlChg(newlevel); /*compute Interrupt vector number*/ IXP2400_INUM_TO_IVEC (newlevel, pVector); return OK;} /******************************************************************************** ixp2400IntLvlVecAck - acknowledge the current interrupt* The current interrupt will be reset by the specific ISR, * so here the interrupt level is returned to its previous level.* * RETURNS: OK or ERROR if a hardware fault is detected.* ARGSUSED*/STATUS ixp2400IntLvlVecAck ( int level, /* old interrupt level to be restored */ int vector /* current interrupt vector, if needed */ ) { return OK; }/******************************************************************************** ixp2400IntLvlChg - 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 are enabled by IXP2000LvlEnable() * routine.** RETURNS: Previous interrupt level.*/int ixp2400IntLvlChg ( int level /* new interrupt level */ ) { return ixp2400LvlCurrent; }/******************************************************************************** ixp2400IntLvlEnable - 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 below the * specified level. 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 ixp2400IntLvlEnable ( int level /* level to be enabled */ ) { UINT32 enable; FAST int key; if (level <0 || level>IXP2400_INT_NUM_LEVELS) return ERROR; enable = 1<< level; ixp2400LvlEnabled |=enable; key=intLock(); IXP2400_REG_WRITE(IXP2400_IRQ_ENABLE_SET_REG, enable); intUnlock (key); return OK; }/******************************************************************************** ixp2400IntLvlDisable - 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.** RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.*/STATUS ixp2400IntLvlDisable ( int level /* level to be disabled */ ) { UINT32 disable; FAST int key; if (level <0 || level>IXP2400_INT_NUM_LEVELS) return ERROR; disable = 1<< level; ixp2400LvlEnabled &= ~disable; key = intLock(); IXP2400_REG_WRITE(IXP2400_IRQ_ENABLE_CLR_REG, disable); intUnlock (key); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -