87 lines
2.5 KiB
C
87 lines
2.5 KiB
C
|
#include <stdint.h>
|
||
|
#include "isr.h"
|
||
|
#include "../libc/string.h"
|
||
|
#include "tty.h"
|
||
|
#include "ports.h"
|
||
|
|
||
|
#define PIC1 0x20 // I/O address for master PIC
|
||
|
#define PIC2 0xA0 // I/O address for slave PIC
|
||
|
#define PIC1_COMMAND PIC1
|
||
|
#define PIC1_DATA (PIC1+1)
|
||
|
#define PIC2_COMMAND PIC2
|
||
|
#define PIC2_DATA (PIC2+1)
|
||
|
#define PIC_EOI 0x20 // End Of Interrupt command
|
||
|
|
||
|
|
||
|
// List of messages for known interrupts
|
||
|
uint8_t *interrupts_messages[] = {
|
||
|
(uint8_t*)"Division by Zero", // 0
|
||
|
(uint8_t*)"Debug",
|
||
|
(uint8_t*)"Non-maskable interrupt",
|
||
|
(uint8_t*)"Breakpoint",
|
||
|
(uint8_t*)"Detected overflow",
|
||
|
(uint8_t*)"Out-of-bounds", // 5
|
||
|
(uint8_t*)"Invalid opcode",
|
||
|
(uint8_t*)"No coprocessor",
|
||
|
(uint8_t*)"Double fault",
|
||
|
(uint8_t*)"Coprocessor segment overrun",
|
||
|
(uint8_t*)"Bad TSS", // 10
|
||
|
(uint8_t*)"Segment not present",
|
||
|
(uint8_t*)"Stack fault",
|
||
|
(uint8_t*)"General protection fault",
|
||
|
(uint8_t*)"Page fault",
|
||
|
(uint8_t*)"Unknown interrupt", // 15
|
||
|
(uint8_t*)"Coprocessor fault",
|
||
|
(uint8_t*)"Alignment check",
|
||
|
(uint8_t*)"Machine check",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved",
|
||
|
(uint8_t*)"Reserved"
|
||
|
};
|
||
|
|
||
|
isr_t interrupt_handler[256];
|
||
|
|
||
|
void isr_handler(registers_t regs) {
|
||
|
if(interrupt_handler[regs.int_num] != 0) {
|
||
|
isr_t handler = interrupt_handler[regs.int_num];
|
||
|
handler(regs);
|
||
|
} else {
|
||
|
kprint_c((uint8_t*)"Received interrupt: ", 20, LIGHT_BROWN, BLACK);
|
||
|
kprint_c(interrupts_messages[(uint8_t)regs.int_num],
|
||
|
strlen(interrupts_messages[(uint8_t)regs.int_num]),
|
||
|
WHITE,
|
||
|
BLACK
|
||
|
);
|
||
|
kprint((uint8_t*)"\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ack_irq(uint32_t int_num) {
|
||
|
// Send and End Of Interrupt(EOF) at the PICs.
|
||
|
if(int_num >= 40)
|
||
|
outb(PIC2_COMMAND, PIC_EOI); // Send reset signal to slave
|
||
|
outb(PIC2_COMMAND, PIC_EOI); // In any case, reset the master
|
||
|
}
|
||
|
|
||
|
void irq_handler(registers_t regs) {
|
||
|
ack_irq(regs.int_num);
|
||
|
|
||
|
if(interrupt_handler[regs.int_num] != 0) {
|
||
|
isr_t handler = interrupt_handler[regs.int_num];
|
||
|
handler(regs);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void register_interrupt_handler(uint8_t n, isr_t handler) {
|
||
|
interrupt_handler[n] = handler;
|
||
|
}
|