feat: make kernel architecture-agnostic; primitive work on arm port

This commit is contained in:
daniel committed 2026-10-24 21:25:18 +02:00
1 parent dab7d5427b
commit 1bae77ec84
164 files changed
+3664 -1641

No files matched your search

+28 -38
View File
@@ -5,6 +5,7 @@
*/
#include "Xhci.hpp"
#include <Arch/Cpu.hpp>
#include <atomic>
#include "UsbDevice.hpp"
#include "HidKeyboard.hpp"
@@ -18,28 +19,26 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/SmpBoot.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Arch/Interrupts.hpp>
#include <Arch/Smp.hpp>
#include <Timekeeping/Timer.hpp>
#include <CppLib/Spinlock.hpp>
#include <atomic>
using namespace Kt;
static void BusyWaitMs(uint64_t ms) {
uint64_t flags;
asm volatile("pushfq; pop %0" : "=r"(flags));
if (flags & (1 << 9)) {
if (Arch::InterruptsEnabled()) {
// Interrupts enabled — use timer-based delay
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
} else {
// Interrupts disabled (e.g. timer tick context) — use I/O port delay
// Each outb to port 0x80 takes ~1µs on x86
// Interrupts disabled (e.g. timer tick context) — the tick is not
// advancing here, so count ~1 µs delays instead
for (uint64_t i = 0; i < ms * 1000; i++) {
asm volatile("outb %%al, $0x80" ::: "memory");
Arch::IoDelay();
}
}
}
@@ -429,17 +428,9 @@ namespace Drivers::USB::Xhci {
uint16_t msgCtrl = Pci::LegacyRead16(bus, dev, func, cap + 2);
bool is64bit = (msgCtrl & (1 << 7)) != 0;
// Write Message Address (cap+4): BSP APIC ID 0, physical destination, fixed delivery
Pci::LegacyWrite32(bus, dev, func, cap + 4, MSI_ADDR_BASE);
// Write Message Data (vector number, edge-triggered, fixed delivery)
if (is64bit) {
// 64-bit: Upper Address at cap+8, Data at cap+12
Pci::LegacyWrite32(bus, dev, func, cap + 8, 0);
Pci::LegacyWrite16(bus, dev, func, cap + 12, MSI_VECTOR);
} else {
// 32-bit: Data at cap+8
Pci::LegacyWrite16(bus, dev, func, cap + 8, MSI_VECTOR);
// Message Address/Data: IRQ slot MSI_IRQ on the boot CPU
if (!Pci::WriteMsiMessage(bus, dev, func, cap, MSI_IRQ)) {
return false;
}
// Enable MSI: set bit 0 (MSI Enable), clear bits 6:4 (single message)
@@ -453,10 +444,9 @@ namespace Drivers::USB::Xhci {
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
// Register the interrupt handler for MSI vector
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "xHCI") << "MSI enabled: vector " << base::dec << (uint64_t)MSI_VECTOR
<< " (IRQ slot " << (uint64_t)MSI_IRQ << ")" << (is64bit ? " [64-bit]" : " [32-bit]");
KernelLogStream(OK, "xHCI") << "MSI enabled: IRQ slot " << base::dec << (uint64_t)MSI_IRQ << (is64bit ? " [64-bit]" : " [32-bit]");
return true;
}
@@ -814,7 +804,7 @@ namespace Drivers::USB::Xhci {
}
// Small delay
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -936,7 +926,7 @@ namespace Drivers::USB::Xhci {
return g_xferCompletionCode[slotId];
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1358,7 +1348,7 @@ namespace Drivers::USB::Xhci {
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1552,7 +1542,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1665,7 +1655,7 @@ namespace Drivers::USB::Xhci {
for (uint32_t i = 0; i < 100000; i++) {
if (ReadOp(OP_USBSTS) & USBSTS_HCH) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
if (!(ReadOp(OP_USBSTS) & USBSTS_HCH)) {
@@ -1677,11 +1667,11 @@ namespace Drivers::USB::Xhci {
WriteOp(OP_USBCMD, USBCMD_HCRST);
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBCMD) & USBCMD_HCRST)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBSTS) & USBSTS_CNR)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
if (ReadOp(OP_USBSTS) & USBSTS_CNR) {
KernelLogStream(WARNING, "xHCI") << "Controller not ready after reset";
@@ -1752,7 +1742,7 @@ namespace Drivers::USB::Xhci {
WriteOp(OP_USBCMD, USBCMD_RS | USBCMD_INTE | USBCMD_HSEE);
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBSTS) & USBSTS_HCH)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
KernelLogStream(OK, "xHCI") << "Controller started";
g_initialized = true;
@@ -1783,7 +1773,7 @@ namespace Drivers::USB::Xhci {
PollEvents();
uint32_t ps = ReadOp(OP_PORTSC_BASE + port * OP_PORTSC_STRIDE);
if (ps & PORTSC_PRC) { resetDone = true; break; }
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
if (!resetDone) {
@@ -1924,7 +1914,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1945,7 +1935,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1955,7 +1945,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -2074,7 +2064,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -2123,7 +2113,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}