#include #include #include #include #define PCI_CONFIG_ADDRESS 0xCF8 #define PCI_CONFIG_DATA 0xCFC /* Register Offset Bits 31-24 Bits 23-16 Bits 15-8 Bits 7-0 0x0 0x0 Device ID Vendor ID 0x1 0x4 Status Command 0x2 0x8 Class code Subclass Prog IF Revision ID 0x3 0xC BIST Header type Latency Timer Cache Line Size */ 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_config_read_block(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, void* buffer, size_t size) { uint8_t* buf = (uint8_t*)buffer; for (size_t i = 0; i < size; i += 4) { uint32_t value = pci_config_read(bus, device, function, offset + i); size_t remaining = size - i; if (remaining >= 4) { *(uint32_t*)(buf + i) = value; } else { for (size_t j = 0; j < remaining; ++j) { buf[i + j] = (value >> (8 * j)) & 0xFF; } } } } void pci_enumerate(void) { 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 */ { struct pci_header pre_header; pci_config_read_block(bus, device, function, 0x00, &pre_header, sizeof(pre_header)); if (pre_header.vendor_id == 0xFFFF) { continue; /* No device present */ } if (pre_header.class_code == 0xB) { printf("Processor found on PCI bus, what?!?!\n"); continue; } if (pre_header.header_type == 0x00) { struct pci_header_type_0 hdr; pci_config_read_block(bus, device, function, 0x00, &hdr, sizeof(hdr)); if (hdr.class_code == 0x1 && hdr.subclass == 0x6 && hdr.prog_if == 0x1) { /*configure_ahci_controller(hdr);*/ } } } } } }