📄 sysepic.c
字号:
pCurrHandler->next = pNewHandler; sharing = TRUE; } if ((int)vector >= 0 && (int)vector < INT_VEC_IRQ0) { /* EPIC IRQ set EPIC registers, priority = WB_PRIO + vector */ if (!sharing) epicIntSourceSet (EPIC_VEC_REG((int)vector), EPIC_INT_POLARITY, EPIC_SENSE_LVL, (int) vector, (int) vector); } else if ((int)vector == EPIC_DUART1_INT_VECT) /* setup duart 1 */ { if (!sharing) epicIntSourceSet (EPIC_VEC_REG((int)vector), EPIC_INT_POLARITY, \ EPIC_SENSE_LVL, 0x03, (int)vector); } else if ((int)vector == EPIC_DUART2_INT_VECT) /* setup duart 2 */ { if (!sharing) epicIntSourceSet (EPIC_VEC_REG((int)vector), EPIC_INT_POLARITY, \ EPIC_SENSE_LVL, 0x05, (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**/void sysEpicIntHandlerExec ( UCHAR intVec ) { INT_HANDLER_DESC * pCurrHandler; /* call each respective interrupt handler */ if ((pCurrHandler = sysIntTbl [intVec]) == NULL) { logMsg ("uninitalized PIC interrupt vector %x\r\n", intVec, 0,0,0,0,0); } else { if (epicIntTrace) { /* execute duart interrupts */ if ((intVec == EPIC_DUART1_INT_VECT) || (intVec == EPIC_DUART2_INT_VECT)) logMsg ("sysEpicIntHandlerExec, duart interrupt vector %x\r\n",intVec, 0,0,0,0,0); } /* call Each respective chained interrupt handler */ while (pCurrHandler != NULL) { (*pCurrHandler->vec) (pCurrHandler->arg); pCurrHandler = pCurrHandler->next; } } /* else */ }/********************************************************************************* sysEpicIntHandler - handles the EPIC interrupts to the CPU** This routine handles interrupts originating from the embedded interrupt* controller on the MPC8240 Power PC 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**/void sysEpicIntHandler (void) { int dontCare; UCHAR epicIntVec;#if FALSE int oldLevel;#endif epicIntVec = epicIntAck (); /* clear int, return the vec for highest IRQ */ /* loop till all interrupts are cleared */ while (epicIntVec != 0xff) { if (epicIntTrace) { /* execute duart interrupt handler */ if ((epicIntVec == EPIC_DUART1_INT_VECT) || (epicIntVec == EPIC_DUART2_INT_VECT)) logMsg ("sysEpicIntHandler: duart interrupt vector %x\r\n",epicIntVec, 0,0,0,0,0); }#ifdef INCLUDE_WINDVIEW WV_EVT_INT_ENT (epicIntVec);#endif #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); /* * Disable External Interrupts * External Interrupts will be re-enabled in the kernel's wrapper * of this Interrupt. */ CPU_INT_LOCK (&dontCare); WRS_ASM ("sync"); epicEOI (); /* signal end of interrupt on EPIC */ WRS_ASM ("sync"); epicIntVec = epicIntAck (); #if FALSE epicCurTaskPrioSet (oldLevel); /* Allow the next interrupt to occur */ #endif } /* while */ }/********************************************************************************* epicCurTaskPrioSet - set the priority of the current task.** NOTES** epicCurTaskPrioSet sets the priority of the Processor Current Task* Priority register to the value of the prioNum parameter. This function* should be called after sysEpicInit() to lower the priority of the processor* current task. Note that valid priority values are 0 through 15 (15 being* the highest priority)** NOMANUAL* * RETURNS: previous priority of the task.*/ULONG epicCurTaskPrioSet ( int prioNum ) { ULONG oldPrio; if ((prioNum < EPIC_PRIORITY_MIN) || (prioNum > EPIC_PRIORITY_MAX)) { return (EPIC_INV_PRIO_ERROR); } oldPrio = sysEUMBBARRead (EPIC_PROC_CTASK_PRI_REG); sysEUMBBARWrite (EPIC_PROC_CTASK_PRI_REG, prioNum); return (oldPrio); }/********************************************************************************* epicIntEnable - enable an EPIC interrupt, given its IVPR** This function clears the mask bit of an external, an internal or* a Timer register to enable the interrupt.** <srcAddr> is the address offset of the Vector Priority register ** NOMANUAL* * RETURNS: OK or an error code if the IVPR passed in was invalid.*/int epicIntEnable ( int srcAddr ) { ULONG srcVal; int errCode; errCode = epicsrcAddrCheck (srcAddr); if (errCode != EPIC_INV_INTER_SOURCE) { srcVal = sysEUMBBARRead (srcAddr); srcVal &= ~(EPIC_IVPR_INTR_MSK); /* clear the mask bit */ if (srcAddr < 0x51120) { sysEUMBBARWrite(srcAddr, srcVal); if (epicIntTrace) { logMsg("epicIntEnable: ext intr enabled, %x \n", srcAddr,0,0,0,0,0); } } else if ((srcAddr == EPIC_DUART1_INT_VEC_REG) || (srcAddr == EPIC_DUART2_INT_VEC_REG)) { sysEUMBBARWrite(srcAddr, srcVal); if (epicIntTrace) { logMsg("epicIntEnable: duart intr enabled, %x \n", srcAddr,0,0,0,0,0); } } return (OK); } else { logMsg("epicIntEnable failed at epicsrcAddrCheck, srsAddr: %x \n", srcAddr,0,0,0,0,0); return (errCode); } }/********************************************************************************* epicIntDisable - disable an EPIC interrupt, given its IVPR** This function sets the mask bit of an external, an internal or* a Timer register to disable the interrupt.* <srcAddr> is the address offset of the Vector Priority register.** NOMANUAL* * RETURNS: OK or an error code if the IVPR passed in was invalid.*/ int epicIntDisable ( int srcAddr ) { ULONG srcVal; int errCode; errCode = epicsrcAddrCheck (srcAddr); if (errCode != EPIC_INV_INTER_SOURCE) { srcVal = sysEUMBBARRead (srcAddr); srcVal |= EPIC_IVPR_INTR_MSK; /* set the mask bit */ sysEUMBBARWrite (srcAddr, srcVal); return OK; } else { return (errCode); } }/********************************************************************************* epicIntAck - read the IACK register and return vector* * NOTES** epicIntAck reads the Interrupt acknowldge register and return* the vector number of the highest pending interrupt.** NOMANUAL* * RETURNS: the vector number of the highest priority pending interrupt.*/int epicIntAck(void) { int eumbVal; eumbVal = sysEUMBBARRead (EPIC_PROC_INT_ACK_REG); WRS_ASM ("eieio"); return eumbVal; }/********************************************************************************* epic EOI 0 signal end of interrupt on the EPIC** NOTES** epicEOI writes 0x0 to the EOI register to signal end of interrupt.* This function is usually called after an interrupt routine is served.** NOMANUAL* * RETURNS: N/A*/void epicEOI(void) { sysEUMBBARWrite (EPIC_PROC_EOI_REG, 0x0); }/********************************************************************************* epicsrcAddrCheck - check if the IVPR address passed in is internal or external** NOTES** Check if the address of a vector priority register is of an internal* interrupt vector or an external interrupt vector.** NOMANUAL* * RETURNS: EPIC_INTERNAL_INTERRUPT for internal interrupt sources,* or EPIC_EXTERNAL_INTERRUPT for external ones, or* EPIC_INV_INTER_SOURCE if an invalid IVPR was passed.*/STATUS epicsrcAddrCheck ( ULONG srcAddr ) { switch(srcAddr) { case EPIC_TM0_VEC_REG: case EPIC_TM1_VEC_REG: case EPIC_TM2_VEC_REG: case EPIC_TM3_VEC_REG: case EPIC_I2C_INT_VEC_REG: case EPIC_DMA0_INT_VEC_REG: case EPIC_DMA1_INT_VEC_REG: case EPIC_MSG_INT_VEC_REG: case EPIC_DUART1_INT_VEC_REG: /* added duart vectors */ case EPIC_DUART2_INT_VEC_REG: return (EPIC_INTERNAL_INTERRUPT); case EPIC_SR_INT0_VEC_REG: case EPIC_SR_INT1_VEC_REG: case EPIC_SR_INT2_VEC_REG: case EPIC_SR_INT3_VEC_REG: case EPIC_SR_INT4_VEC_REG: case EPIC_SR_INT5_VEC_REG: case EPIC_SR_INT6_VEC_REG: case EPIC_SR_INT7_VEC_REG: case EPIC_SR_INT8_VEC_REG: case EPIC_SR_INT9_VEC_REG: case EPIC_SR_INT10_VEC_REG: case EPIC_SR_INT11_VEC_REG: case EPIC_SR_INT12_VEC_REG: case EPIC_SR_INT13_VEC_REG: case EPIC_SR_INT14_VEC_REG: case EPIC_SR_INT15_VEC_REG: return (EPIC_EXTERNAL_INTERRUPT); default: return (EPIC_INV_INTER_SOURCE); } }/********************************************************************************* epicIntSourceSet - set interrupt parameters for an interrupt register** This function sets the interrupt parameters for an External Interrupt* Source Vector Priority register, an Internal Interrupt Source Vector* Priority register, or a Global Timer register. The interrupt parameters* can only be set when the current source is not in-request or in-service,* which is determined by the Activity bit. This routine reads the Activity* bit; if the value of this bit is 1 (in-request or in-service), it returns* error; otherwise, it sets the value of the parameters to the register* offset defined in srcAddr.** inputs: srcAddr: Address Offset of the source interrupt register. This* routine assumes that the srcAddr passed in is an valid* Source Vector Priority address.* polarity: Use by external interrupts only, internal and timer* interrupts ignore this parameter.* 1 - Enable active high or positive edge* 0 - Enable active low or negative edge* sense: Use by external interrupts only, internal and timer* interrupts ignore this parameter.* 1 - Enable level sensitive interrupts* 0 - Enable edge sensitive interrupts* priority: valid number 0 to 15 * vector: valid number 0 - 128 (8 bits)** Errors: Invalid Source Address,* Invalid Priority error,* Unable to set parameters** NOMANUAL* * RETURNS: OK or ERROR*/STATUS epicIntSourceSet ( ULONG srcAddr, int polarity, int sense, int priority, int vector ) { ULONG srcVal; ULONG errCode; errCode = epicsrcAddrCheck(srcAddr); if (errCode == EPIC_INV_INTER_SOURCE) { return (errCode); } srcVal = sysEUMBBARRead(srcAddr); if (srcVal & EPIC_IVPR_INTR_ACTIVE) { return (EPIC_INTER_IN_SERVICE); /* interrupt in process */ } /* polarity and sense doesn't apply to internal interrupts */ if (errCode == EPIC_INTERNAL_INTERRUPT) { polarity = 0; sense = 0; } /* erase previously set polority, sense, prority and vector values */ srcVal &= ~(EPIC_IVPR_INTR_POLARITY | EPIC_IVPR_INTR_SENSE | EPIC_IVPR_PRIORITY_MSK | EPIC_IVPR_VECTOR_MSK); srcVal |= (EPIC_IVPR_POLARITY (polarity) | EPIC_IVPR_SENS (sense) | EPIC_IVPR_PRIORITY (priority) | EPIC_IVPR_VECTOR (vector)); sysEUMBBARWrite(srcAddr, srcVal); return (OK); }/********************************************************************************* epicIntSourceGet - retrieve information of an EPIC source vector register.** This function retrieves information of an epic source vector register.* The information includes the Enable bit, the polarity, sense bits, the* interrupt priority and interrupt vector number.* Input: srcAddr - address of the source vector register* Output: enable - whether the interrupt is enabled* polarity - interrupt polarity (high or low)* sense - interrupt sense (level or edge)* Priority - interrupt priority* Vector - interrupt vector number** NOMANUAL* * RETURNS: N/A*/STATUS epicIntSourceGet ( ULONG srcAddr, int * pEnableMask, int * pPolarity, int * pSense, int * pPriority, int * pVector ) { ULONG srcVal; int errCode; errCode = epicsrcAddrCheck (srcAddr); if (errCode == EPIC_INV_INTER_SOURCE) { return errCode; } srcVal = sysEUMBBARRead(srcAddr); *pEnableMask = (srcVal & 0x80000000) >> 31; /* retrieve enable mask-b31 */ *pPolarity = (srcVal & 0x00800000) >> 23; *pSense = (srcVal & 0x00400000) >> 22; *pPriority = (srcVal & 0x000F0000) >> 16; *pVector = (srcVal & 0x000000FF); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -