| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- #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");
- }
|