⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fixup.c

📁 底层驱动开发
💻 C
字号:
/* * Exceptions for specific devices. Usually work-arounds for fatal design flaws. */#include <linux/pci.h>#include <linux/init.h>#include "pci.h"static void __devinit pci_fixup_i450nx(struct pci_dev *d){	/*	 * i450NX -- Find and scan all secondary buses on all PXB's.	 */	int pxb, reg;	u8 busno, suba, subb;	printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));	reg = 0xd0;	for(pxb=0; pxb<2; pxb++) {		pci_read_config_byte(d, reg++, &busno);		pci_read_config_byte(d, reg++, &suba);		pci_read_config_byte(d, reg++, &subb);		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);		if (busno)			pci_scan_bus(busno, &pci_root_ops, NULL);	/* Bus A */		if (suba < subb)			pci_scan_bus(suba+1, &pci_root_ops, NULL);	/* Bus B */	}	pcibios_last_bus = -1;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);static void __devinit pci_fixup_i450gx(struct pci_dev *d){	/*	 * i450GX and i450KX -- Find and scan all secondary buses.	 * (called separately for each PCI bridge found)	 */	u8 busno;	pci_read_config_byte(d, 0x4a, &busno);	printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);	pci_scan_bus(busno, &pci_root_ops, NULL);	pcibios_last_bus = -1;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);static void __devinit  pci_fixup_umc_ide(struct pci_dev *d){	/*	 * UM8886BF IDE controller sets region type bits incorrectly,	 * therefore they look like memory despite of them being I/O.	 */	int i;	printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));	for(i=0; i<4; i++)		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d){	/*	 * NCR 53C810 returns class code 0 (at least on some systems).	 * Fix class to be PCI_CLASS_STORAGE_SCSI	 */	if (!d->class) {		printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));		d->class = PCI_CLASS_STORAGE_SCSI << 8;	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);static void __devinit pci_fixup_ide_bases(struct pci_dev *d){	int i;	/*	 * PCI IDE controllers use non-standard I/O port decoding, respect it.	 */	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)		return;	DBG("PCI: IDE base address fixup for %s\n", pci_name(d));	for(i=0; i<4; i++) {		struct resource *r = &d->resource[i];		if ((r->start & ~0x80) == 0x374) {			r->start |= 2;			r->end = r->start;		}	}}DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);static void __devinit  pci_fixup_ide_trash(struct pci_dev *d){	int i;	/*	 * Runs the fixup only for the first IDE controller	 * (Shai Fultheim - shai@ftcon.com)	 */	static int called = 0;	if (called)		return;	called = 1;	/*	 * There exist PCI IDE controllers which have utter garbage	 * in first four base registers. Ignore that.	 */	DBG("PCI: IDE base address trash cleared for %s\n", pci_name(d));	for(i=0; i<4; i++)		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash);static void __devinit  pci_fixup_latency(struct pci_dev *d){	/*	 *  SiS 5597 and 5598 chipsets require latency timer set to	 *  at most 32 to avoid lockups.	 */	DBG("PCI: Setting max latency to 32\n");	pcibios_max_latency = 32;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d){	/*	 * PIIX4 ACPI device: hardwired IRQ9	 */	d->irq = 9;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi);/* * Addresses issues with problems in the memory write queue timer in * certain VIA Northbridges.  This bugfix is per VIA's specifications, * except for the KL133/KM133: clearing bit 5 on those Northbridges seems * to trigger a bug in its integrated ProSavage video card, which * causes screen corruption.  We only clear bits 6 and 7 for that chipset, * until VIA can provide us with definitive information on why screen * corruption occurs, and what exactly those bits do. * * VIA 8363,8622,8361 Northbridges: *  - bits  5, 6, 7 at offset 0x55 need to be turned off * VIA 8367 (KT266x) Northbridges: *  - bits  5, 6, 7 at offset 0x95 need to be turned off * VIA 8363 rev 0x81/0x84 (KL133/KM133) Northbridges: *  - bits     6, 7 at offset 0x55 need to be turned off */#define VIA_8363_KL133_REVISION_ID 0x81#define VIA_8363_KM133_REVISION_ID 0x84static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d){	u8 v;	u8 revision;	int where = 0x55;	int mask = 0x1f; /* clear bits 5, 6, 7 by default */	pci_read_config_byte(d, PCI_REVISION_ID, &revision);	if (d->device == PCI_DEVICE_ID_VIA_8367_0) {		/* fix pci bus latency issues resulted by NB bios error		   it appears on bug free^Wreduced kt266x's bios forces		   NB latency to zero */		pci_write_config_byte(d, PCI_LATENCY_TIMER, 0);		where = 0x95; /* the memory write queue timer register is 				different for the KT266x's: 0x95 not 0x55 */	} else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&			(revision == VIA_8363_KL133_REVISION_ID || 			revision == VIA_8363_KM133_REVISION_ID)) {			mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5					causes screen corruption on the KL133/KM133 */	}	pci_read_config_byte(d, where, &v);	if (v & ~mask) {		printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \			d->device, revision, where, v, mask, v & mask);		v &= mask;		pci_write_config_byte(d, where, v);	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);/* * For some reasons Intel decided that certain parts of their * 815, 845 and some other chipsets must look like PCI-to-PCI bridges * while they are obviously not. The 82801 family (AA, AB, BAM/CAM, * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according * to Intel terminology. These devices do forward all addresses from * system to PCI bus no matter what are their window settings, so they are * "transparent" (or subtractive decoding) from programmers point of view. */static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev){	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&	    (dev->device & 0xff00) == 0x2400)		dev->transparent = 1;}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);/* * Fixup for C1 Halt Disconnect problem on nForce2 systems. * * From information provided by "Allen Martin" <AMartin@nvidia.com>: * * A hang is caused when the CPU generates a very fast CONNECT/HALT cycle * sequence.  Workaround is to set the SYSTEM_IDLE_TIMEOUT to 80 ns. * This allows the state-machine and timer to return to a proper state within * 80 ns of the CONNECT and probe appearing together.  Since the CPU will not * issue another HALT within 80 ns of the initial HALT, the failure condition * is avoided. */static void __init pci_fixup_nforce2(struct pci_dev *dev){	u32 val;	/*	 * Chip  Old value   New value	 * C17   0x1F0FFF01  0x1F01FF01	 * C18D  0x9F0FFF01  0x9F01FF01	 *	 * Northbridge chip version may be determined by	 * reading the PCI revision ID (0xC1 or greater is C18D).	 */	pci_read_config_dword(dev, 0x6c, &val);	/*	 * Apply fixup if needed, but don't touch disconnect state	 */	if ((val & 0x00FF0000) != 0x00010000) {		printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");		pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);/* Max PCI Express root ports */#define MAX_PCIEROOT	6static int quirk_aspm_offset[MAX_PCIEROOT << 3];#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value){	return raw_pci_ops->read(0, bus->number, devfn, where, size, value);}/* * Replace the original pci bus ops for write with a new one that will filter * the request to insure ASPM cannot be enabled. */static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value){	u8 offset;	offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];	if ((offset) && (where == offset))		value = value & 0xfffffffc;		return raw_pci_ops->write(0, bus->number, devfn, where, size, value);}static struct pci_ops quirk_pcie_aspm_ops = {	.read = quirk_pcie_aspm_read,	.write = quirk_pcie_aspm_write,};/* * Prevents PCI Express ASPM (Active State Power Management) being enabled. * * Save the register offset, where the ASPM control bits are located, * for each PCI Express device that is in the device list of * the root port in an array for fast indexing. Replace the bus ops * with the modified one. */static void pcie_rootport_aspm_quirk(struct pci_dev *pdev){	int cap_base, i;	struct pci_bus  *pbus;	struct pci_dev *dev;	if ((pbus = pdev->subordinate) == NULL)		return;	/*	 * Check if the DID of pdev matches one of the six root ports. This	 * check is needed in the case this function is called directly by the	 * hot-plug driver.	 */	if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) ||	    (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1))		return;	if (list_empty(&pbus->devices)) {		/*		 * If no device is attached to the root port at power-up or		 * after hot-remove, the pbus->devices is empty and this code		 * will set the offsets to zero and the bus ops to parent's bus		 * ops, which is unmodified.	 	 */		for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)			quirk_aspm_offset[i] = 0;		pbus->ops = pbus->parent->ops;	} else {		/*		 * If devices are attached to the root port at power-up or		 * after hot-add, the code loops through the device list of		 * each root port to save the register offsets and replace the		 * bus ops.		 */		list_for_each_entry(dev, &pbus->devices, bus_list) {			/* There are 0 to 8 devices attached to this bus */			cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);			quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10;		}		pbus->ops = &quirk_pcie_aspm_ops;	}}DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA,	pcie_rootport_aspm_quirk );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA1,	pcie_rootport_aspm_quirk );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PB,	pcie_rootport_aspm_quirk );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PB1,	pcie_rootport_aspm_quirk );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC,	pcie_rootport_aspm_quirk );DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC1,	pcie_rootport_aspm_quirk );/* * Fixup to mark boot BIOS video selected by BIOS before it changes * * From information provided by "Jon Smirl" <jonsmirl@gmail.com> * * The standard boot ROM sequence for an x86 machine uses the BIOS * to select an initial video card for boot display. This boot video  * card will have it's BIOS copied to C0000 in system RAM.  * IORESOURCE_ROM_SHADOW is used to associate the boot video * card with this copy. On laptops this copy has to be used since * the main ROM may be compressed or combined with another image. * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW * is marked here since the boot video device will be the only enabled * video device at this point. */static void __devinit pci_fixup_video(struct pci_dev *pdev){	struct pci_dev *bridge;	struct pci_bus *bus;	u16 config;	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)		return;	/* Is VGA routed to us? */	bus = pdev->bus;	while (bus) {		bridge = bus->self;		if (bridge) {			pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,						&config);			if (!(config & PCI_BRIDGE_CTL_VGA))				return;		}		bus = bus->parent;	}	pci_read_config_word(pdev, PCI_COMMAND, &config);	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));	}}DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);

⌨️ 快捷键说明

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