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