Port-sparc64 archive

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

OF_mapintr() problems



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                        mhitch%NetBSD.org@localhost
Operations Consulting,  Information Technology Center
Montana State University, Bozeman, MT     USA


Home | Main Index | Thread Index | Old Index