kernel: Implement filtered PCI scans
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
3a4ca73df7
commit
15c89a3592
@ -1,6 +1,12 @@
|
||||
#include "arch/PCI.h"
|
||||
#include "Log.h"
|
||||
|
||||
struct ScanInfo
|
||||
{
|
||||
PCI::callback_t callback;
|
||||
PCI::Match match;
|
||||
};
|
||||
|
||||
namespace PCI
|
||||
{
|
||||
Device::ID read_id(const Device::Address& address)
|
||||
@ -27,32 +33,38 @@ namespace PCI
|
||||
read8(address, Field::Subclass) == PCI_TO_PCI_BRIDGE_SUBCLASS;
|
||||
}
|
||||
|
||||
void scan_bus(u32);
|
||||
static bool matches(const Device::Type& type, const Match& match)
|
||||
{
|
||||
if (match.klass != -1 && type.klass != match.klass) return false;
|
||||
if (match.subclass != -1 && type.subclass != match.subclass) return false;
|
||||
if (match.prog_if != -1 && type.prog_if != match.prog_if) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void scan_function(const Device::Address& address)
|
||||
void scan_bus(u32, ScanInfo);
|
||||
|
||||
void scan_function(const Device::Address& address, ScanInfo info)
|
||||
{
|
||||
Device::ID id = read_id(address);
|
||||
Device::Type type = read_type(address);
|
||||
|
||||
kinfoln("Found PCI device %.4x:%.4x (Class %.2x, Subclass %.2x, ProgIF %.2x) at PCI address %u:%u:%u",
|
||||
id.vendor, id.device, type.klass, type.subclass, type.prog_if, address.bus, address.slot,
|
||||
address.function);
|
||||
if (matches(type, info.match)) { info.callback({ id, type, address }); }
|
||||
|
||||
if (is_pci_to_pci_bridge(address))
|
||||
{
|
||||
kdbgln("PCI-to-PCI bridge detected, performing another bus scan");
|
||||
scan_bus(read8(address, Field::SecondaryBus));
|
||||
scan_bus(read8(address, Field::SecondaryBus), info);
|
||||
}
|
||||
}
|
||||
|
||||
void scan_slot(u32 bus, u32 slot)
|
||||
void scan_slot(u32 bus, u32 slot, ScanInfo info)
|
||||
{
|
||||
Device::Address address { bus, slot, 0 };
|
||||
|
||||
// No device on this slot!
|
||||
if (read16(address, Field::VendorID) == PCI::INVALID_ID) return;
|
||||
|
||||
scan_function(address);
|
||||
scan_function(address, info);
|
||||
|
||||
u8 header_type = read8(address, Field::HeaderType);
|
||||
|
||||
@ -63,17 +75,17 @@ namespace PCI
|
||||
{
|
||||
address.function = function;
|
||||
if (read16(address, Field::VendorID) == PCI::INVALID_ID) continue;
|
||||
scan_function(address);
|
||||
scan_function(address, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scan_bus(u32 bus)
|
||||
void scan_bus(u32 bus, ScanInfo info)
|
||||
{
|
||||
for (u32 slot = 0; slot < 32; slot++) { scan_slot(bus, slot); }
|
||||
for (u32 slot = 0; slot < 32; slot++) { scan_slot(bus, slot, info); }
|
||||
}
|
||||
|
||||
void scan()
|
||||
void scan(callback_t callback, Match match)
|
||||
{
|
||||
u8 header_type = read8({ 0, 0, 0 }, Field::HeaderType);
|
||||
|
||||
@ -81,7 +93,7 @@ namespace PCI
|
||||
if ((header_type & 0x80) == 0)
|
||||
{
|
||||
kdbgln("PCI bus is single-function");
|
||||
scan_bus(0);
|
||||
scan_bus(0, { callback, match });
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -91,7 +103,7 @@ namespace PCI
|
||||
if (read16({ 0, 0, function }, Field::VendorID) != PCI::INVALID_ID)
|
||||
{
|
||||
kdbgln("PCI bus has function %u", function);
|
||||
scan_bus(function);
|
||||
scan_bus(function, { callback, match });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace PCI
|
||||
SecondaryBus = 0x19
|
||||
};
|
||||
|
||||
namespace Device
|
||||
struct Device
|
||||
{
|
||||
struct ID
|
||||
{
|
||||
@ -41,7 +41,20 @@ namespace PCI
|
||||
u32 slot;
|
||||
u32 function;
|
||||
};
|
||||
}
|
||||
|
||||
ID id;
|
||||
Type type;
|
||||
Address address;
|
||||
};
|
||||
|
||||
typedef void (*callback_t)(const Device&);
|
||||
|
||||
struct Match
|
||||
{
|
||||
i16 klass { -1 };
|
||||
i16 subclass { -1 };
|
||||
i16 prog_if { -1 };
|
||||
};
|
||||
|
||||
constexpr u16 INVALID_ID = 0xFFFF;
|
||||
|
||||
@ -56,5 +69,5 @@ namespace PCI
|
||||
Device::ID read_id(const Device::Address& address);
|
||||
Device::Type read_type(const Device::Address& address);
|
||||
|
||||
void scan();
|
||||
void scan(callback_t callback, Match match);
|
||||
}
|
||||
|
@ -70,7 +70,12 @@ Result<void> init()
|
||||
TRY(Scheduler::new_kernel_thread(heap_thread));
|
||||
TRY(Scheduler::new_kernel_thread(reap_thread));
|
||||
|
||||
PCI::scan();
|
||||
PCI::scan(
|
||||
[](const PCI::Device& device) {
|
||||
kinfoln("Found PCI mass storage device %.4x:%.4x, at address %u:%u:%u", device.id.vendor, device.id.device,
|
||||
device.address.bus, device.address.slot, device.address.function);
|
||||
},
|
||||
{ .klass = 1 });
|
||||
|
||||
CPU::platform_finish_init();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user