From 528e18a59f7b311129c09a1acb21462edf20b0d3 Mon Sep 17 00:00:00 2001 From: rstone Date: Tue, 1 Apr 2014 15:47:24 +0000 Subject: [PATCH] Add a method to get the PCI RID for a device. Reviewed by: kib MFC after: 2 months Sponsored by: Sandvine Inc. --- sys/conf/files | 1 + sys/dev/pci/pci.c | 10 ++++++ sys/dev/pci/pci_if.m | 6 ++++ sys/dev/pci/pci_pci.c | 2 ++ sys/dev/pci/pcib_if.m | 9 ++++++ sys/dev/pci/pcib_private.h | 2 ++ sys/dev/pci/pcib_support.c | 62 ++++++++++++++++++++++++++++++++++++++ sys/dev/pci/pcireg.h | 17 +++++++++++ sys/dev/pci/pcivar.h | 6 ++++ 9 files changed, 115 insertions(+) create mode 100644 sys/dev/pci/pcib_support.c diff --git a/sys/conf/files b/sys/conf/files index a13ef3883617..7af607999a46 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1951,6 +1951,7 @@ dev/pci/pci_pci.c optional pci dev/pci/pci_subr.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard +dev/pci/pcib_support.c standard dev/pci/vga_pci.c optional pci dev/pcn/if_pcn.c optional pcn pci dev/pdq/if_fea.c optional fea eisa diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 41bb4b11b1fc..ac297057350a 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -124,6 +124,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 device_method_t pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pci_probe), @@ -182,6 +184,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_release_msi, pci_release_msi_method), DEVMETHOD(pci_msi_count, pci_msi_count_method), DEVMETHOD(pci_msix_count, pci_msix_count_method), + DEVMETHOD(pci_get_rid, pci_get_rid_method), DEVMETHOD_END }; @@ -5055,3 +5058,10 @@ pci_restore_state(device_t dev) dinfo = device_get_ivars(dev); pci_cfg_restore(dev, dinfo); } + +static uint16_t +pci_get_rid_method(device_t dev, device_t child) +{ + + return (PCIB_GET_RID(device_get_parent(dev), child)); +} diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index e35d79ecbadc..0f19358d4a2a 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -159,3 +159,9 @@ METHOD int msix_count { device_t dev; device_t child; } DEFAULT null_msi_count; + +METHOD uint16_t get_rid { + device_t dev; + device_t child; +}; + diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index 684e6b71fc1b..2152c23ab2f4 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -93,6 +93,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_get_rid), DEVMETHOD_END }; @@ -1934,3 +1935,4 @@ pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate) bus = device_get_parent(pcib); return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate)); } + diff --git a/sys/dev/pci/pcib_if.m b/sys/dev/pci/pcib_if.m index b946c0f0541b..e8147da164ce 100644 --- a/sys/dev/pci/pcib_if.m +++ b/sys/dev/pci/pcib_if.m @@ -154,3 +154,12 @@ METHOD int power_for_sleep { device_t dev; int *pstate; }; + +# +# Return the PCI Routing Identifier (RID) for the device. +# +METHOD uint16_t get_rid { + device_t pcib; + device_t dev; +}; + diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h index e74f1493dfbe..6001b2e3831b 100644 --- a/sys/dev/pci/pcib_private.h +++ b/sys/dev/pci/pcib_private.h @@ -167,5 +167,7 @@ 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); + #endif diff --git a/sys/dev/pci/pcib_support.c b/sys/dev/pci/pcib_support.c new file mode 100644 index 000000000000..48b94c97a964 --- /dev/null +++ b/sys/dev/pci/pcib_support.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) Sandvine Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Support functions for the PCI:PCI bridge driver. This has to be in a + * separate file because kernel configurations end up referencing the functions + * here even when pci support is compiled out of the kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pcib_if.h" + +uint16_t +pcib_get_rid(device_t pcib, device_t dev) +{ + uint8_t bus, slot, func; + + bus = pci_get_bus(dev); + slot = pci_get_slot(dev); + func = pci_get_function(dev); + + return (PCI_RID(bus, slot, func)); +} + diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index afd140ffce64..ccd41b55bad1 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -48,6 +48,23 @@ #define PCIE_REGMAX 4095 /* highest supported config register addr. */ #define PCI_MAXHDRTYPE 2 +#define PCI_RID_BUS_SHIFT 8 +#define PCI_RID_SLOT_SHIFT 3 +#define PCI_RID_FUNC_SHIFT 0 + +#define PCI_RID(bus, slot, func) \ + ((((bus) & PCI_BUSMAX) << PCI_RID_BUS_SHIFT) | \ + (((slot) & PCI_SLOTMAX) << PCI_RID_SLOT_SHIFT) | \ + (((func) & PCI_FUNCMAX) << PCI_RID_FUNC_SHIFT)) + +#define PCI_ARI_RID(bus, func) \ + ((((bus) & PCI_BUSMAX) << PCI_RID_BUS_SHIFT) | \ + (((func) & PCIE_ARI_FUNCMAX) << PCI_RID_FUNC_SHIFT)) + +#define PCI_RID2BUS(rid) (((rid) >> PCI_RID_BUS_SHIFT) & PCI_BUSMAX) +#define PCI_RID2SLOT(rid) (((rid) >> PCI_RID_SLOT_SHIFT) & PCI_SLOTMAX) +#define PCI_RID2FUNC(rid) (((rid) >> PCI_RID_FUNC_SHIFT) & PCI_FUNCMAX) + /* PCI config header registers for all devices */ #define PCIR_DEVVENDOR 0x00 diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 06e577124478..0157ee7be46f 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -482,6 +482,12 @@ pci_msix_count(device_t dev) return (PCI_MSIX_COUNT(device_get_parent(dev), dev)); } +static __inline uint16_t +pci_get_rid(device_t dev) +{ + return (PCI_GET_RID(device_get_parent(dev), dev)); +} + device_t pci_find_bsf(uint8_t, uint8_t, uint8_t); device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t); device_t pci_find_device(uint16_t, uint16_t);