我们的内核要实现多任务处理,就必须要有一个任务的切换机制:时钟中断,
所以下一步工作就是在内核中加入中断处理.
保护模式的中断处理与实模式很不一样,我们首先要初始化8259A中断控制器,
还要建立中断描述符表IDT.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;保护模式的中断处理:
[1]中断描述符表
[2]初始化8259A
;;;;{1}先来说初始化8259A,因为这个很简单.
;;;;[1]PC中的8259A是两片级联的,分为主片和从片,对应的端口如下:
主:0x20和0x21
从:0xa0和0xa1
;;;;[2]具体的8259A初始化过程就是向这些端口中写入:
ICW(Initialization Command Word)
OCW(Opration Control Word)
ICW共4个,OCW有3个(但我们只知道2个),他们都是8位.
;;;;ICW
;;;;-------------------------------------------------
;;out 0x20, 0x11
;;out 0xa0, 0x11
;;ICW1 -> 主0x20,从0xa0
;; [0]: 0=不需要ICW4,1=需要ICW4
;; [1]: 0=级联8259,1=单个8259
;; [2]: 0=8字节中断向量,1=4字节中断向量
;; [3]: 0=edge triggered模式,1=level triggered模式
;; [4]: 对ICW1必须为1,端口必须为0x20或0xa0
;; [5]: ---/
;; [6]: ----> 对PC系统都为0
;; [7]: ---/
;;;;-------------------------------------------------
;;out 0x21, 0x20
;;out 0xa1, 0x28
;;ICW2 -> 主0x21,从0xa1
;; [0-2]: 80x86系统全为0
;; [3-7]: 80x86系统中断向量
;;;;-------------------------------------------------
;;out 0x21, 0x04
;;out 0xa1, 0x02
;;ICW3 -> 主0x21
;; 级联标志位,若第n位为1,表示IRn级联从片;0,表示无从片
;; 例:IR2级联从片,则主片ICW3=0x04
;;ICW3 -> 从0xa1
;; [0-2]: 从片连接的主片IR号,主片IR2级联从片,则ICW3=0x02
;; [3-7]: 全部为0
;;;;-------------------------------------------------
;;out 0x21, 0x01
;;out 0xa1, 0x01
;;ICW4 -> 主0x21,从0xa1
;; [0]: 0=MCS 80/85,1=8086模式
;; [1]: 0=正常EOI,1=自动EOI
;; [2-3]: 主从缓冲模式
;; [4]: 0=sequential模式,1=SFNM模式
;; [5-7]: 未使用,全为0
;;;;OCW
;;;;-------------------------------------------------
;;out 0x21, 0xff ;屏蔽主8259A的所有外部中断
;;out 0xa1, 0xff ;屏蔽从8259A的多有外部中断
;;OCW1 -> 主0x21,从0xa1
;; 屏蔽或打开外部中断,若第n位为1则表示关闭IRQn;为0则表示打开IRQn
;;;;-------------------------------------------------
;;out 0x20(或0xa0), 0x20 ;发送EOI,通知主或从8259A中断处理结束
;;OCW2 -> 主0x20,从0xa0
;; [0]: L0
;; [1]: L1
;; [2]: L2
;; [3]: 0
;; [4]: 0
;; [5]:EOI
;; [6]:SL
;; [7]:R
;;;;[3]相关C语言代码:
主从中断控制器端口定义:
#define I8259A_M_CTRL 0x20
#define I8259A_M_CTRLMASK 0x21
#define I8259A_S_CTRL 0xa0
#define I8259A_S_CTRLMASK 0xa1
中断向量号定义:
/* 主8259A中断向量号定义 */
#define INT_VECTOR_8259_M_IRQ0 0x20
/* 从8259A中断向量号定义 */
#define INT_VECTOR_8259_S_IRQ0 0x28
8259A初始化函数init_8259A():
PUBLIC void init_8259A()
{
/*ICW1*/
outb(INT_M_CTRL, 0x11); /*主ICW1*/
outb(INT_S_CTRL, 0x11); /*从ICW1*/
/*ICW2*/
outb(INT_M_CTRLMASK, INT_VECTOR_IRQ0); /*主片自IRQ0开始*/
outb(INT_S_CTRLMASK, INT_VECTOR_IRQ8); /*从片自IRQ8开始*/
/*ICW3*/
outb(INT_M_CTRLMASK, 0x04); /*IR2级联从片*/
outb(INT_S_CTRLMASK, 0x02); /*从片连接主片IR2*/
/*ICW4*/
outb(INT_M_CTRLMASK, 0x01);
outb(INT_S_CTRLMASK, 0x01);
/*OCW1*/
outb(INT_M_CTRL, 0xff); /*屏蔽主片所有外部中断*/
outb(INT_S_CTRL, 0xff); /*屏蔽从片所有外部中断*/
}