KimisOS/src/kernel/arch_i386/interrupts.c

235 lines
7.3 KiB
C

#include "../shared/interrupts.h"
#include "../drivers/serial.h"
#include "../drivers/cpuio.h"
#include <stdint.h>
uint8_t in_interrupt = 0;
uint8_t get_in_interrupt(){
return in_interrupt;
}
extern void _isr0();
extern void _isr1();
extern void _isr2();
extern void _isr3();
extern void _isr4();
extern void _isr5();
extern void _isr6();
extern void _isr7();
extern void _isr8();
extern void _isr9();
extern void _isr10();
extern void _isr11();
extern void _isr12();
extern void _isr13();
extern void _isr14();
extern void _isr15();
extern void _isr16();
extern void _isr17();
extern void _isr18();
extern void _isr19();
extern void _isr20();
extern void _isr21();
extern void _isr22();
extern void _isr23();
extern void _isr24();
extern void _isr25();
extern void _isr26();
extern void _isr27();
extern void _isr28();
extern void _isr29();
extern void _isr30();
extern void _isr31();
extern void _irq0();
extern void _irq1();
extern void _syscall();
extern void load_idt(void*);
typedef struct idt_entry{
uint16_t offset_low;
uint16_t code_seg;
uint8_t reserved;
uint8_t flags;
uint16_t offset_high;
}__attribute__((packed)) idt_entry_t;
cpu_registers_t *(*volatile interrupt_handlers[16])(cpu_registers_t *regs) = {0};
idt_t idt_desc;
idt_entry_t idt_table[256];
inline void set_idt_entry(uint32_t index, void *ptr, uint8_t flags, uint16_t segment){
uint32_t offset = (uint32_t) ptr;
idt_table[index].offset_high = offset >> 16;
idt_table[index].offset_low = offset & 0xffff;
idt_table[index].code_seg = segment;
idt_table[index].flags = flags | 0x80;
// idt_table[index] = (segment << 16) | (offset & 0xffff);
// idt_table[index+1] = (offset >> 16) | ((flags | 0x80) << 8);
// idt_table[index] = ((uint64_t)(offset >> 16) << 48) | ((uint64_t)(flags | 0x80) << 40) | (segment << 16) | (offset & 0xffff);
}
cpu_registers_t *_irq_handler(cpu_registers_t *regs){
in_interrupt = 1;
regs->esp = (uint32_t)regs;
if(regs->int_no == 0x80){
regs = syscall(regs);
}
else if(interrupt_handlers[regs->int_no - 32])
{
// printf("found one for an int");
regs = interrupt_handlers[regs->int_no - 32](regs);
// printf("returned;")
// printf("eip: %x", regs->eip);
}
outb(0x20, 0x20);
if(regs->int_no >= 0x28){
outb(0xa0, 0x20);
}
in_interrupt = 0;
return regs;
}
char *isr_error_strings[] = {"DE", "DB", "NMI", "BP", "OF", "BR", "UD", "NM", "DF", "CSO", "TS", "NP", "SS", "GP", "PF", "", "MF", "AC", "MC", "XM", "VE", "CP", ""};
void _isr_handler(cpu_registers_t *regs){
printf("Kernel Panic!\n");
printf("ISR: #%s\n", isr_error_strings[regs->int_no]);
printf("EAX: %x EBX: %x ECX: %x EDX: %x\n", regs->eax, regs->ebx, regs->ecx, regs->edx);
printf("ESI: %x EDI: %x ESP: %x EBP: %x\n", regs->esi, regs->edi, regs->esp, regs->ebp);
printf("EIP: %x CS: %x DS: %x SS: %x\n", regs->eip, regs->cs, regs->ds, regs->ss);
printf("Error Code: %x\n", regs->pfa);
if (regs->int_no == 14){
uint32_t cr2;
asm volatile("mov %%cr2, %%eax;mov %0, %%eax": "=r"(cr2));
printf("Address: %x", cr2);
}
for(;;);
}
cpu_registers_t *syscall(cpu_registers_t *regs){
printf("Hello!\n");
return regs;
}
extern void panic_hold(cpu_registers_t *regs);
void kernel_panic(char *message, cpu_registers_t *regs){
printf("Kernel Panic!\nAn fatal error occured, and could not be recovered.\nError: ");
printf(message);
printf("System halting...\n");
if(regs != 0) panic_hold(regs);
asm volatile ("jmp .");
}
void install_irq_handler(void (*handler)(), uint8_t irqno){
asm("cli");
interrupt_handlers[irqno] = handler;
// printf("called\n");
asm("sti");
}
void *get_irq_handler(uint8_t irqno){
return interrupt_handlers[irqno];
}
void pit_reload(uint8_t mode, uint16_t reload){
const uint16_t PIT_CMD = 0x43;
const uint16_t PIT_DATA = 0x40;
outb(PIT_CMD, 0b00110000 + mode); //channel 0, low/high byte, rate generator mode
outb(PIT_DATA, reload >> 8);
outb(PIT_DATA, reload & 0xff);
return;
}
uint32_t pit_init(uint32_t freq){
uint32_t reload_value = 0x10000;
if(freq <= 18){
pit_reload(0b100, reload_value);
uint32_t ms = (reload_value * 3000)/3579545;
return ms;
}
if(freq >= 1193181){
pit_reload(0b100, reload_value >> 16);
uint32_t ms = (reload_value * 3000)/3579545;
return ms;
}
reload_value = ((3579545)/(freq));
reload_value /= 3;
pit_reload(0b100, reload_value);
uint32_t ms = (reload_value * 3000)/3579545;
return ms;
}
void idt_load(){
// for(uint32_t i = 0; i < 32; i++){
// set_idt_entry(i, (_isr0 + ((_isr1 - _isr0) * i)), IDT_GATE_INT, 0x10);
// // printf("int %d: address: %x\n", i, _isr0 + (_isr1 - _isr0) * i);
// }
set_idt_entry(0, &_isr0, IDT_GATE_INT, 0x10);
set_idt_entry(1, &_isr1, IDT_GATE_INT, 0x10);
set_idt_entry(2, &_isr2, IDT_GATE_INT, 0x10);
set_idt_entry(3, &_isr3, IDT_GATE_INT, 0x10);
set_idt_entry(4, &_isr4, IDT_GATE_INT, 0x10);
set_idt_entry(5, &_isr5, IDT_GATE_INT, 0x10);
set_idt_entry(6, &_isr6, IDT_GATE_INT, 0x10);
set_idt_entry(7, &_isr7, IDT_GATE_INT, 0x10);
set_idt_entry(8, &_isr8, IDT_GATE_INT, 0x10);
set_idt_entry(9, &_isr9, IDT_GATE_INT, 0x10);
set_idt_entry(10, &_isr10, IDT_GATE_INT, 0x10);
set_idt_entry(11, &_isr11, IDT_GATE_INT, 0x10);
set_idt_entry(12, &_isr12, IDT_GATE_INT, 0x10);
set_idt_entry(13, &_isr13, IDT_GATE_INT, 0x10);
set_idt_entry(14, &_isr14, IDT_GATE_INT, 0x10);
set_idt_entry(15, &_isr15, IDT_GATE_INT, 0x10);
set_idt_entry(16, &_isr16, IDT_GATE_INT, 0x10);
set_idt_entry(17, &_isr17, IDT_GATE_INT, 0x10);
set_idt_entry(18, &_isr18, IDT_GATE_INT, 0x10);
set_idt_entry(19, &_isr19, IDT_GATE_INT, 0x10);
set_idt_entry(20, &_isr20, IDT_GATE_INT, 0x10);
set_idt_entry(21, &_isr21, IDT_GATE_INT, 0x10);
set_idt_entry(22, &_isr22, IDT_GATE_INT, 0x10);
set_idt_entry(23, &_isr23, IDT_GATE_INT, 0x10);
set_idt_entry(24, &_isr24, IDT_GATE_INT, 0x10);
set_idt_entry(25, &_isr25, IDT_GATE_INT, 0x10);
set_idt_entry(26, &_isr26, IDT_GATE_INT, 0x10);
set_idt_entry(27, &_isr27, IDT_GATE_INT, 0x10);
set_idt_entry(28, &_isr28, IDT_GATE_INT, 0x10);
set_idt_entry(29, &_isr29, IDT_GATE_INT, 0x10);
set_idt_entry(30, &_isr30, IDT_GATE_INT, 0x10);
set_idt_entry(31, &_isr31, IDT_GATE_INT, 0x10);
// printf("last ")
for(uint32_t i = 0; i < 16; i++){
set_idt_entry(i + 32, (&_irq0 + ((&_irq1 - &_irq0) * i)), IDT_GATE_INT, 0x10);
// printf("int %d: address: %x\n", i + 32, _irq0 + (_irq1 - _irq0) * i);
}
set_idt_entry(0x80, _syscall, IDT_GATE_INT, 0x10);
idt_desc.pointer = (uint32_t)&idt_table;
idt_desc.size = sizeof(idt_entry_t) * 256 - 1;
for(int i = 0; i < 16; i++){
interrupt_handlers[i] = 0;
}
uint32_t hz_ms = pit_init(50000);
// asm volatile("lidt (%0)" : : "m"(&idt_desc));
// outb(0x20, 0x11 );
// outb(0xa0, 0x11);
// outb(0x21, 0x20);
// outb(0xa1, 0x28);
// outb(0x21, 4);
// outb(0xa1, 2);
// outb(0x21, 1);
// outb(0xa1, 1);
// outb(0x21, 0);
// outb(0xa1, 0);
//set pic masks
// outb(0x21, 0);
// outb(0xa1, 0);
load_idt(&idt_desc);
}