From b4ed056d786cd4425ca1696f8bfc524764a870ec Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 11 Oct 2025 16:54:48 -0400 Subject: kern: pci: Support lookups via programming iface Introduce programming interface based lookups for devices with different kinds of interfaces Signed-off-by: Ian Moffett --- src/sys/include/io/pci/pci.h | 20 ++++++++++++++++++ src/sys/io/pci/pci.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'src') 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 @@ -104,6 +104,49 @@ pci_cs_match(struct pci_device *csa, struct pci_device *csb) return 0; } +/* + * 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? */ -- cgit v1.2.3