#include "interrupt.h" #include "stdint.h" #include "global.h" #include "../lib/kernel/print.h" #include "../lib/kernel/io.h" /*创建中断门描述符*/ static void make_idt_desc(gate_desc *p_gdesc, uint8_t attr, intr_handler function) { p_gdesc->offset_low = (uint32_t)function & 0x0000FFFF; p_gdesc->selector = SELECTOR_K_CODE; p_gdesc->dcount = 0; p_gdesc->attribute = attr; p_gdesc->offset_high = ((uint32_t)function & 0xFFFF0000) >> 16; } /* 初始化中断描述符表*/ static void itd_desc_init(void) { int i; for (i = 0; i < IDT_DESC_CNT; i++) { make_idt_desc(&idt[i], IDT_DESC_ATTR_DPL0, intr_entry_table[i]); } put_str(" idt_desc_init done\n"); } /* 初始化可编程中断控制器 8259A */ static void pic_init(void) { /* 初始化主片*/ outb(PIC_M_CTRL, 0x11); // ICW1: 边沿触发,级联8259, 需要 ICW4 outb(PIC_M_DATA, 0x20); // ICW2: 起始中断向量号 0x20, 也就是 IRQ[0~7] 为 0x20~0x27 outb(PIC_M_DATA, 0x04); // ICW3: IR2 接从片 outb(PIC_M_DATA, 0x01); // ICW4: 8086 模式, 正常 EOI /* 初始化从片 */ outb(PIC_S_CTRL, 0x11); // ICW1: 边沿触发,级联8259, 需要 ICW4 outb(PIC_S_DATA, 0x28); // ICW2: 起始中断向量号 0x28, 也就是 IRQ[8~15] 以 0x28~0x2F outb(PIC_S_DATA, 0x02); // ICW3: 设置从片连接到主片的 IR2 引脚 outb(PIC_S_DATA, 0x01); // ICW4: 8086 模式, 正常 EOI /* 打开主片上 IR0, 也就是目前只接受时钟产生的中断*/ outb(PIC_M_DATA, 0xfe); outb(PIC_S_DATA, 0xff); put_str(" pic_init done\n"); } /* 中断初始化主函数 */ void itd_init(void) { put_str("init_idt start\n"); itd_desc_init(); pic_init(); // 初始化可编程中断控制器8259A /* 加载 idt */ uint64_t idt_operand = ((sizeof(idt) - 1) | ((uint64_t)((uint32_t)idt << 16))); asm volatile("lidt %0" ::"m"(idt_operand)); put_str("itd_init done\n"); }