From 5bc285b7ca9901ccffa055e1509c0c96cc9650d9 Mon Sep 17 00:00:00 2001 From: shockrahwow Date: Sun, 27 Oct 2019 20:27:46 -0700 Subject: [PATCH] Adding keyboard interrupt handler as of right now its busted(doesn't printanythng) --- interrupt_entry.s | 41 ++++++++++++++++++---------------------- interrupts.c | 48 +++++++++++++++++++++++++++++++++++++++++++---- interrupts.h | 41 ++++++++++++++++------------------------ serial.c | 15 +++++++++++++++ serial.h | 12 ++++++++++++ 5 files changed, 105 insertions(+), 52 deletions(-) diff --git a/interrupt_entry.s b/interrupt_entry.s index 5753e98..52bf2e7 100644 --- a/interrupt_entry.s +++ b/interrupt_entry.s @@ -35,25 +35,28 @@ err_code_handler_%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 - ;push ecx - ;push edx - ;push ebx + ;push eax ecx edx ebx + ;push esp ebp esi edi - ;push esp - ;push ebp - ;push esi - ;push edi + push ds + push es + push fs + push gs - ;push ds - ;push es - ;push fs - ;push gs - - call interrupt_handler + ; 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 gs @@ -61,15 +64,7 @@ common_int_handler: pop es pop ds - pop edi - pop esi - pop ebp - pop esp - - pop ebx - pop edx - pop ecx - pop eax + popad add esp, 8 ; special instruction which lets us jump back to code diff --git a/interrupts.c b/interrupts.c index 7ad32ed..ac65cda 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,8 +1,33 @@ +#include "stlio.h" #include "interrupts.h" +#include "serial.h" #include "mem.h" #include "types.h" -extern void load_idt(); +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_1(); extern void no_err_handler_2(); extern void no_err_handler_3(); @@ -52,12 +77,27 @@ void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs) { IDT[t_idx].selector = sel; } +void int_keyboard(struct cpu_reg_state* cpu) { + // Get the keycode from the serial buffer + u8 buf[5]; + memset(buf, 0x00, 5); + u8 scancode = serial_read_buffer(0x60); + buf[0] = scancode; + printf((char*)buf); + serial_pic_ack(cpu->int_no); +} + // Generic interrupt handler to be used later on -void interrupt_handler(struct cpu_reg_state cpu, struct stack_state stack, u32 interrupt_code) { +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 - cpu.eax += 1; - stack.error_code += interrupt_code; + switch(cpu.int_no) { + case(i_Keyboard): { + // keyboard interrupt handler gets the stuff now + int_keyboard(&cpu); + } + } + return; } void init_idt() { diff --git a/interrupts.h b/interrupts.h index fad543e..09c0a21 100644 --- a/interrupts.h +++ b/interrupts.h @@ -1,32 +1,22 @@ #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 eax; - u32 ecx; - u32 edx; - u32 ebx; + 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 - u32 esp; - u32 ebp; - u32 esi; - u32 edi; - - u16 ds; - u16 es; - u16 fs; - u16 gs; - - u32 eflags; -}__attribute__((packed)); - -// Populated by the interrupt handler itself -struct stack_state { - u32 error_code; // 8 10 11 12 13 14 17 <= ony interrupts that actually use the error code - u32 eip; - u16 cs; - u32 eflags; -}; #define IDT_SIZE 256 @@ -53,4 +43,5 @@ struct IDT_PTR idt_ptr; void init_idt(); void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs); -//void interrupt_handler(struct cpu_reg_state, struct stack_state, u32); +void int_keyboard(struct cpu_reg_state*); +void interrupt_handler(struct cpu_reg_state); diff --git a/serial.c b/serial.c index 4a91058..26185e5 100644 --- a/serial.c +++ b/serial.c @@ -72,3 +72,18 @@ u64 serial_write(const char* buffer, const u64 size) { return idx; } + +void serial_pic_ack(u32 interrupt) { + // ignore things that are too small and too big + if(interrupt < PIC1_START_INT || interrupt > PIC2_END_INT) { + return; + } + // Send acknoldgement to the pic that we have handled the interrupt + // without this it literally just wait for the ack + if(interrupt < PIC2_START_INT) { + serialport_write_byte(PIC1_PORT, PIC_ACK); + } + else { + serialport_write_byte(PIC2_PORT, PIC_ACK); + } +} \ No newline at end of file diff --git a/serial.h b/serial.h index bf8c2bf..6c32005 100644 --- a/serial.h +++ b/serial.h @@ -21,6 +21,17 @@ #define SERIAL_DEFAULT_MODEM_CFG 0x03 #define SERIAL_FIFO_EMPTY_CODE 0x20 + +#define PIC1_PORT 0x20 +#define PIC2_PORT 0xA0 + +#define PIC1_START_INT 0x20 +#define PIC1_END_INT 0x27 +#define PIC2_START_INT 0x28 +#define PIC2_END_INT 0x2F + +#define PIC_ACK 0x20 + void serial_set_baud_rate(const u16, const u16); void serial_configure_line(const u16, const u8); @@ -29,3 +40,4 @@ u8 serial_fifo_empty(const u16); u64 serial_write(const char* buffer, const u64 size); +void serial_pic_ack(u32 interrupt);