From owner-svn-src-head@FreeBSD.ORG Sat Mar 3 18:08:57 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id C2149106566C; Sat, 3 Mar 2012 18:08:57 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AC2C88FC08; Sat, 3 Mar 2012 18:08:57 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q23I8vws093894; Sat, 3 Mar 2012 18:08:57 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q23I8vPV093886; Sat, 3 Mar 2012 18:08:57 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201203031808.q23I8vPV093886@svn.freebsd.org> From: John Baldwin Date: Sat, 3 Mar 2012 18:08:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232472 - in head/sys/dev: pci siba X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Mar 2012 18:08:57 -0000 Author: jhb Date: Sat Mar 3 18:08:57 2012 New Revision: 232472 URL: http://svn.freebsd.org/changeset/base/232472 Log: Expand the set of APIs available for locating PCI capabilities: - pci_find_extcap() is repurposed to be used for fetching PCI-express extended capabilities (PCIZ_* constants in ). - pci_find_htcap() can be used to locate a specific HyperTransport capability (PCIM_HTCAP_* constants in ). - Cache the starting location of the PCI-express capability for PCI-express devices in PCI device ivars. Modified: head/sys/dev/pci/hostb_pci.c head/sys/dev/pci/pci.c head/sys/dev/pci/pci_if.m head/sys/dev/pci/pci_private.h head/sys/dev/pci/pcivar.h head/sys/dev/pci/vga_pci.c head/sys/dev/siba/siba_bwn.c Modified: head/sys/dev/pci/hostb_pci.c ============================================================================== --- head/sys/dev/pci/hostb_pci.c Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/hostb_pci.c Sat Mar 3 18:08:57 2012 (r232472) @@ -197,6 +197,14 @@ pci_hostb_assign_interrupt(device_t dev, } static int +pci_hostb_find_cap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_cap(dev, capability, capreg)); +} + +static int pci_hostb_find_extcap(device_t dev, device_t child, int capability, int *capreg) { @@ -204,6 +212,14 @@ pci_hostb_find_extcap(device_t dev, devi return (pci_find_extcap(dev, capability, capreg)); } +static int +pci_hostb_find_htcap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_htcap(dev, capability, capreg)); +} + static device_method_t pci_hostb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pci_hostb_probe), @@ -233,7 +249,9 @@ static device_method_t pci_hostb_methods DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate), DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate), DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt), + DEVMETHOD(pci_find_cap, pci_hostb_find_cap), DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap), + DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap), { 0, 0 } }; Modified: head/sys/dev/pci/pci.c ============================================================================== --- head/sys/dev/pci/pci.c Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/pci.c Sat Mar 3 18:08:57 2012 (r232472) @@ -177,7 +177,9 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), + DEVMETHOD(pci_find_cap, pci_find_cap_method), DEVMETHOD(pci_find_extcap, pci_find_extcap_method), + DEVMETHOD(pci_find_htcap, pci_find_htcap_method), DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method), DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method), DEVMETHOD(pci_remap_msix, pci_remap_msix_method), @@ -737,6 +739,9 @@ pci_read_cap(device_t pcib, pcicfgregs * * at least one PCI-express device. */ pcie_chipset = 1; + cfg->pcie.pcie_location = ptr; + val = REG(ptr + PCIR_EXPRESS_FLAGS, 2); + cfg->pcie.pcie_type = val & PCIM_EXP_FLAGS_TYPE; break; default: break; @@ -1154,12 +1159,55 @@ pci_get_vpd_readonly_method(device_t dev } /* - * Find the requested extended capability and return the offset in - * configuration space via the pointer provided. The function returns - * 0 on success and error code otherwise. + * Find the requested HyperTransport capability and return the offset + * in configuration space via the pointer provided. The function + * returns 0 on success and an error code otherwise. */ int -pci_find_extcap_method(device_t dev, device_t child, int capability, +pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg) +{ + int ptr, error; + uint16_t val; + + error = pci_find_cap(child, PCIY_HT, &ptr); + if (error) + return (error); + + /* + * Traverse the capabilities list checking each HT capability + * to see if it matches the requested HT capability. + */ + while (ptr != 0) { + val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2); + if (capability == PCIM_HTCAP_SLAVE || + capability == PCIM_HTCAP_HOST) + val &= 0xe000; + else + val &= PCIM_HTCMD_CAP_MASK; + if (val == capability) { + if (capreg != NULL) + *capreg = ptr; + return (0); + } + + /* Skip to the next HT capability. */ + while (ptr != 0) { + ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1); + if (pci_read_config(child, ptr + PCICAP_ID, 1) == + PCIY_HT) + break; + } + } + return (ENOENT); +} + +/* + * Find the requested capability and return the offset in + * configuration space via the pointer provided. The function returns + * 0 on success and an error code otherwise. + */ +int +pci_find_cap_method(device_t dev, device_t child, int capability, int *capreg) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -1207,6 +1255,43 @@ pci_find_extcap_method(device_t dev, dev } /* + * Find the requested extended capability and return the offset in + * configuration space via the pointer provided. The function returns + * 0 on success and an error code otherwise. + */ +int +pci_find_extcap_method(device_t dev, device_t child, int capability, + int *capreg) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + uint32_t ecap; + uint16_t ptr; + + /* Only supported for PCI-express devices. */ + if (cfg->pcie.pcie_location == 0) + return (ENXIO); + + ptr = PCIR_EXTCAP; + ecap = pci_read_config(child, ptr, 4); + if (ecap == 0xffffffff || ecap == 0) + return (ENOENT); + for (;;) { + if (PCI_EXTCAP_ID(ecap) == capability) { + if (capreg != NULL) + *capreg = ptr; + return (0); + } + ptr = PCI_EXTCAP_NEXTPTR(ecap); + if (ptr == 0) + break; + ecap = pci_read_config(child, ptr, 4); + } + + return (ENOENT); +} + +/* * Support for MSI-X message interrupts. */ void @@ -1696,10 +1781,12 @@ pci_ht_map_msi(device_t dev, uint64_t ad int pci_get_max_read_req(device_t dev) { + struct pci_devinfo *dinfo = device_get_ivars(dev); int cap; uint16_t val; - if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0) + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) return (0); val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2); val &= PCIM_EXP_CTL_MAX_READ_REQUEST; @@ -1710,10 +1797,12 @@ pci_get_max_read_req(device_t dev) int pci_set_max_read_req(device_t dev, int size) { + struct pci_devinfo *dinfo = device_get_ivars(dev); int cap; uint16_t val; - if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0) + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) return (0); if (size < 128) size = 128; Modified: head/sys/dev/pci/pci_if.m ============================================================================== --- head/sys/dev/pci/pci_if.m Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/pci_if.m Sat Mar 3 18:08:57 2012 (r232472) @@ -105,6 +105,13 @@ METHOD int assign_interrupt { device_t child; }; +METHOD int find_cap { + device_t dev; + device_t child; + int capability; + int *capreg; +}; + METHOD int find_extcap { device_t dev; device_t child; @@ -112,6 +119,13 @@ METHOD int find_extcap { int *capreg; }; +METHOD int find_htcap { + device_t dev; + device_t child; + int capability; + int *capreg; +}; + METHOD int alloc_msi { device_t dev; device_t child; Modified: head/sys/dev/pci/pci_private.h ============================================================================== --- head/sys/dev/pci/pci_private.h Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/pci_private.h Sat Mar 3 18:08:57 2012 (r232472) @@ -80,8 +80,12 @@ int pci_enable_busmaster_method(device_ int pci_disable_busmaster_method(device_t dev, device_t child); int pci_enable_io_method(device_t dev, device_t child, int space); int pci_disable_io_method(device_t dev, device_t child, int space); +int pci_find_cap_method(device_t dev, device_t child, + int capability, int *capreg); int pci_find_extcap_method(device_t dev, device_t child, int capability, int *capreg); +int pci_find_htcap_method(device_t dev, device_t child, + int capability, int *capreg); int pci_alloc_msi_method(device_t dev, device_t child, int *count); int pci_alloc_msix_method(device_t dev, device_t child, int *count); int pci_remap_msix_method(device_t dev, device_t child, Modified: head/sys/dev/pci/pcivar.h ============================================================================== --- head/sys/dev/pci/pcivar.h Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/pcivar.h Sat Mar 3 18:08:57 2012 (r232472) @@ -123,6 +123,12 @@ struct pcicfg_ht { uint64_t ht_msiaddr; /* MSI mapping base address */ }; +/* Interesting values for PCI-express */ +struct pcicfg_pcie { + uint8_t pcie_location; /* Offset of PCI-e capability registers. */ + uint8_t pcie_type; /* Device type. */ +}; + /* config header information common to all header types */ typedef struct pcicfg { struct device *dev; /* device which owns this */ @@ -164,6 +170,7 @@ typedef struct pcicfg { struct pcicfg_msi msi; /* PCI MSI */ struct pcicfg_msix msix; /* PCI MSI-X */ struct pcicfg_ht ht; /* HyperTransport */ + struct pcicfg_pcie pcie; /* PCI Express */ } pcicfgregs; /* additional type 1 device config header information (PCI to PCI bridge) */ @@ -409,7 +416,7 @@ pci_get_powerstate(device_t dev) static __inline int pci_find_cap(device_t dev, int capability, int *capreg) { - return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg)); + return (PCI_FIND_CAP(device_get_parent(dev), dev, capability, capreg)); } static __inline int @@ -419,6 +426,12 @@ pci_find_extcap(device_t dev, int capabi } static __inline int +pci_find_htcap(device_t dev, int capability, int *capreg) +{ + return (PCI_FIND_HTCAP(device_get_parent(dev), dev, capability, capreg)); +} + +static __inline int pci_alloc_msi(device_t dev, int *count) { return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count)); Modified: head/sys/dev/pci/vga_pci.c ============================================================================== --- head/sys/dev/pci/vga_pci.c Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/pci/vga_pci.c Sat Mar 3 18:08:57 2012 (r232472) @@ -314,6 +314,14 @@ vga_pci_assign_interrupt(device_t dev, d } static int +vga_pci_find_cap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_cap(dev, capability, capreg)); +} + +static int vga_pci_find_extcap(device_t dev, device_t child, int capability, int *capreg) { @@ -322,6 +330,14 @@ vga_pci_find_extcap(device_t dev, device } static int +vga_pci_find_htcap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_htcap(dev, capability, capreg)); +} + +static int vga_pci_alloc_msi(device_t dev, device_t child, int *count) { struct vga_pci_softc *sc; @@ -422,7 +438,9 @@ static device_method_t vga_pci_methods[] DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate), DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate), DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt), + DEVMETHOD(pci_find_cap, vga_pci_find_cap), DEVMETHOD(pci_find_extcap, vga_pci_find_extcap), + DEVMETHOD(pci_find_htcap, vga_pci_find_htcap), DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi), DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix), DEVMETHOD(pci_remap_msix, vga_pci_remap_msix), Modified: head/sys/dev/siba/siba_bwn.c ============================================================================== --- head/sys/dev/siba/siba_bwn.c Sat Mar 3 18:07:53 2012 (r232471) +++ head/sys/dev/siba/siba_bwn.c Sat Mar 3 18:08:57 2012 (r232472) @@ -279,6 +279,14 @@ siba_bwn_teardown_intr(device_t dev, dev } static int +siba_bwn_find_cap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_cap(dev, capability, capreg)); +} + +static int siba_bwn_find_extcap(device_t dev, device_t child, int capability, int *capreg) { @@ -287,6 +295,14 @@ siba_bwn_find_extcap(device_t dev, devic } static int +siba_bwn_find_htcap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_htcap(dev, capability, capreg)); +} + +static int siba_bwn_alloc_msi(device_t dev, device_t child, int *count) { struct siba_bwn_softc *ssc; @@ -405,7 +421,9 @@ static device_method_t siba_bwn_methods[ DEVMETHOD(bus_teardown_intr, siba_bwn_teardown_intr), /* PCI interface */ + DEVMETHOD(pci_find_cap, siba_bwn_find_cap), DEVMETHOD(pci_find_extcap, siba_bwn_find_extcap), + DEVMETHOD(pci_find_htcap, siba_bwn_find_htcap), DEVMETHOD(pci_alloc_msi, siba_bwn_alloc_msi), DEVMETHOD(pci_release_msi, siba_bwn_release_msi), DEVMETHOD(pci_msi_count, siba_bwn_msi_count),