diff options
author | Danny Holman <dholman@gymli.xyz> | 2021-09-28 09:04:01 -0500 |
---|---|---|
committer | Danny Holman <dholman@gymli.xyz> | 2021-09-28 09:04:38 -0500 |
commit | 0ad50c878838640ce53c202ab028d7b2c5810fe6 (patch) | |
tree | 77f189f1369a31b1941dfc5cacb8da71fe343aca | |
parent | 7bf2c634fdb55d67affe74a2ed0a157610308942 (diff) |
arch: i386: add support for 8259 PIC
Add support for the 8259 programmable interrupt controller.
Signed-off-by: Danny Holman <dholman@gymli.xyz>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | arch/i386/boot/boot.s | 3 | ||||
-rw-r--r-- | arch/i386/boot/pic.c | 53 | ||||
-rw-r--r-- | arch/i386/include/kernel/pic.h | 45 | ||||
-rw-r--r-- | arch/i386/kernel/pic.h | 16 | ||||
-rw-r--r-- | arch/i386/kernel/serial.c | 2 | ||||
-rw-r--r-- | arch/i386/make.config | 1 |
7 files changed, 103 insertions, 19 deletions
@@ -1,6 +1,6 @@ CC=i686-elf-gcc INCLUDE?=-Iinclude -CFLAGS?=-O2 -ffreestanding -std=gnu11 +CFLAGS?=-O2 -ffreestanding -std=gnu11 LDFLAGS?=-nostdlib LIBS?=-lgcc diff --git a/arch/i386/boot/boot.s b/arch/i386/boot/boot.s index e0005bb..c62abbf 100644 --- a/arch/i386/boot/boot.s +++ b/arch/i386/boot/boot.s @@ -45,7 +45,7 @@ _start: loop 1b 3: movl $(0x000B8000 | 0x003), boot_page_table0 - 0xC0000000 + 1023 * 4 - + movl $(boot_page_table0 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 movl $(boot_page_table0 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 @@ -70,6 +70,7 @@ _start: call gdt_install call idt_install + call pic_remap call kernel_main diff --git a/arch/i386/boot/pic.c b/arch/i386/boot/pic.c new file mode 100644 index 0000000..f103b92 --- /dev/null +++ b/arch/i386/boot/pic.c @@ -0,0 +1,53 @@ +#include <kernel/pic.h> + +void pic_eoi(unsigned char irq) { + if (irq >= 8) + outb(PIC2_COMMAND, 0x20); + outb(PIC1_COMMAND, 0x20); +} + +void pic_remap(void) { + unsigned char a1 = inb(PIC1_DATA); + unsigned char a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + outb(PIC1_DATA, PIC1); + outb(PIC2_DATA, PIC2); + outb(PIC1_DATA, 4); + outb(PIC2_DATA, 2); + outb(PIC1_DATA, ICW4_8086); + outb(PIC2_DATA, ICW4_8086); + outb(PIC1_DATA, a1); + outb(PIC2_DATA, a2); +} + +void irq_set_mask(uint8_t irq) { + uint16_t port; + uint8_t data; + + if (irq < 8) { + port = PIC1_DATA; + } else { + port = PIC2_DATA; + irq -= 8; + } + + data = inb(port) | (1 << irq); + outb(port, data); +} + +void irq_clear_mask(unsigned char irq) { + uint16_t port; + uint8_t data; + + if (irq < 8) { + port = PIC1_DATA; + } else { + port = PIC2_DATA; + irq -= 8; + } + + data = inb(port) & ~(1 << irq); + outb(port, data); +} diff --git a/arch/i386/include/kernel/pic.h b/arch/i386/include/kernel/pic.h new file mode 100644 index 0000000..c3ede4f --- /dev/null +++ b/arch/i386/include/kernel/pic.h @@ -0,0 +1,45 @@ +#ifndef I386_PIC_H +#define I386_PIC_H + +#include <stdint.h> + +#define PIC1 0x20 +#define PIC2 0x28 +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + +#define ICW1_ICW4 0x01 +#define ICW1_SINGLE 0x02 +#define ICW1_INTERVAL4 0x04 +#define ICW1_LEVEL 0x08 +#define ICW1_INIT 0x10 + +#define ICW4_8086 0x01 +#define ICW4_AUTO 0x02 +#define ICW4_BUF_SLAVE 0x08 +#define ICW4_BUF_MASTER 0x0C +#define ICW4_SFNM 0x10 + +static inline void outb(uint16_t port, uint8_t value) { + asm volatile("outb %0, %1" : : "a"(value), "Nd"(port)); +} + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void io_wait(void) { + outb(0x80, 0); +} + +void pic_eoi(unsigned char irq); +void pic_remap(void); + +void irq_set_mask(uint8_t irq); +void irq_clear_mask(uint8_t irq); + +#endif diff --git a/arch/i386/kernel/pic.h b/arch/i386/kernel/pic.h deleted file mode 100644 index da4a2ee..0000000 --- a/arch/i386/kernel/pic.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PIC_H -#define PIC_H - -#include <stdint.h> - -static inline void outb(uint16_t port, uint8_t value) { - asm volatile("outb %0, %1" : : "a"(value), "Nd"(port)); -} - -static inline uint8_t inb(uint16_t port) { - uint8_t ret; - asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; -} - -#endif diff --git a/arch/i386/kernel/serial.c b/arch/i386/kernel/serial.c index 20bd8f9..58163cb 100644 --- a/arch/i386/kernel/serial.c +++ b/arch/i386/kernel/serial.c @@ -1,7 +1,7 @@ #include <kernel/serial.h> +#include <kernel/pic.h> #include <kernel/string.h> #include <stddef.h> -#include "pic.h" #define PORT 0x3f8 diff --git a/arch/i386/make.config b/arch/i386/make.config index c807884..df26a3d 100644 --- a/arch/i386/make.config +++ b/arch/i386/make.config @@ -6,6 +6,7 @@ KERNEL_ARCH_LIBS= KERNEL_ARCH_OBJS=$(ARCHDIR)/boot/boot.o \ $(ARCHDIR)/boot/isr.o \ $(ARCHDIR)/boot/tty.o \ + $(ARCHDIR)/boot/pic.o \ $(ARCHDIR)/boot/gdt.o \ $(ARCHDIR)/boot/idt.o \ $(ARCHDIR)/kernel/serial.o \ |