Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/nathanw_sa]: src/sys/arch/atari/isa Expand bus_dma implementation. It wi...
details: https://anonhg.NetBSD.org/src/rev/2e6dca02e1d1
branches: nathanw_sa
changeset: 504570:2e6dca02e1d1
user: leo <leo%NetBSD.org@localhost>
date: Fri Mar 09 20:55:48 2001 +0000
description:
Expand bus_dma implementation. It will now handle the bounce buffer
extensions needed to make the isa floppy driver on the Milan work.
diffstat:
sys/arch/atari/isa/isa_dma.c | 693 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 693 insertions(+), 0 deletions(-)
diffs (truncated from 697 to 300 lines):
diff -r f1063855ab59 -r 2e6dca02e1d1 sys/arch/atari/isa/isa_dma.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/atari/isa/isa_dma.c Fri Mar 09 20:55:48 2001 +0000
@@ -0,0 +1,693 @@
+/* $NetBSD: isa_dma.c,v 1.1.12.2 2001/03/09 20:55:48 leo Exp $ */
+
+#define ISA_DMA_STATS
+
+/*-
+ * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+
+#define _ATARI_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <uvm/uvm_extern.h>
+
+/*
+ * ISA can only DMA to 0-16M.
+ */
+#define ISA_DMA_BOUNCE_THRESHOLD (16 * 1024 * 1024)
+
+extern paddr_t avail_end;
+
+/*
+ * Cookie used by ISA dma. A pointer to one of these it stashed in
+ * the DMA map.
+ */
+struct atari_isa_dma_cookie {
+ int id_flags; /* flags; see below */
+
+ /*
+ * Information about the original buffer used during
+ * DMA map syncs. Note that origibuflen is only used
+ * for ID_BUFTYPE_LINEAR.
+ */
+ void *id_origbuf; /* pointer to orig buffer if
+ bouncing */
+ bus_size_t id_origbuflen; /* ...and size */
+ int id_buftype; /* type of buffer */
+
+ void *id_bouncebuf; /* pointer to the bounce buffer */
+ bus_size_t id_bouncebuflen; /* ...and size */
+ int id_nbouncesegs; /* number of valid bounce segs */
+ bus_dma_segment_t id_bouncesegs[0]; /* array of bounce buffer
+ physical memory segments */
+};
+
+/* id_flags */
+#define ID_MIGHT_NEED_BOUNCE 0x01 /* map could need bounce buffers */
+#define ID_HAS_BOUNCE 0x02 /* map currently has bounce buffers */
+#define ID_IS_BOUNCING 0x04 /* map is bouncing current xfer */
+
+/* id_buftype */
+#define ID_BUFTYPE_INVALID 0
+#define ID_BUFTYPE_LINEAR 1
+#define ID_BUFTYPE_MBUF 2
+#define ID_BUFTYPE_UIO 3
+#define ID_BUFTYPE_RAW 4
+
+int _isa_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *));
+void _isa_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
+int _isa_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int));
+int _isa_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int));
+int _isa_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int));
+int _isa_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int));
+void _isa_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
+void _isa_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_addr_t, bus_size_t, int));
+
+int _isa_bus_dmamem_alloc __P((bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int));
+
+int _isa_dma_alloc_bouncebuf __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_size_t, int));
+void _isa_dma_free_bouncebuf __P((bus_dma_tag_t, bus_dmamap_t));
+
+/*
+ * Entry points for ISA DMA. These are mostly wrappers around
+ * the generic functions that understand how to deal with bounce
+ * buffers, if necessary.
+ */
+struct atari_bus_dma_tag isa_bus_dma_tag = {
+ ISA_DMA_BOUNCE_THRESHOLD,
+ 0,
+ _isa_bus_dmamap_create,
+ _isa_bus_dmamap_destroy,
+ _isa_bus_dmamap_load,
+ _isa_bus_dmamap_load_mbuf,
+ _isa_bus_dmamap_load_uio,
+ _isa_bus_dmamap_load_raw,
+ _isa_bus_dmamap_unload,
+ _isa_bus_dmamap_sync,
+};
+
+/**********************************************************************
+ * bus.h dma interface entry points
+ **********************************************************************/
+
+#ifdef ISA_DMA_STATS
+#define STAT_INCR(v) (v)++
+#define STAT_DECR(v) do { \
+ if ((v) == 0) \
+ printf("%s:%d -- Already 0!\n", __FILE__, __LINE__); \
+ else \
+ (v)--; \
+ } while (0)
+u_long isa_dma_stats_loads;
+u_long isa_dma_stats_bounces;
+u_long isa_dma_stats_nbouncebufs;
+#else
+#define STAT_INCR(v)
+#define STAT_DECR(v)
+#endif
+
+/*
+ * Create an ISA DMA map.
+ */
+int
+_isa_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
+ bus_dma_tag_t t;
+ bus_size_t size;
+ int nsegments;
+ bus_size_t maxsegsz;
+ bus_size_t boundary;
+ int flags;
+ bus_dmamap_t *dmamp;
+{
+ struct atari_isa_dma_cookie *cookie;
+ bus_dmamap_t map;
+ int error, cookieflags;
+ void *cookiestore;
+ size_t cookiesize;
+
+ /* Call common function to create the basic map. */
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp);
+ if (error)
+ return (error);
+
+ map = *dmamp;
+ map->_dm_cookie = NULL;
+
+ cookiesize = sizeof(struct atari_isa_dma_cookie);
+
+ /*
+ * ISA only has 24-bits of address space. This means
+ * we can't DMA to pages over 16M. In order to DMA to
+ * arbitrary buffers, we use "bounce buffers" - pages
+ * in memory below the 16M boundary. On DMA reads,
+ * DMA happens to the bounce buffers, and is copied into
+ * the caller's buffer. On writes, data is copied into
+ * but bounce buffer, and the DMA happens from those
+ * pages. To software using the DMA mapping interface,
+ * this looks simply like a data cache.
+ *
+ * If we have more than 16M of RAM in the system, we may
+ * need bounce buffers. We check and remember that here.
+ *
+ * There are exceptions, however. VLB devices can do
+ * 32-bit DMA, and indicate that here.
+ *
+ * ...or, there is an opposite case. The most segments
+ * a transfer will require is (maxxfer / PAGE_SIZE) + 1. If
+ * the caller can't handle that many segments (e.g. the
+ * ISA DMA controller), we may have to bounce it as well.
+ */
+ if (avail_end <= t->_bounce_thresh ||
+ (flags & ISABUS_DMA_32BIT) != 0) {
+ /* Bouncing not necessary due to memory size. */
+ map->_dm_bounce_thresh = 0;
+ }
+ cookieflags = 0;
+ if (map->_dm_bounce_thresh != 0 ||
+ ((map->_dm_size / PAGE_SIZE) + 1) > map->_dm_segcnt) {
+ cookieflags |= ID_MIGHT_NEED_BOUNCE;
+ cookiesize += (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
+ }
+
+ /*
+ * Allocate our cookie.
+ */
+ if ((cookiestore = malloc(cookiesize, M_DMAMAP,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ memset(cookiestore, 0, cookiesize);
+ cookie = (struct atari_isa_dma_cookie *)cookiestore;
+ cookie->id_flags = cookieflags;
+ map->_dm_cookie = cookie;
+
+ if (cookieflags & ID_MIGHT_NEED_BOUNCE) {
+ /*
+ * Allocate the bounce pages now if the caller
+ * wishes us to do so.
+ */
+ if ((flags & BUS_DMA_ALLOCNOW) == 0)
+ goto out;
+
+ error = _isa_dma_alloc_bouncebuf(t, map, size, flags);
+ }
+
+ out:
+ if (error) {
+ if (map->_dm_cookie != NULL)
+ free(map->_dm_cookie, M_DMAMAP);
+ _bus_dmamap_destroy(t, map);
+ }
+ return (error);
+}
+
+/*
+ * Destroy an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct atari_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ /*
+ * Free any bounce pages this map might hold.
+ */
+ if (cookie->id_flags & ID_HAS_BOUNCE)
+ _isa_dma_free_bouncebuf(t, map);
+
+ free(cookie, M_DMAMAP);
+ _bus_dmamap_destroy(t, map);
+}
+
+/*
+ * Load an ISA DMA map with a linear buffer.
+ */
+int
+_isa_bus_dmamap_load(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ struct atari_isa_dma_cookie *cookie = map->_dm_cookie;
+ int error;
+
+ STAT_INCR(isa_dma_stats_loads);
+
+ /*
+ * Make sure that on error condition we return "no valid mappings."
Home |
Main Index |
Thread Index |
Old Index