furix
cute os
arch/x86_64/ioapic.c
1780 bytes raw
1#include <ioapic.h>
2
3#include <io.h>
4#include <types.h>
5
6/* IO-APIC indirect register file */
7#define IOAPIC_REGSEL 0x00
8#define IOAPIC_WINDOW 0x10
9
10#define REG_ID 0x00
11#define REG_VER 0x01
12#define REG_REDIR 0x10
13
14/* bit 16 of a redirection entry masks that input */
15#define REDIR_MASKED (1u << 16)
16
17/* redirection entry count lives in the version register's bits 23:16 */
18#define IOAPIC_MAX_ENTRIES 24
19
20static volatile uint32_t *ioapic(void) {
21 return (volatile uint32_t *)(uint64_t)IOAPIC_DEFAULT_BASE;
22}
23
24static uint32_t ioapic_read(uint32_t reg) {
25 /*
26 * index-then-read: writing the register number to REGSEL selects it, and the
27 * selected register is then read from WINDOW.
28 */
29 *ioapic() = reg;
30 return *(volatile uint32_t *)((uint64_t)IOAPIC_DEFAULT_BASE + IOAPIC_WINDOW);
31}
32
33static void ioapic_write(uint32_t reg, uint32_t value) {
34 *ioapic() = reg;
35 *(volatile uint32_t *)((uint64_t)IOAPIC_DEFAULT_BASE + IOAPIC_WINDOW) = value;
36}
37
38void ioapic_disarm(void) {
39 uint32_t entries;
40 uint32_t i;
41
42 /*
43 * mask first, before trusting the version register. entries are masked one
44 * at a time, so if anything is already routed it stops as soon as we reach
45 * it.
46 */
47 for (i = 0; i < IOAPIC_MAX_ENTRIES; i++) {
48 uint32_t entry = ioapic_read(REG_REDIR + 2 * i);
49
50 ioapic_write(REG_REDIR + 2 * i, entry | REDIR_MASKED);
51 }
52
53 /* the version register encodes the entry count in bits 23:16 */
54 entries = (ioapic_read(REG_VER) >> 16) & 0xFF;
55
56 if (entries == 0 || entries > IOAPIC_MAX_ENTRIES) {
57 /* no usable count: mask everything the array can hold */
58 entries = IOAPIC_MAX_ENTRIES;
59 }
60
61 for (i = 0; i < entries; i++) {
62 uint32_t entry = ioapic_read(REG_REDIR + 2 * i);
63
64 ioapic_write(REG_REDIR + 2 * i, entry | REDIR_MASKED);
65 }
66}