1 /*
2  * IOAPIC
3  */
4 
5 #include <stdbool.h>
6 #include <stdint.h>
7 
8 #include <sys/kassert.h>
9 #include <sys/kdebug.h>
10 #include <sys/cdefs.h>
11 
12 #include <machine/amd64.h>
13 #include <machine/pmap.h>
14 #include <machine/trap.h>
15 
16 #define IOAPICBASE  0xFEC00000
17 
18 #define IOAPICID    0x00 /* IOAPIC ID */
19 #define IOAPICVER   0x01 /* IOAPIC Version */
20 #define IOAPICARB   0x02 /* IOAPIC Arbitration ID */
21 #define IOREDTBL0   0x10
22 #define IOREDTBL23  0x3E
23 
24 #define IOREDTBL_LEN    24
25 
26 #define IOREDTBL_MASK       0x00010000
27 #define IOREDTBL_LOGICAL    0x00000800
28 
29 uint32_t
IOAPIC_Read(uint32_t reg)30 IOAPIC_Read(uint32_t reg)
31 {
32     uint32_t volatile *addr = (uint32_t volatile *)DMPA2VA(IOAPICBASE);
33     uint32_t volatile *cmd = (uint32_t volatile *)DMPA2VA(IOAPICBASE + 0x10);
34 
35     ASSERT(reg <= 0xFF);
36 
37     *addr = reg;
38     return *cmd;
39 }
40 
41 void
IOAPIC_Write(uint32_t reg,uint32_t val)42 IOAPIC_Write(uint32_t reg, uint32_t val)
43 {
44     uint32_t volatile *addr = (uint32_t volatile *)DMPA2VA(IOAPICBASE);
45     uint32_t volatile *cmd = (uint32_t volatile *)DMPA2VA(IOAPICBASE + 0x10);
46 
47     ASSERT(reg <= 0xFF);
48 
49     *addr = reg;
50     *cmd = val;
51 }
52 
53 void
IOAPIC_Init()54 IOAPIC_Init()
55 {
56     int i;
57     uint32_t id = (IOAPIC_Read(IOAPICID) >> 24) & 0x0F;
58     uint32_t maxInts = (IOAPIC_Read(IOAPICVER) >> 16) & 0xFF;
59 
60     kprintf("IOAPIC: ID:%d Max Interrupts: %d\n", id, maxInts);
61 
62     for (i = 0; i < IOREDTBL_LEN; i++)
63     {
64         IOAPIC_Write(IOREDTBL0 + 2*i, IOREDTBL_MASK | (T_IRQ_BASE + i));
65         IOAPIC_Write(IOREDTBL0 + 2*i + 1, 0);
66     }
67 }
68 
69 void
IOAPIC_Enable(int irq)70 IOAPIC_Enable(int irq)
71 {
72     uint32_t val = IOAPIC_Read(IOREDTBL0 + 2*irq);
73     IOAPIC_Write(IOREDTBL0 + 2*irq, val & ~IOREDTBL_MASK);
74 }
75 
76 void
IOAPIC_Disable(int irq)77 IOAPIC_Disable(int irq)
78 {
79     uint32_t val = IOAPIC_Read(IOREDTBL0 + 2*irq);
80     IOAPIC_Write(IOREDTBL0 + 2*irq, val | IOREDTBL_MASK);
81 }
82 
83 static void
Debug_IOAPIC(int argc,const char * argv[])84 Debug_IOAPIC(int argc, const char *argv[])
85 {
86     int i;
87 
88     kprintf("IOAPIC ID:      %08x\n", IOAPIC_Read(IOAPICID));
89     kprintf("IOAPIC VERSION: %08x\n", IOAPIC_Read(IOAPICVER));
90 
91     for (i = 0; i < IOREDTBL_LEN; i++)
92     {
93 	uint32_t irqInfo = IOAPIC_Read(IOREDTBL0 + 2*i);
94 	uint32_t cpuInfo = IOAPIC_Read(IOREDTBL0 + 2*i + 1);
95 	kprintf("%02x: %08x %08x\n", i, irqInfo, cpuInfo);
96     }
97 }
98 
99 REGISTER_DBGCMD(ioapic, "IOAPIC Dump", Debug_IOAPIC);
100 
101