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*/
64 uint8_t
65 ddi_get8(ddi_acc_handle_t handle, uint8_t *addr)
66 {
67 return (0);
68 }
69
70 /*ARGSUSED*/
71 uint8_t
72 ddi_mem_get8(ddi_acc_handle_t handle, uint8_t *addr)
73 {
74 return (0);
75 }
76
77 /*ARGSUSED*/
78 uint8_t
79 ddi_io_get8(ddi_acc_handle_t handle, uint8_t *dev_addr)
80 {
81 return (0);
82 }
83
84 /*ARGSUSED*/
85 uint16_t
86 ddi_get16(ddi_acc_handle_t handle, uint16_t *addr)
87 {
88 return (0);
89 }
90
91 /*ARGSUSED*/
92 uint16_t
93 ddi_mem_get16(ddi_acc_handle_t handle, uint16_t *addr)
94 {
95 return (0);
96 }
97
98 /*ARGSUSED*/
99 uint16_t
100 ddi_io_get16(ddi_acc_handle_t handle, uint16_t *dev_addr)
101 {
102 return (0);
103 }
104
105 /*ARGSUSED*/
106 uint32_t
107 ddi_get32(ddi_acc_handle_t handle, uint32_t *addr)
108 {
109 return (0);
110 }
111
112 /*ARGSUSED*/
113 uint32_t
114 ddi_mem_get32(ddi_acc_handle_t handle, uint32_t *addr)
115 {
116 return (0);
117 }
118
119 /*ARGSUSED*/
120 uint32_t
121 ddi_io_get32(ddi_acc_handle_t handle, uint32_t *dev_addr)
122 {
123 return (0);
124 }
125
126 /*ARGSUSED*/
127 uint64_t
128 ddi_get64(ddi_acc_handle_t handle, uint64_t *addr)
129 {
130 return (0);
131 }
132
133 /*ARGSUSED*/
134 uint64_t
135 ddi_mem_get64(ddi_acc_handle_t handle, uint64_t *addr)
136 {
137 return (0);
138 }
139
140 /*ARGSUSED*/
141 void
142 ddi_put8(ddi_acc_handle_t handle, uint8_t *addr, uint8_t value) {}
143
144 /*ARGSUSED*/
145 void
146 ddi_mem_put8(ddi_acc_handle_t handle, uint8_t *dev_addr, uint8_t value) {}
147
148 /*ARGSUSED*/
149 void
150 ddi_io_put8(ddi_acc_handle_t handle, uint8_t *dev_addr, uint8_t value) {}
151
152 /*ARGSUSED*/
153 void
154 ddi_put16(ddi_acc_handle_t handle, uint16_t *addr, uint16_t value) {}
155
156 /*ARGSUSED*/
157 void
158 ddi_mem_put16(ddi_acc_handle_t handle, uint16_t *dev_addr, uint16_t value) {}
159
160 /*ARGSUSED*/
161 void
162 ddi_io_put16(ddi_acc_handle_t handle, uint16_t *dev_addr, uint16_t value) {}
163
164 /*ARGSUSED*/
165 void
166 ddi_put32(ddi_acc_handle_t handle, uint32_t *addr, uint32_t value) {}
167
168 /*ARGSUSED*/
169 void
170 ddi_mem_put32(ddi_acc_handle_t handle, uint32_t *dev_addr, uint32_t value) {}
171
172 /*ARGSUSED*/
173 void
174 ddi_io_put32(ddi_acc_handle_t handle, uint32_t *dev_addr, uint32_t value) {}
175
176 /*ARGSUSED*/
177 void
178 ddi_put64(ddi_acc_handle_t handle, uint64_t *addr, uint64_t value) {}
179
180 /*ARGSUSED*/
181 void
182 ddi_mem_put64(ddi_acc_handle_t handle, uint64_t *dev_addr, uint64_t value) {}
183
184 /*ARGSUSED*/
185 void
186 ddi_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*/
192 void
193 ddi_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*/
199 void
200 ddi_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*/
206 void
207 ddi_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*/
213 void
214 ddi_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*/
220 void
221 ddi_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*/
227 void
228 ddi_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*/
234 void
235 ddi_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*/
241 void
242 ddi_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*/
248 void
249 ddi_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*/
255 void
256 ddi_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*/
262 void
263 ddi_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*/
269 void
270 ddi_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*/
276 void
277 ddi_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*/
283 void
284 ddi_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*/
290 void
291 ddi_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*/
297 void
298 ddi_io_rep_get8(ddi_acc_handle_t handle,
299 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) {}
300
301 /*ARGSUSED*/
302 void
303 ddi_io_rep_get16(ddi_acc_handle_t handle,
304 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) {}
305
306 /*ARGSUSED*/
307 void
308 ddi_io_rep_get32(ddi_acc_handle_t handle,
309 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) {}
310
311 /*ARGSUSED*/
312 void
313 ddi_io_rep_put8(ddi_acc_handle_t handle,
314 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) {}
315
316 /*ARGSUSED*/
317 void
318 ddi_io_rep_put16(ddi_acc_handle_t handle,
319 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) {}
320
321
322 /*ARGSUSED*/
323 void
324 ddi_io_rep_put32(ddi_acc_handle_t handle,
325 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) {}
326
327 /*ARGSUSED*/
328 uint8_t
329 i_ddi_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
330 {
331 return (0);
332 }
333
334 /*ARGSUSED*/
335 uint16_t
336 i_ddi_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
337 {
338 return (0);
339 }
340
341 /*ARGSUSED*/
342 uint32_t
343 i_ddi_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
344 {
345 return (0);
346 }
347
348 /*ARGSUSED*/
349 uint64_t
350 i_ddi_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
351 {
352 return (0);
353 }
354
355 /*ARGSUSED*/
356 void
357 i_ddi_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) {}
358
359 /*ARGSUSED*/
360 void
361 i_ddi_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) {}
362
363 /*ARGSUSED*/
364 void
365 i_ddi_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
366
367 /*ARGSUSED*/
368 void
369 i_ddi_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
370
371 /*ARGSUSED*/
372 void
373 i_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*/
379 void
380 i_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*/
386 void
387 i_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*/
393 void
394 i_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*/
400 void
401 i_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*/
407 void
408 i_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*/
414 void
415 i_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*/
421 void
422 i_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*/
428 uint8_t
429 i_ddi_prot_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
430 {
431 return (0);
432 }
433
434 /*ARGSUSED*/
435 uint16_t
436 i_ddi_prot_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
437 {
438 return (0);
439 }
440
441 /*ARGSUSED*/
442 uint32_t
443 i_ddi_prot_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
444 {
445 return (0);
446 }
447
448 /*ARGSUSED*/
449 uint64_t
450 i_ddi_prot_get64(ddi_acc_impl_t *hdlp, uint64_t *addr)
451 {
452 return (0);
453 }
454
455 /*ARGSUSED*/
456 void
457 i_ddi_prot_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) {}
458
459 /*ARGSUSED*/
460 void
461 i_ddi_prot_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) {}
462
463 /*ARGSUSED*/
464 void
465 i_ddi_prot_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
466
467 /*ARGSUSED*/
468 void
469 i_ddi_prot_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
470
471 /*ARGSUSED*/
472 void
473 i_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*/
479 void
480 i_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*/
486 void
487 i_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*/
493 void
494 i_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*/
500 void
501 i_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*/
507 void
508 i_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*/
514 void
515 i_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*/
521 void
522 i_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*/
528 int
529 i_ddi_ontrap(ddi_acc_handle_t handle)
530 {
531 return (0);
532 }
533
534 /*ARGSUSED*/
535 void
536 i_ddi_notrap(ddi_acc_handle_t handle)
537 {
538 }
539
540 /*ARGSUSED*/
541 void
542 i_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; \
783 2: \
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; \
790 1:
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; \
892 2: \
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; \
899 1:
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)
1035 0: ! 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
1120 1:
1121 mov %g0, %o0
1122 done:
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
1183 1:
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
1274 1:
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
1333 1:
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)
1444 1:
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)
1457 1:
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,/**/)
1470 1:
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)
1483 1:
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
1553 cautdone:
1554 retl
1555 nop
1556 SET_SIZE(i_ddi_caut_get)
1557
1558 #endif /* lint */