Serenity Operating System
at master 94 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/ByteReader.h> 8#include <Kernel/Bus/PCI/Access.h> 9#include <Kernel/Bus/PCI/Controller/MemoryBackedHostBridge.h> 10#include <Kernel/Memory/MemoryManager.h> 11 12namespace Kernel::PCI { 13 14NonnullOwnPtr<MemoryBackedHostBridge> MemoryBackedHostBridge::must_create(Domain const& domain, PhysicalAddress start_address) 15{ 16 return adopt_own_if_nonnull(new (nothrow) MemoryBackedHostBridge(domain, start_address)).release_nonnull(); 17} 18 19MemoryBackedHostBridge::MemoryBackedHostBridge(PCI::Domain const& domain, PhysicalAddress start_address) 20 : HostController(domain) 21 , m_start_address(start_address) 22{ 23} 24 25u8 MemoryBackedHostBridge::read8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field) 26{ 27 VERIFY(Access::the().access_lock().is_locked()); 28 VERIFY(field <= 0xfff); 29 return *((u8 volatile*)(get_device_configuration_memory_mapped_space(bus, device, function).get() + (field & 0xfff))); 30} 31u16 MemoryBackedHostBridge::read16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field) 32{ 33 VERIFY(Access::the().access_lock().is_locked()); 34 VERIFY(field < 0xfff); 35 u16 data = 0; 36 ByteReader::load<u16>(get_device_configuration_memory_mapped_space(bus, device, function).offset(field & 0xfff).as_ptr(), data); 37 return data; 38} 39u32 MemoryBackedHostBridge::read32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field) 40{ 41 VERIFY(Access::the().access_lock().is_locked()); 42 VERIFY(field <= 0xffc); 43 u32 data = 0; 44 ByteReader::load<u32>(get_device_configuration_memory_mapped_space(bus, device, function).offset(field & 0xfff).as_ptr(), data); 45 return data; 46} 47void MemoryBackedHostBridge::write8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u8 value) 48{ 49 VERIFY(Access::the().access_lock().is_locked()); 50 VERIFY(field <= 0xfff); 51 *((u8 volatile*)(get_device_configuration_memory_mapped_space(bus, device, function).get() + (field & 0xfff))) = value; 52} 53void MemoryBackedHostBridge::write16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u16 value) 54{ 55 VERIFY(Access::the().access_lock().is_locked()); 56 VERIFY(field < 0xfff); 57 ByteReader::store<u16>(get_device_configuration_memory_mapped_space(bus, device, function).offset(field & 0xfff).as_ptr(), value); 58} 59void MemoryBackedHostBridge::write32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u32 value) 60{ 61 VERIFY(Access::the().access_lock().is_locked()); 62 VERIFY(field <= 0xffc); 63 ByteReader::store<u32>(get_device_configuration_memory_mapped_space(bus, device, function).offset(field & 0xfff).as_ptr(), value); 64} 65 66void MemoryBackedHostBridge::map_bus_region(BusNumber bus) 67{ 68 VERIFY(Access::the().access_lock().is_locked()); 69 if (m_mapped_bus == bus && m_mapped_bus_region) 70 return; 71 auto bus_base_address = determine_memory_mapped_bus_base_address(bus); 72 auto region_or_error = MM.allocate_kernel_region(bus_base_address, memory_range_per_bus, "PCI ECAM"sv, Memory::Region::Access::ReadWrite); 73 // FIXME: Find a way to propagate error from here. 74 if (region_or_error.is_error()) 75 VERIFY_NOT_REACHED(); 76 m_mapped_bus_region = region_or_error.release_value(); 77 m_mapped_bus = bus; 78 dbgln_if(PCI_DEBUG, "PCI: New PCI ECAM Mapped region for bus {} @ {} {}", bus, m_mapped_bus_region->vaddr(), m_mapped_bus_region->physical_page(0)->paddr()); 79} 80 81VirtualAddress MemoryBackedHostBridge::get_device_configuration_memory_mapped_space(BusNumber bus, DeviceNumber device, FunctionNumber function) 82{ 83 VERIFY(Access::the().access_lock().is_locked()); 84 map_bus_region(bus); 85 return m_mapped_bus_region->vaddr().offset(mmio_device_space_size * function.value() + (mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice)) * device.value()); 86} 87 88PhysicalAddress MemoryBackedHostBridge::determine_memory_mapped_bus_base_address(BusNumber bus) const 89{ 90 auto start_bus = min(bus.value(), m_domain.start_bus()); 91 return m_start_address.offset(memory_range_per_bus * (bus.value() - start_bus)); 92} 93 94}