summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-10-11 16:54:48 -0400
committerIan Moffett <ian@osmora.org>2025-10-11 16:54:48 -0400
commitb4ed056d786cd4425ca1696f8bfc524764a870ec (patch)
tree83530e560d6776a4b0e2b1dd60b40982ed5ffa20 /src
parent2692a66b0956434df1411cb9c95aaa5e7a7e4e70 (diff)
kern: pci: Support lookups via programming iface
Introduce programming interface based lookups for devices with different kinds of interfaces Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src')
-rw-r--r--src/sys/include/io/pci/pci.h20
-rw-r--r--src/sys/io/pci/pci.c49
2 files changed, 69 insertions, 0 deletions
diff --git a/src/sys/include/io/pci/pci.h b/src/sys/include/io/pci/pci.h
index fbdead1..e6d0a24 100644
--- a/src/sys/include/io/pci/pci.h
+++ b/src/sys/include/io/pci/pci.h
@@ -49,6 +49,24 @@
.vendor = (VENDOR) \
}
+/*
+ * Use for making instances of the pci_adv
+ * structure while specifying the programming
+ * interface
+ */
+#define PCI_CSI_ID(CLASS, SUBCLASS, IF) \
+ { \
+ .class = (CLASS), \
+ .subclass = (SUBCLASS), \
+ .prog_if = (IF) \
+ }
+#define PCI_DVI_ID(DEVICE, VENDOR, IF) \
+ { \
+ .device = (DEVICE), \
+ .vendor = (VENDOR), \
+ .prog_if = (IF) \
+ }
+
/* PCI specific types */
typedef uint32_t pcireg_t;
typedef uint32_t pcival_t;
@@ -81,6 +99,8 @@ struct pci_device {
typedef enum {
PCI_LU_VENDEV, /* Vendor / device */
PCI_LU_CLASSREV, /* Class / subclass */
+ PCI_LU_IVENDEV, /* Interface + vendor / device */
+ PCI_LU_ICLASSREV, /* Interface + class / revision */
} lookup_type_t;
/*
diff --git a/src/sys/io/pci/pci.c b/src/sys/io/pci/pci.c
index a21b1e8..2258d52 100644
--- a/src/sys/io/pci/pci.c
+++ b/src/sys/io/pci/pci.c
@@ -105,6 +105,49 @@ pci_cs_match(struct pci_device *csa, struct pci_device *csb)
}
/*
+ * Lookup hook for matching vendor device IDs and
+ * programming interfaces
+ *
+ * @vda: Vendor device (A)
+ * @vdb: Vendor device (B)
+ *
+ * Returns zero on match
+ */
+static int
+pci_vdi_match(struct pci_device *vda, struct pci_device *vdb)
+{
+ if (vda == NULL || vdb == NULL)
+ return -EINVAL;
+
+ if (vda->prog_if != vdb->prog_if)
+ return -1;
+
+ return pci_vd_match(vda, vdb);
+
+}
+
+/*
+ * Lookup hook for matching class, subclass IDs and
+ * programming interfaces
+ *
+ * @csa: Class / subclass (A)
+ * @csb: Class / subclass (B)
+ *
+ * Returns zero on match
+ */
+static int
+pci_csi_match(struct pci_device *csa, struct pci_device *csb)
+{
+ if (csa == NULL || csb == NULL)
+ return -EINVAL;
+
+ if (csa->prog_if != csb->prog_if)
+ return -1;
+
+ return pci_cs_match(csa, csb);
+}
+
+/*
* Attempt to register a PCI device and bail
* if it doesn't exist on the bus.
*/
@@ -241,6 +284,12 @@ pci_bus_lookup(struct pci_device *lookup, lookup_type_t type)
case PCI_LU_VENDEV:
cmp = pci_vd_match(lookup, dp);
break;
+ case PCI_LU_ICLASSREV:
+ cmp = pci_csi_match(lookup, dp);
+ break;
+ case PCI_LU_IVENDEV:
+ cmp = pci_vdi_match(lookup, dp);
+ break;
}
/* Does it match? */