📄 sysepic.c
字号:
** NOTE: To allow compatibility, sysEpicIntDisable() can be used only for* external and internal interrupts, and not GT, MSG, IPI. It* assumes there are more internal IRQs than external. It also* gives priority to external over internal given the same IRQ* is valid for both external and internal.*/int sysEpicIntDisable ( int vector ) { if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS)) return (ERROR); /* disable interrupt on EPIC */ return epicIntDisable ( epicGetVecRegAdrs (vector) ); }/********************************************************************************* epicVecOptionsSet - set options for a vector** <srcAddr> is the address offset of the Vector Priority register* <mask> is one of EPIC_OPT_EN_MSK, EPIC_OPT_POLAR_MSK, EPIC_OPT_SENSE_MSK,* EPIC_OPT_PRI_MSK, EPIC_OPT_EXPIN_MSK, EPIC_OPT_CRIT_MSK* <options> is one of * EPIC_OPT_EN_Y interrupt enabled* EPIC_OPT_EN_N interrupt disabled* EPIC_OPT_POLAR_ACT_LOW polarity is active low* EPIC_OPT_POLAR_ACT_HIGH polarity is active high* EPIC_OPT_POLAR_EDG_NEG polarity is negative edge triggered* EPIC_OPT_POLAR_EDG_POS polarity is positive edge triggered* EPIC_OPT_SENSE_EDG edge sensitive* EPIC_OPT_SENSE_LVL level sensitive* EPIC_OPT_PRI_VALUE(p) set priority to p [0..15]* EPIC_OPT_EXPIN_OFF external pin off* EPIC_OPT_EXPIN_ON external pin on* EPIC_OPT_CRIT_OFF route to critical pin off* EPIC_OPT_CRIT_ON route to critical pin on** NOMANUAL** RETURNS: OK or an error code, can be one of the following:* OK* ERROR* EPIC_VEC_OPTION_INV* EPIC_INV_INTER_SOURCE* EPIC_VEC_OPTION_NA* EPIC_VEC_HAS_NO_IDR* EPIC_INTER_IN_SERVICE*/LOCAL int epicVecOptionsSet ( ULONG srcAddr, UINT32 mask, UINT32 options ) { ULONG vprVal; ULONG idrVal; ULONG vprFlag; ULONG idrFlag; int errCode; int idrOffset = 0; /* offset of IDR from VPR */ if ((mask & ((0x3f30 << 16) | (0x3fff))) != 0) return (EPIC_VEC_OPTION_INV); errCode = epicSrcAddrCheck (srcAddr); if (errCode == EPIC_INV_INTER_SOURCE) { return (errCode); } vprFlag = mask & 0xffff0000; /* upper sets upper VPR */ idrFlag = (mask & 0x0000ffff) << 16; /* lower sets upper IDR */ switch (errCode) { case EPIC_EX_INTERRUPT: idrOffset = EPIC_EX_DEST_REG_VECREGOFF; break; case EPIC_IN_INTERRUPT: idrOffset = EPIC_IN_DEST_REG_VECREGOFF; if ((vprFlag & EPIC_OPT_SENSE_MSK) != 0) return (EPIC_VEC_OPTION_NA); break; case EPIC_GT_INTERRUPT: if (idrFlag != 0) return (EPIC_VEC_HAS_NO_IDR); break; case EPIC_MSG_INTERRUPT: idrOffset = EPIC_MSG_DEST_REG_VECREGOFF; if ((vprFlag & (EPIC_OPT_POLAR_MSK | EPIC_OPT_SENSE_MSK)) != 0) return (EPIC_VEC_OPTION_NA); break; case EPIC_IPI_INTERRUPT: if (idrFlag != 0) return (EPIC_VEC_HAS_NO_IDR); break; default: return (ERROR); } vprVal = sysEpicRegRead (srcAddr); if ((vprVal & EPIC_EIVPR_INTR_ACTIVE) != 0) return (EPIC_INTER_IN_SERVICE); if (vprFlag != 0) { vprVal &= ~(vprFlag); vprVal |= (options & 0xffff0000); sysEpicRegWrite (srcAddr, vprVal); } if ((idrFlag != 0) && (idrOffset != 0)) { idrVal = sysEpicRegRead (srcAddr + idrOffset); idrVal &= ~(idrFlag); idrVal |= (options & 0xffff) << 16; sysEpicRegWrite (srcAddr + idrOffset, idrVal); } return OK; }/********************************************************************************* epicVecOptionsGet - get options for a vector** <srcAddr> is the address offset of the Vector Priority register** Use one or more of the following masks to extract the returned value:* EPIC_OPT_EN_MSK* EPIC_OPT_POLAR_MSK* EPIC_OPT_SENSE_MSK* EPIC_OPT_PRI_MSK* EPIC_OPT_EXPIN_MSK* EPIC_OPT_CRIT_MSK** NOMANUAL** RETURNS: OK, ERROR, or EPIC_INV_INTER_SOURCE*/LOCAL UINT32 epicVecOptionsGet ( ULONG srcAddr ) { ULONG vprVal; ULONG idrVal; int errCode; int idrOffset = 0; /* offset of IDR from VPR */ errCode = epicSrcAddrCheck (srcAddr); if (errCode == EPIC_INV_INTER_SOURCE) { return (errCode); } switch (errCode) { case EPIC_EX_INTERRUPT: idrOffset = EPIC_EX_DEST_REG_VECREGOFF; break; case EPIC_IN_INTERRUPT: idrOffset = EPIC_IN_DEST_REG_VECREGOFF; break; case EPIC_GT_INTERRUPT: break; case EPIC_MSG_INTERRUPT: idrOffset = EPIC_MSG_DEST_REG_VECREGOFF; break; case EPIC_IPI_INTERRUPT: break; default: return ((UINT32) ERROR); } vprVal = sysEpicRegRead (srcAddr); if (idrOffset != 0) idrVal = sysEpicRegRead (srcAddr + idrOffset); else idrVal = 0; return ((vprVal & 0xffff0000) | (idrVal >> 16)); }/********************************************************************************* sysEpicVecOptionsSet - change options for a vector**/int sysEpicVecOptionsSet ( int vector, UINT32 mask, UINT32 options ) { if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS)) return (ERROR); /* set vector options on EPIC */ return epicVecOptionsSet ( epicGetVecRegAdrs (vector), mask, options ); }/********************************************************************************* sysEpicVecOptionsGet - obtain options for a vector**/UINT32 sysEpicVecOptionsGet ( int vector ) { if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS)) return ((UINT32) ERROR); /* get vector options on EPIC */ return epicVecOptionsGet ( epicGetVecRegAdrs (vector) ); }/********************************************************************************* sysEpicIntConnect - connect an interrupt handler to the system vector table** This function connects an interrupt handler to the system vector table.** RETURNS: OK or ERROR.*/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 * pNewHandler; INT_HANDLER_DESC * pCurrHandler; int intVal; BOOL sharing = FALSE; if (((int)vector < 0) || ((int) vector >= INTERRUPT_TABLESIZE)) { return (ERROR); /* out of range */ } /* create a new interrupt handler */ pNewHandler = malloc (sizeof (INT_HANDLER_DESC)); /* check if the memory allocation succeed */ if (pNewHandler == NULL) return (ERROR); /* initialize the new handler */ pNewHandler->vec = routine; pNewHandler->arg = parameter; pNewHandler->next = NULL; /* install the handler in the system interrupt table */ intVal = intLock (); /* lock interrupts to prevent races */ if (sysIntTbl [(int) vector] == NULL) { sysIntTbl [(int) vector] = pNewHandler; /* single int. handler case */ } else { pCurrHandler = sysIntTbl[(int) vector];/* multiple int. handler case */ while (pCurrHandler->next != NULL) { pCurrHandler = pCurrHandler->next; } pCurrHandler->next = pNewHandler; sharing = TRUE; } if ((int)vector >= 0 && (int)vector < EPIC_MAX_ALL_IRQS) { /* EPIC IRQ set EPIC registers */ if (!sharing) { if ((int) vector < EPIC_VEC_IN_IRQ0) /* EX type */ {/* use active low for PCI */ if (((int) vector >= 2) && ((int) vector <= 5)) epicIntSourceSet ( epicGetVecRegAdrs ((int) vector), EPIC_INT_ACT_LOW, EPIC_EX_DFT_SENSE, EPIC_PRIORITY_DEFAULT, (int) vector);else epicIntSourceSet ( epicGetVecRegAdrs ((int) vector), EPIC_EX_DFT_POLAR, EPIC_EX_DFT_SENSE, EPIC_PRIORITY_DEFAULT, (int) vector); } else if ((int) vector < EPIC_VEC_GT_IRQ0) /* IN type */ { epicIntSourceSet ( epicGetVecRegAdrs ((int) vector), EPIC_IN_DFT_POLAR, 0x0, EPIC_PRIORITY_DEFAULT, (int) vector); } else /* other types */ { epicIntSourceSet ( epicGetVecRegAdrs ((int) vector), 0x0, 0x0, EPIC_PRIORITY_DEFAULT, (int) vector); } } } intUnlock (intVal); return (OK); }/********************************************************************************* sysEpicIntHandlerExec - execute the handlers for a given vector* * This routine executes all the handlers chained to a given vector.* If a vector has no handlers attached to it, a logMsg is generated.** NOMANUAL** RETURNS: N/A**/LOCAL void sysEpicIntHandlerExec ( int vector ) { INT_HANDLER_DESC * pCurrHandler; /* call each respective interrupt handler */ if ((pCurrHandler = sysIntTbl [vector]) == NULL) { logMsg ("uninitialized PIC interrupt vector 0x%x\r\n", vector, 0,0,0,0,0); } else {#if FALSE /* test for working of serial console */ if (vector != 0x26) logMsg ("epic vector = 0x%x\n", vector);#endif /* call Each respective chained interrupt handler */ while (pCurrHandler != NULL) { (*pCurrHandler->vec) (pCurrHandler->arg); pCurrHandler = pCurrHandler->next; } } }/********************************************************************************* sysEpicIntHandler - handles the EPIC interrupts to the CPU** This routine handles interrupts originating from the embedded interrupt* controller on the MPC8540 PowerPC processor.* This handler is entered from the 0x500 exception.** This routine is entered with CPU external interrupts enables.** Since the EPIC is the primary interrupt controller this driver* first initiates an Epic acknowledge call and reads the vector* put out by the EPIC. Subsequent vectors have to be obtained if* an external interrupt controller is connected to one of the* epic handlers. ** This routine then processes the interrupt by calling all the interrupt* service routines chained to the vector.** Finally, this routine re-arms the interrupt at the PIC by performing an * PIC EOI for both the EPIC and the 8259s.** RETURNS: N/A**/LOCAL void sysEpicIntHandler (void) { int epicIntVec; int oldkey; epicIntVec = epicIntAck (); /* clear int, return the vec for highest IRQ */#ifdef INCLUDE_WINDVIEW WV_EVT_INT_ENT (epicIntVec);#endif /* loop till all interrupts are cleared */ while (epicIntVec != 0xffff) { #if FALSE /* block all lower priority interrupts */ if ((oldLevel = epicCurTaskPrioSet (epicIntVec)) == EPIC_INV_PRIO_ERROR) { return; } #endif /* Allow external interrupts to the CPU. */ CPU_INT_UNLOCK (_PPC_MSR_EE); sysEpicIntHandlerExec (epicIntVec); CPU_INT_LOCK (&oldkey); /* * Disable External Interrupts * External Interrupts will be re-enabled in the kernel's wrapper * of this Interrupt. */ WRS_ASM ("sync");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -