设置IRQ硬件中断(硬件中断包括时钟中断、键盘中断等),可参考《自己动手写操作系统 第1版》p112,《Inter微处理器 第8版》p364
在8259中,需要把 IRQ0~IRQ7 映射到中断向量0x20~0x27,把 IRQ8~IRQ15 映射到中断向量0x28~0x2f。
8259.h的源代码如下所示
#ifndef _8259_H_ #define _8259_H_ #define M_PIC 0x20 #define M_IMR 0x21 #define S_PIC 0xa0 #define S_IMR 0xa1 #define EOI 0x20 void init8259(void); void enable_irq(unsigned short irq_no); void disable_irq(unsigned short irq_no); void enable_all_irq(); void disable_all_irq(); #endif
8259.c的源代码如下所示
#include "8259.h" #include "io.h" unsigned int irq_mask = 0xffff; //所有的IRQ开始时都被屏蔽 void init8259(void) { outportb(M_PIC, 0x11); //主8259,ICW1 outportb(S_PIC, 0x11); //从8259,ICW1 outportb(M_PIC+1, 0x20); //主8259,ICW2. IRQ0~IRQ7对应中断向量0x20~0x27 outportb(S_PIC+1, 0x28); //从8259,ICW2. IRQ8~IRQ15对应中断向量0x28~0x2f outportb(M_PIC+1, 0x04); //主8259,ICW3. 从IR2连接从8259 outportb(S_PIC+1, 0x02); //从8259,ICW3. 连接主8259的IR2 outportb(M_PIC+1, 0x01); //主8259,ICW4. 80x86模式 outportb(S_PIC+1, 0x01); //从8259,ICW4. 80x86模式 outportb(M_IMR, 0xff); //屏蔽主8259上所有中断 outportb(S_IMR, 0xff); //屏蔽从8259上所有中断 } void enable_irq(unsigned short irq_no) { irq_mask &= ~(1 << irq_no); if(irq_no >= 8) { irq_mask &= ~(1 << 2); } outportb(M_IMR, irq_mask & 0xff); outportb(S_IMR, (irq_mask >> 8) & 0xff); } void disable_irq(unsigned short irq_no) { irq_mask |= (1 << irq_no); if((irq_mask & 0xff00) == 0xff00) { irq_mask |= (1<<2); } outportb(M_IMR, irq_mask & 0xff); outportb(S_IMR, (irq_mask >> 8) & 0xff); } void enable_all_irq() { outportb(M_IMR, 0x00); outportb(S_IMR, 0x00); } void disable_all_irq() { outportb(M_IMR, 0xff); outportb(S_IMR, 0xff); }