summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-01-29 18:20:21 -0500
committerFreya Murphy <freya@freyacat.org>2024-01-29 18:20:21 -0500
commit0d2f0d2491be3429a634f1470701bf0790f05111 (patch)
tree0c6cd737ca3a5bcda049539bb1e93322790c7634
parentthings (diff)
downloadcorn-0d2f0d2491be3429a634f1470701bf0790f05111.tar.gz
corn-0d2f0d2491be3429a634f1470701bf0790f05111.tar.bz2
corn-0d2f0d2491be3429a634f1470701bf0790f05111.zip
pic
-rw-r--r--src/arch/amd64/pic.c78
-rw-r--r--src/arch/amd64/pic.h31
-rw-r--r--src/arch/amd64/shim.c3
3 files changed, 112 insertions, 0 deletions
diff --git a/src/arch/amd64/pic.c b/src/arch/amd64/pic.c
new file mode 100644
index 0000000..ebf6b40
--- /dev/null
+++ b/src/arch/amd64/pic.c
@@ -0,0 +1,78 @@
+#include "bindings.h"
+#include "pic.h"
+
+#define PIC1_COMMAND_PORT 0x20
+#define PIC1_DATA_PORT 0x21
+#define PIC2_COMMAND_PORT 0xA0
+#define PIC2_DATA_PORT 0xA1
+
+void pic_remap(void) {
+ char a1 = inb(PIC1_DATA_PORT);
+ char a2 = inb(PIC2_DATA_PORT);
+ // control word 1
+ // 0x11: initialize, enable ICW4
+ outb(PIC1_COMMAND_PORT, 0x11);
+ io_wait();
+ outb(PIC2_COMMAND_PORT, 0x11);
+ io_wait();
+ // control word 2
+ // interrupt offset
+ outb(PIC1_DATA_PORT, PIC_REMAP_OFFSET);
+ io_wait();
+ outb(PIC2_DATA_PORT, PIC_REMAP_OFFSET + 8);
+ io_wait();
+ // control word 3
+ // primary pic: set which pin secondary is connected to
+ // (pin 2)
+ outb(PIC1_DATA_PORT, 0x04);
+ io_wait();
+ outb(PIC2_DATA_PORT, 2);
+ io_wait();
+ // control word 3
+ // 0x01: enable 8086 mode
+ outb(PIC1_DATA_PORT, 0x01);
+ io_wait();
+ outb(PIC2_DATA_PORT, 0x01);
+ io_wait();
+ // clear data registers
+ outb(PIC1_DATA_PORT, a1);
+ outb(PIC2_DATA_PORT, a2);
+}
+
+void pic_mask(int irq) {
+ uint8_t port;
+ if(irq < 8) {
+ port = PIC1_DATA_PORT;
+ } else {
+ irq -= 8;
+ port = PIC2_DATA_PORT;
+ }
+ uint8_t mask = inb(port);
+ outb(port, mask | (1 << irq));
+}
+
+void pic_unmask(int irq) {
+ uint8_t port;
+ if(irq < 8) {
+ port = PIC1_DATA_PORT;
+ } else {
+ irq -= 8;
+ port = PIC2_DATA_PORT;
+ }
+ uint8_t mask = inb(port);
+ outb(port, mask & ~(1 << irq));
+}
+
+void pic_disable(void) {
+ outb(PIC1_DATA_PORT, 0xff);
+ io_wait();
+ outb(PIC2_DATA_PORT, 0xff);
+ io_wait();
+}
+
+void pic_eoi(int irq) {
+ if(irq >= 8) {
+ outb(PIC2_COMMAND_PORT, 0x20);
+ }
+ outb(PIC1_COMMAND_PORT, 0x20);
+}
diff --git a/src/arch/amd64/pic.h b/src/arch/amd64/pic.h
new file mode 100644
index 0000000..2a4670e
--- /dev/null
+++ b/src/arch/amd64/pic.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#define PIC_REMAP_OFFSET 0x20
+
+/**
+ * Remaps the pie, i.e. initializes it
+ */
+void pic_remap(void);
+
+/**
+ * Masks an external irq to stop firing until un masked
+ * @param irq - the irq to mask
+ */
+void pic_mask(int irq);
+
+/**
+ * Unmasks an external irq to allow interrupts to continue for that irq
+ * @param irq - the irq to unmask
+ */
+void pic_unmask(int irq);
+
+/**
+ * Disabled the pick
+ */
+void pic_disable(void);
+
+/**
+ * Tells the pick that the interrupt has ended
+ * @param irq - the irq that has ended
+ */
+void pic_eoi(int irq);
diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c
index 5639aab..ec030db 100644
--- a/src/arch/amd64/shim.c
+++ b/src/arch/amd64/shim.c
@@ -7,12 +7,15 @@
#include "paging.h"
#include "mboot.h"
#include "idt.h"
+#include "pic.h"
+
static struct boot_info boot_info;
void* amd64_shim(void *mboot_data_ptr) {
serial_init();
paging_init();
idt_init();
+ pic_remap();
kmap_page(mboot_data_ptr, mboot_data_ptr, F_WRITEABLE);