quirks.c

来自「linux 内核源代码」· C语言 代码 · 共 1,758 行 · 第 1/5 页

C
1,758
字号
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7501_MCH,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82810_IG3,	asus_hides_smbus_hostbridge );static void asus_hides_smbus_lpc(struct pci_dev *dev){	u16 val;		if (likely(!asus_hides_smbus))		return;	pci_read_config_word(dev, 0xF2, &val);	if (val & 0x8) {		pci_write_config_word(dev, 0xF2, val & (~0x8));		pci_read_config_word(dev, 0xF2, &val);		if (val & 0x8)			printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);		else			printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev){	u32 val, rcba;	void __iomem *base;	if (likely(!asus_hides_smbus))		return;	pci_read_config_dword(dev, 0xF0, &rcba);	base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */	if (base == NULL) return;	val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */	writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */	iounmap(base);	printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );/* * SiS 96x south bridge: BIOS typically hides SMBus device... */static void quirk_sis_96x_smbus(struct pci_dev *dev){	u8 val = 0;	pci_read_config_byte(dev, 0x77, &val);	if (val & 0x10) {		printk(KERN_INFO "Enabling SiS 96x SMBus.\n");		pci_write_config_byte(dev, 0x77, val & ~0x10);	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );/* * ... This is further complicated by the fact that some SiS96x south * bridges pretend to be 85C503/5513 instead.  In that case see if we * spotted a compatible north bridge to make sure. * (pci_find_device doesn't work yet) * * We can also enable the sis96x bit in the discovery register.. */#define SIS_DETECT_REGISTER 0x40static void quirk_sis_503(struct pci_dev *dev){	u8 reg;	u16 devid;	pci_read_config_byte(dev, SIS_DETECT_REGISTER, &reg);	pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg | (1 << 6));	pci_read_config_word(dev, PCI_DEVICE_ID, &devid);	if (((devid & 0xfff0) != 0x0960) && (devid != 0x0018)) {		pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg);		return;	}	/*	 * Ok, it now shows up as a 96x.. run the 96x quirk by	 * hand in case it has already been processed.	 * (depends on link order, which is apparently not guaranteed)	 */	dev->device = devid;	quirk_sis_96x_smbus(dev);}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );/* * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller * and MC97 modem controller are disabled when a second PCI soundcard is * present. This patch, tweaking the VT8237 ISA bridge, enables them. * -- bjd */static void asus_hides_ac97_lpc(struct pci_dev *dev){	u8 val;	int asus_hides_ac97 = 0;	if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {		if (dev->device == PCI_DEVICE_ID_VIA_8237)			asus_hides_ac97 = 1;	}	if (!asus_hides_ac97)		return;	pci_read_config_byte(dev, 0x50, &val);	if (val & 0xc0) {		pci_write_config_byte(dev, 0x50, val & (~0xc0));		pci_read_config_byte(dev, 0x50, &val);		if (val & 0xc0)			printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);		else			printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)/* *	If we are using libata we can drive this chip properly but must *	do this early on to make the additional device appear during *	the PCI scanning. */static void quirk_jmicron_ata(struct pci_dev *pdev){	u32 conf1, conf5, class;	u8 hdr;	/* Only poke fn 0 */	if (PCI_FUNC(pdev->devfn))		return;	pci_read_config_dword(pdev, 0x40, &conf1);	pci_read_config_dword(pdev, 0x80, &conf5);	conf1 &= ~0x00CFF302; /* Clear bit 1, 8, 9, 12-19, 22, 23 */	conf5 &= ~(1 << 24);  /* Clear bit 24 */	switch (pdev->device) {	case PCI_DEVICE_ID_JMICRON_JMB360:		/* The controller should be in single function ahci mode */		conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */		break;	case PCI_DEVICE_ID_JMICRON_JMB365:	case PCI_DEVICE_ID_JMICRON_JMB366:		/* Redirect IDE second PATA port to the right spot */		conf5 |= (1 << 24);		/* Fall through */	case PCI_DEVICE_ID_JMICRON_JMB361:	case PCI_DEVICE_ID_JMICRON_JMB363:		/* Enable dual function mode, AHCI on fn 0, IDE fn1 */		/* Set the class codes correctly and then direct IDE 0 */		conf1 |= 0x00C2A1B3; /* Set 0, 1, 4, 5, 7, 8, 13, 15, 17, 22, 23 */		break;	case PCI_DEVICE_ID_JMICRON_JMB368:		/* The controller should be in single function IDE mode */		conf1 |= 0x00C00000; /* Set 22, 23 */		break;	}	pci_write_config_dword(pdev, 0x40, conf1);	pci_write_config_dword(pdev, 0x80, conf5);	/* Update pdev accordingly */	pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);	pdev->hdr_type = hdr & 0x7f;	pdev->multifunction = !!(hdr & 0x80);	pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class);	pdev->class = class >> 8;}DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);#endif#ifdef CONFIG_X86_IO_APICstatic void __init quirk_alder_ioapic(struct pci_dev *pdev){	int i;	if ((pdev->class >> 8) != 0xff00)		return;	/* the first BAR is the location of the IO APIC...we must	 * not touch this (and it's already covered by the fixmap), so	 * forcibly insert it into the resource tree */	if (pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))		insert_resource(&iomem_resource, &pdev->resource[0]);	/* The next five BARs all seem to be rubbish, so just clean	 * them out */	for (i=1; i < 6; i++) {		memset(&pdev->resource[i], 0, sizeof(pdev->resource[i]));	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );#endifint pcie_mch_quirk;EXPORT_SYMBOL(pcie_mch_quirk);static void __devinit quirk_pcie_mch(struct pci_dev *pdev){	pcie_mch_quirk = 1;}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7520_MCH,	quirk_pcie_mch );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_pcie_mch );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_pcie_mch );/* * It's possible for the MSI to get corrupted if shpc and acpi * are used together on certain PXH-based systems. */static void __devinit quirk_pcie_pxh(struct pci_dev *dev){	pci_msi_off(dev);	dev->no_msi = 1;	printk(KERN_WARNING "PCI: PXH quirk detected, "		"disabling MSI for SHPC device\n");}DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHD_0,	quirk_pcie_pxh);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHD_1,	quirk_pcie_pxh);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXH_0,	quirk_pcie_pxh);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXH_1,	quirk_pcie_pxh);DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHV,	quirk_pcie_pxh);/* * Some Intel PCI Express chipsets have trouble with downstream * device power management. */static void quirk_intel_pcie_pm(struct pci_dev * dev){	pci_pm_d3_delay = 120;	dev->no_d1d2 = 1;}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e2, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e3, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e4, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e5, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e6, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25e7, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25f7, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25f8, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25f9, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x25fa, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2601, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2602, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2603, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2604, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2605, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2606, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2607, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2608, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2609, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x260a, quirk_intel_pcie_pm);DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x260b, quirk_intel_pcie_pm);/* * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. * Re-allocate the region if needed... */static void __init quirk_tc86c001_ide(struct pci_dev *dev){	struct resource *r = &dev->resource[0];	if (r->start & 0x8) {		r->start = 0;		r->end = 0xf;	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,			 PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,			 quirk_tc86c001_ide);static void __devinit quirk_netmos(struct pci_dev *dev){	unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;	unsigned int num_serial = dev->subsystem_device & 0xf;	/*	 * These Netmos parts are multiport serial devices with optional	 * parallel ports.  Even when parallel ports are present, they	 * are identified as class SERIAL, which means the serial driver	 * will claim them.  To prevent this, mark them as class OTHER.	 * These combo devices should be claimed by parport_serial.	 *	 * The subdevice ID is of the form 0x00PS, where <P> is the number	 * of parallel ports and <S> is the number of serial ports.	 */	switch (dev->device) {	case PCI_DEVICE_ID_NETMOS_9735:	case PCI_DEVICE_ID_NETMOS_9745:	case PCI_DEVICE_ID_NETMOS_9835:	case PCI_DEVICE_ID_NETMOS_9845:	case PCI_DEVICE_ID_NETMOS_9855:		if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL &&		    num_parallel) {			printk(KERN_INFO "PCI: Netmos %04x (%u parallel, "				"%u serial); changing class SERIAL to OTHER "				"(use parport_serial)\n",				dev->device, num_parallel, num_serial);			dev->class = (PCI_CLASS_COMMUNICATION_OTHER << 8) |			    (dev->class & 0xff);		}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?