feat: graphics/net PnP, keyboard driver improvements
This commit is contained in:
@@ -398,6 +398,86 @@ namespace Pci {
|
||||
return g_devices;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Shared PCI utilities
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
uint64_t ReadBar0(uint8_t bus, uint8_t device, uint8_t function) {
|
||||
uint32_t bar0Low = LegacyRead32(bus, device, function, (uint8_t)PCI_REG_BAR0);
|
||||
uint64_t addr = bar0Low & 0xFFFFFFF0u;
|
||||
|
||||
// Check for 64-bit BAR (type field bits 2:1 == 0b10)
|
||||
if ((bar0Low & 0x06) == 0x04) {
|
||||
uint32_t bar0High = LegacyRead32(bus, device, function, (uint8_t)(PCI_REG_BAR0 + 4));
|
||||
addr |= ((uint64_t)bar0High << 32);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void EnableBusMaster(uint8_t bus, uint8_t device, uint8_t function) {
|
||||
uint16_t cmd = LegacyRead16(bus, device, function, (uint8_t)PCI_REG_COMMAND);
|
||||
cmd |= PCI_CMD_MEM_SPACE | PCI_CMD_BUS_MASTER;
|
||||
LegacyWrite16(bus, device, function, (uint8_t)PCI_REG_COMMAND, cmd);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// PCI driver matching
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static bool MatchDriver(const PciDriverDesc& drv, const PciDevice& dev) {
|
||||
if (drv.VendorId != 0 && drv.VendorId != dev.VendorId)
|
||||
return false;
|
||||
if (drv.ClassCode != 0xFF && drv.ClassCode != dev.ClassCode)
|
||||
return false;
|
||||
if (drv.SubClass != 0xFF && drv.SubClass != dev.SubClass)
|
||||
return false;
|
||||
if (drv.ProgIf != 0xFF && drv.ProgIf != dev.ProgIf)
|
||||
return false;
|
||||
|
||||
if (drv.DeviceIdCount > 0 && drv.DeviceIds != nullptr) {
|
||||
bool found = false;
|
||||
for (uint16_t i = 0; i < drv.DeviceIdCount; i++) {
|
||||
if (drv.DeviceIds[i] == dev.DeviceId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProbeAll(const PciDriverDesc* table, uint16_t count, ProbePhase phase) {
|
||||
for (uint64_t d = 0; d < g_devices.size(); d++) {
|
||||
const PciDevice& dev = g_devices[d];
|
||||
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
if (table[i].Phase != phase)
|
||||
continue;
|
||||
if (!MatchDriver(table[i], dev))
|
||||
continue;
|
||||
|
||||
KernelLogStream(INFO, "PCI") << "Probing " << table[i].Name
|
||||
<< " for device " << base::hex
|
||||
<< (uint64_t)dev.Bus << ":" << (uint64_t)dev.Device
|
||||
<< "." << (uint64_t)dev.Function;
|
||||
|
||||
if (table[i].Probe(dev)) {
|
||||
KernelLogStream(OK, "PCI") << table[i].Name << " claimed device "
|
||||
<< base::hex << (uint64_t)dev.Bus << ":"
|
||||
<< (uint64_t)dev.Device << "." << (uint64_t)dev.Function;
|
||||
break; // device claimed, move to next device
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public API
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void Initialize(Hal::ACPI::CommonSDTHeader* xsdt) {
|
||||
KernelLogStream(INFO, "PCI") << "Initializing PCI subsystem";
|
||||
|
||||
|
||||
@@ -76,4 +76,47 @@ namespace Pci {
|
||||
// Initialize PCI subsystem: parse MCFG, enumerate devices
|
||||
// xsdt: pointer to the XSDT (already HHDM-mapped)
|
||||
void Initialize(Hal::ACPI::CommonSDTHeader* xsdt);
|
||||
|
||||
// =========================================================================
|
||||
// Shared PCI constants
|
||||
// =========================================================================
|
||||
|
||||
constexpr uint16_t PCI_REG_COMMAND = 0x04;
|
||||
constexpr uint16_t PCI_REG_BAR0 = 0x10;
|
||||
constexpr uint16_t PCI_REG_BAR1 = 0x14;
|
||||
constexpr uint16_t PCI_REG_INTERRUPT = 0x3C;
|
||||
|
||||
constexpr uint16_t PCI_CMD_MEM_SPACE = (1 << 1);
|
||||
constexpr uint16_t PCI_CMD_BUS_MASTER = (1 << 2);
|
||||
constexpr uint16_t PCI_CMD_INTX_DISABLE = (1 << 10);
|
||||
|
||||
// Read BAR0, handling 32/64-bit BARs. Returns physical base address.
|
||||
uint64_t ReadBar0(uint8_t bus, uint8_t device, uint8_t function);
|
||||
|
||||
// Enable memory space access and bus mastering in PCI command register.
|
||||
void EnableBusMaster(uint8_t bus, uint8_t device, uint8_t function);
|
||||
|
||||
// =========================================================================
|
||||
// PCI driver matching
|
||||
// =========================================================================
|
||||
|
||||
enum class ProbePhase : uint8_t { Early = 0, Normal = 1 };
|
||||
|
||||
using PciProbeFunc = bool(*)(const PciDevice& dev);
|
||||
|
||||
struct PciDriverDesc {
|
||||
const char* Name;
|
||||
uint16_t VendorId; // 0 = any
|
||||
uint8_t ClassCode; // 0xFF = any
|
||||
uint8_t SubClass; // 0xFF = any
|
||||
uint8_t ProgIf; // 0xFF = any
|
||||
const uint16_t* DeviceIds; // optional device ID whitelist
|
||||
uint16_t DeviceIdCount; // 0 = skip device ID check
|
||||
ProbePhase Phase;
|
||||
PciProbeFunc Probe;
|
||||
};
|
||||
|
||||
// Probe all PCI devices against a driver table for a given phase.
|
||||
// First driver whose Probe() returns true claims each device.
|
||||
void ProbeAll(const PciDriverDesc* table, uint16_t count, ProbePhase phase);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user