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 + -
显示快捷键?