templateIntrCtl.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:13k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* templateIntrCtl.c - template interrupt controller driver */
  2. /* Copyright 1984-1997, Wind River Systems, Inc. */
  3. /*
  4. TODO - Remove the template modification history and begin a new history
  5. starting with version 01a and growing the history upward with
  6. each revision.
  7. modification history
  8. --------------------
  9. 01e,23nov97,dat  suggestions from Chris and arm code review.
  10. 01d,12aug97,dat  more suggestions from Chris
  11. 01c,05aug97,dat  suggestions from Chris Partington at CSD.
  12. 01b,06may97,dat  added more documentation
  13. 01a,03apr97,dat  written
  14. */
  15. /*
  16. TODO - This is a template driver for an interrupt controller.  Each hardware
  17. dependent function, variable, or macro name begins with TEMPLATE or template.
  18. These names should be changed to a name based upon the final module name.
  19. TODO - If this device is a sub-section of a larger device, describe the
  20. entire larger device in one paragraph.
  21. TODO - Describe this device including all possible operating modes and
  22. limitations. 
  23. TODO - Describe the device modes and any limitations applicable to this driver.
  24. If this driver interacts with any other driver describe that interaction.
  25. TODO - Update the remainder of this documentation as appropriate.
  26. This template driver presents a standard interface between the architecture
  27. level interrupt system, and the BSP and hardware level functions.  One 
  28. purpose of this interface model is to make it easy for BSPs to use standard
  29. interrupt controller devices in both simple and complex situations.  Previous
  30. interfaces assumed that the device driver would be the only device in the
  31. system.  We need more flexibility than that.  This model allows the BSP
  32. to provide complex wrapper functions around any of the hardware level
  33. routines supporting the architecture level functions (see templateIntr.c).
  34. In a simple system with only one controller device, the BSP would initialize
  35. the single device.  The driver will attach itself to the sysIntLvlXXX
  36. entry points used by the higher level functions to call the hardware layer.
  37. Nothing else would be needed by such a simple BSP.
  38. In a complex system the BSP would initialize all the controller devices
  39. individually.  It would then declare a special version of each function
  40. and install those special versions into the entry point variables. An
  41. example would be a system using 8259's for ISA bus interrupts and had a
  42. separate device for handling VMEbus interrupts.  The BSP would initialize
  43. the two individual drivers.  For each hardware function, sysIntLvlXXX,
  44. the BSP would create a routine that would interact with both drivers
  45. as needed.  This new wrapper routine would be installed as the actual
  46. sysIntLvlXXX routine that is called from the architecture layer.
  47. In this template driver, priority level 0 is lowest, and priority level
  48. 16 is the highest.  A priority level of 0 indicates all 16 levels enabled.
  49. The order of interrupt level is undefined at the architecture level.
  50. Whether it goes upward from 0 to 16, or downward is immaterial.  We presume
  51. that the BSP will define the necessary level numbers and will enable them
  52. individually as needed.  The architecture should take no notice of their
  53. numeric values per se.
  54. If the hardware device implements a different scheme from above,
  55. then some of the logic of this template driver will have to be changed
  56. to reflect lower numeric values representing higher priority levels.
  57. The template chip has a TEMPLATE_CSR_ENB register where each bit enables
  58. a specific level, the bit pattern 0x1 enables interrupt level 1, the lowest
  59. level real interrupt. Level 0 is artificial and indicates all levels
  60. enabled.  Level 16 is the highest level, and all levels are disabled.
  61. Not all devices will support individual interrupt level enabling.  If that
  62. is the case, then templateLvlEnable() should always return OK, and
  63. templateLvlDisable() should always return ERROR.
  64. We presume that config.h or <bsp>.h has defined the addresses of the
  65. template chips registers: TEMPLATE_CSR_PEND, TEMPLATE_CSR_ENB, and 
  66. TEMPLATE_CSR_ACK.  This template code presumes that the chip is memory
  67. mapped and does direct memory accesses to the registers.  If a different
  68. access method is needed, the BSP can redefine the macros 
  69. TEMPLATE_REG_READ(addr,result) and TEMPLATE_REG_WRITE(addr,data).
  70. This template chip driver presumes that interrupt vector numbers are
  71. calculated and not the result of a special cycle on the bus.  Vector
  72. numbers are generated by adding the current interrupt level number to
  73. TEMPLATE_VEC_BASE to generate a vector number which the architecture
  74. level will use to invoke the proper handling routine.  If a different
  75. mapping scheme, or a special hardware routine is needed, then the BSP
  76. should redefine the macro TEMPLATE_LVL_VEC_MAP(level,vector).
  77. This driver was designed to support a single instance of a real device.
  78. At some point it should be upgraded to operate on an object model and to
  79. support any number of real devices.
  80. The BSP will initialize this driver in sysHwInit2(), after initializing
  81. the main interrupt library, usually intLibInit().  The initialization
  82. routine, templateDevInit() will setup the interrupt controller device,
  83. it will mask off all individual interrupt sources and then set the 
  84. interrupt level to enable all interrupts.  See templateDevInit
  85. for more information.
  86. All of the functions in this library are global.  This allows them to be
  87. used by the BSP if it is necessary to create wrapper routines or to
  88. incorporate several drivers together as one.
  89. */
  90. #include "vxWorks.h"
  91. #include "config.h"
  92. /*
  93.  * TODO - These declarations should come from an architecture level
  94.  * header file
  95.  */
  96. IMPORT FUNCPTR sysIntLvlVecChkRtn;
  97. IMPORT FUNCPTR sysIntLvlVecAckRtn;
  98. IMPORT FUNCPTR sysIntLvlChgRtn;
  99. IMPORT FUNCPTR sysIntLvlEnableRtn;
  100. IMPORT FUNCPTR sysIntLvlDisableRtn;
  101. /* Defines from config.h, or <bsp>.h */
  102. #define TEMPLATE_CSR_PEND (0x0)
  103. #define TEMPLATE_CSR_ENB (0x1)
  104. #define TEMPLATE_CSR_ACK (0x2)
  105. #define TEMPLATE_VEC_BASE (0x0)
  106. /* hardware access methods */
  107. #ifndef TEMPLATE_REG_READ
  108. #   define TEMPLATE_REG_READ(x,result) 
  109.     ((result) = *(volatile UINT16 *)(x))
  110. #endif /*TEMPLATE_REG_READ*/
  111. #ifndef TEMPLATE_REG_WRITE
  112. #   define TEMPLATE_REG_WRITE(x,data) 
  113.     (*((volatile UINT16 *)(x)) = (data))
  114. #endif /*TEMPLATE_REG_WRITE*/
  115. /* Convert level number to vector number */
  116. #ifndef TEMPLATE_LVL_VEC_MAP
  117. #   define TEMPLATE_LVL_VEC_MAP(level, vector) 
  118.     ((vector) = ((level) + TEMPLATE_VEC_BASE))
  119. #endif
  120. /* Convert pending register value, to a level number */
  121. #ifndef TEMPLATE_PEND_LVL_MAP
  122. #   define TEMPLATE_PEND_LVL_MAP(pendReg, level) 
  123.     ((level) = (pendReg))
  124. #endif
  125. /* driver constants */
  126. #define TEMPLATE_NUM_LEVELS 16
  127. #define TEMPLATE_ALL_ENABLED (TEMPLATE_NUM_LEVELS)
  128. #define TEMPLATE_ALL_DISABLED 0
  129. /* Local data */
  130. /* Current interrupt level setting (templateLvlChg). */
  131. LOCAL UINT32 templateLvlCurrent = TEMPLATE_ALL_DISABLED; /* all levels disabled */
  132. /*
  133.  * A mask word.  Bits are set in this word when a specific level
  134.  * is enabled. It is used to mask off individual levels that have
  135.  * not been explicitly enabled.
  136.  */
  137. LOCAL UINT32 templateLvlEnabled;
  138. /*
  139.  * This array maps interrupt levels to mask patterns.  The interrupt level
  140.  * is the index, the data is the mask value.  A mask bit enables one
  141.  * level.  The mask value is 'and'd with the templateLvlEnabled value
  142.  * before writing to the chip.
  143.  */
  144. LOCAL UINT32 templateLvlMask[TEMPLATE_NUM_LEVELS + 1] = /* int level mask */
  145. {
  146. 0x0000, /* level 0, all disabled */
  147. 0x0001, 0x0003, 0x0007, 0x000f,
  148. 0x001f, 0x003f, 0x007f, 0x00ff,
  149. 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  150. 0x1fff, 0x3fff, 0x7fff, 0xffff /* level 16, all enabled */
  151. };
  152. /* forward declarations */
  153. STATUS templateLvlVecChk (int*, int*);
  154. STATUS  templateLvlVecAck (int, int);
  155. int templateLvlChg (int);
  156. STATUS templateLvlEnable (int);
  157. STATUS templateLvlDisable (int);
  158. /*******************************************************************************
  159. *
  160. * templateDevInit - initialize the interrupt controller
  161. *
  162. * This routine will initialize the interrupt controller device, disabling all
  163. * interrupt sources.  It will also connect the device driver specific routines
  164. * into the architecture level hooks.  If the BSP needs to create a wrapper
  165. * routine around any of the arhitecture level routines, it should install the
  166. * pointer to the wrapper routine after calling this routine.
  167. * RETURNS: N/A.
  168. */
  169. void templateDevInit (void)
  170.     {
  171.     /* install the driver routines in the architecture hooks */
  172.     sysIntLvlVecChkRtn = templateLvlVecChk;
  173.     sysIntLvlVecAckRtn = templateLvlVecAck;
  174.     sysIntLvlChgRtn = templateLvlChg;
  175.     sysIntLvlEnableRtn = templateLvlEnable;
  176.     sysIntLvlDisableRtn = templateLvlDisable;
  177.     templateLvlEnabled = 0;  /* all sources disabled */
  178.     templateLvlChg (TEMPLATE_ALL_ENABLED); /* enable all levels */
  179.     }
  180. /*******************************************************************************
  181. *
  182. * templateLvlVecChk - check for and return any pending interrupts
  183. *
  184. * This routine interrogates the hardware to determine the highest priority
  185. * interrupt pending.  It returns the vector associated with that interrupt, and
  186. * also the interrupt priority level prior to the interrupt (not the
  187. * level of the interrupt).  The current interrupt priority level is then
  188. * raised to the level of the current interrupt so that only higher priority
  189. * interrupts will be accepted until this interrupt is finished.
  190. *
  191. * The return value ERROR indicates that no pending interrupt was found and
  192. * that the level and vector values were not returned.
  193. *
  194. * RETURNS: OK or ERROR if no interrupt is pending.
  195. */
  196. STATUS  templateLvlVecChk
  197.     (
  198.     int* pLevel,  /* ptr to receive old interrupt level */
  199.     int* pVector  /* ptr to receive current interrupt vector */
  200.     )
  201.     {
  202.     int newLevel;
  203.     /* Read pending interrupt register */
  204.     TEMPLATE_REG_READ (TEMPLATE_CSR_PEND, newLevel);
  205.     /* If no interrupt is pending, return ERROR */
  206.     if (newLevel == 0)
  207. return ERROR;
  208.     /* map the return value to an interrupt level number */
  209.     TEMPLATE_PEND_LVL_MAP (newLevel, newLevel);
  210.     /* change to new interrupt level, returning previous level to caller */
  211.     *pLevel = templateLvlChg (newLevel);
  212.     /* fetch, or compute the interrupt vector number */
  213.     TEMPLATE_LVL_VEC_MAP (newLevel, *pVector);
  214.     return OK;
  215.     }
  216. /*******************************************************************************
  217. *
  218. * templateLvlVecAck - acknowledge the current interrupt
  219. *
  220. * Acknowledge the current interrupt cycle.  The level and vector values are
  221. * those generated during the templateLvlVecChk() routine for this interrupt
  222. * cycle.  The basic action is to reset the current interrupt and return
  223. * the interrupt level to its previous setting.
  224. *
  225. * RETURNS: OK or ERROR if a hardware fault is detected.
  226. * ARGSUSED
  227. */
  228. STATUS  templateLvlVecAck
  229.     (
  230.     int level, /* old interrupt level to be restored */
  231.     int vector /* current interrupt vector, if needed */
  232.     )
  233.     {
  234.     /* acknowledge the current interrupt cycle */
  235.     TEMPLATE_REG_WRITE (TEMPLATE_CSR_ACK, (1 << (templateLvlCurrent)));
  236.     /* restore the previous interrupt level */
  237.     templateLvlChg (level);
  238.     return OK;
  239.     }
  240. /*******************************************************************************
  241. *
  242. * templateLvlChg - change the interrupt level value
  243. *
  244. * This routine implements the overall interrupt setting.  All levels
  245. * up to and including the specifed level are disabled.  All levels above
  246. * the specified level will be enabled, but only if they were specifically
  247. * enabled by the templateLvlEnable() routine.
  248. *
  249. * The specific priority level TEMPLATE_NUM_LEVELS is valid and represents
  250. * all levels enabled.
  251. *
  252. * RETURNS: Previous interrupt level.
  253. */
  254. int  templateLvlChg
  255.     (
  256.     int level /* new interrupt level */
  257.     )
  258.     {
  259.     int oldLevel;
  260.     
  261.     oldLevel = templateLvlCurrent;
  262.     if (level >= 0 &&
  263.         level <= TEMPLATE_NUM_LEVELS)
  264. {
  265. /* change current interrupt level */
  266. templateLvlCurrent = level;
  267. }
  268.     /* Activate the enabled interrupts */
  269.     TEMPLATE_REG_WRITE (TEMPLATE_CSR_ENB, 
  270. (templateLvlMask[templateLvlCurrent] & templateLvlEnabled));
  271.     return oldLevel;
  272.     }
  273. /*******************************************************************************
  274. *
  275. * templateLvlEnable - enable a single interrupt level
  276. *
  277. * Enable a specific interrupt level.  The enabled level will be allowed to
  278. * generate an interrupt, when the overall interrupt level is set below the
  279. * specified level.  Without being enabled, the interrupt is blocked regardless
  280. * of the overall interrupt level setting.
  281. *
  282. * RETURNS: OK or ERROR if the specified level cannot be enabled.
  283. */
  284. STATUS  templateLvlEnable
  285.     (
  286.     int level  /* level to be enabled */
  287.     )
  288.     {
  289.     if (level < 0 ||
  290. level > TEMPLATE_NUM_LEVELS)
  291. return ERROR;
  292.     /* set bit in enable mask */
  293.     if (level > 0)
  294. {
  295. int key;
  296. key = intLock ();
  297. templateLvlEnabled |= (1 << level);
  298. intUnlock (key);
  299. }
  300.     templateLvlChg (-1); /* reset current mask */
  301.     return OK;
  302.     }
  303. /*******************************************************************************
  304. *
  305. * templateLvlDisable - disable a single interrupt level
  306. *
  307. * Disable a specific interrupt level.  The disabled level is prevented
  308. * from generating an interrupt even if the overall interrupt level is set
  309. * below the specified level.
  310. *
  311. * RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
  312. */
  313. STATUS  templateLvlDisable
  314.     (
  315.     int level  /* level to be disabled */
  316.     )
  317.     {
  318.     if (level < 0 ||
  319. level > TEMPLATE_NUM_LEVELS)
  320. return ERROR;
  321.     /* clear bit in enable mask */
  322.     if (level > 0)
  323. {
  324. int key;
  325. key = intLock ();
  326. templateLvlEnabled &= ~(1 << level);
  327. intUnlock (key);
  328. }
  329.     templateLvlChg (-1); /* reset current mask */
  330.     return OK;
  331.     }