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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值