Home | History | Annotate | Line # | Download | only in x86
      1 /*	$NetBSD: bus_dma.c,v 1.92 2025/08/04 11:53:52 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996, 1997, 1998, 2007, 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
      9  * Simulation Facility NASA Ames Research Center, and by Andrew Doran.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.92 2025/08/04 11:53:52 skrll Exp $");
     35 
     36 /*
     37  * The following is included because _bus_dma_uiomove is derived from
     38  * uiomove() in kern_subr.c.
     39  */
     40 
     41 /*
     42  * Copyright (c) 1982, 1986, 1991, 1993
     43  *	The Regents of the University of California.  All rights reserved.
     44  * (c) UNIX System Laboratories, Inc.
     45  * All or some portions of this file are derived from material licensed
     46  * to the University of California by American Telephone and Telegraph
     47  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     48  * the permission of UNIX System Laboratories, Inc.
     49  *
     50  * Copyright (c) 1992, 1993
     51  *	The Regents of the University of California.  All rights reserved.
     52  *
     53  * This software was developed by the Computer Systems Engineering group
     54  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     55  * contributed to Berkeley.
     56  *
     57  * All advertising materials mentioning features or use of this software
     58  * must display the following acknowledgement:
     59  *	This product includes software developed by the University of
     60  *	California, Lawrence Berkeley Laboratory.
     61  *
     62  * Redistribution and use in source and binary forms, with or without
     63  * modification, are permitted provided that the following conditions
     64  * are met:
     65  * 1. Redistributions of source code must retain the above copyright
     66  *    notice, this list of conditions and the following disclaimer.
     67  * 2. Redistributions in binary form must reproduce the above copyright
     68  *    notice, this list of conditions and the following disclaimer in the
     69  *    documentation and/or other materials provided with the distribution.
     70  * 3. Neither the name of the University nor the names of its contributors
     71  *    may be used to endorse or promote products derived from this software
     72  *    without specific prior written permission.
     73  *
     74  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     75  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     76  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     77  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     78  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     79  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     80  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     81  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     82  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     83  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     84  * SUCH DAMAGE.
     85  */
     86 
     87 #include "ioapic.h"
     88 #include "isa.h"
     89 #include "opt_mpbios.h"
     90 
     91 #include <sys/param.h>
     92 #include <sys/systm.h>
     93 #include <sys/kernel.h>
     94 #include <sys/kmem.h>
     95 #include <sys/malloc.h>
     96 #include <sys/mbuf.h>
     97 #include <sys/proc.h>
     98 #include <sys/asan.h>
     99 #include <sys/msan.h>
    100 
    101 #include <sys/bus.h>
    102 #include <machine/bus_private.h>
    103 #if NIOAPIC > 0
    104 #include <machine/i82093var.h>
    105 #endif
    106 #ifdef MPBIOS
    107 #include <machine/mpbiosvar.h>
    108 #endif
    109 #include <machine/pmap_private.h>
    110 
    111 #if NISA > 0
    112 #include <dev/isa/isareg.h>
    113 #include <dev/isa/isavar.h>
    114 #endif
    115 
    116 #include <uvm/uvm.h>
    117 
    118 extern	paddr_t avail_end;
    119 
    120 #define	IDTVEC(name)	__CONCAT(X,name)
    121 typedef void (vector)(void);
    122 extern vector *IDTVEC(intr)[];
    123 
    124 #define	BUSDMA_BOUNCESTATS
    125 
    126 #ifdef BUSDMA_BOUNCESTATS
    127 #define	BUSDMA_EVCNT_DECL(name)						\
    128 static struct evcnt bus_dma_ev_##name =					\
    129     EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "bus_dma", #name);		\
    130 EVCNT_ATTACH_STATIC(bus_dma_ev_##name)
    131 
    132 #define	STAT_INCR(name)							\
    133     bus_dma_ev_##name.ev_count++
    134 #define	STAT_DECR(name)							\
    135     bus_dma_ev_##name.ev_count--
    136 
    137 BUSDMA_EVCNT_DECL(nbouncebufs);
    138 BUSDMA_EVCNT_DECL(loads);
    139 BUSDMA_EVCNT_DECL(bounces);
    140 #else
    141 #define STAT_INCR(x)
    142 #define STAT_DECR(x)
    143 #endif
    144 
    145 static int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
    146 	    bus_size_t, int, bus_dmamap_t *);
    147 static void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
    148 static int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
    149 	    bus_size_t, struct proc *, int);
    150 static int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
    151 	    struct mbuf *, int);
    152 static int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
    153 	    struct uio *, int);
    154 static int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
    155 	    bus_dma_segment_t *, int, bus_size_t, int);
    156 static void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
    157 static void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
    158 	    bus_size_t, int);
    159 
    160 static int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
    161 	    bus_size_t alignment, bus_size_t boundary,
    162 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
    163 static void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
    164 	    int nsegs);
    165 static int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
    166 	    int nsegs, size_t size, void **kvap, int flags);
    167 static void	_bus_dmamem_unmap(bus_dma_tag_t tag, void *kva, size_t size);
    168 static paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
    169 	    int nsegs, off_t off, int prot, int flags);
    170 
    171 static int	_bus_dmatag_subregion(bus_dma_tag_t tag, bus_addr_t min_addr,
    172 	    bus_addr_t max_addr, bus_dma_tag_t *newtag, int flags);
    173 static void	_bus_dmatag_destroy(bus_dma_tag_t tag);
    174 
    175 static int _bus_dma_uiomove(void *, struct uio *, size_t, int);
    176 static int _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map,
    177 	    bus_size_t size, int flags);
    178 static void _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map);
    179 static int _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map,
    180 	    void *buf, bus_size_t buflen, struct vmspace *vm, int flags);
    181 static int _bus_dmamap_load_busaddr(bus_dma_tag_t, bus_dmamap_t,
    182     bus_addr_t, bus_size_t);
    183 
    184 #ifndef _BUS_DMAMEM_ALLOC_RANGE
    185 static int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
    186 	    bus_size_t alignment, bus_size_t boundary,
    187 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
    188 	    bus_addr_t low, bus_addr_t high);
    189 
    190 #define _BUS_DMAMEM_ALLOC_RANGE _bus_dmamem_alloc_range
    191 
    192 /*
    193  * Allocate physical memory from the given physical address range.
    194  * Called by DMA-safe memory allocation methods.
    195  */
    196 static int
    197 _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size,
    198     bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs,
    199     int nsegs, int *rsegs, int flags, bus_addr_t low, bus_addr_t high)
    200 {
    201 	paddr_t curaddr, lastaddr;
    202 	struct vm_page *m;
    203 	struct pglist mlist;
    204 	int curseg, error;
    205 	bus_size_t uboundary;
    206 
    207 	/* Always round the size. */
    208 	size = round_page(size);
    209 
    210 	KASSERTMSG(boundary >= PAGE_SIZE || boundary == 0,
    211 	    "boundary=0x%"PRIxBUSSIZE, boundary);
    212 
    213 	/*
    214 	 * Allocate pages from the VM system.
    215 	 * We accept boundaries < size, splitting in multiple segments
    216 	 * if needed. uvm_pglistalloc does not, so compute an appropriate
    217 	 * boundary: next power of 2 >= size
    218 	 */
    219 
    220 	if (boundary == 0)
    221 		uboundary = 0;
    222 	else {
    223 		uboundary = boundary;
    224 		while (uboundary < size)
    225 			uboundary = uboundary << 1;
    226 	}
    227 	error = uvm_pglistalloc(size, low, high, alignment, uboundary,
    228 	    &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
    229 	if (error)
    230 		return (error);
    231 
    232 	/*
    233 	 * Compute the location, size, and number of segments actually
    234 	 * returned by the VM code.
    235 	 */
    236 	m = TAILQ_FIRST(&mlist);
    237 	curseg = 0;
    238 	lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
    239 	segs[curseg].ds_len = PAGE_SIZE;
    240 	m = m->pageq.queue.tqe_next;
    241 
    242 	for (; m != NULL; m = m->pageq.queue.tqe_next) {
    243 		curaddr = VM_PAGE_TO_PHYS(m);
    244 		KASSERTMSG(curaddr >= low, "curaddr=%#"PRIxPADDR
    245 		    " low=%#"PRIxBUSADDR" high=%#"PRIxBUSADDR,
    246 		    curaddr, low, high);
    247 		KASSERTMSG(curaddr < high, "curaddr=%#"PRIxPADDR
    248 		    " low=%#"PRIxBUSADDR" high=%#"PRIxBUSADDR,
    249 		    curaddr, low, high);
    250 		if (curaddr == (lastaddr + PAGE_SIZE) &&
    251 		    (lastaddr & boundary) == (curaddr & boundary)) {
    252 			segs[curseg].ds_len += PAGE_SIZE;
    253 		} else {
    254 			curseg++;
    255 			KASSERTMSG(curseg < nsegs, "curseg %d size %llx",
    256 			    curseg, (long long)size);
    257 			segs[curseg].ds_addr = curaddr;
    258 			segs[curseg].ds_len = PAGE_SIZE;
    259 		}
    260 		lastaddr = curaddr;
    261 	}
    262 
    263 	*rsegs = curseg + 1;
    264 
    265 	return (0);
    266 }
    267 #endif /* _BUS_DMAMEM_ALLOC_RANGE */
    268 
    269 /*
    270  * Create a DMA map.
    271  */
    272 static int
    273 _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
    274     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
    275 {
    276 	struct x86_bus_dma_cookie *cookie;
    277 	bus_dmamap_t map;
    278 	int error, cookieflags;
    279 	void *cookiestore, *mapstore;
    280 	size_t cookiesize, mapsize;
    281 
    282 	/*
    283 	 * Allocate and initialize the DMA map.  The end of the map
    284 	 * is a variable-sized array of segments, so we allocate enough
    285 	 * room for them in one shot.
    286 	 *
    287 	 * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
    288 	 * of ALLOCNOW notifies others that we've reserved these resources,
    289 	 * and they are not to be freed.
    290 	 *
    291 	 * The bus_dmamap_t includes one bus_dma_segment_t, hence
    292 	 * the (nsegments - 1).
    293 	 */
    294 	error = 0;
    295 	mapsize = sizeof(struct x86_bus_dmamap) +
    296 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
    297 	if ((mapstore = malloc(mapsize, M_DMAMAP, M_ZERO |
    298 	    ((flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK))) == NULL)
    299 		return (ENOMEM);
    300 
    301 	map = (struct x86_bus_dmamap *)mapstore;
    302 	map->_dm_size = size;
    303 	map->_dm_segcnt = nsegments;
    304 	map->_dm_maxmaxsegsz = maxsegsz;
    305 	map->_dm_boundary = boundary;
    306 	map->_dm_bounce_thresh = t->_bounce_thresh;
    307 	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
    308 	map->dm_maxsegsz = maxsegsz;
    309 	map->dm_mapsize = 0;		/* no valid mappings */
    310 	map->dm_nsegs = 0;
    311 
    312 	if (t->_bounce_thresh == 0 || _BUS_AVAIL_END <= t->_bounce_thresh - 1)
    313 		map->_dm_bounce_thresh = 0;
    314 	cookieflags = 0;
    315 
    316 	if (t->_may_bounce != NULL) {
    317 		error = t->_may_bounce(t, map, flags, &cookieflags);
    318 		if (error != 0)
    319 			goto out;
    320 	}
    321 
    322 	if (map->_dm_bounce_thresh != 0)
    323 		cookieflags |= X86_DMA_MIGHT_NEED_BOUNCE;
    324 
    325 	if ((cookieflags & X86_DMA_MIGHT_NEED_BOUNCE) == 0) {
    326 		*dmamp = map;
    327 		return 0;
    328 	}
    329 
    330 	cookiesize = sizeof(struct x86_bus_dma_cookie) +
    331 	    (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
    332 
    333 	/*
    334 	 * Allocate our cookie.
    335 	 */
    336 	if ((cookiestore = malloc(cookiesize, M_DMAMAP, M_ZERO |
    337 	    ((flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK))) == NULL) {
    338 		error = ENOMEM;
    339 		goto out;
    340 	}
    341 	cookie = (struct x86_bus_dma_cookie *)cookiestore;
    342 	cookie->id_flags = cookieflags;
    343 	map->_dm_cookie = cookie;
    344 
    345 	error = _bus_dma_alloc_bouncebuf(t, map, size, flags);
    346  out:
    347 	if (error)
    348 		_bus_dmamap_destroy(t, map);
    349 	else
    350 		*dmamp = map;
    351 
    352 	return (error);
    353 }
    354 
    355 /*
    356  * Destroy a DMA map.
    357  */
    358 static void
    359 _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
    360 {
    361 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    362 
    363 	/*
    364 	 * Free any bounce pages this map might hold.
    365 	 */
    366 	if (cookie != NULL) {
    367 		if (cookie->id_flags & X86_DMA_HAS_BOUNCE)
    368 			_bus_dma_free_bouncebuf(t, map);
    369 		free(cookie, M_DMAMAP);
    370 	}
    371 
    372 	free(map, M_DMAMAP);
    373 }
    374 
    375 /*
    376  * Load a DMA map with a linear buffer.
    377  */
    378 static int
    379 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    380     bus_size_t buflen, struct proc *p, int flags)
    381 {
    382 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    383 	int error;
    384 	struct vmspace *vm;
    385 
    386 	STAT_INCR(loads);
    387 
    388 	/*
    389 	 * Make sure that on error condition we return "no valid mappings."
    390 	 */
    391 	map->dm_mapsize = 0;
    392 	map->dm_nsegs = 0;
    393 	KASSERTMSG(map->dm_maxsegsz <= map->_dm_maxmaxsegsz,
    394 	    "maxsegsz=0x%"PRIxBUSSIZE", maxmaxsegsz=0x%"PRIxBUSSIZE,
    395 	    map->dm_maxsegsz, map->_dm_maxmaxsegsz);
    396 
    397 	if (buflen > map->_dm_size)
    398 		return EINVAL;
    399 
    400 	if (p != NULL) {
    401 		vm = p->p_vmspace;
    402 	} else {
    403 		vm = vmspace_kernel();
    404 	}
    405 	error = _bus_dmamap_load_buffer(t, map, buf, buflen, vm, flags);
    406 	if (error == 0) {
    407 		if (cookie != NULL)
    408 			cookie->id_flags &= ~X86_DMA_IS_BOUNCING;
    409 		map->dm_mapsize = buflen;
    410 		return 0;
    411 	}
    412 
    413 	if (cookie == NULL ||
    414 	    (cookie->id_flags & X86_DMA_MIGHT_NEED_BOUNCE) == 0)
    415 		return error;
    416 
    417 	/*
    418 	 * First attempt failed; bounce it.
    419 	 */
    420 
    421 	STAT_INCR(bounces);
    422 
    423 	/*
    424 	 * Allocate bounce pages, if necessary.
    425 	 */
    426 	if ((cookie->id_flags & X86_DMA_HAS_BOUNCE) == 0) {
    427 		error = _bus_dma_alloc_bouncebuf(t, map, buflen, flags);
    428 		if (error)
    429 			return (error);
    430 	}
    431 
    432 	/*
    433 	 * Cache a pointer to the caller's buffer and load the DMA map
    434 	 * with the bounce buffer.
    435 	 */
    436 	cookie->id_origbuf = buf;
    437 	cookie->id_origbuflen = buflen;
    438 	cookie->id_buftype = X86_DMA_BUFTYPE_LINEAR;
    439 	map->dm_nsegs = 0;
    440 	error = bus_dmamap_load(t, map, cookie->id_bouncebuf, buflen,
    441 	    p, flags);
    442 	if (error)
    443 		return (error);
    444 
    445 	/* ...so _bus_dmamap_sync() knows we're bouncing */
    446 	cookie->id_flags |= X86_DMA_IS_BOUNCING;
    447 	return (0);
    448 }
    449 
    450 static int
    451 _bus_dmamap_load_busaddr(bus_dma_tag_t t, bus_dmamap_t map,
    452     bus_addr_t addr, bus_size_t size)
    453 {
    454 	bus_dma_segment_t * const segs = map->dm_segs;
    455 	int nseg = map->dm_nsegs;
    456 	bus_addr_t bmask = ~(map->_dm_boundary - 1);
    457 	bus_addr_t lastaddr = 0xdead; /* XXX gcc */
    458 	bus_size_t sgsize;
    459 
    460 	if (nseg > 0)
    461 		lastaddr = segs[nseg-1].ds_addr + segs[nseg-1].ds_len;
    462 again:
    463 	sgsize = size;
    464 	/*
    465 	 * Make sure we don't cross any boundaries.
    466 	 */
    467 	if (map->_dm_boundary > 0) {
    468 		bus_addr_t baddr; /* next boundary address */
    469 
    470 		baddr = (addr + map->_dm_boundary) & bmask;
    471 		if (sgsize > (baddr - addr))
    472 			sgsize = (baddr - addr);
    473 	}
    474 
    475 	/*
    476 	 * Insert chunk into a segment, coalescing with
    477 	 * previous segment if possible.
    478 	 */
    479 	if (nseg > 0 && addr == lastaddr &&
    480 	    segs[nseg-1].ds_len + sgsize <= map->dm_maxsegsz &&
    481 	    (map->_dm_boundary == 0 ||
    482 	     (segs[nseg-1].ds_addr & bmask) == (addr & bmask))) {
    483 		/* coalesce */
    484 		segs[nseg-1].ds_len += sgsize;
    485 	} else if (nseg >= map->_dm_segcnt) {
    486 		return EFBIG;
    487 	} else {
    488 		/* new segment */
    489 		segs[nseg].ds_addr = addr;
    490 		segs[nseg].ds_len = sgsize;
    491 		nseg++;
    492 	}
    493 
    494 	lastaddr = addr + sgsize;
    495 	if (map->_dm_bounce_thresh != 0 && lastaddr > map->_dm_bounce_thresh)
    496 		return EINVAL;
    497 
    498 	addr += sgsize;
    499 	size -= sgsize;
    500 	if (size > 0)
    501 		goto again;
    502 
    503 	map->dm_nsegs = nseg;
    504 	return 0;
    505 }
    506 
    507 /*
    508  * Like _bus_dmamap_load(), but for mbufs.
    509  */
    510 static int
    511 _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
    512     int flags)
    513 {
    514 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    515 	int error;
    516 	struct mbuf *m;
    517 
    518 	/*
    519 	 * Make sure on error condition we return "no valid mappings."
    520 	 */
    521 	map->dm_mapsize = 0;
    522 	map->dm_nsegs = 0;
    523 	KASSERTMSG(map->dm_maxsegsz <= map->_dm_maxmaxsegsz,
    524 	    "maxsegsz=0x%"PRIxBUSSIZE", maxmaxsegsz=0x%"PRIxBUSSIZE,
    525 	    map->dm_maxsegsz, map->_dm_maxmaxsegsz);
    526 
    527 	KASSERTMSG(m0->m_flags & M_PKTHDR, "m0=%p m_flags=0x%x", m0,
    528 	    m0->m_flags);
    529 	if (m0->m_pkthdr.len > map->_dm_size)
    530 		return (EINVAL);
    531 
    532 	error = 0;
    533 	for (m = m0; m != NULL && error == 0; m = m->m_next) {
    534 		int offset;
    535 		int remainbytes;
    536 		const struct vm_page * const *pgs;
    537 		paddr_t paddr;
    538 		int size;
    539 
    540 		if (m->m_len == 0)
    541 			continue;
    542 		switch (m->m_flags & (M_EXT|M_EXT_CLUSTER|M_EXT_PAGES)) {
    543 		case M_EXT|M_EXT_CLUSTER:
    544 			/* XXX KDASSERT */
    545 			KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID);
    546 			paddr = m->m_ext.ext_paddr +
    547 			    (m->m_data - m->m_ext.ext_buf);
    548 			size = m->m_len;
    549 			error = _bus_dmamap_load_busaddr(t, map,
    550 			    _BUS_PHYS_TO_BUS(paddr), size);
    551 			break;
    552 
    553 		case M_EXT|M_EXT_PAGES:
    554 			KASSERTMSG(m->m_ext.ext_buf <= m->m_data,
    555 			    "m=%p m_ext.ext_buf=%p m_ext.ext_size=%zu"
    556 			    " m_data=%p",
    557 			    m, m->m_ext.ext_buf, m->m_ext.ext_size, m->m_data);
    558 			KASSERTMSG((m->m_data <=
    559 				m->m_ext.ext_buf + m->m_ext.ext_size),
    560 			    "m=%p m_ext.ext_buf=%p m_ext.ext_size=%zu"
    561 			    " m_data=%p",
    562 			    m, m->m_ext.ext_buf, m->m_ext.ext_size, m->m_data);
    563 
    564 			offset = (vaddr_t)m->m_data -
    565 			    trunc_page((vaddr_t)m->m_ext.ext_buf);
    566 			remainbytes = m->m_len;
    567 
    568 			/* skip uninteresting pages */
    569 			pgs = (const struct vm_page * const *)
    570 			    m->m_ext.ext_pgs + (offset >> PAGE_SHIFT);
    571 
    572 			offset &= PAGE_MASK; /* offset in the first page */
    573 
    574 			/* load each pages */
    575 			while (remainbytes > 0) {
    576 				const struct vm_page *pg;
    577 				bus_addr_t busaddr;
    578 
    579 				size = MIN(remainbytes, PAGE_SIZE - offset);
    580 
    581 				pg = *pgs++;
    582 				KASSERT(pg);
    583 				busaddr = _BUS_VM_PAGE_TO_BUS(pg) + offset;
    584 
    585 				error = _bus_dmamap_load_busaddr(t, map,
    586 				    busaddr, size);
    587 				if (error)
    588 					break;
    589 				offset = 0;
    590 				remainbytes -= size;
    591 			}
    592 			break;
    593 
    594 		case 0:
    595 			paddr = m->m_paddr + M_BUFOFFSET(m) +
    596 			    (m->m_data - M_BUFADDR(m));
    597 			size = m->m_len;
    598 			error = _bus_dmamap_load_busaddr(t, map,
    599 			    _BUS_PHYS_TO_BUS(paddr), size);
    600 			break;
    601 
    602 		default:
    603 			error = _bus_dmamap_load_buffer(t, map, m->m_data,
    604 			    m->m_len, vmspace_kernel(), flags);
    605 		}
    606 	}
    607 	if (error == 0) {
    608 		map->dm_mapsize = m0->m_pkthdr.len;
    609 		return 0;
    610 	}
    611 
    612 	map->dm_nsegs = 0;
    613 
    614 	if (cookie == NULL ||
    615 	    (cookie->id_flags & X86_DMA_MIGHT_NEED_BOUNCE) == 0)
    616 		return error;
    617 
    618 	/*
    619 	 * First attempt failed; bounce it.
    620 	 */
    621 
    622 	STAT_INCR(bounces);
    623 
    624 	/*
    625 	 * Allocate bounce pages, if necessary.
    626 	 */
    627 	if ((cookie->id_flags & X86_DMA_HAS_BOUNCE) == 0) {
    628 		error = _bus_dma_alloc_bouncebuf(t, map, m0->m_pkthdr.len,
    629 		    flags);
    630 		if (error)
    631 			return (error);
    632 	}
    633 
    634 	/*
    635 	 * Cache a pointer to the caller's buffer and load the DMA map
    636 	 * with the bounce buffer.
    637 	 */
    638 	cookie->id_origbuf = m0;
    639 	cookie->id_origbuflen = m0->m_pkthdr.len;	/* not really used */
    640 	cookie->id_buftype = X86_DMA_BUFTYPE_MBUF;
    641 	error = bus_dmamap_load(t, map, cookie->id_bouncebuf,
    642 	    m0->m_pkthdr.len, NULL, flags);
    643 	if (error)
    644 		return (error);
    645 
    646 	/* ...so _bus_dmamap_sync() knows we're bouncing */
    647 	cookie->id_flags |= X86_DMA_IS_BOUNCING;
    648 	return (0);
    649 }
    650 
    651 /*
    652  * Like _bus_dmamap_load(), but for uios.
    653  */
    654 static int
    655 _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio,
    656     int flags)
    657 {
    658 	int i, error;
    659 	bus_size_t minlen, resid;
    660 	struct vmspace *vm;
    661 	struct iovec *iov;
    662 	void *addr;
    663 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    664 
    665 	/*
    666 	 * Make sure that on error condition we return "no valid mappings."
    667 	 */
    668 	map->dm_mapsize = 0;
    669 	map->dm_nsegs = 0;
    670 	KASSERTMSG(map->dm_maxsegsz <= map->_dm_maxmaxsegsz,
    671 	    "maxsegsz=0x%"PRIxBUSSIZE", maxmaxsegsz=0x%"PRIxBUSSIZE,
    672 	    map->dm_maxsegsz, map->_dm_maxmaxsegsz);
    673 
    674 	resid = uio->uio_resid;
    675 	iov = uio->uio_iov;
    676 
    677 	vm = uio->uio_vmspace;
    678 
    679 	error = 0;
    680 	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
    681 		/*
    682 		 * Now at the first iovec to load.  Load each iovec
    683 		 * until we have exhausted the residual count.
    684 		 */
    685 		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
    686 		addr = (void *)iov[i].iov_base;
    687 
    688 		error = _bus_dmamap_load_buffer(t, map, addr, minlen,
    689 		    vm, flags);
    690 
    691 		resid -= minlen;
    692 	}
    693 	if (error == 0) {
    694 		map->dm_mapsize = uio->uio_resid;
    695 		return 0;
    696 	}
    697 
    698 	map->dm_nsegs = 0;
    699 
    700 	if (cookie == NULL ||
    701 	    (cookie->id_flags & X86_DMA_MIGHT_NEED_BOUNCE) == 0)
    702 		return error;
    703 
    704 	STAT_INCR(bounces);
    705 
    706 	/*
    707 	 * Allocate bounce pages, if necessary.
    708 	 */
    709 	if ((cookie->id_flags & X86_DMA_HAS_BOUNCE) == 0) {
    710 		error = _bus_dma_alloc_bouncebuf(t, map, uio->uio_resid,
    711 		    flags);
    712 		if (error)
    713 			return (error);
    714 	}
    715 
    716 	/*
    717 	 * Cache a pointer to the caller's buffer and load the DMA map
    718 	 * with the bounce buffer.
    719 	 */
    720 	cookie->id_origbuf = uio;
    721 	cookie->id_origbuflen = uio->uio_resid;
    722 	cookie->id_buftype = X86_DMA_BUFTYPE_UIO;
    723 	error = bus_dmamap_load(t, map, cookie->id_bouncebuf,
    724 	    uio->uio_resid, NULL, flags);
    725 	if (error)
    726 		return (error);
    727 
    728 	/* ...so _bus_dmamap_sync() knows we're bouncing */
    729 	cookie->id_flags |= X86_DMA_IS_BOUNCING;
    730 	return (0);
    731 }
    732 
    733 /*
    734  * Like _bus_dmamap_load(), but for raw memory allocated with
    735  * bus_dmamem_alloc().
    736  */
    737 static int
    738 _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map,
    739     bus_dma_segment_t *segs, int nsegs, bus_size_t size0, int flags)
    740 {
    741 	bus_size_t size;
    742 	int i, error = 0;
    743 
    744 	/*
    745 	 * Make sure that on error condition we return "no valid mappings."
    746 	 */
    747 	map->dm_mapsize = 0;
    748 	map->dm_nsegs = 0;
    749 	KASSERTMSG(map->dm_maxsegsz <= map->_dm_maxmaxsegsz,
    750 	    "maxsegsz=0x%"PRIxBUSSIZE", maxmaxsegsz=0x%"PRIxBUSSIZE,
    751 	    map->dm_maxsegsz, map->_dm_maxmaxsegsz);
    752 
    753 	if (size0 > map->_dm_size)
    754 		return EINVAL;
    755 
    756 	for (i = 0, size = size0; i < nsegs && size > 0; i++) {
    757 		bus_dma_segment_t *ds = &segs[i];
    758 		bus_size_t sgsize;
    759 
    760 		sgsize = MIN(ds->ds_len, size);
    761 		if (sgsize == 0)
    762 			continue;
    763 		error = _bus_dmamap_load_busaddr(t, map, ds->ds_addr, sgsize);
    764 		if (error != 0)
    765 			break;
    766 		size -= sgsize;
    767 	}
    768 
    769 	if (error != 0) {
    770 		map->dm_mapsize = 0;
    771 		map->dm_nsegs = 0;
    772 		return error;
    773 	}
    774 
    775 	/* XXX TBD bounce */
    776 
    777 	map->dm_mapsize = size0;
    778 	return 0;
    779 }
    780 
    781 /*
    782  * Unload a DMA map.
    783  */
    784 static void
    785 _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
    786 {
    787 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    788 
    789 	/*
    790 	 * If we have bounce pages, free them, unless they're
    791 	 * reserved for our exclusive use.
    792 	 */
    793 	if (cookie != NULL) {
    794 		cookie->id_flags &= ~X86_DMA_IS_BOUNCING;
    795 		cookie->id_buftype = X86_DMA_BUFTYPE_INVALID;
    796 	}
    797 	map->dm_maxsegsz = map->_dm_maxmaxsegsz;
    798 	map->dm_mapsize = 0;
    799 	map->dm_nsegs = 0;
    800 }
    801 
    802 /*
    803  * Synchronize a DMA map.
    804  *
    805  * Reference:
    806  *
    807  *	AMD64 Architecture Programmer's Manual, Volume 2: System
    808  *	Programming, 24593--Rev. 3.38--November 2021, Sec. 7.4.2 Memory
    809  *	Barrier Interaction with Memory Types, Table 7-3, p. 196.
    810  *	https://web.archive.org/web/20220625040004/https://www.amd.com/system/files/TechDocs/24593.pdf#page=256
    811  */
    812 static void
    813 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
    814     bus_size_t len, int ops)
    815 {
    816 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
    817 
    818 	/*
    819 	 * Mixing PRE and POST operations is not allowed.
    820 	 */
    821 	if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
    822 	    (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
    823 		panic("%s: mix PRE and POST", __func__);
    824 
    825 	if ((ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTREAD)) != 0) {
    826 		KASSERTMSG(offset < map->dm_mapsize,
    827 		    "bad offset 0x%"PRIxBUSADDR" >= 0x%"PRIxBUSSIZE,
    828 		    offset, map->dm_mapsize);
    829 		KASSERTMSG(len <= map->dm_mapsize - offset,
    830 		    "bad length 0x%"PRIxBUSADDR" + 0x%"PRIxBUSSIZE
    831 		    " > 0x%"PRIxBUSSIZE,
    832 		    offset, len, map->dm_mapsize);
    833 	}
    834 
    835 	/*
    836 	 * BUS_DMASYNC_POSTREAD: The caller has been alerted to DMA
    837 	 * completion by reading a register or DMA descriptor, and the
    838 	 * caller is about to read out of the DMA memory buffer that
    839 	 * the device just filled.
    840 	 *
    841 	 * => LFENCE ensures that these happen in order so that the
    842 	 *    caller, or the bounce buffer logic here, doesn't proceed
    843 	 *    to read any stale data from cache or speculation.  x86
    844 	 *    never reorders loads from wp/wt/wb or uc memory, but it
    845 	 *    may execute loads from wc/wc+ memory early, e.g. with
    846 	 *    BUS_SPACE_MAP_PREFETCHABLE.
    847 	 */
    848 	if (ops & BUS_DMASYNC_POSTREAD)
    849 		x86_lfence();
    850 
    851 	/*
    852 	 * If we're not bouncing, just return; nothing to do.
    853 	 */
    854 	if (len == 0 || cookie == NULL ||
    855 	    (cookie->id_flags & X86_DMA_IS_BOUNCING) == 0)
    856 		goto end;
    857 
    858 	switch (cookie->id_buftype) {
    859 	case X86_DMA_BUFTYPE_LINEAR:
    860 		/*
    861 		 * Nothing to do for pre-read.
    862 		 */
    863 
    864 		if (ops & BUS_DMASYNC_PREWRITE) {
    865 			/*
    866 			 * Copy the caller's buffer to the bounce buffer.
    867 			 */
    868 			memcpy((char *)cookie->id_bouncebuf + offset,
    869 			    (char *)cookie->id_origbuf + offset, len);
    870 		}
    871 
    872 		if (ops & BUS_DMASYNC_POSTREAD) {
    873 			/*
    874 			 * Copy the bounce buffer to the caller's buffer.
    875 			 */
    876 			memcpy((char *)cookie->id_origbuf + offset,
    877 			    (char *)cookie->id_bouncebuf + offset, len);
    878 		}
    879 
    880 		/*
    881 		 * Nothing to do for post-write.
    882 		 */
    883 		break;
    884 
    885 	case X86_DMA_BUFTYPE_MBUF:
    886 	    {
    887 		struct mbuf *m, *m0 = cookie->id_origbuf;
    888 		bus_size_t minlen, moff;
    889 
    890 		/*
    891 		 * Nothing to do for pre-read.
    892 		 */
    893 
    894 		if (ops & BUS_DMASYNC_PREWRITE) {
    895 			/*
    896 			 * Copy the caller's buffer to the bounce buffer.
    897 			 */
    898 			m_copydata(m0, offset, len,
    899 			    (char *)cookie->id_bouncebuf + offset);
    900 		}
    901 
    902 		if (ops & BUS_DMASYNC_POSTREAD) {
    903 			/*
    904 			 * Copy the bounce buffer to the caller's buffer.
    905 			 */
    906 			for (moff = offset, m = m0; m != NULL && len != 0;
    907 			     m = m->m_next) {
    908 				/* Find the beginning mbuf. */
    909 				if (moff >= m->m_len) {
    910 					moff -= m->m_len;
    911 					continue;
    912 				}
    913 
    914 				/*
    915 				 * Now at the first mbuf to sync; nail
    916 				 * each one until we have exhausted the
    917 				 * length.
    918 				 */
    919 				minlen = len < m->m_len - moff ?
    920 				    len : m->m_len - moff;
    921 
    922 				memcpy(mtod(m, char *) + moff,
    923 				    (char *)cookie->id_bouncebuf + offset,
    924 				    minlen);
    925 
    926 				moff = 0;
    927 				len -= minlen;
    928 				offset += minlen;
    929 			}
    930 		}
    931 
    932 		/*
    933 		 * Nothing to do for post-write.
    934 		 */
    935 		break;
    936 	    }
    937 	case X86_DMA_BUFTYPE_UIO:
    938 	    {
    939 		struct uio *uio;
    940 
    941 		uio = (struct uio *)cookie->id_origbuf;
    942 
    943 		/*
    944 		 * Nothing to do for pre-read.
    945 		 */
    946 
    947 		if (ops & BUS_DMASYNC_PREWRITE) {
    948 			/*
    949 			 * Copy the caller's buffer to the bounce buffer.
    950 			 */
    951 			_bus_dma_uiomove((char *)cookie->id_bouncebuf + offset,
    952 			    uio, len, UIO_WRITE);
    953 		}
    954 
    955 		if (ops & BUS_DMASYNC_POSTREAD) {
    956 			_bus_dma_uiomove((char *)cookie->id_bouncebuf + offset,
    957 			    uio, len, UIO_READ);
    958 		}
    959 
    960 		/*
    961 		 * Nothing to do for post-write.
    962 		 */
    963 		break;
    964 	    }
    965 
    966 	case X86_DMA_BUFTYPE_RAW:
    967 		panic("%s: X86_DMA_BUFTYPE_RAW", __func__);
    968 		break;
    969 
    970 	case X86_DMA_BUFTYPE_INVALID:
    971 		panic("%s: X86_DMA_BUFTYPE_INVALID", __func__);
    972 		break;
    973 
    974 	default:
    975 		panic("%s: unknown buffer type %d", __func__,
    976 		    cookie->id_buftype);
    977 		break;
    978 	}
    979 end:
    980 	/*
    981 	 * BUS_DMASYNC_PREREAD: The caller may have previously been
    982 	 * using a DMA memory buffer, with loads and stores, and is
    983 	 * about to trigger DMA by writing to a register or DMA
    984 	 * descriptor.
    985 	 *
    986 	 * => SFENCE ensures that the stores happen in order, in case
    987 	 *    the latter one is non-temporal or to wc/wc+ memory and
    988 	 *    thus may be executed early.  x86 never reorders
    989 	 *    load;store to store;load for any memory type, so no
    990 	 *    barrier is needed for prior loads.
    991 	 *
    992 	 * BUS_DMASYNC_PREWRITE: The caller has just written to a DMA
    993 	 * memory buffer, or we just wrote to the bounce buffer,
    994 	 * data that the device needs to use, and the caller is about
    995 	 * to trigger DMA by writing to a register or DMA descriptor.
    996 	 *
    997 	 * => SFENCE ensures that these happen in order so that any
    998 	 *    buffered stores are visible to the device before the DMA
    999 	 *    is triggered.  x86 never reorders (non-temporal) stores
   1000 	 *    to wp/wt/wb or uc memory, but it may reorder two stores
   1001 	 *    if one is to wc/wc+ memory, e.g. if the DMA descriptor is
   1002 	 *    mapped with BUS_SPACE_MAP_PREFETCHABLE.
   1003 	 */
   1004 	if (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE))
   1005 		x86_sfence();
   1006 
   1007 	/*
   1008 	 * BUS_DMASYNC_POSTWRITE: The caller has been alerted to DMA
   1009 	 * completion by reading a register or DMA descriptor, and the
   1010 	 * caller may proceed to reuse the DMA memory buffer, with
   1011 	 * loads and stores.
   1012 	 *
   1013 	 * => No barrier is needed.  Since the DMA memory buffer is not
   1014 	 *    changing (we're sending data to the device, not receiving
   1015 	 *    data from the device), prefetched loads are safe.  x86
   1016 	 *    never reoreders load;store to store;load for any memory
   1017 	 *    type, so early execution of stores prior to witnessing
   1018 	 *    the DMA completion is not possible.
   1019 	 */
   1020 }
   1021 
   1022 /*
   1023  * Allocate memory safe for DMA.
   1024  */
   1025 static int
   1026 _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
   1027     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
   1028     int flags)
   1029 {
   1030 	bus_addr_t high;
   1031 
   1032 	if (t->_bounce_alloc_hi != 0 && _BUS_AVAIL_END > t->_bounce_alloc_hi - 1)
   1033 		high = t->_bounce_alloc_hi - 1;
   1034 	else
   1035 		high = _BUS_AVAIL_END;
   1036 
   1037 	return (_BUS_DMAMEM_ALLOC_RANGE(t, size, alignment, boundary,
   1038 	    segs, nsegs, rsegs, flags, t->_bounce_alloc_lo, high));
   1039 }
   1040 
   1041 static int
   1042 _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map,
   1043     bus_size_t size, int flags)
   1044 {
   1045 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
   1046 	int error = 0;
   1047 
   1048 	KASSERT(cookie != NULL);
   1049 
   1050 	cookie->id_bouncebuflen = round_page(size);
   1051 	error = _bus_dmamem_alloc(t, cookie->id_bouncebuflen,
   1052 	    PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs,
   1053 	    map->_dm_segcnt, &cookie->id_nbouncesegs, flags);
   1054 	if (error) {
   1055 		cookie->id_bouncebuflen = 0;
   1056 		cookie->id_nbouncesegs = 0;
   1057 		return error;
   1058 	}
   1059 
   1060 	error = _bus_dmamem_map(t, cookie->id_bouncesegs,
   1061 	    cookie->id_nbouncesegs, cookie->id_bouncebuflen,
   1062 	    (void **)&cookie->id_bouncebuf, flags);
   1063 
   1064 	if (error) {
   1065 		_bus_dmamem_free(t, cookie->id_bouncesegs,
   1066 		    cookie->id_nbouncesegs);
   1067 		cookie->id_bouncebuflen = 0;
   1068 		cookie->id_nbouncesegs = 0;
   1069 	} else {
   1070 		cookie->id_flags |= X86_DMA_HAS_BOUNCE;
   1071 		STAT_INCR(nbouncebufs);
   1072 	}
   1073 
   1074 	return (error);
   1075 }
   1076 
   1077 static void
   1078 _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map)
   1079 {
   1080 	struct x86_bus_dma_cookie *cookie = map->_dm_cookie;
   1081 
   1082 	KASSERT(cookie != NULL);
   1083 
   1084 	STAT_DECR(nbouncebufs);
   1085 
   1086 	_bus_dmamem_unmap(t, cookie->id_bouncebuf, cookie->id_bouncebuflen);
   1087 	_bus_dmamem_free(t, cookie->id_bouncesegs,
   1088 	    cookie->id_nbouncesegs);
   1089 	cookie->id_bouncebuflen = 0;
   1090 	cookie->id_nbouncesegs = 0;
   1091 	cookie->id_flags &= ~X86_DMA_HAS_BOUNCE;
   1092 }
   1093 
   1094 
   1095 /*
   1096  * This function does the same as uiomove, but takes an explicit
   1097  * direction, and does not update the uio structure.
   1098  */
   1099 static int
   1100 _bus_dma_uiomove(void *buf, struct uio *uio, size_t n, int direction)
   1101 {
   1102 	struct iovec *iov;
   1103 	int error;
   1104 	struct vmspace *vm;
   1105 	char *cp;
   1106 	size_t resid, cnt;
   1107 	int i;
   1108 
   1109 	iov = uio->uio_iov;
   1110 	vm = uio->uio_vmspace;
   1111 	cp = buf;
   1112 	resid = n;
   1113 
   1114 	for (i = 0; i < uio->uio_iovcnt && resid > 0; i++) {
   1115 		iov = &uio->uio_iov[i];
   1116 		if (iov->iov_len == 0)
   1117 			continue;
   1118 		cnt = MIN(resid, iov->iov_len);
   1119 
   1120 		if (!VMSPACE_IS_KERNEL_P(vm)) {
   1121 			preempt_point();
   1122 		}
   1123 		if (direction == UIO_READ) {
   1124 			error = copyout_vmspace(vm, cp, iov->iov_base, cnt);
   1125 		} else {
   1126 			error = copyin_vmspace(vm, iov->iov_base, cp, cnt);
   1127 		}
   1128 		if (error)
   1129 			return (error);
   1130 		cp += cnt;
   1131 		resid -= cnt;
   1132 	}
   1133 	return (0);
   1134 }
   1135 
   1136 /*
   1137  * Common function for freeing DMA-safe memory.  May be called by
   1138  * bus-specific DMA memory free functions.
   1139  */
   1140 static void
   1141 _bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
   1142 {
   1143 	struct vm_page *m;
   1144 	bus_addr_t addr;
   1145 	struct pglist mlist;
   1146 	int curseg;
   1147 
   1148 	/*
   1149 	 * Build a list of pages to free back to the VM system.
   1150 	 */
   1151 	TAILQ_INIT(&mlist);
   1152 	for (curseg = 0; curseg < nsegs; curseg++) {
   1153 		for (addr = segs[curseg].ds_addr;
   1154 		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
   1155 		    addr += PAGE_SIZE) {
   1156 			m = _BUS_BUS_TO_VM_PAGE(addr);
   1157 			TAILQ_INSERT_TAIL(&mlist, m, pageq.queue);
   1158 		}
   1159 	}
   1160 
   1161 	uvm_pglistfree(&mlist);
   1162 }
   1163 
   1164 /*
   1165  * Common function for mapping DMA-safe memory.  May be called by
   1166  * bus-specific DMA memory map functions.
   1167  * This supports BUS_DMA_NOCACHE and BUS_DMA_PREFETCHABLE.
   1168  */
   1169 static int
   1170 _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
   1171     size_t size, void **kvap, int flags)
   1172 {
   1173 	vaddr_t va;
   1174 	bus_addr_t addr;
   1175 	int curseg;
   1176 	const uvm_flag_t kmflags =
   1177 	    (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0;
   1178 	u_int pmapflags = PMAP_WIRED | VM_PROT_READ | VM_PROT_WRITE;
   1179 
   1180 	size = round_page(size);
   1181 	KASSERTMSG(((flags & (BUS_DMA_NOCACHE|BUS_DMA_PREFETCHABLE)) !=
   1182 		(BUS_DMA_NOCACHE|BUS_DMA_PREFETCHABLE)),
   1183 	    "BUS_DMA_NOCACHE and BUS_DMA_PREFETCHABLE are mutually exclusive");
   1184 	if (flags & BUS_DMA_NOCACHE)
   1185 		pmapflags |= PMAP_NOCACHE;
   1186 	if (flags & BUS_DMA_PREFETCHABLE)
   1187 		pmapflags |= PMAP_WRITE_COMBINE;
   1188 
   1189 	va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags);
   1190 
   1191 	if (va == 0)
   1192 		return ENOMEM;
   1193 
   1194 	*kvap = (void *)va;
   1195 
   1196 	for (curseg = 0; curseg < nsegs; curseg++) {
   1197 		for (addr = segs[curseg].ds_addr;
   1198 		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
   1199 		    addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
   1200 			if (size == 0)
   1201 				panic("_bus_dmamem_map: size botch");
   1202 			_BUS_PMAP_ENTER(pmap_kernel(), va, addr,
   1203 			    VM_PROT_READ | VM_PROT_WRITE,
   1204 			    pmapflags);
   1205 		}
   1206 	}
   1207 	pmap_update(pmap_kernel());
   1208 
   1209 	return 0;
   1210 }
   1211 
   1212 /*
   1213  * Common function for unmapping DMA-safe memory.  May be called by
   1214  * bus-specific DMA memory unmapping functions.
   1215  */
   1216 
   1217 static void
   1218 _bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size)
   1219 {
   1220 	pt_entry_t *pte, opte;
   1221 	vaddr_t va, sva, eva;
   1222 
   1223 	KASSERTMSG(((uintptr_t)kva & PGOFSET) == 0, "kva=%p", kva);
   1224 
   1225 	size = round_page(size);
   1226 	sva = (vaddr_t)kva;
   1227 	eva = sva + size;
   1228 
   1229 	/*
   1230 	 * mark pages cacheable again.
   1231 	 */
   1232 	for (va = sva; va < eva; va += PAGE_SIZE) {
   1233 		pte = kvtopte(va);
   1234 		opte = *pte;
   1235 		if ((opte & PTE_PCD) != 0)
   1236 			pmap_pte_clearbits(pte, PTE_PCD);
   1237 	}
   1238 	pmap_remove(pmap_kernel(), (vaddr_t)kva, (vaddr_t)kva + size);
   1239 	pmap_update(pmap_kernel());
   1240 	uvm_km_free(kernel_map, (vaddr_t)kva, size, UVM_KMF_VAONLY);
   1241 }
   1242 
   1243 /*
   1244  * Common function for mmap(2)'ing DMA-safe memory.  May be called by
   1245  * bus-specific DMA mmap(2)'ing functions.
   1246  */
   1247 static paddr_t
   1248 _bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
   1249     off_t off, int prot, int flags)
   1250 {
   1251 	int i;
   1252 
   1253 	for (i = 0; i < nsegs; i++) {
   1254 		KASSERTMSG((off & PGOFSET) == 0, "off=0x%jx", (uintmax_t)off);
   1255 		KASSERTMSG((segs[i].ds_addr & PGOFSET) == 0,
   1256 		    "segs[%u].ds_addr=%"PRIxBUSADDR, i, segs[i].ds_addr);
   1257 		KASSERTMSG((segs[i].ds_len & PGOFSET) == 0,
   1258 		    "segs[%u].ds_len=%"PRIxBUSSIZE, i, segs[i].ds_len);
   1259 		if (off >= segs[i].ds_len) {
   1260 			off -= segs[i].ds_len;
   1261 			continue;
   1262 		}
   1263 
   1264 		return (x86_btop(_BUS_BUS_TO_PHYS(segs[i].ds_addr + off)));
   1265 	}
   1266 
   1267 	/* Page not found. */
   1268 	return (-1);
   1269 }
   1270 
   1271 /**********************************************************************
   1272  * DMA utility functions
   1273  **********************************************************************/
   1274 
   1275 /*
   1276  * Utility function to load a linear buffer.
   1277  */
   1278 static int
   1279 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
   1280     bus_size_t buflen, struct vmspace *vm, int flags)
   1281 {
   1282 	bus_size_t sgsize;
   1283 	bus_addr_t curaddr;
   1284 	vaddr_t vaddr = (vaddr_t)buf;
   1285 	pmap_t pmap;
   1286 
   1287 	if (vm != NULL)
   1288 		pmap = vm_map_pmap(&vm->vm_map);
   1289 	else
   1290 		pmap = pmap_kernel();
   1291 
   1292 	while (buflen > 0) {
   1293 		int error;
   1294 
   1295 		/*
   1296 		 * Get the bus address for this segment.
   1297 		 */
   1298 		curaddr = _BUS_VIRT_TO_BUS(pmap, vaddr);
   1299 
   1300 		/*
   1301 		 * Compute the segment size, and adjust counts.
   1302 		 */
   1303 		sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
   1304 		if (buflen < sgsize)
   1305 			sgsize = buflen;
   1306 
   1307 		/*
   1308 		 * If we're beyond the bounce threshold, notify
   1309 		 * the caller.
   1310 		 */
   1311 		if (map->_dm_bounce_thresh != 0 &&
   1312 		    curaddr + sgsize >= map->_dm_bounce_thresh)
   1313 			return (EINVAL);
   1314 
   1315 
   1316 		error = _bus_dmamap_load_busaddr(t, map, curaddr, sgsize);
   1317 		if (error)
   1318 			return error;
   1319 
   1320 		vaddr += sgsize;
   1321 		buflen -= sgsize;
   1322 	}
   1323 
   1324 	return (0);
   1325 }
   1326 
   1327 static int
   1328 _bus_dmatag_subregion(bus_dma_tag_t tag, bus_addr_t min_addr,
   1329 		      bus_addr_t max_addr, bus_dma_tag_t *newtag, int flags)
   1330 {
   1331 
   1332 	if ((tag->_bounce_thresh != 0   && max_addr >= tag->_bounce_thresh - 1) &&
   1333 	    (tag->_bounce_alloc_hi != 0 && max_addr >= tag->_bounce_alloc_hi - 1) &&
   1334 	    (min_addr <= tag->_bounce_alloc_lo)) {
   1335 		*newtag = tag;
   1336 		/* if the tag must be freed, add a reference */
   1337 		if (tag->_tag_needs_free)
   1338 			(tag->_tag_needs_free)++;
   1339 		return 0;
   1340 	}
   1341 
   1342 	if ((*newtag = malloc(sizeof(struct x86_bus_dma_tag), M_DMAMAP,
   1343 	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
   1344 		return ENOMEM;
   1345 
   1346 	**newtag = *tag;
   1347 	(*newtag)->_tag_needs_free = 1;
   1348 
   1349 	if (tag->_bounce_thresh == 0 || max_addr < tag->_bounce_thresh)
   1350 		(*newtag)->_bounce_thresh = max_addr;
   1351 	if (tag->_bounce_alloc_hi == 0 || max_addr < tag->_bounce_alloc_hi)
   1352 		(*newtag)->_bounce_alloc_hi = max_addr;
   1353 	if (min_addr > tag->_bounce_alloc_lo)
   1354 		(*newtag)->_bounce_alloc_lo = min_addr;
   1355 
   1356 	return 0;
   1357 }
   1358 
   1359 static void
   1360 _bus_dmatag_destroy(bus_dma_tag_t tag)
   1361 {
   1362 
   1363 	switch (tag->_tag_needs_free) {
   1364 	case 0:
   1365 		break;				/* not allocated with malloc */
   1366 	case 1:
   1367 		free(tag, M_DMAMAP);		/* last reference to tag */
   1368 		break;
   1369 	default:
   1370 		(tag->_tag_needs_free)--;	/* one less reference */
   1371 	}
   1372 }
   1373 
   1374 
   1375 void
   1376 bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t p, bus_addr_t o, bus_size_t l,
   1377 		int ops)
   1378 {
   1379 	bus_dma_tag_t it;
   1380 
   1381 	kasan_dma_sync(p, o, l, ops);
   1382 	kmsan_dma_sync(p, o, l, ops);
   1383 
   1384 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_SYNC) == 0)
   1385 		;	/* skip override */
   1386 	else for (it = t; it != NULL; it = it->bdt_super) {
   1387 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_SYNC) == 0)
   1388 			continue;
   1389 		(*it->bdt_ov->ov_dmamap_sync)(it->bdt_ctx, t, p, o,
   1390 		    l, ops);
   1391 		return;
   1392 	}
   1393 
   1394 	_bus_dmamap_sync(t, p, o, l, ops);
   1395 }
   1396 
   1397 int
   1398 bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
   1399 		  bus_size_t maxsegsz, bus_size_t boundary, int flags,
   1400 		  bus_dmamap_t *dmamp)
   1401 {
   1402 	bus_dma_tag_t it;
   1403 
   1404 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_CREATE) == 0)
   1405 		;	/* skip override */
   1406 	else for (it = t; it != NULL; it = it->bdt_super) {
   1407 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_CREATE) == 0)
   1408 			continue;
   1409 		return (*it->bdt_ov->ov_dmamap_create)(it->bdt_ctx, t, size,
   1410 		    nsegments, maxsegsz, boundary, flags, dmamp);
   1411 	}
   1412 
   1413 	return _bus_dmamap_create(t, size, nsegments, maxsegsz,
   1414 	    boundary, flags, dmamp);
   1415 }
   1416 
   1417 void
   1418 bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t dmam)
   1419 {
   1420 	bus_dma_tag_t it;
   1421 
   1422 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_DESTROY) == 0)
   1423 		;	/* skip override */
   1424 	else for (it = t; it != NULL; it = it->bdt_super) {
   1425 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_DESTROY) == 0)
   1426 			continue;
   1427 		(*it->bdt_ov->ov_dmamap_destroy)(it->bdt_ctx, t, dmam);
   1428 		return;
   1429 	}
   1430 
   1431 	_bus_dmamap_destroy(t, dmam);
   1432 }
   1433 
   1434 int
   1435 bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t dmam, void *buf,
   1436 		bus_size_t buflen, struct proc *p, int flags)
   1437 {
   1438 	bus_dma_tag_t it;
   1439 
   1440 	kasan_dma_load(dmam, buf, buflen, KASAN_DMA_LINEAR);
   1441 	kmsan_dma_load(dmam, buf, buflen, KMSAN_DMA_LINEAR);
   1442 
   1443 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD) == 0)
   1444 		;	/* skip override */
   1445 	else for (it = t; it != NULL; it = it->bdt_super) {
   1446 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_LOAD) == 0)
   1447 			continue;
   1448 		return (*it->bdt_ov->ov_dmamap_load)(it->bdt_ctx, t, dmam,
   1449 		    buf, buflen, p, flags);
   1450 	}
   1451 
   1452 	return _bus_dmamap_load(t, dmam, buf, buflen, p, flags);
   1453 }
   1454 
   1455 int
   1456 bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t dmam,
   1457 		     struct mbuf *chain, int flags)
   1458 {
   1459 	bus_dma_tag_t it;
   1460 
   1461 	kasan_dma_load(dmam, chain, 0, KASAN_DMA_MBUF);
   1462 	kmsan_dma_load(dmam, chain, 0, KMSAN_DMA_MBUF);
   1463 
   1464 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_MBUF) == 0)
   1465 		;	/* skip override */
   1466 	else for (it = t; it != NULL; it = it->bdt_super) {
   1467 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_LOAD_MBUF) == 0)
   1468 			continue;
   1469 		return (*it->bdt_ov->ov_dmamap_load_mbuf)(it->bdt_ctx, t, dmam,
   1470 		    chain, flags);
   1471 	}
   1472 
   1473 	return _bus_dmamap_load_mbuf(t, dmam, chain, flags);
   1474 }
   1475 
   1476 int
   1477 bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t dmam,
   1478 		    struct uio *uio, int flags)
   1479 {
   1480 	bus_dma_tag_t it;
   1481 
   1482 	kasan_dma_load(dmam, uio, 0, KASAN_DMA_UIO);
   1483 	kmsan_dma_load(dmam, uio, 0, KMSAN_DMA_UIO);
   1484 
   1485 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_UIO) == 0)
   1486 		;	/* skip override */
   1487 	else for (it = t; it != NULL; it = it->bdt_super) {
   1488 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_LOAD_UIO) == 0)
   1489 			continue;
   1490 		return (*it->bdt_ov->ov_dmamap_load_uio)(it->bdt_ctx, t, dmam,
   1491 		    uio, flags);
   1492 	}
   1493 
   1494 	return _bus_dmamap_load_uio(t, dmam, uio, flags);
   1495 }
   1496 
   1497 int
   1498 bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t dmam,
   1499 		    bus_dma_segment_t *segs, int nsegs,
   1500 		    bus_size_t size, int flags)
   1501 {
   1502 	bus_dma_tag_t it;
   1503 
   1504 	kasan_dma_load(dmam, NULL, 0, KASAN_DMA_RAW);
   1505 	kmsan_dma_load(dmam, NULL, 0, KMSAN_DMA_RAW);
   1506 
   1507 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_RAW) == 0)
   1508 		;	/* skip override */
   1509 	else for (it = t; it != NULL; it = it->bdt_super) {
   1510 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_LOAD_RAW) == 0)
   1511 			continue;
   1512 		return (*it->bdt_ov->ov_dmamap_load_raw)(it->bdt_ctx, t, dmam,
   1513 		    segs, nsegs, size, flags);
   1514 	}
   1515 
   1516 	return _bus_dmamap_load_raw(t, dmam, segs, nsegs, size, flags);
   1517 }
   1518 
   1519 void
   1520 bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t dmam)
   1521 {
   1522 	bus_dma_tag_t it;
   1523 
   1524 	if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_UNLOAD) == 0)
   1525 		;	/* skip override */
   1526 	else for (it = t; it != NULL; it = it->bdt_super) {
   1527 		if ((it->bdt_present & BUS_DMAMAP_OVERRIDE_UNLOAD) == 0)
   1528 			continue;
   1529 		(*it->bdt_ov->ov_dmamap_unload)(it->bdt_ctx, t, dmam);
   1530 		return;
   1531 	}
   1532 
   1533 	_bus_dmamap_unload(t, dmam);
   1534 }
   1535 
   1536 int
   1537 bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
   1538 		 bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
   1539 		 int *rsegs, int flags)
   1540 {
   1541 	bus_dma_tag_t it;
   1542 
   1543 	if ((t->bdt_exists & BUS_DMAMEM_OVERRIDE_ALLOC) == 0)
   1544 		;	/* skip override */
   1545 	else for (it = t; it != NULL; it = it->bdt_super) {
   1546 		if ((it->bdt_present & BUS_DMAMEM_OVERRIDE_ALLOC) == 0)
   1547 			continue;
   1548 		return (*it->bdt_ov->ov_dmamem_alloc)(it->bdt_ctx, t, size,
   1549 		    alignment, boundary, segs, nsegs, rsegs, flags);
   1550 	}
   1551 
   1552 	return _bus_dmamem_alloc(t, size, alignment, boundary, segs,
   1553 	    nsegs, rsegs, flags);
   1554 }
   1555 
   1556 void
   1557 bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
   1558 {
   1559 	bus_dma_tag_t it;
   1560 
   1561 	if ((t->bdt_exists & BUS_DMAMEM_OVERRIDE_FREE) == 0)
   1562 		;	/* skip override */
   1563 	else for (it = t; it != NULL; it = it->bdt_super) {
   1564 		if ((it->bdt_present & BUS_DMAMEM_OVERRIDE_FREE) == 0)
   1565 			continue;
   1566 		(*it->bdt_ov->ov_dmamem_free)(it->bdt_ctx, t, segs, nsegs);
   1567 		return;
   1568 	}
   1569 
   1570 	_bus_dmamem_free(t, segs, nsegs);
   1571 }
   1572 
   1573 int
   1574 bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
   1575 	       size_t size, void **kvap, int flags)
   1576 {
   1577 	bus_dma_tag_t it;
   1578 
   1579 	if ((t->bdt_exists & BUS_DMAMEM_OVERRIDE_MAP) == 0)
   1580 		;	/* skip override */
   1581 	else for (it = t; it != NULL; it = it->bdt_super) {
   1582 		if ((it->bdt_present & BUS_DMAMEM_OVERRIDE_MAP) == 0)
   1583 			continue;
   1584 		return (*it->bdt_ov->ov_dmamem_map)(it->bdt_ctx, t,
   1585 		    segs, nsegs, size, kvap, flags);
   1586 	}
   1587 
   1588 	return _bus_dmamem_map(t, segs, nsegs, size, kvap, flags);
   1589 }
   1590 
   1591 void
   1592 bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size)
   1593 {
   1594 	bus_dma_tag_t it;
   1595 
   1596 	if ((t->bdt_exists & BUS_DMAMEM_OVERRIDE_UNMAP) == 0)
   1597 		;	/* skip override */
   1598 	else for (it = t; it != NULL; it = it->bdt_super) {
   1599 		if ((it->bdt_present & BUS_DMAMEM_OVERRIDE_UNMAP) == 0)
   1600 			continue;
   1601 		(*it->bdt_ov->ov_dmamem_unmap)(it->bdt_ctx, t, kva, size);
   1602 		return;
   1603 	}
   1604 
   1605 	_bus_dmamem_unmap(t, kva, size);
   1606 }
   1607 
   1608 paddr_t
   1609 bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
   1610 		off_t off, int prot, int flags)
   1611 {
   1612 	bus_dma_tag_t it;
   1613 
   1614 	if ((t->bdt_exists & BUS_DMAMEM_OVERRIDE_MMAP) == 0)
   1615 		;	/* skip override */
   1616 	else for (it = t; it != NULL; it = it->bdt_super) {
   1617 		if ((it->bdt_present & BUS_DMAMEM_OVERRIDE_MMAP) == 0)
   1618 			continue;
   1619 		return (*it->bdt_ov->ov_dmamem_mmap)(it->bdt_ctx, t, segs,
   1620 		    nsegs, off, prot, flags);
   1621 	}
   1622 
   1623 	return _bus_dmamem_mmap(t, segs, nsegs, off, prot, flags);
   1624 }
   1625 
   1626 int
   1627 bus_dmatag_subregion(bus_dma_tag_t t, bus_addr_t min_addr,
   1628 		     bus_addr_t max_addr, bus_dma_tag_t *newtag, int flags)
   1629 {
   1630 	bus_dma_tag_t it;
   1631 
   1632 	if ((t->bdt_exists & BUS_DMATAG_OVERRIDE_SUBREGION) == 0)
   1633 		;	/* skip override */
   1634 	else for (it = t; it != NULL; it = it->bdt_super) {
   1635 		if ((it->bdt_present & BUS_DMATAG_OVERRIDE_SUBREGION) == 0)
   1636 			continue;
   1637 		return (*it->bdt_ov->ov_dmatag_subregion)(it->bdt_ctx, t,
   1638 		    min_addr, max_addr, newtag, flags);
   1639 	}
   1640 
   1641 	return _bus_dmatag_subregion(t, min_addr, max_addr, newtag, flags);
   1642 }
   1643 
   1644 void
   1645 bus_dmatag_destroy(bus_dma_tag_t t)
   1646 {
   1647 	bus_dma_tag_t it;
   1648 
   1649 	if ((t->bdt_exists & BUS_DMATAG_OVERRIDE_DESTROY) == 0)
   1650 		;	/* skip override */
   1651 	else for (it = t; it != NULL; it = it->bdt_super) {
   1652 		if ((it->bdt_present & BUS_DMATAG_OVERRIDE_DESTROY) == 0)
   1653 			continue;
   1654 		(*it->bdt_ov->ov_dmatag_destroy)(it->bdt_ctx, t);
   1655 		return;
   1656 	}
   1657 
   1658 	_bus_dmatag_destroy(t);
   1659 }
   1660 
   1661 static const void *
   1662 bit_to_function_pointer(const struct bus_dma_overrides *ov, uint64_t bit)
   1663 {
   1664 	switch (bit) {
   1665 	case BUS_DMAMAP_OVERRIDE_CREATE:
   1666 		return ov->ov_dmamap_create;
   1667 	case BUS_DMAMAP_OVERRIDE_DESTROY:
   1668 		return ov->ov_dmamap_destroy;
   1669 	case BUS_DMAMAP_OVERRIDE_LOAD:
   1670 		return ov->ov_dmamap_load;
   1671 	case BUS_DMAMAP_OVERRIDE_LOAD_MBUF:
   1672 		return ov->ov_dmamap_load_mbuf;
   1673 	case BUS_DMAMAP_OVERRIDE_LOAD_UIO:
   1674 		return ov->ov_dmamap_load_uio;
   1675 	case BUS_DMAMAP_OVERRIDE_LOAD_RAW:
   1676 		return ov->ov_dmamap_load_raw;
   1677 	case BUS_DMAMAP_OVERRIDE_UNLOAD:
   1678 		return ov->ov_dmamap_unload;
   1679 	case BUS_DMAMAP_OVERRIDE_SYNC:
   1680 		return ov->ov_dmamap_sync;
   1681 	case BUS_DMAMEM_OVERRIDE_ALLOC:
   1682 		return ov->ov_dmamem_alloc;
   1683 	case BUS_DMAMEM_OVERRIDE_FREE:
   1684 		return ov->ov_dmamem_free;
   1685 	case BUS_DMAMEM_OVERRIDE_MAP:
   1686 		return ov->ov_dmamem_map;
   1687 	case BUS_DMAMEM_OVERRIDE_UNMAP:
   1688 		return ov->ov_dmamem_unmap;
   1689 	case BUS_DMAMEM_OVERRIDE_MMAP:
   1690 		return ov->ov_dmamem_mmap;
   1691 	case BUS_DMATAG_OVERRIDE_SUBREGION:
   1692 		return ov->ov_dmatag_subregion;
   1693 	case BUS_DMATAG_OVERRIDE_DESTROY:
   1694 		return ov->ov_dmatag_destroy;
   1695 	default:
   1696 		return NULL;
   1697 	}
   1698 }
   1699 
   1700 void
   1701 bus_dma_tag_destroy(bus_dma_tag_t bdt)
   1702 {
   1703 	if (bdt->bdt_super != NULL)
   1704 		bus_dmatag_destroy(bdt->bdt_super);
   1705 	kmem_free(bdt, sizeof(struct x86_bus_dma_tag));
   1706 }
   1707 
   1708 int
   1709 bus_dma_tag_create(bus_dma_tag_t obdt, const uint64_t present,
   1710     const struct bus_dma_overrides *ov, void *ctx, bus_dma_tag_t *bdtp)
   1711 {
   1712 	uint64_t bit, bits, nbits;
   1713 	bus_dma_tag_t bdt;
   1714 	const void *fp;
   1715 
   1716 	if (ov == NULL || present == 0)
   1717 		return EINVAL;
   1718 
   1719 	bdt = kmem_alloc(sizeof(struct x86_bus_dma_tag), KM_SLEEP);
   1720 	*bdt = *obdt;
   1721 	/* don't let bus_dmatag_destroy free these */
   1722 	bdt->_tag_needs_free = 0;
   1723 
   1724 	bdt->bdt_super = obdt;
   1725 
   1726 	for (bits = present; bits != 0; bits = nbits) {
   1727 		nbits = bits & (bits - 1);
   1728 		bit = nbits ^ bits;
   1729 		if ((fp = bit_to_function_pointer(ov, bit)) == NULL) {
   1730 #ifdef DEBUG
   1731 			printf("%s: missing bit %" PRIx64 "\n", __func__, bit);
   1732 #endif
   1733 			goto einval;
   1734 		}
   1735 	}
   1736 
   1737 	bdt->bdt_ov = ov;
   1738 	bdt->bdt_exists = obdt->bdt_exists | present;
   1739 	bdt->bdt_present = present;
   1740 	bdt->bdt_ctx = ctx;
   1741 
   1742 	*bdtp = bdt;
   1743 	if (obdt->_tag_needs_free)
   1744 		obdt->_tag_needs_free++;
   1745 
   1746 	return 0;
   1747 einval:
   1748 	kmem_free(bdt, sizeof(struct x86_bus_dma_tag));
   1749 	return EINVAL;
   1750 }
   1751