xref: /titanic_52/usr/src/uts/sparc/v9/ml/ddi_v9_asm.s (revision b5c1d037485d15edb481098032579461ef8116cf)
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 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma	ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <sys/asi.h>
29#include <sys/asm_linkage.h>
30#include <sys/machthread.h>
31#include <sys/privregs.h>
32#include <sys/ontrap.h>
33#include <sys/dditypes.h>
34
35#ifndef lint
36#include "assym.h"
37#endif
38
39#if defined(lint)
40#include <sys/isa_defs.h>
41#include <sys/types.h>
42#include <sys/sunddi.h>
43#endif  /* lint */
44
45/*
46 * This file implements the following ddi common access
47 * functions:
48 *
49 *	ddi_get{8,16,32,64}
50 *	ddi_put{8,16,32,64}
51 *
52 * and the underlying "trivial" implementations
53 *
54 *      i_ddi_{get,put}{8,16,32,64}
55 *
56 * which assume that there is no need to check the access handle -
57 * byte swapping will be done by the mmu and the address is always
58 * accessible via ld/st instructions.
59 */
60
61#if defined(lint)
62
63/*ARGSUSED*/
64uint8_t
65ddi_get8(ddi_acc_handle_t handle, uint8_t *addr)
66{
67	return (0);
68}
69
70/*ARGSUSED*/
71uint8_t
72ddi_mem_get8(ddi_acc_handle_t handle, uint8_t *addr)
73{
74	return (0);
75}
76
77/*ARGSUSED*/
78uint8_t
79ddi_io_get8(ddi_acc_handle_t handle, uint8_t *dev_addr)
80{
81	return (0);
82}
83
84/*ARGSUSED*/
85uint16_t
86ddi_get16(ddi_acc_handle_t handle, uint16_t *addr)
87{
88	return (0);
89}
90
91/*ARGSUSED*/
92uint16_t
93ddi_mem_get16(ddi_acc_handle_t handle, uint16_t *addr)
94{
95	return (0);
96}
97
98/*ARGSUSED*/
99uint16_t
100ddi_io_get16(ddi_acc_handle_t handle, uint16_t *dev_addr)
101{
102	return (0);
103}
104
105/*ARGSUSED*/
106uint32_t
107ddi_get32(ddi_acc_handle_t handle, uint32_t *addr)
108{
109	return (0);
110}
111
112/*ARGSUSED*/
113uint32_t
114ddi_mem_get32(ddi_acc_handle_t handle, uint32_t *addr)
115{
116	return (0);
117}
118
119/*ARGSUSED*/
120uint32_t
121ddi_io_get32(ddi_acc_handle_t handle, uint32_t *dev_addr)
122{
123	return (0);
124}
125
126/*ARGSUSED*/
127uint64_t
128ddi_get64(ddi_acc_handle_t handle, uint64_t *addr)
129{
130	return (0);
131}
132
133/*ARGSUSED*/
134uint64_t
135ddi_mem_get64(ddi_acc_handle_t handle, uint64_t *addr)
136{
137	return (0);
138}
139
140/*ARGSUSED*/
141void
142ddi_put8(ddi_acc_handle_t handle, uint8_t *addr, uint8_t value) {}
143
144/*ARGSUSED*/
145void
146ddi_mem_put8(ddi_acc_handle_t handle, uint8_t *dev_addr, uint8_t value) {}
147
148/*ARGSUSED*/
149void
150ddi_io_put8(ddi_acc_handle_t handle, uint8_t *dev_addr, uint8_t value) {}
151
152/*ARGSUSED*/
153void
154ddi_put16(ddi_acc_handle_t handle, uint16_t *addr, uint16_t value) {}
155
156/*ARGSUSED*/
157void
158ddi_mem_put16(ddi_acc_handle_t handle, uint16_t *dev_addr, uint16_t value) {}
159
160/*ARGSUSED*/
161void
162ddi_io_put16(ddi_acc_handle_t handle, uint16_t *dev_addr, uint16_t value) {}
163
164/*ARGSUSED*/
165void
166ddi_put32(ddi_acc_handle_t handle, uint32_t *addr, uint32_t value) {}
167
168/*ARGSUSED*/
169void
170ddi_mem_put32(ddi_acc_handle_t handle, uint32_t *dev_addr, uint32_t value) {}
171
172/*ARGSUSED*/
173void
174ddi_io_put32(ddi_acc_handle_t handle, uint32_t *dev_addr, uint32_t value) {}
175
176/*ARGSUSED*/
177void
178ddi_put64(ddi_acc_handle_t handle, uint64_t *addr, uint64_t value) {}
179
180/*ARGSUSED*/
181void
182ddi_mem_put64(ddi_acc_handle_t handle, uint64_t *dev_addr, uint64_t value) {}
183
184/*ARGSUSED*/
185void
186ddi_rep_get8(ddi_acc_handle_t handle, uint8_t *host_addr, uint8_t *dev_addr,
187        size_t repcount, uint_t flags)
188{
189}
190
191/*ARGSUSED*/
192void
193ddi_rep_get16(ddi_acc_handle_t handle, uint16_t *host_addr, uint16_t *dev_addr,
194        size_t repcount, uint_t flags)
195{
196}
197
198/*ARGSUSED*/
199void
200ddi_rep_get32(ddi_acc_handle_t handle, uint32_t *host_addr, uint32_t *dev_addr,
201        size_t repcount, uint_t flags)
202{
203}
204
205/*ARGSUSED*/
206void
207ddi_rep_get64(ddi_acc_handle_t handle, uint64_t *host_addr, uint64_t *dev_addr,
208        size_t repcount, uint_t flags)
209{
210}
211
212/*ARGSUSED*/
213void
214ddi_rep_put8(ddi_acc_handle_t handle, uint8_t *host_addr, uint8_t *dev_addr,
215        size_t repcount, uint_t flags)
216{
217}
218
219/*ARGSUSED*/
220void
221ddi_rep_put16(ddi_acc_handle_t handle, uint16_t *host_addr, uint16_t *dev_addr,
222        size_t repcount, uint_t flags)
223{
224}
225
226/*ARGSUSED*/
227void
228ddi_rep_put32(ddi_acc_handle_t handle, uint32_t *host_addr, uint32_t *dev_addr,
229        size_t repcount, uint_t flags)
230{
231}
232
233/*ARGSUSED*/
234void
235ddi_rep_put64(ddi_acc_handle_t handle, uint64_t *host_addr, uint64_t *dev_addr,
236        size_t repcount, uint_t flags)
237{
238}
239
240/*ARGSUSED*/
241void
242ddi_mem_rep_get8(ddi_acc_handle_t handle, uint8_t *host_addr,
243        uint8_t *dev_addr, size_t repcount, uint_t flags)
244{
245}
246
247/*ARGSUSED*/
248void
249ddi_mem_rep_get16(ddi_acc_handle_t handle, uint16_t *host_addr,
250        uint16_t *dev_addr, size_t repcount, uint_t flags)
251{
252}
253
254/*ARGSUSED*/
255void
256ddi_mem_rep_get32(ddi_acc_handle_t handle, uint32_t *host_addr,
257        uint32_t *dev_addr, size_t repcount, uint_t flags)
258{
259}
260
261/*ARGSUSED*/
262void
263ddi_mem_rep_get64(ddi_acc_handle_t handle, uint64_t *host_addr,
264        uint64_t *dev_addr, size_t repcount, uint_t flags)
265{
266}
267
268/*ARGSUSED*/
269void
270ddi_mem_rep_put8(ddi_acc_handle_t handle, uint8_t *host_addr,
271        uint8_t *dev_addr, size_t repcount, uint_t flags)
272{
273}
274
275/*ARGSUSED*/
276void
277ddi_mem_rep_put16(ddi_acc_handle_t handle, uint16_t *host_addr,
278        uint16_t *dev_addr, size_t repcount, uint_t flags)
279{
280}
281
282/*ARGSUSED*/
283void
284ddi_mem_rep_put32(ddi_acc_handle_t handle, uint32_t *host_addr,
285        uint32_t *dev_addr, size_t repcount, uint_t flags)
286{
287}
288
289/*ARGSUSED*/
290void
291ddi_mem_rep_put64(ddi_acc_handle_t handle, uint64_t *host_addr,
292        uint64_t *dev_addr, size_t repcount, uint_t flags)
293{
294}
295
296/*ARGSUSED*/
297void
298ddi_io_rep_get8(ddi_acc_handle_t handle,
299	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) {}
300
301/*ARGSUSED*/
302void
303ddi_io_rep_get16(ddi_acc_handle_t handle,
304	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) {}
305
306/*ARGSUSED*/
307void
308ddi_io_rep_get32(ddi_acc_handle_t handle,
309	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) {}
310
311/*ARGSUSED*/
312void
313ddi_io_rep_put8(ddi_acc_handle_t handle,
314	uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) {}
315
316/*ARGSUSED*/
317void
318ddi_io_rep_put16(ddi_acc_handle_t handle,
319	uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) {}
320
321
322/*ARGSUSED*/
323void
324ddi_io_rep_put32(ddi_acc_handle_t handle,
325	uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) {}
326
327/*ARGSUSED*/
328uint8_t
329i_ddi_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
330{
331	return (0);
332}
333
334/*ARGSUSED*/
335uint16_t
336i_ddi_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
337{
338	return (0);
339}
340
341/*ARGSUSED*/
342uint32_t
343i_ddi_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
344{
345	return (0);
346}
347
348/*ARGSUSED*/
349uint64_t
350i_ddi_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
351{
352	return (0);
353}
354
355/*ARGSUSED*/
356void
357i_ddi_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) {}
358
359/*ARGSUSED*/
360void
361i_ddi_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) {}
362
363/*ARGSUSED*/
364void
365i_ddi_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
366
367/*ARGSUSED*/
368void
369i_ddi_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
370
371/*ARGSUSED*/
372void
373i_ddi_rep_get8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, uint8_t *dev_addr,
374        size_t repcount, uint_t flags)
375{
376}
377
378/*ARGSUSED*/
379void
380i_ddi_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
381	uint16_t *dev_addr, size_t repcount, uint_t flags)
382{
383}
384
385/*ARGSUSED*/
386void
387i_ddi_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
388	uint32_t *dev_addr, size_t repcount, uint_t flags)
389{
390}
391
392/*ARGSUSED*/
393void
394i_ddi_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
395	uint64_t *dev_addr, size_t repcount, uint_t flags)
396{
397}
398
399/*ARGSUSED*/
400void
401i_ddi_rep_put8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, uint8_t *dev_addr,
402        size_t repcount, uint_t flags)
403{
404}
405
406/*ARGSUSED*/
407void
408i_ddi_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
409	uint16_t *dev_addr, size_t repcount, uint_t flags)
410{
411}
412
413/*ARGSUSED*/
414void
415i_ddi_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
416	uint32_t *dev_addr, size_t repcount, uint_t flags)
417{
418}
419
420/*ARGSUSED*/
421void
422i_ddi_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
423	uint64_t *dev_addr, size_t repcount, uint_t flags)
424{
425}
426
427/*ARGSUSED*/
428uint8_t
429i_ddi_prot_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
430{
431	return (0);
432}
433
434/*ARGSUSED*/
435uint16_t
436i_ddi_prot_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
437{
438	return (0);
439}
440
441/*ARGSUSED*/
442uint32_t
443i_ddi_prot_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
444{
445	return (0);
446}
447
448/*ARGSUSED*/
449uint64_t
450i_ddi_prot_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
451{
452	return (0);
453}
454
455/*ARGSUSED*/
456void
457i_ddi_prot_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) {}
458
459/*ARGSUSED*/
460void
461i_ddi_prot_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) {}
462
463/*ARGSUSED*/
464void
465i_ddi_prot_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
466
467/*ARGSUSED*/
468void
469i_ddi_prot_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
470
471/*ARGSUSED*/
472void
473i_ddi_prot_rep_get8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, uint8_t *dev_addr,
474        size_t repcount, uint_t flags)
475{
476}
477
478/*ARGSUSED*/
479void
480i_ddi_prot_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
481	uint16_t *dev_addr, size_t repcount, uint_t flags)
482{
483}
484
485/*ARGSUSED*/
486void
487i_ddi_prot_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
488	uint32_t *dev_addr, size_t repcount, uint_t flags)
489{
490}
491
492/*ARGSUSED*/
493void
494i_ddi_prot_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
495	uint64_t *dev_addr, size_t repcount, uint_t flags)
496{
497}
498
499/*ARGSUSED*/
500void
501i_ddi_prot_rep_put8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, uint8_t *dev_addr,
502        size_t repcount, uint_t flags)
503{
504}
505
506/*ARGSUSED*/
507void
508i_ddi_prot_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
509	uint16_t *dev_addr, size_t repcount, uint_t flags)
510{
511}
512
513/*ARGSUSED*/
514void
515i_ddi_prot_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
516	uint32_t *dev_addr, size_t repcount, uint_t flags)
517{
518}
519
520/*ARGSUSED*/
521void
522i_ddi_prot_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
523	uint64_t *dev_addr, size_t repcount, uint_t flags)
524{
525}
526
527/*ARGSUSED*/
528int
529i_ddi_ontrap(ddi_acc_handle_t handle)
530{
531	return (0);
532}
533
534/*ARGSUSED*/
535void
536i_ddi_notrap(ddi_acc_handle_t handle)
537{
538}
539
540/*ARGSUSED*/
541void
542i_ddi_caut_get(size_t getsz, void *addr, void *value)
543{
544}
545
546#else
547
548/*
549 * The functionality of each of the ddi_get/put routines is performed by
550 * the respective indirect function defined in the access handle.  Use of
551 * the access handle functions provides compatibility across platforms for
552 * drivers.
553 *
554 * By default, the indirect access handle functions are initialized to the
555 * i_ddi_get/put routines to perform memory mapped IO.  If memory mapped IO
556 * is not possible or desired, the access handle must be intialized to another
557 * valid routine to perform the sepcified IO operation.
558 *
559 * The alignment and placement of the following functions have been optimized
560 * such that the implementation specific versions, i_ddi*, fall within the
561 * same cache-line of the generic versions, ddi_*.  This insures that an
562 * I-cache hit will occur thus minimizing the performance impact of using the
563 * access handle.
564 */
565
566	.align 32
567	ENTRY(ddi_get8)
568	ALTENTRY(ddi_getb)
569	ALTENTRY(ddi_io_get8)
570	ALTENTRY(ddi_io_getb)
571	ALTENTRY(ddi_mem_get8)
572	ALTENTRY(ddi_mem_getb)
573	ldn      [%o0 + AHI_GET8], %g1   /* hdl->ahi_get8 access hndl */
574	jmpl    %g1, %g0                 /* jump to access handle routine */
575	nop
576	SET_SIZE(ddi_get8)
577	SET_SIZE(ddi_getb)
578	SET_SIZE(ddi_io_get8)
579	SET_SIZE(ddi_io_getb)
580	SET_SIZE(ddi_mem_get8)
581	SET_SIZE(ddi_mem_getb)
582
583	.align 16
584	ENTRY(i_ddi_get8)
585	retl
586	ldub	[%o1], %o0
587	SET_SIZE(i_ddi_get8)
588
589	.align 32
590	ENTRY(ddi_get16)
591	ALTENTRY(ddi_getw)
592	ALTENTRY(ddi_io_get16)
593	ALTENTRY(ddi_io_getw)
594	ALTENTRY(ddi_mem_get16)
595	ALTENTRY(ddi_mem_getw)
596	ldn      [%o0 + AHI_GET16], %g1   /* hdl->ahi_get16 access hndl */
597	jmpl    %g1, %g0                  /* jump to access handle routine */
598	nop
599	SET_SIZE(ddi_get16)
600	SET_SIZE(ddi_getw)
601	SET_SIZE(ddi_io_get16)
602	SET_SIZE(ddi_io_getw)
603	SET_SIZE(ddi_mem_get16)
604	SET_SIZE(ddi_mem_getw)
605
606	.align 16
607	ENTRY(i_ddi_get16)
608	ALTENTRY(i_ddi_swap_get16)
609	retl
610	lduh	[%o1], %o0
611	SET_SIZE(i_ddi_get16)
612	SET_SIZE(i_ddi_swap_get16)
613
614	.align 32
615	ENTRY(ddi_get32)
616	ALTENTRY(ddi_getl)
617	ALTENTRY(ddi_io_get32)
618	ALTENTRY(ddi_io_getl)
619	ALTENTRY(ddi_mem_get32)
620	ALTENTRY(ddi_mem_getl)
621	ldn      [%o0 + AHI_GET32], %g1   /* hdl->ahi_get32 access handle */
622	jmpl    %g1, %g0		  /* jump to access handle routine */
623	nop
624	SET_SIZE(ddi_get32)
625	SET_SIZE(ddi_getl)
626	SET_SIZE(ddi_io_get32)
627	SET_SIZE(ddi_io_getl)
628	SET_SIZE(ddi_mem_get32)
629	SET_SIZE(ddi_mem_getl)
630
631	.align 16
632	ENTRY(i_ddi_get32)
633	ALTENTRY(i_ddi_swap_get32)
634	retl
635	ld	[%o1], %o0
636	SET_SIZE(i_ddi_get32)
637	SET_SIZE(i_ddi_swap_get32)
638
639	.align 32
640	ENTRY(ddi_get64)
641	ALTENTRY(ddi_getll)
642	ALTENTRY(ddi_io_get64)
643	ALTENTRY(ddi_io_getll)
644	ALTENTRY(ddi_mem_get64)
645	ALTENTRY(ddi_mem_getll)
646	ldn      [%o0 + AHI_GET64], %g1   /* hdl->ahi_get64 access handle */
647	jmpl    %g1, %g0                  /* jump to access handle routine */
648	nop
649	SET_SIZE(ddi_get64)
650	SET_SIZE(ddi_getll)
651	SET_SIZE(ddi_io_get64)
652	SET_SIZE(ddi_io_getll)
653	SET_SIZE(ddi_mem_get64)
654	SET_SIZE(ddi_mem_getll)
655
656	.align 16
657	ENTRY(i_ddi_get64)
658	ALTENTRY(i_ddi_swap_get64)
659	retl
660	ldx	[%o1], %o0
661	SET_SIZE(i_ddi_get64)
662	SET_SIZE(i_ddi_swap_get64)
663
664	.align 32
665	ENTRY(ddi_put8)
666	ALTENTRY(ddi_putb)
667	ALTENTRY(ddi_io_put8)
668	ALTENTRY(ddi_io_putb)
669	ALTENTRY(ddi_mem_put8)
670	ALTENTRY(ddi_mem_putb)
671	ldn      [%o0 + AHI_PUT8], %g1   /* hdl->ahi_put8 access handle */
672	jmpl    %g1, %g0                 /* jump to access handle routine */
673	nop
674	SET_SIZE(ddi_put8)
675	SET_SIZE(ddi_putb)
676	SET_SIZE(ddi_io_put8)
677	SET_SIZE(ddi_io_putb)
678	SET_SIZE(ddi_mem_put8)
679	SET_SIZE(ddi_mem_putb)
680
681	.align 16
682	ENTRY(i_ddi_put8)
683	retl
684	stub	%o2, [%o1]
685	SET_SIZE(i_ddi_put8)
686
687	.align 32
688	ENTRY(ddi_put16)
689	ALTENTRY(ddi_putw)
690	ALTENTRY(ddi_io_put16)
691	ALTENTRY(ddi_io_putw)
692	ALTENTRY(ddi_mem_put16)
693	ALTENTRY(ddi_mem_putw)
694	ldn      [%o0 + AHI_PUT16], %g1   /* hdl->ahi_put16 access handle */
695	jmpl    %g1, %g0                  /* jump to access handle routine */
696	nop
697	SET_SIZE(ddi_put16)
698	SET_SIZE(ddi_putw)
699	SET_SIZE(ddi_io_put16)
700	SET_SIZE(ddi_io_putw)
701	SET_SIZE(ddi_mem_put16)
702	SET_SIZE(ddi_mem_putw)
703
704	.align 16
705	ENTRY(i_ddi_put16)
706	ALTENTRY(i_ddi_swap_put16)
707	retl
708	stuh	%o2, [%o1]
709	SET_SIZE(i_ddi_put16)
710	SET_SIZE(i_ddi_swap_put16)
711
712	.align 32
713	ENTRY(ddi_put32)
714	ALTENTRY(ddi_putl)
715	ALTENTRY(ddi_io_put32)
716	ALTENTRY(ddi_io_putl)
717	ALTENTRY(ddi_mem_put32)
718	ALTENTRY(ddi_mem_putl)
719	ldn      [%o0 + AHI_PUT32], %g1   /* hdl->ahi_put16 access handle */
720	jmpl    %g1, %g0                  /* jump to access handle routine */
721	nop
722	SET_SIZE(ddi_put32)
723	SET_SIZE(ddi_putl)
724	SET_SIZE(ddi_io_put32)
725	SET_SIZE(ddi_io_putl)
726	SET_SIZE(ddi_mem_put32)
727	SET_SIZE(ddi_mem_putl)
728
729	.align 16
730	ENTRY(i_ddi_put32)
731	ALTENTRY(i_ddi_swap_put32)
732	retl
733	st	%o2, [%o1]
734	SET_SIZE(i_ddi_put32)
735	SET_SIZE(i_ddi_swap_put32)
736
737	.align 32
738	ENTRY(ddi_put64)
739	ALTENTRY(ddi_putll)
740	ALTENTRY(ddi_io_put64)
741	ALTENTRY(ddi_io_putll)
742	ALTENTRY(ddi_mem_put64)
743	ALTENTRY(ddi_mem_putll)
744	ldn      [%o0 + AHI_PUT64], %g1   /* hdl->ahi_put64 access handle */
745	jmpl    %g1, %g0                  /* jump to access handle routine */
746	nop
747	SET_SIZE(ddi_put64)
748	SET_SIZE(ddi_putll)
749	SET_SIZE(ddi_io_put64)
750	SET_SIZE(ddi_io_putll)
751	SET_SIZE(ddi_mem_put64)
752	SET_SIZE(ddi_mem_putll)
753
754	.align 16
755	ENTRY(i_ddi_put64)
756	ALTENTRY(i_ddi_swap_put64)
757	retl
758	stx	%o2, [%o1]
759	SET_SIZE(i_ddi_put64)
760	SET_SIZE(i_ddi_swap_put64)
761
762/*
763 * The ddi_io_rep_get/put routines don't take a flag argument like the "plain"
764 * and mem versions do.  This flag is used to determine whether or not the
765 * device address or port should be automatically incremented.  For IO space,
766 * the device port is never incremented and as such, the flag is always set
767 * to DDI_DEV_NO_AUTOINCR.
768 *
769 * This define processes the repetitive get functionality.  Automatic
770 * incrementing of the device address is determined by the flag field
771 * %o4.  If this is set for AUTOINCR, %o4 is updated with 1 for the
772 * subsequent increment in 2:.
773 *
774 * If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus
775 * making the increment operation a non-operation.
776 */
777
778#define DDI_REP_GET(n,s)			\
779	cmp	DDI_DEV_NO_AUTOINCR, %o4;	\
780	mov	%g0, %o4;			\
781	brz,pn	%o3, 1f;			\
782	movnz	%xcc, n, %o4;			\
7832:						\
784	dec	%o3;				\
785	ld/**/s	[%o2], %g4;			\
786	add	%o2, %o4, %o2;			\
787	st/**/s	%g4, [%o1];			\
788	brnz,pt	%o3, 2b;			\
789	add	%o1, n, %o1;			\
7901:
791
792	.align 32
793	ENTRY(ddi_rep_get8)
794	ALTENTRY(ddi_rep_getb)
795	ALTENTRY(ddi_mem_rep_get8)
796	ALTENTRY(ddi_mem_rep_getb)
797	ldn      [%o0 + AHI_REP_GET8], %g1
798	jmpl    %g1, %g0
799	nop
800	SET_SIZE(ddi_rep_get8)
801	SET_SIZE(ddi_rep_getb)
802	SET_SIZE(ddi_mem_rep_get8)
803	SET_SIZE(ddi_mem_rep_getb)
804
805	.align 16
806	ENTRY(i_ddi_rep_get8)
807	DDI_REP_GET(1,ub)
808	retl
809	nop
810	SET_SIZE(i_ddi_rep_get8)
811
812	.align 32
813	ENTRY(ddi_rep_get16)
814	ALTENTRY(ddi_rep_getw)
815	ALTENTRY(ddi_mem_rep_get16)
816	ALTENTRY(ddi_mem_rep_getw)
817	ldn	[%o0 + AHI_REP_GET16], %g1
818	jmpl    %g1, %g0
819	nop
820	SET_SIZE(ddi_rep_get16)
821	SET_SIZE(ddi_rep_getw)
822	SET_SIZE(ddi_mem_rep_get16)
823	SET_SIZE(ddi_mem_rep_getw)
824
825	.align 16
826	ENTRY(i_ddi_rep_get16)
827	ALTENTRY(i_ddi_swap_rep_get16)
828	DDI_REP_GET(2,uh)
829	retl
830	nop
831	SET_SIZE(i_ddi_rep_get16)
832	SET_SIZE(i_ddi_swap_rep_get16)
833
834	.align 32
835	ENTRY(ddi_rep_get32)
836	ALTENTRY(ddi_rep_getl)
837	ALTENTRY(ddi_mem_rep_get32)
838	ALTENTRY(ddi_mem_rep_getl)
839	ldn      [%o0 + AHI_REP_GET32], %g1
840	jmpl    %g1, %g0
841	nop
842	SET_SIZE(ddi_rep_get32)
843	SET_SIZE(ddi_rep_getl)
844	SET_SIZE(ddi_mem_rep_get32)
845	SET_SIZE(ddi_mem_rep_getl)
846
847	.align 16
848	ENTRY(i_ddi_rep_get32)
849	ALTENTRY(i_ddi_swap_rep_get32)
850	DDI_REP_GET(4,/**/)
851	retl
852	nop
853	SET_SIZE(i_ddi_rep_get32)
854	SET_SIZE(i_ddi_swap_rep_get32)
855
856	.align 32
857	ENTRY(ddi_rep_get64)
858	ALTENTRY(ddi_rep_getll)
859	ALTENTRY(ddi_mem_rep_get64)
860	ALTENTRY(ddi_mem_rep_getll)
861	ldn      [%o0 + AHI_REP_GET64], %g1
862	jmpl    %g1, %g0
863	nop
864	SET_SIZE(ddi_rep_get64)
865	SET_SIZE(ddi_rep_getll)
866	SET_SIZE(ddi_mem_rep_get64)
867	SET_SIZE(ddi_mem_rep_getll)
868
869	.align 16
870	ENTRY(i_ddi_rep_get64)
871	ALTENTRY(i_ddi_swap_rep_get64)
872	DDI_REP_GET(8,x)
873	retl
874	nop
875	SET_SIZE(i_ddi_rep_get64)
876	SET_SIZE(i_ddi_swap_rep_get64)
877
878/*
879 * This define processes the repetitive put functionality.  Automatic
880 * incrementing of the device address is determined by the flag field
881 * %o4.  If this is set for AUTOINCR, %o4 is updated with 1 for the
882 * subsequent increment in 2:.
883 *
884 * If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus
885 * making the increment operation a non-operation.
886 */
887#define DDI_REP_PUT(n,s)			\
888	cmp	DDI_DEV_NO_AUTOINCR, %o4;	\
889	mov	%g0, %o4;			\
890	brz,pn	%o3, 1f;			\
891	movnz	%xcc, n, %o4;			\
8922:						\
893	dec	%o3;				\
894	ld/**/s	[%o1], %g4;			\
895	add	%o1, n, %o1;			\
896	st/**/s	%g4, [%o2];			\
897	brnz,pt	%o3, 2b;			\
898	add	%o2, %o4, %o2;			\
8991:
900
901	.align 32
902	ENTRY(ddi_rep_put8)
903	ALTENTRY(ddi_rep_putb)
904	ALTENTRY(ddi_mem_rep_put8)
905	ALTENTRY(ddi_mem_rep_putb)
906	ldn      [%o0 + AHI_REP_PUT8], %g1
907	jmpl    %g1, %g0
908	nop
909	SET_SIZE(ddi_rep_put8)
910	SET_SIZE(ddi_rep_putb)
911	SET_SIZE(ddi_mem_rep_put8)
912	SET_SIZE(ddi_mem_rep_putb)
913
914	.align 16
915	ENTRY(i_ddi_rep_put8)
916	DDI_REP_PUT(1,ub)
917	retl
918	nop
919	SET_SIZE(i_ddi_rep_put8)
920
921	.align 32
922	ENTRY(ddi_rep_put16)
923	ALTENTRY(ddi_rep_putw)
924	ALTENTRY(ddi_mem_rep_put16)
925	ALTENTRY(ddi_mem_rep_putw)
926	ldn      [%o0 + AHI_REP_PUT16], %g1
927	jmpl    %g1, %g0
928	nop
929	SET_SIZE(ddi_rep_put16)
930	SET_SIZE(ddi_rep_putw)
931	SET_SIZE(ddi_mem_rep_put16)
932	SET_SIZE(ddi_mem_rep_putw)
933
934	.align 16
935	ENTRY(i_ddi_rep_put16)
936	ALTENTRY(i_ddi_swap_rep_put16)
937	DDI_REP_PUT(2,uh)
938	retl
939	nop
940	SET_SIZE(i_ddi_rep_put16)
941	SET_SIZE(i_ddi_swap_rep_put16)
942
943	.align 32
944	ENTRY(ddi_rep_put32)
945	ALTENTRY(ddi_rep_putl)
946	ALTENTRY(ddi_mem_rep_put32)
947	ALTENTRY(ddi_mem_rep_putl)
948	ldn      [%o0 + AHI_REP_PUT32], %g1
949	jmpl    %g1, %g0
950	nop
951	SET_SIZE(ddi_rep_put32)
952	SET_SIZE(ddi_rep_putl)
953	SET_SIZE(ddi_mem_rep_put32)
954	SET_SIZE(ddi_mem_rep_putl)
955
956	.align 16
957	ENTRY(i_ddi_rep_put32)
958	ALTENTRY(i_ddi_swap_rep_put32)
959	DDI_REP_PUT(4,/**/)
960	retl
961	nop
962	SET_SIZE(i_ddi_rep_put32)
963	SET_SIZE(i_ddi_swap_rep_put32)
964
965	.align 32
966	ENTRY(ddi_rep_put64)
967	ALTENTRY(ddi_rep_putll)
968	ALTENTRY(ddi_mem_rep_put64)
969	ALTENTRY(ddi_mem_rep_putll)
970	ldn      [%o0 + AHI_REP_PUT64], %g1
971	jmpl    %g1, %g0
972	nop
973	SET_SIZE(ddi_rep_put64)
974	SET_SIZE(ddi_rep_putll)
975	SET_SIZE(ddi_mem_rep_put64)
976	SET_SIZE(ddi_mem_rep_putll)
977
978	.align 16
979	ENTRY(i_ddi_rep_put64)
980	ALTENTRY(i_ddi_swap_rep_put64)
981	DDI_REP_PUT(8,x)
982	retl
983	nop
984	SET_SIZE(i_ddi_rep_put64)
985	SET_SIZE(i_ddi_swap_rep_put64)
986
987	.align 16
988	ENTRY(ddi_io_rep_get8)
989	ALTENTRY(ddi_io_rep_getb)
990	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
991	ldn	[%o0 + AHI_REP_GET8], %g1
992	jmpl    %g1, %g0
993	nop
994	SET_SIZE(ddi_io_rep_get8)
995	SET_SIZE(ddi_io_rep_getb)
996
997	.align 16
998	ENTRY(ddi_io_rep_get16)
999	ALTENTRY(ddi_io_rep_getw)
1000	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1001	ldn	[%o0 + AHI_REP_GET16], %g1
1002	jmpl    %g1, %g0
1003	nop
1004	SET_SIZE(ddi_io_rep_get16)
1005	SET_SIZE(ddi_io_rep_getw)
1006
1007	.align 16
1008	ENTRY(ddi_io_rep_get32)
1009	ALTENTRY(ddi_io_rep_getl)
1010	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1011	ldn	[%o0 + AHI_REP_GET32], %g1
1012	jmpl    %g1, %g0
1013	nop
1014	SET_SIZE(ddi_io_rep_get32)
1015	SET_SIZE(ddi_io_rep_getl)
1016
1017	.align 16
1018	ENTRY(ddi_io_rep_get64)
1019	ALTENTRY(ddi_io_rep_getll)
1020	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1021	ldn	[%o0 + AHI_REP_GET64], %g1
1022	jmpl    %g1, %g0
1023	nop
1024	SET_SIZE(ddi_io_rep_get64)
1025	SET_SIZE(ddi_io_rep_getll)
1026
1027        .align 64
1028	ENTRY(ddi_check_acc_handle)
1029	save	%sp, -SA(WINDOWSIZE), %sp	! get a new window
1030	ldn	[%i0 + AHI_FAULT_CHECK], %g1
1031	jmpl	%g1, %o7
1032	mov	%i0, %o0
1033	brnz,a,pn %o0, 0f			! if (return_value != 0)
1034	mov	-1, %o0				! 	return (DDI_FAILURE)
10350:						! else	return (DDI_SUCCESS)
1036	sra	%o0, 0, %i0
1037	ret
1038	restore
1039	SET_SIZE(ddi_check_acc_handle)
1040
1041        .align 16
1042        ENTRY(i_ddi_acc_fault_check)
1043	retl
1044	ld      [%o0 + AHI_FAULT], %o0
1045        SET_SIZE(i_ddi_acc_fault_check)
1046
1047	.align 16
1048	ENTRY(ddi_io_rep_put8)
1049	ALTENTRY(ddi_io_rep_putb)
1050	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1051	ldn	[%o0 + AHI_REP_PUT8], %g1
1052	jmpl    %g1, %g0
1053	nop
1054	SET_SIZE(ddi_io_rep_put8)
1055	SET_SIZE(ddi_io_rep_putb)
1056
1057	.align 16
1058	ENTRY(ddi_io_rep_put16)
1059	ALTENTRY(ddi_io_rep_putw)
1060	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1061	ldn	[%o0 + AHI_REP_PUT16], %g1
1062	jmpl    %g1, %g0
1063	nop
1064	SET_SIZE(ddi_io_rep_put16)
1065	SET_SIZE(ddi_io_rep_putw)
1066
1067	.align 16
1068	ENTRY(ddi_io_rep_put32)
1069	ALTENTRY(ddi_io_rep_putl)
1070	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1071	ldn	[%o0 + AHI_REP_PUT32], %g1
1072	jmpl    %g1, %g0
1073	nop
1074	SET_SIZE(ddi_io_rep_put32)
1075	SET_SIZE(ddi_io_rep_putl)
1076
1077	.align 16
1078	ENTRY(ddi_io_rep_put64)
1079	ALTENTRY(ddi_io_rep_putll)
1080	set	DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */
1081	ldn	[%o0 + AHI_REP_PUT64], %g1
1082	jmpl    %g1, %g0
1083	nop
1084	SET_SIZE(ddi_io_rep_put64)
1085	SET_SIZE(ddi_io_rep_putll)
1086
1087	ENTRY(do_peek)
1088	rdpr	%pstate, %o3	! check ints
1089	andcc	%o3, PSTATE_IE, %g0
1090	bz,a	done
1091	or	%g0, 1, %o0	! Return failure if ints are disabled
1092	wrpr	%o3, PSTATE_IE, %pstate
1093	cmp	%o0, 8		! 64-bit?
1094	bne,a	.peek_int
1095	cmp	%o0, 4		! 32-bit?
1096	ldx	[%o1], %g1
1097	ba	.peekdone
1098	stx	%g1, [%o2]
1099.peek_int:
1100	bne,a	.peek_half
1101	cmp	%o0, 2		! 16-bit?
1102	lduw	[%o1], %g1
1103	ba	.peekdone
1104	stuw	%g1, [%o2]
1105.peek_half:
1106	bne,a	.peek_byte
1107	ldub	[%o1], %g1	! 8-bit!
1108	lduh	[%o1], %g1
1109	ba	.peekdone
1110	stuh	%g1, [%o2]
1111.peek_byte:
1112	stub	%g1, [%o2]
1113.peekdone:
1114	membar	#Sync		! Make sure the loads take
1115	rdpr	%pstate, %o3	! check&enable ints
1116	andcc	%o3, PSTATE_IE, %g0
1117	bnz	1f
1118	nop
1119	wrpr	%o3, PSTATE_IE, %pstate
11201:
1121	mov	%g0, %o0
1122done:
1123	retl
1124	nop
1125	SET_SIZE(do_peek)
1126
1127	ENTRY(do_poke)
1128	cmp	%o0, 8		! 64 bit?
1129	bne,a	.poke_int
1130	cmp	%o0, 4		! 32-bit?
1131	ldx	[%o2], %g1
1132	ba	.pokedone
1133	stx	%g1, [%o1]
1134.poke_int:
1135	bne,a	.poke_half
1136	cmp	%o0, 2		! 16-bit?
1137	lduw	[%o2], %g1
1138	ba	.pokedone
1139	stuw	%g1, [%o1]
1140.poke_half:
1141	bne,a	.poke_byte
1142	ldub	[%o2], %g1	! 8-bit!
1143	lduh	[%o2], %g1
1144	ba	.pokedone
1145	stuh	%g1, [%o1]
1146.poke_byte:
1147	stub	%g1, [%o1]
1148.pokedone:
1149	membar	#Sync
1150	retl
1151	mov	%g0, %o0
1152	SET_SIZE(do_poke)
1153
1154
1155/*
1156 * The peek_fault() and poke_fault() routines below are used as on_trap()
1157 * trampoline routines.  i_ddi_peek and i_ddi_poke execute do_peek and do_poke
1158 * under on_trap protection (see <sys/ontrap.h>), but modify ot_trampoline to
1159 * refer to the corresponding routine below.  If a trap occurs, the trap code
1160 * will bounce back to the trampoline code, which will effectively cause
1161 * do_peek or do_poke to return DDI_FAILURE, instead of longjmp'ing back to
1162 * on_trap.  In the case of a peek, we may also need to re-enable interrupts.
1163 */
1164	.seg	".data"
1165.peek_panic:
1166	.asciz	"peek_fault: missing or invalid on_trap_data"
1167.poke_panic:
1168	.asciz	"poke_fault: missing or invalid on_trap_data"
1169
1170	ENTRY(peek_fault)
1171	ldn	[THREAD_REG + T_ONTRAP], %o0	! %o0 = on_trap_data pointer
1172	brz,pn	%o0, .peekfail			! if (%o0 == NULL) panic
1173	nop
1174	lduh	[%o0 + OT_PROT], %o1		! %o1 = %o0->ot_prot
1175	andcc	%o1, OT_DATA_ACCESS, %g0	! if (!(%o1 & OT_DATA_ACCESS))
1176	bz,pn	%icc, .peekfail			!     panic
1177	rdpr	%pstate, %o3
1178
1179	andcc	%o3, PSTATE_IE, %g0		! enable interrupts
1180	bnz	1f
1181	nop
1182	wrpr	%o3, PSTATE_IE, %pstate
11831:
1184	retl
1185	sub	%g0, 1, %o0			! return (DDI_FAILURE);
1186.peekfail:
1187	set	.peek_panic, %o0		! Load panic message
1188	call	panic				! Panic if bad t_ontrap data
1189	nop
1190	SET_SIZE(peek_fault)
1191
1192
1193	ENTRY(poke_fault)
1194	ldn	[THREAD_REG + T_ONTRAP], %o0	! %o0 = on_trap_data pointer
1195	brz,pn	%o0, .pokefail			! if (%o0 == NULL) panic
1196	nop
1197	lduh	[%o0 + OT_PROT], %o1		! %o1 = %o0->ot_prot
1198	andcc	%o1, OT_DATA_ACCESS, %g0	! if (!(%o1 & OT_DATA_ACCESS))
1199	bz,pn	%icc, .pokefail			!     panic
1200	nop
1201	retl
1202	sub	%g0, 1, %o0			! return (DDI_FAILURE);
1203.pokefail:
1204	set	.poke_panic, %o0		! Load panic message
1205	call	panic				! Panic if bad t_ontrap data
1206	nop
1207	SET_SIZE(poke_fault)
1208
1209
1210/*
1211 * IO Fault Services
1212 *
1213 * Support for protected IO accesses is implemented in the following
1214 * functions.  A driver may request one of three protection mechanisms
1215 * that enable the system to survive an access errors.  The protection
1216 * mechansim is set-up during ddi_regs_map_setup time and may be one of:
1217 *
1218 *	DDI_DEFAULT_ACC	- no error protection requested.  We will
1219 *			use the standard ddi_get/ddi_put operations
1220 *			defined above.
1221 *
1222 *	DDI_FLAGERR - Driver requests that errors encountered will
1223 *			be flagged by the system.  The driver is
1224 *			responsible for checking the error status
1225 *			of the access with a call to ddi_acc_err_get()
1226 *			upon return of ddi_get or ddi_put.  To prevent
1227 *			an access from causing a system we use internal
1228 *			on_trap semantics.
1229 *
1230 *			The system, depending upon the error,
1231 *			may or may not panic.
1232 *
1233 *	DDI_CAUTIOUS_ACC - Driver expects that the access may cause
1234 *			an error to occur.  The system will return
1235 *			an error status but will not generate an ereport.
1236 *			The system will also ensure synchronous and
1237 *			exclusive access to the IO space accessed by
1238 *			the caller.
1239 *
1240 *			To prevent an access from causing a system panic,
1241 *			we use on_trap semantics to catch the error and
1242 *			set error status.
1243 *
1244 *	If a read access error is detected and DDI_CAUTIOUS_ACC or
1245 *	DDI_FLAGERR_ACC	protection was requested, we will trampoline to the
1246 *	error handler, i_ddi_trampoline.  i_ddi_trampoline will:
1247 *		- check for proper protection semantics
1248 *		- set the error status of the access handle to DDI_FM_NONFATAL
1249 *		- re-enable interrupts if neccessary
1250 *		- longjmp back to the initiating access function.
1251
1252 *	If a write access error is detected, an interrupt is typically
1253 *	generated and claimed by a bus nexus responsible for the write
1254 *	transaction.  The nexus error handler is expected to set the
1255 *	error status and the IO initiating driver is expected to check
1256 *	for a failed transaction via ddi_fm_acc_err_get().
1257 *
1258 */
1259
1260	.seg	".data"
1261.acc_panic:
1262	.asciz	"DDI access: missing or invalid on_trap_data"
1263
1264	ENTRY(i_ddi_caut_trampoline)
1265	ldn	[THREAD_REG + T_ONTRAP], %o5    ! %o5 = curthread->t_ontrap
1266	lduh	[%o5 + OT_PROT], %o1		! %o1 = %o0->ot_prot
1267	andcc	%o1, OT_DATA_ACCESS, %g0	! if (!(%o1 & OT_DATA_ACCESS))
1268	bz,pn	%icc, .cautaccfail		!     panic
1269	rdpr	%pstate, %o3
1270	andcc	%o3, PSTATE_IE, %g0		! enable interrupts
1271	bnz	1f
1272	nop
1273	wrpr	%o3, PSTATE_IE, %pstate
12741:
1275	ldn	[%o5 + OT_HANDLE], %o0		! %o0 = ot_handle
1276	brz,pn	%o0, .cautaccfail		! if (ot_handle == NULL) panic
1277	nop
1278	ldn	[%o0 + AHI_ERR], %o4		! %o4 = hp->ahi_err
1279	membar	#Sync
1280	stx	%g0, [%o4 + ERR_ENA]		! ahi_err->err_ena = 0
1281	mov	-2, %o0
1282	st	%o0, [%o4 + ERR_STATUS]		! ahi_err->err_status = NONFATAL
1283	b	longjmp                		! longjmp back
1284	add	%o5, OT_JMPBUF, %o0		! %o0 = &ot_jmpbuf
1285.cautaccfail:
1286	set	.acc_panic, %o0			! Load panic message
1287	call	panic				! Panic if bad t_ontrap data
1288	nop
1289	SET_SIZE(i_ddi_caut_trampoline)
1290
1291/*
1292 * DDI on_trap set-up functions,  i_ddi_ontrap() and i_ddinotrap() are used
1293 * to protect * ddi_get accesses for DDI_CAUT_ACC.  i_ddi_ontrap() sets
1294 * the jumpbuf (setjmp) that will return back to the access routine from
1295 * i_ddi_trampoline().  DDI_NOPROTECT() clears the ontrap set-up.
1296 */
1297	ENTRY(i_ddi_ontrap)
1298	ldn	[%o0 + AHI_ERR], %o4
1299	ldn	[%o4 + ERR_ONTRAP],  %o4	! %o4 = hp->ahi_err->err_ontrap
1300	ldn	[THREAD_REG + T_ONTRAP], %o5	! %o5 = curthread->t_ontrap
1301	stn	%o5, [%o4 + OT_PREV]		! ot_prev = t_ontrap
1302	membar	#Sync				! force error barrier
1303	stn	%o4, [THREAD_REG + T_ONTRAP]	! t_ontrap = err_ontrap
1304	b	setjmp
1305	add	%o4, OT_JMPBUF, %o0
1306	SET_SIZE(i_ddi_ontrap)
1307
1308	ENTRY(i_ddi_notrap)
1309	membar	#Sync				! force error barrier
1310	ldn	[%o0 + AHI_ERR], %o4
1311	ldn	[%o4 + ERR_ONTRAP],  %o4	! %o4 = hp->ahi_err->err_ontrap
1312	ldn	[%o4 + OT_PREV], %o4
1313	retl
1314	stn	%o4, [THREAD_REG + T_ONTRAP]	! restore curthread->t_ontrap
1315	SET_SIZE(i_ddi_notrap)
1316
1317/*
1318 * Internal on_trap set-up macros.  DDI_PROTECT() and DDI_NOPROTECT() are used
1319 * to protect * ddi_get accesses for DDI_FLAGERR_ACC.  DDI_NOPROTECT() sets
1320 * the jumpbuf that will return back to the access routine from
1321 * i_ddi_protect_trampoline().  DDI_NOPROTECT() clears the ontrap set-up.
1322 */
1323	ENTRY(i_ddi_prot_trampoline)
1324	ldn	[THREAD_REG + T_ONTRAP], %o5    ! %o5 = curthread->t_ontrap
1325	lduh	[%o5 + OT_PROT], %o1		! %o1 = %o0->ot_prot
1326	andcc	%o1, OT_DATA_ACCESS, %g0	! if (!(%o1 & OT_DATA_ACCESS))
1327	bz,pn	%icc, .protaccfail		!     panic
1328	rdpr	%pstate, %o3
1329	andcc	%o3, PSTATE_IE, %g0		! enable interrupts
1330	bnz	1f
1331	nop
1332	wrpr	%o3, PSTATE_IE, %pstate
13331:
1334	ldn	[%o5 + OT_HANDLE], %o0		! %o0 = ot_handle
1335	brz,pn	%o0, .protaccfail		! if (ot_handle == NULL) panic
1336	nop
1337	ldn	[%o0 + AHI_ERR], %o4		! %o4 = hp->ahi_err
1338	stn	%g0, [%o4 + ERR_ENA]		! ahi_err->err_ena = 0
1339	mov	-2, %o0
1340	st	%o0, [%o4 + ERR_STATUS]		! ahi_err->err_status = NONFATAL
1341	ldn	[%o5 + OT_PREV], %o0		! restore ontrap
1342	membar	#Sync				! force error barrier
1343	stn	%o0, [THREAD_REG + T_ONTRAP];
1344	b	longjmp                		! longjmp back
1345	add	%o5, OT_JMPBUF, %o0		! %o0 = &ot_jmpbuf
1346.protaccfail:
1347	set	.acc_panic, %o0			! Load panic message
1348	call	panic				! Panic if bad t_ontrap data
1349	nop
1350	SET_SIZE(i_ddi_prot_trampoline)
1351
1352#define	DDI_PROTECT()				\
1353	ldn	[%o0 + AHI_ERR], %o4;		\
1354	ldn	[%o4 + ERR_ONTRAP],  %o4;	\
1355	ldn	[THREAD_REG + T_ONTRAP], %o5;	\
1356	stn	%o5, [%o4 + OT_PREV];		\
1357	membar	#Sync;				\
1358	stn	%o4, [THREAD_REG + T_ONTRAP];	\
1359	add     %o4, OT_JMPBUF, %o0;		\
1360	stn	%o7, [%o0 + L_PC];		\
1361	stn	%sp, [%o0 + L_SP];		\
1362	clr	%o0;
1363
1364#define	DDI_NOPROTECT()				\
1365	ldn	[THREAD_REG + T_ONTRAP], %o4;	\
1366	ldn	[%o4 + OT_PREV], %o5;		\
1367	membar	#Sync;				\
1368	stn	%o5, [THREAD_REG + T_ONTRAP];
1369
1370/*
1371 * DDI_FLAGERR_ACC specific get/put routines.
1372 */
1373	.align 16
1374	ENTRY(i_ddi_prot_get8)
1375	DDI_PROTECT()				! set ontrap protection
1376	ldub	[%o1], %o2			! do the io access
1377	DDI_NOPROTECT()				! remove protection & ret
1378	retl
1379	mov	%o2, %o0			! set return value
1380	SET_SIZE(i_ddi_prot_get8)
1381
1382	.align 16
1383	ENTRY(i_ddi_prot_get16)
1384	DDI_PROTECT()				! set ontrap protection
1385	lduh	[%o1], %o2			! do the io access
1386	DDI_NOPROTECT()				! remove protection & ret
1387	retl
1388	mov	%o2, %o0			! set return value
1389	SET_SIZE(i_ddi_prot_get16)
1390
1391	.align 16
1392	ENTRY(i_ddi_prot_get32)
1393	DDI_PROTECT()				! set ontrap protection
1394	ld	[%o1], %o2			! do the io access
1395	DDI_NOPROTECT()				! remove protection & ret
1396	retl
1397	mov	%o2, %o0			! set return value
1398	SET_SIZE(i_ddi_prot_get32)
1399
1400	.align 16
1401	ENTRY(i_ddi_prot_get64)
1402	DDI_PROTECT()				! set ontrap protection
1403	ldx	[%o1], %o2			! do the io access
1404	DDI_NOPROTECT()				! remove protection & ret
1405	retl
1406	mov	%o2, %o0			! set return value
1407	SET_SIZE(i_ddi_prot_get64)
1408
1409	.align 16
1410	ENTRY(i_ddi_prot_put8)
1411	stub	%o2, [%o1]			! do the io access
1412	retl
1413	membar	#Sync;
1414	SET_SIZE(i_ddi_prot_put8)
1415
1416	.align 16
1417	ENTRY(i_ddi_prot_put16)
1418	stuh	%o2, [%o1]			! do the io access
1419	retl
1420	membar	#Sync;
1421	SET_SIZE(i_ddi_prot_put16)
1422
1423	.align 16
1424	ENTRY(i_ddi_prot_put32)
1425	st	%o2, [%o1]			! do the io access
1426	retl
1427	membar	#Sync;
1428	SET_SIZE(i_ddi_prot_put32)
1429
1430	.align 16
1431	ENTRY(i_ddi_prot_put64)
1432	stx	%o2, [%o1]			! do the io access
1433	retl
1434	membar	#Sync;
1435	SET_SIZE(i_ddi_prot_put64)
1436
1437	.align 16
1438	ENTRY(i_ddi_prot_rep_get8)
1439	DDI_PROTECT()				! set ontrap protection
1440	tst	%o0				! check access error
1441	bnz,a	1f
1442	nop
1443	DDI_REP_GET(1,ub)
14441:
1445	DDI_NOPROTECT()				! remove protection & ret
1446	retl
1447	nop
1448	SET_SIZE(i_ddi_prot_rep_get8)
1449
1450	.align 16
1451	ENTRY(i_ddi_prot_rep_get16)
1452	DDI_PROTECT()				! set ontrap protection
1453	tst	%o0				! check access error
1454	bnz,a	1f
1455	nop
1456	DDI_REP_GET(2,uh)
14571:
1458	DDI_NOPROTECT()				! remove protection & ret
1459	retl
1460	nop
1461	SET_SIZE(i_ddi_prot_rep_get16)
1462
1463	.align 16
1464	ENTRY(i_ddi_prot_rep_get32)
1465	DDI_PROTECT()				! set ontrap protection
1466	tst	%o0				! check access error
1467	bnz,a	1f
1468	nop
1469	DDI_REP_GET(4,/**/)
14701:
1471	DDI_NOPROTECT()				! remove protection & ret
1472	retl
1473	nop
1474	SET_SIZE(i_ddi_prot_rep_get32)
1475
1476	.align 16
1477	ENTRY(i_ddi_prot_rep_get64)
1478	DDI_PROTECT()				! set ontrap protection
1479	tst	%o0				! check access error
1480	bnz,a	1f
1481	nop
1482	DDI_REP_GET(8,x)
14831:
1484	DDI_NOPROTECT()				! remove protection & ret
1485	retl
1486	nop
1487	SET_SIZE(i_ddi_prot_rep_get64)
1488
1489	.align 16
1490	ENTRY(i_ddi_prot_rep_put8)
1491	DDI_REP_PUT(1,ub)
1492	retl
1493	membar	#Sync;
1494	SET_SIZE(i_ddi_prot_rep_put8)
1495
1496	.align 16
1497	ENTRY(i_ddi_prot_rep_put16)
1498	DDI_REP_PUT(2,uh)
1499	retl
1500	membar	#Sync;
1501	SET_SIZE(i_ddi_prot_rep_put16)
1502
1503	.align 16
1504	ENTRY(i_ddi_prot_rep_put32)
1505	DDI_REP_PUT(4,/**/)
1506	retl
1507	membar	#Sync;
1508	SET_SIZE(i_ddi_prot_rep_put32)
1509
1510	.align 16
1511	ENTRY(i_ddi_prot_rep_put64)
1512	DDI_REP_PUT(8,x)
1513	retl
1514	membar	#Sync;
1515	SET_SIZE(i_ddi_prot_rep_put64)
1516
1517/*
1518 * Common DDI_CAUTIOUS_ACC routine called from cautious access routines
1519 * in ddi_impl.c
1520 */
1521	ENTRY(i_ddi_caut_get)
1522	rdpr	%pstate, %o3	! check ints
1523	andcc	%o3, PSTATE_IE, %g0
1524	bz,a	cautdone
1525	nop
1526	wrpr	%o3, PSTATE_IE, %pstate
1527	cmp	%o0, 8		! 64-bit?
1528	bne,a	.get_int
1529	cmp	%o0, 4		! 32-bit?
1530	ldx	[%o1], %g1
1531	ba	.getdone
1532	stx	%g1, [%o2]
1533.get_int:
1534	bne,a	.get_half
1535	cmp	%o0, 2		! 16-bit?
1536	lduw	[%o1], %g1
1537	ba	.getdone
1538	stuw	%g1, [%o2]
1539.get_half:
1540	bne,a	.get_byte
1541	ldub	[%o1], %g1	! 8-bit!
1542	lduh	[%o1], %g1
1543	ba	.getdone
1544	stuh	%g1, [%o2]
1545.get_byte:
1546	stub	%g1, [%o2]
1547.getdone:
1548	rdpr	%pstate, %o3	! check&enable ints
1549	andcc	%o3, PSTATE_IE, %g0
1550	bnz,a	cautdone
1551	nop
1552	wrpr	%o3, PSTATE_IE, %pstate
1553cautdone:
1554	retl
1555	nop
1556	SET_SIZE(i_ddi_caut_get)
1557
1558#endif	/* lint	*/
1559