|
| 1 | +/** @author Levente Kurusa <[email protected]> **/ |
| 2 | +#include <stdint.h> |
| 3 | +#include "../include/x86/idt.h" |
| 4 | +#include "../include/display.h" |
| 5 | + |
| 6 | +MODULE("IDT"); |
| 7 | + |
| 8 | +static uint32_t idt_location = 0; |
| 9 | +static uint32_t idtr_location = 0; |
| 10 | +static uint16_t idt_size = 0x800; |
| 11 | + |
| 12 | +static uint8_t test_success = 0; |
| 13 | +static uint32_t test_timeout = 0x1000; |
| 14 | + |
| 15 | +void __idt_default_handler(); |
| 16 | +void __idt_test_handler(); |
| 17 | + |
| 18 | +void idt_init() |
| 19 | +{ |
| 20 | + idt_location = 0x402000; |
| 21 | + mprint("Location: 0x%x\n", idt_location); |
| 22 | + idtr_location = 0x401F00; |
| 23 | + mprint("IDTR location: 0x%x\n", idtr_location); |
| 24 | + for(uint8_t i = 0; i < 255; i++) |
| 25 | + { |
| 26 | + idt_register_interrupt(i, __idt_default_handler); |
| 27 | + } |
| 28 | + idt_register_interrupt(0x2f, __idt_test_handler); |
| 29 | + mprint("Registered all interrupts to default handler.\n"); |
| 30 | + /* create IDTR now */ |
| 31 | + *(uint16_t*)idtr_location = idt_size - 1; |
| 32 | + *(uint32_t*)(idtr_location + 2) = idt_location; |
| 33 | + mprint("IDTR.size = 0x%x IDTR.offset = 0x%x\n", *(uint16_t*)idtr_location, *(uint32_t*)(idtr_location + 2)); |
| 34 | + _set_idtr(); |
| 35 | + mprint("IDTR set, testing link.\n"); |
| 36 | + asm volatile("int $0x2f"); |
| 37 | + while(test_timeout != 0) |
| 38 | + { |
| 39 | + if(test_success != 0) |
| 40 | + { |
| 41 | + mprint("Test succeeded, disabling INT#0x2F\n"); |
| 42 | + idt_register_interrupt(0x2F, __idt_default_handler); |
| 43 | + break; |
| 44 | + } |
| 45 | + } |
| 46 | + if(!test_success) |
| 47 | + panic("Link test failed."); |
| 48 | + return; |
| 49 | +} |
| 50 | + |
| 51 | +void __idt_test_handler() |
| 52 | +{ |
| 53 | + INT_START; |
| 54 | + test_success = 1; |
| 55 | + INT_END; |
| 56 | +} |
| 57 | + |
| 58 | +void __idt_default_handler() |
| 59 | +{ |
| 60 | + panic("Unhandled interrupt!\n"); |
| 61 | +} |
| 62 | + |
| 63 | +void idt_register_interrupt(uint8_t i, void(*callback)()) |
| 64 | +{ |
| 65 | + idt_descriptor desc = {0}; |
| 66 | + desc.offset_0_15 = (uint16_t)callback; |
| 67 | + desc.selector = 0x8; |
| 68 | + desc.zero = 0; |
| 69 | + desc.type_attr = 0 | IDT_32BIT_INTERRUPT_GATE | IDT_DPL_3 | IDT_PRESENT; |
| 70 | + desc.offset_16_31 = (uint16_t)((uint32_t)callback >> 16); |
| 71 | + /*mprint("Descriptor: id%d offset 0x%x, orig 0x%x\n", |
| 72 | + i, |
| 73 | + desc.offset_16_31 << 16 | desc.offset_0_15, |
| 74 | + (uint32_t)callback);*/ |
| 75 | + add_idt_descriptor(i, desc); |
| 76 | +} |
| 77 | + |
| 78 | +void add_idt_descriptor(uint8_t id, idt_descriptor desc) |
| 79 | +{ |
| 80 | + *(uint16_t*)(idt_location + sizeof(idt_descriptor)*id + 0) = desc.offset_0_15; |
| 81 | + *(uint16_t*)(idt_location + sizeof(idt_descriptor)*id + 2) = desc.selector; |
| 82 | + *(uint8_t*) (idt_location + sizeof(idt_descriptor)*id + 4) = desc.zero; |
| 83 | + *(uint8_t*) (idt_location + sizeof(idt_descriptor)*id + 5) = desc.type_attr; |
| 84 | + *(uint16_t*)(idt_location + sizeof(idt_descriptor)*id + 6) = desc.offset_16_31; |
| 85 | + return; |
| 86 | +} |
0 commit comments