ixp425IntrCtl.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:12k
源码类别:
VxWorks
开发平台:
C/C++
- /* ixp425IntrCtl.c - interrupt controller driver for the ixp425 */
- /* Copyright 2002 Wind River Systems, Inc. */
- /*
- modification history
- --------------------
- 01a,05jun02,jb initial version...
- */
- /*
- DESCRIPTION
- This module implements the Ixp425 interrupt controller driver.
- The Ixp425 interrupt controller is a simple, generic interrupt controller
- described in full Ixp425 Data Book [Reference[]]. The
- interrupt controller has status and request registers, separate enable
- and disable registers and supports level-sensitive interrupts. This
- library provides the routines to manage interrupts multiplexed by the
- Ixp425 interrupt controller.
- The Ixp425 interrupt controller has a number of registers. Those used by
- this driver are described below under the symbolic names used herein.
- IXP425_ICMR (write): this is the "Enable Set" register. When this register is
- written, each data bit that is set (1) causes the corresponding
- interrupt to be enabled. Bits that are clear (0) have no effect.
- IXP425_ICIP (read): this is the "Interrupt Request" register.
- When this register is read, each data bit that is set (1) indicates an
- interrupt source that is both active and enabled i.e. can interrupt the
- processor.
- The number of interrupts supported by the device i.e. the number of
- bits in the IXP425_ICIP register, is specified by
- IXP425_INT_NUM_LEVELS.
- We assume that config.h or <bsp>.h has defined the addresses of the
- controller chips registers: IXP425_ICMR,
- IXP425_ICIP and also the driver constant IXP425_INT_NUM_LEVELS.
- This driver assumes that the chip is memory-mapped and does direct
- memory 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
- IXP425_INT_REG_READ(addr,result) and IXP425_INT_REG_WRITE(addr,data).
- This driver assumes that interrupt vector numbers are calculated and
- not the result of a special cycle on the bus. Vector numbers are
- generated by adding the current interrupt level number to
- AMBA_INT_VEC_BASE to generate a vector number which the architecture
- level will use to invoke the proper handling routine. If a different
- mapping scheme, or a special hardware routine is needed, then the BSP
- should redefine the macro IXP425_INT_LVL_VEC_MAP(level,vector) to
- override the version defined in this file.
- Priorities
- ==========
- The order of interrupt level priority is undefined at the architecture
- level. In this driver, level 0 is highest and and indicates that all
- levels are disabled; level <IXP425_INT_NUM_LEVELS> is the lowest and
- indicates that all levels are enabled.
- By default, this driver implements a least-significant bit first
- interrupt priority scheme (this is compatible with earlier versions of
- this driver) which requires a definition of ambaIntLvlMask (see above).
- Note: The IXP425 interrupt controller provides a mechanism to reorder the
- priority order of the top 8 interrupts sources. The IXP425_ICHR may
- be programmed to change the default behaviour. To change the default
- priority IXP425_ICHR_INIT_VALUE should be redefined.
- The BSP will initialize this driver in sysHwInit2(), after initializing
- the main interrupt library, usually intLibInit(). The initialization
- routine, ixp425IntDevInit() will setup the interrupt controller device,
- it will mask off all individual interrupt sources and then set the
- interrupt level to enable all interrupts. See ixp425IntDevInit for more
- information.
- All of the functions in this library are global. This allows them to
- be used by the BSP if it is necessary to create wrapper routines or to
- incorporate several drivers together as one.
- .SH INCLUDE FILES:
- drv/intrCtl/ixp425IntrCtl.h
- SEE ALSO:
- .I "Ixp425 Data Sheet,"
- */
- #include "vxWorks.h"
- #include "config.h"
- #include "ixp425.h"
- #include "ixp425IntrCtl.h"
- #include "intLib.h"
- IMPORT int ffsLsb (UINT32);
- /* Defines from config.h, or <bsp>.h */
- #if !defined (IXP425_ICIP) || !defined (IXP425_ICMR) ||
- !defined (IXP425_INT_NUM_LEVELS)
- #error missing IXP425 interrupt definitions
- #endif
- #define IXP425_INT_VEC_BASE (0x0)
- /* hardware access methods */
- #ifndef IXP425_REG_INT_READ
- #define IXP425_REG_INT_READ(reg,result)
- ((result) = *(volatile UINT32 *)(reg))
- #endif /*IXP425_REG_INT_READ*/
- #ifndef IXP425_REG_INT_WRITE
- #define IXP425_REG_INT_WRITE(reg,data)
- (*((volatile UINT32 *)(reg)) = (data))
- #endif /*IXP425_REG_INT_WRITE*/
- /* Convert level number to vector number */
- #ifndef IXP425_INT_LVL_VEC_MAP
- #define IXP425_INT_LVL_VEC_MAP(level, vector)
- ((vector) = ((level) + IXP425_INT_VEC_BASE))
- #endif /* IXP425_INT_LVL_VEC_MAP */
- /* Convert pending register value, to a level number */
- #ifndef IXP425_INT_PEND_LVL_MAP
- #define IXP425_INT_PEND_LVL_MAP(pendReg, level)
- ((level) = (pendReg))
- #endif /* IXP425_INT_PEND_LVL_MAP */
- /* driver constants */
- #define IXP425_INT_ALL_ENABLED (IXP425_INT_NUM_LEVELS)
- #define IXP425_INT_ALL_DISABLED 0
- #define IXP425_MASK_ALL_INTERRUPTS() { IXP425_REG_INT_WRITE (IXP425_ICMR,0x00000000); }
- /* Local data */
- /* Current interrupt level setting (ixp425IntLvlChg). */
- LOCAL UINT32 ixp425IntLvlCurrent = IXP425_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 ixp425IntLvlEnabled;
- /* forward declarations */
- STATUS ixp425IntLvlVecChk (int*, int*);
- STATUS ixp425IntLvlVecAck (int, int);
- int ixp425IntLvlChg (int);
- STATUS ixp425IntLvlEnable (int);
- STATUS ixp425IntLvlDisable (int);
- /*******************************************************************************
- *
- * ixp425IntDevInit - 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
- */
- STATUS ixp425IntDevInit (void)
- {
- /* install the driver routines in the architecture hooks */
- sysIntLvlVecChkRtn = ixp425IntLvlVecChk;
- sysIntLvlVecAckRtn = ixp425IntLvlVecAck;
- sysIntLvlChgRtn = ixp425IntLvlChg;
- sysIntLvlEnableRtn = ixp425IntLvlEnable;
- sysIntLvlDisableRtn = ixp425IntLvlDisable;
- ixp425IntLvlEnabled = 0; /* all sources disabled */
- /*
- * Set default interrupty priority.
- */
- IXP425_REG_INT_WRITE (IXP425_ICHR, IXP425_ICHR_INIT_VALUE);
- ixp425IntLvlChg (IXP425_INT_ALL_ENABLED); /* enable all levels */
- return OK;
- }
- /*******************************************************************************
- *
- * ixp425IntLvlVecChk - 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 ixp425IntLvlVecChk
- (
- 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 */
- IXP425_REG_INT_READ (IXP425_ICIP, isr);
- /* If no interrupt is pending, return ERROR */
- if (isr == 0)
- return ERROR;
- /* find first bit set in ISR, starting from lowest-numbered bit */
- if (newLevel = ffsLsb (isr), newLevel == 0)
- return ERROR;
- --newLevel; /* ffsLsb returns numbers from 1, not 0 */
- /* map the interrupting device to an interrupt level number */
- IXP425_INT_PEND_LVL_MAP (newLevel, newLevel);
- /* change to new interrupt level, returning previous level to caller */
- *pLevel = ixp425IntLvlChg (newLevel);
- /* fetch, or compute the interrupt vector number */
- IXP425_INT_LVL_VEC_MAP (newLevel, *pVector);
- return OK;
- }
- /*******************************************************************************
- *
- * ixp425IntLvlVecAck - acknowledge the current interrupt
- *
- * Acknowledge the current interrupt cycle. The level and vector values are
- * those generated during the ixp425IntLvlVecChk() routine for this interrupt
- * cycle. The basic action is to reset the current interrupt and return
- * the interrupt level to its previous setting. Note that the Ixp425 interrupt
- * controller does not need an acknowledge cycle.
- *
- * RETURNS: OK or ERROR if a hardware fault is detected.
- */
- STATUS ixp425IntLvlVecAck
- (
- int level, /* old interrupt level to be restored */
- int vector /* current interrupt vector, if needed */
- )
- {
- /* restore the previous interrupt level */
- ixp425IntLvlChg (level);
- return OK;
- }
- /*******************************************************************************
- *
- * ixp425IntLvlChg - 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 ixp425IntLvlEnable() routine.
- *
- * The specific priority level IXP425_INT_NUM_LEVELS is valid and represents
- * all levels enabled.
- *
- * Passing a value of -1 will reset the current interrupt level mask.
- *
- * RETURNS: Previous interrupt level.
- */
- int ixp425IntLvlChg
- (
- int level /* new interrupt level */
- )
- {
- int oldLevel;
- oldLevel = ixp425IntLvlCurrent;
- if (level >= 0 &&
- level <= IXP425_INT_NUM_LEVELS)
- {
- /* change current interrupt level */
- ixp425IntLvlCurrent = level;
- }
- /* Activate the enabled interrupts */
- IXP425_REG_INT_WRITE (IXP425_ICMR,
- (ixp425IntLvlMask[ixp425IntLvlCurrent] & ixp425IntLvlEnabled));
- return oldLevel;
- }
- /*******************************************************************************
- *
- * ixp425IntLvlEnable - 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 ixp425IntLvlPriMap,
- * if appropriate). 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 ixp425IntLvlEnable
- (
- int level /* level to be enabled */
- )
- {
- int key;
- if (level < 0 ||
- level >= IXP425_INT_NUM_LEVELS)
- return ERROR;
- /* set bit in enable mask */
- key = intLock ();
- ixp425IntLvlEnabled |= (1 << level);
- intUnlock (key);
- ixp425IntLvlChg (-1); /* reset current mask */
- return OK;
- }
- /*******************************************************************************
- *
- * ixp425IntLvlDisable - 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 ixp425IntLvlDisable
- (
- int level /* level to be disabled */
- )
- {
- int key;
- if (level < 0 ||
- level >= IXP425_INT_NUM_LEVELS)
- return ERROR;
- /* clear bit in enable mask */
- key = intLock ();
- ixp425IntLvlEnabled &= ~(1 << level);
- intUnlock (key);
- ixp425IntLvlChg (-1); /* reset current mask */
- return OK;
- }