Merge branch 'master' into isa/arm64
[lunaix-os.git] / lunaix-os / arch / x86 / hal / ioapic.c
1 #include <hal/acpi/acpi.h>
2
3 #include <lunaix/mm/mmio.h>
4
5 #include <asm/hart.h>
6 #include "asm/soc/ioapic.h"
7 #include "asm/x86.h"
8
9 #define IOAPIC_IOREGSEL 0x00
10 #define IOAPIC_IOWIN 0x10
11 #define IOAPIC_IOREDTBL_BASE 0x10
12
13 #define IOAPIC_REG_ID 0x00
14 #define IOAPIC_REG_VER 0x01
15 #define IOAPIC_REG_ARB 0x02
16
17 #define IOAPIC_DELMOD_FIXED 0b000
18 #define IOAPIC_DELMOD_LPRIO 0b001
19 #define IOAPIC_DELMOD_NMI 0b100
20
21 #define IOAPIC_MASKED (1 << 16)
22 #define IOAPIC_TRIG_LEVEL (1 << 15)
23 #define IOAPIC_INTPOL_L (1 << 13)
24 #define IOAPIC_DESTMOD_LOGIC (1 << 11)
25
26 #define IOAPIC_BASE_VADDR 0x2000
27
28 #define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL))
29 #define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN))
30
31 static volatile ptr_t _ioapic_base;
32
33 void
34 ioapic_init()
35 {
36     // Remapping the IRQs
37
38     acpi_context* acpi_ctx = acpi_get_context();
39
40     _ioapic_base =
41         ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096);
42 }
43
44 void
45 ioapic_write(u8_t sel, u32_t val)
46 {
47     IOAPIC_REG_SEL = sel;
48     IOAPIC_REG_WIN = val;
49 }
50
51 u32_t
52 ioapic_read(u8_t sel)
53 {
54     IOAPIC_REG_SEL = sel;
55     return IOAPIC_REG_WIN;
56 }
57
58 void
59 ioapic_irq_remap(struct x86_intc* intc, int irq, int iv, cpu_t dest, u32_t flags)
60 {
61     /*
62         FIXME move it to HAL level. since every platform might have their own
63        wiring, thus gsi mapping is required all the time
64     */
65     irq = acpi_gsimap(irq);
66     u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2;
67
68     u32_t ioapic_fg = 0;
69
70     if ((flags & IRQ_TYPE) == IRQ_TYPE_FIXED) {
71         ioapic_fg |= IOAPIC_DELMOD_FIXED;
72     } else {
73         ioapic_fg |= IOAPIC_DELMOD_NMI;
74     }
75
76     if ((flags & IRQ_TRIG_LEVEL)) {
77         ioapic_fg |= IOAPIC_TRIG_LEVEL;
78     }
79
80     if (!(flags & IRQ_VE_HI)) {
81         ioapic_fg |= IOAPIC_INTPOL_L;
82     }
83
84     // Write low 32 bits
85     ioapic_write(reg_sel, (iv | ioapic_fg) & 0x1FFFF);
86
87     // Write high 32 bits
88     ioapic_write(reg_sel + 1, (dest << 24));
89 }