feat: aarch64 port - Raspberry Pi 4/400 SD boot (SDHCI, ext2 root + first-boot grow), USB hubs, PCI INTx routing, SMP, DMA fences
This commit is contained in:
1 parent
8c09ccef66
commit
808e1d66fd
66 files changed
+3690
-196
No files matched your search
@@ -14,11 +14,16 @@
|
||||
#include <Drivers/USB/Xhci.hpp>
|
||||
#include <Drivers/Storage/Ahci.hpp>
|
||||
#include <Drivers/Storage/Nvme.hpp>
|
||||
#include <Drivers/Storage/Sdhci.hpp>
|
||||
#include <Drivers/Storage/Gpt.hpp>
|
||||
#include <Drivers/Audio/IntelHda.hpp>
|
||||
#include <Graphics/Framebuffer.hpp>
|
||||
#include <Net/Net.hpp>
|
||||
#include <Terminal/Terminal.hpp>
|
||||
#include <ACPI/AcpiDevices.hpp>
|
||||
#include <Boot/Boot.hpp>
|
||||
#include <ACPI/AML/AmlInterpreter.hpp>
|
||||
#include <ACPI/AML/AmlResource.hpp>
|
||||
|
||||
namespace Drivers {
|
||||
|
||||
@@ -89,6 +94,10 @@ namespace Drivers {
|
||||
return Storage::Nvme::Probe(dev);
|
||||
}
|
||||
|
||||
static bool ProbeSdhci(const Pci::PciDevice& dev) {
|
||||
return Storage::Sdhci::Probe(dev);
|
||||
}
|
||||
|
||||
static bool ProbeIntelHda(const Pci::PciDevice& dev) {
|
||||
return Audio::IntelHda::Probe(dev);
|
||||
}
|
||||
@@ -189,6 +198,18 @@ namespace Drivers {
|
||||
// also reports 0x01, but it exposes an I/O-space BAR0:
|
||||
// ReadBar0 returns 0 for I/O BARs and Probe rejects it
|
||||
// cleanly, so matching it here is harmless.
|
||||
// SD host controller (standard interface) - class 0x08/0x05
|
||||
{
|
||||
"SDHCI",
|
||||
0,
|
||||
0x08, // ClassCode (Base system peripheral)
|
||||
0x05, // SubClass (SD host controller)
|
||||
0xFF,
|
||||
nullptr,
|
||||
0,
|
||||
Pci::ProbePhase::Normal,
|
||||
ProbeSdhci,
|
||||
},
|
||||
{
|
||||
"IntelHDA",
|
||||
0x8086, // VendorId (Intel)
|
||||
@@ -227,8 +248,117 @@ namespace Drivers {
|
||||
Graphics::DgpuPower::PowerDownUnused();
|
||||
}
|
||||
|
||||
// A device's _DMA (or its parent's) bounds the addresses it can reach.
|
||||
// DMA buffers come from anywhere in RAM, so RAM past the bound is a
|
||||
// configuration error: on the Raspberry Pi 4 the firmware's "Limit RAM
|
||||
// to 3 GB" setting must stay on.
|
||||
static void WarnIfRamBeyondDma(const char* devicePath) {
|
||||
char path[160];
|
||||
int len = 0;
|
||||
while (devicePath[len] != '\0' && len < 120) { path[len] = devicePath[len]; len++; }
|
||||
|
||||
Hal::AML::ResourceList dma;
|
||||
bool found = false;
|
||||
for (int attempt = 0; attempt < 2 && !found; attempt++) {
|
||||
const char suffix[] = "._DMA";
|
||||
for (int i = 0; i < (int)sizeof(suffix); i++) path[len + i] = suffix[i];
|
||||
Hal::AML::Object obj;
|
||||
if (Hal::AML::GetInterpreter().EvaluateObject(path, obj) &&
|
||||
obj.Type == Hal::AML::ObjectType::Buffer &&
|
||||
Hal::AML::ParseResourceTemplate(obj.Buffer.Data, obj.Buffer.Length, dma)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
// Retry on the parent device.
|
||||
while (len > 0 && path[len - 1] != '.') len--;
|
||||
if (len == 0) return;
|
||||
len--;
|
||||
}
|
||||
|
||||
uint64_t dmaBase = 0, dmaLength = 0;
|
||||
if (!found || !dma.GetMemory(dmaBase, dmaLength) || dmaLength == 0) return;
|
||||
uint64_t dmaEnd = dmaBase + dmaLength;
|
||||
|
||||
const auto& map = montauk::boot::Info().memoryMap;
|
||||
for (uint64_t i = 0; i < map.count; i++) {
|
||||
const auto& r = map.regions[i];
|
||||
if (r.kind == montauk::boot::MemoryKind::Usable && r.base + r.length > dmaEnd) {
|
||||
Kt::KernelLogStream(Kt::WARNING, "Drivers") << devicePath << " can only reach RAM below 0x"
|
||||
<< base::hex << dmaEnd << ", but there is RAM up to 0x" << (r.base + r.length)
|
||||
<< ": its DMA may fail (Raspberry Pi 4: keep 'Limit RAM to 3 GB' enabled)";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An xHCI controller ACPI describes as a platform device (PNP0D10)
|
||||
// instead of a PCI function: the Raspberry Pi 4/400's VL805 under UEFI
|
||||
// firmware in ACPI mode, where firmware has set up the non-ECAM PCIe
|
||||
// behind it. Its DMA is non-coherent unless _CCA says otherwise.
|
||||
static void ProbePlatformXhci() {
|
||||
if (USB::Xhci::IsInitialized()) return;
|
||||
|
||||
Hal::AcpiDevices::DeviceInfo info{};
|
||||
if (!Hal::AcpiDevices::FindDeviceByHid("PNP0D10", info) &&
|
||||
!Hal::AcpiDevices::FindDeviceByHid("PNP0D15", info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Hal::AML::ResourceList resources;
|
||||
uint64_t base = 0, length = 0;
|
||||
if (!Hal::AcpiDevices::EvaluateCrs(info.NodeIndex, resources) ||
|
||||
!resources.GetMemory(base, length) || base == 0) {
|
||||
Kt::KernelLogStream(Kt::WARNING, "Drivers") << "xHCI " << info.Path
|
||||
<< ": no register block in _CRS";
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t gsi = 0;
|
||||
bool level = true, activeLow = false;
|
||||
if (auto* irq = resources.FindFirst(Hal::AML::ResourceType::ExtendedIrq)) {
|
||||
gsi = irq->ExtendedIrq.Interrupt;
|
||||
level = (irq->ExtendedIrq.Flags & 1) == 0;
|
||||
activeLow = (irq->ExtendedIrq.Flags & 2) != 0;
|
||||
}
|
||||
|
||||
bool coherent = false;
|
||||
Hal::AML::Object cca;
|
||||
if (Hal::AML::GetInterpreter().EvaluateChild(info.NodeIndex, "_CCA", nullptr, 0, cca) &&
|
||||
cca.Type == Hal::AML::ObjectType::Integer) {
|
||||
coherent = cca.Integer != 0;
|
||||
}
|
||||
|
||||
Kt::KernelLogStream(Kt::INFO, "Drivers") << "xHCI platform device " << info.Path
|
||||
<< " at 0x" << base::hex << base << ", GSI " << base::dec << (uint64_t)gsi
|
||||
<< (coherent ? ", coherent DMA" : ", non-coherent DMA");
|
||||
WarnIfRamBeyondDma(info.Path);
|
||||
USB::Xhci::ProbePlatform(base, length, gsi, level, activeLow, coherent);
|
||||
}
|
||||
|
||||
// SD host controllers ACPI describes directly: the Raspberry Pi 4's
|
||||
// EMMC2 (BRCME88C, the SD card slot) or a standard PNP0D40.
|
||||
static void ProbePlatformSdhci() {
|
||||
if (Storage::Sdhci::IsInitialized()) return;
|
||||
|
||||
Hal::AcpiDevices::DeviceInfo info{};
|
||||
if (!Hal::AcpiDevices::FindDeviceByHid("BRCME88C", info) &&
|
||||
!Hal::AcpiDevices::FindDeviceByHid("PNP0D40", info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Hal::AML::ResourceList resources;
|
||||
uint64_t base = 0, length = 0;
|
||||
if (!Hal::AcpiDevices::EvaluateCrs(info.NodeIndex, resources) ||
|
||||
!resources.GetMemory(base, length) || base == 0) {
|
||||
return;
|
||||
}
|
||||
Storage::Sdhci::ProbePlatform(base, info.Path);
|
||||
}
|
||||
|
||||
void ProbeNormal() {
|
||||
Pci::ProbeAll(g_driverTable, g_driverTableCount, Pci::ProbePhase::Normal);
|
||||
ProbePlatformXhci();
|
||||
ProbePlatformSdhci();
|
||||
}
|
||||
|
||||
void InitializeNetwork() {
|
||||
|
||||
Reference in new issue
Block a user