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