From b7c0de7ea5bfa2b07af5e8a1b51810ab3690b8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Wed, 9 Nov 2016 21:16:29 +0100 Subject: [PATCH] [INTERRUPTS] IRQs and the Programmable Interrupt Controller --- kernel/boot/kmain.c | 3 ++ kernel/include/int.h | 37 +++++++++++++++++++++++ kernel/interrupts/pic.c | 65 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 kernel/interrupts/pic.c diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 640b996..311334d 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -29,6 +29,7 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) pmm_init(); gdt_init(); scheduler_init(); + pic_init(); process_t *p1 = process_spawn(0); process_t *p2 = process_spawn(p1); @@ -51,6 +52,8 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) scheduler_insert(t2); scheduler_insert(t3); + IRQ_UNMASK(IRQ_TIMER); + asm("sti"); debug_info("BOOT COMPLETE\n"); schedule(); debug_error("PANIC - This line should be unreachable (%s:%d)\n", __FILE__, __LINE__); diff --git a/kernel/include/int.h b/kernel/include/int.h index 84f1588..9e173a7 100644 --- a/kernel/include/int.h +++ b/kernel/include/int.h @@ -33,6 +33,30 @@ #define INT_SX 0x1E // Security exception // Unused exception 0x1F // User interrupts 0x20 and forward +#define INT_IRQ0 0x20 +#define INT_IRQ1 0x21 +#define INT_IRQ2 0x22 +#define INT_IRQ3 0x23 +#define INT_IRQ4 0x24 +#define INT_IRQ5 0x25 +#define INT_IRQ6 0x26 +#define INT_IRQ7 0x27 +#define INT_IRQ8 0x28 +#define INT_IRQ9 0x29 +#define INT_IRQ10 0x2A +#define INT_IRQ11 0x2B +#define INT_IRQ12 0x2C +#define INT_IRQ13 0x2D +#define INT_IRQ14 0x2E +#define INT_IRQ15 0x2F +#define INT_IRQ16 0x30 +#define INT_IRQ17 0x31 +#define INT_IRQ18 0x32 +#define INT_IRQ19 0x33 +#define INT_IRQ20 0x34 +#define INT_IRQ21 0x35 +#define INT_IRQ22 0x36 +#define INT_IRQ23 0x37 #ifndef __ASSEMBLER__ #include @@ -54,6 +78,19 @@ struct idtr uint64_t addr; } __attribute__ ((packed)); +void pic_init(); +void pic_ack(uint8_t irq); +void pic_mask(uint8_t irq); +void pic_unmask(uint8_t irq); +#define IRQ_INT(irq) (INT_IRQ0 + irq) +#define IRQ(irq) (irq) +#define IRQ_MASK(irq) pic_mask(irq) +#define IRQ_UNMASK(irq) pic_unmask(irq) +#define IRQ_ACK(irq) pic_ack(irq) + +#define IRQ_TIMER 0 +#define IRQ_KEYBOARD 1 + typedef struct registers_st { uint64_t rax; diff --git a/kernel/interrupts/pic.c b/kernel/interrupts/pic.c new file mode 100644 index 0000000..85629f4 --- /dev/null +++ b/kernel/interrupts/pic.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#define MPIC_CMD 0x0020 +#define MPIC_DATA 0x0021 +#define SPIC_CMD 0x00A0 +#define SPIC_DATA 0x00A1 + +#define PIC_CMD_INIT 0x10 +#define PIC_CMD_EXTRA 0x01 +#define PIC_CMD_8086 0x01 +#define PIC_CMD_EOI 0x20 + + +void pic_init() +{ + + // Send initialize command + outb(MPIC_CMD, PIC_CMD_INIT | PIC_CMD_EXTRA); + outb(SPIC_CMD, PIC_CMD_INIT | PIC_CMD_EXTRA); + + // Remap offsets + outb(MPIC_DATA, INT_IRQ0); + outb(SPIC_DATA, INT_IRQ8); + + // Setup slave PIC + outb(MPIC_DATA, 0x04); + outb(SPIC_DATA, 0x02); + + // Extra environment data + outb(MPIC_DATA, PIC_CMD_8086); + outb(SPIC_DATA, PIC_CMD_8086); + + // Mask all interrupts + outb(MPIC_DATA, 0xFF); + outb(SPIC_DATA, 0xFF); +} + +void pic_ack(uint8_t irq) +{ + if(irq >= 8) + outb(SPIC_CMD, PIC_CMD_EOI); + outb(MPIC_CMD, PIC_CMD_EOI); +} + +void pic_mask(uint8_t irq) +{ + if(irq >= 8) + { + outb(SPIC_DATA, inb(SPIC_DATA) | 1 << (irq-8)); + } else { + outb(MPIC_DATA, inb(MPIC_DATA) | 1 << irq); + } +} +void pic_unmask(uint8_t irq) +{ + if(irq >= 8) + { + outb(SPIC_DATA, inb(SPIC_DATA) & ~(1 << (irq-8))); + } else { + outb(MPIC_DATA, inb(MPIC_DATA) & ~(1 << irq)); + } +}