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

📄 ixp425intrctl.c

📁 ixp425 bsp for vxworks
💻 C
字号:
/* ixp425IntrCtl.c - interrupt controller driver for the ixp425 *//* Copyright 2002 Wind River Systems, Inc. *//*modification history--------------------01a,05jun02,jb  initial version...*//*DESCRIPTIONThis module implements the Ixp425 interrupt controller driver.The Ixp425 interrupt controller is a simple, generic interrupt controllerdescribed in full Ixp425 Data Book [Reference[]].  Theinterrupt controller has status and request registers, separate enableand disable registers and supports level-sensitive interrupts.	Thislibrary provides the routines to manage interrupts multiplexed by theIxp425 interrupt controller.The Ixp425 interrupt controller has a number of registers.  Those used bythis driver are described below under the symbolic names used herein.IXP425_ICMR (write): this is the "Enable Set" register.	 When this register iswritten, each data bit that is set (1) causes the correspondinginterrupt 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 aninterrupt source that is both active and enabled i.e. can interrupt theprocessor.  The number of interrupts supported by the device i.e. the number ofbits in the IXP425_ICIP register, is specified byIXP425_INT_NUM_LEVELS.We assume that config.h or <bsp>.h has defined the addresses of thecontroller 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 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 macrosIXP425_INT_REG_READ(addr,result) and IXP425_INT_REG_WRITE(addr,data).This driver assumes that interrupt vector numbers are calculated andnot the result of a special cycle on the bus.  Vector numbers aregenerated by adding the current interrupt level number toAMBA_INT_VEC_BASE to generate a vector number which the architecturelevel will use to invoke the proper handling routine.  If a differentmapping scheme, or a special hardware routine is needed, then the BSPshould redefine the macro IXP425_INT_LVL_VEC_MAP(level,vector) tooverride the version defined in this file.Priorities==========The order of interrupt level priority is undefined at the architecturelevel.	In this driver, level 0 is highest and and indicates that alllevels are disabled; level <IXP425_INT_NUM_LEVELS> is the lowest andindicates that all levels are enabled.By default, this driver implements a least-significant bit firstinterrupt priority scheme (this is compatible with earlier versions ofthis 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 initializingthe main interrupt library, usually intLibInit().  The initializationroutine, ixp425IntDevInit() will setup the interrupt controller device,it will mask off all individual interrupt sources and then set theinterrupt level to enable all interrupts.  See ixp425IntDevInit for moreinformation.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..SH INCLUDE FILES:drv/intrCtl/ixp425IntrCtl.hSEE 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;    }

⌨️ 快捷键说明

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