117 lines
3.1 KiB
C
117 lines
3.1 KiB
C
#include "../include/description_table.h"
|
||
#include "../include/memory.h"
|
||
#include "../include/io.h"
|
||
#include "../include/isr.h"
|
||
#include "../include/vga.h"
|
||
|
||
static isr_t interrupt_handlers[256];
|
||
idt_entry_t idt_entries[256]; // IDT有256个描述符
|
||
idt_ptr_t idt_ptr;
|
||
|
||
extern void idt_flush(uint32_t);
|
||
|
||
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||
idt_entries[num].base_low = base & 0xFFFF;
|
||
idt_entries[num].base_high = (base >> 16) & 0xFFFF; // 拆成低位和高位
|
||
|
||
idt_entries[num].sel = sel;
|
||
idt_entries[num].always0 = 0;
|
||
idt_entries[num].flags = flags;
|
||
// flags | 0x60,即可被Ring3调用
|
||
}
|
||
|
||
void isr_handler(registers_t regs) {
|
||
printf("\n[Kernel]: received interrupt: %d",regs.int_no);
|
||
|
||
if (interrupt_handlers[regs.int_no]) {
|
||
isr_t handler = interrupt_handlers[regs.int_no]; // 有自定义处理程序,调用之
|
||
handler(®s); // 传入寄存器
|
||
}
|
||
}
|
||
|
||
void irq_handler(registers_t regs) {
|
||
if (regs.int_no >= 40) outb(0xA0, 0x20); // 中断号 >= 40,来自从片,发送EOI给从片
|
||
outb(0x20, 0x20); // 发送EOI给主片
|
||
|
||
if (interrupt_handlers[regs.int_no]) {
|
||
isr_t handler = interrupt_handlers[regs.int_no]; // 有自定义处理程序,调用之
|
||
handler(®s); // 传入寄存器
|
||
}
|
||
}
|
||
|
||
void register_interrupt_handler(uint8_t n, isr_t handler) {
|
||
interrupt_handlers[n] = handler;
|
||
}
|
||
|
||
void idt_install() {
|
||
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
|
||
idt_ptr.base = (uint32_t) & idt_entries;
|
||
|
||
memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
|
||
|
||
outb(0x20, 0x11);
|
||
outb(0xA0, 0x11);
|
||
outb(0x21, 0x20);
|
||
outb(0xA1, 0x28);
|
||
outb(0x21, 0x04);
|
||
outb(0xA1, 0x02);
|
||
outb(0x21, 0x01);
|
||
outb(0xA1, 0x01);
|
||
outb(0x21, 0x0);
|
||
outb(0xA1, 0x0);
|
||
|
||
|
||
#define REGISTER_ISR(id) idt_set_gate(id, (uint32_t) isr##id, 0x08, 0x8E)
|
||
REGISTER_ISR(0);
|
||
REGISTER_ISR(1);
|
||
REGISTER_ISR(2);
|
||
REGISTER_ISR(3);
|
||
REGISTER_ISR(4);
|
||
REGISTER_ISR(5);
|
||
REGISTER_ISR(6);
|
||
REGISTER_ISR(7);
|
||
REGISTER_ISR(8);
|
||
REGISTER_ISR(9);
|
||
REGISTER_ISR(10);
|
||
REGISTER_ISR(11);
|
||
REGISTER_ISR(12);
|
||
REGISTER_ISR(13);
|
||
REGISTER_ISR(14);
|
||
REGISTER_ISR(15);
|
||
REGISTER_ISR(16);
|
||
REGISTER_ISR(17);
|
||
REGISTER_ISR(18);
|
||
REGISTER_ISR(19);
|
||
REGISTER_ISR(20);
|
||
REGISTER_ISR(21);
|
||
REGISTER_ISR(22);
|
||
REGISTER_ISR(23);
|
||
REGISTER_ISR(24);
|
||
REGISTER_ISR(25);
|
||
REGISTER_ISR(26);
|
||
REGISTER_ISR(27);
|
||
REGISTER_ISR(28);
|
||
REGISTER_ISR(29);
|
||
REGISTER_ISR(30);
|
||
REGISTER_ISR(31);
|
||
#undef REGISTER_ISR
|
||
#define REGISTER_IRQ(id, irq_id) idt_set_gate(id, (uint32_t) irq##irq_id, 0x08, 0x8E)
|
||
REGISTER_IRQ(32, 0);
|
||
REGISTER_IRQ(33, 1);
|
||
REGISTER_IRQ(34, 2);
|
||
REGISTER_IRQ(35, 3);
|
||
REGISTER_IRQ(36, 4);
|
||
REGISTER_IRQ(37, 5);
|
||
REGISTER_IRQ(38, 6);
|
||
REGISTER_IRQ(39, 7);
|
||
REGISTER_IRQ(40, 8);
|
||
REGISTER_IRQ(41, 9);
|
||
REGISTER_IRQ(42, 10);
|
||
REGISTER_IRQ(43, 11);
|
||
REGISTER_IRQ(44, 12);
|
||
REGISTER_IRQ(45, 13);
|
||
REGISTER_IRQ(46, 14);
|
||
REGISTER_IRQ(47, 15);
|
||
#undef REGISTER_IRQ
|
||
idt_flush((uint32_t) & idt_ptr);
|
||
} |