Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Mar 2002 18:39:31 -0800 (PST)
From:      Thomas Moestl <tmm@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 8009 for review
Message-ID:  <200203200239.g2K2dVN60219@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=8009

Change 8009 by tmm@tmm_sparc64 on 2002/03/19 18:39:04

	Integ. with sparc64-tmm:
	- hme fixes and cleanups.
	- the big fearsome ofw interrupt code rework.

Affected files ...

... //depot/projects/sparc64/sys/dev/hme/if_hme.c#16 integrate
... //depot/projects/sparc64/sys/dev/hme/if_hme_pci.c#11 integrate
... //depot/projects/sparc64/sys/dev/hme/if_hme_sbus.c#5 integrate
... //depot/projects/sparc64/sys/dev/hme/if_hmevar.h#9 integrate
... //depot/projects/sparc64/sys/sparc64/ebus/ebus.c#9 integrate
... //depot/projects/sparc64/sys/sparc64/ebus/ebusvar.h#4 integrate
... //depot/projects/sparc64/sys/sparc64/include/ofw_bus.h#5 integrate
... //depot/projects/sparc64/sys/sparc64/isa/isa.c#8 integrate
... //depot/projects/sparc64/sys/sparc64/isa/ofw_isa.c#7 integrate
... //depot/projects/sparc64/sys/sparc64/pci/apb.c#8 integrate
... //depot/projects/sparc64/sys/sparc64/pci/ofw_pci.c#7 integrate
... //depot/projects/sparc64/sys/sparc64/pci/ofw_pci.h#4 integrate
... //depot/projects/sparc64/sys/sparc64/pci/psycho.c#24 integrate
... //depot/projects/sparc64/sys/sparc64/pci/psychovar.h#9 integrate
... //depot/projects/sparc64/sys/sparc64/sparc64/iommu.c#17 integrate
... //depot/projects/sparc64/sys/sparc64/sparc64/ofw_bus.c#5 integrate

Differences ...

==== //depot/projects/sparc64/sys/dev/hme/if_hme.c#16 (text+ko) ====

@@ -1310,13 +1310,6 @@
 	HME_MAC_WRITE_4(sc, HME_MACI_TXCFG, v);
 	if (!hme_mac_bitflip(sc, HME_MACI_TXCFG, v, 0, HME_MAC_TXCFG_ENABLE))
 		return;
-
-	/* If an external transceiver is selected, enable its MII drivers */
-	v = HME_MAC_READ_4(sc, HME_MACI_XIF);
-	v &= ~HME_MAC_XIF_MIIENABLE;
-	if (phy == HME_PHYAD_EXTERNAL)
-		v |= HME_MAC_XIF_MIIENABLE;
-	HME_MAC_WRITE_4(sc, HME_MACI_XIF, v);
 }
 
 static int

==== //depot/projects/sparc64/sys/dev/hme/if_hme_pci.c#11 (text+ko) ====

@@ -151,7 +151,7 @@
 	}
 	hsc->hsc_irid = 0;
 	hsc->hsc_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &hsc->hsc_irid, 0,
-	    ~0, 1, RF_ACTIVE);
+	    ~0, 1, RF_SHAREABLE | RF_ACTIVE);
 	if (hsc->hsc_ires == NULL) {
 		device_printf(dev, "could not allocate interrupt\n");
 		error = ENXIO;

==== //depot/projects/sparc64/sys/dev/hme/if_hme_sbus.c#5 (text+ko) ====

@@ -222,7 +222,7 @@
 
 	hsc->hsc_irid = 0;
 	hsc->hsc_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &hsc->hsc_irid, 0,
-	    ~0, 1, RF_ACTIVE);
+	    ~0, 1, RF_SHAREABLE | RF_ACTIVE);
 	if (hsc->hsc_ires == NULL) {
 		device_printf(dev, "could not allocate interrupt\n");
 		error = ENXIO;

==== //depot/projects/sparc64/sys/dev/hme/if_hmevar.h#9 (text+ko) ====

@@ -50,7 +50,7 @@
  * memory is sizeof(struct hme_txdesc)).
  * Both must be a multiple of 16, and <= 128.
  */
-#define HME_NRXDESC	32
+#define HME_NRXDESC	64
 #define HME_NTXDESC	64
 
 /* Maximum size of a mapped RX buffer. */

==== //depot/projects/sparc64/sys/sparc64/ebus/ebus.c#9 (text+ko) ====

@@ -54,13 +54,13 @@
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 
+#include <ofw/openfirm.h>
+#include <ofw/ofw_pci.h>
+
 #include <machine/bus.h>
 #include <machine/ofw_bus.h>
 #include <machine/resource.h>
 
-#include <ofw/openfirm.h>
-#include <ofw/ofw_pci.h>
-
 #include <pci/pcireg.h>
 #include <pci/pcivar.h>
 
@@ -99,18 +99,7 @@
 
 	struct isa_ranges	*sc_range;
 
-	struct ofw_pci_register	*sc_reg;
-
-	int			sc_imap_type;
-
-	struct isa_imap		*sc_ebus_imap;
-	struct isa_imap_msk	sc_ebus_imapmsk;
-
-	struct ofw_pci_imap	*sc_pci_imap;
-	struct ofw_pci_imap_msk	sc_pci_imapmsk;
-
 	int			sc_nrange;
-	int			sc_nreg;
 	int			sc_nimap;
 };
 
@@ -127,7 +116,6 @@
     phandle_t, char *);
 static void ebus_destroy_dinfo(struct ebus_devinfo *);
 static int ebus_print_res(struct ebus_devinfo *);
-static int ebus_map_intr(struct ebus_softc *, int, struct isa_regs *, int);
 
 static device_method_t ebus_methods[] = {
 	/* Device interface */
@@ -199,42 +187,10 @@
 	sc = device_get_softc(dev);
 	sc->sc_node = node;
 
-	/*
-	 * Fill in our softc with information from the prom.
-	 * There are two possible cases how interrupt mapping needs to be
-	 * handled:
-	 * - if the ebus node has an interrupt-map properties, the interrut
-	 *   numbers in child nodes can be mapped using lookups in this map,
-	 *   using the registers of the child node in question to find the
-	 *   map entry
-	 * - if it does not have such a properties, the interrupts are mapped
-	 *   in the next higher interrupt map (PCI in our case), using the
-	 *   interrupt number of the child, but the registers of the ebus
-	 *   node, to find the mapping.
-	 */
-	sc->sc_imap_type = EBUS_IT_EBUS;
-	sc->sc_nimap = OF_getprop_alloc(node, "interrupt-map",
-	    sizeof(*sc->sc_ebus_imap), (void **)&sc->sc_ebus_imap);
-	if (sc->sc_nimap == -1) {
-		sc->sc_nimap = ofw_pci_find_imap(node, &sc->sc_pci_imap,
-		    &sc->sc_pci_imapmsk);
-		if (sc->sc_nimap == -1)
-			panic("ebus_probe: no interrupt map found");
-		sc->sc_imap_type = EBUS_IT_PCI;
-	} else {
-		if (OF_getprop(node, "interrupt-map-mask",
-		    &sc->sc_ebus_imapmsk, sizeof(sc->sc_ebus_imapmsk)) == -1) {
-			panic("ebus_probe: could not get ebus "
-			    "interrupt-map-mask");
-		}
-	}
-
 	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
 	    sizeof(*sc->sc_range), (void **)&sc->sc_range);
-	sc->sc_nreg = OF_getprop_alloc(node, "reg",
-	    sizeof(*sc->sc_reg), (void **)&sc->sc_reg);
-	if (sc->sc_nrange == -1 || sc->sc_nreg == -1)
-		panic("ebus_attach: could not get ranges/reg property");
+	if (sc->sc_nrange == -1)
+		panic("ebus_attach: could not get ranges property");
 
 	/*
 	 * now attach all our children
@@ -411,9 +367,9 @@
 {
 	struct ebus_devinfo *edi;
 	struct isa_regs *reg;
-	u_int32_t *intrs;
+	u_int32_t *intrs, intr;
 	u_int64_t start;
-	int nreg, nintr, i, intr;
+	int nreg, nintr, i;
 
 	edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK);
 	if (edi == NULL)
@@ -442,10 +398,11 @@
 	nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intrs),
 	    (void **)&intrs);
 	for (i = 0; i < nintr; i++) {
-		intr = ebus_map_intr(sc, intrs[i], reg, nreg);
-		if (intr == -1)
+		intr = ofw_bus_route_intr(node, intrs[i]);
+		if (intr == ORIR_NOTFOUND) {
 			panic("ebus_setup_dinfo: could not map ebus "
 			    "interrupt %d", intrs[i]);
+		}
 		resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i,
 		    intr, intr, 1);
 	}
@@ -479,20 +436,3 @@
 	    "%ld");
 	return (retval);
 }
-
-static int
-ebus_map_intr(struct ebus_softc *sc, int intr, struct isa_regs *regs,
-    int nregs)
-{
-	int rv;
-
-	if (sc->sc_imap_type == EBUS_IT_PCI) {
-		rv = ofw_pci_route_intr2(intr, sc->sc_reg, sc->sc_pci_imap,
-		    sc->sc_nimap, &sc->sc_pci_imapmsk);
-		if (rv == 255)
-			return (-1);
-		return (rv);
-	}
-	return (ofw_isa_map_intr(sc->sc_ebus_imap, sc->sc_nimap,
-	    &sc->sc_ebus_imapmsk, intr, regs, nregs));
-}

==== //depot/projects/sparc64/sys/sparc64/ebus/ebusvar.h#4 (text+ko) ====

@@ -35,17 +35,6 @@
 #ifndef _SPARC64_EBUS_EBUSVAR_H_
 #define _SPARC64_EBUS_EBUSVAR_H_
 
-/*
- * Interrupt map type (for the sc_imap_type softc member):
- * If the ebus node has an interrupt map, this is set to EBUS_IT_EBUS (and the
- * relevant sotfc members are initialized with the EBUS types), otherwise,
- * it is EBUS_IT_PCI, in which case the standard PCI functions are used to
- * map the interrupt (this is needed because the the maps and masks are
- * different).
- */
-#define	EBUS_IT_EBUS	1
-#define	EBUS_IT_PCI	2
-
 enum ebus_device_ivars {
 	EBUS_IVAR_COMPAT,
 	EBUS_IVAR_NAME,

==== //depot/projects/sparc64/sys/sparc64/include/ofw_bus.h#5 (text+ko) ====

@@ -28,7 +28,9 @@
 #ifndef	_MACHINE_OFW_BUS_H_
 #define	_MACHINE_OFW_BUS_H_
 
-u_int32_t ofw_bus_route_intr(int intr, void *regs, int regsz, int physz,
-    int nregs, void *imap, int nimap, void *imapmsk, char *regm);
+#define	ORIP_NOINT	-1
+#define	ORIR_NOTFOUND	0xffffffff
+
+u_int32_t ofw_bus_route_intr(phandle_t, int);
 
 #endif /* !_MACHINE_OFW_BUS_H_ */

==== //depot/projects/sparc64/sys/sparc64/isa/isa.c#8 (text+ko) ====

@@ -51,6 +51,7 @@
 #include <ofw/openfirm.h>
 
 #include <machine/intr_machdep.h>
+#include <machine/ofw_bus.h>
 #include <machine/resource.h>
 
 #include <sparc64/pci/ofw_pci.h>
@@ -71,11 +72,8 @@
 
 device_t isa_bus_device;
 
-static struct ofw_pci_register isab_reg;
-static struct ofw_pci_imap *isab_imap;
-static int isab_nimap;
-static struct ofw_pci_imap_msk isab_imap_msk;
 static phandle_t isab_node;
+static u_int32_t isa_ino[8];
 
 /*
  * XXX: This is really partly partly PCI-specific, but unfortunately is
@@ -92,8 +90,6 @@
 
 static int isa_route_intr_res(device_t, u_long, u_long);
 
-static int isa_ino[8];
-
 intrmask_t
 isa_irq_pending(void)
 {
@@ -103,7 +99,7 @@
 	/* XXX: Is this correct? */
 	for (i = 7, pending = 0; i >= 0; i--) {
 		pending <<= 1; 
-		if (isa_ino[i] != 255) {
+		if (isa_ino[i] != ORIR_NOTFOUND) {
 			pending |= (SPARCBUS_INTR_PENDING(isa_bus_device,
 			    isa_ino[i]) == 0) ? 0 : 1;
 		}
@@ -116,28 +112,30 @@
 {
 	device_t bridge;
 	phandle_t node;
+	u_int32_t ino;
 	struct isa_ranges *br;
 	int nbr, i;
 
 	/* The parent of the bus must be a PCI-ISA bridge. */
 	bridge = device_get_parent(dev);
-	isab_node = ofw_pci_find_node(pci_get_bus(bridge), pci_get_slot(bridge),
-	    pci_get_function(bridge));
-	if (OF_getprop(isab_node, "reg", &isab_reg, sizeof(isab_reg)) < 0)
-		panic("isa_init: cannot get bridge reg property");
+	isab_node = ofw_pci_node(bridge);
 	nbr = OF_getprop_alloc(isab_node, "ranges", sizeof(*br), (void **)&br);
 	if (nbr <= 0)
 		panic("isa_init: cannot get bridge range property");
-	node = isab_node;
-	isab_nimap = ofw_pci_find_imap(node, &isab_imap, &isab_imap_msk);
-	if (isab_nimap == -1)
-		panic("isa_init: could not find interrupt-map");
-	for (i = 0; i < 8; i++) {
-		isa_ino[i] = ofw_pci_route_intr2(i, &isab_reg, isab_imap,
-		    isab_nimap, &isab_imap_msk);
+	/*
+	 * This is really a bad kluge; however, it is needed to provide
+	 * isa_irq_pending().
+	 */
+	for (i = 0; i < 8; i++)
+		isa_ino[i] = ORIR_NOTFOUND;
+	for (node = OF_child(isab_node); node != 0; node = OF_peer(node)) {
+		if (OF_getprop(node, "interrupts", &ino, sizeof(ino)) == -1)
+			continue;
+		if (ino > 7)
+			panic("isa_init: XXX: ino too large");
+		isa_ino[ino] = ofw_bus_route_intr(node, ino);
 	}
 
-
 	for (nbr -= 1; nbr >= 0; nbr--) {
 		switch(ISAB_RANGE_SPACE(br + nbr)) {
 		case ISAR_SPACE_IO:
@@ -168,8 +166,9 @@
 		panic("isa_route_intr_res: allocation of interrupt range not "
 		    "supported (0x%lx - 0x%lx)", start, end);
 	}
-	res = ofw_pci_route_intr2(start, &isab_reg, isab_imap, isab_nimap,
-	    &isab_imap_msk);
+	if (start > 7)
+		panic("isa_route_intr_res: start out of isa range");
+	res = isa_ino[start];
 	if (res == 255)
 		device_printf(bus, "could not map interrupt %d\n", res);
 	return (res);

==== //depot/projects/sparc64/sys/sparc64/isa/ofw_isa.c#7 (text+ko) ====

@@ -48,19 +48,6 @@
 #include <sparc64/isa/ofw_isa.h>
 #include <sparc64/pci/ofw_pci.h>
 
-/*
- * This applies only for an ISA/EBus with an own interrupt-map property.
- */
-int
-ofw_isa_map_intr(struct isa_imap *imap, int nimap, struct isa_imap_msk *imapmsk,
-    int intr, struct isa_regs *regs, int nregs)
-{
-	char regm[8];
-
-	return (ofw_bus_route_intr(intr, regs, sizeof(*regs), 8, nregs,
-	    imap, nimap, imapmsk, regm));
-}
-
 /* XXX: this only supports PCI as parent bus right now. */
 int
 ofw_isa_map_iorange(struct isa_ranges *range, int nrange, u_long *start,

==== //depot/projects/sparc64/sys/sparc64/pci/apb.c#8 (text+ko) ====

@@ -46,8 +46,13 @@
 #include <sys/malloc.h>
 #include <sys/bus.h>
 
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
 #include <machine/resource.h>
 
+#include <sparc64/pci/ofw_pci.h>
+
 #include <pci/pcivar.h>
 #include <pci/pcireg.h>
 
@@ -343,12 +348,27 @@
 }
 
 /*
- * Route an interrupt across a PCI bridge - the APB does not route interrupts,
- * and routing of interrupts that are not preinitialized is not supported yet.
+ * Route an interrupt across a PCI bridge - we need to rely on the firmware
+ * here.
  */
 static int
 apb_route_interrupt(device_t pcib, device_t dev, int pin)
 {
 
-	panic("apb_route_interrupt");
+	/*
+	 * XXX: ugly loathsome hack:
+	 * We can't use ofw_pci_route_intr() here; the device passed may be
+	 * the one of a bridge, so the original device can't be recovered.
+	 *
+	 * We need to use the firmware to route interrupts, however it has
+	 * no interface which could be used to interpret intpins; instead,
+	 * all assignments are done by device.
+	 *
+	 * The MI pci code will try to reroute interrupts of 0, although they
+	 * are correct; all other interrupts are preinitialized, so if we
+	 * get here, the intline is either 0 (so return 0), or we hit a
+	 * device which was not preinitialized (e.g. hotplugged stuff), in
+	 * which case we are lost.
+	 */
+	return (0);
 }

==== //depot/projects/sparc64/sys/sparc64/pci/ofw_pci.c#7 (text+ko) ====

@@ -50,66 +50,15 @@
 
 #include "pcib_if.h"
 
-/*
- * Find the interrupt-map properties for a node. This might not be a property
- * of the parent, because there may be bridges in between, so go up through the
- * tree to find it.
- * This seems to be only needed for PCI systems, so it has not been moved to
- * ofw_bus.c
- */
-int
-ofw_pci_find_imap(phandle_t node, struct ofw_pci_imap **imap,
-    struct ofw_pci_imap_msk *imapmsk)
+u_int32_t
+ofw_pci_route_intr(phandle_t node)
 {
-	int nimap;
+	u_int32_t rv;
 
-	nimap = -1;
-	while ((node = OF_parent(node)) != 0) {
-		if ((nimap = OF_getprop_alloc(node, "interrupt-map",
-		    sizeof(**imap), (void **)imap)) == -1 ||
-		    OF_getprop(node, "interrupt-map-mask",
-		    imapmsk, sizeof(*imapmsk)) == -1) {
-			if (*imap != NULL) {
-				free(*imap, M_OFWPROP);
-				*imap = NULL;
-			}
-			nimap = -1;
-		} else
-			break;
-	}
-	return (nimap);
-}
-
-/*
- * Route an interrupt using the firmware nodes. Returns 255 for interrupts
- * that cannot be routed (suitable for the PCI code).
- */
-int
-ofw_pci_route_intr2(int intr, struct ofw_pci_register *pcir,
-    struct ofw_pci_imap *imap, int nimap, struct ofw_pci_imap_msk *imapmsk)
-{
-	char regm[12];
-	int cintr;
-
-	cintr = ofw_bus_route_intr(intr, pcir, sizeof(*pcir), 12, 1, imap,
-	    nimap, imapmsk, regm);
-	if (cintr == -1)
+	rv = ofw_bus_route_intr(node, ORIP_NOINT);
+	if (rv == ORIR_NOTFOUND)
 		return (255);
-	else
-		return (cintr);
-}
-
-int
-ofw_pci_route_intr(phandle_t node, struct ofw_pci_register *pcir,
-    struct ofw_pci_imap *intrmap, int nintrmap,
-    struct ofw_pci_imap_msk *intrmapmsk)
-{
-	int intr;
-
-	if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1)
-		return (255);
-
-	return (ofw_pci_route_intr2(intr, pcir, intrmap, nintrmap, intrmapmsk));
+	return (rv);
 }
 
 #define	OFW_PCI_PCIBUS	"pci"
@@ -119,10 +68,8 @@
  * of attached devices using firmware information.
  */
 void
-ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap,
-    int nintrmap, struct ofw_pci_imap_msk *intrmapmsk)
+ofw_pci_init_intr(device_t dev, phandle_t bus)
 {
-	struct ofw_pci_imap_msk lintrmapmsk;
 	struct ofw_pci_register pcir;
 	phandle_t node;
 	char type[32];
@@ -146,40 +93,19 @@
 			 * deep, so recursion is feasible.
 			 */
 #ifdef OFW_PCI_DEBUG
-			device_printf(dev, __func__": descending to "
-			    "subordinate PCI bus\n");
+			device_printf(dev, "%s: descending to "
+			    "subordinate PCI bus\n", __func__);
 #endif
-			ofw_pci_init_intr(dev, node, NULL, 0, NULL);
+			ofw_pci_init_intr(dev, node);
 		} else {
 			if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
 				panic("ofw_pci_route_intr: OF_getprop failed");
-			/*
-			 * If we didn't get interrupt map properties passed,
-			 * try to find them now. On some systems, buses that
-			 * have no non-bridge children have no such properties,
-			 * so only try to find them at need.
-			 */
-			if (intrmap == NULL) {
-				nintrmap = OF_getprop_alloc(bus,
-				    "interrupt-map", sizeof(*intrmap),
-				    (void **)&intrmap);
-				if (nintrmap == -1 ||
-				    OF_getprop(bus, "interrupt-map-mask",
-				    &lintrmapmsk, sizeof(lintrmapmsk)) == -1) {
-					printf("ofw_pci_init_intr: could not get "
-					    "interrupt map properties\n");
-					if (nintrmap != -1)
-						free(intrmap, M_OFWPROP);
-					return;
-				}
-				intrmapmsk = &lintrmapmsk;
-				freemap = 1;
-			}
-			if ((intr = ofw_pci_route_intr(node, &pcir, intrmap,
-			    nintrmap, intrmapmsk)) != 255) {
+
+			if ((intr = ofw_pci_route_intr(node)) != 255) {
 #ifdef OFW_PCI_DEBUG
-				device_printf(dev, __func__": mapping intr for "
+				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),
@@ -189,7 +115,6 @@
 					OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi),
 					OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi),
 					PCIR_INTLINE, 1));
-				    
 #endif /* OFW_PCI_DEBUG */
 				PCIB_WRITE_CONFIG(dev,
 				    OFW_PCI_PHYS_HI_BUS(pcir.phys_hi),
@@ -198,8 +123,9 @@
 				    PCIR_INTLINE, intr, 1);
 			} else {
 #ifdef OFW_PCI_DEBUG
-				device_printf(dev, __func__": no interrupt "
+				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),
@@ -218,8 +144,6 @@
 			}
 		}
 	} while ((node = OF_peer(node)) != 0);
-	if (freemap)
-		free(intrmap, M_OFWPROP);
 }
 
 phandle_t
@@ -268,3 +192,11 @@
 	}
 	return (0);
 }
+
+phandle_t
+ofw_pci_node(device_t dev)
+{
+
+	return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
+	    pci_get_function(dev)));
+}

==== //depot/projects/sparc64/sys/sparc64/pci/ofw_pci.h#4 (text+ko) ====

@@ -56,18 +56,9 @@
 	u_int32_t	intr;
 };
 
-int ofw_pci_find_imap(phandle_t, struct ofw_pci_imap **,
-    struct ofw_pci_imap_msk *);
-int ofw_pci_route_intr2(int, struct ofw_pci_register *,
-    struct ofw_pci_imap *, int, struct ofw_pci_imap_msk *);
-int ofw_pci_route_intr(phandle_t, struct ofw_pci_register *,
-    struct ofw_pci_imap *, int, struct ofw_pci_imap_msk *);
-void ofw_pci_init_intr(device_t, phandle_t, struct ofw_pci_imap *, int,
-    struct ofw_pci_imap_msk *);
+u_int32_t ofw_pci_route_intr(phandle_t);
+void ofw_pci_init_intr(device_t, phandle_t);
 phandle_t ofw_pci_find_node(int, int, int);
-int ofw_pci_dev_iterate_node(device_t, phandle_t, uintptr_t *, int, int *,
-    int *, uintptr_t *, uintptr_t *);
-int ofw_pci_dev_iterate(device_t, uintptr_t *, int, int *, int *, uintptr_t *,
-    uintptr_t *);
+phandle_t ofw_pci_node(device_t);
 
 #endif /* ! _SPARC64_PCI_OFW_PCI_H_ */

==== //depot/projects/sparc64/sys/sparc64/pci/psycho.c#24 (text+ko) ====

@@ -478,16 +478,6 @@
 	/* XXX: register as root dma tag (kluge). */
 	sparc64_root_dma_tag = sc->sc_dmat;
 
-	if ((sc->sc_nintrmap = OF_getprop_alloc(sc->sc_node, "interrupt-map",
-	    sizeof(*sc->sc_intrmap), (void **)&sc->sc_intrmap)) == -1 ||
-	    OF_getprop(sc->sc_node, "interrupt-map-mask", &sc->sc_intrmapmsk,
-		sizeof(sc->sc_intrmapmsk)) == -1) {
-		if (sc->sc_intrmap != NULL) {
-			free(sc->sc_intrmap, M_OFWPROP);
-			sc->sc_intrmap = NULL;
-		}
-	}
-
 	/* Register the softc, this is needed for paired psychos. */
 	if (psycho_ndevs < sizeof(psycho_softcs) / sizeof(psycho_softcs[0]))
 		psycho_softcs[psycho_ndevs] = sc;
@@ -617,8 +607,7 @@
 	 * at least on some models, and we probably shouldn't trust that
 	 * the firmware uses the same model as this driver if it does.
 	 */
-	ofw_pci_init_intr(dev, sc->sc_node, sc->sc_intrmap, sc->sc_nintrmap,
-	    &sc->sc_intrmapmsk);
+	ofw_pci_init_intr(dev, sc->sc_node);
 
 	device_add_child(dev, "pci", device_get_unit(dev));
 	return (bus_generic_attach(dev));
@@ -969,18 +958,21 @@
 	int intline;
 
 	/*
-	 * Since we preinitialize all interrupt line registers, this should not
-	 * happen for any built-in device, except it the intline is 0.
-	 * For now, just ignore this case - 0 is a valid intline on sparc64,
-	 * but due to quirky BIOSes the PCI code attempts to route anyway.
-	 * If it is 255, we are lost for now.
-	 * Devices on bridges that route interrupts cannot work now - the
-	 * interrupt pin mappings cannot be obtained from the firmware...
+	 * XXX: ugly loathsome hack:
+	 * We can't use ofw_pci_route_intr() here; the device passed may be
+	 * the one of a bridge, so the original device can't be recovered.
+	 *
+	 * We need to use the firmware to route interrupts, however it has
+	 * no interface which could be used to interpret intpins; instead,
+	 * all assignments are done by device.
+	 *
+	 * The MI pci code will try to reroute interrupts of 0, although they
+	 * are correct; all other interrupts are preinitialized, so if we
+	 * get here, the intline is either 0 (so return 0), or we hit a
+	 * device which was not preinitialized (e.g. hotplugged stuff), in
+	 * which case we are lost.
 	 */
-	intline = pci_read_config(dev, PCIR_INTLINE, 1);
-	if (intline == 255)
-		panic("psycho_route_interrupt: can't get interrupt");
-	return (intline);
+	return (0);
 }
 
 static int

==== //depot/projects/sparc64/sys/sparc64/pci/psychovar.h#9 (text+ko) ====

@@ -74,9 +74,6 @@
 	 */
 	struct upa_ranges		*sc_range;
 	int				sc_nrange;
-	struct ofw_pci_imap	 	*sc_intrmap;
-	int				sc_nintrmap;
-	struct ofw_pci_imap_msk		sc_intrmapmsk;
 
 	/* our tags */
 	bus_space_tag_t			sc_cfgt;

==== //depot/projects/sparc64/sys/sparc64/sparc64/iommu.c#17 (text+ko) ====

@@ -246,7 +246,7 @@
 	 * Now all the hardware's working we need to setup dvma resource
 	 * management.
 	 */
-	printf("DVMA map: %lx to %lx\n",
+	printf("DVMA map: %#lx to %#lx\n",
 	    is->is_dvmabase, is->is_dvmabase +
 	    (size << (IO_PAGE_SHIFT - IOTTE_SHIFT)) - 1);
 

==== //depot/projects/sparc64/sys/sparc64/sparc64/ofw_bus.c#5 (text+ko) ====

@@ -1,3 +1,33 @@
+/*
+ * Copyright (C) 1996 Wolfgang Solfrank.
+ * Copyright (C) 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 /*-
  * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
  * All rights reserved.
@@ -22,6 +52,8 @@
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
+ *	from: $NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $
+ *
  * $FreeBSD: src/sys/sparc64/sparc64/ofw_bus.c,v 1.1 2001/11/09 20:10:55 tmm Exp $
  */
 
@@ -40,51 +72,169 @@
 
 #include <machine/ofw_bus.h>
 
+/*
+ * Other than in OpenFirmware calls, the size of a bus cell seems to be always
+ * the same.
+ */
+typedef u_int32_t pcell_t;
+
+static int
+ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
+{
+	int rv;
+
+	for (; node != 0; node = OF_parent(node)) {
+		if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
+			return (rv);
+	}
+	return (-1);
+}
+
 
 /*
- * Route an interrupt using the firmware. This takes an interrupt map and mask,
- * as retrieved from the firmware (this must be done by the caller, since it
- * is not bus-independent).
- * regs points to a "reg" property as returned by the firmware. regsz ist the
- * the size of one reg element, physz is the size of the physical address member
- * at the start of each reg (this is matched against the interrupt map).
- * The interrupt map has entries of the size (physsz + 12), the 12 being the
- * size of two u_int32_t that hold the interrupt number to compare against, the
- * node the map belongs to and the interrupt that the child interrupt is mapped
- * to (if the map entry matches).
- * The first nregs registers are checked against the map; in some cases (e.g.
- * PCI), only the first must be checked.
- * The mask consists of a mask wich must be and-ed to the checked physical
- * address part of the ofw reg and to the interrupt number before checking
- * against the map.
- * regm should point to a buffer of physsz size (this is not malloc'ed because
- * malloc cannot be called in all situations).
+ * Map an interrupt using the firmware reg, interrupt-map and
+ * interrupt-map-mask properties.
+ * The interrupt is returned in *result, which is malloc()'ed. The size of
+ * the interrupt specifiaction is returned.
  */
-u_int32_t
-ofw_bus_route_intr(int intr, void *regs, int regsz, int physsz, int nregs,
-    void *imap, int nimap, void *imapmsk, char *regm)
+static int
+ofw_bus_find_intr(u_int8_t *intr, int intrsz, u_int8_t *regs, int physsz,
+    u_int8_t *imap, int imapsz, u_int8_t *imapmsk, u_int8_t **result)
 {
+	phandle_t parent;
+	char *ref;
 	u_int8_t *mptr;
-	u_int32_t mintr, cintr;
-	int r, i;
+	pcell_t pintrsz;
+	int i, rsz, tsz;
 
-	cintr = -1;
-	bcopy((u_int8_t *)imapmsk + physsz, &mintr, sizeof(mintr));
-	mintr &= intr;
-	for (r = 0; r < nregs; r++) {
-		for (i = 0; i < physsz; i++) {
-			regm[i] = ((u_int8_t *)regs)[r * regsz + i] &
-			    ((u_int8_t *)imapmsk)[i];
+	rsz = -1;
+	ref = malloc(physsz + intrsz, M_TEMP, M_WAITOK);
+	if (imapmsk != NULL) {
+		for (i = 0; i < physsz; i++)
+			ref[i] = regs[i] & imapmsk[i];
+		for (i = 0; i < intrsz; i++)
+			ref[physsz + i] = intr[i] & imapmsk[physsz + i];
+	} else {
+		bcopy(regs, ref, physsz);
+		bcopy(intr, ref + physsz, intrsz);
+	}
+	mptr = imap;
+	i = imapsz;
+	while (i > 0) {
+		KASSERT(i >= physsz + sizeof(parent),
+		    ("ofw_bus_find_intr: truncated map"));
+		bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
+		if (ofw_bus_searchprop(parent, "#interrupt-cells",
+		    &pintrsz, sizeof(pintrsz)) == -1)
+			pintrsz = 1;	/* default */
+		pintrsz *= sizeof(pcell_t);
+		KASSERT(i >= physsz + intrsz + sizeof(parent) +
+		    pintrsz, ("ofw_bus_find_intr: truncated map"));
+		if (bcmp(ref, mptr, physsz + intrsz) == 0) {
+			*result = malloc(pintrsz, M_OFWPROP, M_WAITOK);
+			bcopy(mptr + physsz + intrsz + sizeof(parent),
+			    *result, pintrsz);
+			rsz = pintrsz;
+			break;
 		}
-		for (i = 0; i < nimap; i++) {
-			mptr = (u_int8_t *)imap + i * (physsz + 12);
-			if (bcmp(regm, mptr, physsz) == 0 &&
-			    bcmp(&mintr, mptr + physsz, sizeof(mintr)) == 0) {
-				bcopy(mptr + physsz + 8, &cintr,
-				    sizeof(cintr));
-				break;
-			}
+		tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz;
+		mptr += tsz;
+		i -= tsz;
+	}
+	free(ref, M_TEMP);
+	return (rsz);
+}
+
+/*
+ * Apply the OpenFirmware algorithm for mapping an interrupt. First, the
+ * 'interrupts' and 'reg' properties are retrieved; those are matched against
+ * 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 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)
+{
+	u_int8_t *reg, *intr, *tintr, *imap, *imapmsk;
+	phandle_t parent;
+	pcell_t addrc, ic;
+	u_int32_t rv;
+	int regsz, tisz, isz, imapsz, found;
+
+	found = 0;
+	reg = imap = imapmsk = NULL;
+	if (intrp == ORIP_NOINT) {
+		isz = OF_getprop_alloc(node, "interrupts", 1, (void **)&intr);
+		if (isz < 0)
+			return (ORIR_NOTFOUND);
+	} else {
+		ic = intrp;
+		isz = sizeof(ic);
+		intr = malloc(isz, M_OFWPROP, M_WAITOK);
+		bcopy(&ic, intr, isz);
+	}
+	/*
+	 * Note that apparently, remapping at multiple levels is allowed;
+	 * however, this causes problems with EBus at least, and seems to never
+	 * be needed, so we disable it for now (*sigh*).
+	 */
+	for (parent = OF_parent(node); parent != 0 && !found;
+	     parent = OF_parent(node = parent)) {
+		if (reg != NULL)
+			free(reg, M_OFWPROP);
+		regsz = OF_getprop_alloc(node, "reg", 1, (void **)&reg);
+		if (regsz < 0)
+			panic("ofw_bus_route_intr: could not get reg property");
+		imapsz = OF_getprop_alloc(parent, "interrupt-map", 1,
+		    (void **)&imap);
+		if (imapsz == -1)
+			continue;
+		if (OF_getprop(parent, "#address-cells", &addrc,
+		    sizeof(addrc)) == -1)
+			addrc = 2;
+		addrc *= sizeof(pcell_t);
+		/*
+		 * Failures to get the mask are ignored; a full mask is assumed
+		 * in this case.
+		 */
+		OF_getprop_alloc(parent, "interrupt-map-mask", 1,
+		    (void **)&imapmsk);
+		tisz = ofw_bus_find_intr(intr, isz, reg, addrc, imap, imapsz,
+		    imapmsk, &tintr);
+		if (tisz != -1) {
+			found = 1;
+			isz = tisz;
+			free(intr, M_OFWPROP);
+			intr = tintr;
 		}
+		free(imap, M_OFWPROP);
+		if (imapmsk != NULL)
+			free(imapmsk, M_OFWPROP);
+	}
+	if (reg != NULL)
+		free(reg, M_OFWPROP);
+#if 0
+	/*
+	 * Obviously there are some boxes that don't require mapping at all,
+	 * for example the U30, which has no interrupt maps for children of
+	 * the root PCI bus.
+	 */
+	if (!found) {
+		if (intrp != ORIP_NOINT)
+			return (ORIR_NOTFOUND);
+		panic("ofw_bus_route_intr: 'interrupts' property, but no "
+		    "mapping found");
 	}
-	return (cintr);
+#endif
+	KASSERT(isz == sizeof(u_int32_t),
+	    ("ofw_bus_route_intr: bad interrupt spec size %d", isz));
+	bcopy(intr, &rv, sizeof(rv));
+	free(intr, M_OFWPROP);
+	return (rv);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203200239.g2K2dVN60219>