Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/perseant-stdc-iso10646]: src/sys/arch/pmax/pmax 2202773



details:   https://anonhg.NetBSD.org/src/rev/ef842f81da71
branches:  perseant-stdc-iso10646
changeset: 850656:ef842f81da71
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Jul 16 17:35:21 2017 +0000

description:
2202773

diffstat:

 sys/arch/pmax/pmax/bus.c |  356 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 356 insertions(+), 0 deletions(-)

diffs (truncated from 360 to 300 lines):

diff -r 6740527c3e73 -r ef842f81da71 sys/arch/pmax/pmax/bus.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/pmax/pmax/bus.c  Sun Jul 16 17:35:21 2017 +0000
@@ -0,0 +1,356 @@
+/*     $NetBSD: bus.c,v 1.3.2.2 2017/07/16 17:35:21 christos Exp $     */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 THE FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.3.2.2 2017/07/16 17:35:21 christos Exp $");
+
+#include "opt_cputype.h"
+
+#define _MIPS_BUS_DMA_PRIVATE
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/mbuf.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <sys/bus.h>
+#include <machine/cpu.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <mips/cpuregs.h>
+#include <mips/locore.h>
+#include <mips/cache.h>
+
+/*
+ * The default DMA tag for all busses on the DECstation.
+ */
+struct mips_bus_dma_tag pmax_default_bus_dma_tag = {
+       ._dmamap_ops = _BUS_DMAMAP_OPS_INITIALIZER,
+       ._dmamem_ops = _BUS_DMAMEM_OPS_INITIALIZER,
+       ._dmatag_ops = _BUS_DMATAG_OPS_INITIALIZER,
+};
+
+static void normal_bus_mem_init(bus_space_tag_t, void *);
+static void _bus_dmamap_sync_r3k(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
+                                bus_size_t, int);
+#if 0
+static void _bus_dmamap_sync_r4k(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
+                                bus_size_t, int);
+#endif
+
+static struct mips_bus_space   normal_mbst;
+bus_space_tag_t        normal_memt = NULL;
+
+
+void
+pmax_bus_dma_init(void)
+{
+
+       normal_bus_mem_init(&normal_mbst, NULL);
+       normal_memt = &normal_mbst;
+
+#ifdef MIPS1
+       if (CPUISMIPS3 == 0)
+               pmax_default_bus_dma_tag._dmamap_ops.dmamap_sync = _bus_dmamap_sync_r3k;
+#endif
+#if 0
+       /* the common dmamap_sync() method should work on those */
+#ifdef MIPS3
+       if (CPUISMIPS3)
+               pmax_default_bus_dma_tag._dmamap_ops.dmamap_sync = _bus_dmamap_sync_r4k;
+#endif
+#endif
+}
+
+#ifdef MIPS1
+/*
+ * Common function for DMA map synchronization.  May be called
+ * by chipset-specific DMA map synchronization functions.
+ *
+ * This is the R3000 version.
+ */
+static void
+_bus_dmamap_sync_r3k(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+    bus_size_t len, int ops)
+{
+       bus_size_t minlen;
+       bus_addr_t addr;
+       int i;
+
+       /*
+        * Mixing PRE and POST operations is not allowed.
+        */
+       if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
+           (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
+               panic("_bus_dmamap_sync_r3k: mix PRE and POST");
+
+#ifdef DIAGNOSTIC
+       if (offset >= map->dm_mapsize)
+               panic("%s: bad offset %ju (map size is %ju)", __func__,
+                     (uintmax_t)offset, (uintmax_t)map->dm_mapsize);
+       if (len == 0 || (offset + len) > map->dm_mapsize)
+               panic("%s: bad length", __func__);
+#endif
+
+       /*
+        * The R3000 cache is write-though.  Therefore, we only need
+        * to drain the write buffer on PREWRITE.  The cache is not
+        * coherent, however, so we need to invalidate the data cache
+        * on PREREAD (should we do it POSTREAD instead?).
+        *
+        * POSTWRITE (and POSTREAD, currently) are noops.
+        */
+
+       if (ops & BUS_DMASYNC_PREWRITE) {
+               /*
+                * Flush the write buffer.
+                */
+               wbflush();
+       }
+
+       /*
+        * If we're not doing PREREAD, nothing more to do.
+        */
+       if ((ops & BUS_DMASYNC_PREREAD) == 0)
+               return;
+
+       /*
+        * No cache invlidation is necessary if the DMA map covers
+        * COHERENT DMA-safe memory (which is mapped un-cached).
+        */
+       if (map->_dm_flags & _BUS_DMAMAP_COHERENT)
+               return;
+
+       /*
+        * If we are going to hit something as large or larger
+        * than the entire data cache, just nail the whole thing.
+        *
+        * NOTE: Even though this is `wbinv_all', since the cache is
+        * write-though, it just invalidates it.
+        */
+       if (len >= mips_cache_info.mci_pdcache_size) {
+               mips_dcache_wbinv_all();
+               return;
+       }
+
+       for (i = 0; i < map->dm_nsegs && len != 0; i++) {
+               /* Find the beginning segment. */
+               if (offset >= map->dm_segs[i].ds_len) {
+                       offset -= map->dm_segs[i].ds_len;
+                       continue;
+               }
+
+               /*
+                * Now at the first segment to sync; nail 
+                * each segment until we have exhausted the
+                * length.
+                */
+               minlen = len < map->dm_segs[i].ds_len - offset ?  
+                   len : map->dm_segs[i].ds_len - offset;
+
+               addr = map->dm_segs[i].ds_addr;
+
+#ifdef BUS_DMA_DEBUG
+               printf("%s: flushing segment %d (%#jx..%#jx) ...", __func__, i,
+                   (intmax_t)addr + offset,
+                   (intmax_t)addr + offset + minlen - 1);
+#endif
+               mips_dcache_inv_range(
+                   MIPS_PHYS_TO_KSEG0(addr + offset), minlen);
+#ifdef BUS_DMA_DEBUG
+               printf("\n");
+#endif
+               offset = 0;
+               len -= minlen;
+       }
+}
+#endif /* MIPS1 */
+
+#if 0
+#ifdef MIPS3
+/*
+ * Common function for DMA map synchronization.  May be called
+ * by chipset-specific DMA map synchronization functions.
+ *
+ * This is the R4000 version.
+ */
+static void
+_bus_dmamap_sync_r4k(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+    bus_size_t len, int ops)
+{
+       bus_size_t minlen;
+       bus_addr_t addr;
+       int i, useindex;
+
+       /*
+        * Mixing PRE and POST operations is not allowed.
+        */
+       if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
+           (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
+               panic("_bus_dmamap_sync_r4k: mix PRE and POST");
+
+#ifdef DIAGNOSTIC
+       if (offset >= map->dm_mapsize)
+               panic("%s: bad offset %ju (map size is %ju)", __func__,
+                     (uintmax_t)offset, (uintmax_t)map->dm_mapsize);
+       if (len == 0 || (offset + len) > map->dm_mapsize)
+               panic("%s: bad length", __func__);
+#endif
+
+       /*
+        * The R4000 cache is virtually-indexed, write-back.  This means
+        * we need to do the following things:
+        *
+        *      PREREAD -- Invalidate D-cache.  Note we might have
+        *      to also write-back here if we have to use an Index
+        *      op, or if the buffer start/end is not cache-line aligned.
+        *
+        *      PREWRITE -- Write-back the D-cache.  If we have to use
+        *      an Index op, we also have to invalidate.  Note that if
+        *      we are doing PREREAD|PREWRITE, we can collapse everything
+        *      into a single op.
+        *
+        *      POSTREAD -- Nothing.
+        *
+        *      POSTWRITE -- Nothing.
+        */
+
+       /*
+        * Flush the write buffer.
+        * XXX Is this always necessary?
+        */
+       wbflush();
+
+       ops &= (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+       if (ops == 0)
+               return;
+
+       /*
+        * If the mapping is of COHERENT DMA-safe memory, no cache
+        * flush is necessary.
+        */
+       if (map->_dm_flags & _BUS_DMAMAP_COHERENT)
+               return;
+
+       /*
+        * If the mapping belongs to the kernel, or if it belongs
+        * to the currently-running process (XXX actually, vmspace),
+        * then we can use Hit ops.  Otherwise, Index ops.
+        *
+        * This should be true the vast majority of the time.
+        */
+       if (__predict_true(VMSPACE_IS_KERNEL_P(map->_dm_vmspace) ||
+           map->_dm_vmspace == curproc->p_vmspace))
+               useindex = 0;
+       else
+               useindex = 1;
+
+       for (i = 0; i < map->dm_nsegs && len != 0; i++) {
+               /* Find the beginning segment. */
+               if (offset >= map->dm_segs[i].ds_len) {
+                       offset -= map->dm_segs[i].ds_len;
+                       continue;
+               }
+
+               /*
+                * Now at the first segment to sync; nail
+                * each segment until we have exhausted the
+                * length.
+                */
+               minlen = len < map->dm_segs[i].ds_len - offset ?
+                   len : map->dm_segs[i].ds_len - offset;
+
+               addr = map->dm_segs[i]._ds_vaddr;
+
+#ifdef BUS_DMA_DEBUG



Home | Main Index | Thread Index | Old Index