Problem enumerating PCI devices--only finds northbridge!
Posted: Tue Aug 18, 2020 8:05 pm
I'm running on qemu, and info qtree shows both the i440FX and PIIX3, as well as numerous other devices (IDE controller, e1000, vga, and USB UHCI), but when I enumerate PCI devices I only get the i440FX. Right now, I'm doing an inefficient but conceptually simple method of scanning every possible function # (without bothering to check if it's meaningful for a given device--I understand this will cause non-multifunction devices to show up multiple times, at the moment I'm just trying to keep the code simple until I get more comfortable with this) on every possible device on every possible bus, and all I get is bus 0, device 0 = vendor 8086, device 1237.
pci_scan() is the function that does the scanning:
and pci_config_address_build(), which assembles the dword that's sent to the config data port:
pci_scan() is the function that does the scanning:
Code: Select all
void pci_scan(){
uint8_t bus = 0, device = 0, function = 0;
uint32_t register_dword;
uint16_t device_id, vendor_id;
uint8_t class_code, subclass_code;
kprintf("Scanning for PCI devices...\n");
for (bus = 0; bus <= 255; bus++){
for (device = 0; device <= 31; device++){
for (function = 0; function <= 7; function++){
asm_out_d(PCI_CONFIG_ADDRESS_PORT, pci_config_address_build(0, function, device, bus, 1));
register_dword = asm_in_d(PCI_CONFIG_DATA_PORT);
vendor_id = (uint16_t)(register_dword & 0x0000FFFF);
device_id = (uint16_t)(register_dword >> 16);
if (vendor_id != 0xFFFF){
kprintf("PCI device found at %#hX:%#hX, vendor %#X, device %#X\n", bus, device, vendor_id, device_id);
asm_out_d(PCI_CONFIG_ADDRESS_PORT, pci_config_address_build(0x08, function, device, bus, 1));
register_dword = asm_in_d(PCI_CONFIG_DATA_PORT);
}
}
}
}
return;
}
Code: Select all
uint32_t pci_config_address_build(uint8_t offset, uint8_t function, uint8_t device, uint8_t bus, uint8_t enabled){
uint32_t r;
r |= (uint32_t)enabled << 31;
r |= (uint32_t)bus << 16;
r |= (uint32_t)device << 11;
r |= (uint32_t)function << 8;
r |= (uint32_t)offset;
return r;
}