#include #include #include #define IOAPICID 0x00 #define IOAPICVER 0x01 #define IOAPICARB 0x02 #define IOAPICREDTBL(n) (0x10 + 2 * n) namespace arch::acpi { io_apic::io_apic(uint32_t *base, unsigned int first_irq) : io_base(base), io_first_irq(first_irq) { io_nr_irq = ((read(IOAPICVER) >> 16) + 1) & 0xFF; } uint32_t io_apic::read(uint32_t reg) { write_once(io_base, reg & 0xFF); return read_once(io_base + 4); } void io_apic::write(uint32_t reg, uint32_t val) { write_once(io_base, reg & 0xFF); write_once(io_base + 4, val); } kern_status_t io_apic::read_irq(unsigned int index, irq_entry &entry) { if (index >= io_nr_irq) { return KERN_NO_ENTRY; } uint32_t *entry_data = (uint32_t *)&entry; entry_data[0] = read(IOAPICREDTBL(index)); entry_data[1] = read(IOAPICREDTBL(index) + 1); return KERN_OK; } void io_apic::write_irq(unsigned int index, const irq_entry &entry) { if (index >= io_nr_irq) { return; } const uint32_t *entry_data = (const uint32_t *)&entry; write(IOAPICREDTBL(index), entry_data[0]); write(IOAPICREDTBL(index) + 1, entry_data[1]); } void io_apic::map_irq(unsigned int src, unsigned int dest) { io_apic::irq_entry irq{}; irq.irq_vec = dest; irq.irq_delivery = 0; irq.irq_destmode = 0; irq.irq_polarity = 0; irq.irq_triggermode = 0; irq.irq_mask = 0; irq.irq_dest = 0; write_irq(src, irq); } }