interrupt.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #include "interrupt.h"
  2. #include "stdint.h"
  3. #include "global.h"
  4. #include "../lib/kernel/print.h"
  5. #include "../lib/kernel/io.h"
  6. /*创建中断门描述符*/
  7. static void make_idt_desc(gate_desc *p_gdesc, uint8_t attr, intr_handler function)
  8. {
  9. p_gdesc->offset_low = (uint32_t)function & 0x0000FFFF;
  10. p_gdesc->selector = SELECTOR_K_CODE;
  11. p_gdesc->dcount = 0;
  12. p_gdesc->attribute = attr;
  13. p_gdesc->offset_high = ((uint32_t)function & 0xFFFF0000) >> 16;
  14. }
  15. /* 初始化中断描述符表*/
  16. static void itd_desc_init(void)
  17. {
  18. int i;
  19. for (i = 0; i < IDT_DESC_CNT; i++)
  20. {
  21. make_idt_desc(&idt[i], IDT_DESC_ATTR_DPL0, intr_entry_table[i]);
  22. }
  23. put_str(" idt_desc_init done\n");
  24. }
  25. /* 初始化可编程中断控制器 8259A */
  26. static void pic_init(void)
  27. {
  28. /* 初始化主片*/
  29. outb(PIC_M_CTRL, 0x11); // ICW1: 边沿触发,级联8259, 需要 ICW4
  30. outb(PIC_M_DATA, 0x20); // ICW2: 起始中断向量号 0x20, 也就是 IRQ[0~7] 为 0x20~0x27
  31. outb(PIC_M_DATA, 0x04); // ICW3: IR2 接从片
  32. outb(PIC_M_DATA, 0x01); // ICW4: 8086 模式, 正常 EOI
  33. /* 初始化从片 */
  34. outb(PIC_S_CTRL, 0x11); // ICW1: 边沿触发,级联8259, 需要 ICW4
  35. outb(PIC_S_DATA, 0x28); // ICW2: 起始中断向量号 0x28, 也就是 IRQ[8~15] 以 0x28~0x2F
  36. outb(PIC_S_DATA, 0x02); // ICW3: 设置从片连接到主片的 IR2 引脚
  37. outb(PIC_S_DATA, 0x01); // ICW4: 8086 模式, 正常 EOI
  38. /* 打开主片上 IR0, 也就是目前只接受时钟产生的中断*/
  39. outb(PIC_M_DATA, 0xfe);
  40. outb(PIC_S_DATA, 0xff);
  41. put_str(" pic_init done\n");
  42. }
  43. /* 中断初始化主函数 */
  44. void itd_init(void)
  45. {
  46. put_str("init_idt start\n");
  47. itd_desc_init();
  48. pic_init(); // 初始化可编程中断控制器8259A
  49. /* 加载 idt */
  50. uint64_t idt_operand = ((sizeof(idt) - 1) | ((uint64_t)((uint32_t)idt << 16)));
  51. asm volatile("lidt %0" ::"m"(idt_operand));
  52. put_str("itd_init done\n");
  53. }