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 2007 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/note.h> 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/buf.h> 34 #include <sys/uio.h> 35 #include <sys/cred.h> 36 #include <sys/poll.h> 37 #include <sys/mman.h> 38 #include <sys/kmem.h> 39 #include <sys/model.h> 40 #include <sys/file.h> 41 #include <sys/proc.h> 42 #include <sys/open.h> 43 #include <sys/user.h> 44 #include <sys/t_lock.h> 45 #include <sys/vm.h> 46 #include <sys/stat.h> 47 #include <vm/hat.h> 48 #include <vm/seg.h> 49 #include <vm/seg_vn.h> 50 #include <vm/seg_dev.h> 51 #include <vm/as.h> 52 #include <sys/cmn_err.h> 53 #include <sys/cpuvar.h> 54 #include <sys/debug.h> 55 #include <sys/autoconf.h> 56 #include <sys/sunddi.h> 57 #include <sys/esunddi.h> 58 #include <sys/sunndi.h> 59 #include <sys/kstat.h> 60 #include <sys/conf.h> 61 #include <sys/ddi_impldefs.h> /* include implementation structure defs */ 62 #include <sys/ndi_impldefs.h> /* include prototypes */ 63 #include <sys/hwconf.h> 64 #include <sys/pathname.h> 65 #include <sys/modctl.h> 66 #include <sys/epm.h> 67 #include <sys/devctl.h> 68 #include <sys/callb.h> 69 #include <sys/cladm.h> 70 #include <sys/sysevent.h> 71 #include <sys/dacf_impl.h> 72 #include <sys/ddidevmap.h> 73 #include <sys/bootconf.h> 74 #include <sys/disp.h> 75 #include <sys/atomic.h> 76 #include <sys/promif.h> 77 #include <sys/instance.h> 78 #include <sys/sysevent/eventdefs.h> 79 #include <sys/task.h> 80 #include <sys/project.h> 81 #include <sys/taskq.h> 82 #include <sys/devpolicy.h> 83 #include <sys/ctype.h> 84 #include <net/if.h> 85 #include <sys/rctl.h> 86 87 extern pri_t minclsyspri; 88 89 extern rctl_hndl_t rc_project_locked_mem; 90 extern rctl_hndl_t rc_zone_locked_mem; 91 92 #ifdef DEBUG 93 static int sunddi_debug = 0; 94 #endif /* DEBUG */ 95 96 /* ddi_umem_unlock miscellaneous */ 97 98 static void i_ddi_umem_unlock_thread_start(void); 99 100 static kmutex_t ddi_umem_unlock_mutex; /* unlock list mutex */ 101 static kcondvar_t ddi_umem_unlock_cv; /* unlock list block/unblock */ 102 static kthread_t *ddi_umem_unlock_thread; 103 /* 104 * The ddi_umem_unlock FIFO list. NULL head pointer indicates empty list. 105 */ 106 static struct ddi_umem_cookie *ddi_umem_unlock_head = NULL; 107 static struct ddi_umem_cookie *ddi_umem_unlock_tail = NULL; 108 109 110 /* 111 * DDI(Sun) Function and flag definitions: 112 */ 113 114 #if defined(__x86) 115 /* 116 * Used to indicate which entries were chosen from a range. 117 */ 118 char *chosen_reg = "chosen-reg"; 119 #endif 120 121 /* 122 * Function used to ring system console bell 123 */ 124 void (*ddi_console_bell_func)(clock_t duration); 125 126 /* 127 * Creating register mappings and handling interrupts: 128 */ 129 130 /* 131 * Generic ddi_map: Call parent to fulfill request... 132 */ 133 134 int 135 ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset, 136 off_t len, caddr_t *addrp) 137 { 138 dev_info_t *pdip; 139 140 ASSERT(dp); 141 pdip = (dev_info_t *)DEVI(dp)->devi_parent; 142 return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip, 143 dp, mp, offset, len, addrp)); 144 } 145 146 /* 147 * ddi_apply_range: (Called by nexi only.) 148 * Apply ranges in parent node dp, to child regspec rp... 149 */ 150 151 int 152 ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp) 153 { 154 return (i_ddi_apply_range(dp, rdip, rp)); 155 } 156 157 int 158 ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 159 off_t len) 160 { 161 ddi_map_req_t mr; 162 #if defined(__x86) 163 struct { 164 int bus; 165 int addr; 166 int size; 167 } reg, *reglist; 168 uint_t length; 169 int rc; 170 171 /* 172 * get the 'registers' or the 'reg' property. 173 * We look up the reg property as an array of 174 * int's. 175 */ 176 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 177 DDI_PROP_DONTPASS, "registers", (int **)®list, &length); 178 if (rc != DDI_PROP_SUCCESS) 179 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 180 DDI_PROP_DONTPASS, "reg", (int **)®list, &length); 181 if (rc == DDI_PROP_SUCCESS) { 182 /* 183 * point to the required entry. 184 */ 185 reg = reglist[rnumber]; 186 reg.addr += offset; 187 if (len != 0) 188 reg.size = len; 189 /* 190 * make a new property containing ONLY the required tuple. 191 */ 192 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 193 chosen_reg, (int *)®, (sizeof (reg)/sizeof (int))) 194 != DDI_PROP_SUCCESS) { 195 cmn_err(CE_WARN, "%s%d: cannot create '%s' " 196 "property", DEVI(dip)->devi_name, 197 DEVI(dip)->devi_instance, chosen_reg); 198 } 199 /* 200 * free the memory allocated by 201 * ddi_prop_lookup_int_array (). 202 */ 203 ddi_prop_free((void *)reglist); 204 } 205 #endif 206 mr.map_op = DDI_MO_MAP_LOCKED; 207 mr.map_type = DDI_MT_RNUMBER; 208 mr.map_obj.rnumber = rnumber; 209 mr.map_prot = PROT_READ | PROT_WRITE; 210 mr.map_flags = DDI_MF_KERNEL_MAPPING; 211 mr.map_handlep = NULL; 212 mr.map_vers = DDI_MAP_VERSION; 213 214 /* 215 * Call my parent to map in my regs. 216 */ 217 218 return (ddi_map(dip, &mr, offset, len, kaddrp)); 219 } 220 221 void 222 ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 223 off_t len) 224 { 225 ddi_map_req_t mr; 226 227 mr.map_op = DDI_MO_UNMAP; 228 mr.map_type = DDI_MT_RNUMBER; 229 mr.map_flags = DDI_MF_KERNEL_MAPPING; 230 mr.map_prot = PROT_READ | PROT_WRITE; /* who cares? */ 231 mr.map_obj.rnumber = rnumber; 232 mr.map_handlep = NULL; 233 mr.map_vers = DDI_MAP_VERSION; 234 235 /* 236 * Call my parent to unmap my regs. 237 */ 238 239 (void) ddi_map(dip, &mr, offset, len, kaddrp); 240 *kaddrp = (caddr_t)0; 241 #if defined(__x86) 242 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg); 243 #endif 244 } 245 246 int 247 ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 248 off_t offset, off_t len, caddr_t *vaddrp) 249 { 250 return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp)); 251 } 252 253 /* 254 * nullbusmap: The/DDI default bus_map entry point for nexi 255 * not conforming to the reg/range paradigm (i.e. scsi, etc.) 256 * with no HAT/MMU layer to be programmed at this level. 257 * 258 * If the call is to map by rnumber, return an error, 259 * otherwise pass anything else up the tree to my parent. 260 */ 261 int 262 nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 263 off_t offset, off_t len, caddr_t *vaddrp) 264 { 265 _NOTE(ARGUNUSED(rdip)) 266 if (mp->map_type == DDI_MT_RNUMBER) 267 return (DDI_ME_UNSUPPORTED); 268 269 return (ddi_map(dip, mp, offset, len, vaddrp)); 270 } 271 272 /* 273 * ddi_rnumber_to_regspec: Not for use by leaf drivers. 274 * Only for use by nexi using the reg/range paradigm. 275 */ 276 struct regspec * 277 ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber) 278 { 279 return (i_ddi_rnumber_to_regspec(dip, rnumber)); 280 } 281 282 283 /* 284 * Note that we allow the dip to be nil because we may be called 285 * prior even to the instantiation of the devinfo tree itself - all 286 * regular leaf and nexus drivers should always use a non-nil dip! 287 * 288 * We treat peek in a somewhat cavalier fashion .. assuming that we'll 289 * simply get a synchronous fault as soon as we touch a missing address. 290 * 291 * Poke is rather more carefully handled because we might poke to a write 292 * buffer, "succeed", then only find some time later that we got an 293 * asynchronous fault that indicated that the address we were writing to 294 * was not really backed by hardware. 295 */ 296 297 static int 298 i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size, 299 void *addr, void *value_p) 300 { 301 union { 302 uint64_t u64; 303 uint32_t u32; 304 uint16_t u16; 305 uint8_t u8; 306 } peekpoke_value; 307 308 peekpoke_ctlops_t peekpoke_args; 309 uint64_t dummy_result; 310 int rval; 311 312 /* Note: size is assumed to be correct; it is not checked. */ 313 peekpoke_args.size = size; 314 peekpoke_args.dev_addr = (uintptr_t)addr; 315 peekpoke_args.handle = NULL; 316 peekpoke_args.repcount = 1; 317 peekpoke_args.flags = 0; 318 319 if (cmd == DDI_CTLOPS_POKE) { 320 switch (size) { 321 case sizeof (uint8_t): 322 peekpoke_value.u8 = *(uint8_t *)value_p; 323 break; 324 case sizeof (uint16_t): 325 peekpoke_value.u16 = *(uint16_t *)value_p; 326 break; 327 case sizeof (uint32_t): 328 peekpoke_value.u32 = *(uint32_t *)value_p; 329 break; 330 case sizeof (uint64_t): 331 peekpoke_value.u64 = *(uint64_t *)value_p; 332 break; 333 } 334 } 335 336 peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64; 337 338 if (devi != NULL) 339 rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args, 340 &dummy_result); 341 else 342 rval = peekpoke_mem(cmd, &peekpoke_args); 343 344 /* 345 * A NULL value_p is permitted by ddi_peek(9F); discard the result. 346 */ 347 if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) { 348 switch (size) { 349 case sizeof (uint8_t): 350 *(uint8_t *)value_p = peekpoke_value.u8; 351 break; 352 case sizeof (uint16_t): 353 *(uint16_t *)value_p = peekpoke_value.u16; 354 break; 355 case sizeof (uint32_t): 356 *(uint32_t *)value_p = peekpoke_value.u32; 357 break; 358 case sizeof (uint64_t): 359 *(uint64_t *)value_p = peekpoke_value.u64; 360 break; 361 } 362 } 363 364 return (rval); 365 } 366 367 /* 368 * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this. 369 * they shouldn't be, but the 9f manpage kind of pseudo exposes it. 370 */ 371 int 372 ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p) 373 { 374 switch (size) { 375 case sizeof (uint8_t): 376 case sizeof (uint16_t): 377 case sizeof (uint32_t): 378 case sizeof (uint64_t): 379 break; 380 default: 381 return (DDI_FAILURE); 382 } 383 384 return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p)); 385 } 386 387 int 388 ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p) 389 { 390 switch (size) { 391 case sizeof (uint8_t): 392 case sizeof (uint16_t): 393 case sizeof (uint32_t): 394 case sizeof (uint64_t): 395 break; 396 default: 397 return (DDI_FAILURE); 398 } 399 400 return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p)); 401 } 402 403 int 404 ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p) 405 { 406 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 407 val_p)); 408 } 409 410 int 411 ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p) 412 { 413 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 414 val_p)); 415 } 416 417 int 418 ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p) 419 { 420 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 421 val_p)); 422 } 423 424 int 425 ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p) 426 { 427 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 428 val_p)); 429 } 430 431 432 /* 433 * We need to separate the old interfaces from the new ones and leave them 434 * in here for a while. Previous versions of the OS defined the new interfaces 435 * to the old interfaces. This way we can fix things up so that we can 436 * eventually remove these interfaces. 437 * e.g. A 3rd party module/driver using ddi_peek8 and built against S10 438 * or earlier will actually have a reference to ddi_peekc in the binary. 439 */ 440 #ifdef _ILP32 441 int 442 ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p) 443 { 444 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 445 val_p)); 446 } 447 448 int 449 ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p) 450 { 451 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 452 val_p)); 453 } 454 455 int 456 ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p) 457 { 458 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 459 val_p)); 460 } 461 462 int 463 ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p) 464 { 465 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 466 val_p)); 467 } 468 #endif /* _ILP32 */ 469 470 int 471 ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val) 472 { 473 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 474 } 475 476 int 477 ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val) 478 { 479 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 480 } 481 482 int 483 ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val) 484 { 485 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 486 } 487 488 int 489 ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val) 490 { 491 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 492 } 493 494 /* 495 * We need to separate the old interfaces from the new ones and leave them 496 * in here for a while. Previous versions of the OS defined the new interfaces 497 * to the old interfaces. This way we can fix things up so that we can 498 * eventually remove these interfaces. 499 * e.g. A 3rd party module/driver using ddi_poke8 and built against S10 500 * or earlier will actually have a reference to ddi_pokec in the binary. 501 */ 502 #ifdef _ILP32 503 int 504 ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val) 505 { 506 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 507 } 508 509 int 510 ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val) 511 { 512 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 513 } 514 515 int 516 ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val) 517 { 518 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 519 } 520 521 int 522 ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val) 523 { 524 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 525 } 526 #endif /* _ILP32 */ 527 528 /* 529 * ddi_peekpokeio() is used primarily by the mem drivers for moving 530 * data to and from uio structures via peek and poke. Note that we 531 * use "internal" routines ddi_peek and ddi_poke to make this go 532 * slightly faster, avoiding the call overhead .. 533 */ 534 int 535 ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw, 536 caddr_t addr, size_t len, uint_t xfersize) 537 { 538 int64_t ibuffer; 539 int8_t w8; 540 size_t sz; 541 int o; 542 543 if (xfersize > sizeof (long)) 544 xfersize = sizeof (long); 545 546 while (len != 0) { 547 if ((len | (uintptr_t)addr) & 1) { 548 sz = sizeof (int8_t); 549 if (rw == UIO_WRITE) { 550 if ((o = uwritec(uio)) == -1) 551 return (DDI_FAILURE); 552 if (ddi_poke8(devi, (int8_t *)addr, 553 (int8_t)o) != DDI_SUCCESS) 554 return (DDI_FAILURE); 555 } else { 556 if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 557 (int8_t *)addr, &w8) != DDI_SUCCESS) 558 return (DDI_FAILURE); 559 if (ureadc(w8, uio)) 560 return (DDI_FAILURE); 561 } 562 } else { 563 switch (xfersize) { 564 case sizeof (int64_t): 565 if (((len | (uintptr_t)addr) & 566 (sizeof (int64_t) - 1)) == 0) { 567 sz = xfersize; 568 break; 569 } 570 /*FALLTHROUGH*/ 571 case sizeof (int32_t): 572 if (((len | (uintptr_t)addr) & 573 (sizeof (int32_t) - 1)) == 0) { 574 sz = xfersize; 575 break; 576 } 577 /*FALLTHROUGH*/ 578 default: 579 /* 580 * This still assumes that we might have an 581 * I/O bus out there that permits 16-bit 582 * transfers (and that it would be upset by 583 * 32-bit transfers from such locations). 584 */ 585 sz = sizeof (int16_t); 586 break; 587 } 588 589 if (rw == UIO_READ) { 590 if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 591 addr, &ibuffer) != DDI_SUCCESS) 592 return (DDI_FAILURE); 593 } 594 595 if (uiomove(&ibuffer, sz, rw, uio)) 596 return (DDI_FAILURE); 597 598 if (rw == UIO_WRITE) { 599 if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz, 600 addr, &ibuffer) != DDI_SUCCESS) 601 return (DDI_FAILURE); 602 } 603 } 604 addr += sz; 605 len -= sz; 606 } 607 return (DDI_SUCCESS); 608 } 609 610 /* 611 * These routines are used by drivers that do layered ioctls 612 * On sparc, they're implemented in assembler to avoid spilling 613 * register windows in the common (copyin) case .. 614 */ 615 #if !defined(__sparc) 616 int 617 ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags) 618 { 619 if (flags & FKIOCTL) 620 return (kcopy(buf, kernbuf, size) ? -1 : 0); 621 return (copyin(buf, kernbuf, size)); 622 } 623 624 int 625 ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags) 626 { 627 if (flags & FKIOCTL) 628 return (kcopy(buf, kernbuf, size) ? -1 : 0); 629 return (copyout(buf, kernbuf, size)); 630 } 631 #endif /* !__sparc */ 632 633 /* 634 * Conversions in nexus pagesize units. We don't duplicate the 635 * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI 636 * routines anyway. 637 */ 638 unsigned long 639 ddi_btop(dev_info_t *dip, unsigned long bytes) 640 { 641 unsigned long pages; 642 643 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages); 644 return (pages); 645 } 646 647 unsigned long 648 ddi_btopr(dev_info_t *dip, unsigned long bytes) 649 { 650 unsigned long pages; 651 652 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages); 653 return (pages); 654 } 655 656 unsigned long 657 ddi_ptob(dev_info_t *dip, unsigned long pages) 658 { 659 unsigned long bytes; 660 661 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes); 662 return (bytes); 663 } 664 665 unsigned int 666 ddi_enter_critical(void) 667 { 668 return ((uint_t)spl7()); 669 } 670 671 void 672 ddi_exit_critical(unsigned int spl) 673 { 674 splx((int)spl); 675 } 676 677 /* 678 * Nexus ctlops punter 679 */ 680 681 #if !defined(__sparc) 682 /* 683 * Request bus_ctl parent to handle a bus_ctl request 684 * 685 * (The sparc version is in sparc_ddi.s) 686 */ 687 int 688 ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v) 689 { 690 int (*fp)(); 691 692 if (!d || !r) 693 return (DDI_FAILURE); 694 695 if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL) 696 return (DDI_FAILURE); 697 698 fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl; 699 return ((*fp)(d, r, op, a, v)); 700 } 701 702 #endif 703 704 /* 705 * DMA/DVMA setup 706 */ 707 708 #if defined(__sparc) 709 static ddi_dma_lim_t standard_limits = { 710 (uint_t)0, /* addr_t dlim_addr_lo */ 711 (uint_t)-1, /* addr_t dlim_addr_hi */ 712 (uint_t)-1, /* uint_t dlim_cntr_max */ 713 (uint_t)1, /* uint_t dlim_burstsizes */ 714 (uint_t)1, /* uint_t dlim_minxfer */ 715 0 /* uint_t dlim_dmaspeed */ 716 }; 717 #elif defined(__x86) 718 static ddi_dma_lim_t standard_limits = { 719 (uint_t)0, /* addr_t dlim_addr_lo */ 720 (uint_t)0xffffff, /* addr_t dlim_addr_hi */ 721 (uint_t)0, /* uint_t dlim_cntr_max */ 722 (uint_t)0x00000001, /* uint_t dlim_burstsizes */ 723 (uint_t)DMA_UNIT_8, /* uint_t dlim_minxfer */ 724 (uint_t)0, /* uint_t dlim_dmaspeed */ 725 (uint_t)0x86<<24+0, /* uint_t dlim_version */ 726 (uint_t)0xffff, /* uint_t dlim_adreg_max */ 727 (uint_t)0xffff, /* uint_t dlim_ctreg_max */ 728 (uint_t)512, /* uint_t dlim_granular */ 729 (int)1, /* int dlim_sgllen */ 730 (uint_t)0xffffffff /* uint_t dlim_reqsizes */ 731 }; 732 733 #endif 734 735 int 736 ddi_dma_setup(dev_info_t *dip, struct ddi_dma_req *dmareqp, 737 ddi_dma_handle_t *handlep) 738 { 739 int (*funcp)() = ddi_dma_map; 740 struct bus_ops *bop; 741 #if defined(__sparc) 742 auto ddi_dma_lim_t dma_lim; 743 744 if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) { 745 dma_lim = standard_limits; 746 } else { 747 dma_lim = *dmareqp->dmar_limits; 748 } 749 dmareqp->dmar_limits = &dma_lim; 750 #endif 751 #if defined(__x86) 752 if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) 753 return (DDI_FAILURE); 754 #endif 755 756 /* 757 * Handle the case that the requester is both a leaf 758 * and a nexus driver simultaneously by calling the 759 * requester's bus_dma_map function directly instead 760 * of ddi_dma_map. 761 */ 762 bop = DEVI(dip)->devi_ops->devo_bus_ops; 763 if (bop && bop->bus_dma_map) 764 funcp = bop->bus_dma_map; 765 return ((*funcp)(dip, dip, dmareqp, handlep)); 766 } 767 768 int 769 ddi_dma_addr_setup(dev_info_t *dip, struct as *as, caddr_t addr, size_t len, 770 uint_t flags, int (*waitfp)(), caddr_t arg, 771 ddi_dma_lim_t *limits, ddi_dma_handle_t *handlep) 772 { 773 int (*funcp)() = ddi_dma_map; 774 ddi_dma_lim_t dma_lim; 775 struct ddi_dma_req dmareq; 776 struct bus_ops *bop; 777 778 if (len == 0) { 779 return (DDI_DMA_NOMAPPING); 780 } 781 if (limits == (ddi_dma_lim_t *)0) { 782 dma_lim = standard_limits; 783 } else { 784 dma_lim = *limits; 785 } 786 dmareq.dmar_limits = &dma_lim; 787 dmareq.dmar_flags = flags; 788 dmareq.dmar_fp = waitfp; 789 dmareq.dmar_arg = arg; 790 dmareq.dmar_object.dmao_size = len; 791 dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 792 dmareq.dmar_object.dmao_obj.virt_obj.v_as = as; 793 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr; 794 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 795 796 /* 797 * Handle the case that the requester is both a leaf 798 * and a nexus driver simultaneously by calling the 799 * requester's bus_dma_map function directly instead 800 * of ddi_dma_map. 801 */ 802 bop = DEVI(dip)->devi_ops->devo_bus_ops; 803 if (bop && bop->bus_dma_map) 804 funcp = bop->bus_dma_map; 805 806 return ((*funcp)(dip, dip, &dmareq, handlep)); 807 } 808 809 int 810 ddi_dma_buf_setup(dev_info_t *dip, struct buf *bp, uint_t flags, 811 int (*waitfp)(), caddr_t arg, ddi_dma_lim_t *limits, 812 ddi_dma_handle_t *handlep) 813 { 814 int (*funcp)() = ddi_dma_map; 815 ddi_dma_lim_t dma_lim; 816 struct ddi_dma_req dmareq; 817 struct bus_ops *bop; 818 819 if (limits == (ddi_dma_lim_t *)0) { 820 dma_lim = standard_limits; 821 } else { 822 dma_lim = *limits; 823 } 824 dmareq.dmar_limits = &dma_lim; 825 dmareq.dmar_flags = flags; 826 dmareq.dmar_fp = waitfp; 827 dmareq.dmar_arg = arg; 828 dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount; 829 830 if (bp->b_flags & B_PAGEIO) { 831 dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES; 832 dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages; 833 dmareq.dmar_object.dmao_obj.pp_obj.pp_offset = 834 (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET); 835 } else { 836 dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR; 837 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr; 838 if (bp->b_flags & B_SHADOW) { 839 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = 840 bp->b_shadow; 841 } else { 842 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 843 } 844 845 /* 846 * If the buffer has no proc pointer, or the proc 847 * struct has the kernel address space, or the buffer has 848 * been marked B_REMAPPED (meaning that it is now 849 * mapped into the kernel's address space), then 850 * the address space is kas (kernel address space). 851 */ 852 if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) || 853 (bp->b_flags & B_REMAPPED)) { 854 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0; 855 } else { 856 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 857 bp->b_proc->p_as; 858 } 859 } 860 861 /* 862 * Handle the case that the requester is both a leaf 863 * and a nexus driver simultaneously by calling the 864 * requester's bus_dma_map function directly instead 865 * of ddi_dma_map. 866 */ 867 bop = DEVI(dip)->devi_ops->devo_bus_ops; 868 if (bop && bop->bus_dma_map) 869 funcp = bop->bus_dma_map; 870 871 return ((*funcp)(dip, dip, &dmareq, handlep)); 872 } 873 874 #if !defined(__sparc) 875 /* 876 * Request bus_dma_ctl parent to fiddle with a dma request. 877 * 878 * (The sparc version is in sparc_subr.s) 879 */ 880 int 881 ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 882 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 883 off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags) 884 { 885 int (*fp)(); 886 887 dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl; 888 fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl; 889 return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags)); 890 } 891 #endif 892 893 /* 894 * For all DMA control functions, call the DMA control 895 * routine and return status. 896 * 897 * Just plain assume that the parent is to be called. 898 * If a nexus driver or a thread outside the framework 899 * of a nexus driver or a leaf driver calls these functions, 900 * it is up to them to deal with the fact that the parent's 901 * bus_dma_ctl function will be the first one called. 902 */ 903 904 #define HD ((ddi_dma_impl_t *)h)->dmai_rdip 905 906 int 907 ddi_dma_kvaddrp(ddi_dma_handle_t h, off_t off, size_t len, caddr_t *kp) 908 { 909 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_KVADDR, &off, &len, kp, 0)); 910 } 911 912 int 913 ddi_dma_htoc(ddi_dma_handle_t h, off_t o, ddi_dma_cookie_t *c) 914 { 915 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_HTOC, &o, 0, (caddr_t *)c, 0)); 916 } 917 918 int 919 ddi_dma_coff(ddi_dma_handle_t h, ddi_dma_cookie_t *c, off_t *o) 920 { 921 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_COFF, 922 (off_t *)c, 0, (caddr_t *)o, 0)); 923 } 924 925 int 926 ddi_dma_movwin(ddi_dma_handle_t h, off_t *o, size_t *l, ddi_dma_cookie_t *c) 927 { 928 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_MOVWIN, o, 929 l, (caddr_t *)c, 0)); 930 } 931 932 int 933 ddi_dma_curwin(ddi_dma_handle_t h, off_t *o, size_t *l) 934 { 935 if ((((ddi_dma_impl_t *)h)->dmai_rflags & DDI_DMA_PARTIAL) == 0) 936 return (DDI_FAILURE); 937 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_REPWIN, o, l, 0, 0)); 938 } 939 940 int 941 ddi_dma_nextwin(ddi_dma_handle_t h, ddi_dma_win_t win, 942 ddi_dma_win_t *nwin) 943 { 944 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTWIN, (off_t *)&win, 0, 945 (caddr_t *)nwin, 0)); 946 } 947 948 int 949 ddi_dma_nextseg(ddi_dma_win_t win, ddi_dma_seg_t seg, ddi_dma_seg_t *nseg) 950 { 951 ddi_dma_handle_t h = (ddi_dma_handle_t)win; 952 953 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTSEG, (off_t *)&win, 954 (size_t *)&seg, (caddr_t *)nseg, 0)); 955 } 956 957 #if (defined(__i386) && !defined(__amd64)) || defined(__sparc) 958 /* 959 * This routine is Obsolete and should be removed from ALL architectures 960 * in a future release of Solaris. 961 * 962 * It is deliberately NOT ported to amd64; please fix the code that 963 * depends on this routine to use ddi_dma_nextcookie(9F). 964 * 965 * NOTE: even though we fixed the pointer through a 32-bit param issue (the fix 966 * is a side effect to some other cleanup), we're still not going to support 967 * this interface on x64. 968 */ 969 int 970 ddi_dma_segtocookie(ddi_dma_seg_t seg, off_t *o, off_t *l, 971 ddi_dma_cookie_t *cookiep) 972 { 973 ddi_dma_handle_t h = (ddi_dma_handle_t)seg; 974 975 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SEGTOC, o, (size_t *)l, 976 (caddr_t *)cookiep, 0)); 977 } 978 #endif /* (__i386 && !__amd64) || __sparc */ 979 980 #if !defined(__sparc) 981 982 /* 983 * The SPARC versions of these routines are done in assembler to 984 * save register windows, so they're in sparc_subr.s. 985 */ 986 987 int 988 ddi_dma_map(dev_info_t *dip, dev_info_t *rdip, 989 struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 990 { 991 dev_info_t *hdip; 992 int (*funcp)(dev_info_t *, dev_info_t *, struct ddi_dma_req *, 993 ddi_dma_handle_t *); 994 995 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_map; 996 997 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_map; 998 return ((*funcp)(hdip, rdip, dmareqp, handlep)); 999 } 1000 1001 int 1002 ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 1003 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 1004 { 1005 dev_info_t *hdip; 1006 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *, 1007 int (*)(caddr_t), caddr_t, ddi_dma_handle_t *); 1008 1009 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 1010 1011 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_allochdl; 1012 return ((*funcp)(hdip, rdip, attr, waitfp, arg, handlep)); 1013 } 1014 1015 int 1016 ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep) 1017 { 1018 dev_info_t *hdip; 1019 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1020 1021 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 1022 1023 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_freehdl; 1024 return ((*funcp)(hdip, rdip, handlep)); 1025 } 1026 1027 int 1028 ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 1029 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 1030 ddi_dma_cookie_t *cp, uint_t *ccountp) 1031 { 1032 dev_info_t *hdip; 1033 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1034 struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *); 1035 1036 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 1037 1038 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl; 1039 return ((*funcp)(hdip, rdip, handle, dmareq, cp, ccountp)); 1040 } 1041 1042 int 1043 ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 1044 ddi_dma_handle_t handle) 1045 { 1046 dev_info_t *hdip; 1047 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1048 1049 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1050 1051 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl; 1052 return ((*funcp)(hdip, rdip, handle)); 1053 } 1054 1055 1056 int 1057 ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip, 1058 ddi_dma_handle_t handle, off_t off, size_t len, 1059 uint_t cache_flags) 1060 { 1061 dev_info_t *hdip; 1062 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1063 off_t, size_t, uint_t); 1064 1065 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1066 1067 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_flush; 1068 return ((*funcp)(hdip, rdip, handle, off, len, cache_flags)); 1069 } 1070 1071 int 1072 ddi_dma_win(dev_info_t *dip, dev_info_t *rdip, 1073 ddi_dma_handle_t handle, uint_t win, off_t *offp, 1074 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 1075 { 1076 dev_info_t *hdip; 1077 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1078 uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *); 1079 1080 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win; 1081 1082 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_win; 1083 return ((*funcp)(hdip, rdip, handle, win, offp, lenp, 1084 cookiep, ccountp)); 1085 } 1086 1087 int 1088 ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom) 1089 { 1090 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1091 dev_info_t *hdip, *dip; 1092 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t, 1093 size_t, uint_t); 1094 1095 /* 1096 * the DMA nexus driver will set DMP_NOSYNC if the 1097 * platform does not require any sync operation. For 1098 * example if the memory is uncached or consistent 1099 * and without any I/O write buffers involved. 1100 */ 1101 if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC) 1102 return (DDI_SUCCESS); 1103 1104 dip = hp->dmai_rdip; 1105 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1106 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_flush; 1107 return ((*funcp)(hdip, dip, h, o, l, whom)); 1108 } 1109 1110 int 1111 ddi_dma_unbind_handle(ddi_dma_handle_t h) 1112 { 1113 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1114 dev_info_t *hdip, *dip; 1115 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1116 1117 dip = hp->dmai_rdip; 1118 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1119 funcp = DEVI(dip)->devi_bus_dma_unbindfunc; 1120 return ((*funcp)(hdip, dip, h)); 1121 } 1122 1123 #endif /* !__sparc */ 1124 1125 int 1126 ddi_dma_free(ddi_dma_handle_t h) 1127 { 1128 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_FREE, 0, 0, 0, 0)); 1129 } 1130 1131 int 1132 ddi_iopb_alloc(dev_info_t *dip, ddi_dma_lim_t *limp, uint_t len, caddr_t *iopbp) 1133 { 1134 ddi_dma_lim_t defalt; 1135 size_t size = len; 1136 1137 if (!limp) { 1138 defalt = standard_limits; 1139 limp = &defalt; 1140 } 1141 return (i_ddi_mem_alloc_lim(dip, limp, size, 0, 0, 0, 1142 iopbp, NULL, NULL)); 1143 } 1144 1145 void 1146 ddi_iopb_free(caddr_t iopb) 1147 { 1148 i_ddi_mem_free(iopb, NULL); 1149 } 1150 1151 int 1152 ddi_mem_alloc(dev_info_t *dip, ddi_dma_lim_t *limits, uint_t length, 1153 uint_t flags, caddr_t *kaddrp, uint_t *real_length) 1154 { 1155 ddi_dma_lim_t defalt; 1156 size_t size = length; 1157 1158 if (!limits) { 1159 defalt = standard_limits; 1160 limits = &defalt; 1161 } 1162 return (i_ddi_mem_alloc_lim(dip, limits, size, flags & 0x1, 1163 1, 0, kaddrp, real_length, NULL)); 1164 } 1165 1166 void 1167 ddi_mem_free(caddr_t kaddr) 1168 { 1169 i_ddi_mem_free(kaddr, NULL); 1170 } 1171 1172 /* 1173 * DMA attributes, alignment, burst sizes, and transfer minimums 1174 */ 1175 int 1176 ddi_dma_get_attr(ddi_dma_handle_t handle, ddi_dma_attr_t *attrp) 1177 { 1178 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1179 1180 if (attrp == NULL) 1181 return (DDI_FAILURE); 1182 *attrp = dimp->dmai_attr; 1183 return (DDI_SUCCESS); 1184 } 1185 1186 int 1187 ddi_dma_burstsizes(ddi_dma_handle_t handle) 1188 { 1189 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1190 1191 if (!dimp) 1192 return (0); 1193 else 1194 return (dimp->dmai_burstsizes); 1195 } 1196 1197 int 1198 ddi_dma_devalign(ddi_dma_handle_t handle, uint_t *alignment, uint_t *mineffect) 1199 { 1200 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1201 1202 if (!dimp || !alignment || !mineffect) 1203 return (DDI_FAILURE); 1204 if (!(dimp->dmai_rflags & DDI_DMA_SBUS_64BIT)) { 1205 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1206 } else { 1207 if (dimp->dmai_burstsizes & 0xff0000) { 1208 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes >> 16); 1209 } else { 1210 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1211 } 1212 } 1213 *mineffect = dimp->dmai_minxfer; 1214 return (DDI_SUCCESS); 1215 } 1216 1217 int 1218 ddi_iomin(dev_info_t *a, int i, int stream) 1219 { 1220 int r; 1221 1222 /* 1223 * Make sure that the initial value is sane 1224 */ 1225 if (i & (i - 1)) 1226 return (0); 1227 if (i == 0) 1228 i = (stream) ? 4 : 1; 1229 1230 r = ddi_ctlops(a, a, 1231 DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i); 1232 if (r != DDI_SUCCESS || (i & (i - 1))) 1233 return (0); 1234 return (i); 1235 } 1236 1237 /* 1238 * Given two DMA attribute structures, apply the attributes 1239 * of one to the other, following the rules of attributes 1240 * and the wishes of the caller. 1241 * 1242 * The rules of DMA attribute structures are that you cannot 1243 * make things *less* restrictive as you apply one set 1244 * of attributes to another. 1245 * 1246 */ 1247 void 1248 ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod) 1249 { 1250 attr->dma_attr_addr_lo = 1251 MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo); 1252 attr->dma_attr_addr_hi = 1253 MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi); 1254 attr->dma_attr_count_max = 1255 MIN(attr->dma_attr_count_max, mod->dma_attr_count_max); 1256 attr->dma_attr_align = 1257 MAX(attr->dma_attr_align, mod->dma_attr_align); 1258 attr->dma_attr_burstsizes = 1259 (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes); 1260 attr->dma_attr_minxfer = 1261 maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer); 1262 attr->dma_attr_maxxfer = 1263 MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer); 1264 attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg); 1265 attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen, 1266 (uint_t)mod->dma_attr_sgllen); 1267 attr->dma_attr_granular = 1268 MAX(attr->dma_attr_granular, mod->dma_attr_granular); 1269 } 1270 1271 /* 1272 * mmap/segmap interface: 1273 */ 1274 1275 /* 1276 * ddi_segmap: setup the default segment driver. Calls the drivers 1277 * XXmmap routine to validate the range to be mapped. 1278 * Return ENXIO of the range is not valid. Create 1279 * a seg_dev segment that contains all of the 1280 * necessary information and will reference the 1281 * default segment driver routines. It returns zero 1282 * on success or non-zero on failure. 1283 */ 1284 int 1285 ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len, 1286 uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp) 1287 { 1288 extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *, 1289 off_t, uint_t, uint_t, uint_t, struct cred *); 1290 1291 return (spec_segmap(dev, offset, asp, addrp, len, 1292 prot, maxprot, flags, credp)); 1293 } 1294 1295 /* 1296 * ddi_map_fault: Resolve mappings at fault time. Used by segment 1297 * drivers. Allows each successive parent to resolve 1298 * address translations and add its mappings to the 1299 * mapping list supplied in the page structure. It 1300 * returns zero on success or non-zero on failure. 1301 */ 1302 1303 int 1304 ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg, 1305 caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock) 1306 { 1307 return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock)); 1308 } 1309 1310 /* 1311 * ddi_device_mapping_check: Called from ddi_segmap_setup. 1312 * Invokes platform specific DDI to determine whether attributes specified 1313 * in attr(9s) are valid for the region of memory that will be made 1314 * available for direct access to user process via the mmap(2) system call. 1315 */ 1316 int 1317 ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp, 1318 uint_t rnumber, uint_t *hat_flags) 1319 { 1320 ddi_acc_handle_t handle; 1321 ddi_map_req_t mr; 1322 ddi_acc_hdl_t *hp; 1323 int result; 1324 dev_info_t *dip; 1325 1326 /* 1327 * we use e_ddi_hold_devi_by_dev to search for the devi. We 1328 * release it immediately since it should already be held by 1329 * a devfs vnode. 1330 */ 1331 if ((dip = 1332 e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL) 1333 return (-1); 1334 ddi_release_devi(dip); /* for e_ddi_hold_devi_by_dev() */ 1335 1336 /* 1337 * Allocate and initialize the common elements of data 1338 * access handle. 1339 */ 1340 handle = impl_acc_hdl_alloc(KM_SLEEP, NULL); 1341 if (handle == NULL) 1342 return (-1); 1343 1344 hp = impl_acc_hdl_get(handle); 1345 hp->ah_vers = VERS_ACCHDL; 1346 hp->ah_dip = dip; 1347 hp->ah_rnumber = rnumber; 1348 hp->ah_offset = 0; 1349 hp->ah_len = 0; 1350 hp->ah_acc = *accattrp; 1351 1352 /* 1353 * Set up the mapping request and call to parent. 1354 */ 1355 mr.map_op = DDI_MO_MAP_HANDLE; 1356 mr.map_type = DDI_MT_RNUMBER; 1357 mr.map_obj.rnumber = rnumber; 1358 mr.map_prot = PROT_READ | PROT_WRITE; 1359 mr.map_flags = DDI_MF_KERNEL_MAPPING; 1360 mr.map_handlep = hp; 1361 mr.map_vers = DDI_MAP_VERSION; 1362 result = ddi_map(dip, &mr, 0, 0, NULL); 1363 1364 /* 1365 * Region must be mappable, pick up flags from the framework. 1366 */ 1367 *hat_flags = hp->ah_hat_flags; 1368 1369 impl_acc_hdl_free(handle); 1370 1371 /* 1372 * check for end result. 1373 */ 1374 if (result != DDI_SUCCESS) 1375 return (-1); 1376 return (0); 1377 } 1378 1379 1380 /* 1381 * Property functions: See also, ddipropdefs.h. 1382 * 1383 * These functions are the framework for the property functions, 1384 * i.e. they support software defined properties. All implementation 1385 * specific property handling (i.e.: self-identifying devices and 1386 * PROM defined properties are handled in the implementation specific 1387 * functions (defined in ddi_implfuncs.h). 1388 */ 1389 1390 /* 1391 * nopropop: Shouldn't be called, right? 1392 */ 1393 int 1394 nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1395 char *name, caddr_t valuep, int *lengthp) 1396 { 1397 _NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp)) 1398 return (DDI_PROP_NOT_FOUND); 1399 } 1400 1401 #ifdef DDI_PROP_DEBUG 1402 int ddi_prop_debug_flag = 0; 1403 1404 int 1405 ddi_prop_debug(int enable) 1406 { 1407 int prev = ddi_prop_debug_flag; 1408 1409 if ((enable != 0) || (prev != 0)) 1410 printf("ddi_prop_debug: debugging %s\n", 1411 enable ? "enabled" : "disabled"); 1412 ddi_prop_debug_flag = enable; 1413 return (prev); 1414 } 1415 1416 #endif /* DDI_PROP_DEBUG */ 1417 1418 /* 1419 * Search a property list for a match, if found return pointer 1420 * to matching prop struct, else return NULL. 1421 */ 1422 1423 ddi_prop_t * 1424 i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head) 1425 { 1426 ddi_prop_t *propp; 1427 1428 /* 1429 * find the property in child's devinfo: 1430 * Search order defined by this search function is first matching 1431 * property with input dev == DDI_DEV_T_ANY matching any dev or 1432 * dev == propp->prop_dev, name == propp->name, and the correct 1433 * data type as specified in the flags. If a DDI_DEV_T_NONE dev 1434 * value made it this far then it implies a DDI_DEV_T_ANY search. 1435 */ 1436 if (dev == DDI_DEV_T_NONE) 1437 dev = DDI_DEV_T_ANY; 1438 1439 for (propp = *list_head; propp != NULL; propp = propp->prop_next) { 1440 1441 if (!DDI_STRSAME(propp->prop_name, name)) 1442 continue; 1443 1444 if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev)) 1445 continue; 1446 1447 if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1448 continue; 1449 1450 return (propp); 1451 } 1452 1453 return ((ddi_prop_t *)0); 1454 } 1455 1456 /* 1457 * Search for property within devnames structures 1458 */ 1459 ddi_prop_t * 1460 i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags) 1461 { 1462 major_t major; 1463 struct devnames *dnp; 1464 ddi_prop_t *propp; 1465 1466 /* 1467 * Valid dev_t value is needed to index into the 1468 * correct devnames entry, therefore a dev_t 1469 * value of DDI_DEV_T_ANY is not appropriate. 1470 */ 1471 ASSERT(dev != DDI_DEV_T_ANY); 1472 if (dev == DDI_DEV_T_ANY) { 1473 return ((ddi_prop_t *)0); 1474 } 1475 1476 major = getmajor(dev); 1477 dnp = &(devnamesp[major]); 1478 1479 if (dnp->dn_global_prop_ptr == NULL) 1480 return ((ddi_prop_t *)0); 1481 1482 LOCK_DEV_OPS(&dnp->dn_lock); 1483 1484 for (propp = dnp->dn_global_prop_ptr->prop_list; 1485 propp != NULL; 1486 propp = (ddi_prop_t *)propp->prop_next) { 1487 1488 if (!DDI_STRSAME(propp->prop_name, name)) 1489 continue; 1490 1491 if ((!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev)) 1492 continue; 1493 1494 if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1495 continue; 1496 1497 /* Property found, return it */ 1498 UNLOCK_DEV_OPS(&dnp->dn_lock); 1499 return (propp); 1500 } 1501 1502 UNLOCK_DEV_OPS(&dnp->dn_lock); 1503 return ((ddi_prop_t *)0); 1504 } 1505 1506 static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>"; 1507 1508 /* 1509 * ddi_prop_search_global: 1510 * Search the global property list within devnames 1511 * for the named property. Return the encoded value. 1512 */ 1513 static int 1514 i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name, 1515 void *valuep, uint_t *lengthp) 1516 { 1517 ddi_prop_t *propp; 1518 caddr_t buffer; 1519 1520 propp = i_ddi_search_global_prop(dev, name, flags); 1521 1522 /* Property NOT found, bail */ 1523 if (propp == (ddi_prop_t *)0) 1524 return (DDI_PROP_NOT_FOUND); 1525 1526 if (propp->prop_flags & DDI_PROP_UNDEF_IT) 1527 return (DDI_PROP_UNDEFINED); 1528 1529 if ((buffer = kmem_alloc(propp->prop_len, 1530 (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) { 1531 cmn_err(CE_CONT, prop_no_mem_msg, name); 1532 return (DDI_PROP_NO_MEMORY); 1533 } 1534 1535 /* 1536 * Return the encoded data 1537 */ 1538 *(caddr_t *)valuep = buffer; 1539 *lengthp = propp->prop_len; 1540 bcopy(propp->prop_val, buffer, propp->prop_len); 1541 1542 return (DDI_PROP_SUCCESS); 1543 } 1544 1545 /* 1546 * ddi_prop_search_common: Lookup and return the encoded value 1547 */ 1548 int 1549 ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1550 uint_t flags, char *name, void *valuep, uint_t *lengthp) 1551 { 1552 ddi_prop_t *propp; 1553 int i; 1554 caddr_t buffer; 1555 caddr_t prealloc = NULL; 1556 int plength = 0; 1557 dev_info_t *pdip; 1558 int (*bop)(); 1559 1560 /*CONSTANTCONDITION*/ 1561 while (1) { 1562 1563 mutex_enter(&(DEVI(dip)->devi_lock)); 1564 1565 1566 /* 1567 * find the property in child's devinfo: 1568 * Search order is: 1569 * 1. driver defined properties 1570 * 2. system defined properties 1571 * 3. driver global properties 1572 * 4. boot defined properties 1573 */ 1574 1575 propp = i_ddi_prop_search(dev, name, flags, 1576 &(DEVI(dip)->devi_drv_prop_ptr)); 1577 if (propp == NULL) { 1578 propp = i_ddi_prop_search(dev, name, flags, 1579 &(DEVI(dip)->devi_sys_prop_ptr)); 1580 } 1581 if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) { 1582 propp = i_ddi_prop_search(dev, name, flags, 1583 &DEVI(dip)->devi_global_prop_list->prop_list); 1584 } 1585 1586 if (propp == NULL) { 1587 propp = i_ddi_prop_search(dev, name, flags, 1588 &(DEVI(dip)->devi_hw_prop_ptr)); 1589 } 1590 1591 /* 1592 * Software property found? 1593 */ 1594 if (propp != (ddi_prop_t *)0) { 1595 1596 /* 1597 * If explicit undefine, return now. 1598 */ 1599 if (propp->prop_flags & DDI_PROP_UNDEF_IT) { 1600 mutex_exit(&(DEVI(dip)->devi_lock)); 1601 if (prealloc) 1602 kmem_free(prealloc, plength); 1603 return (DDI_PROP_UNDEFINED); 1604 } 1605 1606 /* 1607 * If we only want to know if it exists, return now 1608 */ 1609 if (prop_op == PROP_EXISTS) { 1610 mutex_exit(&(DEVI(dip)->devi_lock)); 1611 ASSERT(prealloc == NULL); 1612 return (DDI_PROP_SUCCESS); 1613 } 1614 1615 /* 1616 * If length only request or prop length == 0, 1617 * service request and return now. 1618 */ 1619 if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) { 1620 *lengthp = propp->prop_len; 1621 1622 /* 1623 * if prop_op is PROP_LEN_AND_VAL_ALLOC 1624 * that means prop_len is 0, so set valuep 1625 * also to NULL 1626 */ 1627 if (prop_op == PROP_LEN_AND_VAL_ALLOC) 1628 *(caddr_t *)valuep = NULL; 1629 1630 mutex_exit(&(DEVI(dip)->devi_lock)); 1631 if (prealloc) 1632 kmem_free(prealloc, plength); 1633 return (DDI_PROP_SUCCESS); 1634 } 1635 1636 /* 1637 * If LEN_AND_VAL_ALLOC and the request can sleep, 1638 * drop the mutex, allocate the buffer, and go 1639 * through the loop again. If we already allocated 1640 * the buffer, and the size of the property changed, 1641 * keep trying... 1642 */ 1643 if ((prop_op == PROP_LEN_AND_VAL_ALLOC) && 1644 (flags & DDI_PROP_CANSLEEP)) { 1645 if (prealloc && (propp->prop_len != plength)) { 1646 kmem_free(prealloc, plength); 1647 prealloc = NULL; 1648 } 1649 if (prealloc == NULL) { 1650 plength = propp->prop_len; 1651 mutex_exit(&(DEVI(dip)->devi_lock)); 1652 prealloc = kmem_alloc(plength, 1653 KM_SLEEP); 1654 continue; 1655 } 1656 } 1657 1658 /* 1659 * Allocate buffer, if required. Either way, 1660 * set `buffer' variable. 1661 */ 1662 i = *lengthp; /* Get callers length */ 1663 *lengthp = propp->prop_len; /* Set callers length */ 1664 1665 switch (prop_op) { 1666 1667 case PROP_LEN_AND_VAL_ALLOC: 1668 1669 if (prealloc == NULL) { 1670 buffer = kmem_alloc(propp->prop_len, 1671 KM_NOSLEEP); 1672 } else { 1673 buffer = prealloc; 1674 } 1675 1676 if (buffer == NULL) { 1677 mutex_exit(&(DEVI(dip)->devi_lock)); 1678 cmn_err(CE_CONT, prop_no_mem_msg, name); 1679 return (DDI_PROP_NO_MEMORY); 1680 } 1681 /* Set callers buf ptr */ 1682 *(caddr_t *)valuep = buffer; 1683 break; 1684 1685 case PROP_LEN_AND_VAL_BUF: 1686 1687 if (propp->prop_len > (i)) { 1688 mutex_exit(&(DEVI(dip)->devi_lock)); 1689 return (DDI_PROP_BUF_TOO_SMALL); 1690 } 1691 1692 buffer = valuep; /* Get callers buf ptr */ 1693 break; 1694 1695 default: 1696 break; 1697 } 1698 1699 /* 1700 * Do the copy. 1701 */ 1702 bcopy(propp->prop_val, buffer, propp->prop_len); 1703 mutex_exit(&(DEVI(dip)->devi_lock)); 1704 return (DDI_PROP_SUCCESS); 1705 } 1706 1707 mutex_exit(&(DEVI(dip)->devi_lock)); 1708 if (prealloc) 1709 kmem_free(prealloc, plength); 1710 prealloc = NULL; 1711 1712 /* 1713 * Prop not found, call parent bus_ops to deal with possible 1714 * h/w layer (possible PROM defined props, etc.) and to 1715 * possibly ascend the hierarchy, if allowed by flags. 1716 */ 1717 pdip = (dev_info_t *)DEVI(dip)->devi_parent; 1718 1719 /* 1720 * One last call for the root driver PROM props? 1721 */ 1722 if (dip == ddi_root_node()) { 1723 return (ddi_bus_prop_op(dev, dip, dip, prop_op, 1724 flags, name, valuep, (int *)lengthp)); 1725 } 1726 1727 /* 1728 * We may have been called to check for properties 1729 * within a single devinfo node that has no parent - 1730 * see make_prop() 1731 */ 1732 if (pdip == NULL) { 1733 ASSERT((flags & 1734 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) == 1735 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)); 1736 return (DDI_PROP_NOT_FOUND); 1737 } 1738 1739 /* 1740 * Instead of recursing, we do iterative calls up the tree. 1741 * As a bit of optimization, skip the bus_op level if the 1742 * node is a s/w node and if the parent's bus_prop_op function 1743 * is `ddi_bus_prop_op', because we know that in this case, 1744 * this function does nothing. 1745 * 1746 * 4225415: If the parent isn't attached, or the child 1747 * hasn't been named by the parent yet, use the default 1748 * ddi_bus_prop_op as a proxy for the parent. This 1749 * allows property lookups in any child/parent state to 1750 * include 'prom' and inherited properties, even when 1751 * there are no drivers attached to the child or parent. 1752 */ 1753 1754 bop = ddi_bus_prop_op; 1755 if (i_ddi_devi_attached(pdip) && 1756 (i_ddi_node_state(dip) >= DS_INITIALIZED)) 1757 bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op; 1758 1759 i = DDI_PROP_NOT_FOUND; 1760 1761 if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) { 1762 i = (*bop)(dev, pdip, dip, prop_op, 1763 flags | DDI_PROP_DONTPASS, 1764 name, valuep, lengthp); 1765 } 1766 1767 if ((flags & DDI_PROP_DONTPASS) || 1768 (i != DDI_PROP_NOT_FOUND)) 1769 return (i); 1770 1771 dip = pdip; 1772 } 1773 /*NOTREACHED*/ 1774 } 1775 1776 1777 /* 1778 * ddi_prop_op: The basic property operator for drivers. 1779 * 1780 * In ddi_prop_op, the type of valuep is interpreted based on prop_op: 1781 * 1782 * prop_op valuep 1783 * ------ ------ 1784 * 1785 * PROP_LEN <unused> 1786 * 1787 * PROP_LEN_AND_VAL_BUF Pointer to callers buffer 1788 * 1789 * PROP_LEN_AND_VAL_ALLOC Address of callers pointer (will be set to 1790 * address of allocated buffer, if successful) 1791 */ 1792 int 1793 ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1794 char *name, caddr_t valuep, int *lengthp) 1795 { 1796 int i; 1797 1798 ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0); 1799 1800 /* 1801 * If this was originally an LDI prop lookup then we bail here. 1802 * The reason is that the LDI property lookup interfaces first call 1803 * a drivers prop_op() entry point to allow it to override 1804 * properties. But if we've made it here, then the driver hasn't 1805 * overriden any properties. We don't want to continue with the 1806 * property search here because we don't have any type inforamtion. 1807 * When we return failure, the LDI interfaces will then proceed to 1808 * call the typed property interfaces to look up the property. 1809 */ 1810 if (mod_flags & DDI_PROP_DYNAMIC) 1811 return (DDI_PROP_NOT_FOUND); 1812 1813 /* 1814 * check for pre-typed property consumer asking for typed property: 1815 * see e_ddi_getprop_int64. 1816 */ 1817 if (mod_flags & DDI_PROP_CONSUMER_TYPED) 1818 mod_flags |= DDI_PROP_TYPE_INT64; 1819 mod_flags |= DDI_PROP_TYPE_ANY; 1820 1821 i = ddi_prop_search_common(dev, dip, prop_op, 1822 mod_flags, name, valuep, (uint_t *)lengthp); 1823 if (i == DDI_PROP_FOUND_1275) 1824 return (DDI_PROP_SUCCESS); 1825 return (i); 1826 } 1827 1828 /* 1829 * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that 1830 * maintain size in number of blksize blocks. Provides a dynamic property 1831 * implementation for size oriented properties based on nblocks64 and blksize 1832 * values passed in by the driver. Fallback to ddi_prop_op if the nblocks64 1833 * is too large. This interface should not be used with a nblocks64 that 1834 * represents the driver's idea of how to represent unknown, if nblocks is 1835 * unknown use ddi_prop_op. 1836 */ 1837 int 1838 ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1839 int mod_flags, char *name, caddr_t valuep, int *lengthp, 1840 uint64_t nblocks64, uint_t blksize) 1841 { 1842 uint64_t size64; 1843 int blkshift; 1844 1845 /* convert block size to shift value */ 1846 ASSERT(BIT_ONLYONESET(blksize)); 1847 blkshift = highbit(blksize) - 1; 1848 1849 /* 1850 * There is no point in supporting nblocks64 values that don't have 1851 * an accurate uint64_t byte count representation. 1852 */ 1853 if (nblocks64 >= (UINT64_MAX >> blkshift)) 1854 return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1855 name, valuep, lengthp)); 1856 1857 size64 = nblocks64 << blkshift; 1858 return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags, 1859 name, valuep, lengthp, size64, blksize)); 1860 } 1861 1862 /* 1863 * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize. 1864 */ 1865 int 1866 ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1867 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64) 1868 { 1869 return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, 1870 mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE)); 1871 } 1872 1873 /* 1874 * ddi_prop_op_size_blksize: The basic property operator for block drivers that 1875 * maintain size in bytes. Provides a of dynamic property implementation for 1876 * size oriented properties based on size64 value and blksize passed in by the 1877 * driver. Fallback to ddi_prop_op if the size64 is too large. This interface 1878 * should not be used with a size64 that represents the driver's idea of how 1879 * to represent unknown, if size is unknown use ddi_prop_op. 1880 * 1881 * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned 1882 * integers. While the most likely interface to request them ([bc]devi_size) 1883 * is declared int (signed) there is no enforcement of this, which means we 1884 * can't enforce limitations here without risking regression. 1885 */ 1886 int 1887 ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1888 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64, 1889 uint_t blksize) 1890 { 1891 uint64_t nblocks64; 1892 int callers_length; 1893 caddr_t buffer; 1894 int blkshift; 1895 1896 /* convert block size to shift value */ 1897 ASSERT(BIT_ONLYONESET(blksize)); 1898 blkshift = highbit(blksize) - 1; 1899 1900 /* compute DEV_BSIZE nblocks value */ 1901 nblocks64 = size64 >> blkshift; 1902 1903 /* get callers length, establish length of our dynamic properties */ 1904 callers_length = *lengthp; 1905 1906 if (strcmp(name, "Nblocks") == 0) 1907 *lengthp = sizeof (uint64_t); 1908 else if (strcmp(name, "Size") == 0) 1909 *lengthp = sizeof (uint64_t); 1910 else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX)) 1911 *lengthp = sizeof (uint32_t); 1912 else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX)) 1913 *lengthp = sizeof (uint32_t); 1914 else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX)) 1915 *lengthp = sizeof (uint32_t); 1916 else { 1917 /* fallback to ddi_prop_op */ 1918 return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1919 name, valuep, lengthp)); 1920 } 1921 1922 /* service request for the length of the property */ 1923 if (prop_op == PROP_LEN) 1924 return (DDI_PROP_SUCCESS); 1925 1926 /* the length of the property and the request must match */ 1927 if (callers_length != *lengthp) 1928 return (DDI_PROP_INVAL_ARG); 1929 1930 switch (prop_op) { 1931 case PROP_LEN_AND_VAL_ALLOC: 1932 if ((buffer = kmem_alloc(*lengthp, 1933 (mod_flags & DDI_PROP_CANSLEEP) ? 1934 KM_SLEEP : KM_NOSLEEP)) == NULL) 1935 return (DDI_PROP_NO_MEMORY); 1936 1937 *(caddr_t *)valuep = buffer; /* set callers buf ptr */ 1938 break; 1939 1940 case PROP_LEN_AND_VAL_BUF: 1941 buffer = valuep; /* get callers buf ptr */ 1942 break; 1943 1944 default: 1945 return (DDI_PROP_INVAL_ARG); 1946 } 1947 1948 /* transfer the value into the buffer */ 1949 if (strcmp(name, "Nblocks") == 0) 1950 *((uint64_t *)buffer) = nblocks64; 1951 else if (strcmp(name, "Size") == 0) 1952 *((uint64_t *)buffer) = size64; 1953 else if (strcmp(name, "nblocks") == 0) 1954 *((uint32_t *)buffer) = (uint32_t)nblocks64; 1955 else if (strcmp(name, "size") == 0) 1956 *((uint32_t *)buffer) = (uint32_t)size64; 1957 else if (strcmp(name, "blksize") == 0) 1958 *((uint32_t *)buffer) = (uint32_t)blksize; 1959 return (DDI_PROP_SUCCESS); 1960 } 1961 1962 /* 1963 * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size. 1964 */ 1965 int 1966 ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1967 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64) 1968 { 1969 return (ddi_prop_op_size_blksize(dev, dip, prop_op, 1970 mod_flags, name, valuep, lengthp, size64, DEV_BSIZE)); 1971 } 1972 1973 /* 1974 * Variable length props... 1975 */ 1976 1977 /* 1978 * ddi_getlongprop: Get variable length property len+val into a buffer 1979 * allocated by property provider via kmem_alloc. Requester 1980 * is responsible for freeing returned property via kmem_free. 1981 * 1982 * Arguments: 1983 * 1984 * dev_t: Input: dev_t of property. 1985 * dip: Input: dev_info_t pointer of child. 1986 * flags: Input: Possible flag modifiers are: 1987 * DDI_PROP_DONTPASS: Don't pass to parent if prop not found. 1988 * DDI_PROP_CANSLEEP: Memory allocation may sleep. 1989 * name: Input: name of property. 1990 * valuep: Output: Addr of callers buffer pointer. 1991 * lengthp:Output: *lengthp will contain prop length on exit. 1992 * 1993 * Possible Returns: 1994 * 1995 * DDI_PROP_SUCCESS: Prop found and returned. 1996 * DDI_PROP_NOT_FOUND: Prop not found 1997 * DDI_PROP_UNDEFINED: Prop explicitly undefined. 1998 * DDI_PROP_NO_MEMORY: Prop found, but unable to alloc mem. 1999 */ 2000 2001 int 2002 ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags, 2003 char *name, caddr_t valuep, int *lengthp) 2004 { 2005 return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC, 2006 flags, name, valuep, lengthp)); 2007 } 2008 2009 /* 2010 * 2011 * ddi_getlongprop_buf: Get long prop into pre-allocated callers 2012 * buffer. (no memory allocation by provider). 2013 * 2014 * dev_t: Input: dev_t of property. 2015 * dip: Input: dev_info_t pointer of child. 2016 * flags: Input: DDI_PROP_DONTPASS or NULL 2017 * name: Input: name of property 2018 * valuep: Input: ptr to callers buffer. 2019 * lengthp:I/O: ptr to length of callers buffer on entry, 2020 * actual length of property on exit. 2021 * 2022 * Possible returns: 2023 * 2024 * DDI_PROP_SUCCESS Prop found and returned 2025 * DDI_PROP_NOT_FOUND Prop not found 2026 * DDI_PROP_UNDEFINED Prop explicitly undefined. 2027 * DDI_PROP_BUF_TOO_SMALL Prop found, callers buf too small, 2028 * no value returned, but actual prop 2029 * length returned in *lengthp 2030 * 2031 */ 2032 2033 int 2034 ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags, 2035 char *name, caddr_t valuep, int *lengthp) 2036 { 2037 return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2038 flags, name, valuep, lengthp)); 2039 } 2040 2041 /* 2042 * Integer/boolean sized props. 2043 * 2044 * Call is value only... returns found boolean or int sized prop value or 2045 * defvalue if prop not found or is wrong length or is explicitly undefined. 2046 * Only flag is DDI_PROP_DONTPASS... 2047 * 2048 * By convention, this interface returns boolean (0) sized properties 2049 * as value (int)1. 2050 * 2051 * This never returns an error, if property not found or specifically 2052 * undefined, the input `defvalue' is returned. 2053 */ 2054 2055 int 2056 ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue) 2057 { 2058 int propvalue = defvalue; 2059 int proplength = sizeof (int); 2060 int error; 2061 2062 error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2063 flags, name, (caddr_t)&propvalue, &proplength); 2064 2065 if ((error == DDI_PROP_SUCCESS) && (proplength == 0)) 2066 propvalue = 1; 2067 2068 return (propvalue); 2069 } 2070 2071 /* 2072 * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS 2073 * if returns DDI_PROP_SUCCESS, length returned in *lengthp. 2074 */ 2075 2076 int 2077 ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp) 2078 { 2079 return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp)); 2080 } 2081 2082 /* 2083 * Allocate a struct prop_driver_data, along with 'size' bytes 2084 * for decoded property data. This structure is freed by 2085 * calling ddi_prop_free(9F). 2086 */ 2087 static void * 2088 ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *)) 2089 { 2090 struct prop_driver_data *pdd; 2091 2092 /* 2093 * Allocate a structure with enough memory to store the decoded data. 2094 */ 2095 pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP); 2096 pdd->pdd_size = (sizeof (struct prop_driver_data) + size); 2097 pdd->pdd_prop_free = prop_free; 2098 2099 /* 2100 * Return a pointer to the location to put the decoded data. 2101 */ 2102 return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data))); 2103 } 2104 2105 /* 2106 * Allocated the memory needed to store the encoded data in the property 2107 * handle. 2108 */ 2109 static int 2110 ddi_prop_encode_alloc(prop_handle_t *ph, size_t size) 2111 { 2112 /* 2113 * If size is zero, then set data to NULL and size to 0. This 2114 * is a boolean property. 2115 */ 2116 if (size == 0) { 2117 ph->ph_size = 0; 2118 ph->ph_data = NULL; 2119 ph->ph_cur_pos = NULL; 2120 ph->ph_save_pos = NULL; 2121 } else { 2122 if (ph->ph_flags == DDI_PROP_DONTSLEEP) { 2123 ph->ph_data = kmem_zalloc(size, KM_NOSLEEP); 2124 if (ph->ph_data == NULL) 2125 return (DDI_PROP_NO_MEMORY); 2126 } else 2127 ph->ph_data = kmem_zalloc(size, KM_SLEEP); 2128 ph->ph_size = size; 2129 ph->ph_cur_pos = ph->ph_data; 2130 ph->ph_save_pos = ph->ph_data; 2131 } 2132 return (DDI_PROP_SUCCESS); 2133 } 2134 2135 /* 2136 * Free the space allocated by the lookup routines. Each lookup routine 2137 * returns a pointer to the decoded data to the driver. The driver then 2138 * passes this pointer back to us. This data actually lives in a struct 2139 * prop_driver_data. We use negative indexing to find the beginning of 2140 * the structure and then free the entire structure using the size and 2141 * the free routine stored in the structure. 2142 */ 2143 void 2144 ddi_prop_free(void *datap) 2145 { 2146 struct prop_driver_data *pdd; 2147 2148 /* 2149 * Get the structure 2150 */ 2151 pdd = (struct prop_driver_data *) 2152 ((caddr_t)datap - sizeof (struct prop_driver_data)); 2153 /* 2154 * Call the free routine to free it 2155 */ 2156 (*pdd->pdd_prop_free)(pdd); 2157 } 2158 2159 /* 2160 * Free the data associated with an array of ints, 2161 * allocated with ddi_prop_decode_alloc(). 2162 */ 2163 static void 2164 ddi_prop_free_ints(struct prop_driver_data *pdd) 2165 { 2166 kmem_free(pdd, pdd->pdd_size); 2167 } 2168 2169 /* 2170 * Free a single string property or a single string contained within 2171 * the argv style return value of an array of strings. 2172 */ 2173 static void 2174 ddi_prop_free_string(struct prop_driver_data *pdd) 2175 { 2176 kmem_free(pdd, pdd->pdd_size); 2177 2178 } 2179 2180 /* 2181 * Free an array of strings. 2182 */ 2183 static void 2184 ddi_prop_free_strings(struct prop_driver_data *pdd) 2185 { 2186 kmem_free(pdd, pdd->pdd_size); 2187 } 2188 2189 /* 2190 * Free the data associated with an array of bytes. 2191 */ 2192 static void 2193 ddi_prop_free_bytes(struct prop_driver_data *pdd) 2194 { 2195 kmem_free(pdd, pdd->pdd_size); 2196 } 2197 2198 /* 2199 * Reset the current location pointer in the property handle to the 2200 * beginning of the data. 2201 */ 2202 void 2203 ddi_prop_reset_pos(prop_handle_t *ph) 2204 { 2205 ph->ph_cur_pos = ph->ph_data; 2206 ph->ph_save_pos = ph->ph_data; 2207 } 2208 2209 /* 2210 * Restore the current location pointer in the property handle to the 2211 * saved position. 2212 */ 2213 void 2214 ddi_prop_save_pos(prop_handle_t *ph) 2215 { 2216 ph->ph_save_pos = ph->ph_cur_pos; 2217 } 2218 2219 /* 2220 * Save the location that the current location pointer is pointing to.. 2221 */ 2222 void 2223 ddi_prop_restore_pos(prop_handle_t *ph) 2224 { 2225 ph->ph_cur_pos = ph->ph_save_pos; 2226 } 2227 2228 /* 2229 * Property encode/decode functions 2230 */ 2231 2232 /* 2233 * Decode a single integer property 2234 */ 2235 static int 2236 ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements) 2237 { 2238 int i; 2239 int tmp; 2240 2241 /* 2242 * If there is nothing to decode return an error 2243 */ 2244 if (ph->ph_size == 0) 2245 return (DDI_PROP_END_OF_DATA); 2246 2247 /* 2248 * Decode the property as a single integer and return it 2249 * in data if we were able to decode it. 2250 */ 2251 i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp); 2252 if (i < DDI_PROP_RESULT_OK) { 2253 switch (i) { 2254 case DDI_PROP_RESULT_EOF: 2255 return (DDI_PROP_END_OF_DATA); 2256 2257 case DDI_PROP_RESULT_ERROR: 2258 return (DDI_PROP_CANNOT_DECODE); 2259 } 2260 } 2261 2262 *(int *)data = tmp; 2263 *nelements = 1; 2264 return (DDI_PROP_SUCCESS); 2265 } 2266 2267 /* 2268 * Decode a single 64 bit integer property 2269 */ 2270 static int 2271 ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements) 2272 { 2273 int i; 2274 int64_t tmp; 2275 2276 /* 2277 * If there is nothing to decode return an error 2278 */ 2279 if (ph->ph_size == 0) 2280 return (DDI_PROP_END_OF_DATA); 2281 2282 /* 2283 * Decode the property as a single integer and return it 2284 * in data if we were able to decode it. 2285 */ 2286 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp); 2287 if (i < DDI_PROP_RESULT_OK) { 2288 switch (i) { 2289 case DDI_PROP_RESULT_EOF: 2290 return (DDI_PROP_END_OF_DATA); 2291 2292 case DDI_PROP_RESULT_ERROR: 2293 return (DDI_PROP_CANNOT_DECODE); 2294 } 2295 } 2296 2297 *(int64_t *)data = tmp; 2298 *nelements = 1; 2299 return (DDI_PROP_SUCCESS); 2300 } 2301 2302 /* 2303 * Decode an array of integers property 2304 */ 2305 static int 2306 ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 2307 { 2308 int i; 2309 int cnt = 0; 2310 int *tmp; 2311 int *intp; 2312 int n; 2313 2314 /* 2315 * Figure out how many array elements there are by going through the 2316 * data without decoding it first and counting. 2317 */ 2318 for (;;) { 2319 i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 2320 if (i < 0) 2321 break; 2322 cnt++; 2323 } 2324 2325 /* 2326 * If there are no elements return an error 2327 */ 2328 if (cnt == 0) 2329 return (DDI_PROP_END_OF_DATA); 2330 2331 /* 2332 * If we cannot skip through the data, we cannot decode it 2333 */ 2334 if (i == DDI_PROP_RESULT_ERROR) 2335 return (DDI_PROP_CANNOT_DECODE); 2336 2337 /* 2338 * Reset the data pointer to the beginning of the encoded data 2339 */ 2340 ddi_prop_reset_pos(ph); 2341 2342 /* 2343 * Allocated memory to store the decoded value in. 2344 */ 2345 intp = ddi_prop_decode_alloc((cnt * sizeof (int)), 2346 ddi_prop_free_ints); 2347 2348 /* 2349 * Decode each element and place it in the space we just allocated 2350 */ 2351 tmp = intp; 2352 for (n = 0; n < cnt; n++, tmp++) { 2353 i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp); 2354 if (i < DDI_PROP_RESULT_OK) { 2355 /* 2356 * Free the space we just allocated 2357 * and return an error. 2358 */ 2359 ddi_prop_free(intp); 2360 switch (i) { 2361 case DDI_PROP_RESULT_EOF: 2362 return (DDI_PROP_END_OF_DATA); 2363 2364 case DDI_PROP_RESULT_ERROR: 2365 return (DDI_PROP_CANNOT_DECODE); 2366 } 2367 } 2368 } 2369 2370 *nelements = cnt; 2371 *(int **)data = intp; 2372 2373 return (DDI_PROP_SUCCESS); 2374 } 2375 2376 /* 2377 * Decode a 64 bit integer array property 2378 */ 2379 static int 2380 ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements) 2381 { 2382 int i; 2383 int n; 2384 int cnt = 0; 2385 int64_t *tmp; 2386 int64_t *intp; 2387 2388 /* 2389 * Count the number of array elements by going 2390 * through the data without decoding it. 2391 */ 2392 for (;;) { 2393 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL); 2394 if (i < 0) 2395 break; 2396 cnt++; 2397 } 2398 2399 /* 2400 * If there are no elements return an error 2401 */ 2402 if (cnt == 0) 2403 return (DDI_PROP_END_OF_DATA); 2404 2405 /* 2406 * If we cannot skip through the data, we cannot decode it 2407 */ 2408 if (i == DDI_PROP_RESULT_ERROR) 2409 return (DDI_PROP_CANNOT_DECODE); 2410 2411 /* 2412 * Reset the data pointer to the beginning of the encoded data 2413 */ 2414 ddi_prop_reset_pos(ph); 2415 2416 /* 2417 * Allocate memory to store the decoded value. 2418 */ 2419 intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)), 2420 ddi_prop_free_ints); 2421 2422 /* 2423 * Decode each element and place it in the space allocated 2424 */ 2425 tmp = intp; 2426 for (n = 0; n < cnt; n++, tmp++) { 2427 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp); 2428 if (i < DDI_PROP_RESULT_OK) { 2429 /* 2430 * Free the space we just allocated 2431 * and return an error. 2432 */ 2433 ddi_prop_free(intp); 2434 switch (i) { 2435 case DDI_PROP_RESULT_EOF: 2436 return (DDI_PROP_END_OF_DATA); 2437 2438 case DDI_PROP_RESULT_ERROR: 2439 return (DDI_PROP_CANNOT_DECODE); 2440 } 2441 } 2442 } 2443 2444 *nelements = cnt; 2445 *(int64_t **)data = intp; 2446 2447 return (DDI_PROP_SUCCESS); 2448 } 2449 2450 /* 2451 * Encode an array of integers property (Can be one element) 2452 */ 2453 int 2454 ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements) 2455 { 2456 int i; 2457 int *tmp; 2458 int cnt; 2459 int size; 2460 2461 /* 2462 * If there is no data, we cannot do anything 2463 */ 2464 if (nelements == 0) 2465 return (DDI_PROP_CANNOT_ENCODE); 2466 2467 /* 2468 * Get the size of an encoded int. 2469 */ 2470 size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2471 2472 if (size < DDI_PROP_RESULT_OK) { 2473 switch (size) { 2474 case DDI_PROP_RESULT_EOF: 2475 return (DDI_PROP_END_OF_DATA); 2476 2477 case DDI_PROP_RESULT_ERROR: 2478 return (DDI_PROP_CANNOT_ENCODE); 2479 } 2480 } 2481 2482 /* 2483 * Allocate space in the handle to store the encoded int. 2484 */ 2485 if (ddi_prop_encode_alloc(ph, size * nelements) != 2486 DDI_PROP_SUCCESS) 2487 return (DDI_PROP_NO_MEMORY); 2488 2489 /* 2490 * Encode the array of ints. 2491 */ 2492 tmp = (int *)data; 2493 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2494 i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp); 2495 if (i < DDI_PROP_RESULT_OK) { 2496 switch (i) { 2497 case DDI_PROP_RESULT_EOF: 2498 return (DDI_PROP_END_OF_DATA); 2499 2500 case DDI_PROP_RESULT_ERROR: 2501 return (DDI_PROP_CANNOT_ENCODE); 2502 } 2503 } 2504 } 2505 2506 return (DDI_PROP_SUCCESS); 2507 } 2508 2509 2510 /* 2511 * Encode a 64 bit integer array property 2512 */ 2513 int 2514 ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements) 2515 { 2516 int i; 2517 int cnt; 2518 int size; 2519 int64_t *tmp; 2520 2521 /* 2522 * If there is no data, we cannot do anything 2523 */ 2524 if (nelements == 0) 2525 return (DDI_PROP_CANNOT_ENCODE); 2526 2527 /* 2528 * Get the size of an encoded 64 bit int. 2529 */ 2530 size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2531 2532 if (size < DDI_PROP_RESULT_OK) { 2533 switch (size) { 2534 case DDI_PROP_RESULT_EOF: 2535 return (DDI_PROP_END_OF_DATA); 2536 2537 case DDI_PROP_RESULT_ERROR: 2538 return (DDI_PROP_CANNOT_ENCODE); 2539 } 2540 } 2541 2542 /* 2543 * Allocate space in the handle to store the encoded int. 2544 */ 2545 if (ddi_prop_encode_alloc(ph, size * nelements) != 2546 DDI_PROP_SUCCESS) 2547 return (DDI_PROP_NO_MEMORY); 2548 2549 /* 2550 * Encode the array of ints. 2551 */ 2552 tmp = (int64_t *)data; 2553 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2554 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp); 2555 if (i < DDI_PROP_RESULT_OK) { 2556 switch (i) { 2557 case DDI_PROP_RESULT_EOF: 2558 return (DDI_PROP_END_OF_DATA); 2559 2560 case DDI_PROP_RESULT_ERROR: 2561 return (DDI_PROP_CANNOT_ENCODE); 2562 } 2563 } 2564 } 2565 2566 return (DDI_PROP_SUCCESS); 2567 } 2568 2569 /* 2570 * Decode a single string property 2571 */ 2572 static int 2573 ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements) 2574 { 2575 char *tmp; 2576 char *str; 2577 int i; 2578 int size; 2579 2580 /* 2581 * If there is nothing to decode return an error 2582 */ 2583 if (ph->ph_size == 0) 2584 return (DDI_PROP_END_OF_DATA); 2585 2586 /* 2587 * Get the decoded size of the encoded string. 2588 */ 2589 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2590 if (size < DDI_PROP_RESULT_OK) { 2591 switch (size) { 2592 case DDI_PROP_RESULT_EOF: 2593 return (DDI_PROP_END_OF_DATA); 2594 2595 case DDI_PROP_RESULT_ERROR: 2596 return (DDI_PROP_CANNOT_DECODE); 2597 } 2598 } 2599 2600 /* 2601 * Allocated memory to store the decoded value in. 2602 */ 2603 str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string); 2604 2605 ddi_prop_reset_pos(ph); 2606 2607 /* 2608 * Decode the str and place it in the space we just allocated 2609 */ 2610 tmp = str; 2611 i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp); 2612 if (i < DDI_PROP_RESULT_OK) { 2613 /* 2614 * Free the space we just allocated 2615 * and return an error. 2616 */ 2617 ddi_prop_free(str); 2618 switch (i) { 2619 case DDI_PROP_RESULT_EOF: 2620 return (DDI_PROP_END_OF_DATA); 2621 2622 case DDI_PROP_RESULT_ERROR: 2623 return (DDI_PROP_CANNOT_DECODE); 2624 } 2625 } 2626 2627 *(char **)data = str; 2628 *nelements = 1; 2629 2630 return (DDI_PROP_SUCCESS); 2631 } 2632 2633 /* 2634 * Decode an array of strings. 2635 */ 2636 int 2637 ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 2638 { 2639 int cnt = 0; 2640 char **strs; 2641 char **tmp; 2642 char *ptr; 2643 int i; 2644 int n; 2645 int size; 2646 size_t nbytes; 2647 2648 /* 2649 * Figure out how many array elements there are by going through the 2650 * data without decoding it first and counting. 2651 */ 2652 for (;;) { 2653 i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL); 2654 if (i < 0) 2655 break; 2656 cnt++; 2657 } 2658 2659 /* 2660 * If there are no elements return an error 2661 */ 2662 if (cnt == 0) 2663 return (DDI_PROP_END_OF_DATA); 2664 2665 /* 2666 * If we cannot skip through the data, we cannot decode it 2667 */ 2668 if (i == DDI_PROP_RESULT_ERROR) 2669 return (DDI_PROP_CANNOT_DECODE); 2670 2671 /* 2672 * Reset the data pointer to the beginning of the encoded data 2673 */ 2674 ddi_prop_reset_pos(ph); 2675 2676 /* 2677 * Figure out how much memory we need for the sum total 2678 */ 2679 nbytes = (cnt + 1) * sizeof (char *); 2680 2681 for (n = 0; n < cnt; n++) { 2682 /* 2683 * Get the decoded size of the current encoded string. 2684 */ 2685 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2686 if (size < DDI_PROP_RESULT_OK) { 2687 switch (size) { 2688 case DDI_PROP_RESULT_EOF: 2689 return (DDI_PROP_END_OF_DATA); 2690 2691 case DDI_PROP_RESULT_ERROR: 2692 return (DDI_PROP_CANNOT_DECODE); 2693 } 2694 } 2695 2696 nbytes += size; 2697 } 2698 2699 /* 2700 * Allocate memory in which to store the decoded strings. 2701 */ 2702 strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings); 2703 2704 /* 2705 * Set up pointers for each string by figuring out yet 2706 * again how long each string is. 2707 */ 2708 ddi_prop_reset_pos(ph); 2709 ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *)); 2710 for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2711 /* 2712 * Get the decoded size of the current encoded string. 2713 */ 2714 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2715 if (size < DDI_PROP_RESULT_OK) { 2716 ddi_prop_free(strs); 2717 switch (size) { 2718 case DDI_PROP_RESULT_EOF: 2719 return (DDI_PROP_END_OF_DATA); 2720 2721 case DDI_PROP_RESULT_ERROR: 2722 return (DDI_PROP_CANNOT_DECODE); 2723 } 2724 } 2725 2726 *tmp = ptr; 2727 ptr += size; 2728 } 2729 2730 /* 2731 * String array is terminated by a NULL 2732 */ 2733 *tmp = NULL; 2734 2735 /* 2736 * Finally, we can decode each string 2737 */ 2738 ddi_prop_reset_pos(ph); 2739 for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2740 i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp); 2741 if (i < DDI_PROP_RESULT_OK) { 2742 /* 2743 * Free the space we just allocated 2744 * and return an error 2745 */ 2746 ddi_prop_free(strs); 2747 switch (i) { 2748 case DDI_PROP_RESULT_EOF: 2749 return (DDI_PROP_END_OF_DATA); 2750 2751 case DDI_PROP_RESULT_ERROR: 2752 return (DDI_PROP_CANNOT_DECODE); 2753 } 2754 } 2755 } 2756 2757 *(char ***)data = strs; 2758 *nelements = cnt; 2759 2760 return (DDI_PROP_SUCCESS); 2761 } 2762 2763 /* 2764 * Encode a string. 2765 */ 2766 int 2767 ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements) 2768 { 2769 char **tmp; 2770 int size; 2771 int i; 2772 2773 /* 2774 * If there is no data, we cannot do anything 2775 */ 2776 if (nelements == 0) 2777 return (DDI_PROP_CANNOT_ENCODE); 2778 2779 /* 2780 * Get the size of the encoded string. 2781 */ 2782 tmp = (char **)data; 2783 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2784 if (size < DDI_PROP_RESULT_OK) { 2785 switch (size) { 2786 case DDI_PROP_RESULT_EOF: 2787 return (DDI_PROP_END_OF_DATA); 2788 2789 case DDI_PROP_RESULT_ERROR: 2790 return (DDI_PROP_CANNOT_ENCODE); 2791 } 2792 } 2793 2794 /* 2795 * Allocate space in the handle to store the encoded string. 2796 */ 2797 if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS) 2798 return (DDI_PROP_NO_MEMORY); 2799 2800 ddi_prop_reset_pos(ph); 2801 2802 /* 2803 * Encode the string. 2804 */ 2805 tmp = (char **)data; 2806 i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2807 if (i < DDI_PROP_RESULT_OK) { 2808 switch (i) { 2809 case DDI_PROP_RESULT_EOF: 2810 return (DDI_PROP_END_OF_DATA); 2811 2812 case DDI_PROP_RESULT_ERROR: 2813 return (DDI_PROP_CANNOT_ENCODE); 2814 } 2815 } 2816 2817 return (DDI_PROP_SUCCESS); 2818 } 2819 2820 2821 /* 2822 * Encode an array of strings. 2823 */ 2824 int 2825 ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements) 2826 { 2827 int cnt = 0; 2828 char **tmp; 2829 int size; 2830 uint_t total_size; 2831 int i; 2832 2833 /* 2834 * If there is no data, we cannot do anything 2835 */ 2836 if (nelements == 0) 2837 return (DDI_PROP_CANNOT_ENCODE); 2838 2839 /* 2840 * Get the total size required to encode all the strings. 2841 */ 2842 total_size = 0; 2843 tmp = (char **)data; 2844 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2845 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2846 if (size < DDI_PROP_RESULT_OK) { 2847 switch (size) { 2848 case DDI_PROP_RESULT_EOF: 2849 return (DDI_PROP_END_OF_DATA); 2850 2851 case DDI_PROP_RESULT_ERROR: 2852 return (DDI_PROP_CANNOT_ENCODE); 2853 } 2854 } 2855 total_size += (uint_t)size; 2856 } 2857 2858 /* 2859 * Allocate space in the handle to store the encoded strings. 2860 */ 2861 if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS) 2862 return (DDI_PROP_NO_MEMORY); 2863 2864 ddi_prop_reset_pos(ph); 2865 2866 /* 2867 * Encode the array of strings. 2868 */ 2869 tmp = (char **)data; 2870 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2871 i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2872 if (i < DDI_PROP_RESULT_OK) { 2873 switch (i) { 2874 case DDI_PROP_RESULT_EOF: 2875 return (DDI_PROP_END_OF_DATA); 2876 2877 case DDI_PROP_RESULT_ERROR: 2878 return (DDI_PROP_CANNOT_ENCODE); 2879 } 2880 } 2881 } 2882 2883 return (DDI_PROP_SUCCESS); 2884 } 2885 2886 2887 /* 2888 * Decode an array of bytes. 2889 */ 2890 static int 2891 ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 2892 { 2893 uchar_t *tmp; 2894 int nbytes; 2895 int i; 2896 2897 /* 2898 * If there are no elements return an error 2899 */ 2900 if (ph->ph_size == 0) 2901 return (DDI_PROP_END_OF_DATA); 2902 2903 /* 2904 * Get the size of the encoded array of bytes. 2905 */ 2906 nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE, 2907 data, ph->ph_size); 2908 if (nbytes < DDI_PROP_RESULT_OK) { 2909 switch (nbytes) { 2910 case DDI_PROP_RESULT_EOF: 2911 return (DDI_PROP_END_OF_DATA); 2912 2913 case DDI_PROP_RESULT_ERROR: 2914 return (DDI_PROP_CANNOT_DECODE); 2915 } 2916 } 2917 2918 /* 2919 * Allocated memory to store the decoded value in. 2920 */ 2921 tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes); 2922 2923 /* 2924 * Decode each element and place it in the space we just allocated 2925 */ 2926 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 2927 if (i < DDI_PROP_RESULT_OK) { 2928 /* 2929 * Free the space we just allocated 2930 * and return an error 2931 */ 2932 ddi_prop_free(tmp); 2933 switch (i) { 2934 case DDI_PROP_RESULT_EOF: 2935 return (DDI_PROP_END_OF_DATA); 2936 2937 case DDI_PROP_RESULT_ERROR: 2938 return (DDI_PROP_CANNOT_DECODE); 2939 } 2940 } 2941 2942 *(uchar_t **)data = tmp; 2943 *nelements = nbytes; 2944 2945 return (DDI_PROP_SUCCESS); 2946 } 2947 2948 /* 2949 * Encode an array of bytes. 2950 */ 2951 int 2952 ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements) 2953 { 2954 int size; 2955 int i; 2956 2957 /* 2958 * If there are no elements, then this is a boolean property, 2959 * so just create a property handle with no data and return. 2960 */ 2961 if (nelements == 0) { 2962 (void) ddi_prop_encode_alloc(ph, 0); 2963 return (DDI_PROP_SUCCESS); 2964 } 2965 2966 /* 2967 * Get the size of the encoded array of bytes. 2968 */ 2969 size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data, 2970 nelements); 2971 if (size < DDI_PROP_RESULT_OK) { 2972 switch (size) { 2973 case DDI_PROP_RESULT_EOF: 2974 return (DDI_PROP_END_OF_DATA); 2975 2976 case DDI_PROP_RESULT_ERROR: 2977 return (DDI_PROP_CANNOT_DECODE); 2978 } 2979 } 2980 2981 /* 2982 * Allocate space in the handle to store the encoded bytes. 2983 */ 2984 if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS) 2985 return (DDI_PROP_NO_MEMORY); 2986 2987 /* 2988 * Encode the array of bytes. 2989 */ 2990 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data, 2991 nelements); 2992 if (i < DDI_PROP_RESULT_OK) { 2993 switch (i) { 2994 case DDI_PROP_RESULT_EOF: 2995 return (DDI_PROP_END_OF_DATA); 2996 2997 case DDI_PROP_RESULT_ERROR: 2998 return (DDI_PROP_CANNOT_ENCODE); 2999 } 3000 } 3001 3002 return (DDI_PROP_SUCCESS); 3003 } 3004 3005 /* 3006 * OBP 1275 integer, string and byte operators. 3007 * 3008 * DDI_PROP_CMD_DECODE: 3009 * 3010 * DDI_PROP_RESULT_ERROR: cannot decode the data 3011 * DDI_PROP_RESULT_EOF: end of data 3012 * DDI_PROP_OK: data was decoded 3013 * 3014 * DDI_PROP_CMD_ENCODE: 3015 * 3016 * DDI_PROP_RESULT_ERROR: cannot encode the data 3017 * DDI_PROP_RESULT_EOF: end of data 3018 * DDI_PROP_OK: data was encoded 3019 * 3020 * DDI_PROP_CMD_SKIP: 3021 * 3022 * DDI_PROP_RESULT_ERROR: cannot skip the data 3023 * DDI_PROP_RESULT_EOF: end of data 3024 * DDI_PROP_OK: data was skipped 3025 * 3026 * DDI_PROP_CMD_GET_ESIZE: 3027 * 3028 * DDI_PROP_RESULT_ERROR: cannot get encoded size 3029 * DDI_PROP_RESULT_EOF: end of data 3030 * > 0: the encoded size 3031 * 3032 * DDI_PROP_CMD_GET_DSIZE: 3033 * 3034 * DDI_PROP_RESULT_ERROR: cannot get decoded size 3035 * DDI_PROP_RESULT_EOF: end of data 3036 * > 0: the decoded size 3037 */ 3038 3039 /* 3040 * OBP 1275 integer operator 3041 * 3042 * OBP properties are a byte stream of data, so integers may not be 3043 * properly aligned. Therefore we need to copy them one byte at a time. 3044 */ 3045 int 3046 ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 3047 { 3048 int i; 3049 3050 switch (cmd) { 3051 case DDI_PROP_CMD_DECODE: 3052 /* 3053 * Check that there is encoded data 3054 */ 3055 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3056 return (DDI_PROP_RESULT_ERROR); 3057 if (ph->ph_flags & PH_FROM_PROM) { 3058 i = MIN(ph->ph_size, PROP_1275_INT_SIZE); 3059 if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3060 ph->ph_size - i)) 3061 return (DDI_PROP_RESULT_ERROR); 3062 } else { 3063 if (ph->ph_size < sizeof (int) || 3064 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3065 ph->ph_size - sizeof (int)))) 3066 return (DDI_PROP_RESULT_ERROR); 3067 } 3068 3069 /* 3070 * Copy the integer, using the implementation-specific 3071 * copy function if the property is coming from the PROM. 3072 */ 3073 if (ph->ph_flags & PH_FROM_PROM) { 3074 *data = impl_ddi_prop_int_from_prom( 3075 (uchar_t *)ph->ph_cur_pos, 3076 (ph->ph_size < PROP_1275_INT_SIZE) ? 3077 ph->ph_size : PROP_1275_INT_SIZE); 3078 } else { 3079 bcopy(ph->ph_cur_pos, data, sizeof (int)); 3080 } 3081 3082 /* 3083 * Move the current location to the start of the next 3084 * bit of undecoded data. 3085 */ 3086 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3087 PROP_1275_INT_SIZE; 3088 return (DDI_PROP_RESULT_OK); 3089 3090 case DDI_PROP_CMD_ENCODE: 3091 /* 3092 * Check that there is room to encoded the data 3093 */ 3094 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3095 ph->ph_size < PROP_1275_INT_SIZE || 3096 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3097 ph->ph_size - sizeof (int)))) 3098 return (DDI_PROP_RESULT_ERROR); 3099 3100 /* 3101 * Encode the integer into the byte stream one byte at a 3102 * time. 3103 */ 3104 bcopy(data, ph->ph_cur_pos, sizeof (int)); 3105 3106 /* 3107 * Move the current location to the start of the next bit of 3108 * space where we can store encoded data. 3109 */ 3110 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3111 return (DDI_PROP_RESULT_OK); 3112 3113 case DDI_PROP_CMD_SKIP: 3114 /* 3115 * Check that there is encoded data 3116 */ 3117 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3118 ph->ph_size < PROP_1275_INT_SIZE) 3119 return (DDI_PROP_RESULT_ERROR); 3120 3121 3122 if ((caddr_t)ph->ph_cur_pos == 3123 (caddr_t)ph->ph_data + ph->ph_size) { 3124 return (DDI_PROP_RESULT_EOF); 3125 } else if ((caddr_t)ph->ph_cur_pos > 3126 (caddr_t)ph->ph_data + ph->ph_size) { 3127 return (DDI_PROP_RESULT_EOF); 3128 } 3129 3130 /* 3131 * Move the current location to the start of the next bit of 3132 * undecoded data. 3133 */ 3134 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3135 return (DDI_PROP_RESULT_OK); 3136 3137 case DDI_PROP_CMD_GET_ESIZE: 3138 /* 3139 * Return the size of an encoded integer on OBP 3140 */ 3141 return (PROP_1275_INT_SIZE); 3142 3143 case DDI_PROP_CMD_GET_DSIZE: 3144 /* 3145 * Return the size of a decoded integer on the system. 3146 */ 3147 return (sizeof (int)); 3148 3149 default: 3150 #ifdef DEBUG 3151 panic("ddi_prop_1275_int: %x impossible", cmd); 3152 /*NOTREACHED*/ 3153 #else 3154 return (DDI_PROP_RESULT_ERROR); 3155 #endif /* DEBUG */ 3156 } 3157 } 3158 3159 /* 3160 * 64 bit integer operator. 3161 * 3162 * This is an extension, defined by Sun, to the 1275 integer 3163 * operator. This routine handles the encoding/decoding of 3164 * 64 bit integer properties. 3165 */ 3166 int 3167 ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 3168 { 3169 3170 switch (cmd) { 3171 case DDI_PROP_CMD_DECODE: 3172 /* 3173 * Check that there is encoded data 3174 */ 3175 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3176 return (DDI_PROP_RESULT_ERROR); 3177 if (ph->ph_flags & PH_FROM_PROM) { 3178 return (DDI_PROP_RESULT_ERROR); 3179 } else { 3180 if (ph->ph_size < sizeof (int64_t) || 3181 ((int64_t *)ph->ph_cur_pos > 3182 ((int64_t *)ph->ph_data + 3183 ph->ph_size - sizeof (int64_t)))) 3184 return (DDI_PROP_RESULT_ERROR); 3185 } 3186 /* 3187 * Copy the integer, using the implementation-specific 3188 * copy function if the property is coming from the PROM. 3189 */ 3190 if (ph->ph_flags & PH_FROM_PROM) { 3191 return (DDI_PROP_RESULT_ERROR); 3192 } else { 3193 bcopy(ph->ph_cur_pos, data, sizeof (int64_t)); 3194 } 3195 3196 /* 3197 * Move the current location to the start of the next 3198 * bit of undecoded data. 3199 */ 3200 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3201 sizeof (int64_t); 3202 return (DDI_PROP_RESULT_OK); 3203 3204 case DDI_PROP_CMD_ENCODE: 3205 /* 3206 * Check that there is room to encoded the data 3207 */ 3208 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3209 ph->ph_size < sizeof (int64_t) || 3210 ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 3211 ph->ph_size - sizeof (int64_t)))) 3212 return (DDI_PROP_RESULT_ERROR); 3213 3214 /* 3215 * Encode the integer into the byte stream one byte at a 3216 * time. 3217 */ 3218 bcopy(data, ph->ph_cur_pos, sizeof (int64_t)); 3219 3220 /* 3221 * Move the current location to the start of the next bit of 3222 * space where we can store encoded data. 3223 */ 3224 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3225 sizeof (int64_t); 3226 return (DDI_PROP_RESULT_OK); 3227 3228 case DDI_PROP_CMD_SKIP: 3229 /* 3230 * Check that there is encoded data 3231 */ 3232 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3233 ph->ph_size < sizeof (int64_t)) 3234 return (DDI_PROP_RESULT_ERROR); 3235 3236 if ((caddr_t)ph->ph_cur_pos == 3237 (caddr_t)ph->ph_data + ph->ph_size) { 3238 return (DDI_PROP_RESULT_EOF); 3239 } else if ((caddr_t)ph->ph_cur_pos > 3240 (caddr_t)ph->ph_data + ph->ph_size) { 3241 return (DDI_PROP_RESULT_EOF); 3242 } 3243 3244 /* 3245 * Move the current location to the start of 3246 * the next bit of undecoded data. 3247 */ 3248 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3249 sizeof (int64_t); 3250 return (DDI_PROP_RESULT_OK); 3251 3252 case DDI_PROP_CMD_GET_ESIZE: 3253 /* 3254 * Return the size of an encoded integer on OBP 3255 */ 3256 return (sizeof (int64_t)); 3257 3258 case DDI_PROP_CMD_GET_DSIZE: 3259 /* 3260 * Return the size of a decoded integer on the system. 3261 */ 3262 return (sizeof (int64_t)); 3263 3264 default: 3265 #ifdef DEBUG 3266 panic("ddi_prop_int64_op: %x impossible", cmd); 3267 /*NOTREACHED*/ 3268 #else 3269 return (DDI_PROP_RESULT_ERROR); 3270 #endif /* DEBUG */ 3271 } 3272 } 3273 3274 /* 3275 * OBP 1275 string operator. 3276 * 3277 * OBP strings are NULL terminated. 3278 */ 3279 int 3280 ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data) 3281 { 3282 int n; 3283 char *p; 3284 char *end; 3285 3286 switch (cmd) { 3287 case DDI_PROP_CMD_DECODE: 3288 /* 3289 * Check that there is encoded data 3290 */ 3291 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3292 return (DDI_PROP_RESULT_ERROR); 3293 } 3294 3295 /* 3296 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and 3297 * how to NULL terminate result. 3298 */ 3299 p = (char *)ph->ph_cur_pos; 3300 end = (char *)ph->ph_data + ph->ph_size; 3301 if (p >= end) 3302 return (DDI_PROP_RESULT_EOF); 3303 3304 while (p < end) { 3305 *data++ = *p; 3306 if (*p++ == 0) { /* NULL from OBP */ 3307 ph->ph_cur_pos = p; 3308 return (DDI_PROP_RESULT_OK); 3309 } 3310 } 3311 3312 /* 3313 * If OBP did not NULL terminate string, which happens 3314 * (at least) for 'true'/'false' boolean values, account for 3315 * the space and store null termination on decode. 3316 */ 3317 ph->ph_cur_pos = p; 3318 *data = 0; 3319 return (DDI_PROP_RESULT_OK); 3320 3321 case DDI_PROP_CMD_ENCODE: 3322 /* 3323 * Check that there is room to encoded the data 3324 */ 3325 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3326 return (DDI_PROP_RESULT_ERROR); 3327 } 3328 3329 n = strlen(data) + 1; 3330 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3331 ph->ph_size - n)) { 3332 return (DDI_PROP_RESULT_ERROR); 3333 } 3334 3335 /* 3336 * Copy the NULL terminated string 3337 */ 3338 bcopy(data, ph->ph_cur_pos, n); 3339 3340 /* 3341 * Move the current location to the start of the next bit of 3342 * space where we can store encoded data. 3343 */ 3344 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 3345 return (DDI_PROP_RESULT_OK); 3346 3347 case DDI_PROP_CMD_SKIP: 3348 /* 3349 * Check that there is encoded data 3350 */ 3351 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3352 return (DDI_PROP_RESULT_ERROR); 3353 } 3354 3355 /* 3356 * Return the string length plus one for the NULL 3357 * We know the size of the property, we need to 3358 * ensure that the string is properly formatted, 3359 * since we may be looking up random OBP data. 3360 */ 3361 p = (char *)ph->ph_cur_pos; 3362 end = (char *)ph->ph_data + ph->ph_size; 3363 if (p >= end) 3364 return (DDI_PROP_RESULT_EOF); 3365 3366 while (p < end) { 3367 if (*p++ == 0) { /* NULL from OBP */ 3368 ph->ph_cur_pos = p; 3369 return (DDI_PROP_RESULT_OK); 3370 } 3371 } 3372 3373 /* 3374 * Accommodate the fact that OBP does not always NULL 3375 * terminate strings. 3376 */ 3377 ph->ph_cur_pos = p; 3378 return (DDI_PROP_RESULT_OK); 3379 3380 case DDI_PROP_CMD_GET_ESIZE: 3381 /* 3382 * Return the size of the encoded string on OBP. 3383 */ 3384 return (strlen(data) + 1); 3385 3386 case DDI_PROP_CMD_GET_DSIZE: 3387 /* 3388 * Return the string length plus one for the NULL. 3389 * We know the size of the property, we need to 3390 * ensure that the string is properly formatted, 3391 * since we may be looking up random OBP data. 3392 */ 3393 p = (char *)ph->ph_cur_pos; 3394 end = (char *)ph->ph_data + ph->ph_size; 3395 if (p >= end) 3396 return (DDI_PROP_RESULT_EOF); 3397 3398 for (n = 0; p < end; n++) { 3399 if (*p++ == 0) { /* NULL from OBP */ 3400 ph->ph_cur_pos = p; 3401 return (n + 1); 3402 } 3403 } 3404 3405 /* 3406 * If OBP did not NULL terminate string, which happens for 3407 * 'true'/'false' boolean values, account for the space 3408 * to store null termination here. 3409 */ 3410 ph->ph_cur_pos = p; 3411 return (n + 1); 3412 3413 default: 3414 #ifdef DEBUG 3415 panic("ddi_prop_1275_string: %x impossible", cmd); 3416 /*NOTREACHED*/ 3417 #else 3418 return (DDI_PROP_RESULT_ERROR); 3419 #endif /* DEBUG */ 3420 } 3421 } 3422 3423 /* 3424 * OBP 1275 byte operator 3425 * 3426 * Caller must specify the number of bytes to get. OBP encodes bytes 3427 * as a byte so there is a 1-to-1 translation. 3428 */ 3429 int 3430 ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data, 3431 uint_t nelements) 3432 { 3433 switch (cmd) { 3434 case DDI_PROP_CMD_DECODE: 3435 /* 3436 * Check that there is encoded data 3437 */ 3438 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3439 ph->ph_size < nelements || 3440 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3441 ph->ph_size - nelements))) 3442 return (DDI_PROP_RESULT_ERROR); 3443 3444 /* 3445 * Copy out the bytes 3446 */ 3447 bcopy(ph->ph_cur_pos, data, nelements); 3448 3449 /* 3450 * Move the current location 3451 */ 3452 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3453 return (DDI_PROP_RESULT_OK); 3454 3455 case DDI_PROP_CMD_ENCODE: 3456 /* 3457 * Check that there is room to encode the data 3458 */ 3459 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3460 ph->ph_size < nelements || 3461 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3462 ph->ph_size - nelements))) 3463 return (DDI_PROP_RESULT_ERROR); 3464 3465 /* 3466 * Copy in the bytes 3467 */ 3468 bcopy(data, ph->ph_cur_pos, nelements); 3469 3470 /* 3471 * Move the current location to the start of the next bit of 3472 * space where we can store encoded data. 3473 */ 3474 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3475 return (DDI_PROP_RESULT_OK); 3476 3477 case DDI_PROP_CMD_SKIP: 3478 /* 3479 * Check that there is encoded data 3480 */ 3481 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3482 ph->ph_size < nelements) 3483 return (DDI_PROP_RESULT_ERROR); 3484 3485 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3486 ph->ph_size - nelements)) 3487 return (DDI_PROP_RESULT_EOF); 3488 3489 /* 3490 * Move the current location 3491 */ 3492 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3493 return (DDI_PROP_RESULT_OK); 3494 3495 case DDI_PROP_CMD_GET_ESIZE: 3496 /* 3497 * The size in bytes of the encoded size is the 3498 * same as the decoded size provided by the caller. 3499 */ 3500 return (nelements); 3501 3502 case DDI_PROP_CMD_GET_DSIZE: 3503 /* 3504 * Just return the number of bytes specified by the caller. 3505 */ 3506 return (nelements); 3507 3508 default: 3509 #ifdef DEBUG 3510 panic("ddi_prop_1275_bytes: %x impossible", cmd); 3511 /*NOTREACHED*/ 3512 #else 3513 return (DDI_PROP_RESULT_ERROR); 3514 #endif /* DEBUG */ 3515 } 3516 } 3517 3518 /* 3519 * Used for properties that come from the OBP, hardware configuration files, 3520 * or that are created by calls to ddi_prop_update(9F). 3521 */ 3522 static struct prop_handle_ops prop_1275_ops = { 3523 ddi_prop_1275_int, 3524 ddi_prop_1275_string, 3525 ddi_prop_1275_bytes, 3526 ddi_prop_int64_op 3527 }; 3528 3529 3530 /* 3531 * Interface to create/modify a managed property on child's behalf... 3532 * Flags interpreted are: 3533 * DDI_PROP_CANSLEEP: Allow memory allocation to sleep. 3534 * DDI_PROP_SYSTEM_DEF: Manipulate system list rather than driver list. 3535 * 3536 * Use same dev_t when modifying or undefining a property. 3537 * Search for properties with DDI_DEV_T_ANY to match first named 3538 * property on the list. 3539 * 3540 * Properties are stored LIFO and subsequently will match the first 3541 * `matching' instance. 3542 */ 3543 3544 /* 3545 * ddi_prop_add: Add a software defined property 3546 */ 3547 3548 /* 3549 * define to get a new ddi_prop_t. 3550 * km_flags are KM_SLEEP or KM_NOSLEEP. 3551 */ 3552 3553 #define DDI_NEW_PROP_T(km_flags) \ 3554 (kmem_zalloc(sizeof (ddi_prop_t), km_flags)) 3555 3556 static int 3557 ddi_prop_add(dev_t dev, dev_info_t *dip, int flags, 3558 char *name, caddr_t value, int length) 3559 { 3560 ddi_prop_t *new_propp, *propp; 3561 ddi_prop_t **list_head = &(DEVI(dip)->devi_drv_prop_ptr); 3562 int km_flags = KM_NOSLEEP; 3563 int name_buf_len; 3564 3565 /* 3566 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error. 3567 */ 3568 3569 if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0) 3570 return (DDI_PROP_INVAL_ARG); 3571 3572 if (flags & DDI_PROP_CANSLEEP) 3573 km_flags = KM_SLEEP; 3574 3575 if (flags & DDI_PROP_SYSTEM_DEF) 3576 list_head = &(DEVI(dip)->devi_sys_prop_ptr); 3577 else if (flags & DDI_PROP_HW_DEF) 3578 list_head = &(DEVI(dip)->devi_hw_prop_ptr); 3579 3580 if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL) { 3581 cmn_err(CE_CONT, prop_no_mem_msg, name); 3582 return (DDI_PROP_NO_MEMORY); 3583 } 3584 3585 /* 3586 * If dev is major number 0, then we need to do a ddi_name_to_major 3587 * to get the real major number for the device. This needs to be 3588 * done because some drivers need to call ddi_prop_create in their 3589 * attach routines but they don't have a dev. By creating the dev 3590 * ourself if the major number is 0, drivers will not have to know what 3591 * their major number. They can just create a dev with major number 3592 * 0 and pass it in. For device 0, we will be doing a little extra 3593 * work by recreating the same dev that we already have, but its the 3594 * price you pay :-). 3595 * 3596 * This fixes bug #1098060. 3597 */ 3598 if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) { 3599 new_propp->prop_dev = 3600 makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name), 3601 getminor(dev)); 3602 } else 3603 new_propp->prop_dev = dev; 3604 3605 /* 3606 * Allocate space for property name and copy it in... 3607 */ 3608 3609 name_buf_len = strlen(name) + 1; 3610 new_propp->prop_name = kmem_alloc(name_buf_len, km_flags); 3611 if (new_propp->prop_name == 0) { 3612 kmem_free(new_propp, sizeof (ddi_prop_t)); 3613 cmn_err(CE_CONT, prop_no_mem_msg, name); 3614 return (DDI_PROP_NO_MEMORY); 3615 } 3616 bcopy(name, new_propp->prop_name, name_buf_len); 3617 3618 /* 3619 * Set the property type 3620 */ 3621 new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK; 3622 3623 /* 3624 * Set length and value ONLY if not an explicit property undefine: 3625 * NOTE: value and length are zero for explicit undefines. 3626 */ 3627 3628 if (flags & DDI_PROP_UNDEF_IT) { 3629 new_propp->prop_flags |= DDI_PROP_UNDEF_IT; 3630 } else { 3631 if ((new_propp->prop_len = length) != 0) { 3632 new_propp->prop_val = kmem_alloc(length, km_flags); 3633 if (new_propp->prop_val == 0) { 3634 kmem_free(new_propp->prop_name, name_buf_len); 3635 kmem_free(new_propp, sizeof (ddi_prop_t)); 3636 cmn_err(CE_CONT, prop_no_mem_msg, name); 3637 return (DDI_PROP_NO_MEMORY); 3638 } 3639 bcopy(value, new_propp->prop_val, length); 3640 } 3641 } 3642 3643 /* 3644 * Link property into beginning of list. (Properties are LIFO order.) 3645 */ 3646 3647 mutex_enter(&(DEVI(dip)->devi_lock)); 3648 propp = *list_head; 3649 new_propp->prop_next = propp; 3650 *list_head = new_propp; 3651 mutex_exit(&(DEVI(dip)->devi_lock)); 3652 return (DDI_PROP_SUCCESS); 3653 } 3654 3655 3656 /* 3657 * ddi_prop_change: Modify a software managed property value 3658 * 3659 * Set new length and value if found. 3660 * returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or 3661 * input name is the NULL string. 3662 * returns DDI_PROP_NO_MEMORY if unable to allocate memory 3663 * 3664 * Note: an undef can be modified to be a define, 3665 * (you can't go the other way.) 3666 */ 3667 3668 static int 3669 ddi_prop_change(dev_t dev, dev_info_t *dip, int flags, 3670 char *name, caddr_t value, int length) 3671 { 3672 ddi_prop_t *propp; 3673 ddi_prop_t **ppropp; 3674 caddr_t p = NULL; 3675 3676 if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0)) 3677 return (DDI_PROP_INVAL_ARG); 3678 3679 /* 3680 * Preallocate buffer, even if we don't need it... 3681 */ 3682 if (length != 0) { 3683 p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ? 3684 KM_SLEEP : KM_NOSLEEP); 3685 if (p == NULL) { 3686 cmn_err(CE_CONT, prop_no_mem_msg, name); 3687 return (DDI_PROP_NO_MEMORY); 3688 } 3689 } 3690 3691 /* 3692 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major 3693 * number, a real dev_t value should be created based upon the dip's 3694 * binding driver. See ddi_prop_add... 3695 */ 3696 if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) 3697 dev = makedevice( 3698 ddi_name_to_major(DEVI(dip)->devi_binding_name), 3699 getminor(dev)); 3700 3701 /* 3702 * Check to see if the property exists. If so we modify it. 3703 * Else we create it by calling ddi_prop_add(). 3704 */ 3705 mutex_enter(&(DEVI(dip)->devi_lock)); 3706 ppropp = &DEVI(dip)->devi_drv_prop_ptr; 3707 if (flags & DDI_PROP_SYSTEM_DEF) 3708 ppropp = &DEVI(dip)->devi_sys_prop_ptr; 3709 else if (flags & DDI_PROP_HW_DEF) 3710 ppropp = &DEVI(dip)->devi_hw_prop_ptr; 3711 3712 if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) { 3713 /* 3714 * Need to reallocate buffer? If so, do it 3715 * carefully (reuse same space if new prop 3716 * is same size and non-NULL sized). 3717 */ 3718 if (length != 0) 3719 bcopy(value, p, length); 3720 3721 if (propp->prop_len != 0) 3722 kmem_free(propp->prop_val, propp->prop_len); 3723 3724 propp->prop_len = length; 3725 propp->prop_val = p; 3726 propp->prop_flags &= ~DDI_PROP_UNDEF_IT; 3727 mutex_exit(&(DEVI(dip)->devi_lock)); 3728 return (DDI_PROP_SUCCESS); 3729 } 3730 3731 mutex_exit(&(DEVI(dip)->devi_lock)); 3732 if (length != 0) 3733 kmem_free(p, length); 3734 3735 return (ddi_prop_add(dev, dip, flags, name, value, length)); 3736 } 3737 3738 /* 3739 * Common update routine used to update and encode a property. Creates 3740 * a property handle, calls the property encode routine, figures out if 3741 * the property already exists and updates if it does. Otherwise it 3742 * creates if it does not exist. 3743 */ 3744 int 3745 ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags, 3746 char *name, void *data, uint_t nelements, 3747 int (*prop_create)(prop_handle_t *, void *data, uint_t nelements)) 3748 { 3749 prop_handle_t ph; 3750 int rval; 3751 uint_t ourflags; 3752 3753 /* 3754 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3755 * return error. 3756 */ 3757 if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3758 return (DDI_PROP_INVAL_ARG); 3759 3760 /* 3761 * Create the handle 3762 */ 3763 ph.ph_data = NULL; 3764 ph.ph_cur_pos = NULL; 3765 ph.ph_save_pos = NULL; 3766 ph.ph_size = 0; 3767 ph.ph_ops = &prop_1275_ops; 3768 3769 /* 3770 * ourflags: 3771 * For compatibility with the old interfaces. The old interfaces 3772 * didn't sleep by default and slept when the flag was set. These 3773 * interfaces to the opposite. So the old interfaces now set the 3774 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep. 3775 * 3776 * ph.ph_flags: 3777 * Blocked data or unblocked data allocation 3778 * for ph.ph_data in ddi_prop_encode_alloc() 3779 */ 3780 if (flags & DDI_PROP_DONTSLEEP) { 3781 ourflags = flags; 3782 ph.ph_flags = DDI_PROP_DONTSLEEP; 3783 } else { 3784 ourflags = flags | DDI_PROP_CANSLEEP; 3785 ph.ph_flags = DDI_PROP_CANSLEEP; 3786 } 3787 3788 /* 3789 * Encode the data and store it in the property handle by 3790 * calling the prop_encode routine. 3791 */ 3792 if ((rval = (*prop_create)(&ph, data, nelements)) != 3793 DDI_PROP_SUCCESS) { 3794 if (rval == DDI_PROP_NO_MEMORY) 3795 cmn_err(CE_CONT, prop_no_mem_msg, name); 3796 if (ph.ph_size != 0) 3797 kmem_free(ph.ph_data, ph.ph_size); 3798 return (rval); 3799 } 3800 3801 /* 3802 * The old interfaces use a stacking approach to creating 3803 * properties. If we are being called from the old interfaces, 3804 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a 3805 * create without checking. 3806 */ 3807 if (flags & DDI_PROP_STACK_CREATE) { 3808 rval = ddi_prop_add(match_dev, dip, 3809 ourflags, name, ph.ph_data, ph.ph_size); 3810 } else { 3811 rval = ddi_prop_change(match_dev, dip, 3812 ourflags, name, ph.ph_data, ph.ph_size); 3813 } 3814 3815 /* 3816 * Free the encoded data allocated in the prop_encode routine. 3817 */ 3818 if (ph.ph_size != 0) 3819 kmem_free(ph.ph_data, ph.ph_size); 3820 3821 return (rval); 3822 } 3823 3824 3825 /* 3826 * ddi_prop_create: Define a managed property: 3827 * See above for details. 3828 */ 3829 3830 int 3831 ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, 3832 char *name, caddr_t value, int length) 3833 { 3834 if (!(flag & DDI_PROP_CANSLEEP)) { 3835 flag |= DDI_PROP_DONTSLEEP; 3836 #ifdef DDI_PROP_DEBUG 3837 if (length != 0) 3838 cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete," 3839 "use ddi_prop_update (prop = %s, node = %s%d)", 3840 name, ddi_driver_name(dip), ddi_get_instance(dip)); 3841 #endif /* DDI_PROP_DEBUG */ 3842 } 3843 flag &= ~DDI_PROP_SYSTEM_DEF; 3844 return (ddi_prop_update_common(dev, dip, 3845 (flag | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY), name, 3846 value, length, ddi_prop_fm_encode_bytes)); 3847 } 3848 3849 int 3850 e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, 3851 char *name, caddr_t value, int length) 3852 { 3853 if (!(flag & DDI_PROP_CANSLEEP)) 3854 flag |= DDI_PROP_DONTSLEEP; 3855 return (ddi_prop_update_common(dev, dip, 3856 (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | 3857 DDI_PROP_TYPE_ANY), 3858 name, value, length, ddi_prop_fm_encode_bytes)); 3859 } 3860 3861 int 3862 ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag, 3863 char *name, caddr_t value, int length) 3864 { 3865 ASSERT((flag & DDI_PROP_TYPE_MASK) == 0); 3866 3867 /* 3868 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3869 * return error. 3870 */ 3871 if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3872 return (DDI_PROP_INVAL_ARG); 3873 3874 if (!(flag & DDI_PROP_CANSLEEP)) 3875 flag |= DDI_PROP_DONTSLEEP; 3876 flag &= ~DDI_PROP_SYSTEM_DEF; 3877 if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0) 3878 return (DDI_PROP_NOT_FOUND); 3879 3880 return (ddi_prop_update_common(dev, dip, 3881 (flag | DDI_PROP_TYPE_BYTE), name, 3882 value, length, ddi_prop_fm_encode_bytes)); 3883 } 3884 3885 int 3886 e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag, 3887 char *name, caddr_t value, int length) 3888 { 3889 ASSERT((flag & DDI_PROP_TYPE_MASK) == 0); 3890 3891 /* 3892 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3893 * return error. 3894 */ 3895 if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3896 return (DDI_PROP_INVAL_ARG); 3897 3898 if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0) 3899 return (DDI_PROP_NOT_FOUND); 3900 3901 if (!(flag & DDI_PROP_CANSLEEP)) 3902 flag |= DDI_PROP_DONTSLEEP; 3903 return (ddi_prop_update_common(dev, dip, 3904 (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE), 3905 name, value, length, ddi_prop_fm_encode_bytes)); 3906 } 3907 3908 3909 /* 3910 * Common lookup routine used to lookup and decode a property. 3911 * Creates a property handle, searches for the raw encoded data, 3912 * fills in the handle, and calls the property decode functions 3913 * passed in. 3914 * 3915 * This routine is not static because ddi_bus_prop_op() which lives in 3916 * ddi_impl.c calls it. No driver should be calling this routine. 3917 */ 3918 int 3919 ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip, 3920 uint_t flags, char *name, void *data, uint_t *nelements, 3921 int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements)) 3922 { 3923 int rval; 3924 uint_t ourflags; 3925 prop_handle_t ph; 3926 3927 if ((match_dev == DDI_DEV_T_NONE) || 3928 (name == NULL) || (strlen(name) == 0)) 3929 return (DDI_PROP_INVAL_ARG); 3930 3931 ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags : 3932 flags | DDI_PROP_CANSLEEP; 3933 3934 /* 3935 * Get the encoded data 3936 */ 3937 bzero(&ph, sizeof (prop_handle_t)); 3938 3939 if (flags & DDI_UNBND_DLPI2) { 3940 /* 3941 * For unbound dlpi style-2 devices, index into 3942 * the devnames' array and search the global 3943 * property list. 3944 */ 3945 ourflags &= ~DDI_UNBND_DLPI2; 3946 rval = i_ddi_prop_search_global(match_dev, 3947 ourflags, name, &ph.ph_data, &ph.ph_size); 3948 } else { 3949 rval = ddi_prop_search_common(match_dev, dip, 3950 PROP_LEN_AND_VAL_ALLOC, ourflags, name, 3951 &ph.ph_data, &ph.ph_size); 3952 3953 } 3954 3955 if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) { 3956 ASSERT(ph.ph_data == NULL); 3957 ASSERT(ph.ph_size == 0); 3958 return (rval); 3959 } 3960 3961 /* 3962 * If the encoded data came from a OBP or software 3963 * use the 1275 OBP decode/encode routines. 3964 */ 3965 ph.ph_cur_pos = ph.ph_data; 3966 ph.ph_save_pos = ph.ph_data; 3967 ph.ph_ops = &prop_1275_ops; 3968 ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0; 3969 3970 rval = (*prop_decoder)(&ph, data, nelements); 3971 3972 /* 3973 * Free the encoded data 3974 */ 3975 if (ph.ph_size != 0) 3976 kmem_free(ph.ph_data, ph.ph_size); 3977 3978 return (rval); 3979 } 3980 3981 /* 3982 * Lookup and return an array of composite properties. The driver must 3983 * provide the decode routine. 3984 */ 3985 int 3986 ddi_prop_lookup(dev_t match_dev, dev_info_t *dip, 3987 uint_t flags, char *name, void *data, uint_t *nelements, 3988 int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements)) 3989 { 3990 return (ddi_prop_lookup_common(match_dev, dip, 3991 (flags | DDI_PROP_TYPE_COMPOSITE), name, 3992 data, nelements, prop_decoder)); 3993 } 3994 3995 /* 3996 * Return 1 if a property exists (no type checking done). 3997 * Return 0 if it does not exist. 3998 */ 3999 int 4000 ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name) 4001 { 4002 int i; 4003 uint_t x = 0; 4004 4005 i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS, 4006 flags | DDI_PROP_TYPE_MASK, name, NULL, &x); 4007 return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275); 4008 } 4009 4010 4011 /* 4012 * Update an array of composite properties. The driver must 4013 * provide the encode routine. 4014 */ 4015 int 4016 ddi_prop_update(dev_t match_dev, dev_info_t *dip, 4017 char *name, void *data, uint_t nelements, 4018 int (*prop_create)(prop_handle_t *, void *data, uint_t nelements)) 4019 { 4020 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE, 4021 name, data, nelements, prop_create)); 4022 } 4023 4024 /* 4025 * Get a single integer or boolean property and return it. 4026 * If the property does not exists, or cannot be decoded, 4027 * then return the defvalue passed in. 4028 * 4029 * This routine always succeeds. 4030 */ 4031 int 4032 ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags, 4033 char *name, int defvalue) 4034 { 4035 int data; 4036 uint_t nelements; 4037 int rval; 4038 4039 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4040 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4041 #ifdef DEBUG 4042 if (dip != NULL) { 4043 cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag" 4044 " 0x%x (prop = %s, node = %s%d)", flags, 4045 name, ddi_driver_name(dip), ddi_get_instance(dip)); 4046 } 4047 #endif /* DEBUG */ 4048 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4049 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4050 } 4051 4052 if ((rval = ddi_prop_lookup_common(match_dev, dip, 4053 (flags | DDI_PROP_TYPE_INT), name, &data, &nelements, 4054 ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) { 4055 if (rval == DDI_PROP_END_OF_DATA) 4056 data = 1; 4057 else 4058 data = defvalue; 4059 } 4060 return (data); 4061 } 4062 4063 /* 4064 * Get a single 64 bit integer or boolean property and return it. 4065 * If the property does not exists, or cannot be decoded, 4066 * then return the defvalue passed in. 4067 * 4068 * This routine always succeeds. 4069 */ 4070 int64_t 4071 ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags, 4072 char *name, int64_t defvalue) 4073 { 4074 int64_t data; 4075 uint_t nelements; 4076 int rval; 4077 4078 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4079 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4080 #ifdef DEBUG 4081 if (dip != NULL) { 4082 cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag" 4083 " 0x%x (prop = %s, node = %s%d)", flags, 4084 name, ddi_driver_name(dip), ddi_get_instance(dip)); 4085 } 4086 #endif /* DEBUG */ 4087 return (DDI_PROP_INVAL_ARG); 4088 } 4089 4090 if ((rval = ddi_prop_lookup_common(match_dev, dip, 4091 (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM), 4092 name, &data, &nelements, ddi_prop_fm_decode_int64)) 4093 != DDI_PROP_SUCCESS) { 4094 if (rval == DDI_PROP_END_OF_DATA) 4095 data = 1; 4096 else 4097 data = defvalue; 4098 } 4099 return (data); 4100 } 4101 4102 /* 4103 * Get an array of integer property 4104 */ 4105 int 4106 ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4107 char *name, int **data, uint_t *nelements) 4108 { 4109 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4110 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4111 #ifdef DEBUG 4112 if (dip != NULL) { 4113 cmn_err(CE_WARN, "ddi_prop_lookup_int_array: " 4114 "invalid flag 0x%x (prop = %s, node = %s%d)", 4115 flags, name, ddi_driver_name(dip), 4116 ddi_get_instance(dip)); 4117 } 4118 #endif /* DEBUG */ 4119 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4120 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4121 } 4122 4123 return (ddi_prop_lookup_common(match_dev, dip, 4124 (flags | DDI_PROP_TYPE_INT), name, data, 4125 nelements, ddi_prop_fm_decode_ints)); 4126 } 4127 4128 /* 4129 * Get an array of 64 bit integer properties 4130 */ 4131 int 4132 ddi_prop_lookup_int64_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4133 char *name, int64_t **data, uint_t *nelements) 4134 { 4135 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4136 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4137 #ifdef DEBUG 4138 if (dip != NULL) { 4139 cmn_err(CE_WARN, "ddi_prop_lookup_int64_array: " 4140 "invalid flag 0x%x (prop = %s, node = %s%d)", 4141 flags, name, ddi_driver_name(dip), 4142 ddi_get_instance(dip)); 4143 } 4144 #endif /* DEBUG */ 4145 return (DDI_PROP_INVAL_ARG); 4146 } 4147 4148 return (ddi_prop_lookup_common(match_dev, dip, 4149 (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM), 4150 name, data, nelements, ddi_prop_fm_decode_int64_array)); 4151 } 4152 4153 /* 4154 * Update a single integer property. If the property exists on the drivers 4155 * property list it updates, else it creates it. 4156 */ 4157 int 4158 ddi_prop_update_int(dev_t match_dev, dev_info_t *dip, 4159 char *name, int data) 4160 { 4161 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT, 4162 name, &data, 1, ddi_prop_fm_encode_ints)); 4163 } 4164 4165 /* 4166 * Update a single 64 bit integer property. 4167 * Update the driver property list if it exists, else create it. 4168 */ 4169 int 4170 ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip, 4171 char *name, int64_t data) 4172 { 4173 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64, 4174 name, &data, 1, ddi_prop_fm_encode_int64)); 4175 } 4176 4177 int 4178 e_ddi_prop_update_int(dev_t match_dev, dev_info_t *dip, 4179 char *name, int data) 4180 { 4181 return (ddi_prop_update_common(match_dev, dip, 4182 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT, 4183 name, &data, 1, ddi_prop_fm_encode_ints)); 4184 } 4185 4186 int 4187 e_ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip, 4188 char *name, int64_t data) 4189 { 4190 return (ddi_prop_update_common(match_dev, dip, 4191 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64, 4192 name, &data, 1, ddi_prop_fm_encode_int64)); 4193 } 4194 4195 /* 4196 * Update an array of integer property. If the property exists on the drivers 4197 * property list it updates, else it creates it. 4198 */ 4199 int 4200 ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip, 4201 char *name, int *data, uint_t nelements) 4202 { 4203 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT, 4204 name, data, nelements, ddi_prop_fm_encode_ints)); 4205 } 4206 4207 /* 4208 * Update an array of 64 bit integer properties. 4209 * Update the driver property list if it exists, else create it. 4210 */ 4211 int 4212 ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip, 4213 char *name, int64_t *data, uint_t nelements) 4214 { 4215 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64, 4216 name, data, nelements, ddi_prop_fm_encode_int64)); 4217 } 4218 4219 int 4220 e_ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip, 4221 char *name, int64_t *data, uint_t nelements) 4222 { 4223 return (ddi_prop_update_common(match_dev, dip, 4224 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64, 4225 name, data, nelements, ddi_prop_fm_encode_int64)); 4226 } 4227 4228 int 4229 e_ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip, 4230 char *name, int *data, uint_t nelements) 4231 { 4232 return (ddi_prop_update_common(match_dev, dip, 4233 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT, 4234 name, data, nelements, ddi_prop_fm_encode_ints)); 4235 } 4236 4237 /* 4238 * Get a single string property. 4239 */ 4240 int 4241 ddi_prop_lookup_string(dev_t match_dev, dev_info_t *dip, uint_t flags, 4242 char *name, char **data) 4243 { 4244 uint_t x; 4245 4246 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4247 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4248 #ifdef DEBUG 4249 if (dip != NULL) { 4250 cmn_err(CE_WARN, "%s: invalid flag 0x%x " 4251 "(prop = %s, node = %s%d); invalid bits ignored", 4252 "ddi_prop_lookup_string", flags, name, 4253 ddi_driver_name(dip), ddi_get_instance(dip)); 4254 } 4255 #endif /* DEBUG */ 4256 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4257 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4258 } 4259 4260 return (ddi_prop_lookup_common(match_dev, dip, 4261 (flags | DDI_PROP_TYPE_STRING), name, data, 4262 &x, ddi_prop_fm_decode_string)); 4263 } 4264 4265 /* 4266 * Get an array of strings property. 4267 */ 4268 int 4269 ddi_prop_lookup_string_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4270 char *name, char ***data, uint_t *nelements) 4271 { 4272 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4273 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4274 #ifdef DEBUG 4275 if (dip != NULL) { 4276 cmn_err(CE_WARN, "ddi_prop_lookup_string_array: " 4277 "invalid flag 0x%x (prop = %s, node = %s%d)", 4278 flags, name, ddi_driver_name(dip), 4279 ddi_get_instance(dip)); 4280 } 4281 #endif /* DEBUG */ 4282 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4283 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4284 } 4285 4286 return (ddi_prop_lookup_common(match_dev, dip, 4287 (flags | DDI_PROP_TYPE_STRING), name, data, 4288 nelements, ddi_prop_fm_decode_strings)); 4289 } 4290 4291 /* 4292 * Update a single string property. 4293 */ 4294 int 4295 ddi_prop_update_string(dev_t match_dev, dev_info_t *dip, 4296 char *name, char *data) 4297 { 4298 return (ddi_prop_update_common(match_dev, dip, 4299 DDI_PROP_TYPE_STRING, name, &data, 1, 4300 ddi_prop_fm_encode_string)); 4301 } 4302 4303 int 4304 e_ddi_prop_update_string(dev_t match_dev, dev_info_t *dip, 4305 char *name, char *data) 4306 { 4307 return (ddi_prop_update_common(match_dev, dip, 4308 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING, 4309 name, &data, 1, ddi_prop_fm_encode_string)); 4310 } 4311 4312 4313 /* 4314 * Update an array of strings property. 4315 */ 4316 int 4317 ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip, 4318 char *name, char **data, uint_t nelements) 4319 { 4320 return (ddi_prop_update_common(match_dev, dip, 4321 DDI_PROP_TYPE_STRING, name, data, nelements, 4322 ddi_prop_fm_encode_strings)); 4323 } 4324 4325 int 4326 e_ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip, 4327 char *name, char **data, uint_t nelements) 4328 { 4329 return (ddi_prop_update_common(match_dev, dip, 4330 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING, 4331 name, data, nelements, 4332 ddi_prop_fm_encode_strings)); 4333 } 4334 4335 4336 /* 4337 * Get an array of bytes property. 4338 */ 4339 int 4340 ddi_prop_lookup_byte_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4341 char *name, uchar_t **data, uint_t *nelements) 4342 { 4343 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4344 LDI_DEV_T_ANY | DDI_UNBND_DLPI2)) { 4345 #ifdef DEBUG 4346 if (dip != NULL) { 4347 cmn_err(CE_WARN, "ddi_prop_lookup_byte_array: " 4348 " invalid flag 0x%x (prop = %s, node = %s%d)", 4349 flags, name, ddi_driver_name(dip), 4350 ddi_get_instance(dip)); 4351 } 4352 #endif /* DEBUG */ 4353 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4354 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4355 } 4356 4357 return (ddi_prop_lookup_common(match_dev, dip, 4358 (flags | DDI_PROP_TYPE_BYTE), name, data, 4359 nelements, ddi_prop_fm_decode_bytes)); 4360 } 4361 4362 /* 4363 * Update an array of bytes property. 4364 */ 4365 int 4366 ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip, 4367 char *name, uchar_t *data, uint_t nelements) 4368 { 4369 if (nelements == 0) 4370 return (DDI_PROP_INVAL_ARG); 4371 4372 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_BYTE, 4373 name, data, nelements, ddi_prop_fm_encode_bytes)); 4374 } 4375 4376 4377 int 4378 e_ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip, 4379 char *name, uchar_t *data, uint_t nelements) 4380 { 4381 if (nelements == 0) 4382 return (DDI_PROP_INVAL_ARG); 4383 4384 return (ddi_prop_update_common(match_dev, dip, 4385 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE, 4386 name, data, nelements, ddi_prop_fm_encode_bytes)); 4387 } 4388 4389 4390 /* 4391 * ddi_prop_remove_common: Undefine a managed property: 4392 * Input dev_t must match dev_t when defined. 4393 * Returns DDI_PROP_NOT_FOUND, possibly. 4394 * DDI_PROP_INVAL_ARG is also possible if dev is 4395 * DDI_DEV_T_ANY or incoming name is the NULL string. 4396 */ 4397 int 4398 ddi_prop_remove_common(dev_t dev, dev_info_t *dip, char *name, int flag) 4399 { 4400 ddi_prop_t **list_head = &(DEVI(dip)->devi_drv_prop_ptr); 4401 ddi_prop_t *propp; 4402 ddi_prop_t *lastpropp = NULL; 4403 4404 if ((dev == DDI_DEV_T_ANY) || (name == (char *)0) || 4405 (strlen(name) == 0)) { 4406 return (DDI_PROP_INVAL_ARG); 4407 } 4408 4409 if (flag & DDI_PROP_SYSTEM_DEF) 4410 list_head = &(DEVI(dip)->devi_sys_prop_ptr); 4411 else if (flag & DDI_PROP_HW_DEF) 4412 list_head = &(DEVI(dip)->devi_hw_prop_ptr); 4413 4414 mutex_enter(&(DEVI(dip)->devi_lock)); 4415 4416 for (propp = *list_head; propp != NULL; propp = propp->prop_next) { 4417 if (DDI_STRSAME(propp->prop_name, name) && 4418 (dev == propp->prop_dev)) { 4419 /* 4420 * Unlink this propp allowing for it to 4421 * be first in the list: 4422 */ 4423 4424 if (lastpropp == NULL) 4425 *list_head = propp->prop_next; 4426 else 4427 lastpropp->prop_next = propp->prop_next; 4428 4429 mutex_exit(&(DEVI(dip)->devi_lock)); 4430 4431 /* 4432 * Free memory and return... 4433 */ 4434 kmem_free(propp->prop_name, 4435 strlen(propp->prop_name) + 1); 4436 if (propp->prop_len != 0) 4437 kmem_free(propp->prop_val, propp->prop_len); 4438 kmem_free(propp, sizeof (ddi_prop_t)); 4439 return (DDI_PROP_SUCCESS); 4440 } 4441 lastpropp = propp; 4442 } 4443 mutex_exit(&(DEVI(dip)->devi_lock)); 4444 return (DDI_PROP_NOT_FOUND); 4445 } 4446 4447 int 4448 ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name) 4449 { 4450 return (ddi_prop_remove_common(dev, dip, name, 0)); 4451 } 4452 4453 int 4454 e_ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name) 4455 { 4456 return (ddi_prop_remove_common(dev, dip, name, DDI_PROP_SYSTEM_DEF)); 4457 } 4458 4459 /* 4460 * e_ddi_prop_list_delete: remove a list of properties 4461 * Note that the caller needs to provide the required protection 4462 * (eg. devi_lock if these properties are still attached to a devi) 4463 */ 4464 void 4465 e_ddi_prop_list_delete(ddi_prop_t *props) 4466 { 4467 i_ddi_prop_list_delete(props); 4468 } 4469 4470 /* 4471 * ddi_prop_remove_all_common: 4472 * Used before unloading a driver to remove 4473 * all properties. (undefines all dev_t's props.) 4474 * Also removes `explicitly undefined' props. 4475 * No errors possible. 4476 */ 4477 void 4478 ddi_prop_remove_all_common(dev_info_t *dip, int flag) 4479 { 4480 ddi_prop_t **list_head; 4481 4482 mutex_enter(&(DEVI(dip)->devi_lock)); 4483 if (flag & DDI_PROP_SYSTEM_DEF) { 4484 list_head = &(DEVI(dip)->devi_sys_prop_ptr); 4485 } else if (flag & DDI_PROP_HW_DEF) { 4486 list_head = &(DEVI(dip)->devi_hw_prop_ptr); 4487 } else { 4488 list_head = &(DEVI(dip)->devi_drv_prop_ptr); 4489 } 4490 i_ddi_prop_list_delete(*list_head); 4491 *list_head = NULL; 4492 mutex_exit(&(DEVI(dip)->devi_lock)); 4493 } 4494 4495 4496 /* 4497 * ddi_prop_remove_all: Remove all driver prop definitions. 4498 */ 4499 4500 void 4501 ddi_prop_remove_all(dev_info_t *dip) 4502 { 4503 ddi_prop_remove_all_common(dip, 0); 4504 } 4505 4506 /* 4507 * e_ddi_prop_remove_all: Remove all system prop definitions. 4508 */ 4509 4510 void 4511 e_ddi_prop_remove_all(dev_info_t *dip) 4512 { 4513 ddi_prop_remove_all_common(dip, (int)DDI_PROP_SYSTEM_DEF); 4514 } 4515 4516 4517 /* 4518 * ddi_prop_undefine: Explicitly undefine a property. Property 4519 * searches which match this property return 4520 * the error code DDI_PROP_UNDEFINED. 4521 * 4522 * Use ddi_prop_remove to negate effect of 4523 * ddi_prop_undefine 4524 * 4525 * See above for error returns. 4526 */ 4527 4528 int 4529 ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name) 4530 { 4531 if (!(flag & DDI_PROP_CANSLEEP)) 4532 flag |= DDI_PROP_DONTSLEEP; 4533 return (ddi_prop_update_common(dev, dip, 4534 (flag | DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | 4535 DDI_PROP_TYPE_ANY), name, NULL, 0, ddi_prop_fm_encode_bytes)); 4536 } 4537 4538 int 4539 e_ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name) 4540 { 4541 if (!(flag & DDI_PROP_CANSLEEP)) 4542 flag |= DDI_PROP_DONTSLEEP; 4543 return (ddi_prop_update_common(dev, dip, 4544 (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | 4545 DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY), 4546 name, NULL, 0, ddi_prop_fm_encode_bytes)); 4547 } 4548 4549 /* 4550 * Code to search hardware layer (PROM), if it exists, on behalf of child. 4551 * 4552 * if input dip != child_dip, then call is on behalf of child 4553 * to search PROM, do it via ddi_prop_search_common() and ascend only 4554 * if allowed. 4555 * 4556 * if input dip == ch_dip (child_dip), call is on behalf of root driver, 4557 * to search for PROM defined props only. 4558 * 4559 * Note that the PROM search is done only if the requested dev 4560 * is either DDI_DEV_T_ANY or DDI_DEV_T_NONE. PROM properties 4561 * have no associated dev, thus are automatically associated with 4562 * DDI_DEV_T_NONE. 4563 * 4564 * Modifying flag DDI_PROP_NOTPROM inhibits the search in the h/w layer. 4565 * 4566 * Returns DDI_PROP_FOUND_1275 if found to indicate to framework 4567 * that the property resides in the prom. 4568 */ 4569 int 4570 impl_ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip, 4571 ddi_prop_op_t prop_op, int mod_flags, 4572 char *name, caddr_t valuep, int *lengthp) 4573 { 4574 int len; 4575 caddr_t buffer; 4576 4577 /* 4578 * If requested dev is DDI_DEV_T_NONE or DDI_DEV_T_ANY, then 4579 * look in caller's PROM if it's a self identifying device... 4580 * 4581 * Note that this is very similar to ddi_prop_op, but we 4582 * search the PROM instead of the s/w defined properties, 4583 * and we are called on by the parent driver to do this for 4584 * the child. 4585 */ 4586 4587 if (((dev == DDI_DEV_T_NONE) || (dev == DDI_DEV_T_ANY)) && 4588 ndi_dev_is_prom_node(ch_dip) && 4589 ((mod_flags & DDI_PROP_NOTPROM) == 0)) { 4590 len = prom_getproplen((pnode_t)DEVI(ch_dip)->devi_nodeid, name); 4591 if (len == -1) { 4592 return (DDI_PROP_NOT_FOUND); 4593 } 4594 4595 /* 4596 * If exists only request, we're done 4597 */ 4598 if (prop_op == PROP_EXISTS) { 4599 return (DDI_PROP_FOUND_1275); 4600 } 4601 4602 /* 4603 * If length only request or prop length == 0, get out 4604 */ 4605 if ((prop_op == PROP_LEN) || (len == 0)) { 4606 *lengthp = len; 4607 return (DDI_PROP_FOUND_1275); 4608 } 4609 4610 /* 4611 * Allocate buffer if required... (either way `buffer' 4612 * is receiving address). 4613 */ 4614 4615 switch (prop_op) { 4616 4617 case PROP_LEN_AND_VAL_ALLOC: 4618 4619 buffer = kmem_alloc((size_t)len, 4620 mod_flags & DDI_PROP_CANSLEEP ? 4621 KM_SLEEP : KM_NOSLEEP); 4622 if (buffer == NULL) { 4623 return (DDI_PROP_NO_MEMORY); 4624 } 4625 *(caddr_t *)valuep = buffer; 4626 break; 4627 4628 case PROP_LEN_AND_VAL_BUF: 4629 4630 if (len > (*lengthp)) { 4631 *lengthp = len; 4632 return (DDI_PROP_BUF_TOO_SMALL); 4633 } 4634 4635 buffer = valuep; 4636 break; 4637 4638 default: 4639 break; 4640 } 4641 4642 /* 4643 * Call the PROM function to do the copy. 4644 */ 4645 (void) prom_getprop((pnode_t)DEVI(ch_dip)->devi_nodeid, 4646 name, buffer); 4647 4648 *lengthp = len; /* return the actual length to the caller */ 4649 (void) impl_fix_props(dip, ch_dip, name, len, buffer); 4650 return (DDI_PROP_FOUND_1275); 4651 } 4652 4653 return (DDI_PROP_NOT_FOUND); 4654 } 4655 4656 /* 4657 * The ddi_bus_prop_op default bus nexus prop op function. 4658 * 4659 * Code to search hardware layer (PROM), if it exists, 4660 * on behalf of child, then, if appropriate, ascend and check 4661 * my own software defined properties... 4662 */ 4663 int 4664 ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip, 4665 ddi_prop_op_t prop_op, int mod_flags, 4666 char *name, caddr_t valuep, int *lengthp) 4667 { 4668 int error; 4669 4670 error = impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op, mod_flags, 4671 name, valuep, lengthp); 4672 4673 if (error == DDI_PROP_SUCCESS || error == DDI_PROP_FOUND_1275 || 4674 error == DDI_PROP_BUF_TOO_SMALL) 4675 return (error); 4676 4677 if (error == DDI_PROP_NO_MEMORY) { 4678 cmn_err(CE_CONT, prop_no_mem_msg, name); 4679 return (DDI_PROP_NO_MEMORY); 4680 } 4681 4682 /* 4683 * Check the 'options' node as a last resort 4684 */ 4685 if ((mod_flags & DDI_PROP_DONTPASS) != 0) 4686 return (DDI_PROP_NOT_FOUND); 4687 4688 if (ch_dip == ddi_root_node()) { 4689 /* 4690 * As a last resort, when we've reached 4691 * the top and still haven't found the 4692 * property, see if the desired property 4693 * is attached to the options node. 4694 * 4695 * The options dip is attached right after boot. 4696 */ 4697 ASSERT(options_dip != NULL); 4698 /* 4699 * Force the "don't pass" flag to *just* see 4700 * what the options node has to offer. 4701 */ 4702 return (ddi_prop_search_common(dev, options_dip, prop_op, 4703 mod_flags|DDI_PROP_DONTPASS, name, valuep, 4704 (uint_t *)lengthp)); 4705 } 4706 4707 /* 4708 * Otherwise, continue search with parent's s/w defined properties... 4709 * NOTE: Using `dip' in following call increments the level. 4710 */ 4711 4712 return (ddi_prop_search_common(dev, dip, prop_op, mod_flags, 4713 name, valuep, (uint_t *)lengthp)); 4714 } 4715 4716 /* 4717 * External property functions used by other parts of the kernel... 4718 */ 4719 4720 /* 4721 * e_ddi_getlongprop: See comments for ddi_get_longprop. 4722 */ 4723 4724 int 4725 e_ddi_getlongprop(dev_t dev, vtype_t type, char *name, int flags, 4726 caddr_t valuep, int *lengthp) 4727 { 4728 _NOTE(ARGUNUSED(type)) 4729 dev_info_t *devi; 4730 ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_ALLOC; 4731 int error; 4732 4733 if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 4734 return (DDI_PROP_NOT_FOUND); 4735 4736 error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp); 4737 ddi_release_devi(devi); 4738 return (error); 4739 } 4740 4741 /* 4742 * e_ddi_getlongprop_buf: See comments for ddi_getlongprop_buf. 4743 */ 4744 4745 int 4746 e_ddi_getlongprop_buf(dev_t dev, vtype_t type, char *name, int flags, 4747 caddr_t valuep, int *lengthp) 4748 { 4749 _NOTE(ARGUNUSED(type)) 4750 dev_info_t *devi; 4751 ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF; 4752 int error; 4753 4754 if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 4755 return (DDI_PROP_NOT_FOUND); 4756 4757 error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp); 4758 ddi_release_devi(devi); 4759 return (error); 4760 } 4761 4762 /* 4763 * e_ddi_getprop: See comments for ddi_getprop. 4764 */ 4765 int 4766 e_ddi_getprop(dev_t dev, vtype_t type, char *name, int flags, int defvalue) 4767 { 4768 _NOTE(ARGUNUSED(type)) 4769 dev_info_t *devi; 4770 ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF; 4771 int propvalue = defvalue; 4772 int proplength = sizeof (int); 4773 int error; 4774 4775 if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 4776 return (defvalue); 4777 4778 error = cdev_prop_op(dev, devi, prop_op, 4779 flags, name, (caddr_t)&propvalue, &proplength); 4780 ddi_release_devi(devi); 4781 4782 if ((error == DDI_PROP_SUCCESS) && (proplength == 0)) 4783 propvalue = 1; 4784 4785 return (propvalue); 4786 } 4787 4788 /* 4789 * e_ddi_getprop_int64: 4790 * 4791 * This is a typed interfaces, but predates typed properties. With the 4792 * introduction of typed properties the framework tries to ensure 4793 * consistent use of typed interfaces. This is why TYPE_INT64 is not 4794 * part of TYPE_ANY. E_ddi_getprop_int64 is a special case where a 4795 * typed interface invokes legacy (non-typed) interfaces: 4796 * cdev_prop_op(), prop_op(9E), ddi_prop_op(9F)). In this case the 4797 * fact that TYPE_INT64 is not part of TYPE_ANY matters. To support 4798 * this type of lookup as a single operation we invoke the legacy 4799 * non-typed interfaces with the special CONSUMER_TYPED bit set. The 4800 * framework ddi_prop_op(9F) implementation is expected to check for 4801 * CONSUMER_TYPED and, if set, expand type bits beyond TYPE_ANY 4802 * (currently TYPE_INT64). 4803 */ 4804 int64_t 4805 e_ddi_getprop_int64(dev_t dev, vtype_t type, char *name, 4806 int flags, int64_t defvalue) 4807 { 4808 _NOTE(ARGUNUSED(type)) 4809 dev_info_t *devi; 4810 ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF; 4811 int64_t propvalue = defvalue; 4812 int proplength = sizeof (propvalue); 4813 int error; 4814 4815 if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 4816 return (defvalue); 4817 4818 error = cdev_prop_op(dev, devi, prop_op, flags | 4819 DDI_PROP_CONSUMER_TYPED, name, (caddr_t)&propvalue, &proplength); 4820 ddi_release_devi(devi); 4821 4822 if ((error == DDI_PROP_SUCCESS) && (proplength == 0)) 4823 propvalue = 1; 4824 4825 return (propvalue); 4826 } 4827 4828 /* 4829 * e_ddi_getproplen: See comments for ddi_getproplen. 4830 */ 4831 int 4832 e_ddi_getproplen(dev_t dev, vtype_t type, char *name, int flags, int *lengthp) 4833 { 4834 _NOTE(ARGUNUSED(type)) 4835 dev_info_t *devi; 4836 ddi_prop_op_t prop_op = PROP_LEN; 4837 int error; 4838 4839 if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 4840 return (DDI_PROP_NOT_FOUND); 4841 4842 error = cdev_prop_op(dev, devi, prop_op, flags, name, NULL, lengthp); 4843 ddi_release_devi(devi); 4844 return (error); 4845 } 4846 4847 /* 4848 * Routines to get at elements of the dev_info structure 4849 */ 4850 4851 /* 4852 * ddi_binding_name: Return the driver binding name of the devinfo node 4853 * This is the name the OS used to bind the node to a driver. 4854 */ 4855 char * 4856 ddi_binding_name(dev_info_t *dip) 4857 { 4858 return (DEVI(dip)->devi_binding_name); 4859 } 4860 4861 /* 4862 * ddi_driver_major: Return the major number of the driver that 4863 * the supplied devinfo is bound to (-1 if none) 4864 */ 4865 major_t 4866 ddi_driver_major(dev_info_t *devi) 4867 { 4868 return (DEVI(devi)->devi_major); 4869 } 4870 4871 /* 4872 * ddi_driver_name: Return the normalized driver name. this is the 4873 * actual driver name 4874 */ 4875 const char * 4876 ddi_driver_name(dev_info_t *devi) 4877 { 4878 major_t major; 4879 4880 if ((major = ddi_driver_major(devi)) != (major_t)-1) 4881 return (ddi_major_to_name(major)); 4882 4883 return (ddi_node_name(devi)); 4884 } 4885 4886 /* 4887 * i_ddi_set_binding_name: Set binding name. 4888 * 4889 * Set the binding name to the given name. 4890 * This routine is for use by the ddi implementation, not by drivers. 4891 */ 4892 void 4893 i_ddi_set_binding_name(dev_info_t *dip, char *name) 4894 { 4895 DEVI(dip)->devi_binding_name = name; 4896 4897 } 4898 4899 /* 4900 * ddi_get_name: A synonym of ddi_binding_name() ... returns a name 4901 * the implementation has used to bind the node to a driver. 4902 */ 4903 char * 4904 ddi_get_name(dev_info_t *dip) 4905 { 4906 return (DEVI(dip)->devi_binding_name); 4907 } 4908 4909 /* 4910 * ddi_node_name: Return the name property of the devinfo node 4911 * This may differ from ddi_binding_name if the node name 4912 * does not define a binding to a driver (i.e. generic names). 4913 */ 4914 char * 4915 ddi_node_name(dev_info_t *dip) 4916 { 4917 return (DEVI(dip)->devi_node_name); 4918 } 4919 4920 4921 /* 4922 * ddi_get_nodeid: Get nodeid stored in dev_info structure. 4923 */ 4924 int 4925 ddi_get_nodeid(dev_info_t *dip) 4926 { 4927 return (DEVI(dip)->devi_nodeid); 4928 } 4929 4930 int 4931 ddi_get_instance(dev_info_t *dip) 4932 { 4933 return (DEVI(dip)->devi_instance); 4934 } 4935 4936 struct dev_ops * 4937 ddi_get_driver(dev_info_t *dip) 4938 { 4939 return (DEVI(dip)->devi_ops); 4940 } 4941 4942 void 4943 ddi_set_driver(dev_info_t *dip, struct dev_ops *devo) 4944 { 4945 DEVI(dip)->devi_ops = devo; 4946 } 4947 4948 /* 4949 * ddi_set_driver_private/ddi_get_driver_private: 4950 * Get/set device driver private data in devinfo. 4951 */ 4952 void 4953 ddi_set_driver_private(dev_info_t *dip, void *data) 4954 { 4955 DEVI(dip)->devi_driver_data = data; 4956 } 4957 4958 void * 4959 ddi_get_driver_private(dev_info_t *dip) 4960 { 4961 return (DEVI(dip)->devi_driver_data); 4962 } 4963 4964 /* 4965 * ddi_get_parent, ddi_get_child, ddi_get_next_sibling 4966 */ 4967 4968 dev_info_t * 4969 ddi_get_parent(dev_info_t *dip) 4970 { 4971 return ((dev_info_t *)DEVI(dip)->devi_parent); 4972 } 4973 4974 dev_info_t * 4975 ddi_get_child(dev_info_t *dip) 4976 { 4977 return ((dev_info_t *)DEVI(dip)->devi_child); 4978 } 4979 4980 dev_info_t * 4981 ddi_get_next_sibling(dev_info_t *dip) 4982 { 4983 return ((dev_info_t *)DEVI(dip)->devi_sibling); 4984 } 4985 4986 dev_info_t * 4987 ddi_get_next(dev_info_t *dip) 4988 { 4989 return ((dev_info_t *)DEVI(dip)->devi_next); 4990 } 4991 4992 void 4993 ddi_set_next(dev_info_t *dip, dev_info_t *nextdip) 4994 { 4995 DEVI(dip)->devi_next = DEVI(nextdip); 4996 } 4997 4998 /* 4999 * ddi_root_node: Return root node of devinfo tree 5000 */ 5001 5002 dev_info_t * 5003 ddi_root_node(void) 5004 { 5005 extern dev_info_t *top_devinfo; 5006 5007 return (top_devinfo); 5008 } 5009 5010 /* 5011 * Miscellaneous functions: 5012 */ 5013 5014 /* 5015 * Implementation specific hooks 5016 */ 5017 5018 void 5019 ddi_report_dev(dev_info_t *d) 5020 { 5021 char *b; 5022 5023 (void) ddi_ctlops(d, d, DDI_CTLOPS_REPORTDEV, (void *)0, (void *)0); 5024 5025 /* 5026 * If this devinfo node has cb_ops, it's implicitly accessible from 5027 * userland, so we print its full name together with the instance 5028 * number 'abbreviation' that the driver may use internally. 5029 */ 5030 if (DEVI(d)->devi_ops->devo_cb_ops != (struct cb_ops *)0 && 5031 (b = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP))) { 5032 cmn_err(CE_CONT, "?%s%d is %s\n", 5033 ddi_driver_name(d), ddi_get_instance(d), 5034 ddi_pathname(d, b)); 5035 kmem_free(b, MAXPATHLEN); 5036 } 5037 } 5038 5039 /* 5040 * ddi_ctlops() is described in the assembler not to buy a new register 5041 * window when it's called and can reduce cost in climbing the device tree 5042 * without using the tail call optimization. 5043 */ 5044 int 5045 ddi_dev_regsize(dev_info_t *dev, uint_t rnumber, off_t *result) 5046 { 5047 int ret; 5048 5049 ret = ddi_ctlops(dev, dev, DDI_CTLOPS_REGSIZE, 5050 (void *)&rnumber, (void *)result); 5051 5052 return (ret == DDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE); 5053 } 5054 5055 int 5056 ddi_dev_nregs(dev_info_t *dev, int *result) 5057 { 5058 return (ddi_ctlops(dev, dev, DDI_CTLOPS_NREGS, 0, (void *)result)); 5059 } 5060 5061 int 5062 ddi_dev_is_sid(dev_info_t *d) 5063 { 5064 return (ddi_ctlops(d, d, DDI_CTLOPS_SIDDEV, (void *)0, (void *)0)); 5065 } 5066 5067 int 5068 ddi_slaveonly(dev_info_t *d) 5069 { 5070 return (ddi_ctlops(d, d, DDI_CTLOPS_SLAVEONLY, (void *)0, (void *)0)); 5071 } 5072 5073 int 5074 ddi_dev_affinity(dev_info_t *a, dev_info_t *b) 5075 { 5076 return (ddi_ctlops(a, a, DDI_CTLOPS_AFFINITY, (void *)b, (void *)0)); 5077 } 5078 5079 int 5080 ddi_streams_driver(dev_info_t *dip) 5081 { 5082 if (i_ddi_devi_attached(dip) && 5083 (DEVI(dip)->devi_ops->devo_cb_ops != NULL) && 5084 (DEVI(dip)->devi_ops->devo_cb_ops->cb_str != NULL)) 5085 return (DDI_SUCCESS); 5086 return (DDI_FAILURE); 5087 } 5088 5089 /* 5090 * callback free list 5091 */ 5092 5093 static int ncallbacks; 5094 static int nc_low = 170; 5095 static int nc_med = 512; 5096 static int nc_high = 2048; 5097 static struct ddi_callback *callbackq; 5098 static struct ddi_callback *callbackqfree; 5099 5100 /* 5101 * set/run callback lists 5102 */ 5103 struct cbstats { 5104 kstat_named_t cb_asked; 5105 kstat_named_t cb_new; 5106 kstat_named_t cb_run; 5107 kstat_named_t cb_delete; 5108 kstat_named_t cb_maxreq; 5109 kstat_named_t cb_maxlist; 5110 kstat_named_t cb_alloc; 5111 kstat_named_t cb_runouts; 5112 kstat_named_t cb_L2; 5113 kstat_named_t cb_grow; 5114 } cbstats = { 5115 {"asked", KSTAT_DATA_UINT32}, 5116 {"new", KSTAT_DATA_UINT32}, 5117 {"run", KSTAT_DATA_UINT32}, 5118 {"delete", KSTAT_DATA_UINT32}, 5119 {"maxreq", KSTAT_DATA_UINT32}, 5120 {"maxlist", KSTAT_DATA_UINT32}, 5121 {"alloc", KSTAT_DATA_UINT32}, 5122 {"runouts", KSTAT_DATA_UINT32}, 5123 {"L2", KSTAT_DATA_UINT32}, 5124 {"grow", KSTAT_DATA_UINT32}, 5125 }; 5126 5127 #define nc_asked cb_asked.value.ui32 5128 #define nc_new cb_new.value.ui32 5129 #define nc_run cb_run.value.ui32 5130 #define nc_delete cb_delete.value.ui32 5131 #define nc_maxreq cb_maxreq.value.ui32 5132 #define nc_maxlist cb_maxlist.value.ui32 5133 #define nc_alloc cb_alloc.value.ui32 5134 #define nc_runouts cb_runouts.value.ui32 5135 #define nc_L2 cb_L2.value.ui32 5136 #define nc_grow cb_grow.value.ui32 5137 5138 static kmutex_t ddi_callback_mutex; 5139 5140 /* 5141 * callbacks are handled using a L1/L2 cache. The L1 cache 5142 * comes out of kmem_cache_alloc and can expand/shrink dynamically. If 5143 * we can't get callbacks from the L1 cache [because pageout is doing 5144 * I/O at the time freemem is 0], we allocate callbacks out of the 5145 * L2 cache. The L2 cache is static and depends on the memory size. 5146 * [We might also count the number of devices at probe time and 5147 * allocate one structure per device and adjust for deferred attach] 5148 */ 5149 void 5150 impl_ddi_callback_init(void) 5151 { 5152 int i; 5153 uint_t physmegs; 5154 kstat_t *ksp; 5155 5156 physmegs = physmem >> (20 - PAGESHIFT); 5157 if (physmegs < 48) { 5158 ncallbacks = nc_low; 5159 } else if (physmegs < 128) { 5160 ncallbacks = nc_med; 5161 } else { 5162 ncallbacks = nc_high; 5163 } 5164 5165 /* 5166 * init free list 5167 */ 5168 callbackq = kmem_zalloc( 5169 ncallbacks * sizeof (struct ddi_callback), KM_SLEEP); 5170 for (i = 0; i < ncallbacks-1; i++) 5171 callbackq[i].c_nfree = &callbackq[i+1]; 5172 callbackqfree = callbackq; 5173 5174 /* init kstats */ 5175 if (ksp = kstat_create("unix", 0, "cbstats", "misc", KSTAT_TYPE_NAMED, 5176 sizeof (cbstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL)) { 5177 ksp->ks_data = (void *) &cbstats; 5178 kstat_install(ksp); 5179 } 5180 5181 } 5182 5183 static void 5184 callback_insert(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid, 5185 int count) 5186 { 5187 struct ddi_callback *list, *marker, *new; 5188 size_t size = sizeof (struct ddi_callback); 5189 5190 list = marker = (struct ddi_callback *)*listid; 5191 while (list != NULL) { 5192 if (list->c_call == funcp && list->c_arg == arg) { 5193 list->c_count += count; 5194 return; 5195 } 5196 marker = list; 5197 list = list->c_nlist; 5198 } 5199 new = kmem_alloc(size, KM_NOSLEEP); 5200 if (new == NULL) { 5201 new = callbackqfree; 5202 if (new == NULL) { 5203 new = kmem_alloc_tryhard(sizeof (struct ddi_callback), 5204 &size, KM_NOSLEEP | KM_PANIC); 5205 cbstats.nc_grow++; 5206 } else { 5207 callbackqfree = new->c_nfree; 5208 cbstats.nc_L2++; 5209 } 5210 } 5211 if (marker != NULL) { 5212 marker->c_nlist = new; 5213 } else { 5214 *listid = (uintptr_t)new; 5215 } 5216 new->c_size = size; 5217 new->c_nlist = NULL; 5218 new->c_call = funcp; 5219 new->c_arg = arg; 5220 new->c_count = count; 5221 cbstats.nc_new++; 5222 cbstats.nc_alloc++; 5223 if (cbstats.nc_alloc > cbstats.nc_maxlist) 5224 cbstats.nc_maxlist = cbstats.nc_alloc; 5225 } 5226 5227 void 5228 ddi_set_callback(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid) 5229 { 5230 mutex_enter(&ddi_callback_mutex); 5231 cbstats.nc_asked++; 5232 if ((cbstats.nc_asked - cbstats.nc_run) > cbstats.nc_maxreq) 5233 cbstats.nc_maxreq = (cbstats.nc_asked - cbstats.nc_run); 5234 (void) callback_insert(funcp, arg, listid, 1); 5235 mutex_exit(&ddi_callback_mutex); 5236 } 5237 5238 static void 5239 real_callback_run(void *Queue) 5240 { 5241 int (*funcp)(caddr_t); 5242 caddr_t arg; 5243 int count, rval; 5244 uintptr_t *listid; 5245 struct ddi_callback *list, *marker; 5246 int check_pending = 1; 5247 int pending = 0; 5248 5249 do { 5250 mutex_enter(&ddi_callback_mutex); 5251 listid = Queue; 5252 list = (struct ddi_callback *)*listid; 5253 if (list == NULL) { 5254 mutex_exit(&ddi_callback_mutex); 5255 return; 5256 } 5257 if (check_pending) { 5258 marker = list; 5259 while (marker != NULL) { 5260 pending += marker->c_count; 5261 marker = marker->c_nlist; 5262 } 5263 check_pending = 0; 5264 } 5265 ASSERT(pending > 0); 5266 ASSERT(list->c_count > 0); 5267 funcp = list->c_call; 5268 arg = list->c_arg; 5269 count = list->c_count; 5270 *(uintptr_t *)Queue = (uintptr_t)list->c_nlist; 5271 if (list >= &callbackq[0] && 5272 list <= &callbackq[ncallbacks-1]) { 5273 list->c_nfree = callbackqfree; 5274 callbackqfree = list; 5275 } else 5276 kmem_free(list, list->c_size); 5277 5278 cbstats.nc_delete++; 5279 cbstats.nc_alloc--; 5280 mutex_exit(&ddi_callback_mutex); 5281 5282 do { 5283 if ((rval = (*funcp)(arg)) == 0) { 5284 pending -= count; 5285 mutex_enter(&ddi_callback_mutex); 5286 (void) callback_insert(funcp, arg, listid, 5287 count); 5288 cbstats.nc_runouts++; 5289 } else { 5290 pending--; 5291 mutex_enter(&ddi_callback_mutex); 5292 cbstats.nc_run++; 5293 } 5294 mutex_exit(&ddi_callback_mutex); 5295 } while (rval != 0 && (--count > 0)); 5296 } while (pending > 0); 5297 } 5298 5299 void 5300 ddi_run_callback(uintptr_t *listid) 5301 { 5302 softcall(real_callback_run, listid); 5303 } 5304 5305 dev_info_t * 5306 nodevinfo(dev_t dev, int otyp) 5307 { 5308 _NOTE(ARGUNUSED(dev, otyp)) 5309 return ((dev_info_t *)0); 5310 } 5311 5312 /* 5313 * A driver should support its own getinfo(9E) entry point. This function 5314 * is provided as a convenience for ON drivers that don't expect their 5315 * getinfo(9E) entry point to be called. A driver that uses this must not 5316 * call ddi_create_minor_node. 5317 */ 5318 int 5319 ddi_no_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 5320 { 5321 _NOTE(ARGUNUSED(dip, infocmd, arg, result)) 5322 return (DDI_FAILURE); 5323 } 5324 5325 /* 5326 * A driver should support its own getinfo(9E) entry point. This function 5327 * is provided as a convenience for ON drivers that where the minor number 5328 * is the instance. Drivers that do not have 1:1 mapping must implement 5329 * their own getinfo(9E) function. 5330 */ 5331 int 5332 ddi_getinfo_1to1(dev_info_t *dip, ddi_info_cmd_t infocmd, 5333 void *arg, void **result) 5334 { 5335 _NOTE(ARGUNUSED(dip)) 5336 int instance; 5337 5338 if (infocmd != DDI_INFO_DEVT2INSTANCE) 5339 return (DDI_FAILURE); 5340 5341 instance = getminor((dev_t)(uintptr_t)arg); 5342 *result = (void *)(uintptr_t)instance; 5343 return (DDI_SUCCESS); 5344 } 5345 5346 int 5347 ddifail(dev_info_t *devi, ddi_attach_cmd_t cmd) 5348 { 5349 _NOTE(ARGUNUSED(devi, cmd)) 5350 return (DDI_FAILURE); 5351 } 5352 5353 int 5354 ddi_no_dma_map(dev_info_t *dip, dev_info_t *rdip, 5355 struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 5356 { 5357 _NOTE(ARGUNUSED(dip, rdip, dmareqp, handlep)) 5358 return (DDI_DMA_NOMAPPING); 5359 } 5360 5361 int 5362 ddi_no_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 5363 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 5364 { 5365 _NOTE(ARGUNUSED(dip, rdip, attr, waitfp, arg, handlep)) 5366 return (DDI_DMA_BADATTR); 5367 } 5368 5369 int 5370 ddi_no_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 5371 ddi_dma_handle_t handle) 5372 { 5373 _NOTE(ARGUNUSED(dip, rdip, handle)) 5374 return (DDI_FAILURE); 5375 } 5376 5377 int 5378 ddi_no_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 5379 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 5380 ddi_dma_cookie_t *cp, uint_t *ccountp) 5381 { 5382 _NOTE(ARGUNUSED(dip, rdip, handle, dmareq, cp, ccountp)) 5383 return (DDI_DMA_NOMAPPING); 5384 } 5385 5386 int 5387 ddi_no_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 5388 ddi_dma_handle_t handle) 5389 { 5390 _NOTE(ARGUNUSED(dip, rdip, handle)) 5391 return (DDI_FAILURE); 5392 } 5393 5394 int 5395 ddi_no_dma_flush(dev_info_t *dip, dev_info_t *rdip, 5396 ddi_dma_handle_t handle, off_t off, size_t len, 5397 uint_t cache_flags) 5398 { 5399 _NOTE(ARGUNUSED(dip, rdip, handle, off, len, cache_flags)) 5400 return (DDI_FAILURE); 5401 } 5402 5403 int 5404 ddi_no_dma_win(dev_info_t *dip, dev_info_t *rdip, 5405 ddi_dma_handle_t handle, uint_t win, off_t *offp, 5406 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 5407 { 5408 _NOTE(ARGUNUSED(dip, rdip, handle, win, offp, lenp, cookiep, ccountp)) 5409 return (DDI_FAILURE); 5410 } 5411 5412 int 5413 ddi_no_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 5414 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 5415 off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags) 5416 { 5417 _NOTE(ARGUNUSED(dip, rdip, handle, request, offp, lenp, objp, flags)) 5418 return (DDI_FAILURE); 5419 } 5420 5421 void 5422 ddivoid(void) 5423 {} 5424 5425 int 5426 nochpoll(dev_t dev, short events, int anyyet, short *reventsp, 5427 struct pollhead **pollhdrp) 5428 { 5429 _NOTE(ARGUNUSED(dev, events, anyyet, reventsp, pollhdrp)) 5430 return (ENXIO); 5431 } 5432 5433 cred_t * 5434 ddi_get_cred(void) 5435 { 5436 return (CRED()); 5437 } 5438 5439 clock_t 5440 ddi_get_lbolt(void) 5441 { 5442 return (lbolt); 5443 } 5444 5445 time_t 5446 ddi_get_time(void) 5447 { 5448 time_t now; 5449 5450 if ((now = gethrestime_sec()) == 0) { 5451 timestruc_t ts; 5452 mutex_enter(&tod_lock); 5453 ts = tod_get(); 5454 mutex_exit(&tod_lock); 5455 return (ts.tv_sec); 5456 } else { 5457 return (now); 5458 } 5459 } 5460 5461 pid_t 5462 ddi_get_pid(void) 5463 { 5464 return (ttoproc(curthread)->p_pid); 5465 } 5466 5467 kt_did_t 5468 ddi_get_kt_did(void) 5469 { 5470 return (curthread->t_did); 5471 } 5472 5473 /* 5474 * This function returns B_TRUE if the caller can reasonably expect that a call 5475 * to cv_wait_sig(9F), cv_timedwait_sig(9F), or qwait_sig(9F) could be awakened 5476 * by user-level signal. If it returns B_FALSE, then the caller should use 5477 * other means to make certain that the wait will not hang "forever." 5478 * 5479 * It does not check the signal mask, nor for reception of any particular 5480 * signal. 5481 * 5482 * Currently, a thread can receive a signal if it's not a kernel thread and it 5483 * is not in the middle of exit(2) tear-down. Threads that are in that 5484 * tear-down effectively convert cv_wait_sig to cv_wait, cv_timedwait_sig to 5485 * cv_timedwait, and qwait_sig to qwait. 5486 */ 5487 boolean_t 5488 ddi_can_receive_sig(void) 5489 { 5490 proc_t *pp; 5491 5492 if (curthread->t_proc_flag & TP_LWPEXIT) 5493 return (B_FALSE); 5494 if ((pp = ttoproc(curthread)) == NULL) 5495 return (B_FALSE); 5496 return (pp->p_as != &kas); 5497 } 5498 5499 /* 5500 * Swap bytes in 16-bit [half-]words 5501 */ 5502 void 5503 swab(void *src, void *dst, size_t nbytes) 5504 { 5505 uchar_t *pf = (uchar_t *)src; 5506 uchar_t *pt = (uchar_t *)dst; 5507 uchar_t tmp; 5508 int nshorts; 5509 5510 nshorts = nbytes >> 1; 5511 5512 while (--nshorts >= 0) { 5513 tmp = *pf++; 5514 *pt++ = *pf++; 5515 *pt++ = tmp; 5516 } 5517 } 5518 5519 static void 5520 ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp) 5521 { 5522 struct ddi_minor_data *dp; 5523 5524 mutex_enter(&(DEVI(ddip)->devi_lock)); 5525 i_devi_enter(ddip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1); 5526 5527 if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) { 5528 DEVI(ddip)->devi_minor = dmdp; 5529 } else { 5530 while (dp->next != (struct ddi_minor_data *)NULL) 5531 dp = dp->next; 5532 dp->next = dmdp; 5533 } 5534 5535 i_devi_exit(ddip, DEVI_S_MD_UPDATE, 1); 5536 mutex_exit(&(DEVI(ddip)->devi_lock)); 5537 } 5538 5539 /* 5540 * Part of the obsolete SunCluster DDI Hooks. 5541 * Keep for binary compatibility 5542 */ 5543 minor_t 5544 ddi_getiminor(dev_t dev) 5545 { 5546 return (getminor(dev)); 5547 } 5548 5549 static int 5550 i_log_devfs_minor_create(dev_info_t *dip, char *minor_name) 5551 { 5552 int se_flag; 5553 int kmem_flag; 5554 int se_err; 5555 char *pathname, *class_name; 5556 sysevent_t *ev = NULL; 5557 sysevent_id_t eid; 5558 sysevent_value_t se_val; 5559 sysevent_attr_list_t *ev_attr_list = NULL; 5560 5561 /* determine interrupt context */ 5562 se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP; 5563 kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP; 5564 5565 i_ddi_di_cache_invalidate(kmem_flag); 5566 5567 #ifdef DEBUG 5568 if ((se_flag == SE_NOSLEEP) && sunddi_debug) { 5569 cmn_err(CE_CONT, "ddi_create_minor_node: called from " 5570 "interrupt level by driver %s", 5571 ddi_driver_name(dip)); 5572 } 5573 #endif /* DEBUG */ 5574 5575 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_CREATE, EP_DDI, se_flag); 5576 if (ev == NULL) { 5577 goto fail; 5578 } 5579 5580 pathname = kmem_alloc(MAXPATHLEN, kmem_flag); 5581 if (pathname == NULL) { 5582 sysevent_free(ev); 5583 goto fail; 5584 } 5585 5586 (void) ddi_pathname(dip, pathname); 5587 ASSERT(strlen(pathname)); 5588 se_val.value_type = SE_DATA_TYPE_STRING; 5589 se_val.value.sv_string = pathname; 5590 if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME, 5591 &se_val, se_flag) != 0) { 5592 kmem_free(pathname, MAXPATHLEN); 5593 sysevent_free(ev); 5594 goto fail; 5595 } 5596 kmem_free(pathname, MAXPATHLEN); 5597 5598 /* add the device class attribute */ 5599 if ((class_name = i_ddi_devi_class(dip)) != NULL) { 5600 se_val.value_type = SE_DATA_TYPE_STRING; 5601 se_val.value.sv_string = class_name; 5602 if (sysevent_add_attr(&ev_attr_list, 5603 DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) { 5604 sysevent_free_attr(ev_attr_list); 5605 goto fail; 5606 } 5607 } 5608 5609 /* 5610 * allow for NULL minor names 5611 */ 5612 if (minor_name != NULL) { 5613 se_val.value.sv_string = minor_name; 5614 if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME, 5615 &se_val, se_flag) != 0) { 5616 sysevent_free_attr(ev_attr_list); 5617 sysevent_free(ev); 5618 goto fail; 5619 } 5620 } 5621 5622 if (sysevent_attach_attributes(ev, ev_attr_list) != 0) { 5623 sysevent_free_attr(ev_attr_list); 5624 sysevent_free(ev); 5625 goto fail; 5626 } 5627 5628 if ((se_err = log_sysevent(ev, se_flag, &eid)) != 0) { 5629 if (se_err == SE_NO_TRANSPORT) { 5630 cmn_err(CE_WARN, "/devices or /dev may not be current " 5631 "for driver %s (%s). Run devfsadm -i %s", 5632 ddi_driver_name(dip), "syseventd not responding", 5633 ddi_driver_name(dip)); 5634 } else { 5635 sysevent_free(ev); 5636 goto fail; 5637 } 5638 } 5639 5640 sysevent_free(ev); 5641 return (DDI_SUCCESS); 5642 fail: 5643 cmn_err(CE_WARN, "/devices or /dev may not be current " 5644 "for driver %s. Run devfsadm -i %s", 5645 ddi_driver_name(dip), ddi_driver_name(dip)); 5646 return (DDI_SUCCESS); 5647 } 5648 5649 /* 5650 * failing to remove a minor node is not of interest 5651 * therefore we do not generate an error message 5652 */ 5653 static int 5654 i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name) 5655 { 5656 char *pathname, *class_name; 5657 sysevent_t *ev; 5658 sysevent_id_t eid; 5659 sysevent_value_t se_val; 5660 sysevent_attr_list_t *ev_attr_list = NULL; 5661 5662 /* 5663 * only log ddi_remove_minor_node() calls outside the scope 5664 * of attach/detach reconfigurations and when the dip is 5665 * still initialized. 5666 */ 5667 if (DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip) || 5668 (i_ddi_node_state(dip) < DS_INITIALIZED)) { 5669 return (DDI_SUCCESS); 5670 } 5671 5672 i_ddi_di_cache_invalidate(KM_SLEEP); 5673 5674 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_REMOVE, EP_DDI, SE_SLEEP); 5675 if (ev == NULL) { 5676 return (DDI_SUCCESS); 5677 } 5678 5679 pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP); 5680 if (pathname == NULL) { 5681 sysevent_free(ev); 5682 return (DDI_SUCCESS); 5683 } 5684 5685 (void) ddi_pathname(dip, pathname); 5686 ASSERT(strlen(pathname)); 5687 se_val.value_type = SE_DATA_TYPE_STRING; 5688 se_val.value.sv_string = pathname; 5689 if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME, 5690 &se_val, SE_SLEEP) != 0) { 5691 kmem_free(pathname, MAXPATHLEN); 5692 sysevent_free(ev); 5693 return (DDI_SUCCESS); 5694 } 5695 5696 kmem_free(pathname, MAXPATHLEN); 5697 5698 /* 5699 * allow for NULL minor names 5700 */ 5701 if (minor_name != NULL) { 5702 se_val.value.sv_string = minor_name; 5703 if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME, 5704 &se_val, SE_SLEEP) != 0) { 5705 sysevent_free_attr(ev_attr_list); 5706 goto fail; 5707 } 5708 } 5709 5710 if ((class_name = i_ddi_devi_class(dip)) != NULL) { 5711 /* add the device class, driver name and instance attributes */ 5712 5713 se_val.value_type = SE_DATA_TYPE_STRING; 5714 se_val.value.sv_string = class_name; 5715 if (sysevent_add_attr(&ev_attr_list, 5716 DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) { 5717 sysevent_free_attr(ev_attr_list); 5718 goto fail; 5719 } 5720 5721 se_val.value_type = SE_DATA_TYPE_STRING; 5722 se_val.value.sv_string = (char *)ddi_driver_name(dip); 5723 if (sysevent_add_attr(&ev_attr_list, 5724 DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) { 5725 sysevent_free_attr(ev_attr_list); 5726 goto fail; 5727 } 5728 5729 se_val.value_type = SE_DATA_TYPE_INT32; 5730 se_val.value.sv_int32 = ddi_get_instance(dip); 5731 if (sysevent_add_attr(&ev_attr_list, 5732 DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) { 5733 sysevent_free_attr(ev_attr_list); 5734 goto fail; 5735 } 5736 5737 } 5738 5739 if (sysevent_attach_attributes(ev, ev_attr_list) != 0) { 5740 sysevent_free_attr(ev_attr_list); 5741 } else { 5742 (void) log_sysevent(ev, SE_SLEEP, &eid); 5743 } 5744 fail: 5745 sysevent_free(ev); 5746 return (DDI_SUCCESS); 5747 } 5748 5749 /* 5750 * Derive the device class of the node. 5751 * Device class names aren't defined yet. Until this is done we use 5752 * devfs event subclass names as device class names. 5753 */ 5754 static int 5755 derive_devi_class(dev_info_t *dip, char *node_type, int flag) 5756 { 5757 int rv = DDI_SUCCESS; 5758 5759 if (i_ddi_devi_class(dip) == NULL) { 5760 if (strncmp(node_type, DDI_NT_BLOCK, 5761 sizeof (DDI_NT_BLOCK) - 1) == 0 && 5762 (node_type[sizeof (DDI_NT_BLOCK) - 1] == '\0' || 5763 node_type[sizeof (DDI_NT_BLOCK) - 1] == ':') && 5764 strcmp(node_type, DDI_NT_FD) != 0) { 5765 5766 rv = i_ddi_set_devi_class(dip, ESC_DISK, flag); 5767 5768 } else if (strncmp(node_type, DDI_NT_NET, 5769 sizeof (DDI_NT_NET) - 1) == 0 && 5770 (node_type[sizeof (DDI_NT_NET) - 1] == '\0' || 5771 node_type[sizeof (DDI_NT_NET) - 1] == ':')) { 5772 5773 rv = i_ddi_set_devi_class(dip, ESC_NETWORK, flag); 5774 5775 } else if (strncmp(node_type, DDI_NT_PRINTER, 5776 sizeof (DDI_NT_PRINTER) - 1) == 0 && 5777 (node_type[sizeof (DDI_NT_PRINTER) - 1] == '\0' || 5778 node_type[sizeof (DDI_NT_PRINTER) - 1] == ':')) { 5779 5780 rv = i_ddi_set_devi_class(dip, ESC_PRINTER, flag); 5781 5782 } else if (strncmp(node_type, DDI_PSEUDO, 5783 sizeof (DDI_PSEUDO) -1) == 0 && 5784 (strncmp(ESC_LOFI, ddi_node_name(dip), 5785 sizeof (ESC_LOFI) -1) == 0)) { 5786 rv = i_ddi_set_devi_class(dip, ESC_LOFI, flag); 5787 } 5788 } 5789 5790 return (rv); 5791 } 5792 5793 /* 5794 * Check compliance with PSARC 2003/375: 5795 * 5796 * The name must contain only characters a-z, A-Z, 0-9 or _ and it must not 5797 * exceed IFNAMSIZ (16) characters in length. 5798 */ 5799 static boolean_t 5800 verify_name(char *name) 5801 { 5802 size_t len = strlen(name); 5803 char *cp; 5804 5805 if (len == 0 || len > IFNAMSIZ) 5806 return (B_FALSE); 5807 5808 for (cp = name; *cp != '\0'; cp++) { 5809 if (!isalnum(*cp) && *cp != '_') 5810 return (B_FALSE); 5811 } 5812 5813 return (B_TRUE); 5814 } 5815 5816 /* 5817 * ddi_create_minor_common: Create a ddi_minor_data structure and 5818 * attach it to the given devinfo node. 5819 */ 5820 5821 int 5822 ddi_create_minor_common(dev_info_t *dip, char *name, int spec_type, 5823 minor_t minor_num, char *node_type, int flag, ddi_minor_type mtype, 5824 const char *read_priv, const char *write_priv, mode_t priv_mode) 5825 { 5826 struct ddi_minor_data *dmdp; 5827 major_t major; 5828 5829 if (spec_type != S_IFCHR && spec_type != S_IFBLK) 5830 return (DDI_FAILURE); 5831 5832 if (name == NULL) 5833 return (DDI_FAILURE); 5834 5835 /* 5836 * Log a message if the minor number the driver is creating 5837 * is not expressible on the on-disk filesystem (currently 5838 * this is limited to 18 bits both by UFS). The device can 5839 * be opened via devfs, but not by device special files created 5840 * via mknod(). 5841 */ 5842 if (minor_num > L_MAXMIN32) { 5843 cmn_err(CE_WARN, 5844 "%s%d:%s minor 0x%x too big for 32-bit applications", 5845 ddi_driver_name(dip), ddi_get_instance(dip), 5846 name, minor_num); 5847 return (DDI_FAILURE); 5848 } 5849 5850 /* dip must be bound and attached */ 5851 major = ddi_driver_major(dip); 5852 ASSERT(major != (major_t)-1); 5853 5854 /* 5855 * Default node_type to DDI_PSEUDO and issue notice in debug mode 5856 */ 5857 if (node_type == NULL) { 5858 node_type = DDI_PSEUDO; 5859 NDI_CONFIG_DEBUG((CE_NOTE, "!illegal node_type NULL for %s%d " 5860 " minor node %s; default to DDI_PSEUDO", 5861 ddi_driver_name(dip), ddi_get_instance(dip), name)); 5862 } 5863 5864 /* 5865 * If the driver is a network driver, ensure that the name falls within 5866 * the interface naming constraints specified by PSARC/2003/375. 5867 */ 5868 if (strcmp(node_type, DDI_NT_NET) == 0) { 5869 if (!verify_name(name)) 5870 return (DDI_FAILURE); 5871 5872 if (mtype == DDM_MINOR) { 5873 struct devnames *dnp = &devnamesp[major]; 5874 5875 /* Mark driver as a network driver */ 5876 LOCK_DEV_OPS(&dnp->dn_lock); 5877 dnp->dn_flags |= DN_NETWORK_DRIVER; 5878 UNLOCK_DEV_OPS(&dnp->dn_lock); 5879 } 5880 } 5881 5882 if (mtype == DDM_MINOR) { 5883 if (derive_devi_class(dip, node_type, KM_NOSLEEP) != 5884 DDI_SUCCESS) 5885 return (DDI_FAILURE); 5886 } 5887 5888 /* 5889 * Take care of minor number information for the node. 5890 */ 5891 5892 if ((dmdp = kmem_zalloc(sizeof (struct ddi_minor_data), 5893 KM_NOSLEEP)) == NULL) { 5894 return (DDI_FAILURE); 5895 } 5896 if ((dmdp->ddm_name = i_ddi_strdup(name, KM_NOSLEEP)) == NULL) { 5897 kmem_free(dmdp, sizeof (struct ddi_minor_data)); 5898 return (DDI_FAILURE); 5899 } 5900 dmdp->dip = dip; 5901 dmdp->ddm_dev = makedevice(major, minor_num); 5902 dmdp->ddm_spec_type = spec_type; 5903 dmdp->ddm_node_type = node_type; 5904 dmdp->type = mtype; 5905 if (flag & CLONE_DEV) { 5906 dmdp->type = DDM_ALIAS; 5907 dmdp->ddm_dev = makedevice(ddi_driver_major(clone_dip), major); 5908 } 5909 if (flag & PRIVONLY_DEV) { 5910 dmdp->ddm_flags |= DM_NO_FSPERM; 5911 } 5912 if (read_priv || write_priv) { 5913 dmdp->ddm_node_priv = 5914 devpolicy_priv_by_name(read_priv, write_priv); 5915 } 5916 dmdp->ddm_priv_mode = priv_mode; 5917 5918 ddi_append_minor_node(dip, dmdp); 5919 5920 /* 5921 * only log ddi_create_minor_node() calls which occur 5922 * outside the scope of attach(9e)/detach(9e) reconfigurations 5923 */ 5924 if (!(DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip)) && 5925 mtype != DDM_INTERNAL_PATH) { 5926 (void) i_log_devfs_minor_create(dip, name); 5927 } 5928 5929 /* 5930 * Check if any dacf rules match the creation of this minor node 5931 */ 5932 dacfc_match_create_minor(name, node_type, dip, dmdp, flag); 5933 return (DDI_SUCCESS); 5934 } 5935 5936 int 5937 ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type, 5938 minor_t minor_num, char *node_type, int flag) 5939 { 5940 return (ddi_create_minor_common(dip, name, spec_type, minor_num, 5941 node_type, flag, DDM_MINOR, NULL, NULL, 0)); 5942 } 5943 5944 int 5945 ddi_create_priv_minor_node(dev_info_t *dip, char *name, int spec_type, 5946 minor_t minor_num, char *node_type, int flag, 5947 const char *rdpriv, const char *wrpriv, mode_t priv_mode) 5948 { 5949 return (ddi_create_minor_common(dip, name, spec_type, minor_num, 5950 node_type, flag, DDM_MINOR, rdpriv, wrpriv, priv_mode)); 5951 } 5952 5953 int 5954 ddi_create_default_minor_node(dev_info_t *dip, char *name, int spec_type, 5955 minor_t minor_num, char *node_type, int flag) 5956 { 5957 return (ddi_create_minor_common(dip, name, spec_type, minor_num, 5958 node_type, flag, DDM_DEFAULT, NULL, NULL, 0)); 5959 } 5960 5961 /* 5962 * Internal (non-ddi) routine for drivers to export names known 5963 * to the kernel (especially ddi_pathname_to_dev_t and friends) 5964 * but not exported externally to /dev 5965 */ 5966 int 5967 ddi_create_internal_pathname(dev_info_t *dip, char *name, int spec_type, 5968 minor_t minor_num) 5969 { 5970 return (ddi_create_minor_common(dip, name, spec_type, minor_num, 5971 "internal", 0, DDM_INTERNAL_PATH, NULL, NULL, 0)); 5972 } 5973 5974 void 5975 ddi_remove_minor_node(dev_info_t *dip, char *name) 5976 { 5977 struct ddi_minor_data *dmdp, *dmdp1; 5978 struct ddi_minor_data **dmdp_prev; 5979 5980 mutex_enter(&(DEVI(dip)->devi_lock)); 5981 i_devi_enter(dip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1); 5982 5983 dmdp_prev = &DEVI(dip)->devi_minor; 5984 dmdp = DEVI(dip)->devi_minor; 5985 while (dmdp != NULL) { 5986 dmdp1 = dmdp->next; 5987 if ((name == NULL || (dmdp->ddm_name != NULL && 5988 strcmp(name, dmdp->ddm_name) == 0))) { 5989 if (dmdp->ddm_name != NULL) { 5990 if (dmdp->type != DDM_INTERNAL_PATH) 5991 (void) i_log_devfs_minor_remove(dip, 5992 dmdp->ddm_name); 5993 kmem_free(dmdp->ddm_name, 5994 strlen(dmdp->ddm_name) + 1); 5995 } 5996 /* 5997 * Release device privilege, if any. 5998 * Release dacf client data associated with this minor 5999 * node by storing NULL. 6000 */ 6001 if (dmdp->ddm_node_priv) 6002 dpfree(dmdp->ddm_node_priv); 6003 dacf_store_info((dacf_infohdl_t)dmdp, NULL); 6004 kmem_free(dmdp, sizeof (struct ddi_minor_data)); 6005 *dmdp_prev = dmdp1; 6006 /* 6007 * OK, we found it, so get out now -- if we drive on, 6008 * we will strcmp against garbage. See 1139209. 6009 */ 6010 if (name != NULL) 6011 break; 6012 } else { 6013 dmdp_prev = &dmdp->next; 6014 } 6015 dmdp = dmdp1; 6016 } 6017 6018 i_devi_exit(dip, DEVI_S_MD_UPDATE, 1); 6019 mutex_exit(&(DEVI(dip)->devi_lock)); 6020 } 6021 6022 6023 int 6024 ddi_in_panic() 6025 { 6026 return (panicstr != NULL); 6027 } 6028 6029 6030 /* 6031 * Find first bit set in a mask (returned counting from 1 up) 6032 */ 6033 6034 int 6035 ddi_ffs(long mask) 6036 { 6037 return (ffs(mask)); 6038 } 6039 6040 /* 6041 * Find last bit set. Take mask and clear 6042 * all but the most significant bit, and 6043 * then let ffs do the rest of the work. 6044 * 6045 * Algorithm courtesy of Steve Chessin. 6046 */ 6047 6048 int 6049 ddi_fls(long mask) 6050 { 6051 while (mask) { 6052 long nx; 6053 6054 if ((nx = (mask & (mask - 1))) == 0) 6055 break; 6056 mask = nx; 6057 } 6058 return (ffs(mask)); 6059 } 6060 6061 /* 6062 * The next five routines comprise generic storage management utilities 6063 * for driver soft state structures (in "the old days," this was done 6064 * with a statically sized array - big systems and dynamic loading 6065 * and unloading make heap allocation more attractive) 6066 */ 6067 6068 /* 6069 * Allocate a set of pointers to 'n_items' objects of size 'size' 6070 * bytes. Each pointer is initialized to nil. 6071 * 6072 * The 'size' and 'n_items' values are stashed in the opaque 6073 * handle returned to the caller. 6074 * 6075 * This implementation interprets 'set of pointers' to mean 'array 6076 * of pointers' but note that nothing in the interface definition 6077 * precludes an implementation that uses, for example, a linked list. 6078 * However there should be a small efficiency gain from using an array 6079 * at lookup time. 6080 * 6081 * NOTE As an optimization, we make our growable array allocations in 6082 * powers of two (bytes), since that's how much kmem_alloc (currently) 6083 * gives us anyway. It should save us some free/realloc's .. 6084 * 6085 * As a further optimization, we make the growable array start out 6086 * with MIN_N_ITEMS in it. 6087 */ 6088 6089 #define MIN_N_ITEMS 8 /* 8 void *'s == 32 bytes */ 6090 6091 int 6092 ddi_soft_state_init(void **state_p, size_t size, size_t n_items) 6093 { 6094 struct i_ddi_soft_state *ss; 6095 6096 if (state_p == NULL || *state_p != NULL || size == 0) 6097 return (EINVAL); 6098 6099 ss = kmem_zalloc(sizeof (*ss), KM_SLEEP); 6100 mutex_init(&ss->lock, NULL, MUTEX_DRIVER, NULL); 6101 ss->size = size; 6102 6103 if (n_items < MIN_N_ITEMS) 6104 ss->n_items = MIN_N_ITEMS; 6105 else { 6106 int bitlog; 6107 6108 if ((bitlog = ddi_fls(n_items)) == ddi_ffs(n_items)) 6109 bitlog--; 6110 ss->n_items = 1 << bitlog; 6111 } 6112 6113 ASSERT(ss->n_items >= n_items); 6114 6115 ss->array = kmem_zalloc(ss->n_items * sizeof (void *), KM_SLEEP); 6116 6117 *state_p = ss; 6118 6119 return (0); 6120 } 6121 6122 6123 /* 6124 * Allocate a state structure of size 'size' to be associated 6125 * with item 'item'. 6126 * 6127 * In this implementation, the array is extended to 6128 * allow the requested offset, if needed. 6129 */ 6130 int 6131 ddi_soft_state_zalloc(void *state, int item) 6132 { 6133 struct i_ddi_soft_state *ss; 6134 void **array; 6135 void *new_element; 6136 6137 if ((ss = state) == NULL || item < 0) 6138 return (DDI_FAILURE); 6139 6140 mutex_enter(&ss->lock); 6141 if (ss->size == 0) { 6142 mutex_exit(&ss->lock); 6143 cmn_err(CE_WARN, "ddi_soft_state_zalloc: bad handle: %s", 6144 mod_containing_pc(caller())); 6145 return (DDI_FAILURE); 6146 } 6147 6148 array = ss->array; /* NULL if ss->n_items == 0 */ 6149 ASSERT(ss->n_items != 0 && array != NULL); 6150 6151 /* 6152 * refuse to tread on an existing element 6153 */ 6154 if (item < ss->n_items && array[item] != NULL) { 6155 mutex_exit(&ss->lock); 6156 return (DDI_FAILURE); 6157 } 6158 6159 /* 6160 * Allocate a new element to plug in 6161 */ 6162 new_element = kmem_zalloc(ss->size, KM_SLEEP); 6163 6164 /* 6165 * Check if the array is big enough, if not, grow it. 6166 */ 6167 if (item >= ss->n_items) { 6168 void **new_array; 6169 size_t new_n_items; 6170 struct i_ddi_soft_state *dirty; 6171 6172 /* 6173 * Allocate a new array of the right length, copy 6174 * all the old pointers to the new array, then 6175 * if it exists at all, put the old array on the 6176 * dirty list. 6177 * 6178 * Note that we can't kmem_free() the old array. 6179 * 6180 * Why -- well the 'get' operation is 'mutex-free', so we 6181 * can't easily catch a suspended thread that is just about 6182 * to dereference the array we just grew out of. So we 6183 * cons up a header and put it on a list of 'dirty' 6184 * pointer arrays. (Dirty in the sense that there may 6185 * be suspended threads somewhere that are in the middle 6186 * of referencing them). Fortunately, we -can- garbage 6187 * collect it all at ddi_soft_state_fini time. 6188 */ 6189 new_n_items = ss->n_items; 6190 while (new_n_items < (1 + item)) 6191 new_n_items <<= 1; /* double array size .. */ 6192 6193 ASSERT(new_n_items >= (1 + item)); /* sanity check! */ 6194 6195 new_array = kmem_zalloc(new_n_items * sizeof (void *), 6196 KM_SLEEP); 6197 /* 6198 * Copy the pointers into the new array 6199 */ 6200 bcopy(array, new_array, ss->n_items * sizeof (void *)); 6201 6202 /* 6203 * Save the old array on the dirty list 6204 */ 6205 dirty = kmem_zalloc(sizeof (*dirty), KM_SLEEP); 6206 dirty->array = ss->array; 6207 dirty->n_items = ss->n_items; 6208 dirty->next = ss->next; 6209 ss->next = dirty; 6210 6211 ss->array = (array = new_array); 6212 ss->n_items = new_n_items; 6213 } 6214 6215 ASSERT(array != NULL && item < ss->n_items && array[item] == NULL); 6216 6217 array[item] = new_element; 6218 6219 mutex_exit(&ss->lock); 6220 return (DDI_SUCCESS); 6221 } 6222 6223 6224 /* 6225 * Fetch a pointer to the allocated soft state structure. 6226 * 6227 * This is designed to be cheap. 6228 * 6229 * There's an argument that there should be more checking for 6230 * nil pointers and out of bounds on the array.. but we do a lot 6231 * of that in the alloc/free routines. 6232 * 6233 * An array has the convenience that we don't need to lock read-access 6234 * to it c.f. a linked list. However our "expanding array" strategy 6235 * means that we should hold a readers lock on the i_ddi_soft_state 6236 * structure. 6237 * 6238 * However, from a performance viewpoint, we need to do it without 6239 * any locks at all -- this also makes it a leaf routine. The algorithm 6240 * is 'lock-free' because we only discard the pointer arrays at 6241 * ddi_soft_state_fini() time. 6242 */ 6243 void * 6244 ddi_get_soft_state(void *state, int item) 6245 { 6246 struct i_ddi_soft_state *ss = state; 6247 6248 ASSERT(ss != NULL && item >= 0); 6249 6250 if (item < ss->n_items && ss->array != NULL) 6251 return (ss->array[item]); 6252 return (NULL); 6253 } 6254 6255 /* 6256 * Free the state structure corresponding to 'item.' Freeing an 6257 * element that has either gone or was never allocated is not 6258 * considered an error. Note that we free the state structure, but 6259 * we don't shrink our pointer array, or discard 'dirty' arrays, 6260 * since even a few pointers don't really waste too much memory. 6261 * 6262 * Passing an item number that is out of bounds, or a null pointer will 6263 * provoke an error message. 6264 */ 6265 void 6266 ddi_soft_state_free(void *state, int item) 6267 { 6268 struct i_ddi_soft_state *ss; 6269 void **array; 6270 void *element; 6271 static char msg[] = "ddi_soft_state_free:"; 6272 6273 if ((ss = state) == NULL) { 6274 cmn_err(CE_WARN, "%s null handle: %s", 6275 msg, mod_containing_pc(caller())); 6276 return; 6277 } 6278 6279 element = NULL; 6280 6281 mutex_enter(&ss->lock); 6282 6283 if ((array = ss->array) == NULL || ss->size == 0) { 6284 cmn_err(CE_WARN, "%s bad handle: %s", 6285 msg, mod_containing_pc(caller())); 6286 } else if (item < 0 || item >= ss->n_items) { 6287 cmn_err(CE_WARN, "%s item %d not in range [0..%lu]: %s", 6288 msg, item, ss->n_items - 1, mod_containing_pc(caller())); 6289 } else if (array[item] != NULL) { 6290 element = array[item]; 6291 array[item] = NULL; 6292 } 6293 6294 mutex_exit(&ss->lock); 6295 6296 if (element) 6297 kmem_free(element, ss->size); 6298 } 6299 6300 6301 /* 6302 * Free the entire set of pointers, and any 6303 * soft state structures contained therein. 6304 * 6305 * Note that we don't grab the ss->lock mutex, even though 6306 * we're inspecting the various fields of the data structure. 6307 * 6308 * There is an implicit assumption that this routine will 6309 * never run concurrently with any of the above on this 6310 * particular state structure i.e. by the time the driver 6311 * calls this routine, there should be no other threads 6312 * running in the driver. 6313 */ 6314 void 6315 ddi_soft_state_fini(void **state_p) 6316 { 6317 struct i_ddi_soft_state *ss, *dirty; 6318 int item; 6319 static char msg[] = "ddi_soft_state_fini:"; 6320 6321 if (state_p == NULL || (ss = *state_p) == NULL) { 6322 cmn_err(CE_WARN, "%s null handle: %s", 6323 msg, mod_containing_pc(caller())); 6324 return; 6325 } 6326 6327 if (ss->size == 0) { 6328 cmn_err(CE_WARN, "%s bad handle: %s", 6329 msg, mod_containing_pc(caller())); 6330 return; 6331 } 6332 6333 if (ss->n_items > 0) { 6334 for (item = 0; item < ss->n_items; item++) 6335 ddi_soft_state_free(ss, item); 6336 kmem_free(ss->array, ss->n_items * sizeof (void *)); 6337 } 6338 6339 /* 6340 * Now delete any dirty arrays from previous 'grow' operations 6341 */ 6342 for (dirty = ss->next; dirty; dirty = ss->next) { 6343 ss->next = dirty->next; 6344 kmem_free(dirty->array, dirty->n_items * sizeof (void *)); 6345 kmem_free(dirty, sizeof (*dirty)); 6346 } 6347 6348 mutex_destroy(&ss->lock); 6349 kmem_free(ss, sizeof (*ss)); 6350 6351 *state_p = NULL; 6352 } 6353 6354 /* 6355 * This sets the devi_addr entry in the dev_info structure 'dip' to 'name'. 6356 * Storage is double buffered to prevent updates during devi_addr use - 6357 * double buffering is adaquate for reliable ddi_deviname() consumption. 6358 * The double buffer is not freed until dev_info structure destruction 6359 * (by i_ddi_free_node). 6360 */ 6361 void 6362 ddi_set_name_addr(dev_info_t *dip, char *name) 6363 { 6364 char *buf = DEVI(dip)->devi_addr_buf; 6365 char *newaddr; 6366 6367 if (buf == NULL) { 6368 buf = kmem_zalloc(2 * MAXNAMELEN, KM_SLEEP); 6369 DEVI(dip)->devi_addr_buf = buf; 6370 } 6371 6372 if (name) { 6373 ASSERT(strlen(name) < MAXNAMELEN); 6374 newaddr = (DEVI(dip)->devi_addr == buf) ? 6375 (buf + MAXNAMELEN) : buf; 6376 (void) strlcpy(newaddr, name, MAXNAMELEN); 6377 } else 6378 newaddr = NULL; 6379 6380 DEVI(dip)->devi_addr = newaddr; 6381 } 6382 6383 char * 6384 ddi_get_name_addr(dev_info_t *dip) 6385 { 6386 return (DEVI(dip)->devi_addr); 6387 } 6388 6389 void 6390 ddi_set_parent_data(dev_info_t *dip, void *pd) 6391 { 6392 DEVI(dip)->devi_parent_data = pd; 6393 } 6394 6395 void * 6396 ddi_get_parent_data(dev_info_t *dip) 6397 { 6398 return (DEVI(dip)->devi_parent_data); 6399 } 6400 6401 /* 6402 * ddi_name_to_major: Returns the major number of a module given its name. 6403 */ 6404 major_t 6405 ddi_name_to_major(char *name) 6406 { 6407 return (mod_name_to_major(name)); 6408 } 6409 6410 /* 6411 * ddi_major_to_name: Returns the module name bound to a major number. 6412 */ 6413 char * 6414 ddi_major_to_name(major_t major) 6415 { 6416 return (mod_major_to_name(major)); 6417 } 6418 6419 /* 6420 * Return the name of the devinfo node pointed at by 'dip' in the buffer 6421 * pointed at by 'name.' A devinfo node is named as a result of calling 6422 * ddi_initchild(). 6423 * 6424 * Note: the driver must be held before calling this function! 6425 */ 6426 char * 6427 ddi_deviname(dev_info_t *dip, char *name) 6428 { 6429 char *addrname; 6430 char none = '\0'; 6431 6432 if (dip == ddi_root_node()) { 6433 *name = '\0'; 6434 return (name); 6435 } 6436 6437 if (i_ddi_node_state(dip) < DS_BOUND) { 6438 addrname = &none; 6439 } else { 6440 /* 6441 * Use ddi_get_name_addr() without checking state so we get 6442 * a unit-address if we are called after ddi_set_name_addr() 6443 * by nexus DDI_CTL_INITCHILD code, but before completing 6444 * node promotion to DS_INITIALIZED. We currently have 6445 * two situations where we are called in this state: 6446 * o For framework processing of a path-oriented alias. 6447 * o If a SCSA nexus driver calls ddi_devid_register() 6448 * from it's tran_tgt_init(9E) implementation. 6449 */ 6450 addrname = ddi_get_name_addr(dip); 6451 if (addrname == NULL) 6452 addrname = &none; 6453 } 6454 6455 if (*addrname == '\0') { 6456 (void) sprintf(name, "/%s", ddi_node_name(dip)); 6457 } else { 6458 (void) sprintf(name, "/%s@%s", ddi_node_name(dip), addrname); 6459 } 6460 6461 return (name); 6462 } 6463 6464 /* 6465 * Spits out the name of device node, typically name@addr, for a given node, 6466 * using the driver name, not the nodename. 6467 * 6468 * Used by match_parent. Not to be used elsewhere. 6469 */ 6470 char * 6471 i_ddi_parname(dev_info_t *dip, char *name) 6472 { 6473 char *addrname; 6474 6475 if (dip == ddi_root_node()) { 6476 *name = '\0'; 6477 return (name); 6478 } 6479 6480 ASSERT(i_ddi_node_state(dip) >= DS_INITIALIZED); 6481 6482 if (*(addrname = ddi_get_name_addr(dip)) == '\0') 6483 (void) sprintf(name, "%s", ddi_binding_name(dip)); 6484 else 6485 (void) sprintf(name, "%s@%s", ddi_binding_name(dip), addrname); 6486 return (name); 6487 } 6488 6489 static char * 6490 pathname_work(dev_info_t *dip, char *path) 6491 { 6492 char *bp; 6493 6494 if (dip == ddi_root_node()) { 6495 *path = '\0'; 6496 return (path); 6497 } 6498 (void) pathname_work(ddi_get_parent(dip), path); 6499 bp = path + strlen(path); 6500 (void) ddi_deviname(dip, bp); 6501 return (path); 6502 } 6503 6504 char * 6505 ddi_pathname(dev_info_t *dip, char *path) 6506 { 6507 return (pathname_work(dip, path)); 6508 } 6509 6510 /* 6511 * Given a dev_t, return the pathname of the corresponding device in the 6512 * buffer pointed at by "path." The buffer is assumed to be large enough 6513 * to hold the pathname of the device (MAXPATHLEN). 6514 * 6515 * The pathname of a device is the pathname of the devinfo node to which 6516 * the device "belongs," concatenated with the character ':' and the name 6517 * of the minor node corresponding to the dev_t. If spec_type is 0 then 6518 * just the pathname of the devinfo node is returned without driving attach 6519 * of that node. For a non-zero spec_type, an attach is performed and a 6520 * search of the minor list occurs. 6521 * 6522 * It is possible that the path associated with the dev_t is not 6523 * currently available in the devinfo tree. In order to have a 6524 * dev_t, a device must have been discovered before, which means 6525 * that the path is always in the instance tree. The one exception 6526 * to this is if the dev_t is associated with a pseudo driver, in 6527 * which case the device must exist on the pseudo branch of the 6528 * devinfo tree as a result of parsing .conf files. 6529 */ 6530 int 6531 ddi_dev_pathname(dev_t devt, int spec_type, char *path) 6532 { 6533 major_t major = getmajor(devt); 6534 int instance; 6535 dev_info_t *dip; 6536 char *minorname; 6537 char *drvname; 6538 6539 if (major >= devcnt) 6540 goto fail; 6541 if (major == clone_major) { 6542 /* clone has no minor nodes, manufacture the path here */ 6543 if ((drvname = ddi_major_to_name(getminor(devt))) == NULL) 6544 goto fail; 6545 6546 (void) snprintf(path, MAXPATHLEN, "%s:%s", CLONE_PATH, drvname); 6547 return (DDI_SUCCESS); 6548 } 6549 6550 /* extract instance from devt (getinfo(9E) DDI_INFO_DEVT2INSTANCE). */ 6551 if ((instance = dev_to_instance(devt)) == -1) 6552 goto fail; 6553 6554 /* reconstruct the path given the major/instance */ 6555 if (e_ddi_majorinstance_to_path(major, instance, path) != DDI_SUCCESS) 6556 goto fail; 6557 6558 /* if spec_type given we must drive attach and search minor nodes */ 6559 if ((spec_type == S_IFCHR) || (spec_type == S_IFBLK)) { 6560 /* attach the path so we can search minors */ 6561 if ((dip = e_ddi_hold_devi_by_path(path, 0)) == NULL) 6562 goto fail; 6563 6564 /* Add minorname to path. */ 6565 mutex_enter(&(DEVI(dip)->devi_lock)); 6566 minorname = i_ddi_devtspectype_to_minorname(dip, 6567 devt, spec_type); 6568 if (minorname) { 6569 (void) strcat(path, ":"); 6570 (void) strcat(path, minorname); 6571 } 6572 mutex_exit(&(DEVI(dip)->devi_lock)); 6573 ddi_release_devi(dip); 6574 if (minorname == NULL) 6575 goto fail; 6576 } 6577 ASSERT(strlen(path) < MAXPATHLEN); 6578 return (DDI_SUCCESS); 6579 6580 fail: *path = 0; 6581 return (DDI_FAILURE); 6582 } 6583 6584 /* 6585 * Given a major number and an instance, return the path. 6586 * This interface does NOT drive attach. 6587 */ 6588 int 6589 e_ddi_majorinstance_to_path(major_t major, int instance, char *path) 6590 { 6591 struct devnames *dnp; 6592 dev_info_t *dip; 6593 6594 if ((major >= devcnt) || (instance == -1)) { 6595 *path = 0; 6596 return (DDI_FAILURE); 6597 } 6598 6599 /* look for the major/instance in the instance tree */ 6600 if (e_ddi_instance_majorinstance_to_path(major, instance, 6601 path) == DDI_SUCCESS) { 6602 ASSERT(strlen(path) < MAXPATHLEN); 6603 return (DDI_SUCCESS); 6604 } 6605 6606 /* 6607 * Not in instance tree, find the instance on the per driver list and 6608 * construct path to instance via ddi_pathname(). This is how paths 6609 * down the 'pseudo' branch are constructed. 6610 */ 6611 dnp = &(devnamesp[major]); 6612 LOCK_DEV_OPS(&(dnp->dn_lock)); 6613 for (dip = dnp->dn_head; dip; 6614 dip = (dev_info_t *)DEVI(dip)->devi_next) { 6615 /* Skip if instance does not match. */ 6616 if (DEVI(dip)->devi_instance != instance) 6617 continue; 6618 6619 /* 6620 * An ndi_hold_devi() does not prevent DS_INITIALIZED->DS_BOUND 6621 * node demotion, so it is not an effective way of ensuring 6622 * that the ddi_pathname result has a unit-address. Instead, 6623 * we reverify the node state after calling ddi_pathname(). 6624 */ 6625 if (i_ddi_node_state(dip) >= DS_INITIALIZED) { 6626 (void) ddi_pathname(dip, path); 6627 if (i_ddi_node_state(dip) < DS_INITIALIZED) 6628 continue; 6629 UNLOCK_DEV_OPS(&(dnp->dn_lock)); 6630 ASSERT(strlen(path) < MAXPATHLEN); 6631 return (DDI_SUCCESS); 6632 } 6633 } 6634 UNLOCK_DEV_OPS(&(dnp->dn_lock)); 6635 6636 /* can't reconstruct the path */ 6637 *path = 0; 6638 return (DDI_FAILURE); 6639 } 6640 6641 #define GLD_DRIVER_PPA "SUNW,gld_v0_ppa" 6642 6643 /* 6644 * Given the dip for a network interface return the ppa for that interface. 6645 * 6646 * In all cases except GLD v0 drivers, the ppa == instance. 6647 * In the case of GLD v0 drivers, the ppa is equal to the attach order. 6648 * So for these drivers when the attach routine calls gld_register(), 6649 * the GLD framework creates an integer property called "gld_driver_ppa" 6650 * that can be queried here. 6651 * 6652 * The only time this function is used is when a system is booting over nfs. 6653 * In this case the system has to resolve the pathname of the boot device 6654 * to it's ppa. 6655 */ 6656 int 6657 i_ddi_devi_get_ppa(dev_info_t *dip) 6658 { 6659 return (ddi_prop_get_int(DDI_DEV_T_ANY, dip, 6660 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 6661 GLD_DRIVER_PPA, ddi_get_instance(dip))); 6662 } 6663 6664 /* 6665 * i_ddi_devi_set_ppa() should only be called from gld_register() 6666 * and only for GLD v0 drivers 6667 */ 6668 void 6669 i_ddi_devi_set_ppa(dev_info_t *dip, int ppa) 6670 { 6671 (void) e_ddi_prop_update_int(DDI_DEV_T_NONE, dip, GLD_DRIVER_PPA, ppa); 6672 } 6673 6674 6675 /* 6676 * Private DDI Console bell functions. 6677 */ 6678 void 6679 ddi_ring_console_bell(clock_t duration) 6680 { 6681 if (ddi_console_bell_func != NULL) 6682 (*ddi_console_bell_func)(duration); 6683 } 6684 6685 void 6686 ddi_set_console_bell(void (*bellfunc)(clock_t duration)) 6687 { 6688 ddi_console_bell_func = bellfunc; 6689 } 6690 6691 int 6692 ddi_dma_alloc_handle(dev_info_t *dip, ddi_dma_attr_t *attr, 6693 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 6694 { 6695 int (*funcp)() = ddi_dma_allochdl; 6696 ddi_dma_attr_t dma_attr; 6697 struct bus_ops *bop; 6698 6699 if (attr == (ddi_dma_attr_t *)0) 6700 return (DDI_DMA_BADATTR); 6701 6702 dma_attr = *attr; 6703 6704 bop = DEVI(dip)->devi_ops->devo_bus_ops; 6705 if (bop && bop->bus_dma_allochdl) 6706 funcp = bop->bus_dma_allochdl; 6707 6708 return ((*funcp)(dip, dip, &dma_attr, waitfp, arg, handlep)); 6709 } 6710 6711 void 6712 ddi_dma_free_handle(ddi_dma_handle_t *handlep) 6713 { 6714 ddi_dma_handle_t h = *handlep; 6715 (void) ddi_dma_freehdl(HD, HD, h); 6716 } 6717 6718 static uintptr_t dma_mem_list_id = 0; 6719 6720 6721 int 6722 ddi_dma_mem_alloc(ddi_dma_handle_t handle, size_t length, 6723 ddi_device_acc_attr_t *accattrp, uint_t flags, 6724 int (*waitfp)(caddr_t), caddr_t arg, caddr_t *kaddrp, 6725 size_t *real_length, ddi_acc_handle_t *handlep) 6726 { 6727 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6728 dev_info_t *dip = hp->dmai_rdip; 6729 ddi_acc_hdl_t *ap; 6730 ddi_dma_attr_t *attrp = &hp->dmai_attr; 6731 uint_t sleepflag, xfermodes; 6732 int (*fp)(caddr_t); 6733 int rval; 6734 6735 if (waitfp == DDI_DMA_SLEEP) 6736 fp = (int (*)())KM_SLEEP; 6737 else if (waitfp == DDI_DMA_DONTWAIT) 6738 fp = (int (*)())KM_NOSLEEP; 6739 else 6740 fp = waitfp; 6741 *handlep = impl_acc_hdl_alloc(fp, arg); 6742 if (*handlep == NULL) 6743 return (DDI_FAILURE); 6744 6745 /* check if the cache attributes are supported */ 6746 if (i_ddi_check_cache_attr(flags) == B_FALSE) 6747 return (DDI_FAILURE); 6748 6749 /* 6750 * Transfer the meaningful bits to xfermodes. 6751 * Double-check if the 3rd party driver correctly sets the bits. 6752 * If not, set DDI_DMA_STREAMING to keep compatibility. 6753 */ 6754 xfermodes = flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING); 6755 if (xfermodes == 0) { 6756 xfermodes = DDI_DMA_STREAMING; 6757 } 6758 6759 /* 6760 * initialize the common elements of data access handle 6761 */ 6762 ap = impl_acc_hdl_get(*handlep); 6763 ap->ah_vers = VERS_ACCHDL; 6764 ap->ah_dip = dip; 6765 ap->ah_offset = 0; 6766 ap->ah_len = 0; 6767 ap->ah_xfermodes = flags; 6768 ap->ah_acc = *accattrp; 6769 6770 sleepflag = ((waitfp == DDI_DMA_SLEEP) ? 1 : 0); 6771 if (xfermodes == DDI_DMA_CONSISTENT) { 6772 rval = i_ddi_mem_alloc(dip, attrp, length, sleepflag, 6773 flags, accattrp, kaddrp, NULL, ap); 6774 *real_length = length; 6775 } else { 6776 rval = i_ddi_mem_alloc(dip, attrp, length, sleepflag, 6777 flags, accattrp, kaddrp, real_length, ap); 6778 } 6779 if (rval == DDI_SUCCESS) { 6780 ap->ah_len = (off_t)(*real_length); 6781 ap->ah_addr = *kaddrp; 6782 } else { 6783 impl_acc_hdl_free(*handlep); 6784 *handlep = (ddi_acc_handle_t)NULL; 6785 if (waitfp != DDI_DMA_SLEEP && waitfp != DDI_DMA_DONTWAIT) { 6786 ddi_set_callback(waitfp, arg, &dma_mem_list_id); 6787 } 6788 rval = DDI_FAILURE; 6789 } 6790 return (rval); 6791 } 6792 6793 void 6794 ddi_dma_mem_free(ddi_acc_handle_t *handlep) 6795 { 6796 ddi_acc_hdl_t *ap; 6797 6798 ap = impl_acc_hdl_get(*handlep); 6799 ASSERT(ap); 6800 6801 i_ddi_mem_free((caddr_t)ap->ah_addr, ap); 6802 6803 /* 6804 * free the handle 6805 */ 6806 impl_acc_hdl_free(*handlep); 6807 *handlep = (ddi_acc_handle_t)NULL; 6808 6809 if (dma_mem_list_id != 0) { 6810 ddi_run_callback(&dma_mem_list_id); 6811 } 6812 } 6813 6814 int 6815 ddi_dma_buf_bind_handle(ddi_dma_handle_t handle, struct buf *bp, 6816 uint_t flags, int (*waitfp)(caddr_t), caddr_t arg, 6817 ddi_dma_cookie_t *cookiep, uint_t *ccountp) 6818 { 6819 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6820 dev_info_t *hdip, *dip; 6821 struct ddi_dma_req dmareq; 6822 int (*funcp)(); 6823 6824 dmareq.dmar_flags = flags; 6825 dmareq.dmar_fp = waitfp; 6826 dmareq.dmar_arg = arg; 6827 dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount; 6828 6829 if (bp->b_flags & B_PAGEIO) { 6830 dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES; 6831 dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages; 6832 dmareq.dmar_object.dmao_obj.pp_obj.pp_offset = 6833 (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET); 6834 } else { 6835 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr; 6836 if (bp->b_flags & B_SHADOW) { 6837 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = 6838 bp->b_shadow; 6839 dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR; 6840 } else { 6841 dmareq.dmar_object.dmao_type = 6842 (bp->b_flags & (B_PHYS | B_REMAPPED)) ? 6843 DMA_OTYP_BUFVADDR : DMA_OTYP_VADDR; 6844 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 6845 } 6846 6847 /* 6848 * If the buffer has no proc pointer, or the proc 6849 * struct has the kernel address space, or the buffer has 6850 * been marked B_REMAPPED (meaning that it is now 6851 * mapped into the kernel's address space), then 6852 * the address space is kas (kernel address space). 6853 */ 6854 if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) || 6855 (bp->b_flags & B_REMAPPED)) { 6856 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0; 6857 } else { 6858 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 6859 bp->b_proc->p_as; 6860 } 6861 } 6862 6863 dip = hp->dmai_rdip; 6864 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 6865 funcp = DEVI(dip)->devi_bus_dma_bindfunc; 6866 return ((*funcp)(hdip, dip, handle, &dmareq, cookiep, ccountp)); 6867 } 6868 6869 int 6870 ddi_dma_addr_bind_handle(ddi_dma_handle_t handle, struct as *as, 6871 caddr_t addr, size_t len, uint_t flags, int (*waitfp)(caddr_t), 6872 caddr_t arg, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 6873 { 6874 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6875 dev_info_t *hdip, *dip; 6876 struct ddi_dma_req dmareq; 6877 int (*funcp)(); 6878 6879 if (len == (uint_t)0) { 6880 return (DDI_DMA_NOMAPPING); 6881 } 6882 dmareq.dmar_flags = flags; 6883 dmareq.dmar_fp = waitfp; 6884 dmareq.dmar_arg = arg; 6885 dmareq.dmar_object.dmao_size = len; 6886 dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 6887 dmareq.dmar_object.dmao_obj.virt_obj.v_as = as; 6888 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr; 6889 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 6890 6891 dip = hp->dmai_rdip; 6892 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 6893 funcp = DEVI(dip)->devi_bus_dma_bindfunc; 6894 return ((*funcp)(hdip, dip, handle, &dmareq, cookiep, ccountp)); 6895 } 6896 6897 void 6898 ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep) 6899 { 6900 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6901 ddi_dma_cookie_t *cp; 6902 6903 cp = hp->dmai_cookie; 6904 ASSERT(cp); 6905 6906 cookiep->dmac_notused = cp->dmac_notused; 6907 cookiep->dmac_type = cp->dmac_type; 6908 cookiep->dmac_address = cp->dmac_address; 6909 cookiep->dmac_size = cp->dmac_size; 6910 hp->dmai_cookie++; 6911 } 6912 6913 int 6914 ddi_dma_numwin(ddi_dma_handle_t handle, uint_t *nwinp) 6915 { 6916 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6917 if ((hp->dmai_rflags & DDI_DMA_PARTIAL) == 0) { 6918 return (DDI_FAILURE); 6919 } else { 6920 *nwinp = hp->dmai_nwin; 6921 return (DDI_SUCCESS); 6922 } 6923 } 6924 6925 int 6926 ddi_dma_getwin(ddi_dma_handle_t h, uint_t win, off_t *offp, 6927 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 6928 { 6929 int (*funcp)() = ddi_dma_win; 6930 struct bus_ops *bop; 6931 6932 bop = DEVI(HD)->devi_ops->devo_bus_ops; 6933 if (bop && bop->bus_dma_win) 6934 funcp = bop->bus_dma_win; 6935 6936 return ((*funcp)(HD, HD, h, win, offp, lenp, cookiep, ccountp)); 6937 } 6938 6939 int 6940 ddi_dma_set_sbus64(ddi_dma_handle_t h, ulong_t burstsizes) 6941 { 6942 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SET_SBUS64, 0, 6943 &burstsizes, 0, 0)); 6944 } 6945 6946 int 6947 i_ddi_dma_fault_check(ddi_dma_impl_t *hp) 6948 { 6949 return (hp->dmai_fault); 6950 } 6951 6952 int 6953 ddi_check_dma_handle(ddi_dma_handle_t handle) 6954 { 6955 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6956 int (*check)(ddi_dma_impl_t *); 6957 6958 if ((check = hp->dmai_fault_check) == NULL) 6959 check = i_ddi_dma_fault_check; 6960 6961 return (((*check)(hp) == DDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 6962 } 6963 6964 void 6965 i_ddi_dma_set_fault(ddi_dma_handle_t handle) 6966 { 6967 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6968 void (*notify)(ddi_dma_impl_t *); 6969 6970 if (!hp->dmai_fault) { 6971 hp->dmai_fault = 1; 6972 if ((notify = hp->dmai_fault_notify) != NULL) 6973 (*notify)(hp); 6974 } 6975 } 6976 6977 void 6978 i_ddi_dma_clr_fault(ddi_dma_handle_t handle) 6979 { 6980 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; 6981 void (*notify)(ddi_dma_impl_t *); 6982 6983 if (hp->dmai_fault) { 6984 hp->dmai_fault = 0; 6985 if ((notify = hp->dmai_fault_notify) != NULL) 6986 (*notify)(hp); 6987 } 6988 } 6989 6990 /* 6991 * register mapping routines. 6992 */ 6993 int 6994 ddi_regs_map_setup(dev_info_t *dip, uint_t rnumber, caddr_t *addrp, 6995 offset_t offset, offset_t len, ddi_device_acc_attr_t *accattrp, 6996 ddi_acc_handle_t *handle) 6997 { 6998 ddi_map_req_t mr; 6999 ddi_acc_hdl_t *hp; 7000 int result; 7001 7002 /* 7003 * Allocate and initialize the common elements of data access handle. 7004 */ 7005 *handle = impl_acc_hdl_alloc(KM_SLEEP, NULL); 7006 hp = impl_acc_hdl_get(*handle); 7007 hp->ah_vers = VERS_ACCHDL; 7008 hp->ah_dip = dip; 7009 hp->ah_rnumber = rnumber; 7010 hp->ah_offset = offset; 7011 hp->ah_len = len; 7012 hp->ah_acc = *accattrp; 7013 7014 /* 7015 * Set up the mapping request and call to parent. 7016 */ 7017 mr.map_op = DDI_MO_MAP_LOCKED; 7018 mr.map_type = DDI_MT_RNUMBER; 7019 mr.map_obj.rnumber = rnumber; 7020 mr.map_prot = PROT_READ | PROT_WRITE; 7021 mr.map_flags = DDI_MF_KERNEL_MAPPING; 7022 mr.map_handlep = hp; 7023 mr.map_vers = DDI_MAP_VERSION; 7024 result = ddi_map(dip, &mr, offset, len, addrp); 7025 7026 /* 7027 * check for end result 7028 */ 7029 if (result != DDI_SUCCESS) { 7030 impl_acc_hdl_free(*handle); 7031 *handle = (ddi_acc_handle_t)NULL; 7032 } else { 7033 hp->ah_addr = *addrp; 7034 } 7035 7036 return (result); 7037 } 7038 7039 void 7040 ddi_regs_map_free(ddi_acc_handle_t *handlep) 7041 { 7042 ddi_map_req_t mr; 7043 ddi_acc_hdl_t *hp; 7044 7045 hp = impl_acc_hdl_get(*handlep); 7046 ASSERT(hp); 7047 7048 mr.map_op = DDI_MO_UNMAP; 7049 mr.map_type = DDI_MT_RNUMBER; 7050 mr.map_obj.rnumber = hp->ah_rnumber; 7051 mr.map_prot = PROT_READ | PROT_WRITE; 7052 mr.map_flags = DDI_MF_KERNEL_MAPPING; 7053 mr.map_handlep = hp; 7054 mr.map_vers = DDI_MAP_VERSION; 7055 7056 /* 7057 * Call my parent to unmap my regs. 7058 */ 7059 (void) ddi_map(hp->ah_dip, &mr, hp->ah_offset, 7060 hp->ah_len, &hp->ah_addr); 7061 /* 7062 * free the handle 7063 */ 7064 impl_acc_hdl_free(*handlep); 7065 *handlep = (ddi_acc_handle_t)NULL; 7066 } 7067 7068 int 7069 ddi_device_zero(ddi_acc_handle_t handle, caddr_t dev_addr, size_t bytecount, 7070 ssize_t dev_advcnt, uint_t dev_datasz) 7071 { 7072 uint8_t *b; 7073 uint16_t *w; 7074 uint32_t *l; 7075 uint64_t *ll; 7076 7077 /* check for total byte count is multiple of data transfer size */ 7078 if (bytecount != ((bytecount / dev_datasz) * dev_datasz)) 7079 return (DDI_FAILURE); 7080 7081 switch (dev_datasz) { 7082 case DDI_DATA_SZ01_ACC: 7083 for (b = (uint8_t *)dev_addr; 7084 bytecount != 0; bytecount -= 1, b += dev_advcnt) 7085 ddi_put8(handle, b, 0); 7086 break; 7087 case DDI_DATA_SZ02_ACC: 7088 for (w = (uint16_t *)dev_addr; 7089 bytecount != 0; bytecount -= 2, w += dev_advcnt) 7090 ddi_put16(handle, w, 0); 7091 break; 7092 case DDI_DATA_SZ04_ACC: 7093 for (l = (uint32_t *)dev_addr; 7094 bytecount != 0; bytecount -= 4, l += dev_advcnt) 7095 ddi_put32(handle, l, 0); 7096 break; 7097 case DDI_DATA_SZ08_ACC: 7098 for (ll = (uint64_t *)dev_addr; 7099 bytecount != 0; bytecount -= 8, ll += dev_advcnt) 7100 ddi_put64(handle, ll, 0x0ll); 7101 break; 7102 default: 7103 return (DDI_FAILURE); 7104 } 7105 return (DDI_SUCCESS); 7106 } 7107 7108 int 7109 ddi_device_copy( 7110 ddi_acc_handle_t src_handle, caddr_t src_addr, ssize_t src_advcnt, 7111 ddi_acc_handle_t dest_handle, caddr_t dest_addr, ssize_t dest_advcnt, 7112 size_t bytecount, uint_t dev_datasz) 7113 { 7114 uint8_t *b_src, *b_dst; 7115 uint16_t *w_src, *w_dst; 7116 uint32_t *l_src, *l_dst; 7117 uint64_t *ll_src, *ll_dst; 7118 7119 /* check for total byte count is multiple of data transfer size */ 7120 if (bytecount != ((bytecount / dev_datasz) * dev_datasz)) 7121 return (DDI_FAILURE); 7122 7123 switch (dev_datasz) { 7124 case DDI_DATA_SZ01_ACC: 7125 b_src = (uint8_t *)src_addr; 7126 b_dst = (uint8_t *)dest_addr; 7127 7128 for (; bytecount != 0; bytecount -= 1) { 7129 ddi_put8(dest_handle, b_dst, 7130 ddi_get8(src_handle, b_src)); 7131 b_dst += dest_advcnt; 7132 b_src += src_advcnt; 7133 } 7134 break; 7135 case DDI_DATA_SZ02_ACC: 7136 w_src = (uint16_t *)src_addr; 7137 w_dst = (uint16_t *)dest_addr; 7138 7139 for (; bytecount != 0; bytecount -= 2) { 7140 ddi_put16(dest_handle, w_dst, 7141 ddi_get16(src_handle, w_src)); 7142 w_dst += dest_advcnt; 7143 w_src += src_advcnt; 7144 } 7145 break; 7146 case DDI_DATA_SZ04_ACC: 7147 l_src = (uint32_t *)src_addr; 7148 l_dst = (uint32_t *)dest_addr; 7149 7150 for (; bytecount != 0; bytecount -= 4) { 7151 ddi_put32(dest_handle, l_dst, 7152 ddi_get32(src_handle, l_src)); 7153 l_dst += dest_advcnt; 7154 l_src += src_advcnt; 7155 } 7156 break; 7157 case DDI_DATA_SZ08_ACC: 7158 ll_src = (uint64_t *)src_addr; 7159 ll_dst = (uint64_t *)dest_addr; 7160 7161 for (; bytecount != 0; bytecount -= 8) { 7162 ddi_put64(dest_handle, ll_dst, 7163 ddi_get64(src_handle, ll_src)); 7164 ll_dst += dest_advcnt; 7165 ll_src += src_advcnt; 7166 } 7167 break; 7168 default: 7169 return (DDI_FAILURE); 7170 } 7171 return (DDI_SUCCESS); 7172 } 7173 7174 #define swap16(value) \ 7175 ((((value) & 0xff) << 8) | ((value) >> 8)) 7176 7177 #define swap32(value) \ 7178 (((uint32_t)swap16((uint16_t)((value) & 0xffff)) << 16) | \ 7179 (uint32_t)swap16((uint16_t)((value) >> 16))) 7180 7181 #define swap64(value) \ 7182 (((uint64_t)swap32((uint32_t)((value) & 0xffffffff)) \ 7183 << 32) | \ 7184 (uint64_t)swap32((uint32_t)((value) >> 32))) 7185 7186 uint16_t 7187 ddi_swap16(uint16_t value) 7188 { 7189 return (swap16(value)); 7190 } 7191 7192 uint32_t 7193 ddi_swap32(uint32_t value) 7194 { 7195 return (swap32(value)); 7196 } 7197 7198 uint64_t 7199 ddi_swap64(uint64_t value) 7200 { 7201 return (swap64(value)); 7202 } 7203 7204 /* 7205 * Convert a binding name to a driver name. 7206 * A binding name is the name used to determine the driver for a 7207 * device - it may be either an alias for the driver or the name 7208 * of the driver itself. 7209 */ 7210 char * 7211 i_binding_to_drv_name(char *bname) 7212 { 7213 major_t major_no; 7214 7215 ASSERT(bname != NULL); 7216 7217 if ((major_no = ddi_name_to_major(bname)) == -1) 7218 return (NULL); 7219 return (ddi_major_to_name(major_no)); 7220 } 7221 7222 /* 7223 * Search for minor name that has specified dev_t and spec_type. 7224 * If spec_type is zero then any dev_t match works. Since we 7225 * are returning a pointer to the minor name string, we require the 7226 * caller to do the locking. 7227 */ 7228 char * 7229 i_ddi_devtspectype_to_minorname(dev_info_t *dip, dev_t dev, int spec_type) 7230 { 7231 struct ddi_minor_data *dmdp; 7232 7233 /* 7234 * The did layered driver currently intentionally returns a 7235 * devinfo ptr for an underlying sd instance based on a did 7236 * dev_t. In this case it is not an error. 7237 * 7238 * The did layered driver is associated with Sun Cluster. 7239 */ 7240 ASSERT((ddi_driver_major(dip) == getmajor(dev)) || 7241 (strcmp(ddi_major_to_name(getmajor(dev)), "did") == 0)); 7242 ASSERT(MUTEX_HELD(&(DEVI(dip)->devi_lock))); 7243 7244 for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { 7245 if (((dmdp->type == DDM_MINOR) || 7246 (dmdp->type == DDM_INTERNAL_PATH) || 7247 (dmdp->type == DDM_DEFAULT)) && 7248 (dmdp->ddm_dev == dev) && 7249 ((((spec_type & (S_IFCHR|S_IFBLK))) == 0) || 7250 (dmdp->ddm_spec_type == spec_type))) 7251 return (dmdp->ddm_name); 7252 } 7253 7254 return (NULL); 7255 } 7256 7257 /* 7258 * Find the devt and spectype of the specified minor_name. 7259 * Return DDI_FAILURE if minor_name not found. Since we are 7260 * returning everything via arguments we can do the locking. 7261 */ 7262 int 7263 i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name, 7264 dev_t *devtp, int *spectypep) 7265 { 7266 struct ddi_minor_data *dmdp; 7267 7268 /* deal with clone minor nodes */ 7269 if (dip == clone_dip) { 7270 major_t major; 7271 /* 7272 * Make sure minor_name is a STREAMS driver. 7273 * We load the driver but don't attach to any instances. 7274 */ 7275 7276 major = ddi_name_to_major(minor_name); 7277 if (major == (major_t)-1) 7278 return (DDI_FAILURE); 7279 7280 if (ddi_hold_driver(major) == NULL) 7281 return (DDI_FAILURE); 7282 7283 if (STREAMSTAB(major) == NULL) { 7284 ddi_rele_driver(major); 7285 return (DDI_FAILURE); 7286 } 7287 ddi_rele_driver(major); 7288 7289 if (devtp) 7290 *devtp = makedevice(clone_major, (minor_t)major); 7291 7292 if (spectypep) 7293 *spectypep = S_IFCHR; 7294 7295 return (DDI_SUCCESS); 7296 } 7297 7298 ASSERT(!MUTEX_HELD(&(DEVI(dip)->devi_lock))); 7299 mutex_enter(&(DEVI(dip)->devi_lock)); 7300 7301 for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { 7302 if (((dmdp->type != DDM_MINOR) && 7303 (dmdp->type != DDM_INTERNAL_PATH) && 7304 (dmdp->type != DDM_DEFAULT)) || 7305 strcmp(minor_name, dmdp->ddm_name)) 7306 continue; 7307 7308 if (devtp) 7309 *devtp = dmdp->ddm_dev; 7310 7311 if (spectypep) 7312 *spectypep = dmdp->ddm_spec_type; 7313 7314 mutex_exit(&(DEVI(dip)->devi_lock)); 7315 return (DDI_SUCCESS); 7316 } 7317 7318 mutex_exit(&(DEVI(dip)->devi_lock)); 7319 return (DDI_FAILURE); 7320 } 7321 7322 extern char hw_serial[]; 7323 static kmutex_t devid_gen_mutex; 7324 static short devid_gen_number; 7325 7326 #ifdef DEBUG 7327 7328 static int devid_register_corrupt = 0; 7329 static int devid_register_corrupt_major = 0; 7330 static int devid_register_corrupt_hint = 0; 7331 static int devid_register_corrupt_hint_major = 0; 7332 7333 static int devid_lyr_debug = 0; 7334 7335 #define DDI_DEBUG_DEVID_DEVTS(msg, ndevs, devs) \ 7336 if (devid_lyr_debug) \ 7337 ddi_debug_devid_devts(msg, ndevs, devs) 7338 7339 #else 7340 7341 #define DDI_DEBUG_DEVID_DEVTS(msg, ndevs, devs) 7342 7343 #endif /* DEBUG */ 7344 7345 7346 #ifdef DEBUG 7347 7348 static void 7349 ddi_debug_devid_devts(char *msg, int ndevs, dev_t *devs) 7350 { 7351 int i; 7352 7353 cmn_err(CE_CONT, "%s:\n", msg); 7354 for (i = 0; i < ndevs; i++) { 7355 cmn_err(CE_CONT, " 0x%lx\n", devs[i]); 7356 } 7357 } 7358 7359 static void 7360 ddi_debug_devid_paths(char *msg, int npaths, char **paths) 7361 { 7362 int i; 7363 7364 cmn_err(CE_CONT, "%s:\n", msg); 7365 for (i = 0; i < npaths; i++) { 7366 cmn_err(CE_CONT, " %s\n", paths[i]); 7367 } 7368 } 7369 7370 static void 7371 ddi_debug_devid_devts_per_path(char *path, int ndevs, dev_t *devs) 7372 { 7373 int i; 7374 7375 cmn_err(CE_CONT, "dev_ts per path %s\n", path); 7376 for (i = 0; i < ndevs; i++) { 7377 cmn_err(CE_CONT, " 0x%lx\n", devs[i]); 7378 } 7379 } 7380 7381 #endif /* DEBUG */ 7382 7383 /* 7384 * Register device id into DDI framework. 7385 * Must be called when device is attached. 7386 */ 7387 static int 7388 i_ddi_devid_register(dev_info_t *dip, ddi_devid_t devid) 7389 { 7390 impl_devid_t *i_devid = (impl_devid_t *)devid; 7391 size_t driver_len; 7392 const char *driver_name; 7393 char *devid_str; 7394 major_t major; 7395 7396 if ((dip == NULL) || 7397 ((major = ddi_driver_major(dip)) == (major_t)-1)) 7398 return (DDI_FAILURE); 7399 7400 /* verify that the devid is valid */ 7401 if (ddi_devid_valid(devid) != DDI_SUCCESS) 7402 return (DDI_FAILURE); 7403 7404 /* Updating driver name hint in devid */ 7405 driver_name = ddi_driver_name(dip); 7406 driver_len = strlen(driver_name); 7407 if (driver_len > DEVID_HINT_SIZE) { 7408 /* Pick up last four characters of driver name */ 7409 driver_name += driver_len - DEVID_HINT_SIZE; 7410 driver_len = DEVID_HINT_SIZE; 7411 } 7412 bzero(i_devid->did_driver, DEVID_HINT_SIZE); 7413 bcopy(driver_name, i_devid->did_driver, driver_len); 7414 7415 #ifdef DEBUG 7416 /* Corrupt the devid for testing. */ 7417 if (devid_register_corrupt) 7418 i_devid->did_id[0] += devid_register_corrupt; 7419 if (devid_register_corrupt_major && 7420 (major == devid_register_corrupt_major)) 7421 i_devid->did_id[0] += 1; 7422 if (devid_register_corrupt_hint) 7423 i_devid->did_driver[0] += devid_register_corrupt_hint; 7424 if (devid_register_corrupt_hint_major && 7425 (major == devid_register_corrupt_hint_major)) 7426 i_devid->did_driver[0] += 1; 7427 #endif /* DEBUG */ 7428 7429 /* encode the devid as a string */ 7430 if ((devid_str = ddi_devid_str_encode(devid, NULL)) == NULL) 7431 return (DDI_FAILURE); 7432 7433 /* add string as a string property */ 7434 if (ndi_prop_update_string(DDI_DEV_T_NONE, dip, 7435 DEVID_PROP_NAME, devid_str) != DDI_SUCCESS) { 7436 cmn_err(CE_WARN, "%s%d: devid property update failed", 7437 ddi_driver_name(dip), ddi_get_instance(dip)); 7438 ddi_devid_str_free(devid_str); 7439 return (DDI_FAILURE); 7440 } 7441 7442 ddi_devid_str_free(devid_str); 7443 7444 #ifdef DEVID_COMPATIBILITY 7445 /* 7446 * marker for devinfo snapshot compatibility. 7447 * This code gets deleted when di_devid is gone from libdevid 7448 */ 7449 DEVI(dip)->devi_devid = DEVID_COMPATIBILITY; 7450 #endif /* DEVID_COMPATIBILITY */ 7451 return (DDI_SUCCESS); 7452 } 7453 7454 int 7455 ddi_devid_register(dev_info_t *dip, ddi_devid_t devid) 7456 { 7457 int rval; 7458 7459 rval = i_ddi_devid_register(dip, devid); 7460 if (rval == DDI_SUCCESS) { 7461 /* 7462 * Register devid in devid-to-path cache 7463 */ 7464 if (e_devid_cache_register(dip, devid) == DDI_SUCCESS) { 7465 mutex_enter(&DEVI(dip)->devi_lock); 7466 DEVI(dip)->devi_flags |= DEVI_REGISTERED_DEVID; 7467 mutex_exit(&DEVI(dip)->devi_lock); 7468 } else { 7469 cmn_err(CE_WARN, "%s%d: failed to cache devid", 7470 ddi_driver_name(dip), ddi_get_instance(dip)); 7471 } 7472 } else { 7473 cmn_err(CE_WARN, "%s%d: failed to register devid", 7474 ddi_driver_name(dip), ddi_get_instance(dip)); 7475 } 7476 return (rval); 7477 } 7478 7479 /* 7480 * Remove (unregister) device id from DDI framework. 7481 * Must be called when device is detached. 7482 */ 7483 static void 7484 i_ddi_devid_unregister(dev_info_t *dip) 7485 { 7486 #ifdef DEVID_COMPATIBILITY 7487 /* 7488 * marker for micro release devinfo snapshot compatibility. 7489 * This code gets deleted for the minor release. 7490 */ 7491 DEVI(dip)->devi_devid = NULL; /* unset DEVID_PROP */ 7492 #endif /* DEVID_COMPATIBILITY */ 7493 7494 /* remove the devid property */ 7495 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, DEVID_PROP_NAME); 7496 } 7497 7498 void 7499 ddi_devid_unregister(dev_info_t *dip) 7500 { 7501 mutex_enter(&DEVI(dip)->devi_lock); 7502 DEVI(dip)->devi_flags &= ~DEVI_REGISTERED_DEVID; 7503 mutex_exit(&DEVI(dip)->devi_lock); 7504 e_devid_cache_unregister(dip); 7505 i_ddi_devid_unregister(dip); 7506 } 7507 7508 /* 7509 * Allocate and initialize a device id. 7510 */ 7511 int 7512 ddi_devid_init( 7513 dev_info_t *dip, 7514 ushort_t devid_type, 7515 ushort_t nbytes, 7516 void *id, 7517 ddi_devid_t *ret_devid) 7518 { 7519 impl_devid_t *i_devid; 7520 int sz = sizeof (*i_devid) + nbytes - sizeof (char); 7521 int driver_len; 7522 const char *driver_name; 7523 7524 switch (devid_type) { 7525 case DEVID_SCSI3_WWN: 7526 /*FALLTHRU*/ 7527 case DEVID_SCSI_SERIAL: 7528 /*FALLTHRU*/ 7529 case DEVID_ATA_SERIAL: 7530 /*FALLTHRU*/ 7531 case DEVID_ENCAP: 7532 if (nbytes == 0) 7533 return (DDI_FAILURE); 7534 if (id == NULL) 7535 return (DDI_FAILURE); 7536 break; 7537 case DEVID_FAB: 7538 if (nbytes != 0) 7539 return (DDI_FAILURE); 7540 if (id != NULL) 7541 return (DDI_FAILURE); 7542 nbytes = sizeof (int) + 7543 sizeof (struct timeval32) + sizeof (short); 7544 sz += nbytes; 7545 break; 7546 default: 7547 return (DDI_FAILURE); 7548 } 7549 7550 if ((i_devid = kmem_zalloc(sz, KM_SLEEP)) == NULL) 7551 return (DDI_FAILURE); 7552 7553 i_devid->did_magic_hi = DEVID_MAGIC_MSB; 7554 i_devid->did_magic_lo = DEVID_MAGIC_LSB; 7555 i_devid->did_rev_hi = DEVID_REV_MSB; 7556 i_devid->did_rev_lo = DEVID_REV_LSB; 7557 DEVID_FORMTYPE(i_devid, devid_type); 7558 DEVID_FORMLEN(i_devid, nbytes); 7559 7560 /* Fill in driver name hint */ 7561 driver_name = ddi_driver_name(dip); 7562 driver_len = strlen(driver_name); 7563 if (driver_len > DEVID_HINT_SIZE) { 7564 /* Pick up last four characters of driver name */ 7565 driver_name += driver_len - DEVID_HINT_SIZE; 7566 driver_len = DEVID_HINT_SIZE; 7567 } 7568 7569 bcopy(driver_name, i_devid->did_driver, driver_len); 7570 7571 /* Fill in id field */ 7572 if (devid_type == DEVID_FAB) { 7573 char *cp; 7574 int hostid; 7575 char *hostid_cp = &hw_serial[0]; 7576 struct timeval32 timestamp32; 7577 int i; 7578 int *ip; 7579 short gen; 7580 7581 /* increase the generation number */ 7582 mutex_enter(&devid_gen_mutex); 7583 gen = devid_gen_number++; 7584 mutex_exit(&devid_gen_mutex); 7585 7586 cp = i_devid->did_id; 7587 7588 /* Fill in host id (big-endian byte ordering) */ 7589 hostid = stoi(&hostid_cp); 7590 *cp++ = hibyte(hiword(hostid)); 7591 *cp++ = lobyte(hiword(hostid)); 7592 *cp++ = hibyte(loword(hostid)); 7593 *cp++ = lobyte(loword(hostid)); 7594 7595 /* 7596 * Fill in timestamp (big-endian byte ordering) 7597 * 7598 * (Note that the format may have to be changed 7599 * before 2038 comes around, though it's arguably 7600 * unique enough as it is..) 7601 */ 7602 uniqtime32(×tamp32); 7603 ip = (int *)×tamp32; 7604 for (i = 0; 7605 i < sizeof (timestamp32) / sizeof (int); i++, ip++) { 7606 int val; 7607 val = *ip; 7608 *cp++ = hibyte(hiword(val)); 7609 *cp++ = lobyte(hiword(val)); 7610 *cp++ = hibyte(loword(val)); 7611 *cp++ = lobyte(loword(val)); 7612 } 7613 7614 /* fill in the generation number */ 7615 *cp++ = hibyte(gen); 7616 *cp++ = lobyte(gen); 7617 } else 7618 bcopy(id, i_devid->did_id, nbytes); 7619 7620 /* return device id */ 7621 *ret_devid = (ddi_devid_t)i_devid; 7622 return (DDI_SUCCESS); 7623 } 7624 7625 int 7626 ddi_devid_get(dev_info_t *dip, ddi_devid_t *ret_devid) 7627 { 7628 return (i_ddi_devi_get_devid(DDI_DEV_T_ANY, dip, ret_devid)); 7629 } 7630 7631 int 7632 i_ddi_devi_get_devid(dev_t dev, dev_info_t *dip, ddi_devid_t *ret_devid) 7633 { 7634 char *devidstr; 7635 7636 ASSERT(dev != DDI_DEV_T_NONE); 7637 7638 /* look up the property, devt specific first */ 7639 if (ddi_prop_lookup_string(dev, dip, DDI_PROP_DONTPASS, 7640 DEVID_PROP_NAME, &devidstr) != DDI_PROP_SUCCESS) { 7641 if ((dev == DDI_DEV_T_ANY) || 7642 (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 7643 DDI_PROP_DONTPASS, DEVID_PROP_NAME, &devidstr) != 7644 DDI_PROP_SUCCESS)) { 7645 return (DDI_FAILURE); 7646 } 7647 } 7648 7649 /* convert to binary form */ 7650 if (ddi_devid_str_decode(devidstr, ret_devid, NULL) == -1) { 7651 ddi_prop_free(devidstr); 7652 return (DDI_FAILURE); 7653 } 7654 ddi_prop_free(devidstr); 7655 return (DDI_SUCCESS); 7656 } 7657 7658 /* 7659 * Return a copy of the device id for dev_t 7660 */ 7661 int 7662 ddi_lyr_get_devid(dev_t dev, ddi_devid_t *ret_devid) 7663 { 7664 dev_info_t *dip; 7665 int rval; 7666 7667 /* get the dip */ 7668 if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 7669 return (DDI_FAILURE); 7670 7671 rval = i_ddi_devi_get_devid(dev, dip, ret_devid); 7672 7673 ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ 7674 return (rval); 7675 } 7676 7677 /* 7678 * Return a copy of the minor name for dev_t and spec_type 7679 */ 7680 int 7681 ddi_lyr_get_minor_name(dev_t dev, int spec_type, char **minor_name) 7682 { 7683 dev_info_t *dip; 7684 char *nm; 7685 size_t alloc_sz, sz; 7686 7687 if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 7688 return (DDI_FAILURE); 7689 7690 mutex_enter(&(DEVI(dip)->devi_lock)); 7691 7692 if ((nm = i_ddi_devtspectype_to_minorname(dip, 7693 dev, spec_type)) == NULL) { 7694 mutex_exit(&(DEVI(dip)->devi_lock)); 7695 ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ 7696 return (DDI_FAILURE); 7697 } 7698 7699 /* make a copy */ 7700 alloc_sz = strlen(nm) + 1; 7701 retry: 7702 /* drop lock to allocate memory */ 7703 mutex_exit(&(DEVI(dip)->devi_lock)); 7704 *minor_name = kmem_alloc(alloc_sz, KM_SLEEP); 7705 mutex_enter(&(DEVI(dip)->devi_lock)); 7706 7707 /* re-check things, since we dropped the lock */ 7708 if ((nm = i_ddi_devtspectype_to_minorname(dip, 7709 dev, spec_type)) == NULL) { 7710 mutex_exit(&(DEVI(dip)->devi_lock)); 7711 kmem_free(*minor_name, alloc_sz); 7712 *minor_name = NULL; 7713 ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ 7714 return (DDI_FAILURE); 7715 } 7716 7717 /* verify size is the same */ 7718 sz = strlen(nm) + 1; 7719 if (alloc_sz != sz) { 7720 kmem_free(*minor_name, alloc_sz); 7721 alloc_sz = sz; 7722 goto retry; 7723 } 7724 7725 /* sz == alloc_sz - make a copy */ 7726 (void) strcpy(*minor_name, nm); 7727 7728 mutex_exit(&(DEVI(dip)->devi_lock)); 7729 ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ 7730 return (DDI_SUCCESS); 7731 } 7732 7733 int 7734 ddi_lyr_devid_to_devlist( 7735 ddi_devid_t devid, 7736 char *minor_name, 7737 int *retndevs, 7738 dev_t **retdevs) 7739 { 7740 ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS); 7741 7742 if (e_devid_cache_to_devt_list(devid, minor_name, 7743 retndevs, retdevs) == DDI_SUCCESS) { 7744 ASSERT(*retndevs > 0); 7745 DDI_DEBUG_DEVID_DEVTS("ddi_lyr_devid_to_devlist", 7746 *retndevs, *retdevs); 7747 return (DDI_SUCCESS); 7748 } 7749 7750 if (e_ddi_devid_discovery(devid) == DDI_FAILURE) { 7751 return (DDI_FAILURE); 7752 } 7753 7754 if (e_devid_cache_to_devt_list(devid, minor_name, 7755 retndevs, retdevs) == DDI_SUCCESS) { 7756 ASSERT(*retndevs > 0); 7757 DDI_DEBUG_DEVID_DEVTS("ddi_lyr_devid_to_devlist", 7758 *retndevs, *retdevs); 7759 return (DDI_SUCCESS); 7760 } 7761 7762 return (DDI_FAILURE); 7763 } 7764 7765 void 7766 ddi_lyr_free_devlist(dev_t *devlist, int ndevs) 7767 { 7768 kmem_free(devlist, sizeof (dev_t) * ndevs); 7769 } 7770 7771 /* 7772 * Note: This will need to be fixed if we ever allow processes to 7773 * have more than one data model per exec. 7774 */ 7775 model_t 7776 ddi_mmap_get_model(void) 7777 { 7778 return (get_udatamodel()); 7779 } 7780 7781 model_t 7782 ddi_model_convert_from(model_t model) 7783 { 7784 return ((model & DDI_MODEL_MASK) & ~DDI_MODEL_NATIVE); 7785 } 7786 7787 /* 7788 * ddi interfaces managing storage and retrieval of eventcookies. 7789 */ 7790 7791 /* 7792 * Invoke bus nexus driver's implementation of the 7793 * (*bus_remove_eventcall)() interface to remove a registered 7794 * callback handler for "event". 7795 */ 7796 int 7797 ddi_remove_event_handler(ddi_callback_id_t id) 7798 { 7799 ndi_event_callbacks_t *cb = (ndi_event_callbacks_t *)id; 7800 dev_info_t *ddip; 7801 7802 ASSERT(cb); 7803 if (!cb) { 7804 return (DDI_FAILURE); 7805 } 7806 7807 ddip = NDI_EVENT_DDIP(cb->ndi_evtcb_cookie); 7808 return (ndi_busop_remove_eventcall(ddip, id)); 7809 } 7810 7811 /* 7812 * Invoke bus nexus driver's implementation of the 7813 * (*bus_add_eventcall)() interface to register a callback handler 7814 * for "event". 7815 */ 7816 int 7817 ddi_add_event_handler(dev_info_t *dip, ddi_eventcookie_t event, 7818 void (*handler)(dev_info_t *, ddi_eventcookie_t, void *, void *), 7819 void *arg, ddi_callback_id_t *id) 7820 { 7821 return (ndi_busop_add_eventcall(dip, dip, event, handler, arg, id)); 7822 } 7823 7824 7825 /* 7826 * Return a handle for event "name" by calling up the device tree 7827 * hierarchy via (*bus_get_eventcookie)() interface until claimed 7828 * by a bus nexus or top of dev_info tree is reached. 7829 */ 7830 int 7831 ddi_get_eventcookie(dev_info_t *dip, char *name, 7832 ddi_eventcookie_t *event_cookiep) 7833 { 7834 return (ndi_busop_get_eventcookie(dip, dip, 7835 name, event_cookiep)); 7836 } 7837 7838 /* 7839 * single thread access to dev_info node and set state 7840 */ 7841 void 7842 i_devi_enter(dev_info_t *dip, uint_t s_mask, uint_t w_mask, int has_lock) 7843 { 7844 if (!has_lock) 7845 mutex_enter(&(DEVI(dip)->devi_lock)); 7846 7847 ASSERT(mutex_owned(&(DEVI(dip)->devi_lock))); 7848 7849 /* 7850 * wait until state(s) have been changed 7851 */ 7852 while ((DEVI(dip)->devi_state & w_mask) != 0) { 7853 cv_wait(&(DEVI(dip)->devi_cv), &(DEVI(dip)->devi_lock)); 7854 } 7855 DEVI(dip)->devi_state |= s_mask; 7856 7857 if (!has_lock) 7858 mutex_exit(&(DEVI(dip)->devi_lock)); 7859 } 7860 7861 void 7862 i_devi_exit(dev_info_t *dip, uint_t c_mask, int has_lock) 7863 { 7864 if (!has_lock) 7865 mutex_enter(&(DEVI(dip)->devi_lock)); 7866 7867 ASSERT(mutex_owned(&(DEVI(dip)->devi_lock))); 7868 7869 /* 7870 * clear the state(s) and wakeup any threads waiting 7871 * for state change 7872 */ 7873 DEVI(dip)->devi_state &= ~c_mask; 7874 cv_broadcast(&(DEVI(dip)->devi_cv)); 7875 7876 if (!has_lock) 7877 mutex_exit(&(DEVI(dip)->devi_lock)); 7878 } 7879 7880 /* 7881 * This procedure is provided as the general callback function when 7882 * umem_lockmemory calls as_add_callback for long term memory locking. 7883 * When as_unmap, as_setprot, or as_free encounter segments which have 7884 * locked memory, this callback will be invoked. 7885 */ 7886 void 7887 umem_lock_undo(struct as *as, void *arg, uint_t event) 7888 { 7889 _NOTE(ARGUNUSED(as, event)) 7890 struct ddi_umem_cookie *cp = (struct ddi_umem_cookie *)arg; 7891 7892 /* 7893 * Call the cleanup function. Decrement the cookie reference 7894 * count, if it goes to zero, return the memory for the cookie. 7895 * The i_ddi_umem_unlock for this cookie may or may not have been 7896 * called already. It is the responsibility of the caller of 7897 * umem_lockmemory to handle the case of the cleanup routine 7898 * being called after a ddi_umem_unlock for the cookie 7899 * was called. 7900 */ 7901 7902 (*cp->callbacks.cbo_umem_lock_cleanup)((ddi_umem_cookie_t)cp); 7903 7904 /* remove the cookie if reference goes to zero */ 7905 if (atomic_add_long_nv((ulong_t *)(&(cp->cook_refcnt)), -1) == 0) { 7906 kmem_free(cp, sizeof (struct ddi_umem_cookie)); 7907 } 7908 } 7909 7910 /* 7911 * The following two Consolidation Private routines provide generic 7912 * interfaces to increase/decrease the amount of device-locked memory. 7913 * 7914 * To keep project_rele and project_hold consistent, i_ddi_decr_locked_memory() 7915 * must be called every time i_ddi_incr_locked_memory() is called. 7916 */ 7917 int 7918 /* ARGSUSED */ 7919 i_ddi_incr_locked_memory(proc_t *procp, rctl_qty_t inc) 7920 { 7921 ASSERT(procp != NULL); 7922 mutex_enter(&procp->p_lock); 7923 if (rctl_incr_locked_mem(procp, NULL, inc, 1)) { 7924 mutex_exit(&procp->p_lock); 7925 return (ENOMEM); 7926 } 7927 mutex_exit(&procp->p_lock); 7928 return (0); 7929 } 7930 7931 /* 7932 * To keep project_rele and project_hold consistent, i_ddi_incr_locked_memory() 7933 * must be called every time i_ddi_decr_locked_memory() is called. 7934 */ 7935 /* ARGSUSED */ 7936 void 7937 i_ddi_decr_locked_memory(proc_t *procp, rctl_qty_t dec) 7938 { 7939 ASSERT(procp != NULL); 7940 mutex_enter(&procp->p_lock); 7941 rctl_decr_locked_mem(procp, NULL, dec, 1); 7942 mutex_exit(&procp->p_lock); 7943 } 7944 7945 /* 7946 * This routine checks if the max-locked-memory resource ctl is 7947 * exceeded, if not increments it, grabs a hold on the project. 7948 * Returns 0 if successful otherwise returns error code 7949 */ 7950 static int 7951 umem_incr_devlockmem(struct ddi_umem_cookie *cookie) 7952 { 7953 proc_t *procp; 7954 int ret; 7955 7956 ASSERT(cookie); 7957 procp = cookie->procp; 7958 ASSERT(procp); 7959 7960 if ((ret = i_ddi_incr_locked_memory(procp, 7961 cookie->size)) != 0) { 7962 return (ret); 7963 } 7964 return (0); 7965 } 7966 7967 /* 7968 * Decrements the max-locked-memory resource ctl and releases 7969 * the hold on the project that was acquired during umem_incr_devlockmem 7970 */ 7971 static void 7972 umem_decr_devlockmem(struct ddi_umem_cookie *cookie) 7973 { 7974 proc_t *proc; 7975 7976 proc = (proc_t *)cookie->procp; 7977 if (!proc) 7978 return; 7979 7980 i_ddi_decr_locked_memory(proc, cookie->size); 7981 } 7982 7983 /* 7984 * A consolidation private function which is essentially equivalent to 7985 * ddi_umem_lock but with the addition of arguments ops_vector and procp. 7986 * A call to as_add_callback is done if DDI_UMEMLOCK_LONGTERM is set, and 7987 * the ops_vector is valid. 7988 * 7989 * Lock the virtual address range in the current process and create a 7990 * ddi_umem_cookie (of type UMEM_LOCKED). This can be used to pass to 7991 * ddi_umem_iosetup to create a buf or do devmap_umem_setup/remap to export 7992 * to user space. 7993 * 7994 * Note: The resource control accounting currently uses a full charge model 7995 * in other words attempts to lock the same/overlapping areas of memory 7996 * will deduct the full size of the buffer from the projects running 7997 * counter for the device locked memory. 7998 * 7999 * addr, size should be PAGESIZE aligned 8000 * 8001 * flags - DDI_UMEMLOCK_READ, DDI_UMEMLOCK_WRITE or both 8002 * identifies whether the locked memory will be read or written or both 8003 * DDI_UMEMLOCK_LONGTERM must be set when the locking will 8004 * be maintained for an indefinitely long period (essentially permanent), 8005 * rather than for what would be required for a typical I/O completion. 8006 * When DDI_UMEMLOCK_LONGTERM is set, umem_lockmemory will return EFAULT 8007 * if the memory pertains to a regular file which is mapped MAP_SHARED. 8008 * This is to prevent a deadlock if a file truncation is attempted after 8009 * after the locking is done. 8010 * 8011 * Returns 0 on success 8012 * EINVAL - for invalid parameters 8013 * EPERM, ENOMEM and other error codes returned by as_pagelock 8014 * ENOMEM - is returned if the current request to lock memory exceeds 8015 * *.max-locked-memory resource control value. 8016 * EFAULT - memory pertains to a regular file mapped shared and 8017 * and DDI_UMEMLOCK_LONGTERM flag is set 8018 * EAGAIN - could not start the ddi_umem_unlock list processing thread 8019 */ 8020 int 8021 umem_lockmemory(caddr_t addr, size_t len, int flags, ddi_umem_cookie_t *cookie, 8022 struct umem_callback_ops *ops_vector, 8023 proc_t *procp) 8024 { 8025 int error; 8026 struct ddi_umem_cookie *p; 8027 void (*driver_callback)() = NULL; 8028 struct as *as = procp->p_as; 8029 struct seg *seg; 8030 vnode_t *vp; 8031 8032 *cookie = NULL; /* in case of any error return */ 8033 8034 /* These are the only three valid flags */ 8035 if ((flags & ~(DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE | 8036 DDI_UMEMLOCK_LONGTERM)) != 0) 8037 return (EINVAL); 8038 8039 /* At least one (can be both) of the two access flags must be set */ 8040 if ((flags & (DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) == 0) 8041 return (EINVAL); 8042 8043 /* addr and len must be page-aligned */ 8044 if (((uintptr_t)addr & PAGEOFFSET) != 0) 8045 return (EINVAL); 8046 8047 if ((len & PAGEOFFSET) != 0) 8048 return (EINVAL); 8049 8050 /* 8051 * For longterm locking a driver callback must be specified; if 8052 * not longterm then a callback is optional. 8053 */ 8054 if (ops_vector != NULL) { 8055 if (ops_vector->cbo_umem_callback_version != 8056 UMEM_CALLBACK_VERSION) 8057 return (EINVAL); 8058 else 8059 driver_callback = ops_vector->cbo_umem_lock_cleanup; 8060 } 8061 if ((driver_callback == NULL) && (flags & DDI_UMEMLOCK_LONGTERM)) 8062 return (EINVAL); 8063 8064 /* 8065 * Call i_ddi_umem_unlock_thread_start if necessary. It will 8066 * be called on first ddi_umem_lock or umem_lockmemory call. 8067 */ 8068 if (ddi_umem_unlock_thread == NULL) 8069 i_ddi_umem_unlock_thread_start(); 8070 8071 /* Allocate memory for the cookie */ 8072 p = kmem_zalloc(sizeof (struct ddi_umem_cookie), KM_SLEEP); 8073 8074 /* Convert the flags to seg_rw type */ 8075 if (flags & DDI_UMEMLOCK_WRITE) { 8076 p->s_flags = S_WRITE; 8077 } else { 8078 p->s_flags = S_READ; 8079 } 8080 8081 /* Store procp in cookie for later iosetup/unlock */ 8082 p->procp = (void *)procp; 8083 8084 /* 8085 * Store the struct as pointer in cookie for later use by 8086 * ddi_umem_unlock. The proc->p_as will be stale if ddi_umem_unlock 8087 * is called after relvm is called. 8088 */ 8089 p->asp = as; 8090 8091 /* 8092 * The size field is needed for lockmem accounting. 8093 */ 8094 p->size = len; 8095 8096 if (umem_incr_devlockmem(p) != 0) { 8097 /* 8098 * The requested memory cannot be locked 8099 */ 8100 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8101 *cookie = (ddi_umem_cookie_t)NULL; 8102 return (ENOMEM); 8103 } 8104 8105 /* Lock the pages corresponding to addr, len in memory */ 8106 error = as_pagelock(as, &(p->pparray), addr, len, p->s_flags); 8107 if (error != 0) { 8108 umem_decr_devlockmem(p); 8109 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8110 *cookie = (ddi_umem_cookie_t)NULL; 8111 return (error); 8112 } 8113 8114 /* 8115 * For longterm locking the addr must pertain to a seg_vn segment or 8116 * or a seg_spt segment. 8117 * If the segment pertains to a regular file, it cannot be 8118 * mapped MAP_SHARED. 8119 * This is to prevent a deadlock if a file truncation is attempted 8120 * after the locking is done. 8121 * Doing this after as_pagelock guarantees persistence of the as; if 8122 * an unacceptable segment is found, the cleanup includes calling 8123 * as_pageunlock before returning EFAULT. 8124 */ 8125 if (flags & DDI_UMEMLOCK_LONGTERM) { 8126 extern struct seg_ops segspt_shmops; 8127 AS_LOCK_ENTER(as, &as->a_lock, RW_READER); 8128 for (seg = as_segat(as, addr); ; seg = AS_SEGNEXT(as, seg)) { 8129 if (seg == NULL || seg->s_base > addr + len) 8130 break; 8131 if (((seg->s_ops != &segvn_ops) && 8132 (seg->s_ops != &segspt_shmops)) || 8133 ((SEGOP_GETVP(seg, addr, &vp) == 0 && 8134 vp != NULL && vp->v_type == VREG) && 8135 (SEGOP_GETTYPE(seg, addr) & MAP_SHARED))) { 8136 as_pageunlock(as, p->pparray, 8137 addr, len, p->s_flags); 8138 AS_LOCK_EXIT(as, &as->a_lock); 8139 umem_decr_devlockmem(p); 8140 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8141 *cookie = (ddi_umem_cookie_t)NULL; 8142 return (EFAULT); 8143 } 8144 } 8145 AS_LOCK_EXIT(as, &as->a_lock); 8146 } 8147 8148 8149 /* Initialize the fields in the ddi_umem_cookie */ 8150 p->cvaddr = addr; 8151 p->type = UMEM_LOCKED; 8152 if (driver_callback != NULL) { 8153 /* i_ddi_umem_unlock and umem_lock_undo may need the cookie */ 8154 p->cook_refcnt = 2; 8155 p->callbacks = *ops_vector; 8156 } else { 8157 /* only i_ddi_umme_unlock needs the cookie */ 8158 p->cook_refcnt = 1; 8159 } 8160 8161 *cookie = (ddi_umem_cookie_t)p; 8162 8163 /* 8164 * If a driver callback was specified, add an entry to the 8165 * as struct callback list. The as_pagelock above guarantees 8166 * the persistence of as. 8167 */ 8168 if (driver_callback) { 8169 error = as_add_callback(as, umem_lock_undo, p, AS_ALL_EVENT, 8170 addr, len, KM_SLEEP); 8171 if (error != 0) { 8172 as_pageunlock(as, p->pparray, 8173 addr, len, p->s_flags); 8174 umem_decr_devlockmem(p); 8175 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8176 *cookie = (ddi_umem_cookie_t)NULL; 8177 } 8178 } 8179 return (error); 8180 } 8181 8182 /* 8183 * Unlock the pages locked by ddi_umem_lock or umem_lockmemory and free 8184 * the cookie. Called from i_ddi_umem_unlock_thread. 8185 */ 8186 8187 static void 8188 i_ddi_umem_unlock(struct ddi_umem_cookie *p) 8189 { 8190 uint_t rc; 8191 8192 /* 8193 * There is no way to determine whether a callback to 8194 * umem_lock_undo was registered via as_add_callback. 8195 * (i.e. umem_lockmemory was called with DDI_MEMLOCK_LONGTERM and 8196 * a valid callback function structure.) as_delete_callback 8197 * is called to delete a possible registered callback. If the 8198 * return from as_delete_callbacks is AS_CALLBACK_DELETED, it 8199 * indicates that there was a callback registered, and that is was 8200 * successfully deleted. Thus, the cookie reference count 8201 * will never be decremented by umem_lock_undo. Just return the 8202 * memory for the cookie, since both users of the cookie are done. 8203 * A return of AS_CALLBACK_NOTFOUND indicates a callback was 8204 * never registered. A return of AS_CALLBACK_DELETE_DEFERRED 8205 * indicates that callback processing is taking place and, and 8206 * umem_lock_undo is, or will be, executing, and thus decrementing 8207 * the cookie reference count when it is complete. 8208 * 8209 * This needs to be done before as_pageunlock so that the 8210 * persistence of as is guaranteed because of the locked pages. 8211 * 8212 */ 8213 rc = as_delete_callback(p->asp, p); 8214 8215 8216 /* 8217 * The proc->p_as will be stale if i_ddi_umem_unlock is called 8218 * after relvm is called so use p->asp. 8219 */ 8220 as_pageunlock(p->asp, p->pparray, p->cvaddr, p->size, p->s_flags); 8221 8222 /* 8223 * Now that we have unlocked the memory decrement the 8224 * *.max-locked-memory rctl 8225 */ 8226 umem_decr_devlockmem(p); 8227 8228 if (rc == AS_CALLBACK_DELETED) { 8229 /* umem_lock_undo will not happen, return the cookie memory */ 8230 ASSERT(p->cook_refcnt == 2); 8231 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8232 } else { 8233 /* 8234 * umem_undo_lock may happen if as_delete_callback returned 8235 * AS_CALLBACK_DELETE_DEFERRED. In that case, decrement the 8236 * reference count, atomically, and return the cookie 8237 * memory if the reference count goes to zero. The only 8238 * other value for rc is AS_CALLBACK_NOTFOUND. In that 8239 * case, just return the cookie memory. 8240 */ 8241 if ((rc != AS_CALLBACK_DELETE_DEFERRED) || 8242 (atomic_add_long_nv((ulong_t *)(&(p->cook_refcnt)), -1) 8243 == 0)) { 8244 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8245 } 8246 } 8247 } 8248 8249 /* 8250 * i_ddi_umem_unlock_thread - deferred ddi_umem_unlock list handler. 8251 * 8252 * Call i_ddi_umem_unlock for entries in the ddi_umem_unlock list 8253 * until it is empty. Then, wait for more to be added. This thread is awoken 8254 * via calls to ddi_umem_unlock. 8255 */ 8256 8257 static void 8258 i_ddi_umem_unlock_thread(void) 8259 { 8260 struct ddi_umem_cookie *ret_cookie; 8261 callb_cpr_t cprinfo; 8262 8263 /* process the ddi_umem_unlock list */ 8264 CALLB_CPR_INIT(&cprinfo, &ddi_umem_unlock_mutex, 8265 callb_generic_cpr, "unlock_thread"); 8266 for (;;) { 8267 mutex_enter(&ddi_umem_unlock_mutex); 8268 if (ddi_umem_unlock_head != NULL) { /* list not empty */ 8269 ret_cookie = ddi_umem_unlock_head; 8270 /* take if off the list */ 8271 if ((ddi_umem_unlock_head = 8272 ddi_umem_unlock_head->unl_forw) == NULL) { 8273 ddi_umem_unlock_tail = NULL; 8274 } 8275 mutex_exit(&ddi_umem_unlock_mutex); 8276 /* unlock the pages in this cookie */ 8277 (void) i_ddi_umem_unlock(ret_cookie); 8278 } else { /* list is empty, wait for next ddi_umem_unlock */ 8279 CALLB_CPR_SAFE_BEGIN(&cprinfo); 8280 cv_wait(&ddi_umem_unlock_cv, &ddi_umem_unlock_mutex); 8281 CALLB_CPR_SAFE_END(&cprinfo, &ddi_umem_unlock_mutex); 8282 mutex_exit(&ddi_umem_unlock_mutex); 8283 } 8284 } 8285 /* ddi_umem_unlock_thread does not exit */ 8286 /* NOTREACHED */ 8287 } 8288 8289 /* 8290 * Start the thread that will process the ddi_umem_unlock list if it is 8291 * not already started (i_ddi_umem_unlock_thread). 8292 */ 8293 static void 8294 i_ddi_umem_unlock_thread_start(void) 8295 { 8296 mutex_enter(&ddi_umem_unlock_mutex); 8297 if (ddi_umem_unlock_thread == NULL) { 8298 ddi_umem_unlock_thread = thread_create(NULL, 0, 8299 i_ddi_umem_unlock_thread, NULL, 0, &p0, 8300 TS_RUN, minclsyspri); 8301 } 8302 mutex_exit(&ddi_umem_unlock_mutex); 8303 } 8304 8305 /* 8306 * Lock the virtual address range in the current process and create a 8307 * ddi_umem_cookie (of type UMEM_LOCKED). This can be used to pass to 8308 * ddi_umem_iosetup to create a buf or do devmap_umem_setup/remap to export 8309 * to user space. 8310 * 8311 * Note: The resource control accounting currently uses a full charge model 8312 * in other words attempts to lock the same/overlapping areas of memory 8313 * will deduct the full size of the buffer from the projects running 8314 * counter for the device locked memory. This applies to umem_lockmemory too. 8315 * 8316 * addr, size should be PAGESIZE aligned 8317 * flags - DDI_UMEMLOCK_READ, DDI_UMEMLOCK_WRITE or both 8318 * identifies whether the locked memory will be read or written or both 8319 * 8320 * Returns 0 on success 8321 * EINVAL - for invalid parameters 8322 * EPERM, ENOMEM and other error codes returned by as_pagelock 8323 * ENOMEM - is returned if the current request to lock memory exceeds 8324 * *.max-locked-memory resource control value. 8325 * EAGAIN - could not start the ddi_umem_unlock list processing thread 8326 */ 8327 int 8328 ddi_umem_lock(caddr_t addr, size_t len, int flags, ddi_umem_cookie_t *cookie) 8329 { 8330 int error; 8331 struct ddi_umem_cookie *p; 8332 8333 *cookie = NULL; /* in case of any error return */ 8334 8335 /* These are the only two valid flags */ 8336 if ((flags & ~(DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) != 0) { 8337 return (EINVAL); 8338 } 8339 8340 /* At least one of the two flags (or both) must be set */ 8341 if ((flags & (DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) == 0) { 8342 return (EINVAL); 8343 } 8344 8345 /* addr and len must be page-aligned */ 8346 if (((uintptr_t)addr & PAGEOFFSET) != 0) { 8347 return (EINVAL); 8348 } 8349 8350 if ((len & PAGEOFFSET) != 0) { 8351 return (EINVAL); 8352 } 8353 8354 /* 8355 * Call i_ddi_umem_unlock_thread_start if necessary. It will 8356 * be called on first ddi_umem_lock or umem_lockmemory call. 8357 */ 8358 if (ddi_umem_unlock_thread == NULL) 8359 i_ddi_umem_unlock_thread_start(); 8360 8361 /* Allocate memory for the cookie */ 8362 p = kmem_zalloc(sizeof (struct ddi_umem_cookie), KM_SLEEP); 8363 8364 /* Convert the flags to seg_rw type */ 8365 if (flags & DDI_UMEMLOCK_WRITE) { 8366 p->s_flags = S_WRITE; 8367 } else { 8368 p->s_flags = S_READ; 8369 } 8370 8371 /* Store curproc in cookie for later iosetup/unlock */ 8372 p->procp = (void *)curproc; 8373 8374 /* 8375 * Store the struct as pointer in cookie for later use by 8376 * ddi_umem_unlock. The proc->p_as will be stale if ddi_umem_unlock 8377 * is called after relvm is called. 8378 */ 8379 p->asp = curproc->p_as; 8380 /* 8381 * The size field is needed for lockmem accounting. 8382 */ 8383 p->size = len; 8384 8385 if (umem_incr_devlockmem(p) != 0) { 8386 /* 8387 * The requested memory cannot be locked 8388 */ 8389 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8390 *cookie = (ddi_umem_cookie_t)NULL; 8391 return (ENOMEM); 8392 } 8393 8394 /* Lock the pages corresponding to addr, len in memory */ 8395 error = as_pagelock(((proc_t *)p->procp)->p_as, &(p->pparray), 8396 addr, len, p->s_flags); 8397 if (error != 0) { 8398 umem_decr_devlockmem(p); 8399 kmem_free(p, sizeof (struct ddi_umem_cookie)); 8400 *cookie = (ddi_umem_cookie_t)NULL; 8401 return (error); 8402 } 8403 8404 /* Initialize the fields in the ddi_umem_cookie */ 8405 p->cvaddr = addr; 8406 p->type = UMEM_LOCKED; 8407 p->cook_refcnt = 1; 8408 8409 *cookie = (ddi_umem_cookie_t)p; 8410 return (error); 8411 } 8412 8413 /* 8414 * Add the cookie to the ddi_umem_unlock list. Pages will be 8415 * unlocked by i_ddi_umem_unlock_thread. 8416 */ 8417 8418 void 8419 ddi_umem_unlock(ddi_umem_cookie_t cookie) 8420 { 8421 struct ddi_umem_cookie *p = (struct ddi_umem_cookie *)cookie; 8422 8423 ASSERT(p->type == UMEM_LOCKED); 8424 ASSERT(CPU_ON_INTR(CPU) == 0); /* cannot be high level */ 8425 ASSERT(ddi_umem_unlock_thread != NULL); 8426 8427 p->unl_forw = (struct ddi_umem_cookie *)NULL; /* end of list */ 8428 /* 8429 * Queue the unlock request and notify i_ddi_umem_unlock thread 8430 * if it's called in the interrupt context. Otherwise, unlock pages 8431 * immediately. 8432 */ 8433 if (servicing_interrupt()) { 8434 /* queue the unlock request and notify the thread */ 8435 mutex_enter(&ddi_umem_unlock_mutex); 8436 if (ddi_umem_unlock_head == NULL) { 8437 ddi_umem_unlock_head = ddi_umem_unlock_tail = p; 8438 cv_broadcast(&ddi_umem_unlock_cv); 8439 } else { 8440 ddi_umem_unlock_tail->unl_forw = p; 8441 ddi_umem_unlock_tail = p; 8442 } 8443 mutex_exit(&ddi_umem_unlock_mutex); 8444 } else { 8445 /* unlock the pages right away */ 8446 (void) i_ddi_umem_unlock(p); 8447 } 8448 } 8449 8450 /* 8451 * Create a buf structure from a ddi_umem_cookie 8452 * cookie - is a ddi_umem_cookie for from ddi_umem_lock and ddi_umem_alloc 8453 * (only UMEM_LOCKED & KMEM_NON_PAGEABLE types supported) 8454 * off, len - identifies the portion of the memory represented by the cookie 8455 * that the buf points to. 8456 * NOTE: off, len need to follow the alignment/size restrictions of the 8457 * device (dev) that this buf will be passed to. Some devices 8458 * will accept unrestricted alignment/size, whereas others (such as 8459 * st) require some block-size alignment/size. It is the caller's 8460 * responsibility to ensure that the alignment/size restrictions 8461 * are met (we cannot assert as we do not know the restrictions) 8462 * 8463 * direction - is one of B_READ or B_WRITE and needs to be compatible with 8464 * the flags used in ddi_umem_lock 8465 * 8466 * The following three arguments are used to initialize fields in the 8467 * buf structure and are uninterpreted by this routine. 8468 * 8469 * dev 8470 * blkno 8471 * iodone 8472 * 8473 * sleepflag - is one of DDI_UMEM_SLEEP or DDI_UMEM_NOSLEEP 8474 * 8475 * Returns a buf structure pointer on success (to be freed by freerbuf) 8476 * NULL on any parameter error or memory alloc failure 8477 * 8478 */ 8479 struct buf * 8480 ddi_umem_iosetup(ddi_umem_cookie_t cookie, off_t off, size_t len, 8481 int direction, dev_t dev, daddr_t blkno, 8482 int (*iodone)(struct buf *), int sleepflag) 8483 { 8484 struct ddi_umem_cookie *p = (struct ddi_umem_cookie *)cookie; 8485 struct buf *bp; 8486 8487 /* 8488 * check for valid cookie offset, len 8489 */ 8490 if ((off + len) > p->size) { 8491 return (NULL); 8492 } 8493 8494 if (len > p->size) { 8495 return (NULL); 8496 } 8497 8498 /* direction has to be one of B_READ or B_WRITE */ 8499 if ((direction != B_READ) && (direction != B_WRITE)) { 8500 return (NULL); 8501 } 8502 8503 /* These are the only two valid sleepflags */ 8504 if ((sleepflag != DDI_UMEM_SLEEP) && (sleepflag != DDI_UMEM_NOSLEEP)) { 8505 return (NULL); 8506 } 8507 8508 /* 8509 * Only cookies of type UMEM_LOCKED and KMEM_NON_PAGEABLE are supported 8510 */ 8511 if ((p->type != UMEM_LOCKED) && (p->type != KMEM_NON_PAGEABLE)) { 8512 return (NULL); 8513 } 8514 8515 /* If type is KMEM_NON_PAGEABLE procp is NULL */ 8516 ASSERT((p->type == KMEM_NON_PAGEABLE) ? 8517 (p->procp == NULL) : (p->procp != NULL)); 8518 8519 bp = kmem_alloc(sizeof (struct buf), sleepflag); 8520 if (bp == NULL) { 8521 return (NULL); 8522 } 8523 bioinit(bp); 8524 8525 bp->b_flags = B_BUSY | B_PHYS | direction; 8526 bp->b_edev = dev; 8527 bp->b_lblkno = blkno; 8528 bp->b_iodone = iodone; 8529 bp->b_bcount = len; 8530 bp->b_proc = (proc_t *)p->procp; 8531 ASSERT(((uintptr_t)(p->cvaddr) & PAGEOFFSET) == 0); 8532 bp->b_un.b_addr = (caddr_t)((uintptr_t)(p->cvaddr) + off); 8533 if (p->pparray != NULL) { 8534 bp->b_flags |= B_SHADOW; 8535 ASSERT(((uintptr_t)(p->cvaddr) & PAGEOFFSET) == 0); 8536 bp->b_shadow = p->pparray + btop(off); 8537 } 8538 return (bp); 8539 } 8540 8541 /* 8542 * Fault-handling and related routines 8543 */ 8544 8545 ddi_devstate_t 8546 ddi_get_devstate(dev_info_t *dip) 8547 { 8548 if (DEVI_IS_DEVICE_OFFLINE(dip)) 8549 return (DDI_DEVSTATE_OFFLINE); 8550 else if (DEVI_IS_DEVICE_DOWN(dip) || DEVI_IS_BUS_DOWN(dip)) 8551 return (DDI_DEVSTATE_DOWN); 8552 else if (DEVI_IS_BUS_QUIESCED(dip)) 8553 return (DDI_DEVSTATE_QUIESCED); 8554 else if (DEVI_IS_DEVICE_DEGRADED(dip)) 8555 return (DDI_DEVSTATE_DEGRADED); 8556 else 8557 return (DDI_DEVSTATE_UP); 8558 } 8559 8560 void 8561 ddi_dev_report_fault(dev_info_t *dip, ddi_fault_impact_t impact, 8562 ddi_fault_location_t location, const char *message) 8563 { 8564 struct ddi_fault_event_data fd; 8565 ddi_eventcookie_t ec; 8566 8567 /* 8568 * Assemble all the information into a fault-event-data structure 8569 */ 8570 fd.f_dip = dip; 8571 fd.f_impact = impact; 8572 fd.f_location = location; 8573 fd.f_message = message; 8574 fd.f_oldstate = ddi_get_devstate(dip); 8575 8576 /* 8577 * Get eventcookie from defining parent. 8578 */ 8579 if (ddi_get_eventcookie(dip, DDI_DEVI_FAULT_EVENT, &ec) != 8580 DDI_SUCCESS) 8581 return; 8582 8583 (void) ndi_post_event(dip, dip, ec, &fd); 8584 } 8585 8586 char * 8587 i_ddi_devi_class(dev_info_t *dip) 8588 { 8589 return (DEVI(dip)->devi_device_class); 8590 } 8591 8592 int 8593 i_ddi_set_devi_class(dev_info_t *dip, char *devi_class, int flag) 8594 { 8595 struct dev_info *devi = DEVI(dip); 8596 8597 mutex_enter(&devi->devi_lock); 8598 8599 if (devi->devi_device_class) 8600 kmem_free(devi->devi_device_class, 8601 strlen(devi->devi_device_class) + 1); 8602 8603 if ((devi->devi_device_class = i_ddi_strdup(devi_class, flag)) 8604 != NULL) { 8605 mutex_exit(&devi->devi_lock); 8606 return (DDI_SUCCESS); 8607 } 8608 8609 mutex_exit(&devi->devi_lock); 8610 8611 return (DDI_FAILURE); 8612 } 8613 8614 8615 /* 8616 * Task Queues DDI interfaces. 8617 */ 8618 8619 /* ARGSUSED */ 8620 ddi_taskq_t * 8621 ddi_taskq_create(dev_info_t *dip, const char *name, int nthreads, 8622 pri_t pri, uint_t cflags) 8623 { 8624 char full_name[TASKQ_NAMELEN]; 8625 const char *tq_name; 8626 int nodeid = 0; 8627 8628 if (dip == NULL) 8629 tq_name = name; 8630 else { 8631 nodeid = ddi_get_instance(dip); 8632 8633 if (name == NULL) 8634 name = "tq"; 8635 8636 (void) snprintf(full_name, sizeof (full_name), "%s_%s", 8637 ddi_driver_name(dip), name); 8638 8639 tq_name = full_name; 8640 } 8641 8642 return ((ddi_taskq_t *)taskq_create_instance(tq_name, nodeid, nthreads, 8643 pri == TASKQ_DEFAULTPRI ? minclsyspri : pri, 8644 nthreads, INT_MAX, TASKQ_PREPOPULATE)); 8645 } 8646 8647 void 8648 ddi_taskq_destroy(ddi_taskq_t *tq) 8649 { 8650 taskq_destroy((taskq_t *)tq); 8651 } 8652 8653 int 8654 ddi_taskq_dispatch(ddi_taskq_t *tq, void (* func)(void *), 8655 void *arg, uint_t dflags) 8656 { 8657 taskqid_t id = taskq_dispatch((taskq_t *)tq, func, arg, 8658 dflags == DDI_SLEEP ? TQ_SLEEP : TQ_NOSLEEP); 8659 8660 return (id != 0 ? DDI_SUCCESS : DDI_FAILURE); 8661 } 8662 8663 void 8664 ddi_taskq_wait(ddi_taskq_t *tq) 8665 { 8666 taskq_wait((taskq_t *)tq); 8667 } 8668 8669 void 8670 ddi_taskq_suspend(ddi_taskq_t *tq) 8671 { 8672 taskq_suspend((taskq_t *)tq); 8673 } 8674 8675 boolean_t 8676 ddi_taskq_suspended(ddi_taskq_t *tq) 8677 { 8678 return (taskq_suspended((taskq_t *)tq)); 8679 } 8680 8681 void 8682 ddi_taskq_resume(ddi_taskq_t *tq) 8683 { 8684 taskq_resume((taskq_t *)tq); 8685 } 8686 8687 int 8688 ddi_parse( 8689 const char *ifname, 8690 char *alnum, 8691 uint_t *nump) 8692 { 8693 const char *p; 8694 int l; 8695 ulong_t num; 8696 boolean_t nonum = B_TRUE; 8697 char c; 8698 8699 l = strlen(ifname); 8700 for (p = ifname + l; p != ifname; l--) { 8701 c = *--p; 8702 if (!isdigit(c)) { 8703 (void) strlcpy(alnum, ifname, l + 1); 8704 if (ddi_strtoul(p + 1, NULL, 10, &num) != 0) 8705 return (DDI_FAILURE); 8706 break; 8707 } 8708 nonum = B_FALSE; 8709 } 8710 if (l == 0 || nonum) 8711 return (DDI_FAILURE); 8712 8713 *nump = num; 8714 return (DDI_SUCCESS); 8715 } 8716