Subject: Re: wi via cbb in Netra 105, "spurious vector"
To: Michael K. Sanders <msanders@confusion.net>
From: Andrey Petrov <petrov@netbsd.org>
List: port-sparc64
Date: 08/26/2003 21:43:25
On Tue, Aug 26, 2003 at 01:40:40PM +0200, Martin Husemann wrote:
> On Mon, Aug 25, 2003 at 08:03:04PM -0700, Michael K. Sanders wrote:
> > cbb0 at pci3 dev 15 function 0: Texas Instruments PCI1410 PCI-CardBus Bridge (rev. 0x01)
> > cbb0: interrupting at ivec 0
> 
> There is an interrupt routing bug in our code for devices behind PCI
> bridges w/o OF support - Matt Thomas and Andrey Petrov analyzed this recently
> and Andrey was going to commit a fix (but apparently didn't came around to
> this yet).
> 

It still needs some work, but meanwhile if patch could be tried that
would be great.

	Andrey

Index: ofw_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/ofw_machdep.c,v
retrieving revision 1.17
diff -u -p -r1.17 ofw_machdep.c
--- ofw_machdep.c	2003/07/15 03:36:09	1.17
+++ ofw_machdep.c	2003/08/22 00:27:56
@@ -48,6 +48,8 @@ __KERNEL_RCSID(0, "$NetBSD: ofw_machdep.
 
 #include <machine/openfirm.h>
 
+#include <dev/ofw/ofw_pci.h>
+
 #if defined(FFS) && defined(CD9660)
 #include <ufs/ffs/fs.h>
 #endif
@@ -679,6 +681,8 @@ OF_mapintr(int node, int *interrupt, int
 	int interrupt_map[100];
 	int interrupt_map_mask[10];
 	int reg[10];
+	char dev_type[32];
+	int blen, bus_range[2];
 
 	/*
 	 * If there is no interrupt map in the bus node, we 
@@ -705,14 +709,29 @@ OF_mapintr(int node, int *interrupt, int
 
 		if (ofmapintrdebug) {
 			OF_getprop(node, "name", &name, sizeof(name));
-			printf("Node %s\n", name);
+			printf("Node %s (%x)\n", name, node);
 		}
 #endif
 
 		if ((interrupt_map_len = OF_getprop(node,
 			"interrupt-map", &interrupt_map,
 			sizeof(interrupt_map))) <= 0) {
+
+			/* Swizzle interrupt if this is PCI bridge. */
+			if (((len = OF_getprop(node, "device_type", &dev_type,
+					      sizeof(dev_type))) > 0) &&
+			    !strcmp(dev_type, "pci") &&
+			    ((blen = OF_getprop(node, "bus-range", &bus_range,
+					     sizeof(bus_range))) > 0) &&
+			    (bus_range[0] > 0)) {
+				*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;
 		}