Index: dev/siba/siba_bwn.c =================================================================== --- dev/siba/siba_bwn.c (revision 232401) +++ dev/siba/siba_bwn.c (working copy) @@ -279,6 +279,14 @@ } 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 @@ } 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 @@ 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), Index: dev/pci/pci_if.m =================================================================== --- dev/pci/pci_if.m (revision 232401) +++ dev/pci/pci_if.m (working copy) @@ -105,6 +105,13 @@ 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 @@ 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; Index: dev/pci/vga_pci.c =================================================================== --- dev/pci/vga_pci.c (revision 232401) +++ dev/pci/vga_pci.c (working copy) @@ -314,6 +314,14 @@ } 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 @@ } 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 @@ 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), Index: dev/pci/hostb_pci.c =================================================================== --- dev/pci/hostb_pci.c (revision 232401) +++ dev/pci/hostb_pci.c (working copy) @@ -197,6 +197,14 @@ } 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 @@ 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 @@ 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 } }; Index: dev/pci/pci_private.h =================================================================== --- dev/pci/pci_private.h (revision 232401) +++ dev/pci/pci_private.h (working copy) @@ -74,8 +74,12 @@ 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, Index: dev/pci/pci.c =================================================================== --- dev/pci/pci.c (revision 232401) +++ dev/pci/pci.c (working copy) @@ -162,7 +162,9 @@ 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), @@ -722,6 +724,9 @@ * 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; @@ -1139,12 +1144,55 @@ } /* - * 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); @@ -1192,6 +1240,43 @@ } /* + * 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 @@ -1681,10 +1766,12 @@ 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; @@ -1695,10 +1782,12 @@ 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; Index: dev/pci/pcivar.h =================================================================== --- dev/pci/pcivar.h (revision 232401) +++ dev/pci/pcivar.h (working copy) @@ -123,6 +123,12 @@ 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 @@ 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 @@ 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 @@ } 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));