diff options
Diffstat (limited to 'kernel/src/apic/ioapic.c')
| -rw-r--r-- | kernel/src/apic/ioapic.c | 67 |
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;"); +} |
