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