xref: /freebsd-src/sys/kern/subr_bus_dma.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1dd0b4fb6SKonstantin Belousov /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni  *
4dd0b4fb6SKonstantin Belousov  * Copyright (c) 2012 EMC Corp.
5dd0b4fb6SKonstantin Belousov  * All rights reserved.
6dd0b4fb6SKonstantin Belousov  *
7dd0b4fb6SKonstantin Belousov  * Copyright (c) 1997, 1998 Justin T. Gibbs.
8dd0b4fb6SKonstantin Belousov  * All rights reserved.
9dd0b4fb6SKonstantin Belousov  *
10dd0b4fb6SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
11dd0b4fb6SKonstantin Belousov  * modification, are permitted provided that the following conditions
12dd0b4fb6SKonstantin Belousov  * are met:
13dd0b4fb6SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
14dd0b4fb6SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
15dd0b4fb6SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
16dd0b4fb6SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
17dd0b4fb6SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
18dd0b4fb6SKonstantin Belousov  *
19dd0b4fb6SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20dd0b4fb6SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21dd0b4fb6SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22dd0b4fb6SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23dd0b4fb6SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24dd0b4fb6SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25dd0b4fb6SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26dd0b4fb6SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27dd0b4fb6SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28dd0b4fb6SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29dd0b4fb6SKonstantin Belousov  * SUCH DAMAGE.
30dd0b4fb6SKonstantin Belousov  */
31dd0b4fb6SKonstantin Belousov 
32dd0b4fb6SKonstantin Belousov #include <sys/cdefs.h>
33dd0b4fb6SKonstantin Belousov #include "opt_bus.h"
349729b149SRuslan Bukin #include "opt_iommu.h"
35dd0b4fb6SKonstantin Belousov 
36dd0b4fb6SKonstantin Belousov #include <sys/param.h>
37dd0b4fb6SKonstantin Belousov #include <sys/conf.h>
38dd0b4fb6SKonstantin Belousov #include <sys/systm.h>
39dd0b4fb6SKonstantin Belousov #include <sys/bus.h>
40dd0b4fb6SKonstantin Belousov #include <sys/callout.h>
41e2e050c8SConrad Meyer #include <sys/ktr.h>
42*0b416346SMarius Strobl #include <sys/limits.h>
437def1e10SJohn Baldwin #include <sys/lock.h>
44dd0b4fb6SKonstantin Belousov #include <sys/mbuf.h>
45dd0b4fb6SKonstantin Belousov #include <sys/memdesc.h>
467def1e10SJohn Baldwin #include <sys/mutex.h>
47dd0b4fb6SKonstantin Belousov #include <sys/proc.h>
48dd0b4fb6SKonstantin Belousov #include <sys/uio.h>
49dd0b4fb6SKonstantin Belousov 
50dd0b4fb6SKonstantin Belousov #include <vm/vm.h>
51dd0b4fb6SKonstantin Belousov #include <vm/vm_page.h>
52dd0b4fb6SKonstantin Belousov #include <vm/vm_map.h>
53dd0b4fb6SKonstantin Belousov #include <vm/pmap.h>
54dd0b4fb6SKonstantin Belousov 
55c0341432SJohn Baldwin #include <opencrypto/cryptodev.h>
56c0341432SJohn Baldwin 
57dd0b4fb6SKonstantin Belousov #include <machine/bus.h>
58dd0b4fb6SKonstantin Belousov 
59dd0b4fb6SKonstantin Belousov /*
607def1e10SJohn Baldwin  * Convenience function for manipulating driver locks from busdma (during
617def1e10SJohn Baldwin  * busdma_swi, for example).
627def1e10SJohn Baldwin  */
637def1e10SJohn Baldwin void
busdma_lock_mutex(void * arg,bus_dma_lock_op_t op)647def1e10SJohn Baldwin busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
657def1e10SJohn Baldwin {
667def1e10SJohn Baldwin 	struct mtx *dmtx;
677def1e10SJohn Baldwin 
687def1e10SJohn Baldwin 	dmtx = (struct mtx *)arg;
697def1e10SJohn Baldwin 	switch (op) {
707def1e10SJohn Baldwin 	case BUS_DMA_LOCK:
717def1e10SJohn Baldwin 		mtx_lock(dmtx);
727def1e10SJohn Baldwin 		break;
737def1e10SJohn Baldwin 	case BUS_DMA_UNLOCK:
747def1e10SJohn Baldwin 		mtx_unlock(dmtx);
757def1e10SJohn Baldwin 		break;
767def1e10SJohn Baldwin 	default:
777def1e10SJohn Baldwin 		panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
787def1e10SJohn Baldwin 	}
797def1e10SJohn Baldwin }
807def1e10SJohn Baldwin 
817def1e10SJohn Baldwin /*
827def1e10SJohn Baldwin  * dflt_lock should never get called.  It gets put into the dma tag when
837def1e10SJohn Baldwin  * lockfunc == NULL, which is only valid if the maps that are associated
847def1e10SJohn Baldwin  * with the tag are meant to never be deferred.
857def1e10SJohn Baldwin  *
867def1e10SJohn Baldwin  * XXX Should have a way to identify which driver is responsible here.
877def1e10SJohn Baldwin  */
887def1e10SJohn Baldwin void
_busdma_dflt_lock(void * arg,bus_dma_lock_op_t op)897def1e10SJohn Baldwin _busdma_dflt_lock(void *arg, bus_dma_lock_op_t op)
907def1e10SJohn Baldwin {
917def1e10SJohn Baldwin 
927def1e10SJohn Baldwin 	panic("driver error: _bus_dma_dflt_lock called");
937def1e10SJohn Baldwin }
947def1e10SJohn Baldwin 
957def1e10SJohn Baldwin 
967def1e10SJohn Baldwin /*
97a9934668SKenneth D. Merry  * Load up data starting at offset within a region specified by a
98a9934668SKenneth D. Merry  * list of virtual address ranges until either length or the region
99a9934668SKenneth D. Merry  * are exhausted.
100dd0b4fb6SKonstantin Belousov  */
101dd0b4fb6SKonstantin Belousov static int
_bus_dmamap_load_vlist(bus_dma_tag_t dmat,bus_dmamap_t map,bus_dma_segment_t * list,int sglist_cnt,struct pmap * pmap,int * nsegs,int flags,size_t offset,size_t length)102dd0b4fb6SKonstantin Belousov _bus_dmamap_load_vlist(bus_dma_tag_t dmat, bus_dmamap_t map,
103dd0b4fb6SKonstantin Belousov     bus_dma_segment_t *list, int sglist_cnt, struct pmap *pmap, int *nsegs,
104a9934668SKenneth D. Merry     int flags, size_t offset, size_t length)
105dd0b4fb6SKonstantin Belousov {
106dd0b4fb6SKonstantin Belousov 	int error;
107dd0b4fb6SKonstantin Belousov 
108dd0b4fb6SKonstantin Belousov 	error = 0;
109a9934668SKenneth D. Merry 	for (; sglist_cnt > 0 && length != 0; sglist_cnt--, list++) {
110a9934668SKenneth D. Merry 		char *addr;
111a9934668SKenneth D. Merry 		size_t ds_len;
112a9934668SKenneth D. Merry 
113a9934668SKenneth D. Merry 		KASSERT((offset < list->ds_len),
114a9934668SKenneth D. Merry 		    ("Invalid mid-segment offset"));
115a9934668SKenneth D. Merry 		addr = (char *)(uintptr_t)list->ds_addr + offset;
116a9934668SKenneth D. Merry 		ds_len = list->ds_len - offset;
117a9934668SKenneth D. Merry 		offset = 0;
118a9934668SKenneth D. Merry 		if (ds_len > length)
119a9934668SKenneth D. Merry 			ds_len = length;
120a9934668SKenneth D. Merry 		length -= ds_len;
121a9934668SKenneth D. Merry 		KASSERT((ds_len != 0), ("Segment length is zero"));
122a9934668SKenneth D. Merry 		error = _bus_dmamap_load_buffer(dmat, map, addr, ds_len, pmap,
12344d95698SKonstantin Belousov 		    flags, NULL, nsegs);
124dd0b4fb6SKonstantin Belousov 		if (error)
125dd0b4fb6SKonstantin Belousov 			break;
126dd0b4fb6SKonstantin Belousov 	}
127dd0b4fb6SKonstantin Belousov 	return (error);
128dd0b4fb6SKonstantin Belousov }
129dd0b4fb6SKonstantin Belousov 
130dd0b4fb6SKonstantin Belousov /*
131dd0b4fb6SKonstantin Belousov  * Load a list of physical addresses.
132dd0b4fb6SKonstantin Belousov  */
133dd0b4fb6SKonstantin Belousov static int
_bus_dmamap_load_plist(bus_dma_tag_t dmat,bus_dmamap_t map,bus_dma_segment_t * list,int sglist_cnt,int * nsegs,int flags)134dd0b4fb6SKonstantin Belousov _bus_dmamap_load_plist(bus_dma_tag_t dmat, bus_dmamap_t map,
135dd0b4fb6SKonstantin Belousov     bus_dma_segment_t *list, int sglist_cnt, int *nsegs, int flags)
136dd0b4fb6SKonstantin Belousov {
137dd0b4fb6SKonstantin Belousov 	int error;
138dd0b4fb6SKonstantin Belousov 
139dd0b4fb6SKonstantin Belousov 	error = 0;
140dd0b4fb6SKonstantin Belousov 	for (; sglist_cnt > 0; sglist_cnt--, list++) {
141dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_phys(dmat, map,
142dd0b4fb6SKonstantin Belousov 		    (vm_paddr_t)list->ds_addr, list->ds_len, flags, NULL,
143dd0b4fb6SKonstantin Belousov 		    nsegs);
144dd0b4fb6SKonstantin Belousov 		if (error)
145dd0b4fb6SKonstantin Belousov 			break;
146dd0b4fb6SKonstantin Belousov 	}
147dd0b4fb6SKonstantin Belousov 	return (error);
148dd0b4fb6SKonstantin Belousov }
149dd0b4fb6SKonstantin Belousov 
150dd0b4fb6SKonstantin Belousov /*
15182334850SJohn Baldwin  * Load an unmapped mbuf
15282334850SJohn Baldwin  */
15382334850SJohn Baldwin static int
_bus_dmamap_load_mbuf_epg(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m,bus_dma_segment_t * segs,int * nsegs,int flags)15449b6b60eSGleb Smirnoff _bus_dmamap_load_mbuf_epg(bus_dma_tag_t dmat, bus_dmamap_t map,
15582334850SJohn Baldwin     struct mbuf *m, bus_dma_segment_t *segs, int *nsegs, int flags)
15682334850SJohn Baldwin {
15782334850SJohn Baldwin 	int error, i, off, len, pglen, pgoff, seglen, segoff;
15882334850SJohn Baldwin 
159365e8da4SGleb Smirnoff 	M_ASSERTEXTPG(m);
16082334850SJohn Baldwin 
16182334850SJohn Baldwin 	len = m->m_len;
16282334850SJohn Baldwin 	error = 0;
16382334850SJohn Baldwin 
16482334850SJohn Baldwin 	/* Skip over any data removed from the front. */
16582334850SJohn Baldwin 	off = mtod(m, vm_offset_t);
16682334850SJohn Baldwin 
1677b6c99d0SGleb Smirnoff 	if (m->m_epg_hdrlen != 0) {
1687b6c99d0SGleb Smirnoff 		if (off >= m->m_epg_hdrlen) {
1697b6c99d0SGleb Smirnoff 			off -= m->m_epg_hdrlen;
17082334850SJohn Baldwin 		} else {
1717b6c99d0SGleb Smirnoff 			seglen = m->m_epg_hdrlen - off;
17282334850SJohn Baldwin 			segoff = off;
17382334850SJohn Baldwin 			seglen = min(seglen, len);
17482334850SJohn Baldwin 			off = 0;
17582334850SJohn Baldwin 			len -= seglen;
17682334850SJohn Baldwin 			error = _bus_dmamap_load_buffer(dmat, map,
1770c103266SGleb Smirnoff 			    &m->m_epg_hdr[segoff], seglen, kernel_pmap,
17882334850SJohn Baldwin 			    flags, segs, nsegs);
17982334850SJohn Baldwin 		}
18082334850SJohn Baldwin 	}
1817b6c99d0SGleb Smirnoff 	pgoff = m->m_epg_1st_off;
1827b6c99d0SGleb Smirnoff 	for (i = 0; i < m->m_epg_npgs && error == 0 && len > 0; i++) {
183c4ee38f8SGleb Smirnoff 		pglen = m_epg_pagelen(m, i, pgoff);
18482334850SJohn Baldwin 		if (off >= pglen) {
18582334850SJohn Baldwin 			off -= pglen;
18682334850SJohn Baldwin 			pgoff = 0;
18782334850SJohn Baldwin 			continue;
18882334850SJohn Baldwin 		}
18982334850SJohn Baldwin 		seglen = pglen - off;
19082334850SJohn Baldwin 		segoff = pgoff + off;
19182334850SJohn Baldwin 		off = 0;
19282334850SJohn Baldwin 		seglen = min(seglen, len);
19382334850SJohn Baldwin 		len -= seglen;
19482334850SJohn Baldwin 		error = _bus_dmamap_load_phys(dmat, map,
1950c103266SGleb Smirnoff 		    m->m_epg_pa[i] + segoff, seglen, flags, segs, nsegs);
19682334850SJohn Baldwin 		pgoff = 0;
19782334850SJohn Baldwin 	};
19882334850SJohn Baldwin 	if (len != 0 && error == 0) {
1997b6c99d0SGleb Smirnoff 		KASSERT((off + len) <= m->m_epg_trllen,
20082334850SJohn Baldwin 		    ("off + len > trail (%d + %d > %d)", off, len,
2017b6c99d0SGleb Smirnoff 		    m->m_epg_trllen));
20282334850SJohn Baldwin 		error = _bus_dmamap_load_buffer(dmat, map,
2030c103266SGleb Smirnoff 		    &m->m_epg_trail[off], len, kernel_pmap, flags, segs,
20482334850SJohn Baldwin 		    nsegs);
20582334850SJohn Baldwin 	}
20682334850SJohn Baldwin 	return (error);
20782334850SJohn Baldwin }
20882334850SJohn Baldwin 
20982334850SJohn Baldwin /*
210883a0196SJohn Baldwin  * Load a single mbuf.
211883a0196SJohn Baldwin  */
212883a0196SJohn Baldwin static int
_bus_dmamap_load_single_mbuf(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m,bus_dma_segment_t * segs,int * nsegs,int flags)213883a0196SJohn Baldwin _bus_dmamap_load_single_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
214883a0196SJohn Baldwin     struct mbuf *m, bus_dma_segment_t *segs, int *nsegs, int flags)
215883a0196SJohn Baldwin {
216883a0196SJohn Baldwin 	int error;
217883a0196SJohn Baldwin 
218883a0196SJohn Baldwin 	error = 0;
219883a0196SJohn Baldwin 	if ((m->m_flags & M_EXTPG) != 0)
220883a0196SJohn Baldwin 		error = _bus_dmamap_load_mbuf_epg(dmat, map, m, segs, nsegs,
221883a0196SJohn Baldwin 		    flags);
222883a0196SJohn Baldwin 	else
223883a0196SJohn Baldwin 		error = _bus_dmamap_load_buffer(dmat, map, m->m_data, m->m_len,
224883a0196SJohn Baldwin 		    kernel_pmap, flags | BUS_DMA_LOAD_MBUF, segs, nsegs);
225883a0196SJohn Baldwin 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
226883a0196SJohn Baldwin 	    __func__, dmat, flags, error, *nsegs);
227883a0196SJohn Baldwin 	return (error);
228883a0196SJohn Baldwin }
229883a0196SJohn Baldwin 
230883a0196SJohn Baldwin /*
231dd0b4fb6SKonstantin Belousov  * Load an mbuf chain.
232dd0b4fb6SKonstantin Belousov  */
233dd0b4fb6SKonstantin Belousov static int
_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m0,bus_dma_segment_t * segs,int * nsegs,int flags)234dd0b4fb6SKonstantin Belousov _bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map,
235dd0b4fb6SKonstantin Belousov     struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags)
236dd0b4fb6SKonstantin Belousov {
237dd0b4fb6SKonstantin Belousov 	struct mbuf *m;
238dd0b4fb6SKonstantin Belousov 	int error;
239dd0b4fb6SKonstantin Belousov 
240dd0b4fb6SKonstantin Belousov 	error = 0;
241dd0b4fb6SKonstantin Belousov 	for (m = m0; m != NULL && error == 0; m = m->m_next) {
242dd0b4fb6SKonstantin Belousov 		if (m->m_len > 0) {
2436edfd179SGleb Smirnoff 			if ((m->m_flags & M_EXTPG) != 0)
24449b6b60eSGleb Smirnoff 				error = _bus_dmamap_load_mbuf_epg(dmat,
24582334850SJohn Baldwin 				    map, m, segs, nsegs, flags);
24682334850SJohn Baldwin 			else
24782334850SJohn Baldwin 				error = _bus_dmamap_load_buffer(dmat, map,
24882334850SJohn Baldwin 				    m->m_data, m->m_len, kernel_pmap,
24982334850SJohn Baldwin 				    flags | BUS_DMA_LOAD_MBUF, segs, nsegs);
250dd0b4fb6SKonstantin Belousov 		}
251dd0b4fb6SKonstantin Belousov 	}
252dd0b4fb6SKonstantin Belousov 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
253dd0b4fb6SKonstantin Belousov 	    __func__, dmat, flags, error, *nsegs);
254dd0b4fb6SKonstantin Belousov 	return (error);
255dd0b4fb6SKonstantin Belousov }
256dd0b4fb6SKonstantin Belousov 
25780938e75SKonstantin Belousov int
bus_dmamap_load_ma_triv(bus_dma_tag_t dmat,bus_dmamap_t map,struct vm_page ** ma,bus_size_t tlen,int ma_offs,int flags,bus_dma_segment_t * segs,int * segp)25880938e75SKonstantin Belousov bus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map,
25980938e75SKonstantin Belousov     struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
26080938e75SKonstantin Belousov     bus_dma_segment_t *segs, int *segp)
26180938e75SKonstantin Belousov {
26280938e75SKonstantin Belousov 	vm_paddr_t paddr;
26380938e75SKonstantin Belousov 	bus_size_t len;
26480938e75SKonstantin Belousov 	int error, i;
26580938e75SKonstantin Belousov 
266ee75e7deSKonstantin Belousov 	error = 0;
267ee75e7deSKonstantin Belousov 	for (i = 0; tlen > 0; i++, tlen -= len) {
268ee75e7deSKonstantin Belousov 		len = min(PAGE_SIZE - ma_offs, tlen);
26980938e75SKonstantin Belousov 		paddr = VM_PAGE_TO_PHYS(ma[i]) + ma_offs;
270ee75e7deSKonstantin Belousov 		error = _bus_dmamap_load_phys(dmat, map, paddr, len,
27180938e75SKonstantin Belousov 		    flags, segs, segp);
272ee75e7deSKonstantin Belousov 		if (error != 0)
273ee75e7deSKonstantin Belousov 			break;
274ee75e7deSKonstantin Belousov 		ma_offs = 0;
275ee75e7deSKonstantin Belousov 	}
276dd0b4fb6SKonstantin Belousov 	return (error);
277dd0b4fb6SKonstantin Belousov }
278dd0b4fb6SKonstantin Belousov 
279dd0b4fb6SKonstantin Belousov /*
280dd0b4fb6SKonstantin Belousov  * Load a uio.
281dd0b4fb6SKonstantin Belousov  */
282dd0b4fb6SKonstantin Belousov static int
_bus_dmamap_load_uio(bus_dma_tag_t dmat,bus_dmamap_t map,struct uio * uio,int * nsegs,int flags)283dd0b4fb6SKonstantin Belousov _bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
284dd0b4fb6SKonstantin Belousov     int *nsegs, int flags)
285dd0b4fb6SKonstantin Belousov {
286dd0b4fb6SKonstantin Belousov 	bus_size_t resid;
287dd0b4fb6SKonstantin Belousov 	bus_size_t minlen;
288dd0b4fb6SKonstantin Belousov 	struct iovec *iov;
289dd0b4fb6SKonstantin Belousov 	pmap_t pmap;
290dd0b4fb6SKonstantin Belousov 	caddr_t addr;
291dd0b4fb6SKonstantin Belousov 	int error, i;
292dd0b4fb6SKonstantin Belousov 
293dd0b4fb6SKonstantin Belousov 	if (uio->uio_segflg == UIO_USERSPACE) {
294dd0b4fb6SKonstantin Belousov 		KASSERT(uio->uio_td != NULL,
295dd0b4fb6SKonstantin Belousov 			("bus_dmamap_load_uio: USERSPACE but no proc"));
296dd0b4fb6SKonstantin Belousov 		pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace);
297dd0b4fb6SKonstantin Belousov 	} else
298dd0b4fb6SKonstantin Belousov 		pmap = kernel_pmap;
299dd0b4fb6SKonstantin Belousov 	resid = uio->uio_resid;
300dd0b4fb6SKonstantin Belousov 	iov = uio->uio_iov;
301dd0b4fb6SKonstantin Belousov 	error = 0;
302dd0b4fb6SKonstantin Belousov 
303dd0b4fb6SKonstantin Belousov 	for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) {
304dd0b4fb6SKonstantin Belousov 		/*
305dd0b4fb6SKonstantin Belousov 		 * Now at the first iovec to load.  Load each iovec
306dd0b4fb6SKonstantin Belousov 		 * until we have exhausted the residual count.
307dd0b4fb6SKonstantin Belousov 		 */
308dd0b4fb6SKonstantin Belousov 
309dd0b4fb6SKonstantin Belousov 		addr = (caddr_t) iov[i].iov_base;
310dd0b4fb6SKonstantin Belousov 		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
311dd0b4fb6SKonstantin Belousov 		if (minlen > 0) {
312dd0b4fb6SKonstantin Belousov 			error = _bus_dmamap_load_buffer(dmat, map, addr,
313dd0b4fb6SKonstantin Belousov 			    minlen, pmap, flags, NULL, nsegs);
314dd0b4fb6SKonstantin Belousov 			resid -= minlen;
315dd0b4fb6SKonstantin Belousov 		}
316dd0b4fb6SKonstantin Belousov 	}
317dd0b4fb6SKonstantin Belousov 
318dd0b4fb6SKonstantin Belousov 	return (error);
319dd0b4fb6SKonstantin Belousov }
320dd0b4fb6SKonstantin Belousov 
321dd0b4fb6SKonstantin Belousov /*
322dd0b4fb6SKonstantin Belousov  * Map the buffer buf into bus space using the dmamap map.
323dd0b4fb6SKonstantin Belousov  */
324dd0b4fb6SKonstantin Belousov int
bus_dmamap_load(bus_dma_tag_t dmat,bus_dmamap_t map,void * buf,bus_size_t buflen,bus_dmamap_callback_t * callback,void * callback_arg,int flags)325dd0b4fb6SKonstantin Belousov bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
326dd0b4fb6SKonstantin Belousov     bus_size_t buflen, bus_dmamap_callback_t *callback,
327dd0b4fb6SKonstantin Belousov     void *callback_arg, int flags)
328dd0b4fb6SKonstantin Belousov {
329dd0b4fb6SKonstantin Belousov 	bus_dma_segment_t *segs;
330dd0b4fb6SKonstantin Belousov 	struct memdesc mem;
331dd0b4fb6SKonstantin Belousov 	int error;
332dd0b4fb6SKonstantin Belousov 	int nsegs;
333dd0b4fb6SKonstantin Belousov 
334693c9516SMark Johnston #ifdef KMSAN
335693c9516SMark Johnston 	mem = memdesc_vaddr(buf, buflen);
336693c9516SMark Johnston 	_bus_dmamap_load_kmsan(dmat, map, &mem);
337693c9516SMark Johnston #endif
338693c9516SMark Johnston 
339dd0b4fb6SKonstantin Belousov 	if ((flags & BUS_DMA_NOWAIT) == 0) {
340dd0b4fb6SKonstantin Belousov 		mem = memdesc_vaddr(buf, buflen);
341dd0b4fb6SKonstantin Belousov 		_bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg);
342dd0b4fb6SKonstantin Belousov 	}
343dd0b4fb6SKonstantin Belousov 
344dd0b4fb6SKonstantin Belousov 	nsegs = -1;
345dd0b4fb6SKonstantin Belousov 	error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap,
346dd0b4fb6SKonstantin Belousov 	    flags, NULL, &nsegs);
347dd0b4fb6SKonstantin Belousov 	nsegs++;
348dd0b4fb6SKonstantin Belousov 
349dd0b4fb6SKonstantin Belousov 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
350ab72998eSJim Harris 	    __func__, dmat, flags, error, nsegs);
351dd0b4fb6SKonstantin Belousov 
352dd0b4fb6SKonstantin Belousov 	if (error == EINPROGRESS)
353dd0b4fb6SKonstantin Belousov 		return (error);
354dd0b4fb6SKonstantin Belousov 
355dd0b4fb6SKonstantin Belousov 	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
356dd0b4fb6SKonstantin Belousov 	if (error)
357dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, 0, error);
358dd0b4fb6SKonstantin Belousov 	else
359dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, nsegs, 0);
360dd0b4fb6SKonstantin Belousov 
361dd0b4fb6SKonstantin Belousov 	/*
362dd0b4fb6SKonstantin Belousov 	 * Return ENOMEM to the caller so that it can pass it up the stack.
36347301c53SJim Harris 	 * This error only happens when NOWAIT is set, so deferral is disabled.
364dd0b4fb6SKonstantin Belousov 	 */
365dd0b4fb6SKonstantin Belousov 	if (error == ENOMEM)
366dd0b4fb6SKonstantin Belousov 		return (error);
367dd0b4fb6SKonstantin Belousov 
368dd0b4fb6SKonstantin Belousov 	return (0);
369dd0b4fb6SKonstantin Belousov }
370dd0b4fb6SKonstantin Belousov 
371dd0b4fb6SKonstantin Belousov int
bus_dmamap_load_mbuf(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m0,bus_dmamap_callback2_t * callback,void * callback_arg,int flags)372dd0b4fb6SKonstantin Belousov bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
373dd0b4fb6SKonstantin Belousov     bus_dmamap_callback2_t *callback, void *callback_arg, int flags)
374dd0b4fb6SKonstantin Belousov {
375dd0b4fb6SKonstantin Belousov 	bus_dma_segment_t *segs;
376dd0b4fb6SKonstantin Belousov 	int nsegs, error;
377dd0b4fb6SKonstantin Belousov 
3780ad17e4bSMarius Strobl 	M_ASSERTPKTHDR(m0);
3790ad17e4bSMarius Strobl 
380693c9516SMark Johnston #ifdef KMSAN
381693c9516SMark Johnston 	struct memdesc mem = memdesc_mbuf(m0);
382693c9516SMark Johnston 	_bus_dmamap_load_kmsan(dmat, map, &mem);
383693c9516SMark Johnston #endif
384693c9516SMark Johnston 
385dd0b4fb6SKonstantin Belousov 	flags |= BUS_DMA_NOWAIT;
386dd0b4fb6SKonstantin Belousov 	nsegs = -1;
387dd0b4fb6SKonstantin Belousov 	error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags);
388dd0b4fb6SKonstantin Belousov 	++nsegs;
389dd0b4fb6SKonstantin Belousov 
390dd0b4fb6SKonstantin Belousov 	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
391dd0b4fb6SKonstantin Belousov 	if (error)
392dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, 0, 0, error);
393dd0b4fb6SKonstantin Belousov 	else
394dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, nsegs, m0->m_pkthdr.len, error);
395dd0b4fb6SKonstantin Belousov 
396dd0b4fb6SKonstantin Belousov 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
397dd0b4fb6SKonstantin Belousov 	    __func__, dmat, flags, error, nsegs);
398dd0b4fb6SKonstantin Belousov 	return (error);
399dd0b4fb6SKonstantin Belousov }
400dd0b4fb6SKonstantin Belousov 
401dd0b4fb6SKonstantin Belousov int
bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m0,bus_dma_segment_t * segs,int * nsegs,int flags)402dd0b4fb6SKonstantin Belousov bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
403dd0b4fb6SKonstantin Belousov     bus_dma_segment_t *segs, int *nsegs, int flags)
404dd0b4fb6SKonstantin Belousov {
405dd0b4fb6SKonstantin Belousov 	int error;
406dd0b4fb6SKonstantin Belousov 
407693c9516SMark Johnston #ifdef KMSAN
408693c9516SMark Johnston 	struct memdesc mem = memdesc_mbuf(m0);
409693c9516SMark Johnston 	_bus_dmamap_load_kmsan(dmat, map, &mem);
410693c9516SMark Johnston #endif
411693c9516SMark Johnston 
412dd0b4fb6SKonstantin Belousov 	flags |= BUS_DMA_NOWAIT;
413dd0b4fb6SKonstantin Belousov 	*nsegs = -1;
414dd0b4fb6SKonstantin Belousov 	error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags);
415dd0b4fb6SKonstantin Belousov 	++*nsegs;
416dd0b4fb6SKonstantin Belousov 	_bus_dmamap_complete(dmat, map, segs, *nsegs, error);
417dd0b4fb6SKonstantin Belousov 	return (error);
418dd0b4fb6SKonstantin Belousov }
419dd0b4fb6SKonstantin Belousov 
420dd0b4fb6SKonstantin Belousov int
bus_dmamap_load_uio(bus_dma_tag_t dmat,bus_dmamap_t map,struct uio * uio,bus_dmamap_callback2_t * callback,void * callback_arg,int flags)421dd0b4fb6SKonstantin Belousov bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
422dd0b4fb6SKonstantin Belousov     bus_dmamap_callback2_t *callback, void *callback_arg, int flags)
423dd0b4fb6SKonstantin Belousov {
424dd0b4fb6SKonstantin Belousov 	bus_dma_segment_t *segs;
425dd0b4fb6SKonstantin Belousov 	int nsegs, error;
426dd0b4fb6SKonstantin Belousov 
427693c9516SMark Johnston #ifdef KMSAN
428693c9516SMark Johnston 	struct memdesc mem = memdesc_uio(uio);
429693c9516SMark Johnston 	_bus_dmamap_load_kmsan(dmat, map, &mem);
430693c9516SMark Johnston #endif
431693c9516SMark Johnston 
432dd0b4fb6SKonstantin Belousov 	flags |= BUS_DMA_NOWAIT;
433dd0b4fb6SKonstantin Belousov 	nsegs = -1;
434dd0b4fb6SKonstantin Belousov 	error = _bus_dmamap_load_uio(dmat, map, uio, &nsegs, flags);
435dd0b4fb6SKonstantin Belousov 	nsegs++;
436dd0b4fb6SKonstantin Belousov 
437dd0b4fb6SKonstantin Belousov 	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
438dd0b4fb6SKonstantin Belousov 	if (error)
439dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, 0, 0, error);
440dd0b4fb6SKonstantin Belousov 	else
441dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, nsegs, uio->uio_resid, error);
442dd0b4fb6SKonstantin Belousov 
443dd0b4fb6SKonstantin Belousov 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
444ab72998eSJim Harris 	    __func__, dmat, flags, error, nsegs);
445dd0b4fb6SKonstantin Belousov 	return (error);
446dd0b4fb6SKonstantin Belousov }
447dd0b4fb6SKonstantin Belousov 
448dd0b4fb6SKonstantin Belousov int
bus_dmamap_load_bio(bus_dma_tag_t dmat,bus_dmamap_t map,struct bio * bio,bus_dmamap_callback_t * callback,void * callback_arg,int flags)44910a93479SJim Harris bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio,
45010a93479SJim Harris 		    bus_dmamap_callback_t *callback, void *callback_arg,
45110a93479SJim Harris 		    int flags)
45210a93479SJim Harris {
45310a93479SJim Harris 	struct memdesc mem;
45410a93479SJim Harris 
455693c9516SMark Johnston 	mem = memdesc_bio(bio);
456c9b19803SJohn Baldwin 	return (bus_dmamap_load_mem(dmat, map, &mem, callback, callback_arg,
457c9b19803SJohn Baldwin 	    flags));
45810a93479SJim Harris }
45910a93479SJim Harris 
46010a93479SJim Harris int
bus_dmamap_load_mem(bus_dma_tag_t dmat,bus_dmamap_t map,struct memdesc * mem,bus_dmamap_callback_t * callback,void * callback_arg,int flags)461dd0b4fb6SKonstantin Belousov bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map,
462dd0b4fb6SKonstantin Belousov     struct memdesc *mem, bus_dmamap_callback_t *callback,
463dd0b4fb6SKonstantin Belousov     void *callback_arg, int flags)
464dd0b4fb6SKonstantin Belousov {
465dd0b4fb6SKonstantin Belousov 	bus_dma_segment_t *segs;
466dd0b4fb6SKonstantin Belousov 	int error;
467dd0b4fb6SKonstantin Belousov 	int nsegs;
468dd0b4fb6SKonstantin Belousov 
469693c9516SMark Johnston #ifdef KMSAN
470693c9516SMark Johnston 	_bus_dmamap_load_kmsan(dmat, map, mem);
471693c9516SMark Johnston #endif
472693c9516SMark Johnston 
473dd0b4fb6SKonstantin Belousov 	if ((flags & BUS_DMA_NOWAIT) == 0)
474dd0b4fb6SKonstantin Belousov 		_bus_dmamap_waitok(dmat, map, mem, callback, callback_arg);
475dd0b4fb6SKonstantin Belousov 
476dd0b4fb6SKonstantin Belousov 	nsegs = -1;
477dd0b4fb6SKonstantin Belousov 	error = 0;
478dd0b4fb6SKonstantin Belousov 	switch (mem->md_type) {
479dd0b4fb6SKonstantin Belousov 	case MEMDESC_VADDR:
480dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_buffer(dmat, map, mem->u.md_vaddr,
4813dba010eSJohn Baldwin 		    mem->md_len, kernel_pmap, flags, NULL, &nsegs);
482dd0b4fb6SKonstantin Belousov 		break;
483dd0b4fb6SKonstantin Belousov 	case MEMDESC_PADDR:
484dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_phys(dmat, map, mem->u.md_paddr,
4853dba010eSJohn Baldwin 		    mem->md_len, flags, NULL, &nsegs);
486dd0b4fb6SKonstantin Belousov 		break;
487dd0b4fb6SKonstantin Belousov 	case MEMDESC_VLIST:
488dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_vlist(dmat, map, mem->u.md_list,
4893dba010eSJohn Baldwin 		    mem->md_nseg, kernel_pmap, &nsegs, flags, 0, SIZE_T_MAX);
490dd0b4fb6SKonstantin Belousov 		break;
491dd0b4fb6SKonstantin Belousov 	case MEMDESC_PLIST:
492dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_plist(dmat, map, mem->u.md_list,
4933dba010eSJohn Baldwin 		    mem->md_nseg, &nsegs, flags);
494dd0b4fb6SKonstantin Belousov 		break;
495dd0b4fb6SKonstantin Belousov 	case MEMDESC_UIO:
496dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_uio(dmat, map, mem->u.md_uio,
497dd0b4fb6SKonstantin Belousov 		    &nsegs, flags);
498dd0b4fb6SKonstantin Belousov 		break;
499dd0b4fb6SKonstantin Belousov 	case MEMDESC_MBUF:
500dd0b4fb6SKonstantin Belousov 		error = _bus_dmamap_load_mbuf_sg(dmat, map, mem->u.md_mbuf,
501dd0b4fb6SKonstantin Belousov 		    NULL, &nsegs, flags);
502dd0b4fb6SKonstantin Belousov 		break;
503bab38b44SJohn Baldwin 	case MEMDESC_VMPAGES:
504bab38b44SJohn Baldwin 		error = _bus_dmamap_load_ma(dmat, map, mem->u.md_ma,
505bab38b44SJohn Baldwin 		    mem->md_len, mem->md_offset, flags, NULL, &nsegs);
506bab38b44SJohn Baldwin 		break;
507dd0b4fb6SKonstantin Belousov 	}
508dd0b4fb6SKonstantin Belousov 	nsegs++;
509dd0b4fb6SKonstantin Belousov 
510dd0b4fb6SKonstantin Belousov 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
511ab72998eSJim Harris 	    __func__, dmat, flags, error, nsegs);
512dd0b4fb6SKonstantin Belousov 
513dd0b4fb6SKonstantin Belousov 	if (error == EINPROGRESS)
514dd0b4fb6SKonstantin Belousov 		return (error);
515dd0b4fb6SKonstantin Belousov 
516dd0b4fb6SKonstantin Belousov 	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
517dd0b4fb6SKonstantin Belousov 	if (error)
518dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, 0, error);
519dd0b4fb6SKonstantin Belousov 	else
520dd0b4fb6SKonstantin Belousov 		(*callback)(callback_arg, segs, nsegs, 0);
521dd0b4fb6SKonstantin Belousov 
522dd0b4fb6SKonstantin Belousov 	/*
523dd0b4fb6SKonstantin Belousov 	 * Return ENOMEM to the caller so that it can pass it up the stack.
52447301c53SJim Harris 	 * This error only happens when NOWAIT is set, so deferral is disabled.
525dd0b4fb6SKonstantin Belousov 	 */
526dd0b4fb6SKonstantin Belousov 	if (error == ENOMEM)
527dd0b4fb6SKonstantin Belousov 		return (error);
528dd0b4fb6SKonstantin Belousov 
529dd0b4fb6SKonstantin Belousov 	return (0);
530dd0b4fb6SKonstantin Belousov }
531c0341432SJohn Baldwin 
532c0341432SJohn Baldwin int
bus_dmamap_load_crp_buffer(bus_dma_tag_t dmat,bus_dmamap_t map,struct crypto_buffer * cb,bus_dmamap_callback_t * callback,void * callback_arg,int flags)5339c0e3d3aSJohn Baldwin bus_dmamap_load_crp_buffer(bus_dma_tag_t dmat, bus_dmamap_t map,
5349c0e3d3aSJohn Baldwin     struct crypto_buffer *cb, bus_dmamap_callback_t *callback,
5359c0e3d3aSJohn Baldwin     void *callback_arg, int flags)
536c0341432SJohn Baldwin {
537c0341432SJohn Baldwin 	bus_dma_segment_t *segs;
538c0341432SJohn Baldwin 	int error;
539c0341432SJohn Baldwin 	int nsegs;
540c0341432SJohn Baldwin 
541c0341432SJohn Baldwin 	flags |= BUS_DMA_NOWAIT;
542c0341432SJohn Baldwin 	nsegs = -1;
543c0341432SJohn Baldwin 	error = 0;
5449c0e3d3aSJohn Baldwin 	switch (cb->cb_type) {
545c0341432SJohn Baldwin 	case CRYPTO_BUF_CONTIG:
5469c0e3d3aSJohn Baldwin 		error = _bus_dmamap_load_buffer(dmat, map, cb->cb_buf,
5479c0e3d3aSJohn Baldwin 		    cb->cb_buf_len, kernel_pmap, flags, NULL, &nsegs);
548c0341432SJohn Baldwin 		break;
549c0341432SJohn Baldwin 	case CRYPTO_BUF_MBUF:
5509c0e3d3aSJohn Baldwin 		error = _bus_dmamap_load_mbuf_sg(dmat, map, cb->cb_mbuf,
551c0341432SJohn Baldwin 		    NULL, &nsegs, flags);
552c0341432SJohn Baldwin 		break;
553883a0196SJohn Baldwin 	case CRYPTO_BUF_SINGLE_MBUF:
554883a0196SJohn Baldwin 		error = _bus_dmamap_load_single_mbuf(dmat, map, cb->cb_mbuf,
555883a0196SJohn Baldwin 		    NULL, &nsegs, flags);
556883a0196SJohn Baldwin 		break;
557c0341432SJohn Baldwin 	case CRYPTO_BUF_UIO:
5589c0e3d3aSJohn Baldwin 		error = _bus_dmamap_load_uio(dmat, map, cb->cb_uio, &nsegs,
559c0341432SJohn Baldwin 		    flags);
560c0341432SJohn Baldwin 		break;
561e6f6d0c9SAlan Somers 	case CRYPTO_BUF_VMPAGE:
562e6f6d0c9SAlan Somers 		error = _bus_dmamap_load_ma(dmat, map, cb->cb_vm_page,
563e6f6d0c9SAlan Somers 		    cb->cb_vm_page_len, cb->cb_vm_page_offset, flags, NULL,
564e6f6d0c9SAlan Somers 		    &nsegs);
565e6f6d0c9SAlan Somers 		break;
5669c0e3d3aSJohn Baldwin 	default:
5679c0e3d3aSJohn Baldwin 		error = EINVAL;
568c0341432SJohn Baldwin 	}
569c0341432SJohn Baldwin 	nsegs++;
570c0341432SJohn Baldwin 
571c0341432SJohn Baldwin 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
572c0341432SJohn Baldwin 	    __func__, dmat, flags, error, nsegs);
573c0341432SJohn Baldwin 
574c0341432SJohn Baldwin 	if (error == EINPROGRESS)
575c0341432SJohn Baldwin 		return (error);
576c0341432SJohn Baldwin 
577c0341432SJohn Baldwin 	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
578c0341432SJohn Baldwin 	if (error)
579c0341432SJohn Baldwin 		(*callback)(callback_arg, segs, 0, error);
580c0341432SJohn Baldwin 	else
581c0341432SJohn Baldwin 		(*callback)(callback_arg, segs, nsegs, 0);
582c0341432SJohn Baldwin 
583c0341432SJohn Baldwin 	/*
584c0341432SJohn Baldwin 	 * Return ENOMEM to the caller so that it can pass it up the stack.
585c0341432SJohn Baldwin 	 * This error only happens when NOWAIT is set, so deferral is disabled.
586c0341432SJohn Baldwin 	 */
587c0341432SJohn Baldwin 	if (error == ENOMEM)
588c0341432SJohn Baldwin 		return (error);
589c0341432SJohn Baldwin 
590c0341432SJohn Baldwin 	return (0);
591c0341432SJohn Baldwin }
5929c0e3d3aSJohn Baldwin 
5939c0e3d3aSJohn Baldwin int
bus_dmamap_load_crp(bus_dma_tag_t dmat,bus_dmamap_t map,struct cryptop * crp,bus_dmamap_callback_t * callback,void * callback_arg,int flags)5949c0e3d3aSJohn Baldwin bus_dmamap_load_crp(bus_dma_tag_t dmat, bus_dmamap_t map, struct cryptop *crp,
5959c0e3d3aSJohn Baldwin     bus_dmamap_callback_t *callback, void *callback_arg, int flags)
5969c0e3d3aSJohn Baldwin {
5979c0e3d3aSJohn Baldwin 	return (bus_dmamap_load_crp_buffer(dmat, map, &crp->crp_buf, callback,
5989c0e3d3aSJohn Baldwin 	    callback_arg, flags));
5999c0e3d3aSJohn Baldwin }
60074c781edSScott Long 
60174c781edSScott Long void
bus_dma_template_init(bus_dma_template_t * t,bus_dma_tag_t parent)60274c781edSScott Long bus_dma_template_init(bus_dma_template_t *t, bus_dma_tag_t parent)
60374c781edSScott Long {
60474c781edSScott Long 
60574c781edSScott Long 	if (t == NULL)
60674c781edSScott Long 		return;
60774c781edSScott Long 
60874c781edSScott Long 	t->parent = parent;
60974c781edSScott Long 	t->alignment = 1;
61074c781edSScott Long 	t->boundary = 0;
61174c781edSScott Long 	t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR;
61274c781edSScott Long 	t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE;
61374c781edSScott Long 	t->nsegments = BUS_SPACE_UNRESTRICTED;
61474c781edSScott Long 	t->lockfunc = NULL;
61574c781edSScott Long 	t->lockfuncarg = NULL;
61674c781edSScott Long 	t->flags = 0;
61774c781edSScott Long }
61874c781edSScott Long 
61974c781edSScott Long int
bus_dma_template_tag(bus_dma_template_t * t,bus_dma_tag_t * dmat)62074c781edSScott Long bus_dma_template_tag(bus_dma_template_t *t, bus_dma_tag_t *dmat)
62174c781edSScott Long {
62274c781edSScott Long 
62374c781edSScott Long 	if (t == NULL || dmat == NULL)
62474c781edSScott Long 		return (EINVAL);
62574c781edSScott Long 
62674c781edSScott Long 	return (bus_dma_tag_create(t->parent, t->alignment, t->boundary,
62774c781edSScott Long 	    t->lowaddr, t->highaddr, NULL, NULL, t->maxsize,
62874c781edSScott Long 	    t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg,
62974c781edSScott Long 	    dmat));
63074c781edSScott Long }
63174c781edSScott Long 
63274c781edSScott Long void
bus_dma_template_fill(bus_dma_template_t * t,bus_dma_param_t * kv,u_int count)63374c781edSScott Long bus_dma_template_fill(bus_dma_template_t *t, bus_dma_param_t *kv, u_int count)
63474c781edSScott Long {
63574c781edSScott Long 	bus_dma_param_t *pkv;
63674c781edSScott Long 
63774c781edSScott Long 	while (count) {
63874c781edSScott Long 		pkv = &kv[--count];
63974c781edSScott Long 		switch (pkv->key) {
64074c781edSScott Long 		case BD_PARAM_PARENT:
64174c781edSScott Long 			t->parent = pkv->ptr;
64274c781edSScott Long 			break;
64374c781edSScott Long 		case BD_PARAM_ALIGNMENT:
64474c781edSScott Long 			t->alignment = pkv->num;
64574c781edSScott Long 			break;
64674c781edSScott Long 		case BD_PARAM_BOUNDARY:
64774c781edSScott Long 			t->boundary = pkv->num;
64874c781edSScott Long 			break;
64974c781edSScott Long 		case BD_PARAM_LOWADDR:
65074c781edSScott Long 			t->lowaddr = pkv->pa;
65174c781edSScott Long 			break;
65274c781edSScott Long 		case BD_PARAM_HIGHADDR:
65374c781edSScott Long 			t->highaddr = pkv->pa;
65474c781edSScott Long 			break;
65574c781edSScott Long 		case BD_PARAM_MAXSIZE:
65674c781edSScott Long 			t->maxsize = pkv->num;
65774c781edSScott Long 			break;
65874c781edSScott Long 		case BD_PARAM_NSEGMENTS:
65974c781edSScott Long 			t->nsegments = pkv->num;
66074c781edSScott Long 			break;
66174c781edSScott Long 		case BD_PARAM_MAXSEGSIZE:
66274c781edSScott Long 			t->maxsegsize = pkv->num;
66374c781edSScott Long 			break;
66474c781edSScott Long 		case BD_PARAM_FLAGS:
66574c781edSScott Long 			t->flags = pkv->num;
66674c781edSScott Long 			break;
66774c781edSScott Long 		case BD_PARAM_LOCKFUNC:
66874c781edSScott Long 			t->lockfunc = pkv->ptr;
66974c781edSScott Long 			break;
67074c781edSScott Long 		case BD_PARAM_LOCKFUNCARG:
67174c781edSScott Long 			t->lockfuncarg = pkv->ptr;
67274c781edSScott Long 			break;
67374c781edSScott Long 		case BD_PARAM_NAME:
67474c781edSScott Long 			t->name = pkv->ptr;
67574c781edSScott Long 			break;
67674c781edSScott Long 		case BD_PARAM_INVALID:
67774c781edSScott Long 		default:
67874c781edSScott Long 			KASSERT(0, ("Invalid key %d\n", pkv->key));
67974c781edSScott Long 			break;
68074c781edSScott Long 		}
68174c781edSScott Long 	}
68274c781edSScott Long 	return;
68374c781edSScott Long }
68474c781edSScott Long 
6859729b149SRuslan Bukin #ifndef IOMMU
6869729b149SRuslan Bukin bool bus_dma_iommu_set_buswide(device_t dev);
6879729b149SRuslan Bukin int bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map,
6889729b149SRuslan Bukin     vm_paddr_t start, vm_size_t length, int flags);
6899729b149SRuslan Bukin 
6909729b149SRuslan Bukin bool
bus_dma_iommu_set_buswide(device_t dev)6919729b149SRuslan Bukin bus_dma_iommu_set_buswide(device_t dev)
6929729b149SRuslan Bukin {
6939729b149SRuslan Bukin 	return (false);
6949729b149SRuslan Bukin }
6959729b149SRuslan Bukin 
6969729b149SRuslan Bukin int
bus_dma_iommu_load_ident(bus_dma_tag_t dmat,bus_dmamap_t map,vm_paddr_t start,vm_size_t length,int flags)6979729b149SRuslan Bukin bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map,
6989729b149SRuslan Bukin     vm_paddr_t start, vm_size_t length, int flags)
6999729b149SRuslan Bukin {
7009729b149SRuslan Bukin 	return (0);
7019729b149SRuslan Bukin }
7029729b149SRuslan Bukin #endif
703