Explorar el Código

Kernel/USB: Handle non-page aligned EHCI controller BARs correctly

BARs don't have to be page-aligned. This patch correctly calculates the
needed memory range and register base address in that region.
Sönke Holz hace 1 año
padre
commit
06a32b6e16
Se han modificado 2 ficheros con 10 adiciones y 6 borrados
  1. 9 5
      Kernel/Bus/USB/EHCI/EHCIController.cpp
  2. 1 1
      Kernel/Bus/USB/EHCI/EHCIController.h

+ 9 - 5
Kernel/Bus/USB/EHCI/EHCIController.cpp

@@ -16,24 +16,28 @@ ErrorOr<NonnullLockRefPtr<EHCIController>> EHCIController::try_to_initialize(con
     // FIXME: This assumes the BIOS left us a physical region for the controller
     auto pci_bar_address = TRY(PCI::get_bar_address(pci_device_identifier, SpaceBaseAddressRegister));
     auto pci_bar_space_size = PCI::get_BAR_space_size(pci_device_identifier, SpaceBaseAddressRegister);
-    auto register_region = TRY(MM.allocate_kernel_region(pci_bar_address, pci_bar_space_size, {}, Memory::Region::Access::ReadWrite));
+
+    auto register_region_size = TRY(Memory::page_round_up(pci_bar_address.offset_in_page() + pci_bar_space_size));
+    auto register_region = TRY(MM.allocate_kernel_region(pci_bar_address.page_base(), register_region_size, {}, Memory::Region::Access::ReadWrite));
+
+    VirtualAddress register_base_address = register_region->vaddr().offset(pci_bar_address.offset_in_page());
 
     PCI::enable_bus_mastering(pci_device_identifier);
     PCI::enable_memory_space(pci_device_identifier);
 
-    auto controller = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) EHCIController(pci_device_identifier, move(register_region))));
+    auto controller = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) EHCIController(pci_device_identifier, move(register_region), register_base_address)));
 
     TRY(controller->initialize());
 
     return controller;
 }
 
-EHCIController::EHCIController(PCI::DeviceIdentifier const& pci_device_identifier, NonnullOwnPtr<Memory::Region> register_region)
+EHCIController::EHCIController(PCI::DeviceIdentifier const& pci_device_identifier, NonnullOwnPtr<Memory::Region> register_region, VirtualAddress register_base_address)
     : PCI::Device(pci_device_identifier)
     , m_register_region(move(register_region))
 {
-    m_cap_regs = bit_cast<CapabilityRegisters const*>(m_register_region->vaddr().get());
-    m_op_regs = bit_cast<OperationalRegisters volatile*>(m_register_region->vaddr().get() + m_cap_regs->capability_length);
+    m_cap_regs = bit_cast<CapabilityRegisters const*>(register_base_address.get());
+    m_op_regs = bit_cast<OperationalRegisters volatile*>(register_base_address.get() + m_cap_regs->capability_length);
 }
 
 ErrorOr<void> EHCIController::initialize()

+ 1 - 1
Kernel/Bus/USB/EHCI/EHCIController.h

@@ -36,7 +36,7 @@ public:
     virtual ErrorOr<void> submit_async_interrupt_transfer(NonnullLockRefPtr<Transfer>, u16) override { return ENOTSUP; }
 
 private:
-    EHCIController(PCI::DeviceIdentifier const& pci_device_identifier, NonnullOwnPtr<Memory::Region> register_region);
+    EHCIController(PCI::DeviceIdentifier const& pci_device_identifier, NonnullOwnPtr<Memory::Region> register_region, VirtualAddress register_base_address);
 
     NonnullOwnPtr<Memory::Region> m_register_region;
     CapabilityRegisters const* m_cap_regs;