Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/i386/pci Search the entire device-space of bus 0 if...



details:   https://anonhg.NetBSD.org/src/rev/a37e84d9a123
branches:  trunk
changeset: 509976:a37e84d9a123
user:      kanaoka <kanaoka%NetBSD.org@localhost>
date:      Wed May 16 08:10:36 2001 +0000

description:
Search the entire device-space of bus 0 if the router device
address is set to 000:00:0, and the compatible router entry
is undefined.

  Patch PR port-i386/12880 by Dave Sainty <dave%dtsp.co.nz@localhost>.

diffstat:

 sys/arch/i386/pci/pci_intr_fixup.c |  60 ++++++++++++++++++++++++++++++++++---
 1 files changed, 55 insertions(+), 5 deletions(-)

diffs (90 lines):

diff -r fa35a5075934 -r a37e84d9a123 sys/arch/i386/pci/pci_intr_fixup.c
--- a/sys/arch/i386/pci/pci_intr_fixup.c        Wed May 16 07:53:54 2001 +0000
+++ b/sys/arch/i386/pci/pci_intr_fixup.c        Wed May 16 08:10:36 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pci_intr_fixup.c,v 1.12 2001/04/19 17:32:40 uch Exp $  */
+/*     $NetBSD: pci_intr_fixup.c,v 1.13 2001/05/16 08:10:36 kanaoka Exp $      */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -716,8 +716,21 @@
         * specified by the PIR Table, and use the compat ID,
         * if present.  Otherwise, we have to look for the router
         * ourselves (the PCI-ISA bridge).
+        *
+        * A number of buggy BIOS implementations leave the router
+        * entry as 000:00:0, which is typically not the correct
+        * device/function.  If the router device address is set to
+        * this value, and the compatible router entry is undefined
+        * (zero is the correct value to indicate undefined), then we
+        * work on the basis it is most likely an error, and search
+        * the entire device-space of bus 0 (but obviously starting
+        * with 000:00:0, in case that really is the right one).
         */
-       if (pcibios_pir_header.signature != 0) {
+       if (pcibios_pir_header.signature != 0 &&
+           (pcibios_pir_header.router_bus != 0 ||
+            PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc) != 0 ||
+            PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc) != 0 ||
+            pcibios_pir_header.compat_router != 0)) {
                icutag = pci_make_tag(pc, pcibios_pir_header.router_bus,
                    PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc),
                    PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc));
@@ -740,6 +753,10 @@
                 * router.
                 */
                for (device = 0; device < maxdevs; device++) {
+                       const struct pci_quirkdata *qd;
+                       int function, nfuncs;
+                       pcireg_t bhlcr;
+
                        icutag = pci_make_tag(pc, 0, device, 0);
                        icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
 
@@ -750,10 +767,43 @@
                        if (PCI_VENDOR(icuid) == 0)
                                continue;
 
-                       piit = pciintr_icu_lookup(icuid);
-                       if (piit != NULL)
-                               break;
+                       qd = pci_lookup_quirkdata(PCI_VENDOR(icuid),
+                           PCI_PRODUCT(icuid));
+
+                       bhlcr = pci_conf_read(pc, icutag, PCI_BHLC_REG);
+                       if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
+                           (qd != NULL &&
+                            (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+                               nfuncs = 8;
+                       else
+                               nfuncs = 1;
+
+                       for (function = 0; function < nfuncs; function++) {
+                               icutag = pci_make_tag(pc, 0, device, function);
+                               icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
+
+                               /* Invalid vendor ID value? */
+                               if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
+                                       continue;
+                               /* Not invalid, but we've done this ~forever */
+                               if (PCI_VENDOR(icuid) == 0)
+                                       continue;
+
+                               piit = pciintr_icu_lookup(icuid);
+                               if (piit != NULL)
+                                       goto found;
+                       }
                }
+
+               /*
+                * Invalidate the ICU ID.  If we failed to find the
+                * interrupt router (piit == NULL) we don't want to
+                * display a spurious device address below containing
+                * the product information of the last device we
+                * looked at.
+                */
+               icuid = 0;
+found:
        }
 
        if (piit == NULL) {



Home | Main Index | Thread Index | Old Index