summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.xyz>2021-09-28 09:04:01 -0500
committerDanny Holman <dholman@gymli.xyz>2021-09-28 09:04:38 -0500
commit0ad50c878838640ce53c202ab028d7b2c5810fe6 (patch)
tree77f189f1369a31b1941dfc5cacb8da71fe343aca
parent7bf2c634fdb55d67affe74a2ed0a157610308942 (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--Makefile2
-rw-r--r--arch/i386/boot/boot.s3
-rw-r--r--arch/i386/boot/pic.c53
-rw-r--r--arch/i386/include/kernel/pic.h45
-rw-r--r--arch/i386/kernel/pic.h16
-rw-r--r--arch/i386/kernel/serial.c2
-rw-r--r--arch/i386/make.config1
7 files changed, 103 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 9ce287d..52fda4e 100644
--- a/Makefile
+++ b/Makefile
@@ -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 \