#include #include "assembly.h" #include "core.h" #include "list.h" #include "memory.h" #define CONFIG_ADDR_ENABLE (31) #define CONFIG_ADDR_BUS (16) #define CONFIG_ADDR_PORT (11) #define CONFIG_ADDR_FUNC (8) #define CONFIG_ADDR_REG (0) #define VENDOR_DEVICE_ID_REGISTER (0x00) #define VENDOR_ID_BIT_MASK (0x0000FFFF) #define VENDOR_ID_BIT_SHIFT (0) #define DEVICE_ID_BIT_MASK (0xFFFF0000) #define DEVICE_ID_BIT_SHIFT (16) #define CLASS_CODE_REGISTER (0x08) #define CLASS_CODE_BIT_MASK (0xFF000000) #define CLASS_CODE_BIT_SHIFT (24) #define SUBCLASS_CODE_BIT_MASK (0x00FF0000) #define SUBCLASS_CODE_BIT_SHIFT (16) #define HEADER_TYPE_REGISTER (0x0C) #define HEADER_TYPE_BIT_MASK (0x00FF0000) #define HEADER_TYPE_BIT_SHIFT (16) struct pci_device { uint8_t bus; uint8_t port; uint16_t vendor_id; uint16_t device_id; uint8_t class_code; uint8_t subclass_code; uint8_t header_type; struct list_node node; }; struct list pci_devices = LIST_INIT(); static int pci_read_register(struct pci_device *dev, uint8_t func, uint8_t reg, uint32_t *res) { uint32_t config_addr = 0; config_addr |= (1U << CONFIG_ADDR_ENABLE); config_addr |= (uint32_t)(dev->bus) << CONFIG_ADDR_BUS; config_addr |= (uint32_t)(dev->port) << CONFIG_ADDR_PORT; config_addr |= (uint32_t)(func) << CONFIG_ADDR_FUNC; config_addr |= (uint32_t)(reg) << CONFIG_ADDR_REG; outl(config_addr, 0xCF8); *res = inl(0xCFC); return 0; } int pci_init(void) { int num_devices = 0; for (int bus = 0; bus < 256; bus++) { for (int port = 0; port < 256; port++) { struct pci_device dev = { .bus = (uint8_t)(bus), .port = (uint8_t)(port), }; uint32_t reg_value = 0; pci_read_register(&dev, 0, VENDOR_DEVICE_ID_REGISTER, ®_value); uint16_t vendor_id = (reg_value & VENDOR_ID_BIT_MASK) >> VENDOR_ID_BIT_SHIFT; uint16_t device_id = (reg_value & DEVICE_ID_BIT_MASK) >> DEVICE_ID_BIT_SHIFT; if (vendor_id == 0xFFFF) { continue; } struct pci_device *list_entry = malloc(sizeof(struct pci_device)); list_entry->bus = dev.bus; list_entry->port = dev.port; list_entry->vendor_id = vendor_id; list_entry->device_id = device_id; pci_read_register(&dev, 0, CLASS_CODE_REGISTER, ®_value); list_entry->class_code = (reg_value & CLASS_CODE_BIT_MASK) >> CLASS_CODE_BIT_SHIFT; list_entry->subclass_code = (reg_value & SUBCLASS_CODE_BIT_MASK) >> SUBCLASS_CODE_BIT_SHIFT; pci_read_register(&dev, 0, HEADER_TYPE_REGISTER, ®_value); list_entry->header_type = (reg_value & HEADER_TYPE_BIT_MASK) >> HEADER_TYPE_BIT_SHIFT; list_append(&pci_devices, &(list_entry->node)); num_devices++; } } printk("\nfound %i PCI devices:\n", num_devices); struct pci_device *entry; LIST_FOR_EACH_ENTRY(&pci_devices, struct pci_device, node, entry) { printk( "- bus: %x\n" " port: %x\n" " vendor id: %x\n" " device id: %x\n" " class: %x\n" " subclass: %x\n" " header type: %x\n", entry->bus, entry->port, entry->vendor_id, entry->device_id, entry->class_code, entry->subclass_code, entry->header_type); } return 0; }