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 */