Add ATA drive support #27
@ -29,5 +29,7 @@ namespace CPU
|
||||
|
||||
u16 get_processor_id();
|
||||
|
||||
bool register_interrupt(u8 interrupt, void (*handler)(Registers*));
|
||||
|
||||
void pause();
|
||||
}
|
||||
|
@ -188,4 +188,18 @@ ISR_ERROR 21 ; control-protection exception (#CP)
|
||||
; ISR 22-31 reserved
|
||||
IRQ 32, 0 ; timer interrupt
|
||||
IRQ 33, 1 ; keyboard interrupt
|
||||
IRQ 34, 2
|
||||
IRQ 35, 3
|
||||
IRQ 36, 4
|
||||
IRQ 37, 5
|
||||
IRQ 38, 6
|
||||
IRQ 39, 7
|
||||
IRQ 40, 8
|
||||
IRQ 41, 9
|
||||
IRQ 42, 10
|
||||
IRQ 43, 11
|
||||
IRQ 44, 12
|
||||
IRQ 45, 13
|
||||
IRQ 46, 14
|
||||
IRQ 47, 15
|
||||
ISR 66 ; system call
|
||||
|
@ -28,6 +28,10 @@ extern void setup_idt();
|
||||
|
||||
static Thread* g_io_thread;
|
||||
|
||||
typedef void (*interrupt_handler_t)(Registers*);
|
||||
|
||||
static interrupt_handler_t irq_handlers[16];
|
||||
|
||||
void FPData::save()
|
||||
{
|
||||
asm volatile("fxsave (%0)" : : "r"(m_data));
|
||||
@ -150,21 +154,34 @@ void io_thread()
|
||||
}
|
||||
}
|
||||
|
||||
static void timer_interrupt(Registers* regs)
|
||||
{
|
||||
Timer::tick();
|
||||
if (should_invoke_scheduler()) Scheduler::invoke(regs);
|
||||
}
|
||||
|
||||
static void keyboard_interrupt(Registers*)
|
||||
{
|
||||
u8 scancode = IO::inb(0x60);
|
||||
scancode_queue.try_push(scancode);
|
||||
g_io_thread->wake_up();
|
||||
}
|
||||
|
||||
// Called from _asm_interrupt_entry
|
||||
extern "C" void arch_interrupt_entry(Registers* regs)
|
||||
{
|
||||
if (regs->isr < 32) handle_x86_exception(regs);
|
||||
else if (regs->isr == 32) // Timer interrupt
|
||||
else if (regs->isr >= 32 && regs->isr < 48) // IRQ from the PIC
|
||||
{
|
||||
Timer::tick();
|
||||
if (should_invoke_scheduler()) Scheduler::invoke(regs);
|
||||
pic_eoi(regs);
|
||||
}
|
||||
else if (regs->isr == 33) // Keyboard interrupt
|
||||
{
|
||||
u8 scancode = IO::inb(0x60);
|
||||
scancode_queue.try_push(scancode);
|
||||
g_io_thread->wake_up();
|
||||
u64 irq = regs->error;
|
||||
interrupt_handler_t handler = irq_handlers[irq];
|
||||
if (!handler)
|
||||
{
|
||||
kwarnln("Unhandled IRQ catched! Halting.");
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
|
||||
handler(regs);
|
||||
pic_eoi(regs);
|
||||
}
|
||||
else if (regs->isr == 66) // System call
|
||||
@ -174,7 +191,7 @@ extern "C" void arch_interrupt_entry(Registers* regs)
|
||||
}
|
||||
else
|
||||
{
|
||||
kwarnln("IRQ catched! Halting.");
|
||||
kwarnln("Unhandled interrupt catched! Halting.");
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
}
|
||||
@ -233,6 +250,10 @@ namespace CPU
|
||||
kwarnln("not setting the NX bit as it is unsupported");
|
||||
setup_gdt();
|
||||
setup_idt();
|
||||
|
||||
memset(irq_handlers, 0, sizeof(irq_handlers));
|
||||
register_interrupt(0, timer_interrupt);
|
||||
register_interrupt(1, keyboard_interrupt);
|
||||
}
|
||||
|
||||
void platform_finish_init()
|
||||
@ -353,6 +374,15 @@ namespace CPU
|
||||
__get_cpuid(1, &unused, &ebx, &unused, &unused);
|
||||
return (u16)(ebx >> 24);
|
||||
}
|
||||
|
||||
bool register_interrupt(u8 interrupt, interrupt_handler_t handler)
|
||||
{
|
||||
if (irq_handlers[interrupt]) return false;
|
||||
|
||||
irq_handlers[interrupt] = handler;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// called by kernel_yield
|
||||
|
Loading…
Reference in New Issue
Block a user