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