OF_mapintr() problems

"Michael L. Hitch" <[email protected]>
Newsgroups gmane.os.netbsd.ports.sparc64
Message-ID <[email protected]>
Having just acquired a couple of Ultra 45 machines, I tried booting a 
NetBSD installation CD, and ran into the aceride timeout issued mentioned 
here before.  I then tried to set up netbooting, and after some 
trial-and-errors, I was able to netboot the INSTALL kernel.  At that point 
I ran into the issues with bge(4), also mentioned here (and I think 
current-users).  I was able to use the INSTALL kernel to create a bootable 
disk partition with the intall tools on ig, but even booting directly from 
the disk, I could not get either bge0 or bge1 to work.

I enabled DEBUG and started getting information about the interrupt 
mapping.  One thing I noticed is that the interrupts for bge0 and bge1 
were not getting swizzled like I expected.  When looking at OF_mapintr() 
and the various .properties from OpenBoot, I noticed that the Ultra45 had 
the device-type "pciex" instead of the "pci" that NetBSD was looking for.
My first attempt at just changing "pci" to "pciex" changed the ivec 
values, but only resulting in mpt(4) not working anymore.

That led me to look at the OpenBSD OF_mapintr(), and I found a number of 
changes - including handling the device-type "pciex".  Making those change 
to me kernel got me to the point of no more aceride or ehci timeouts, and 
I could configure the bge devices.  I could see packets sent out, and the 
input counters were increasing, but didn't seem to be processing any input 
packets.

I burned a CD with my build, and was able to boot it, install NetBSD, and 
both bge interfaces are now working.  Also, I was able to insert a USB 
flash drive and read from it.

The only thing now is I'm not sure if the changes I have might break 
something else that is working.

If anyone wants to try out these changes, here they are:


Index: sys/arch/sparc64/sparc64/ofw_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/ofw_machdep.c,v
retrieving revision 1.38
diff -u -p -r1.38 ofw_machdep.c
--- sys/arch/sparc64/sparc64/ofw_machdep.c	17 Jul 2011 20:54:48 -0000	1.38
+++ sys/arch/sparc64/sparc64/ofw_machdep.c	8 Jul 2013 15:07:18 -0000
@@ -608,7 +608,7 @@ prom_has_stop_other(void)
  #endif

  #ifdef DEBUG
-int ofmapintrdebug = 0;
+int ofmapintrdebug = 1;
  #define	DPRINTF(x)	if (ofmapintrdebug) printf x
  #else
  #define DPRINTF(x)
@@ -668,7 +668,8 @@ find_pci_host_node(int node)
  				 &dev_type, sizeof(dev_type));
  		if (len <= 0)
  			continue;
-		if (!strcmp(dev_type, "pci"))
+		if (!strcmp(dev_type, "pci") ||
+		    !strcmp(dev_type, "pciex"))
  			pch = node;
  	}
  	return pch;
@@ -687,7 +688,7 @@ OF_mapintr(int node, int *interrupt, int
  {
  	int i, len;
  	int address_cells, size_cells, interrupt_cells, interrupt_map_len;
-	int static_interrupt_map[100];
+	int static_interrupt_map[256];
  	int interrupt_map_mask[10];
  	int *interrupt_map = &static_interrupt_map[0];
  	int maplen = sizeof static_interrupt_map;
@@ -698,7 +699,7 @@ OF_mapintr(int node, int *interrupt, int
  	int rc = -1;

  	/* Don't need to map OBP interrupt, it's already */
-	if (*interrupt & 0x20)
+	if (*interrupt & 0x20 || *interrupt & 0x7c0)
  		return validlen;

  	/*
@@ -722,7 +723,7 @@ OF_mapintr(int node, int *interrupt, int

  	phc_node = find_pci_host_node(node);

-	for (; node; node = OF_parent(node)) {
+	while (node) {
  #ifdef DEBUG
  		char name[40];

@@ -740,7 +741,8 @@ OF_mapintr(int node, int *interrupt, int
  			/* 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") &&
+			    (!strcmp(dev_type, "pci") ||
+			     !strcmp(dev_type, "pciex")) &&
  			    (node != phc_node)) {
  #ifdef DEBUG
  				int ointerrupt = *interrupt;
@@ -755,6 +757,8 @@ OF_mapintr(int node, int *interrupt, int
  			/* Get reg for next level compare. */
  			reg[0] = 0;
  			OF_getprop(node, "reg", &reg, sizeof(reg));
+
+			node = OF_parent(node);
  			continue;
  		}
  		if (interrupt_map_len > maplen) {
@@ -813,7 +817,7 @@ OF_mapintr(int node, int *interrupt, int

  		/* finally we can attempt the compare */
  		i = 0;
-		while (i < interrupt_map_len) {
+		while (i < interrupt_map_len + address_cells + interrupt_cells) {
  			int pintr_cells;
  			int *imap = &interrupt_map[i];
  			int *parent = &imap[address_cells + interrupt_cells];
@@ -850,6 +854,7 @@ OF_mapintr(int node, int *interrupt, int
  						free(free_map, M_DEVBUF);
  					return (-1);
  				}
+				node = *parent;
  				parent++;
  #ifdef DEBUG
  				DPRINTF(("Match! using "));
@@ -860,6 +865,8 @@ OF_mapintr(int node, int *interrupt, int
  				for (i = 0; i < pintr_cells; i++)
  					interrupt[i] = parent[i];
  				rc = validlen = pintr_cells;
+				if (node == phc_node)
+					return(rc);
  				break;
  			}
  			/* Move on to the next interrupt_map entry. */
@@ -877,14 +884,15 @@ OF_mapintr(int node, int *interrupt, int
  		/* Get reg for the next level search. */
  		if ((len = OF_getprop(node, "reg", &reg, sizeof(reg))) <= 0) {
  			DPRINTF(("OF_mapintr: no reg property?\n"));
-			continue;
+		} else {
+			DPRINTF(("reg len %d\n", len));
  		}
-		DPRINTF(("reg len %d\n", len));

  		if (free_map) {
  			free(free_map, M_DEVBUF);
  			free_map = NULL;
  		}
+		node = OF_parent(node);
  	}
  	return (rc);
  }


---
Michael L. Hitch                        [email protected]
Operations Consulting,  Information Technology Center
Montana State University, Bozeman, MT     USA
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.