summaryrefslogtreecommitdiff
path: root/src/sys/io
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-09-18 13:47:21 -0400
committerIan Moffett <ian@osmora.org>2025-09-18 13:47:21 -0400
commitc0b1a2d6c0e0009a32755911b2a2f65de0e50986 (patch)
tree365ac51f09ff45cc222712b19dfced952e51bfb9 /src/sys/io
parent89b99f6342d7a4ec2629850b06dc91a2864681bc (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.c81
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);
}