patch-2.1.115 linux/arch/i386/kernel/bios32.c
Next file: linux/arch/i386/kernel/entry.S
Previous file: linux/arch/i386/defconfig
Back to the patch index
Back to the overall index
- Lines: 84
- Date:
Tue Aug 4 10:54:37 1998
- Orig file:
v2.1.114/linux/arch/i386/kernel/bios32.c
- Orig date:
Mon Aug 3 17:48:26 1998
diff -u --recursive --new-file v2.1.114/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
@@ -1,7 +1,7 @@
/*
* bios32.c - Low-Level PCI Access
*
- * $Id: bios32.c,v 1.43 1998/08/03 15:59:20 mj Exp $
+ * $Id: bios32.c,v 1.44 1998/08/04 14:54:56 mj Exp $
*
* Copyright 1993, 1994 Drew Eckhardt
* Visionary Computing
@@ -65,6 +65,12 @@
*
* Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
* can be accessed from interrupts even on SMP systems. [mj]
+ *
+ * August 1998 : Better support for peer host bridges and more paranoid
+ * checks for direct hardware access. Ugh, this file starts to look as
+ * a large gallery of common hardware bug workarounds (watch the comments)
+ * -- the PCI specs themselves are sane, but most implementors should be
+ * hit hard with \hammer scaled \magstep5. [mj]
*/
#include <linux/config.h>
@@ -331,6 +337,25 @@
pci_conf2_write_config_dword
};
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ */
+__initfunc(int pci_sanity_check(struct pci_access *a))
+{
+ u16 dfn, class;
+
+ for(dfn=0; dfn < 0x100; dfn++)
+ if (!a->read_config_word(0, dfn, PCI_CLASS_DEVICE, &class) &&
+ class == PCI_CLASS_BRIDGE_HOST)
+ return 1;
+ DBG("PCI: Sanity check failed\n");
+ return 0;
+}
+
__initfunc(static struct pci_access *pci_check_direct(void))
{
unsigned int tmp;
@@ -345,7 +370,8 @@
outb (0x01, 0xCFB);
tmp = inl (0xCF8);
outl (0x80000000, 0xCF8);
- if (inl (0xCF8) == 0x80000000) {
+ if (inl (0xCF8) == 0x80000000 &&
+ pci_sanity_check(&pci_direct_conf1)) {
outl (tmp, 0xCF8);
__restore_flags(flags);
printk("PCI: Using configuration type 1\n");
@@ -361,7 +387,8 @@
outb (0x00, 0xCFB);
outb (0x00, 0xCF8);
outb (0x00, 0xCFA);
- if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
+ if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 &&
+ pci_sanity_check(&pci_direct_conf2)) {
__restore_flags(flags);
printk("PCI: Using configuration type 2\n");
return &pci_direct_conf2;
@@ -920,6 +947,7 @@
struct pci_bus *b = &pci_root;
int i;
+#ifdef CONFIG_PCI_DIRECT
/*
* Don't search for peer host bridges if we use config type 2
* since it reads bogus values for non-existent busses and
@@ -927,6 +955,7 @@
*/
if (access_pci == &pci_direct_conf2)
return;
+#endif
do {
int n = b->subordinate+1;
u16 l;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov