pci.c
来自「linux 内核源代码」· C语言 代码 · 共 1,653 行 · 第 1/3 页
C
1,653 行
for (i = 0; i < 6; i++) if (bars & (1 << i)) pci_release_region(pdev, i);}/** * pci_request_selected_regions - Reserve selected PCI I/O and memory resources * @pdev: PCI device whose resources are to be reserved * @bars: Bitmask of BARs to be requested * @res_name: Name to be associated with resource */int pci_request_selected_regions(struct pci_dev *pdev, int bars, const char *res_name){ int i; for (i = 0; i < 6; i++) if (bars & (1 << i)) if(pci_request_region(pdev, i, res_name)) goto err_out; return 0;err_out: while(--i >= 0) if (bars & (1 << i)) pci_release_region(pdev, i); return -EBUSY;}/** * pci_release_regions - Release reserved PCI I/O and memory resources * @pdev: PCI device whose resources were previously reserved by pci_request_regions * * Releases all PCI I/O and memory resources previously reserved by a * successful call to pci_request_regions. Call this function only * after all use of the PCI regions has ceased. */void pci_release_regions(struct pci_dev *pdev){ pci_release_selected_regions(pdev, (1 << 6) - 1);}/** * pci_request_regions - Reserved PCI I/O and memory resources * @pdev: PCI device whose resources are to be reserved * @res_name: Name to be associated with resource. * * Mark all PCI regions associated with PCI device @pdev as * being reserved by owner @res_name. Do not access any * address inside the PCI regions unless this call returns * successfully. * * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */int pci_request_regions(struct pci_dev *pdev, const char *res_name){ return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name);}/** * pci_set_master - enables bus-mastering for device dev * @dev: the PCI device to enable * * Enables bus-mastering on the device and calls pcibios_set_master() * to do the needed arch specific settings. */voidpci_set_master(struct pci_dev *dev){ u16 cmd; pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_MASTER)) { pr_debug("PCI: Enabling bus mastering for device %s\n", pci_name(dev)); cmd |= PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, cmd); } dev->is_busmaster = 1; pcibios_set_master(dev);}#ifdef PCI_DISABLE_MWIint pci_set_mwi(struct pci_dev *dev){ return 0;}int pci_try_set_mwi(struct pci_dev *dev){ return 0;}void pci_clear_mwi(struct pci_dev *dev){}#else#ifndef PCI_CACHE_LINE_BYTES#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES#endif/* This can be overridden by arch code. *//* Don't forget this is measured in 32-bit words, not bytes */u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;/** * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed * @dev: the PCI device for which MWI is to be enabled * * Helper function for pci_set_mwi. * Originally copied from drivers/net/acenic.c. * Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>. * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */static intpci_set_cacheline_size(struct pci_dev *dev){ u8 cacheline_size; if (!pci_cache_line_size) return -EINVAL; /* The system doesn't support MWI. */ /* Validate current setting: the PCI_CACHE_LINE_SIZE must be equal to or multiple of the right value. */ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); if (cacheline_size >= pci_cache_line_size && (cacheline_size % pci_cache_line_size) == 0) return 0; /* Write the correct value. */ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); /* Read it back. */ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); if (cacheline_size == pci_cache_line_size) return 0; printk(KERN_DEBUG "PCI: cache line size of %d is not supported " "by device %s\n", pci_cache_line_size << 2, pci_name(dev)); return -EINVAL;}/** * pci_set_mwi - enables memory-write-invalidate PCI transaction * @dev: the PCI device for which MWI is enabled * * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND. * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */intpci_set_mwi(struct pci_dev *dev){ int rc; u16 cmd; rc = pci_set_cacheline_size(dev); if (rc) return rc; pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_INVALIDATE)) { pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev)); cmd |= PCI_COMMAND_INVALIDATE; pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0;}/** * pci_try_set_mwi - enables memory-write-invalidate PCI transaction * @dev: the PCI device for which MWI is enabled * * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND. * Callers are not required to check the return value. * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */int pci_try_set_mwi(struct pci_dev *dev){ int rc = pci_set_mwi(dev); return rc;}/** * pci_clear_mwi - disables Memory-Write-Invalidate for device dev * @dev: the PCI device to disable * * Disables PCI Memory-Write-Invalidate transaction on the device */voidpci_clear_mwi(struct pci_dev *dev){ u16 cmd; pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & PCI_COMMAND_INVALIDATE) { cmd &= ~PCI_COMMAND_INVALIDATE; pci_write_config_word(dev, PCI_COMMAND, cmd); }}#endif /* ! PCI_DISABLE_MWI *//** * pci_intx - enables/disables PCI INTx for device dev * @pdev: the PCI device to operate on * @enable: boolean: whether to enable or disable PCI INTx * * Enables/disables PCI INTx for device dev */voidpci_intx(struct pci_dev *pdev, int enable){ u16 pci_command, new; pci_read_config_word(pdev, PCI_COMMAND, &pci_command); if (enable) { new = pci_command & ~PCI_COMMAND_INTX_DISABLE; } else { new = pci_command | PCI_COMMAND_INTX_DISABLE; } if (new != pci_command) { struct pci_devres *dr; pci_write_config_word(pdev, PCI_COMMAND, new); dr = find_pci_dr(pdev); if (dr && !dr->restore_intx) { dr->restore_intx = 1; dr->orig_intx = !enable; } }}/** * pci_msi_off - disables any msi or msix capabilities * @dev: the PCI device to operate on * * If you want to use msi see pci_enable_msi and friends. * This is a lower level primitive that allows us to disable * msi operation at the device level. */void pci_msi_off(struct pci_dev *dev){ int pos; u16 control; pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (pos) { pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); control &= ~PCI_MSI_FLAGS_ENABLE; pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); } pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (pos) { pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); control &= ~PCI_MSIX_FLAGS_ENABLE; pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); }}#ifndef HAVE_ARCH_PCI_SET_DMA_MASK/* * These can be overridden by arch-specific implementations */intpci_set_dma_mask(struct pci_dev *dev, u64 mask){ if (!pci_dma_supported(dev, mask)) return -EIO; dev->dma_mask = mask; return 0;} intpci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask){ if (!pci_dma_supported(dev, mask)) return -EIO; dev->dev.coherent_dma_mask = mask; return 0;}#endif/** * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count * @dev: PCI device to query * * Returns mmrbc: maximum designed memory read count in bytes * or appropriate error value. */int pcix_get_max_mmrbc(struct pci_dev *dev){ int err, cap; u32 stat; cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!cap) return -EINVAL; err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); if (err) return -EINVAL; return (stat & PCI_X_STATUS_MAX_READ) >> 12;}EXPORT_SYMBOL(pcix_get_max_mmrbc);/** * pcix_get_mmrbc - get PCI-X maximum memory read byte count * @dev: PCI device to query * * Returns mmrbc: maximum memory read count in bytes * or appropriate error value. */int pcix_get_mmrbc(struct pci_dev *dev){ int ret, cap; u32 cmd; cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!cap) return -EINVAL; ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); if (!ret) ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); return ret;}EXPORT_SYMBOL(pcix_get_mmrbc);/** * pcix_set_mmrbc - set PCI-X maximum memory read byte count * @dev: PCI device to query * @mmrbc: maximum memory read count in bytes * valid values are 512, 1024, 2048, 4096 * * If possible sets maximum memory read byte count, some bridges have erratas * that prevent this. */int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc){ int cap, err = -EINVAL; u32 stat, cmd, v, o; if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) goto out; v = ffs(mmrbc) - 10; cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!cap) goto out; err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); if (err) goto out; if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) return -E2BIG; err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); if (err) goto out; o = (cmd & PCI_X_CMD_MAX_READ) >> 2; if (o != v) { if (v > o && dev->bus && (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC)) return -EIO; cmd &= ~PCI_X_CMD_MAX_READ; cmd |= v << 2; err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd); }out: return err;}EXPORT_SYMBOL(pcix_set_mmrbc);/** * pcie_get_readrq - get PCI Express read request size * @dev: PCI device to query * * Returns maximum memory read request in bytes * or appropriate error value. */int pcie_get_readrq(struct pci_dev *dev){ int ret, cap; u16 ctl; cap = pci_find_capability(dev, PCI_CAP_ID_EXP); if (!cap) return -EINVAL; ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); if (!ret) ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); return ret;}EXPORT_SYMBOL(pcie_get_readrq);/** * pcie_set_readrq - set PCI Express maximum memory read request * @dev: PCI device to query * @rq: maximum memory read count in bytes * valid values are 128, 256, 512, 1024, 2048, 4096 * * If possible sets maximum read byte count */int pcie_set_readrq(struct pci_dev *dev, int rq){ int cap, err = -EINVAL; u16 ctl, v; if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) goto out; v = (ffs(rq) - 8) << 12; cap = pci_find_capability(dev, PCI_CAP_ID_EXP); if (!cap) goto out; err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); if (err) goto out; if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { ctl &= ~PCI_EXP_DEVCTL_READRQ; ctl |= v; err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl); }out: return err;}EXPORT_SYMBOL(pcie_set_readrq);/** * pci_select_bars - Make BAR mask from the type of resource * @dev: the PCI device for which BAR mask is made * @flags: resource type mask to be selected * * This helper routine makes bar mask from the type of resource. */int pci_select_bars(struct pci_dev *dev, unsigned long flags){ int i, bars = 0; for (i = 0; i < PCI_NUM_RESOURCES; i++) if (pci_resource_flags(dev, i) & flags) bars |= (1 << i); return bars;}static void __devinit pci_no_domains(void){#ifdef CONFIG_PCI_DOMAINS pci_domains_supported = 0;#endif}static int __devinit pci_init(void){ struct pci_dev *dev = NULL; while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_fixup_device(pci_fixup_final, dev); } return 0;}static int __devinit pci_setup(char *str){ while (str) { char *k = strchr(str, ','); if (k) *k++ = 0; if (*str && (str = pcibios_setup(str)) && *str) { if (!strcmp(str, "nomsi")) { pci_no_msi(); } else if (!strcmp(str, "noaer")) { pci_no_aer(); } else if (!strcmp(str, "nodomains")) { pci_no_domains(); } else if (!strncmp(str, "cbiosize=", 9)) { pci_cardbus_io_size = memparse(str + 9, &str); } else if (!strncmp(str, "cbmemsize=", 10)) { pci_cardbus_mem_size = memparse(str + 10, &str); } else { printk(KERN_ERR "PCI: Unknown option `%s'\n", str); } } str = k; } return 0;}early_param("pci", pci_setup);device_initcall(pci_init);EXPORT_SYMBOL_GPL(pci_restore_bars);EXPORT_SYMBOL(pci_reenable_device);EXPORT_SYMBOL(pci_enable_device_bars);EXPORT_SYMBOL(pci_enable_device);EXPORT_SYMBOL(pcim_enable_device);EXPORT_SYMBOL(pcim_pin_device);EXPORT_SYMBOL(pci_disable_device);EXPORT_SYMBOL(pci_find_capability);EXPORT_SYMBOL(pci_bus_find_capability);EXPORT_SYMBOL(pci_release_regions);EXPORT_SYMBOL(pci_request_regions);EXPORT_SYMBOL(pci_release_region);EXPORT_SYMBOL(pci_request_region);EXPORT_SYMBOL(pci_release_selected_regions);EXPORT_SYMBOL(pci_request_selected_regions);EXPORT_SYMBOL(pci_set_master);EXPORT_SYMBOL(pci_set_mwi);EXPORT_SYMBOL(pci_try_set_mwi);EXPORT_SYMBOL(pci_clear_mwi);EXPORT_SYMBOL_GPL(pci_intx);EXPORT_SYMBOL(pci_set_dma_mask);EXPORT_SYMBOL(pci_set_consistent_dma_mask);EXPORT_SYMBOL(pci_assign_resource);EXPORT_SYMBOL(pci_find_parent_resource);EXPORT_SYMBOL(pci_select_bars);EXPORT_SYMBOL(pci_set_power_state);EXPORT_SYMBOL(pci_save_state);EXPORT_SYMBOL(pci_restore_state);EXPORT_SYMBOL(pci_enable_wake);EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?