VolumeManagementDevice.cpp 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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/Bus/PCI/API.h>
  8. #include <Kernel/Bus/PCI/Access.h>
  9. #include <Kernel/Bus/PCI/Controller/VolumeManagementDevice.h>
  10. namespace Kernel::PCI {
  11. static Atomic<u32> s_vmd_pci_domain_number = 0x10000;
  12. NonnullOwnPtr<VolumeManagementDevice> VolumeManagementDevice::must_create(PCI::DeviceIdentifier const& device_identifier)
  13. {
  14. u8 start_bus = 0;
  15. switch ((PCI::read16(device_identifier.address(), static_cast<PCI::RegisterOffset>(0x44)) >> 8) & 0x3) {
  16. case 0:
  17. break;
  18. case 1:
  19. start_bus = 128;
  20. break;
  21. case 2:
  22. start_bus = 224;
  23. break;
  24. default:
  25. dbgln("VMD @ {}: Unknown bus offset option was set to {}", device_identifier.address(),
  26. ((PCI::read16(device_identifier.address(), static_cast<PCI::RegisterOffset>(0x44)) >> 8) & 0x3));
  27. VERIFY_NOT_REACHED();
  28. }
  29. // FIXME: The end bus might not be 255, so we actually need to check it with the
  30. // resource size of BAR0.
  31. dbgln("VMD Host bridge @ {}: Start bus at {}, end bus {}", device_identifier.address(), start_bus, 0xff);
  32. PCI::Domain domain { s_vmd_pci_domain_number++, start_bus, 0xff };
  33. auto start_address = PhysicalAddress(PCI::get_BAR0(device_identifier.address())).page_base();
  34. return adopt_own_if_nonnull(new (nothrow) VolumeManagementDevice(domain, start_address)).release_nonnull();
  35. }
  36. void VolumeManagementDevice::write8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u8 value)
  37. {
  38. SpinlockLocker locker(m_config_lock);
  39. // Note: We must write then read to ensure completion before returning.
  40. MemoryBackedHostBridge::write8_field(bus, device, function, field, value);
  41. MemoryBackedHostBridge::read8_field(bus, device, function, field);
  42. }
  43. void VolumeManagementDevice::write16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u16 value)
  44. {
  45. SpinlockLocker locker(m_config_lock);
  46. // Note: We must write then read to ensure completion before returning.
  47. MemoryBackedHostBridge::write16_field(bus, device, function, field, value);
  48. MemoryBackedHostBridge::read16_field(bus, device, function, field);
  49. }
  50. void VolumeManagementDevice::write32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u32 value)
  51. {
  52. SpinlockLocker locker(m_config_lock);
  53. // Note: We must write then read to ensure completion before returning.
  54. MemoryBackedHostBridge::write32_field(bus, device, function, field, value);
  55. MemoryBackedHostBridge::read32_field(bus, device, function, field);
  56. }
  57. u8 VolumeManagementDevice::read8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
  58. {
  59. SpinlockLocker locker(m_config_lock);
  60. return MemoryBackedHostBridge::read8_field(bus, device, function, field);
  61. }
  62. u16 VolumeManagementDevice::read16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
  63. {
  64. SpinlockLocker locker(m_config_lock);
  65. return MemoryBackedHostBridge::read16_field(bus, device, function, field);
  66. }
  67. u32 VolumeManagementDevice::read32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
  68. {
  69. SpinlockLocker locker(m_config_lock);
  70. return MemoryBackedHostBridge::read32_field(bus, device, function, field);
  71. }
  72. VolumeManagementDevice::VolumeManagementDevice(PCI::Domain const& domain, PhysicalAddress start_address)
  73. : MemoryBackedHostBridge(domain, start_address)
  74. {
  75. }
  76. }