diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 21e8af4cf9e7..27316080813c 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1290,6 +1290,7 @@ MLINKS+=pci.9 pci_alloc_msi.9 \ pci.9 pci_find_extcap.9 \ pci.9 pci_find_htcap.9 \ pci.9 pci_find_pcie_root_port.9 \ + pci.9 pci_get_id.9 \ pci.9 pci_get_max_read_req.9 \ pci.9 pci_get_powerstate.9 \ pci.9 pci_get_vpd_ident.9 \ diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9 index 0e1024cf1850..8c16317bed18 100644 --- a/share/man/man9/pci.9 +++ b/share/man/man9/pci.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 23, 2015 +.Dd May 11, 2016 .Dt PCI 9 .Os .Sh NAME @@ -43,6 +43,7 @@ .Nm pci_find_extcap , .Nm pci_find_htcap , .Nm pci_find_pcie_root_port , +.Nm pci_get_id , .Nm pci_get_max_read_req , .Nm pci_get_powerstate , .Nm pci_get_vpd_ident , @@ -97,6 +98,8 @@ .Ft device_t .Fn pci_find_pcie_root_port "device_t dev" .Ft int +.Fn pci_get_id "device_t dev" "enum pci_id_type type" "uintptr_t *id" +.Ft int .Fn pci_get_max_read_req "device_t dev" .Ft int .Fn pci_get_powerstate "device_t dev" @@ -357,6 +360,18 @@ returns .Dv NULL . .Pp The +.Fn pci_get_id +function is used to read an identifier from a device. +The +.Fa type +flag is used to specify which identifier to read. +The following flags are supported: +.Bl -hang -width ".Dv PCI_ID_RID" +.It Dv PCI_ID_RID +Read the routing identifier for the device. +.El +.Pp +The .Fn pci_get_vpd_ident function is used to fetch a device's Vital Product Data .Pq VPD diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 3c998b4f6681..06877b9bb5b7 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -122,7 +122,8 @@ static void pci_resume_msix(device_t dev); static int pci_remap_intr_method(device_t bus, device_t dev, u_int irq); -static uint16_t pci_get_rid_method(device_t dev, device_t child); +static int pci_get_id_method(device_t dev, device_t child, + enum pci_id_type type, uintptr_t *rid); static struct pci_devinfo * pci_fill_devinfo(device_t pcib, device_t bus, int d, int b, int s, int f, uint16_t vid, uint16_t did); @@ -190,7 +191,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_msix_count, pci_msix_count_method), DEVMETHOD(pci_msix_pba_bar, pci_msix_pba_bar_method), DEVMETHOD(pci_msix_table_bar, pci_msix_table_bar_method), - DEVMETHOD(pci_get_rid, pci_get_rid_method), + DEVMETHOD(pci_get_id, pci_get_id_method), DEVMETHOD(pci_alloc_devinfo, pci_alloc_devinfo_method), DEVMETHOD(pci_child_added, pci_child_added_method), #ifdef PCI_IOV @@ -5823,11 +5824,12 @@ pci_restore_state(device_t dev) pci_cfg_restore(dev, dinfo); } -static uint16_t -pci_get_rid_method(device_t dev, device_t child) +static int +pci_get_id_method(device_t dev, device_t child, enum pci_id_type type, + uintptr_t *id) { - return (PCIB_GET_RID(device_get_parent(dev), child)); + return (PCIB_GET_ID(device_get_parent(dev), child, type, id)); } /* Find the upstream port of a given PCI device in a root complex. */ diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index da8030584538..9b4b6602e034 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -27,6 +27,7 @@ # #include +#include INTERFACE pci; @@ -208,9 +209,11 @@ METHOD int msix_table_bar { device_t child; } DEFAULT null_msix_bar; -METHOD uint16_t get_rid { +METHOD int get_id { device_t dev; device_t child; + enum pci_id_type type; + uintptr_t *id; }; METHOD struct pci_devinfo * alloc_devinfo { diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index e3539f5a9a84..87475f662736 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -59,7 +59,8 @@ static int pcib_suspend(device_t dev); static int pcib_resume(device_t dev); static int pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate); -static uint16_t pcib_ari_get_rid(device_t pcib, device_t dev); +static int pcib_ari_get_id(device_t pcib, device_t dev, + enum pci_id_type type, uintptr_t *id); static uint32_t pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width); static void pcib_write_config(device_t dev, u_int b, u_int s, @@ -114,7 +115,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(pcib_release_msix, pcib_release_msix), DEVMETHOD(pcib_map_msi, pcib_map_msi), DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep), - DEVMETHOD(pcib_get_rid, pcib_ari_get_rid), + DEVMETHOD(pcib_get_id, pcib_ari_get_id), DEVMETHOD(pcib_try_enable_ari, pcib_try_enable_ari), DEVMETHOD(pcib_ari_enabled, pcib_ari_enabled), DEVMETHOD(pcib_decode_rid, pcib_ari_decode_rid), @@ -2574,26 +2575,32 @@ pcib_ari_enabled(device_t pcib) return ((sc->flags & PCIB_ENABLE_ARI) != 0); } -static uint16_t -pcib_ari_get_rid(device_t pcib, device_t dev) +static int +pcib_ari_get_id(device_t pcib, device_t dev, enum pci_id_type type, + uintptr_t *id) { struct pcib_softc *sc; uint8_t bus, slot, func; + if (type != PCI_ID_RID) + return (ENXIO); + sc = device_get_softc(pcib); if (sc->flags & PCIB_ENABLE_ARI) { bus = pci_get_bus(dev); func = pci_get_function(dev); - return (PCI_ARI_RID(bus, func)); + *id = (PCI_ARI_RID(bus, func)); } else { bus = pci_get_bus(dev); slot = pci_get_slot(dev); func = pci_get_function(dev); - return (PCI_RID(bus, slot, func)); + *id = (PCI_RID(bus, slot, func)); } + + return (0); } /* diff --git a/sys/dev/pci/pcib_if.m b/sys/dev/pci/pcib_if.m index 6fdc0f42518e..df9f2b72394a 100644 --- a/sys/dev/pci/pcib_if.m +++ b/sys/dev/pci/pcib_if.m @@ -175,10 +175,12 @@ METHOD int power_for_sleep { # # Return the PCI Routing Identifier (RID) for the device. # -METHOD uint16_t get_rid { +METHOD int get_id { device_t pcib; device_t dev; -} DEFAULT pcib_get_rid; + enum pci_id_type type; + uintptr_t *id; +} DEFAULT pcib_get_id; # # Enable Alternative RID Interpretation if both the downstream port (pcib) diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h index c209162b34ed..7d43e60a3547 100644 --- a/sys/dev/pci/pcib_private.h +++ b/sys/dev/pci/pcib_private.h @@ -190,7 +190,8 @@ int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs); int pcib_alloc_msix(device_t pcib, device_t dev, int *irq); int pcib_release_msix(device_t pcib, device_t dev, int irq); int pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data); -uint16_t pcib_get_rid(device_t pcib, device_t dev); +int pcib_get_id(device_t pcib, device_t dev, enum pci_id_type type, + uintptr_t *id); void pcib_decode_rid(device_t pcib, uint16_t rid, int *bus, int *slot, int *func); diff --git a/sys/dev/pci/pcib_support.c b/sys/dev/pci/pcib_support.c index ef88a601ac64..fdd3a45e2572 100644 --- a/sys/dev/pci/pcib_support.c +++ b/sys/dev/pci/pcib_support.c @@ -54,16 +54,20 @@ pcib_maxfuncs(device_t dev) return (PCI_FUNCMAX); } -uint16_t -pcib_get_rid(device_t pcib, device_t dev) +int +pcib_get_id(device_t pcib, device_t dev, enum pci_id_type type, uintptr_t *id) { uint8_t bus, slot, func; + if (type != PCI_ID_RID) + return (ENXIO); + bus = pci_get_bus(dev); slot = pci_get_slot(dev); func = pci_get_function(dev); - return (PCI_RID(bus, slot, func)); + *id = (PCI_RID(bus, slot, func)); + return (0); } void diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 8d9ea7ec02fb..39de675a685f 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -268,6 +268,10 @@ struct pci_devinfo { #ifdef _SYS_BUS_H_ +enum pci_id_type { + PCI_ID_RID, +}; + #include "pci_if.h" enum pci_device_ivars { @@ -542,10 +546,26 @@ pci_msix_table_bar(device_t dev) return (PCI_MSIX_TABLE_BAR(device_get_parent(dev), dev)); } +static __inline int +pci_get_id(device_t dev, enum pci_id_type type, uintptr_t *id) +{ + return (PCI_GET_ID(device_get_parent(dev), dev, type, id)); +} + +/* + * This is the deprecated interface, there is no way to tell the difference + * between a failure and a valid value that happens to be the same as the + * failure value. + */ static __inline uint16_t pci_get_rid(device_t dev) { - return (PCI_GET_RID(device_get_parent(dev), dev)); + uintptr_t rid; + + if (pci_get_id(dev, PCI_ID_RID, &rid) != 0) + return (0); + + return (rid); } static __inline void