diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-01-20 18:40:37 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-01-20 18:40:37 +0000 |
commit | e4232757b30346a182214fb65da8a76f2edb7b24 (patch) | |
tree | 5c1b89b92ef8c67dfa2d0f3a078804042a1555ee /sys/arch/i386 | |
parent | 0a8f2cc87f99deec610ef91696850a249bd8fb81 (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.c | 63 | ||||
-rw-r--r-- | sys/arch/i386/eisa/eisa_machdep.h | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 484 | ||||
-rw-r--r-- | sys/arch/i386/i386/mainbus.c | 13 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmap.c | 16 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmap.old.c | 16 | ||||
-rw-r--r-- | sys/arch/i386/include/bus.h | 210 | ||||
-rw-r--r-- | sys/arch/i386/isa/isa_machdep.c | 844 | ||||
-rw-r--r-- | sys/arch/i386/isa/isa_machdep.h | 67 | ||||
-rw-r--r-- | sys/arch/i386/pci/pchb.c | 3 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.c | 65 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.h | 6 |
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 */ |