mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:28:11 +00:00
Kernel: Create support for PCI ECAM
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.
This commit is contained in:
parent
d85874be4b
commit
e5ffa960d7
20 changed files with 878 additions and 16 deletions
63
Kernel/PCI/IOAccess.cpp
Normal file
63
Kernel/PCI/IOAccess.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue