mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:52:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			86 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/ByteReader.h>
 | |
| #include <Kernel/Arch/x86/IO.h>
 | |
| #include <Kernel/Bus/PCI/API.h>
 | |
| #include <Kernel/Bus/PCI/Access.h>
 | |
| #include <Kernel/Bus/PCI/Controller/VolumeManagementDevice.h>
 | |
| 
 | |
| namespace Kernel::PCI {
 | |
| 
 | |
| static Atomic<u32> s_vmd_pci_domain_number = 0x10000;
 | |
| 
 | |
| NonnullOwnPtr<VolumeManagementDevice> VolumeManagementDevice::must_create(PCI::DeviceIdentifier const& device_identifier)
 | |
| {
 | |
|     u8 start_bus = 0;
 | |
|     switch ((PCI::read16(device_identifier.address(), static_cast<PCI::RegisterOffset>(0x44)) >> 8) & 0x3) {
 | |
|     case 0:
 | |
|         break;
 | |
|     case 1:
 | |
|         start_bus = 128;
 | |
|         break;
 | |
|     case 2:
 | |
|         start_bus = 224;
 | |
|         break;
 | |
|     default:
 | |
|         dbgln("VMD @ {}: Unknown bus offset option was set to {}", device_identifier.address(),
 | |
|             ((PCI::read16(device_identifier.address(), static_cast<PCI::RegisterOffset>(0x44)) >> 8) & 0x3));
 | |
|         VERIFY_NOT_REACHED();
 | |
|     }
 | |
| 
 | |
|     // FIXME: The end bus might not be 255, so we actually need to check it with the
 | |
|     // resource size of BAR0.
 | |
|     dbgln("VMD Host bridge @ {}: Start bus at {}, end bus {}", device_identifier.address(), start_bus, 0xff);
 | |
|     PCI::Domain domain { s_vmd_pci_domain_number++, start_bus, 0xff };
 | |
|     auto start_address = PhysicalAddress(PCI::get_BAR0(device_identifier.address())).page_base();
 | |
|     return adopt_own_if_nonnull(new (nothrow) VolumeManagementDevice(domain, start_address)).release_nonnull();
 | |
| }
 | |
| 
 | |
| void VolumeManagementDevice::write8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u8 value)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     // Note: We must write then read to ensure completion before returning.
 | |
|     MemoryBackedHostBridge::write8_field(bus, device, function, field, value);
 | |
|     MemoryBackedHostBridge::read8_field(bus, device, function, field);
 | |
| }
 | |
| void VolumeManagementDevice::write16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u16 value)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     // Note: We must write then read to ensure completion before returning.
 | |
|     MemoryBackedHostBridge::write16_field(bus, device, function, field, value);
 | |
|     MemoryBackedHostBridge::read16_field(bus, device, function, field);
 | |
| }
 | |
| void VolumeManagementDevice::write32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field, u32 value)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     // Note: We must write then read to ensure completion before returning.
 | |
|     MemoryBackedHostBridge::write32_field(bus, device, function, field, value);
 | |
|     MemoryBackedHostBridge::read32_field(bus, device, function, field);
 | |
| }
 | |
| 
 | |
| u8 VolumeManagementDevice::read8_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     return MemoryBackedHostBridge::read8_field(bus, device, function, field);
 | |
| }
 | |
| u16 VolumeManagementDevice::read16_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     return MemoryBackedHostBridge::read16_field(bus, device, function, field);
 | |
| }
 | |
| u32 VolumeManagementDevice::read32_field(BusNumber bus, DeviceNumber device, FunctionNumber function, u32 field)
 | |
| {
 | |
|     SpinlockLocker locker(m_config_lock);
 | |
|     return MemoryBackedHostBridge::read32_field(bus, device, function, field);
 | |
| }
 | |
| 
 | |
| VolumeManagementDevice::VolumeManagementDevice(PCI::Domain const& domain, PhysicalAddress start_address)
 | |
|     : MemoryBackedHostBridge(domain, start_address)
 | |
| {
 | |
| }
 | |
| 
 | |
| }
 | 
