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

📄 templateintrctl.c

📁 操作系统vxworks平台下中断控制器设备的驱动程序,支持多种芯片,支持多种cpu
💻 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 Chris01c,05aug97,dat  suggestions from Chris Partington at CSD.01b,06may97,dat  added more documentation01a,03apr97,dat  written*//*TODO - This is a template driver for an interrupt controller.  Each hardwaredependent 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 theentire larger device in one paragraph.TODO - Describe this device including all possible operating modes andlimitations. 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 architecturelevel interrupt system, and the BSP and hardware level functions.  One purpose of this interface model is to make it easy for BSPs to use standardinterrupt controller devices in both simple and complex situations.  Previousinterfaces assumed that the device driver would be the only device in thesystem.  We need more flexibility than that.  This model allows the BSPto provide complex wrapper functions around any of the hardware levelroutines supporting the architecture level functions (see templateIntr.c).In a simple system with only one controller device, the BSP would initializethe single device.  The driver will attach itself to the sysIntLvlXXXentry 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 devicesindividually.  It would then declare a special version of each functionand install those special versions into the entry point variables. Anexample would be a system using 8259's for ISA bus interrupts and had aseparate device for handling VMEbus interrupts.  The BSP would initializethe two individual drivers.  For each hardware function, sysIntLvlXXX,the BSP would create a routine that would interact with both driversas needed.  This new wrapper routine would be installed as the actualsysIntLvlXXX routine that is called from the architecture layer.In this template driver, priority level 0 is lowest, and priority level16 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 presumethat the BSP will define the necessary level numbers and will enable themindividually as needed.  The architecture should take no notice of theirnumeric 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 changedto reflect lower numeric values representing higher priority levels.The template chip has a TEMPLATE_CSR_ENB register where each bit enablesa specific level, the bit pattern 0x1 enables interrupt level 1, the lowestlevel real interrupt. Level 0 is artificial and indicates all levelsenabled.  Level 16 is the highest level, and all levels are disabled.Not all devices will support individual interrupt level enabling.  If thatis the case, then templateLvlEnable() should always return OK, andtemplateLvlDisable() should always return ERROR.We presume that config.h or <bsp>.h has defined the addresses of thetemplate chips registers: TEMPLATE_CSR_PEND, TEMPLATE_CSR_ENB, and TEMPLATE_CSR_ACK.  This template code presumes that the chip is memorymapped and does direct memory accesses to the registers.  If a differentaccess 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 arecalculated and not the result of a special cycle on the bus.  Vectornumbers are generated by adding the current interrupt level number toTEMPLATE_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 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 tosupport any number of real devices.The BSP will initialize this driver in sysHwInit2(), after initializingthe main interrupt library, usually intLibInit().  The initializationroutine, 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 templateDevInitfor more information.All of the functions in this library are global.  This allows them to beused by the BSP if it is necessary to create wrapper routines or toincorporate 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;    }

⌨️ 快捷键说明

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