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