📄 w83553pciibc.c
字号:
} /********************************************************************************* sysPciIbcIntDisable - disable a Pic interrupt level** This routine disables a specified Pic interrupt level.** NOMANUAL** RETURNS: OK.**/LOCAL int sysPciIbcIntDisable ( int intNum /* interrupt level to disable */ ) { if (intNum < WB_MAX_IRQS) { if (intNum < 8) { sysPicMask1 |= (1 << intNum); PIC_BYTE_OUT (PIC1_OCW1, sysPicMask1 | sysPicLevel1 ); } else { sysPicMask2 |= (1 << (intNum - 8)); PIC_BYTE_OUT (PIC2_OCW1, sysPicMask2 | sysPicLevel2); } if ((sysPicMask1 == 0xfb) && (sysPicMask2 == 0xff)) return (OK); else return (sysPicMask1 | sysPicMask2); } else { return ERROR; } } /********************************************************************************* pciIbcIntHandler - handle a Winbond interrupt*** This routine handles an interrupt which may have originated from the* Winbond chip's 8259 controllers. Since we support sharing, it is not* known whether the interrupt really came from the Winbond or was* actually generated by another device which shares the same IRQ level* as the Winbond chip on the EPIC. So first, the IRR is checked to* see if an interrupt was pending, and if not the handler is not invoked.** NOMANUAL** RETURNS: N/A*/void pciIbcIntHandler ( int arg ) { UCHAR irrVal; UCHAR intVec; UCHAR winbIntNum; int oldLevel; static int lvl7Int = 0; static int lvl15Int = 0; /* * read the IRR and check if the interrupt came from the Winbond * This is beause we allow sharing of interrupt vectors between the * devices attached directly to the EPIC and the ones controlled by * the Winbond chip. */ PIC_BYTE_OUT (PIC1_OCW3, 0x08+0x02); PIC_BYTE_IN (PIC1_OCW3, &irrVal); if (irrVal == 0) /* check cascaded 8259 */ { PIC_BYTE_OUT (PIC2_OCW3, 0x08+0x02); PIC_BYTE_IN (PIC2_OCW3, &irrVal); } if (irrVal == 0) { return; } /* * reading ISA_INTR_ACK_REG generates PCI IACK cycles on the PCI bus * which will cause the PIC to put out the vector on the bus. * This occurs because Bit 5 of the PCI control reg in the PIC is * programmed to 1 by default. */ MEM_READ(PCI_MSTR_IACK_LOCAL, &intVec); /* read the vector */ if ((intVec == 0xff) || (intVec > INT_NUM_IRQ0 +WB_MAX_IRQS)) { /* bogus vector value on bus i.e. interrupt not meant for winbond */ return; } winbIntNum = intVec - INT_VEC_IRQ0; /* * In both edge and level triggered modes, the IR inputs must * remain high until until after the falling edge of the first * !INTA. If the IR input goes low before this time a DEFAULT * IR7 will occur when the CPU acknowleges the interrupt. This * can be a useful safeguard for detecting interrupts caused by * spurious noise glitches on the IR inputs. (sic) */ if ((winbIntNum & 7) == 7) /* Special check for phantom interrupts */ { if (sysPicPhantomInt (&winbIntNum, lvl7Int, lvl15Int) == TRUE) { return; /* It's phantom so just return. */ } } /* Keep track of level 7 & 15 nesting for phantom interrupt handling */ if (winbIntNum == 7) { lvl7Int++; } else if (winbIntNum == 15) /* yellowknife code has a bug here */ { lvl15Int++; } /* mask this interrupt level and lower priority interrupt levels */ oldLevel = sysPicLevelCur; sysPicIntLevelSet (winbIntNum); /* Re-arm (enable) the interrupt chip */ sysPicEndOfInt (winbIntNum); sysEpicIntHandlerExec (intVec); if (winbIntNum == 7) { lvl7Int--; } else if (winbIntNum == 15) { lvl15Int--; } /* set the original interrupt mask back the way it was */ sysPicIntLevelSet (oldLevel); }/********************************************************************************* sysPicEndOfInt - send EOI(end of interrupt) signal.** NOTES** 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.** RETURNS: N/A*/LOCAL void sysPicEndOfInt ( int intNum ) { if (intNum > 7) { PIC_BYTE_OUT (PIC2_OCW2, 0x20); /* 0010 0000*/ } PIC_BYTE_OUT (PIC1_OCW2, 0x20); /* 0010 0000*/ } /* End of sysPicEndOfInt *//********************************************************************************* sysPicIntLevelSet - set the interrupt priority level** NOTES** 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 sysPicIntEnable() 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*/void sysPicIntLevelSet ( int intNum /* interrupt level to implement */ ) { if (intNum > 16) intNum = 16; sysPicLevelCur = intNum; if (sysPicLevel2 != sysPicPriMask2[intNum]) { sysPicLevel2 = sysPicPriMask2[intNum]; PIC_BYTE_OUT (PIC2_OCW1, sysPicMask2 | sysPicLevel2); } if (sysPicLevel1 != sysPicPriMask1[intNum]) { sysPicLevel1 = sysPicPriMask1[intNum]; PIC_BYTE_OUT (PIC1_OCW1, sysPicMask1 | sysPicLevel1); } } /* end of sysPicIntLevelSet *//********************************************************************************* sysPicPhantomInt - Determine if IRQ interrupt number 7 or 15 is "phantom".** NOTES** This routine determines if an IRQ number of 7 or 15 is a phantom* interrupt. According to Intel 82C59A-2 documentation, the IR (interrupt* request) inputs must remain high until after the falling edge of the first* INTA (interrupt acknowledge). If the IR goes low before this, a DEFAULT* (phantom) IRQ7 will occur when the CPU acknowledges the interrupt. Note* that if an IRQ7 is generated it may really be another interrupt, IRQ4 for* example. IRQ 7 is associated with the master 8259, IRQ 15 is associated * with the slave 8259. This function should only be called if the * acknowledged IRQ number is 7 or 15 but does behave sanely if called with* other IRQ numbers.** RETURNS: TRUE if phantom IRQ, *intNum unaltered.* FALSE if not phantom interrupt, *intNum is "real" IRQ number.*/ LOCAL UCHAR sysPicPhantomInt ( UCHAR *intNum, /* interrupt number received on acknowledge */ int lvl7Int, /* interrupt 7 nesting level */ int lvl15Int /* interrupt 15 nesting level */ ) { UINT irqBit; UINT irqNum; switch (*intNum) { case 7: /* Read the in-service register (ISR) */ PIC_BYTE_OUT (PIC1_OCW3, 0x08+0x03); PIC_BYTE_IN (PIC1_OCW3, &irqBit); if (irqBit == 0) return (TRUE); /* No in-service int so it MUST be phantom */ else { for (irqNum = 0; ((irqBit & 1) == 0) ; irqNum++, irqBit >>= 1) ; if (irqNum == 7) if (lvl7Int > 1) return (TRUE); /* We're nested so it MUST be phantom */ *intNum = irqNum; return (FALSE); } break; case 15: /* Read the in-service register (ISR) */ PIC_BYTE_OUT (PIC2_OCW3, 0x08+0x03); PIC_BYTE_IN (PIC2_OCW3, &irqBit); if (irqBit == 0) return (TRUE); /* No in-service int so it MUST be phantom */ else { for (irqNum = 8; ((irqBit & 1) == 0) ; irqNum++, irqBit >>= 1) ; if (irqNum == 15) if (lvl15Int > 1) return (TRUE); /* Were nested so it MUST be phantom */ *intNum = irqNum; return (FALSE); } break; default: return (FALSE); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -