diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-19 18:00:05 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-19 18:00:05 -0400 |
commit | 1330e1e54c38d6ba0391d556b694813ae389daa1 (patch) | |
tree | 679f34f4092fc0091cc5cf42fac60181e6f67e87 /src/sys/io | |
parent | bfe26529fc77755dc5dd9e41473ebbe84044c5f3 (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.c | 80 |
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 |