mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 17:40:27 +00:00
Kernel/PCI: Remove all macros and replace them with enum classes
This commit is contained in:
parent
9d9d57056e
commit
ef9b8ff0c7
Notes:
sideshowbarker
2024-07-18 03:21:02 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/ef9b8ff0c7f Pull-request: https://github.com/SerenityOS/serenity/pull/10187 Reviewed-by: https://github.com/awesomekling
11 changed files with 206 additions and 146 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue