xref: /titanic_52/usr/src/uts/intel/ia32/os/ddi_i86.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 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/conf.h>
30 #include <sys/kmem.h>
31 #include <sys/ddi_impldefs.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/ddifm.h>
35 #include <sys/fm/io/ddi.h>
36 #include <sys/ontrap.h>
37 
38 
39 /*
40  * DDI DMA Engine functions for x86.
41  * These functions are more naturally generic, but do not apply to SPARC.
42  */
43 
44 int
45 ddi_dmae_alloc(dev_info_t *dip, int chnl, int (*dmae_waitfp)(), caddr_t arg)
46 {
47 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_ACQUIRE,
48 	    (off_t *)dmae_waitfp, (size_t *)arg,
49 	    (caddr_t *)(uintptr_t)chnl, 0));
50 }
51 
52 int
53 ddi_dmae_release(dev_info_t *dip, int chnl)
54 {
55 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_FREE, 0, 0,
56 	    (caddr_t *)(uintptr_t)chnl, 0));
57 }
58 
59 int
60 ddi_dmae_getlim(dev_info_t *dip, ddi_dma_lim_t *limitsp)
61 {
62 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETLIM, 0, 0,
63 	    (caddr_t *)limitsp, 0));
64 }
65 
66 int
67 ddi_dmae_getattr(dev_info_t *dip, ddi_dma_attr_t *attrp)
68 {
69 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETATTR, 0, 0,
70 	    (caddr_t *)attrp, 0));
71 }
72 
73 int
74 ddi_dmae_1stparty(dev_info_t *dip, int chnl)
75 {
76 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_1STPTY, 0, 0,
77 	    (caddr_t *)(uintptr_t)chnl, 0));
78 }
79 
80 int
81 ddi_dmae_prog(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
82 	ddi_dma_cookie_t *cookiep, int chnl)
83 {
84 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_PROG, (off_t *)dmaereqp,
85 	    (size_t *)cookiep, (caddr_t *)(uintptr_t)chnl, 0));
86 }
87 
88 int
89 ddi_dmae_swsetup(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
90 	ddi_dma_cookie_t *cookiep, int chnl)
91 {
92 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_SWSETUP, (off_t *)dmaereqp,
93 	    (size_t *)cookiep, (caddr_t *)(uintptr_t)chnl, 0));
94 }
95 
96 int
97 ddi_dmae_swstart(dev_info_t *dip, int chnl)
98 {
99 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_SWSTART, 0, 0,
100 	    (caddr_t *)(uintptr_t)chnl, 0));
101 }
102 
103 int
104 ddi_dmae_stop(dev_info_t *dip, int chnl)
105 {
106 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_STOP, 0, 0,
107 	    (caddr_t *)(uintptr_t)chnl, 0));
108 }
109 
110 int
111 ddi_dmae_enable(dev_info_t *dip, int chnl)
112 {
113 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_ENABLE, 0, 0,
114 	    (caddr_t *)(uintptr_t)chnl, 0));
115 }
116 
117 int
118 ddi_dmae_disable(dev_info_t *dip, int chnl)
119 {
120 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_DISABLE, 0, 0,
121 	    (caddr_t *)(uintptr_t)chnl, 0));
122 }
123 
124 int
125 ddi_dmae_getcnt(dev_info_t *dip, int chnl, int *countp)
126 {
127 	return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETCNT, 0, (size_t *)countp,
128 	    (caddr_t *)(uintptr_t)chnl, 0));
129 }
130 
131 /*
132  * implementation specific access handle and routines:
133  */
134 
135 static uintptr_t impl_acc_hdl_id = 0;
136 
137 /*
138  * access handle allocator
139  */
140 ddi_acc_hdl_t *
141 impl_acc_hdl_get(ddi_acc_handle_t hdl)
142 {
143 	/*
144 	 * recast to ddi_acc_hdl_t instead of
145 	 * casting to ddi_acc_impl_t and then return the ah_platform_private
146 	 *
147 	 * this optimization based on the ddi_acc_hdl_t is the
148 	 * first member of the ddi_acc_impl_t.
149 	 */
150 	return ((ddi_acc_hdl_t *)hdl);
151 }
152 
153 ddi_acc_handle_t
154 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg)
155 {
156 	ddi_acc_impl_t *hp;
157 	on_trap_data_t *otp;
158 	int sleepflag;
159 
160 	sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
161 	/*
162 	 * Allocate and initialize the data access handle and error status.
163 	 */
164 	if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL)
165 		goto fail;
166 	if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc(
167 	    sizeof (ndi_err_t), sleepflag)) == NULL) {
168 		kmem_free(hp, sizeof (ddi_acc_impl_t));
169 		goto fail;
170 	}
171 	if ((otp = (on_trap_data_t *)kmem_zalloc(
172 	    sizeof (on_trap_data_t), sleepflag)) == NULL) {
173 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
174 		kmem_free(hp, sizeof (ddi_acc_impl_t));
175 		goto fail;
176 	}
177 	hp->ahi_err->err_ontrap = otp;
178 	hp->ahi_common.ah_platform_private = (void *)hp;
179 
180 	return ((ddi_acc_handle_t)hp);
181 fail:
182 	if ((waitfp != (int (*)())KM_SLEEP) &&
183 	    (waitfp != (int (*)())KM_NOSLEEP))
184 		ddi_set_callback(waitfp, arg, &impl_acc_hdl_id);
185 	return (NULL);
186 }
187 
188 void
189 impl_acc_hdl_free(ddi_acc_handle_t handle)
190 {
191 	ddi_acc_impl_t *hp;
192 
193 	/*
194 	 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *),
195 	 * because that's what we allocated in impl_acc_hdl_alloc() above.
196 	 */
197 	hp = (ddi_acc_impl_t *)handle;
198 	if (hp) {
199 		kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t));
200 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
201 		kmem_free(hp, sizeof (ddi_acc_impl_t));
202 		if (impl_acc_hdl_id)
203 			ddi_run_callback(&impl_acc_hdl_id);
204 	}
205 }
206 
207 /*
208  * Function used to check if a given access handle owns the failing address.
209  * Called by ndi_fmc_error, when we detect a PIO error.
210  */
211 /* ARGSUSED */
212 static int
213 impl_acc_check(dev_info_t *dip, const void *handle, const void *addr,
214     const void *not_used)
215 {
216 	pfn_t pfn, fault_pfn;
217 	ddi_acc_hdl_t *hp;
218 
219 	hp = impl_acc_hdl_get((ddi_acc_handle_t)handle);
220 
221 	ASSERT(hp);
222 
223 	if (addr != NULL) {
224 		pfn = hp->ah_pfn;
225 		fault_pfn = mmu_btop(*(uint64_t *)addr);
226 		if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum))
227 			return (DDI_FM_NONFATAL);
228 	}
229 	return (DDI_FM_UNKNOWN);
230 }
231 
232 void
233 impl_acc_err_init(ddi_acc_hdl_t *handlep)
234 {
235 	int fmcap;
236 	ndi_err_t *errp;
237 	on_trap_data_t *otp;
238 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep;
239 
240 	fmcap = ddi_fm_capable(handlep->ah_dip);
241 
242 	if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
243 	    !DDI_FM_ACC_ERR_CAP(fmcap)) {
244 		handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC;
245 	} else if (DDI_FM_ACC_ERR_CAP(fmcap)) {
246 		if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) {
247 			i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP,
248 			    NULL, DDI_NOSLEEP);
249 		} else {
250 			errp = hp->ahi_err;
251 			otp = (on_trap_data_t *)errp->err_ontrap;
252 			otp->ot_handle = (void *)(hp);
253 			otp->ot_prot = OT_DATA_ACCESS;
254 			errp->err_status = DDI_FM_OK;
255 			errp->err_expected = DDI_FM_ERR_UNEXPECTED;
256 			errp->err_cf = impl_acc_check;
257 		}
258 	}
259 }
260 
261 /* ARGSUSED */
262 int
263 impl_dma_check(dev_info_t *dip, const void *handle, const void *pci_hdl,
264     const void *not_used)
265 {
266 	return (DDI_FM_UNKNOWN);
267 }
268 
269 void
270 impl_acc_hdl_init(ddi_acc_hdl_t *handlep)
271 {
272 	ddi_acc_impl_t *hp;
273 	int fmcap;
274 	int devacc_attr_access;
275 
276 	if (!handlep)
277 		return;
278 	fmcap = ddi_fm_capable(handlep->ah_dip);
279 	if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
280 	    !DDI_FM_ACC_ERR_CAP(fmcap))
281 		devacc_attr_access = DDI_DEFAULT_ACC;
282 	else
283 		devacc_attr_access = handlep->ah_acc.devacc_attr_access;
284 
285 	hp = (ddi_acc_impl_t *)handlep->ah_platform_private;
286 	switch (devacc_attr_access) {
287 	case DDI_FLAGERR_ACC:
288 	case DDI_CAUTIOUS_ACC:
289 		hp->ahi_get8 = i_ddi_caut_get8;
290 		hp->ahi_put8 = i_ddi_caut_put8;
291 		hp->ahi_rep_get8 = i_ddi_caut_rep_get8;
292 		hp->ahi_rep_put8 = i_ddi_caut_rep_put8;
293 		hp->ahi_get16 = i_ddi_caut_get16;
294 		hp->ahi_get32 = i_ddi_caut_get32;
295 		hp->ahi_put16 = i_ddi_caut_put16;
296 		hp->ahi_put32 = i_ddi_caut_put32;
297 		hp->ahi_rep_get16 = i_ddi_caut_rep_get16;
298 		hp->ahi_rep_get32 = i_ddi_caut_rep_get32;
299 		hp->ahi_rep_put16 = i_ddi_caut_rep_put16;
300 		hp->ahi_rep_put32 = i_ddi_caut_rep_put32;
301 		hp->ahi_get64 = i_ddi_caut_get64;
302 		hp->ahi_put64 = i_ddi_caut_put64;
303 		hp->ahi_rep_get64 = i_ddi_caut_rep_get64;
304 		hp->ahi_rep_put64 = i_ddi_caut_rep_put64;
305 		break;
306 	case DDI_DEFAULT_ACC:
307 		if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) {
308 			hp->ahi_get8 = i_ddi_io_get8;
309 			hp->ahi_put8 = i_ddi_io_put8;
310 			hp->ahi_rep_get8 = i_ddi_io_rep_get8;
311 			hp->ahi_rep_put8 = i_ddi_io_rep_put8;
312 
313 			/* temporary set these 64 functions to no-ops */
314 			hp->ahi_get64 = i_ddi_io_get64;
315 			hp->ahi_put64 = i_ddi_io_put64;
316 			hp->ahi_rep_get64 = i_ddi_io_rep_get64;
317 			hp->ahi_rep_put64 = i_ddi_io_rep_put64;
318 
319 			/*
320 			 * check for BIG endian access
321 			 */
322 			if (handlep->ah_acc.devacc_attr_endian_flags ==
323 				DDI_STRUCTURE_BE_ACC) {
324 				hp->ahi_get16 = i_ddi_io_swap_get16;
325 				hp->ahi_get32 = i_ddi_io_swap_get32;
326 				hp->ahi_put16 = i_ddi_io_swap_put16;
327 				hp->ahi_put32 = i_ddi_io_swap_put32;
328 				hp->ahi_rep_get16 = i_ddi_io_swap_rep_get16;
329 				hp->ahi_rep_get32 = i_ddi_io_swap_rep_get32;
330 				hp->ahi_rep_put16 = i_ddi_io_swap_rep_put16;
331 				hp->ahi_rep_put32 = i_ddi_io_swap_rep_put32;
332 			} else {
333 				hp->ahi_acc_attr |= DDI_ACCATTR_DIRECT;
334 				hp->ahi_get16 = i_ddi_io_get16;
335 				hp->ahi_get32 = i_ddi_io_get32;
336 				hp->ahi_put16 = i_ddi_io_put16;
337 				hp->ahi_put32 = i_ddi_io_put32;
338 				hp->ahi_rep_get16 = i_ddi_io_rep_get16;
339 				hp->ahi_rep_get32 = i_ddi_io_rep_get32;
340 				hp->ahi_rep_put16 = i_ddi_io_rep_put16;
341 				hp->ahi_rep_put32 = i_ddi_io_rep_put32;
342 			}
343 
344 		} else if (hp->ahi_acc_attr & DDI_ACCATTR_CPU_VADDR) {
345 
346 			hp->ahi_get8 = i_ddi_vaddr_get8;
347 			hp->ahi_put8 = i_ddi_vaddr_put8;
348 			hp->ahi_rep_get8 = i_ddi_vaddr_rep_get8;
349 			hp->ahi_rep_put8 = i_ddi_vaddr_rep_put8;
350 
351 			/*
352 			 * check for BIG endian access
353 			 */
354 			if (handlep->ah_acc.devacc_attr_endian_flags ==
355 				DDI_STRUCTURE_BE_ACC) {
356 
357 				hp->ahi_get16 = i_ddi_vaddr_swap_get16;
358 				hp->ahi_get32 = i_ddi_vaddr_swap_get32;
359 				hp->ahi_get64 = i_ddi_vaddr_swap_get64;
360 				hp->ahi_put16 = i_ddi_vaddr_swap_put16;
361 				hp->ahi_put32 = i_ddi_vaddr_swap_put32;
362 				hp->ahi_put64 = i_ddi_vaddr_swap_put64;
363 				hp->ahi_rep_get16 = i_ddi_vaddr_swap_rep_get16;
364 				hp->ahi_rep_get32 = i_ddi_vaddr_swap_rep_get32;
365 				hp->ahi_rep_get64 = i_ddi_vaddr_swap_rep_get64;
366 				hp->ahi_rep_put16 = i_ddi_vaddr_swap_rep_put16;
367 				hp->ahi_rep_put32 = i_ddi_vaddr_swap_rep_put32;
368 				hp->ahi_rep_put64 = i_ddi_vaddr_swap_rep_put64;
369 			} else {
370 				hp->ahi_acc_attr |= DDI_ACCATTR_DIRECT;
371 				hp->ahi_get16 = i_ddi_vaddr_get16;
372 				hp->ahi_get32 = i_ddi_vaddr_get32;
373 				hp->ahi_get64 = i_ddi_vaddr_get64;
374 				hp->ahi_put16 = i_ddi_vaddr_put16;
375 				hp->ahi_put32 = i_ddi_vaddr_put32;
376 				hp->ahi_put64 = i_ddi_vaddr_put64;
377 				hp->ahi_rep_get16 = i_ddi_vaddr_rep_get16;
378 				hp->ahi_rep_get32 = i_ddi_vaddr_rep_get32;
379 				hp->ahi_rep_get64 = i_ddi_vaddr_rep_get64;
380 				hp->ahi_rep_put16 = i_ddi_vaddr_rep_put16;
381 				hp->ahi_rep_put32 = i_ddi_vaddr_rep_put32;
382 				hp->ahi_rep_put64 = i_ddi_vaddr_rep_put64;
383 			}
384 		}
385 		break;
386 	}
387 	hp->ahi_fault_check = i_ddi_acc_fault_check;
388 	hp->ahi_fault_notify = i_ddi_acc_fault_notify;
389 	hp->ahi_fault = 0;
390 	impl_acc_err_init(handlep);
391 }
392 
393 /*
394  * The followings are low-level routines for data access.
395  *
396  * All of these routines should be implemented in assembly. Those
397  * that have been rewritten be found in ~ml/ddi_i86_asm.s
398  */
399 
400 /*ARGSUSED*/
401 uint16_t
402 i_ddi_vaddr_swap_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
403 {
404 	return (ddi_swap16(*addr));
405 }
406 
407 /*ARGSUSED*/
408 uint16_t
409 i_ddi_io_swap_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
410 {
411 	return (ddi_swap16(inw((uintptr_t)addr)));
412 }
413 
414 /*ARGSUSED*/
415 uint32_t
416 i_ddi_vaddr_swap_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
417 {
418 	return (ddi_swap32(*addr));
419 }
420 
421 /*ARGSUSED*/
422 uint32_t
423 i_ddi_io_swap_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
424 {
425 	return (ddi_swap32(inl((uintptr_t)addr)));
426 }
427 
428 /*ARGSUSED*/
429 uint64_t
430 i_ddi_vaddr_swap_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
431 {
432 	return (ddi_swap64(*addr));
433 }
434 
435 /*ARGSUSED*/
436 void
437 i_ddi_vaddr_swap_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
438 {
439 	*addr = ddi_swap16(value);
440 }
441 
442 /*ARGSUSED*/
443 void
444 i_ddi_io_swap_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
445 {
446 	outw((uintptr_t)addr, ddi_swap16(value));
447 }
448 
449 /*ARGSUSED*/
450 void
451 i_ddi_vaddr_swap_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
452 {
453 	*addr = ddi_swap32(value);
454 }
455 
456 /*ARGSUSED*/
457 void
458 i_ddi_io_swap_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
459 {
460 	outl((uintptr_t)addr, ddi_swap32(value));
461 }
462 
463 /*ARGSUSED*/
464 void
465 i_ddi_vaddr_swap_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
466 {
467 	*addr = ddi_swap64(value);
468 }
469 
470 /*ARGSUSED*/
471 void
472 i_ddi_vaddr_rep_get8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
473 	uint8_t *dev_addr, size_t repcount, uint_t flags)
474 {
475 	uint8_t	*h, *d;
476 
477 	h = host_addr;
478 	d = dev_addr;
479 
480 	if (flags == DDI_DEV_AUTOINCR)
481 		for (; repcount; repcount--)
482 			*h++ = *d++;
483 	else
484 		for (; repcount; repcount--)
485 			*h++ = *d;
486 }
487 
488 /*ARGSUSED*/
489 void
490 i_ddi_vaddr_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
491 	uint16_t *dev_addr, size_t repcount, uint_t flags)
492 {
493 	uint16_t *h, *d;
494 
495 	h = host_addr;
496 	d = dev_addr;
497 
498 	if (flags == DDI_DEV_AUTOINCR)
499 		for (; repcount; repcount--)
500 			*h++ = *d++;
501 	else
502 		for (; repcount; repcount--)
503 			*h++ = *d;
504 }
505 
506 /*ARGSUSED*/
507 void
508 i_ddi_vaddr_swap_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
509 	uint16_t *dev_addr, size_t repcount, uint_t flags)
510 {
511 	uint16_t *h, *d;
512 
513 	h = host_addr;
514 	d = dev_addr;
515 
516 	if (flags == DDI_DEV_AUTOINCR)
517 		for (; repcount; repcount--)
518 			*h++ = ddi_swap16(*d++);
519 	else
520 		for (; repcount; repcount--)
521 			*h++ = ddi_swap16(*d);
522 }
523 
524 /*ARGSUSED*/
525 void
526 i_ddi_io_swap_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
527 	uint16_t *dev_addr, size_t repcount, uint_t flags)
528 {
529 	uint16_t *h;
530 	uintptr_t port;
531 
532 	h = host_addr;
533 	port = (uintptr_t)dev_addr;
534 
535 	if (flags == DDI_DEV_AUTOINCR)
536 		for (; repcount; repcount--, port += 2)
537 			*h++ = ddi_swap16(inw(port));
538 	else
539 		for (; repcount; repcount--)
540 			*h++ = ddi_swap16(inw(port));
541 }
542 
543 /*ARGSUSED*/
544 void
545 i_ddi_vaddr_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
546 	uint32_t *dev_addr, size_t repcount, uint_t flags)
547 {
548 	uint32_t *h, *d;
549 
550 	h = host_addr;
551 	d = dev_addr;
552 
553 	if (flags == DDI_DEV_AUTOINCR)
554 		for (; repcount; repcount--)
555 			*h++ = *d++;
556 	else
557 		for (; repcount; repcount--)
558 			*h++ = *d;
559 }
560 
561 /*ARGSUSED*/
562 void
563 i_ddi_vaddr_swap_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
564 	uint32_t *dev_addr, size_t repcount, uint_t flags)
565 {
566 	uint32_t *h, *d;
567 
568 	h = host_addr;
569 	d = dev_addr;
570 
571 	if (flags == DDI_DEV_AUTOINCR)
572 		for (; repcount; repcount--)
573 			*h++ = ddi_swap32(*d++);
574 	else
575 		for (; repcount; repcount--)
576 			*h++ = ddi_swap32(*d);
577 }
578 
579 /*ARGSUSED*/
580 void
581 i_ddi_io_swap_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
582 	uint32_t *dev_addr, size_t repcount, uint_t flags)
583 {
584 	uint32_t *h;
585 	uintptr_t port;
586 
587 	h = host_addr;
588 	port = (uintptr_t)dev_addr;
589 
590 	if (flags == DDI_DEV_AUTOINCR)
591 		for (; repcount; repcount--, port += 4)
592 			*h++ = ddi_swap32(inl(port));
593 	else
594 		for (; repcount; repcount--)
595 			*h++ = ddi_swap32(inl(port));
596 }
597 
598 /*ARGSUSED*/
599 void
600 i_ddi_vaddr_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
601 	uint64_t *dev_addr, size_t repcount, uint_t flags)
602 {
603 	uint64_t *h, *d;
604 
605 	h = host_addr;
606 	d = dev_addr;
607 
608 	if (flags == DDI_DEV_AUTOINCR)
609 		for (; repcount; repcount--)
610 			*h++ = *d++;
611 	else
612 		for (; repcount; repcount--)
613 			*h++ = *d;
614 }
615 
616 /*ARGSUSED*/
617 void
618 i_ddi_vaddr_swap_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
619 	uint64_t *dev_addr, size_t repcount, uint_t flags)
620 {
621 	uint64_t *h, *d;
622 
623 	h = host_addr;
624 	d = dev_addr;
625 
626 	if (flags == DDI_DEV_AUTOINCR)
627 		for (; repcount; repcount--)
628 			*h++ = ddi_swap64(*d++);
629 	else
630 		for (; repcount; repcount--)
631 			*h++ = ddi_swap64(*d);
632 }
633 
634 /*ARGSUSED*/
635 void
636 i_ddi_vaddr_rep_put8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
637 	uint8_t *dev_addr, size_t repcount, uint_t flags)
638 {
639 	uint8_t	*h, *d;
640 
641 	h = host_addr;
642 	d = dev_addr;
643 
644 	if (flags == DDI_DEV_AUTOINCR)
645 		for (; repcount; repcount--)
646 			*d++ = *h++;
647 	else
648 		for (; repcount; repcount--)
649 			*d = *h++;
650 }
651 
652 /*ARGSUSED*/
653 void
654 i_ddi_vaddr_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
655 	uint16_t *dev_addr, size_t repcount, uint_t flags)
656 {
657 	uint16_t *h, *d;
658 
659 	h = host_addr;
660 	d = dev_addr;
661 
662 	if (flags == DDI_DEV_AUTOINCR)
663 		for (; repcount; repcount--)
664 			*d++ = *h++;
665 	else
666 		for (; repcount; repcount--)
667 			*d = *h++;
668 }
669 
670 /*ARGSUSED*/
671 void
672 i_ddi_vaddr_swap_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
673 	uint16_t *dev_addr, size_t repcount, uint_t flags)
674 {
675 	uint16_t *h, *d;
676 
677 	h = host_addr;
678 	d = dev_addr;
679 
680 	if (flags == DDI_DEV_AUTOINCR)
681 		for (; repcount; repcount--)
682 			*d++ = ddi_swap16(*h++);
683 	else
684 		for (; repcount; repcount--)
685 			*d = ddi_swap16(*h++);
686 }
687 
688 /*ARGSUSED*/
689 void
690 i_ddi_io_swap_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
691 	uint16_t *dev_addr, size_t repcount, uint_t flags)
692 {
693 	uint16_t *h;
694 	uintptr_t port;
695 
696 	h = host_addr;
697 	port = (uintptr_t)dev_addr;
698 
699 	if (flags == DDI_DEV_AUTOINCR)
700 		for (; repcount; repcount--, port += 2)
701 			outw(port, ddi_swap16(*h++));
702 	else
703 		for (; repcount; repcount--)
704 			outw(port, ddi_swap16(*h++));
705 }
706 
707 /*ARGSUSED*/
708 void
709 i_ddi_vaddr_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
710 	uint32_t *dev_addr, size_t repcount, uint_t flags)
711 {
712 	uint32_t *h, *d;
713 
714 	h = host_addr;
715 	d = dev_addr;
716 
717 	if (flags == DDI_DEV_AUTOINCR)
718 		for (; repcount; repcount--)
719 			*d++ = *h++;
720 	else
721 		for (; repcount; repcount--)
722 			*d = *h++;
723 }
724 
725 /*ARGSUSED*/
726 void
727 i_ddi_vaddr_swap_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
728 	uint32_t *dev_addr, size_t repcount, uint_t flags)
729 {
730 	uint32_t *h, *d;
731 
732 	h = host_addr;
733 	d = dev_addr;
734 
735 	if (flags == DDI_DEV_AUTOINCR)
736 		for (; repcount; repcount--)
737 			*d++ = ddi_swap32(*h++);
738 	else
739 		for (; repcount; repcount--)
740 			*d = ddi_swap32(*h++);
741 }
742 
743 /*ARGSUSED*/
744 void
745 i_ddi_io_swap_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
746 	uint32_t *dev_addr, size_t repcount, uint_t flags)
747 {
748 	uint32_t *h;
749 	uintptr_t port;
750 
751 	h = host_addr;
752 	port = (uintptr_t)dev_addr;
753 
754 	if (flags == DDI_DEV_AUTOINCR)
755 		for (; repcount; repcount--, port += 4)
756 			outl(port, ddi_swap32(*h++));
757 	else
758 		for (; repcount; repcount--)
759 			outl(port, ddi_swap32(*h++));
760 }
761 
762 /*ARGSUSED*/
763 void
764 i_ddi_vaddr_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
765 	uint64_t *dev_addr, size_t repcount, uint_t flags)
766 {
767 	uint64_t *h, *d;
768 
769 	h = host_addr;
770 	d = dev_addr;
771 
772 	if (flags == DDI_DEV_AUTOINCR)
773 		for (; repcount; repcount--)
774 			*d++ = *h++;
775 	else
776 		for (; repcount; repcount--)
777 			*d = *h++;
778 }
779 
780 /*ARGSUSED*/
781 void
782 i_ddi_vaddr_swap_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
783 	uint64_t *dev_addr, size_t repcount, uint_t flags)
784 {
785 	uint64_t *h, *d;
786 
787 	h = host_addr;
788 	d = dev_addr;
789 
790 	if (flags == DDI_DEV_AUTOINCR)
791 		for (; repcount; repcount--)
792 			*d++ = ddi_swap64(*h++);
793 	else
794 		for (; repcount; repcount--)
795 			*d = ddi_swap64(*h++);
796 }
797 
798 /*ARGSUSED*/
799 uint64_t
800 i_ddi_io_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
801 {
802 	panic("ddi_get64 from i/o space");
803 	/*NOTREACHED*/
804 	return (0);
805 }
806 
807 /*ARGSUSED*/
808 void
809 i_ddi_io_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, uint64_t value)
810 {
811 	panic("ddi_put64 to i/o space");
812 	/*NOTREACHED*/
813 }
814 
815 void
816 ddi_io_rep_get8(ddi_acc_handle_t handle,
817 	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount)
818 {
819 	(((ddi_acc_impl_t *)handle)->ahi_rep_get8)
820 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
821 		repcount, DDI_DEV_NO_AUTOINCR);
822 }
823 
824 void
825 ddi_io_rep_get16(ddi_acc_handle_t handle,
826 	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount)
827 {
828 	(((ddi_acc_impl_t *)handle)->ahi_rep_get16)
829 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
830 		repcount, DDI_DEV_NO_AUTOINCR);
831 }
832 
833 void
834 ddi_io_rep_get32(ddi_acc_handle_t handle,
835 	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount)
836 {
837 	(((ddi_acc_impl_t *)handle)->ahi_rep_get32)
838 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
839 		repcount, DDI_DEV_NO_AUTOINCR);
840 }
841 
842 /*ARGSUSED*/
843 void
844 i_ddi_io_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
845 	uint64_t *dev_addr, size_t repcount, uint_t flags)
846 {
847 	cmn_err(CE_PANIC, "ddi_rep_get64 from i/o space");
848 }
849 
850 void
851 ddi_io_rep_put8(ddi_acc_handle_t handle,
852 	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount)
853 {
854 	(((ddi_acc_impl_t *)handle)->ahi_rep_put8)
855 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
856 		repcount, DDI_DEV_NO_AUTOINCR);
857 }
858 
859 void
860 ddi_io_rep_put16(ddi_acc_handle_t handle,
861 	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount)
862 {
863 	(((ddi_acc_impl_t *)handle)->ahi_rep_put16)
864 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
865 		repcount, DDI_DEV_NO_AUTOINCR);
866 }
867 
868 void
869 ddi_io_rep_put32(ddi_acc_handle_t handle,
870 	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount)
871 {
872 	(((ddi_acc_impl_t *)handle)->ahi_rep_put32)
873 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
874 		repcount, DDI_DEV_NO_AUTOINCR);
875 }
876 
877 /*ARGSUSED*/
878 void
879 i_ddi_io_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
880 	uint64_t *dev_addr, size_t repcount, uint_t flags)
881 {
882 	cmn_err(CE_PANIC, "ddi_rep_put64 to i/o space");
883 }
884 
885 /*
886  * We need to separate the old interfaces from the new ones and leave them
887  * in here for a while. Previous versions of the OS defined the new interfaces
888  * to the old interfaces. This way we can fix things up so that we can
889  * eventually remove these interfaces.
890  * e.g. A 3rd party module/driver using ddi_io_rep_get8 and built against S10
891  * or earlier will actually have a reference to ddi_io_rep_getb in the binary.
892  */
893 #ifdef _ILP32
894 void
895 ddi_io_rep_getb(ddi_acc_handle_t handle,
896 	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount)
897 {
898 	(((ddi_acc_impl_t *)handle)->ahi_rep_get8)
899 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
900 		repcount, DDI_DEV_NO_AUTOINCR);
901 }
902 
903 void
904 ddi_io_rep_getw(ddi_acc_handle_t handle,
905 	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount)
906 {
907 	(((ddi_acc_impl_t *)handle)->ahi_rep_get16)
908 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
909 		repcount, DDI_DEV_NO_AUTOINCR);
910 }
911 
912 void
913 ddi_io_rep_getl(ddi_acc_handle_t handle,
914 	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount)
915 {
916 	(((ddi_acc_impl_t *)handle)->ahi_rep_get32)
917 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
918 		repcount, DDI_DEV_NO_AUTOINCR);
919 }
920 
921 void
922 ddi_io_rep_putb(ddi_acc_handle_t handle,
923 	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount)
924 {
925 	(((ddi_acc_impl_t *)handle)->ahi_rep_put8)
926 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
927 		repcount, DDI_DEV_NO_AUTOINCR);
928 }
929 
930 void
931 ddi_io_rep_putw(ddi_acc_handle_t handle,
932 	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount)
933 {
934 	(((ddi_acc_impl_t *)handle)->ahi_rep_put16)
935 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
936 		repcount, DDI_DEV_NO_AUTOINCR);
937 }
938 
939 void
940 ddi_io_rep_putl(ddi_acc_handle_t handle,
941 	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount)
942 {
943 	(((ddi_acc_impl_t *)handle)->ahi_rep_put32)
944 		((ddi_acc_impl_t *)handle, host_addr, dev_addr,
945 		repcount, DDI_DEV_NO_AUTOINCR);
946 }
947 #endif /* _ILP32 */
948 
949 /*
950  * These next two functions could be translated into assembler someday
951  */
952 int
953 ddi_check_acc_handle(ddi_acc_handle_t handle)
954 {
955 	ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle;
956 	return (((*hdlp->ahi_fault_check)(hdlp) == DDI_SUCCESS) ? DDI_SUCCESS :
957 	    DDI_FAILURE);
958 }
959 
960 int
961 i_ddi_acc_fault_check(ddi_acc_impl_t *hdlp)
962 {
963 	/* Default version, just returns flag value */
964 	return (hdlp->ahi_fault);
965 }
966 
967 /*ARGSUSED*/
968 void
969 i_ddi_acc_fault_notify(ddi_acc_impl_t *hdlp)
970 {
971 	/* Default version, does nothing for now */
972 }
973 
974 void
975 i_ddi_acc_set_fault(ddi_acc_handle_t handle)
976 {
977 	ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle;
978 
979 	if (!hdlp->ahi_fault) {
980 		hdlp->ahi_fault = 1;
981 		(*hdlp->ahi_fault_notify)(hdlp);
982 	}
983 }
984 
985 void
986 i_ddi_acc_clr_fault(ddi_acc_handle_t handle)
987 {
988 	ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle;
989 
990 	if (hdlp->ahi_fault) {
991 		hdlp->ahi_fault = 0;
992 		(*hdlp->ahi_fault_notify)(hdlp);
993 	}
994 }
995