quirks.c
来自「linux 内核源代码」· C语言 代码 · 共 1,758 行 · 第 1/5 页
C
1,758 行
}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);static void __devinit quirk_e100_interrupt(struct pci_dev *dev){ u16 command; u8 __iomem *csr; u8 cmd_hi; switch (dev->device) { /* PCI IDs taken from drivers/net/e100.c */ case 0x1029: case 0x1030 ... 0x1034: case 0x1038 ... 0x103E: case 0x1050 ... 0x1057: case 0x1059: case 0x1064 ... 0x106B: case 0x1091 ... 0x1095: case 0x1209: case 0x1229: case 0x2449: case 0x2459: case 0x245D: case 0x27DC: break; default: return; } /* * Some firmware hands off the e100 with interrupts enabled, * which can cause a flood of interrupts if packets are * received before the driver attaches to the device. So * disable all e100 interrupts here. The driver will * re-enable them when it's ready. */ pci_read_config_word(dev, PCI_COMMAND, &command); if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0)) return; /* Convert from PCI bus to resource space. */ csr = ioremap(pci_resource_start(dev, 0), 8); if (!csr) { printk(KERN_WARNING "PCI: Can't map %s e100 registers\n", pci_name(dev)); return; } cmd_hi = readb(csr + 3); if (cmd_hi == 0) { printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts " "enabled, disabling\n", pci_name(dev)); writeb(1, csr + 3); } iounmap(csr);}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt);static void __devinit fixup_rev1_53c810(struct pci_dev* dev){ /* rev 1 ncr53c810 chips don't set the class at all which means * they don't get their resources remapped. Fix that here. */ if (dev->class == PCI_CLASS_NOT_DEFINED) { printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n"); dev->class = PCI_CLASS_STORAGE_SCSI; }}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end){ while (f < end) { if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { pr_debug("PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev)); f->hook(dev); } f++; }}extern struct pci_fixup __start_pci_fixups_early[];extern struct pci_fixup __end_pci_fixups_early[];extern struct pci_fixup __start_pci_fixups_header[];extern struct pci_fixup __end_pci_fixups_header[];extern struct pci_fixup __start_pci_fixups_final[];extern struct pci_fixup __end_pci_fixups_final[];extern struct pci_fixup __start_pci_fixups_enable[];extern struct pci_fixup __end_pci_fixups_enable[];extern struct pci_fixup __start_pci_fixups_resume[];extern struct pci_fixup __end_pci_fixups_resume[];void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev){ struct pci_fixup *start, *end; switch(pass) { case pci_fixup_early: start = __start_pci_fixups_early; end = __end_pci_fixups_early; break; case pci_fixup_header: start = __start_pci_fixups_header; end = __end_pci_fixups_header; break; case pci_fixup_final: start = __start_pci_fixups_final; end = __end_pci_fixups_final; break; case pci_fixup_enable: start = __start_pci_fixups_enable; end = __end_pci_fixups_enable; break; case pci_fixup_resume: start = __start_pci_fixups_resume; end = __end_pci_fixups_resume; break; default: /* stupid compiler warning, you would think with an enum... */ return; } pci_do_fixups(dev, start, end);}EXPORT_SYMBOL(pci_fixup_device);/* Enable 1k I/O space granularity on the Intel P64H2 */static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev){ u16 en1k; u8 io_base_lo, io_limit_lo; unsigned long base, limit; struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; pci_read_config_word(dev, 0x40, &en1k); if (en1k & 0x200) { printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n"); pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; if (base <= limit) { res->start = base; res->end = limit + 0x3ff; } }}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2 * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge() * in drivers/pci/setup-bus.c */static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev){ u16 en1k, iobl_adr, iobl_adr_1k; struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; pci_read_config_word(dev, 0x40, &en1k); if (en1k & 0x200) { pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr); iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00); if (iobl_adr != iobl_adr_1k) { printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n", iobl_adr,iobl_adr_1k); pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k); } }}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl);/* Under some circumstances, AER is not linked with extended capabilities. * Force it to be linked by setting the corresponding control bit in the * config space. */static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev){ uint8_t b; if (pci_read_config_byte(dev, 0xf41, &b) == 0) { if (!(b & 0x20)) { pci_write_config_byte(dev, 0xf41, b | 0x20); printk(KERN_INFO "PCI: Linking AER extended capability on %s\n", pci_name(dev)); } }}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap);#ifdef CONFIG_PCI_MSI/* Some chipsets do not support MSI. We cannot easily rely on setting * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually * some other busses controlled by the chipset even if Linux is not * aware of it. Instead of setting the flag on all busses in the * machine, simply disable MSI globally. */static void __init quirk_disable_all_msi(struct pci_dev *dev){ pci_no_msi(); printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);/* Disable MSI on chipsets that are known to not support it */static void __devinit quirk_disable_msi(struct pci_dev *dev){ if (dev->subordinate) { printk(KERN_WARNING "PCI: MSI quirk detected. " "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n", pci_name(dev)); dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; }}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);/* Go through the list of Hypertransport capabilities and * return 1 if a HT MSI capability is found and enabled */static int __devinit msi_ht_cap_enabled(struct pci_dev *dev){ int pos, ttl = 48; pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); while (pos && ttl--) { u8 flags; if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) { printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n", flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", pci_name(dev)); return (flags & HT_MSI_FLAGS_ENABLE) != 0; } pos = pci_find_next_ht_capability(dev, pos, HT_CAPTYPE_MSI_MAPPING); } return 0;}/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */static void __devinit quirk_msi_ht_cap(struct pci_dev *dev){ if (dev->subordinate && !msi_ht_cap_enabled(dev)) { printk(KERN_WARNING "PCI: MSI quirk detected. " "MSI disabled on chipset %s.\n", pci_name(dev)); dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; }}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, quirk_msi_ht_cap);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, quirk_msi_ht_cap);/* The nVidia CK804 chipset may have 2 HT MSI mappings. * MSI are supported if the MSI capability set in any of these mappings. */static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev){ struct pci_dev *pdev; if (!dev->subordinate) return; /* check HT MSI cap on this chipset and the root one. * a single one having MSI is enough to be sure that MSI are supported. */ pdev = pci_get_slot(dev->bus, 0); if (!pdev) return; if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { printk(KERN_WARNING "PCI: MSI quirk detected. " "MSI disabled on chipset %s.\n", pci_name(dev)); dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; } pci_dev_put(pdev);}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_msi_ht_cap);static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev){ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4395, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374, quirk_msi_intx_disable_bug);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, quirk_msi_intx_disable_bug);#endif /* CONFIG_PCI_MSI */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?