<30天自制操作系统>第六天

来源:互联网 发布:剑三明教成女捏脸数据 编辑:程序博客网 时间:2024/05/16 23:50

为了让鼠标能移动起来,必须使用中断,而要使用中断则必须将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,表示这是中断处理的有效设定。

0 0
原创粉丝点击