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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/conf.h> 30 #include <sys/kmem.h> 31 #include <sys/ddi_impldefs.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/ddifm.h> 35 #include <sys/fm/io/ddi.h> 36 #include <sys/ontrap.h> 37 38 39 /* 40 * DDI DMA Engine functions for x86. 41 * These functions are more naturally generic, but do not apply to SPARC. 42 */ 43 44 int 45 ddi_dmae_alloc(dev_info_t *dip, int chnl, int (*dmae_waitfp)(), caddr_t arg) 46 { 47 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_ACQUIRE, 48 (off_t *)dmae_waitfp, (size_t *)arg, 49 (caddr_t *)(uintptr_t)chnl, 0)); 50 } 51 52 int 53 ddi_dmae_release(dev_info_t *dip, int chnl) 54 { 55 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_FREE, 0, 0, 56 (caddr_t *)(uintptr_t)chnl, 0)); 57 } 58 59 int 60 ddi_dmae_getlim(dev_info_t *dip, ddi_dma_lim_t *limitsp) 61 { 62 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETLIM, 0, 0, 63 (caddr_t *)limitsp, 0)); 64 } 65 66 int 67 ddi_dmae_getattr(dev_info_t *dip, ddi_dma_attr_t *attrp) 68 { 69 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETATTR, 0, 0, 70 (caddr_t *)attrp, 0)); 71 } 72 73 int 74 ddi_dmae_1stparty(dev_info_t *dip, int chnl) 75 { 76 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_1STPTY, 0, 0, 77 (caddr_t *)(uintptr_t)chnl, 0)); 78 } 79 80 int 81 ddi_dmae_prog(dev_info_t *dip, struct ddi_dmae_req *dmaereqp, 82 ddi_dma_cookie_t *cookiep, int chnl) 83 { 84 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_PROG, (off_t *)dmaereqp, 85 (size_t *)cookiep, (caddr_t *)(uintptr_t)chnl, 0)); 86 } 87 88 int 89 ddi_dmae_swsetup(dev_info_t *dip, struct ddi_dmae_req *dmaereqp, 90 ddi_dma_cookie_t *cookiep, int chnl) 91 { 92 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_SWSETUP, (off_t *)dmaereqp, 93 (size_t *)cookiep, (caddr_t *)(uintptr_t)chnl, 0)); 94 } 95 96 int 97 ddi_dmae_swstart(dev_info_t *dip, int chnl) 98 { 99 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_SWSTART, 0, 0, 100 (caddr_t *)(uintptr_t)chnl, 0)); 101 } 102 103 int 104 ddi_dmae_stop(dev_info_t *dip, int chnl) 105 { 106 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_STOP, 0, 0, 107 (caddr_t *)(uintptr_t)chnl, 0)); 108 } 109 110 int 111 ddi_dmae_enable(dev_info_t *dip, int chnl) 112 { 113 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_ENABLE, 0, 0, 114 (caddr_t *)(uintptr_t)chnl, 0)); 115 } 116 117 int 118 ddi_dmae_disable(dev_info_t *dip, int chnl) 119 { 120 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_DISABLE, 0, 0, 121 (caddr_t *)(uintptr_t)chnl, 0)); 122 } 123 124 int 125 ddi_dmae_getcnt(dev_info_t *dip, int chnl, int *countp) 126 { 127 return (ddi_dma_mctl(dip, dip, 0, DDI_DMA_E_GETCNT, 0, (size_t *)countp, 128 (caddr_t *)(uintptr_t)chnl, 0)); 129 } 130 131 /* 132 * implementation specific access handle and routines: 133 */ 134 135 static uintptr_t impl_acc_hdl_id = 0; 136 137 /* 138 * access handle allocator 139 */ 140 ddi_acc_hdl_t * 141 impl_acc_hdl_get(ddi_acc_handle_t hdl) 142 { 143 /* 144 * recast to ddi_acc_hdl_t instead of 145 * casting to ddi_acc_impl_t and then return the ah_platform_private 146 * 147 * this optimization based on the ddi_acc_hdl_t is the 148 * first member of the ddi_acc_impl_t. 149 */ 150 return ((ddi_acc_hdl_t *)hdl); 151 } 152 153 ddi_acc_handle_t 154 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg) 155 { 156 ddi_acc_impl_t *hp; 157 on_trap_data_t *otp; 158 int sleepflag; 159 160 sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 161 /* 162 * Allocate and initialize the data access handle and error status. 163 */ 164 if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL) 165 goto fail; 166 if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc( 167 sizeof (ndi_err_t), sleepflag)) == NULL) { 168 kmem_free(hp, sizeof (ddi_acc_impl_t)); 169 goto fail; 170 } 171 if ((otp = (on_trap_data_t *)kmem_zalloc( 172 sizeof (on_trap_data_t), sleepflag)) == NULL) { 173 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 174 kmem_free(hp, sizeof (ddi_acc_impl_t)); 175 goto fail; 176 } 177 hp->ahi_err->err_ontrap = otp; 178 hp->ahi_common.ah_platform_private = (void *)hp; 179 180 return ((ddi_acc_handle_t)hp); 181 fail: 182 if ((waitfp != (int (*)())KM_SLEEP) && 183 (waitfp != (int (*)())KM_NOSLEEP)) 184 ddi_set_callback(waitfp, arg, &impl_acc_hdl_id); 185 return (NULL); 186 } 187 188 void 189 impl_acc_hdl_free(ddi_acc_handle_t handle) 190 { 191 ddi_acc_impl_t *hp; 192 193 /* 194 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *), 195 * because that's what we allocated in impl_acc_hdl_alloc() above. 196 */ 197 hp = (ddi_acc_impl_t *)handle; 198 if (hp) { 199 kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t)); 200 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 201 kmem_free(hp, sizeof (ddi_acc_impl_t)); 202 if (impl_acc_hdl_id) 203 ddi_run_callback(&impl_acc_hdl_id); 204 } 205 } 206 207 /* 208 * Function used to check if a given access handle owns the failing address. 209 * Called by ndi_fmc_error, when we detect a PIO error. 210 */ 211 /* ARGSUSED */ 212 static int 213 impl_acc_check(dev_info_t *dip, const void *handle, const void *addr, 214 const void *not_used) 215 { 216 pfn_t pfn, fault_pfn; 217 ddi_acc_hdl_t *hp; 218 219 hp = impl_acc_hdl_get((ddi_acc_handle_t)handle); 220 221 ASSERT(hp); 222 223 if (addr != NULL) { 224 pfn = hp->ah_pfn; 225 fault_pfn = mmu_btop(*(uint64_t *)addr); 226 if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum)) 227 return (DDI_FM_NONFATAL); 228 } 229 return (DDI_FM_UNKNOWN); 230 } 231 232 void 233 impl_acc_err_init(ddi_acc_hdl_t *handlep) 234 { 235 int fmcap; 236 ndi_err_t *errp; 237 on_trap_data_t *otp; 238 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep; 239 240 fmcap = ddi_fm_capable(handlep->ah_dip); 241 242 if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 || 243 !DDI_FM_ACC_ERR_CAP(fmcap)) { 244 handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC; 245 } else if (DDI_FM_ACC_ERR_CAP(fmcap)) { 246 if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) { 247 i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP, 248 NULL, DDI_NOSLEEP); 249 } else { 250 errp = hp->ahi_err; 251 otp = (on_trap_data_t *)errp->err_ontrap; 252 otp->ot_handle = (void *)(hp); 253 otp->ot_prot = OT_DATA_ACCESS; 254 errp->err_status = DDI_FM_OK; 255 errp->err_expected = DDI_FM_ERR_UNEXPECTED; 256 errp->err_cf = impl_acc_check; 257 } 258 } 259 } 260 261 /* ARGSUSED */ 262 int 263 impl_dma_check(dev_info_t *dip, const void *handle, const void *pci_hdl, 264 const void *not_used) 265 { 266 return (DDI_FM_UNKNOWN); 267 } 268 269 void 270 impl_acc_hdl_init(ddi_acc_hdl_t *handlep) 271 { 272 ddi_acc_impl_t *hp; 273 int fmcap; 274 int devacc_attr_access; 275 276 if (!handlep) 277 return; 278 fmcap = ddi_fm_capable(handlep->ah_dip); 279 if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 || 280 !DDI_FM_ACC_ERR_CAP(fmcap)) 281 devacc_attr_access = DDI_DEFAULT_ACC; 282 else 283 devacc_attr_access = handlep->ah_acc.devacc_attr_access; 284 285 hp = (ddi_acc_impl_t *)handlep->ah_platform_private; 286 switch (devacc_attr_access) { 287 case DDI_FLAGERR_ACC: 288 case DDI_CAUTIOUS_ACC: 289 hp->ahi_get8 = i_ddi_caut_get8; 290 hp->ahi_put8 = i_ddi_caut_put8; 291 hp->ahi_rep_get8 = i_ddi_caut_rep_get8; 292 hp->ahi_rep_put8 = i_ddi_caut_rep_put8; 293 hp->ahi_get16 = i_ddi_caut_get16; 294 hp->ahi_get32 = i_ddi_caut_get32; 295 hp->ahi_put16 = i_ddi_caut_put16; 296 hp->ahi_put32 = i_ddi_caut_put32; 297 hp->ahi_rep_get16 = i_ddi_caut_rep_get16; 298 hp->ahi_rep_get32 = i_ddi_caut_rep_get32; 299 hp->ahi_rep_put16 = i_ddi_caut_rep_put16; 300 hp->ahi_rep_put32 = i_ddi_caut_rep_put32; 301 hp->ahi_get64 = i_ddi_caut_get64; 302 hp->ahi_put64 = i_ddi_caut_put64; 303 hp->ahi_rep_get64 = i_ddi_caut_rep_get64; 304 hp->ahi_rep_put64 = i_ddi_caut_rep_put64; 305 break; 306 case DDI_DEFAULT_ACC: 307 if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) { 308 hp->ahi_get8 = i_ddi_io_get8; 309 hp->ahi_put8 = i_ddi_io_put8; 310 hp->ahi_rep_get8 = i_ddi_io_rep_get8; 311 hp->ahi_rep_put8 = i_ddi_io_rep_put8; 312 313 /* temporary set these 64 functions to no-ops */ 314 hp->ahi_get64 = i_ddi_io_get64; 315 hp->ahi_put64 = i_ddi_io_put64; 316 hp->ahi_rep_get64 = i_ddi_io_rep_get64; 317 hp->ahi_rep_put64 = i_ddi_io_rep_put64; 318 319 /* 320 * check for BIG endian access 321 */ 322 if (handlep->ah_acc.devacc_attr_endian_flags == 323 DDI_STRUCTURE_BE_ACC) { 324 hp->ahi_get16 = i_ddi_io_swap_get16; 325 hp->ahi_get32 = i_ddi_io_swap_get32; 326 hp->ahi_put16 = i_ddi_io_swap_put16; 327 hp->ahi_put32 = i_ddi_io_swap_put32; 328 hp->ahi_rep_get16 = i_ddi_io_swap_rep_get16; 329 hp->ahi_rep_get32 = i_ddi_io_swap_rep_get32; 330 hp->ahi_rep_put16 = i_ddi_io_swap_rep_put16; 331 hp->ahi_rep_put32 = i_ddi_io_swap_rep_put32; 332 } else { 333 hp->ahi_acc_attr |= DDI_ACCATTR_DIRECT; 334 hp->ahi_get16 = i_ddi_io_get16; 335 hp->ahi_get32 = i_ddi_io_get32; 336 hp->ahi_put16 = i_ddi_io_put16; 337 hp->ahi_put32 = i_ddi_io_put32; 338 hp->ahi_rep_get16 = i_ddi_io_rep_get16; 339 hp->ahi_rep_get32 = i_ddi_io_rep_get32; 340 hp->ahi_rep_put16 = i_ddi_io_rep_put16; 341 hp->ahi_rep_put32 = i_ddi_io_rep_put32; 342 } 343 344 } else if (hp->ahi_acc_attr & DDI_ACCATTR_CPU_VADDR) { 345 346 hp->ahi_get8 = i_ddi_vaddr_get8; 347 hp->ahi_put8 = i_ddi_vaddr_put8; 348 hp->ahi_rep_get8 = i_ddi_vaddr_rep_get8; 349 hp->ahi_rep_put8 = i_ddi_vaddr_rep_put8; 350 351 /* 352 * check for BIG endian access 353 */ 354 if (handlep->ah_acc.devacc_attr_endian_flags == 355 DDI_STRUCTURE_BE_ACC) { 356 357 hp->ahi_get16 = i_ddi_vaddr_swap_get16; 358 hp->ahi_get32 = i_ddi_vaddr_swap_get32; 359 hp->ahi_get64 = i_ddi_vaddr_swap_get64; 360 hp->ahi_put16 = i_ddi_vaddr_swap_put16; 361 hp->ahi_put32 = i_ddi_vaddr_swap_put32; 362 hp->ahi_put64 = i_ddi_vaddr_swap_put64; 363 hp->ahi_rep_get16 = i_ddi_vaddr_swap_rep_get16; 364 hp->ahi_rep_get32 = i_ddi_vaddr_swap_rep_get32; 365 hp->ahi_rep_get64 = i_ddi_vaddr_swap_rep_get64; 366 hp->ahi_rep_put16 = i_ddi_vaddr_swap_rep_put16; 367 hp->ahi_rep_put32 = i_ddi_vaddr_swap_rep_put32; 368 hp->ahi_rep_put64 = i_ddi_vaddr_swap_rep_put64; 369 } else { 370 hp->ahi_acc_attr |= DDI_ACCATTR_DIRECT; 371 hp->ahi_get16 = i_ddi_vaddr_get16; 372 hp->ahi_get32 = i_ddi_vaddr_get32; 373 hp->ahi_get64 = i_ddi_vaddr_get64; 374 hp->ahi_put16 = i_ddi_vaddr_put16; 375 hp->ahi_put32 = i_ddi_vaddr_put32; 376 hp->ahi_put64 = i_ddi_vaddr_put64; 377 hp->ahi_rep_get16 = i_ddi_vaddr_rep_get16; 378 hp->ahi_rep_get32 = i_ddi_vaddr_rep_get32; 379 hp->ahi_rep_get64 = i_ddi_vaddr_rep_get64; 380 hp->ahi_rep_put16 = i_ddi_vaddr_rep_put16; 381 hp->ahi_rep_put32 = i_ddi_vaddr_rep_put32; 382 hp->ahi_rep_put64 = i_ddi_vaddr_rep_put64; 383 } 384 } 385 break; 386 } 387 hp->ahi_fault_check = i_ddi_acc_fault_check; 388 hp->ahi_fault_notify = i_ddi_acc_fault_notify; 389 hp->ahi_fault = 0; 390 impl_acc_err_init(handlep); 391 } 392 393 /* 394 * The followings are low-level routines for data access. 395 * 396 * All of these routines should be implemented in assembly. Those 397 * that have been rewritten be found in ~ml/ddi_i86_asm.s 398 */ 399 400 /*ARGSUSED*/ 401 uint16_t 402 i_ddi_vaddr_swap_get16(ddi_acc_impl_t *hdlp, uint16_t *addr) 403 { 404 return (ddi_swap16(*addr)); 405 } 406 407 /*ARGSUSED*/ 408 uint16_t 409 i_ddi_io_swap_get16(ddi_acc_impl_t *hdlp, uint16_t *addr) 410 { 411 return (ddi_swap16(inw((uintptr_t)addr))); 412 } 413 414 /*ARGSUSED*/ 415 uint32_t 416 i_ddi_vaddr_swap_get32(ddi_acc_impl_t *hdlp, uint32_t *addr) 417 { 418 return (ddi_swap32(*addr)); 419 } 420 421 /*ARGSUSED*/ 422 uint32_t 423 i_ddi_io_swap_get32(ddi_acc_impl_t *hdlp, uint32_t *addr) 424 { 425 return (ddi_swap32(inl((uintptr_t)addr))); 426 } 427 428 /*ARGSUSED*/ 429 uint64_t 430 i_ddi_vaddr_swap_get64(ddi_acc_impl_t *hdlp, uint64_t *addr) 431 { 432 return (ddi_swap64(*addr)); 433 } 434 435 /*ARGSUSED*/ 436 void 437 i_ddi_vaddr_swap_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) 438 { 439 *addr = ddi_swap16(value); 440 } 441 442 /*ARGSUSED*/ 443 void 444 i_ddi_io_swap_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) 445 { 446 outw((uintptr_t)addr, ddi_swap16(value)); 447 } 448 449 /*ARGSUSED*/ 450 void 451 i_ddi_vaddr_swap_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) 452 { 453 *addr = ddi_swap32(value); 454 } 455 456 /*ARGSUSED*/ 457 void 458 i_ddi_io_swap_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) 459 { 460 outl((uintptr_t)addr, ddi_swap32(value)); 461 } 462 463 /*ARGSUSED*/ 464 void 465 i_ddi_vaddr_swap_put64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) 466 { 467 *addr = ddi_swap64(value); 468 } 469 470 /*ARGSUSED*/ 471 void 472 i_ddi_vaddr_rep_get8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 473 uint8_t *dev_addr, size_t repcount, uint_t flags) 474 { 475 uint8_t *h, *d; 476 477 h = host_addr; 478 d = dev_addr; 479 480 if (flags == DDI_DEV_AUTOINCR) 481 for (; repcount; repcount--) 482 *h++ = *d++; 483 else 484 for (; repcount; repcount--) 485 *h++ = *d; 486 } 487 488 /*ARGSUSED*/ 489 void 490 i_ddi_vaddr_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 491 uint16_t *dev_addr, size_t repcount, uint_t flags) 492 { 493 uint16_t *h, *d; 494 495 h = host_addr; 496 d = dev_addr; 497 498 if (flags == DDI_DEV_AUTOINCR) 499 for (; repcount; repcount--) 500 *h++ = *d++; 501 else 502 for (; repcount; repcount--) 503 *h++ = *d; 504 } 505 506 /*ARGSUSED*/ 507 void 508 i_ddi_vaddr_swap_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 509 uint16_t *dev_addr, size_t repcount, uint_t flags) 510 { 511 uint16_t *h, *d; 512 513 h = host_addr; 514 d = dev_addr; 515 516 if (flags == DDI_DEV_AUTOINCR) 517 for (; repcount; repcount--) 518 *h++ = ddi_swap16(*d++); 519 else 520 for (; repcount; repcount--) 521 *h++ = ddi_swap16(*d); 522 } 523 524 /*ARGSUSED*/ 525 void 526 i_ddi_io_swap_rep_get16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 527 uint16_t *dev_addr, size_t repcount, uint_t flags) 528 { 529 uint16_t *h; 530 uintptr_t port; 531 532 h = host_addr; 533 port = (uintptr_t)dev_addr; 534 535 if (flags == DDI_DEV_AUTOINCR) 536 for (; repcount; repcount--, port += 2) 537 *h++ = ddi_swap16(inw(port)); 538 else 539 for (; repcount; repcount--) 540 *h++ = ddi_swap16(inw(port)); 541 } 542 543 /*ARGSUSED*/ 544 void 545 i_ddi_vaddr_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 546 uint32_t *dev_addr, size_t repcount, uint_t flags) 547 { 548 uint32_t *h, *d; 549 550 h = host_addr; 551 d = dev_addr; 552 553 if (flags == DDI_DEV_AUTOINCR) 554 for (; repcount; repcount--) 555 *h++ = *d++; 556 else 557 for (; repcount; repcount--) 558 *h++ = *d; 559 } 560 561 /*ARGSUSED*/ 562 void 563 i_ddi_vaddr_swap_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 564 uint32_t *dev_addr, size_t repcount, uint_t flags) 565 { 566 uint32_t *h, *d; 567 568 h = host_addr; 569 d = dev_addr; 570 571 if (flags == DDI_DEV_AUTOINCR) 572 for (; repcount; repcount--) 573 *h++ = ddi_swap32(*d++); 574 else 575 for (; repcount; repcount--) 576 *h++ = ddi_swap32(*d); 577 } 578 579 /*ARGSUSED*/ 580 void 581 i_ddi_io_swap_rep_get32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 582 uint32_t *dev_addr, size_t repcount, uint_t flags) 583 { 584 uint32_t *h; 585 uintptr_t port; 586 587 h = host_addr; 588 port = (uintptr_t)dev_addr; 589 590 if (flags == DDI_DEV_AUTOINCR) 591 for (; repcount; repcount--, port += 4) 592 *h++ = ddi_swap32(inl(port)); 593 else 594 for (; repcount; repcount--) 595 *h++ = ddi_swap32(inl(port)); 596 } 597 598 /*ARGSUSED*/ 599 void 600 i_ddi_vaddr_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 601 uint64_t *dev_addr, size_t repcount, uint_t flags) 602 { 603 uint64_t *h, *d; 604 605 h = host_addr; 606 d = dev_addr; 607 608 if (flags == DDI_DEV_AUTOINCR) 609 for (; repcount; repcount--) 610 *h++ = *d++; 611 else 612 for (; repcount; repcount--) 613 *h++ = *d; 614 } 615 616 /*ARGSUSED*/ 617 void 618 i_ddi_vaddr_swap_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 619 uint64_t *dev_addr, size_t repcount, uint_t flags) 620 { 621 uint64_t *h, *d; 622 623 h = host_addr; 624 d = dev_addr; 625 626 if (flags == DDI_DEV_AUTOINCR) 627 for (; repcount; repcount--) 628 *h++ = ddi_swap64(*d++); 629 else 630 for (; repcount; repcount--) 631 *h++ = ddi_swap64(*d); 632 } 633 634 /*ARGSUSED*/ 635 void 636 i_ddi_vaddr_rep_put8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 637 uint8_t *dev_addr, size_t repcount, uint_t flags) 638 { 639 uint8_t *h, *d; 640 641 h = host_addr; 642 d = dev_addr; 643 644 if (flags == DDI_DEV_AUTOINCR) 645 for (; repcount; repcount--) 646 *d++ = *h++; 647 else 648 for (; repcount; repcount--) 649 *d = *h++; 650 } 651 652 /*ARGSUSED*/ 653 void 654 i_ddi_vaddr_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 655 uint16_t *dev_addr, size_t repcount, uint_t flags) 656 { 657 uint16_t *h, *d; 658 659 h = host_addr; 660 d = dev_addr; 661 662 if (flags == DDI_DEV_AUTOINCR) 663 for (; repcount; repcount--) 664 *d++ = *h++; 665 else 666 for (; repcount; repcount--) 667 *d = *h++; 668 } 669 670 /*ARGSUSED*/ 671 void 672 i_ddi_vaddr_swap_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 673 uint16_t *dev_addr, size_t repcount, uint_t flags) 674 { 675 uint16_t *h, *d; 676 677 h = host_addr; 678 d = dev_addr; 679 680 if (flags == DDI_DEV_AUTOINCR) 681 for (; repcount; repcount--) 682 *d++ = ddi_swap16(*h++); 683 else 684 for (; repcount; repcount--) 685 *d = ddi_swap16(*h++); 686 } 687 688 /*ARGSUSED*/ 689 void 690 i_ddi_io_swap_rep_put16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 691 uint16_t *dev_addr, size_t repcount, uint_t flags) 692 { 693 uint16_t *h; 694 uintptr_t port; 695 696 h = host_addr; 697 port = (uintptr_t)dev_addr; 698 699 if (flags == DDI_DEV_AUTOINCR) 700 for (; repcount; repcount--, port += 2) 701 outw(port, ddi_swap16(*h++)); 702 else 703 for (; repcount; repcount--) 704 outw(port, ddi_swap16(*h++)); 705 } 706 707 /*ARGSUSED*/ 708 void 709 i_ddi_vaddr_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 710 uint32_t *dev_addr, size_t repcount, uint_t flags) 711 { 712 uint32_t *h, *d; 713 714 h = host_addr; 715 d = dev_addr; 716 717 if (flags == DDI_DEV_AUTOINCR) 718 for (; repcount; repcount--) 719 *d++ = *h++; 720 else 721 for (; repcount; repcount--) 722 *d = *h++; 723 } 724 725 /*ARGSUSED*/ 726 void 727 i_ddi_vaddr_swap_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 728 uint32_t *dev_addr, size_t repcount, uint_t flags) 729 { 730 uint32_t *h, *d; 731 732 h = host_addr; 733 d = dev_addr; 734 735 if (flags == DDI_DEV_AUTOINCR) 736 for (; repcount; repcount--) 737 *d++ = ddi_swap32(*h++); 738 else 739 for (; repcount; repcount--) 740 *d = ddi_swap32(*h++); 741 } 742 743 /*ARGSUSED*/ 744 void 745 i_ddi_io_swap_rep_put32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 746 uint32_t *dev_addr, size_t repcount, uint_t flags) 747 { 748 uint32_t *h; 749 uintptr_t port; 750 751 h = host_addr; 752 port = (uintptr_t)dev_addr; 753 754 if (flags == DDI_DEV_AUTOINCR) 755 for (; repcount; repcount--, port += 4) 756 outl(port, ddi_swap32(*h++)); 757 else 758 for (; repcount; repcount--) 759 outl(port, ddi_swap32(*h++)); 760 } 761 762 /*ARGSUSED*/ 763 void 764 i_ddi_vaddr_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 765 uint64_t *dev_addr, size_t repcount, uint_t flags) 766 { 767 uint64_t *h, *d; 768 769 h = host_addr; 770 d = dev_addr; 771 772 if (flags == DDI_DEV_AUTOINCR) 773 for (; repcount; repcount--) 774 *d++ = *h++; 775 else 776 for (; repcount; repcount--) 777 *d = *h++; 778 } 779 780 /*ARGSUSED*/ 781 void 782 i_ddi_vaddr_swap_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 783 uint64_t *dev_addr, size_t repcount, uint_t flags) 784 { 785 uint64_t *h, *d; 786 787 h = host_addr; 788 d = dev_addr; 789 790 if (flags == DDI_DEV_AUTOINCR) 791 for (; repcount; repcount--) 792 *d++ = ddi_swap64(*h++); 793 else 794 for (; repcount; repcount--) 795 *d = ddi_swap64(*h++); 796 } 797 798 /*ARGSUSED*/ 799 uint64_t 800 i_ddi_io_get64(ddi_acc_impl_t *hdlp, uint64_t *addr) 801 { 802 panic("ddi_get64 from i/o space"); 803 /*NOTREACHED*/ 804 return (0); 805 } 806 807 /*ARGSUSED*/ 808 void 809 i_ddi_io_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, uint64_t value) 810 { 811 panic("ddi_put64 to i/o space"); 812 /*NOTREACHED*/ 813 } 814 815 void 816 ddi_io_rep_get8(ddi_acc_handle_t handle, 817 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) 818 { 819 (((ddi_acc_impl_t *)handle)->ahi_rep_get8) 820 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 821 repcount, DDI_DEV_NO_AUTOINCR); 822 } 823 824 void 825 ddi_io_rep_get16(ddi_acc_handle_t handle, 826 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) 827 { 828 (((ddi_acc_impl_t *)handle)->ahi_rep_get16) 829 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 830 repcount, DDI_DEV_NO_AUTOINCR); 831 } 832 833 void 834 ddi_io_rep_get32(ddi_acc_handle_t handle, 835 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) 836 { 837 (((ddi_acc_impl_t *)handle)->ahi_rep_get32) 838 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 839 repcount, DDI_DEV_NO_AUTOINCR); 840 } 841 842 /*ARGSUSED*/ 843 void 844 i_ddi_io_rep_get64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 845 uint64_t *dev_addr, size_t repcount, uint_t flags) 846 { 847 cmn_err(CE_PANIC, "ddi_rep_get64 from i/o space"); 848 } 849 850 void 851 ddi_io_rep_put8(ddi_acc_handle_t handle, 852 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) 853 { 854 (((ddi_acc_impl_t *)handle)->ahi_rep_put8) 855 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 856 repcount, DDI_DEV_NO_AUTOINCR); 857 } 858 859 void 860 ddi_io_rep_put16(ddi_acc_handle_t handle, 861 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) 862 { 863 (((ddi_acc_impl_t *)handle)->ahi_rep_put16) 864 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 865 repcount, DDI_DEV_NO_AUTOINCR); 866 } 867 868 void 869 ddi_io_rep_put32(ddi_acc_handle_t handle, 870 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) 871 { 872 (((ddi_acc_impl_t *)handle)->ahi_rep_put32) 873 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 874 repcount, DDI_DEV_NO_AUTOINCR); 875 } 876 877 /*ARGSUSED*/ 878 void 879 i_ddi_io_rep_put64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 880 uint64_t *dev_addr, size_t repcount, uint_t flags) 881 { 882 cmn_err(CE_PANIC, "ddi_rep_put64 to i/o space"); 883 } 884 885 /* 886 * We need to separate the old interfaces from the new ones and leave them 887 * in here for a while. Previous versions of the OS defined the new interfaces 888 * to the old interfaces. This way we can fix things up so that we can 889 * eventually remove these interfaces. 890 * e.g. A 3rd party module/driver using ddi_io_rep_get8 and built against S10 891 * or earlier will actually have a reference to ddi_io_rep_getb in the binary. 892 */ 893 #ifdef _ILP32 894 void 895 ddi_io_rep_getb(ddi_acc_handle_t handle, 896 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) 897 { 898 (((ddi_acc_impl_t *)handle)->ahi_rep_get8) 899 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 900 repcount, DDI_DEV_NO_AUTOINCR); 901 } 902 903 void 904 ddi_io_rep_getw(ddi_acc_handle_t handle, 905 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) 906 { 907 (((ddi_acc_impl_t *)handle)->ahi_rep_get16) 908 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 909 repcount, DDI_DEV_NO_AUTOINCR); 910 } 911 912 void 913 ddi_io_rep_getl(ddi_acc_handle_t handle, 914 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) 915 { 916 (((ddi_acc_impl_t *)handle)->ahi_rep_get32) 917 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 918 repcount, DDI_DEV_NO_AUTOINCR); 919 } 920 921 void 922 ddi_io_rep_putb(ddi_acc_handle_t handle, 923 uint8_t *host_addr, uint8_t *dev_addr, size_t repcount) 924 { 925 (((ddi_acc_impl_t *)handle)->ahi_rep_put8) 926 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 927 repcount, DDI_DEV_NO_AUTOINCR); 928 } 929 930 void 931 ddi_io_rep_putw(ddi_acc_handle_t handle, 932 uint16_t *host_addr, uint16_t *dev_addr, size_t repcount) 933 { 934 (((ddi_acc_impl_t *)handle)->ahi_rep_put16) 935 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 936 repcount, DDI_DEV_NO_AUTOINCR); 937 } 938 939 void 940 ddi_io_rep_putl(ddi_acc_handle_t handle, 941 uint32_t *host_addr, uint32_t *dev_addr, size_t repcount) 942 { 943 (((ddi_acc_impl_t *)handle)->ahi_rep_put32) 944 ((ddi_acc_impl_t *)handle, host_addr, dev_addr, 945 repcount, DDI_DEV_NO_AUTOINCR); 946 } 947 #endif /* _ILP32 */ 948 949 /* 950 * These next two functions could be translated into assembler someday 951 */ 952 int 953 ddi_check_acc_handle(ddi_acc_handle_t handle) 954 { 955 ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle; 956 return (((*hdlp->ahi_fault_check)(hdlp) == DDI_SUCCESS) ? DDI_SUCCESS : 957 DDI_FAILURE); 958 } 959 960 int 961 i_ddi_acc_fault_check(ddi_acc_impl_t *hdlp) 962 { 963 /* Default version, just returns flag value */ 964 return (hdlp->ahi_fault); 965 } 966 967 /*ARGSUSED*/ 968 void 969 i_ddi_acc_fault_notify(ddi_acc_impl_t *hdlp) 970 { 971 /* Default version, does nothing for now */ 972 } 973 974 void 975 i_ddi_acc_set_fault(ddi_acc_handle_t handle) 976 { 977 ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle; 978 979 if (!hdlp->ahi_fault) { 980 hdlp->ahi_fault = 1; 981 (*hdlp->ahi_fault_notify)(hdlp); 982 } 983 } 984 985 void 986 i_ddi_acc_clr_fault(ddi_acc_handle_t handle) 987 { 988 ddi_acc_impl_t *hdlp = (ddi_acc_impl_t *)handle; 989 990 if (hdlp->ahi_fault) { 991 hdlp->ahi_fault = 0; 992 (*hdlp->ahi_fault_notify)(hdlp); 993 } 994 } 995