xref: /titanic_52/usr/src/uts/sun4u/io/iommu.c (revision 56a424cca6b3f91f31bdab72a4626c48c779fe8b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/conf.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/ddi_impldefs.h>
35 #include <sys/cmn_err.h>
36 #include <sys/kmem.h>
37 #include <sys/vmem.h>
38 #include <sys/sysmacros.h>
39 
40 #include <sys/ddidmareq.h>
41 #include <sys/sysiosbus.h>
42 #include <sys/iommu.h>
43 #include <sys/iocache.h>
44 #include <sys/dvma.h>
45 
46 #include <vm/as.h>
47 #include <vm/hat.h>
48 #include <vm/page.h>
49 #include <vm/hat_sfmmu.h>
50 #include <sys/machparam.h>
51 #include <sys/machsystm.h>
52 #include <sys/vmsystm.h>
53 #include <sys/iommutsb.h>
54 
55 /* Useful debugging Stuff */
56 #include <sys/nexusdebug.h>
57 #include <sys/debug.h>
58 /* Bitfield debugging definitions for this file */
59 #define	IOMMU_GETDVMAPAGES_DEBUG	0x1
60 #define	IOMMU_DMAMAP_DEBUG		0x2
61 #define	IOMMU_DMAMCTL_DEBUG		0x4
62 #define	IOMMU_DMAMCTL_SYNC_DEBUG	0x8
63 #define	IOMMU_DMAMCTL_HTOC_DEBUG	0x10
64 #define	IOMMU_DMAMCTL_KVADDR_DEBUG	0x20
65 #define	IOMMU_DMAMCTL_NEXTWIN_DEBUG	0x40
66 #define	IOMMU_DMAMCTL_NEXTSEG_DEBUG	0x80
67 #define	IOMMU_DMAMCTL_MOVWIN_DEBUG	0x100
68 #define	IOMMU_DMAMCTL_REPWIN_DEBUG	0x200
69 #define	IOMMU_DMAMCTL_GETERR_DEBUG	0x400
70 #define	IOMMU_DMAMCTL_COFF_DEBUG	0x800
71 #define	IOMMU_DMAMCTL_DMA_FREE_DEBUG	0x1000
72 #define	IOMMU_REGISTERS_DEBUG		0x2000
73 #define	IOMMU_DMA_SETUP_DEBUG		0x4000
74 #define	IOMMU_DMA_UNBINDHDL_DEBUG	0x8000
75 #define	IOMMU_DMA_BINDHDL_DEBUG		0x10000
76 #define	IOMMU_DMA_WIN_DEBUG		0x20000
77 #define	IOMMU_DMA_ALLOCHDL_DEBUG	0x40000
78 #define	IOMMU_DMA_LIM_SETUP_DEBUG	0x80000
79 #define	IOMMU_FASTDMA_RESERVE		0x100000
80 #define	IOMMU_FASTDMA_LOAD		0x200000
81 #define	IOMMU_INTER_INTRA_XFER		0x400000
82 #define	IOMMU_TTE			0x800000
83 #define	IOMMU_TLB			0x1000000
84 #define	IOMMU_FASTDMA_SYNC		0x2000000
85 
86 /* Turn on if you need to keep track of outstanding IOMMU usage */
87 /* #define	IO_MEMUSAGE */
88 /* Turn on to debug IOMMU unmapping code */
89 /* #define	IO_MEMDEBUG */
90 
91 static struct dvma_ops iommu_dvma_ops = {
92 	DVMAO_REV,
93 	iommu_dvma_kaddr_load,
94 	iommu_dvma_unload,
95 	iommu_dvma_sync
96 };
97 
98 extern void *sbusp;		/* sbus soft state hook */
99 
100 #define	DVMA_MAX_CACHE	65536
101 
102 /*
103  * This is the number of pages that a mapping request needs before we force
104  * the TLB flush code to use diagnostic registers.  This value was determined
105  * through a series of test runs measuring dma mapping settup performance.
106  */
107 int tlb_flush_using_diag = 16;
108 
109 int sysio_iommu_tsb_sizes[] = {
110 	IOMMU_TSB_SIZE_8M,
111 	IOMMU_TSB_SIZE_16M,
112 	IOMMU_TSB_SIZE_32M,
113 	IOMMU_TSB_SIZE_64M,
114 	IOMMU_TSB_SIZE_128M,
115 	IOMMU_TSB_SIZE_256M,
116 	IOMMU_TSB_SIZE_512M,
117 	IOMMU_TSB_SIZE_1G
118 };
119 
120 static int iommu_map_window(ddi_dma_impl_t *, off_t, size_t);
121 
122 int
123 iommu_init(struct sbus_soft_state *softsp, caddr_t address)
124 {
125 	int i;
126 	char name[40];
127 
128 #ifdef DEBUG
129 	debug_info = 1;
130 #endif
131 
132 	/*
133 	 * Simply add each registers offset to the base address
134 	 * to calculate the already mapped virtual address of
135 	 * the device register...
136 	 *
137 	 * define a macro for the pointer arithmetic; all registers
138 	 * are 64 bits wide and are defined as uint64_t's.
139 	 */
140 
141 #define	REG_ADDR(b, o)	(uint64_t *)((caddr_t)(b) + (o))
142 
143 	softsp->iommu_ctrl_reg = REG_ADDR(address, OFF_IOMMU_CTRL_REG);
144 	softsp->tsb_base_addr = REG_ADDR(address, OFF_TSB_BASE_ADDR);
145 	softsp->iommu_flush_reg = REG_ADDR(address, OFF_IOMMU_FLUSH_REG);
146 	softsp->iommu_tlb_tag = REG_ADDR(address, OFF_IOMMU_TLB_TAG);
147 	softsp->iommu_tlb_data = REG_ADDR(address, OFF_IOMMU_TLB_DATA);
148 
149 #undef REG_ADDR
150 
151 	mutex_init(&softsp->dma_pool_lock, NULL, MUTEX_DEFAULT, NULL);
152 	mutex_init(&softsp->intr_poll_list_lock, NULL, MUTEX_DEFAULT, NULL);
153 
154 	/* Set up the DVMA resource sizes */
155 	if ((softsp->iommu_tsb_cookie = iommu_tsb_alloc(softsp->upa_id)) ==
156 	    IOMMU_TSB_COOKIE_NONE) {
157 		cmn_err(CE_WARN, "%s%d: Unable to retrieve IOMMU array.",
158 		    ddi_driver_name(softsp->dip),
159 		    ddi_get_instance(softsp->dip));
160 		return (DDI_FAILURE);
161 	}
162 	softsp->soft_tsb_base_addr =
163 	    iommu_tsb_cookie_to_va(softsp->iommu_tsb_cookie);
164 	softsp->iommu_dvma_size =
165 	    iommu_tsb_cookie_to_size(softsp->iommu_tsb_cookie) <<
166 	    IOMMU_TSB_TO_RNG;
167 	softsp->iommu_dvma_base = (ioaddr_t)
168 	    (0 - (ioaddr_t)softsp->iommu_dvma_size);
169 
170 	(void) snprintf(name, sizeof (name), "%s%d_dvma",
171 	    ddi_driver_name(softsp->dip), ddi_get_instance(softsp->dip));
172 
173 	/*
174 	 * Initialize the DVMA vmem arena.
175 	 */
176 	softsp->dvma_arena = vmem_create(name,
177 	    (void *)(uintptr_t)softsp->iommu_dvma_base,
178 	    softsp->iommu_dvma_size, PAGESIZE, NULL, NULL, NULL,
179 	    DVMA_MAX_CACHE, VM_SLEEP);
180 
181 	/* Set the limit for dvma_reserve() to 1/2 of the total dvma space */
182 	softsp->dma_reserve = iommu_btop(softsp->iommu_dvma_size >> 1);
183 
184 #if defined(DEBUG) && defined(IO_MEMUSAGE)
185 	mutex_init(&softsp->iomemlock, NULL, MUTEX_DEFAULT, NULL);
186 	softsp->iomem = (struct io_mem_list *)0;
187 #endif /* DEBUG && IO_MEMUSAGE */
188 	/*
189 	 * Get the base address of the TSB table and store it in the hardware
190 	 */
191 
192 	/*
193 	 * We plan on the PROM flushing all TLB entries.  If this is not the
194 	 * case, this is where we should flush the hardware TLB.
195 	 */
196 
197 	/* Set the IOMMU registers */
198 	(void) iommu_resume_init(softsp);
199 
200 	/* check the convenient copy of TSB base, and flush write buffers */
201 	if (*softsp->tsb_base_addr !=
202 	    va_to_pa((caddr_t)softsp->soft_tsb_base_addr)) {
203 		iommu_tsb_free(softsp->iommu_tsb_cookie);
204 		return (DDI_FAILURE);
205 	}
206 
207 	softsp->sbus_io_lo_pfn = UINT32_MAX;
208 	softsp->sbus_io_hi_pfn = 0;
209 	for (i = 0; i < sysio_pd_getnrng(softsp->dip); i++) {
210 		struct rangespec *rangep;
211 		uint64_t addr;
212 		pfn_t hipfn, lopfn;
213 
214 		rangep = sysio_pd_getrng(softsp->dip, i);
215 		addr = (uint64_t)((uint64_t)rangep->rng_bustype << 32);
216 		addr |= (uint64_t)rangep->rng_offset;
217 		lopfn = (pfn_t)(addr >> MMU_PAGESHIFT);
218 		addr += (uint64_t)(rangep->rng_size - 1);
219 		hipfn = (pfn_t)(addr >> MMU_PAGESHIFT);
220 
221 		softsp->sbus_io_lo_pfn = (lopfn < softsp->sbus_io_lo_pfn) ?
222 		    lopfn : softsp->sbus_io_lo_pfn;
223 
224 		softsp->sbus_io_hi_pfn = (hipfn > softsp->sbus_io_hi_pfn) ?
225 		    hipfn : softsp->sbus_io_hi_pfn;
226 	}
227 
228 	DPRINTF(IOMMU_REGISTERS_DEBUG, ("IOMMU Control reg: %p IOMMU TSB "
229 	    "base reg: %p IOMMU flush reg: %p TSB base addr %p\n",
230 	    softsp->iommu_ctrl_reg, softsp->tsb_base_addr,
231 	    softsp->iommu_flush_reg, softsp->soft_tsb_base_addr));
232 
233 	return (DDI_SUCCESS);
234 }
235 
236 /*
237  * function to uninitialize the iommu and release the tsb back to
238  * the spare pool.  See startup.c for tsb spare management.
239  */
240 
241 int
242 iommu_uninit(struct sbus_soft_state *softsp)
243 {
244 	vmem_destroy(softsp->dvma_arena);
245 
246 	/* flip off the IOMMU enable switch */
247 	*softsp->iommu_ctrl_reg &=
248 		(TSB_SIZE << TSB_SIZE_SHIFT | IOMMU_DISABLE);
249 
250 	iommu_tsb_free(softsp->iommu_tsb_cookie);
251 
252 	return (DDI_SUCCESS);
253 }
254 
255 /*
256  * Initialize iommu hardware registers when the system is being resumed.
257  * (Subset of iommu_init())
258  */
259 int
260 iommu_resume_init(struct sbus_soft_state *softsp)
261 {
262 	int i;
263 	uint_t tsb_size;
264 	uint_t tsb_bytes;
265 
266 	/*
267 	 * Reset the base address of the TSB table in the hardware
268 	 */
269 	*softsp->tsb_base_addr = va_to_pa((caddr_t)softsp->soft_tsb_base_addr);
270 
271 	/*
272 	 * Figure out the correct size of the IOMMU TSB entries.  If we
273 	 * end up with a size smaller than that needed for 8M of IOMMU
274 	 * space, default the size to 8M.  XXX We could probably panic here
275 	 */
276 	i = sizeof (sysio_iommu_tsb_sizes) / sizeof (sysio_iommu_tsb_sizes[0])
277 	    - 1;
278 
279 	tsb_bytes = iommu_tsb_cookie_to_size(softsp->iommu_tsb_cookie);
280 
281 	while (i > 0) {
282 		if (tsb_bytes >= sysio_iommu_tsb_sizes[i])
283 			break;
284 		i--;
285 	}
286 
287 	tsb_size = i;
288 
289 	/* OK, lets flip the "on" switch of the IOMMU */
290 	*softsp->iommu_ctrl_reg = (uint64_t)(tsb_size << TSB_SIZE_SHIFT
291 	    | IOMMU_ENABLE | IOMMU_DIAG_ENABLE);
292 
293 	return (DDI_SUCCESS);
294 }
295 
296 void
297 iommu_tlb_flush(struct sbus_soft_state *softsp, ioaddr_t addr, pgcnt_t npages)
298 {
299 	volatile uint64_t tmpreg;
300 	volatile uint64_t *vaddr_reg, *valid_bit_reg;
301 	ioaddr_t hiaddr, ioaddr;
302 	int i, do_flush = 0;
303 
304 	if (npages == 1) {
305 		*softsp->iommu_flush_reg = (uint64_t)addr;
306 		tmpreg = *softsp->sbus_ctrl_reg;
307 		return;
308 	}
309 
310 	hiaddr = addr + (ioaddr_t)(npages * IOMMU_PAGESIZE);
311 	for (i = 0, vaddr_reg = softsp->iommu_tlb_tag,
312 	    valid_bit_reg = softsp->iommu_tlb_data;
313 	    i < IOMMU_TLB_ENTRIES; i++, vaddr_reg++, valid_bit_reg++) {
314 		tmpreg = *vaddr_reg;
315 		ioaddr = (ioaddr_t)((tmpreg & IOMMU_TLBTAG_VA_MASK) <<
316 		    IOMMU_TLBTAG_VA_SHIFT);
317 
318 		DPRINTF(IOMMU_TLB, ("Vaddr reg 0x%p, "
319 		    "TLB vaddr reg %lx, IO addr 0x%x "
320 		    "Base addr 0x%x, Hi addr 0x%x\n",
321 		    vaddr_reg, tmpreg, ioaddr, addr, hiaddr));
322 
323 		if (ioaddr >= addr && ioaddr <= hiaddr) {
324 			tmpreg = *valid_bit_reg;
325 
326 			DPRINTF(IOMMU_TLB, ("Valid reg addr 0x%p, "
327 			    "TLB valid reg %lx\n",
328 			    valid_bit_reg, tmpreg));
329 
330 			if (tmpreg & IOMMU_TLB_VALID) {
331 				*softsp->iommu_flush_reg = (uint64_t)ioaddr;
332 				do_flush = 1;
333 			}
334 		}
335 	}
336 
337 	if (do_flush)
338 		tmpreg = *softsp->sbus_ctrl_reg;
339 }
340 
341 
342 /*
343  * Shorthand defines
344  */
345 
346 #define	ALO		dma_lim->dlim_addr_lo
347 #define	AHI		dma_lim->dlim_addr_hi
348 #define	OBJSIZE		dmareq->dmar_object.dmao_size
349 #define	IOTTE_NDX(vaddr, base) (base + \
350 		(int)(iommu_btop((vaddr & ~IOMMU_PAGEMASK) - \
351 		softsp->iommu_dvma_base)))
352 /*
353  * If DDI_DMA_PARTIAL flag is set and the request is for
354  * less than MIN_DVMA_WIN_SIZE, it's not worth the hassle so
355  * we turn off the DDI_DMA_PARTIAL flag
356  */
357 #define	MIN_DVMA_WIN_SIZE	(128)
358 
359 /* ARGSUSED */
360 void
361 iommu_remove_mappings(ddi_dma_impl_t *mp)
362 {
363 #if defined(DEBUG) && defined(IO_MEMDEBUG)
364 	pgcnt_t npages;
365 	ioaddr_t ioaddr;
366 	volatile uint64_t *iotte_ptr;
367 	ioaddr_t ioaddr = mp->dmai_mapping & ~IOMMU_PAGEOFFSET;
368 	pgcnt_t npages = mp->dmai_ndvmapages;
369 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
370 	struct sbus_soft_state *softsp = mppriv->softsp;
371 
372 #if defined(IO_MEMUSAGE)
373 	struct io_mem_list **prevp, *walk;
374 #endif /* DEBUG && IO_MEMUSAGE */
375 
376 	ASSERT(softsp != NULL);
377 	/*
378 	 * Run thru the mapped entries and free 'em
379 	 */
380 
381 	ioaddr = mp->dmai_mapping & ~IOMMU_PAGEOFFSET;
382 	npages = mp->dmai_ndvmapages;
383 
384 #if defined(IO_MEMUSAGE)
385 	mutex_enter(&softsp->iomemlock);
386 	prevp = &softsp->iomem;
387 	walk = softsp->iomem;
388 
389 	while (walk) {
390 		if (walk->ioaddr == ioaddr) {
391 			*prevp = walk->next;
392 			break;
393 		}
394 
395 		prevp = &walk->next;
396 		walk = walk->next;
397 	}
398 	mutex_exit(&softsp->iomemlock);
399 
400 	kmem_free(walk->pfn, sizeof (pfn_t) * (npages + 1));
401 	kmem_free(walk, sizeof (struct io_mem_list));
402 #endif /* IO_MEMUSAGE */
403 
404 	iotte_ptr = IOTTE_NDX(ioaddr, softsp->soft_tsb_base_addr);
405 
406 	while (npages) {
407 		DPRINTF(IOMMU_DMAMCTL_DEBUG,
408 		    ("dma_mctl: freeing ioaddr %x iotte %p\n",
409 		    ioaddr, iotte_ptr));
410 		*iotte_ptr = (uint64_t)0;	/* unload tte */
411 		iommu_tlb_flush(softsp, ioaddr, 1);
412 		npages--;
413 		ioaddr += IOMMU_PAGESIZE;
414 		iotte_ptr++;
415 	}
416 #endif /* DEBUG && IO_MEMDEBUG */
417 }
418 
419 
420 int
421 iommu_create_vaddr_mappings(ddi_dma_impl_t *mp, uintptr_t addr)
422 {
423 	pfn_t pfn;
424 	struct as *as = NULL;
425 	pgcnt_t npages;
426 	ioaddr_t ioaddr;
427 	uint_t offset;
428 	volatile uint64_t *iotte_ptr;
429 	uint64_t tmp_iotte_flag;
430 	int rval = DDI_DMA_MAPPED;
431 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
432 	struct sbus_soft_state *softsp = mppriv->softsp;
433 	int diag_tlb_flush;
434 #if defined(DEBUG) && defined(IO_MEMUSAGE)
435 	struct io_mem_list *iomemp;
436 	pfn_t *pfnp;
437 #endif /* DEBUG && IO_MEMUSAGE */
438 
439 	ASSERT(softsp != NULL);
440 
441 	/* Set Valid and Cache for mem xfer */
442 	tmp_iotte_flag = IOTTE_VALID | IOTTE_CACHE | IOTTE_WRITE | IOTTE_STREAM;
443 
444 	offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
445 	npages = iommu_btopr(mp->dmai_size + offset);
446 	ioaddr = (ioaddr_t)(mp->dmai_mapping & ~IOMMU_PAGEOFFSET);
447 	iotte_ptr = IOTTE_NDX(ioaddr, softsp->soft_tsb_base_addr);
448 	diag_tlb_flush = npages > tlb_flush_using_diag ? 1 : 0;
449 
450 	as = mp->dmai_object.dmao_obj.virt_obj.v_as;
451 	if (as == NULL)
452 		as = &kas;
453 
454 	/*
455 	 * Set the per object bits of the TTE here. We optimize this for
456 	 * the memory case so that the while loop overhead is minimal.
457 	 */
458 	/* Turn on NOSYNC if we need consistent mem */
459 	if (mp->dmai_rflags & DDI_DMA_CONSISTENT) {
460 		mp->dmai_rflags |= DMP_NOSYNC;
461 		tmp_iotte_flag ^= IOTTE_STREAM;
462 	/* Set streaming mode if not consistent mem */
463 	} else if (softsp->stream_buf_off) {
464 		tmp_iotte_flag ^= IOTTE_STREAM;
465 	}
466 
467 #if defined(DEBUG) && defined(IO_MEMUSAGE)
468 	iomemp = kmem_alloc(sizeof (struct io_mem_list), KM_SLEEP);
469 	iomemp->rdip = mp->dmai_rdip;
470 	iomemp->ioaddr = ioaddr;
471 	iomemp->addr = addr;
472 	iomemp->npages = npages;
473 	pfnp = iomemp->pfn = kmem_zalloc(sizeof (*pfnp) * (npages + 1),
474 	    KM_SLEEP);
475 #endif /* DEBUG && IO_MEMUSAGE */
476 	/*
477 	 * Grab the mappings from the dmmu and stick 'em into the
478 	 * iommu.
479 	 */
480 	ASSERT(npages != 0);
481 
482 	/* If we're going to flush the TLB using diag mode, do it now. */
483 	if (diag_tlb_flush)
484 		iommu_tlb_flush(softsp, ioaddr, npages);
485 
486 	do {
487 		uint64_t iotte_flag = tmp_iotte_flag;
488 
489 		/*
490 		 * Fetch the pfn for the DMA object
491 		 */
492 
493 		ASSERT(as);
494 		pfn = hat_getpfnum(as->a_hat, (caddr_t)addr);
495 		ASSERT(pfn != PFN_INVALID);
496 
497 		if (!pf_is_memory(pfn)) {
498 			/* DVMA'ing to IO space */
499 
500 			/* Turn off cache bit if set */
501 			if (iotte_flag & IOTTE_CACHE)
502 				iotte_flag ^= IOTTE_CACHE;
503 
504 			/* Turn off stream bit if set */
505 			if (iotte_flag & IOTTE_STREAM)
506 				iotte_flag ^= IOTTE_STREAM;
507 
508 			if (IS_INTRA_SBUS(softsp, pfn)) {
509 				/* Intra sbus transfer */
510 
511 				/* Turn on intra flag */
512 				iotte_flag |= IOTTE_INTRA;
513 
514 				DPRINTF(IOMMU_INTER_INTRA_XFER, (
515 				    "Intra xfer pfnum %lx TTE %lx\n",
516 				    pfn, iotte_flag));
517 			} else {
518 				if (pf_is_dmacapable(pfn) == 1) {
519 					/*EMPTY*/
520 					DPRINTF(IOMMU_INTER_INTRA_XFER,
521 					    ("Inter xfer pfnum %lx "
522 					    "tte hi %lx\n",
523 					    pfn, iotte_flag));
524 				} else {
525 					rval = DDI_DMA_NOMAPPING;
526 #if defined(DEBUG) && defined(IO_MEMDEBUG)
527 					goto bad;
528 #endif /* DEBUG && IO_MEMDEBUG */
529 				}
530 			}
531 		}
532 		addr += IOMMU_PAGESIZE;
533 
534 		DPRINTF(IOMMU_TTE, ("vaddr mapping: tte index %p pfn %lx "
535 		    "tte flag %lx addr %lx ioaddr %x\n",
536 		    iotte_ptr, pfn, iotte_flag, addr, ioaddr));
537 
538 		/* Flush the IOMMU TLB before loading a new mapping */
539 		if (!diag_tlb_flush)
540 			iommu_tlb_flush(softsp, ioaddr, 1);
541 
542 		/* Set the hardware IO TTE */
543 		*iotte_ptr = ((uint64_t)pfn << IOMMU_PAGESHIFT) | iotte_flag;
544 
545 		ioaddr += IOMMU_PAGESIZE;
546 		npages--;
547 		iotte_ptr++;
548 #if defined(DEBUG) && defined(IO_MEMUSAGE)
549 		*pfnp = pfn;
550 		pfnp++;
551 #endif /* DEBUG && IO_MEMUSAGE */
552 	} while (npages != 0);
553 
554 #if defined(DEBUG) && defined(IO_MEMUSAGE)
555 	mutex_enter(&softsp->iomemlock);
556 	iomemp->next = softsp->iomem;
557 	softsp->iomem = iomemp;
558 	mutex_exit(&softsp->iomemlock);
559 #endif /* DEBUG && IO_MEMUSAGE */
560 
561 	return (rval);
562 
563 #if defined(DEBUG) && defined(IO_MEMDEBUG)
564 bad:
565 	/* If we fail a mapping, free up any mapping resources used */
566 	iommu_remove_mappings(mp);
567 	return (rval);
568 #endif /* DEBUG && IO_MEMDEBUG */
569 }
570 
571 
572 int
573 iommu_create_pp_mappings(ddi_dma_impl_t *mp, page_t *pp, page_t **pplist)
574 {
575 	pfn_t pfn;
576 	pgcnt_t npages;
577 	ioaddr_t ioaddr;
578 	uint_t offset;
579 	volatile uint64_t *iotte_ptr;
580 	uint64_t tmp_iotte_flag;
581 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
582 	struct sbus_soft_state *softsp = mppriv->softsp;
583 	int diag_tlb_flush;
584 #if defined(DEBUG) && defined(IO_MEMUSAGE)
585 	struct io_mem_list *iomemp;
586 	pfn_t *pfnp;
587 #endif /* DEBUG && IO_MEMUSAGE */
588 	int rval = DDI_DMA_MAPPED;
589 
590 	/* Set Valid and Cache for mem xfer */
591 	tmp_iotte_flag = IOTTE_VALID | IOTTE_CACHE | IOTTE_WRITE | IOTTE_STREAM;
592 
593 	ASSERT(softsp != NULL);
594 
595 	offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
596 	npages = iommu_btopr(mp->dmai_size + offset);
597 	ioaddr = (ioaddr_t)(mp->dmai_mapping & ~IOMMU_PAGEOFFSET);
598 	iotte_ptr = IOTTE_NDX(ioaddr, softsp->soft_tsb_base_addr);
599 	diag_tlb_flush = npages > tlb_flush_using_diag ? 1 : 0;
600 
601 	/*
602 	 * Set the per object bits of the TTE here. We optimize this for
603 	 * the memory case so that the while loop overhead is minimal.
604 	 */
605 	if (mp->dmai_rflags & DDI_DMA_CONSISTENT) {
606 		/* Turn on NOSYNC if we need consistent mem */
607 		mp->dmai_rflags |= DMP_NOSYNC;
608 		tmp_iotte_flag ^= IOTTE_STREAM;
609 	} else if (softsp->stream_buf_off) {
610 		/* Set streaming mode if not consistent mem */
611 		tmp_iotte_flag ^= IOTTE_STREAM;
612 	}
613 
614 #if defined(DEBUG) && defined(IO_MEMUSAGE)
615 	iomemp = kmem_alloc(sizeof (struct io_mem_list), KM_SLEEP);
616 	iomemp->rdip = mp->dmai_rdip;
617 	iomemp->ioaddr = ioaddr;
618 	iomemp->npages = npages;
619 	pfnp = iomemp->pfn = kmem_zalloc(sizeof (*pfnp) * (npages + 1),
620 	    KM_SLEEP);
621 #endif /* DEBUG && IO_MEMUSAGE */
622 	/*
623 	 * Grab the mappings from the dmmu and stick 'em into the
624 	 * iommu.
625 	 */
626 	ASSERT(npages != 0);
627 
628 	/* If we're going to flush the TLB using diag mode, do it now. */
629 	if (diag_tlb_flush)
630 		iommu_tlb_flush(softsp, ioaddr, npages);
631 
632 	do {
633 		uint64_t iotte_flag;
634 
635 		iotte_flag = tmp_iotte_flag;
636 
637 		if (pp != NULL) {
638 			pfn = pp->p_pagenum;
639 			pp = pp->p_next;
640 		} else {
641 			pfn = (*pplist)->p_pagenum;
642 			pplist++;
643 		}
644 
645 		DPRINTF(IOMMU_TTE, ("pp mapping TTE index %p pfn %lx "
646 		    "tte flag %lx ioaddr %x\n", iotte_ptr,
647 		    pfn, iotte_flag, ioaddr));
648 
649 		/* Flush the IOMMU TLB before loading a new mapping */
650 		if (!diag_tlb_flush)
651 			iommu_tlb_flush(softsp, ioaddr, 1);
652 
653 		/* Set the hardware IO TTE */
654 		*iotte_ptr = ((uint64_t)pfn << IOMMU_PAGESHIFT) | iotte_flag;
655 
656 		ioaddr += IOMMU_PAGESIZE;
657 		npages--;
658 		iotte_ptr++;
659 
660 #if defined(DEBUG) && defined(IO_MEMUSAGE)
661 		*pfnp = pfn;
662 		pfnp++;
663 #endif /* DEBUG && IO_MEMUSAGE */
664 
665 	} while (npages != 0);
666 
667 #if defined(DEBUG) && defined(IO_MEMUSAGE)
668 	mutex_enter(&softsp->iomemlock);
669 	iomemp->next = softsp->iomem;
670 	softsp->iomem = iomemp;
671 	mutex_exit(&softsp->iomemlock);
672 #endif /* DEBUG && IO_MEMUSAGE */
673 
674 	return (rval);
675 }
676 
677 
678 int
679 iommu_dma_lim_setup(dev_info_t *dip, dev_info_t *rdip,
680     struct sbus_soft_state *softsp, uint_t *burstsizep, uint_t burstsize64,
681     uint_t *minxferp, uint_t dma_flags)
682 {
683 	struct regspec *rp;
684 
685 	/* Take care of 64 bit limits. */
686 	if (!(dma_flags & DDI_DMA_SBUS_64BIT)) {
687 		/*
688 		 * return burst size for 32-bit mode
689 		 */
690 		*burstsizep &= softsp->sbus_burst_sizes;
691 		return (DDI_FAILURE);
692 	}
693 
694 	/*
695 	 * check if SBus supports 64 bit and if caller
696 	 * is child of SBus. No support through bridges
697 	 */
698 	if (!softsp->sbus64_burst_sizes || (ddi_get_parent(rdip) != dip)) {
699 		/*
700 		 * SBus doesn't support it or bridge. Do 32-bit
701 		 * xfers
702 		 */
703 		*burstsizep &= softsp->sbus_burst_sizes;
704 		return (DDI_FAILURE);
705 	}
706 
707 	rp = ddi_rnumber_to_regspec(rdip, 0);
708 	if (rp == NULL) {
709 		*burstsizep &= softsp->sbus_burst_sizes;
710 		return (DDI_FAILURE);
711 	}
712 
713 	/* Check for old-style 64 bit burstsizes */
714 	if (burstsize64 & SYSIO64_BURST_MASK) {
715 		/* Scale back burstsizes if Necessary */
716 		*burstsizep &= (softsp->sbus64_burst_sizes |
717 		    softsp->sbus_burst_sizes);
718 	} else {
719 		/* Get the 64 bit burstsizes. */
720 		*burstsizep = burstsize64;
721 
722 		/* Scale back burstsizes if Necessary */
723 		*burstsizep &= (softsp->sbus64_burst_sizes >>
724 		    SYSIO64_BURST_SHIFT);
725 	}
726 
727 	/*
728 	 * Set the largest value of the smallest burstsize that the
729 	 * device or the bus can manage.
730 	 */
731 	*minxferp = MAX(*minxferp,
732 	    (1 << (ddi_ffs(softsp->sbus64_burst_sizes) - 1)));
733 
734 	return (DDI_SUCCESS);
735 }
736 
737 
738 int
739 iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
740     ddi_dma_attr_t *dma_attr, int (*waitfp)(caddr_t), caddr_t arg,
741     ddi_dma_handle_t *handlep)
742 {
743 	ioaddr_t addrlow, addrhigh, segalign;
744 	ddi_dma_impl_t *mp;
745 	struct dma_impl_priv *mppriv;
746 	struct sbus_soft_state *softsp = (struct sbus_soft_state *)
747 	    ddi_get_soft_state(sbusp, ddi_get_instance(dip));
748 
749 	/*
750 	 * Setup dma burstsizes and min-xfer counts.
751 	 */
752 	(void) iommu_dma_lim_setup(dip, rdip, softsp,
753 	    &dma_attr->dma_attr_burstsizes,
754 	    dma_attr->dma_attr_burstsizes, &dma_attr->dma_attr_minxfer,
755 	    dma_attr->dma_attr_flags);
756 
757 	if (dma_attr->dma_attr_burstsizes == 0)
758 		return (DDI_DMA_BADATTR);
759 
760 	addrlow = (ioaddr_t)dma_attr->dma_attr_addr_lo;
761 	addrhigh = (ioaddr_t)dma_attr->dma_attr_addr_hi;
762 	segalign = (ioaddr_t)dma_attr->dma_attr_seg;
763 
764 	/*
765 	 * Check sanity for hi and lo address limits
766 	 */
767 	if ((addrhigh <= addrlow) ||
768 	    (addrhigh < (ioaddr_t)softsp->iommu_dvma_base)) {
769 		return (DDI_DMA_BADATTR);
770 	}
771 	if (dma_attr->dma_attr_flags & DDI_DMA_FORCE_PHYSICAL)
772 		return (DDI_DMA_BADATTR);
773 
774 	mppriv = kmem_zalloc(sizeof (*mppriv),
775 	    (waitfp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
776 
777 	if (mppriv == NULL) {
778 		if (waitfp != DDI_DMA_DONTWAIT) {
779 		    ddi_set_callback(waitfp, arg, &softsp->dvma_call_list_id);
780 		}
781 		return (DDI_DMA_NORESOURCES);
782 	}
783 	mp = (ddi_dma_impl_t *)mppriv;
784 
785 	DPRINTF(IOMMU_DMA_ALLOCHDL_DEBUG, ("dma_allochdl: (%s) handle %p "
786 	    "hi %x lo %x min %x burst %x\n",
787 	    ddi_get_name(dip), mp, addrhigh, addrlow,
788 	    dma_attr->dma_attr_minxfer, dma_attr->dma_attr_burstsizes));
789 
790 	mp->dmai_rdip = rdip;
791 	mp->dmai_minxfer = (uint_t)dma_attr->dma_attr_minxfer;
792 	mp->dmai_burstsizes = (uint_t)dma_attr->dma_attr_burstsizes;
793 	mp->dmai_attr = *dma_attr;
794 	/* See if the DMA engine has any limit restrictions. */
795 	if (segalign == (ioaddr_t)UINT32_MAX &&
796 	    addrhigh == (ioaddr_t)UINT32_MAX &&
797 	    (dma_attr->dma_attr_align <= IOMMU_PAGESIZE) && addrlow == 0) {
798 		mp->dmai_rflags |= DMP_NOLIMIT;
799 	}
800 	mppriv->softsp = softsp;
801 	mppriv->phys_sync_flag = va_to_pa((caddr_t)&mppriv->sync_flag);
802 
803 	*handlep = (ddi_dma_handle_t)mp;
804 	return (DDI_SUCCESS);
805 }
806 
807 /*ARGSUSED*/
808 int
809 iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
810 {
811 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)handle;
812 	struct sbus_soft_state *softsp = mppriv->softsp;
813 	ASSERT(softsp != NULL);
814 
815 	kmem_free(mppriv, sizeof (*mppriv));
816 
817 	if (softsp->dvma_call_list_id != 0) {
818 		ddi_run_callback(&softsp->dvma_call_list_id);
819 	}
820 	return (DDI_SUCCESS);
821 }
822 
823 static int
824 check_dma_attr(struct ddi_dma_req *dmareq, ddi_dma_attr_t *dma_attr,
825     uint32_t *size)
826 {
827 	ioaddr_t addrlow;
828 	ioaddr_t addrhigh;
829 	uint32_t segalign;
830 	uint32_t smask;
831 
832 	smask = *size - 1;
833 	segalign = dma_attr->dma_attr_seg;
834 	if (smask > segalign) {
835 		if ((dmareq->dmar_flags & DDI_DMA_PARTIAL) == 0)
836 			return (DDI_DMA_TOOBIG);
837 		*size = segalign + 1;
838 	}
839 	addrlow = (ioaddr_t)dma_attr->dma_attr_addr_lo;
840 	addrhigh = (ioaddr_t)dma_attr->dma_attr_addr_hi;
841 	if (addrlow + smask > addrhigh || addrlow + smask < addrlow) {
842 		if (!((addrlow + dmareq->dmar_object.dmao_size == 0) &&
843 		    (addrhigh == (ioaddr_t)-1))) {
844 			if ((dmareq->dmar_flags & DDI_DMA_PARTIAL) == 0)
845 				return (DDI_DMA_TOOBIG);
846 			*size = MIN(addrhigh - addrlow + 1, *size);
847 		}
848 	}
849 	return (DDI_DMA_MAPOK);
850 }
851 
852 int
853 iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
854     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
855     ddi_dma_cookie_t *cp, uint_t *ccountp)
856 {
857 	page_t *pp;
858 	uint32_t size;
859 	ioaddr_t ioaddr;
860 	uint_t offset;
861 	uintptr_t addr = 0;
862 	pgcnt_t npages;
863 	int rval;
864 	ddi_dma_attr_t *dma_attr;
865 	struct sbus_soft_state *softsp;
866 	struct page **pplist = NULL;
867 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
868 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
869 
870 #ifdef lint
871 	dip = dip;
872 	rdip = rdip;
873 #endif
874 
875 	if (mp->dmai_inuse)
876 		return (DDI_DMA_INUSE);
877 
878 	dma_attr = &mp->dmai_attr;
879 	size = (uint32_t)dmareq->dmar_object.dmao_size;
880 	if (!(mp->dmai_rflags & DMP_NOLIMIT)) {
881 		rval = check_dma_attr(dmareq, dma_attr, &size);
882 		if (rval != DDI_DMA_MAPOK)
883 			return (rval);
884 	}
885 	mp->dmai_inuse = 1;
886 	mp->dmai_offset = 0;
887 	mp->dmai_rflags = (dmareq->dmar_flags & DMP_DDIFLAGS) |
888 	    (mp->dmai_rflags & DMP_NOLIMIT);
889 
890 	switch (dmareq->dmar_object.dmao_type) {
891 	case DMA_OTYP_VADDR:
892 	case DMA_OTYP_BUFVADDR:
893 		addr = (uintptr_t)dmareq->dmar_object.dmao_obj.virt_obj.v_addr;
894 		offset = addr & IOMMU_PAGEOFFSET;
895 		pplist = dmareq->dmar_object.dmao_obj.virt_obj.v_priv;
896 		npages = iommu_btopr(OBJSIZE + offset);
897 
898 		DPRINTF(IOMMU_DMAMAP_DEBUG, ("dma_map vaddr: %lx pages "
899 		    "req addr %lx off %x OBJSIZE %x\n",
900 		    npages, addr, offset, OBJSIZE));
901 
902 		/* We don't need the addr anymore if we have a shadow list */
903 		if (pplist != NULL)
904 			addr = NULL;
905 		pp = NULL;
906 		break;
907 
908 	case DMA_OTYP_PAGES:
909 		pp = dmareq->dmar_object.dmao_obj.pp_obj.pp_pp;
910 		offset = dmareq->dmar_object.dmao_obj.pp_obj.pp_offset;
911 		npages = iommu_btopr(OBJSIZE + offset);
912 		break;
913 
914 	case DMA_OTYP_PADDR:
915 	default:
916 		/*
917 		 * Not a supported type for this implementation
918 		 */
919 		rval = DDI_DMA_NOMAPPING;
920 		goto bad;
921 	}
922 
923 	/* Get our soft state once we know we're mapping an object. */
924 	softsp = mppriv->softsp;
925 	ASSERT(softsp != NULL);
926 
927 	if (mp->dmai_rflags & DDI_DMA_PARTIAL) {
928 		if (size != OBJSIZE) {
929 			/*
930 			 * If the request is for partial mapping arrangement,
931 			 * the device has to be able to address at least the
932 			 * size of the window we are establishing.
933 			 */
934 			if (size < iommu_ptob(MIN_DVMA_WIN_SIZE)) {
935 				rval = DDI_DMA_NOMAPPING;
936 				goto bad;
937 			}
938 			npages = iommu_btopr(size + offset);
939 		}
940 		/*
941 		 * If the size requested is less than a moderate amt,
942 		 * skip the partial mapping stuff- it's not worth the
943 		 * effort.
944 		 */
945 		if (npages > MIN_DVMA_WIN_SIZE) {
946 			npages = MIN_DVMA_WIN_SIZE + iommu_btopr(offset);
947 			size = iommu_ptob(MIN_DVMA_WIN_SIZE);
948 			DPRINTF(IOMMU_DMA_SETUP_DEBUG, ("dma_setup: SZ %x pg "
949 			    "%lx sz %x\n", OBJSIZE, npages, size));
950 			if (pplist != NULL) {
951 				mp->dmai_minfo = (void *)pplist;
952 				mp->dmai_rflags |= DMP_SHADOW;
953 			}
954 		} else {
955 			mp->dmai_rflags ^= DDI_DMA_PARTIAL;
956 		}
957 	} else {
958 		if (npages >= iommu_btop(softsp->iommu_dvma_size) -
959 		    MIN_DVMA_WIN_SIZE) {
960 			rval = DDI_DMA_TOOBIG;
961 			goto bad;
962 		}
963 	}
964 
965 	/*
966 	 * save dmareq-object, size and npages into mp
967 	 */
968 	mp->dmai_object = dmareq->dmar_object;
969 	mp->dmai_size = size;
970 	mp->dmai_ndvmapages = npages;
971 
972 	if (mp->dmai_rflags & DMP_NOLIMIT) {
973 		ioaddr = (ioaddr_t)(uintptr_t)vmem_alloc(softsp->dvma_arena,
974 		    iommu_ptob(npages),
975 		    dmareq->dmar_fp == DDI_DMA_SLEEP ? VM_SLEEP : VM_NOSLEEP);
976 		if (ioaddr == 0) {
977 			rval = DDI_DMA_NORESOURCES;
978 			goto bad;
979 		}
980 
981 		/*
982 		 * If we have a 1 page request and we're working with a page
983 		 * list, we're going to speed load an IOMMU entry.
984 		 */
985 		if (npages == 1 && !addr) {
986 			uint64_t iotte_flag = IOTTE_VALID | IOTTE_CACHE |
987 			    IOTTE_WRITE | IOTTE_STREAM;
988 			volatile uint64_t *iotte_ptr;
989 			pfn_t pfn;
990 #if defined(DEBUG) && defined(IO_MEMUSAGE)
991 			struct io_mem_list *iomemp;
992 			pfn_t *pfnp;
993 #endif /* DEBUG && IO_MEMUSAGE */
994 
995 			iotte_ptr = IOTTE_NDX(ioaddr,
996 			    softsp->soft_tsb_base_addr);
997 
998 			if (mp->dmai_rflags & DDI_DMA_CONSISTENT) {
999 				mp->dmai_rflags |= DMP_NOSYNC;
1000 				iotte_flag ^= IOTTE_STREAM;
1001 			} else if (softsp->stream_buf_off)
1002 				iotte_flag ^= IOTTE_STREAM;
1003 
1004 			mp->dmai_rflags ^= DDI_DMA_PARTIAL;
1005 
1006 			if (pp != NULL)
1007 				pfn = pp->p_pagenum;
1008 			else
1009 				pfn = (*pplist)->p_pagenum;
1010 
1011 			iommu_tlb_flush(softsp, ioaddr, 1);
1012 
1013 			*iotte_ptr =
1014 			    ((uint64_t)pfn << IOMMU_PAGESHIFT) | iotte_flag;
1015 
1016 			mp->dmai_mapping = (ioaddr_t)(ioaddr + offset);
1017 			mp->dmai_nwin = 0;
1018 			if (cp != NULL) {
1019 				cp->dmac_notused = 0;
1020 				cp->dmac_address = (ioaddr_t)mp->dmai_mapping;
1021 				cp->dmac_size = mp->dmai_size;
1022 				cp->dmac_type = 0;
1023 				*ccountp = 1;
1024 			}
1025 
1026 			DPRINTF(IOMMU_TTE, ("speed loading: TTE index %p "
1027 			    "pfn %lx tte flag %lx addr %lx ioaddr %x\n",
1028 			    iotte_ptr, pfn, iotte_flag, addr, ioaddr));
1029 
1030 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1031 			iomemp = kmem_alloc(sizeof (struct io_mem_list),
1032 			    KM_SLEEP);
1033 			iomemp->rdip = mp->dmai_rdip;
1034 			iomemp->ioaddr = ioaddr;
1035 			iomemp->addr = addr;
1036 			iomemp->npages = npages;
1037 			pfnp = iomemp->pfn = kmem_zalloc(sizeof (*pfnp) *
1038 			    (npages + 1), KM_SLEEP);
1039 			*pfnp = pfn;
1040 			mutex_enter(&softsp->iomemlock);
1041 			iomemp->next = softsp->iomem;
1042 			softsp->iomem = iomemp;
1043 			mutex_exit(&softsp->iomemlock);
1044 #endif /* DEBUG && IO_MEMUSAGE */
1045 
1046 			return (DDI_DMA_MAPPED);
1047 		}
1048 	} else {
1049 		ioaddr = (ioaddr_t)(uintptr_t)vmem_xalloc(softsp->dvma_arena,
1050 		    iommu_ptob(npages),
1051 		    MAX((uint_t)dma_attr->dma_attr_align, IOMMU_PAGESIZE), 0,
1052 		    (uint_t)dma_attr->dma_attr_seg + 1,
1053 		    (void *)(uintptr_t)(ioaddr_t)dma_attr->dma_attr_addr_lo,
1054 		    (void *)(uintptr_t)
1055 			((ioaddr_t)dma_attr->dma_attr_addr_hi + 1),
1056 		    dmareq->dmar_fp == DDI_DMA_SLEEP ? VM_SLEEP : VM_NOSLEEP);
1057 	}
1058 
1059 	if (ioaddr == 0) {
1060 		if (dmareq->dmar_fp == DDI_DMA_SLEEP)
1061 			rval = DDI_DMA_NOMAPPING;
1062 		else
1063 			rval = DDI_DMA_NORESOURCES;
1064 		goto bad;
1065 	}
1066 
1067 	mp->dmai_mapping = ioaddr + offset;
1068 	ASSERT(mp->dmai_mapping >= softsp->iommu_dvma_base);
1069 
1070 	/*
1071 	 * At this point we have a range of virtual address allocated
1072 	 * with which we now have to map to the requested object.
1073 	 */
1074 	if (addr) {
1075 		rval = iommu_create_vaddr_mappings(mp,
1076 		    addr & ~IOMMU_PAGEOFFSET);
1077 		if (rval == DDI_DMA_NOMAPPING)
1078 			goto bad_nomap;
1079 	} else {
1080 		rval = iommu_create_pp_mappings(mp, pp, pplist);
1081 		if (rval == DDI_DMA_NOMAPPING)
1082 			goto bad_nomap;
1083 	}
1084 
1085 	if (cp) {
1086 		cp->dmac_notused = 0;
1087 		cp->dmac_address = (ioaddr_t)mp->dmai_mapping;
1088 		cp->dmac_size = mp->dmai_size;
1089 		cp->dmac_type = 0;
1090 		*ccountp = 1;
1091 	}
1092 	if (mp->dmai_rflags & DDI_DMA_PARTIAL) {
1093 		size = iommu_ptob(mp->dmai_ndvmapages - iommu_btopr(offset));
1094 		mp->dmai_nwin =
1095 		    (dmareq->dmar_object.dmao_size + (size - 1)) / size;
1096 		return (DDI_DMA_PARTIAL_MAP);
1097 	} else {
1098 		mp->dmai_nwin = 0;
1099 		return (DDI_DMA_MAPPED);
1100 	}
1101 
1102 bad_nomap:
1103 	/*
1104 	 * Could not create mmu mappings.
1105 	 */
1106 	if (mp->dmai_rflags & DMP_NOLIMIT) {
1107 		vmem_free(softsp->dvma_arena, (void *)(uintptr_t)ioaddr,
1108 		    iommu_ptob(npages));
1109 	} else {
1110 		vmem_xfree(softsp->dvma_arena, (void *)(uintptr_t)ioaddr,
1111 		    iommu_ptob(npages));
1112 	}
1113 
1114 bad:
1115 	if (rval == DDI_DMA_NORESOURCES &&
1116 	    dmareq->dmar_fp != DDI_DMA_DONTWAIT) {
1117 		ddi_set_callback(dmareq->dmar_fp,
1118 		    dmareq->dmar_arg, &softsp->dvma_call_list_id);
1119 	}
1120 	mp->dmai_inuse = 0;
1121 	return (rval);
1122 }
1123 
1124 /* ARGSUSED */
1125 int
1126 iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
1127     ddi_dma_handle_t handle)
1128 {
1129 	ioaddr_t addr;
1130 	uint_t npages;
1131 	size_t size;
1132 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1133 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
1134 	struct sbus_soft_state *softsp = mppriv->softsp;
1135 	ASSERT(softsp != NULL);
1136 
1137 	addr = (ioaddr_t)(mp->dmai_mapping & ~IOMMU_PAGEOFFSET);
1138 	npages = mp->dmai_ndvmapages;
1139 	size = iommu_ptob(npages);
1140 
1141 	DPRINTF(IOMMU_DMA_UNBINDHDL_DEBUG, ("iommu_dma_unbindhdl: "
1142 	    "unbinding addr %x for %x pages\n", addr, mp->dmai_ndvmapages));
1143 
1144 	/* sync the entire object */
1145 	if (!(mp->dmai_rflags & DDI_DMA_CONSISTENT)) {
1146 		/* flush stream write buffers */
1147 		sync_stream_buf(softsp, addr, npages, (int *)&mppriv->sync_flag,
1148 		    mppriv->phys_sync_flag);
1149 	}
1150 
1151 #if defined(DEBUG) && defined(IO_MEMDEBUG)
1152 	/*
1153 	 * 'Free' the dma mappings.
1154 	 */
1155 	iommu_remove_mappings(mp);
1156 #endif /* DEBUG && IO_MEMDEBUG */
1157 
1158 	ASSERT(npages > (uint_t)0);
1159 	if (mp->dmai_rflags & DMP_NOLIMIT)
1160 		vmem_free(softsp->dvma_arena, (void *)(uintptr_t)addr, size);
1161 	else
1162 		vmem_xfree(softsp->dvma_arena, (void *)(uintptr_t)addr, size);
1163 
1164 	mp->dmai_ndvmapages = 0;
1165 	mp->dmai_inuse = 0;
1166 	mp->dmai_minfo = NULL;
1167 
1168 	if (softsp->dvma_call_list_id != 0)
1169 		ddi_run_callback(&softsp->dvma_call_list_id);
1170 
1171 	return (DDI_SUCCESS);
1172 }
1173 
1174 /*ARGSUSED*/
1175 int
1176 iommu_dma_flush(dev_info_t *dip, dev_info_t *rdip,
1177     ddi_dma_handle_t handle, off_t off, size_t len,
1178     uint_t cache_flags)
1179 {
1180 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1181 	struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
1182 
1183 	if (!(mp->dmai_rflags & DDI_DMA_CONSISTENT)) {
1184 		sync_stream_buf(mppriv->softsp, mp->dmai_mapping,
1185 		    mp->dmai_ndvmapages, (int *)&mppriv->sync_flag,
1186 		    mppriv->phys_sync_flag);
1187 	}
1188 	return (DDI_SUCCESS);
1189 }
1190 
1191 /*ARGSUSED*/
1192 int
1193 iommu_dma_win(dev_info_t *dip, dev_info_t *rdip,
1194     ddi_dma_handle_t handle, uint_t win, off_t *offp,
1195     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
1196 {
1197 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1198 	off_t offset;
1199 	uint_t winsize;
1200 	uint_t newoff;
1201 	int rval;
1202 
1203 	offset = mp->dmai_mapping & IOMMU_PAGEOFFSET;
1204 	winsize = iommu_ptob(mp->dmai_ndvmapages - iommu_btopr(offset));
1205 
1206 	DPRINTF(IOMMU_DMA_WIN_DEBUG, ("getwin win %d winsize %x\n", win,
1207 	    winsize));
1208 
1209 	/*
1210 	 * win is in the range [0 .. dmai_nwin-1]
1211 	 */
1212 	if (win >= mp->dmai_nwin)
1213 		return (DDI_FAILURE);
1214 
1215 	newoff = win * winsize;
1216 	if (newoff > mp->dmai_object.dmao_size - mp->dmai_minxfer)
1217 		return (DDI_FAILURE);
1218 
1219 	ASSERT(cookiep);
1220 	cookiep->dmac_notused = 0;
1221 	cookiep->dmac_type = 0;
1222 	cookiep->dmac_address = (ioaddr_t)mp->dmai_mapping;
1223 	cookiep->dmac_size = mp->dmai_size;
1224 	*ccountp = 1;
1225 	*offp = (off_t)newoff;
1226 	*lenp = (uint_t)winsize;
1227 
1228 	if (newoff == mp->dmai_offset) {
1229 		/*
1230 		 * Nothing to do...
1231 		 */
1232 		return (DDI_SUCCESS);
1233 	}
1234 
1235 	if ((rval = iommu_map_window(mp, newoff, winsize)) != DDI_SUCCESS)
1236 		return (rval);
1237 
1238 	/*
1239 	 * Set this again in case iommu_map_window() has changed it
1240 	 */
1241 	cookiep->dmac_size = mp->dmai_size;
1242 
1243 	return (DDI_SUCCESS);
1244 }
1245 
1246 static int
1247 iommu_map_window(ddi_dma_impl_t *mp, off_t newoff, size_t winsize)
1248 {
1249 	uintptr_t addr = 0;
1250 	page_t *pp;
1251 	uint_t flags;
1252 	struct page **pplist = NULL;
1253 
1254 #if defined(DEBUG) && defined(IO_MEMDEBUG)
1255 	/* Free mappings for current window */
1256 	iommu_remove_mappings(mp);
1257 #endif /* DEBUG && IO_MEMDEBUG */
1258 
1259 	mp->dmai_offset = newoff;
1260 	mp->dmai_size = mp->dmai_object.dmao_size - newoff;
1261 	mp->dmai_size = MIN(mp->dmai_size, winsize);
1262 
1263 	if (mp->dmai_object.dmao_type == DMA_OTYP_VADDR ||
1264 	    mp->dmai_object.dmao_type == DMA_OTYP_BUFVADDR) {
1265 		if (mp->dmai_rflags & DMP_SHADOW) {
1266 			pplist = (struct page **)mp->dmai_minfo;
1267 			ASSERT(pplist != NULL);
1268 			pplist = pplist + (newoff >> MMU_PAGESHIFT);
1269 		} else {
1270 			addr = (uintptr_t)
1271 			    mp->dmai_object.dmao_obj.virt_obj.v_addr;
1272 			addr = (addr + newoff) & ~IOMMU_PAGEOFFSET;
1273 		}
1274 		pp = NULL;
1275 	} else {
1276 		pp = mp->dmai_object.dmao_obj.pp_obj.pp_pp;
1277 		flags = 0;
1278 		while (flags < newoff) {
1279 			pp = pp->p_next;
1280 			flags += MMU_PAGESIZE;
1281 		}
1282 	}
1283 
1284 	/* Set up mappings for next window */
1285 	if (addr) {
1286 		if (iommu_create_vaddr_mappings(mp, addr) < 0)
1287 			return (DDI_FAILURE);
1288 	} else {
1289 		if (iommu_create_pp_mappings(mp, pp, pplist) < 0)
1290 			return (DDI_FAILURE);
1291 	}
1292 
1293 	/*
1294 	 * also invalidate read stream buffer
1295 	 */
1296 	if (!(mp->dmai_rflags & DDI_DMA_CONSISTENT)) {
1297 		struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
1298 
1299 		sync_stream_buf(mppriv->softsp, mp->dmai_mapping,
1300 		    mp->dmai_ndvmapages, (int *)&mppriv->sync_flag,
1301 		    mppriv->phys_sync_flag);
1302 	}
1303 
1304 	return (DDI_SUCCESS);
1305 
1306 }
1307 
1308 int
1309 iommu_dma_map(dev_info_t *dip, dev_info_t *rdip,
1310     struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep)
1311 {
1312 	ddi_dma_lim_t *dma_lim = dmareq->dmar_limits;
1313 	ddi_dma_impl_t *mp;
1314 	ddi_dma_attr_t *dma_attr;
1315 	struct dma_impl_priv *mppriv;
1316 	ioaddr_t addrlow, addrhigh;
1317 	ioaddr_t segalign;
1318 	int rval;
1319 	struct sbus_soft_state *softsp =
1320 		(struct sbus_soft_state *)ddi_get_soft_state(sbusp,
1321 		ddi_get_instance(dip));
1322 
1323 	addrlow = dma_lim->dlim_addr_lo;
1324 	addrhigh = dma_lim->dlim_addr_hi;
1325 	if ((addrhigh <= addrlow) ||
1326 	    (addrhigh < (ioaddr_t)softsp->iommu_dvma_base)) {
1327 		return (DDI_DMA_NOMAPPING);
1328 	}
1329 
1330 	/*
1331 	 * Setup DMA burstsizes and min-xfer counts.
1332 	 */
1333 	(void) iommu_dma_lim_setup(dip, rdip, softsp, &dma_lim->dlim_burstsizes,
1334 		(uint_t)dma_lim->dlim_burstsizes, &dma_lim->dlim_minxfer,
1335 		dmareq->dmar_flags);
1336 
1337 	if (dma_lim->dlim_burstsizes == 0)
1338 		return (DDI_DMA_NOMAPPING);
1339 	/*
1340 	 * If not an advisory call, get a DMA handle
1341 	 */
1342 	if (!handlep) {
1343 		return (DDI_DMA_MAPOK);
1344 	}
1345 
1346 	mppriv = kmem_zalloc(sizeof (*mppriv),
1347 	    (dmareq->dmar_fp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
1348 	if (mppriv == NULL) {
1349 		if (dmareq->dmar_fp != DDI_DMA_DONTWAIT) {
1350 			ddi_set_callback(dmareq->dmar_fp,
1351 			    dmareq->dmar_arg, &softsp->dvma_call_list_id);
1352 		}
1353 		return (DDI_DMA_NORESOURCES);
1354 	}
1355 	mp = (ddi_dma_impl_t *)mppriv;
1356 	mp->dmai_rdip = rdip;
1357 	mp->dmai_rflags = dmareq->dmar_flags & DMP_DDIFLAGS;
1358 	mp->dmai_minxfer = dma_lim->dlim_minxfer;
1359 	mp->dmai_burstsizes = dma_lim->dlim_burstsizes;
1360 	mp->dmai_offset = 0;
1361 	mp->dmai_ndvmapages = 0;
1362 	mp->dmai_minfo = 0;
1363 	mp->dmai_inuse = 0;
1364 	segalign = dma_lim->dlim_cntr_max;
1365 	/* See if the DMA engine has any limit restrictions. */
1366 	if (segalign == UINT32_MAX && addrhigh == UINT32_MAX &&
1367 	    addrlow == 0) {
1368 		mp->dmai_rflags |= DMP_NOLIMIT;
1369 	}
1370 	mppriv->softsp = softsp;
1371 	mppriv->phys_sync_flag = va_to_pa((caddr_t)&mppriv->sync_flag);
1372 	dma_attr = &mp->dmai_attr;
1373 	dma_attr->dma_attr_align = 1;
1374 	dma_attr->dma_attr_addr_lo = addrlow;
1375 	dma_attr->dma_attr_addr_hi = addrhigh;
1376 	dma_attr->dma_attr_seg = segalign;
1377 	dma_attr->dma_attr_burstsizes = dma_lim->dlim_burstsizes;
1378 	rval = iommu_dma_bindhdl(dip, rdip, (ddi_dma_handle_t)mp,
1379 		dmareq, NULL, NULL);
1380 	if (rval && (rval != DDI_DMA_PARTIAL_MAP)) {
1381 		kmem_free(mppriv, sizeof (*mppriv));
1382 	} else {
1383 		*handlep = (ddi_dma_handle_t)mp;
1384 	}
1385 	return (rval);
1386 }
1387 
1388 /*ARGSUSED*/
1389 int
1390 iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
1391     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
1392     off_t *offp, size_t *lenp, caddr_t *objp, uint_t cache_flags)
1393 {
1394 	ioaddr_t addr;
1395 	uint_t offset;
1396 	pgcnt_t npages;
1397 	size_t size;
1398 	ddi_dma_cookie_t *cp;
1399 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1400 
1401 	DPRINTF(IOMMU_DMAMCTL_DEBUG, ("dma_mctl: handle %p ", mp));
1402 	switch (request) {
1403 	case DDI_DMA_FREE:
1404 	{
1405 		struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
1406 		struct sbus_soft_state *softsp = mppriv->softsp;
1407 		ASSERT(softsp != NULL);
1408 
1409 		/*
1410 		 * 'Free' the dma mappings.
1411 		 */
1412 		addr = (ioaddr_t)(mp->dmai_mapping & ~IOMMU_PAGEOFFSET);
1413 		npages = mp->dmai_ndvmapages;
1414 		size = iommu_ptob(npages);
1415 
1416 		DPRINTF(IOMMU_DMAMCTL_DMA_FREE_DEBUG, ("iommu_dma_mctl dmafree:"
1417 		    "freeing vaddr %x for %x pages.\n", addr,
1418 		    mp->dmai_ndvmapages));
1419 		/* sync the entire object */
1420 		if (!(mp->dmai_rflags & DDI_DMA_CONSISTENT)) {
1421 			/* flush stream write buffers */
1422 			sync_stream_buf(softsp, addr, npages,
1423 			    (int *)&mppriv->sync_flag, mppriv->phys_sync_flag);
1424 		}
1425 
1426 #if defined(DEBUG) && defined(IO_MEMDEBUG)
1427 		iommu_remove_mappings(mp);
1428 #endif /* DEBUG && IO_MEMDEBUG */
1429 
1430 		ASSERT(npages > (uint_t)0);
1431 		if (mp->dmai_rflags & DMP_NOLIMIT)
1432 			vmem_free(softsp->dvma_arena,
1433 			    (void *)(uintptr_t)addr, size);
1434 		else
1435 			vmem_xfree(softsp->dvma_arena,
1436 			    (void *)(uintptr_t)addr, size);
1437 
1438 		kmem_free(mppriv, sizeof (*mppriv));
1439 
1440 		if (softsp->dvma_call_list_id != 0)
1441 			ddi_run_callback(&softsp->dvma_call_list_id);
1442 
1443 		break;
1444 	}
1445 
1446 	case DDI_DMA_SET_SBUS64:
1447 	{
1448 		struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
1449 
1450 		return (iommu_dma_lim_setup(dip, rdip, mppriv->softsp,
1451 		    &mp->dmai_burstsizes, (uint_t)*lenp, &mp->dmai_minxfer,
1452 		    DDI_DMA_SBUS_64BIT));
1453 	}
1454 
1455 	case DDI_DMA_HTOC:
1456 		DPRINTF(IOMMU_DMAMCTL_HTOC_DEBUG, ("htoc off %lx mapping %lx "
1457 		    "size %x\n", *offp, mp->dmai_mapping,
1458 		    mp->dmai_size));
1459 
1460 		if ((uint_t)(*offp) >= mp->dmai_size)
1461 			return (DDI_FAILURE);
1462 
1463 		cp = (ddi_dma_cookie_t *)objp;
1464 		cp->dmac_notused = 0;
1465 		cp->dmac_address = (mp->dmai_mapping + (uint_t)(*offp));
1466 		cp->dmac_size =
1467 		    mp->dmai_mapping + mp->dmai_size - cp->dmac_address;
1468 		cp->dmac_type = 0;
1469 
1470 		break;
1471 
1472 	case DDI_DMA_KVADDR:
1473 		/*
1474 		 * If a physical address mapping has percolated this high,
1475 		 * that is an error (maybe?).
1476 		 */
1477 		if (mp->dmai_rflags & DMP_PHYSADDR) {
1478 			DPRINTF(IOMMU_DMAMCTL_KVADDR_DEBUG, ("kvaddr of phys "
1479 			    "mapping\n"));
1480 			return (DDI_FAILURE);
1481 		}
1482 
1483 		return (DDI_FAILURE);
1484 
1485 	case DDI_DMA_NEXTWIN:
1486 	{
1487 		ddi_dma_win_t *owin, *nwin;
1488 		uint_t winsize, newoff;
1489 		int rval;
1490 
1491 		DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG, ("nextwin\n"));
1492 
1493 		mp = (ddi_dma_impl_t *)handle;
1494 		owin = (ddi_dma_win_t *)offp;
1495 		nwin = (ddi_dma_win_t *)objp;
1496 		if (mp->dmai_rflags & DDI_DMA_PARTIAL) {
1497 			if (*owin == NULL) {
1498 				DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG,
1499 				    ("nextwin: win == NULL\n"));
1500 				mp->dmai_offset = 0;
1501 				*nwin = (ddi_dma_win_t)mp;
1502 				return (DDI_SUCCESS);
1503 			}
1504 
1505 			offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
1506 			winsize = iommu_ptob(mp->dmai_ndvmapages -
1507 			    iommu_btopr(offset));
1508 
1509 			newoff = (uint_t)(mp->dmai_offset + winsize);
1510 			if (newoff > mp->dmai_object.dmao_size -
1511 			    mp->dmai_minxfer)
1512 				return (DDI_DMA_DONE);
1513 
1514 			if ((rval = iommu_map_window(mp, newoff, winsize))
1515 			    != DDI_SUCCESS)
1516 				return (rval);
1517 		} else {
1518 			DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG, ("nextwin: no "
1519 			    "partial mapping\n"));
1520 			if (*owin != NULL)
1521 				return (DDI_DMA_DONE);
1522 			mp->dmai_offset = 0;
1523 			*nwin = (ddi_dma_win_t)mp;
1524 		}
1525 		break;
1526 	}
1527 
1528 	case DDI_DMA_NEXTSEG:
1529 	{
1530 		ddi_dma_seg_t *oseg, *nseg;
1531 
1532 		DPRINTF(IOMMU_DMAMCTL_NEXTSEG_DEBUG, ("nextseg:\n"));
1533 
1534 		oseg = (ddi_dma_seg_t *)lenp;
1535 		if (*oseg != NULL)
1536 			return (DDI_DMA_DONE);
1537 		nseg = (ddi_dma_seg_t *)objp;
1538 		*nseg = *((ddi_dma_seg_t *)offp);
1539 		break;
1540 	}
1541 
1542 	case DDI_DMA_SEGTOC:
1543 	{
1544 		ddi_dma_seg_impl_t *seg;
1545 
1546 		seg = (ddi_dma_seg_impl_t *)handle;
1547 		cp = (ddi_dma_cookie_t *)objp;
1548 		cp->dmac_notused = 0;
1549 		cp->dmac_address = (ioaddr_t)seg->dmai_mapping;
1550 		cp->dmac_size = *lenp = seg->dmai_size;
1551 		cp->dmac_type = 0;
1552 		*offp = seg->dmai_offset;
1553 		break;
1554 	}
1555 
1556 	case DDI_DMA_MOVWIN:
1557 	{
1558 		uint_t winsize;
1559 		uint_t newoff;
1560 		int rval;
1561 
1562 		offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
1563 		winsize = iommu_ptob(mp->dmai_ndvmapages - iommu_btopr(offset));
1564 
1565 		DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("movwin off %lx len %lx "
1566 		    "winsize %x\n", *offp, *lenp, winsize));
1567 
1568 		if ((mp->dmai_rflags & DDI_DMA_PARTIAL) == 0)
1569 			return (DDI_FAILURE);
1570 
1571 		if (*lenp != (uint_t)-1 && *lenp != winsize) {
1572 			DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("bad length\n"));
1573 			return (DDI_FAILURE);
1574 		}
1575 		newoff = (uint_t)*offp;
1576 		if (newoff & (winsize - 1)) {
1577 			DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("bad off\n"));
1578 			return (DDI_FAILURE);
1579 		}
1580 
1581 		if (newoff == mp->dmai_offset) {
1582 			/*
1583 			 * Nothing to do...
1584 			 */
1585 			break;
1586 		}
1587 
1588 		/*
1589 		 * Check out new address...
1590 		 */
1591 		if (newoff > mp->dmai_object.dmao_size - mp->dmai_minxfer) {
1592 			DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("newoff out of "
1593 			    "range\n"));
1594 			return (DDI_FAILURE);
1595 		}
1596 
1597 		rval = iommu_map_window(mp, newoff, winsize);
1598 		if (rval != DDI_SUCCESS)
1599 			return (rval);
1600 
1601 		if ((cp = (ddi_dma_cookie_t *)objp) != 0) {
1602 			cp->dmac_notused = 0;
1603 			cp->dmac_address = (ioaddr_t)mp->dmai_mapping;
1604 			cp->dmac_size = mp->dmai_size;
1605 			cp->dmac_type = 0;
1606 		}
1607 		*offp = (off_t)newoff;
1608 		*lenp = (uint_t)winsize;
1609 		break;
1610 	}
1611 
1612 	case DDI_DMA_REPWIN:
1613 		if ((mp->dmai_rflags & DDI_DMA_PARTIAL) == 0) {
1614 			DPRINTF(IOMMU_DMAMCTL_REPWIN_DEBUG, ("repwin fail\n"));
1615 			return (DDI_FAILURE);
1616 		}
1617 
1618 		*offp = (off_t)mp->dmai_offset;
1619 
1620 		addr = mp->dmai_ndvmapages -
1621 		    iommu_btopr(mp->dmai_mapping & IOMMU_PAGEOFFSET);
1622 
1623 		*lenp = (uint_t)iommu_ptob(addr);
1624 
1625 		DPRINTF(IOMMU_DMAMCTL_REPWIN_DEBUG, ("repwin off %lx len %x\n",
1626 		    mp->dmai_offset, mp->dmai_size));
1627 
1628 		break;
1629 
1630 	case DDI_DMA_GETERR:
1631 		DPRINTF(IOMMU_DMAMCTL_GETERR_DEBUG,
1632 		    ("iommu_dma_mctl: geterr\n"));
1633 
1634 		break;
1635 
1636 	case DDI_DMA_COFF:
1637 		cp = (ddi_dma_cookie_t *)offp;
1638 		addr = cp->dmac_address;
1639 
1640 		if (addr < mp->dmai_mapping ||
1641 		    addr >= mp->dmai_mapping + mp->dmai_size)
1642 			return (DDI_FAILURE);
1643 
1644 		*objp = (caddr_t)(addr - mp->dmai_mapping);
1645 
1646 		DPRINTF(IOMMU_DMAMCTL_COFF_DEBUG, ("coff off %lx mapping %lx "
1647 		    "size %x\n", (ulong_t)*objp, mp->dmai_mapping,
1648 		    mp->dmai_size));
1649 
1650 		break;
1651 
1652 	case DDI_DMA_RESERVE:
1653 	{
1654 		struct ddi_dma_req *dmareq = (struct ddi_dma_req *)offp;
1655 		ddi_dma_lim_t *dma_lim;
1656 		ddi_dma_handle_t *handlep;
1657 		uint_t np;
1658 		ioaddr_t ioaddr;
1659 		int i;
1660 		struct fast_dvma *iommu_fast_dvma;
1661 		struct sbus_soft_state *softsp =
1662 		    (struct sbus_soft_state *)ddi_get_soft_state(sbusp,
1663 		    ddi_get_instance(dip));
1664 
1665 		/* Some simple sanity checks */
1666 		dma_lim = dmareq->dmar_limits;
1667 		if (dma_lim->dlim_burstsizes == 0) {
1668 			DPRINTF(IOMMU_FASTDMA_RESERVE,
1669 			    ("Reserve: bad burstsizes\n"));
1670 			return (DDI_DMA_BADLIMITS);
1671 		}
1672 		if ((AHI <= ALO) || (AHI < softsp->iommu_dvma_base)) {
1673 			DPRINTF(IOMMU_FASTDMA_RESERVE,
1674 			    ("Reserve: bad limits\n"));
1675 			return (DDI_DMA_BADLIMITS);
1676 		}
1677 
1678 		np = dmareq->dmar_object.dmao_size;
1679 		mutex_enter(&softsp->dma_pool_lock);
1680 		if (np > softsp->dma_reserve) {
1681 			mutex_exit(&softsp->dma_pool_lock);
1682 			DPRINTF(IOMMU_FASTDMA_RESERVE,
1683 			    ("Reserve: dma_reserve is exhausted\n"));
1684 			return (DDI_DMA_NORESOURCES);
1685 		}
1686 
1687 		softsp->dma_reserve -= np;
1688 		mutex_exit(&softsp->dma_pool_lock);
1689 		mp = kmem_zalloc(sizeof (*mp), KM_SLEEP);
1690 		mp->dmai_rflags = DMP_BYPASSNEXUS;
1691 		mp->dmai_rdip = rdip;
1692 		mp->dmai_minxfer = dma_lim->dlim_minxfer;
1693 		mp->dmai_burstsizes = dma_lim->dlim_burstsizes;
1694 
1695 		ioaddr = (ioaddr_t)(uintptr_t)vmem_xalloc(softsp->dvma_arena,
1696 		    iommu_ptob(np), IOMMU_PAGESIZE, 0,
1697 		    dma_lim->dlim_cntr_max + 1,
1698 		    (void *)(uintptr_t)ALO, (void *)(uintptr_t)(AHI + 1),
1699 		    dmareq->dmar_fp == DDI_DMA_SLEEP ? VM_SLEEP : VM_NOSLEEP);
1700 
1701 		if (ioaddr == 0) {
1702 			mutex_enter(&softsp->dma_pool_lock);
1703 			softsp->dma_reserve += np;
1704 			mutex_exit(&softsp->dma_pool_lock);
1705 			kmem_free(mp, sizeof (*mp));
1706 			DPRINTF(IOMMU_FASTDMA_RESERVE,
1707 			    ("Reserve: No dvma resources available\n"));
1708 			return (DDI_DMA_NOMAPPING);
1709 		}
1710 
1711 		/* create a per request structure */
1712 		iommu_fast_dvma = kmem_alloc(sizeof (struct fast_dvma),
1713 		    KM_SLEEP);
1714 
1715 		/*
1716 		 * We need to remember the size of the transfer so that
1717 		 * we can figure the virtual pages to sync when the transfer
1718 		 * is complete.
1719 		 */
1720 		iommu_fast_dvma->pagecnt = kmem_zalloc(np *
1721 		    sizeof (uint_t), KM_SLEEP);
1722 
1723 		/* Allocate a streaming cache sync flag for each index */
1724 		iommu_fast_dvma->sync_flag = kmem_zalloc(np *
1725 		    sizeof (int), KM_SLEEP);
1726 
1727 		/* Allocate a physical sync flag for each index */
1728 		iommu_fast_dvma->phys_sync_flag =
1729 		    kmem_zalloc(np * sizeof (uint64_t), KM_SLEEP);
1730 
1731 		for (i = 0; i < np; i++)
1732 			iommu_fast_dvma->phys_sync_flag[i] = va_to_pa((caddr_t)
1733 			    &iommu_fast_dvma->sync_flag[i]);
1734 
1735 		mp->dmai_mapping = ioaddr;
1736 		mp->dmai_ndvmapages = np;
1737 		iommu_fast_dvma->ops = &iommu_dvma_ops;
1738 		iommu_fast_dvma->softsp = (caddr_t)softsp;
1739 		mp->dmai_nexus_private = (caddr_t)iommu_fast_dvma;
1740 		handlep = (ddi_dma_handle_t *)objp;
1741 		*handlep = (ddi_dma_handle_t)mp;
1742 
1743 		DPRINTF(IOMMU_FASTDMA_RESERVE,
1744 		    ("Reserve: mapping object %p base addr %lx size %x\n",
1745 		    mp, mp->dmai_mapping, mp->dmai_ndvmapages));
1746 
1747 		break;
1748 	}
1749 
1750 	case DDI_DMA_RELEASE:
1751 	{
1752 		ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1753 		uint_t np = npages = mp->dmai_ndvmapages;
1754 		ioaddr_t ioaddr = mp->dmai_mapping;
1755 		volatile uint64_t *iotte_ptr;
1756 		struct fast_dvma *iommu_fast_dvma = (struct fast_dvma *)
1757 		    mp->dmai_nexus_private;
1758 		struct sbus_soft_state *softsp = (struct sbus_soft_state *)
1759 		    iommu_fast_dvma->softsp;
1760 
1761 		ASSERT(softsp != NULL);
1762 
1763 		/* Unload stale mappings and flush stale tlb's */
1764 		iotte_ptr = IOTTE_NDX(ioaddr, softsp->soft_tsb_base_addr);
1765 
1766 		while (npages > (uint_t)0) {
1767 			*iotte_ptr = (uint64_t)0;	/* unload tte */
1768 			iommu_tlb_flush(softsp, ioaddr, 1);
1769 
1770 			npages--;
1771 			iotte_ptr++;
1772 			ioaddr += IOMMU_PAGESIZE;
1773 		}
1774 
1775 		ioaddr = (ioaddr_t)mp->dmai_mapping;
1776 		mutex_enter(&softsp->dma_pool_lock);
1777 		softsp->dma_reserve += np;
1778 		mutex_exit(&softsp->dma_pool_lock);
1779 
1780 		if (mp->dmai_rflags & DMP_NOLIMIT)
1781 			vmem_free(softsp->dvma_arena,
1782 			    (void *)(uintptr_t)ioaddr, iommu_ptob(np));
1783 		else
1784 			vmem_xfree(softsp->dvma_arena,
1785 			    (void *)(uintptr_t)ioaddr, iommu_ptob(np));
1786 
1787 		kmem_free(mp, sizeof (*mp));
1788 		kmem_free(iommu_fast_dvma->pagecnt, np * sizeof (uint_t));
1789 		kmem_free(iommu_fast_dvma->sync_flag, np * sizeof (int));
1790 		kmem_free(iommu_fast_dvma->phys_sync_flag, np *
1791 		    sizeof (uint64_t));
1792 		kmem_free(iommu_fast_dvma, sizeof (struct fast_dvma));
1793 
1794 
1795 		DPRINTF(IOMMU_FASTDMA_RESERVE,
1796 		    ("Release: Base addr %x size %x\n", ioaddr, np));
1797 		/*
1798 		 * Now that we've freed some resource,
1799 		 * if there is anybody waiting for it
1800 		 * try and get them going.
1801 		 */
1802 		if (softsp->dvma_call_list_id != 0)
1803 			ddi_run_callback(&softsp->dvma_call_list_id);
1804 
1805 		break;
1806 	}
1807 
1808 	default:
1809 		DPRINTF(IOMMU_DMAMCTL_DEBUG, ("iommu_dma_mctl: unknown option "
1810 		    "0%x\n", request));
1811 
1812 		return (DDI_FAILURE);
1813 	}
1814 	return (DDI_SUCCESS);
1815 }
1816 
1817 /*ARGSUSED*/
1818 void
1819 iommu_dvma_kaddr_load(ddi_dma_handle_t h, caddr_t a, uint_t len, uint_t index,
1820     ddi_dma_cookie_t *cp)
1821 {
1822 	uintptr_t addr;
1823 	ioaddr_t ioaddr;
1824 	uint_t offset;
1825 	pfn_t pfn;
1826 	int npages;
1827 	volatile uint64_t *iotte_ptr;
1828 	uint64_t iotte_flag = 0;
1829 	struct as *as = NULL;
1830 	extern struct as kas;
1831 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)h;
1832 	struct fast_dvma *iommu_fast_dvma =
1833 	    (struct fast_dvma *)mp->dmai_nexus_private;
1834 	struct sbus_soft_state *softsp = (struct sbus_soft_state *)
1835 	    iommu_fast_dvma->softsp;
1836 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1837 	struct io_mem_list *iomemp;
1838 	pfn_t *pfnp;
1839 #endif /* DEBUG && IO_MEMUSAGE */
1840 
1841 	ASSERT(softsp != NULL);
1842 
1843 	addr = (uintptr_t)a;
1844 	ioaddr = (ioaddr_t)(mp->dmai_mapping + iommu_ptob(index));
1845 	offset = (uint_t)(addr & IOMMU_PAGEOFFSET);
1846 	iommu_fast_dvma->pagecnt[index] = iommu_btopr(len + offset);
1847 	as = &kas;
1848 	addr &= ~IOMMU_PAGEOFFSET;
1849 	npages = iommu_btopr(len + offset);
1850 
1851 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1852 	iomemp = kmem_alloc(sizeof (struct io_mem_list), KM_SLEEP);
1853 	iomemp->rdip = mp->dmai_rdip;
1854 	iomemp->ioaddr = ioaddr;
1855 	iomemp->addr = addr;
1856 	iomemp->npages = npages;
1857 	pfnp = iomemp->pfn = kmem_zalloc(sizeof (*pfnp) * (npages + 1),
1858 	    KM_SLEEP);
1859 #endif /* DEBUG && IO_MEMUSAGE */
1860 
1861 	cp->dmac_address = ioaddr | offset;
1862 	cp->dmac_size = len;
1863 
1864 	iotte_ptr = IOTTE_NDX(ioaddr, softsp->soft_tsb_base_addr);
1865 	/* read/write and streaming io on */
1866 	iotte_flag = IOTTE_VALID | IOTTE_WRITE | IOTTE_CACHE;
1867 
1868 	if (mp->dmai_rflags & DDI_DMA_CONSISTENT)
1869 		mp->dmai_rflags |= DMP_NOSYNC;
1870 	else if (!softsp->stream_buf_off)
1871 		iotte_flag |= IOTTE_STREAM;
1872 
1873 	DPRINTF(IOMMU_FASTDMA_LOAD, ("kaddr_load: ioaddr %x "
1874 	    "size %x offset %x index %x kaddr %lx\n",
1875 	    ioaddr, len, offset, index, addr));
1876 	ASSERT(npages > 0);
1877 	do {
1878 		pfn = hat_getpfnum(as->a_hat, (caddr_t)addr);
1879 		if (pfn == PFN_INVALID) {
1880 			DPRINTF(IOMMU_FASTDMA_LOAD, ("kaddr_load: invalid pfn "
1881 			    "from hat_getpfnum()\n"));
1882 		}
1883 
1884 		iommu_tlb_flush(softsp, ioaddr, 1);
1885 
1886 		/* load tte */
1887 		*iotte_ptr = ((uint64_t)pfn << IOMMU_PAGESHIFT) | iotte_flag;
1888 
1889 		npages--;
1890 		iotte_ptr++;
1891 
1892 		addr += IOMMU_PAGESIZE;
1893 		ioaddr += IOMMU_PAGESIZE;
1894 
1895 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1896 		*pfnp = pfn;
1897 		pfnp++;
1898 #endif /* DEBUG && IO_MEMUSAGE */
1899 
1900 	} while (npages > 0);
1901 
1902 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1903 	mutex_enter(&softsp->iomemlock);
1904 	iomemp->next = softsp->iomem;
1905 	softsp->iomem = iomemp;
1906 	mutex_exit(&softsp->iomemlock);
1907 #endif /* DEBUG && IO_MEMUSAGE */
1908 }
1909 
1910 /*ARGSUSED*/
1911 void
1912 iommu_dvma_unload(ddi_dma_handle_t h, uint_t index, uint_t view)
1913 {
1914 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)h;
1915 	ioaddr_t ioaddr;
1916 	pgcnt_t npages;
1917 	struct fast_dvma *iommu_fast_dvma =
1918 	    (struct fast_dvma *)mp->dmai_nexus_private;
1919 	struct sbus_soft_state *softsp = (struct sbus_soft_state *)
1920 	    iommu_fast_dvma->softsp;
1921 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1922 	struct io_mem_list **prevp, *walk;
1923 #endif /* DEBUG && IO_MEMUSAGE */
1924 
1925 	ASSERT(softsp != NULL);
1926 
1927 	ioaddr = (ioaddr_t)(mp->dmai_mapping + iommu_ptob(index));
1928 	npages = iommu_fast_dvma->pagecnt[index];
1929 
1930 #if defined(DEBUG) && defined(IO_MEMUSAGE)
1931 	mutex_enter(&softsp->iomemlock);
1932 	prevp = &softsp->iomem;
1933 	walk = softsp->iomem;
1934 
1935 	while (walk != NULL) {
1936 		if (walk->ioaddr == ioaddr) {
1937 			*prevp = walk->next;
1938 			break;
1939 		}
1940 		prevp = &walk->next;
1941 		walk = walk->next;
1942 	}
1943 	mutex_exit(&softsp->iomemlock);
1944 
1945 	kmem_free(walk->pfn, sizeof (pfn_t) * (npages + 1));
1946 	kmem_free(walk, sizeof (struct io_mem_list));
1947 #endif /* DEBUG && IO_MEMUSAGE */
1948 
1949 	DPRINTF(IOMMU_FASTDMA_SYNC, ("kaddr_unload: handle %p sync flag "
1950 	    "addr %p sync flag pfn %llx index %x page count %lx\n", mp,
1951 	    &iommu_fast_dvma->sync_flag[index],
1952 	    iommu_fast_dvma->phys_sync_flag[index],
1953 	    index, npages));
1954 
1955 	if ((mp->dmai_rflags & DMP_NOSYNC) != DMP_NOSYNC) {
1956 		sync_stream_buf(softsp, ioaddr, npages,
1957 			(int *)&iommu_fast_dvma->sync_flag[index],
1958 			iommu_fast_dvma->phys_sync_flag[index]);
1959 	}
1960 }
1961 
1962 /*ARGSUSED*/
1963 void
1964 iommu_dvma_sync(ddi_dma_handle_t h, uint_t index, uint_t view)
1965 {
1966 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)h;
1967 	ioaddr_t ioaddr;
1968 	uint_t npages;
1969 	struct fast_dvma *iommu_fast_dvma =
1970 	    (struct fast_dvma *)mp->dmai_nexus_private;
1971 	struct sbus_soft_state *softsp = (struct sbus_soft_state *)
1972 	    iommu_fast_dvma->softsp;
1973 
1974 	if ((mp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
1975 		return;
1976 
1977 	ASSERT(softsp != NULL);
1978 	ioaddr = (ioaddr_t)(mp->dmai_mapping + iommu_ptob(index));
1979 	npages = iommu_fast_dvma->pagecnt[index];
1980 
1981 	DPRINTF(IOMMU_FASTDMA_SYNC, ("kaddr_sync: handle %p, "
1982 	    "sync flag addr %p, sync flag pfn %llx\n", mp,
1983 	    &iommu_fast_dvma->sync_flag[index],
1984 	    iommu_fast_dvma->phys_sync_flag[index]));
1985 
1986 	sync_stream_buf(softsp, ioaddr, npages,
1987 	    (int *)&iommu_fast_dvma->sync_flag[index],
1988 	    iommu_fast_dvma->phys_sync_flag[index]);
1989 }
1990