📄 ppc860intr.c
字号:
if (IVEC_TO_INUM(vector) >= NUM_VEC_MAX) 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[IVEC_TO_INUM(vector)] == NULL) /* single int. handler case */ sysIntTbl[IVEC_TO_INUM(vector)] = newHandler; else { /* multiple intr. handler case */ currHandler = sysIntTbl[IVEC_TO_INUM(vector)]; while (currHandler->next != NULL) { currHandler = currHandler->next; } currHandler->next = newHandler; } return (OK); }/********************************************************************************* ppc860IntrDeMux - SIU level interrupt demultiplexer ** This routine is bound to external interrupt exception (vector 0x500). * It handles all external interrupts routed through the SIU, including* additional support devices for the board (e.g. PCI ).* It calls the appropriate handler(s) with its argument when an* interrupt occurs to the SIU.** NOTE: when this function is called the interrupts are still locked. It's* this function responsibility to unlock the interrupt.** RETURNS: N/A*/void ppc860IntrDeMux (void) {#ifdef INCLUDE_INSTRUMENTATION UINT32 evtIntNum; /* windview interrupt vector */#endif /* INCLUDE_INSTRUMENATATION */ UINT8 intVec; /* interrupt vector */ UINT32 regBase; /* register Base Address */ UINT32 intMask; /* current interrupt mask */ INT_HANDLER_DESC * currHandler; regBase = vxImmrGet(); /* read the interrupt vector register */ intVec = (* SIVEC(regBase)) >> 26;#ifdef INCLUDE_INSTRUMENTATION /* * if it is a cpm interrupt we need to know the correspondingcpm * level, that we should get from the CPM demultiplexer. But we * need the value here and the value can be read only once. We * save the value here so that once the CPM demultiplexer is called, * it will read the value from the global variable cpmIntNum. * * Since we do not know the CPM level a priori, we have to leave * enough space for the cpm interrupts in the windview list. * Therefore, any interrupt number bigger than the CPM level will * be increased of 15 so to leave those spots to the corresponding * CPM interrupts. */ if (intVec == cpmVecNum) { /* acknowledge the interrupt */ *CIVR(regBase) = CIVR_IACK; cpmIntNum = * CIVR(regBase) >> 11; evtIntNum = intVec + (cpmIntNum%15); } else evtIntNum = ((intVec < cpmVecNum)? intVec : (intVec+15)); if (evtLogTIsOn) (* _func_evtLogT1_noTS) (EVENT_INT_ENT((int)evtIntNum), evtTimeStamp);#endif /* INCLUDE_INSTRUMENTATION */ /* Ignore spurious interrupts */ if (intVec == 0xFF) { logMsg ("Spurious External Interrupt!\n", 0,0,0,0,0,0); return; } /* save the current interrupt mask */ intMask = * SIMASK(regBase); /* lock all levels inferior to the interrupt detected */ * SIMASK(regBase) &= (0xffffffff << (32 - intVec)); /* unlock the interrupt */ intUnlock (_PPC_MSR_EE); /* call the necessary interrupt handlers */ if ((currHandler = sysIntTbl [intVec]) == NULL) { logMsg ("uninitialized external interrupt %d\r\n", intVec, 0,0,0,0,0); } else { /* Call EACH respective chained interrupt handler */ while (currHandler != NULL) { currHandler->vec (currHandler->arg); currHandler = currHandler->next; } } /* restore the interrupt mask */ * SIMASK(regBase) = intMask; return; }/********************************************************************************* ppc860CpmIntrDeMux - CPM interrupt demultiplexer ** This routine must be bound to one of the SIU interrupts, which will cause* the ppc860IntrDeMux handler to call this handler when a CPM interrupt is* received. ** It is used to call the appropriate handler with its argument when a CPM* interrupt occurs. Since CPM interrupts cannot be chained, we only make a* single handler call and then exit.** RETURNS: N/A*/void ppc860CpmIntrDeMux ( int simaskLevel /* mask out lower level CPM intrs */ ) { int intVec; /* interrupt vector number */ UINT32 regBase; /* register Base Address */ UINT32 intOldMask; /* interrupt mask before the interrupt*/ /* get the device register base address */ regBase = vxImmrGet(); /* acknowledge the interrupt */ * CIVR(regBase) = CIVR_IACK; /* get the interrupt vector */#ifdef INCLUDE_INSTRUMENTATION intVec = cpmIntNum; #else intVec = * CIVR(regBase) >> 11; #endif /* INCLUDE_INSTRUMENTATION */ /* save the interrupt mask before the interrupt */ intOldMask = * CIMR(regBase); /* lock all levels inferior to the interrupt detected */ * CIMR(regBase) &= (0xffffffff << (intVec + 1)); /* enable the CPM interrupt in the SIU controller */ * SIMASK(regBase) |= simaskLevel; /* call the Interrupt Handler */ sysIntTbl[intVec + 32]->vec (sysIntTbl[intVec + 32]->arg); /* clear the bit in the CISR */ * CISR(regBase) = (1 << intVec); /* restore the interrupt mask */ * CIMR(regBase) = intOldMask; }/********************************************************************************* ppc860IntEnable - enable one of the Level or IRQ interrupts into the SIU* or one of the CPM interrupts** This routine will unmask the bit in the SIMASK register corresponding to* the requested interrupt level for SIU interrupts, or unmask the appropriate* bit in the CIMR register for the CPM. The interrupt level must be in the* range of 0 - 31 for SIU interrupts, and 32 - 63 for CPM interrupts.* * RETURNS: OK, or ERROR if intNum is out of range*/int ppc860IntEnable ( int intNum /* interrupt level to enable */ ) { UINT32 regBase; regBase = vxImmrGet(); if ((intNum >= SIU_INT_NUM_LOW) && (intNum <= SIU_INT_NUM_HIGH)) * SIMASK(regBase) |= (1 << (SIU_INT_NUM_HIGH - intNum)); else if ((intNum >= CPM_INT_NUM_LOW) && (intNum <= CPM_INT_NUM_HIGH)) * CIMR(regBase) |= (1 << (intNum - CPM_INT_NUM_LOW)); else return (ERROR); return (OK); }/********************************************************************************* ppc860IntDisable - disable one of the Level or IRQ interrupts into the SIU* or one of the CPM interrupts** This routine will mask the bit in the SIMASK register corresponding to* the requested interrupt level for SIU interrupts, or mask the appropriate* bit in the CIMR register for the CPM. The interrupt level must be in the* range of 0 - 31 for SIU interrupts, and 32 - 63 for CPM interrupts.** RETURNS: OK, or ERROR if intNum is out of range*/int ppc860IntDisable ( int intNum /* interrupt level to disable */ ) { UINT32 regBase; regBase = vxImmrGet(); if ((intNum >= SIU_INT_NUM_LOW) && (intNum <= SIU_INT_NUM_HIGH)) * SIMASK(regBase) &= ~(1 << (SIU_INT_NUM_HIGH - intNum)); else if ((intNum >= CPM_INT_NUM_LOW) && (intNum <= CPM_INT_NUM_HIGH)) * CIMR(regBase) &= ~(1 << (intNum - CPM_INT_NUM_LOW)); else return (ERROR); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -