diff --git a/src/kernel/cpu/apic.c b/src/kernel/cpu/apic.c index 2f57551..6d72057 100644 --- a/src/kernel/cpu/apic.c +++ b/src/kernel/cpu/apic.c @@ -3,93 +3,8 @@ #include #include -#define APIC_BASE 0xFEE00000 - #define APIC_MSR_ENABLE (1<<11) -#define APIC_EOI 0xB0 -#define APIC_SPURIOUS 0xF0 -#define APIC_REG(r) (((uint32_t *)P2V(APIC_BASE + (r)))[0]) - -#define IOREDTBL(irq) (0x10 + (irq)*2) - -union iored { - struct { - uint8_t vector; - uint8_t flags; - uint8_t mask; - uint32_t reserved; - uint8_t target; - }__attribute__((packed)); - struct { - uint32_t l; - uint32_t h; - }__attribute__((packed)); - uint64_t val; -}; - -static uint32_t ioapic_read(int reg) { - uint32_t volatile *ioregsel = P2V(ioapic.addr); - uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); - *ioregsel = reg; - return *iowin; -} -static void ioapic_write(int reg, uint32_t value) { - uint32_t volatile *ioregsel = P2V(ioapic.addr); - uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); - *ioregsel = reg; - *iowin = value; -} - -static uint64_t ioapic_read_redirection(int irq) { - union iored retval; - retval.l = ioapic_read(IOREDTBL(irq)); - retval.h = ioapic_read(IOREDTBL(irq)+1); - return retval.val; -} -static void ioapic_write_redirection(int irq, uint64_t val) { - union iored value; - value.val = val; - ioapic_write(IOREDTBL(irq), value.l); - ioapic_write(IOREDTBL(irq) + 1, value.h); -} - -void irq_ack() { - APIC_REG(APIC_EOI) = 0; -} - -void irq_mask(int irq) { - union iored iored; - iored.val = ioapic_read_redirection(irq_redirects[irq]); - iored.mask |= 0x1; - ioapic_write_redirection(irq_redirects[irq], iored.val); -} -void irq_unmask(int irq) { - union iored iored; - iored.val = ioapic_read_redirection(irq_redirects[irq]); - iored.mask &= ~0x1; - ioapic_write_redirection(irq_redirects[irq], iored.val); -} - -void ioapic_init() { - // Map ioapic offset into kernel memory - vmm_set_page(kernel_P4, - (uintptr_t)P2V(ioapic.addr), - ioapic.addr, - PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL - ); - - union iored iored; - for(int i = 0; i < 24; i++) { - iored.val = ioapic_read_redirection(i); - iored.vector = IRQ_BASE+i; - iored.flags = 0x0; - iored.mask |= 1; - iored.target = 0x0; - ioapic_write_redirection(i, iored.val); - } -} - void apic_init() { // Map apic offset into kernel memory vmm_set_page(kernel_P4, diff --git a/src/kernel/cpu/ioapic.c b/src/kernel/cpu/ioapic.c new file mode 100644 index 0000000..e9311aa --- /dev/null +++ b/src/kernel/cpu/ioapic.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#define IOREDTBL(irq) (0x10 + (irq)*2) + +union iored { + struct { + uint8_t vector; + uint8_t flags; + uint8_t mask; + uint32_t reserved; + uint8_t target; + }__attribute__((packed)); + struct { + uint32_t l; + uint32_t h; + }__attribute__((packed)); + uint64_t val; +}; + +static uint32_t ioapic_read(int reg) { + uint32_t volatile *ioregsel = P2V(ioapic.addr); + uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); + *ioregsel = reg; + return *iowin; +} +static void ioapic_write(int reg, uint32_t value) { + uint32_t volatile *ioregsel = P2V(ioapic.addr); + uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); + *ioregsel = reg; + *iowin = value; +} + +static uint64_t ioapic_read_redirection(int irq) { + union iored retval; + retval.l = ioapic_read(IOREDTBL(irq)); + retval.h = ioapic_read(IOREDTBL(irq)+1); + return retval.val; +} +static void ioapic_write_redirection(int irq, uint64_t val) { + union iored value; + value.val = val; + ioapic_write(IOREDTBL(irq), value.l); + ioapic_write(IOREDTBL(irq) + 1, value.h); +} + +void irq_ack() { + APIC_REG(APIC_EOI) = 0; +} + +void irq_mask(int irq) { + union iored iored; + iored.val = ioapic_read_redirection(irq_redirects[irq]); + iored.mask |= 0x1; + ioapic_write_redirection(irq_redirects[irq], iored.val); +} +void irq_unmask(int irq) { + union iored iored; + iored.val = ioapic_read_redirection(irq_redirects[irq]); + iored.mask &= ~0x1; + ioapic_write_redirection(irq_redirects[irq], iored.val); +} + +void ioapic_init() { + // Map ioapic offset into kernel memory + vmm_set_page(kernel_P4, + (uintptr_t)P2V(ioapic.addr), + ioapic.addr, + PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL + ); + + union iored iored; + for(int i = 0; i < 24; i++) { + iored.val = ioapic_read_redirection(i); + iored.vector = IRQ_BASE+i; + iored.flags = 0x0; + iored.mask |= 1; + iored.target = 0x0; + ioapic_write_redirection(i, iored.val); + } +} \ No newline at end of file diff --git a/src/kernel/include/cpu.h b/src/kernel/include/cpu.h index 6cd80c3..8986cb4 100644 --- a/src/kernel/include/cpu.h +++ b/src/kernel/include/cpu.h @@ -1,5 +1,6 @@ #pragma once #include +#include #define MSR_APIC_BASE 0x0000001B @@ -12,6 +13,14 @@ #define IRQ_PS2_KBD 0x1 #define IRQ_SPURIOUS 0xFF +#define APIC_BASE 0xFEE00000 +#define APIC_REG(r) (((uint32_t *)P2V(APIC_BASE + (r)))[0]) +#define APIC_EOI 0xB0 +#define APIC_SPURIOUS 0xF0 +#define APIC_LVT(r) (0x320 + 0x10*(r)) +#define LVT_TIMER 0 + + typedef struct { uint64_t rax; uint64_t rbx; @@ -75,6 +84,9 @@ int_handler_t bind_interrupt(uint32_t num, int_handler_t fn); void acpi_parse(void *_rsdp); // cpu/apic.c +void apic_init(); + +// cpu/ioapic.c void irq_ack(); void irq_mask(int irq); void irq_unmask(int irq);