summaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /drivers/pci/quirks.c
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff)
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash. o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index eb51794af..552756e5f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1,5 +1,5 @@
/*
- * $Id: quirks.c,v 1.2 1997/09/20 21:43:34 davem Exp $
+ * $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $
*
* PCI Chipset-Specific Quirks
*
@@ -11,15 +11,17 @@
* the bridge optimization, but others might appear later.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/bios32.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
@@ -104,35 +106,87 @@ __initfunc(static void quirk_bridge(struct pci_dev *dev, int pos))
}
}
+#endif
+
+
+/* Deal with broken BIOS'es that neglect to enable passive release,
+ which can cause problems in combination with the 82441FX/PPro MTRRs */
+__initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
+{
+ struct pci_dev *piix3;
+ unsigned char dlc;
+
+ /* We have to make sure a particular bit is set in the PIIX3
+ ISA bridge, so we have to go out and find it. */
+ for (piix3 = pci_devices; ; piix3 = piix3->next) {
+ if (!piix3)
+ return;
+
+ if (piix3->vendor == PCI_VENDOR_ID_INTEL
+ && piix3->device == PCI_DEVICE_ID_INTEL_82371SB_0)
+ break;
+ }
+
+ pcibios_read_config_byte(piix3->bus->number, piix3->devfn, 0x82, &dlc);
+
+ if (!(dlc & 1<<1)) {
+ printk("PIIX3: Enabling Passive Release\n");
+ dlc |= 1<<1;
+ pcibios_write_config_byte(piix3->bus->number, piix3->devfn,
+ 0x82, dlc);
+ }
+}
+
+
+typedef void (*quirk_handler)(struct pci_dev *, int);
+
/*
- * Table of quirk handler functions
+ * Mpping from quirk handler functions to names.
*/
-#define Q_BRIDGE 0
-
-struct quirk_type {
- void (*handler)(struct pci_dev *, int);
+struct quirk_name {
+ quirk_handler handler;
char *name;
};
-static struct quirk_type quirk_types[] __initdata = {
+static struct quirk_name quirk_names[] __initdata = {
+#ifdef CONFIG_PCI_OPTIMIZE
{ quirk_bridge, "Bridge optimization" },
+#endif
+ { quirk_passive_release, "Passive release enable" },
};
+
+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;
- unsigned short quirk, arg;
+ quirk_handler handler;
+ unsigned short arg;
};
static struct quirk_info quirk_list[] __initdata = {
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_BRD, Q_BRIDGE, 0x00 },
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8891A, Q_BRIDGE, 0x01 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, Q_BRIDGE, 0x00 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82434, Q_BRIDGE, 0x00 }
+#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 },
+#endif
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release, 0x00 },
};
__initfunc(void pci_quirks_init(void))
@@ -147,11 +201,10 @@ __initfunc(void pci_quirks_init(void))
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) {
- struct quirk_type *t = quirk_types + q->quirk;
printk("PCI: %02x:%02x [%04x/%04x]: %s (%02x)\n",
d->bus->number, d->devfn, d->vendor, d->device,
- t->name, q->arg);
- t->handler(d, q->arg);
+ get_quirk_name(q->handler), q->arg);
+ q->handler(d, q->arg);
}
}
}