?? m5200intr.c
字號:
/* m5200Intr.c - Motorola MPC5200 interrupt driver *//* Copyright 1989-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01d,11nov03,pdr added support for main interrupt.01c,24sep03,pdr added support for Slice Timer 1. pkr01b,17sep03,pdr changed registers method access.01a,03jul03,pkr derived from ppc860Intr.c*//*DESCRIPTIONThis module provides the interrupt handler libary for the MPC5200. *//* includes */#include "intLib.h"#include "dbgLib.h"#include "iv.h"#include "drv/intrCtl/m5200Intr.h"#include "rebootLib.h"#include "fioLib.h"#ifdef INCLUDE_WINDVIEW#include "private/funcBindP.h"#include "private/eventP.h"#include "wdb/wdbDbgLib.h"#endif /* INCLUDE_WINDVIEW */FUNCPTR _func_sdmaIntEnableRtn = NULL;FUNCPTR _func_sdmaIntDisableRtn = NULL;FUNCPTR _func_sdmaIntSetLevelRtn = NULL;void m5200SdmaIntTrigger(int intNum);/* local */LOCAL INTR_HANDLER intrVecTable[NUM_VEC_MAX]; /* Intr vector table *//* all peripheral sources at level i have their corresponding PIMR bit set in lvlPIMR[i]. mskPIMR[i] is the union of all lvlPIMR[j] with j > i */ LOCAL UINT32 lvlPIMR[16];LOCAL UINT32 mskPIMR[16];/* forward declarations */LOCAL void m5200ExtIntrDeMux (void);LOCAL void m5200SysMngIntrDeMux (void);LOCAL STATUS m5200IntConnect (VOIDFUNCPTR *, VOIDFUNCPTR, int);LOCAL int m5200IntEnable (int);LOCAL int m5200IntDisable (int);LOCAL void m5200MachCheckHandler(ESFPPC *pEsf);LOCAL void m5200ExcInfoShow (EXC_INFO *pExcInfo, BOOL doBell);LOCAL VOIDFUNCPTR org_func_excInfoShow = NULL;#if USE_CRITICAL_INTERRUPT#define _EXC_OFF_CRIT _EXC_OFF_RES1LOCAL void m5200CriticalIntrDeMux (int);#endif/********************************************************************************* m5200IntrInit - initialize the interrupt manager for the PowerPC 800 series** This routine connects the default demultiplexers, m5200IntrDeMux() and * m5200CpmIntrDeMux, to the external interrupt vector and associates all * interrupt sources with the default interrupt handler. This routine is* called by sysHwInit() in sysLib.c.** NOTE: All interrupt from the SIU and CPM unit are enabled, CICR is setup so* that SCC1 has the highest relative interrupt priority, through SCC4 with the* lowest.** RETURN : OK or ERROR if the SUI interrupt level to connect the CPM * interrupt contoller is wrong.*/STATUS m5200IntrInit ( void ) { VOIDFUNCPTR defaultVec; /* INTR3 default vector */ int vector; int level; /* Get the default vector connected to the Machine Check exception */ defaultVec = (VOIDFUNCPTR) excVecGet ((FUNCPTR *) _EXC_OFF_MACH); /* Connect new machine check handler */ excConnect ((VOIDFUNCPTR *) _EXC_OFF_MACH, m5200MachCheckHandler); /* Get the default vector connected to the External Interrupt (0x500) */ defaultVec = (VOIDFUNCPTR) excVecGet ((FUNCPTR *) _EXC_OFF_INTR); /* Connect the interrupt demultiplexer to External Interrupt (0x500) */ excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, m5200ExtIntrDeMux); /* Get the default vector connected to the System Mng Interrupt (0x1400) */ defaultVec = (VOIDFUNCPTR) excVecGet ((FUNCPTR *) _EXC_OFF_SYS_MNG); /* Connect the interrupt demultiplexer to System Mng Interrupt (0x1400) */ excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_SYS_MNG, m5200SysMngIntrDeMux);#if USE_CRITICAL_INTERRUPT /* Get the default vector connected to the Critical Interrupt (0xA00) */ defaultVec = (VOIDFUNCPTR) excVecGet ((FUNCPTR *) _EXC_OFF_CRIT); /* Connect the interrupt demultiplexer to Critical Interrupt (0xA00) */ excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_CRIT, m5200CriticalIntrDeMux);#endif /* Install `system' intConnect routine */ if (_func_intConnectRtn == NULL) _func_intConnectRtn = m5200IntConnect; if (_func_intEnableRtn == NULL) _func_intEnableRtn = m5200IntEnable; if (_func_intDisableRtn == NULL) _func_intDisableRtn = m5200IntDisable; /* Set all vectors to default handler */ for (vector = 0; vector < NUM_VEC_MAX; vector++) intConnect (INUM_TO_IVEC(vector), defaultVec, 0); /* initially we have all masked and level is all 0 */ lvlPIMR[0] = 0xFFFFFFFF; for(level=1; level < 15; level++) lvlPIMR[level] = 0; mskPIMR[0] = 0x0; for(level=1; level < 15; level++) mskPIMR[level] = 0xFFFFFFFF; /* Init SIU */ *ICTL_PIMR = 0xFFFFFFFF; /* mask all peripheral interrupts */ ICTL_PPR[0] = 0x0; /* peripherals prio 0 */ ICTL_PPR[1] = 0x0; /* peripherals prio 0 */ ICTL_PPR[2] = 0x0; /* peripherals prio 0 */ /* clear and disable all IRQ's */ *ICTL_EEETR = ICTL_EEETR_ECLR0_MASK | ICTL_EEETR_ECLR1_MASK | ICTL_EEETR_ECLR2_MASK | ICTL_EEETR_ECLR3_MASK; *ICTL_EEETR |= ICTL_EEETR_MEE;#if !USE_CRITICAL_INTERRUPT *ICTL_EEETR |= ICTL_EEETR_CEb; /* set CEb */#endif *ICTL_CPMIMR = 0x0001EFFF; /* mask all main interrupts but LO */ ICTL_MIPR[0] = 0x00070000; /* main ints prio 0, LO to prio 7 */ ICTL_MIPR[1] = 0x0; /* main ints prio 0 */ /* make sure no critical interrupt is pending */ /* Reset Slice Timer 0 */ *SLT0_CTRL = 0; /* Reset Slice Timer 0 Status Bit */ *SLT0_STATUS = SLT_STATUS_RESET; /* Setup XLB */ /* addresss and data timeout */ *XLB_CR |= XLB_CR_DT_ENABLED | XLB_CR_AT_ENABLED; *XLB_SR = XLB_SR_CLEAR_ALL; *XLB_IER = 0; *XLB_ATTOR = XLB_ADDR_TO; *XLB_DTTOR = XLB_DATA_TO; return (OK); }/********************************************************************************* m5200IntConnect - connect a routine to an interrupt ** This routine connects any C or assembly routine to one of the multiple * sources of interrupts.** The connected 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.** <vector> types are defined in h/drv/intrClt/m5200Intr.h.** RETURNS: OK, or ERROR if <vector> is unknown.** SEE ALSO: m5200Intr.h*/LOCAL STATUS m5200IntConnect ( VOIDFUNCPTR * vector, /* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ) { int inum = IVEC_TO_INUM(vector); /* test the vector */ if (inum >= NUM_VEC_MAX) return (ERROR); intrVecTable[IVEC_TO_INUM(vector)].vec = routine; intrVecTable[IVEC_TO_INUM(vector)].arg = parameter; m5200IntrSetLevel (inum, INTR_LEVEL_DEFAULT); return (OK); }void m5200SdmaIntTrigger(int intNum){ if (intNum < INUM_SDMA_FIRST || intNum > INUM_SDMA_LAST) return; /* make sure other sdma interrupts can be handled while this on is served */ /* TBD */ /* EE is already unlocked but SDMA int level is masked */ intrVecTable[intNum].vec (intrVecTable[intNum].arg);}/********************************************************************************* m5200ExtIntrDeMux - SIU interrupt demultiplexer ** This routine must be bound to external interrupt exception (vector 0x500). * It is used to call the appropriate handler with its argument when an* interrupt occurs. ** The interrupts are prioritized in the following order:** NOTE: when this function is called the interrupts are still locked. It's* this function responsability to unlock the interrupt.** RETURNS: N/A*/LOCAL void m5200ExtIntrDeMux (void) { UINT32 isr; UINT32 isr_PSe; UINT32 isr_MSe;#if !USE_CRITICAL_INTERRUPT UINT32 isr_CSe; UINT32 isr_CSe_Nr;#endif VOIDFUNCPTR *vector; UINT32 intMask; isr = *ICTL_ISR; /* get interrupt status */#if !USE_CRITICAL_INTERRUPT /* check for critical interrupt */ if ((isr_CSe = (isr & ICTL_ISR_CSe_MASK)) != 0) { isr_CSe_Nr = isr_CSe & ICTL_ISR_CSe_MASK_NR; isr_CSe_Nr >>= ICTL_ISR_CSe_SHIFT; vector = INUM_TO_IVEC(INUM_CRITICAL_FIRST + isr_CSe_Nr); } else#endif /* check for peripheral interrupt BEFORE main interrupt */ if ((isr_PSe = (isr & ICTL_ISR_PSe_MASK)) != 0) { isr_PSe &= ICTL_ISR_PSe_MASK_NR; isr_PSe >>= ICTL_ISR_PSe_SHIFT; vector = INUM_TO_IVEC(INUM_PERIPHERAL_FIRST + isr_PSe); } else /* check for main interrupt routed this way */ if ((isr_MSe = (isr & ICTL_ISR_MSe_MASK)) != 0) { isr_MSe &= ICTL_ISR_MSe_MASK_NR; isr_MSe >>= ICTL_ISR_MSe_SHIFT; vector = INUM_TO_IVEC(INUM_MAIN_FIRST + isr_MSe); } else /* spurious interrupt */ { return; }#ifdef INCLUDE_WINDVIEW WV_EVT_INT_ENT(vector)#endif#if !USE_CRITICAL_INTERRUPT/* TBD correct prio handling */ if (isr_CSe > 0) { /* as there is no masking of the critical interrupts, the MSR_EE needs to remain set until the ISR deasserts the interrupt cause It shall call m5200IntAck() for that purpose */ } else#endif if (isr_MSe > 0) { /* save the current interrupt mask */ intMask = *ICTL_CPMIMR; *ICTL_CPMIMR |= ICTL_CPMIMR_MASK_ALL; /* mask all for now -> no nesting */ /* unlock the interrupt */ #if 0 /* TBD: remove to enable nesting */ intUnlock (_PPC_MSR_EE);#endif } else { intMask = *ICTL_PIMR; /* lock all levels inferior to the interrupt detected */ /* those with lower priority level are all in mskPIMR[isr_PSe] */ *ICTL_PIMR |= mskPIMR[isr_PSe]; /* those with same priority level are all in lvlPIMR[isr_PSe] mask only those bits on the right hand side and including isr_PSe */ *ICTL_PIMR |= (lvlPIMR[isr_PSe] & ( ( 1 << (32-isr_PSe) ) - 1)); /* unlock the interrupt */#if 0 /* TBD: remove to enable nesting */ intUnlock (_PPC_MSR_EE);#endif } /* call the Interrupt Handler */ intrVecTable[IVEC_TO_INUM(vector)].vec (intrVecTable[IVEC_TO_INUM(vector)].arg); /* restore the interrupt mask */#if !USE_CRITICAL_INTERRUPT if (isr_CSe > 0) { /* unlock the interrupt in case the ISR did not call m5200IntAck */ intUnlock (_PPC_MSR_EE); } else#endif if (isr_MSe >0) { *ICTL_CPMIMR = intMask; } else { *ICTL_PIMR = intMask; } return; }/********************************************************************************* m5200SysMngIntrDeMux - SIU interrupt demultiplexer ** This routine must be bound to system management interrupt exception (vector 0x1400). * It is used to call the appropriate handler with its argument when an* interrupt occurs. ** The interrupts are prioritized in the following order:** NOTE: when this function is called the interrupts are still locked. It's* this function responsability to unlock the interrupt.** RETURNS: N/A*/LOCAL void m5200SysMngIntrDeMux (void) { UINT32 isr; UINT32 isr_MSe; VOIDFUNCPTR *vector; UINT32 intMask; isr = *ICTL_ISR; /* get interrupt status */ /* check for main interrupt */ if ((isr_MSe = (isr & ICTL_ISR_MSe_MASK)) != 0) { isr_MSe &= ICTL_ISR_MSe_MASK_NR; isr_MSe >>= ICTL_ISR_MSe_SHIFT; vector = INUM_TO_IVEC(INUM_MAIN_FIRST + isr_MSe); } else { return; }#ifdef INCLUDE_WINDVIEW WV_EVT_INT_ENT(vector)#endif /* save the current interrupt mask */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -