Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/sparc64/sparc64 OF_mapintr: swizzle interrupt for P...



details:   https://anonhg.NetBSD.org/src/rev/46f282822d5f
branches:  trunk
changeset: 551549:46f282822d5f
user:      petrov <petrov%NetBSD.org@localhost>
date:      Mon Sep 08 03:33:52 2003 +0000

description:
OF_mapintr: swizzle interrupt for PCI bridges,
don't process OBP interrupts, return error if interrupt is not mapped.

diffstat:

 sys/arch/sparc64/sparc64/ofw_machdep.c |  56 ++++++++++++++++++++++++++++++---
 1 files changed, 51 insertions(+), 5 deletions(-)

diffs (123 lines):

diff -r b10773d105e7 -r 46f282822d5f sys/arch/sparc64/sparc64/ofw_machdep.c
--- a/sys/arch/sparc64/sparc64/ofw_machdep.c    Mon Sep 08 03:33:31 2003 +0000
+++ b/sys/arch/sparc64/sparc64/ofw_machdep.c    Mon Sep 08 03:33:52 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ofw_machdep.c,v 1.17 2003/07/15 03:36:09 lukem Exp $   */
+/*     $NetBSD: ofw_machdep.c,v 1.18 2003/09/08 03:33:52 petrov Exp $  */
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.17 2003/07/15 03:36:09 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.18 2003/09/08 03:33:52 petrov Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -48,6 +48,8 @@
 
 #include <machine/openfirm.h>
 
+#include <dev/ofw/ofw_pci.h>
+
 #if defined(FFS) && defined(CD9660)
 #include <ufs/ffs/fs.h>
 #endif
@@ -664,6 +666,27 @@
 }
 
 /*
+ * Find top pci bus host controller for a node.
+ */
+static int
+find_pci_host_node(int node)
+{
+       char dev_type[16];
+       int pch = 0;
+       int len;
+
+       for (; node; node = OF_parent(node)) {
+               len = OF_getprop(node, "device_type",
+                                &dev_type, sizeof(dev_type));
+               if (len <= 0)
+                       continue;
+               if (!strcmp(dev_type, "pci"))
+                       pch = node;
+       }
+       return pch;
+}
+
+/*
  * Follow the OFW algorithm and return an interrupt specifier.
  *
  * Pass in the interrupt specifier you want mapped and the node
@@ -679,6 +702,13 @@
        int interrupt_map[100];
        int interrupt_map_mask[10];
        int reg[10];
+       char dev_type[32];
+       int phc_node;
+       int rc = -1;
+
+       /* Don't need to map OBP interrupt, it's already */
+       if (*interrupt & 0x20)
+               return validlen;
 
        /*
         * If there is no interrupt map in the bus node, we 
@@ -699,20 +729,36 @@
                return (-1);
        }
 
+       phc_node = find_pci_host_node(node);
+
        for (; node; node = OF_parent(node)) {
 #ifdef DEBUG
                char name[40];
 
                if (ofmapintrdebug) {
                        OF_getprop(node, "name", &name, sizeof(name));
-                       printf("Node %s\n", name);
+                       printf("Node %s (%x), host %x\n", name,
+                              node, phc_node);
                }
 #endif
 
                if ((interrupt_map_len = OF_getprop(node,
                        "interrupt-map", &interrupt_map,
                        sizeof(interrupt_map))) <= 0) {
+
+                       /* Swizzle interrupt if this is a PCI bridge. */
+                       if (((len = OF_getprop(node, "device_type", &dev_type,
+                                             sizeof(dev_type))) > 0) &&
+                           !strcmp(dev_type, "pci") &&
+                           (node != phc_node)) {
+                               *interrupt = ((*interrupt +
+                                   OFW_PCI_PHYS_HI_DEVICE(reg[0]) - 1) & 3) + 1;
+                               DPRINTF(("OF_mapintr: interrupt %x, reg[0] %x\n",
+                                        *interrupt, reg[0]));
+                       }
+
                        /* Get reg for next level compare. */
+                       reg[0] = 0;
                        OF_getprop(node, "reg", &reg, sizeof(reg));
                        continue;
                }
@@ -801,7 +847,7 @@
 #endif
                                for (i=0; i<pintr_cells; i++)
                                        interrupt[i] = parent[i];
-                               validlen = pintr_cells;
+                               rc = validlen = pintr_cells;
                                break;
                        }
                        /* Move on to the next interrupt_map entry. */
@@ -824,5 +870,5 @@
                DPRINTF(("reg len %d\n", len));
 
        } 
-       return (validlen);
+       return (rc);
 }



Home | Main Index | Thread Index | Old Index