luxos/Kernel/hal/cpu/irq.c

92 lines
2.7 KiB
C

#include <stdio.h>
#include "pic.h"
#include "irq.h"
#include "idt.h"
/* These are own ISRs that point to our special IRQ handler
* instead of the regular 'fault_handler' function */
extern void Irq_0();
extern void Irq_1();
extern void Irq_2();
extern void Irq_3();
extern void Irq_4();
extern void Irq_5();
extern void Irq_6();
extern void Irq_7();
extern void Irq_8();
extern void Irq_9();
extern void Irq_10();
extern void Irq_11();
extern void Irq_12();
extern void Irq_13();
extern void Irq_14();
extern void Irq_15();
/* This array is actually an array of function pointers. We use
* this to handle custom IRQ handlers for a given IRQ */
void *IrqRoutines[16] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/* This installs a custom IRQ handler for the given IRQ */
void IrqInstallHandler (int irq, void (*handler)(_RegsStack32 *r))
{
IrqRoutines[irq] = handler;
}
void IrqUninstallHandler (int irq)
{
IrqRoutines[irq] = 0;
}
/* We first remap the interrupt controllers, and then we install
* the appropriate ISRs to the correct entries in the IDT. This
* is just like installing the exception handlers */
void IrqInstall()
{
PicRemap(32,40);
IdtSetGate(32, (unsigned)Irq_0, 0x08, 0x8E);
IdtSetGate(33, (unsigned)Irq_1, 0x08, 0x8E);
IdtSetGate(34, (unsigned)Irq_2, 0x08, 0x8E);
IdtSetGate(35, (unsigned)Irq_3, 0x08, 0x8E);
IdtSetGate(36, (unsigned)Irq_4, 0x08, 0x8E);
IdtSetGate(37, (unsigned)Irq_5, 0x08, 0x8E);
IdtSetGate(38, (unsigned)Irq_6, 0x08, 0x8E);
IdtSetGate(39, (unsigned)Irq_7, 0x08, 0x8E);
IdtSetGate(40, (unsigned)Irq_8, 0x08, 0x8E);
IdtSetGate(41, (unsigned)Irq_9, 0x08, 0x8E);
IdtSetGate(42, (unsigned)Irq_10, 0x08, 0x8E);
IdtSetGate(43, (unsigned)Irq_11, 0x08, 0x8E);
IdtSetGate(44, (unsigned)Irq_12, 0x08, 0x8E);
IdtSetGate(45, (unsigned)Irq_13, 0x08, 0x8E);
IdtSetGate(46, (unsigned)Irq_14, 0x08, 0x8E);
IdtSetGate(47, (unsigned)Irq_15, 0x08, 0x8E);
}
// Default IRQ handler, launches other handler if installed.
// Also sends end-of-interrupt messages to PIC
void IrqHandler (_RegsStack32 *r)
{
/* This is a blank function pointer */
void (*handler)(_RegsStack32 *r);
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
handler = IrqRoutines[r->int_no - 32];
if (handler) handler(r);
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to
* the slave controller */
if (r->int_no >=40) outportb(0xA0, 0x20);
/* In either case, we need to send an EOI to the master
* interrupt controller too */
outportb(0x20, 0x20);
}