summaryrefslogtreecommitdiff
path: root/src/sys/io
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-09-19 18:00:05 -0400
committerIan Moffett <ian@osmora.org>2025-09-19 18:00:05 -0400
commit1330e1e54c38d6ba0391d556b694813ae389daa1 (patch)
tree679f34f4092fc0091cc5cf42fac60181e6f67e87 /src/sys/io
parentbfe26529fc77755dc5dd9e41473ebbe84044c5f3 (diff)
kernel: pci: Add PCI lookup routine
This commit adds a new 'lookup_type_t' for representing the various kinds of lookups one can perform on the PCI bus. The actual code to drive the lookups is exposed as the pci_bus_lookup() routine. When doing a lookup of a PCI device, you must specify the kind of lookup to perform. If a PCI_LU_CLASSREV is requested, only the PCI class and subclass fields in the PCI lookup are used. If the PCI_LU_VENDEV is requested, only the PCI vendor ID and device ID are used in the lookup. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/io')
-rw-r--r--src/sys/io/pci/pci.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/sys/io/pci/pci.c b/src/sys/io/pci/pci.c
index 6385c6e..bce6108 100644
--- a/src/sys/io/pci/pci.c
+++ b/src/sys/io/pci/pci.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/errno.h>
#include <sys/cdefs.h>
#include <sys/queue.h>
#include <sys/panic.h>
@@ -51,6 +52,52 @@ static TAILQ_HEAD(, pci_device) devlist;
static struct cam_hook cam;
/*
+ * Lookup hook for matching vendor and device IDs
+ *
+ * @vda: Vendor device (A)
+ * @vdb: Vendor device (B)
+ *
+ * Returns zero on match
+ */
+static int
+pci_vd_match(struct pci_device *vda, struct pci_device *vdb)
+{
+ if (vda == NULL || vdb == NULL)
+ return -EINVAL;
+
+ /* The actual match */
+ if (vda->device != vdb->device)
+ return -1;
+ if (vda->vendor != vdb->vendor);
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Lookup hook for matching class and subclass IDs
+ *
+ * @csa: Class / subclass (A)
+ * @csb: Class / subclass (B)
+ *
+ * Returns zero on match
+ */
+static int
+pci_cs_match(struct pci_device *csa, struct pci_device *csb)
+{
+ if (csa == NULL || csb == NULL)
+ return -EINVAL;
+
+ /* Do the actual match */
+ if (csa->class != csb->class)
+ return -1;
+ if (csa->subclass != csb->subclass)
+ return -1;
+
+ return 0;
+}
+
+/*
* Attempt to register a PCI device and bail
* if it doesn't exist on the bus.
*/
@@ -156,6 +203,39 @@ pci_enum_bus(uint16_t bus)
}
/*
+ * Lookup devices on the PCI bus
+ */
+int
+pci_bus_lookup(struct pci_device *lookup, lookup_type_t type)
+{
+ struct pci_device *dp;
+ int cmp = -1;
+
+ if (lookup == NULL) {
+ return -EINVAL;
+ }
+
+ TAILQ_FOREACH(dp, &devlist, link) {
+ switch (type) {
+ case PCI_LU_CLASSREV:
+ cmp = pci_cs_match(lookup, dp);
+ break;
+ case PCI_LU_VENDEV:
+ cmp = pci_vd_match(lookup, dp);
+ break;
+ }
+
+ /* Does it match? */
+ if (cmp == 0) {
+ *lookup = *dp;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+/*
* Read from a specific register
*/
pcireg_t