📄 intarchlib.c
字号:
/* intArchLib.c - I80x86 interrupt subroutine library *//* Copyright 1984-1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------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(). The vector (trap)base register can be accessed by the routines intVecBaseSet() andintVecBaseGet().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/vxmIfLibP.h"#include "private/vmLibP.h"IMPORT void intVBRSet (FUNCPTR *baseAddr);IMPORT void intEnt (); /* interrupt entrance stub */IMPORT void intExit (); /* interrupt exit stub *//* 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 suchas 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 */UINT intIdtType = 0x0000ef00; /* trap gate */USHORT excIdtSelector = 0x0018; /* no.3(4th) code descriptor */USHORT intIdtSelector = 0x0020; /* no.4(5th) code descriptor *//* 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() and intVecSet(). The address* of the handler returned by intHandlerCreate() is what actually gets put in* the interrupt vector.** RETURNS:* OK, or ERROR if the interrupt handler cannot be built.** SEE ALSO: intHandlerCreate(), intVecSet()*/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 = intHandlerCreateX86 ((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); }/********************************************************************************* 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 (4, sizeof (intConnectCode)); /* 2**4 aligned */ if (pCode != NULL) { /* copy intConnectCode into new code area */ bcopy ((char *)intConnectCode, (char *)pCode, sizeof (intConnectCode)); /* set the addresses & instructions */ *(int *)&pCode[1] = (int)intEnt - (int)&pCode[5]; for (ix = 0; ix < 10; ix++) pCode[8 + ix] = 0x90; /* no BOI so replace by NOP */ pCode[40] = 8; /* pop two parameters */ *(int *)&pCode[19] = (int)parameter; *(int *)&pCode[24] = (int)routine - (int)&pCode[28]; if (intEOI == NULL) { for (ix = 0; ix < 5; ix++) pCode[33 + ix] = 0x90; /* replace by NOP */ } else { *(int *)&pCode[34] = (int)intEOI - (int)&pCode[38]; } *(int *)&pCode[45] = (int)intExit - (int)&pCode[49]; } CACHE_TEXT_UPDATE ((void *) pCode, sizeof (intConnectCode)); return ((FUNCPTR)(int)pCode); }/********************************************************************************* intHandlerCreateX86 - 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 intHandlerCreateX86 ( 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 */ ) { FAST UCHAR *pCode; /* pointer to newly synthesized code */ FAST int ix; pCode = (UCHAR *)memalign (4, sizeof (intConnectCode)); /* 2**4 aligned */ if (pCode != NULL) { /* copy intConnectCode into new code area */ bcopy ((char *)intConnectCode, (char *)pCode, sizeof (intConnectCode)); /* set the addresses & instructions */ *(int *)&pCode[1] = (int)intEnt - (int)&pCode[5];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -