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