#include "apic.hpp" #include "paging.hpp" #include "types.hpp" #include "asm.hpp" #include "libs/stdio.hpp" #define APIC_LAPIC_ADDR 0xFEE00000 #define APIC_IOAPIC_ADDR 0xFEC00000 #define APIC_LAPIC_REG_SPURIOUS 0xF0 #define APIC_LAPIC_TIMER_LVT 0x320 #define APIC_LAPIC_TIMER_IC 0x380 #define APIC_LAPIC_TIMER_DVD 0x3E0 #define APIC_PRIOR 0x80 #define APIC_DFR 0xE0 #define APIC_EOI 0xB0 u8 lapic_space[4096] __attribute__((aligned(4096))); u8 ioapic_space[4096] __attribute__((aligned(4096))); char enable=0; void apic_enable(){ // Memory Allocation PAGE_MAP(lapic_space,APIC_LAPIC_ADDR, PAGING_OPT_PCD|PAGING_OPT_DEFAULTS); PAGE_MAP(ioapic_space,APIC_IOAPIC_ADDR,PAGING_OPT_PCD|PAGING_OPT_DEFAULTS); // Configure APIC register location and enable it via MSR /* u64 lapic_addr=(u64)APIC_LAPIC_ADDR; u32 high=lapic_addr>>32; u32 low=((u64)APIC_LAPIC_ADDR&0xFFFFFFFF); low|=0x800; // Enable apic WRITE_MSR(0x1B,high,low);*/ // Configure LAPIC device using mmap apic_write(APIC_LAPIC_REG_SPURIOUS, 0x100&apic_read(APIC_LAPIC_REG_SPURIOUS)); //apic_write(APIC_DFR, 0xFFFFFFFF); // apic_write(APIC_PRIOR, 0); apic_write(APIC_LAPIC_TIMER_DVD, 1); apic_write(APIC_LAPIC_TIMER_LVT, (1<<17)|61); apic_write(APIC_LAPIC_TIMER_IC, 100000); // Configure I/O APIC u32 *ioapic_reg=(u32*)ioapic_space; *ioapic_reg=0x12; // Select the 0x12 IRQ ioapic_reg=(u32*)(((u64)ioapic_space)+0x10); // Now use the IOREGWIN to write *ioapic_reg=(0x0<<12)|60; // Enable IRQ 1 (0x12) and assign it to the vector 0x3C (index 60 in the IDT) enable=1; } void apic_write(u32 reg, u32 value){ u32 *lapic_reg=(u32*)(lapic_space+reg); *lapic_reg=value; } u32 apic_read(u32 reg){ u32 *lapic_reg=(u32*)(lapic_space+reg); return *lapic_reg; } extern "C" void apic_ack(){ if(enable){ /* u8 data; do { inb(0x64,data); } while((data&0x01) == 0); inb(0x60,data); */ apic_write(APIC_EOI, 0); } }