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;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to