templateIntrCtl.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:13k
源码类别:
VxWorks
开发平台:
C/C++
- /* templateIntrCtl.c - template interrupt controller driver */
- /* Copyright 1984-1997, Wind River Systems, Inc. */
- /*
- TODO - Remove the template modification history and begin a new history
- starting with version 01a and growing the history upward with
- each revision.
- modification history
- --------------------
- 01e,23nov97,dat suggestions from Chris and arm code review.
- 01d,12aug97,dat more suggestions from Chris
- 01c,05aug97,dat suggestions from Chris Partington at CSD.
- 01b,06may97,dat added more documentation
- 01a,03apr97,dat written
- */
- /*
- TODO - This is a template driver for an interrupt controller. Each hardware
- dependent function, variable, or macro name begins with TEMPLATE or template.
- These names should be changed to a name based upon the final module name.
- TODO - If this device is a sub-section of a larger device, describe the
- entire larger device in one paragraph.
- TODO - Describe this device including all possible operating modes and
- limitations.
- TODO - Describe the device modes and any limitations applicable to this driver.
- If this driver interacts with any other driver describe that interaction.
- TODO - Update the remainder of this documentation as appropriate.
- This template driver presents a standard interface between the architecture
- level interrupt system, and the BSP and hardware level functions. One
- purpose of this interface model is to make it easy for BSPs to use standard
- interrupt controller devices in both simple and complex situations. Previous
- interfaces assumed that the device driver would be the only device in the
- system. We need more flexibility than that. This model allows the BSP
- to provide complex wrapper functions around any of the hardware level
- routines supporting the architecture level functions (see templateIntr.c).
- In a simple system with only one controller device, the BSP would initialize
- the single device. The driver will attach itself to the sysIntLvlXXX
- entry points used by the higher level functions to call the hardware layer.
- Nothing else would be needed by such a simple BSP.
- In a complex system the BSP would initialize all the controller devices
- individually. It would then declare a special version of each function
- and install those special versions into the entry point variables. An
- example would be a system using 8259's for ISA bus interrupts and had a
- separate device for handling VMEbus interrupts. The BSP would initialize
- the two individual drivers. For each hardware function, sysIntLvlXXX,
- the BSP would create a routine that would interact with both drivers
- as needed. This new wrapper routine would be installed as the actual
- sysIntLvlXXX routine that is called from the architecture layer.
- In this template driver, priority level 0 is lowest, and priority level
- 16 is the highest. A priority level of 0 indicates all 16 levels enabled.
- The order of interrupt level is undefined at the architecture level.
- Whether it goes upward from 0 to 16, or downward is immaterial. We presume
- that the BSP will define the necessary level numbers and will enable them
- individually as needed. The architecture should take no notice of their
- numeric values per se.
- If the hardware device implements a different scheme from above,
- then some of the logic of this template driver will have to be changed
- to reflect lower numeric values representing higher priority levels.
- The template chip has a TEMPLATE_CSR_ENB register where each bit enables
- a specific level, the bit pattern 0x1 enables interrupt level 1, the lowest
- level real interrupt. Level 0 is artificial and indicates all levels
- enabled. Level 16 is the highest level, and all levels are disabled.
- Not all devices will support individual interrupt level enabling. If that
- is the case, then templateLvlEnable() should always return OK, and
- templateLvlDisable() should always return ERROR.
- We presume that config.h or <bsp>.h has defined the addresses of the
- template chips registers: TEMPLATE_CSR_PEND, TEMPLATE_CSR_ENB, and
- TEMPLATE_CSR_ACK. This template code presumes that the chip is memory
- mapped and does direct memory accesses to the registers. If a different
- access method is needed, the BSP can redefine the macros
- TEMPLATE_REG_READ(addr,result) and TEMPLATE_REG_WRITE(addr,data).
- This template chip driver presumes 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
- TEMPLATE_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 TEMPLATE_LVL_VEC_MAP(level,vector).
- This driver was designed to support a single instance of a real device.
- At some point it should be upgraded to operate on an object model and to
- support any number of real devices.
- The BSP will initialize this driver in sysHwInit2(), after initializing
- the main interrupt library, usually intLibInit(). The initialization
- routine, templateDevInit() 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 templateDevInit
- 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.
- */
- #include "vxWorks.h"
- #include "config.h"
- /*
- * TODO - These declarations should come from an architecture level
- * header file
- */
- IMPORT FUNCPTR sysIntLvlVecChkRtn;
- IMPORT FUNCPTR sysIntLvlVecAckRtn;
- IMPORT FUNCPTR sysIntLvlChgRtn;
- IMPORT FUNCPTR sysIntLvlEnableRtn;
- IMPORT FUNCPTR sysIntLvlDisableRtn;
- /* Defines from config.h, or <bsp>.h */
- #define TEMPLATE_CSR_PEND (0x0)
- #define TEMPLATE_CSR_ENB (0x1)
- #define TEMPLATE_CSR_ACK (0x2)
- #define TEMPLATE_VEC_BASE (0x0)
- /* hardware access methods */
- #ifndef TEMPLATE_REG_READ
- # define TEMPLATE_REG_READ(x,result)
- ((result) = *(volatile UINT16 *)(x))
- #endif /*TEMPLATE_REG_READ*/
- #ifndef TEMPLATE_REG_WRITE
- # define TEMPLATE_REG_WRITE(x,data)
- (*((volatile UINT16 *)(x)) = (data))
- #endif /*TEMPLATE_REG_WRITE*/
- /* Convert level number to vector number */
- #ifndef TEMPLATE_LVL_VEC_MAP
- # define TEMPLATE_LVL_VEC_MAP(level, vector)
- ((vector) = ((level) + TEMPLATE_VEC_BASE))
- #endif
- /* Convert pending register value, to a level number */
- #ifndef TEMPLATE_PEND_LVL_MAP
- # define TEMPLATE_PEND_LVL_MAP(pendReg, level)
- ((level) = (pendReg))
- #endif
- /* driver constants */
- #define TEMPLATE_NUM_LEVELS 16
- #define TEMPLATE_ALL_ENABLED (TEMPLATE_NUM_LEVELS)
- #define TEMPLATE_ALL_DISABLED 0
- /* Local data */
- /* Current interrupt level setting (templateLvlChg). */
- LOCAL UINT32 templateLvlCurrent = TEMPLATE_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 templateLvlEnabled;
- /*
- * This array maps interrupt levels to mask patterns. The interrupt level
- * is the index, the data is the mask value. A mask bit enables one
- * level. The mask value is 'and'd with the templateLvlEnabled value
- * before writing to the chip.
- */
- LOCAL UINT32 templateLvlMask[TEMPLATE_NUM_LEVELS + 1] = /* int level mask */
- {
- 0x0000, /* level 0, all disabled */
- 0x0001, 0x0003, 0x0007, 0x000f,
- 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff,
- 0x1fff, 0x3fff, 0x7fff, 0xffff /* level 16, all enabled */
- };
- /* forward declarations */
- STATUS templateLvlVecChk (int*, int*);
- STATUS templateLvlVecAck (int, int);
- int templateLvlChg (int);
- STATUS templateLvlEnable (int);
- STATUS templateLvlDisable (int);
- /*******************************************************************************
- *
- * templateDevInit - 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: N/A.
- */
- void templateDevInit (void)
- {
- /* install the driver routines in the architecture hooks */
- sysIntLvlVecChkRtn = templateLvlVecChk;
- sysIntLvlVecAckRtn = templateLvlVecAck;
- sysIntLvlChgRtn = templateLvlChg;
- sysIntLvlEnableRtn = templateLvlEnable;
- sysIntLvlDisableRtn = templateLvlDisable;
- templateLvlEnabled = 0; /* all sources disabled */
- templateLvlChg (TEMPLATE_ALL_ENABLED); /* enable all levels */
- }
- /*******************************************************************************
- *
- * templateLvlVecChk - 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.
- *
- * 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 templateLvlVecChk
- (
- int* pLevel, /* ptr to receive old interrupt level */
- int* pVector /* ptr to receive current interrupt vector */
- )
- {
- int newLevel;
- /* Read pending interrupt register */
- TEMPLATE_REG_READ (TEMPLATE_CSR_PEND, newLevel);
- /* If no interrupt is pending, return ERROR */
- if (newLevel == 0)
- return ERROR;
- /* map the return value to an interrupt level number */
- TEMPLATE_PEND_LVL_MAP (newLevel, newLevel);
- /* change to new interrupt level, returning previous level to caller */
- *pLevel = templateLvlChg (newLevel);
- /* fetch, or compute the interrupt vector number */
- TEMPLATE_LVL_VEC_MAP (newLevel, *pVector);
- return OK;
- }
- /*******************************************************************************
- *
- * templateLvlVecAck - acknowledge the current interrupt
- *
- * Acknowledge the current interrupt cycle. The level and vector values are
- * those generated during the templateLvlVecChk() 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 templateLvlVecAck
- (
- int level, /* old interrupt level to be restored */
- int vector /* current interrupt vector, if needed */
- )
- {
- /* acknowledge the current interrupt cycle */
- TEMPLATE_REG_WRITE (TEMPLATE_CSR_ACK, (1 << (templateLvlCurrent)));
- /* restore the previous interrupt level */
- templateLvlChg (level);
- return OK;
- }
- /*******************************************************************************
- *
- * templateLvlChg - 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 templateLvlEnable() routine.
- *
- * The specific priority level TEMPLATE_NUM_LEVELS is valid and represents
- * all levels enabled.
- *
- * RETURNS: Previous interrupt level.
- */
- int templateLvlChg
- (
- int level /* new interrupt level */
- )
- {
- int oldLevel;
- oldLevel = templateLvlCurrent;
- if (level >= 0 &&
- level <= TEMPLATE_NUM_LEVELS)
- {
- /* change current interrupt level */
- templateLvlCurrent = level;
- }
- /* Activate the enabled interrupts */
- TEMPLATE_REG_WRITE (TEMPLATE_CSR_ENB,
- (templateLvlMask[templateLvlCurrent] & templateLvlEnabled));
- return oldLevel;
- }
- /*******************************************************************************
- *
- * templateLvlEnable - 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 templateLvlEnable
- (
- int level /* level to be enabled */
- )
- {
- if (level < 0 ||
- level > TEMPLATE_NUM_LEVELS)
- return ERROR;
- /* set bit in enable mask */
- if (level > 0)
- {
- int key;
- key = intLock ();
- templateLvlEnabled |= (1 << level);
- intUnlock (key);
- }
- templateLvlChg (-1); /* reset current mask */
- return OK;
- }
- /*******************************************************************************
- *
- * templateLvlDisable - 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
- * below the specified level.
- *
- * RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
- */
- STATUS templateLvlDisable
- (
- int level /* level to be disabled */
- )
- {
- if (level < 0 ||
- level > TEMPLATE_NUM_LEVELS)
- return ERROR;
- /* clear bit in enable mask */
- if (level > 0)
- {
- int key;
- key = intLock ();
- templateLvlEnabled &= ~(1 << level);
- intUnlock (key);
- }
- templateLvlChg (-1); /* reset current mask */
- return OK;
- }