From 9a1a7b9955f0d2b5f1bf33091b31a0a7a3b61c61 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Mar 2023 04:56:36 +0200 Subject: [PATCH] Fixed PCI BAR mapping --- Core/Driver/DriverLoading/BindPCI.cpp | 139 +++++++++++++++++++++----- Kernel.cpp | 4 + include/driver.hpp | 1 + include/pci.hpp | 78 +++++++++++++-- 4 files changed, 191 insertions(+), 31 deletions(-) diff --git a/Core/Driver/DriverLoading/BindPCI.cpp b/Core/Driver/DriverLoading/BindPCI.cpp index f670307..7c013a4 100644 --- a/Core/Driver/DriverLoading/BindPCI.cpp +++ b/Core/Driver/DriverLoading/BindPCI.cpp @@ -14,6 +14,119 @@ namespace Driver { + void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice) + { + Memory::Virtual vma = Memory::Virtual(nullptr); + + debug("Header Type: %d", PCIDevice->HeaderType); + switch (PCIDevice->HeaderType) + { + case 0: // PCI Header 0 + { + uint32_t BAR[6] = {0}; + size_t BARsSize[6] = {0}; + + BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0; + BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1; + BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2; + BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3; + BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4; + BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5; + + uintptr_t BAR_Type = BAR[0] & 1; + uintptr_t BAR_IOBase = BAR[1] & (~3); + uintptr_t BAR_MemoryBase = BAR[0] & (~15); + + debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase); + + for (size_t i = 0; i < 6; i++) + { + if (BAR[i] == 0) + continue; + debug("BAR%d: %#lx", i, BAR[i]); + } + + /* BARs Size */ + for (size_t i = 0; i < 6; i++) + { + if (BAR[i] == 0) + continue; + + if ((BAR[i] & 1) == 0) // Memory Base + { + ((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF; + size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0; + ((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i]; + BARsSize[i] = size & (~15); + BARsSize[i] = ~BARsSize[i] + 1; + BARsSize[i] = BARsSize[i] & 0xFFFFFFFF; + debug("BAR%dSize: %#lx", i, BARsSize[i]); + } + else if ((BAR[i] & 1) == 1) // I/O Base + { + ((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF; + size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1; + ((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i]; + BARsSize[i] = size & (~3); + BARsSize[i] = ~BARsSize[i] + 1; + BARsSize[i] = BARsSize[i] & 0xFFFF; + debug("BAR%dSize: %#lx", i, BARsSize[i]); + } + } + + /* Mapping the BARs */ + for (size_t i = 0; i < 6; i++) + { + if (BAR[i] == 0) + continue; + + if ((BAR[i] & 1) == 0) // Memory Base + { + uintptr_t BARBase = BAR[i] & (~15); + size_t BARSize = BARsSize[i]; + + debug("Mapping BAR%d from %#lx to %#lx", i, BARBase, BARBase + BARSize); + for (uintptr_t j = BARBase; + j < (BARBase + BARSize); + j += PAGE_SIZE) + { + vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT); + } + } + else if ((BAR[i] & 1) == 1) // I/O Base + { + uintptr_t BARBase = BAR[i] & (~3); + uintptr_t BARSize = BARsSize[i]; + + debug("Mapping BAR%d from %#x to %#x", i, BARBase, BARBase + BARSize); + for (uintptr_t j = BARBase; + j < (BARBase + BARSize); + j += PAGE_SIZE) + { + vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT); + } + } + } + break; + } + case 1: // PCI Header 1 (PCI-to-PCI Bridge) + { + fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet"); + break; + } + case 2: // PCI Header 2 (PCI-to-CardBus Bridge) + { + fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet"); + break; + } + default: + { + error("Unknown header type %d", PCIDevice->HeaderType); + return; + } + } + } + DriverCode Driver::BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice) { FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS); @@ -317,31 +430,7 @@ namespace Driver } debug("Starting driver %s", fexExtended->Driver.Name); - debug("Type: %d; IOBase: %#x; MemoryBase: %#x", - ((PCI::PCIHeader0 *)PCIDevice)->BAR0 & 1, - ((PCI::PCIHeader0 *)PCIDevice)->BAR1 & (~3), - ((PCI::PCIHeader0 *)PCIDevice)->BAR0 & (~15)); - - if ((((PCI::PCIHeader0 *)PCIDevice)->BAR0 & 1) != 0) - if (!Memory::Virtual().Check((void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR1 & (~3)))) - { - debug("IO base (BAR1 & ~3) is not mapped"); - Memory::Virtual().Map((void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR1 & (~3)), (void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR1 & (~3)), Memory::PTFlag::RW); - } - - if ((((PCI::PCIHeader0 *)PCIDevice)->BAR0 & 1) == 0) - if (!Memory::Virtual().Check((void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR0 & (~15)))) - { - debug("Memory base (BAR0 & ~15) is not mapped"); - Memory::Virtual().Map((void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR0 & (~15)), (void *)(uintptr_t)(((PCI::PCIHeader0 *)PCIDevice)->BAR0 & (~15)), Memory::PTFlag::RW); - - uintptr_t original = ((PCI::PCIHeader0 *)PCIDevice)->BAR0; - ((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF; - uintptr_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0 & 0xFFFFFFF0; - ((PCI::PCIHeader0 *)PCIDevice)->BAR0 = original; - debug("Size: %#lx (%ld pages)", size, TO_PAGES(size)); - fixme("TODO: [BUG] Mapping is broken!!!!!!"); - } + MapPCIAddresses(PCIDevice); switch (fexExtended->Driver.Type) { diff --git a/Kernel.cpp b/Kernel.cpp index 0d6eeb4..9ee5b62 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -91,6 +91,10 @@ * https://en.wikipedia.org/wiki/Inter-process_communication * https://www.geeksforgeeks.org/inter-process-communication-ipc/ * + * - PCI: + * https://wiki.osdev.org/PCI + * https://en.wikipedia.org/wiki/PCI_configuration_space + * */ #ifdef a64 diff --git a/include/driver.hpp b/include/driver.hpp index bd784ba..6cfde2a 100644 --- a/include/driver.hpp +++ b/include/driver.hpp @@ -62,6 +62,7 @@ namespace Driver unsigned long DriverUIDs = 0; DriverCode CallDriverEntryPoint(void *fex, void *KAPIAddress); + void MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice); DriverCode BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice); DriverCode BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice); DriverCode BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice); diff --git a/include/pci.hpp b/include/pci.hpp index 19b0cc6..7287002 100644 --- a/include/pci.hpp +++ b/include/pci.hpp @@ -104,6 +104,10 @@ namespace PCI uint8_t BIST; }; + /** + * @brief PCI Header Type 0 + * + */ struct PCIHeader0 { PCIDeviceHeader Header; @@ -113,20 +117,82 @@ namespace PCI uint32_t BAR3; uint32_t BAR4; uint32_t BAR5; - uint32_t CardbusCISPtr; + uint32_t CardbusCISPointer; uint16_t SubsystemVendorID; uint16_t SubsystemID; - uint32_t ExpansionROMBaseAddr; - uint8_t CapabilitiesPtr; - uint8_t Rsv0; - uint16_t Rsv1; - uint32_t Rsv2; + uint32_t ExpansionROMBaseAddress; + uint8_t CapabilitiesPointer; + uint8_t Reserved0; + uint16_t Reserved1; + uint32_t Reserved2; uint8_t InterruptLine; uint8_t InterruptPin; uint8_t MinGrant; uint8_t MaxLatency; }; + /** + * @brief PCI Header Type 1 (PCI-to-PCI Bridge) + */ + struct PCIHeader1 + { + PCIDeviceHeader Header; + uint32_t BAR0; + uint32_t BAR1; + uint8_t PrimaryBusNumber; + uint8_t SecondaryBusNumber; + uint8_t SubordinateBusNumber; + uint8_t SecondaryLatencyTimer; + uint8_t IOBase; + uint8_t IOLimit; + uint16_t SecondaryStatus; + uint16_t MemoryBase; + uint16_t MemoryLimit; + uint16_t PrefetchableMemoryBase; + uint16_t PrefetchableMemoryLimit; + uint32_t PrefetchableMemoryBaseUpper32; + uint32_t PrefetchableMemoryLimitUpper32; + uint16_t IOBaseUpper16; + uint16_t IOLimitUpper16; + uint8_t CapabilitiesPointer; + uint8_t Reserved0; + uint16_t Reserved1; + uint32_t ExpansionROMBaseAddress; + uint8_t InterruptLine; + uint8_t InterruptPin; + uint16_t BridgeControl; + }; + + /** + * @brief PCI Header Type 2 (PCI-to-CardBus Bridge) + */ + struct PCIHeader2 + { + PCIDeviceHeader Header; + uint32_t CardbusSocketRegistersBaseAddress; + uint8_t CapabilitiesPointer; + uint8_t Reserved0; + uint16_t SecondaryStatus; + uint8_t PCIbusNumber; + uint8_t CardbusBusNumber; + uint8_t SubordinateBusNumber; + uint8_t CardbusLatencyTimer; + uint32_t MemoryBase0; + uint32_t MemoryLimit0; + uint32_t MemoryBase1; + uint32_t MemoryLimit1; + uint32_t IOBase0; + uint32_t IOLimit0; + uint32_t IOBase1; + uint32_t IOLimit1; + uint8_t InterruptLine; + uint8_t InterruptPin; + uint16_t BridgeControl; + uint16_t SubsystemVendorID; + uint16_t SubsystemID; + uint32_t LegacyBaseAddress; + }; + struct DeviceConfig { uintptr_t BaseAddress;