📄 ravenmpic.c
字号:
/* ravenMpic.c - Raven Interrupt Controller driver *//* Copyright 1984-1998 Wind River Systems, Inc. *//* Copyright 1996,1997,1998 Motorola, Inc., All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01v,01nov01,mil Cleaned up compiler warnings.01u,17nov98,srr Correct phantom interrupt else if test and remove semicolon.01t,24aug98,cjtc windview 2.0 event logging is now single step and handled in the interrupt controller driver. Fixes a problem with out of sequence timestamps in the event log for this architechture. Method of initiating event logging is now via a macro (SPR 21868)01s,20aug98,scg SPR 21961: fix sysIbcPhantomInt to correctly handle phantom interrupts on slave 8259. Remove extra semicolons in sysIbcIntHandler()01q,21jul98,scb #define name cleanup - removal of board name defines.01p,07jul98,scb Initial support for MCPN750.01o,17apr98,pr added windview 20 support01n,14apr98,ms_ merged Motorola mv2700 support01m,11apr98,scb HW rework makes ISA IRQ's 14 & 15 edge (note level) sensitive.01l,22apr98,scb added phantom IBC int handling for IRQ7 and IRQ1501k,13jan98,srr updated copyright dates to 1998.01j,11dec97,srr Updated comment in sysIbcInit to show support for VIA chip.01i,20jul97,srr send end of interrupt acknowledge to master IBC first.01h,23oct97,dat, removed IACK loop from sysMpicIntHandler() (SPR 9389). mas01g,20jul97,dat implemented dave's second revision + some code cleanup01f,11jun97,dmw MPIC handler cleanup. 01e,06may97,dat added IBC updates from sl82565 controller.01d,30apr97,dat added WindView instrumentation SPR 843401c,29apr97,dat Fixed Motorola MR #62, moved MPIC_EOI01b,23apr97,mas merged with sl82565IntrCtl.c (SPR 8170).01a,11nov96,rhk created by Motorola.*//*DESCRIPTIONThis module implements the Raven Mpic and the Winbond W83C553 PCI-ISA Bridge(PIB) drivers. (The W83C553 PIB was formerly known as the Motorola sl82565 ISABridge Controller (IBC).These merged drivers provide support for initializing their respective devicesand handling interrupts from them.*//* includes */#include "ravenMpic.h"#include "private/eventP.h"/* defines */#define MPIC_EOI sysPciWrite32(MPIC_ADDR(MPIC_CPU0_EOI_REG),0)#define IBC_INT_PENDING 0x80/* globals */IMPORT STATUS (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);IMPORT int (*_func_intEnableRtn) (int);IMPORT int (*_func_intDisableRtn) (int);IMPORT void sysOutByte (ULONG, UCHAR);IMPORT UCHAR sysInByte (ULONG);IMPORT void sysPciRead32 (UINT32, UINT32 *);IMPORT void sysPciWrite32 (UINT32, UINT32);IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);void sysIbcIntEnable (int);void sysIbcIntDisable (int);void sysIbcIntHandler (void);void sysMpicIntHandler (void);IMPORT UINT sysVectorIRQ0; /* vector for IRQ0 */INT_HANDLER_DESC * sysIntTbl [256]; /* system interrupt table */int tpr;/* forward declarations */LOCAL int getMpicVecOffset (int);LOCAL STATUS sysMpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine, int parameter);LOCAL int sysMpicIntEnable (int);LOCAL int sysMpicIntDisable (int);LOCAL void sysIbcMpicConnect (void);LOCAL BOOL sysIbcPhantomInt (UCHAR *intNum, int lvl7Int, int lvl15Int);LOCAL void sysIbcEndOfInt (int);LOCAL void sysIbcIntLevelSet (int);/* Mask values are the currently disabled sources */LOCAL UINT8 sysPicMask1 = 0xfb; /* all levels disabled */LOCAL UINT8 sysPicMask2 = 0xff;/* Level values are the interrupt level masks */LOCAL UINT8 sysPicLevel1;LOCAL UINT8 sysPicLevel2;LOCAL UINT8 sysPicLevelCur; /* current priority level, 0 to 16 *//* level values by real priority */LOCAL UCHAR sysPicPriMask1[17] = {0xFB,0xFA,0xF8,0xF8,0xF0,0xE0,0xC0,0x80, 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x0};LOCAL UCHAR sysPicPriMask2[17] = {0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0};/* Hardware access methods */#ifndef IBC_BYTE_OUT# define IBC_BYTE_OUT(reg,data) \ (sysOutByte (reg,data))#endif#ifndef IBC_BYTE_IN# define IBC_BYTE_IN(reg,pData) \ (*pData = sysInByte(reg))#endif#ifndef CPU_INT_LOCK# define CPU_INT_LOCK(x) \ (*x = intLock ())#endif#ifndef CPU_INT_UNLOCK# define CPU_INT_UNLOCK(data) \ (intUnlock (data))#endif/********************************************************************************* sysMpicInit - initialize the MPIC in the Raven** This function initializes the Multi-Processor Interrupt Controller (MPIC)* contained in the Raven chip.** It first initializes the system vector table, connects the MPIC interrupt* handler to the PPC external interrupt and attaches the local MPIC routines* for interrupt connecting, enabling and disabling to the corresponding system* routine pointers.** It then initializes the MPIC registers, clears any pending MPIC interrupts,* enables interrupt handling by the MPIC and enables external ISA interrupts* (from the W83C553).** RETURNS: OK always*/STATUS sysMpicInit (void) { int i; UINT32 timerReg; UINT32 ipiReg; UINT32 destReg; LOCAL_INT_DATA init; /* Initialize the interrupt table */ for (i = 0; i < 256; i++) sysIntTbl[i] = NULL; /* Connect the interrupt demultiplexer to the PowerPC external interrupt */ excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysMpicIntHandler); /* * Set up the BSP specific routines * Attach the local routines to the vxWorks system calls */ _func_intConnectRtn = sysMpicIntConnect; _func_intEnableRtn = sysMpicIntEnable; _func_intDisableRtn = sysMpicIntDisable; /* Initialize the MPIC */ /* generate a PCI IACK to clear any pending interrupts */ sysPciRead32( MPIC_ADDR(MPIC_CPU0_IACK_REG), (UINT32 *) &init.temp ); /* inhibit the timer and IPI regs. and clear the counter regs. */ timerReg = MPIC_TIMER0_BASE_CT_REG; ipiReg = MPIC_IPI0_VEC_PRI_REG; for (i=0; i<4; i++) { sysPciWrite32( MPIC_ADDR(ipiReg), IPI_INHIBIT ); ipiReg += REG_OFFSET; sysPciWrite32( MPIC_ADDR(timerReg), TIMER_INHIBIT ); timerReg += REG_OFFSET; sysPciWrite32( MPIC_ADDR(timerReg), TIMER_INHIBIT ); timerReg += (REG_OFFSET * 3); } /* setup the external source vector/priority registers */ sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC0_VEC_PRI_REG), INIT_EXT_SRC0 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC1_VEC_PRI_REG), INIT_EXT_SRC1 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC2_VEC_PRI_REG), INIT_EXT_SRC2 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC3_VEC_PRI_REG), INIT_EXT_SRC3 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC4_VEC_PRI_REG), INIT_EXT_SRC4 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC5_VEC_PRI_REG), INIT_EXT_SRC5 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC6_VEC_PRI_REG), INIT_EXT_SRC6 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC7_VEC_PRI_REG), INIT_EXT_SRC7 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC8_VEC_PRI_REG), INIT_EXT_SRC8 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC9_VEC_PRI_REG), INIT_EXT_SRC9 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC10_VEC_PRI_REG), INIT_EXT_SRC10 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC11_VEC_PRI_REG), INIT_EXT_SRC11 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC12_VEC_PRI_REG), INIT_EXT_SRC12 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC13_VEC_PRI_REG), INIT_EXT_SRC13 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC14_VEC_PRI_REG), INIT_EXT_SRC14 ); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC15_VEC_PRI_REG), INIT_EXT_SRC15 ); destReg = MPIC_EXT_SRC0_DEST_REG; for (i=0; i<=15; i++) { sysPciWrite32( MPIC_ADDR(destReg), DESTINATION_CPU0 ); destReg += (REG_OFFSET*2); } /* setup the Ext source 0 reg (8259 input) for normal operation */ sysPciRead32( MPIC_ADDR(MPIC_EXT_SRC0_VEC_PRI_REG), &init.regVal ); init.regVal |= PIB_INT_VEC; init.regVal &= (~INT_MASK_BIT); sysPciWrite32( MPIC_ADDR(MPIC_EXT_SRC0_VEC_PRI_REG), init.regVal ); /* enable interrupts for this processor */ sysPciWrite32( MPIC_ADDR(MPIC_CPU0_CUR_TASK_PRI_REG), 1 ); /* setup the MPIC to process the 8259 interrupts ( mixed mode ) */ sysPciWrite32( MPIC_ADDR(MPIC_GLOBAL_CONFIG_REG), SET_MIXED_MODE ); return (OK); }/******************************************************************************** sysMpicIntConnect - connect an interrupt handler to the system vector table** This function connects an interrupt handler to the system vector table.** RETURNS: OK/ERROR.*/ LOCAL STATUS sysMpicIntConnect ( VOIDFUNCPTR * vector, /* interrupt vector to attach */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ) { INT_HANDLER_DESC * newHandler; INT_HANDLER_DESC * currHandler; LOCAL_INT_DATA connect; static BOOL firstTime = TRUE; if (((int)vector < 0) || ((int)vector > 0xff)) /* Out of Range? */ return (ERROR); if (firstTime) { /* connect the PIB to MPIC, before any other connections */ firstTime = FALSE; sysIbcMpicConnect (); /* calls this rtn, recursively */ } /* create a new interrupt handler */ if ((newHandler = (INT_HANDLER_DESC *)calloc (1, sizeof (INT_HANDLER_DESC))) == NULL) return (ERROR); /* initialize the new handler */ newHandler->vec = routine; newHandler->arg = parameter; newHandler->next = NULL; /* install the handler in the system interrupt table */ if (sysIntTbl[(int) vector] == NULL) sysIntTbl [(int ) vector] = newHandler; /* single int. handler case */ else { currHandler = sysIntTbl[(int) vector]; /* multiple int. handler case */ while (currHandler->next != NULL) { currHandler = currHandler->next; } currHandler->next = newHandler; } /* * if the connect is for an MPIC interrupt, * then store the vector into the appropriate MPIC vector register */ connect.regAddr = getMpicVecOffset( (int)vector ); if ( connect.regAddr > 0 ) { /* read the vector register */ sysPciRead32( MPIC_ADDR(connect.regAddr), &connect.regVal ); /* store the interrupt vector number */ connect.regVal |= (int)vector; /* write the contents of the vector register back */ sysPciWrite32( MPIC_ADDR(connect.regAddr), connect.regVal ); } return (OK); } /********************************************************************************* sysMpicIntEnable - enable an Mpic interrupt level** This routine enables a specified Mpic interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/ LOCAL int sysMpicIntEnable ( int intLevel /* interrupt level to enable */ ) { LOCAL_INT_DATA enable; /* * if the int. level is not for ISA or MPIC, then it is not supported. * If not supported, just return. */ if ((intLevel < 0) || (intLevel > ERR_INTERRUPT_BASE)) return (ERROR); /* If ISA interrupt level,call the IBC driver enable routine, */ if ( intLevel < EXT_INTERRUPT_BASE ) sysIbcIntEnable( intLevel ); enable.regAddr = getMpicVecOffset( intLevel ); if ( enable.regAddr > 0 ) { /* read the vector register */ sysPciRead32( MPIC_ADDR(enable.regAddr), &enable.regVal ); /* enable the interrupt */ enable.regVal &= (~INT_MASK_BIT); /* write the contents of the vector register back */ sysPciWrite32( MPIC_ADDR(enable.regAddr), enable.regVal ); } return (OK); }/********************************************************************************* sysMpicIntDisable - disable an Mpic interrupt level** This routine disables a specified Mpic interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/ LOCAL int sysMpicIntDisable ( int intLevel /* interrupt level to disable */ ) { LOCAL_INT_DATA disable; /* * if the int. level is not for ISA or MPIC, then it is not supported. * If not supported, just return. */ if ((intLevel < 0) || (intLevel > ERR_INTERRUPT_BASE)) return (ERROR); /* If ISA interrupt level, call the IBC driver disable routine, */ if ( intLevel < EXT_INTERRUPT_BASE ) sysIbcIntDisable( intLevel ); /* else, it is an MPIC interrupt level */ else { /* get the vector reg. offset value */ disable.regAddr = getMpicVecOffset( intLevel ); if ( disable.regAddr > 0 ) { /* read the vector register */ sysPciRead32( MPIC_ADDR(disable.regAddr), &disable.regVal ); /* disable the interrupt */ disable.regVal |= INT_MASK_BIT; /* write the contents of the vector register back */ sysPciWrite32( MPIC_ADDR(disable.regAddr), disable.regVal ); } } return (OK); }/******************************************************************************** sysMpicIntHandler - handle an interrupt received at the Mpic* * This routine will process interrupts received from PCI or ISA devices as* these interrupts arrive via the MPIC. This routine supports MPIC interrupt* nesting.** RETURNS: N/A*/void sysMpicIntHandler (void) { INT_HANDLER_DESC * currHandler; UINT32 vecNum; int dontCare; /* get the vector from the MPIC IACK reg. */ sysPciRead32 (MPIC_ADDR (MPIC_CPU0_IACK_REG), &vecNum); vecNum &= VECTOR_MASK; /* Ignore spurious interrupts */ if (vecNum == 0xFF) { logMsg ("MPIC Spurious Interrupt!\n", 0,0,0,0,0,0); return; } /* * Allow maskable interrupts to the CPU. MPIC will hold off * lower and equal interrupts until MPIC_EOI is performed. */ CPU_INT_UNLOCK(_PPC_MSR_EE);#ifdef INCLUDE_WINDVIEW WV_EVT_INT_ENT(vecNum)#endif /* call the necessary interrupt handlers */ if ((currHandler = sysIntTbl [vecNum]) == NULL) { logMsg ("uninitialized MPIC interrupt %d\r\n", vecNum, 0,0,0,0,0); } else { /* Call EACH respective chained interrupt handler */ while (currHandler != NULL) { currHandler->vec (currHandler->arg); currHandler = currHandler->next; } } /* issue an end-of-interrupt to the MPIC */ MPIC_EOI; CPU_INT_LOCK (&dontCare); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -