ladybird/Kernel/Bus/PCI/Definitions.h

333 lines
8.8 KiB
C
Raw Normal View History

/*
2020-03-06 11:59:29 -03:00
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Badge.h>
#include <AK/DistinctNumeric.h>
#include <AK/Function.h>
#include <AK/Types.h>
#include <AK/Vector.h>
Meta: Split debug defines into multiple headers. The following script was used to make these changes: #!/bin/bash set -e tmp=$(mktemp -d) echo "tmp=$tmp" find Kernel \( -name '*.cpp' -o -name '*.h' \) | sort > $tmp/Kernel.files find . \( -path ./Toolchain -prune -o -path ./Build -prune -o -path ./Kernel -prune \) -o \( -name '*.cpp' -o -name '*.h' \) -print | sort > $tmp/EverythingExceptKernel.files cat $tmp/Kernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/Kernel.macros cat $tmp/EverythingExceptKernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/EverythingExceptKernel.macros comm -23 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/Kernel.unique comm -1 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/EverythingExceptKernel.unique cat $tmp/Kernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/Kernel.header cat $tmp/EverythingExceptKernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/EverythingExceptKernel.header for macro in $(cat $tmp/Kernel.unique) do cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.new-includes ||: done cat $tmp/Kernel.new-includes | sort > $tmp/Kernel.new-includes.sorted for macro in $(cat $tmp/EverythingExceptKernel.unique) do cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.old-includes ||: done cat $tmp/Kernel.old-includes | sort > $tmp/Kernel.old-includes.sorted comm -23 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.new comm -13 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.old comm -12 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.mixed for file in $(cat $tmp/Kernel.includes.new) do sed -i -E 's/#include <AK\/Debug\.h>/#include <Kernel\/Debug\.h>/' $file done for file in $(cat $tmp/Kernel.includes.mixed) do echo "mixed include in $file, requires manual editing." done
2021-01-25 12:07:10 -03:00
#include <Kernel/Debug.h>
#include <Kernel/PhysicalAddress.h>
namespace Kernel::PCI {
enum class HeaderType {
Device = 0,
Bridge = 1,
};
enum class HeaderType0BaseRegister {
BAR0 = 0,
BAR1,
BAR2,
BAR3,
BAR4,
BAR5,
};
Kernel: Introduce the IOWindow class This class is intended to replace all IOAddress usages in the Kernel codebase altogether. The idea is to ensure IO can be done in arch-specific manner that is determined mostly in compile-time, but to still be able to use most of the Kernel code in non-x86 builds. Specific devices that rely on x86-specific IO instructions are already placed in the Arch/x86 directory and are omitted for non-x86 builds. The reason this works so well is the fact that x86 IO space acts in a similar fashion to the traditional memory space being available in most CPU architectures - the x86 IO space is essentially just an array of bytes like the physical memory address space, but requires x86 IO instructions to load and store data. Therefore, many devices allow host software to interact with the hardware registers in both ways, with a noticeable trend even in the modern x86 hardware to move away from the old x86 IO space to exclusively using memory-mapped IO. Therefore, the IOWindow class encapsulates both methods for x86 builds. The idea is to allow PCI devices to be used in either way in x86 builds, so when trying to map an IOWindow on a PCI BAR, the Kernel will try to find the proper method being declared with the PCI BAR flags. For old PCI hardware on non-x86 builds this might turn into a problem as we can't use port mapped IO, so the Kernel will gracefully fail with ENOTSUP error code if that's the case, as there's really nothing we can do within such case. For general IO, the read{8,16,32} and write{8,16,32} methods are available as a convenient API for other places in the Kernel. There are simply no direct 64-bit IO API methods yet, as it's not needed right now and is not considered to be Arch-agnostic too - the x86 IO space doesn't support generating 64 bit cycle on IO bus and instead requires two 2 32-bit accesses. If for whatever reason it appears to be necessary to do IO in such manner, it could probably be added with some neat tricks to do so. It is recommended to use Memory::TypedMapping struct if direct 64 bit IO is actually needed.
2022-09-23 05:50:04 -03:00
enum class BARSpaceType {
IOSpace,
Memory16BitSpace,
Memory32BitSpace,
Memory64BitSpace,
};
enum class RegisterOffset {
VENDOR_ID = 0x00, // word
DEVICE_ID = 0x02, // word
COMMAND = 0x04, // word
STATUS = 0x06, // word
REVISION_ID = 0x08, // byte
PROG_IF = 0x09, // byte
SUBCLASS = 0x0a, // byte
CLASS = 0x0b, // byte
CACHE_LINE_SIZE = 0x0c, // byte
LATENCY_TIMER = 0x0d, // byte
HEADER_TYPE = 0x0e, // byte
BIST = 0x0f, // byte
BAR0 = 0x10, // u32
BAR1 = 0x14, // u32
BAR2 = 0x18, // u32
SECONDARY_BUS = 0x19, // byte
BAR3 = 0x1C, // u32
BAR4 = 0x20, // u32
BAR5 = 0x24, // u32
SUBSYSTEM_VENDOR_ID = 0x2C, // u16
SUBSYSTEM_ID = 0x2E, // u16
CAPABILITIES_POINTER = 0x34, // u8
INTERRUPT_LINE = 0x3C, // byte
INTERRUPT_PIN = 0x3D, // byte
};
enum class Limits {
MaxDevicesPerBus = 32,
MaxBusesPerDomain = 256,
MaxFunctionsPerDevice = 8,
};
static constexpr u16 address_port = 0xcf8;
static constexpr u16 value_port = 0xcfc;
static constexpr size_t mmio_device_space_size = 4096;
static constexpr u16 none_value = 0xffff;
static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice) * to_underlying(Limits::MaxDevicesPerBus);
// Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf
enum class ClassID {
MassStorage = 0x1,
Multimedia = 0x4,
Bridge = 0x6,
};
namespace MassStorage {
enum class SubclassID {
IDEController = 0x1,
SATAController = 0x6,
NVMeController = 0x8,
};
enum class SATAProgIF {
AHCI = 0x1,
};
}
namespace Multimedia {
enum class SubclassID {
AudioController = 0x1,
};
}
namespace Bridge {
enum class SubclassID {
PCI_TO_PCI = 0x4,
};
}
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, CapabilityID);
namespace Capabilities {
enum ID {
Null = 0x0,
MSI = 0x5,
VendorSpecific = 0x9,
MSIX = 0x11,
};
}
struct HardwareID {
u16 vendor_id { 0 };
u16 device_id { 0 };
bool is_null() const { return !vendor_id && !device_id; }
2022-04-01 14:58:27 -03:00
bool operator==(HardwareID const& other) const
{
return vendor_id == other.vendor_id && device_id == other.device_id;
}
2022-04-01 14:58:27 -03:00
bool operator!=(HardwareID const& other) const
{
return vendor_id != other.vendor_id || device_id != other.device_id;
}
};
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
class Domain {
public:
Domain() = delete;
Domain(u32 domain_number, u8 start_bus, u8 end_bus)
: m_domain_number(domain_number)
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
, m_start_bus(start_bus)
, m_end_bus(end_bus)
{
}
u8 start_bus() const { return m_start_bus; }
u8 end_bus() const { return m_end_bus; }
u32 domain_number() const { return m_domain_number; }
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
private:
u32 m_domain_number;
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
u8 m_start_bus;
u8 m_end_bus;
};
struct Address {
public:
Address() = default;
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
Address(u32 domain)
: m_domain(domain)
, m_bus(0)
, m_device(0)
, m_function(0)
{
}
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
Address(u32 domain, u8 bus, u8 device, u8 function)
: m_domain(domain)
, m_bus(bus)
, m_device(device)
, m_function(function)
{
}
2022-04-01 14:58:27 -03:00
Address(Address const& address) = default;
bool is_null() const { return !m_bus && !m_device && !m_function; }
operator bool() const { return !is_null(); }
// Disable default implementations that would use surprising integer promotion.
2022-04-01 14:58:27 -03:00
bool operator<=(Address const&) const = delete;
bool operator>=(Address const&) const = delete;
bool operator<(Address const&) const = delete;
bool operator>(Address const&) const = delete;
2022-04-01 14:58:27 -03:00
bool operator==(Address const& other) const
{
if (this == &other)
return true;
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
return m_domain == other.m_domain && m_bus == other.m_bus && m_device == other.m_device && m_function == other.m_function;
}
2022-04-01 14:58:27 -03:00
bool operator!=(Address const& other) const
{
return !(*this == other);
}
u32 domain() const { return m_domain; }
u8 bus() const { return m_bus; }
u8 device() const { return m_device; }
u8 function() const { return m_function; }
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
private:
u32 m_domain { 0 };
u8 m_bus { 0 };
u8 m_device { 0 };
u8 m_function { 0 };
};
class Capability {
public:
2022-04-01 14:58:27 -03:00
Capability(Address const& address, u8 id, u8 ptr)
: m_address(address)
, m_id(id)
, m_ptr(ptr)
{
}
CapabilityID id() const { return m_id; }
u8 read8(u32) const;
u16 read16(u32) const;
u32 read32(u32) const;
void write8(u32, u8);
void write16(u32, u16);
void write32(u32, u32);
private:
Address m_address;
const CapabilityID m_id;
const u8 m_ptr;
};
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, ClassCode);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, SubclassCode);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, ProgrammingInterface);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, RevisionID);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemID);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemVendorID);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, InterruptLine);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, InterruptPin);
class Access;
class DeviceIdentifier {
public:
DeviceIdentifier(Address address, HardwareID hardware_id, RevisionID revision_id, ClassCode class_code, SubclassCode subclass_code, ProgrammingInterface prog_if, SubsystemID subsystem_id, SubsystemVendorID subsystem_vendor_id, InterruptLine interrupt_line, InterruptPin interrupt_pin, Vector<Capability> const& capabilities)
: m_address(address)
, m_hardware_id(hardware_id)
, m_revision_id(revision_id)
, m_class_code(class_code)
, m_subclass_code(subclass_code)
, m_prog_if(prog_if)
, m_subsystem_id(subsystem_id)
, m_subsystem_vendor_id(subsystem_vendor_id)
, m_interrupt_line(interrupt_line)
, m_interrupt_pin(interrupt_pin)
, m_capabilities(capabilities)
{
if constexpr (PCI_DEBUG) {
2022-04-01 14:58:27 -03:00
for (auto const& capability : capabilities)
dbgln("{} has capability {}", address, capability.id());
}
}
Vector<Capability> const& capabilities() const { return m_capabilities; }
HardwareID const& hardware_id() const { return m_hardware_id; }
Address const& address() const { return m_address; }
RevisionID revision_id() const { return m_revision_id; }
ClassCode class_code() const { return m_class_code; }
SubclassCode subclass_code() const { return m_subclass_code; }
ProgrammingInterface prog_if() const { return m_prog_if; }
SubsystemID subsystem_id() const { return m_subsystem_id; }
SubsystemVendorID subsystem_vendor_id() const { return m_subsystem_vendor_id; }
InterruptLine interrupt_line() const { return m_interrupt_line; }
InterruptPin interrupt_pin() const { return m_interrupt_pin; }
void apply_subclass_code_change(Badge<Access>, SubclassCode new_subclass)
{
m_subclass_code = new_subclass;
}
void apply_prog_if_change(Badge<Access>, ProgrammingInterface new_progif)
{
m_prog_if = new_progif;
}
private:
Address m_address;
HardwareID m_hardware_id;
RevisionID m_revision_id;
ClassCode m_class_code;
SubclassCode m_subclass_code;
ProgrammingInterface m_prog_if;
SubsystemID m_subsystem_id;
SubsystemVendorID m_subsystem_vendor_id;
InterruptLine m_interrupt_line;
InterruptPin m_interrupt_pin;
Vector<Capability> m_capabilities;
};
Kernel/PCI: Simplify the entire subsystem A couple of things were changed: 1. Semantic changes - PCI segments are now called PCI domains, to better match what they are really. It's also the name that Linux gave, and it seems that Wikipedia also uses this name. We also remove PCI::ChangeableAddress, because it was used in the past but now it's no longer being used. 2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as they made a bunch of unnecessary complexity. Instead, Windowed access is removed entirely (this was tested, but never was benchmarked), so we are left with IO access and memory access options. The memory access option is essentially mapping the PCI bus (from the chosen PCI domain), to virtual memory as-is. This means that unless needed, at any time, there is only one PCI bus being mapped, and this is changed if access to another PCI bus in the same PCI domain is needed. For now, we don't support mapping of different PCI buses from different PCI domains at the same time, because basically it's still a non-issue for most machines out there. 2. OOM-safety is increased, especially when constructing the Access object. It means that we pre-allocating any needed resources, and we try to find PCI domains (if requested to initialize memory access) after we attempt to construct the Access object, so it's possible to fail at this point "gracefully". 3. All PCI API functions are now separated into a different header file, which means only "clients" of the PCI subsystem API will need to include that header file. 4. Functional changes - we only allow now to enumerate the bus after a hardware scan. This means that the old method "enumerate_hardware" is removed, so, when initializing an Access object, the initializing function must call rescan on it to force it to find devices. This makes it possible to fail rescan, and also to defer it after construction from both OOM-safety terms and hotplug capabilities.
2021-09-07 06:08:38 -03:00
class Domain;
class Device;
}
template<>
struct AK::Formatter<Kernel::PCI::Address> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, Kernel::PCI::Address value)
{
return Formatter<FormatString>::format(
builder,
"PCI [{:04x}:{:02x}:{:02x}:{:02x}]"sv, value.domain(), value.bus(), value.device(), value.function());
}
};
template<>
struct AK::Formatter<Kernel::PCI::HardwareID> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, Kernel::PCI::HardwareID value)
{
return Formatter<FormatString>::format(
builder,
"PCI::HardwareID [{:04x}:{:04x}]"sv, value.vendor_id, value.device_id);
}
};