Index: ebus/ebus.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/ebus/ebus.c,v
retrieving revision 1.4
diff -u -r1.4 ebus.c
--- ebus/ebus.c	24 Mar 2002 02:11:06 -0000	1.4
+++ ebus/ebus.c	6 Nov 2002 23:20:54 -0000
@@ -398,7 +398,7 @@
 	nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intrs),
 	    (void **)&intrs);
 	for (i = 0; i < nintr; i++) {
-		intr = ofw_bus_route_intr(node, intrs[i]);
+		intr = ofw_bus_route_intr(node, intrs[i], ofw_pci_orb_callback);
 		if (intr == ORIR_NOTFOUND) {
 			panic("ebus_setup_dinfo: could not map ebus "
 			    "interrupt %d", intrs[i]);
Index: include/ofw_bus.h
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/include/ofw_bus.h,v
retrieving revision 1.2
diff -u -r1.2 ofw_bus.h
--- include/ofw_bus.h	24 Mar 2002 02:11:00 -0000	1.2
+++ include/ofw_bus.h	6 Nov 2002 23:20:54 -0000
@@ -31,6 +31,9 @@
 #define	ORIP_NOINT	-1
 #define	ORIR_NOTFOUND	0xffffffff
 
-u_int32_t ofw_bus_route_intr(phandle_t, int);
+typedef int obr_callback_t(phandle_t, u_int8_t *, int, u_int8_t *, int,
+    u_int8_t **, int *);
+
+u_int32_t ofw_bus_route_intr(phandle_t, int, obr_callback_t *);
 
 #endif /* !_MACHINE_OFW_BUS_H_ */
Index: include/ver.h
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/include/ver.h,v
retrieving revision 1.3
diff -u -r1.3 ver.h
--- include/ver.h	13 Jul 2002 03:23:29 -0000	1.3
+++ include/ver.h	6 Nov 2002 23:20:54 -0000
@@ -59,6 +59,7 @@
 	(((ver) & VER_MAXWIN_MASK) >> VER_MAXWIN_SHIFT)
 
 extern int cpu_impl;
+extern char sparc64_model[];
 
 /* Known implementations. */
 #define	CPU_IMPL_SPARC64	0x01
Index: isa/isa.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/isa/isa.c,v
retrieving revision 1.4
diff -u -r1.4 isa.c
--- isa/isa.c	2 Apr 2002 17:23:45 -0000	1.4
+++ isa/isa.c	6 Nov 2002 23:20:54 -0000
@@ -133,7 +133,8 @@
 			continue;
 		if (ino > 7)
 			panic("isa_init: XXX: ino too large");
-		isa_ino[ino] = ofw_bus_route_intr(node, ino);
+		isa_ino[ino] = ofw_bus_route_intr(node, ino,
+		    ofw_pci_orb_callback);
 	}
 
 	for (nbr -= 1; nbr >= 0; nbr--) {
Index: pci/ofw_pci.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/pci/ofw_pci.c,v
retrieving revision 1.4
diff -u -r1.4 ofw_pci.c
--- pci/ofw_pci.c	12 Jun 2002 19:20:57 -0000	1.4
+++ pci/ofw_pci.c	7 Nov 2002 00:07:55 -0000
@@ -47,6 +47,7 @@
 #include <sparc64/pci/ofw_pci.h>
 
 #include <machine/ofw_bus.h>
+#include <machine/ver.h>
 
 #include "pcib_if.h"
 
@@ -54,16 +55,63 @@
 phandle_t *pci_bus_map;
 int pci_bus_map_sz;
 
+#define	OPQ_NEED_SWIZZLE	1
+static struct ofw_pci_quirk {
+	char	*opq_model;
+	int	opq_quirks;
+} ofw_pci_quirks[] = {
+	{ "SUNW,UltraSPARC-IIi-cEngine", OPQ_NEED_SWIZZLE }
+};
+#define	OPQ_NENT	(sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0]))
+
+static int pci_quirks;
+
+#define	OFW_PCI_PCIBUS	"pci"
 #define	PCI_BUS_MAP_INC	10
 
+int
+ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
+    u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate)
+{
+	struct ofw_pci_register preg;
+	u_int32_t pintr, intr;
+	char type[32];
+
+	if ((pci_quirks & OPQ_NEED_SWIZZLE) != 0 &&
+	    pintsz == sizeof(u_int32_t) && pregsz >= sizeof(preg) &&
+	    OF_getprop(node, "device_type", type, sizeof(type)) != -1 &&
+	    strcmp(type, OFW_PCI_PCIBUS) == 0) {
+		/*
+		 * Handle a quirk found on some Netra t1 models: there exist
+		 * PCI bridges without interrupt maps, where we apparently must
+		 * do the PCI swizzle and continue to map on at the parent.
+		 */
+		bcopy(pintptr, &pintr, sizeof(pintr));
+		bcopy(pregptr, &preg, sizeof(preg));
+		intr = (OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi) + pintr) % 4;
+		*rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK);
+		bcopy(&intr, *rintr, sizeof(intr));
+		*terminate = 0;
+		return (sizeof(intr));
+	}
+	return (-1);
+}
+
 u_int32_t
-ofw_pci_route_intr(phandle_t node)
+ofw_pci_route_intr(phandle_t node, u_int32_t ign)
 {
 	u_int32_t rv;
 
-	rv = ofw_bus_route_intr(node, ORIP_NOINT);
+	rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback);
 	if (rv == ORIR_NOTFOUND)
 		return (255);
+	/*
+	 * Some machines (notably the SPARCengine Ultra AX) have no mappings
+	 * at all, but use complete interrupt vector number including the IGN.
+	 * Catch this case and remove the IGN.
+	 */
+	if (rv > ign)
+		rv -= ign;
 	return (rv);
 }
 
@@ -112,7 +160,6 @@
 	    PCIR_SUBBUS_1, obd->obd_subbus, 1);
 }
 
-#define	OFW_PCI_PCIBUS	"pci"
 /*
  * Walk the PCI bus hierarchy, starting with the root PCI bus and descending
  * through bridges, and initialize the interrupt line and latency timer
@@ -120,15 +167,24 @@
  * as well as the the bus numbers and ranges of the bridges.
  */
 void
-ofw_pci_init(device_t dev, phandle_t bushdl, struct ofw_pci_bdesc *obd)
+ofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
+    struct ofw_pci_bdesc *obd)
 {
 	struct ofw_pci_register pcir;
 	struct ofw_pci_bdesc subobd, *tobd;
 	phandle_t node;
 	char type[32];
-	int intr, freemap;
+	int i, intr, freemap;
 	u_int slot, busno, func, sub, lat;
 
+	/* Initialize the quirk list. */
+	for (i = 0; i < OPQ_NENT; i++) {
+		if (strcmp(sparc64_model, ofw_pci_quirks[i].opq_model) == 0) {
+			pci_quirks = ofw_pci_quirks[i].opq_quirks;
+			break;
+		}
+	}
+
 	if ((node = OF_child(bushdl)) == 0)
 		return;
 	freemap = 0;
@@ -141,7 +197,7 @@
 		else
 			type[sizeof(type) - 1] = '\0';
 		if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
-			panic("ofw_pci_route_intr: OF_getprop failed");
+			panic("ofw_pci_init: OF_getprop failed");
 		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
 		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
 		if (strcmp(type, OFW_PCI_PCIBUS) == 0) {
@@ -173,7 +229,7 @@
 			device_printf(dev, "%s: descending to "
 			    "subordinate PCI bus\n", __func__);
 #endif /* OFW_PCI_DEBUG */
-			ofw_pci_init(dev, node, &subobd);
+			ofw_pci_init(dev, node, ign, &subobd);
 		} else {
 			/*
 			 * Initialize the latency timer register for
@@ -199,7 +255,7 @@
 			}
 
 			/* Initialize the intline registers. */
-			if ((intr = ofw_pci_route_intr(node)) != 255) {
+			if ((intr = ofw_pci_route_intr(node, ign)) != 255) {
 #ifdef OFW_PCI_DEBUG
 				device_printf(dev, "%s: mapping intr for "
 				    "%d/%d/%d to %d (preset was %d)\n",
Index: pci/ofw_pci.h
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/pci/ofw_pci.h,v
retrieving revision 1.3
diff -u -r1.3 ofw_pci.h
--- pci/ofw_pci.h	12 Jun 2002 19:20:57 -0000	1.3
+++ pci/ofw_pci.h	6 Nov 2002 23:20:54 -0000
@@ -34,6 +34,8 @@
 #ifndef _SPARC64_PCI_OFW_PCI_H_
 #define _SPARC64_PCI_OFW_PCI_H_
 
+#include <machine/ofw_bus.h>
+
 /* PCI range child spaces. XXX: are these MI? */
 #define	PCI_CS_CONFIG	0x00
 #define	PCI_CS_IO	0x01
@@ -69,10 +71,11 @@
 	struct ofw_pci_bdesc	*obd_super;
 };
 
-u_int32_t ofw_pci_route_intr(phandle_t);
+u_int32_t ofw_pci_route_intr(phandle_t, u_int32_t);
+obr_callback_t ofw_pci_orb_callback;
 u_int8_t ofw_pci_alloc_busno(phandle_t);
 ofw_pci_binit_t ofw_pci_binit;
-void ofw_pci_init(device_t, phandle_t, struct ofw_pci_bdesc *);
+void ofw_pci_init(device_t, phandle_t, u_int32_t, struct ofw_pci_bdesc *);
 phandle_t ofw_pci_find_node(int, int, int);
 phandle_t ofw_pci_node(device_t);
 
Index: pci/psycho.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/pci/psycho.c,v
retrieving revision 1.16
diff -u -r1.16 psycho.c
--- pci/psycho.c	16 Oct 2002 17:37:50 -0000	1.16
+++ pci/psycho.c	6 Nov 2002 23:20:54 -0000
@@ -630,7 +630,7 @@
 	 * the firmware uses the same model as this driver if it does.
 	 * Additionally, set up the bus numbers and ranges.
 	 */
-	ofw_pci_init(dev, sc->sc_node, &obd);
+	ofw_pci_init(dev, sc->sc_node, sc->sc_ign, &obd);
 
 	device_add_child(dev, "pci", device_get_unit(dev));
 	return (bus_generic_attach(dev));
Index: sparc64/machdep.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/sparc64/machdep.c,v
retrieving revision 1.69
diff -u -r1.69 machdep.c
--- sparc64/machdep.c	25 Oct 2002 19:10:58 -0000	1.69
+++ sparc64/machdep.c	6 Nov 2002 23:20:54 -0000
@@ -130,6 +130,8 @@
 
 static struct timecounter tick_tc;
 
+char sparc64_model[128];
+
 static timecounter_get_t tick_get_timecount;
 void sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3,
 		  ofw_vec_t *vec);
@@ -159,6 +161,7 @@
 	tc_init(&tick_tc);
 
 	cpu_identify(rdpr(ver), tick_freq, PCPU_GET(cpuid));
+	printf("Model: %s\n", sparc64_model);
 
 	vm_ksubmap_init(&kmi);
 
@@ -348,6 +351,8 @@
 
 	OF_getprop(PCPU_GET(node), "clock-frequency", &clock, sizeof(clock));
 	tick_init(clock);
+
+	OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1);
 }
 
 void
Index: sparc64/ofw_bus.c
===================================================================
RCS file: /space/ncvs/src/sys/sparc64/sparc64/ofw_bus.c,v
retrieving revision 1.2
diff -u -r1.2 ofw_bus.c
--- sparc64/ofw_bus.c	24 Mar 2002 02:11:04 -0000	1.2
+++ sparc64/ofw_bus.c	6 Nov 2002 23:43:00 -0000
@@ -151,15 +151,16 @@
  * the interrupt map of the next higher node. If there is no match or no such
  * propery, we go to the next higher node, using the 'reg' property of the node
  * that was just processed unusccessfully.
- * When a match occurs, we continue to search, using the new interrupt
- * specification that was just found.
+ * When a match occurs, we should continue to search, using the new interrupt
+ * specification that was just found; this is currently not performed
+ * (see below).
  * When the root node is reached with at least one successful mapping performed,
  * and the format is right, the interrupt number is returned.
  *
  * This should work for all bus systems.
  */
 u_int32_t
-ofw_bus_route_intr(phandle_t node, int intrp)
+ofw_bus_route_intr(phandle_t node, int intrp, obr_callback_t *cb)
 {
 	u_int8_t *reg, *intr, *tintr, *imap, *imapmsk;
 	phandle_t parent;
@@ -193,8 +194,22 @@
 			panic("ofw_bus_route_intr: could not get reg property");
 		imapsz = OF_getprop_alloc(parent, "interrupt-map", 1,
 		    (void **)&imap);
-		if (imapsz == -1)
+		if (imapsz == -1) {
+			/*
+			 * Use the callback to allow caller-specific workarounds
+			 * for firmware bugs (missing properties).
+			 */
+			if (cb != NULL) {
+				tisz = cb(parent, intr, isz, reg, regsz, &tintr,
+				    &found);
+				if (tisz != -1) {
+					isz = tisz;
+					free(intr, M_OFWPROP);
+					intr = tintr;
+				}
+			}
 			continue;
+		}
 		if (OF_getprop(parent, "#address-cells", &addrc,
 		    sizeof(addrc)) == -1)
 			addrc = 2;
