mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-24 21:45:20 +00:00
Kernel: Detect devices when enumerating the PCI bus
Instead of making each driver to enumerate the PCI bus itself, PCI::Initializer will call detect_devices() to do one enumeration of the bus.
This commit is contained in:
parent
60715695b2
commit
583e9ad372
Notes:
sideshowbarker
2024-07-19 09:42:51 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/583e9ad3723 Pull-request: https://github.com/SerenityOS/serenity/pull/1161
10 changed files with 64 additions and 50 deletions
|
@ -119,20 +119,16 @@
|
||||||
#define STATUS_SPEED_1000MB1 0x80
|
#define STATUS_SPEED_1000MB1 0x80
|
||||||
#define STATUS_SPEED_1000MB2 0xC0
|
#define STATUS_SPEED_1000MB2 0xC0
|
||||||
|
|
||||||
OwnPtr<E1000NetworkAdapter> E1000NetworkAdapter::autodetect()
|
void E1000NetworkAdapter::detect(const PCI::Address& address)
|
||||||
{
|
{
|
||||||
|
if (address.is_null())
|
||||||
|
return;
|
||||||
static const PCI::ID qemu_bochs_vbox_id = { 0x8086, 0x100e };
|
static const PCI::ID qemu_bochs_vbox_id = { 0x8086, 0x100e };
|
||||||
PCI::Address found_address;
|
const PCI::ID id = PCI::get_id(address);
|
||||||
PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) {
|
if (id != qemu_bochs_vbox_id)
|
||||||
if (id == qemu_bochs_vbox_id) {
|
return;
|
||||||
found_address = address;
|
u8 irq = PCI::get_interrupt_line(address);
|
||||||
return;
|
new E1000NetworkAdapter(address, irq);
|
||||||
}
|
|
||||||
});
|
|
||||||
if (found_address.is_null())
|
|
||||||
return nullptr;
|
|
||||||
u8 irq = PCI::get_interrupt_line(found_address);
|
|
||||||
return make<E1000NetworkAdapter>(found_address, irq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq)
|
E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq)
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
class E1000NetworkAdapter final : public NetworkAdapter
|
class E1000NetworkAdapter final : public NetworkAdapter
|
||||||
, public IRQHandler {
|
, public IRQHandler {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<E1000NetworkAdapter> autodetect();
|
static void detect(const PCI::Address&);
|
||||||
|
|
||||||
E1000NetworkAdapter(PCI::Address, u8 irq);
|
E1000NetworkAdapter(PCI::Address, u8 irq);
|
||||||
virtual ~E1000NetworkAdapter() override;
|
virtual ~E1000NetworkAdapter() override;
|
||||||
|
|
|
@ -123,20 +123,16 @@
|
||||||
#define RX_BUFFER_SIZE 32768
|
#define RX_BUFFER_SIZE 32768
|
||||||
#define TX_BUFFER_SIZE PACKET_SIZE_MAX
|
#define TX_BUFFER_SIZE PACKET_SIZE_MAX
|
||||||
|
|
||||||
OwnPtr<RTL8139NetworkAdapter> RTL8139NetworkAdapter::autodetect()
|
void RTL8139NetworkAdapter::detect(const PCI::Address& address)
|
||||||
{
|
{
|
||||||
|
if (address.is_null())
|
||||||
|
return;
|
||||||
static const PCI::ID rtl8139_id = { 0x10EC, 0x8139 };
|
static const PCI::ID rtl8139_id = { 0x10EC, 0x8139 };
|
||||||
PCI::Address found_address;
|
PCI::ID id = PCI::get_id(address);
|
||||||
PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) {
|
if (id != rtl8139_id)
|
||||||
if (id == rtl8139_id) {
|
return;
|
||||||
found_address = address;
|
u8 irq = PCI::get_interrupt_line(address);
|
||||||
return;
|
new RTL8139NetworkAdapter(address, irq);
|
||||||
}
|
|
||||||
});
|
|
||||||
if (found_address.is_null())
|
|
||||||
return nullptr;
|
|
||||||
u8 irq = PCI::get_interrupt_line(found_address);
|
|
||||||
return make<RTL8139NetworkAdapter>(found_address, irq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq)
|
RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq)
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
class RTL8139NetworkAdapter final : public NetworkAdapter
|
class RTL8139NetworkAdapter final : public NetworkAdapter
|
||||||
, public IRQHandler {
|
, public IRQHandler {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<RTL8139NetworkAdapter> autodetect();
|
static void detect(const PCI::Address&);
|
||||||
|
|
||||||
RTL8139NetworkAdapter(PCI::Address, u8 irq);
|
RTL8139NetworkAdapter(PCI::Address, u8 irq);
|
||||||
virtual ~RTL8139NetworkAdapter() override;
|
virtual ~RTL8139NetworkAdapter() override;
|
||||||
|
|
|
@ -77,6 +77,11 @@ void PCI::Access::enumerate_slot(int type, u8 bus, u8 slot, Function<void(Addres
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCI::ID PCI::Access::get_id(Address address)
|
||||||
|
{
|
||||||
|
return { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) };
|
||||||
|
}
|
||||||
|
|
||||||
void PCI::Access::enumerate_bus(int type, u8 bus, Function<void(Address, ID)>& callback)
|
void PCI::Access::enumerate_bus(int type, u8 bus, Function<void(Address, ID)>& callback)
|
||||||
{
|
{
|
||||||
for (u8 slot = 0; slot < 32; ++slot)
|
for (u8 slot = 0; slot < 32; ++slot)
|
||||||
|
@ -105,6 +110,11 @@ void enumerate_all(Function<void(Address, ID)> callback)
|
||||||
PCI::Access::the().enumerate_all(callback);
|
PCI::Access::the().enumerate_all(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID get_id(Address address)
|
||||||
|
{
|
||||||
|
return PCI::Access::the().get_id(address);
|
||||||
|
}
|
||||||
|
|
||||||
u8 get_interrupt_line(Address address)
|
u8 get_interrupt_line(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_interrupt_line(address);
|
return PCI::Access::the().get_interrupt_line(address);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
space_size = (~space_size) + 1;
|
space_size = (~space_size) + 1;
|
||||||
return space_size;
|
return space_size;
|
||||||
}
|
}
|
||||||
|
virtual ID get_id(Address address) final;
|
||||||
virtual u8 get_revision_id(Address address) { return read8_field(address, PCI_REVISION_ID); }
|
virtual u8 get_revision_id(Address address) { return read8_field(address, PCI_REVISION_ID); }
|
||||||
virtual u8 get_subclass(Address address) { return read8_field(address, PCI_SUBCLASS); }
|
virtual u8 get_subclass(Address address) { return read8_field(address, PCI_SUBCLASS); }
|
||||||
virtual u8 get_class(Address address) { return read8_field(address, PCI_CLASS); }
|
virtual u8 get_class(Address address) { return read8_field(address, PCI_CLASS); }
|
||||||
|
|
|
@ -74,6 +74,10 @@ struct ID {
|
||||||
{
|
{
|
||||||
return vendor_id == other.vendor_id && device_id == other.device_id;
|
return vendor_id == other.vendor_id && device_id == other.device_id;
|
||||||
}
|
}
|
||||||
|
bool operator!=(const ID& other) const
|
||||||
|
{
|
||||||
|
return vendor_id != other.vendor_id || device_id != other.device_id;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Address {
|
struct Address {
|
||||||
|
@ -156,6 +160,7 @@ struct ChangeableAddress : public Address {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ID get_id(PCI::Address);
|
||||||
void enumerate_all(Function<void(Address, ID)> callback);
|
void enumerate_all(Function<void(Address, ID)> callback);
|
||||||
u8 get_interrupt_line(Address);
|
u8 get_interrupt_line(Address);
|
||||||
u32 get_BAR0(Address);
|
u32 get_BAR0(Address);
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include <Kernel/ACPI/ACPIParser.h>
|
#include <Kernel/ACPI/ACPIParser.h>
|
||||||
#include <Kernel/IO.h>
|
#include <Kernel/IO.h>
|
||||||
#include <Kernel/KParams.h>
|
#include <Kernel/KParams.h>
|
||||||
|
#include <Kernel/Net/E1000NetworkAdapter.h>
|
||||||
|
#include <Kernel/Net/RTL8139NetworkAdapter.h>
|
||||||
#include <Kernel/PCI/IOAccess.h>
|
#include <Kernel/PCI/IOAccess.h>
|
||||||
#include <Kernel/PCI/Initializer.h>
|
#include <Kernel/PCI/Initializer.h>
|
||||||
#include <Kernel/PCI/MMIOAccess.h>
|
#include <Kernel/PCI/MMIOAccess.h>
|
||||||
|
@ -43,11 +45,29 @@ PCI::Initializer& PCI::Initializer::the()
|
||||||
void PCI::Initializer::initialize_pci_mmio_access(ACPI_RAW::MCFG& mcfg)
|
void PCI::Initializer::initialize_pci_mmio_access(ACPI_RAW::MCFG& mcfg)
|
||||||
{
|
{
|
||||||
PCI::MMIOAccess::initialize(mcfg);
|
PCI::MMIOAccess::initialize(mcfg);
|
||||||
|
detect_devices();
|
||||||
}
|
}
|
||||||
void PCI::Initializer::initialize_pci_io_access()
|
void PCI::Initializer::initialize_pci_io_access()
|
||||||
{
|
{
|
||||||
PCI::IOAccess::initialize();
|
PCI::IOAccess::initialize();
|
||||||
|
detect_devices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PCI::Initializer::detect_devices()
|
||||||
|
{
|
||||||
|
PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) {
|
||||||
|
kprintf("PCI: device @ %w:%b:%b.%d [%w:%w]\n",
|
||||||
|
address.seg(),
|
||||||
|
address.bus(),
|
||||||
|
address.slot(),
|
||||||
|
address.function(),
|
||||||
|
id.vendor_id,
|
||||||
|
id.device_id);
|
||||||
|
E1000NetworkAdapter::detect(address);
|
||||||
|
RTL8139NetworkAdapter::detect(address);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void PCI::Initializer::test_and_initialize(bool disable_pci_mmio)
|
void PCI::Initializer::test_and_initialize(bool disable_pci_mmio)
|
||||||
{
|
{
|
||||||
if (disable_pci_mmio) {
|
if (disable_pci_mmio) {
|
||||||
|
@ -129,4 +149,4 @@ void PCI::Initializer::dismiss()
|
||||||
|
|
||||||
PCI::Initializer::~Initializer()
|
PCI::Initializer::~Initializer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,11 @@ public:
|
||||||
static void dismiss();
|
static void dismiss();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void detect_devices();
|
||||||
~Initializer();
|
~Initializer();
|
||||||
Initializer();
|
Initializer();
|
||||||
bool test_acpi();
|
bool test_acpi();
|
||||||
bool test_pci_io();
|
bool test_pci_io();
|
||||||
bool test_pci_mmio();
|
bool test_pci_mmio();
|
||||||
void initialize_pci_mmio_access_after_test();
|
void initialize_pci_mmio_access_after_test();
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,10 +62,8 @@
|
||||||
#include <Kernel/Heap/kmalloc.h>
|
#include <Kernel/Heap/kmalloc.h>
|
||||||
#include <Kernel/KParams.h>
|
#include <Kernel/KParams.h>
|
||||||
#include <Kernel/Multiboot.h>
|
#include <Kernel/Multiboot.h>
|
||||||
#include <Kernel/Net/E1000NetworkAdapter.h>
|
|
||||||
#include <Kernel/Net/LoopbackAdapter.h>
|
#include <Kernel/Net/LoopbackAdapter.h>
|
||||||
#include <Kernel/Net/NetworkTask.h>
|
#include <Kernel/Net/NetworkTask.h>
|
||||||
#include <Kernel/Net/RTL8139NetworkAdapter.h>
|
|
||||||
#include <Kernel/PCI/Access.h>
|
#include <Kernel/PCI/Access.h>
|
||||||
#include <Kernel/PCI/Initializer.h>
|
#include <Kernel/PCI/Initializer.h>
|
||||||
#include <Kernel/Random.h>
|
#include <Kernel/Random.h>
|
||||||
|
@ -145,16 +143,6 @@ extern "C" [[noreturn]] void init()
|
||||||
|
|
||||||
PIT::initialize();
|
PIT::initialize();
|
||||||
|
|
||||||
PCI::enumerate_all([](const PCI::Address& address, PCI::ID id) {
|
|
||||||
kprintf("PCI: device @ %w:%b:%b.%d [%w:%w]\n",
|
|
||||||
address.seg(),
|
|
||||||
address.bus(),
|
|
||||||
address.slot(),
|
|
||||||
address.function(),
|
|
||||||
id.vendor_id,
|
|
||||||
id.device_id);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (text_debug) {
|
if (text_debug) {
|
||||||
dbgprintf("Text mode enabled\n");
|
dbgprintf("Text mode enabled\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -170,8 +158,6 @@ extern "C" [[noreturn]] void init()
|
||||||
}
|
}
|
||||||
|
|
||||||
LoopbackAdapter::the();
|
LoopbackAdapter::the();
|
||||||
auto e1000 = E1000NetworkAdapter::autodetect();
|
|
||||||
auto rtl8139 = RTL8139NetworkAdapter::autodetect();
|
|
||||||
|
|
||||||
Process::initialize();
|
Process::initialize();
|
||||||
Thread::initialize();
|
Thread::initialize();
|
||||||
|
@ -218,6 +204,13 @@ void init_stage2()
|
||||||
new RandomDevice;
|
new RandomDevice;
|
||||||
new PTYMultiplexer;
|
new PTYMultiplexer;
|
||||||
|
|
||||||
|
bool dmi_unreliable = KParams::the().has("dmi_unreliable");
|
||||||
|
if (dmi_unreliable) {
|
||||||
|
DMIDecoder::initialize_untrusted();
|
||||||
|
} else {
|
||||||
|
DMIDecoder::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
bool text_debug = KParams::the().has("text_debug");
|
bool text_debug = KParams::the().has("text_debug");
|
||||||
bool force_pio = KParams::the().has("force_pio");
|
bool force_pio = KParams::the().has("force_pio");
|
||||||
|
|
||||||
|
@ -226,13 +219,6 @@ void init_stage2()
|
||||||
root = "/dev/hda";
|
root = "/dev/hda";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dmi_unreliable = KParams::the().has("dmi_unreliable");
|
|
||||||
if (dmi_unreliable) {
|
|
||||||
DMIDecoder::initialize_untrusted();
|
|
||||||
} else {
|
|
||||||
DMIDecoder::initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root.starts_with("/dev/hda")) {
|
if (!root.starts_with("/dev/hda")) {
|
||||||
kprintf("init_stage2: root filesystem must be on the first IDE hard drive (/dev/hda)\n");
|
kprintf("init_stage2: root filesystem must be on the first IDE hard drive (/dev/hda)\n");
|
||||||
hang();
|
hang();
|
||||||
|
|
Loading…
Add table
Reference in a new issue