📄 w83c553f.c
字号:
intConnect (IV_IRQ3, sysIbcIntHandler, 0); intEnable( (int)IV_IRQ3 ); /* Permanently turn off ISA refresh by never completing init steps */ IBC_BYTE_OUT (W83C553F_TMR1_CMOD, 0x74); /* Perform the PCI Interrupt Ack cycle */ IBC_BYTE_IN (QSPAN_BASE_ADRS + QSPAN_IACK_REG, &intVec); /* Perform the end of interrupt procedure */ sysIbcEndOfInt (15); sysIbcIntLevelSet (16); return (OK); }/******************************************************************************** sysIbcIntConnect - 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 sysIbcIntConnect ( 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 */ newHandler = malloc (sizeof (INT_HANDLER_DESC)); /* check if the memory allocation succeed */ if (newHandler == 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 (intVecTable[(int) vector] == NULL) intVecTable [(int ) vector] = newHandler; /* single int. handler case */ else { /* multiple int. handler case */ currHandler = intVecTable[(int) vector]; while (currHandler->next != NULL) { currHandler = currHandler->next; } currHandler->next = newHandler; } return (OK); }/********************************************************************************* sysIbcIntEnable - enable a IBC interrupt level** This routine enables a specified IBC interrupt level.** RETURNS: N/A*/void sysIbcIntEnable ( int intNum /* interrupt level to enable */ ) { if (intNum < 8) { sysPicMask1 &= ~(1 << intNum); IBC_BYTE_OUT (PIC_IMASK (PIC1_BASE_ADR), sysPicMask1 | sysPicLevel1); } else { sysPicMask2 &= ~(1 << (intNum - 8)); IBC_BYTE_OUT (PIC_IMASK (PIC2_BASE_ADR), sysPicMask2 | sysPicLevel2); } }/********************************************************************************* sysIbcIntDisable - disable a IBC interrupt level** This routine disables a specified IBC interrupt level.** RETURNS: N/A*/void sysIbcIntDisable ( int intNum /* interrupt level to disable */ ) { if (intNum < 8) { sysPicMask1 |= (1 << intNum); IBC_BYTE_OUT (PIC_IMASK (PIC1_BASE_ADR), sysPicMask1 | sysPicLevel1 ); } else { sysPicMask2 |= (1 << (intNum - 8)); IBC_BYTE_OUT (PIC_IMASK (PIC2_BASE_ADR), sysPicMask2 | sysPicLevel2); } }/******************************************************************************** sysIbcIntHandler - handler of the sl82565 IBC interrupt.** This routine handles interrupts originating from the W83C553 PIB ISA Bus* Controller (IBC). This device implements the functional equivalent of two* cascaded 8259 PICs.** This routine is entered with CPU external interrupts disabled.** Because the ISA bus is only accessible via the PCI bus, this driver first* initiates a PCI interrupt acknowledge cycle to read the interrupt number* (vector) coming from the IBC.** It then saves the current ISA interrupt mask values and sets the new mask* values to mask all further ISA interrupts of equal or lesser level. It then* re-enables MPIC interrupts and re-enables CPU external interrupts.** This routine then processes the interrupt by calling all interrupt service* routines chained to the vector.** Finally, this routine disables CPU external interrupts and restores the ISA* interrupt mask values before returning.** RETURNS: N/A*/void sysIbcIntHandler (void) { int intNum; INT_HANDLER_DESC * currHandler; int dontCare; int oldLevel; /* Perform the PCI Interrupt Ack cycle * * Note: IBC_BYTE_IN() always returns 8 for intNum (not too useful). * through experimentation if was found that doing an IBC_LONG_IN * and shifting the result as shown below, gives us the correct * interrupt number. Must be some goofiness with the Qspan. */ IBC_LONG_IN (QSPAN_BASE_ADRS + QSPAN_IACK_REG, &intNum); intNum = intNum >> 24; /* Save current interrupt mask */ oldLevel = sysPicLevelCur; sysIbcIntLevelSet (intNum); /* Re-arm (enable) the interrupt chip */ sysIbcEndOfInt (intNum); /* Allow external interrupts to the CPU. */ CPU_INT_UNLOCK (_PPC_MSR_EE); if ((currHandler = intVecTable [intNum + IBC_INUM_SYS_BASE]) == NULL) { logMsg ("uninitialized interrupt level %d\n", intNum, 0,0,0,0,0); } else { /* Call EACH respective interrupt handler */ while (currHandler != NULL) { currHandler->vec (currHandler->arg); currHandler = currHandler->next; } } /* * Disable External Interrupts * External Interrupts will be re-enabled in the kernel's wrapper * of this Interrupt. */ CPU_INT_LOCK (&dontCare); /* Restore original interrupt level */ sysIbcIntLevelSet (oldLevel); }/********************************************************************************* sysIbcEndOfInt - send EOI(end of interrupt) signal.** This routine is called at the end of the interrupt handler to* send a non-specific end of interrupt (EOI) signal.** The second PIC is acked only if the interrupt came from that PIC.* The first PIC is always acked.*/LOCAL void sysIbcEndOfInt ( int intNum ) { if (intNum > 7) { IBC_BYTE_OUT (PIC_IACK (PIC2_BASE_ADR), 0x20); } IBC_BYTE_OUT (PIC_IACK (PIC1_BASE_ADR), 0x20); }/********************************************************************************* sysIbcIntLevelSet - set the interrupt priority level** This routine masks interrupts with real priority equal to or lower than* <intNum>. The special* value 16 indicates all interrupts are enabled. Individual interrupt* numbers have to be specifically enabled by sysIbcIntEnable() before they* are ever enabled by setting the interrupt level value.** Note because of the IBM cascade scheme, the actual priority order for* interrupt numbers is (high to low) 0, 1, 8, 9, 10, 11, 12, 13, 14, 15,* 3, 4, 5, 6, 7, 16 (all enabled)** INTERNAL: It is possible that we need to determine if we are raising* or lowering our priority level. It may be that the order of loading the* two mask registers is dependent upon raising or lowering the priority.** RETURNS: N/A*/LOCAL void sysIbcIntLevelSet ( int intNum /* interrupt level to implement */ ) { if (intNum > 16) intNum = 16; sysPicLevelCur = intNum; if (sysPicLevel2 != sysPicPriMask2[intNum]) { sysPicLevel2 = sysPicPriMask2[intNum]; IBC_BYTE_OUT (PIC_IMASK (PIC2_BASE_ADR), sysPicMask2 | sysPicLevel2); } if (sysPicLevel1 != sysPicPriMask1[intNum]) { sysPicLevel1 = sysPicPriMask1[intNum]; IBC_BYTE_OUT (PIC_IMASK (PIC1_BASE_ADR), sysPicMask1 | sysPicLevel1); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -