diff --git a/sys/sparc64/pci/ofw_pci.c b/sys/sparc64/pci/ofw_pci.c
index 636c9f98cbc3..d36e7307ace6 100644
--- a/sys/sparc64/pci/ofw_pci.c
+++ b/sys/sparc64/pci/ofw_pci.c
@@ -50,6 +50,12 @@
 
 #include "pcib_if.h"
 
+u_int8_t pci_bus_cnt;
+phandle_t *pci_bus_map;
+int pci_bus_map_sz;
+
+#define	PCI_BUS_MAP_INC	10
+
 u_int32_t
 ofw_pci_route_intr(phandle_t node)
 {
@@ -61,24 +67,72 @@ ofw_pci_route_intr(phandle_t node)
 	return (rv);
 }
 
+u_int8_t
+ofw_pci_alloc_busno(phandle_t node)
+{
+	phandle_t *om;
+	int osz;
+	u_int8_t n;
+
+	n = pci_bus_cnt++;
+	/* Establish a mapping between bus numbers and device nodes. */
+	if (n >= pci_bus_map_sz) {
+		osz = pci_bus_map_sz;
+		om = pci_bus_map;
+		pci_bus_map_sz = n + PCI_BUS_MAP_INC;
+		pci_bus_map = malloc(sizeof(*pci_bus_map) * pci_bus_map_sz,
+		    M_DEVBUF, M_WAITOK | M_ZERO);
+		if (om != NULL) {
+			bcopy(om, pci_bus_map, sizeof(*om) * osz);
+			free(om, M_DEVBUF);
+		}
+	}
+	pci_bus_map[n] = node;
+	return (n);
+}
+
+/*
+ * Initialize bridge bus numbers for bridges that implement the primary,
+ * secondary and subordinate bus number registers.
+ */
+void
+ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
+{
+
+#ifdef OFW_PCI_DEBUG
+	printf("PCI-PCI bridge at %u/%u/%u: setting bus #s to %u/%u/%u\n",
+	    obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
+	    obd->obd_secbus, obd->obd_subbus);
+#endif /* OFW_PCI_DEBUG */
+	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
+	    PCIR_PRIBUS_1, obd->obd_bus, 1);
+	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
+	    PCIR_SECBUS_1, obd->obd_secbus, 1);
+	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
+	    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 configuration registers
- * of attached devices using firmware information.
+ * through bridges, and initialize the interrupt line and latency timer
+ * configuration registers of attached devices using firmware information,
+ * as well as the the bus numbers and ranges of the bridges.
  */
 void
-ofw_pci_init_intr(device_t dev, phandle_t bus)
+ofw_pci_init(device_t dev, phandle_t bushdl, struct ofw_pci_bdesc *obd)
 {
 	struct ofw_pci_register pcir;
+	struct ofw_pci_bdesc subobd, *tobd;
 	phandle_t node;
 	char type[32];
-	int intr;
-	int freemap;
+	int intr, freemap;
+	u_int slot, busno, func, sub, lat;
 
-	if ((node = OF_child(bus)) == 0)
+	if ((node = OF_child(bushdl)) == 0)
 		return;
 	freemap = 0;
+	busno = obd->obd_secbus;
 	do {
 		if (node == -1)
 			panic("ofw_pci_init_intr: OF_child failed");
@@ -86,60 +140,88 @@ ofw_pci_init_intr(device_t dev, phandle_t bus)
 			type[0] = '\0';
 		else
 			type[sizeof(type) - 1] = '\0';
+		if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
+			panic("ofw_pci_route_intr: 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) {
 			/*
-			 * This is a pci-pci bridge, recurse to initialize the
-			 * child bus. The hierarchy is usually at most 2 levels
-			 * deep, so recursion is feasible.
+			 * This is a pci-pci bridge, initalize the bus number and
+			 * recurse to initialize the child bus. The hierarchy is
+			 * usually at most 2 levels deep, so recursion is
+			 * feasible.
 			 */
+			subobd.obd_bus = busno;
+			subobd.obd_slot = slot;
+			subobd.obd_func = func;
+			sub = ofw_pci_alloc_busno(node);
+			subobd.obd_secbus = subobd.obd_subbus = sub;
+			/* Assume this bridge is mostly standard conforming. */
+			subobd.obd_init = ofw_pci_binit;
+			subobd.obd_super = obd;
+			/*
+			 * Need to change all subordinate bus registers of the
+			 * bridges above this one now so that configuration
+			 * transactions will get through.
+			 */
+			for (tobd = obd; tobd != NULL; tobd = tobd->obd_super) {
+				tobd->obd_subbus = sub;
+				tobd->obd_init(dev, tobd);
+			}
+			subobd.obd_init(dev, &subobd);
 #ifdef OFW_PCI_DEBUG
 			device_printf(dev, "%s: descending to "
 			    "subordinate PCI bus\n", __func__);
-#endif
-			ofw_pci_init_intr(dev, node);
+#endif /* OFW_PCI_DEBUG */
+			ofw_pci_init(dev, node, &subobd);
 		} else {
-			if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
-				panic("ofw_pci_route_intr: OF_getprop failed");
+			/*
+			 * Initialize the latency timer register for
+			 * busmaster devices to work properly. This is another
+			 * task which the firmware does not always perform.
+			 * The Min_Gnt register can be used to compute it's
+			 * recommended value: it contains the desired latency
+			 * in units of 1/4 us. To calculate the correct latency
+			 * timer value, a bus clock of 33 and no wait states
+			 * should be assumed.
+			 */
+			lat = PCIB_READ_CONFIG(dev, busno, slot, func,
+			    PCIR_MINGNT, 1) * 33 / 4;
+			if (lat != 0) {
+#ifdef OFW_PCI_DEBUG
+				printf("device %d/%d/%d: latency timer %d -> "
+				    "%d\n", busno, slot, func,
+				    PCIB_READ_CONFIG(dev, busno, slot, func,
+					PCIR_LATTIMER, 1), lat);
+#endif /* OFW_PCI_DEBUG */
+				PCIB_WRITE_CONFIG(dev, busno, slot, func,
+				    PCIR_LATTIMER, imin(lat, 255), 1);
+			}
 
+			/* Initialize the intline registers. */
 			if ((intr = ofw_pci_route_intr(node)) != 255) {
 #ifdef OFW_PCI_DEBUG
 				device_printf(dev, "%s: mapping intr for "
 				    "%d/%d/%d to %d (preset was %d)\n",
-				    __func__,
-				    OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
-				    intr,
-				    (int)PCIB_READ_CONFIG(dev,
-					OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-					OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-					OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
-					PCIR_INTLINE, 1));
+				    __func__, busno, slot, func, intr,
+				    (int)PCIB_READ_CONFIG(dev, busno, slot,
+					func, PCIR_INTLINE, 1));
 #endif /* OFW_PCI_DEBUG */
-				PCIB_WRITE_CONFIG(dev,
-				    OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
+				PCIB_WRITE_CONFIG(dev, busno, slot, func,
 				    PCIR_INTLINE, intr, 1);
 			} else {
 #ifdef OFW_PCI_DEBUG
 				device_printf(dev, "%s: no interrupt "
 				    "mapping found for %d/%d/%d (preset %d)\n",
-				    __func__,
-				    OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
-				    (int)PCIB_READ_CONFIG(dev,
-					OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-					OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-					OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
-					PCIR_INTLINE, 1));
+				    __func__, busno, slot, func,
+				    (int)PCIB_READ_CONFIG(dev, busno, slot,
+					func, PCIR_INTLINE, 1));
 #endif /* OFW_PCI_DEBUG */
-				/* The firmware initializes to 0 instead 255 */
-				PCIB_WRITE_CONFIG(dev,
-				    OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
-				    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
+				/*
+				 * The firmware initializes to 0 instead of
+				 * 255.
+				 */
+				PCIB_WRITE_CONFIG(dev, busno, slot, func,
 				    PCIR_INTLINE, 255, 1);
 			}
 		}
@@ -149,34 +231,17 @@ ofw_pci_init_intr(device_t dev, phandle_t bus)
 phandle_t
 ofw_pci_find_node(int bus, int slot, int func)
 {
-	phandle_t node, bnode, parent;
+	phandle_t node, bnode;
 	struct ofw_pci_register pcir;
-	int br[2];
-	char name[16];
 
-	/* 1. Try to find the bus in question. */
-	bnode = 0;
-	name[sizeof(name) - 1] = '\0';
-	parent = OF_peer(0);
-	node = OF_child(parent);
-	while (node != 0 && node != -1) {
-		if (OF_getprop(node, "name", name, sizeof(name) - 1) != -1 &&
-		    strcmp(name, "pci") == 0 &&
-		    OF_getprop(node, "bus-range", br, sizeof(br)) != -1) {
-			/* Found the bus? */
-			if (bus == br[0]) {
-				bnode = node;
-				break;
-			}
-			/* Need to descend? */
-			if (bus > br[0] && bus <= br[1]) {
-				parent = node;
-				node = OF_child(node);
-				continue;
-			}
-		}
-		node = OF_peer(node);
-	}
+	/*
+	 * Retrieve the bus node from the mapping that was created on
+	 * initialization. The bus numbers the firmware uses cannot be trusted,
+	 * so they might have needed to be changed and this is necessary.
+	 */
+	if (bus >= pci_bus_map_sz)
+		return (0);
+	bnode = pci_bus_map[bus];
 	if (bnode == 0)
 		return (0);
 	for (node = OF_child(bnode); node != 0 && node != -1;
@@ -184,11 +249,8 @@ ofw_pci_find_node(int bus, int slot, int func)
 		if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
 			continue;
 		if (OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi) == slot &&
-		    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi) == func) {
-			if (OFW_PCI_PHYS_HI_BUS(pcir.phys_hi) != bus)
-				panic("ofw_pci_find_node: bus number mismatch");
+		    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi) == func)
 			return (node);
-		}
 	}
 	return (0);
 }
diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h
index 862df92843fb..68cf1ec8947d 100644
--- a/sys/sparc64/pci/ofw_pci.h
+++ b/sys/sparc64/pci/ofw_pci.h
@@ -56,8 +56,23 @@ struct ofw_pci_imap_msk {
 	u_int32_t	intr;
 };
 
+struct ofw_pci_bdesc;
+typedef void ofw_pci_binit_t(device_t, struct ofw_pci_bdesc *);
+
+struct ofw_pci_bdesc {
+	u_int	obd_bus;
+	u_int	obd_slot;
+	u_int	obd_func;
+	u_int	obd_secbus;
+	u_int	obd_subbus;
+	ofw_pci_binit_t	*obd_init;
+	struct ofw_pci_bdesc	*obd_super;
+};
+
 u_int32_t ofw_pci_route_intr(phandle_t);
-void ofw_pci_init_intr(device_t, phandle_t);
+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 *);
 phandle_t ofw_pci_find_node(int, int, int);
 phandle_t ofw_pci_node(device_t);
 
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index f62eceb74015..901639ed3b1a 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -94,6 +94,7 @@ static void psycho_wakeup(void *);
 
 /* IOMMU support */
 static void psycho_iommu_init(struct psycho_softc *, int);
+static ofw_pci_binit_t psycho_binit;
 
 /*
  * bus space and bus dma support for UltraSPARC `psycho'.  note that most
@@ -288,6 +289,7 @@ psycho_attach(device_t dev)
 	struct psycho_softc *osc = NULL;
 	struct psycho_softc *asc;
 	struct upa_regs *reg;
+	struct ofw_pci_bdesc obd;
 	char compat[32];
 	char *model;
 	phandle_t node;
@@ -416,21 +418,9 @@ psycho_attach(device_t dev)
 	    PCICTL_RTRYWAIT);
 	PCICTL_WRITE8(sc, PCR_CS, csr);
 
-	/* grab the psycho ranges */
+	/* Grab the psycho ranges */
 	psycho_get_ranges(sc->sc_node, &sc->sc_range, &sc->sc_nrange);
 
-	/* get the bus-range for the psycho */
-	n = OF_getprop(node, "bus-range", (void *)psycho_br, sizeof(psycho_br));
-	if (n == -1)
-		panic("could not get psycho bus-range");
-	if (n != sizeof(psycho_br))
-		panic("broken psycho bus-range (%d)", n);
-
-	printf("bus range %u to %u; PCI bus %d\n", psycho_br[0], psycho_br[1],
-	    psycho_br[0]);
-
-	sc->sc_busno = psycho_br[0];
-
 	/* Initialize memory and i/o rmans */
 	sc->sc_io_rman.rm_type = RMAN_ARRAY;
 	sc->sc_io_rman.rm_descr = "Psycho PCI I/O Ports";
@@ -605,6 +595,27 @@ psycho_attach(device_t dev)
 	}
 #endif
 
+	/*
+	 * Get the bus range from the firmware; it is used solely for obtaining
+	 * the inital bus number, and cannot be trusted on all machines.
+	 */
+	n = OF_getprop(node, "bus-range", (void *)psycho_br, sizeof(psycho_br));
+	if (n == -1)
+		panic("could not get psycho bus-range");
+	if (n != sizeof(psycho_br))
+		panic("broken psycho bus-range (%d)", n);
+
+	sc->sc_busno = ofw_pci_alloc_busno(sc->sc_node);
+	obd.obd_bus = psycho_br[0];
+	obd.obd_secbus = obd.obd_subbus = sc->sc_busno;
+	obd.obd_slot = PCS_DEVICE;
+	obd.obd_func = PCS_FUNC;
+	obd.obd_init = psycho_binit;
+	obd.obd_super = NULL;
+	/* Initial setup. */
+	psycho_binit(dev, &obd);
+	/* Update the bus number to what was just programmed. */
+	obd.obd_bus = obd.obd_secbus;
 	/*
 	 * Initialize the interrupt registers of all devices hanging from
 	 * the host bridge directly or indirectly via PCI-PCI bridges.
@@ -612,8 +623,9 @@ psycho_attach(device_t dev)
 	 * system initialization, however the firmware does not do this
 	 * at least on some models, and we probably shouldn't trust that
 	 * the firmware uses the same model as this driver if it does.
+	 * Additionally, set up the bus numbers and ranges.
 	 */
-	ofw_pci_init_intr(dev, sc->sc_node);
+	ofw_pci_init(dev, sc->sc_node, &obd);
 
 	device_add_child(dev, "pci", device_get_unit(dev));
 	return (bus_generic_attach(dev));
@@ -837,6 +849,25 @@ psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
 	iommu_init(name, is, tsbsize, iobase);
 }
 
+static void
+psycho_binit(device_t busdev, struct ofw_pci_bdesc *obd)
+{
+
+#ifdef PSYCHO_DEBUG
+	printf("psycho at %u/%u/%u: setting bus #s to %u/%u/%u\n",
+	    obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
+	    obd->obd_secbus, obd->obd_subbus);
+#endif /* PSYCHO_DEBUG */
+	/*
+	 * NOTE: this must be kept in this order, since the last write will
+	 * change the config space address of the psycho.
+	 */
+	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
+	    PCSR_SUBBUS, obd->obd_subbus, 1);
+	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
+	    PCSR_SECBUS, obd->obd_secbus, 1);
+}
+
 static int
 psycho_maxslots(device_t dev)
 {
@@ -961,7 +992,6 @@ psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
 static int
 psycho_route_interrupt(device_t bus, device_t dev, int pin)
 {
-	int intline;
 
 	/*
 	 * XXX: ugly loathsome hack:
diff --git a/sys/sparc64/pci/psychoreg.h b/sys/sparc64/pci/psychoreg.h
index 7de9c62097f9..412a217b0cb9 100644
--- a/sys/sparc64/pci/psychoreg.h
+++ b/sys/sparc64/pci/psychoreg.h
@@ -240,6 +240,14 @@
 #define	UEAFSR_P_DWR	(1UL << 61)	/* pri. error during write */
 #define	UEAFSR_P_DRD	(1UL << 62)	/* pri. error during read */
 
+/* Definitions for the psycho configuration space */
+#define	PCS_DEVICE	0		/* Device number of psycho CS entry */
+#define	PCS_FUNC	0		/* Function number of psycho CS entry */
+
+/* Non-Standard registers in the configration space */
+#define	PCSR_SECBUS	0x40		/* Secondary bus number register */
+#define	PCSR_SUBBUS	0x41		/* Subordinate bus number register */
+
 /*
  * these are the PROM structures we grovel
  */