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