📄 s3c2410intrctl.c
字号:
/* sngks32cIntrCtl.c - Samsung KS32C interrupt controller driver *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"#include "vxWorks.h"#include "config.h"#include "intLib.h"#define rSRCPND (0x4a000000) /*Interrupt request status */#define rINTMOD (0x4a000004) /*Interrupt mode control */#define rINTMSK (0x4a000008) /*Interrupt mask control */#define rPRIORITY (0x4a00000c) /*IRQ priority control */#define rINTPND (0x4a000010) /*Interrupt request status */#define rINTOFFSET (0x4a000014) /*Interruot request source offset */#define rSUBSRCPND (0x4a000018) /*Sub source pending */#define rINTSUBMSK (0x4a00001c) /*Interrupt sub mask */#define SNGKS32C_INTMASK_VAL (~((0x1<<6)|(0x1<<24))) #define SNGKS32C_INT_VEC_BASE (0x0)/* hardware access methods */#ifndef SNGKS32C_INT_REG_READ# define SNGKS32C_INT_REG_READ(x,result) \ ((result) = *(volatile UINT32 *)(x))#endif /*SNGKS32C_INT_REG_READ*/#ifndef SNGKS32C_INT_REG_WRITE# define SNGKS32C_INT_REG_WRITE(x,data) \ (*((volatile UINT32 *)(x)) = (data))#endif /*SNGKS32C_INT_REG_WRITE*//* Convert level number to vector number */#ifndef SNGKS32C_INT_LVL_VEC_MAP# define SNGKS32C_INT_LVL_VEC_MAP(level, vector) \ ((vector) = ((level) + SNGKS32C_INT_VEC_BASE))#endif/* Convert pending register value, to a level number */#ifndef SNGKS32C_INT_PEND_LVL_MAP# define SNGKS32C_INT_PEND_LVL_MAP(pendReg, level) \ ((level) = (pendReg))#endif/* driver constants */#define SNGKS32C_INT_ALL_ENABLED (SNGKS32C_INTNUMLEVELS)#define SNGKS32C_INT_ALL_DISABLED (SNGKS32C_INTNUMLEVELS-1)/* Local data *//* * 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 sngks32cIntLvlEnabled;/* forward declarations */STATUS sngks32cIntLvlVecChk (int*, int*);STATUS sngks32cIntLvlEnable (int);STATUS sngks32cIntLvlDisable (int);/********************************************************************************* sngks32cIntDevInit - 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 sngks32cIntDevInit (void) { int index; /* install the driver routines in the architecture hooks */ sysIntLvlVecChkRtn = sngks32cIntLvlVecChk; sysIntLvlEnableRtn = sngks32cIntLvlEnable; sysIntLvlDisableRtn = sngks32cIntLvlDisable; sngks32cIntLvlEnabled = 0x0; /* all sources disabled */ SNGKS32C_INT_REG_WRITE (rINTMOD, 0x00000000); /* All=IRQ mode */ SNGKS32C_INT_REG_WRITE (rINTMSK, 0xFFFFFFFF); /* All interrupt is masked. */ SNGKS32C_INT_REG_WRITE (rINTSUBMSK, 0x7FF); /* All sub-interrupt is masked. */ }/********************************************************************************* sngks32cIntLvlVecChk - 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 sngks32cIntLvlVecChk ( int* pLevel, /* ptr to receive old interrupt level */ int* pVector /* ptr to receive current interrupt vector */ ) { int newLevel; int intPendMask = 0x80000000; int count; UINT32 isr; /* Read pending interrupt register and mask undefined bits */ SNGKS32C_INT_REG_READ (rINTPND, newLevel); newLevel &= SNGKS32C_INTMASK_VAL; if (newLevel == 0) return ERROR; newLevel &= sngks32cIntLvlEnabled ; if(newLevel==0) return ERROR; /* * Step through the bits looking for a 1. This *will* terminate. * We could use ffsLsb() for this if we don't mind the function call * overhead */ for (count = 0, isr = 31; count < 32; count++) { if (intPendMask & newLevel) break; isr--; intPendMask >>= 1; } *pVector = isr; SNGKS32C_INT_REG_WRITE(rSRCPND,(1 << isr)); SNGKS32C_INT_REG_WRITE(rINTPND,(1 << isr)); return OK; }/********************************************************************************* sngks32cIntLvlEnable - 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 sngks32cIntLvlEnable ( int level /* level to be enabled */ ) { int key; /* clear bit in mask register */ key = intLock (); sngks32cIntLvlEnabled |= ((1 << level)); SNGKS32C_INT_REG_WRITE (rINTMSK, ((~sngks32cIntLvlEnabled))); intUnlock (key); return OK; }/********************************************************************************* sngks32cIntLvlDisable - 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 sngks32cIntLvlDisable ( int level /* level to be disabled */ ) { int key; /* set bit in mask register */ key = intLock (); sngks32cIntLvlEnabled &= ~(1 << level); SNGKS32C_INT_REG_WRITE (rINTMSK, ((~sngks32cIntLvlEnabled))); intUnlock (key); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -