1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 12:35:07 +00:00
serenity/Kernel/Bus/PCI/Initializer.cpp
Liav A 2272d93215 Kernel/PCI: Unify disable checks under PCI::Access::is_disabled method
To declare that we don't have a PCI bus in the system we do two things:
1. Probe IO ports before enabling access -
In case we are using the QEMU ISA-PC machine type, IO probing results in
floating bus condition (returning 0xFF values), thus, we know we don't
have PCI bus on the system.
2. Allow the user to specify to not use the PCI bus at all in the kernel
commandline.
2022-03-02 18:41:54 +01:00

86 lines
2.4 KiB
C++

/*
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/x86/IO.h>
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/Bus/PCI/Access.h>
#include <Kernel/Bus/PCI/Initializer.h>
#include <Kernel/Bus/PCI/SysFSPCI.h>
#include <Kernel/CommandLine.h>
#include <Kernel/Firmware/ACPI/Parser.h>
#include <Kernel/Panic.h>
#include <Kernel/Sections.h>
namespace Kernel {
namespace PCI {
READONLY_AFTER_INIT bool g_pci_access_io_probe_failed;
READONLY_AFTER_INIT bool g_pci_access_is_disabled_from_commandline;
static bool test_pci_io();
UNMAP_AFTER_INIT static PCIAccessLevel detect_optimal_access_type()
{
auto boot_determined = kernel_command_line().pci_access_level();
if (!ACPI::is_enabled() || !ACPI::Parser::the()->find_table("MCFG").has_value())
return PCIAccessLevel::IOAddressing;
if (boot_determined != PCIAccessLevel::IOAddressing)
return boot_determined;
if (!g_pci_access_io_probe_failed)
return PCIAccessLevel::IOAddressing;
PANIC("No PCI bus access method detected!");
}
UNMAP_AFTER_INIT void initialize()
{
g_pci_access_io_probe_failed = !test_pci_io();
g_pci_access_is_disabled_from_commandline = kernel_command_line().is_pci_disabled();
if (g_pci_access_is_disabled_from_commandline || g_pci_access_io_probe_failed)
return;
switch (detect_optimal_access_type()) {
case PCIAccessLevel::MemoryAddressing: {
auto mcfg = ACPI::Parser::the()->find_table("MCFG");
VERIFY(mcfg.has_value());
auto success = Access::initialize_for_multiple_pci_domains(mcfg.value());
VERIFY(success);
break;
}
case PCIAccessLevel::IOAddressing: {
auto success = Access::initialize_for_one_pci_domain();
VERIFY(success);
break;
}
default:
VERIFY_NOT_REACHED();
}
PCI::PCIBusSysFSDirectory::initialize();
PCI::enumerate([&](DeviceIdentifier const& device_identifier) {
dmesgln("{} {}", device_identifier.address(), device_identifier.hardware_id());
});
}
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);
if (tmp == 0x80000000) {
dmesgln("PCI IO supported");
return true;
}
dmesgln("PCI IO not supported");
return false;
}
}
}