diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /drivers/pci/quirks.c | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (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.c | 85 |
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); } } } |