#include "include/interrupts.h" #include "datatypes.h" #include "packing.h" #include "include/screen.h" #include "include/pic_8259.h" OS_PACK_START typedef struct __idt_attributes { os_u8 gate_type: 4; os_u8 empty : 1; os_u8 dpl : 2; os_u8 present: 1; } OS_PACK_MID idt_attributes; OS_PACK_END #define IDT_GATE_TYPE_TASK 0x5 #define IDT_GATE_TYPE_INTERRUPT_16 0x6 #define IDT_GATE_TYPE_TRAP_16 0x7 #define IDT_GATE_TYPE_INTERRUPT_32 0xE #define IDT_GATE_TYPE_TRAP_32 0xF OS_PACK_START typedef struct __idt_entry { os_u16 isr_low; os_u16 kernel_gdt_code_segment; os_u8 reserved; idt_attributes attributes; //os_u8 attributes; os_u16 isr_high; } OS_PACK_MID idt_entry; OS_PACK_END OS_PACK_START typedef struct __idt_ptr { os_u16 limit; os_u32 base; } OS_PACK_MID idt_ptr; OS_PACK_END #define EFFECTIVE_INTERRUPT_AMOUNT 256 __attribute__((aligned(0x10))) idt_entry main_idt[EFFECTIVE_INTERRUPT_AMOUNT]; idt_ptr main_idt_ptr; volatile void* interrupt_service_list[EFFECTIVE_INTERRUPT_AMOUNT]; os_u64 os_ticks = 0; os_u32 target_waiting_interrupt = 0; os_u32 target_waiting_flag = 0; void os_interrupt_signal(os_u32 interrupt_id) { if (target_waiting_interrupt == interrupt_id && target_waiting_flag != 0) { target_waiting_flag = 0; target_waiting_interrupt = 0; } } void generic_exception(os_u32 interrupt_id) { //screen_clear(); screen_set_pos(0, 0); screen_write_error("Exception received: ", 0); screen_write_number_error(interrupt_id); screen_write_string("\n", 0); while(1) { } } void handle_irq0(os_u32 interrupt_id) { os_ticks++; pic_sendEOI(0); } void handle_irq1(os_u32 interrupt_id) { os_interrupt_signal(interrupt_id); pic_sendEOI(1); } void handle_double_fault(os_u32 interrupt_id) { screen_set_pos(0, 0); screen_write_error("Double fault.\n", 0); while(1) { } } /* The following is defined in interrupt_utils.asm */ extern void* interrupt_service_table[]; extern void load_idt(); /* --- */ void setup_interrupts() { main_idt_ptr.base = (os_u32) &main_idt[0]; main_idt_ptr.limit = ((os_u16) (sizeof(idt_entry) * EFFECTIVE_INTERRUPT_AMOUNT)) - 1; for (int i = 0; i < EFFECTIVE_INTERRUPT_AMOUNT; i++) { os_u32 val = (os_u32) interrupt_service_table[i]; //os_u32 val = (os_u32) &generic_exception; main_idt[i].isr_low = (os_u16)(val & 0xFFFF); main_idt[i].isr_high = (os_u16)(val >> 16); main_idt[i].kernel_gdt_code_segment = 0x08; main_idt[i].reserved = 0; main_idt[i].attributes.present = 1; main_idt[i].attributes.gate_type = IDT_GATE_TYPE_INTERRUPT_32; main_idt[i].attributes.empty = 0; main_idt[i].attributes.dpl = i == 0x49 ? 3 : 0; interrupt_service_list[i] = (void*)&generic_exception; } main_idt[3].attributes.gate_type = IDT_GATE_TYPE_TRAP_32; main_idt[4].attributes.gate_type = IDT_GATE_TYPE_TRAP_32; interrupt_service_list[8] = (void*)&handle_double_fault; interrupt_service_list[32] = (void*)&handle_irq0; interrupt_service_list[33] = (void*)&handle_irq1; load_idt(); } os_bool os_interrupt_wait(os_u32 interrupt, os_u64 timeout) { if (interrupt != 33) //Keyboard interrupt return OS_FALSE; if (target_waiting_interrupt != 0 || target_waiting_flag != (os_u32*)0) { return OS_FALSE; } os_u64 start_ticks = os_ticks; target_waiting_interrupt = interrupt; target_waiting_flag = 1; while(target_waiting_flag) { if(timeout != 0 && (os_ticks - start_ticks) >= timeout) { target_waiting_flag = 0; target_waiting_interrupt = 0; return OS_FALSE; } } return OS_TRUE; }