MemoryBackedHostBridge.cpp 4.1 KB

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