svn commit: r190297 - in stable/7/sys: . conf contrib/pf dev/ath/ath_hal dev/cxgb sparc64/pci sparc64/sparc64

Marius Strobl marius at FreeBSD.org
Sun Mar 22 15:19:55 PDT 2009


Author: marius
Date: Sun Mar 22 22:19:54 2009
New Revision: 190297
URL: http://svn.freebsd.org/changeset/base/190297

Log:
  MFC: r183423, r184428, r185133, r186290, r190108
  
  Add a driver for `Schizo' Fireplane/Safari to PCI 2.1 and `Tomatillo'
  JBus to PCI 2.2 bridges including subsequent fixes and improvements
  as of r190108.

Added:
  stable/7/sys/sparc64/pci/schizo.c
     - copied, changed from r183423, head/sys/sparc64/pci/schizo.c
  stable/7/sys/sparc64/pci/schizoreg.h
     - copied, changed from r183423, head/sys/sparc64/pci/schizoreg.h
  stable/7/sys/sparc64/pci/schizovar.h
     - copied, changed from r183423, head/sys/sparc64/pci/schizovar.h
Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/conf/files.sparc64
  stable/7/sys/conf/options.sparc64
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/sparc64/sparc64/nexus.c

Modified: stable/7/sys/conf/files.sparc64
==============================================================================
--- stable/7/sys/conf/files.sparc64	Sun Mar 22 22:14:46 2009	(r190296)
+++ stable/7/sys/conf/files.sparc64	Sun Mar 22 22:19:54 2009	(r190297)
@@ -74,6 +74,7 @@ sparc64/pci/ofw_pcib.c		optional	pci
 sparc64/pci/ofw_pcib_subr.c	optional	pci
 sparc64/pci/ofw_pcibus.c	optional	pci
 sparc64/pci/psycho.c		optional	pci
+sparc64/pci/schizo.c		optional	pci
 sparc64/sbus/dma_sbus.c		optional	sbus
 sparc64/sbus/sbus.c		optional	sbus
 sparc64/sbus/lsi64854.c		optional	sbus

Modified: stable/7/sys/conf/options.sparc64
==============================================================================
--- stable/7/sys/conf/options.sparc64	Sun Mar 22 22:14:46 2009	(r190296)
+++ stable/7/sys/conf/options.sparc64	Sun Mar 22 22:19:54 2009	(r190297)
@@ -24,5 +24,7 @@ PSM_RESETAFTERSUSPEND	opt_psm.h
 DEBUGGER_ON_POWERFAIL	opt_psycho.h
 PSYCHO_DEBUG		opt_psycho.h
 
+SCHIZO_DEBUG		opt_schizo.h
+
 SUNKBD_DFLT_KEYMAP	opt_sunkbd.h
 SUNKBD_EMULATE_ATKBD	opt_sunkbd.h

Copied and modified: stable/7/sys/sparc64/pci/schizo.c (from r183423, head/sys/sparc64/pci/schizo.c)
==============================================================================
--- head/sys/sparc64/pci/schizo.c	Sun Sep 28 00:07:05 2008	(r183423, copy source)
+++ stable/7/sys/sparc64/pci/schizo.c	Sun Mar 22 22:19:54 2009	(r190297)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/pcpu.h>
 #include <sys/rman.h>
+#include <sys/time.h>
 #include <sys/timetc.h>
 
 #include <dev/ofw/ofw_bus.h>
@@ -79,11 +80,13 @@ __FBSDID("$FreeBSD$");
 static const struct schizo_desc *schizo_get_desc(device_t);
 static void schizo_set_intr(struct schizo_softc *, u_int, u_int,
     driver_filter_t);
-static driver_filter_t schizo_dmasync;
+static driver_filter_t schizo_dma_sync_stub;
+static driver_filter_t ichip_dma_sync_stub;
 static void schizo_intr_enable(void *);
 static void schizo_intr_disable(void *);
 static void schizo_intr_assign(void *);
 static void schizo_intr_clear(void *);
+static int schizo_intr_register(struct schizo_softc *sc, u_int ino);
 static int schizo_get_intrmap(struct schizo_softc *, u_int,
     bus_addr_t *, bus_addr_t *);
 static bus_space_tag_t schizo_alloc_bus_tag(struct schizo_softc *, int);
@@ -94,6 +97,7 @@ static driver_filter_t schizo_pci_bus;
 static driver_filter_t schizo_ue;
 static driver_filter_t schizo_ce;
 static driver_filter_t schizo_host_bus;
+static driver_filter_t schizo_cdma;
 
 /* IOMMU support */
 static void schizo_iommu_init(struct schizo_softc *, int, uint32_t);
@@ -145,7 +149,7 @@ static device_method_t schizo_methods[] 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_node,	schizo_get_node),
 
-	{ 0, 0 }
+	KOBJMETHOD_END
 };
 
 static devclass_t schizo_devclass;
@@ -170,14 +174,16 @@ struct schizo_icarg {
 	bus_addr_t		sica_clr;
 };
 
-struct schizo_dmasync {
+struct schizo_dma_sync {
 	struct schizo_softc	*sds_sc;
 	driver_filter_t		*sds_handler;
 	void			*sds_arg;
 	void			*sds_cookie;
-	bus_size_t		sds_syncreg;
 	uint64_t		sds_syncval;
-	u_int			sds_bswar;
+	device_t		sds_ppb;	/* farest PCI-PCI bridge */
+	uint8_t			sds_bus;	/* bus of farest PCI device */
+	uint8_t			sds_slot;	/* slot of farest PCI device */
+	uint8_t			sds_func;	/* func. of farest PCI device */
 };
 
 #define	SCHIZO_PERF_CNT_QLTY	100
@@ -212,7 +218,7 @@ struct schizo_desc {
 	const char	*sd_name;
 };
 
-static const struct schizo_desc schizo_compats[] = {
+static const struct schizo_desc const schizo_compats[] = {
 	{ "pci108e,8001",	SCHIZO_MODE_SCZ,	"Schizo" },
 	{ "pci108e,a801",	SCHIZO_MODE_TOM,	"Tomatillo" },
 	{ NULL,			0,			NULL }
@@ -252,10 +258,8 @@ schizo_attach(device_t dev)
 {
 	struct ofw_pci_ranges *range;
 	const struct schizo_desc *desc;
-	struct schizo_icarg *sica;
 	struct schizo_softc *asc, *sc, *osc;
 	struct timecounter *tc;
-	bus_addr_t intrclr, intrmap;
 	uint64_t ino_bitmap, reg;
 	phandle_t node;
 	uint32_t prop, prop_array[2];
@@ -269,6 +273,7 @@ schizo_attach(device_t dev)
 	sc->sc_dev = dev;
 	sc->sc_node = node;
 	sc->sc_mode = mode;
+	sc->sc_flags = 0;
 
 	/*
 	 * The Schizo has three register banks:
@@ -322,6 +327,8 @@ schizo_attach(device_t dev)
 			panic("%s: could not malloc mutex", __func__);
 		mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN);
 	} else {
+		if (sc->sc_mode != SCHIZO_MODE_SCZ)
+			panic("%s: no partner expected", __func__);
 		if (mtx_initialized(osc->sc_mtx) == 0)
 			panic("%s: mutex not initialized", __func__);
 		sc->sc_mtx = osc->sc_mtx;
@@ -388,9 +395,10 @@ schizo_attach(device_t dev)
 
 	/*
 	 * Hunt through all the interrupt mapping regs and register
-	 * the interrupt controller for our interrupt vectors.  This
-	 * is complicated by the fact that a pair of Schizo PBMs
-	 * share one IGN.
+	 * the interrupt controller for our interrupt vectors.  We do
+	 * this early in order to be able to catch stray interrupts.
+	 * This is complicated by the fact that a pair of Schizo PBMs
+	 * shares one IGN.
 	 */
 	n = OF_getprop(node, "ino-bitmap", (void *)prop_array,
 	    sizeof(prop_array));
@@ -403,24 +411,10 @@ schizo_attach(device_t dev)
 		if (n == STX_FB0_INO || n == STX_FB1_INO)
 			/* Leave for upa(4). */
 			continue;
-		if (schizo_get_intrmap(sc, n, &intrmap, &intrclr) == 0)
-			continue;
-		sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT);
-		if (sica == NULL)
-			panic("%s: could not allocate interrupt controller "
-			    "argument", __func__);
-		sica->sica_sc = sc;
-		sica->sica_map = intrmap;
-		sica->sica_clr = intrclr;
-#ifdef SCHIZO_DEBUG
-		device_printf(dev, "intr map (INO %d) %#lx: %#lx, clr: %#lx\n",
-		    n, (u_long)intrmap, (u_long)SCHIZO_PCI_READ_8(sc, intrmap),
-		    (u_long)intrclr);
-#endif
-		if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
-		    &schizo_ic, sica) != 0)
-			panic("%s: could not register interrupt controller "
-			    "for INO %d", __func__, n);
+		i = schizo_intr_register(sc, n);
+		if (i != 0)
+			device_printf(dev, "could not register interrupt "
+			    "controller for INO %d (%d)\n", n, i);
 	}
 
 	/*
@@ -456,11 +450,16 @@ schizo_attach(device_t dev)
 		tc_init(tc);
 	}
 
-	/* Set up the IOMMU.  Both Schizo and Tomatillo have one per PBM. */
+	/*
+	 * Set up the IOMMU.  Schizo, Tomatillo and XMITS all have
+	 * one per PBM.  Schizo and XMITS additionally have a streaming
+	 * buffer, in Schizo version < 5 (i.e. revision < 2.3) it's
+	 * affected by several errata and basically unusable though.
+	 */
 	sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(STX_IOMMU_BITS);
-	sc->sc_is.is_sb[0] = 0;
-	sc->sc_is.is_sb[1] = 0;
-	if (OF_getproplen(node, "no-streaming-cache") < 0)
+	sc->sc_is.is_sb[0] = sc->sc_is.is_sb[1] = 0;
+	if (OF_getproplen(node, "no-streaming-cache") < 0 &&
+	    !(sc->sc_mode == SCHIZO_MODE_SCZ && sc->sc_ver < 5))
 		sc->sc_is.is_sb[0] = STX_PCI_STRBUF;
 
 #define	TSBCASE(x)							\
@@ -489,6 +488,7 @@ schizo_attach(device_t dev)
 		}
 		schizo_iommu_init(sc, tsbsize, prop_array[0]);
 	}
+
 #undef TSBCASE
 
 	/* Initialize memory and I/O rmans. */
@@ -627,6 +627,39 @@ schizo_attach(device_t dev)
 		schizo_set_intr(sc, 3, STX_BUS_INO, schizo_host_bus);
 
 	/*
+	 * According to the Schizo Errata I-13, consistent DMA flushing/
+	 * syncing is FUBAR in version < 5 (i.e. revision < 2.3) bridges,
+	 * so we can't use it and need to live with the consequences.
+	 * With Schizo version >= 5, CDMA flushing/syncing is usable
+	 * but requires the the workaround described in Schizo Errata
+	 * I-23.  With Tomatillo and XMITS, CDMA flushing/syncing works
+	 * as expected, Tomatillo version <= 4 (i.e. revision <= 2.3)
+	 * bridges additionally require a block store after a write to
+	 * TOMXMS_PCI_DMA_SYNC_PEND though.
+	 */
+	if ((sc->sc_mode == SCHIZO_MODE_SCZ && sc->sc_ver >= 5) ||
+	    sc->sc_mode == SCHIZO_MODE_TOM || sc->sc_mode == SCHIZO_MODE_XMS) {
+		sc->sc_flags |= SCHIZO_FLAGS_CDMA;
+		if (sc->sc_mode == SCHIZO_MODE_SCZ) {
+			n = STX_CDMA_A_INO + sc->sc_half;
+			if (bus_set_resource(dev, SYS_RES_IRQ, 5,
+			    INTMAP_VEC(sc->sc_ign, n), 1) != 0)
+				panic("%s: failed to add CDMA interrupt",
+				    __func__);
+			i = schizo_intr_register(sc, n);
+			if (i != 0)
+				panic("%s: could not register interrupt "
+				    "controller for CDMA (%d)", __func__, i);
+			(void)schizo_get_intrmap(sc, n, NULL,
+			   &sc->sc_cdma_clr);
+			sc->sc_cdma_state = SCHIZO_CDMA_STATE_DONE;
+			schizo_set_intr(sc, 5, n, schizo_cdma);
+		}
+		if (sc->sc_mode == SCHIZO_MODE_TOM && sc->sc_ver <= 4)
+			sc->sc_flags |= SCHIZO_FLAGS_BSWAR;
+	}
+
+	/*
 	 * Set the latency timer register as this isn't always done by the
 	 * firmware.
 	 */
@@ -653,12 +686,40 @@ schizo_set_intr(struct schizo_softc *sc,
 	    INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign ||
 	    INTINO(vec) != ino ||
 	    intr_vectors[vec].iv_ic != &schizo_ic ||
-	    bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC,
-	    handler, NULL, sc, &sc->sc_ihand[index]) != 0)
+	    bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
+	    INTR_TYPE_MISC | INTR_FAST, handler, NULL, sc,
+	    &sc->sc_ihand[index]) != 0)
 		panic("%s: failed to set up interrupt %d", __func__, index);
 }
 
 static int
+schizo_intr_register(struct schizo_softc *sc, u_int ino)
+{
+	struct schizo_icarg *sica;
+	bus_addr_t intrclr, intrmap;
+	int error;
+
+	if (schizo_get_intrmap(sc, ino, &intrmap, &intrclr) == 0)
+		return (ENXIO);
+	sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT);
+	if (sica == NULL)
+		return (ENOMEM);
+	sica->sica_sc = sc;
+	sica->sica_map = intrmap;
+	sica->sica_clr = intrclr;
+#ifdef SCHIZO_DEBUG
+	device_printf(sc->sc_dev, "intr map (INO %d) %#lx: %#lx, clr: %#lx\n",
+	    ino, (u_long)intrmap, (u_long)SCHIZO_PCI_READ_8(sc, intrmap),
+	    (u_long)intrclr);
+#endif
+	error = (intr_controller_register(INTMAP_VEC(sc->sc_ign, ino),
+	    &schizo_ic, sica));
+	if (error != 0)
+		free(sica, M_DEVBUF);
+	return (error);
+}
+
+static int
 schizo_get_intrmap(struct schizo_softc *sc, u_int ino, bus_addr_t *intrmapptr,
     bus_addr_t *intrclrptr)
 {
@@ -801,6 +862,15 @@ schizo_host_bus(void *arg)
 	return (FILTER_HANDLED);
 }
 
+static int
+schizo_cdma(void *arg)
+{
+	struct schizo_softc *sc = arg;
+
+	atomic_store_rel_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_DONE);
+	return (FILTER_HANDLED);
+}
+
 static void
 schizo_iommu_init(struct schizo_softc *sc, int tsbsize, uint32_t dvmabase)
 {
@@ -947,33 +1017,65 @@ schizo_read_ivar(device_t dev, device_t 
 	return (ENOENT);
 }
 
+static int
+schizo_dma_sync_stub(void *arg)
+{
+	struct timeval cur, end;
+	struct schizo_dma_sync *sds = arg;
+	struct schizo_softc *sc = sds->sds_sc;
+	uint32_t state;
+
+	(void)PCIB_READ_CONFIG(sds->sds_ppb, sds->sds_bus, sds->sds_slot,
+	    sds->sds_func, PCIR_VENDOR, 2);
+	for (; atomic_cmpset_acq_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_DONE,
+	    SCHIZO_CDMA_STATE_PENDING) == 0;)
+		;
+	SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_clr, 1);
+	microuptime(&cur);
+	end.tv_sec = 1;
+	end.tv_usec = 0;
+	timevaladd(&end, &cur);
+	for (; (state = atomic_load_32(&sc->sc_cdma_state)) !=
+	    SCHIZO_CDMA_STATE_DONE && timevalcmp(&cur, &end, <=);)
+		microuptime(&cur);
+	if (state != SCHIZO_CDMA_STATE_DONE)
+		panic("%s: DMA does not sync", __func__);
+	return (sds->sds_handler(sds->sds_arg));
+}
+
 #define	VIS_BLOCKSIZE	64
 
 static int
-schizo_dmasync(void *arg)
+ichip_dma_sync_stub(void *arg)
 {
 	static u_char buf[VIS_BLOCKSIZE] __aligned(VIS_BLOCKSIZE);
-	struct schizo_dmasync *sds = arg;
+	struct timeval cur, end;
+	struct schizo_dma_sync *sds = arg;
 	struct schizo_softc *sc = sds->sds_sc;
-	uint64_t reg;
-	int timeout;
+	register_t reg, s;
 
-	SCHIZO_PCI_WRITE_8(sc, sds->sds_syncreg, sds->sds_syncval);
-	timeout = 1000000;
-	for (; (SCHIZO_PCI_READ_8(sc, sds->sds_syncreg) &
-	    sds->sds_syncval) != 0;)
-		if (--timeout < 0)
-			panic("%s: DMA does not sync", __func__);
+	(void)PCIB_READ_CONFIG(sds->sds_ppb, sds->sds_bus, sds->sds_slot,
+	    sds->sds_func, PCIR_VENDOR, 2);
+	SCHIZO_PCI_WRITE_8(sc, TOMXMS_PCI_DMA_SYNC_PEND, sds->sds_syncval);
+	microuptime(&cur);
+	end.tv_sec = 1;
+	end.tv_usec = 0;
+	timevaladd(&end, &cur);
+	for (; ((reg = SCHIZO_PCI_READ_8(sc, TOMXMS_PCI_DMA_SYNC_PEND)) &
+	    sds->sds_syncval) != 0 && timevalcmp(&cur, &end, <=);)
+		microuptime(&cur);
+	if ((reg & sds->sds_syncval) != 0)
+		panic("%s: DMA does not sync", __func__);
 
-	if (sds->sds_bswar != 0) {
-		critical_enter();
+	if ((sc->sc_flags & SCHIZO_FLAGS_BSWAR) != 0) {
+		s = intr_disable();
 		reg = rd(fprs);
 		wr(fprs, reg | FPRS_FEF, 0);
-		__asm__ __volatile__("stda %%f0, [%0] %1"
+		__asm __volatile("stda %%f0, [%0] %1"
 		    : : "r" (buf), "n" (ASI_BLK_COMMIT_S));
-		wr(fprs, reg, 0);
 		membar(Sync);
-		critical_exit();
+		wr(fprs, reg, 0);
+		intr_restore(s);
 	}
 	return (sds->sds_handler(sds->sds_arg));
 }
@@ -1021,56 +1123,109 @@ schizo_setup_intr(device_t dev, device_t
     int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
     void **cookiep)
 {
-	struct schizo_dmasync *sds;
+	devclass_t pci_devclass;
+	device_t cdev, pdev, pcidev;
+	struct schizo_dma_sync *sds;
 	struct schizo_softc *sc;
 	u_long vec;
-	int error;
+	int error, found;
 
 	sc = device_get_softc(dev);
 	/*
-	 * Make sure the vector is fully specified and we registered
-	 * our interrupt controller for it.
+	 * Make sure the vector is fully specified.
 	 */
 	vec = rman_get_start(ires);
-	if (INTIGN(vec) != sc->sc_ign ||
-	    intr_vectors[vec].iv_ic != &schizo_ic) {
+	if (INTIGN(vec) != sc->sc_ign) {
 		device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
 		return (EINVAL);
 	}
 
+	if (intr_vectors[vec].iv_ic == &schizo_ic) {
+		/*
+		 * Ensure we use the right softc in case the interrupt
+		 * is routed to our companion PBM for some odd reason.
+		 */
+		sc = ((struct schizo_icarg *)intr_vectors[vec].iv_icarg)->
+		    sica_sc;
+	} else if (intr_vectors[vec].iv_ic == NULL) {
+		/*
+		 * Work around broken firmware which misses entries in
+		 * the ino-bitmap.
+		 */
+		error = schizo_intr_register(sc, INTINO(vec));
+		if (error != 0) {
+			device_printf(dev, "could not register interrupt "
+			    "controller for vector 0x%lx (%d)\n", vec, error);
+			return (error);
+		}
+		if (bootverbose)
+			device_printf(dev, "belatedly registered as "
+			    "interrupt controller for vector 0x%lx\n", vec);
+	} else {
+		device_printf(dev,
+		    "invalid interrupt controller for vector 0x%lx\n", vec);
+		return (EINVAL);
+	}
+
 	/*
-	 * Schizo revision >= 2.3 (i.e. version >= 5) and Tomatillo bridges
-	 * need to be manually told to sync DMA writes.
-	 * Tomatillo revision <= 2.3 (i.e. version <= 4) bridges additionally
-	 * need a block store as a workaround for a hardware bug.
-	 * XXX setup of the wrapper and the contents of schizo_dmasync()
-	 * should be moved to schizo(4)-specific bus_dma_tag_create() and
-	 * bus_dmamap_sync() methods, respectively, once DMA tag creation
-	 * is newbus'ified, so the wrapper isn't only applied for interrupt
-	 * handlers but also for polling(4) callbacks.
+	 * Install a a wrapper for CDMA flushing/syncing for devices
+	 * behind PCI-PCI bridges if possible.
 	 */
-	if ((sc->sc_mode == SCHIZO_MODE_SCZ && sc->sc_ver >= 5) ||
-	    sc->sc_mode == SCHIZO_MODE_TOM) {
+	pcidev = NULL;
+	found = 0;
+	pci_devclass = devclass_find("pci");
+	for (cdev = child; cdev != dev; cdev = pdev) {
+		pdev = device_get_parent(cdev);
+		if (pcidev == NULL) {
+			if (device_get_devclass(pdev) != pci_devclass)
+				continue;
+			pcidev = cdev;
+			continue;
+		}
+		if (pci_get_class(cdev) == PCIC_BRIDGE &&
+		    pci_get_subclass(cdev) == PCIS_BRIDGE_PCI)
+			found = 1;
+	}
+	if ((sc->sc_flags & SCHIZO_FLAGS_CDMA) != 0) {
 		sds = malloc(sizeof(*sds), M_DEVBUF, M_NOWAIT | M_ZERO);
 		if (sds == NULL)
 			return (ENOMEM);
-		sds->sds_sc = sc;
-		sds->sds_arg = arg;
-		sds->sds_syncreg = sc->sc_mode == SCHIZO_MODE_SCZ ?
-		    SCZ_PCI_DMA_SYNC : TOMXMS_PCI_DMA_SYNC_PEND;
-		sds->sds_syncval = 1ULL << INTINO(vec);
-		if (sc->sc_mode == SCHIZO_MODE_TOM && sc->sc_ver <= 4)
-			sds->sds_bswar = 1;
-		if (intr == NULL) {
-			sds->sds_handler = filt;
-			error = bus_generic_setup_intr(dev, child, ires,
-			    flags, schizo_dmasync, intr, sds, cookiep);
-		} else {
-			sds->sds_handler = (driver_filter_t *)intr;
+		if (found != 0 && pcidev != NULL) {
+			sds->sds_sc = sc;
+			sds->sds_arg = arg;
+			sds->sds_ppb =
+			    device_get_parent(device_get_parent(pcidev));
+			sds->sds_bus = pci_get_bus(pcidev);
+			sds->sds_slot = pci_get_slot(pcidev);
+			sds->sds_func = pci_get_function(pcidev);
+			sds->sds_syncval = 1ULL << INTINO(vec);
+			if (bootverbose)
+				device_printf(dev, "installed DMA sync "
+				    "wrapper for device %d.%d on bus %d\n",
+				    sds->sds_slot, sds->sds_func,
+				    sds->sds_bus);
+
+#define	DMA_SYNC_STUB							\
+	(sc->sc_mode == SCHIZO_MODE_SCZ ? schizo_dma_sync_stub :	\
+	ichip_dma_sync_stub)
+
+			if (intr == NULL) {
+				sds->sds_handler = filt;
+				error = bus_generic_setup_intr(dev, child,
+				    ires, flags, DMA_SYNC_STUB, intr, sds,
+				    cookiep);
+			} else {
+				sds->sds_handler = (driver_filter_t *)intr;
+				error = bus_generic_setup_intr(dev, child,
+				    ires, flags, filt, (driver_intr_t *)
+				    DMA_SYNC_STUB, sds, cookiep);
+			}
+
+#undef DMA_SYNC_STUB
+
+		} else
 			error = bus_generic_setup_intr(dev, child, ires,
-			    flags, filt, (driver_intr_t *)schizo_dmasync,
-			    sds, cookiep);
-		}
+			    flags, filt, intr, arg, cookiep);
 		if (error != 0) {
 			free(sds, M_DEVBUF);
 			return (error);
@@ -1078,7 +1233,9 @@ schizo_setup_intr(device_t dev, device_t
 		sds->sds_cookie = *cookiep;
 		*cookiep = sds;
 		return (error);
-	}
+	} else if (found != 0)
+		device_printf(dev, "WARNING: using devices behind PCI-PCI "
+		    "bridges may cause data corruption\n");
 	return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
 	    arg, cookiep));
 }
@@ -1087,12 +1244,12 @@ static int
 schizo_teardown_intr(device_t dev, device_t child, struct resource *vec,
     void *cookie)
 {
-	struct schizo_dmasync *sds;
+	struct schizo_dma_sync *sds;
 	struct schizo_softc *sc;
 	int error;
 
 	sc = device_get_softc(dev);
-	if (sc->sc_mode == SCHIZO_MODE_TOM) {
+	if ((sc->sc_flags & SCHIZO_FLAGS_CDMA) != 0) {
 		sds = cookie;
 		error = bus_generic_teardown_intr(dev, child, vec,
 		    sds->sds_cookie);
@@ -1176,8 +1333,8 @@ schizo_activate_resource(device_t bus, d
 		    type, rid, r));
 	if (type == SYS_RES_MEMORY) {
 		/*
-		 * Need to memory-map the device space, as some drivers depend
-		 * on the virtual address being set and useable.
+		 * Need to memory-map the device space, as some drivers
+		 * depend on the virtual address being set and usable.
 		 */
 		error = sparc64_bus_mem_map(rman_get_bustag(r),
 		    rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);

Copied and modified: stable/7/sys/sparc64/pci/schizoreg.h (from r183423, head/sys/sparc64/pci/schizoreg.h)
==============================================================================
--- head/sys/sparc64/pci/schizoreg.h	Sun Sep 28 00:07:05 2008	(r183423, copy source)
+++ stable/7/sys/sparc64/pci/schizoreg.h	Sun Mar 22 22:19:54 2009	(r190297)
@@ -31,7 +31,7 @@
 #ifndef _SPARC64_PCI_SCHIZOREG_H_
 #define	_SPARC64_PCI_SCHIZOREG_H_
 
-#define	STX_NINTR			4
+#define	STX_NINTR			5	/* 4 via OFW + 1 CDMA */
 #define	STX_NRANGE			4
 #define	SCZ_NREG			3
 #define	TOM_NREG			4
@@ -276,6 +276,8 @@
 #define	STX_PCIERR_A_INO		0x32	/* PCI bus A error */
 #define	STX_PCIERR_B_INO		0x33	/* PCI bus B error */
 #define	STX_BUS_INO			0x34	/* Safari/JBus error */
+#define	STX_CDMA_A_INO			0x35	/* PCI bus A CDMA */
+#define	STX_CDMA_B_INO			0x36	/* PCI bus B CDMA */
 #define	STX_MAX_INO			0x37
 
 /* Device space defines */

Copied and modified: stable/7/sys/sparc64/pci/schizovar.h (from r183423, head/sys/sparc64/pci/schizovar.h)
==============================================================================
--- head/sys/sparc64/pci/schizovar.h	Sun Sep 28 00:07:05 2008	(r183423, copy source)
+++ stable/7/sys/sparc64/pci/schizovar.h	Sun Mar 22 22:19:54 2009	(r190297)
@@ -39,9 +39,18 @@ struct schizo_softc {
 	phandle_t			sc_node;
 
 	u_int				sc_mode;
-#define	SCHIZO_MODE_SCZ		1
-#define	SCHIZO_MODE_TOM		2
-#define	SCHIZO_MODE_XMS		3
+#define	SCHIZO_MODE_SCZ			0
+#define	SCHIZO_MODE_TOM			1
+#define	SCHIZO_MODE_XMS			2
+
+	u_int				sc_flags;
+#define	SCHIZO_FLAGS_BSWAR		(1 << 0)
+#define	SCHIZO_FLAGS_CDMA		(1 << 1)
+
+	bus_addr_t			sc_cdma_clr;
+	uint32_t			sc_cdma_state;
+#define	SCHIZO_CDMA_STATE_DONE		(1 << 0)
+#define	SCHIZO_CDMA_STATE_PENDING	(1 << 1)
 
 	u_int				sc_half;
 	uint32_t			sc_ign;

Modified: stable/7/sys/sparc64/sparc64/nexus.c
==============================================================================
--- stable/7/sys/sparc64/sparc64/nexus.c	Sun Mar 22 22:14:46 2009	(r190296)
+++ stable/7/sys/sparc64/sparc64/nexus.c	Sun Mar 22 22:19:54 2009	(r190297)
@@ -96,7 +96,7 @@ static ofw_bus_get_devinfo_t nexus_get_d
 #ifdef SMP
 static int nexus_bind_intr(device_t, device_t, struct resource *, int);
 #endif
-static int nexus_inlist(const char *, const char **);
+static int nexus_inlist(const char *, const char *const *);
 static struct nexus_devinfo * nexus_setup_dinfo(device_t, phandle_t);
 static void nexus_destroy_dinfo(struct nexus_devinfo *);
 static int nexus_print_res(struct nexus_devinfo *);
@@ -122,6 +122,7 @@ static device_method_t nexus_methods[] =
 	DEVMETHOD(bus_release_resource,	nexus_release_resource),
 	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
 	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
+	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
 	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
 	DEVMETHOD(bus_get_resource_list, nexus_get_resource_list),
 #ifdef SMP
@@ -145,7 +146,7 @@ static devclass_t nexus_devclass;
 DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, sizeof(struct nexus_softc));
 DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
 
-static const char *nexus_excl_name[] = {
+static const char *const nexus_excl_name[] = {
 	"aliases",
 	"associations",
 	"chosen",
@@ -159,7 +160,7 @@ static const char *nexus_excl_name[] = {
 	NULL
 };
 
-static const char *nexus_excl_type[] = {
+static const char *const nexus_excl_type[] = {
 	"cpu",
 	NULL
 };
@@ -168,7 +169,7 @@ extern struct bus_space_tag nexus_bustag
 extern struct bus_dma_tag nexus_dmatag;
 
 static int
-nexus_inlist(const char *name, const char **list)
+nexus_inlist(const char *name, const char *const *list)
 {
 	int i;
 


More information about the svn-src-stable-7 mailing list