1 #include "8259A.h"
2 #include <common/printk.h>
3 #include <common/kprint.h>
4 #include <exception/gate.h>
5 
6 // 导出定义在irq.c中的中段门表
7 extern void (*interrupt_table[24])(void);
8 
init_8259A()9 void init_8259A()
10 {
11     // 初始化中断门, 中断使用第0个ist
12     for(int i=32;i<=55;++i)
13         set_intr_gate(i, 0, interrupt_table[i-32]);
14     kinfo("Initializing 8259A...");
15 
16     // 初始化主芯片
17     io_out8(0x20, 0x11);    // 初始化主芯片的icw1
18     io_out8(0x21, 0x20);    // 设置主芯片的中断向量号为0x20(0x20-0x27)
19     io_out8(0x21, 0x04);    // 设置int2端口级联从芯片
20     io_out8(0x21, 0x01);    // 设置为AEOI模式、FNM、无缓冲
21 
22     // 初始化从芯片
23     io_out8(0xa0, 0x11);
24     io_out8(0xa1, 0x28);    // 设置从芯片的中断向量号为0x28(0x28-0x2f)
25     io_out8(0xa1, 0x02);    // 设置从芯片连接到主芯片的int2
26     io_out8(0xa1, 0x01);
27 
28 
29     // 设置ocw1, 允许所有中断请求
30     io_out8(0x21, 0x00);
31     io_out8(0xa1, 0x00);
32 
33     sti();
34 
35     kinfo("IRQ circuit 8259A initialized.");
36 
37 }
38 
39 /**
40  * @brief 中断服务程序
41  *
42  * @param rsp 中断栈指针
43  * @param number 中断号
44  */
do_IRQ(struct pt_regs * regs,ul number)45 void do_IRQ(struct pt_regs *regs, ul number)
46 {
47     unsigned char x;
48     switch (number)
49     {
50     case 0x20:  // 时钟中断信号
51 
52         break;
53     case 0x21:  // 键盘中断
54 
55         x = io_in8(0x60);
56         printk_color(ORANGE, BLACK, "Received key irq, key code:%#018lx\n", x);
57         break;
58     default:
59         break;
60     }
61     if(number!=0x20)
62     printk_color(ORANGE, BLACK, "Received irq:%#018x\n", number);
63 
64     // 向主芯片发送中断结束信号
65     io_out8(PIC_master, PIC_EOI);
66 }