📄 i8259intr.c
字号:
} }/********************************************************************************* i8259IntEoiSmm - disable Special Mask Mode with EOI signal to the master PIC** This routine is called at the end of the IRQ0 interrupt handler that is * PIT(8253) channel 0 system clock interrupt handler in the Special Mask Mode.**/VOID i8259IntEoiSmm ( int irqNo /* IRQ number to send EOI */ ) { INT32 oldLevel = intLock (); /* LOCK INTERRUPT */ sysOutByte (PIC_IMASK (PIC1_BASE_ADR), i8259Mask); /* restore old mask */ sysOutByte (PIC_port1 (PIC1_BASE_ADR), 0x08); /* disable SMM PIC1 */ sysOutByte (PIC_IACK (PIC1_BASE_ADR), 0x20); /* NS EOI to PIC1 */ intUnlock (oldLevel); /* UNLOCK INTERRUPT */ }/********************************************************************************* i8259IntEoiMaster - send EOI(end of interrupt) signal to the master PIC.** This routine is called at the end of the interrupt handler.**/VOID i8259IntEoiMaster ( INT32 irqNo /* IRQ number to send EOI */ ) {#ifdef I8259_EOI_OPTIMIZED /* optimized version */ WRS_ASM (" \ pushfl; \ cli; \ movl $0x20, %edx; \ movl $0x20, %eax; \ outb %al, %dx; \ popfl; \ ");#else /* portable version */ INT32 oldLevel = intLock (); /* LOCK INTERRUPTS */ sysOutByte (PIC_IACK (PIC1_BASE_ADR), I8259_EOI); /* non-specific EOI */ intUnlock (oldLevel); /* UNLOCK INTERRUPTS */#endif /* I8259_EOI_OPTIMIZED */ }/********************************************************************************* i8259IntEoiSlave - send EOI(end of interrupt) signal to the slave PIC.** This routine is called at the end of the interrupt handler in the Normal * Fully Nested Mode. This is kept for the backward compatibility.**/VOID i8259IntEoiSlave ( INT32 irqNo /* IRQ number to send EOI */ ) {#ifdef I8259_EOI_OPTIMIZED /* optimized version */ WRS_ASM (" \ pushfl; \ cli; \ movl $0xa0, %edx; \ movl $0x20, %eax; \ outb %al, %dx; \ movl $0x20, %edx; \ outb %al, %dx; \ popfl; \ ");#else /* portable version */ INT32 oldLevel = intLock (); /* LOCK INTERRUPTS */ sysOutByte (PIC_IACK (PIC2_BASE_ADR), I8259_EOI); /* non-specific EOI */ sysOutByte (PIC_IACK (PIC1_BASE_ADR), I8259_EOI); /* non-specific EOI */ intUnlock (oldLevel); /* UNLOCK INTERRUPTS */#endif /* I8259_EOI_OPTIMIZED */ }/********************************************************************************* i8259IntEoiSlaveNfnm - send EOI(end of interrupt) signal to the slave PIC.** This routine is called at the end of the interrupt handler in the Normal * Fully Nested Mode.**/VOID i8259IntEoiSlaveNfnm ( INT32 irqNo /* IRQ number to send EOI */ ) {#ifdef I8259_EOI_OPTIMIZED /* optimized version */ WRS_ASM (" \ pushfl; \ cli; \ movl $0xa0, %edx; \ movl $0x20, %eax; \ outb %al, %dx; \ movl $0x20, %edx; \ outb %al, %dx; \ popfl; \ ");#else /* portable version */ INT32 oldLevel = intLock (); /* LOCK INTERRUPTS */ sysOutByte (PIC_IACK (PIC2_BASE_ADR), I8259_EOI); /* non-specific EOI */ sysOutByte (PIC_IACK (PIC1_BASE_ADR), I8259_EOI); /* non-specific EOI */ intUnlock (oldLevel); /* UNLOCK INTERRUPTS */#endif /* I8259_EOI_OPTIMIZED */ }/********************************************************************************* i8259IntEoiSlaveSfnm - send EOI(end of interrupt) signal to the slave PIC.** This routine is called at the end of the interrupt handler in the Special * Fully Nested Mode.**/VOID i8259IntEoiSlaveSfnm ( int irqNo /* IRQ number to send EOI */ ) { INT8 inserviceReg; INT32 oldLevel = intLock (); /* LOCK INTERRUPT */ sysOutByte (PIC_IACK (PIC2_BASE_ADR), 0x20); /* NS EOI to PIC2 */ sysOutByte (PIC_port1 (PIC2_BASE_ADR), 0x0b); /* issue OCW3 */ inserviceReg = sysInByte (PIC_port1 (PIC2_BASE_ADR)); /* read ISR */ if (inserviceReg == 0) sysOutByte (PIC_IACK (PIC1_BASE_ADR), 0x20); /* NS EOI to PIC1 */ intUnlock (oldLevel); /* UNLOCK INTERRUPT */ }/********************************************************************************* i8259IntDisable - disable a specified PIC interrupt input line** This routine disables a specified PIC interrupt input line.** RETURNS: OK, always.** SEE ALSO: i8259IntEnable()** ARGSUSED0*/LOCAL STATUS i8259IntDisable ( INT32 irqNo /* IRQ number to disable */ ) { if (irqNo < 8) { sysOutByte (PIC_IMASK (PIC1_BASE_ADR), sysInByte (PIC_IMASK (PIC1_BASE_ADR)) | (1 << irqNo)); } else { sysOutByte (PIC_IMASK (PIC2_BASE_ADR), sysInByte (PIC_IMASK (PIC2_BASE_ADR)) | (1 << (irqNo - 8))); } return (OK); }/********************************************************************************* i8259IntEnable - enable a specified PIC interrupt input line** This routine enables a specified PIC interrupt input line.** RETURNS: OK, always.** SEE ALSO: i8259IntDisable()** ARGSUSED0*/LOCAL STATUS i8259IntEnable ( INT32 irqNo /* IRQ number to enable */ ) { if (irqNo < 8) { sysOutByte (PIC_IMASK (PIC1_BASE_ADR), sysInByte (PIC_IMASK (PIC1_BASE_ADR)) & ~(1 << irqNo)); } else { sysOutByte (PIC_IMASK (PIC2_BASE_ADR), sysInByte (PIC_IMASK (PIC2_BASE_ADR)) & ~(1 << (irqNo - 8))); } return (OK); }/********************************************************************************* i8259IntLock - lock out all PIC interrupts** This routine saves the mask and locks out all PIC interrupts.* It should be called in the interrupt disable state(IF bit is 0).** SEE ALSO: i8259IntUnlock()** ARGSUSED0*/LOCAL VOID i8259IntLock (void) { i8259IntMask1 = sysInByte (PIC_IMASK (PIC1_BASE_ADR)); i8259IntMask2 = sysInByte (PIC_IMASK (PIC2_BASE_ADR)); sysOutByte (PIC_IMASK (PIC1_BASE_ADR), 0xff); sysOutByte (PIC_IMASK (PIC2_BASE_ADR), 0xff); }/********************************************************************************* i8259IntUnlock - unlock the PIC interrupts** This routine restores the mask and unlocks the PIC interrupts* It should be called in the interrupt disable state(IF bit is 0).** SEE ALSO: i8259IntLock()** ARGSUSED0*/LOCAL VOID i8259IntUnlock (void) { sysOutByte (PIC_IMASK (PIC1_BASE_ADR), i8259IntMask1); sysOutByte (PIC_IMASK (PIC2_BASE_ADR), i8259IntMask2); }#if FALSE/* * There is a function sysIntLevel() which get the interrupt level from the * interrupt stub, so we don't need it anymore. *//********************************************************************************* i8259IntLevel - Get IRQ number by reading Interrupt Service Register.** This routine is called to get an IRQ number in service.** RETURNS: 0 - 15.** ARGSUSED0*/LOCAL INT32 i8259IntLevel (void) { INT32 inserviceReg; INT32 irq; INT32 oldLevel; INT32 retry; oldLevel = intLock (); for (retry=0; retry < 1; retry ++) { sysOutByte (PIC_port1 (PIC1_BASE_ADR), 0x0b); inserviceReg = sysInByte (PIC_port1 (PIC1_BASE_ADR)); for (irq=0; irq < 8; irq++) if ((inserviceReg & 1) && (irq != 2)) goto i8259IntLevelExit; else inserviceReg >>= 1; sysOutByte (PIC_port1 (PIC2_BASE_ADR), 0x0b); inserviceReg = sysInByte (PIC_port1 (PIC2_BASE_ADR)); for (irq=8; irq < 16; irq++) if (inserviceReg & 1) goto i8259IntLevelExit; else inserviceReg >>= 1; } i8259IntLevelExit: intUnlock (oldLevel); return (irq); }#endif /* FALSE */#endif /* SYMMETRIC_IO_MODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -