aboutsummaryrefslogtreecommitdiff
path: root/mubios/drivers/ioapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'mubios/drivers/ioapic.c')
-rw-r--r--mubios/drivers/ioapic.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/mubios/drivers/ioapic.c b/mubios/drivers/ioapic.c
new file mode 100644
index 0000000..98f2210
--- /dev/null
+++ b/mubios/drivers/ioapic.c
@@ -0,0 +1,87 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+ */
+
+#include "bios.h"
+#include "io.h"
+
+#define IOAPIC_INDEX 0xFEC00000u
+#define IOAPIC_DATA 0xFEC00010u
+
+#define IOAPIC_IRQ0_LOW 0x10u
+#define IOAPIC_IRQ0_HIGH 0x11u
+
+#define IOAPIC_IRQ0_EXTINT 0x00000700u
+
+#define IA32_APIC_BASE_MSR 0x0000001Bu
+#define APIC_BASE 0xFEE00000u
+#define APIC_SVR_OFFSET 0x000000F0u
+#define APIC_LVT0_OFFSET 0x00000350u
+
+static volatile u32 *const ioapic_index = (volatile u32 *)IOAPIC_INDEX;
+
+static volatile u32 *const ioapic_data = (volatile u32 *)IOAPIC_DATA;
+
+static inline void
+rdmsr (u32 msr, u32 *low, u32 *high)
+{
+ __asm__ volatile ("rdmsr" : "=a"(*low), "=d"(*high) : "c"(msr));
+}
+
+static inline void
+wrmsr (u32 msr, u32 low, u32 high)
+{
+ __asm__ volatile ("wrmsr" : : "a"(low), "d"(high), "c"(msr));
+}
+
+static void
+ioapic_write (u8 index, u32 value)
+{
+ *ioapic_index = index;
+ *ioapic_data = value;
+}
+
+void
+ioapic_init (void)
+{
+ u32 apic_base_low;
+ u32 apic_base_high;
+
+ rdmsr (IA32_APIC_BASE_MSR, &apic_base_low, &apic_base_high);
+
+ apic_base_low |= 0x00000800u;
+ wrmsr (IA32_APIC_BASE_MSR, apic_base_low, apic_base_high);
+
+ /*
+ * Enable the local APIC.
+ */
+ *(volatile u32 *)(APIC_BASE + APIC_SVR_OFFSET) = 0x000001FFu;
+
+ /*
+ * Route legacy PIC interrupts through LVT0.
+ */
+ *(volatile u32 *)(APIC_BASE + APIC_LVT0_OFFSET) = 0x00000700u;
+
+ /*
+ * Route IOAPIC pin 0 to the legacy PIC ExtINT path.
+ */
+ ioapic_write (IOAPIC_IRQ0_LOW, IOAPIC_IRQ0_EXTINT);
+ ioapic_write (IOAPIC_IRQ0_HIGH, 0x00000000u);
+}