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