os3/stage1/interrupts.c
John Stefanelli 7a1f072e4a
[Stage1] Add RSDP and basic ACPI parsing
[Stage1] Add HEX display to screen.h
[Stage1] Handle IRQ1 semi-gracefully
[Stage1] Try (unsuccessfully) to "wait" for IRQ 1 (os_interrupt_wait())
2023-06-05 13:13:37 +02:00

148 lines
No EOL
3.4 KiB
C

#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;
}