summaryrefslogtreecommitdiff
path: root/kernel/src/apic/ioapic.c
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksa@vuckovic.cc>2023-02-16 21:46:25 +0100
committerAleksa Vuckovic <aleksa@vuckovic.cc>2023-02-16 23:49:29 +0100
commit2bb4e7fb4c0f5895148bb32da64381b985c8dcef (patch)
tree1e1fa9a38dba75d0ca0b5fea85b63c8ca0b05a8f /kernel/src/apic/ioapic.c
parentbf20ce47a9d5dcad841e4549a68f4ec3db3c57de (diff)
code refactoring
Diffstat (limited to 'kernel/src/apic/ioapic.c')
-rw-r--r--kernel/src/apic/ioapic.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/kernel/src/apic/ioapic.c b/kernel/src/apic/ioapic.c
new file mode 100644
index 0000000..a8c3452
--- /dev/null
+++ b/kernel/src/apic/ioapic.c
@@ -0,0 +1,67 @@
+#include <ioapic.h>
+#include <apic.h>
+#include <paging.h>
+#include <libk/stdio.h>
+
+void ioapic_eoi()
+{
+ *((volatile uint32_t*)((uint64_t)lapic_addr + 0xB0)) = 0;
+}
+
+uint32_t ioapic_read(const uint8_t offset)
+{
+ /* tell IOREGSEL where we want to read from */
+ *(volatile uint32_t*)(uint64_t)ioapic_addr = offset;
+ /* return the data from IOWIN */
+ return *(volatile uint32_t*)((uint64_t)ioapic_addr + 0x10);
+}
+
+void ioapic_write(const uint8_t offset, const uint32_t val)
+{
+ /* tell IOREGSEL where we want to write to */
+ *(volatile uint32_t*)(uint64_t)ioapic_addr = offset;
+ /* write the value to IOWIN */
+ *(volatile uint32_t*)((uint64_t)ioapic_addr + 0x10) = val;
+}
+
+void ioapic_set_irq(uint8_t irq, uint64_t apic_id, uint8_t vector)
+{
+ const uint32_t low_index = (uint32_t)0x10 + irq*2;
+ const uint32_t high_index = (uint32_t)0x10 + irq*2 + 1;
+
+ uint32_t high = ioapic_read((uint8_t)high_index);
+ // set APIC ID
+ high &= (uint32_t)~0xff000000;
+ high |= (uint32_t)apic_id << 24;
+ ioapic_write((uint8_t)high_index, high);
+
+ uint32_t low = ioapic_read((uint8_t)low_index);
+
+ // unmask the IRQ
+ low &= (uint32_t)~(1<<16);
+
+ // set to physical delivery mode
+ low &= (uint32_t)~(1<<11);
+
+ // set to fixed delivery mode
+ low &= (uint32_t)~0x700;
+
+ // set delivery vector
+ low &= (uint32_t)~0xff;
+ low |= vector;
+
+ ioapic_write((uint8_t)low_index, low);
+}
+
+void apic_remap_interrupts()
+{
+ uint8_t bspid = curr_cpu_apic_id();
+
+ map_addr(ioapic_addr, ioapic_addr, FLAG_PRESENT);
+ map_addr(lapic_addr, lapic_addr, FLAG_PRESENT);
+
+ // irq is 2 because of gsi remap
+ ioapic_set_irq(0x2, bspid, 0x20); // timer
+ ioapic_set_irq(0x1, bspid, 0x21); // keyboard
+ __asm__ volatile ("sti;");
+}