第六天

2019-04-15 12:55发布

为了让鼠标能移动起来,必须使用中断,而要使用中断则必须将GDT和IDT初始化。在此之前,首先要初始化PIC,它的意思是可编程中断控制器。它是将多个中断信号集合成一个中断信号的装置,PIC检测着输入管脚的多个中断信号,只要有一个中断信号过来,就将唯一的输出管脚信号变成ON,并通知给CPU。
其中与CPU直接相连的PIC为主PIC,与主PIC相连的PIC称为从PIC。其中从PIC通过第2号IRQ与主PIC相连。 PIC设定如下: void init_pic(void) /* PIC的初始化 */ { io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */ io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */ io_out8(PIC0_ICW1, 0x11 ); /* 边沿触发模式 */ io_out8(PIC0_ICW2, 0x20 ); /* IRQ0-7由INT20-27接收 */ io_out8(PIC0_ICW3, 1 << 2); /* PIC1由IRQ2连接 */ io_out8(PIC0_ICW4, 0x01 ); /* 无缓冲区模式 */ io_out8(PIC1_ICW1, 0x11 ); /* 边沿触发模式 */ io_out8(PIC1_ICW2, 0x28 ); /* IRQ8-15由INT28-2f接收 */ io_out8(PIC1_ICW3, 2 ); /* PIC1由IRQ2连接 */ io_out8(PIC1_ICW4, 0x01 ); /* 无缓冲区模式 */ io_out8(PIC0_IMR, 0xfb ); /* 11111011 PIC1以外全部禁止 */ io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */ return; } 从CPU角度看,PIC是外部设备,CPU使用OUT指令进行操作。
PIC的寄存器都是8位寄存器,其中IMR是中断屏蔽寄存器。ICW是初始化控制数据。ICW有4个,其中ICW1与ICW4与主板配线方式、中断信号的电气特性有关。ICW3是有关主从连接的设定。ICW2则决定哪一号中断通知CPU。至于为什么从INT20开始,原因是0x00~0x1f已经被操作系统所用,当应用程序对操作系统干坏事时,CPU内部会自动产生INT0x00~0x1f,如果IRQ与这些号码重复,则CPU会分不清它到底是IRQ还是CPU的系统保护通知。 初始化完PIC之后就可以来设定鼠标中断和键盘中断了,它们分别对应IRQ12和IRQ1。代码如下: void inthandler21(int *esp) /* 来自PS/2键盘的中断 */ { struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 21 (IRQ-1) : PS/2 keyboard"); for (;;) { io_hlt(); } } void inthandler2c(int *esp) /* 来自PS/2鼠标的中断 */ { struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 2C (IRQ-12) : PS/2 mouse"); for (;;) { io_hlt(); } } 有了相关的中断函数,则进行注册,注册语句如下: set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32); asm_inthandler21注册在idt的第0x21号,如果中断发生,CPU会自动调用asm_inthandler21,2 * 8表示的是asm_inthandler21属于哪一个段,即段号是2,乘以8是因为低3位有别的意思。对于号码段为2的段,有如下设置: set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER); 该段涵盖了整个bootpack。最后的AR_INTGATE32将IDT的属性设定为0x008e,表示这是中断处理的有效设定。