第7章 初始化中断(8259A编程 PIC编程)

设置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);
}

Leave a Reply

Your email address will not be published. Required fields are marked *