Adding keyboard interrupt handler

as of right now its busted(doesn't printanythng)
This commit is contained in:
shockrahwow 2019-10-27 20:27:46 -07:00
parent a0752cba62
commit 5bc285b7ca
5 changed files with 105 additions and 52 deletions

View File

@ -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

View File

@ -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() {

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);