Files
Espresso/drivers/pci.c

60 lines
2.3 KiB
C
Raw Normal View History

2025-05-28 14:41:02 -05:00
#include <stdint.h>
#include <stddef.h>
#include <drivers/pci.h>
#include <port_io.h>
#include <stdio.h>
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset)
{
uint32_t address = 0;
address |= (bus << 16); // Bus number (bits 23-16)
address |= (device << 11); // Device number (bits 15-11)
address |= (function << 8); // Function number (bits 10-8)
address |= (offset & 0xFC); // Register offset (bits 7-0)
address |= (1 << 31); // Enable configuration access
outl(PCI_CONFIG_ADDRESS, address); // Write address to PCI config space
return inl(PCI_CONFIG_DATA); // Read data from PCI config space
}
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value)
{
uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
outl(PCI_CONFIG_ADDRESS, address); // Send the address to PCI config space
outl(PCI_CONFIG_DATA, value); // Write data to PCI config space
}
void pci_enumerate()
{
for (uint16_t bus = 0; bus < 256; bus++) // Maximum 256 buses
{
for (uint8_t device = 0; device < 32; device++) // Maximum 32 devices per bus
{
for (uint8_t function = 0; function < 8; function++) // Maximum 8 functions per device
{
uint32_t vendor_id = pci_config_read(bus, device, function, 0x00);
if (vendor_id == 0xFFFFFFFF) continue; // No device present
uint32_t device_id = pci_config_read(bus, device, function, 0x02);
uint32_t class_code = pci_config_read(bus, device, function, 0x08);
printf("Found PCI device: Vendor ID: 0x%X Device ID: 0x%X Class: 0x%X\n", vendor_id, device_id, class_code);
printf("0x%X", class_code);
printf(" --- ");
printf("0x%X\n", (class_code >> 8));
if ((class_code >> 8) == 0x0C) {
printf("Found USB controller (Class: 0x%02X)\n", class_code);
// Now, you can initialize and configure the USB controller.
}
}
}
}
}