diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-18 13:47:21 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-18 13:47:21 -0400 |
commit | c0b1a2d6c0e0009a32755911b2a2f65de0e50986 (patch) | |
tree | 365ac51f09ff45cc222712b19dfced952e51bfb9 /src/sys/io | |
parent | 89b99f6342d7a4ec2629850b06dc91a2864681bc (diff) |
kern: pci: Add initial bus enumeration
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/io')
-rw-r--r-- | src/sys/io/pci/pci.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/sys/io/pci/pci.c b/src/sys/io/pci/pci.c index 864e4c3..a4bf125 100644 --- a/src/sys/io/pci/pci.c +++ b/src/sys/io/pci/pci.c @@ -35,9 +35,88 @@ #include <io/pci/pci.h> #include <io/pci/cam.h> +#define PCI_BUS_ROOT 0 + static struct cam_hook cam; /* + * Attempt to register a PCI device and bail + * if it doesn't exist on the bus. + */ +static void +pci_register_dev(struct pci_device *dev) +{ + pcireg_t vend_dev; + uint16_t device_id; + uint16_t vendor_id; + + if (dev == NULL) { + return; + } + + /* Get the vendor and device ID */ + vend_dev = pci_readl(dev, PCIREG_VENDOR_ID); + vendor_id = vend_dev & 0xFFFF; + device_id = (vendor_id >> 16) & 0xFFFF; + + /* Does this device exist? */ + if (vendor_id == 0xFFFF) { + return; + } + + /* + * Log out the BDF notation as well as vendor, + * and logical slot ID. + */ + printf( + "bridge: device @ pci <%x.%x.%x>\n", + dev->bus, dev->slot, + dev->func, dev->vendor, + dev->slot + ); +} + +/* + * Enumerate a specifc bus of its devices + * + * @bus: Bus to enumerate + */ +static void +pci_enum_bus(uint16_t bus) +{ + pcireg_t reg; + struct pci_device dev; + if (bus > 256) { + printf("pci_enum_bus: bad bus number %x\n", bus); + return; + } + + dev.bus = bus; + for (int slot = 0; slot < 32; ++slot) { + dev.slot = slot; + dev.func = 0; + reg = pci_readl(&dev, PCIREG_HDRTYPE); + + /* + * Section 6.2.1 of the PCI spec states that some + * devices may only implement a single function. + * We can check this with bit 7 of the header type + * register. If we read a 1, it is a multifunction + * device. + */ + if (!ISSET(reg, BIT(7))) { + pci_register_dev(&dev); + continue; + } + + for (uint8_t func = 0; func < 8; ++func) { + pci_register_dev(&dev); + ++dev.func; + } + } +} + +/* * Read from a specific register */ pcireg_t @@ -73,4 +152,6 @@ pci_init_bus(void) printf("pci_init_bus: pci_cam_init() returned %d\n", error); panic("pci_init_bus: failed to init CAM\n"); } + + pci_enum_bus(PCI_BUS_ROOT); } |