📄 hawkmpic.c
字号:
/* hawkMpic.c - Hawk Interrupt Controller driver *//* Copyright 1984-2002 Wind River Systems, Inc. *//* Copyright 1996,1997,1998 Motorola, Inc., All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01c,16apr02,dat Removing warnings for T2.2 release01b,16jul99,rhv Changing to new Windview support.01a,15dec98,mdp Written (from version 01k of mv2304/ravenMpic.c*//*DESCRIPTIONThis module implements the Hawk 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 "hawkMpic.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 UCHAR 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 Hawk** This function initializes the Multi-Processor Interrupt Controller (MPIC)* contained in the Hawk 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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -