quirks.c

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

C
1,758
字号
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237,		quirk_via_bridge);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237A,	quirk_via_bridge);/** *	quirk_via_vlink		-	VIA VLink IRQ number update *	@dev: PCI device * *	If the device we are dealing with is on a PIC IRQ we need to *	ensure that the IRQ line register which usually is not relevant *	for PCI cards, is actually written so that interrupts get sent *	to the right place. *	We only do this on systems where a VIA south bridge was detected, *	and only for VIA devices on the motherboard (see quirk_via_bridge *	above). */static void quirk_via_vlink(struct pci_dev *dev){	u8 irq, new_irq;	/* Check if we have VLink at all */	if (via_vlink_dev_lo == -1)		return;	new_irq = dev->irq;	/* Don't quirk interrupts outside the legacy IRQ range */	if (!new_irq || new_irq > 15)		return;	/* Internal device ? */	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > via_vlink_dev_hi ||	    PCI_SLOT(dev->devfn) < via_vlink_dev_lo)		return;	/* This is an internal VLink device on a PIC interrupt. The BIOS	   ought to have set this but may not have, so we redo it */	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);	if (new_irq != irq) {		printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",			pci_name(dev), irq, new_irq);		udelay(15);	/* unknown if delay really needed */		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);	}}DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);/* * VIA VT82C598 has its device ID settable and many BIOSes * set it to the ID of VT82C597 for backward compatibility. * We need to switch it off to be able to recognize the real * type of the chip. */static void __devinit quirk_vt82c598_id(struct pci_dev *dev){	pci_write_config_byte(dev, 0xfc, 0);	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id );/* * CardBus controllers have a legacy base address that enables them * to respond as i82365 pcmcia controllers.  We don't want them to * do this even if the Linux CardBus driver is not loaded, because * the Linux i82365 driver does not (and should not) handle CardBus. */static void quirk_cardbus_legacy(struct pci_dev *dev){	if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)		return;	pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);}DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);/* * Following the PCI ordering rules is optional on the AMD762. I'm not * sure what the designers were smoking but let's not inhale... * * To be fair to AMD, it follows the spec by default, its BIOS people * who turn it off! */static void quirk_amd_ordering(struct pci_dev *dev){	u32 pcic;	pci_read_config_dword(dev, 0x4C, &pcic);	if ((pcic&6)!=6) {		pcic |= 6;		printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");		pci_write_config_dword(dev, 0x4C, pcic);		pci_read_config_dword(dev, 0x84, &pcic);		pcic |= (1<<23);	/* Required in this mode */		pci_write_config_dword(dev, 0x84, pcic);	}}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );/* *	DreamWorks provided workaround for Dunord I-3000 problem * *	This card decodes and responds to addresses not apparently *	assigned to it. We force a larger allocation to ensure that *	nothing gets put too close to it. */static void __devinit quirk_dunord ( struct pci_dev * dev ){	struct resource *r = &dev->resource [1];	r->start = 0;	r->end = 0xffffff;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord );/* * i82380FB mobile docking controller: its PCI-to-PCI bridge * is subtractive decoding (transparent), and does indicate this * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80 * instead of 0x01. */static void __devinit quirk_transparent_bridge(struct pci_dev *dev){	dev->transparent = 1;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge );/* * Common misconfiguration of the MediaGX/Geode PCI master that will * reduce PCI bandwidth from 70MB/s to 25MB/s.  See the GXM/GXLV/GX1 * datasheets found at http://www.national.com/ds/GX for info on what * these bits do.  <christer@weinigel.se> */static void quirk_mediagx_master(struct pci_dev *dev){	u8 reg;	pci_read_config_byte(dev, 0x41, &reg);	if (reg & 2) {		reg &= ~2;		printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);                pci_write_config_byte(dev, 0x41, reg);	}}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );/* *	Ensure C0 rev restreaming is off. This is normally done by *	the BIOS but in the odd case it is not the results are corruption *	hence the presence of a Linux check */static void quirk_disable_pxb(struct pci_dev *pdev){	u16 config;		if (pdev->revision != 0x04)		/* Only C0 requires this */		return;	pci_read_config_word(pdev, 0x40, &config);	if (config & (1<<6)) {		config &= ~(1<<6);		pci_write_config_word(pdev, 0x40, config);		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");	}}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );static void __devinit quirk_sb600_sata(struct pci_dev *pdev){	/* set sb600 sata to ahci mode */	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {		u8 tmp;		pci_read_config_byte(pdev, 0x40, &tmp);		pci_write_config_byte(pdev, 0x40, tmp|1);		pci_write_config_byte(pdev, 0x9, 1);		pci_write_config_byte(pdev, 0xa, 6);		pci_write_config_byte(pdev, 0x40, tmp);		pdev->class = PCI_CLASS_STORAGE_SATA_AHCI;	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_sb600_sata);/* *	Serverworks CSB5 IDE does not fully support native mode */static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev){	u8 prog;	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);	if (prog & 5) {		prog &= ~5;		pdev->class &= ~5;		pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);		/* PCI layer will sort out resources */	}}DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );/* *	Intel 82801CAM ICH3-M datasheet says IDE modes must be the same */static void __init quirk_ide_samemode(struct pci_dev *pdev){	u8 prog;	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);	if (((prog & 1) && !(prog & 4)) || ((prog & 4) && !(prog & 1))) {		printk(KERN_INFO "PCI: IDE mode mismatch; forcing legacy mode\n");		prog &= ~5;		pdev->class &= ~5;		pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);	}}DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);/* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. */static void __init quirk_eisa_bridge(struct pci_dev *dev){	dev->class = PCI_CLASS_BRIDGE_EISA << 8;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );/* * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge * is not activated. The myth is that Asus said that they do not want the * users to be irritated by just another PCI Device in the Win98 device * manager. (see the file prog/hotplug/README.p4b in the lm_sensors  * package 2.7.0 for details) * * The SMBus PCI Device can be activated by setting a bit in the ICH LPC  * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it  * becomes necessary to do this tweak in two steps -- the chosen trigger * is either the Host bridge (preferred) or on-board VGA controller. * * Note that we used to unhide the SMBus that way on Toshiba laptops * (Satellite A40 and Tecra M2) but then found that the thermal management * was done by SMM code, which could cause unsynchronized concurrent * accesses to the SMBus registers, with potentially bad effects. Thus you * should be very careful when adding new entries: if SMM is accessing the * Intel SMBus, this is a very good reason to leave it hidden. */static int asus_hides_smbus;static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev){	if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {		if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)			switch(dev->subsystem_device) {			case 0x8025: /* P4B-LX */			case 0x8070: /* P4B */			case 0x8088: /* P4B533 */			case 0x1626: /* L3C notebook */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)			switch(dev->subsystem_device) {			case 0x80b1: /* P4GE-V */			case 0x80b2: /* P4PE */			case 0x8093: /* P4B533-V */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB)			switch(dev->subsystem_device) {			case 0x8030: /* P4T533 */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_7205_0)			switch (dev->subsystem_device) {			case 0x8070: /* P4G8X Deluxe */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH)			switch (dev->subsystem_device) {			case 0x80c9: /* PU-DLS */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)			switch (dev->subsystem_device) {			case 0x1751: /* M2N notebook */			case 0x1821: /* M5N notebook */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)			switch (dev->subsystem_device) {			case 0x184b: /* W1N notebook */			case 0x186a: /* M6Ne notebook */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)			switch (dev->subsystem_device) {			case 0x80f2: /* P4P800-X */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)			switch (dev->subsystem_device) {			case 0x1882: /* M6V notebook */			case 0x1977: /* A6VA notebook */				asus_hides_smbus = 1;			}	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {		if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)			switch(dev->subsystem_device) {			case 0x088C: /* HP Compaq nc8000 */			case 0x0890: /* HP Compaq nc6000 */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)			switch (dev->subsystem_device) {			case 0x12bc: /* HP D330L */			case 0x12bd: /* HP D530 */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)			switch (dev->subsystem_device) {			case 0x099c: /* HP Compaq nx6110 */				asus_hides_smbus = 1;			}       } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) {               if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)                       switch(dev->subsystem_device) {                       case 0xC00C: /* Samsung P35 notebook */                               asus_hides_smbus = 1;                       }	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {		if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)			switch(dev->subsystem_device) {			case 0x0058: /* Compaq Evo N620c */				asus_hides_smbus = 1;			}		else if (dev->device == PCI_DEVICE_ID_INTEL_82810_IG3)			switch(dev->subsystem_device) {			case 0xB16C: /* Compaq Deskpro EP 401963-001 (PCA# 010174) */				/* Motherboard doesn't have Host bridge				 * subvendor/subdevice IDs, therefore checking				 * its on-board VGA controller */				asus_hides_smbus = 1;			}	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge );DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );

⌨️ 快捷键说明

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