?? intarchlib.c
字號:
/* intArchLib.c - I80x86 interrupt subroutine library *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01p,20nov01,hdn doc clean up for 5.501o,09nov01,hdn replaced magic numbers with intConnectCode offset macros01n,29aug01,hdn got rid of VXM stuff. added intVecGet2() correspond to intVecSet2(). replaced {exc,int}IdtSelector with sysCs{Exc,Int}. added document for intHandlerCreateI86() (spr 30292)01m,14dec00,pai Added stub routines for intEnable() and intDisable() (SPR #63046).01l,09feb99,wsl add comment to document ERRNO value01k,29may98,hdn added intHandlerCreateX86(), modified intConnectCode[] to solve EOI issue and sprious interrupt issue. removed intEOI. added intEoiGet.01j,13apr98,hdn changed malloc to memalign in intHandlerCreate().01i,14jan98,dbt added dbgLib.h include01h,23aug95,ms removed taskSafe/Unsafe calls from intVecSet().01g,15jun95,ms added intRegsLock, intRegsUnlock01f,14jun95,hdn added intVecSetEnt and intVecSetExit. renamed pSysEndOfInt to intEOI.01e,26jan95,rhp doc tweaks01d,29jul93,hdn added intVecTableWriteProtect(). - intVecSet checks taskIdCurrent before TASK_{SAFE,UNSAFE}. - deleted mention of intContext() and intCount(). - added vxmIfVecxxx callout for monitor support.01c,03jun93,hdn updated to 5.1 - changed functions to ansi style - changed includes to have absolute path from h/ - fixed #else and #endif - changed VOID to void - changed copyright notice01b,15oct92,hdn supported nested interrupt.01a,28feb92,hdn written based on TRON, 68k version.*//*DESCRIPTIONThis library provides architecture-dependent routines to manipulateand connect to hardware interrupts. Any C language routine can beconnected to any interrupt by calling intConnect(). Vectors can beaccessed directly by intVecSet() and intVecGet(), or by intVecSet2()and intVecGet2(). The vector (trap) base register can be accessed by the routines intVecBaseSet() and intVecBaseGet().Tasks can lock and unlock interrupts by calling intLock() and intUnlock().The lock-out level can be set and reported by intLockLevelSet() andintLockLevelGet().WARNINGDo not call VxWorks system routines with interrupts locked.Violating this rule may re-enable interrupts unpredictably.INTERRUPT VECTORS AND NUMBERSMost of the routines in this library take an interrupt vector as aparameter, which is the byte offset into the vector table. Macros areprovided to convert between interrupt vectors and interrupt numbers:.iP IVEC_TO_INUM(intVector) 10changes a vector to a number..iP INUM_TO_IVEC(intNumber)turns a number into a vector..iP TRAPNUM_TO_IVEC(trapNumber)converts a trap number to a vector.EXAMPLETo switch between one of several routines for a particular interrupt,the following code fragment is one alternative:.CS vector = INUM_TO_IVEC(some_int_vec_num); oldfunc = intVecGet (vector); newfunc = intHandlerCreate (routine, parameter); intVecSet (vector, newfunc); ... intVecSet (vector, oldfunc); /@ use original routine @/ ... intVecSet (vector, newfunc); /@ reconnect new routine @/.CEINCLUDE FILE: iv.hSEE ALSO: intLib, intALib*//* LINTLIBRARY */#include "vxWorks.h"#include "cacheLib.h"#include "errnoLib.h"#include "intLib.h"#include "memLib.h"#include "sysLib.h"#include "taskLib.h"#include "string.h"#include "stdlib.h"#include "dbgLib.h"#include "private/vmLibP.h"/* imports */IMPORT void intVBRSet (FUNCPTR *baseAddr);IMPORT void intEnt (); /* interrupt entrance stub */IMPORT void intExit (); /* interrupt exit stub */IMPORT int sysCsExc;IMPORT int sysCsInt;/* globals *//* The routine intLock(), found in intALib.s uses intLockMask to construct a * new EFLAGS with the correct interrupt lock-out level. The difficulty is * intLock() may be called from either interrupt level, or task level, so * simply reserving a EFLAGS such as 0x80000000 does not work because such a * EFLAGS would assume task-level code. */UINT intLockMask = 0x0; /* interrupt lock mask - level 0 */VOIDFUNCPTR intVecSetEnt = NULL; /* entry hook for intVecSet() */VOIDFUNCPTR intVecSetExit = NULL; /* exit hook for intVecSet() */VOIDFUNCPTR intEOI = NULL; /* pointer to EOI routine in BSP */VOIDFUNCPTR intEoiGet = NULL; /* pointer to EoiGet routine in BSP */LOCAL int dummy (void) { return ERROR; } /* dummy, returns ERROR */FUNCPTR sysIntLvlEnableRtn = dummy; /* enable a single level */FUNCPTR sysIntLvlDisableRtn = dummy; /* disable a single level *//* locals */LOCAL FUNCPTR * intVecBase = 0; /* vector base address */LOCAL UCHAR intConnectCode [] = /* intConnect stub */ {/* * 00 e8 kk kk kk kk call _intEnt * tell kernel * 05 50 pushl %eax * save regs * 06 52 pushl %edx * 07 51 pushl %ecx * 08 68 pp pp pp pp pushl $_parameterBoi * push BOI param * 13 e8 rr rr rr rr call _routineBoi * call BOI routine * 18 68 pp pp pp pp pushl $_parameter * push param * 23 e8 rr rr rr rr call _routine * call C routine * 28 68 pp pp pp pp pushl $_parameterEoi * push EOI param * 33 e8 rr rr rr rr call _routineEoi * call EOI routine * 38 83 c4 0c addl $12, %esp * pop param * 41 59 popl %ecx * restore regs * 42 5a popl %edx * 43 58 popl %eax * 44 e9 kk kk kk kk jmp _intExit * exit via kernel */ 0xe8, 0x00, 0x00, 0x00, 0x00, /* _intEnt filled in at runtime */ 0x50, 0x52, 0x51, 0x68, 0x00, 0x00, 0x00, 0x00, /* BOI parameter filled in at runtime */ 0xe8, 0x00, 0x00, 0x00, 0x00, /* BOI routine filled in at runtime */ 0x68, 0x00, 0x00, 0x00, 0x00, /* parameter filled in at runtime */ 0xe8, 0x00, 0x00, 0x00, 0x00, /* routine filled in at runtime */ 0x68, 0x00, 0x00, 0x00, 0x00, /* EOI parameter filled in at runtime */ 0xe8, 0x00, 0x00, 0x00, 0x00, /* EOI routine filled in at runtime */ 0x83, 0xc4, 0x0c, /* pop parameters */ 0x59, 0x5a, 0x58, 0xe9, 0x00, 0x00, 0x00, 0x00, /* _intExit filled in at runtime */ };/* forward declarations *//********************************************************************************* intConnect - connect a C routine to a hardware interrupt** This routine connects a specified C routine to a specified interrupt* vector. The address of <routine> is stored at <vector> so that <routine>* is called with <parameter> when the interrupt occurs. The routine is* invoked in supervisor mode at interrupt level. A proper C environment* is established, the necessary registers saved, and the stack set up.** The routine can be any normal C code, except that it must not invoke* certain operating system functions that may block or perform I/O* operations.** This routine simply calls intHandlerCreate()/intHandlerCreateI86() and * intVecSet(). The address of the handler returned by intHandlerCreate()/* intHandlerCreateI86() is what actually gets put in the interrupt vector.** RETURNS:* OK, or ERROR if the interrupt handler cannot be built.** SEE ALSO: intHandlerCreate(), intVecSet(), intHandlerCreateI86()*/STATUS intConnect ( VOIDFUNCPTR *vector, /* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ) { FUNCPTR intDrvRtn; VOIDFUNCPTR routineBoi; VOIDFUNCPTR routineEoi; int parameterBoi; int parameterEoi; if (intEoiGet == NULL) { intDrvRtn = intHandlerCreate ((FUNCPTR)routine, parameter); } else { (* intEoiGet) (vector, &routineBoi, ¶meterBoi, &routineEoi, ¶meterEoi); intDrvRtn = intHandlerCreateI86 ((FUNCPTR)routine, parameter, (FUNCPTR)routineBoi, parameterBoi, (FUNCPTR)routineEoi, parameterEoi); } if (intDrvRtn == NULL) return (ERROR); /* make vector point to synthesized code */ intVecSet ((FUNCPTR *)vector, (FUNCPTR)intDrvRtn); return (OK); }/********************************************************************************* intEnable - enable a specific interrupt level** Enable a specific interrupt level. For each interrupt level to be used,* there must be a call to this routine before it will be* allowed to interrupt.** RETURNS:* OK or ERROR for invalid arguments.*/int intEnable ( int level /* level to be enabled */ ) { return (*sysIntLvlEnableRtn) (level); }/********************************************************************************* intDisable - disable a particular interrupt level** This call disables a particular interrupt level, regardless of the current* interrupt mask level.** RETURNS:* OK or ERROR for invalid arguments.*/int intDisable ( int level /* level to be disabled */ ) { return (*sysIntLvlDisableRtn) (level); }/********************************************************************************* intHandlerCreate - construct an interrupt handler for a C routine** This routine builds an interrupt handler around a specified C routine.* This interrupt handler is then suitable for connecting to a specific* vector address with intVecSet(). The interrupt handler is invoked in* supervisor mode at interrupt level. A proper C environment is* established, the necessary registers saved, and the stack set up.* * The routine can be any normal C code, except that it must not invoke* certain operating system functions that may block or perform I/O* operations.** IMPLEMENTATION:* This routine builds an interrupt handler of the following form in* allocated memory:** .CS* 00 e8 kk kk kk kk call _intEnt * tell kernel* 05 50 pushl %eax * save regs* 06 52 pushl %edx* 07 51 pushl %ecx* 08 68 pp pp pp pp pushl $_parameterBoi * push BOI param* 13 e8 rr rr rr rr call _routineBoi * call BOI routine* 18 68 pp pp pp pp pushl $_parameter * push param* 23 e8 rr rr rr rr call _routine * call C routine* 28 68 pp pp pp pp pushl $_parameterEoi * push EOI param* 33 e8 rr rr rr rr call _routineEoi * call EOI routine* 38 83 c4 0c addl $12, %esp * pop param* 41 59 popl %ecx * restore regs* 42 5a popl %edx* 43 58 popl %eax* 44 e9 kk kk kk kk jmp _intExit * exit via kernel* .CE* * RETURNS: A pointer to the new interrupt handler, or NULL if memory* is insufficient.*/FUNCPTR intHandlerCreate ( FUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ) { FAST UCHAR *pCode; /* pointer to newly synthesized code */ FAST int ix; pCode = (UCHAR *)memalign (_CACHE_ALIGN_SIZE, sizeof (intConnectCode)); if (pCode != NULL) { /* copy intConnectCode into new code area */ bcopy ((char *)intConnectCode, (char *)pCode, sizeof (intConnectCode)); /* set the addresses & instructions */ *(int *)&pCode[ICC_INT_ENT] = (int)intEnt - (int)&pCode[ICC_INT_ENT + 4]; for (ix = 0; ix < 10; ix++) pCode[ICC_BOI_PUSH + ix] = 0x90; /* no BOI so replace by NOP */ pCode[ICC_ADD_N] = 8; /* pop two parameters */ *(int *)&pCode[ICC_INT_PARAM] = (int)parameter; *(int *)&pCode[ICC_INT_ROUTN] = (int)routine - (int)&pCode[ICC_INT_ROUTN + 4]; if (intEOI == NULL) { for (ix = 0; ix < 5; ix++) pCode[ICC_EOI_CALL + ix] = 0x90; /* replace by NOP */ } else { *(int *)&pCode[ICC_EOI_ROUTN] = (int)intEOI - (int)&pCode[ICC_EOI_ROUTN + 4]; } *(int *)&pCode[ICC_INT_EXIT] = (int)intExit - (int)&pCode[ICC_INT_EXIT + 4]; } CACHE_TEXT_UPDATE ((void *) pCode, sizeof (intConnectCode)); return ((FUNCPTR)(int)pCode); }/********************************************************************************* intHandlerCreateI86 - construct an interrupt handler for a C routine** This routine builds an interrupt handler around a specified C routine.* This interrupt handler is then suitable for connecting to a specific* vector address with intVecSet(). The interrupt handler is invoked in* supervisor mode at interrupt level. A proper C environment is* established, the necessary registers saved, and the stack set up.* * The routine can be any normal C code, except that it must not invoke* certain operating system functions that may block or perform I/O* operations.** IMPLEMENTATION:* This routine builds an interrupt handler of the following form in* allocated memory:** .CS* 00 e8 kk kk kk kk call _intEnt * tell kernel* 05 50 pushl %eax * save regs* 06 52 pushl %edx* 07 51 pushl %ecx* 08 68 pp pp pp pp pushl $_parameterBoi * push BOI param* 13 e8 rr rr rr rr call _routineBoi * call BOI routine* 18 68 pp pp pp pp pushl $_parameter * push param* 23 e8 rr rr rr rr call _routine * call C routine* 28 68 pp pp pp pp pushl $_parameterEoi * push EOI param* 33 e8 rr rr rr rr call _routineEoi * call EOI routine* 38 83 c4 0c addl $12, %esp * pop param* 41 59 popl %ecx * restore regs* 42 5a popl %edx* 43 58 popl %eax* 44 e9 kk kk kk kk jmp _intExit * exit via kernel* .CE* * Third and fourth parameter of intHandlerCreateI86() are the BOI routine * address and its parameter that are inserted into the code as "routineBoi" * and "parameterBoi". * Fifth and sixth parameter of intHandlerCreateI86() are the EOI routine * address and its parameter that are inserted into the code as "routineEoi" * and "parameterEoi". * The BOI routine detects if this interrupt is stray/spurious/phantom by* interrogating the interrupt controller, and returns from the interrupt* if it is. The EOI routine issues End Of Interrupt signal to the * interrupt controller, if it is required by the controller. * Each interrupt controller has its own BOI and EOI routine. They are* located in the BSP, and their address and parameter are taken by the* intEoiGet function (set to sysIntEoiGet() in the BSP).* The Tornado 2, and later, BSPs should use the BOI and EOI mechanism with* intEoiGet function pointer.** To keep the Tornado 101 BSP backward compatible, the function pointer * intEOI is not removed. If intEoiGet is NULL, it should be set to the* sysIntEoiGet() routine in the BSP, intHandlerCreate() and the intEOI * function pointer (set to sysIntEOI() in the Tornado 101 BSP) is used.* * RETURNS: A pointer to the new interrupt handler, or NULL if memory* is insufficient.*/FUNCPTR intHandlerCreateI86 ( FUNCPTR routine, /* routine to be called */ int parameter, /* parameter to be passed to routine */ FUNCPTR routineBoi, /* BOI routine to be called */ int parameterBoi, /* parameter to be passed to routineBoi */ FUNCPTR routineEoi, /* EOI routine to be called */ int parameterEoi /* parameter to be passed to routineEoi */ )
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -