intArchLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:27k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* intArchLib.c - I80x86 interrupt subroutine library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01p,20nov01,hdn  doc clean up for 5.5
  8. 01o,09nov01,hdn  replaced magic numbers with intConnectCode offset macros
  9. 01n,29aug01,hdn  got rid of VXM stuff.
  10.  added intVecGet2() correspond to intVecSet2().
  11.  replaced {exc,int}IdtSelector with sysCs{Exc,Int}.
  12.  added document for intHandlerCreateI86() (spr 30292)
  13. 01m,14dec00,pai  Added stub routines for intEnable() and intDisable() (SPR
  14.                  #63046).
  15. 01l,09feb99,wsl  add comment to document ERRNO value
  16. 01k,29may98,hdn  added intHandlerCreateX86(), modified intConnectCode[]
  17.  to solve EOI issue and sprious interrupt issue.
  18.  removed intEOI.  added intEoiGet.
  19. 01j,13apr98,hdn  changed malloc to memalign in intHandlerCreate().
  20. 01i,14jan98,dbt  added dbgLib.h include
  21. 01h,23aug95,ms   removed taskSafe/Unsafe calls from intVecSet().
  22. 01g,15jun95,ms   added intRegsLock, intRegsUnlock
  23. 01f,14jun95,hdn  added intVecSetEnt and intVecSetExit.
  24.  renamed pSysEndOfInt to intEOI.
  25. 01e,26jan95,rhp  doc tweaks
  26. 01d,29jul93,hdn  added intVecTableWriteProtect().
  27.   - intVecSet checks taskIdCurrent before TASK_{SAFE,UNSAFE}.
  28.   - deleted mention of intContext() and intCount().
  29.   - added vxmIfVecxxx callout for monitor support.
  30. 01c,03jun93,hdn  updated to 5.1
  31.   - changed functions to ansi style
  32.   - changed includes to have absolute path from h/
  33.   - fixed #else and #endif
  34.   - changed VOID to void
  35.   - changed copyright notice
  36. 01b,15oct92,hdn  supported nested interrupt.
  37. 01a,28feb92,hdn  written based on TRON, 68k version.
  38. */
  39. /*
  40. DESCRIPTION
  41. This library provides architecture-dependent routines to manipulate
  42. and connect to hardware interrupts.  Any C language routine can be
  43. connected to any interrupt by calling intConnect().  Vectors can be
  44. accessed directly by intVecSet() and intVecGet(), or by intVecSet2()
  45. and intVecGet2().  The vector (trap) base register can be accessed 
  46. by the routines intVecBaseSet() and intVecBaseGet().
  47. Tasks can lock and unlock interrupts by calling intLock() and intUnlock().
  48. The lock-out level can be set and reported by intLockLevelSet() and
  49. intLockLevelGet().
  50. WARNING
  51. Do not call VxWorks system routines with interrupts locked.
  52. Violating this rule may re-enable interrupts unpredictably.
  53. INTERRUPT VECTORS AND NUMBERS
  54. Most of the routines in this library take an interrupt vector as a
  55. parameter, which is the byte offset into the vector table.  Macros are
  56. provided to convert between interrupt vectors and interrupt numbers:
  57. .iP IVEC_TO_INUM(intVector) 10
  58. changes a vector to a number.
  59. .iP INUM_TO_IVEC(intNumber)
  60. turns a number into a vector.
  61. .iP TRAPNUM_TO_IVEC(trapNumber)
  62. converts a trap number to a vector.
  63. EXAMPLE
  64. To switch between one of several routines for a particular interrupt,
  65. the following code fragment is one alternative:
  66. .CS
  67.     vector  = INUM_TO_IVEC(some_int_vec_num);
  68.     oldfunc = intVecGet (vector);
  69.     newfunc = intHandlerCreate (routine, parameter);
  70.     intVecSet (vector, newfunc);
  71.         ...
  72.     intVecSet (vector, oldfunc);    /@ use original routine  @/
  73.         ...
  74.     intVecSet (vector, newfunc);    /@ reconnect new routine @/
  75. .CE
  76. INCLUDE FILE: iv.h
  77. SEE ALSO: intLib, intALib
  78. */
  79. /* LINTLIBRARY */
  80. #include "vxWorks.h"
  81. #include "cacheLib.h"
  82. #include "errnoLib.h"
  83. #include "intLib.h"
  84. #include "memLib.h"
  85. #include "sysLib.h"
  86. #include "taskLib.h"
  87. #include "string.h"
  88. #include "stdlib.h"
  89. #include "dbgLib.h"
  90. #include "private/vmLibP.h"
  91. /* imports */
  92. IMPORT void intVBRSet (FUNCPTR *baseAddr);
  93. IMPORT void intEnt (); /* interrupt entrance stub */
  94. IMPORT void intExit (); /* interrupt exit stub */
  95. IMPORT int sysCsExc;
  96. IMPORT int sysCsInt;
  97. /* globals */
  98. /* The routine intLock(), found in intALib.s uses intLockMask to construct a
  99.  * new EFLAGS with the correct interrupt lock-out level.  The difficulty is
  100.  * intLock() may be called from either interrupt level, or task level, so
  101.  * simply reserving a EFLAGS such as 0x80000000 does not work because such a 
  102.  * EFLAGS would assume task-level code.
  103.  */
  104. UINT intLockMask   = 0x0; /* interrupt lock mask - level 0 */
  105. VOIDFUNCPTR intVecSetEnt  = NULL; /* entry hook for intVecSet() */
  106. VOIDFUNCPTR intVecSetExit = NULL; /* exit  hook for intVecSet() */
  107. VOIDFUNCPTR intEOI   = NULL; /* pointer to EOI routine in BSP */
  108. VOIDFUNCPTR intEoiGet   = NULL; /* pointer to EoiGet routine in BSP */
  109. LOCAL int  dummy (void) { return ERROR; }  /* dummy, returns ERROR   */
  110. FUNCPTR    sysIntLvlEnableRtn  = dummy;    /* enable a single level  */
  111. FUNCPTR    sysIntLvlDisableRtn = dummy;    /* disable a single level */
  112. /* locals */
  113. LOCAL FUNCPTR * intVecBase = 0; /* vector base address */
  114. LOCAL UCHAR intConnectCode [] = /* intConnect stub */
  115.     {
  116. /*
  117.  * 00  e8 kk kk kk kk call _intEnt * tell kernel
  118.  * 05  50 pushl %eax * save regs
  119.  * 06  52 pushl %edx
  120.  * 07  51 pushl %ecx
  121.  * 08  68 pp pp pp pp pushl $_parameterBoi * push BOI param
  122.  * 13  e8 rr rr rr rr call _routineBoi * call BOI routine
  123.  * 18  68 pp pp pp pp pushl $_parameter * push param
  124.  * 23  e8 rr rr rr rr call _routine * call C routine
  125.  * 28  68 pp pp pp pp pushl $_parameterEoi * push EOI param
  126.  * 33  e8 rr rr rr rr call _routineEoi * call EOI routine
  127.  * 38  83 c4 0c addl $12, %esp * pop param
  128.  * 41  59 popl %ecx * restore regs
  129.  * 42  5a popl %edx
  130.  * 43  58 popl %eax
  131.  * 44  e9 kk kk kk kk jmp _intExit * exit via kernel
  132.  */
  133.      0xe8, 0x00, 0x00, 0x00, 0x00, /* _intEnt filled in at runtime */
  134.      0x50,
  135.      0x52,
  136.      0x51,
  137.      0x68, 0x00, 0x00, 0x00, 0x00, /* BOI parameter filled in at runtime */
  138.      0xe8, 0x00, 0x00, 0x00, 0x00, /* BOI routine filled in at runtime */
  139.      0x68, 0x00, 0x00, 0x00, 0x00, /* parameter filled in at runtime */
  140.      0xe8, 0x00, 0x00, 0x00, 0x00, /* routine filled in at runtime */
  141.      0x68, 0x00, 0x00, 0x00, 0x00, /* EOI parameter filled in at runtime */
  142.      0xe8, 0x00, 0x00, 0x00, 0x00, /* EOI routine filled in at runtime */
  143.      0x83, 0xc4, 0x0c, /* pop parameters */
  144.      0x59,
  145.      0x5a,
  146.      0x58,
  147.      0xe9, 0x00, 0x00, 0x00, 0x00, /* _intExit filled in at runtime */
  148.     };
  149. /* forward declarations */
  150. /*******************************************************************************
  151. *
  152. * intConnect - connect a C routine to a hardware interrupt
  153. *
  154. * This routine connects a specified C routine to a specified interrupt
  155. * vector.  The address of <routine> is stored at <vector> so that <routine>
  156. * is called with <parameter> when the interrupt occurs.  The routine is
  157. * invoked in supervisor mode at interrupt level.  A proper C environment
  158. * is established, the necessary registers saved, and the stack set up.
  159. *
  160. * The routine can be any normal C code, except that it must not invoke
  161. * certain operating system functions that may block or perform I/O
  162. * operations.
  163. *
  164. * This routine simply calls intHandlerCreate()/intHandlerCreateI86() and 
  165. * intVecSet().  The address of the handler returned by intHandlerCreate()/
  166. * intHandlerCreateI86() is what actually gets put in the interrupt vector.
  167. *
  168. * RETURNS:
  169. * OK, or ERROR if the interrupt handler cannot be built.
  170. *
  171. * SEE ALSO: intHandlerCreate(), intVecSet(), intHandlerCreateI86()
  172. */
  173. STATUS intConnect
  174.     (
  175.     VOIDFUNCPTR *vector, /* interrupt vector to attach to     */
  176.     VOIDFUNCPTR routine, /* routine to be called              */
  177.     int parameter /* parameter to be passed to routine */
  178.     )
  179.     {
  180.     FUNCPTR intDrvRtn;
  181.     VOIDFUNCPTR routineBoi;
  182.     VOIDFUNCPTR routineEoi;
  183.     int parameterBoi;
  184.     int parameterEoi;
  185.     if (intEoiGet == NULL)
  186. {
  187.         intDrvRtn = intHandlerCreate ((FUNCPTR)routine, parameter); 
  188. }
  189.     else
  190. {
  191.         (* intEoiGet) (vector, &routineBoi, &parameterBoi, 
  192.        &routineEoi, &parameterEoi);
  193.         intDrvRtn = intHandlerCreateI86 ((FUNCPTR)routine, parameter,
  194.  (FUNCPTR)routineBoi, parameterBoi,
  195.  (FUNCPTR)routineEoi, parameterEoi); 
  196. }
  197.     if (intDrvRtn == NULL)
  198. return (ERROR);
  199.     /* make vector point to synthesized code */
  200.     intVecSet ((FUNCPTR *)vector, (FUNCPTR)intDrvRtn);
  201.     return (OK);
  202.     }
  203. /*******************************************************************************
  204. *
  205. * intEnable - enable a specific interrupt level
  206. *
  207. * Enable a specific interrupt level.  For each interrupt level to be used,
  208. * there must be a call to this routine before it will be
  209. * allowed to interrupt.
  210. *
  211. * RETURNS:
  212. * OK or ERROR for invalid arguments.
  213. */
  214. int intEnable
  215.     (
  216.     int level   /* level to be enabled */
  217.     )
  218.     {
  219.     return (*sysIntLvlEnableRtn) (level);
  220.     }
  221. /*******************************************************************************
  222. *
  223. * intDisable - disable a particular interrupt level
  224. *
  225. * This call disables a particular interrupt level, regardless of the current
  226. * interrupt mask level.
  227. *
  228. * RETURNS:
  229. * OK or ERROR for invalid arguments.
  230. */
  231. int intDisable
  232.     (
  233.     int level   /* level to be disabled */
  234.     )
  235.     {
  236.     return (*sysIntLvlDisableRtn) (level);
  237.     }
  238. /*******************************************************************************
  239. *
  240. * intHandlerCreate - construct an interrupt handler for a C routine
  241. *
  242. * This routine builds an interrupt handler around a specified C routine.
  243. * This interrupt handler is then suitable for connecting to a specific
  244. * vector address with intVecSet().  The interrupt handler is invoked in
  245. * supervisor mode at interrupt level.  A proper C environment is
  246. * established, the necessary registers saved, and the stack set up.
  247. * The routine can be any normal C code, except that it must not invoke
  248. * certain operating system functions that may block or perform I/O
  249. * operations.
  250. *
  251. * IMPLEMENTATION:
  252. * This routine builds an interrupt handler of the following form in
  253. * allocated memory:
  254. *
  255. * .CS
  256. * 00  e8 kk kk kk kk call _intEnt * tell kernel
  257. * 05  50 pushl %eax * save regs
  258. * 06  52 pushl %edx
  259. * 07  51 pushl %ecx
  260. * 08  68 pp pp pp pp pushl $_parameterBoi * push BOI param
  261. * 13  e8 rr rr rr rr call _routineBoi * call BOI routine
  262. * 18  68 pp pp pp pp pushl $_parameter * push param
  263. * 23  e8 rr rr rr rr call _routine * call C routine
  264. * 28  68 pp pp pp pp pushl $_parameterEoi * push EOI param
  265. * 33  e8 rr rr rr rr call _routineEoi * call EOI routine
  266. * 38  83 c4 0c addl $12, %esp * pop param
  267. * 41  59 popl %ecx * restore regs
  268. * 42  5a popl %edx
  269. * 43  58 popl %eax
  270. * 44  e9 kk kk kk kk jmp _intExit * exit via kernel
  271. * .CE
  272. * RETURNS: A pointer to the new interrupt handler, or NULL if memory
  273. * is insufficient.
  274. */
  275. FUNCPTR intHandlerCreate
  276.     (
  277.     FUNCPTR routine, /* routine to be called              */
  278.     int parameter /* parameter to be passed to routine */
  279.     )
  280.     {
  281.     FAST UCHAR *pCode; /* pointer to newly synthesized code */
  282.     FAST int ix;
  283.     pCode = (UCHAR *)memalign (_CACHE_ALIGN_SIZE, sizeof (intConnectCode));
  284.     if (pCode != NULL)
  285. {
  286. /* copy intConnectCode into new code area */
  287. bcopy ((char *)intConnectCode, (char *)pCode, sizeof (intConnectCode));
  288. /* set the addresses & instructions */
  289. *(int *)&pCode[ICC_INT_ENT] = (int)intEnt - 
  290.       (int)&pCode[ICC_INT_ENT + 4];
  291. for (ix = 0; ix < 10; ix++)
  292.     pCode[ICC_BOI_PUSH + ix] = 0x90; /* no BOI so replace by NOP */
  293. pCode[ICC_ADD_N] = 8; /* pop two parameters */
  294. *(int *)&pCode[ICC_INT_PARAM] = (int)parameter;
  295. *(int *)&pCode[ICC_INT_ROUTN] = (int)routine - 
  296. (int)&pCode[ICC_INT_ROUTN + 4];
  297. if (intEOI == NULL)
  298.     {
  299.     for (ix = 0; ix < 5; ix++)
  300. pCode[ICC_EOI_CALL + ix] = 0x90; /* replace by NOP */
  301.     }
  302. else
  303.     {
  304.     *(int *)&pCode[ICC_EOI_ROUTN] = (int)intEOI - 
  305.     (int)&pCode[ICC_EOI_ROUTN + 4];
  306.     }
  307. *(int *)&pCode[ICC_INT_EXIT] = (int)intExit - 
  308.        (int)&pCode[ICC_INT_EXIT + 4];
  309. }
  310.     CACHE_TEXT_UPDATE ((void *) pCode, sizeof (intConnectCode));
  311.     return ((FUNCPTR)(int)pCode);
  312.     }
  313. /*******************************************************************************
  314. *
  315. * intHandlerCreateI86 - construct an interrupt handler for a C routine
  316. *
  317. * This routine builds an interrupt handler around a specified C routine.
  318. * This interrupt handler is then suitable for connecting to a specific
  319. * vector address with intVecSet().  The interrupt handler is invoked in
  320. * supervisor mode at interrupt level.  A proper C environment is
  321. * established, the necessary registers saved, and the stack set up.
  322. * The routine can be any normal C code, except that it must not invoke
  323. * certain operating system functions that may block or perform I/O
  324. * operations.
  325. *
  326. * IMPLEMENTATION:
  327. * This routine builds an interrupt handler of the following form in
  328. * allocated memory:
  329. *
  330. * .CS
  331. * 00  e8 kk kk kk kk call _intEnt * tell kernel
  332. * 05  50 pushl %eax * save regs
  333. * 06  52 pushl %edx
  334. * 07  51 pushl %ecx
  335. * 08  68 pp pp pp pp pushl $_parameterBoi * push BOI param
  336. * 13  e8 rr rr rr rr call _routineBoi * call BOI routine
  337. * 18  68 pp pp pp pp pushl $_parameter * push param
  338. * 23  e8 rr rr rr rr call _routine * call C routine
  339. * 28  68 pp pp pp pp pushl $_parameterEoi * push EOI param
  340. * 33  e8 rr rr rr rr call _routineEoi * call EOI routine
  341. * 38  83 c4 0c addl $12, %esp * pop param
  342. * 41  59 popl %ecx * restore regs
  343. * 42  5a popl %edx
  344. * 43  58 popl %eax
  345. * 44  e9 kk kk kk kk jmp _intExit * exit via kernel
  346. * .CE
  347. * Third and fourth parameter of intHandlerCreateI86() are the BOI routine 
  348. * address and its parameter that are inserted into the code as "routineBoi" 
  349. * and "parameterBoi". 
  350. * Fifth and sixth parameter of intHandlerCreateI86() are the EOI routine 
  351. * address and its parameter that are inserted into the code as "routineEoi" 
  352. * and "parameterEoi". 
  353. * The BOI routine detects if this interrupt is stray/spurious/phantom by
  354. * interrogating the interrupt controller, and returns from the interrupt
  355. * if it is.  The EOI routine issues End Of Interrupt signal to the 
  356. * interrupt controller, if it is required by the controller.  
  357. * Each interrupt controller has its own BOI and EOI routine.  They are
  358. * located in the BSP, and their address and parameter are taken by the
  359. * intEoiGet function (set to sysIntEoiGet() in the BSP).
  360. * The Tornado 2, and later, BSPs should use the BOI and EOI mechanism with
  361. * intEoiGet function pointer.
  362. *
  363. * To keep the Tornado 101 BSP backward compatible, the function pointer 
  364. * intEOI is not removed.  If intEoiGet is NULL, it should be set to the
  365. * sysIntEoiGet() routine in the BSP, intHandlerCreate() and the intEOI 
  366. * function pointer (set to sysIntEOI() in the Tornado 101 BSP) is used.
  367. * RETURNS: A pointer to the new interrupt handler, or NULL if memory
  368. * is insufficient.
  369. */
  370. FUNCPTR intHandlerCreateI86
  371.     (
  372.     FUNCPTR routine, /* routine to be called              */
  373.     int parameter, /* parameter to be passed to routine */
  374.     FUNCPTR routineBoi, /* BOI routine to be called          */
  375.     int parameterBoi, /* parameter to be passed to routineBoi */
  376.     FUNCPTR routineEoi, /* EOI routine to be called          */
  377.     int parameterEoi /* parameter to be passed to routineEoi */
  378.     )
  379.     {
  380.     FAST UCHAR *pCode; /* pointer to newly synthesized code */
  381.     FAST int ix;
  382.     pCode = (UCHAR *)memalign (_CACHE_ALIGN_SIZE, sizeof (intConnectCode));
  383.     if (pCode != NULL)
  384. {
  385. /* copy intConnectCode into new code area */
  386. bcopy ((char *)intConnectCode, (char *)pCode, sizeof (intConnectCode));
  387. /* set the addresses & instructions */
  388. *(int *)&pCode[ICC_INT_ENT] = (int)intEnt - 
  389.       (int)&pCode[ICC_INT_ENT + 4];
  390. if (routineBoi == NULL) /* BOI routine */
  391.     {
  392.     for (ix = 0; ix < 10; ix++)
  393. pCode[ICC_BOI_PUSH + ix] = 0x90; /* replace by NOP */
  394.     pCode[ICC_ADD_N] = 8; /* pop two params */
  395.     }
  396. else
  397.     {
  398.     *(int *)&pCode[ICC_BOI_PARAM] = (int)parameterBoi;
  399.     *(int *)&pCode[ICC_BOI_ROUTN] = (int)routineBoi - 
  400.     (int)&pCode[ICC_BOI_ROUTN + 4];
  401.     }
  402. *(int *)&pCode[ICC_INT_PARAM] = (int)parameter;
  403. *(int *)&pCode[ICC_INT_ROUTN] = (int)routine - 
  404. (int)&pCode[ICC_INT_ROUTN + 4];
  405. if (routineEoi == NULL) /* EOI routine */
  406.     {
  407.     for (ix = 0; ix < 5; ix++)
  408. pCode[ICC_EOI_CALL + ix] = 0x90; /* replace by NOP */
  409.     }
  410. else
  411.     {
  412.     *(int *)&pCode[ICC_EOI_PARAM] = (int)parameterEoi;
  413.     *(int *)&pCode[ICC_EOI_ROUTN] = (int)routineEoi - 
  414.     (int)&pCode[ICC_EOI_ROUTN + 4];
  415.     }
  416. *(int *)&pCode[ICC_INT_EXIT] = (int)intExit - 
  417.        (int)&pCode[ICC_INT_EXIT + 4];
  418. }
  419.     CACHE_TEXT_UPDATE ((void *) pCode, sizeof (intConnectCode));
  420.     return ((FUNCPTR)(int)pCode);
  421.     }
  422. /*******************************************************************************
  423. *
  424. * intLockLevelSet - set the current interrupt lock-out level
  425. *
  426. * This routine sets the current interrupt lock-out level and stores it
  427. * in the globally accessible variable `intLockMask'.  The specified
  428. * interrupt level is masked when interrupts are locked by
  429. * intLock().  The default lock-out level (1 for I80x86 processors)
  430. * is initially set by kernelInit() when VxWorks is initialized.
  431. * RETURNS: N/A
  432. */
  433. void intLockLevelSet
  434.     (
  435.     int newLevel /* new interrupt level */
  436.     )
  437.     {
  438.     intLockMask    = newLevel;
  439.     }
  440. /*******************************************************************************
  441. *
  442. * intLockLevelGet - get the current interrupt lock-out level
  443. * This routine returns the current interrupt lock-out level, which is
  444. * set by intLockLevelSet() and stored in the globally accessible
  445. * variable `intLockMask'.  This is the interrupt level currently
  446. * masked when interrupts are locked out by intLock().  The default
  447. * lock-out level is 1 for I80x86 processors, and is initially set by
  448. * kernelInit() when VxWorks is initialized.
  449. *
  450. * RETURNS:
  451. * The interrupt level currently stored in the interrupt lock-out mask.
  452. */
  453. int intLockLevelGet (void)
  454.     {
  455.     return ((int)(intLockMask));
  456.     }
  457. /*******************************************************************************
  458. *
  459. * intVecBaseSet - set the vector base address
  460. *
  461. * This routine sets the vector base address.  The CPU's vector base register
  462. * is set to the specified value, and subsequent calls to intVecGet() or
  463. * intVecSet() will use this base address.  The vector base address is
  464. * initially 0, until modified by calls to this routine.
  465. *
  466. * RETURNS: N/A
  467. *
  468. * SEE ALSO: intVecBaseGet(), intVecGet(), intVecSet()
  469. */
  470. void intVecBaseSet
  471.     (
  472.     FUNCPTR *baseAddr     /* new vector base address */
  473.     )
  474.     {
  475.     char idt[6]; /* interrupt descriptor table register */
  476.     char *p = idt;
  477.     intVecBase = baseAddr; /* keep the base address in a static variable */
  478.     *(short *)p = 0x07ff; /* IDT limit */
  479.     *(int *)(p + 2) = (int)baseAddr; /* IDT base address */
  480.     intVBRSet ((FUNCPTR *)idt); /* set the actual IDT register */
  481.     CACHE_TEXT_UPDATE ((void *)baseAddr, 256 * 8);
  482.     }
  483. /*******************************************************************************
  484. *
  485. * intVecBaseGet - get the vector base address
  486. *
  487. * This routine returns the current vector base address, which is set
  488. * with intVecBaseSet().
  489. *
  490. * RETURNS: The current vector base address.
  491. *
  492. * SEE ALSO: intVecBaseSet()
  493. */
  494. FUNCPTR *intVecBaseGet (void)
  495.     {
  496.     return (intVecBase);
  497.     }
  498. /******************************************************************************
  499. *
  500. * intVecSet - set a CPU vector
  501. *
  502. * This routine attaches an exception/interrupt handler to a specified vector.
  503. * The vector is specified as an offset into the CPU's vector table.  This
  504. * vector table starts, by default, at address 0.  
  505. * However, the vector table may be set to start at any address with
  506. * intVecBaseSet().  The vector table is set up in usrInit().
  507. *
  508. * RETURNS: N/A
  509. *
  510. * SEE ALSO: intVecBaseSet(), intVecGet(), intVecGet2(), intVecSet2()
  511. */
  512. void intVecSet
  513.     (
  514.     FUNCPTR *vector, /* vector offset              */
  515.     FUNCPTR function /* address to place in vector */
  516.     )
  517.     {
  518.     FUNCPTR * newVector;
  519.     UINT state;
  520.     BOOL writeProtected = FALSE;
  521.     int pageSize = 0;
  522.     char * pageAddr = 0;
  523.     if (intVecSetEnt != NULL) /* entry hook */
  524. (* intVecSetEnt) (vector, function);
  525.     /* vector is offset by the vector base address */
  526.     newVector = (FUNCPTR *) ((int) vector + (int) intVecBaseGet ());
  527.     /* see if we need to write enable the memory */
  528.     if (vmLibInfo.vmLibInstalled)
  529. {
  530. pageSize = VM_PAGE_SIZE_GET();
  531. pageAddr = (char *) ((UINT) newVector / pageSize * pageSize);
  532. if (VM_STATE_GET (NULL, (void *) pageAddr, &state) != ERROR)
  533.     if ((state & VM_STATE_MASK_WRITABLE) == VM_STATE_WRITABLE_NOT)
  534. {
  535. writeProtected = TRUE;
  536. VM_STATE_SET (NULL, pageAddr, pageSize, VM_STATE_MASK_WRITABLE,
  537.       VM_STATE_WRITABLE);
  538. }
  539. }
  540.     *(int *)newVector = (sysCsInt << 16) | ((int)function & 0xffff);
  541.     *((short *)newVector + 3) = (short)(((int)function & 0xffff0000) >> 16);
  542.     if (writeProtected)
  543. {
  544. VM_STATE_SET (NULL, pageAddr, pageSize, 
  545.       VM_STATE_MASK_WRITABLE, VM_STATE_WRITABLE_NOT);
  546. }
  547.     if (intVecSetExit != NULL) /* exit hook */
  548. (* intVecSetExit) (vector, function);
  549.     CACHE_TEXT_UPDATE ((void *)newVector, 8);
  550.     }
  551. /******************************************************************************
  552. *
  553. * intVecSet2 - set a CPU vector, gate type(int/trap), and selector (x86)
  554. *
  555. * This routine attaches an exception handler to a specified vector,
  556. * with the type of the gate and the selector of the gate.  
  557. * The vector is specified as an offset into the CPU's vector table.  This
  558. * vector table starts, by default, at address 0.  
  559. * However, the vector table may be set to start at any address with
  560. * intVecBaseSet().  The vector table is set up in usrInit().
  561. *
  562. * RETURNS: N/A
  563. *
  564. * SEE ALSO: intVecBaseSet(), intVecGet(), intVecSet(), intVecGet2()
  565. */
  566. void intVecSet2
  567.     (
  568.     FUNCPTR * vector, /* vector offset              */
  569.     FUNCPTR function, /* address to place in vector */
  570.     int idtGate, /* IDT_TRAP_GATE or IDT_INT_GATE */
  571.     int idtSelector /* sysCsExc or sysCsInt */
  572.     )
  573.     {
  574.     FUNCPTR * newVector;
  575.     UINT state;
  576.     BOOL writeProtected = FALSE;
  577.     int pageSize = 0;
  578.     char * pageAddr = 0;
  579.     if (intVecSetEnt != NULL) /* entry hook */
  580. (* intVecSetEnt) (vector, function);
  581.     /* vector is offset by the vector base address */
  582.     newVector = (FUNCPTR *) ((int) vector + (int) intVecBaseGet ());
  583.     /* see if we need to write enable the memory */
  584.     if (vmLibInfo.vmLibInstalled)
  585. {
  586. pageSize = VM_PAGE_SIZE_GET();
  587. pageAddr = (char *) ((UINT) newVector / pageSize * pageSize);
  588. if (VM_STATE_GET (NULL, (void *) pageAddr, &state) != ERROR)
  589.     if ((state & VM_STATE_MASK_WRITABLE) == VM_STATE_WRITABLE_NOT)
  590. {
  591. writeProtected = TRUE;
  592. VM_STATE_SET (NULL, pageAddr, pageSize, VM_STATE_MASK_WRITABLE,
  593.       VM_STATE_WRITABLE);
  594. }
  595. }
  596.     *(int *)newVector = (idtSelector << 16) | ((int)function & 0x0000ffff);
  597.     *((int *)newVector + 1) = ((int)function & 0xffff0000) | idtGate;
  598.     if (writeProtected)
  599. {
  600. VM_STATE_SET (NULL, pageAddr, pageSize, 
  601.       VM_STATE_MASK_WRITABLE, VM_STATE_WRITABLE_NOT);
  602. }
  603.     if (intVecSetExit != NULL) /* exit hook */
  604. (* intVecSetExit) (vector, function);
  605.     CACHE_TEXT_UPDATE ((void *)newVector, 8);
  606.     }
  607. /*******************************************************************************
  608. *
  609. * intVecGet - get an interrupt vector
  610. *
  611. * This routine returns a pointer to the exception/interrupt handler attached
  612. * to a specified vector.  The vector is specified as an offset into the CPU's
  613. * vector table.  This vector table starts, by default, at address 0.
  614. * However, the vector table may be set to start at any address with
  615. * intVecBaseSet().
  616. *
  617. * RETURNS:
  618. * A pointer to the exception/interrupt handler attached to the specified vector.
  619. *
  620. * SEE ALSO: intVecSet(), intVecBaseSet(), intVecGet2(), intVecSet2()
  621. */
  622. FUNCPTR intVecGet
  623.     (
  624.     FUNCPTR *vector /* vector offset */
  625.     )
  626.     {
  627.     FUNCPTR *newVector;
  628.     /* vector is offset by vector base address */
  629.     newVector = (FUNCPTR *) ((int) vector + (int) intVecBaseGet ());
  630.     return ((FUNCPTR)(((int)*(newVector + 1) & 0xffff0000) | 
  631.  ((int)*newVector & 0x0000ffff)));
  632.     }
  633. /******************************************************************************
  634. *
  635. * intVecGet2 - get a CPU vector, gate type(int/trap), and gate selector (x86)
  636. *
  637. * This routine gets a pointer to the exception/interrupt handler attached
  638. * to a specified vector, the type of the gate, the selector of the gate.  
  639. * The vector is specified as an offset into the CPU's vector table.  
  640. * This vector table starts, by default, at address 0.
  641. * However, the vector table may be set to start at any address with
  642. * intVecBaseSet().
  643. *
  644. * RETURNS: N/A
  645. *
  646. * SEE ALSO: intVecBaseSet(), intVecGet(), intVecSet(), intVecSet2()
  647. */
  648. void intVecGet2
  649.     (
  650.     FUNCPTR * vector, /* vector offset              */
  651.     FUNCPTR * pFunction, /* address to place in vector */
  652.     int *     pIdtGate, /* IDT_TRAP_GATE or IDT_INT_GATE */
  653.     int *     pIdtSelector /* sysCsExc or sysCsInt */
  654.     )
  655.     {
  656.     FUNCPTR *newVector;
  657.     /* vector is offset by vector base address */
  658.     newVector = (FUNCPTR *) ((int) vector + (int) intVecBaseGet ());
  659.     /* get a pointer to the handler */
  660.     *pFunction = ((FUNCPTR)(((int)*(newVector + 1) & 0xffff0000) | 
  661.     ((int)*newVector & 0x0000ffff)));
  662.     /* get a gate selector */
  663.     *pIdtSelector = ((int)*newVector >> 16) & 0x0000ffff;
  664.     /* get a gate type (int/trap) */
  665.     *pIdtGate = (int)*(newVector + 1) & 0x0000ffff;
  666.     }
  667. /*******************************************************************************
  668. *
  669. * intVecTableWriteProtect - write protect exception vector table
  670. *
  671. * If the unbundled Memory Management Unit (MMU) support package (VxVMI) is
  672. * present, this routine write-protects the exception vector table to
  673. * protect it from being accidentally corrupted.
  674. * Note that other data structures contained in the page will also be
  675. * write-protected.  In the default VxWorks configuration, the exception vector
  676. * table is located at location 0 in memory.  Write-protecting this affects
  677. * the backplane anchor, boot configuration information, and potentially the
  678. * text segment (assuming the default text location of 0x1000.)  All code
  679. * that manipulates these structures has been modified to write-enable the
  680. * memory for the duration of the operation.  If you select a different
  681. * address for the exception vector table, be sure it resides in a page
  682. * separate from other writable data structures.
  683. * RETURNS: OK, or ERROR if unable to write protect memory.
  684. *
  685. * ERRNO: S_intLib_VEC_TABLE_WP_UNAVAILABLE
  686. */
  687. STATUS intVecTableWriteProtect
  688.     (
  689.     void
  690.     )
  691.     {
  692.     int pageSize;
  693.     UINT vectorPage;
  694.     if (!vmLibInfo.vmLibInstalled)
  695. {
  696. errno = S_intLib_VEC_TABLE_WP_UNAVAILABLE;
  697. return (ERROR);
  698. }
  699.     pageSize = VM_PAGE_SIZE_GET();
  700.     vectorPage = (UINT) intVecBaseGet () / pageSize * pageSize;
  701.     return (VM_STATE_SET (0, (void *) vectorPage, pageSize, 
  702.   VM_STATE_MASK_WRITABLE, VM_STATE_WRITABLE_NOT));
  703.     }
  704. /******************************************************************************
  705. *
  706. * intRegsLock - modify a REG_SET to have interrupts locked.
  707. */
  708. int intRegsLock
  709.     (
  710.     REG_SET *pRegs                      /* register set to modify */
  711.     )
  712.     {
  713.     int oldFlags = pRegs->eflags;
  714.     pRegs->eflags &= ~INT_FLAG;
  715.     return (oldFlags);
  716.     }
  717. /******************************************************************************
  718. *
  719. * intRegsUnlock - restore an REG_SET's interrupt lockout level.
  720. */
  721. void intRegsUnlock
  722.     (
  723.     REG_SET *   pRegs,                  /* register set to modify */
  724.     int         oldFlags                /* int lock level to restore */
  725.     )
  726.     {
  727.     pRegs->eflags &= ~INT_FLAG;
  728.     pRegs->eflags |= (oldFlags & INT_FLAG);
  729.     }