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