92 lines
2.7 KiB
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);
|
||
|
}
|