patch-2.3.15 linux/drivers/pci/quirks.c

Next file: linux/drivers/pnp/isapnp.c
Previous file: linux/drivers/pci/proc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.14/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
@@ -1,114 +1,27 @@
 /*
  * $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $
  *
- * PCI Chipset-Specific Quirks
+ *  This file contains work-arounds for many known PCI hardware
+ *  bugs.  Devices present only on certain architectures (host
+ *  bridges et cetera) should be handled in arch-specific code.
  *
- * Extracted from pci.c and rewritten by Martin Mares
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  *
- * This is the right place for all special fixups for on-board
- * devices not depending on system architecture -- for example
- * bus bridges.
+ *  The bridge optimization stuff has been removed. If you really
+ *  have a silly BIOS which is unable to set your host bridge right,
+ *  use the PowerTweak utility (see http://linux.powertweak.com/).
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/string.h>
 #include <linux/init.h>
 
 #undef DEBUG
 
-#ifdef CONFIG_PCI_OPTIMIZE
-
-/*
- *	The PCI Bridge Optimization -- Some BIOS'es are too lazy
- *	and are unable to turn on several features which can burst
- *	system performance.
- */
-
-/*
- * An item of this structure has the following meaning:
- * for each optimization, the register address, the mask
- * and value to write to turn it on.
- */
-struct optimization_type {
-	const char	*type;
-	const char	*off;
-	const char	*on;
-} bridge_optimization[] __initdata = {
-	{"Cache L2",			"write through",	"write back"},
-	{"CPU-PCI posted write",	"off",			"on"},
-	{"CPU-Memory posted write",	"off",			"on"},
-	{"PCI-Memory posted write",	"off",			"on"},
-	{"PCI burst",			"off",			"on"}
-};
-
-#define NUM_OPTIMIZATIONS \
-	(sizeof(bridge_optimization) / sizeof(bridge_optimization[0]))
-
-struct bridge_mapping_type {
-	unsigned char	addr;	/* config space address */
-	unsigned char	mask;
-	unsigned char	value;
-} bridge_mapping[] = {
-	/*
-	 * Intel Neptune/Mercury/Saturn:
-	 *	If the internal cache is write back,
-	 *	the L2 cache must be write through!
-	 *	I've to check out how to control that
-	 *	for the moment, we won't touch the cache
-	 */
-	{0x0	,0x02	,0x02	},
-	{0x53	,0x02	,0x02	},
-	{0x53	,0x01	,0x01	},
-	{0x54	,0x01	,0x01	},
-	{0x54	,0x02	,0x02	},
-
-	/*
-	 * UMC 8891A Pentium chipset:
-	 *	Why did you think UMC was cheaper ??
-	 */
-	{0x50	,0x10	,0x00	},
-	{0x51	,0x40	,0x40	},
-	{0x0	,0x0	,0x0	},
-	{0x0	,0x0	,0x0	},
-	{0x0	,0x0	,0x0	},
-};
-
-static void __init quirk_bridge(struct pci_dev *dev, int pos)
-{
-	struct bridge_mapping_type *bmap;
-	unsigned char val;
-	int i;
-
-	pos *= NUM_OPTIMIZATIONS;
-	for (i = 0; i < NUM_OPTIMIZATIONS; i++) {
-		printk("    %s: ", bridge_optimization[i].type);
-		bmap = &bridge_mapping[pos + i];
-		if (!bmap->addr) {
-			printk("Not supported.\n");
-		} else {
-			pci_read_config_byte(dev, bmap->addr, &val);
-			if ((val & bmap->mask) == bmap->value)
-				printk("%s.\n", bridge_optimization[i].on);
-			else {
-				printk("%s", bridge_optimization[i].off);
-				pci_write_config_byte(dev,
-						      bmap->addr,
-						      (val & (0xff - bmap->mask)) + bmap->value);
-				printk(" -> %s.\n", bridge_optimization[i].on);
-			}
-		}
-	}
-}
-
-#endif
-
-
 /* Deal with broken BIOS'es that neglect to enable passive release,
    which can cause problems in combination with the 82441FX/PPro MTRRs */
-static void __init quirk_passive_release(struct pci_dev *dev, int arg)
+static void __init quirk_passive_release(struct pci_dev *dev)
 {
 	struct pci_dev *d = NULL;
 	unsigned char dlc;
@@ -118,7 +31,7 @@
 	while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
 		pci_read_config_byte(d, 0x82, &dlc);
 		if (!(dlc & 1<<1)) {
-			printk("PIIX3: Enabling Passive Release\n");
+			printk("PCI: PIIX3: Enabling Passive Release on %s\n", d->name);
 			dlc |= 1<<1;
 			pci_write_config_byte(d, 0x82, dlc);
 		}
@@ -135,92 +48,48 @@
 
 int isa_dma_bridge_buggy = 0;		/* Exported */
     
-static void __init quirk_isa_dma_hangs(struct pci_dev *dev, int arg)
+static void __init quirk_isa_dma_hangs(struct pci_dev *dev)
 {
-	if(!isa_dma_bridge_buggy)
-	{
+	if (!isa_dma_bridge_buggy) {
 		isa_dma_bridge_buggy=1;
 		printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
 	}
 }
 
 
-typedef void (*quirk_handler)(struct pci_dev *, int);
-
 /*
- * Mapping from quirk handler functions to names.
+ *  The main table of quirks.
  */
 
-struct quirk_name {
-	quirk_handler handler;
-	char *name;
-};
-
-static struct quirk_name quirk_names[] __initdata = {
-#ifdef CONFIG_PCI_OPTIMIZE
-	{ quirk_bridge,		"Bridge optimization" },
-#endif
-	{ quirk_passive_release,"Passive release enable" },
-	{ quirk_isa_dma_hangs,	"Work around ISA DMA hangs" },
-};
-
-
-static inline char *get_quirk_name(quirk_handler handler)
-{
-	int i;
-
-	for (i = 0; i < sizeof(quirk_names)/sizeof(quirk_names[0]); i++)
-		if (handler == quirk_names[i].handler)
-			return quirk_names[i].name;
-
-	return NULL;
-}
-  
-
-/*
- * Mapping from PCI vendor/device ID pairs to quirk function types and arguments
- */
-
-struct quirk_info {
-	unsigned short vendor, device;
-	quirk_handler handler;
-	unsigned short arg;
-};
-
-static struct quirk_info quirk_list[] __initdata = {
-#ifdef CONFIG_PCI_OPTIMIZE
-	{ PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_BRD,		quirk_bridge,	0x00 },
-	{ PCI_VENDOR_ID_UMC,	PCI_DEVICE_ID_UMC_UM8891A,	quirk_bridge,	0x01 },
-	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82424,	quirk_bridge,	0x00 },
-	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82434,	quirk_bridge,	0x00 },
-	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82430,	quirk_bridge,	0x00 },
-#endif
-	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release,	0x00 },
+static struct pci_fixup pci_fixups[] __initdata = {
+	{ 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
 	 * This is the 82C586 variants. At the moment the 596 is an unknown
-	 * quantity 
+	 * quantity.
 	 */
-	{ PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs,	0x00 },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
+	{ 0 }
 };
 
-void __init pci_quirks_init(void)
-{
-	struct pci_dev *d;
-	int i;
 
+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("PCI: pci_quirks_init\n");
+			printk("PCI: Calling quirk %p for %s\n", f->hook, dev->name);
 #endif
-	for(d=pci_devices; d; d=d->next) {
-		for(i=0; i<sizeof(quirk_list)/sizeof(quirk_list[0]); i++) {
-			struct quirk_info *q = quirk_list + i;
-			if (q->vendor == d->vendor && q->device == d->device) {
-				printk("PCI: %02x:%02x [%04x/%04x]: %s (%02x)\n",
-				       d->bus->number, d->devfn, d->vendor, d->device,
-				       get_quirk_name(q->handler), q->arg);
-				q->handler(d, q->arg);
-			}
+			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);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)