summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1998-01-20 18:40:37 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1998-01-20 18:40:37 +0000
commite4232757b30346a182214fb65da8a76f2edb7b24 (patch)
tree5c1b89b92ef8c67dfa2d0f3a078804042a1555ee /sys/arch/i386
parent0a8f2cc87f99deec610ef91696850a249bd8fb81 (diff)
Merge bus_dma support from NetBSD, mostly by Jason Thorpe. Only i386 uses it
so far, the other archs gets placeholders for now. I wrote a compatibility layer for OpenBSD's old isadma code so we can still use our old driver sources. They will however get changed to native bus_dma use, on a case by case basis. Oh yes, I almost forgot, I kept our notion of isadma being a device so DMA-less ISA-busses still work
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/eisa/eisa_machdep.c63
-rw-r--r--sys/arch/i386/eisa/eisa_machdep.h6
-rw-r--r--sys/arch/i386/i386/machdep.c484
-rw-r--r--sys/arch/i386/i386/mainbus.c13
-rw-r--r--sys/arch/i386/i386/pmap.c16
-rw-r--r--sys/arch/i386/i386/pmap.old.c16
-rw-r--r--sys/arch/i386/include/bus.h210
-rw-r--r--sys/arch/i386/isa/isa_machdep.c844
-rw-r--r--sys/arch/i386/isa/isa_machdep.h67
-rw-r--r--sys/arch/i386/pci/pchb.c3
-rw-r--r--sys/arch/i386/pci/pci_machdep.c65
-rw-r--r--sys/arch/i386/pci/pci_machdep.h6
12 files changed, 1539 insertions, 254 deletions
diff --git a/sys/arch/i386/eisa/eisa_machdep.c b/sys/arch/i386/eisa/eisa_machdep.c
index fd1e28c11a3..766b3a0cb45 100644
--- a/sys/arch/i386/eisa/eisa_machdep.c
+++ b/sys/arch/i386/eisa/eisa_machdep.c
@@ -1,4 +1,41 @@
-/* $NetBSD: eisa_machdep.c,v 1.2 1996/04/11 22:15:08 cgd Exp $ */
+/* $NetBSD: eisa_machdep.c,v 1.6 1997/06/06 23:12:52 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 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.
+ * 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.
+ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -41,10 +78,34 @@
#include <sys/errno.h>
#include <sys/device.h>
+#define _I386_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
#include <i386/isa/icu.h>
#include <dev/isa/isavar.h>
#include <dev/eisa/eisavar.h>
+/*
+ * EISA doesn't have any special needs; just use the generic versions
+ * of these funcions.
+ */
+struct i386_bus_dma_tag eisa_bus_dma_tag = {
+ NULL, /* _cookie */
+ _bus_dmamap_create,
+ _bus_dmamap_destroy,
+ _bus_dmamap_load,
+ _bus_dmamap_load_mbuf,
+ _bus_dmamap_load_uio,
+ _bus_dmamap_load_raw,
+ _bus_dmamap_unload,
+ NULL, /* _dmamap_sync */
+ _bus_dmamem_alloc,
+ _bus_dmamem_free,
+ _bus_dmamem_map,
+ _bus_dmamem_unmap,
+ _bus_dmamem_mmap,
+};
+
void
eisa_attach_hook(parent, self, eba)
struct device *parent, *self;
diff --git a/sys/arch/i386/eisa/eisa_machdep.h b/sys/arch/i386/eisa/eisa_machdep.h
index 2e4f1019e2f..2ac1f5810c3 100644
--- a/sys/arch/i386/eisa/eisa_machdep.h
+++ b/sys/arch/i386/eisa/eisa_machdep.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: eisa_machdep.h,v 1.2 1996/04/21 22:16:19 deraadt Exp $ */
-/* $NetBSD: eisa_machdep.h,v 1.2 1996/04/09 23:00:27 cgd Exp $ */
+/* $OpenBSD: eisa_machdep.h,v 1.3 1998/01/20 18:40:13 niklas Exp $ */
+/* $NetBSD: eisa_machdep.h,v 1.4 1997/06/06 23:12:52 thorpej Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -43,6 +43,8 @@
#define EISA_ID_LEN (sizeof(EISA_ID) - 1)
#define EISA_ID_PADDR 0xfffd9
+extern struct i386_bus_dma_tag eisa_bus_dma_tag;
+
/*
* Types provided to machine-independent EISA code.
*/
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 04ad65d6059..c4b01b7534f 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,7 +1,44 @@
-/* $OpenBSD: machdep.c,v 1.75 1998/01/17 09:57:05 niklas Exp $ */
+/* $OpenBSD: machdep.c,v 1.76 1998/01/20 18:40:14 niklas Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
+ * Copyright (c) 1996, 1997 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.
+ * 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.
+ */
+
+/*-
* Copyright (c) 1993, 1994, 1995, 1996 Charles M. Hannum. All rights reserved.
* Copyright (c) 1992 Terrence R. Lambert.
* Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
@@ -82,6 +119,9 @@
#include <sys/sysctl.h>
+#define _I386_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/gdt.h>
@@ -116,6 +156,7 @@
#endif
#include "isa.h"
+#include "isadma.h"
#include "npx.h"
#if NNPX > 0
extern struct proc *npxproc;
@@ -125,6 +166,7 @@ extern struct proc *npxproc;
/* the following is used externally (sysctl_hw) */
char machine[] = "i386"; /* cpu "architecture" */
+char machine_arch[] = "i386"; /* machine == machine_arch */
/*
* Declare these as initialized data so we can patch them.
@@ -1537,6 +1579,25 @@ init386(first_avail)
printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM IOMEM EXTENT MAP!\n");
}
+#if NISADMA > 0
+ /*
+ * Some motherboards/BIOSes remap the 384K of RAM that would
+ * normally be covered by the ISA hole to the end of memory
+ * so that it can be used. However, on a 16M system, this
+ * would cause bounce buffers to be allocated and used.
+ * This is not desirable behaviour, as more than 384K of
+ * bounce buffers might be allocated. As a work-around,
+ * we round memory down to the nearest 1M boundary if
+ * we're using any isadma devices and the remapped memory
+ * is what puts us over 16M.
+ */
+ if (extmem > (15*1024) && extmem < (16*1024)) {
+ printf("Warning: ignoring %dk of remapped memory\n",
+ extmem - (15*1024));
+ extmem = (15*1024);
+ }
+#endif
+
/* Round down to whole pages. */
cm = i386_round_page(cnvmem * 1024);
em = i386_round_page(extmem * 1024);
@@ -2002,3 +2063,424 @@ bus_space_subregion(t, bsh, offset, size, nbshp)
*nbshp = bsh + offset;
return (0);
}
+
+/*
+ * Common function for DMA map creation. May be called by bus-specific
+ * DMA map creation functions.
+ */
+int
+_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 i386_bus_dmamap *map;
+ void *mapstore;
+ size_t mapsize;
+
+ /*
+ * Allocate and initialize the DMA map. The end of the map
+ * is a variable-sized array of segments, so we allocate enough
+ * room for them in one shot.
+ *
+ * Note we don't preserve the WAITOK or NOWAIT flags. Preservation
+ * of ALLOCNOW notifies others that we've reserved these resources,
+ * and they are not to be freed.
+ *
+ * The bus_dmamap_t includes one bus_dma_segment_t, hence
+ * the (nsegments - 1).
+ */
+ mapsize = sizeof(struct i386_bus_dmamap) +
+ (sizeof(bus_dma_segment_t) * (nsegments - 1));
+ if ((mapstore = malloc(mapsize, M_DEVBUF,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
+ return (ENOMEM);
+
+ bzero(mapstore, mapsize);
+ map = (struct i386_bus_dmamap *)mapstore;
+ map->_dm_size = size;
+ map->_dm_segcnt = nsegments;
+ map->_dm_maxsegsz = maxsegsz;
+ map->_dm_boundary = boundary;
+ map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+ map->dm_nsegs = 0; /* no valid mappings */
+
+ *dmamp = map;
+ return (0);
+}
+
+/*
+ * Common function for DMA map destruction. May be called by bus-specific
+ * DMA map destruction functions.
+ */
+void
+_bus_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ free(map, M_DEVBUF);
+}
+
+/*
+ * Common function for loading a DMA map with a linear buffer. May
+ * be called by bus-specific DMA map load functions.
+ */
+int
+_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;
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr, lastaddr;
+ caddr_t vaddr = buf;
+ int first, seg;
+ pmap_t pmap;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_nsegs = 0;
+
+ if (buflen > map->_dm_size)
+ return (EINVAL);
+
+ /*
+ * XXX Need to implement "don't dma across this boundry".
+ */
+
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ lastaddr = ~0; /* XXX gcc */
+ for (first = 1, seg = 0; buflen > 0 && seg < map->_dm_segcnt; ) {
+ /*
+ * Get the physical address for this segment.
+ */
+ curaddr = (bus_addr_t)pmap_extract(pmap, (vm_offset_t)vaddr);
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = NBPG - ((u_long)vaddr & PGOFSET);
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ /*
+ * Insert chunk into a segment, coalescing with
+ * previous segment if possible.
+ */
+ if (first) {
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ first = 0;
+ } else {
+ if (curaddr == lastaddr &&
+ (map->dm_segs[seg].ds_len + sgsize) <=
+ map->_dm_maxsegsz)
+ map->dm_segs[seg].ds_len += sgsize;
+ else {
+ seg++;
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ }
+ }
+
+ lastaddr = curaddr + sgsize;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0)
+ return (EFBIG); /* XXX better return value here? */
+
+ map->dm_nsegs = seg + 1;
+ return (0);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for mbufs.
+ */
+int
+_bus_dmamap_load_mbuf(t, map, m, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m;
+ int flags;
+{
+
+ panic("_bus_dmamap_load: not implemented");
+}
+
+/*
+ * Like _bus_dmamap_load(), but for uios.
+ */
+int
+_bus_dmamap_load_uio(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
+{
+
+ panic("_bus_dmamap_load_uio: not implemented");
+}
+
+/*
+ * Like _bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
+int
+_bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+
+ panic("_bus_dmamap_load_raw: not implemented");
+}
+
+/*
+ * Common function for unloading a DMA map. May be called by
+ * bus-specific DMA map unload functions.
+ */
+void
+_bus_dmamap_unload(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ /*
+ * No resources to free; just mark the mappings as
+ * invalid.
+ */
+ map->dm_nsegs = 0;
+}
+
+/*
+ * Common function for DMA map synchronization. May be called
+ * by bus-specific DMA map synchronization functions.
+ */
+void
+_bus_dmamap_sync(t, map, op)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dmasync_op_t op;
+{
+
+ /* Nothing to do here. */
+}
+
+/*
+ * Common function for DMA-safe memory allocation. May be called
+ * by bus-specific DMA memory allocation functions.
+ */
+int
+_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+{
+
+ return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, trunc_page(avail_end)));
+}
+
+/*
+ * Common function for freeing DMA-safe memory. May be called by
+ * bus-specific DMA memory free functions.
+ */
+void
+_bus_dmamem_free(t, segs, nsegs)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+{
+ vm_page_t m;
+ bus_addr_t addr;
+ struct pglist mlist;
+ int curseg;
+
+ /*
+ * Build a list of pages to free back to the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE) {
+ m = PHYS_TO_VM_PAGE(addr);
+ TAILQ_INSERT_TAIL(&mlist, m, pageq);
+ }
+ }
+
+ vm_page_free_memory(&mlist);
+}
+
+/*
+ * Common function for mapping DMA-safe memory. May be called by
+ * bus-specific DMA memory map functions.
+ */
+int
+_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ size_t size;
+ caddr_t *kvap;
+ int flags;
+{
+ vm_offset_t va;
+ bus_addr_t addr;
+ int curseg;
+
+ size = round_page(size);
+ va = kmem_alloc_pageable(kmem_map, size);
+ if (va == 0)
+ return (ENOMEM);
+
+ *kvap = (caddr_t)va;
+
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += NBPG, va += NBPG, size -= NBPG) {
+ if (size == 0)
+ panic("_bus_dmamem_map: size botch");
+ pmap_enter(pmap_kernel(), va, addr,
+ VM_PROT_READ | VM_PROT_WRITE, TRUE);
+#if 0
+ if (flags & BUS_DMAMEM_NOSYNC)
+ pmap_changebit(addr, PG_N, ~0);
+ else
+ pmap_changebit(addr, 0, ~PG_N);
+#endif
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Common function for unmapping DMA-safe memory. May be called by
+ * bus-specific DMA memory unmapping functions.
+ */
+void
+_bus_dmamem_unmap(t, kva, size)
+ bus_dma_tag_t t;
+ caddr_t kva;
+ size_t size;
+{
+
+#ifdef DIAGNOSTIC
+ if ((u_long)kva & PGOFSET)
+ panic("_bus_dmamem_unmap");
+#endif
+
+ size = round_page(size);
+ kmem_free(kmem_map, (vm_offset_t)kva, size);
+}
+
+/*
+ * Common functin for mmap(2)'ing DMA-safe memory. May be called by
+ * bus-specific DMA mmap(2)'ing functions.
+ */
+int
+_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs, off, prot, flags;
+{
+
+ panic("_bus_dmamem_mmap: not implemented");
+}
+
+/**********************************************************************
+ * DMA utility functions
+ **********************************************************************/
+
+/*
+ * Allocate physical memory from the given physical address range.
+ * Called by DMA-safe memory allocation methods.
+ */
+int
+_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
+ flags, low, high)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+ vm_offset_t low;
+ vm_offset_t high;
+{
+ vm_offset_t curaddr, lastaddr;
+ vm_page_t m;
+ struct pglist mlist;
+ int curseg, error;
+
+ /* Always round the size. */
+ size = round_page(size);
+
+ /*
+ * Allocate pages from the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ error = vm_page_alloc_memory(size, low, high,
+ alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
+ if (error)
+ return (error);
+
+ /*
+ * Compute the location, size, and number of segments actually
+ * returned by the VM code.
+ */
+ m = mlist.tqh_first;
+ curseg = 0;
+ lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
+ segs[curseg].ds_len = PAGE_SIZE;
+ m = m->pageq.tqe_next;
+
+ for (; m != NULL; m = m->pageq.tqe_next) {
+ curaddr = VM_PAGE_TO_PHYS(m);
+#ifdef DIAGNOSTIC
+ if (curaddr < low || curaddr >= high) {
+ printf("vm_page_alloc_memory returned non-sensical"
+ " address 0x%lx\n", curaddr);
+ panic("_bus_dmamem_alloc_range");
+ }
+#endif
+ if (curaddr == (lastaddr + PAGE_SIZE))
+ segs[curseg].ds_len += PAGE_SIZE;
+ else {
+ curseg++;
+ segs[curseg].ds_addr = curaddr;
+ segs[curseg].ds_len = PAGE_SIZE;
+ }
+ lastaddr = curaddr;
+ }
+
+ *rsegs = curseg + 1;
+
+ return (0);
+}
diff --git a/sys/arch/i386/i386/mainbus.c b/sys/arch/i386/i386/mainbus.c
index 384c7ffc7d6..fe240425ea4 100644
--- a/sys/arch/i386/i386/mainbus.c
+++ b/sys/arch/i386/i386/mainbus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mainbus.c,v 1.12 1997/12/25 06:09:52 downsj Exp $ */
-/* $NetBSD: mainbus.c,v 1.8 1996/04/11 22:13:37 cgd Exp $ */
+/* $OpenBSD: mainbus.c,v 1.13 1998/01/20 18:40:15 niklas Exp $ */
+/* $NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -45,6 +45,8 @@
#include <i386/isa/isa_machdep.h>
#include "pci.h"
+#include "eisa.h"
+#include "isa.h"
#include "apm.h"
#include "bios.h"
@@ -125,6 +127,7 @@ mainbus_attach(parent, self, aux)
mba.mba_pba.pba_busname = "pci";
mba.mba_pba.pba_iot = I386_BUS_SPACE_IO;
mba.mba_pba.pba_memt = I386_BUS_SPACE_MEM;
+ mba.mba_pba.pba_dmat = &pci_bus_dma_tag;
mba.mba_pba.pba_bus = 0;
config_found(self, &mba.mba_pba, mainbus_print);
}
@@ -134,6 +137,9 @@ mainbus_attach(parent, self, aux)
mba.mba_eba.eba_busname = "eisa";
mba.mba_eba.eba_iot = I386_BUS_SPACE_IO;
mba.mba_eba.eba_memt = I386_BUS_SPACE_MEM;
+#if NEISA > 0
+ mba.mba_eba.eba_dmat = &eisa_bus_dma_tag;
+#endif
config_found(self, &mba.mba_eba, mainbus_print);
}
@@ -141,6 +147,9 @@ mainbus_attach(parent, self, aux)
mba.mba_iba.iba_busname = "isa";
mba.mba_iba.iba_iot = I386_BUS_SPACE_IO;
mba.mba_iba.iba_memt = I386_BUS_SPACE_MEM;
+#if NISA > 0
+ mba.mba_iba.iba_dmat = &isa_bus_dma_tag;
+#endif
config_found(self, &mba.mba_iba, mainbus_print);
}
}
diff --git a/sys/arch/i386/i386/pmap.c b/sys/arch/i386/i386/pmap.c
index 890b6dbfdbf..bf773284dde 100644
--- a/sys/arch/i386/i386/pmap.c
+++ b/sys/arch/i386/i386/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.22 1997/10/25 06:57:59 niklas Exp $ */
+/* $OpenBSD: pmap.c,v 1.23 1998/01/20 18:40:15 niklas Exp $ */
/* $NetBSD: pmap.c,v 1.36 1996/05/03 19:42:22 christos Exp $ */
/*
@@ -287,20 +287,6 @@ pmap_bootstrap(virtual_start)
*/
virtual_avail = reserve_dumppages(virtual_avail);
- /*
- * reserve special hunk of memory for use by bus dma as a bounce
- * buffer (contiguous virtual *and* physical memory). XXX
- */
-#if NISA > 0 && NISADMA > 0
- if (ctob(physmem) >= 0x1000000) {
- isaphysmem = pmap_steal_memory(DMA_BOUNCE * NBPG);
- isaphysmempgs = DMA_BOUNCE;
- } else {
- isaphysmem = pmap_steal_memory(DMA_BOUNCE_LOW * NBPG);
- isaphysmempgs = DMA_BOUNCE_LOW;
- }
-#endif
-
/* flawed, no mappings?? */
if (ctob(physmem) > 31*1024*1024 && MAXKPDE != NKPDE) {
vm_offset_t p;
diff --git a/sys/arch/i386/i386/pmap.old.c b/sys/arch/i386/i386/pmap.old.c
index 9ede2c1ca21..fc10b16125b 100644
--- a/sys/arch/i386/i386/pmap.old.c
+++ b/sys/arch/i386/i386/pmap.old.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.old.c,v 1.22 1997/10/25 06:57:59 niklas Exp $ */
+/* $OpenBSD: pmap.old.c,v 1.23 1998/01/20 18:40:15 niklas Exp $ */
/* $NetBSD: pmap.c,v 1.36 1996/05/03 19:42:22 christos Exp $ */
/*
@@ -287,20 +287,6 @@ pmap_bootstrap(virtual_start)
*/
virtual_avail = reserve_dumppages(virtual_avail);
- /*
- * reserve special hunk of memory for use by bus dma as a bounce
- * buffer (contiguous virtual *and* physical memory). XXX
- */
-#if NISA > 0 && NISADMA > 0
- if (ctob(physmem) >= 0x1000000) {
- isaphysmem = pmap_steal_memory(DMA_BOUNCE * NBPG);
- isaphysmempgs = DMA_BOUNCE;
- } else {
- isaphysmem = pmap_steal_memory(DMA_BOUNCE_LOW * NBPG);
- isaphysmempgs = DMA_BOUNCE_LOW;
- }
-#endif
-
/* flawed, no mappings?? */
if (ctob(physmem) > 31*1024*1024 && MAXKPDE != NKPDE) {
vm_offset_t p;
diff --git a/sys/arch/i386/include/bus.h b/sys/arch/i386/include/bus.h
index 48d8bd81201..15c457b6c90 100644
--- a/sys/arch/i386/include/bus.h
+++ b/sys/arch/i386/include/bus.h
@@ -1,6 +1,43 @@
-/* $OpenBSD: bus.h,v 1.9 1998/01/17 09:58:39 niklas Exp $ */
+/* $OpenBSD: bus.h,v 1.10 1998/01/20 18:40:17 niklas Exp $ */
/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */
+/*-
+ * Copyright (c) 1996, 1997 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.
+ * 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.
+ */
+
/*
* Copyright (c) 1996 Charles M. Hannum. All rights reserved.
* Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
@@ -697,4 +734,175 @@ void bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh,
#define BUS_BARRIER_READ 0x01 /* force read barrier */
#define BUS_BARRIER_WRITE 0x02 /* force write barrier */
+/*
+ * Flags used in various bus DMA methods.
+ */
+#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */
+#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */
+#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */
+#define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */
+#define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */
+#define BUS_DMA_BUS2 0x20
+#define BUS_DMA_BUS3 0x40
+#define BUS_DMA_BUS4 0x80
+
+/* Forwards needed by prototypes below. */
+struct mbuf;
+struct uio;
+
+/*
+ * bus_dmasync_op_t
+ *
+ * Operations performed by bus_dmamap_sync().
+ */
+typedef enum {
+ BUS_DMASYNC_PREREAD,
+ BUS_DMASYNC_POSTREAD,
+ BUS_DMASYNC_PREWRITE,
+ BUS_DMASYNC_POSTWRITE,
+} bus_dmasync_op_t;
+
+typedef struct i386_bus_dma_tag *bus_dma_tag_t;
+typedef struct i386_bus_dmamap *bus_dmamap_t;
+
+/*
+ * bus_dma_segment_t
+ *
+ * Describes a single contiguous DMA transaction. Values
+ * are suitable for programming into DMA registers.
+ */
+struct i386_bus_dma_segment {
+ bus_addr_t ds_addr; /* DMA address */
+ bus_size_t ds_len; /* length of transfer */
+};
+typedef struct i386_bus_dma_segment bus_dma_segment_t;
+
+/*
+ * bus_dma_tag_t
+ *
+ * A machine-dependent opaque type describing the implementation of
+ * DMA for a given bus.
+ */
+
+struct i386_bus_dma_tag {
+ void *_cookie; /* cookie used in the guts */
+
+ /*
+ * DMA mapping methods.
+ */
+ int (*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *));
+ void (*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
+ int (*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int));
+ int (*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int));
+ int (*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int));
+ int (*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int));
+ void (*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
+ void (*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dmasync_op_t));
+
+ /*
+ * DMA memory utility functions.
+ */
+ int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int));
+ void (*_dmamem_free) __P((bus_dma_tag_t,
+ bus_dma_segment_t *, int));
+ int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int));
+ void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
+ int (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
+ int, int, int, int));
+};
+
+#define bus_dmamap_create(t, s, n, m, b, f, p) \
+ (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
+#define bus_dmamap_destroy(t, p) \
+ (*(t)->_dmamap_destroy)((t), (p))
+#define bus_dmamap_load(t, m, b, s, p, f) \
+ (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
+#define bus_dmamap_load_mbuf(t, m, b, f) \
+ (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
+#define bus_dmamap_load_uio(t, m, u, f) \
+ (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
+#define bus_dmamap_load_raw(t, m, sg, n, s, f) \
+ (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
+#define bus_dmamap_unload(t, p) \
+ (*(t)->_dmamap_unload)((t), (p))
+#define bus_dmamap_sync(t, p, o) \
+ (void)((t)->_dmamap_sync ? \
+ (*(t)->_dmamap_sync)((t), (p), (o)) : (void)0)
+
+#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
+ (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
+#define bus_dmamem_free(t, sg, n) \
+ (*(t)->_dmamem_free)((t), (sg), (n))
+#define bus_dmamem_map(t, sg, n, s, k, f) \
+ (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
+#define bus_dmamem_unmap(t, k, s) \
+ (*(t)->_dmamem_unmap)((t), (k), (s))
+#define bus_dmamem_mmap(t, sg, n, o, p, f) \
+ (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
+
+/*
+ * bus_dmamap_t
+ *
+ * Describes a DMA mapping.
+ */
+struct i386_bus_dmamap {
+ /*
+ * PRIVATE MEMBERS: not for use my machine-independent code.
+ */
+ bus_size_t _dm_size; /* largest DMA transfer mappable */
+ int _dm_segcnt; /* number of segs this map can map */
+ bus_size_t _dm_maxsegsz; /* largest possible segment */
+ bus_size_t _dm_boundary; /* don't cross this */
+ int _dm_flags; /* misc. flags */
+
+ void *_dm_cookie; /* cookie for bus-specific functions */
+
+ /*
+ * PUBLIC MEMBERS: these are used by machine-independent code.
+ */
+ int dm_nsegs; /* # valid segments in mapping */
+ bus_dma_segment_t dm_segs[1]; /* segments; variable length */
+};
+
+#ifdef _I386_BUS_DMA_PRIVATE
+int _bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
+ bus_size_t, int, bus_dmamap_t *));
+void _bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
+int _bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int));
+int _bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int));
+int _bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int));
+int _bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int));
+void _bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
+void _bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t));
+
+int _bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary,
+ bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
+void _bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs));
+int _bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs, size_t size, caddr_t *kvap, int flags));
+void _bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
+ size_t size));
+int _bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs, int off, int prot, int flags));
+
+int _bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary,
+ bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
+ vm_offset_t low, vm_offset_t high));
+#endif /* _I386_BUS_DMA_PRIVATE */
+
#endif /* _I386_BUS_H_ */
diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c
index de30e9e4e32..c907f63e7d5 100644
--- a/sys/arch/i386/isa/isa_machdep.c
+++ b/sys/arch/i386/isa/isa_machdep.c
@@ -1,5 +1,44 @@
-/* $OpenBSD: isa_machdep.c,v 1.26 1997/12/25 12:49:04 downsj Exp $ */
-/* $NetBSD: isa_machdep.c,v 1.14 1996/05/12 23:06:18 mycroft Exp $ */
+/* $OpenBSD: isa_machdep.c,v 1.27 1998/01/20 18:40:20 niklas Exp $ */
+/* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */
+
+#define ISA_DMA_STATS
+
+/*-
+ * Copyright (c) 1996, 1997 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.
+ * 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.
+ */
/*-
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -87,6 +126,9 @@
#include <vm/vm.h>
+#define _I386_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
#include <machine/pio.h>
#include <machine/cpufunc.h>
@@ -96,6 +138,17 @@
#include <i386/isa/isa_machdep.h>
#include <i386/isa/icu.h>
+#include <vm/vm.h>
+
+#include "isadma.h"
+
+/*
+ * ISA can only DMA to 0-16M.
+ */
+#define ISA_DMA_BOUNCE_THRESHOLD 0x00ffffff
+
+extern vm_offset_t avail_end;
+
#define IDTVEC(name) __CONCAT(X,name)
/* default interrupt vector table entries */
typedef (*vector) __P((void));
@@ -104,13 +157,63 @@ void isa_strayintr __P((int));
void intr_calculatemasks __P((void));
int fakeintr __P((void *));
-vm_offset_t bounce_alloc __P((vm_size_t, vm_offset_t, int));
-caddr_t bounce_vaddr __P((vm_offset_t));
-void bounce_free __P((vm_offset_t, vm_size_t));
-void isadma_copyfrombuf __P((caddr_t, vm_size_t, int, struct isadma_seg *));
+#if NISADMA > 0
+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_dmasync_op_t));
+
+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));
+void _isa_bus_dmamem_free __P((bus_dma_tag_t,
+ bus_dma_segment_t *, int));
+int _isa_bus_dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int));
+void _isa_bus_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t));
+int _isa_bus_dmamem_mmap __P((bus_dma_tag_t, bus_dma_segment_t *,
+ int, int, int, int));
+
+int _isa_dma_check_buffer __P((void *, bus_size_t, int, bus_size_t,
+ struct proc *));
+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));
/*
- * Fill in default interrupt table (in case of spuruious interrupt
+ * Entry points for ISA DMA. These are mostly wrappers around
+ * the generic functions that understand how to deal with bounce
+ * buffers, if necessary.
+ */
+struct i386_bus_dma_tag isa_bus_dma_tag = {
+ NULL, /* _cookie */
+ _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,
+ _isa_bus_dmamem_alloc,
+ _isa_bus_dmamem_free,
+ _isa_bus_dmamem_map,
+ _isa_bus_dmamem_unmap,
+ _isa_bus_dmamem_mmap,
+};
+#endif /* NISADMA > 0 */
+
+/*
+ * Fill in default interrupt table (in case of spurious interrupt
* during configuration of kernel, setup interrupt control unit
*/
void
@@ -465,167 +568,533 @@ isa_attach_hook(parent, self, iba)
isa_has_been_seen = 1;
}
+#if NISADMA > 0
+/**********************************************************************
+ * 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
+
/*
- * ISA DMA and bounce buffer management
+ * 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 i386_isa_dma_cookie *cookie;
+ bus_dmamap_t map;
+ int error, cookieflags;
+ void *cookiestore;
+ size_t cookiesize;
-#define MAX_CHUNK 256 /* number of low memory segments */
+ /* Call common function to create the basic map. */
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp);
+ if (error)
+ return (error);
-static u_int32_t bitmap[MAX_CHUNK / 32 + 1];
+ map = *dmamp;
+ map->_dm_cookie = NULL;
-#define set(i) (bitmap[(i) >> 5] |= (1 << (i)))
-#define clr(i) (bitmap[(i) >> 5] &= ~(1 << (i)))
-#define bit(i) ((bitmap[(i) >> 5] & (1 << (i))) != 0)
+ cookiesize = sizeof(struct i386_isa_dma_cookie);
-static int bit_ptr = -1; /* last segment visited */
-static int chunk_size = 0; /* size (bytes) of one low mem segment */
-static int chunk_num = 0; /* actual number of low mem segments */
-#ifdef DIAGNOSTIC
-int bounce_alloc_cur = 0;
-int bounce_alloc_max = 0;
-#endif
+ /*
+ * 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 / NBPG) + 1. If
+ * the caller can't handle that many segments (e.g. the
+ * ISA DMA controller), we may have to bounce it as well.
+ */
+ cookieflags = 0;
+ if ((avail_end > ISA_DMA_BOUNCE_THRESHOLD &&
+ (flags & ISABUS_DMA_32BIT) == 0) ||
+ ((map->_dm_size / NBPG) + 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_DEVBUF,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ bzero(cookiestore, cookiesize);
+ cookie = (struct i386_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);
+ }
-vm_offset_t isaphysmem; /* base address of low mem arena */
-int isaphysmempgs; /* number of pages of low mem arena */
+ out:
+ if (error) {
+ if (map->_dm_cookie != NULL)
+ free(map->_dm_cookie, M_DEVBUF);
+ _bus_dmamap_destroy(t, map);
+ }
+ return (error);
+}
/*
- * if addr is the physical address of an allocated bounce buffer return the
- * corresponding virtual address, 0 otherwise
+ * Destroy an ISA DMA map.
*/
+void
+_isa_bus_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_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_DEVBUF);
+ _bus_dmamap_destroy(t, map);
+}
-caddr_t
-bounce_vaddr(addr)
- vm_offset_t addr;
+/*
+ * 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;
{
- int i;
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+ int error;
+
+ STAT_INCR(isa_dma_stats_loads);
- if (addr < vtophys(isaphysmem) ||
- addr >= vtophys(isaphysmem + chunk_num*chunk_size) ||
- ((i = (int)(addr-vtophys(isaphysmem))) % chunk_size) != 0 ||
- bit(i/chunk_size))
- return(0);
+ /*
+ * Check to see if we might need to bounce the transfer.
+ */
+ if (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) {
+ /*
+ * Check if all pages are below the bounce
+ * threshold. If they are, don't bother bouncing.
+ */
+ if (_isa_dma_check_buffer(buf, buflen,
+ map->_dm_segcnt, map->_dm_boundary, p) == 0)
+ return (_bus_dmamap_load(t, map, buf, buflen,
+ p, flags));
+
+ STAT_INCR(isa_dma_stats_bounces);
+
+ /*
+ * Allocate bounce pages, if necessary.
+ */
+ if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) {
+ error = _isa_dma_alloc_bouncebuf(t, map, buflen,
+ flags);
+ if (error)
+ return (error);
+ }
- return((caddr_t) (isaphysmem + (addr - vtophys(isaphysmem))));
+ /*
+ * Cache a pointer to the caller's buffer and
+ * load the DMA map with the bounce buffer.
+ */
+ cookie->id_origbuf = buf;
+ cookie->id_origbuflen = buflen;
+ error = _bus_dmamap_load(t, map, cookie->id_bouncebuf,
+ buflen, p, flags);
+
+ if (error) {
+ /*
+ * Free the bounce pages, unless our resources
+ * are reserved for our exclusive use.
+ */
+ if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
+ _isa_dma_free_bouncebuf(t, map);
+ }
+
+ /* ...so _isa_bus_dmamap_sync() knows we're bouncing */
+ cookie->id_flags |= ID_IS_BOUNCING;
+ } else {
+ /*
+ * Just use the generic load function.
+ */
+ error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
+ }
+
+ return (error);
}
/*
- * alloc a low mem segment of size nbytes. Alignment constraint is:
- * (addr & pmask) == ((addr+size-1) & pmask)
- * if waitok, call may wait for memory to become available.
- * returns 0 on failure
+ * Like _isa_bus_dmamap_load(), but for mbufs.
*/
+int
+_isa_bus_dmamap_load_mbuf(t, map, m, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m;
+ int flags;
+{
-vm_offset_t
-bounce_alloc(nbytes, pmask, waitok)
- vm_size_t nbytes;
- vm_offset_t pmask;
- int waitok;
+ panic("_isa_bus_dmamap_load_mbuf: not implemented");
+}
+
+/*
+ * Like _isa_bus_dmamap_load(), but for uios.
+ */
+int
+_isa_bus_dmamap_load_uio(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
{
- int i, l;
- vm_offset_t a, b, c, r;
- vm_size_t n;
- int nunits, opri;
-
- opri = splbio();
-
- if (bit_ptr < 0) { /* initialize low mem arena */
- if ((chunk_size = isaphysmempgs*NBPG/MAX_CHUNK) & 1)
- chunk_size--;
- chunk_num = (isaphysmempgs*NBPG) / chunk_size;
- for(i = 0; i < chunk_num; i++)
- set(i);
- bit_ptr = 0;
- }
- nunits = (nbytes+chunk_size-1)/chunk_size;
+ panic("_isa_bus_dmamap_load_uio: not implemented");
+}
+
+/*
+ * Like _isa_bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
+int
+_isa_bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+
+ panic("_isa_bus_dmamap_load_raw: not implemented");
+}
+
+/*
+ * Unload an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_unload(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ /*
+ * If we have bounce pages, free them, unless they're
+ * reserved for our exclusive use.
+ */
+ if ((cookie->id_flags & ID_HAS_BOUNCE) &&
+ (map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
+ _isa_dma_free_bouncebuf(t, map);
+
+ cookie->id_flags &= ~ID_IS_BOUNCING;
/*
- * set a=start, b=start with address constraints, c=end
- * check if this request may ever succeed.
+ * Do the generic bits of the unload.
*/
+ _bus_dmamap_unload(t, map);
+}
- a = isaphysmem;
- b = (isaphysmem + ~pmask) & pmask;
- c = isaphysmem + chunk_num*chunk_size;
- n = nunits*chunk_size;
- if (a + n >= c || (pmask != 0 && a + n >= b && b + n >= c)) {
- splx(opri);
- return(0);
+/*
+ * Synchronize an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_sync(t, map, op)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dmasync_op_t op;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ switch (op) {
+ case BUS_DMASYNC_PREREAD:
+ /*
+ * Nothing to do for pre-read.
+ */
+ break;
+
+ case BUS_DMASYNC_PREWRITE:
+ /*
+ * If we're bouncing this transfer, copy the
+ * caller's buffer to the bounce buffer.
+ */
+ if (cookie->id_flags & ID_IS_BOUNCING)
+ bcopy(cookie->id_origbuf, cookie->id_bouncebuf,
+ cookie->id_origbuflen);
+ break;
+
+ case BUS_DMASYNC_POSTREAD:
+ /*
+ * If we're bouncing this transfer, copy the
+ * bounce buffer to the caller's buffer.
+ */
+ if (cookie->id_flags & ID_IS_BOUNCING)
+ bcopy(cookie->id_bouncebuf, cookie->id_origbuf,
+ cookie->id_origbuflen);
+ break;
+
+ case BUS_DMASYNC_POSTWRITE:
+ /*
+ * Nothing to do for post-write.
+ */
+ break;
}
- for (;;) {
- i = bit_ptr;
- l = -1;
- do{
- if (bit(i) && l >= 0 && (i - l + 1) >= nunits){
- r = vtophys(isaphysmem + (i - nunits + 1)*chunk_size);
- if (((r ^ (r + nbytes - 1)) & pmask) == 0) {
- for (l = i - nunits + 1; l <= i; l++)
- clr(l);
- bit_ptr = i;
-#ifdef DIAGNOSTIC
- bounce_alloc_cur += nunits*chunk_size;
- bounce_alloc_max = max(bounce_alloc_max,
- bounce_alloc_cur);
+#if 0
+ /* This is a noop anyhow, so why bother calling it? */
+ _bus_dmamap_sync(t, map, op);
#endif
- splx(opri);
- return(r);
- }
- } else if (bit(i) && l < 0)
- l = i;
- else if (!bit(i))
- l = -1;
- if (++i == chunk_num) {
- i = 0;
- l = -1;
- }
- } while(i != bit_ptr);
+}
- if (waitok)
- tsleep((caddr_t) &bit_ptr, PRIBIO, "physmem", 0);
- else {
- splx(opri);
- return(0);
- }
- }
+/*
+ * Allocate memory safe for ISA DMA.
+ */
+int
+_isa_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+{
+ vm_offset_t high;
+
+ if (avail_end > ISA_DMA_BOUNCE_THRESHOLD)
+ high = trunc_page(ISA_DMA_BOUNCE_THRESHOLD);
+ else
+ high = trunc_page(avail_end);
+
+ return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, high));
+}
+
+/*
+ * Free memory safe for ISA DMA.
+ */
+void
+_isa_bus_dmamem_free(t, segs, nsegs)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+{
+
+ _bus_dmamem_free(t, segs, nsegs);
}
-/*
- * return a segent of the low mem arena to the free pool
+/*
+ * Map ISA DMA-safe memory into kernel virtual address space.
*/
+int
+_isa_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ size_t size;
+ caddr_t *kvap;
+ int flags;
+{
+
+ return (_bus_dmamem_map(t, segs, nsegs, size, kvap, flags));
+}
+/*
+ * Unmap ISA DMA-safe memory from kernel virtual address space.
+ */
void
-bounce_free(addr, nbytes)
- vm_offset_t addr;
- vm_size_t nbytes;
+_isa_bus_dmamem_unmap(t, kva, size)
+ bus_dma_tag_t t;
+ caddr_t kva;
+ size_t size;
+{
+
+ _bus_dmamem_unmap(t, kva, size);
+}
+
+/*
+ * mmap(2) ISA DMA-safe memory.
+ */
+int
+_isa_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs, off, prot, flags;
{
- int i, j, opri;
- vm_offset_t vaddr;
- opri = splbio();
+ return (_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags));
+}
+
+/**********************************************************************
+ * ISA DMA utility functions
+ **********************************************************************/
- if ((vaddr = (vm_offset_t) bounce_vaddr(addr)) == 0)
- panic("bounce_free: bad address");
+/*
+ * Return 0 if all pages in the passed buffer lie within the DMA'able
+ * range RAM.
+ */
+int
+_isa_dma_check_buffer(buf, buflen, segcnt, boundary, p)
+ void *buf;
+ bus_size_t buflen;
+ int segcnt;
+ bus_size_t boundary;
+ struct proc *p;
+{
+ vm_offset_t vaddr = (vm_offset_t)buf;
+ vm_offset_t pa, lastpa, endva;
+ u_long pagemask = ~(boundary - 1);
+ pmap_t pmap;
+ int nsegs;
- i = (int) (vaddr - isaphysmem)/chunk_size;
- j = i + (nbytes + chunk_size - 1)/chunk_size;
+ endva = round_page(vaddr + buflen);
-#ifdef DIAGNOSTIC
- bounce_alloc_cur -= (j - i)*chunk_size;
-#endif
+ nsegs = 1;
+ lastpa = 0;
- while (i < j) {
- if (bit(i))
- panic("bounce_free: already free");
- set(i);
- i++;
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ for (; vaddr < endva; vaddr += NBPG) {
+ /*
+ * Get physical address for this segment.
+ */
+ pa = pmap_extract(pmap, (vm_offset_t)vaddr);
+ pa = trunc_page(pa);
+
+ /*
+ * Is it below the DMA'able threshold?
+ */
+ if (pa > ISA_DMA_BOUNCE_THRESHOLD)
+ return (EINVAL);
+
+ if (lastpa) {
+ /*
+ * Check excessive segment count.
+ */
+ if (lastpa + NBPG != pa) {
+ if (++nsegs > segcnt)
+ return (EFBIG);
+ }
+
+ /*
+ * Check boundary restriction.
+ */
+ if (boundary) {
+ if ((lastpa ^ pa) & pagemask)
+ return (EINVAL);
+ }
+ }
+ lastpa = pa;
}
- wakeup((caddr_t) &bit_ptr);
- splx(opri);
+ return (0);
}
+int
+_isa_dma_alloc_bouncebuf(t, map, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_size_t size;
+ int flags;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+ int error = 0;
+
+ cookie->id_bouncebuflen = round_page(size);
+ error = _isa_bus_dmamem_alloc(t, cookie->id_bouncebuflen,
+ NBPG, map->_dm_boundary, cookie->id_bouncesegs,
+ map->_dm_segcnt, &cookie->id_nbouncesegs, flags);
+ if (error)
+ goto out;
+ error = _isa_bus_dmamem_map(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs, cookie->id_bouncebuflen,
+ (caddr_t *)&cookie->id_bouncebuf, flags);
+
+ out:
+ if (error) {
+ _isa_bus_dmamem_free(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs);
+ cookie->id_bouncebuflen = 0;
+ cookie->id_nbouncesegs = 0;
+ } else {
+ cookie->id_flags |= ID_HAS_BOUNCE;
+ STAT_INCR(isa_dma_stats_nbouncebufs);
+ }
+
+ return (error);
+}
+
+void
+_isa_dma_free_bouncebuf(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ STAT_DECR(isa_dma_stats_nbouncebufs);
+
+ _isa_bus_dmamem_unmap(t, cookie->id_bouncebuf,
+ cookie->id_bouncebuflen);
+ _isa_bus_dmamem_free(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs);
+ cookie->id_bouncebuflen = 0;
+ cookie->id_nbouncesegs = 0;
+ cookie->id_flags &= ~ID_HAS_BOUNCE;
+}
+
+#ifdef __ISADMA_COMPAT
/*
* setup (addr, nbytes) for an ISA dma transfer.
* flags&ISADMA_MAP_WAITOK may wait
@@ -637,7 +1106,6 @@ bounce_free(addr, nbytes)
* returns the number of used phys entries, 0 on failure.
* if flags&ISADMA_MAP_CONTIG result is 1 on sucess!
*/
-
int
isadma_map(addr, nbytes, phys, flags)
caddr_t addr;
@@ -645,78 +1113,39 @@ isadma_map(addr, nbytes, phys, flags)
struct isadma_seg *phys;
int flags;
{
- vm_offset_t pmask, thiskv, thisphys, nextphys;
- vm_size_t datalen;
- int seg, waitok, i;
-
- if (flags & ISADMA_MAP_8BIT)
- pmask = ~((64*1024) - 1);
- else if (flags & ISADMA_MAP_16BIT)
- pmask = ~((128*1024) - 1);
- else
- pmask = 0;
-
- waitok = (flags & ISADMA_MAP_WAITOK) != 0;
-
- thiskv = (vm_offset_t) addr;
- datalen = nbytes;
- thisphys = vtophys(thiskv);
- seg = 0;
-
- while (datalen > 0 && (seg == 0 || (flags & ISADMA_MAP_CONTIG) == 0)) {
- phys[seg].length = 0;
- phys[seg].addr = thisphys;
-
- nextphys = thisphys;
- while (datalen > 0 && thisphys == nextphys) {
- nextphys = trunc_page(thisphys) + NBPG;
- phys[seg].length += min(nextphys - thisphys, datalen);
- datalen -= min(nextphys - thisphys, datalen);
- thiskv = trunc_page(thiskv) + NBPG;
- if (datalen)
- thisphys = vtophys(thiskv);
- }
-
- if (phys[seg].addr + phys[seg].length > 0xffffff) {
- if (flags & ISADMA_MAP_CONTIG) {
- phys[seg].length = nbytes;
- datalen = 0;
- }
- if ((flags & ISADMA_MAP_BOUNCE) == 0)
- phys[seg].addr = 0;
- else
- phys[seg].addr = bounce_alloc(phys[seg].length,
- pmask, waitok);
- if (phys[seg].addr == 0) {
- for (i = 0; i < seg; i++)
- if (bounce_vaddr(phys[i].addr))
- bounce_free(phys[i].addr,
- phys[i].length);
- return 0;
- }
- }
+ bus_dma_tag_t dmat = ((struct isa_softc *)isa_dev)->sc_dmat;
+ bus_dmamap_t dmam;
+ int i;
- seg++;
+/* XXX if this turns out to be too low, convert the driver to real bus_dma */
+#define ISADMA_MAX_SEGMENTS 64
+#define ISADMA_MAX_SEGSZ 0xffffff
+
+ if (bus_dmamap_create(dmat, nbytes,
+ (flags & ISADMA_MAP_CONTIG) ? 1 : ISADMA_MAX_SEGMENTS,
+ ISADMA_MAX_SEGSZ,
+ (flags & ISADMA_MAP_8BIT) ? 0xffff :
+ ((flags & ISADMA_MAP_16BIT) ? 0x1ffff : 0),
+ (flags & ISADMA_MAP_WAITOK) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT,
+ &dmam) != 0)
+ return (0);
+ if (bus_dmamap_load(dmat, dmam, addr, nbytes, 0,
+ (flags & ISADMA_MAP_WAITOK) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) !=
+ 0) {
+ bus_dmamap_destroy(dmat, dmam);
+ return (0);
}
-
- /* check all constraints */
- if (datalen ||
- ((phys[0].addr ^ (phys[0].addr + phys[0].length - 1)) & pmask) != 0 ||
- ((phys[0].addr & 1) && (flags & ISADMA_MAP_16BIT))) {
- if ((flags & ISADMA_MAP_BOUNCE) == 0)
- return 0;
- if ((phys[0].addr = bounce_alloc(nbytes, pmask, waitok)) == 0)
- return 0;
- phys[0].length = nbytes;
+ for (i = 0; i < dmam->dm_nsegs; i++) {
+ phys[i].addr = dmam->dm_segs[i].ds_addr;
+ phys[i].length = dmam->dm_segs[i].ds_len;
}
-
- return seg;
+ phys[0].dmam = dmam;
+ return (dmam->dm_nsegs);
}
/*
* undo a ISA dma mapping. Simply return the bounced segments to the pool.
*/
-
void
isadma_unmap(addr, nbytes, nphys, phys)
caddr_t addr;
@@ -724,17 +1153,19 @@ isadma_unmap(addr, nbytes, nphys, phys)
int nphys;
struct isadma_seg *phys;
{
- int i;
-
- for (i = 0; i < nphys; i++)
- if (bounce_vaddr(phys[i].addr))
- bounce_free(phys[i].addr, phys[i].length);
+ bus_dma_tag_t dmat = ((struct isa_softc *)isa_dev)->sc_dmat;
+ bus_dmamap_t dmam = phys[0].dmam;
+
+ if (dmam == NULL)
+ return;
+ bus_dmamap_unload(dmat, dmam);
+ bus_dmamap_destroy(dmat, dmam);
+ phys[0].dmam = NULL;
}
/*
* copy bounce buffer to buffer where needed
*/
-
void
isadma_copyfrombuf(addr, nbytes, nphys, phys)
caddr_t addr;
@@ -742,21 +1173,15 @@ isadma_copyfrombuf(addr, nbytes, nphys, phys)
int nphys;
struct isadma_seg *phys;
{
- int i;
- caddr_t vaddr;
+ bus_dma_tag_t dmat = ((struct isa_softc *)isa_dev)->sc_dmat;
+ bus_dmamap_t dmam = phys[0].dmam;
- for (i = 0; i < nphys; i++) {
- vaddr = bounce_vaddr(phys[i].addr);
- if (vaddr)
- bcopy(vaddr, addr, phys[i].length);
- addr += phys[i].length;
- }
+ bus_dmamap_sync(dmat, dmam, BUS_DMASYNC_POSTREAD);
}
/*
* copy buffer to bounce buffer where needed
*/
-
void
isadma_copytobuf(addr, nbytes, nphys, phys)
caddr_t addr;
@@ -764,13 +1189,10 @@ isadma_copytobuf(addr, nbytes, nphys, phys)
int nphys;
struct isadma_seg *phys;
{
- int i;
- caddr_t vaddr;
+ bus_dma_tag_t dmat = ((struct isa_softc *)isa_dev)->sc_dmat;
+ bus_dmamap_t dmam = phys[0].dmam;
- for (i = 0; i < nphys; i++) {
- vaddr = bounce_vaddr(phys[i].addr);
- if (vaddr)
- bcopy(addr, vaddr, phys[i].length);
- addr += phys[i].length;
- }
+ bus_dmamap_sync(dmat, dmam, BUS_DMASYNC_PREWRITE);
}
+#endif /* __ISADMA_COMPAT */
+#endif /* NISADMA > 0 */
diff --git a/sys/arch/i386/isa/isa_machdep.h b/sys/arch/i386/isa/isa_machdep.h
index a2c8482979b..b86993cfbc6 100644
--- a/sys/arch/i386/isa/isa_machdep.h
+++ b/sys/arch/i386/isa/isa_machdep.h
@@ -1,4 +1,41 @@
-/* $NetBSD: isa_machdep.h,v 1.6 1996/05/03 19:14:56 christos Exp $ */
+/* $NetBSD: isa_machdep.h,v 1.7 1997/06/06 23:28:42 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 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.
+ * 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.
+ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -46,6 +83,8 @@
#ifndef _I386_ISA_MACHDEP_H_ /* XXX */
#define _I386_ISA_MACHDEP_H_ /* XXX */
+#include <machine/bus.h>
+
/*
* XXX THIS FILE IS A MESS. copyright: berkeley's probably.
* contents from isavar.h and isareg.h, mostly the latter.
@@ -76,6 +115,32 @@ void isa_intr_disestablish __P((isa_chipset_tag_t ic, void *handler));
* ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED
* BY PORTABLE CODE.
*/
+
+extern struct i386_bus_dma_tag isa_bus_dma_tag;
+
+/*
+ * Cookie used by ISA dma. A pointer to one of these it stashed in
+ * the DMA map.
+ */
+struct i386_isa_dma_cookie {
+ int id_flags; /* flags; see below */
+
+ void *id_origbuf; /* pointer to orig buffer if
+ bouncing */
+ bus_size_t id_origbuflen; /* ...and size */
+
+ 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 */
+
/*
* XXX Various seemingly PC-specific constants, some of which may be
* unnecessary anyway.
diff --git a/sys/arch/i386/pci/pchb.c b/sys/arch/i386/pci/pchb.c
index c6bdb77c24b..88b5cb6aea1 100644
--- a/sys/arch/i386/pci/pchb.c
+++ b/sys/arch/i386/pci/pchb.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pchb.c,v 1.9 1997/10/09 08:48:33 jtc Exp $ */
+/* $NetBSD: pchb.c,v 1.6 1997/06/06 23:29:16 thorpej Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -122,6 +122,7 @@ pchbattach(parent, self, aux)
pba.pba_busname = "pci";
pba.pba_iot = pa->pa_iot;
pba.pba_memt = pa->pa_memt;
+ pba.pba_dmat = pa->pa_dmat;
pba.pba_bus = pbnum;
pba.pba_pc = pa->pa_pc;
config_found(self, &pba, pchb_print);
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index 4a66aa2632b..9146ad91640 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,5 +1,42 @@
-/* $OpenBSD: pci_machdep.c,v 1.10 1997/06/18 19:07:01 dm Exp $ */
-/* $NetBSD: pci_machdep.c,v 1.26 1996/10/24 12:32:29 fvdl Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.11 1998/01/20 18:40:23 niklas Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 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.
+ * 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.
+ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -53,6 +90,9 @@
#include <vm/vm.h>
#include <vm/vm_kern.h>
+#define _I386_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
#include <machine/pio.h>
#include <i386/isa/icu.h>
@@ -69,6 +109,27 @@ int pci_mode = -1;
#define PCI_MODE2_ENABLE_REG 0x0cf8
#define PCI_MODE2_FORWARD_REG 0x0cfa
+/*
+ * PCI doesn't have any special needs; just use the generic versions
+ * of these functions.
+ */
+struct i386_bus_dma_tag pci_bus_dma_tag = {
+ NULL, /* _cookie */
+ _bus_dmamap_create,
+ _bus_dmamap_destroy,
+ _bus_dmamap_load,
+ _bus_dmamap_load_mbuf,
+ _bus_dmamap_load_uio,
+ _bus_dmamap_load_raw,
+ _bus_dmamap_unload,
+ NULL, /* _dmamap_sync */
+ _bus_dmamem_alloc,
+ _bus_dmamem_free,
+ _bus_dmamem_map,
+ _bus_dmamem_unmap,
+ _bus_dmamem_mmap,
+};
+
void
pci_attach_hook(parent, self, pba)
struct device *parent, *self;
diff --git a/sys/arch/i386/pci/pci_machdep.h b/sys/arch/i386/pci/pci_machdep.h
index 02e02048084..35d75a09793 100644
--- a/sys/arch/i386/pci/pci_machdep.h
+++ b/sys/arch/i386/pci/pci_machdep.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pci_machdep.h,v 1.4 1997/06/18 19:07:02 dm Exp $ */
-/* $NetBSD: pci_machdep.h,v 1.5 1996/03/27 04:01:16 cgd Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.5 1998/01/20 18:40:23 niklas Exp $ */
+/* $NetBSD: pci_machdep.h,v 1.7 1997/06/06 23:29:18 thorpej Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -55,6 +55,8 @@ union i386_pci_tag_u {
} mode2;
};
+extern struct i386_bus_dma_tag pci_bus_dma_tag;
+
/*
* Types provided to machine-independent PCI code
*/