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 #include <sys/asi.h> 27 #include <sys/asm_linkage.h> 28 #include <sys/machthread.h> 29 #include <sys/privregs.h> 30 #include <sys/ontrap.h> 31 #include <sys/dditypes.h> 32 33 #include "assym.h" 34 35 /* 36 * This file implements the following ddi common access 37 * functions: 38 * 39 * ddi_get{8,16,32,64} 40 * ddi_put{8,16,32,64} 41 * 42 * and the underlying "trivial" implementations 43 * 44 * i_ddi_{get,put}{8,16,32,64} 45 * 46 * which assume that there is no need to check the access handle - 47 * byte swapping will be done by the mmu and the address is always 48 * accessible via ld/st instructions. 49 */ 50 51 /* 52 * The functionality of each of the ddi_get/put routines is performed by 53 * the respective indirect function defined in the access handle. Use of 54 * the access handle functions provides compatibility across platforms for 55 * drivers. 56 * 57 * By default, the indirect access handle functions are initialized to the 58 * i_ddi_get/put routines to perform memory mapped IO. If memory mapped IO 59 * is not possible or desired, the access handle must be intialized to another 60 * valid routine to perform the sepcified IO operation. 61 * 62 * The alignment and placement of the following functions have been optimized 63 * such that the implementation specific versions, i_ddi*, fall within the 64 * same cache-line of the generic versions, ddi_*. This insures that an 65 * I-cache hit will occur thus minimizing the performance impact of using the 66 * access handle. 67 */ 68 69 .align 32 70 ENTRY(ddi_get8) 71 ALTENTRY(ddi_getb) 72 ALTENTRY(ddi_io_get8) 73 ALTENTRY(ddi_io_getb) 74 ALTENTRY(ddi_mem_get8) 75 ALTENTRY(ddi_mem_getb) 76 ldn [%o0 + AHI_GET8], %g1 /* hdl->ahi_get8 access hndl */ 77 jmpl %g1, %g0 /* jump to access handle routine */ 78 nop 79 SET_SIZE(ddi_get8) 80 SET_SIZE(ddi_getb) 81 SET_SIZE(ddi_io_get8) 82 SET_SIZE(ddi_io_getb) 83 SET_SIZE(ddi_mem_get8) 84 SET_SIZE(ddi_mem_getb) 85 86 .align 16 87 ENTRY(i_ddi_get8) 88 retl 89 ldub [%o1], %o0 90 SET_SIZE(i_ddi_get8) 91 92 .align 32 93 ENTRY(ddi_get16) 94 ALTENTRY(ddi_getw) 95 ALTENTRY(ddi_io_get16) 96 ALTENTRY(ddi_io_getw) 97 ALTENTRY(ddi_mem_get16) 98 ALTENTRY(ddi_mem_getw) 99 ldn [%o0 + AHI_GET16], %g1 /* hdl->ahi_get16 access hndl */ 100 jmpl %g1, %g0 /* jump to access handle routine */ 101 nop 102 SET_SIZE(ddi_get16) 103 SET_SIZE(ddi_getw) 104 SET_SIZE(ddi_io_get16) 105 SET_SIZE(ddi_io_getw) 106 SET_SIZE(ddi_mem_get16) 107 SET_SIZE(ddi_mem_getw) 108 109 .align 16 110 ENTRY(i_ddi_get16) 111 ALTENTRY(i_ddi_swap_get16) 112 retl 113 lduh [%o1], %o0 114 SET_SIZE(i_ddi_get16) 115 SET_SIZE(i_ddi_swap_get16) 116 117 .align 32 118 ENTRY(ddi_get32) 119 ALTENTRY(ddi_getl) 120 ALTENTRY(ddi_io_get32) 121 ALTENTRY(ddi_io_getl) 122 ALTENTRY(ddi_mem_get32) 123 ALTENTRY(ddi_mem_getl) 124 ldn [%o0 + AHI_GET32], %g1 /* hdl->ahi_get32 access handle */ 125 jmpl %g1, %g0 /* jump to access handle routine */ 126 nop 127 SET_SIZE(ddi_get32) 128 SET_SIZE(ddi_getl) 129 SET_SIZE(ddi_io_get32) 130 SET_SIZE(ddi_io_getl) 131 SET_SIZE(ddi_mem_get32) 132 SET_SIZE(ddi_mem_getl) 133 134 .align 16 135 ENTRY(i_ddi_get32) 136 ALTENTRY(i_ddi_swap_get32) 137 retl 138 ld [%o1], %o0 139 SET_SIZE(i_ddi_get32) 140 SET_SIZE(i_ddi_swap_get32) 141 142 .align 32 143 ENTRY(ddi_get64) 144 ALTENTRY(ddi_getll) 145 ALTENTRY(ddi_io_get64) 146 ALTENTRY(ddi_io_getll) 147 ALTENTRY(ddi_mem_get64) 148 ALTENTRY(ddi_mem_getll) 149 ldn [%o0 + AHI_GET64], %g1 /* hdl->ahi_get64 access handle */ 150 jmpl %g1, %g0 /* jump to access handle routine */ 151 nop 152 SET_SIZE(ddi_get64) 153 SET_SIZE(ddi_getll) 154 SET_SIZE(ddi_io_get64) 155 SET_SIZE(ddi_io_getll) 156 SET_SIZE(ddi_mem_get64) 157 SET_SIZE(ddi_mem_getll) 158 159 .align 16 160 ENTRY(i_ddi_get64) 161 ALTENTRY(i_ddi_swap_get64) 162 retl 163 ldx [%o1], %o0 164 SET_SIZE(i_ddi_get64) 165 SET_SIZE(i_ddi_swap_get64) 166 167 .align 32 168 ENTRY(ddi_put8) 169 ALTENTRY(ddi_putb) 170 ALTENTRY(ddi_io_put8) 171 ALTENTRY(ddi_io_putb) 172 ALTENTRY(ddi_mem_put8) 173 ALTENTRY(ddi_mem_putb) 174 ldn [%o0 + AHI_PUT8], %g1 /* hdl->ahi_put8 access handle */ 175 jmpl %g1, %g0 /* jump to access handle routine */ 176 nop 177 SET_SIZE(ddi_put8) 178 SET_SIZE(ddi_putb) 179 SET_SIZE(ddi_io_put8) 180 SET_SIZE(ddi_io_putb) 181 SET_SIZE(ddi_mem_put8) 182 SET_SIZE(ddi_mem_putb) 183 184 .align 16 185 ENTRY(i_ddi_put8) 186 retl 187 stub %o2, [%o1] 188 SET_SIZE(i_ddi_put8) 189 190 .align 32 191 ENTRY(ddi_put16) 192 ALTENTRY(ddi_putw) 193 ALTENTRY(ddi_io_put16) 194 ALTENTRY(ddi_io_putw) 195 ALTENTRY(ddi_mem_put16) 196 ALTENTRY(ddi_mem_putw) 197 ldn [%o0 + AHI_PUT16], %g1 /* hdl->ahi_put16 access handle */ 198 jmpl %g1, %g0 /* jump to access handle routine */ 199 nop 200 SET_SIZE(ddi_put16) 201 SET_SIZE(ddi_putw) 202 SET_SIZE(ddi_io_put16) 203 SET_SIZE(ddi_io_putw) 204 SET_SIZE(ddi_mem_put16) 205 SET_SIZE(ddi_mem_putw) 206 207 .align 16 208 ENTRY(i_ddi_put16) 209 ALTENTRY(i_ddi_swap_put16) 210 retl 211 stuh %o2, [%o1] 212 SET_SIZE(i_ddi_put16) 213 SET_SIZE(i_ddi_swap_put16) 214 215 .align 32 216 ENTRY(ddi_put32) 217 ALTENTRY(ddi_putl) 218 ALTENTRY(ddi_io_put32) 219 ALTENTRY(ddi_io_putl) 220 ALTENTRY(ddi_mem_put32) 221 ALTENTRY(ddi_mem_putl) 222 ldn [%o0 + AHI_PUT32], %g1 /* hdl->ahi_put16 access handle */ 223 jmpl %g1, %g0 /* jump to access handle routine */ 224 nop 225 SET_SIZE(ddi_put32) 226 SET_SIZE(ddi_putl) 227 SET_SIZE(ddi_io_put32) 228 SET_SIZE(ddi_io_putl) 229 SET_SIZE(ddi_mem_put32) 230 SET_SIZE(ddi_mem_putl) 231 232 .align 16 233 ENTRY(i_ddi_put32) 234 ALTENTRY(i_ddi_swap_put32) 235 retl 236 st %o2, [%o1] 237 SET_SIZE(i_ddi_put32) 238 SET_SIZE(i_ddi_swap_put32) 239 240 .align 32 241 ENTRY(ddi_put64) 242 ALTENTRY(ddi_putll) 243 ALTENTRY(ddi_io_put64) 244 ALTENTRY(ddi_io_putll) 245 ALTENTRY(ddi_mem_put64) 246 ALTENTRY(ddi_mem_putll) 247 ldn [%o0 + AHI_PUT64], %g1 /* hdl->ahi_put64 access handle */ 248 jmpl %g1, %g0 /* jump to access handle routine */ 249 nop 250 SET_SIZE(ddi_put64) 251 SET_SIZE(ddi_putll) 252 SET_SIZE(ddi_io_put64) 253 SET_SIZE(ddi_io_putll) 254 SET_SIZE(ddi_mem_put64) 255 SET_SIZE(ddi_mem_putll) 256 257 .align 16 258 ENTRY(i_ddi_put64) 259 ALTENTRY(i_ddi_swap_put64) 260 retl 261 stx %o2, [%o1] 262 SET_SIZE(i_ddi_put64) 263 SET_SIZE(i_ddi_swap_put64) 264 265 /* 266 * The ddi_io_rep_get/put routines don't take a flag argument like the "plain" 267 * and mem versions do. This flag is used to determine whether or not the 268 * device address or port should be automatically incremented. For IO space, 269 * the device port is never incremented and as such, the flag is always set 270 * to DDI_DEV_NO_AUTOINCR. 271 * 272 * This define processes the repetitive get functionality. Automatic 273 * incrementing of the device address is determined by the flag field 274 * %o4. If this is set for AUTOINCR, %o4 is updated with 1 for the 275 * subsequent increment in 2:. 276 * 277 * If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus 278 * making the increment operation a non-operation. 279 */ 280 281 #define DDI_REP_GET(n,s) \ 282 cmp DDI_DEV_NO_AUTOINCR, %o4; \ 283 mov %g0, %o4; \ 284 brz,pn %o3, 1f; \ 285 movnz %xcc, n, %o4; \ 286 2: \ 287 dec %o3; \ 288 ld/**/s [%o2], %g4; \ 289 add %o2, %o4, %o2; \ 290 st/**/s %g4, [%o1]; \ 291 brnz,pt %o3, 2b; \ 292 add %o1, n, %o1; \ 293 1: 294 295 .align 32 296 ENTRY(ddi_rep_get8) 297 ALTENTRY(ddi_rep_getb) 298 ALTENTRY(ddi_mem_rep_get8) 299 ALTENTRY(ddi_mem_rep_getb) 300 ldn [%o0 + AHI_REP_GET8], %g1 301 jmpl %g1, %g0 302 nop 303 SET_SIZE(ddi_rep_get8) 304 SET_SIZE(ddi_rep_getb) 305 SET_SIZE(ddi_mem_rep_get8) 306 SET_SIZE(ddi_mem_rep_getb) 307 308 .align 16 309 ENTRY(i_ddi_rep_get8) 310 DDI_REP_GET(1,ub) 311 retl 312 nop 313 SET_SIZE(i_ddi_rep_get8) 314 315 .align 32 316 ENTRY(ddi_rep_get16) 317 ALTENTRY(ddi_rep_getw) 318 ALTENTRY(ddi_mem_rep_get16) 319 ALTENTRY(ddi_mem_rep_getw) 320 ldn [%o0 + AHI_REP_GET16], %g1 321 jmpl %g1, %g0 322 nop 323 SET_SIZE(ddi_rep_get16) 324 SET_SIZE(ddi_rep_getw) 325 SET_SIZE(ddi_mem_rep_get16) 326 SET_SIZE(ddi_mem_rep_getw) 327 328 .align 16 329 ENTRY(i_ddi_rep_get16) 330 ALTENTRY(i_ddi_swap_rep_get16) 331 DDI_REP_GET(2,uh) 332 retl 333 nop 334 SET_SIZE(i_ddi_rep_get16) 335 SET_SIZE(i_ddi_swap_rep_get16) 336 337 .align 32 338 ENTRY(ddi_rep_get32) 339 ALTENTRY(ddi_rep_getl) 340 ALTENTRY(ddi_mem_rep_get32) 341 ALTENTRY(ddi_mem_rep_getl) 342 ldn [%o0 + AHI_REP_GET32], %g1 343 jmpl %g1, %g0 344 nop 345 SET_SIZE(ddi_rep_get32) 346 SET_SIZE(ddi_rep_getl) 347 SET_SIZE(ddi_mem_rep_get32) 348 SET_SIZE(ddi_mem_rep_getl) 349 350 .align 16 351 ENTRY(i_ddi_rep_get32) 352 ALTENTRY(i_ddi_swap_rep_get32) 353 DDI_REP_GET(4,/**/) 354 retl 355 nop 356 SET_SIZE(i_ddi_rep_get32) 357 SET_SIZE(i_ddi_swap_rep_get32) 358 359 .align 32 360 ENTRY(ddi_rep_get64) 361 ALTENTRY(ddi_rep_getll) 362 ALTENTRY(ddi_mem_rep_get64) 363 ALTENTRY(ddi_mem_rep_getll) 364 ldn [%o0 + AHI_REP_GET64], %g1 365 jmpl %g1, %g0 366 nop 367 SET_SIZE(ddi_rep_get64) 368 SET_SIZE(ddi_rep_getll) 369 SET_SIZE(ddi_mem_rep_get64) 370 SET_SIZE(ddi_mem_rep_getll) 371 372 .align 16 373 ENTRY(i_ddi_rep_get64) 374 ALTENTRY(i_ddi_swap_rep_get64) 375 DDI_REP_GET(8,x) 376 retl 377 nop 378 SET_SIZE(i_ddi_rep_get64) 379 SET_SIZE(i_ddi_swap_rep_get64) 380 381 /* 382 * This define processes the repetitive put functionality. Automatic 383 * incrementing of the device address is determined by the flag field 384 * %o4. If this is set for AUTOINCR, %o4 is updated with 1 for the 385 * subsequent increment in 2:. 386 * 387 * If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus 388 * making the increment operation a non-operation. 389 */ 390 #define DDI_REP_PUT(n,s) \ 391 cmp DDI_DEV_NO_AUTOINCR, %o4; \ 392 mov %g0, %o4; \ 393 brz,pn %o3, 1f; \ 394 movnz %xcc, n, %o4; \ 395 2: \ 396 dec %o3; \ 397 ld/**/s [%o1], %g4; \ 398 add %o1, n, %o1; \ 399 st/**/s %g4, [%o2]; \ 400 brnz,pt %o3, 2b; \ 401 add %o2, %o4, %o2; \ 402 1: 403 404 .align 32 405 ENTRY(ddi_rep_put8) 406 ALTENTRY(ddi_rep_putb) 407 ALTENTRY(ddi_mem_rep_put8) 408 ALTENTRY(ddi_mem_rep_putb) 409 ldn [%o0 + AHI_REP_PUT8], %g1 410 jmpl %g1, %g0 411 nop 412 SET_SIZE(ddi_rep_put8) 413 SET_SIZE(ddi_rep_putb) 414 SET_SIZE(ddi_mem_rep_put8) 415 SET_SIZE(ddi_mem_rep_putb) 416 417 .align 16 418 ENTRY(i_ddi_rep_put8) 419 DDI_REP_PUT(1,ub) 420 retl 421 nop 422 SET_SIZE(i_ddi_rep_put8) 423 424 .align 32 425 ENTRY(ddi_rep_put16) 426 ALTENTRY(ddi_rep_putw) 427 ALTENTRY(ddi_mem_rep_put16) 428 ALTENTRY(ddi_mem_rep_putw) 429 ldn [%o0 + AHI_REP_PUT16], %g1 430 jmpl %g1, %g0 431 nop 432 SET_SIZE(ddi_rep_put16) 433 SET_SIZE(ddi_rep_putw) 434 SET_SIZE(ddi_mem_rep_put16) 435 SET_SIZE(ddi_mem_rep_putw) 436 437 .align 16 438 ENTRY(i_ddi_rep_put16) 439 ALTENTRY(i_ddi_swap_rep_put16) 440 DDI_REP_PUT(2,uh) 441 retl 442 nop 443 SET_SIZE(i_ddi_rep_put16) 444 SET_SIZE(i_ddi_swap_rep_put16) 445 446 .align 32 447 ENTRY(ddi_rep_put32) 448 ALTENTRY(ddi_rep_putl) 449 ALTENTRY(ddi_mem_rep_put32) 450 ALTENTRY(ddi_mem_rep_putl) 451 ldn [%o0 + AHI_REP_PUT32], %g1 452 jmpl %g1, %g0 453 nop 454 SET_SIZE(ddi_rep_put32) 455 SET_SIZE(ddi_rep_putl) 456 SET_SIZE(ddi_mem_rep_put32) 457 SET_SIZE(ddi_mem_rep_putl) 458 459 .align 16 460 ENTRY(i_ddi_rep_put32) 461 ALTENTRY(i_ddi_swap_rep_put32) 462 DDI_REP_PUT(4,/**/) 463 retl 464 nop 465 SET_SIZE(i_ddi_rep_put32) 466 SET_SIZE(i_ddi_swap_rep_put32) 467 468 .align 32 469 ENTRY(ddi_rep_put64) 470 ALTENTRY(ddi_rep_putll) 471 ALTENTRY(ddi_mem_rep_put64) 472 ALTENTRY(ddi_mem_rep_putll) 473 ldn [%o0 + AHI_REP_PUT64], %g1 474 jmpl %g1, %g0 475 nop 476 SET_SIZE(ddi_rep_put64) 477 SET_SIZE(ddi_rep_putll) 478 SET_SIZE(ddi_mem_rep_put64) 479 SET_SIZE(ddi_mem_rep_putll) 480 481 .align 16 482 ENTRY(i_ddi_rep_put64) 483 ALTENTRY(i_ddi_swap_rep_put64) 484 DDI_REP_PUT(8,x) 485 retl 486 nop 487 SET_SIZE(i_ddi_rep_put64) 488 SET_SIZE(i_ddi_swap_rep_put64) 489 490 .align 16 491 ENTRY(ddi_io_rep_get8) 492 ALTENTRY(ddi_io_rep_getb) 493 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 494 ldn [%o0 + AHI_REP_GET8], %g1 495 jmpl %g1, %g0 496 nop 497 SET_SIZE(ddi_io_rep_get8) 498 SET_SIZE(ddi_io_rep_getb) 499 500 .align 16 501 ENTRY(ddi_io_rep_get16) 502 ALTENTRY(ddi_io_rep_getw) 503 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 504 ldn [%o0 + AHI_REP_GET16], %g1 505 jmpl %g1, %g0 506 nop 507 SET_SIZE(ddi_io_rep_get16) 508 SET_SIZE(ddi_io_rep_getw) 509 510 .align 16 511 ENTRY(ddi_io_rep_get32) 512 ALTENTRY(ddi_io_rep_getl) 513 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 514 ldn [%o0 + AHI_REP_GET32], %g1 515 jmpl %g1, %g0 516 nop 517 SET_SIZE(ddi_io_rep_get32) 518 SET_SIZE(ddi_io_rep_getl) 519 520 .align 16 521 ENTRY(ddi_io_rep_get64) 522 ALTENTRY(ddi_io_rep_getll) 523 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 524 ldn [%o0 + AHI_REP_GET64], %g1 525 jmpl %g1, %g0 526 nop 527 SET_SIZE(ddi_io_rep_get64) 528 SET_SIZE(ddi_io_rep_getll) 529 530 .align 64 531 ENTRY(ddi_check_acc_handle) 532 save %sp, -SA(WINDOWSIZE), %sp ! get a new window 533 ldn [%i0 + AHI_FAULT_CHECK], %g1 534 jmpl %g1, %o7 535 mov %i0, %o0 536 brnz,a,pn %o0, 0f ! if (return_value != 0) 537 mov -1, %o0 ! return (DDI_FAILURE) 538 0: ! else return (DDI_SUCCESS) 539 sra %o0, 0, %i0 540 ret 541 restore 542 SET_SIZE(ddi_check_acc_handle) 543 544 .align 16 545 ENTRY(i_ddi_acc_fault_check) 546 retl 547 ld [%o0 + AHI_FAULT], %o0 548 SET_SIZE(i_ddi_acc_fault_check) 549 550 .align 16 551 ENTRY(ddi_io_rep_put8) 552 ALTENTRY(ddi_io_rep_putb) 553 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 554 ldn [%o0 + AHI_REP_PUT8], %g1 555 jmpl %g1, %g0 556 nop 557 SET_SIZE(ddi_io_rep_put8) 558 SET_SIZE(ddi_io_rep_putb) 559 560 .align 16 561 ENTRY(ddi_io_rep_put16) 562 ALTENTRY(ddi_io_rep_putw) 563 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 564 ldn [%o0 + AHI_REP_PUT16], %g1 565 jmpl %g1, %g0 566 nop 567 SET_SIZE(ddi_io_rep_put16) 568 SET_SIZE(ddi_io_rep_putw) 569 570 .align 16 571 ENTRY(ddi_io_rep_put32) 572 ALTENTRY(ddi_io_rep_putl) 573 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 574 ldn [%o0 + AHI_REP_PUT32], %g1 575 jmpl %g1, %g0 576 nop 577 SET_SIZE(ddi_io_rep_put32) 578 SET_SIZE(ddi_io_rep_putl) 579 580 .align 16 581 ENTRY(ddi_io_rep_put64) 582 ALTENTRY(ddi_io_rep_putll) 583 set DDI_DEV_NO_AUTOINCR, %o4 /* Set flag to DDI_DEV_NO_AUTOINCR */ 584 ldn [%o0 + AHI_REP_PUT64], %g1 585 jmpl %g1, %g0 586 nop 587 SET_SIZE(ddi_io_rep_put64) 588 SET_SIZE(ddi_io_rep_putll) 589 590 ENTRY(do_peek) 591 rdpr %pstate, %o3 ! check ints 592 andcc %o3, PSTATE_IE, %g0 593 bz,a done 594 or %g0, 1, %o0 ! Return failure if ints are disabled 595 wrpr %o3, PSTATE_IE, %pstate 596 cmp %o0, 8 ! 64-bit? 597 bne,a .peek_int 598 cmp %o0, 4 ! 32-bit? 599 ldx [%o1], %g1 600 ba .peekdone 601 stx %g1, [%o2] 602 .peek_int: 603 bne,a .peek_half 604 cmp %o0, 2 ! 16-bit? 605 lduw [%o1], %g1 606 ba .peekdone 607 stuw %g1, [%o2] 608 .peek_half: 609 bne,a .peek_byte 610 ldub [%o1], %g1 ! 8-bit! 611 lduh [%o1], %g1 612 ba .peekdone 613 stuh %g1, [%o2] 614 .peek_byte: 615 stub %g1, [%o2] 616 .peekdone: 617 membar #Sync ! Make sure the loads take 618 rdpr %pstate, %o3 ! check&enable ints 619 andcc %o3, PSTATE_IE, %g0 620 bnz 1f 621 nop 622 wrpr %o3, PSTATE_IE, %pstate 623 1: 624 mov %g0, %o0 625 done: 626 retl 627 nop 628 SET_SIZE(do_peek) 629 630 ENTRY(do_poke) 631 cmp %o0, 8 ! 64 bit? 632 bne,a .poke_int 633 cmp %o0, 4 ! 32-bit? 634 ldx [%o2], %g1 635 ba .pokedone 636 stx %g1, [%o1] 637 .poke_int: 638 bne,a .poke_half 639 cmp %o0, 2 ! 16-bit? 640 lduw [%o2], %g1 641 ba .pokedone 642 stuw %g1, [%o1] 643 .poke_half: 644 bne,a .poke_byte 645 ldub [%o2], %g1 ! 8-bit! 646 lduh [%o2], %g1 647 ba .pokedone 648 stuh %g1, [%o1] 649 .poke_byte: 650 stub %g1, [%o1] 651 .pokedone: 652 membar #Sync 653 retl 654 mov %g0, %o0 655 SET_SIZE(do_poke) 656 657 658 /* 659 * The peek_fault() and poke_fault() routines below are used as on_trap() 660 * trampoline routines. i_ddi_peek and i_ddi_poke execute do_peek and do_poke 661 * under on_trap protection (see <sys/ontrap.h>), but modify ot_trampoline to 662 * refer to the corresponding routine below. If a trap occurs, the trap code 663 * will bounce back to the trampoline code, which will effectively cause 664 * do_peek or do_poke to return DDI_FAILURE, instead of longjmp'ing back to 665 * on_trap. In the case of a peek, we may also need to re-enable interrupts. 666 */ 667 .seg ".data" 668 .peek_panic: 669 .asciz "peek_fault: missing or invalid on_trap_data" 670 .poke_panic: 671 .asciz "poke_fault: missing or invalid on_trap_data" 672 673 ENTRY(peek_fault) 674 ldn [THREAD_REG + T_ONTRAP], %o0 ! %o0 = on_trap_data pointer 675 brz,pn %o0, .peekfail ! if (%o0 == NULL) panic 676 nop 677 lduh [%o0 + OT_PROT], %o1 ! %o1 = %o0->ot_prot 678 andcc %o1, OT_DATA_ACCESS, %g0 ! if (!(%o1 & OT_DATA_ACCESS)) 679 bz,pn %icc, .peekfail ! panic 680 rdpr %pstate, %o3 681 682 andcc %o3, PSTATE_IE, %g0 ! enable interrupts 683 bnz 1f 684 nop 685 wrpr %o3, PSTATE_IE, %pstate 686 1: 687 retl 688 sub %g0, 1, %o0 ! return (DDI_FAILURE); 689 .peekfail: 690 set .peek_panic, %o0 ! Load panic message 691 call panic ! Panic if bad t_ontrap data 692 nop 693 SET_SIZE(peek_fault) 694 695 696 ENTRY(poke_fault) 697 ldn [THREAD_REG + T_ONTRAP], %o0 ! %o0 = on_trap_data pointer 698 brz,pn %o0, .pokefail ! if (%o0 == NULL) panic 699 nop 700 lduh [%o0 + OT_PROT], %o1 ! %o1 = %o0->ot_prot 701 andcc %o1, OT_DATA_ACCESS, %g0 ! if (!(%o1 & OT_DATA_ACCESS)) 702 bz,pn %icc, .pokefail ! panic 703 nop 704 retl 705 sub %g0, 1, %o0 ! return (DDI_FAILURE); 706 .pokefail: 707 set .poke_panic, %o0 ! Load panic message 708 call panic ! Panic if bad t_ontrap data 709 nop 710 SET_SIZE(poke_fault) 711 712 713 /* 714 * IO Fault Services 715 * 716 * Support for protected IO accesses is implemented in the following 717 * functions. A driver may request one of three protection mechanisms 718 * that enable the system to survive an access errors. The protection 719 * mechansim is set-up during ddi_regs_map_setup time and may be one of: 720 * 721 * DDI_DEFAULT_ACC - no error protection requested. We will 722 * use the standard ddi_get/ddi_put operations 723 * defined above. 724 * 725 * DDI_FLAGERR - Driver requests that errors encountered will 726 * be flagged by the system. The driver is 727 * responsible for checking the error status 728 * of the access with a call to ddi_acc_err_get() 729 * upon return of ddi_get or ddi_put. To prevent 730 * an access from causing a system we use internal 731 * on_trap semantics. 732 * 733 * The system, depending upon the error, 734 * may or may not panic. 735 * 736 * DDI_CAUTIOUS_ACC - Driver expects that the access may cause 737 * an error to occur. The system will return 738 * an error status but will not generate an ereport. 739 * The system will also ensure synchronous and 740 * exclusive access to the IO space accessed by 741 * the caller. 742 * 743 * To prevent an access from causing a system panic, 744 * we use on_trap semantics to catch the error and 745 * set error status. 746 * 747 * If a read access error is detected and DDI_CAUTIOUS_ACC or 748 * DDI_FLAGERR_ACC protection was requested, we will trampoline to the 749 * error handler, i_ddi_trampoline. i_ddi_trampoline will: 750 * - check for proper protection semantics 751 * - set the error status of the access handle to DDI_FM_NONFATAL 752 * - re-enable interrupts if neccessary 753 * - longjmp back to the initiating access function. 754 755 * If a write access error is detected, an interrupt is typically 756 * generated and claimed by a bus nexus responsible for the write 757 * transaction. The nexus error handler is expected to set the 758 * error status and the IO initiating driver is expected to check 759 * for a failed transaction via ddi_fm_acc_err_get(). 760 * 761 */ 762 763 .seg ".data" 764 .acc_panic: 765 .asciz "DDI access: missing or invalid on_trap_data" 766 767 ENTRY(i_ddi_caut_trampoline) 768 ldn [THREAD_REG + T_ONTRAP], %o5 ! %o5 = curthread->t_ontrap 769 lduh [%o5 + OT_PROT], %o1 ! %o1 = %o0->ot_prot 770 andcc %o1, OT_DATA_ACCESS, %g0 ! if (!(%o1 & OT_DATA_ACCESS)) 771 bz,pn %icc, .cautaccfail ! panic 772 rdpr %pstate, %o3 773 andcc %o3, PSTATE_IE, %g0 ! enable interrupts 774 bnz 1f 775 nop 776 wrpr %o3, PSTATE_IE, %pstate 777 1: 778 ldn [%o5 + OT_HANDLE], %o0 ! %o0 = ot_handle 779 brz,pn %o0, .cautaccfail ! if (ot_handle == NULL) panic 780 nop 781 ldn [%o0 + AHI_ERR], %o4 ! %o4 = hp->ahi_err 782 membar #Sync 783 stx %g0, [%o4 + ERR_ENA] ! ahi_err->err_ena = 0 784 mov -2, %o0 785 st %o0, [%o4 + ERR_STATUS] ! ahi_err->err_status = NONFATAL 786 b longjmp ! longjmp back 787 add %o5, OT_JMPBUF, %o0 ! %o0 = &ot_jmpbuf 788 .cautaccfail: 789 set .acc_panic, %o0 ! Load panic message 790 call panic ! Panic if bad t_ontrap data 791 nop 792 SET_SIZE(i_ddi_caut_trampoline) 793 794 /* 795 * DDI on_trap set-up functions, i_ddi_ontrap() and i_ddinotrap() are used 796 * to protect * ddi_get accesses for DDI_CAUT_ACC. i_ddi_ontrap() sets 797 * the jumpbuf (setjmp) that will return back to the access routine from 798 * i_ddi_trampoline(). DDI_NOPROTECT() clears the ontrap set-up. 799 */ 800 ENTRY(i_ddi_ontrap) 801 ldn [%o0 + AHI_ERR], %o4 802 ldn [%o4 + ERR_ONTRAP], %o4 ! %o4 = hp->ahi_err->err_ontrap 803 ldn [THREAD_REG + T_ONTRAP], %o5 ! %o5 = curthread->t_ontrap 804 stn %o5, [%o4 + OT_PREV] ! ot_prev = t_ontrap 805 membar #Sync ! force error barrier 806 stn %o4, [THREAD_REG + T_ONTRAP] ! t_ontrap = err_ontrap 807 b setjmp 808 add %o4, OT_JMPBUF, %o0 809 SET_SIZE(i_ddi_ontrap) 810 811 ENTRY(i_ddi_notrap) 812 membar #Sync ! force error barrier 813 ldn [%o0 + AHI_ERR], %o4 814 ldn [%o4 + ERR_ONTRAP], %o4 ! %o4 = hp->ahi_err->err_ontrap 815 ldn [%o4 + OT_PREV], %o4 816 retl 817 stn %o4, [THREAD_REG + T_ONTRAP] ! restore curthread->t_ontrap 818 SET_SIZE(i_ddi_notrap) 819 820 /* 821 * Internal on_trap set-up macros. DDI_PROTECT() and DDI_NOPROTECT() are used 822 * to protect * ddi_get accesses for DDI_FLAGERR_ACC. DDI_NOPROTECT() sets 823 * the jumpbuf that will return back to the access routine from 824 * i_ddi_protect_trampoline(). DDI_NOPROTECT() clears the ontrap set-up. 825 */ 826 ENTRY(i_ddi_prot_trampoline) 827 ldn [THREAD_REG + T_ONTRAP], %o5 ! %o5 = curthread->t_ontrap 828 lduh [%o5 + OT_PROT], %o1 ! %o1 = %o0->ot_prot 829 andcc %o1, OT_DATA_ACCESS, %g0 ! if (!(%o1 & OT_DATA_ACCESS)) 830 bz,pn %icc, .protaccfail ! panic 831 rdpr %pstate, %o3 832 andcc %o3, PSTATE_IE, %g0 ! enable interrupts 833 bnz 1f 834 nop 835 wrpr %o3, PSTATE_IE, %pstate 836 1: 837 ldn [%o5 + OT_HANDLE], %o0 ! %o0 = ot_handle 838 brz,pn %o0, .protaccfail ! if (ot_handle == NULL) panic 839 nop 840 ldn [%o0 + AHI_ERR], %o4 ! %o4 = hp->ahi_err 841 stn %g0, [%o4 + ERR_ENA] ! ahi_err->err_ena = 0 842 mov -2, %o0 843 st %o0, [%o4 + ERR_STATUS] ! ahi_err->err_status = NONFATAL 844 ldn [%o5 + OT_PREV], %o0 ! restore ontrap 845 membar #Sync ! force error barrier 846 stn %o0, [THREAD_REG + T_ONTRAP]; 847 b longjmp ! longjmp back 848 add %o5, OT_JMPBUF, %o0 ! %o0 = &ot_jmpbuf 849 .protaccfail: 850 set .acc_panic, %o0 ! Load panic message 851 call panic ! Panic if bad t_ontrap data 852 nop 853 SET_SIZE(i_ddi_prot_trampoline) 854 855 #define DDI_PROTECT() \ 856 ldn [%o0 + AHI_ERR], %o4; \ 857 ldn [%o4 + ERR_ONTRAP], %o4; \ 858 ldn [THREAD_REG + T_ONTRAP], %o5; \ 859 stn %o5, [%o4 + OT_PREV]; \ 860 membar #Sync; \ 861 stn %o4, [THREAD_REG + T_ONTRAP]; \ 862 add %o4, OT_JMPBUF, %o0; \ 863 stn %o7, [%o0 + L_PC]; \ 864 stn %sp, [%o0 + L_SP]; \ 865 clr %o0; 866 867 #define DDI_NOPROTECT() \ 868 ldn [THREAD_REG + T_ONTRAP], %o4; \ 869 ldn [%o4 + OT_PREV], %o5; \ 870 membar #Sync; \ 871 stn %o5, [THREAD_REG + T_ONTRAP]; 872 873 /* 874 * DDI_FLAGERR_ACC specific get/put routines. 875 */ 876 .align 16 877 ENTRY(i_ddi_prot_get8) 878 DDI_PROTECT() ! set ontrap protection 879 ldub [%o1], %o2 ! do the io access 880 DDI_NOPROTECT() ! remove protection & ret 881 retl 882 mov %o2, %o0 ! set return value 883 SET_SIZE(i_ddi_prot_get8) 884 885 .align 16 886 ENTRY(i_ddi_prot_get16) 887 DDI_PROTECT() ! set ontrap protection 888 lduh [%o1], %o2 ! do the io access 889 DDI_NOPROTECT() ! remove protection & ret 890 retl 891 mov %o2, %o0 ! set return value 892 SET_SIZE(i_ddi_prot_get16) 893 894 .align 16 895 ENTRY(i_ddi_prot_get32) 896 DDI_PROTECT() ! set ontrap protection 897 ld [%o1], %o2 ! do the io access 898 DDI_NOPROTECT() ! remove protection & ret 899 retl 900 mov %o2, %o0 ! set return value 901 SET_SIZE(i_ddi_prot_get32) 902 903 .align 16 904 ENTRY(i_ddi_prot_get64) 905 DDI_PROTECT() ! set ontrap protection 906 ldx [%o1], %o2 ! do the io access 907 DDI_NOPROTECT() ! remove protection & ret 908 retl 909 mov %o2, %o0 ! set return value 910 SET_SIZE(i_ddi_prot_get64) 911 912 .align 16 913 ENTRY(i_ddi_prot_put8) 914 stub %o2, [%o1] ! do the io access 915 retl 916 membar #Sync; 917 SET_SIZE(i_ddi_prot_put8) 918 919 .align 16 920 ENTRY(i_ddi_prot_put16) 921 stuh %o2, [%o1] ! do the io access 922 retl 923 membar #Sync; 924 SET_SIZE(i_ddi_prot_put16) 925 926 .align 16 927 ENTRY(i_ddi_prot_put32) 928 st %o2, [%o1] ! do the io access 929 retl 930 membar #Sync; 931 SET_SIZE(i_ddi_prot_put32) 932 933 .align 16 934 ENTRY(i_ddi_prot_put64) 935 stx %o2, [%o1] ! do the io access 936 retl 937 membar #Sync; 938 SET_SIZE(i_ddi_prot_put64) 939 940 .align 16 941 ENTRY(i_ddi_prot_rep_get8) 942 DDI_PROTECT() ! set ontrap protection 943 tst %o0 ! check access error 944 bnz,a 1f 945 nop 946 DDI_REP_GET(1,ub) 947 1: 948 DDI_NOPROTECT() ! remove protection & ret 949 retl 950 nop 951 SET_SIZE(i_ddi_prot_rep_get8) 952 953 .align 16 954 ENTRY(i_ddi_prot_rep_get16) 955 DDI_PROTECT() ! set ontrap protection 956 tst %o0 ! check access error 957 bnz,a 1f 958 nop 959 DDI_REP_GET(2,uh) 960 1: 961 DDI_NOPROTECT() ! remove protection & ret 962 retl 963 nop 964 SET_SIZE(i_ddi_prot_rep_get16) 965 966 .align 16 967 ENTRY(i_ddi_prot_rep_get32) 968 DDI_PROTECT() ! set ontrap protection 969 tst %o0 ! check access error 970 bnz,a 1f 971 nop 972 DDI_REP_GET(4,/**/) 973 1: 974 DDI_NOPROTECT() ! remove protection & ret 975 retl 976 nop 977 SET_SIZE(i_ddi_prot_rep_get32) 978 979 .align 16 980 ENTRY(i_ddi_prot_rep_get64) 981 DDI_PROTECT() ! set ontrap protection 982 tst %o0 ! check access error 983 bnz,a 1f 984 nop 985 DDI_REP_GET(8,x) 986 1: 987 DDI_NOPROTECT() ! remove protection & ret 988 retl 989 nop 990 SET_SIZE(i_ddi_prot_rep_get64) 991 992 .align 16 993 ENTRY(i_ddi_prot_rep_put8) 994 DDI_REP_PUT(1,ub) 995 retl 996 membar #Sync; 997 SET_SIZE(i_ddi_prot_rep_put8) 998 999 .align 16 1000 ENTRY(i_ddi_prot_rep_put16) 1001 DDI_REP_PUT(2,uh) 1002 retl 1003 membar #Sync; 1004 SET_SIZE(i_ddi_prot_rep_put16) 1005 1006 .align 16 1007 ENTRY(i_ddi_prot_rep_put32) 1008 DDI_REP_PUT(4,/**/) 1009 retl 1010 membar #Sync; 1011 SET_SIZE(i_ddi_prot_rep_put32) 1012 1013 .align 16 1014 ENTRY(i_ddi_prot_rep_put64) 1015 DDI_REP_PUT(8,x) 1016 retl 1017 membar #Sync; 1018 SET_SIZE(i_ddi_prot_rep_put64) 1019 1020 /* 1021 * Common DDI_CAUTIOUS_ACC routine called from cautious access routines 1022 * in ddi_impl.c 1023 */ 1024 ENTRY(i_ddi_caut_get) 1025 rdpr %pstate, %o3 ! check ints 1026 andcc %o3, PSTATE_IE, %g0 1027 bz,a cautdone 1028 nop 1029 wrpr %o3, PSTATE_IE, %pstate 1030 cmp %o0, 8 ! 64-bit? 1031 bne,a .get_int 1032 cmp %o0, 4 ! 32-bit? 1033 ldx [%o1], %g1 1034 ba .getdone 1035 stx %g1, [%o2] 1036 .get_int: 1037 bne,a .get_half 1038 cmp %o0, 2 ! 16-bit? 1039 lduw [%o1], %g1 1040 ba .getdone 1041 stuw %g1, [%o2] 1042 .get_half: 1043 bne,a .get_byte 1044 ldub [%o1], %g1 ! 8-bit! 1045 lduh [%o1], %g1 1046 ba .getdone 1047 stuh %g1, [%o2] 1048 .get_byte: 1049 stub %g1, [%o2] 1050 .getdone: 1051 rdpr %pstate, %o3 ! check&enable ints 1052 andcc %o3, PSTATE_IE, %g0 1053 bnz,a cautdone 1054 nop 1055 wrpr %o3, PSTATE_IE, %pstate 1056 cautdone: 1057 retl 1058 nop 1059 SET_SIZE(i_ddi_caut_get) 1060