mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
e5ffa960d7
The new PCI subsystem is initialized during runtime. PCI::Initializer is supposed to be called during early boot, to perform a few tests, and initialize the proper configuration space access mechanism. Kernel boot parameters can be specified by a user to determine what tests will occur, to aid debugging on problematic machines. After that, PCI::Initializer should be dismissed. PCI::IOAccess is a class that is derived from PCI::Access class and implements PCI configuration space access mechanism via x86 IO ports. PCI::MMIOAccess is a class that is derived from PCI::Access and implements PCI configurtaion space access mechanism via memory access. The new PCI subsystem also supports determination of IO/MMIO space needed by a device by checking a given BAR. In addition, Every device or component that use the PCI subsystem has changed to match the last changes.
63 lines
1.8 KiB
C++
63 lines
1.8 KiB
C++
#include <Kernel/IO.h>
|
|
#include <Kernel/PCI/IOAccess.h>
|
|
|
|
void PCI::IOAccess::initialize()
|
|
{
|
|
if (!PCI::Access::is_initialized())
|
|
new PCI::IOAccess();
|
|
}
|
|
|
|
PCI::IOAccess::IOAccess()
|
|
{
|
|
kprintf("PCI: Using IO Mechanism for PCI Configuartion Space Access\n");
|
|
}
|
|
|
|
u8 PCI::IOAccess::read8_field(Address address, u32 field)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
return IO::in8(PCI_VALUE_PORT + (field & 3));
|
|
}
|
|
|
|
u16 PCI::IOAccess::read16_field(Address address, u32 field)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
return IO::in16(PCI_VALUE_PORT + (field & 2));
|
|
}
|
|
|
|
u32 PCI::IOAccess::read32_field(Address address, u32 field)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
return IO::in32(PCI_VALUE_PORT);
|
|
}
|
|
|
|
void PCI::IOAccess::write8_field(Address address, u32 field, u8 value)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
IO::out8(PCI_VALUE_PORT + (field & 3), value);
|
|
}
|
|
void PCI::IOAccess::write16_field(Address address, u32 field, u16 value)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
IO::out16(PCI_VALUE_PORT + (field & 2), value);
|
|
}
|
|
void PCI::IOAccess::write32_field(Address address, u32 field, u32 value)
|
|
{
|
|
IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field));
|
|
IO::out32(PCI_VALUE_PORT, value);
|
|
}
|
|
|
|
void PCI::IOAccess::enumerate_all(Function<void(Address, ID)>& callback)
|
|
{
|
|
// Single PCI host controller.
|
|
if ((read8_field(Address(), PCI_HEADER_TYPE) & 0x80) == 0) {
|
|
enumerate_bus(-1, 0, callback);
|
|
return;
|
|
}
|
|
|
|
// Multiple PCI host controllers.
|
|
for (u8 function = 0; function < 8; ++function) {
|
|
if (read16_field(Address(0, 0, 0, function), PCI_VENDOR_ID) == PCI_NONE)
|
|
break;
|
|
enumerate_bus(-1, function, callback);
|
|
}
|
|
}
|