📄 quirks.c
字号:
d->irq = irq;}static void __init quirk_via_irqpic(struct pci_dev *dev){ u8 irq, new_irq = dev->irq & 0xf; pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); if (new_irq != irq) { printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", dev->slot_name, irq, new_irq); udelay(15); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); }}/* * PIIX3 USB: We have to disable USB interrupts that are * hardwired to PIRQD# and may be shared with an * external device. * * Legacy Support Register (LEGSUP): * bit13: USB PIRQ Enable (USBPIRQDEN), * bit4: Trap/SMI On IRQ Enable (USBSMIEN). * * We mask out all r/wc bits, too. */static void __init quirk_piix3_usb(struct pci_dev *dev){ u16 legsup; pci_read_config_word(dev, 0xc0, &legsup); legsup &= 0x50ef; pci_write_config_word(dev, 0xc0, legsup);}/* * 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 __init quirk_vt82c598_id(struct pci_dev *dev){ pci_write_config_byte(dev, 0xfc, 0); pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);}/* * 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 __init 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);}/* * The AMD io apic can hang the box when an apic irq is masked. * We check all revs >= B0 (yet not in the pre production!) as the bug * is currently marked NoFix * * We have multiple reports of hangs with this chipset that went away with * noapic specified. For the moment we assume its the errata. We may be wrong * of course. However the advice is demonstrably good even if so.. */ static void __init quirk_amd_ioapic(struct pci_dev *dev){ u8 rev; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); if(rev >= 0x02) { printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n"); printk(KERN_WARNING " : booting with the \"noapic\" option.\n"); }}/* * 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 __init 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); }}#ifdef CONFIG_X86_IO_APIC#define AMD8131_revA0 0x01#define AMD8131_revB0 0x11#define AMD8131_MISC 0x40#define AMD8131_NIOAMODE_BIT 0static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; if (nr_ioapics == 0) return; pci_read_config_byte(dev, PCI_REVISION_ID, &revid); if (revid == AMD8131_revA0 || revid == AMD8131_revB0) { printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); pci_read_config_byte( dev, AMD8131_MISC, &tmp); tmp &= ~(1 << AMD8131_NIOAMODE_BIT); pci_write_config_byte( dev, AMD8131_MISC, tmp); }} #endif/* * 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 __init quirk_dunord ( struct pci_dev * dev ){ struct resource * r = & dev -> resource [ 1 ]; r -> start = 0; r -> end = 0xffffff;}static void __init quirk_transparent_bridge(struct pci_dev *dev){ dev->transparent = 1;}/* * 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 __init quirk_mediagx_master(struct pci_dev *dev){ u8 reg; pci_read_config_byte(dev, 0x41, ®); 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); }}/* * As per PCI spec, ignore base address registers 0-3 of the IDE controllers * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and * secondary channels respectively). If the device reports Compatible mode * but does use BAR0-3 for address decoding, we assume that firmware has * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374). * Exceptions (if they exist) must be handled in chip/architecture specific * fixups. * * Note: for non x86 people. You may need an arch specific quirk to handle * moving IDE devices to native mode as well. Some plug in card devices power * up in compatible mode and assume the BIOS will adjust them. * * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as * we do now ? We don't want is pci_enable_device to come along * and assign new resources. Both approaches work for that. */ static void __devinit quirk_ide_bases(struct pci_dev *dev){ struct resource *res; int first_bar = 2, last_bar = 0; if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) return; res = &dev->resource[0]; /* primary channel: ProgIf bit 0, BAR0, BAR1 */ if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { res[0].start = res[0].end = res[0].flags = 0; res[1].start = res[1].end = res[1].flags = 0; first_bar = 0; last_bar = 1; } /* secondary channel: ProgIf bit 2, BAR2, BAR3 */ if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { res[2].start = res[2].end = res[2].flags = 0; res[3].start = res[3].end = res[3].flags = 0; last_bar = 3; } if (!last_bar) return; printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", first_bar, last_bar, dev->slot_name);}/* * 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 __init quirk_disable_pxb(struct pci_dev *pdev){ u16 config; u8 rev; pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); if(rev != 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"); }}/* * VIA northbridges care about PCI_INTERRUPT_LINE */ int interrupt_line_quirk;static void __init quirk_via_bridge(struct pci_dev *pdev){ if(pdev->devfn == 0) interrupt_line_quirk = 1;} /* * Serverworks CSB5 IDE does not fully support native mode */static void __init 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); /* need to re-assign BARs for compat mode */ quirk_ide_bases(pdev); }}/* * The main table of quirks. */static struct pci_fixup pci_fixups[] __initdata = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, /* * Its not totally clear which chipsets are the problematic ones * We know 82C586 and 82C596 variants are affected. */ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge }, { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy },#ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic },#endif { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, quirk_ati_exploding_mce }, /* * 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. */ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide },#ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic }, #endif { 0 }};static void pci_do_fixups(struct pci_dev *dev, int pass, struct pci_fixup *f){ while (f->pass) { if (f->pass == pass && (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {#ifdef DEBUG printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);#endif f->hook(dev); } f++; }}void pci_fixup_device(int pass, struct pci_dev *dev){ pci_do_fixups(dev, pass, pcibios_fixups); pci_do_fixups(dev, pass, pci_fixups);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -