X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b26d3165c52589d1f8de37bf0df27ad96f460f47..1fe5f5eb5378a47bf0f3451762743c162e40faad:/lunaix-os/arch/i386/hal/ioapic.c diff --git a/lunaix-os/arch/i386/hal/ioapic.c b/lunaix-os/arch/i386/hal/ioapic.c new file mode 100644 index 0000000..5d233f4 --- /dev/null +++ b/lunaix-os/arch/i386/hal/ioapic.c @@ -0,0 +1,90 @@ +#include +#include + +#include +#include + +#include +#include + +#define IOAPIC_IOREGSEL 0x00 +#define IOAPIC_IOWIN 0x10 +#define IOAPIC_IOREDTBL_BASE 0x10 + +#define IOAPIC_REG_ID 0x00 +#define IOAPIC_REG_VER 0x01 +#define IOAPIC_REG_ARB 0x02 + +#define IOAPIC_DELMOD_FIXED 0b000 +#define IOAPIC_DELMOD_LPRIO 0b001 +#define IOAPIC_DELMOD_NMI 0b100 + +#define IOAPIC_MASKED (1 << 16) +#define IOAPIC_TRIG_LEVEL (1 << 15) +#define IOAPIC_INTPOL_L (1 << 13) +#define IOAPIC_DESTMOD_LOGIC (1 << 11) + +#define IOAPIC_BASE_VADDR 0x2000 + +#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL)) +#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN)) + +static volatile ptr_t _ioapic_base; + +void +ioapic_init() +{ + // Remapping the IRQs + + acpi_context* acpi_ctx = acpi_get_context(); + + _ioapic_base = + (ptr_t)ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096); +} + +void +ioapic_write(u8_t sel, u32_t val) +{ + IOAPIC_REG_SEL = sel; + IOAPIC_REG_WIN = val; +} + +u32_t +ioapic_read(u8_t sel) +{ + IOAPIC_REG_SEL = sel; + return IOAPIC_REG_WIN; +} + +void +ioapic_irq_remap(struct intc_context*, int irq, int iv, cpu_t dest, u32_t flags) +{ + /* + FIXME move it to HAL level. since every platform might have their own + wiring, thus gsi mapping is required all the time + */ + irq = acpi_gsimap(irq); + u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2; + + u32_t ioapic_fg = 0; + + if ((flags & IRQ_TYPE) == IRQ_TYPE_FIXED) { + ioapic_fg |= IOAPIC_DELMOD_FIXED; + } else { + ioapic_fg |= IOAPIC_DELMOD_NMI; + } + + if ((flags & IRQ_TRIG_LEVEL)) { + ioapic_fg |= IOAPIC_TRIG_LEVEL; + } + + if (!(flags & IRQ_VE_HI)) { + ioapic_fg |= IOAPIC_INTPOL_L; + } + + // Write low 32 bits + ioapic_write(reg_sel, (iv | ioapic_fg) & 0x1FFFF); + + // Write high 32 bits + ioapic_write(reg_sel + 1, (dest << 24)); +} \ No newline at end of file