static int vtpci_attach(device_t dev) { struct vtpci_softc *sc; device_t child; int rid; sc = device_get_softc(dev); sc->vtpci_dev = dev; pci_enable_busmaster(dev); rid = PCIR_BAR(0); sc->vtpci_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (sc->vtpci_res == NULL) { device_printf(dev, "cannot map I/O space\n"); return (ENXIO); } if (pci_find_extcap(dev, PCIY_MSI, NULL) != 0) sc->vtpci_flags |= VIRTIO_PCI_FLAG_NO_MSI; if (pci_find_extcap(dev, PCIY_MSIX, NULL) == 0) { rid = PCIR_BAR(1); sc->vtpci_msix_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); } if (sc->vtpci_msix_res == NULL) sc->vtpci_flags |= VIRTIO_PCI_FLAG_NO_MSIX; vtpci_reset(sc); /* Tell the host we've noticed this device. */ vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_ACK); if ((child = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "cannot create child device\n"); vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED); vtpci_detach(dev); return (ENOMEM); } sc->vtpci_child_dev = child; vtpci_probe_and_attach_child(sc); return (0); }
static int siba_bwn_find_extcap(device_t dev, device_t child, int capability, int *capreg) { return (pci_find_extcap(dev, capability, capreg)); }
static int pci_hostb_find_extcap(device_t dev, device_t child, int capability, int *capreg) { return (pci_find_extcap(dev, capability, capreg)); }
/* * Write the PCI Express capabilities */ int32_t e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { device_t dev = ((struct e1000_osdep *)hw->back)->dev; u32 offset; pci_find_extcap(dev, PCIY_EXPRESS, &offset); pci_write_config(dev, offset + reg, *value, 2); return (E1000_SUCCESS); }
int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) { device_t root; int pos; u32 lnkcap = 0, lnkcap2 = 0; *mask = 0; if (!drm_device_is_pcie(dev)) return -EINVAL; root = device_get_parent(dev->device); pos = 0; pci_find_extcap(root, PCIY_EXPRESS, &pos); if (!pos) return -EINVAL; /* we've been informed via and serverworks don't make the cut */ if (pci_get_vendor(root) == PCI_VENDOR_ID_VIA || pci_get_vendor(root) == PCI_VENDOR_ID_SERVERWORKS) return -EINVAL; lnkcap = pci_read_config(root, pos + PCIER_LINKCAP, 4); lnkcap2 = pci_read_config(root, pos + PCIER_LINK_CAP2, 4); lnkcap &= PCIEM_LNKCAP_SPEED_MASK; lnkcap2 &= 0xfe; #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ if (lnkcap2) { /* PCIE GEN 3.0 */ if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) *mask |= DRM_PCIE_SPEED_25; if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) *mask |= DRM_PCIE_SPEED_50; if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) *mask |= DRM_PCIE_SPEED_80; } else { if (lnkcap & 1) *mask |= DRM_PCIE_SPEED_25; if (lnkcap & 2) *mask |= DRM_PCIE_SPEED_50; } DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", pci_get_vendor(root), pci_get_device(root), lnkcap, lnkcap2); return 0; }
/** * @brief Function to get the PCI capabilities * @param sc software handle to the device */ static void oce_get_pci_capabilities(POCE_SOFTC sc) { uint32_t val; #if __FreeBSD_version >= 1000000 #define pci_find_extcap pci_find_cap #endif if (pci_find_extcap(sc->dev, PCIY_PCIX, &val) == 0) { if (val != 0) sc->flags |= OCE_FLAGS_PCIX; } if (pci_find_extcap(sc->dev, PCIY_EXPRESS, &val) == 0) { if (val != 0) { uint16_t link_status = pci_read_config(sc->dev, val + 0x12, 2); sc->flags |= OCE_FLAGS_PCIE; sc->pcie_link_speed = link_status & 0xf; sc->pcie_link_width = (link_status >> 4) & 0x3f; } }
/* * Set the ARI_EN bit in the lowest-numbered PCI function with the SR-IOV * capability. This bit is only writeable on the lowest-numbered PF but * affects all PFs on the device. */ static int pci_iov_set_ari(device_t bus) { device_t lowest; device_t *devlist; int i, error, devcount, lowest_func, lowest_pos, iov_pos, dev_func; uint16_t iov_ctl; /* If ARI is disabled on the downstream port there is nothing to do. */ if (!PCIB_ARI_ENABLED(device_get_parent(bus))) return (0); error = device_get_children(bus, &devlist, &devcount); if (error != 0) return (error); lowest = NULL; for (i = 0; i < devcount; i++) { if (pci_find_extcap(devlist[i], PCIZ_SRIOV, &iov_pos) == 0) { dev_func = pci_get_function(devlist[i]); if (lowest == NULL || dev_func < lowest_func) { lowest = devlist[i]; lowest_func = dev_func; lowest_pos = iov_pos; } } } free(devlist, M_TEMP); /* * If we called this function some device must have the SR-IOV * capability. */ KASSERT(lowest != NULL, ("Could not find child of %s with SR-IOV capability", device_get_nameunit(bus))); iov_ctl = pci_read_config(lowest, lowest_pos + PCIR_SRIOV_CTL, 2); iov_ctl |= PCIM_SRIOV_ARI_EN; pci_write_config(lowest, lowest_pos + PCIR_SRIOV_CTL, iov_ctl, 2); if ((pci_read_config(lowest, lowest_pos + PCIR_SRIOV_CTL, 2) & PCIM_SRIOV_ARI_EN) == 0) { device_printf(lowest, "failed to enable ARI\n"); return (ENXIO); } return (0); }
static void cxgb_controller_attach(device_t parent, device_t dev, void *context) { device_t child; const struct adapter_info *ai; struct adapter *sc; struct pci_attach_args *pa = context; struct cxgb_attach_args cxgb_args; int locs[2]; int i, error = 0; uint32_t vers; int port_qsets = 1; int reg; #ifdef MSI_SUPPORTED int msi_needed; #endif sc = device_private(dev); sc->dev = dev; memcpy(&sc->pa, pa, sizeof(struct pci_attach_args)); sc->msi_count = 0; ai = cxgb_get_adapter_info(pa); /* * XXX not really related but a recent addition */ #ifdef MSI_SUPPORTED /* find the PCIe link width and set max read request to 4KB*/ if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { uint16_t lnk, pectl; lnk = pci_read_config(dev, reg + 0x12, 2); sc->link_width = (lnk >> 4) & 0x3f; pectl = pci_read_config(dev, reg + 0x8, 2); pectl = (pectl & ~0x7000) | (5 << 12); pci_write_config(dev, reg + 0x8, pectl, 2); }
/* Returns 1 if AGP or 0 if not. */ static int drm_device_find_capability(struct drm_device *dev, int cap) { #if __FreeBSD_version >= 602102 return (pci_find_extcap(dev->device, cap, NULL) == 0); #else /* Code taken from agp.c. IWBNI that was a public interface. */ u_int32_t status; u_int8_t ptr, next; /* * Check the CAP_LIST bit of the PCI status register first. */ status = pci_read_config(dev->device, PCIR_STATUS, 2); if (!(status & 0x10)) return 0; /* * Traverse the capabilities list. */ for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1); ptr != 0; ptr = next) { u_int32_t capid = pci_read_config(dev->device, ptr, 4); next = AGP_CAPID_GET_NEXT_PTR(capid); /* * If this capability entry ID is cap, then we are done. */ if (AGP_CAPID_GET_CAP_ID(capid) == cap) return 1; } return 0; #endif }
int pci_iov_attach_method(device_t bus, device_t dev, nvlist_t *pf_schema, nvlist_t *vf_schema) { device_t pcib; struct pci_devinfo *dinfo; struct pcicfg_iov *iov; nvlist_t *schema; uint32_t version; int error; int iov_pos; dinfo = device_get_ivars(dev); pcib = device_get_parent(bus); schema = NULL; error = pci_find_extcap(dev, PCIZ_SRIOV, &iov_pos); if (error != 0) return (error); version = pci_read_config(dev, iov_pos, 4); if (PCI_EXTCAP_VER(version) != 1) { if (bootverbose) device_printf(dev, "Unsupported version of SR-IOV (%d) detected\n", PCI_EXTCAP_VER(version)); return (ENXIO); } iov = malloc(sizeof(*dinfo->cfg.iov), M_SRIOV, M_WAITOK | M_ZERO); mtx_lock(&Giant); if (dinfo->cfg.iov != NULL) { error = EBUSY; goto cleanup; } iov->iov_pos = iov_pos; schema = pci_iov_build_schema(&pf_schema, &vf_schema); if (schema == NULL) { error = ENOMEM; goto cleanup; } error = pci_iov_validate_schema(schema); if (error != 0) goto cleanup; iov->iov_schema = schema; iov->iov_cdev = make_dev(&iov_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "iov/%s", device_get_nameunit(dev)); if (iov->iov_cdev == NULL) { error = ENOMEM; goto cleanup; } dinfo->cfg.iov = iov; iov->iov_cdev->si_drv1 = dinfo; mtx_unlock(&Giant); return (0); cleanup: nvlist_destroy(schema); nvlist_destroy(pf_schema); nvlist_destroy(vf_schema); free(iov, M_SRIOV); mtx_unlock(&Giant); return (error); }
/* Returns 1 if AGP or 0 if not. */ static int drm_device_find_capability(struct drm_device *dev, int cap) { return (pci_find_extcap(dev->device, cap, NULL) == 0); }