VolumeManagementDevice.cpp 3.5 KB

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