Kernel/PCI: Remove all macros and replace them with enum classes

This commit is contained in:
Liav A 2021-09-28 20:18:51 +03:00 committed by Andreas Kling
parent 9d9d57056e
commit ef9b8ff0c7
11 changed files with 206 additions and 146 deletions

View file

@ -10,12 +10,12 @@
namespace Kernel::PCI {
void write8(Address address, u32 field, u8 value) { Access::the().write8_field(address, field, value); }
void write16(Address address, u32 field, u16 value) { Access::the().write16_field(address, field, value); }
void write32(Address address, u32 field, u32 value) { Access::the().write32_field(address, field, value); }
u8 read8(Address address, u32 field) { return Access::the().read8_field(address, field); }
u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); }
u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); }
void write8(Address address, PCI::RegisterOffset field, u8 value) { Access::the().write8_field(address, to_underlying(field), value); }
void write16(Address address, PCI::RegisterOffset field, u16 value) { Access::the().write16_field(address, to_underlying(field), value); }
void write32(Address address, PCI::RegisterOffset field, u32 value) { Access::the().write32_field(address, to_underlying(field), value); }
u8 read8(Address address, PCI::RegisterOffset field) { return Access::the().read8_field(address, to_underlying(field)); }
u16 read16(Address address, PCI::RegisterOffset field) { return Access::the().read16_field(address, to_underlying(field)); }
u32 read32(Address address, PCI::RegisterOffset field) { return Access::the().read32_field(address, to_underlying(field)); }
void enumerate(Function<void(DeviceIdentifier const&)> callback)
{
@ -29,69 +29,69 @@ DeviceIdentifier get_device_identifier(Address address)
HardwareID get_hardware_id(Address address)
{
return { read16(address, PCI_VENDOR_ID), read16(address, PCI_DEVICE_ID) };
return { read16(address, PCI::RegisterOffset::VENDOR_ID), read16(address, PCI::RegisterOffset::DEVICE_ID) };
}
void enable_io_space(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 0));
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) | (1 << 0));
}
void disable_io_space(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 0));
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) & ~(1 << 0));
}
void enable_memory_space(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 1));
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) | (1 << 1));
}
void disable_memory_space(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 1));
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) & ~(1 << 1));
}
bool is_io_space_enabled(Address address)
{
return (read16(address, PCI_COMMAND) & 1) != 0;
return (read16(address, PCI::RegisterOffset::COMMAND) & 1) != 0;
}
void enable_interrupt_line(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 10));
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) & ~(1 << 10));
}
void disable_interrupt_line(Address address)
{
write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | 1 << 10);
write16(address, PCI::RegisterOffset::COMMAND, read16(address, PCI::RegisterOffset::COMMAND) | 1 << 10);
}
u32 get_BAR0(Address address)
{
return read32(address, PCI_BAR0);
return read32(address, PCI::RegisterOffset::BAR0);
}
u32 get_BAR1(Address address)
{
return read32(address, PCI_BAR1);
return read32(address, PCI::RegisterOffset::BAR1);
}
u32 get_BAR2(Address address)
{
return read32(address, PCI_BAR2);
return read32(address, PCI::RegisterOffset::BAR2);
}
u32 get_BAR3(Address address)
{
return read16(address, PCI_BAR3);
return read16(address, PCI::RegisterOffset::BAR3);
}
u32 get_BAR4(Address address)
{
return read32(address, PCI_BAR4);
return read32(address, PCI::RegisterOffset::BAR4);
}
u32 get_BAR5(Address address)
{
return read32(address, PCI_BAR5);
return read32(address, PCI::RegisterOffset::BAR5);
}
u32 get_BAR(Address address, u8 bar)
@ -117,29 +117,36 @@ u32 get_BAR(Address address, u8 bar)
void enable_bus_mastering(Address address)
{
auto value = read16(address, PCI_COMMAND);
auto value = read16(address, PCI::RegisterOffset::COMMAND);
value |= (1 << 2);
value |= (1 << 0);
write16(address, PCI_COMMAND, value);
write16(address, PCI::RegisterOffset::COMMAND, value);
}
void disable_bus_mastering(Address address)
{
auto value = read16(address, PCI_COMMAND);
auto value = read16(address, PCI::RegisterOffset::COMMAND);
value &= ~(1 << 2);
value |= (1 << 0);
write16(address, PCI_COMMAND, value);
write16(address, PCI::RegisterOffset::COMMAND, value);
}
static void write8_offseted(Address address, u32 field, u8 value) { Access::the().write8_field(address, field, value); }
static void write16_offseted(Address address, u32 field, u16 value) { Access::the().write16_field(address, field, value); }
static void write32_offseted(Address address, u32 field, u32 value) { Access::the().write32_field(address, field, value); }
static u8 read8_offseted(Address address, u32 field) { return Access::the().read8_field(address, field); }
static u16 read16_offseted(Address address, u32 field) { return Access::the().read16_field(address, field); }
static u32 read32_offseted(Address address, u32 field) { return Access::the().read32_field(address, field); }
size_t get_BAR_space_size(Address address, u8 bar_number)
{
// See PCI Spec 2.3, Page 222
VERIFY(bar_number < 6);
u8 field = (PCI_BAR0 + (bar_number << 2));
u32 bar_reserved = read32(address, field);
write32(address, field, 0xFFFFFFFF);
u32 space_size = read32(address, field);
write32(address, field, bar_reserved);
u8 field = to_underlying(PCI::RegisterOffset::BAR0) + (bar_number << 2);
u32 bar_reserved = read32_offseted(address, field);
write32_offseted(address, field, 0xFFFFFFFF);
u32 space_size = read32_offseted(address, field);
write32_offseted(address, field, bar_reserved);
space_size &= 0xfffffff0;
space_size = (~space_size) + 1;
return space_size;
@ -149,15 +156,15 @@ void raw_access(Address address, u32 field, size_t access_size, u32 value)
{
VERIFY(access_size != 0);
if (access_size == 1) {
write8(address, field, value);
write8_offseted(address, field, value);
return;
}
if (access_size == 2) {
write16(address, field, value);
write16_offseted(address, field, value);
return;
}
if (access_size == 4) {
write32(address, field, value);
write32_offseted(address, field, value);
return;
}
VERIFY_NOT_REACHED();
@ -165,32 +172,32 @@ void raw_access(Address address, u32 field, size_t access_size, u32 value)
u8 Capability::read8(u32 field) const
{
return PCI::read8(m_address, m_ptr + field);
return read8_offseted(m_address, m_ptr + field);
}
u16 Capability::read16(u32 field) const
{
return PCI::read16(m_address, m_ptr + field);
return read16_offseted(m_address, m_ptr + field);
}
u32 Capability::read32(u32 field) const
{
return PCI::read32(m_address, m_ptr + field);
return read32_offseted(m_address, m_ptr + field);
}
void Capability::write8(u32 field, u8 value)
{
PCI::write8(m_address, m_ptr + field, value);
write8_offseted(m_address, m_ptr + field, value);
}
void Capability::write16(u32 field, u16 value)
{
PCI::write16(m_address, m_ptr + field, value);
write16_offseted(m_address, m_ptr + field, value);
}
void Capability::write32(u32 field, u32 value)
{
PCI::write32(m_address, m_ptr + field, value);
write32_offseted(m_address, m_ptr + field, value);
}
}

View file

@ -10,12 +10,12 @@
namespace Kernel::PCI {
void write8(Address address, u32 field, u8 value);
void write16(Address address, u32 field, u16 value);
void write32(Address address, u32 field, u32 value);
u8 read8(Address address, u32 field);
u16 read16(Address address, u32 field);
u32 read32(Address address, u32 field);
void write8(Address address, PCI::RegisterOffset field, u8 value);
void write16(Address address, PCI::RegisterOffset field, u16 value);
void write32(Address address, PCI::RegisterOffset field, u32 value);
u8 read8(Address address, PCI::RegisterOffset field);
u16 read16(Address address, PCI::RegisterOffset field);
u32 read32(Address address, PCI::RegisterOffset field);
HardwareID get_hardware_id(PCI::Address);
bool is_io_space_enabled(Address);

View file

@ -18,7 +18,6 @@
namespace Kernel::PCI {
#define PCI_MMIO_CONFIG_SPACE_SIZE 4096
#define MEMORY_RANGE_PER_BUS (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE * PCI_MAX_DEVICES_PER_BUS)
static Access* s_access;
@ -109,7 +108,7 @@ Optional<PhysicalAddress> Access::determine_memory_mapped_bus_base_address(u32 d
return {};
if (!(chosen_domain.value().start_bus() <= bus && bus <= chosen_domain.value().end_bus()))
return {};
return chosen_domain.value().paddr().offset(MEMORY_RANGE_PER_BUS * (bus - chosen_domain.value().start_bus()));
return chosen_domain.value().paddr().offset(memory_range_per_bus * (bus - chosen_domain.value().start_bus()));
}
void Access::map_bus_region(u32 domain, u8 bus)
@ -121,7 +120,7 @@ void Access::map_bus_region(u32 domain, u8 bus)
// FIXME: Find a way to propagate error from here.
if (!bus_base_address.has_value())
VERIFY_NOT_REACHED();
auto region_or_error = MM.allocate_kernel_region(bus_base_address.value(), MEMORY_RANGE_PER_BUS, "PCI ECAM", Memory::Region::Access::ReadWrite);
auto region_or_error = MM.allocate_kernel_region(bus_base_address.value(), memory_range_per_bus, "PCI ECAM", Memory::Region::Access::ReadWrite);
// FIXME: Find a way to propagate error from here.
if (region_or_error.is_error())
VERIFY_NOT_REACHED();
@ -135,50 +134,50 @@ VirtualAddress Access::get_device_configuration_memory_mapped_space(Address addr
VERIFY(m_access_lock.is_locked());
dbgln_if(PCI_DEBUG, "PCI: Getting device configuration space for {}", address);
map_bus_region(address.domain(), address.bus());
return m_mapped_bus_region->vaddr().offset(PCI_MMIO_CONFIG_SPACE_SIZE * address.function() + (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE) * address.device());
return m_mapped_bus_region->vaddr().offset(mmio_device_space_size * address.function() + (mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice)) * address.device());
}
u8 Access::io_read8_field(Address address, u32 field)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Reading 8-bit field {:#08x} for {}", field, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
return IO::in8(PCI_VALUE_PORT + (field & 3));
IO::out32(PCI::address_port, address.io_address_for_field(field));
return IO::in8(PCI::value_port + (field & 3));
}
u16 Access::io_read16_field(Address address, u32 field)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Reading 16-bit field {:#08x} for {}", field, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
return IO::in16(PCI_VALUE_PORT + (field & 2));
IO::out32(PCI::address_port, address.io_address_for_field(field));
return IO::in16(PCI::value_port + (field & 2));
}
u32 Access::io_read32_field(Address address, u32 field)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Reading 32-bit field {:#08x} for {}", field, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
return IO::in32(PCI_VALUE_PORT);
IO::out32(PCI::address_port, address.io_address_for_field(field));
return IO::in32(PCI::value_port);
}
void Access::io_write8_field(Address address, u32 field, u8 value)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Writing to 8-bit field {:#08x}, value={:#02x} for {}", field, value, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
IO::out8(PCI_VALUE_PORT + (field & 3), value);
IO::out32(PCI::address_port, address.io_address_for_field(field));
IO::out8(PCI::value_port + (field & 3), value);
}
void Access::io_write16_field(Address address, u32 field, u16 value)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Writing to 16-bit field {:#08x}, value={:#02x} for {}", field, value, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
IO::out16(PCI_VALUE_PORT + (field & 2), value);
IO::out32(PCI::address_port, address.io_address_for_field(field));
IO::out16(PCI::value_port + (field & 2), value);
}
void Access::io_write32_field(Address address, u32 field, u32 value)
{
MutexLocker lock(m_access_lock);
dbgln_if(PCI_DEBUG, "PCI: IO Writing to 32-bit field {:#08x}, value={:#02x} for {}", field, value, address);
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
IO::out32(PCI_VALUE_PORT, value);
IO::out32(PCI::address_port, address.io_address_for_field(field));
IO::out32(PCI::value_port, value);
}
u8 Access::memory_read8_field(Address address, u32 field)
@ -265,6 +264,15 @@ void Access::write32_field(Address address, u32 field, u32 value)
VERIFY_NOT_REACHED();
}
u8 Access::read8_field(Address address, RegisterOffset field)
{
return read8_field(address, to_underlying(field));
}
u16 Access::read16_field(Address address, RegisterOffset field)
{
return read16_field(address, to_underlying(field));
}
u8 Access::read8_field(Address address, u32 field)
{
switch (m_access_type) {
@ -311,11 +319,11 @@ UNMAP_AFTER_INIT void Access::rescan_hardware()
// Handle Multiple PCI host bridges on slot 0, device 0.
// If we happen to miss some PCI buses because they are not reachable through
// recursive PCI-to-PCI bridges starting from bus 0, we might find them here.
if ((read8_field(Address(), PCI_HEADER_TYPE) & 0x80) != 0) {
if ((read8_field(Address(), PCI::RegisterOffset::HEADER_TYPE) & 0x80) != 0) {
for (int bus = 1; bus < 256; ++bus) {
if (read16_field(Address(0, 0, 0, bus), PCI_VENDOR_ID) == PCI_NONE)
if (read16_field(Address(0, 0, 0, bus), PCI::RegisterOffset::VENDOR_ID) == PCI::none_value)
continue;
if (read16_field(Address(0, 0, 0, bus), PCI_CLASS) != 0x6)
if (read16_field(Address(0, 0, 0, bus), PCI::RegisterOffset::CLASS) != 0x6)
continue;
if (m_enumerated_buses.get(bus))
continue;
@ -330,14 +338,14 @@ UNMAP_AFTER_INIT void Access::rescan_hardware()
for (u32 domain = 0; domain < m_domains.size(); domain++) {
dbgln_if(PCI_DEBUG, "PCI: Scan memory mapped domain {}", domain);
// Single PCI host controller.
if ((read8_field(Address(domain), PCI_HEADER_TYPE) & 0x80) == 0) {
if ((read8_field(Address(domain), PCI::RegisterOffset::HEADER_TYPE) & 0x80) == 0) {
enumerate_bus(-1, 0, true);
return;
}
// Multiple PCI host controllers.
for (u8 function = 0; function < 8; ++function) {
if (read16_field(Address(domain, 0, 0, function), PCI_VENDOR_ID) == PCI_NONE)
if (read16_field(Address(domain, 0, 0, function), PCI::RegisterOffset::VENDOR_ID) == PCI::none_value)
break;
enumerate_bus(-1, function, false);
}
@ -347,9 +355,9 @@ UNMAP_AFTER_INIT void Access::rescan_hardware()
UNMAP_AFTER_INIT Optional<u8> Access::get_capabilities_pointer(Address address)
{
dbgln_if(PCI_DEBUG, "PCI: Getting capabilities pointer for {}", address);
if (read16_field(address, PCI_STATUS) & (1 << 4)) {
if (read16_field(address, PCI::RegisterOffset::STATUS) & (1 << 4)) {
dbgln_if(PCI_DEBUG, "PCI: Found capabilities pointer for {}", address);
return read8_field(address, PCI_CAPABILITIES_POINTER);
return read8_field(address, PCI::RegisterOffset::CAPABILITIES_POINTER);
}
dbgln_if(PCI_DEBUG, "PCI: No capabilities pointer for {}", address);
return {};
@ -379,22 +387,24 @@ UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u
{
dbgln_if(PCI_DEBUG, "PCI: Enumerating function type={}, bus={}, device={}, function={}", type, bus, device, function);
Address address(0, bus, device, function);
auto read_type = (read8_field(address, PCI_CLASS) << 8u) | read8_field(address, PCI_SUBCLASS);
auto read_type = (read8_field(address, PCI::RegisterOffset::CLASS) << 8u) | read8_field(address, PCI::RegisterOffset::SUBCLASS);
if (type == -1 || type == read_type) {
HardwareID id = { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) };
ClassCode class_code = read8_field(address, PCI_CLASS);
SubclassCode subclass_code = read8_field(address, PCI_SUBCLASS);
ProgrammingInterface prog_if = read8_field(address, PCI_PROG_IF);
RevisionID revision_id = read8_field(address, PCI_REVISION_ID);
SubsystemID subsystem_id = read16_field(address, PCI_SUBSYSTEM_ID);
SubsystemVendorID subsystem_vendor_id = read16_field(address, PCI_SUBSYSTEM_VENDOR_ID);
InterruptLine interrupt_line = read8_field(address, PCI_INTERRUPT_LINE);
InterruptPin interrupt_pin = read8_field(address, PCI_INTERRUPT_PIN);
HardwareID id = { read16_field(address, PCI::RegisterOffset::VENDOR_ID), read16_field(address, PCI::RegisterOffset::DEVICE_ID) };
ClassCode class_code = read8_field(address, PCI::RegisterOffset::CLASS);
SubclassCode subclass_code = read8_field(address, PCI::RegisterOffset::SUBCLASS);
ProgrammingInterface prog_if = read8_field(address, PCI::RegisterOffset::PROG_IF);
RevisionID revision_id = read8_field(address, PCI::RegisterOffset::REVISION_ID);
SubsystemID subsystem_id = read16_field(address, PCI::RegisterOffset::SUBSYSTEM_ID);
SubsystemVendorID subsystem_vendor_id = read16_field(address, PCI::RegisterOffset::SUBSYSTEM_VENDOR_ID);
InterruptLine interrupt_line = read8_field(address, PCI::RegisterOffset::INTERRUPT_LINE);
InterruptPin interrupt_pin = read8_field(address, PCI::RegisterOffset::INTERRUPT_PIN);
m_device_identifiers.append(DeviceIdentifier { address, id, revision_id, class_code, subclass_code, prog_if, subsystem_id, subsystem_vendor_id, interrupt_line, interrupt_pin, get_capabilities(address) });
}
if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) {
u8 secondary_bus = read8_field(address, PCI_SECONDARY_BUS);
if (read_type == (to_underlying(PCI::ClassID::Bridge) << 8 | to_underlying(PCI::Bridge::SubclassID::PCI_TO_PCI))
&& recursive
&& (!m_enumerated_buses.get(read8_field(address, PCI::RegisterOffset::SECONDARY_BUS)))) {
u8 secondary_bus = read8_field(address, PCI::RegisterOffset::SECONDARY_BUS);
dbgln_if(PCI_DEBUG, "PCI: Found secondary bus: {}", secondary_bus);
VERIFY(secondary_bus != bus);
m_enumerated_buses.set(secondary_bus, true);
@ -406,14 +416,14 @@ UNMAP_AFTER_INIT void Access::enumerate_device(int type, u8 bus, u8 device, bool
{
dbgln_if(PCI_DEBUG, "PCI: Enumerating device type={}, bus={}, device={}", type, bus, device);
Address address(0, bus, device, 0);
if (read16_field(address, PCI_VENDOR_ID) == PCI_NONE)
if (read16_field(address, PCI::RegisterOffset::VENDOR_ID) == PCI::none_value)
return;
enumerate_functions(type, bus, device, 0, recursive);
if (!(read8_field(address, PCI_HEADER_TYPE) & 0x80))
if (!(read8_field(address, PCI::RegisterOffset::HEADER_TYPE) & 0x80))
return;
for (u8 function = 1; function < 8; ++function) {
Address address(0, bus, device, function);
if (read16_field(address, PCI_VENDOR_ID) != PCI_NONE)
if (read16_field(address, PCI::RegisterOffset::VENDOR_ID) != PCI::none_value)
enumerate_functions(type, bus, device, function, recursive);
}
}

View file

@ -40,6 +40,9 @@ public:
DeviceIdentifier get_device_identifier(Address address) const;
private:
u8 read8_field(Address address, RegisterOffset field);
u16 read16_field(Address address, RegisterOffset field);
void enumerate_bus(int type, u8 bus, bool recursive);
void enumerate_functions(int type, u8 bus, u8 device, u8 function, bool recursive);
void enumerate_device(int type, u8 bus, u8 device, bool recursive);

View file

@ -14,52 +14,89 @@
namespace Kernel {
#define PCI_VENDOR_ID 0x00 // word
#define PCI_DEVICE_ID 0x02 // word
#define PCI_COMMAND 0x04 // word
#define PCI_STATUS 0x06 // word
#define PCI_REVISION_ID 0x08 // byte
#define PCI_PROG_IF 0x09 // byte
#define PCI_SUBCLASS 0x0a // byte
#define PCI_CLASS 0x0b // byte
#define PCI_CACHE_LINE_SIZE 0x0c // byte
#define PCI_LATENCY_TIMER 0x0d // byte
#define PCI_HEADER_TYPE 0x0e // byte
#define PCI_BIST 0x0f // byte
#define PCI_BAR0 0x10 // u32
#define PCI_BAR1 0x14 // u32
#define PCI_BAR2 0x18 // u32
#define PCI_BAR3 0x1C // u32
#define PCI_BAR4 0x20 // u32
#define PCI_BAR5 0x24 // u32
#define PCI_SUBSYSTEM_VENDOR_ID 0x2C // u16
#define PCI_SUBSYSTEM_ID 0x2E // u16
#define PCI_CAPABILITIES_POINTER 0x34 // u8
#define PCI_INTERRUPT_LINE 0x3C // byte
#define PCI_INTERRUPT_PIN 0x3D // byte
#define PCI_SECONDARY_BUS 0x19 // byte
#define PCI_HEADER_TYPE_DEVICE 0
#define PCI_HEADER_TYPE_BRIDGE 1
#define PCI_TYPE_BRIDGE 0x0604
#define PCI_ADDRESS_PORT 0xCF8
#define PCI_VALUE_PORT 0xCFC
#define PCI_NONE 0xFFFF
#define PCI_MAX_DEVICES_PER_BUS 32
#define PCI_MAX_BUSES 256
#define PCI_MAX_FUNCTIONS_PER_DEVICE 8
namespace PCI {
#define PCI_CAPABILITY_NULL 0x0
#define PCI_CAPABILITY_MSI 0x5
#define PCI_CAPABILITY_VENDOR_SPECIFIC 0x9
#define PCI_CAPABILITY_MSIX 0x11
enum class HeaderType {
Device = 0,
Bridge = 1,
};
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
#define PCI_MASS_STORAGE_CLASS_ID 0x1
#define PCI_IDE_CTRL_SUBCLASS_ID 0x1
#define PCI_SATA_CTRL_SUBCLASS_ID 0x6
#define PCI_AHCI_IF_PROGIF 0x1
enum class ClassID {
MassStorage = 0x1,
Bridge = 0x6,
};
namespace MassStorage {
enum class SubclassID {
IDEController = 0x1,
SATAController = 0x6,
};
enum class SATAProgIF {
AHCI = 0x1,
};
}
namespace Bridge {
enum class SubclassID {
PCI_TO_PCI = 0x4,
};
}
TYPEDEF_DISTINCT_ORDERED_ID(u8, CapabilityID);
namespace Capabilities {
enum ID {
Null = 0x0,
MSI = 0x5,
VendorSpecific = 0x9,
MSIX = 0x11,
};
}
namespace PCI {
struct HardwareID {
u16 vendor_id { 0 };
u16 device_id { 0 };
@ -167,7 +204,7 @@ public:
{
}
u8 id() const { return m_id; }
CapabilityID id() const { return m_id; }
u8 read8(u32) const;
u16 read16(u32) const;
@ -178,7 +215,7 @@ public:
private:
Address m_address;
const u8 m_id;
const CapabilityID m_id;
const u8 m_ptr;
};

View file

@ -18,7 +18,7 @@ Device::Device(Address address)
bool Device::is_msi_capable() const
{
for (const auto& capability : PCI::get_device_identifier(pci_address()).capabilities()) {
if (capability.id() == PCI_CAPABILITY_MSI)
if (capability.id().value() == PCI::Capabilities::ID::MSI)
return true;
}
return false;
@ -26,7 +26,7 @@ bool Device::is_msi_capable() const
bool Device::is_msix_capable() const
{
for (const auto& capability : PCI::get_device_identifier(pci_address()).capabilities()) {
if (capability.id() == PCI_CAPABILITY_MSIX)
if (capability.id().value() == PCI::Capabilities::ID::MSIX)
return true;
}
return false;

View file

@ -65,8 +65,8 @@ UNMAP_AFTER_INIT bool test_pci_io()
{
dmesgln("Testing PCI via manual probing...");
u32 tmp = 0x80000000;
IO::out32(PCI_ADDRESS_PORT, tmp);
tmp = IO::in32(PCI_ADDRESS_PORT);
IO::out32(PCI::address_port, tmp);
tmp = IO::in32(PCI::address_port);
if (tmp == 0x80000000) {
dmesgln("PCI IO supported");
return true;

View file

@ -22,14 +22,14 @@ UNMAP_AFTER_INIT PCIDeviceSysFSDirectory::PCIDeviceSysFSDirectory(const SysFSDir
: SysFSDirectory(String::formatted("{:04x}:{:02x}:{:02x}.{}", address.domain(), address.bus(), address.device(), address.function()), parent_directory)
, m_address(address)
{
m_components.append(PCIDeviceAttributeSysFSComponent::create("vendor", *this, PCI_VENDOR_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("device_id", *this, PCI_DEVICE_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("class", *this, PCI_CLASS, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subclass", *this, PCI_SUBCLASS, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("revision", *this, PCI_REVISION_ID, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("progif", *this, PCI_PROG_IF, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_vendor", *this, PCI_SUBSYSTEM_VENDOR_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_id", *this, PCI_SUBSYSTEM_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("vendor", *this, PCI::RegisterOffset::VENDOR_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("device_id", *this, PCI::RegisterOffset::DEVICE_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("class", *this, PCI::RegisterOffset::CLASS, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subclass", *this, PCI::RegisterOffset::SUBCLASS, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("revision", *this, PCI::RegisterOffset::REVISION_ID, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("progif", *this, PCI::RegisterOffset::PROG_IF, 1));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_vendor", *this, PCI::RegisterOffset::SUBSYSTEM_VENDOR_ID, 2));
m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_id", *this, PCI::RegisterOffset::SUBSYSTEM_ID, 2));
}
UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize()
@ -47,12 +47,12 @@ UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory()
});
}
NonnullRefPtr<PCIDeviceAttributeSysFSComponent> PCIDeviceAttributeSysFSComponent::create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width)
NonnullRefPtr<PCIDeviceAttributeSysFSComponent> PCIDeviceAttributeSysFSComponent::create(String name, const PCIDeviceSysFSDirectory& device, PCI::RegisterOffset offset, size_t field_bytes_width)
{
return adopt_ref(*new (nothrow) PCIDeviceAttributeSysFSComponent(name, device, offset, field_bytes_width));
}
PCIDeviceAttributeSysFSComponent::PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width)
PCIDeviceAttributeSysFSComponent::PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, PCI::RegisterOffset offset, size_t field_bytes_width)
: SysFSComponent(name)
, m_device(device)
, m_offset(offset)

View file

@ -35,16 +35,16 @@ private:
class PCIDeviceAttributeSysFSComponent : public SysFSComponent {
public:
static NonnullRefPtr<PCIDeviceAttributeSysFSComponent> create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width);
static NonnullRefPtr<PCIDeviceAttributeSysFSComponent> create(String name, const PCIDeviceSysFSDirectory& device, PCI::RegisterOffset offset, size_t field_bytes_width);
virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override;
virtual ~PCIDeviceAttributeSysFSComponent() {};
protected:
KResultOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const;
PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width);
PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, PCI::RegisterOffset offset, size_t field_bytes_width);
NonnullRefPtr<PCIDeviceSysFSDirectory> m_device;
size_t m_offset;
PCI::RegisterOffset m_offset;
size_t m_field_bytes_width;
};

View file

@ -95,7 +95,7 @@ UNMAP_AFTER_INIT void Device::initialize()
auto capabilities = PCI::get_device_identifier(address).capabilities();
for (auto& capability : capabilities) {
if (capability.id() == PCI_CAPABILITY_VENDOR_SPECIFIC) {
if (capability.id().value() == PCI::Capabilities::ID::VendorSpecific) {
// We have a virtio_pci_cap
auto cfg = make<Configuration>();
auto raw_config_type = capability.read8(0x3);

View file

@ -45,13 +45,16 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
if (!kernel_command_line().disable_physical_storage()) {
if (kernel_command_line().is_ide_enabled()) {
PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
if (device_identifier.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && device_identifier.subclass_code().value() == PCI_IDE_CTRL_SUBCLASS_ID) {
if (device_identifier.class_code().value() == to_underlying(PCI::ClassID::MassStorage)
&& device_identifier.subclass_code().value() == to_underlying(PCI::MassStorage::SubclassID::IDEController)) {
m_controllers.append(IDEController::initialize(device_identifier, force_pio));
}
});
}
PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
if (device_identifier.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && device_identifier.subclass_code().value() == PCI_SATA_CTRL_SUBCLASS_ID && device_identifier.prog_if().value() == PCI_AHCI_IF_PROGIF) {
if (device_identifier.class_code().value() == to_underlying(PCI::ClassID::MassStorage)
&& device_identifier.subclass_code().value() == to_underlying(PCI::MassStorage::SubclassID::SATAController)
&& device_identifier.prog_if().value() == to_underlying(PCI::MassStorage::SATAProgIF::AHCI)) {
m_controllers.append(AHCIController::initialize(device_identifier));
}
});