diff --git a/idt.c b/idt.c index 6ea8a02..6a63af3 100644 --- a/idt.c +++ b/idt.c @@ -42,3 +42,23 @@ int idtSetup() return 0; } +int idt_set_handler(int index, unsigned int addr, int priviledge) +{ + struct idtEntry *idte; + + if (index < 0 || index >= IDT_NUM) + return -1; + if ((priviledge < 0) || priviledge > 3) + return -1; + + idte = &idt[index]; + + if (addr != (unsigned int)NULL) { + idte->offset_low = addr && 0xffff; + idte->offset_high = (addr >> 16) && 0xffff; + idte->dpl = priviledge; + idte->present = 1; + } + + return 0; +} diff --git a/idt.h b/idt.h index 35ac63d..a87266d 100644 --- a/idt.h +++ b/idt.h @@ -42,3 +42,4 @@ struct idtRegister { ((index) << 3)) int idtSetup(); +int idt_set_handler(int index, unsigned int addr, int priviledge); diff --git a/irq.c b/irq.c index de6fe45..7fe27f4 100644 --- a/irq.c +++ b/irq.c @@ -1,8 +1,32 @@ #include "irq.h" +#include "idt.h" #include "pic.h" +#include "types.h" int irqSetup() { initPic(); return 0; } + +irq_handler irq_handler_array[IRQ_NUM] = {NULL, }; + +int irqSetRoutine(int irq, irq_handler handler) +{ + uint32_t flags; + if ((irq < 0) || irq >= IRQ_NUM) + return -1; + + disable_IRQs(flags); + + irq_handler_array[irq] = handler; + + if (handler != NULL) { + int ret = + idt_set_handler(IRQ_BASE_ADDRESS + irq, (unsigned int)irq_handler_array[irq], 0); + if (!ret) + enableIrq(irq); + } + restore_IRQs(flags); + return 0; +} diff --git a/irq.h b/irq.h index 3e3b608..6277e81 100644 --- a/irq.h +++ b/irq.h @@ -1,5 +1,16 @@ #pragma once +#define save_flags(flags) asm volatile("pushfl ; popl %0" : "=g"(flags)::"memory") +#define restore_flags(flags) asm volatile("push %0; popfl" ::"g"(flags) : "memory") + +#define disable_IRQs(flags) \ + ({ \ + save_flags(flags); \ + asm("cli\n"); \ + }) +#define restore_IRQs(flags) restore_flags(flags) + + #define IRQ_TIMER 0 // MASTER IRQ #define IRQ_KEYBOARD 1 #define IRQ_SLAVE_PIC 2 @@ -17,5 +28,12 @@ #define IRQ_HARDDISK 14 #define IRQ_RESERVED_5 15 -typedef void (*irq_handler)(int irq); +#define IRQ_BASE_ADDRESS 0x20 +#define IRQ_NUM 16 + +// An handler should finish by the iret opcode -> https://wiki.osdev.org/Interrupt_Service_Routines +// That's why we use wrapper around them or the gcc interrupt attribut +// __attribute__((interrupt)) void (*irq_handler)(int irq); +typedef void (*irq_handler)(int *irq); int irqSetup(); +int irqSetRoutine(int irq, irq_handler handler); diff --git a/main.c b/main.c index a6884c0..478839d 100644 --- a/main.c +++ b/main.c @@ -6,32 +6,45 @@ char getScancode() { - char c = 0; - do { - if (inb(0x60) != c) { - c = inb(0x60); - if (c > 0) - return c; - } - } while (1); + char c = 0; + do { + if (inb(0x60) != c) { + c = inb(0x60); + if (c > 0) + return c; + } + } while (1); } void cpuid(int code, uint32_t *a, uint32_t *d) { - asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); + asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); +} + +void keyboard_handler(int *id) +{ + __asm__("pushal"); + (void)id; + const char *tictac = "tic tac"; + const short color = RED; + printString(tictac, color, BLACK, 0, 3); + __asm__("popal; leave; iret"); } void kmain() { - const short color = GREEN; - clearScreen(BLACK); - printString("Setting up IDT", color, BLACK, 0, 0); - idtSetup(); - printString("Setting up IRQ", color, BLACK, 0, 1); - irqSetup(); + const short color = GREEN; + clearScreen(BLACK); + printString("Setting up IDT", color, BLACK, 0, 0); + idtSetup(); + printString("Setting up IRQ", color, BLACK, 0, 1); + irqSetup(); - while (1) { - char c = getScancode(); - printChar(c, color, BLACK, 0, 5); - } + irqSetRoutine(IRQ_KEYBOARD, keyboard_handler); + // Enabling the HW interrupts + //asm volatile("sti\n"); + while (1) { + char c = getScancode(); + printChar(c, color, BLACK, 0, 5); + } } diff --git a/mbr.asm b/mbr.asm index 577597e..d82c7c4 100644 --- a/mbr.asm +++ b/mbr.asm @@ -83,6 +83,7 @@ main: mov ax, 0x3 int 0x10 + ; http://www.ctyme.com/intr/rb-0607.htm ; Bios read first 512 bytes, read next disk sector mov ah, 0x2 ;read sectors mov al, 6 ;sectors to read diff --git a/pic.c b/pic.c index 4c7b279..844d55a 100644 --- a/pic.c +++ b/pic.c @@ -1,29 +1,30 @@ #include "pic.h" #include "io.h" +#include "irq.h" -#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ -#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ -#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ -#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ -#define ICW1_INIT 0x10 /* Initialization - required! */ +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ -#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ -#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ -#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ -#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ -#define ICW4_SFNM 0x10 /* Special fully nested (not) */ +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ void initPic(void) { - /* Send CMD: Init + senquence in 4 DATA */ + /* Send CMD: Init + sequence in 4 DATA */ outb(ICW1_INIT + ICW1_ICW4, PIC_MASTER_CMD); outb(ICW1_INIT + ICW1_ICW4, PIC_SLAVE_CMD); /* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as * intel * reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */ - outb(0x20, PIC_MASTER_DATA); - outb(0x28, PIC_SLAVE_DATA); + outb(IRQ_BASE_ADDRESS, PIC_MASTER_DATA); + outb(IRQ_BASE_ADDRESS + 8, PIC_SLAVE_DATA); /* Send ICW3 master: mask where slaves are connected */ outb(0x4, PIC_MASTER_DATA); diff --git a/types.h b/types.h index 1d00f76..5601972 100644 --- a/types.h +++ b/types.h @@ -34,3 +34,5 @@ typedef __u32 uint32_t; typedef __u64 uint64_t; typedef __u64 u_int64_t; typedef __s64 int64_t; + +#define NULL ((void*)0)