Moving components modules to a more proper directory
This commit is contained in:
170
components/interrupts/interrupt_entry.s
Normal file
170
components/interrupts/interrupt_entry.s
Normal file
@@ -0,0 +1,170 @@
|
||||
; Dispatching to our interrupt handler code from assembly because some of this is
|
||||
; enourmous pain in C
|
||||
|
||||
; Save the register state
|
||||
; call the C handler
|
||||
; executes iret(expects the stack to look like struct stack_state)
|
||||
|
||||
|
||||
; If the interrupt we need to handle doesn't produce an error code then must provide a 0
|
||||
; for consistency
|
||||
|
||||
extern interrupt_handler
|
||||
extern cpu_reg_state
|
||||
extern stack_state
|
||||
extern idt_ptr
|
||||
extern irq_handler
|
||||
|
||||
global load_idt
|
||||
load_idt:
|
||||
lidt [idt_ptr]
|
||||
ret
|
||||
|
||||
%macro irq 2
|
||||
global irq_handler_%1
|
||||
irq_handler_%1:
|
||||
push dword 0
|
||||
push dword %2
|
||||
jmp common_irq_handler
|
||||
%endmacro
|
||||
|
||||
%macro no_err_handler 1
|
||||
global no_err_handler_%1 ; defined in interrupts.h
|
||||
no_err_handler_%1:
|
||||
push dword 0
|
||||
push dword %1
|
||||
jmp common_int_handler
|
||||
%endmacro
|
||||
|
||||
; deals with the intterrupts that do give us an error code
|
||||
%macro err_code_handler 1
|
||||
global err_code_handler_%1
|
||||
err_code_handler_%1:
|
||||
push dword %1
|
||||
jmp common_int_handler
|
||||
%endmacro
|
||||
|
||||
extern interrupt_handler ; external handler (interrupts.c)
|
||||
common_int_handler:
|
||||
; save thigns before do our C-call
|
||||
pushad
|
||||
;push eax ecx edx ebx
|
||||
;push esp ebp esi edi
|
||||
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
; load the kernel segment descriptor
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov eax, esp ; pushing the stack into the next call
|
||||
push eax
|
||||
mov eax, interrupt_handler
|
||||
call eax ; preserve the eip register past this call
|
||||
|
||||
; segments
|
||||
pop eax
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
popad
|
||||
|
||||
add esp, 8
|
||||
; special instruction which lets us jump back to code
|
||||
; which was previously interrupted
|
||||
iret
|
||||
|
||||
|
||||
no_err_handler 0
|
||||
no_err_handler 1
|
||||
no_err_handler 2
|
||||
no_err_handler 3
|
||||
no_err_handler 4
|
||||
no_err_handler 5
|
||||
no_err_handler 6
|
||||
no_err_handler 7
|
||||
|
||||
err_code_handler 8
|
||||
|
||||
no_err_handler 9
|
||||
|
||||
err_code_handler 10
|
||||
err_code_handler 11
|
||||
err_code_handler 12
|
||||
err_code_handler 13
|
||||
err_code_handler 14
|
||||
|
||||
no_err_handler 15
|
||||
no_err_handler 16
|
||||
no_err_handler 17
|
||||
no_err_handler 18
|
||||
no_err_handler 19
|
||||
no_err_handler 20
|
||||
no_err_handler 21
|
||||
no_err_handler 22
|
||||
no_err_handler 23
|
||||
no_err_handler 24
|
||||
no_err_handler 25
|
||||
no_err_handler 26
|
||||
no_err_handler 27
|
||||
no_err_handler 28
|
||||
no_err_handler 29
|
||||
no_err_handler 30
|
||||
no_err_handler 31
|
||||
|
||||
|
||||
common_irq_handler:
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
mov eax, esp
|
||||
push eax
|
||||
mov eax, irq_handler
|
||||
call eax
|
||||
pop eax
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
popa
|
||||
add esp, 8
|
||||
iret
|
||||
|
||||
|
||||
; Remapped IRQ's for the APIC
|
||||
|
||||
; starting from irq 0 -> 15 but remapped to 32 -> 47
|
||||
irq 0, 32
|
||||
irq 1, 33
|
||||
irq 2, 34
|
||||
irq 3, 35
|
||||
irq 4, 36
|
||||
irq 5, 37
|
||||
irq 6, 38
|
||||
irq 7, 39
|
||||
irq 8, 40
|
||||
irq 9, 41
|
||||
irq 10, 42
|
||||
irq 11, 43
|
||||
irq 12, 44
|
||||
irq 13, 45
|
||||
irq 14, 46
|
||||
irq 15, 47
|
||||
217
components/interrupts/interrupts.c
Normal file
217
components/interrupts/interrupts.c
Normal file
@@ -0,0 +1,217 @@
|
||||
#include "stlio.h"
|
||||
#include "interrupts.h"
|
||||
#include "serial.h"
|
||||
#include "mem.h"
|
||||
#include "types.h"
|
||||
#include "ports.h"
|
||||
#include "pit.h"
|
||||
#include "kbd.h"
|
||||
|
||||
const char* err_msg[] = {
|
||||
"Divide by zero\n",
|
||||
"Debug Exception\n",
|
||||
"Non Maskable Interrupt Exception\n",
|
||||
"Breakpoint Exception\n",
|
||||
"Into Detected Overflow Exception\n",
|
||||
"Out of Bounds Exception\n",
|
||||
"Invalid Opcode Exception\n",
|
||||
"No Coprocessor Exception\n",
|
||||
"Double Fault Exception\n",
|
||||
"Coprocessor Segment Overrun Exception\n",
|
||||
"Bad TSS Exception\n",
|
||||
"Segment Not Present Exception\n",
|
||||
"Stack Fault Exception\n",
|
||||
"General Protection Fault Exception\n",
|
||||
"Page Fault Exception\n",
|
||||
"Unknown Interrupt Exception\n",
|
||||
"Coprocessor Fault Exception\n",
|
||||
"Alignment Check Exception (486+)\n",
|
||||
"Machine Check Exception (Pentium/586+)\n",
|
||||
"Reserved Exceptions\n", /* for 19 - 31 */
|
||||
};
|
||||
|
||||
extern void load_idt(); // found in interrupts_entry.s
|
||||
extern void no_err_handler_0();
|
||||
extern void no_err_handler_1();
|
||||
extern void no_err_handler_2();
|
||||
extern void no_err_handler_3();
|
||||
extern void no_err_handler_4();
|
||||
extern void no_err_handler_5();
|
||||
extern void no_err_handler_6();
|
||||
extern void no_err_handler_7();
|
||||
|
||||
extern void err_code_handler_8();
|
||||
|
||||
extern void no_err_handler_9();
|
||||
|
||||
extern void err_code_handler_10();
|
||||
extern void err_code_handler_11();
|
||||
extern void err_code_handler_12();
|
||||
extern void err_code_handler_13();
|
||||
extern void err_code_handler_14();
|
||||
|
||||
extern void no_err_handler_15();
|
||||
extern void no_err_handler_16();
|
||||
extern void no_err_handler_17();
|
||||
extern void no_err_handler_18();
|
||||
extern void no_err_handler_19();
|
||||
extern void no_err_handler_20();
|
||||
extern void no_err_handler_21();
|
||||
extern void no_err_handler_22();
|
||||
extern void no_err_handler_23();
|
||||
extern void no_err_handler_24();
|
||||
extern void no_err_handler_25();
|
||||
extern void no_err_handler_26();
|
||||
extern void no_err_handler_27();
|
||||
extern void no_err_handler_28();
|
||||
extern void no_err_handler_29();
|
||||
extern void no_err_handler_30();
|
||||
extern void no_err_handler_31();
|
||||
|
||||
// Remapped IRQ's
|
||||
extern void irq_handler_0();
|
||||
extern void irq_handler_1();
|
||||
extern void irq_handler_2();
|
||||
extern void irq_handler_3();
|
||||
extern void irq_handler_4();
|
||||
extern void irq_handler_5();
|
||||
extern void irq_handler_6();
|
||||
extern void irq_handler_7();
|
||||
extern void irq_handler_8();
|
||||
extern void irq_handler_9();
|
||||
extern void irq_handler_10();
|
||||
extern void irq_handler_11();
|
||||
extern void irq_handler_12();
|
||||
extern void irq_handler_13();
|
||||
extern void irq_handler_14();
|
||||
extern void irq_handler_15();
|
||||
|
||||
void* irq_handlers[16] = {0};
|
||||
|
||||
void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs) {
|
||||
// Configuring a single given entry in the IDT table
|
||||
IDT[t_idx].offset_low = (base & 0xffff);
|
||||
IDT[t_idx].offset_high = ((base >> 16) & 0xffff);
|
||||
|
||||
IDT[t_idx].type_attrs = type_attrs;
|
||||
IDT[t_idx].zero = 0;
|
||||
IDT[t_idx].selector = sel;
|
||||
}
|
||||
|
||||
// Generic interrupt handler to be used later on
|
||||
void interrupt_handler(struct cpu_reg_state* cpu) {
|
||||
// treating things on the stack like it were a cpu_reg_state
|
||||
// NOTE: dummy stuff to stop gcc from complaining atm
|
||||
printf("handled exception\n");
|
||||
if(cpu->int_no < 32) {
|
||||
printf(err_msg[cpu->int_no]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the index into the table and the handler(strut* cpu_reg_state)
|
||||
void init_irq_handler(u32 irq, void (*handler)(struct cpu_reg_state* cpu)) {
|
||||
// install handle
|
||||
irq_handlers[irq] = handler;
|
||||
}
|
||||
|
||||
void irq_handler(struct cpu_reg_state* cpu) {
|
||||
void (*handler)(struct cpu_reg_state* cpu);
|
||||
// Dispatcher for irq's
|
||||
handler = irq_handlers[cpu->int_no - 0x20];
|
||||
// Handler the timer by hand because fuck this tbh
|
||||
if(handler) {
|
||||
handler(cpu);
|
||||
}
|
||||
// pretend like nothing happend for now
|
||||
if(cpu->int_no >= 40) {
|
||||
serialport_write_byte(0xa0, 0x20);
|
||||
}
|
||||
// notify master pic controller that we're done handling the interrupt
|
||||
serialport_write_byte(0x20, 0x20);
|
||||
}
|
||||
|
||||
void init_idt() {
|
||||
// setup special idt pointer
|
||||
idt_ptr.address = (u32)(&IDT);
|
||||
idt_ptr.limit = (sizeof(struct IDT_Entry) * IDT_SIZE) - 1;
|
||||
// clear table
|
||||
memset((u8*)IDT, 0x00, (sizeof(struct IDT_Entry) * IDT_SIZE));
|
||||
// add interrupt service routines here
|
||||
setup_idt_entry(0,(u32)no_err_handler_0,0x08, 0x8e);
|
||||
setup_idt_entry(1,(u32)no_err_handler_1,0x08, 0x8e);
|
||||
setup_idt_entry(2,(u32)no_err_handler_2,0x08, 0x8e);
|
||||
setup_idt_entry(3,(u32)no_err_handler_3,0x08, 0x8e);
|
||||
setup_idt_entry(4,(u32)no_err_handler_4,0x08, 0x8e);
|
||||
setup_idt_entry(5,(u32)no_err_handler_5,0x08, 0x8e);
|
||||
setup_idt_entry(6,(u32)no_err_handler_6,0x08, 0x8e);
|
||||
setup_idt_entry(7,(u32)no_err_handler_7,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(8,(u32)err_code_handler_8,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(9,(u32)no_err_handler_9,0x08, 0x8e);
|
||||
|
||||
|
||||
setup_idt_entry(10,(u32)err_code_handler_10,0x08, 0x8e);
|
||||
setup_idt_entry(11,(u32)err_code_handler_11,0x08, 0x8e);
|
||||
setup_idt_entry(12,(u32)err_code_handler_12,0x08, 0x8e);
|
||||
setup_idt_entry(13,(u32)err_code_handler_13,0x08, 0x8e);
|
||||
setup_idt_entry(14,(u32)err_code_handler_14,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(15,(u32)no_err_handler_15,0x08, 0x8e);
|
||||
setup_idt_entry(16,(u32)no_err_handler_16,0x08, 0x8e);
|
||||
setup_idt_entry(17,(u32)no_err_handler_17,0x08, 0x8e);
|
||||
setup_idt_entry(18,(u32)no_err_handler_18,0x08, 0x8e);
|
||||
setup_idt_entry(19,(u32)no_err_handler_19,0x08, 0x8e);
|
||||
setup_idt_entry(20,(u32)no_err_handler_20,0x08, 0x8e);
|
||||
setup_idt_entry(21,(u32)no_err_handler_21,0x08, 0x8e);
|
||||
setup_idt_entry(22,(u32)no_err_handler_22,0x08, 0x8e);
|
||||
setup_idt_entry(23,(u32)no_err_handler_23,0x08, 0x8e);
|
||||
setup_idt_entry(24,(u32)no_err_handler_24,0x08, 0x8e);
|
||||
setup_idt_entry(25,(u32)no_err_handler_25,0x08, 0x8e);
|
||||
setup_idt_entry(26,(u32)no_err_handler_26,0x08, 0x8e);
|
||||
setup_idt_entry(27,(u32)no_err_handler_27,0x08, 0x8e);
|
||||
setup_idt_entry(28,(u32)no_err_handler_28,0x08, 0x8e);
|
||||
setup_idt_entry(29,(u32)no_err_handler_29,0x08, 0x8e);
|
||||
setup_idt_entry(30,(u32)no_err_handler_30,0x08, 0x8e);
|
||||
setup_idt_entry(31,(u32)no_err_handler_31,0x08, 0x8e);
|
||||
|
||||
// Load IDT with all the new information in place, ready to use
|
||||
load_idt();
|
||||
|
||||
// clear table in case there's garbage in there
|
||||
memset((u8*)irq_handlers, 0, sizeof(void*));
|
||||
irq_handlers[0] = pit_inc_ticks; // LULW
|
||||
|
||||
// Remap irq's to proper location
|
||||
serialport_write_byte(0x20, 0x11);
|
||||
serialport_write_byte(0xA0, 0x11);
|
||||
serialport_write_byte(0x21, 0x20);
|
||||
serialport_write_byte(0xA1, 0x28);
|
||||
serialport_write_byte(0x21, 0x04);
|
||||
serialport_write_byte(0xA1, 0x02);
|
||||
serialport_write_byte(0x21, 0x01);
|
||||
serialport_write_byte(0xA1, 0x01);
|
||||
serialport_write_byte(0x21, 0x0);
|
||||
serialport_write_byte(0xA1, 0x0);
|
||||
|
||||
// Install handlers for irq's
|
||||
setup_idt_entry(32,(u32)irq_handler_0,0x08, 0x8e);
|
||||
setup_idt_entry(33,(u32)irq_handler_1,0x08, 0x8e);
|
||||
setup_idt_entry(34,(u32)irq_handler_2,0x08, 0x8e);
|
||||
setup_idt_entry(35,(u32)irq_handler_3,0x08, 0x8e);
|
||||
setup_idt_entry(36,(u32)irq_handler_4,0x08, 0x8e);
|
||||
setup_idt_entry(37,(u32)irq_handler_5,0x08, 0x8e);
|
||||
setup_idt_entry(38,(u32)irq_handler_6,0x08, 0x8e);
|
||||
setup_idt_entry(39,(u32)irq_handler_7,0x08, 0x8e);
|
||||
setup_idt_entry(40,(u32)irq_handler_8,0x08, 0x8e);
|
||||
setup_idt_entry(41,(u32)irq_handler_9,0x08, 0x8e);
|
||||
setup_idt_entry(42,(u32)irq_handler_10,0x08, 0x8e);
|
||||
setup_idt_entry(43,(u32)irq_handler_11,0x08, 0x8e);
|
||||
setup_idt_entry(44,(u32)irq_handler_12,0x08, 0x8e);
|
||||
setup_idt_entry(45,(u32)irq_handler_13,0x08, 0x8e);
|
||||
setup_idt_entry(46,(u32)irq_handler_14,0x08, 0x8e);
|
||||
setup_idt_entry(47,(u32)irq_handler_15,0x08, 0x8e);
|
||||
// Enable interrupt flags
|
||||
__asm__ __volatile__("sti");
|
||||
}
|
||||
55
components/interrupts/interrupts.h
Normal file
55
components/interrupts/interrupts.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERRUPTS_H
|
||||
#define INTERRUPTS_H
|
||||
#include "types.h"
|
||||
|
||||
// There are more interrupts but tbh i doubt we're going to need them
|
||||
#define i_Timer 0
|
||||
#define i_Keyboard 1
|
||||
#define i_PIC2 2
|
||||
#define i_COM2 3
|
||||
#define i_COM1 4
|
||||
#define i_LPT2 5
|
||||
|
||||
|
||||
struct cpu_reg_state {
|
||||
u32 gs, fs, es, ds; // segment registers
|
||||
u32 edi, esi, ebp, esp; // generaal purupose via pushad
|
||||
u32 ebx, edx, ecx, eax;
|
||||
u32 int_no, err_code; // pushed by each interrupt dispatcher
|
||||
u32 eip, cs, eflags, useresp, ss; // processor pushes this automatically
|
||||
}__attribute__((packed)); // we shouldn't need packing since everythign is dwords here
|
||||
|
||||
|
||||
#define IDT_SIZE 256
|
||||
|
||||
struct IDT_Entry {
|
||||
u16 offset_low; // offset bits 0..15
|
||||
u16 selector; // code segment in either gdt or ldt
|
||||
u8 zero; // not used always 0
|
||||
/* 7 0
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | P | DPL | S | GateType |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
u8 type_attrs; // format specified above
|
||||
u16 offset_high;// offset bits 16..31
|
||||
}__attribute__((packed));
|
||||
|
||||
struct IDT_PTR {
|
||||
u16 limit;
|
||||
u32 address;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct IDT_Entry IDT[IDT_SIZE];
|
||||
struct IDT_PTR idt_ptr;
|
||||
|
||||
void init_idt();
|
||||
void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs);
|
||||
void int_keyboard(struct cpu_reg_state*);
|
||||
void interrupt_handler(struct cpu_reg_state*);
|
||||
|
||||
|
||||
// IRQ specifi functions
|
||||
void init_irq_handler(u32 irq, void (*handler)(struct cpu_reg_state* cpu));
|
||||
void irq_handler(struct cpu_reg_state* cpu);
|
||||
#endif
|
||||
Reference in New Issue
Block a user