📄 m8240epic.c
字号:
/* m8240Epic.c - Motorola MPC8240 Interrupt Controller driver *//* Copyright 1984-2001 Wind River Systems, Inc. *//*modification history--------------------01a,24may99,wfg written*//*DESCRIPTIONThis module implements the MC8240 EPIC interrupt controller driver.*//* includes */#include "m8240Epic.h"/* defines *//* 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 sysEpicIntHandler (void);IMPORT UINT sysVectorIRQ0; /* vector for IRQ0 */INT_HANDLER_DESC * sysIntTbl [256]; /* system interrupt table */int tpr;int spurIntCnt;#ifdef INCLUDE_INSTRUMENTATIONIMPORT int evtTimeStamp;#endif/* forward declarations */LOCAL STATUS sysEpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine, int parameter);LOCAL int sysEpicIntEnable (int);LOCAL int sysEpicIntDisable (int);#ifndef CPU_INT_LOCK# define CPU_INT_LOCK(x) \ (*x = intLock ())#endif#ifndef CPU_INT_UNLOCK# define CPU_INT_UNLOCK(data) \ (intUnlock (data))#endif/************************************************************************* sysEpicInit - initialize the EPIC in the MC8240** This function initializes the Embedded Programmable * Interrupt Controller (EPIC) which is part of the 8240.** It first initializes the system vector table, connects the EPIC interrupt* handler to the PPC external interrupt and attaches the local EPIC routines* for interrupt connecting, enabling and disabling to the corresponding system* routine pointers.** It then initializes the EPIC register and clears any pending EPIC interrupts.** RETURNS: OK always*/STATUS sysEpicInit ( void ) { int i; int j; /* 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, sysEpicIntHandler); /* * Set up the BSP specific routines * Attach the local routines to the vxWorks system calls */ _func_intConnectRtn = sysEpicIntConnect; _func_intEnableRtn = sysEpicIntEnable; _func_intDisableRtn = sysEpicIntDisable; /* Initialize the MPIC */ /* reset the EPIC */ *M8240_EPIC_GCR(EUMB) = 0x0a0 ; for (i=0; i < 1024 ; i++); /* wait for reset to complete */ /* put the EPIC into mixed mode */ *M8240_EPIC_GCR(EUMB) = 0x020 ; /* initialize all interrupt sources */ /* external interrupts */ *M8240_EPIC_EISVP0(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_EXT_IRQ0 | INT_PRI_EXT_IRQ0) ; *M8240_EPIC_EISVP1(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_EXT_IRQ1 | INT_PRI_EXT_IRQ1) ; *M8240_EPIC_EISVP2(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_EXT_IRQ2 | INT_PRI_EXT_IRQ2) ; *M8240_EPIC_EISVP3(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_EXT_IRQ3 | INT_PRI_EXT_IRQ3) ; *M8240_EPIC_EISVP4(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_EXT_IRQ4 | INT_PRI_EXT_IRQ4) ; /* timer interrupts */ *M8240_EPIC_GTVR0(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_TIMER0 | INT_PRI_TIMER0) ; *M8240_EPIC_GTVR1(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_TIMER1 | INT_PRI_TIMER1) ; *M8240_EPIC_GTVR2(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_TIMER2 | INT_PRI_TIMER2) ; *M8240_EPIC_GTVR3(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_TIMER3 | INT_PRI_TIMER3) ; /* DMA,I2C and I20 interrupts */ *M8240_EPIC_DMA0_VR(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_DMA0 | INT_PRI_DMA0) ; *M8240_EPIC_DMA1_VR(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_DMA1 | INT_PRI_DMA1) ; *M8240_EPIC_I2C_VR(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_I2C | INT_PRI_I2C ) ; *M8240_EPIC_I2O_VR(EUMB) = LONGSWAP(EPIC_INT_MASK | INT_VEC_I2O | INT_PRI_I2O ) ; /* set the current processor priority level */ *M8240_EPIC_PCTP(EUMB) = LONGSWAP (0x00) ; /* clear out all possible pending interrupts */ for (i=0; i < 32 ; i++) { j = *M8240_EPIC_PIACK(EUMB) ; *M8240_EPIC_PEOI(EUMB) = 0 ; } return (OK); }/************************************************************************* sysEpicIntConnect - 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 sysEpicIntConnect ( 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; if (((int)vector < 0) || ((int)vector > 0xff)) /* Out of Range? */ return (ERROR); /* 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; } return (OK); } /************************************************************************* sysEpicIntEnable - enable an EPIC external interrupt level** This routine enables a specified EPIC interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/ LOCAL int sysEpicIntEnable ( int intLevel /* interrupt level to enable */ ) { /* * if the int. level is not a valid IRQ * If not supported, just return. */ if ((intLevel < 0) || (intLevel > 4)) return (ERROR); /* clear the interrupt mask bit Note: on pointer arithmetic subtlety below - External Interrupt Vector Priority registers are 8 longwords apart */ (M8240_EPIC_EISVP0(EUMB))[intLevel*8] &= LONGSWAP(~EPIC_INT_MASK) ; return (OK); }/************************************************************************* sysEpicIntDisable - disable an Mpic interrupt level** This routine disables a specified Mpic interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/ LOCAL int sysEpicIntDisable ( int intLevel /* interrupt level to disable */ ) { /* * if the int. level is not a valid IRQ * If not supported, just return. */ if ((intLevel < 0) || (intLevel > 4)) return (ERROR); /* set the interrupt mask bit Note: on pointer arithmetic subtlety below - External Interrupt Vector Priority registers are 8 longwords apart */ (M8240_EPIC_EISVP0(EUMB))[intLevel*8] |= LONGSWAP(EPIC_INT_MASK) ; return (OK); }/************************************************************************* sysEpicIntHandler - handle an interrupt received at the EPIC* * This routine will process interrupts received EPIC interrupt sources.** RETURNS: N/A*/void sysEpicIntHandler ( void ) { INT_HANDLER_DESC * currHandler; UINT32 vecNum; /* get the vector from the EPIC IACK reg. */ vecNum = *M8240_EPIC_PIACK(EUMB) ; EIEIO ; vecNum = LONGSWAP(vecNum) & VECTOR_MASK ; /* Ignore spurious interrupts */ if (vecNum == 0xFF) spurIntCnt++ ; while (vecNum != 0xff) { /* * Allow maskable interrupts to the CPU. MPIC will hold off * lower and equal interrupts until MPIC_EOI is performed. */#ifdef INCLUDE_INSTRUMENTATION if (evtLogTIsOn) (* _func_evtLogT1_noTS) (EVENT_INT_ENT((int)vecNum), evtTimeStamp);#endif /* call the necessary interrupt handlers */ if ((currHandler = sysIntTbl [vecNum]) == NULL) { logMsg ("uninitialized EPIC 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 EPIC */ *M8240_EPIC_PEOI(EUMB) = 0 ; EIEIO ; /* get the next vector from the EPIC IACK reg. */ vecNum = *M8240_EPIC_PIACK(EUMB) ; EIEIO ; vecNum = LONGSWAP(vecNum) & VECTOR_MASK ; } return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -