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