kernel/x86_64: Add a way to register IRQ handlers from other kernel subsystems
This commit is contained in:
parent
b0506bf88f
commit
acf21da441
@ -29,5 +29,7 @@ namespace CPU
|
|||||||
|
|
||||||
u16 get_processor_id();
|
u16 get_processor_id();
|
||||||
|
|
||||||
|
bool register_interrupt(u8 interrupt, void (*handler)(Registers*));
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
}
|
}
|
||||||
|
@ -188,4 +188,18 @@ ISR_ERROR 21 ; control-protection exception (#CP)
|
|||||||
; ISR 22-31 reserved
|
; ISR 22-31 reserved
|
||||||
IRQ 32, 0 ; timer interrupt
|
IRQ 32, 0 ; timer interrupt
|
||||||
IRQ 33, 1 ; keyboard 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
|
ISR 66 ; system call
|
||||||
|
@ -28,6 +28,10 @@ extern void setup_idt();
|
|||||||
|
|
||||||
static Thread* g_io_thread;
|
static Thread* g_io_thread;
|
||||||
|
|
||||||
|
typedef void (*interrupt_handler_t)(Registers*);
|
||||||
|
|
||||||
|
static interrupt_handler_t irq_handlers[16];
|
||||||
|
|
||||||
void FPData::save()
|
void FPData::save()
|
||||||
{
|
{
|
||||||
asm volatile("fxsave (%0)" : : "r"(m_data));
|
asm volatile("fxsave (%0)" : : "r"(m_data));
|
||||||
@ -135,21 +139,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
|
// Called from _asm_interrupt_entry
|
||||||
extern "C" void arch_interrupt_entry(Registers* regs)
|
extern "C" void arch_interrupt_entry(Registers* regs)
|
||||||
{
|
{
|
||||||
if (regs->isr < 32) handle_x86_exception(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();
|
u64 irq = regs->error;
|
||||||
if (should_invoke_scheduler()) Scheduler::invoke(regs);
|
interrupt_handler_t handler = irq_handlers[irq];
|
||||||
pic_eoi(regs);
|
if (!handler)
|
||||||
}
|
{
|
||||||
else if (regs->isr == 33) // Keyboard interrupt
|
kwarnln("Unhandled IRQ catched! Halting.");
|
||||||
{
|
CPU::efficient_halt();
|
||||||
u8 scancode = IO::inb(0x60);
|
}
|
||||||
scancode_queue.try_push(scancode);
|
|
||||||
g_io_thread->wake_up();
|
handler(regs);
|
||||||
pic_eoi(regs);
|
pic_eoi(regs);
|
||||||
}
|
}
|
||||||
else if (regs->isr == 66) // System call
|
else if (regs->isr == 66) // System call
|
||||||
@ -159,7 +176,7 @@ extern "C" void arch_interrupt_entry(Registers* regs)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kwarnln("IRQ catched! Halting.");
|
kwarnln("Unhandled interrupt catched! Halting.");
|
||||||
CPU::efficient_halt();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,6 +235,10 @@ namespace CPU
|
|||||||
kwarnln("not setting the NX bit as it is unsupported");
|
kwarnln("not setting the NX bit as it is unsupported");
|
||||||
setup_gdt();
|
setup_gdt();
|
||||||
setup_idt();
|
setup_idt();
|
||||||
|
|
||||||
|
memset(irq_handlers, 0, sizeof(irq_handlers));
|
||||||
|
register_interrupt(0, timer_interrupt);
|
||||||
|
register_interrupt(1, keyboard_interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_finish_init()
|
void platform_finish_init()
|
||||||
@ -338,6 +359,15 @@ namespace CPU
|
|||||||
__get_cpuid(1, &unused, &ebx, &unused, &unused);
|
__get_cpuid(1, &unused, &ebx, &unused, &unused);
|
||||||
return (u16)(ebx >> 24);
|
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
|
// called by kernel_yield
|
||||||
|
Loading…
Reference in New Issue
Block a user