1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/note.h> 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/buf.h> 32 #include <sys/uio.h> 33 #include <sys/cred.h> 34 #include <sys/poll.h> 35 #include <sys/mman.h> 36 #include <sys/kmem.h> 37 #include <sys/model.h> 38 #include <sys/file.h> 39 #include <sys/proc.h> 40 #include <sys/open.h> 41 #include <sys/user.h> 42 #include <sys/t_lock.h> 43 #include <sys/vm.h> 44 #include <sys/stat.h> 45 #include <vm/hat.h> 46 #include <vm/seg.h> 47 #include <vm/seg_vn.h> 48 #include <vm/seg_dev.h> 49 #include <vm/as.h> 50 #include <sys/cmn_err.h> 51 #include <sys/cpuvar.h> 52 #include <sys/debug.h> 53 #include <sys/autoconf.h> 54 #include <sys/sunddi.h> 55 #include <sys/esunddi.h> 56 #include <sys/sunndi.h> 57 #include <sys/kstat.h> 58 #include <sys/conf.h> 59 #include <sys/ddi_impldefs.h> /* include implementation structure defs */ 60 #include <sys/ndi_impldefs.h> /* include prototypes */ 61 #include <sys/ddi_timer.h> 62 #include <sys/hwconf.h> 63 #include <sys/pathname.h> 64 #include <sys/modctl.h> 65 #include <sys/epm.h> 66 #include <sys/devctl.h> 67 #include <sys/callb.h> 68 #include <sys/cladm.h> 69 #include <sys/sysevent.h> 70 #include <sys/dacf_impl.h> 71 #include <sys/ddidevmap.h> 72 #include <sys/bootconf.h> 73 #include <sys/disp.h> 74 #include <sys/atomic.h> 75 #include <sys/promif.h> 76 #include <sys/instance.h> 77 #include <sys/sysevent/eventdefs.h> 78 #include <sys/task.h> 79 #include <sys/project.h> 80 #include <sys/taskq.h> 81 #include <sys/devpolicy.h> 82 #include <sys/ctype.h> 83 #include <net/if.h> 84 #include <sys/rctl.h> 85 #include <sys/zone.h> 86 87 extern pri_t minclsyspri; 88 89 extern rctl_hndl_t rc_project_locked_mem; 90 extern rctl_hndl_t rc_zone_locked_mem; 91 92 #ifdef DEBUG 93 static int sunddi_debug = 0; 94 #endif /* DEBUG */ 95 96 /* ddi_umem_unlock miscellaneous */ 97 98 static void i_ddi_umem_unlock_thread_start(void); 99 100 static kmutex_t ddi_umem_unlock_mutex; /* unlock list mutex */ 101 static kcondvar_t ddi_umem_unlock_cv; /* unlock list block/unblock */ 102 static kthread_t *ddi_umem_unlock_thread; 103 /* 104 * The ddi_umem_unlock FIFO list. NULL head pointer indicates empty list. 105 */ 106 static struct ddi_umem_cookie *ddi_umem_unlock_head = NULL; 107 static struct ddi_umem_cookie *ddi_umem_unlock_tail = NULL; 108 109 110 /* 111 * DDI(Sun) Function and flag definitions: 112 */ 113 114 #if defined(__x86) 115 /* 116 * Used to indicate which entries were chosen from a range. 117 */ 118 char *chosen_reg = "chosen-reg"; 119 #endif 120 121 /* 122 * Function used to ring system console bell 123 */ 124 void (*ddi_console_bell_func)(clock_t duration); 125 126 /* 127 * Creating register mappings and handling interrupts: 128 */ 129 130 /* 131 * Generic ddi_map: Call parent to fulfill request... 132 */ 133 134 int 135 ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset, 136 off_t len, caddr_t *addrp) 137 { 138 dev_info_t *pdip; 139 140 ASSERT(dp); 141 pdip = (dev_info_t *)DEVI(dp)->devi_parent; 142 return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip, 143 dp, mp, offset, len, addrp)); 144 } 145 146 /* 147 * ddi_apply_range: (Called by nexi only.) 148 * Apply ranges in parent node dp, to child regspec rp... 149 */ 150 151 int 152 ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp) 153 { 154 return (i_ddi_apply_range(dp, rdip, rp)); 155 } 156 157 int 158 ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 159 off_t len) 160 { 161 ddi_map_req_t mr; 162 #if defined(__x86) 163 struct { 164 int bus; 165 int addr; 166 int size; 167 } reg, *reglist; 168 uint_t length; 169 int rc; 170 171 /* 172 * get the 'registers' or the 'reg' property. 173 * We look up the reg property as an array of 174 * int's. 175 */ 176 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 177 DDI_PROP_DONTPASS, "registers", (int **)®list, &length); 178 if (rc != DDI_PROP_SUCCESS) 179 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 180 DDI_PROP_DONTPASS, "reg", (int **)®list, &length); 181 if (rc == DDI_PROP_SUCCESS) { 182 /* 183 * point to the required entry. 184 */ 185 reg = reglist[rnumber]; 186 reg.addr += offset; 187 if (len != 0) 188 reg.size = len; 189 /* 190 * make a new property containing ONLY the required tuple. 191 */ 192 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 193 chosen_reg, (int *)®, (sizeof (reg)/sizeof (int))) 194 != DDI_PROP_SUCCESS) { 195 cmn_err(CE_WARN, "%s%d: cannot create '%s' " 196 "property", DEVI(dip)->devi_name, 197 DEVI(dip)->devi_instance, chosen_reg); 198 } 199 /* 200 * free the memory allocated by 201 * ddi_prop_lookup_int_array (). 202 */ 203 ddi_prop_free((void *)reglist); 204 } 205 #endif 206 mr.map_op = DDI_MO_MAP_LOCKED; 207 mr.map_type = DDI_MT_RNUMBER; 208 mr.map_obj.rnumber = rnumber; 209 mr.map_prot = PROT_READ | PROT_WRITE; 210 mr.map_flags = DDI_MF_KERNEL_MAPPING; 211 mr.map_handlep = NULL; 212 mr.map_vers = DDI_MAP_VERSION; 213 214 /* 215 * Call my parent to map in my regs. 216 */ 217 218 return (ddi_map(dip, &mr, offset, len, kaddrp)); 219 } 220 221 void 222 ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 223 off_t len) 224 { 225 ddi_map_req_t mr; 226 227 mr.map_op = DDI_MO_UNMAP; 228 mr.map_type = DDI_MT_RNUMBER; 229 mr.map_flags = DDI_MF_KERNEL_MAPPING; 230 mr.map_prot = PROT_READ | PROT_WRITE; /* who cares? */ 231 mr.map_obj.rnumber = rnumber; 232 mr.map_handlep = NULL; 233 mr.map_vers = DDI_MAP_VERSION; 234 235 /* 236 * Call my parent to unmap my regs. 237 */ 238 239 (void) ddi_map(dip, &mr, offset, len, kaddrp); 240 *kaddrp = (caddr_t)0; 241 #if defined(__x86) 242 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg); 243 #endif 244 } 245 246 int 247 ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 248 off_t offset, off_t len, caddr_t *vaddrp) 249 { 250 return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp)); 251 } 252 253 /* 254 * nullbusmap: The/DDI default bus_map entry point for nexi 255 * not conforming to the reg/range paradigm (i.e. scsi, etc.) 256 * with no HAT/MMU layer to be programmed at this level. 257 * 258 * If the call is to map by rnumber, return an error, 259 * otherwise pass anything else up the tree to my parent. 260 */ 261 int 262 nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 263 off_t offset, off_t len, caddr_t *vaddrp) 264 { 265 _NOTE(ARGUNUSED(rdip)) 266 if (mp->map_type == DDI_MT_RNUMBER) 267 return (DDI_ME_UNSUPPORTED); 268 269 return (ddi_map(dip, mp, offset, len, vaddrp)); 270 } 271 272 /* 273 * ddi_rnumber_to_regspec: Not for use by leaf drivers. 274 * Only for use by nexi using the reg/range paradigm. 275 */ 276 struct regspec * 277 ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber) 278 { 279 return (i_ddi_rnumber_to_regspec(dip, rnumber)); 280 } 281 282 283 /* 284 * Note that we allow the dip to be nil because we may be called 285 * prior even to the instantiation of the devinfo tree itself - all 286 * regular leaf and nexus drivers should always use a non-nil dip! 287 * 288 * We treat peek in a somewhat cavalier fashion .. assuming that we'll 289 * simply get a synchronous fault as soon as we touch a missing address. 290 * 291 * Poke is rather more carefully handled because we might poke to a write 292 * buffer, "succeed", then only find some time later that we got an 293 * asynchronous fault that indicated that the address we were writing to 294 * was not really backed by hardware. 295 */ 296 297 static int 298 i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size, 299 void *addr, void *value_p) 300 { 301 union { 302 uint64_t u64; 303 uint32_t u32; 304 uint16_t u16; 305 uint8_t u8; 306 } peekpoke_value; 307 308 peekpoke_ctlops_t peekpoke_args; 309 uint64_t dummy_result; 310 int rval; 311 312 /* Note: size is assumed to be correct; it is not checked. */ 313 peekpoke_args.size = size; 314 peekpoke_args.dev_addr = (uintptr_t)addr; 315 peekpoke_args.handle = NULL; 316 peekpoke_args.repcount = 1; 317 peekpoke_args.flags = 0; 318 319 if (cmd == DDI_CTLOPS_POKE) { 320 switch (size) { 321 case sizeof (uint8_t): 322 peekpoke_value.u8 = *(uint8_t *)value_p; 323 break; 324 case sizeof (uint16_t): 325 peekpoke_value.u16 = *(uint16_t *)value_p; 326 break; 327 case sizeof (uint32_t): 328 peekpoke_value.u32 = *(uint32_t *)value_p; 329 break; 330 case sizeof (uint64_t): 331 peekpoke_value.u64 = *(uint64_t *)value_p; 332 break; 333 } 334 } 335 336 peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64; 337 338 if (devi != NULL) 339 rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args, 340 &dummy_result); 341 else 342 rval = peekpoke_mem(cmd, &peekpoke_args); 343 344 /* 345 * A NULL value_p is permitted by ddi_peek(9F); discard the result. 346 */ 347 if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) { 348 switch (size) { 349 case sizeof (uint8_t): 350 *(uint8_t *)value_p = peekpoke_value.u8; 351 break; 352 case sizeof (uint16_t): 353 *(uint16_t *)value_p = peekpoke_value.u16; 354 break; 355 case sizeof (uint32_t): 356 *(uint32_t *)value_p = peekpoke_value.u32; 357 break; 358 case sizeof (uint64_t): 359 *(uint64_t *)value_p = peekpoke_value.u64; 360 break; 361 } 362 } 363 364 return (rval); 365 } 366 367 /* 368 * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this. 369 * they shouldn't be, but the 9f manpage kind of pseudo exposes it. 370 */ 371 int 372 ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p) 373 { 374 switch (size) { 375 case sizeof (uint8_t): 376 case sizeof (uint16_t): 377 case sizeof (uint32_t): 378 case sizeof (uint64_t): 379 break; 380 default: 381 return (DDI_FAILURE); 382 } 383 384 return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p)); 385 } 386 387 int 388 ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p) 389 { 390 switch (size) { 391 case sizeof (uint8_t): 392 case sizeof (uint16_t): 393 case sizeof (uint32_t): 394 case sizeof (uint64_t): 395 break; 396 default: 397 return (DDI_FAILURE); 398 } 399 400 return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p)); 401 } 402 403 int 404 ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p) 405 { 406 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 407 val_p)); 408 } 409 410 int 411 ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p) 412 { 413 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 414 val_p)); 415 } 416 417 int 418 ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p) 419 { 420 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 421 val_p)); 422 } 423 424 int 425 ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p) 426 { 427 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 428 val_p)); 429 } 430 431 432 /* 433 * We need to separate the old interfaces from the new ones and leave them 434 * in here for a while. Previous versions of the OS defined the new interfaces 435 * to the old interfaces. This way we can fix things up so that we can 436 * eventually remove these interfaces. 437 * e.g. A 3rd party module/driver using ddi_peek8 and built against S10 438 * or earlier will actually have a reference to ddi_peekc in the binary. 439 */ 440 #ifdef _ILP32 441 int 442 ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p) 443 { 444 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 445 val_p)); 446 } 447 448 int 449 ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p) 450 { 451 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 452 val_p)); 453 } 454 455 int 456 ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p) 457 { 458 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 459 val_p)); 460 } 461 462 int 463 ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p) 464 { 465 return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 466 val_p)); 467 } 468 #endif /* _ILP32 */ 469 470 int 471 ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val) 472 { 473 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 474 } 475 476 int 477 ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val) 478 { 479 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 480 } 481 482 int 483 ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val) 484 { 485 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 486 } 487 488 int 489 ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val) 490 { 491 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 492 } 493 494 /* 495 * We need to separate the old interfaces from the new ones and leave them 496 * in here for a while. Previous versions of the OS defined the new interfaces 497 * to the old interfaces. This way we can fix things up so that we can 498 * eventually remove these interfaces. 499 * e.g. A 3rd party module/driver using ddi_poke8 and built against S10 500 * or earlier will actually have a reference to ddi_pokec in the binary. 501 */ 502 #ifdef _ILP32 503 int 504 ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val) 505 { 506 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 507 } 508 509 int 510 ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val) 511 { 512 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 513 } 514 515 int 516 ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val) 517 { 518 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 519 } 520 521 int 522 ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val) 523 { 524 return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 525 } 526 #endif /* _ILP32 */ 527 528 /* 529 * ddi_peekpokeio() is used primarily by the mem drivers for moving 530 * data to and from uio structures via peek and poke. Note that we 531 * use "internal" routines ddi_peek and ddi_poke to make this go 532 * slightly faster, avoiding the call overhead .. 533 */ 534 int 535 ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw, 536 caddr_t addr, size_t len, uint_t xfersize) 537 { 538 int64_t ibuffer; 539 int8_t w8; 540 size_t sz; 541 int o; 542 543 if (xfersize > sizeof (long)) 544 xfersize = sizeof (long); 545 546 while (len != 0) { 547 if ((len | (uintptr_t)addr) & 1) { 548 sz = sizeof (int8_t); 549 if (rw == UIO_WRITE) { 550 if ((o = uwritec(uio)) == -1) 551 return (DDI_FAILURE); 552 if (ddi_poke8(devi, (int8_t *)addr, 553 (int8_t)o) != DDI_SUCCESS) 554 return (DDI_FAILURE); 555 } else { 556 if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 557 (int8_t *)addr, &w8) != DDI_SUCCESS) 558 return (DDI_FAILURE); 559 if (ureadc(w8, uio)) 560 return (DDI_FAILURE); 561 } 562 } else { 563 switch (xfersize) { 564 case sizeof (int64_t): 565 if (((len | (uintptr_t)addr) & 566 (sizeof (int64_t) - 1)) == 0) { 567 sz = xfersize; 568 break; 569 } 570 /*FALLTHROUGH*/ 571 case sizeof (int32_t): 572 if (((len | (uintptr_t)addr) & 573 (sizeof (int32_t) - 1)) == 0) { 574 sz = xfersize; 575 break; 576 } 577 /*FALLTHROUGH*/ 578 default: 579 /* 580 * This still assumes that we might have an 581 * I/O bus out there that permits 16-bit 582 * transfers (and that it would be upset by 583 * 32-bit transfers from such locations). 584 */ 585 sz = sizeof (int16_t); 586 break; 587 } 588 589 if (rw == UIO_READ) { 590 if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 591 addr, &ibuffer) != DDI_SUCCESS) 592 return (DDI_FAILURE); 593 } 594 595 if (uiomove(&ibuffer, sz, rw, uio)) 596 return (DDI_FAILURE); 597 598 if (rw == UIO_WRITE) { 599 if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz, 600 addr, &ibuffer) != DDI_SUCCESS) 601 return (DDI_FAILURE); 602 } 603 } 604 addr += sz; 605 len -= sz; 606 } 607 return (DDI_SUCCESS); 608 } 609 610 /* 611 * These routines are used by drivers that do layered ioctls 612 * On sparc, they're implemented in assembler to avoid spilling 613 * register windows in the common (copyin) case .. 614 */ 615 #if !defined(__sparc) 616 int 617 ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags) 618 { 619 if (flags & FKIOCTL) 620 return (kcopy(buf, kernbuf, size) ? -1 : 0); 621 return (copyin(buf, kernbuf, size)); 622 } 623 624 int 625 ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags) 626 { 627 if (flags & FKIOCTL) 628 return (kcopy(buf, kernbuf, size) ? -1 : 0); 629 return (copyout(buf, kernbuf, size)); 630 } 631 #endif /* !__sparc */ 632 633 /* 634 * Conversions in nexus pagesize units. We don't duplicate the 635 * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI 636 * routines anyway. 637 */ 638 unsigned long 639 ddi_btop(dev_info_t *dip, unsigned long bytes) 640 { 641 unsigned long pages; 642 643 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages); 644 return (pages); 645 } 646 647 unsigned long 648 ddi_btopr(dev_info_t *dip, unsigned long bytes) 649 { 650 unsigned long pages; 651 652 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages); 653 return (pages); 654 } 655 656 unsigned long 657 ddi_ptob(dev_info_t *dip, unsigned long pages) 658 { 659 unsigned long bytes; 660 661 (void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes); 662 return (bytes); 663 } 664 665 unsigned int 666 ddi_enter_critical(void) 667 { 668 return ((uint_t)spl7()); 669 } 670 671 void 672 ddi_exit_critical(unsigned int spl) 673 { 674 splx((int)spl); 675 } 676 677 /* 678 * Nexus ctlops punter 679 */ 680 681 #if !defined(__sparc) 682 /* 683 * Request bus_ctl parent to handle a bus_ctl request 684 * 685 * (The sparc version is in sparc_ddi.s) 686 */ 687 int 688 ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v) 689 { 690 int (*fp)(); 691 692 if (!d || !r) 693 return (DDI_FAILURE); 694 695 if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL) 696 return (DDI_FAILURE); 697 698 fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl; 699 return ((*fp)(d, r, op, a, v)); 700 } 701 702 #endif 703 704 /* 705 * DMA/DVMA setup 706 */ 707 708 #if defined(__sparc) 709 static ddi_dma_lim_t standard_limits = { 710 (uint_t)0, /* addr_t dlim_addr_lo */ 711 (uint_t)-1, /* addr_t dlim_addr_hi */ 712 (uint_t)-1, /* uint_t dlim_cntr_max */ 713 (uint_t)1, /* uint_t dlim_burstsizes */ 714 (uint_t)1, /* uint_t dlim_minxfer */ 715 0 /* uint_t dlim_dmaspeed */ 716 }; 717 #elif defined(__x86) 718 static ddi_dma_lim_t standard_limits = { 719 (uint_t)0, /* addr_t dlim_addr_lo */ 720 (uint_t)0xffffff, /* addr_t dlim_addr_hi */ 721 (uint_t)0, /* uint_t dlim_cntr_max */ 722 (uint_t)0x00000001, /* uint_t dlim_burstsizes */ 723 (uint_t)DMA_UNIT_8, /* uint_t dlim_minxfer */ 724 (uint_t)0, /* uint_t dlim_dmaspeed */ 725 (uint_t)0x86<<24+0, /* uint_t dlim_version */ 726 (uint_t)0xffff, /* uint_t dlim_adreg_max */ 727 (uint_t)0xffff, /* uint_t dlim_ctreg_max */ 728 (uint_t)512, /* uint_t dlim_granular */ 729 (int)1, /* int dlim_sgllen */ 730 (uint_t)0xffffffff /* uint_t dlim_reqsizes */ 731 }; 732 733 #endif 734 735 int 736 ddi_dma_setup(dev_info_t *dip, struct ddi_dma_req *dmareqp, 737 ddi_dma_handle_t *handlep) 738 { 739 int (*funcp)() = ddi_dma_map; 740 struct bus_ops *bop; 741 #if defined(__sparc) 742 auto ddi_dma_lim_t dma_lim; 743 744 if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) { 745 dma_lim = standard_limits; 746 } else { 747 dma_lim = *dmareqp->dmar_limits; 748 } 749 dmareqp->dmar_limits = &dma_lim; 750 #endif 751 #if defined(__x86) 752 if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) 753 return (DDI_FAILURE); 754 #endif 755 756 /* 757 * Handle the case that the requester is both a leaf 758 * and a nexus driver simultaneously by calling the 759 * requester's bus_dma_map function directly instead 760 * of ddi_dma_map. 761 */ 762 bop = DEVI(dip)->devi_ops->devo_bus_ops; 763 if (bop && bop->bus_dma_map) 764 funcp = bop->bus_dma_map; 765 return ((*funcp)(dip, dip, dmareqp, handlep)); 766 } 767 768 int 769 ddi_dma_addr_setup(dev_info_t *dip, struct as *as, caddr_t addr, size_t len, 770 uint_t flags, int (*waitfp)(), caddr_t arg, 771 ddi_dma_lim_t *limits, ddi_dma_handle_t *handlep) 772 { 773 int (*funcp)() = ddi_dma_map; 774 ddi_dma_lim_t dma_lim; 775 struct ddi_dma_req dmareq; 776 struct bus_ops *bop; 777 778 if (len == 0) { 779 return (DDI_DMA_NOMAPPING); 780 } 781 if (limits == (ddi_dma_lim_t *)0) { 782 dma_lim = standard_limits; 783 } else { 784 dma_lim = *limits; 785 } 786 dmareq.dmar_limits = &dma_lim; 787 dmareq.dmar_flags = flags; 788 dmareq.dmar_fp = waitfp; 789 dmareq.dmar_arg = arg; 790 dmareq.dmar_object.dmao_size = len; 791 dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 792 dmareq.dmar_object.dmao_obj.virt_obj.v_as = as; 793 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr; 794 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 795 796 /* 797 * Handle the case that the requester is both a leaf 798 * and a nexus driver simultaneously by calling the 799 * requester's bus_dma_map function directly instead 800 * of ddi_dma_map. 801 */ 802 bop = DEVI(dip)->devi_ops->devo_bus_ops; 803 if (bop && bop->bus_dma_map) 804 funcp = bop->bus_dma_map; 805 806 return ((*funcp)(dip, dip, &dmareq, handlep)); 807 } 808 809 int 810 ddi_dma_buf_setup(dev_info_t *dip, struct buf *bp, uint_t flags, 811 int (*waitfp)(), caddr_t arg, ddi_dma_lim_t *limits, 812 ddi_dma_handle_t *handlep) 813 { 814 int (*funcp)() = ddi_dma_map; 815 ddi_dma_lim_t dma_lim; 816 struct ddi_dma_req dmareq; 817 struct bus_ops *bop; 818 819 if (limits == (ddi_dma_lim_t *)0) { 820 dma_lim = standard_limits; 821 } else { 822 dma_lim = *limits; 823 } 824 dmareq.dmar_limits = &dma_lim; 825 dmareq.dmar_flags = flags; 826 dmareq.dmar_fp = waitfp; 827 dmareq.dmar_arg = arg; 828 dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount; 829 830 if (bp->b_flags & B_PAGEIO) { 831 dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES; 832 dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages; 833 dmareq.dmar_object.dmao_obj.pp_obj.pp_offset = 834 (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET); 835 } else { 836 dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR; 837 dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr; 838 if (bp->b_flags & B_SHADOW) { 839 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = 840 bp->b_shadow; 841 } else { 842 dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 843 } 844 845 /* 846 * If the buffer has no proc pointer, or the proc 847 * struct has the kernel address space, or the buffer has 848 * been marked B_REMAPPED (meaning that it is now 849 * mapped into the kernel's address space), then 850 * the address space is kas (kernel address space). 851 */ 852 if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) || 853 (bp->b_flags & B_REMAPPED)) { 854 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0; 855 } else { 856 dmareq.dmar_object.dmao_obj.virt_obj.v_as = 857 bp->b_proc->p_as; 858 } 859 } 860 861 /* 862 * Handle the case that the requester is both a leaf 863 * and a nexus driver simultaneously by calling the 864 * requester's bus_dma_map function directly instead 865 * of ddi_dma_map. 866 */ 867 bop = DEVI(dip)->devi_ops->devo_bus_ops; 868 if (bop && bop->bus_dma_map) 869 funcp = bop->bus_dma_map; 870 871 return ((*funcp)(dip, dip, &dmareq, handlep)); 872 } 873 874 #if !defined(__sparc) 875 /* 876 * Request bus_dma_ctl parent to fiddle with a dma request. 877 * 878 * (The sparc version is in sparc_subr.s) 879 */ 880 int 881 ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 882 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 883 off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags) 884 { 885 int (*fp)(); 886 887 dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl; 888 fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl; 889 return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags)); 890 } 891 #endif 892 893 /* 894 * For all DMA control functions, call the DMA control 895 * routine and return status. 896 * 897 * Just plain assume that the parent is to be called. 898 * If a nexus driver or a thread outside the framework 899 * of a nexus driver or a leaf driver calls these functions, 900 * it is up to them to deal with the fact that the parent's 901 * bus_dma_ctl function will be the first one called. 902 */ 903 904 #define HD ((ddi_dma_impl_t *)h)->dmai_rdip 905 906 int 907 ddi_dma_kvaddrp(ddi_dma_handle_t h, off_t off, size_t len, caddr_t *kp) 908 { 909 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_KVADDR, &off, &len, kp, 0)); 910 } 911 912 int 913 ddi_dma_htoc(ddi_dma_handle_t h, off_t o, ddi_dma_cookie_t *c) 914 { 915 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_HTOC, &o, 0, (caddr_t *)c, 0)); 916 } 917 918 int 919 ddi_dma_coff(ddi_dma_handle_t h, ddi_dma_cookie_t *c, off_t *o) 920 { 921 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_COFF, 922 (off_t *)c, 0, (caddr_t *)o, 0)); 923 } 924 925 int 926 ddi_dma_movwin(ddi_dma_handle_t h, off_t *o, size_t *l, ddi_dma_cookie_t *c) 927 { 928 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_MOVWIN, o, 929 l, (caddr_t *)c, 0)); 930 } 931 932 int 933 ddi_dma_curwin(ddi_dma_handle_t h, off_t *o, size_t *l) 934 { 935 if ((((ddi_dma_impl_t *)h)->dmai_rflags & DDI_DMA_PARTIAL) == 0) 936 return (DDI_FAILURE); 937 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_REPWIN, o, l, 0, 0)); 938 } 939 940 int 941 ddi_dma_nextwin(ddi_dma_handle_t h, ddi_dma_win_t win, 942 ddi_dma_win_t *nwin) 943 { 944 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTWIN, (off_t *)&win, 0, 945 (caddr_t *)nwin, 0)); 946 } 947 948 int 949 ddi_dma_nextseg(ddi_dma_win_t win, ddi_dma_seg_t seg, ddi_dma_seg_t *nseg) 950 { 951 ddi_dma_handle_t h = (ddi_dma_handle_t)win; 952 953 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTSEG, (off_t *)&win, 954 (size_t *)&seg, (caddr_t *)nseg, 0)); 955 } 956 957 #if (defined(__i386) && !defined(__amd64)) || defined(__sparc) 958 /* 959 * This routine is Obsolete and should be removed from ALL architectures 960 * in a future release of Solaris. 961 * 962 * It is deliberately NOT ported to amd64; please fix the code that 963 * depends on this routine to use ddi_dma_nextcookie(9F). 964 * 965 * NOTE: even though we fixed the pointer through a 32-bit param issue (the fix 966 * is a side effect to some other cleanup), we're still not going to support 967 * this interface on x64. 968 */ 969 int 970 ddi_dma_segtocookie(ddi_dma_seg_t seg, off_t *o, off_t *l, 971 ddi_dma_cookie_t *cookiep) 972 { 973 ddi_dma_handle_t h = (ddi_dma_handle_t)seg; 974 975 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SEGTOC, o, (size_t *)l, 976 (caddr_t *)cookiep, 0)); 977 } 978 #endif /* (__i386 && !__amd64) || __sparc */ 979 980 #if !defined(__sparc) 981 982 /* 983 * The SPARC versions of these routines are done in assembler to 984 * save register windows, so they're in sparc_subr.s. 985 */ 986 987 int 988 ddi_dma_map(dev_info_t *dip, dev_info_t *rdip, 989 struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 990 { 991 dev_info_t *hdip; 992 int (*funcp)(dev_info_t *, dev_info_t *, struct ddi_dma_req *, 993 ddi_dma_handle_t *); 994 995 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_map; 996 997 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_map; 998 return ((*funcp)(hdip, rdip, dmareqp, handlep)); 999 } 1000 1001 int 1002 ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 1003 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 1004 { 1005 dev_info_t *hdip; 1006 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *, 1007 int (*)(caddr_t), caddr_t, ddi_dma_handle_t *); 1008 1009 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 1010 1011 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_allochdl; 1012 return ((*funcp)(hdip, rdip, attr, waitfp, arg, handlep)); 1013 } 1014 1015 int 1016 ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep) 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_allochdl; 1022 1023 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_freehdl; 1024 return ((*funcp)(hdip, rdip, handlep)); 1025 } 1026 1027 int 1028 ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 1029 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 1030 ddi_dma_cookie_t *cp, uint_t *ccountp) 1031 { 1032 dev_info_t *hdip; 1033 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1034 struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *); 1035 1036 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 1037 1038 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl; 1039 return ((*funcp)(hdip, rdip, handle, dmareq, cp, ccountp)); 1040 } 1041 1042 int 1043 ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 1044 ddi_dma_handle_t handle) 1045 { 1046 dev_info_t *hdip; 1047 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1048 1049 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1050 1051 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl; 1052 return ((*funcp)(hdip, rdip, handle)); 1053 } 1054 1055 1056 int 1057 ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip, 1058 ddi_dma_handle_t handle, off_t off, size_t len, 1059 uint_t cache_flags) 1060 { 1061 dev_info_t *hdip; 1062 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1063 off_t, size_t, uint_t); 1064 1065 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1066 1067 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_flush; 1068 return ((*funcp)(hdip, rdip, handle, off, len, cache_flags)); 1069 } 1070 1071 int 1072 ddi_dma_win(dev_info_t *dip, dev_info_t *rdip, 1073 ddi_dma_handle_t handle, uint_t win, off_t *offp, 1074 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 1075 { 1076 dev_info_t *hdip; 1077 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1078 uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *); 1079 1080 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win; 1081 1082 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_win; 1083 return ((*funcp)(hdip, rdip, handle, win, offp, lenp, 1084 cookiep, ccountp)); 1085 } 1086 1087 int 1088 ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom) 1089 { 1090 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1091 dev_info_t *hdip, *dip; 1092 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t, 1093 size_t, uint_t); 1094 1095 /* 1096 * the DMA nexus driver will set DMP_NOSYNC if the 1097 * platform does not require any sync operation. For 1098 * example if the memory is uncached or consistent 1099 * and without any I/O write buffers involved. 1100 */ 1101 if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC) 1102 return (DDI_SUCCESS); 1103 1104 dip = hp->dmai_rdip; 1105 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1106 funcp = DEVI(hdip)->devi_ops->devo_bus_ops->bus_dma_flush; 1107 return ((*funcp)(hdip, dip, h, o, l, whom)); 1108 } 1109 1110 int 1111 ddi_dma_unbind_handle(ddi_dma_handle_t h) 1112 { 1113 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1114 dev_info_t *hdip, *dip; 1115 int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1116 1117 dip = hp->dmai_rdip; 1118 hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1119 funcp = DEVI(dip)->devi_bus_dma_unbindfunc; 1120 return ((*funcp)(hdip, dip, h)); 1121 } 1122 1123 #endif /* !__sparc */ 1124 1125 int 1126 ddi_dma_free(ddi_dma_handle_t h) 1127 { 1128 return (ddi_dma_mctl(HD, HD, h, DDI_DMA_FREE, 0, 0, 0, 0)); 1129 } 1130 1131 int 1132 ddi_iopb_alloc(dev_info_t *dip, ddi_dma_lim_t *limp, uint_t len, caddr_t *iopbp) 1133 { 1134 ddi_dma_lim_t defalt; 1135 size_t size = len; 1136 1137 if (!limp) { 1138 defalt = standard_limits; 1139 limp = &defalt; 1140 } 1141 return (i_ddi_mem_alloc_lim(dip, limp, size, 0, 0, 0, 1142 iopbp, NULL, NULL)); 1143 } 1144 1145 void 1146 ddi_iopb_free(caddr_t iopb) 1147 { 1148 i_ddi_mem_free(iopb, NULL); 1149 } 1150 1151 int 1152 ddi_mem_alloc(dev_info_t *dip, ddi_dma_lim_t *limits, uint_t length, 1153 uint_t flags, caddr_t *kaddrp, uint_t *real_length) 1154 { 1155 ddi_dma_lim_t defalt; 1156 size_t size = length; 1157 1158 if (!limits) { 1159 defalt = standard_limits; 1160 limits = &defalt; 1161 } 1162 return (i_ddi_mem_alloc_lim(dip, limits, size, flags & 0x1, 1163 1, 0, kaddrp, real_length, NULL)); 1164 } 1165 1166 void 1167 ddi_mem_free(caddr_t kaddr) 1168 { 1169 i_ddi_mem_free(kaddr, NULL); 1170 } 1171 1172 /* 1173 * DMA attributes, alignment, burst sizes, and transfer minimums 1174 */ 1175 int 1176 ddi_dma_get_attr(ddi_dma_handle_t handle, ddi_dma_attr_t *attrp) 1177 { 1178 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1179 1180 if (attrp == NULL) 1181 return (DDI_FAILURE); 1182 *attrp = dimp->dmai_attr; 1183 return (DDI_SUCCESS); 1184 } 1185 1186 int 1187 ddi_dma_burstsizes(ddi_dma_handle_t handle) 1188 { 1189 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1190 1191 if (!dimp) 1192 return (0); 1193 else 1194 return (dimp->dmai_burstsizes); 1195 } 1196 1197 int 1198 ddi_dma_devalign(ddi_dma_handle_t handle, uint_t *alignment, uint_t *mineffect) 1199 { 1200 ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1201 1202 if (!dimp || !alignment || !mineffect) 1203 return (DDI_FAILURE); 1204 if (!(dimp->dmai_rflags & DDI_DMA_SBUS_64BIT)) { 1205 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1206 } else { 1207 if (dimp->dmai_burstsizes & 0xff0000) { 1208 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes >> 16); 1209 } else { 1210 *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1211 } 1212 } 1213 *mineffect = dimp->dmai_minxfer; 1214 return (DDI_SUCCESS); 1215 } 1216 1217 int 1218 ddi_iomin(dev_info_t *a, int i, int stream) 1219 { 1220 int r; 1221 1222 /* 1223 * Make sure that the initial value is sane 1224 */ 1225 if (i & (i - 1)) 1226 return (0); 1227 if (i == 0) 1228 i = (stream) ? 4 : 1; 1229 1230 r = ddi_ctlops(a, a, 1231 DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i); 1232 if (r != DDI_SUCCESS || (i & (i - 1))) 1233 return (0); 1234 return (i); 1235 } 1236 1237 /* 1238 * Given two DMA attribute structures, apply the attributes 1239 * of one to the other, following the rules of attributes 1240 * and the wishes of the caller. 1241 * 1242 * The rules of DMA attribute structures are that you cannot 1243 * make things *less* restrictive as you apply one set 1244 * of attributes to another. 1245 * 1246 */ 1247 void 1248 ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod) 1249 { 1250 attr->dma_attr_addr_lo = 1251 MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo); 1252 attr->dma_attr_addr_hi = 1253 MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi); 1254 attr->dma_attr_count_max = 1255 MIN(attr->dma_attr_count_max, mod->dma_attr_count_max); 1256 attr->dma_attr_align = 1257 MAX(attr->dma_attr_align, mod->dma_attr_align); 1258 attr->dma_attr_burstsizes = 1259 (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes); 1260 attr->dma_attr_minxfer = 1261 maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer); 1262 attr->dma_attr_maxxfer = 1263 MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer); 1264 attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg); 1265 attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen, 1266 (uint_t)mod->dma_attr_sgllen); 1267 attr->dma_attr_granular = 1268 MAX(attr->dma_attr_granular, mod->dma_attr_granular); 1269 } 1270 1271 /* 1272 * mmap/segmap interface: 1273 */ 1274 1275 /* 1276 * ddi_segmap: setup the default segment driver. Calls the drivers 1277 * XXmmap routine to validate the range to be mapped. 1278 * Return ENXIO of the range is not valid. Create 1279 * a seg_dev segment that contains all of the 1280 * necessary information and will reference the 1281 * default segment driver routines. It returns zero 1282 * on success or non-zero on failure. 1283 */ 1284 int 1285 ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len, 1286 uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp) 1287 { 1288 extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *, 1289 off_t, uint_t, uint_t, uint_t, struct cred *); 1290 1291 return (spec_segmap(dev, offset, asp, addrp, len, 1292 prot, maxprot, flags, credp)); 1293 } 1294 1295 /* 1296 * ddi_map_fault: Resolve mappings at fault time. Used by segment 1297 * drivers. Allows each successive parent to resolve 1298 * address translations and add its mappings to the 1299 * mapping list supplied in the page structure. It 1300 * returns zero on success or non-zero on failure. 1301 */ 1302 1303 int 1304 ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg, 1305 caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock) 1306 { 1307 return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock)); 1308 } 1309 1310 /* 1311 * ddi_device_mapping_check: Called from ddi_segmap_setup. 1312 * Invokes platform specific DDI to determine whether attributes specified 1313 * in attr(9s) are valid for the region of memory that will be made 1314 * available for direct access to user process via the mmap(2) system call. 1315 */ 1316 int 1317 ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp, 1318 uint_t rnumber, uint_t *hat_flags) 1319 { 1320 ddi_acc_handle_t handle; 1321 ddi_map_req_t mr; 1322 ddi_acc_hdl_t *hp; 1323 int result; 1324 dev_info_t *dip; 1325 1326 /* 1327 * we use e_ddi_hold_devi_by_dev to search for the devi. We 1328 * release it immediately since it should already be held by 1329 * a devfs vnode. 1330 */ 1331 if ((dip = 1332 e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL) 1333 return (-1); 1334 ddi_release_devi(dip); /* for e_ddi_hold_devi_by_dev() */ 1335 1336 /* 1337 * Allocate and initialize the common elements of data 1338 * access handle. 1339 */ 1340 handle = impl_acc_hdl_alloc(KM_SLEEP, NULL); 1341 if (handle == NULL) 1342 return (-1); 1343 1344 hp = impl_acc_hdl_get(handle); 1345 hp->ah_vers = VERS_ACCHDL; 1346 hp->ah_dip = dip; 1347 hp->ah_rnumber = rnumber; 1348 hp->ah_offset = 0; 1349 hp->ah_len = 0; 1350 hp->ah_acc = *accattrp; 1351 1352 /* 1353 * Set up the mapping request and call to parent. 1354 */ 1355 mr.map_op = DDI_MO_MAP_HANDLE; 1356 mr.map_type = DDI_MT_RNUMBER; 1357 mr.map_obj.rnumber = rnumber; 1358 mr.map_prot = PROT_READ | PROT_WRITE; 1359 mr.map_flags = DDI_MF_KERNEL_MAPPING; 1360 mr.map_handlep = hp; 1361 mr.map_vers = DDI_MAP_VERSION; 1362 result = ddi_map(dip, &mr, 0, 0, NULL); 1363 1364 /* 1365 * Region must be mappable, pick up flags from the framework. 1366 */ 1367 *hat_flags = hp->ah_hat_flags; 1368 1369 impl_acc_hdl_free(handle); 1370 1371 /* 1372 * check for end result. 1373 */ 1374 if (result != DDI_SUCCESS) 1375 return (-1); 1376 return (0); 1377 } 1378 1379 1380 /* 1381 * Property functions: See also, ddipropdefs.h. 1382 * 1383 * These functions are the framework for the property functions, 1384 * i.e. they support software defined properties. All implementation 1385 * specific property handling (i.e.: self-identifying devices and 1386 * PROM defined properties are handled in the implementation specific 1387 * functions (defined in ddi_implfuncs.h). 1388 */ 1389 1390 /* 1391 * nopropop: Shouldn't be called, right? 1392 */ 1393 int 1394 nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1395 char *name, caddr_t valuep, int *lengthp) 1396 { 1397 _NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp)) 1398 return (DDI_PROP_NOT_FOUND); 1399 } 1400 1401 #ifdef DDI_PROP_DEBUG 1402 int ddi_prop_debug_flag = 0; 1403 1404 int 1405 ddi_prop_debug(int enable) 1406 { 1407 int prev = ddi_prop_debug_flag; 1408 1409 if ((enable != 0) || (prev != 0)) 1410 printf("ddi_prop_debug: debugging %s\n", 1411 enable ? "enabled" : "disabled"); 1412 ddi_prop_debug_flag = enable; 1413 return (prev); 1414 } 1415 1416 #endif /* DDI_PROP_DEBUG */ 1417 1418 /* 1419 * Search a property list for a match, if found return pointer 1420 * to matching prop struct, else return NULL. 1421 */ 1422 1423 ddi_prop_t * 1424 i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head) 1425 { 1426 ddi_prop_t *propp; 1427 1428 /* 1429 * find the property in child's devinfo: 1430 * Search order defined by this search function is first matching 1431 * property with input dev == DDI_DEV_T_ANY matching any dev or 1432 * dev == propp->prop_dev, name == propp->name, and the correct 1433 * data type as specified in the flags. If a DDI_DEV_T_NONE dev 1434 * value made it this far then it implies a DDI_DEV_T_ANY search. 1435 */ 1436 if (dev == DDI_DEV_T_NONE) 1437 dev = DDI_DEV_T_ANY; 1438 1439 for (propp = *list_head; propp != NULL; propp = propp->prop_next) { 1440 1441 if (!DDI_STRSAME(propp->prop_name, name)) 1442 continue; 1443 1444 if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev)) 1445 continue; 1446 1447 if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1448 continue; 1449 1450 return (propp); 1451 } 1452 1453 return ((ddi_prop_t *)0); 1454 } 1455 1456 /* 1457 * Search for property within devnames structures 1458 */ 1459 ddi_prop_t * 1460 i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags) 1461 { 1462 major_t major; 1463 struct devnames *dnp; 1464 ddi_prop_t *propp; 1465 1466 /* 1467 * Valid dev_t value is needed to index into the 1468 * correct devnames entry, therefore a dev_t 1469 * value of DDI_DEV_T_ANY is not appropriate. 1470 */ 1471 ASSERT(dev != DDI_DEV_T_ANY); 1472 if (dev == DDI_DEV_T_ANY) { 1473 return ((ddi_prop_t *)0); 1474 } 1475 1476 major = getmajor(dev); 1477 dnp = &(devnamesp[major]); 1478 1479 if (dnp->dn_global_prop_ptr == NULL) 1480 return ((ddi_prop_t *)0); 1481 1482 LOCK_DEV_OPS(&dnp->dn_lock); 1483 1484 for (propp = dnp->dn_global_prop_ptr->prop_list; 1485 propp != NULL; 1486 propp = (ddi_prop_t *)propp->prop_next) { 1487 1488 if (!DDI_STRSAME(propp->prop_name, name)) 1489 continue; 1490 1491 if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) && 1492 (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev)) 1493 continue; 1494 1495 if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1496 continue; 1497 1498 /* Property found, return it */ 1499 UNLOCK_DEV_OPS(&dnp->dn_lock); 1500 return (propp); 1501 } 1502 1503 UNLOCK_DEV_OPS(&dnp->dn_lock); 1504 return ((ddi_prop_t *)0); 1505 } 1506 1507 static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>"; 1508 1509 /* 1510 * ddi_prop_search_global: 1511 * Search the global property list within devnames 1512 * for the named property. Return the encoded value. 1513 */ 1514 static int 1515 i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name, 1516 void *valuep, uint_t *lengthp) 1517 { 1518 ddi_prop_t *propp; 1519 caddr_t buffer; 1520 1521 propp = i_ddi_search_global_prop(dev, name, flags); 1522 1523 /* Property NOT found, bail */ 1524 if (propp == (ddi_prop_t *)0) 1525 return (DDI_PROP_NOT_FOUND); 1526 1527 if (propp->prop_flags & DDI_PROP_UNDEF_IT) 1528 return (DDI_PROP_UNDEFINED); 1529 1530 if ((buffer = kmem_alloc(propp->prop_len, 1531 (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) { 1532 cmn_err(CE_CONT, prop_no_mem_msg, name); 1533 return (DDI_PROP_NO_MEMORY); 1534 } 1535 1536 /* 1537 * Return the encoded data 1538 */ 1539 *(caddr_t *)valuep = buffer; 1540 *lengthp = propp->prop_len; 1541 bcopy(propp->prop_val, buffer, propp->prop_len); 1542 1543 return (DDI_PROP_SUCCESS); 1544 } 1545 1546 /* 1547 * ddi_prop_search_common: Lookup and return the encoded value 1548 */ 1549 int 1550 ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1551 uint_t flags, char *name, void *valuep, uint_t *lengthp) 1552 { 1553 ddi_prop_t *propp; 1554 int i; 1555 caddr_t buffer; 1556 caddr_t prealloc = NULL; 1557 int plength = 0; 1558 dev_info_t *pdip; 1559 int (*bop)(); 1560 1561 /*CONSTANTCONDITION*/ 1562 while (1) { 1563 1564 mutex_enter(&(DEVI(dip)->devi_lock)); 1565 1566 1567 /* 1568 * find the property in child's devinfo: 1569 * Search order is: 1570 * 1. driver defined properties 1571 * 2. system defined properties 1572 * 3. driver global properties 1573 * 4. boot defined properties 1574 */ 1575 1576 propp = i_ddi_prop_search(dev, name, flags, 1577 &(DEVI(dip)->devi_drv_prop_ptr)); 1578 if (propp == NULL) { 1579 propp = i_ddi_prop_search(dev, name, flags, 1580 &(DEVI(dip)->devi_sys_prop_ptr)); 1581 } 1582 if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) { 1583 propp = i_ddi_prop_search(dev, name, flags, 1584 &DEVI(dip)->devi_global_prop_list->prop_list); 1585 } 1586 1587 if (propp == NULL) { 1588 propp = i_ddi_prop_search(dev, name, flags, 1589 &(DEVI(dip)->devi_hw_prop_ptr)); 1590 } 1591 1592 /* 1593 * Software property found? 1594 */ 1595 if (propp != (ddi_prop_t *)0) { 1596 1597 /* 1598 * If explicit undefine, return now. 1599 */ 1600 if (propp->prop_flags & DDI_PROP_UNDEF_IT) { 1601 mutex_exit(&(DEVI(dip)->devi_lock)); 1602 if (prealloc) 1603 kmem_free(prealloc, plength); 1604 return (DDI_PROP_UNDEFINED); 1605 } 1606 1607 /* 1608 * If we only want to know if it exists, return now 1609 */ 1610 if (prop_op == PROP_EXISTS) { 1611 mutex_exit(&(DEVI(dip)->devi_lock)); 1612 ASSERT(prealloc == NULL); 1613 return (DDI_PROP_SUCCESS); 1614 } 1615 1616 /* 1617 * If length only request or prop length == 0, 1618 * service request and return now. 1619 */ 1620 if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) { 1621 *lengthp = propp->prop_len; 1622 1623 /* 1624 * if prop_op is PROP_LEN_AND_VAL_ALLOC 1625 * that means prop_len is 0, so set valuep 1626 * also to NULL 1627 */ 1628 if (prop_op == PROP_LEN_AND_VAL_ALLOC) 1629 *(caddr_t *)valuep = NULL; 1630 1631 mutex_exit(&(DEVI(dip)->devi_lock)); 1632 if (prealloc) 1633 kmem_free(prealloc, plength); 1634 return (DDI_PROP_SUCCESS); 1635 } 1636 1637 /* 1638 * If LEN_AND_VAL_ALLOC and the request can sleep, 1639 * drop the mutex, allocate the buffer, and go 1640 * through the loop again. If we already allocated 1641 * the buffer, and the size of the property changed, 1642 * keep trying... 1643 */ 1644 if ((prop_op == PROP_LEN_AND_VAL_ALLOC) && 1645 (flags & DDI_PROP_CANSLEEP)) { 1646 if (prealloc && (propp->prop_len != plength)) { 1647 kmem_free(prealloc, plength); 1648 prealloc = NULL; 1649 } 1650 if (prealloc == NULL) { 1651 plength = propp->prop_len; 1652 mutex_exit(&(DEVI(dip)->devi_lock)); 1653 prealloc = kmem_alloc(plength, 1654 KM_SLEEP); 1655 continue; 1656 } 1657 } 1658 1659 /* 1660 * Allocate buffer, if required. Either way, 1661 * set `buffer' variable. 1662 */ 1663 i = *lengthp; /* Get callers length */ 1664 *lengthp = propp->prop_len; /* Set callers length */ 1665 1666 switch (prop_op) { 1667 1668 case PROP_LEN_AND_VAL_ALLOC: 1669 1670 if (prealloc == NULL) { 1671 buffer = kmem_alloc(propp->prop_len, 1672 KM_NOSLEEP); 1673 } else { 1674 buffer = prealloc; 1675 } 1676 1677 if (buffer == NULL) { 1678 mutex_exit(&(DEVI(dip)->devi_lock)); 1679 cmn_err(CE_CONT, prop_no_mem_msg, name); 1680 return (DDI_PROP_NO_MEMORY); 1681 } 1682 /* Set callers buf ptr */ 1683 *(caddr_t *)valuep = buffer; 1684 break; 1685 1686 case PROP_LEN_AND_VAL_BUF: 1687 1688 if (propp->prop_len > (i)) { 1689 mutex_exit(&(DEVI(dip)->devi_lock)); 1690 return (DDI_PROP_BUF_TOO_SMALL); 1691 } 1692 1693 buffer = valuep; /* Get callers buf ptr */ 1694 break; 1695 1696 default: 1697 break; 1698 } 1699 1700 /* 1701 * Do the copy. 1702 */ 1703 bcopy(propp->prop_val, buffer, propp->prop_len); 1704 mutex_exit(&(DEVI(dip)->devi_lock)); 1705 return (DDI_PROP_SUCCESS); 1706 } 1707 1708 mutex_exit(&(DEVI(dip)->devi_lock)); 1709 if (prealloc) 1710 kmem_free(prealloc, plength); 1711 prealloc = NULL; 1712 1713 /* 1714 * Prop not found, call parent bus_ops to deal with possible 1715 * h/w layer (possible PROM defined props, etc.) and to 1716 * possibly ascend the hierarchy, if allowed by flags. 1717 */ 1718 pdip = (dev_info_t *)DEVI(dip)->devi_parent; 1719 1720 /* 1721 * One last call for the root driver PROM props? 1722 */ 1723 if (dip == ddi_root_node()) { 1724 return (ddi_bus_prop_op(dev, dip, dip, prop_op, 1725 flags, name, valuep, (int *)lengthp)); 1726 } 1727 1728 /* 1729 * We may have been called to check for properties 1730 * within a single devinfo node that has no parent - 1731 * see make_prop() 1732 */ 1733 if (pdip == NULL) { 1734 ASSERT((flags & 1735 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) == 1736 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)); 1737 return (DDI_PROP_NOT_FOUND); 1738 } 1739 1740 /* 1741 * Instead of recursing, we do iterative calls up the tree. 1742 * As a bit of optimization, skip the bus_op level if the 1743 * node is a s/w node and if the parent's bus_prop_op function 1744 * is `ddi_bus_prop_op', because we know that in this case, 1745 * this function does nothing. 1746 * 1747 * 4225415: If the parent isn't attached, or the child 1748 * hasn't been named by the parent yet, use the default 1749 * ddi_bus_prop_op as a proxy for the parent. This 1750 * allows property lookups in any child/parent state to 1751 * include 'prom' and inherited properties, even when 1752 * there are no drivers attached to the child or parent. 1753 */ 1754 1755 bop = ddi_bus_prop_op; 1756 if (i_ddi_devi_attached(pdip) && 1757 (i_ddi_node_state(dip) >= DS_INITIALIZED)) 1758 bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op; 1759 1760 i = DDI_PROP_NOT_FOUND; 1761 1762 if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) { 1763 i = (*bop)(dev, pdip, dip, prop_op, 1764 flags | DDI_PROP_DONTPASS, 1765 name, valuep, lengthp); 1766 } 1767 1768 if ((flags & DDI_PROP_DONTPASS) || 1769 (i != DDI_PROP_NOT_FOUND)) 1770 return (i); 1771 1772 dip = pdip; 1773 } 1774 /*NOTREACHED*/ 1775 } 1776 1777 1778 /* 1779 * ddi_prop_op: The basic property operator for drivers. 1780 * 1781 * In ddi_prop_op, the type of valuep is interpreted based on prop_op: 1782 * 1783 * prop_op valuep 1784 * ------ ------ 1785 * 1786 * PROP_LEN <unused> 1787 * 1788 * PROP_LEN_AND_VAL_BUF Pointer to callers buffer 1789 * 1790 * PROP_LEN_AND_VAL_ALLOC Address of callers pointer (will be set to 1791 * address of allocated buffer, if successful) 1792 */ 1793 int 1794 ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1795 char *name, caddr_t valuep, int *lengthp) 1796 { 1797 int i; 1798 1799 ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0); 1800 1801 /* 1802 * If this was originally an LDI prop lookup then we bail here. 1803 * The reason is that the LDI property lookup interfaces first call 1804 * a drivers prop_op() entry point to allow it to override 1805 * properties. But if we've made it here, then the driver hasn't 1806 * overriden any properties. We don't want to continue with the 1807 * property search here because we don't have any type inforamtion. 1808 * When we return failure, the LDI interfaces will then proceed to 1809 * call the typed property interfaces to look up the property. 1810 */ 1811 if (mod_flags & DDI_PROP_DYNAMIC) 1812 return (DDI_PROP_NOT_FOUND); 1813 1814 /* 1815 * check for pre-typed property consumer asking for typed property: 1816 * see e_ddi_getprop_int64. 1817 */ 1818 if (mod_flags & DDI_PROP_CONSUMER_TYPED) 1819 mod_flags |= DDI_PROP_TYPE_INT64; 1820 mod_flags |= DDI_PROP_TYPE_ANY; 1821 1822 i = ddi_prop_search_common(dev, dip, prop_op, 1823 mod_flags, name, valuep, (uint_t *)lengthp); 1824 if (i == DDI_PROP_FOUND_1275) 1825 return (DDI_PROP_SUCCESS); 1826 return (i); 1827 } 1828 1829 /* 1830 * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that 1831 * maintain size in number of blksize blocks. Provides a dynamic property 1832 * implementation for size oriented properties based on nblocks64 and blksize 1833 * values passed in by the driver. Fallback to ddi_prop_op if the nblocks64 1834 * is too large. This interface should not be used with a nblocks64 that 1835 * represents the driver's idea of how to represent unknown, if nblocks is 1836 * unknown use ddi_prop_op. 1837 */ 1838 int 1839 ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1840 int mod_flags, char *name, caddr_t valuep, int *lengthp, 1841 uint64_t nblocks64, uint_t blksize) 1842 { 1843 uint64_t size64; 1844 int blkshift; 1845 1846 /* convert block size to shift value */ 1847 ASSERT(BIT_ONLYONESET(blksize)); 1848 blkshift = highbit(blksize) - 1; 1849 1850 /* 1851 * There is no point in supporting nblocks64 values that don't have 1852 * an accurate uint64_t byte count representation. 1853 */ 1854 if (nblocks64 >= (UINT64_MAX >> blkshift)) 1855 return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1856 name, valuep, lengthp)); 1857 1858 size64 = nblocks64 << blkshift; 1859 return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags, 1860 name, valuep, lengthp, size64, blksize)); 1861 } 1862 1863 /* 1864 * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize. 1865 */ 1866 int 1867 ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1868 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64) 1869 { 1870 return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, 1871 mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE)); 1872 } 1873 1874 /* 1875 * ddi_prop_op_size_blksize: The basic property operator for block drivers that 1876 * maintain size in bytes. Provides a of dynamic property implementation for 1877 * size oriented properties based on size64 value and blksize passed in by the 1878 * driver. Fallback to ddi_prop_op if the size64 is too large. This interface 1879 * should not be used with a size64 that represents the driver's idea of how 1880 * to represent unknown, if size is unknown use ddi_prop_op. 1881 * 1882 * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned 1883 * integers. While the most likely interface to request them ([bc]devi_size) 1884 * is declared int (signed) there is no enforcement of this, which means we 1885 * can't enforce limitations here without risking regression. 1886 */ 1887 int 1888 ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1889 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64, 1890 uint_t blksize) 1891 { 1892 uint64_t nblocks64; 1893 int callers_length; 1894 caddr_t buffer; 1895 int blkshift; 1896 1897 /* 1898 * This is a kludge to support capture of size(9P) pure dynamic 1899 * properties in snapshots for non-cmlb code (without exposing 1900 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code 1901 * should be removed. 1902 */ 1903 if (i_ddi_prop_dyn_driver_get(dip) == NULL) { 1904 static i_ddi_prop_dyn_t prop_dyn_size[] = { 1905 {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, 1906 {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, 1907 {NULL} 1908 }; 1909 i_ddi_prop_dyn_driver_set(dip, prop_dyn_size); 1910 } 1911 1912 /* convert block size to shift value */ 1913 ASSERT(BIT_ONLYONESET(blksize)); 1914 blkshift = highbit(blksize) - 1; 1915 1916 /* compute DEV_BSIZE nblocks value */ 1917 nblocks64 = size64 >> blkshift; 1918 1919 /* get callers length, establish length of our dynamic properties */ 1920 callers_length = *lengthp; 1921 1922 if (strcmp(name, "Nblocks") == 0) 1923 *lengthp = sizeof (uint64_t); 1924 else if (strcmp(name, "Size") == 0) 1925 *lengthp = sizeof (uint64_t); 1926 else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX)) 1927 *lengthp = sizeof (uint32_t); 1928 else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX)) 1929 *lengthp = sizeof (uint32_t); 1930 else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX)) 1931 *lengthp = sizeof (uint32_t); 1932 else { 1933 /* fallback to ddi_prop_op */ 1934 return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1935 name, valuep, lengthp)); 1936 } 1937 1938 /* service request for the length of the property */ 1939 if (prop_op == PROP_LEN) 1940 return (DDI_PROP_SUCCESS); 1941 1942 switch (prop_op) { 1943 case PROP_LEN_AND_VAL_ALLOC: 1944 if ((buffer = kmem_alloc(*lengthp, 1945 (mod_flags & DDI_PROP_CANSLEEP) ? 1946 KM_SLEEP : KM_NOSLEEP)) == NULL) 1947 return (DDI_PROP_NO_MEMORY); 1948 1949 *(caddr_t *)valuep = buffer; /* set callers buf ptr */ 1950 break; 1951 1952 case PROP_LEN_AND_VAL_BUF: 1953 /* the length of the property and the request must match */ 1954 if (callers_length != *lengthp) 1955 return (DDI_PROP_INVAL_ARG); 1956 1957 buffer = valuep; /* get callers buf ptr */ 1958 break; 1959 1960 default: 1961 return (DDI_PROP_INVAL_ARG); 1962 } 1963 1964 /* transfer the value into the buffer */ 1965 if (strcmp(name, "Nblocks") == 0) 1966 *((uint64_t *)buffer) = nblocks64; 1967 else if (strcmp(name, "Size") == 0) 1968 *((uint64_t *)buffer) = size64; 1969 else if (strcmp(name, "nblocks") == 0) 1970 *((uint32_t *)buffer) = (uint32_t)nblocks64; 1971 else if (strcmp(name, "size") == 0) 1972 *((uint32_t *)buffer) = (uint32_t)size64; 1973 else if (strcmp(name, "blksize") == 0) 1974 *((uint32_t *)buffer) = (uint32_t)blksize; 1975 return (DDI_PROP_SUCCESS); 1976 } 1977 1978 /* 1979 * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size. 1980 */ 1981 int 1982 ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1983 int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64) 1984 { 1985 return (ddi_prop_op_size_blksize(dev, dip, prop_op, 1986 mod_flags, name, valuep, lengthp, size64, DEV_BSIZE)); 1987 } 1988 1989 /* 1990 * Variable length props... 1991 */ 1992 1993 /* 1994 * ddi_getlongprop: Get variable length property len+val into a buffer 1995 * allocated by property provider via kmem_alloc. Requester 1996 * is responsible for freeing returned property via kmem_free. 1997 * 1998 * Arguments: 1999 * 2000 * dev_t: Input: dev_t of property. 2001 * dip: Input: dev_info_t pointer of child. 2002 * flags: Input: Possible flag modifiers are: 2003 * DDI_PROP_DONTPASS: Don't pass to parent if prop not found. 2004 * DDI_PROP_CANSLEEP: Memory allocation may sleep. 2005 * name: Input: name of property. 2006 * valuep: Output: Addr of callers buffer pointer. 2007 * lengthp:Output: *lengthp will contain prop length on exit. 2008 * 2009 * Possible Returns: 2010 * 2011 * DDI_PROP_SUCCESS: Prop found and returned. 2012 * DDI_PROP_NOT_FOUND: Prop not found 2013 * DDI_PROP_UNDEFINED: Prop explicitly undefined. 2014 * DDI_PROP_NO_MEMORY: Prop found, but unable to alloc mem. 2015 */ 2016 2017 int 2018 ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags, 2019 char *name, caddr_t valuep, int *lengthp) 2020 { 2021 return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC, 2022 flags, name, valuep, lengthp)); 2023 } 2024 2025 /* 2026 * 2027 * ddi_getlongprop_buf: Get long prop into pre-allocated callers 2028 * buffer. (no memory allocation by provider). 2029 * 2030 * dev_t: Input: dev_t of property. 2031 * dip: Input: dev_info_t pointer of child. 2032 * flags: Input: DDI_PROP_DONTPASS or NULL 2033 * name: Input: name of property 2034 * valuep: Input: ptr to callers buffer. 2035 * lengthp:I/O: ptr to length of callers buffer on entry, 2036 * actual length of property on exit. 2037 * 2038 * Possible returns: 2039 * 2040 * DDI_PROP_SUCCESS Prop found and returned 2041 * DDI_PROP_NOT_FOUND Prop not found 2042 * DDI_PROP_UNDEFINED Prop explicitly undefined. 2043 * DDI_PROP_BUF_TOO_SMALL Prop found, callers buf too small, 2044 * no value returned, but actual prop 2045 * length returned in *lengthp 2046 * 2047 */ 2048 2049 int 2050 ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags, 2051 char *name, caddr_t valuep, int *lengthp) 2052 { 2053 return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2054 flags, name, valuep, lengthp)); 2055 } 2056 2057 /* 2058 * Integer/boolean sized props. 2059 * 2060 * Call is value only... returns found boolean or int sized prop value or 2061 * defvalue if prop not found or is wrong length or is explicitly undefined. 2062 * Only flag is DDI_PROP_DONTPASS... 2063 * 2064 * By convention, this interface returns boolean (0) sized properties 2065 * as value (int)1. 2066 * 2067 * This never returns an error, if property not found or specifically 2068 * undefined, the input `defvalue' is returned. 2069 */ 2070 2071 int 2072 ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue) 2073 { 2074 int propvalue = defvalue; 2075 int proplength = sizeof (int); 2076 int error; 2077 2078 error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2079 flags, name, (caddr_t)&propvalue, &proplength); 2080 2081 if ((error == DDI_PROP_SUCCESS) && (proplength == 0)) 2082 propvalue = 1; 2083 2084 return (propvalue); 2085 } 2086 2087 /* 2088 * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS 2089 * if returns DDI_PROP_SUCCESS, length returned in *lengthp. 2090 */ 2091 2092 int 2093 ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp) 2094 { 2095 return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp)); 2096 } 2097 2098 /* 2099 * Allocate a struct prop_driver_data, along with 'size' bytes 2100 * for decoded property data. This structure is freed by 2101 * calling ddi_prop_free(9F). 2102 */ 2103 static void * 2104 ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *)) 2105 { 2106 struct prop_driver_data *pdd; 2107 2108 /* 2109 * Allocate a structure with enough memory to store the decoded data. 2110 */ 2111 pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP); 2112 pdd->pdd_size = (sizeof (struct prop_driver_data) + size); 2113 pdd->pdd_prop_free = prop_free; 2114 2115 /* 2116 * Return a pointer to the location to put the decoded data. 2117 */ 2118 return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data))); 2119 } 2120 2121 /* 2122 * Allocated the memory needed to store the encoded data in the property 2123 * handle. 2124 */ 2125 static int 2126 ddi_prop_encode_alloc(prop_handle_t *ph, size_t size) 2127 { 2128 /* 2129 * If size is zero, then set data to NULL and size to 0. This 2130 * is a boolean property. 2131 */ 2132 if (size == 0) { 2133 ph->ph_size = 0; 2134 ph->ph_data = NULL; 2135 ph->ph_cur_pos = NULL; 2136 ph->ph_save_pos = NULL; 2137 } else { 2138 if (ph->ph_flags == DDI_PROP_DONTSLEEP) { 2139 ph->ph_data = kmem_zalloc(size, KM_NOSLEEP); 2140 if (ph->ph_data == NULL) 2141 return (DDI_PROP_NO_MEMORY); 2142 } else 2143 ph->ph_data = kmem_zalloc(size, KM_SLEEP); 2144 ph->ph_size = size; 2145 ph->ph_cur_pos = ph->ph_data; 2146 ph->ph_save_pos = ph->ph_data; 2147 } 2148 return (DDI_PROP_SUCCESS); 2149 } 2150 2151 /* 2152 * Free the space allocated by the lookup routines. Each lookup routine 2153 * returns a pointer to the decoded data to the driver. The driver then 2154 * passes this pointer back to us. This data actually lives in a struct 2155 * prop_driver_data. We use negative indexing to find the beginning of 2156 * the structure and then free the entire structure using the size and 2157 * the free routine stored in the structure. 2158 */ 2159 void 2160 ddi_prop_free(void *datap) 2161 { 2162 struct prop_driver_data *pdd; 2163 2164 /* 2165 * Get the structure 2166 */ 2167 pdd = (struct prop_driver_data *) 2168 ((caddr_t)datap - sizeof (struct prop_driver_data)); 2169 /* 2170 * Call the free routine to free it 2171 */ 2172 (*pdd->pdd_prop_free)(pdd); 2173 } 2174 2175 /* 2176 * Free the data associated with an array of ints, 2177 * allocated with ddi_prop_decode_alloc(). 2178 */ 2179 static void 2180 ddi_prop_free_ints(struct prop_driver_data *pdd) 2181 { 2182 kmem_free(pdd, pdd->pdd_size); 2183 } 2184 2185 /* 2186 * Free a single string property or a single string contained within 2187 * the argv style return value of an array of strings. 2188 */ 2189 static void 2190 ddi_prop_free_string(struct prop_driver_data *pdd) 2191 { 2192 kmem_free(pdd, pdd->pdd_size); 2193 2194 } 2195 2196 /* 2197 * Free an array of strings. 2198 */ 2199 static void 2200 ddi_prop_free_strings(struct prop_driver_data *pdd) 2201 { 2202 kmem_free(pdd, pdd->pdd_size); 2203 } 2204 2205 /* 2206 * Free the data associated with an array of bytes. 2207 */ 2208 static void 2209 ddi_prop_free_bytes(struct prop_driver_data *pdd) 2210 { 2211 kmem_free(pdd, pdd->pdd_size); 2212 } 2213 2214 /* 2215 * Reset the current location pointer in the property handle to the 2216 * beginning of the data. 2217 */ 2218 void 2219 ddi_prop_reset_pos(prop_handle_t *ph) 2220 { 2221 ph->ph_cur_pos = ph->ph_data; 2222 ph->ph_save_pos = ph->ph_data; 2223 } 2224 2225 /* 2226 * Restore the current location pointer in the property handle to the 2227 * saved position. 2228 */ 2229 void 2230 ddi_prop_save_pos(prop_handle_t *ph) 2231 { 2232 ph->ph_save_pos = ph->ph_cur_pos; 2233 } 2234 2235 /* 2236 * Save the location that the current location pointer is pointing to.. 2237 */ 2238 void 2239 ddi_prop_restore_pos(prop_handle_t *ph) 2240 { 2241 ph->ph_cur_pos = ph->ph_save_pos; 2242 } 2243 2244 /* 2245 * Property encode/decode functions 2246 */ 2247 2248 /* 2249 * Decode a single integer property 2250 */ 2251 static int 2252 ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements) 2253 { 2254 int i; 2255 int tmp; 2256 2257 /* 2258 * If there is nothing to decode return an error 2259 */ 2260 if (ph->ph_size == 0) 2261 return (DDI_PROP_END_OF_DATA); 2262 2263 /* 2264 * Decode the property as a single integer and return it 2265 * in data if we were able to decode it. 2266 */ 2267 i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp); 2268 if (i < DDI_PROP_RESULT_OK) { 2269 switch (i) { 2270 case DDI_PROP_RESULT_EOF: 2271 return (DDI_PROP_END_OF_DATA); 2272 2273 case DDI_PROP_RESULT_ERROR: 2274 return (DDI_PROP_CANNOT_DECODE); 2275 } 2276 } 2277 2278 *(int *)data = tmp; 2279 *nelements = 1; 2280 return (DDI_PROP_SUCCESS); 2281 } 2282 2283 /* 2284 * Decode a single 64 bit integer property 2285 */ 2286 static int 2287 ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements) 2288 { 2289 int i; 2290 int64_t tmp; 2291 2292 /* 2293 * If there is nothing to decode return an error 2294 */ 2295 if (ph->ph_size == 0) 2296 return (DDI_PROP_END_OF_DATA); 2297 2298 /* 2299 * Decode the property as a single integer and return it 2300 * in data if we were able to decode it. 2301 */ 2302 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp); 2303 if (i < DDI_PROP_RESULT_OK) { 2304 switch (i) { 2305 case DDI_PROP_RESULT_EOF: 2306 return (DDI_PROP_END_OF_DATA); 2307 2308 case DDI_PROP_RESULT_ERROR: 2309 return (DDI_PROP_CANNOT_DECODE); 2310 } 2311 } 2312 2313 *(int64_t *)data = tmp; 2314 *nelements = 1; 2315 return (DDI_PROP_SUCCESS); 2316 } 2317 2318 /* 2319 * Decode an array of integers property 2320 */ 2321 static int 2322 ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 2323 { 2324 int i; 2325 int cnt = 0; 2326 int *tmp; 2327 int *intp; 2328 int n; 2329 2330 /* 2331 * Figure out how many array elements there are by going through the 2332 * data without decoding it first and counting. 2333 */ 2334 for (;;) { 2335 i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 2336 if (i < 0) 2337 break; 2338 cnt++; 2339 } 2340 2341 /* 2342 * If there are no elements return an error 2343 */ 2344 if (cnt == 0) 2345 return (DDI_PROP_END_OF_DATA); 2346 2347 /* 2348 * If we cannot skip through the data, we cannot decode it 2349 */ 2350 if (i == DDI_PROP_RESULT_ERROR) 2351 return (DDI_PROP_CANNOT_DECODE); 2352 2353 /* 2354 * Reset the data pointer to the beginning of the encoded data 2355 */ 2356 ddi_prop_reset_pos(ph); 2357 2358 /* 2359 * Allocated memory to store the decoded value in. 2360 */ 2361 intp = ddi_prop_decode_alloc((cnt * sizeof (int)), 2362 ddi_prop_free_ints); 2363 2364 /* 2365 * Decode each element and place it in the space we just allocated 2366 */ 2367 tmp = intp; 2368 for (n = 0; n < cnt; n++, tmp++) { 2369 i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp); 2370 if (i < DDI_PROP_RESULT_OK) { 2371 /* 2372 * Free the space we just allocated 2373 * and return an error. 2374 */ 2375 ddi_prop_free(intp); 2376 switch (i) { 2377 case DDI_PROP_RESULT_EOF: 2378 return (DDI_PROP_END_OF_DATA); 2379 2380 case DDI_PROP_RESULT_ERROR: 2381 return (DDI_PROP_CANNOT_DECODE); 2382 } 2383 } 2384 } 2385 2386 *nelements = cnt; 2387 *(int **)data = intp; 2388 2389 return (DDI_PROP_SUCCESS); 2390 } 2391 2392 /* 2393 * Decode a 64 bit integer array property 2394 */ 2395 static int 2396 ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements) 2397 { 2398 int i; 2399 int n; 2400 int cnt = 0; 2401 int64_t *tmp; 2402 int64_t *intp; 2403 2404 /* 2405 * Count the number of array elements by going 2406 * through the data without decoding it. 2407 */ 2408 for (;;) { 2409 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL); 2410 if (i < 0) 2411 break; 2412 cnt++; 2413 } 2414 2415 /* 2416 * If there are no elements return an error 2417 */ 2418 if (cnt == 0) 2419 return (DDI_PROP_END_OF_DATA); 2420 2421 /* 2422 * If we cannot skip through the data, we cannot decode it 2423 */ 2424 if (i == DDI_PROP_RESULT_ERROR) 2425 return (DDI_PROP_CANNOT_DECODE); 2426 2427 /* 2428 * Reset the data pointer to the beginning of the encoded data 2429 */ 2430 ddi_prop_reset_pos(ph); 2431 2432 /* 2433 * Allocate memory to store the decoded value. 2434 */ 2435 intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)), 2436 ddi_prop_free_ints); 2437 2438 /* 2439 * Decode each element and place it in the space allocated 2440 */ 2441 tmp = intp; 2442 for (n = 0; n < cnt; n++, tmp++) { 2443 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp); 2444 if (i < DDI_PROP_RESULT_OK) { 2445 /* 2446 * Free the space we just allocated 2447 * and return an error. 2448 */ 2449 ddi_prop_free(intp); 2450 switch (i) { 2451 case DDI_PROP_RESULT_EOF: 2452 return (DDI_PROP_END_OF_DATA); 2453 2454 case DDI_PROP_RESULT_ERROR: 2455 return (DDI_PROP_CANNOT_DECODE); 2456 } 2457 } 2458 } 2459 2460 *nelements = cnt; 2461 *(int64_t **)data = intp; 2462 2463 return (DDI_PROP_SUCCESS); 2464 } 2465 2466 /* 2467 * Encode an array of integers property (Can be one element) 2468 */ 2469 int 2470 ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements) 2471 { 2472 int i; 2473 int *tmp; 2474 int cnt; 2475 int size; 2476 2477 /* 2478 * If there is no data, we cannot do anything 2479 */ 2480 if (nelements == 0) 2481 return (DDI_PROP_CANNOT_ENCODE); 2482 2483 /* 2484 * Get the size of an encoded int. 2485 */ 2486 size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2487 2488 if (size < DDI_PROP_RESULT_OK) { 2489 switch (size) { 2490 case DDI_PROP_RESULT_EOF: 2491 return (DDI_PROP_END_OF_DATA); 2492 2493 case DDI_PROP_RESULT_ERROR: 2494 return (DDI_PROP_CANNOT_ENCODE); 2495 } 2496 } 2497 2498 /* 2499 * Allocate space in the handle to store the encoded int. 2500 */ 2501 if (ddi_prop_encode_alloc(ph, size * nelements) != 2502 DDI_PROP_SUCCESS) 2503 return (DDI_PROP_NO_MEMORY); 2504 2505 /* 2506 * Encode the array of ints. 2507 */ 2508 tmp = (int *)data; 2509 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2510 i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp); 2511 if (i < DDI_PROP_RESULT_OK) { 2512 switch (i) { 2513 case DDI_PROP_RESULT_EOF: 2514 return (DDI_PROP_END_OF_DATA); 2515 2516 case DDI_PROP_RESULT_ERROR: 2517 return (DDI_PROP_CANNOT_ENCODE); 2518 } 2519 } 2520 } 2521 2522 return (DDI_PROP_SUCCESS); 2523 } 2524 2525 2526 /* 2527 * Encode a 64 bit integer array property 2528 */ 2529 int 2530 ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements) 2531 { 2532 int i; 2533 int cnt; 2534 int size; 2535 int64_t *tmp; 2536 2537 /* 2538 * If there is no data, we cannot do anything 2539 */ 2540 if (nelements == 0) 2541 return (DDI_PROP_CANNOT_ENCODE); 2542 2543 /* 2544 * Get the size of an encoded 64 bit int. 2545 */ 2546 size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2547 2548 if (size < DDI_PROP_RESULT_OK) { 2549 switch (size) { 2550 case DDI_PROP_RESULT_EOF: 2551 return (DDI_PROP_END_OF_DATA); 2552 2553 case DDI_PROP_RESULT_ERROR: 2554 return (DDI_PROP_CANNOT_ENCODE); 2555 } 2556 } 2557 2558 /* 2559 * Allocate space in the handle to store the encoded int. 2560 */ 2561 if (ddi_prop_encode_alloc(ph, size * nelements) != 2562 DDI_PROP_SUCCESS) 2563 return (DDI_PROP_NO_MEMORY); 2564 2565 /* 2566 * Encode the array of ints. 2567 */ 2568 tmp = (int64_t *)data; 2569 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2570 i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp); 2571 if (i < DDI_PROP_RESULT_OK) { 2572 switch (i) { 2573 case DDI_PROP_RESULT_EOF: 2574 return (DDI_PROP_END_OF_DATA); 2575 2576 case DDI_PROP_RESULT_ERROR: 2577 return (DDI_PROP_CANNOT_ENCODE); 2578 } 2579 } 2580 } 2581 2582 return (DDI_PROP_SUCCESS); 2583 } 2584 2585 /* 2586 * Decode a single string property 2587 */ 2588 static int 2589 ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements) 2590 { 2591 char *tmp; 2592 char *str; 2593 int i; 2594 int size; 2595 2596 /* 2597 * If there is nothing to decode return an error 2598 */ 2599 if (ph->ph_size == 0) 2600 return (DDI_PROP_END_OF_DATA); 2601 2602 /* 2603 * Get the decoded size of the encoded string. 2604 */ 2605 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2606 if (size < DDI_PROP_RESULT_OK) { 2607 switch (size) { 2608 case DDI_PROP_RESULT_EOF: 2609 return (DDI_PROP_END_OF_DATA); 2610 2611 case DDI_PROP_RESULT_ERROR: 2612 return (DDI_PROP_CANNOT_DECODE); 2613 } 2614 } 2615 2616 /* 2617 * Allocated memory to store the decoded value in. 2618 */ 2619 str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string); 2620 2621 ddi_prop_reset_pos(ph); 2622 2623 /* 2624 * Decode the str and place it in the space we just allocated 2625 */ 2626 tmp = str; 2627 i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp); 2628 if (i < DDI_PROP_RESULT_OK) { 2629 /* 2630 * Free the space we just allocated 2631 * and return an error. 2632 */ 2633 ddi_prop_free(str); 2634 switch (i) { 2635 case DDI_PROP_RESULT_EOF: 2636 return (DDI_PROP_END_OF_DATA); 2637 2638 case DDI_PROP_RESULT_ERROR: 2639 return (DDI_PROP_CANNOT_DECODE); 2640 } 2641 } 2642 2643 *(char **)data = str; 2644 *nelements = 1; 2645 2646 return (DDI_PROP_SUCCESS); 2647 } 2648 2649 /* 2650 * Decode an array of strings. 2651 */ 2652 int 2653 ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 2654 { 2655 int cnt = 0; 2656 char **strs; 2657 char **tmp; 2658 char *ptr; 2659 int i; 2660 int n; 2661 int size; 2662 size_t nbytes; 2663 2664 /* 2665 * Figure out how many array elements there are by going through the 2666 * data without decoding it first and counting. 2667 */ 2668 for (;;) { 2669 i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL); 2670 if (i < 0) 2671 break; 2672 cnt++; 2673 } 2674 2675 /* 2676 * If there are no elements return an error 2677 */ 2678 if (cnt == 0) 2679 return (DDI_PROP_END_OF_DATA); 2680 2681 /* 2682 * If we cannot skip through the data, we cannot decode it 2683 */ 2684 if (i == DDI_PROP_RESULT_ERROR) 2685 return (DDI_PROP_CANNOT_DECODE); 2686 2687 /* 2688 * Reset the data pointer to the beginning of the encoded data 2689 */ 2690 ddi_prop_reset_pos(ph); 2691 2692 /* 2693 * Figure out how much memory we need for the sum total 2694 */ 2695 nbytes = (cnt + 1) * sizeof (char *); 2696 2697 for (n = 0; n < cnt; n++) { 2698 /* 2699 * Get the decoded size of the current encoded string. 2700 */ 2701 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2702 if (size < DDI_PROP_RESULT_OK) { 2703 switch (size) { 2704 case DDI_PROP_RESULT_EOF: 2705 return (DDI_PROP_END_OF_DATA); 2706 2707 case DDI_PROP_RESULT_ERROR: 2708 return (DDI_PROP_CANNOT_DECODE); 2709 } 2710 } 2711 2712 nbytes += size; 2713 } 2714 2715 /* 2716 * Allocate memory in which to store the decoded strings. 2717 */ 2718 strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings); 2719 2720 /* 2721 * Set up pointers for each string by figuring out yet 2722 * again how long each string is. 2723 */ 2724 ddi_prop_reset_pos(ph); 2725 ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *)); 2726 for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2727 /* 2728 * Get the decoded size of the current encoded string. 2729 */ 2730 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2731 if (size < DDI_PROP_RESULT_OK) { 2732 ddi_prop_free(strs); 2733 switch (size) { 2734 case DDI_PROP_RESULT_EOF: 2735 return (DDI_PROP_END_OF_DATA); 2736 2737 case DDI_PROP_RESULT_ERROR: 2738 return (DDI_PROP_CANNOT_DECODE); 2739 } 2740 } 2741 2742 *tmp = ptr; 2743 ptr += size; 2744 } 2745 2746 /* 2747 * String array is terminated by a NULL 2748 */ 2749 *tmp = NULL; 2750 2751 /* 2752 * Finally, we can decode each string 2753 */ 2754 ddi_prop_reset_pos(ph); 2755 for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2756 i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp); 2757 if (i < DDI_PROP_RESULT_OK) { 2758 /* 2759 * Free the space we just allocated 2760 * and return an error 2761 */ 2762 ddi_prop_free(strs); 2763 switch (i) { 2764 case DDI_PROP_RESULT_EOF: 2765 return (DDI_PROP_END_OF_DATA); 2766 2767 case DDI_PROP_RESULT_ERROR: 2768 return (DDI_PROP_CANNOT_DECODE); 2769 } 2770 } 2771 } 2772 2773 *(char ***)data = strs; 2774 *nelements = cnt; 2775 2776 return (DDI_PROP_SUCCESS); 2777 } 2778 2779 /* 2780 * Encode a string. 2781 */ 2782 int 2783 ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements) 2784 { 2785 char **tmp; 2786 int size; 2787 int i; 2788 2789 /* 2790 * If there is no data, we cannot do anything 2791 */ 2792 if (nelements == 0) 2793 return (DDI_PROP_CANNOT_ENCODE); 2794 2795 /* 2796 * Get the size of the encoded string. 2797 */ 2798 tmp = (char **)data; 2799 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2800 if (size < DDI_PROP_RESULT_OK) { 2801 switch (size) { 2802 case DDI_PROP_RESULT_EOF: 2803 return (DDI_PROP_END_OF_DATA); 2804 2805 case DDI_PROP_RESULT_ERROR: 2806 return (DDI_PROP_CANNOT_ENCODE); 2807 } 2808 } 2809 2810 /* 2811 * Allocate space in the handle to store the encoded string. 2812 */ 2813 if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS) 2814 return (DDI_PROP_NO_MEMORY); 2815 2816 ddi_prop_reset_pos(ph); 2817 2818 /* 2819 * Encode the string. 2820 */ 2821 tmp = (char **)data; 2822 i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2823 if (i < DDI_PROP_RESULT_OK) { 2824 switch (i) { 2825 case DDI_PROP_RESULT_EOF: 2826 return (DDI_PROP_END_OF_DATA); 2827 2828 case DDI_PROP_RESULT_ERROR: 2829 return (DDI_PROP_CANNOT_ENCODE); 2830 } 2831 } 2832 2833 return (DDI_PROP_SUCCESS); 2834 } 2835 2836 2837 /* 2838 * Encode an array of strings. 2839 */ 2840 int 2841 ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements) 2842 { 2843 int cnt = 0; 2844 char **tmp; 2845 int size; 2846 uint_t total_size; 2847 int i; 2848 2849 /* 2850 * If there is no data, we cannot do anything 2851 */ 2852 if (nelements == 0) 2853 return (DDI_PROP_CANNOT_ENCODE); 2854 2855 /* 2856 * Get the total size required to encode all the strings. 2857 */ 2858 total_size = 0; 2859 tmp = (char **)data; 2860 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2861 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2862 if (size < DDI_PROP_RESULT_OK) { 2863 switch (size) { 2864 case DDI_PROP_RESULT_EOF: 2865 return (DDI_PROP_END_OF_DATA); 2866 2867 case DDI_PROP_RESULT_ERROR: 2868 return (DDI_PROP_CANNOT_ENCODE); 2869 } 2870 } 2871 total_size += (uint_t)size; 2872 } 2873 2874 /* 2875 * Allocate space in the handle to store the encoded strings. 2876 */ 2877 if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS) 2878 return (DDI_PROP_NO_MEMORY); 2879 2880 ddi_prop_reset_pos(ph); 2881 2882 /* 2883 * Encode the array of strings. 2884 */ 2885 tmp = (char **)data; 2886 for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2887 i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2888 if (i < DDI_PROP_RESULT_OK) { 2889 switch (i) { 2890 case DDI_PROP_RESULT_EOF: 2891 return (DDI_PROP_END_OF_DATA); 2892 2893 case DDI_PROP_RESULT_ERROR: 2894 return (DDI_PROP_CANNOT_ENCODE); 2895 } 2896 } 2897 } 2898 2899 return (DDI_PROP_SUCCESS); 2900 } 2901 2902 2903 /* 2904 * Decode an array of bytes. 2905 */ 2906 static int 2907 ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 2908 { 2909 uchar_t *tmp; 2910 int nbytes; 2911 int i; 2912 2913 /* 2914 * If there are no elements return an error 2915 */ 2916 if (ph->ph_size == 0) 2917 return (DDI_PROP_END_OF_DATA); 2918 2919 /* 2920 * Get the size of the encoded array of bytes. 2921 */ 2922 nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE, 2923 data, ph->ph_size); 2924 if (nbytes < DDI_PROP_RESULT_OK) { 2925 switch (nbytes) { 2926 case DDI_PROP_RESULT_EOF: 2927 return (DDI_PROP_END_OF_DATA); 2928 2929 case DDI_PROP_RESULT_ERROR: 2930 return (DDI_PROP_CANNOT_DECODE); 2931 } 2932 } 2933 2934 /* 2935 * Allocated memory to store the decoded value in. 2936 */ 2937 tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes); 2938 2939 /* 2940 * Decode each element and place it in the space we just allocated 2941 */ 2942 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 2943 if (i < DDI_PROP_RESULT_OK) { 2944 /* 2945 * Free the space we just allocated 2946 * and return an error 2947 */ 2948 ddi_prop_free(tmp); 2949 switch (i) { 2950 case DDI_PROP_RESULT_EOF: 2951 return (DDI_PROP_END_OF_DATA); 2952 2953 case DDI_PROP_RESULT_ERROR: 2954 return (DDI_PROP_CANNOT_DECODE); 2955 } 2956 } 2957 2958 *(uchar_t **)data = tmp; 2959 *nelements = nbytes; 2960 2961 return (DDI_PROP_SUCCESS); 2962 } 2963 2964 /* 2965 * Encode an array of bytes. 2966 */ 2967 int 2968 ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements) 2969 { 2970 int size; 2971 int i; 2972 2973 /* 2974 * If there are no elements, then this is a boolean property, 2975 * so just create a property handle with no data and return. 2976 */ 2977 if (nelements == 0) { 2978 (void) ddi_prop_encode_alloc(ph, 0); 2979 return (DDI_PROP_SUCCESS); 2980 } 2981 2982 /* 2983 * Get the size of the encoded array of bytes. 2984 */ 2985 size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data, 2986 nelements); 2987 if (size < DDI_PROP_RESULT_OK) { 2988 switch (size) { 2989 case DDI_PROP_RESULT_EOF: 2990 return (DDI_PROP_END_OF_DATA); 2991 2992 case DDI_PROP_RESULT_ERROR: 2993 return (DDI_PROP_CANNOT_DECODE); 2994 } 2995 } 2996 2997 /* 2998 * Allocate space in the handle to store the encoded bytes. 2999 */ 3000 if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS) 3001 return (DDI_PROP_NO_MEMORY); 3002 3003 /* 3004 * Encode the array of bytes. 3005 */ 3006 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data, 3007 nelements); 3008 if (i < DDI_PROP_RESULT_OK) { 3009 switch (i) { 3010 case DDI_PROP_RESULT_EOF: 3011 return (DDI_PROP_END_OF_DATA); 3012 3013 case DDI_PROP_RESULT_ERROR: 3014 return (DDI_PROP_CANNOT_ENCODE); 3015 } 3016 } 3017 3018 return (DDI_PROP_SUCCESS); 3019 } 3020 3021 /* 3022 * OBP 1275 integer, string and byte operators. 3023 * 3024 * DDI_PROP_CMD_DECODE: 3025 * 3026 * DDI_PROP_RESULT_ERROR: cannot decode the data 3027 * DDI_PROP_RESULT_EOF: end of data 3028 * DDI_PROP_OK: data was decoded 3029 * 3030 * DDI_PROP_CMD_ENCODE: 3031 * 3032 * DDI_PROP_RESULT_ERROR: cannot encode the data 3033 * DDI_PROP_RESULT_EOF: end of data 3034 * DDI_PROP_OK: data was encoded 3035 * 3036 * DDI_PROP_CMD_SKIP: 3037 * 3038 * DDI_PROP_RESULT_ERROR: cannot skip the data 3039 * DDI_PROP_RESULT_EOF: end of data 3040 * DDI_PROP_OK: data was skipped 3041 * 3042 * DDI_PROP_CMD_GET_ESIZE: 3043 * 3044 * DDI_PROP_RESULT_ERROR: cannot get encoded size 3045 * DDI_PROP_RESULT_EOF: end of data 3046 * > 0: the encoded size 3047 * 3048 * DDI_PROP_CMD_GET_DSIZE: 3049 * 3050 * DDI_PROP_RESULT_ERROR: cannot get decoded size 3051 * DDI_PROP_RESULT_EOF: end of data 3052 * > 0: the decoded size 3053 */ 3054 3055 /* 3056 * OBP 1275 integer operator 3057 * 3058 * OBP properties are a byte stream of data, so integers may not be 3059 * properly aligned. Therefore we need to copy them one byte at a time. 3060 */ 3061 int 3062 ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 3063 { 3064 int i; 3065 3066 switch (cmd) { 3067 case DDI_PROP_CMD_DECODE: 3068 /* 3069 * Check that there is encoded data 3070 */ 3071 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3072 return (DDI_PROP_RESULT_ERROR); 3073 if (ph->ph_flags & PH_FROM_PROM) { 3074 i = MIN(ph->ph_size, PROP_1275_INT_SIZE); 3075 if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3076 ph->ph_size - i)) 3077 return (DDI_PROP_RESULT_ERROR); 3078 } else { 3079 if (ph->ph_size < sizeof (int) || 3080 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3081 ph->ph_size - sizeof (int)))) 3082 return (DDI_PROP_RESULT_ERROR); 3083 } 3084 3085 /* 3086 * Copy the integer, using the implementation-specific 3087 * copy function if the property is coming from the PROM. 3088 */ 3089 if (ph->ph_flags & PH_FROM_PROM) { 3090 *data = impl_ddi_prop_int_from_prom( 3091 (uchar_t *)ph->ph_cur_pos, 3092 (ph->ph_size < PROP_1275_INT_SIZE) ? 3093 ph->ph_size : PROP_1275_INT_SIZE); 3094 } else { 3095 bcopy(ph->ph_cur_pos, data, sizeof (int)); 3096 } 3097 3098 /* 3099 * Move the current location to the start of the next 3100 * bit of undecoded data. 3101 */ 3102 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3103 PROP_1275_INT_SIZE; 3104 return (DDI_PROP_RESULT_OK); 3105 3106 case DDI_PROP_CMD_ENCODE: 3107 /* 3108 * Check that there is room to encoded the data 3109 */ 3110 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3111 ph->ph_size < PROP_1275_INT_SIZE || 3112 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3113 ph->ph_size - sizeof (int)))) 3114 return (DDI_PROP_RESULT_ERROR); 3115 3116 /* 3117 * Encode the integer into the byte stream one byte at a 3118 * time. 3119 */ 3120 bcopy(data, ph->ph_cur_pos, sizeof (int)); 3121 3122 /* 3123 * Move the current location to the start of the next bit of 3124 * space where we can store encoded data. 3125 */ 3126 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3127 return (DDI_PROP_RESULT_OK); 3128 3129 case DDI_PROP_CMD_SKIP: 3130 /* 3131 * Check that there is encoded data 3132 */ 3133 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3134 ph->ph_size < PROP_1275_INT_SIZE) 3135 return (DDI_PROP_RESULT_ERROR); 3136 3137 3138 if ((caddr_t)ph->ph_cur_pos == 3139 (caddr_t)ph->ph_data + ph->ph_size) { 3140 return (DDI_PROP_RESULT_EOF); 3141 } else if ((caddr_t)ph->ph_cur_pos > 3142 (caddr_t)ph->ph_data + ph->ph_size) { 3143 return (DDI_PROP_RESULT_EOF); 3144 } 3145 3146 /* 3147 * Move the current location to the start of the next bit of 3148 * undecoded data. 3149 */ 3150 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3151 return (DDI_PROP_RESULT_OK); 3152 3153 case DDI_PROP_CMD_GET_ESIZE: 3154 /* 3155 * Return the size of an encoded integer on OBP 3156 */ 3157 return (PROP_1275_INT_SIZE); 3158 3159 case DDI_PROP_CMD_GET_DSIZE: 3160 /* 3161 * Return the size of a decoded integer on the system. 3162 */ 3163 return (sizeof (int)); 3164 3165 default: 3166 #ifdef DEBUG 3167 panic("ddi_prop_1275_int: %x impossible", cmd); 3168 /*NOTREACHED*/ 3169 #else 3170 return (DDI_PROP_RESULT_ERROR); 3171 #endif /* DEBUG */ 3172 } 3173 } 3174 3175 /* 3176 * 64 bit integer operator. 3177 * 3178 * This is an extension, defined by Sun, to the 1275 integer 3179 * operator. This routine handles the encoding/decoding of 3180 * 64 bit integer properties. 3181 */ 3182 int 3183 ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 3184 { 3185 3186 switch (cmd) { 3187 case DDI_PROP_CMD_DECODE: 3188 /* 3189 * Check that there is encoded data 3190 */ 3191 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3192 return (DDI_PROP_RESULT_ERROR); 3193 if (ph->ph_flags & PH_FROM_PROM) { 3194 return (DDI_PROP_RESULT_ERROR); 3195 } else { 3196 if (ph->ph_size < sizeof (int64_t) || 3197 ((int64_t *)ph->ph_cur_pos > 3198 ((int64_t *)ph->ph_data + 3199 ph->ph_size - sizeof (int64_t)))) 3200 return (DDI_PROP_RESULT_ERROR); 3201 } 3202 /* 3203 * Copy the integer, using the implementation-specific 3204 * copy function if the property is coming from the PROM. 3205 */ 3206 if (ph->ph_flags & PH_FROM_PROM) { 3207 return (DDI_PROP_RESULT_ERROR); 3208 } else { 3209 bcopy(ph->ph_cur_pos, data, sizeof (int64_t)); 3210 } 3211 3212 /* 3213 * Move the current location to the start of the next 3214 * bit of undecoded data. 3215 */ 3216 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3217 sizeof (int64_t); 3218 return (DDI_PROP_RESULT_OK); 3219 3220 case DDI_PROP_CMD_ENCODE: 3221 /* 3222 * Check that there is room to encoded the data 3223 */ 3224 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3225 ph->ph_size < sizeof (int64_t) || 3226 ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 3227 ph->ph_size - sizeof (int64_t)))) 3228 return (DDI_PROP_RESULT_ERROR); 3229 3230 /* 3231 * Encode the integer into the byte stream one byte at a 3232 * time. 3233 */ 3234 bcopy(data, ph->ph_cur_pos, sizeof (int64_t)); 3235 3236 /* 3237 * Move the current location to the start of the next bit of 3238 * space where we can store encoded data. 3239 */ 3240 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3241 sizeof (int64_t); 3242 return (DDI_PROP_RESULT_OK); 3243 3244 case DDI_PROP_CMD_SKIP: 3245 /* 3246 * Check that there is encoded data 3247 */ 3248 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3249 ph->ph_size < sizeof (int64_t)) 3250 return (DDI_PROP_RESULT_ERROR); 3251 3252 if ((caddr_t)ph->ph_cur_pos == 3253 (caddr_t)ph->ph_data + ph->ph_size) { 3254 return (DDI_PROP_RESULT_EOF); 3255 } else if ((caddr_t)ph->ph_cur_pos > 3256 (caddr_t)ph->ph_data + ph->ph_size) { 3257 return (DDI_PROP_RESULT_EOF); 3258 } 3259 3260 /* 3261 * Move the current location to the start of 3262 * the next bit of undecoded data. 3263 */ 3264 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3265 sizeof (int64_t); 3266 return (DDI_PROP_RESULT_OK); 3267 3268 case DDI_PROP_CMD_GET_ESIZE: 3269 /* 3270 * Return the size of an encoded integer on OBP 3271 */ 3272 return (sizeof (int64_t)); 3273 3274 case DDI_PROP_CMD_GET_DSIZE: 3275 /* 3276 * Return the size of a decoded integer on the system. 3277 */ 3278 return (sizeof (int64_t)); 3279 3280 default: 3281 #ifdef DEBUG 3282 panic("ddi_prop_int64_op: %x impossible", cmd); 3283 /*NOTREACHED*/ 3284 #else 3285 return (DDI_PROP_RESULT_ERROR); 3286 #endif /* DEBUG */ 3287 } 3288 } 3289 3290 /* 3291 * OBP 1275 string operator. 3292 * 3293 * OBP strings are NULL terminated. 3294 */ 3295 int 3296 ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data) 3297 { 3298 int n; 3299 char *p; 3300 char *end; 3301 3302 switch (cmd) { 3303 case DDI_PROP_CMD_DECODE: 3304 /* 3305 * Check that there is encoded data 3306 */ 3307 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3308 return (DDI_PROP_RESULT_ERROR); 3309 } 3310 3311 /* 3312 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and 3313 * how to NULL terminate result. 3314 */ 3315 p = (char *)ph->ph_cur_pos; 3316 end = (char *)ph->ph_data + ph->ph_size; 3317 if (p >= end) 3318 return (DDI_PROP_RESULT_EOF); 3319 3320 while (p < end) { 3321 *data++ = *p; 3322 if (*p++ == 0) { /* NULL from OBP */ 3323 ph->ph_cur_pos = p; 3324 return (DDI_PROP_RESULT_OK); 3325 } 3326 } 3327 3328 /* 3329 * If OBP did not NULL terminate string, which happens 3330 * (at least) for 'true'/'false' boolean values, account for 3331 * the space and store null termination on decode. 3332 */ 3333 ph->ph_cur_pos = p; 3334 *data = 0; 3335 return (DDI_PROP_RESULT_OK); 3336 3337 case DDI_PROP_CMD_ENCODE: 3338 /* 3339 * Check that there is room to encoded the data 3340 */ 3341 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3342 return (DDI_PROP_RESULT_ERROR); 3343 } 3344 3345 n = strlen(data) + 1; 3346 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3347 ph->ph_size - n)) { 3348 return (DDI_PROP_RESULT_ERROR); 3349 } 3350 3351 /* 3352 * Copy the NULL terminated string 3353 */ 3354 bcopy(data, ph->ph_cur_pos, n); 3355 3356 /* 3357 * Move the current location to the start of the next bit of 3358 * space where we can store encoded data. 3359 */ 3360 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 3361 return (DDI_PROP_RESULT_OK); 3362 3363 case DDI_PROP_CMD_SKIP: 3364 /* 3365 * Check that there is encoded data 3366 */ 3367 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 3368 return (DDI_PROP_RESULT_ERROR); 3369 } 3370 3371 /* 3372 * Return the string length plus one for the NULL 3373 * We know the size of the property, we need to 3374 * ensure that the string is properly formatted, 3375 * since we may be looking up random OBP data. 3376 */ 3377 p = (char *)ph->ph_cur_pos; 3378 end = (char *)ph->ph_data + ph->ph_size; 3379 if (p >= end) 3380 return (DDI_PROP_RESULT_EOF); 3381 3382 while (p < end) { 3383 if (*p++ == 0) { /* NULL from OBP */ 3384 ph->ph_cur_pos = p; 3385 return (DDI_PROP_RESULT_OK); 3386 } 3387 } 3388 3389 /* 3390 * Accommodate the fact that OBP does not always NULL 3391 * terminate strings. 3392 */ 3393 ph->ph_cur_pos = p; 3394 return (DDI_PROP_RESULT_OK); 3395 3396 case DDI_PROP_CMD_GET_ESIZE: 3397 /* 3398 * Return the size of the encoded string on OBP. 3399 */ 3400 return (strlen(data) + 1); 3401 3402 case DDI_PROP_CMD_GET_DSIZE: 3403 /* 3404 * Return the string length plus one for the NULL. 3405 * We know the size of the property, we need to 3406 * ensure that the string is properly formatted, 3407 * since we may be looking up random OBP data. 3408 */ 3409 p = (char *)ph->ph_cur_pos; 3410 end = (char *)ph->ph_data + ph->ph_size; 3411 if (p >= end) 3412 return (DDI_PROP_RESULT_EOF); 3413 3414 for (n = 0; p < end; n++) { 3415 if (*p++ == 0) { /* NULL from OBP */ 3416 ph->ph_cur_pos = p; 3417 return (n + 1); 3418 } 3419 } 3420 3421 /* 3422 * If OBP did not NULL terminate string, which happens for 3423 * 'true'/'false' boolean values, account for the space 3424 * to store null termination here. 3425 */ 3426 ph->ph_cur_pos = p; 3427 return (n + 1); 3428 3429 default: 3430 #ifdef DEBUG 3431 panic("ddi_prop_1275_string: %x impossible", cmd); 3432 /*NOTREACHED*/ 3433 #else 3434 return (DDI_PROP_RESULT_ERROR); 3435 #endif /* DEBUG */ 3436 } 3437 } 3438 3439 /* 3440 * OBP 1275 byte operator 3441 * 3442 * Caller must specify the number of bytes to get. OBP encodes bytes 3443 * as a byte so there is a 1-to-1 translation. 3444 */ 3445 int 3446 ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data, 3447 uint_t nelements) 3448 { 3449 switch (cmd) { 3450 case DDI_PROP_CMD_DECODE: 3451 /* 3452 * Check that there is encoded data 3453 */ 3454 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3455 ph->ph_size < nelements || 3456 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3457 ph->ph_size - nelements))) 3458 return (DDI_PROP_RESULT_ERROR); 3459 3460 /* 3461 * Copy out the bytes 3462 */ 3463 bcopy(ph->ph_cur_pos, data, nelements); 3464 3465 /* 3466 * Move the current location 3467 */ 3468 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3469 return (DDI_PROP_RESULT_OK); 3470 3471 case DDI_PROP_CMD_ENCODE: 3472 /* 3473 * Check that there is room to encode the data 3474 */ 3475 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3476 ph->ph_size < nelements || 3477 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3478 ph->ph_size - nelements))) 3479 return (DDI_PROP_RESULT_ERROR); 3480 3481 /* 3482 * Copy in the bytes 3483 */ 3484 bcopy(data, ph->ph_cur_pos, nelements); 3485 3486 /* 3487 * Move the current location to the start of the next bit of 3488 * space where we can store encoded data. 3489 */ 3490 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3491 return (DDI_PROP_RESULT_OK); 3492 3493 case DDI_PROP_CMD_SKIP: 3494 /* 3495 * Check that there is encoded data 3496 */ 3497 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3498 ph->ph_size < nelements) 3499 return (DDI_PROP_RESULT_ERROR); 3500 3501 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 3502 ph->ph_size - nelements)) 3503 return (DDI_PROP_RESULT_EOF); 3504 3505 /* 3506 * Move the current location 3507 */ 3508 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 3509 return (DDI_PROP_RESULT_OK); 3510 3511 case DDI_PROP_CMD_GET_ESIZE: 3512 /* 3513 * The size in bytes of the encoded size is the 3514 * same as the decoded size provided by the caller. 3515 */ 3516 return (nelements); 3517 3518 case DDI_PROP_CMD_GET_DSIZE: 3519 /* 3520 * Just return the number of bytes specified by the caller. 3521 */ 3522 return (nelements); 3523 3524 default: 3525 #ifdef DEBUG 3526 panic("ddi_prop_1275_bytes: %x impossible", cmd); 3527 /*NOTREACHED*/ 3528 #else 3529 return (DDI_PROP_RESULT_ERROR); 3530 #endif /* DEBUG */ 3531 } 3532 } 3533 3534 /* 3535 * Used for properties that come from the OBP, hardware configuration files, 3536 * or that are created by calls to ddi_prop_update(9F). 3537 */ 3538 static struct prop_handle_ops prop_1275_ops = { 3539 ddi_prop_1275_int, 3540 ddi_prop_1275_string, 3541 ddi_prop_1275_bytes, 3542 ddi_prop_int64_op 3543 }; 3544 3545 3546 /* 3547 * Interface to create/modify a managed property on child's behalf... 3548 * Flags interpreted are: 3549 * DDI_PROP_CANSLEEP: Allow memory allocation to sleep. 3550 * DDI_PROP_SYSTEM_DEF: Manipulate system list rather than driver list. 3551 * 3552 * Use same dev_t when modifying or undefining a property. 3553 * Search for properties with DDI_DEV_T_ANY to match first named 3554 * property on the list. 3555 * 3556 * Properties are stored LIFO and subsequently will match the first 3557 * `matching' instance. 3558 */ 3559 3560 /* 3561 * ddi_prop_add: Add a software defined property 3562 */ 3563 3564 /* 3565 * define to get a new ddi_prop_t. 3566 * km_flags are KM_SLEEP or KM_NOSLEEP. 3567 */ 3568 3569 #define DDI_NEW_PROP_T(km_flags) \ 3570 (kmem_zalloc(sizeof (ddi_prop_t), km_flags)) 3571 3572 static int 3573 ddi_prop_add(dev_t dev, dev_info_t *dip, int flags, 3574 char *name, caddr_t value, int length) 3575 { 3576 ddi_prop_t *new_propp, *propp; 3577 ddi_prop_t **list_head = &(DEVI(dip)->devi_drv_prop_ptr); 3578 int km_flags = KM_NOSLEEP; 3579 int name_buf_len; 3580 3581 /* 3582 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error. 3583 */ 3584 3585 if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0) 3586 return (DDI_PROP_INVAL_ARG); 3587 3588 if (flags & DDI_PROP_CANSLEEP) 3589 km_flags = KM_SLEEP; 3590 3591 if (flags & DDI_PROP_SYSTEM_DEF) 3592 list_head = &(DEVI(dip)->devi_sys_prop_ptr); 3593 else if (flags & DDI_PROP_HW_DEF) 3594 list_head = &(DEVI(dip)->devi_hw_prop_ptr); 3595 3596 if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL) { 3597 cmn_err(CE_CONT, prop_no_mem_msg, name); 3598 return (DDI_PROP_NO_MEMORY); 3599 } 3600 3601 /* 3602 * If dev is major number 0, then we need to do a ddi_name_to_major 3603 * to get the real major number for the device. This needs to be 3604 * done because some drivers need to call ddi_prop_create in their 3605 * attach routines but they don't have a dev. By creating the dev 3606 * ourself if the major number is 0, drivers will not have to know what 3607 * their major number. They can just create a dev with major number 3608 * 0 and pass it in. For device 0, we will be doing a little extra 3609 * work by recreating the same dev that we already have, but its the 3610 * price you pay :-). 3611 * 3612 * This fixes bug #1098060. 3613 */ 3614 if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) { 3615 new_propp->prop_dev = 3616 makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name), 3617 getminor(dev)); 3618 } else 3619 new_propp->prop_dev = dev; 3620 3621 /* 3622 * Allocate space for property name and copy it in... 3623 */ 3624 3625 name_buf_len = strlen(name) + 1; 3626 new_propp->prop_name = kmem_alloc(name_buf_len, km_flags); 3627 if (new_propp->prop_name == 0) { 3628 kmem_free(new_propp, sizeof (ddi_prop_t)); 3629 cmn_err(CE_CONT, prop_no_mem_msg, name); 3630 return (DDI_PROP_NO_MEMORY); 3631 } 3632 bcopy(name, new_propp->prop_name, name_buf_len); 3633 3634 /* 3635 * Set the property type 3636 */ 3637 new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK; 3638 3639 /* 3640 * Set length and value ONLY if not an explicit property undefine: 3641 * NOTE: value and length are zero for explicit undefines. 3642 */ 3643 3644 if (flags & DDI_PROP_UNDEF_IT) { 3645 new_propp->prop_flags |= DDI_PROP_UNDEF_IT; 3646 } else { 3647 if ((new_propp->prop_len = length) != 0) { 3648 new_propp->prop_val = kmem_alloc(length, km_flags); 3649 if (new_propp->prop_val == 0) { 3650 kmem_free(new_propp->prop_name, name_buf_len); 3651 kmem_free(new_propp, sizeof (ddi_prop_t)); 3652 cmn_err(CE_CONT, prop_no_mem_msg, name); 3653 return (DDI_PROP_NO_MEMORY); 3654 } 3655 bcopy(value, new_propp->prop_val, length); 3656 } 3657 } 3658 3659 /* 3660 * Link property into beginning of list. (Properties are LIFO order.) 3661 */ 3662 3663 mutex_enter(&(DEVI(dip)->devi_lock)); 3664 propp = *list_head; 3665 new_propp->prop_next = propp; 3666 *list_head = new_propp; 3667 mutex_exit(&(DEVI(dip)->devi_lock)); 3668 return (DDI_PROP_SUCCESS); 3669 } 3670 3671 3672 /* 3673 * ddi_prop_change: Modify a software managed property value 3674 * 3675 * Set new length and value if found. 3676 * returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or 3677 * input name is the NULL string. 3678 * returns DDI_PROP_NO_MEMORY if unable to allocate memory 3679 * 3680 * Note: an undef can be modified to be a define, 3681 * (you can't go the other way.) 3682 */ 3683 3684 static int 3685 ddi_prop_change(dev_t dev, dev_info_t *dip, int flags, 3686 char *name, caddr_t value, int length) 3687 { 3688 ddi_prop_t *propp; 3689 ddi_prop_t **ppropp; 3690 caddr_t p = NULL; 3691 3692 if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0)) 3693 return (DDI_PROP_INVAL_ARG); 3694 3695 /* 3696 * Preallocate buffer, even if we don't need it... 3697 */ 3698 if (length != 0) { 3699 p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ? 3700 KM_SLEEP : KM_NOSLEEP); 3701 if (p == NULL) { 3702 cmn_err(CE_CONT, prop_no_mem_msg, name); 3703 return (DDI_PROP_NO_MEMORY); 3704 } 3705 } 3706 3707 /* 3708 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major 3709 * number, a real dev_t value should be created based upon the dip's 3710 * binding driver. See ddi_prop_add... 3711 */ 3712 if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) 3713 dev = makedevice( 3714 ddi_name_to_major(DEVI(dip)->devi_binding_name), 3715 getminor(dev)); 3716 3717 /* 3718 * Check to see if the property exists. If so we modify it. 3719 * Else we create it by calling ddi_prop_add(). 3720 */ 3721 mutex_enter(&(DEVI(dip)->devi_lock)); 3722 ppropp = &DEVI(dip)->devi_drv_prop_ptr; 3723 if (flags & DDI_PROP_SYSTEM_DEF) 3724 ppropp = &DEVI(dip)->devi_sys_prop_ptr; 3725 else if (flags & DDI_PROP_HW_DEF) 3726 ppropp = &DEVI(dip)->devi_hw_prop_ptr; 3727 3728 if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) { 3729 /* 3730 * Need to reallocate buffer? If so, do it 3731 * carefully (reuse same space if new prop 3732 * is same size and non-NULL sized). 3733 */ 3734 if (length != 0) 3735 bcopy(value, p, length); 3736 3737 if (propp->prop_len != 0) 3738 kmem_free(propp->prop_val, propp->prop_len); 3739 3740 propp->prop_len = length; 3741 propp->prop_val = p; 3742 propp->prop_flags &= ~DDI_PROP_UNDEF_IT; 3743 mutex_exit(&(DEVI(dip)->devi_lock)); 3744 return (DDI_PROP_SUCCESS); 3745 } 3746 3747 mutex_exit(&(DEVI(dip)->devi_lock)); 3748 if (length != 0) 3749 kmem_free(p, length); 3750 3751 return (ddi_prop_add(dev, dip, flags, name, value, length)); 3752 } 3753 3754 /* 3755 * Common update routine used to update and encode a property. Creates 3756 * a property handle, calls the property encode routine, figures out if 3757 * the property already exists and updates if it does. Otherwise it 3758 * creates if it does not exist. 3759 */ 3760 int 3761 ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags, 3762 char *name, void *data, uint_t nelements, 3763 int (*prop_create)(prop_handle_t *, void *data, uint_t nelements)) 3764 { 3765 prop_handle_t ph; 3766 int rval; 3767 uint_t ourflags; 3768 3769 /* 3770 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3771 * return error. 3772 */ 3773 if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3774 return (DDI_PROP_INVAL_ARG); 3775 3776 /* 3777 * Create the handle 3778 */ 3779 ph.ph_data = NULL; 3780 ph.ph_cur_pos = NULL; 3781 ph.ph_save_pos = NULL; 3782 ph.ph_size = 0; 3783 ph.ph_ops = &prop_1275_ops; 3784 3785 /* 3786 * ourflags: 3787 * For compatibility with the old interfaces. The old interfaces 3788 * didn't sleep by default and slept when the flag was set. These 3789 * interfaces to the opposite. So the old interfaces now set the 3790 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep. 3791 * 3792 * ph.ph_flags: 3793 * Blocked data or unblocked data allocation 3794 * for ph.ph_data in ddi_prop_encode_alloc() 3795 */ 3796 if (flags & DDI_PROP_DONTSLEEP) { 3797 ourflags = flags; 3798 ph.ph_flags = DDI_PROP_DONTSLEEP; 3799 } else { 3800 ourflags = flags | DDI_PROP_CANSLEEP; 3801 ph.ph_flags = DDI_PROP_CANSLEEP; 3802 } 3803 3804 /* 3805 * Encode the data and store it in the property handle by 3806 * calling the prop_encode routine. 3807 */ 3808 if ((rval = (*prop_create)(&ph, data, nelements)) != 3809 DDI_PROP_SUCCESS) { 3810 if (rval == DDI_PROP_NO_MEMORY) 3811 cmn_err(CE_CONT, prop_no_mem_msg, name); 3812 if (ph.ph_size != 0) 3813 kmem_free(ph.ph_data, ph.ph_size); 3814 return (rval); 3815 } 3816 3817 /* 3818 * The old interfaces use a stacking approach to creating 3819 * properties. If we are being called from the old interfaces, 3820 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a 3821 * create without checking. 3822 */ 3823 if (flags & DDI_PROP_STACK_CREATE) { 3824 rval = ddi_prop_add(match_dev, dip, 3825 ourflags, name, ph.ph_data, ph.ph_size); 3826 } else { 3827 rval = ddi_prop_change(match_dev, dip, 3828 ourflags, name, ph.ph_data, ph.ph_size); 3829 } 3830 3831 /* 3832 * Free the encoded data allocated in the prop_encode routine. 3833 */ 3834 if (ph.ph_size != 0) 3835 kmem_free(ph.ph_data, ph.ph_size); 3836 3837 return (rval); 3838 } 3839 3840 3841 /* 3842 * ddi_prop_create: Define a managed property: 3843 * See above for details. 3844 */ 3845 3846 int 3847 ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, 3848 char *name, caddr_t value, int length) 3849 { 3850 if (!(flag & DDI_PROP_CANSLEEP)) { 3851 flag |= DDI_PROP_DONTSLEEP; 3852 #ifdef DDI_PROP_DEBUG 3853 if (length != 0) 3854 cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete," 3855 "use ddi_prop_update (prop = %s, node = %s%d)", 3856 name, ddi_driver_name(dip), ddi_get_instance(dip)); 3857 #endif /* DDI_PROP_DEBUG */ 3858 } 3859 flag &= ~DDI_PROP_SYSTEM_DEF; 3860 flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY; 3861 return (ddi_prop_update_common(dev, dip, flag, name, 3862 value, length, ddi_prop_fm_encode_bytes)); 3863 } 3864 3865 int 3866 e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, 3867 char *name, caddr_t value, int length) 3868 { 3869 if (!(flag & DDI_PROP_CANSLEEP)) 3870 flag |= DDI_PROP_DONTSLEEP; 3871 flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY; 3872 return (ddi_prop_update_common(dev, dip, flag, 3873 name, value, length, ddi_prop_fm_encode_bytes)); 3874 } 3875 3876 int 3877 ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag, 3878 char *name, caddr_t value, int length) 3879 { 3880 ASSERT((flag & DDI_PROP_TYPE_MASK) == 0); 3881 3882 /* 3883 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3884 * return error. 3885 */ 3886 if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3887 return (DDI_PROP_INVAL_ARG); 3888 3889 if (!(flag & DDI_PROP_CANSLEEP)) 3890 flag |= DDI_PROP_DONTSLEEP; 3891 flag &= ~DDI_PROP_SYSTEM_DEF; 3892 if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0) 3893 return (DDI_PROP_NOT_FOUND); 3894 3895 return (ddi_prop_update_common(dev, dip, 3896 (flag | DDI_PROP_TYPE_BYTE), name, 3897 value, length, ddi_prop_fm_encode_bytes)); 3898 } 3899 3900 int 3901 e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag, 3902 char *name, caddr_t value, int length) 3903 { 3904 ASSERT((flag & DDI_PROP_TYPE_MASK) == 0); 3905 3906 /* 3907 * If dev_t is DDI_DEV_T_ANY or name's length is zero, 3908 * return error. 3909 */ 3910 if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0) 3911 return (DDI_PROP_INVAL_ARG); 3912 3913 if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0) 3914 return (DDI_PROP_NOT_FOUND); 3915 3916 if (!(flag & DDI_PROP_CANSLEEP)) 3917 flag |= DDI_PROP_DONTSLEEP; 3918 return (ddi_prop_update_common(dev, dip, 3919 (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE), 3920 name, value, length, ddi_prop_fm_encode_bytes)); 3921 } 3922 3923 3924 /* 3925 * Common lookup routine used to lookup and decode a property. 3926 * Creates a property handle, searches for the raw encoded data, 3927 * fills in the handle, and calls the property decode functions 3928 * passed in. 3929 * 3930 * This routine is not static because ddi_bus_prop_op() which lives in 3931 * ddi_impl.c calls it. No driver should be calling this routine. 3932 */ 3933 int 3934 ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip, 3935 uint_t flags, char *name, void *data, uint_t *nelements, 3936 int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements)) 3937 { 3938 int rval; 3939 uint_t ourflags; 3940 prop_handle_t ph; 3941 3942 if ((match_dev == DDI_DEV_T_NONE) || 3943 (name == NULL) || (strlen(name) == 0)) 3944 return (DDI_PROP_INVAL_ARG); 3945 3946 ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags : 3947 flags | DDI_PROP_CANSLEEP; 3948 3949 /* 3950 * Get the encoded data 3951 */ 3952 bzero(&ph, sizeof (prop_handle_t)); 3953 3954 if ((flags & DDI_UNBND_DLPI2) || (flags & DDI_PROP_ROOTNEX_GLOBAL)) { 3955 /* 3956 * For rootnex and unbound dlpi style-2 devices, index into 3957 * the devnames' array and search the global 3958 * property list. 3959 */ 3960 ourflags &= ~DDI_UNBND_DLPI2; 3961 rval = i_ddi_prop_search_global(match_dev, 3962 ourflags, name, &ph.ph_data, &ph.ph_size); 3963 } else { 3964 rval = ddi_prop_search_common(match_dev, dip, 3965 PROP_LEN_AND_VAL_ALLOC, ourflags, name, 3966 &ph.ph_data, &ph.ph_size); 3967 3968 } 3969 3970 if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) { 3971 ASSERT(ph.ph_data == NULL); 3972 ASSERT(ph.ph_size == 0); 3973 return (rval); 3974 } 3975 3976 /* 3977 * If the encoded data came from a OBP or software 3978 * use the 1275 OBP decode/encode routines. 3979 */ 3980 ph.ph_cur_pos = ph.ph_data; 3981 ph.ph_save_pos = ph.ph_data; 3982 ph.ph_ops = &prop_1275_ops; 3983 ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0; 3984 3985 rval = (*prop_decoder)(&ph, data, nelements); 3986 3987 /* 3988 * Free the encoded data 3989 */ 3990 if (ph.ph_size != 0) 3991 kmem_free(ph.ph_data, ph.ph_size); 3992 3993 return (rval); 3994 } 3995 3996 /* 3997 * Lookup and return an array of composite properties. The driver must 3998 * provide the decode routine. 3999 */ 4000 int 4001 ddi_prop_lookup(dev_t match_dev, dev_info_t *dip, 4002 uint_t flags, char *name, void *data, uint_t *nelements, 4003 int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements)) 4004 { 4005 return (ddi_prop_lookup_common(match_dev, dip, 4006 (flags | DDI_PROP_TYPE_COMPOSITE), name, 4007 data, nelements, prop_decoder)); 4008 } 4009 4010 /* 4011 * Return 1 if a property exists (no type checking done). 4012 * Return 0 if it does not exist. 4013 */ 4014 int 4015 ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name) 4016 { 4017 int i; 4018 uint_t x = 0; 4019 4020 i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS, 4021 flags | DDI_PROP_TYPE_MASK, name, NULL, &x); 4022 return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275); 4023 } 4024 4025 4026 /* 4027 * Update an array of composite properties. The driver must 4028 * provide the encode routine. 4029 */ 4030 int 4031 ddi_prop_update(dev_t match_dev, dev_info_t *dip, 4032 char *name, void *data, uint_t nelements, 4033 int (*prop_create)(prop_handle_t *, void *data, uint_t nelements)) 4034 { 4035 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE, 4036 name, data, nelements, prop_create)); 4037 } 4038 4039 /* 4040 * Get a single integer or boolean property and return it. 4041 * If the property does not exists, or cannot be decoded, 4042 * then return the defvalue passed in. 4043 * 4044 * This routine always succeeds. 4045 */ 4046 int 4047 ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags, 4048 char *name, int defvalue) 4049 { 4050 int data; 4051 uint_t nelements; 4052 int rval; 4053 4054 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4055 LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) { 4056 #ifdef DEBUG 4057 if (dip != NULL) { 4058 cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag" 4059 " 0x%x (prop = %s, node = %s%d)", flags, 4060 name, ddi_driver_name(dip), ddi_get_instance(dip)); 4061 } 4062 #endif /* DEBUG */ 4063 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4064 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4065 } 4066 4067 if ((rval = ddi_prop_lookup_common(match_dev, dip, 4068 (flags | DDI_PROP_TYPE_INT), name, &data, &nelements, 4069 ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) { 4070 if (rval == DDI_PROP_END_OF_DATA) 4071 data = 1; 4072 else 4073 data = defvalue; 4074 } 4075 return (data); 4076 } 4077 4078 /* 4079 * Get a single 64 bit integer or boolean property and return it. 4080 * If the property does not exists, or cannot be decoded, 4081 * then return the defvalue passed in. 4082 * 4083 * This routine always succeeds. 4084 */ 4085 int64_t 4086 ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags, 4087 char *name, int64_t defvalue) 4088 { 4089 int64_t data; 4090 uint_t nelements; 4091 int rval; 4092 4093 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4094 LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) { 4095 #ifdef DEBUG 4096 if (dip != NULL) { 4097 cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag" 4098 " 0x%x (prop = %s, node = %s%d)", flags, 4099 name, ddi_driver_name(dip), ddi_get_instance(dip)); 4100 } 4101 #endif /* DEBUG */ 4102 return (DDI_PROP_INVAL_ARG); 4103 } 4104 4105 if ((rval = ddi_prop_lookup_common(match_dev, dip, 4106 (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM), 4107 name, &data, &nelements, ddi_prop_fm_decode_int64)) 4108 != DDI_PROP_SUCCESS) { 4109 if (rval == DDI_PROP_END_OF_DATA) 4110 data = 1; 4111 else 4112 data = defvalue; 4113 } 4114 return (data); 4115 } 4116 4117 /* 4118 * Get an array of integer property 4119 */ 4120 int 4121 ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4122 char *name, int **data, uint_t *nelements) 4123 { 4124 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4125 LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) { 4126 #ifdef DEBUG 4127 if (dip != NULL) { 4128 cmn_err(CE_WARN, "ddi_prop_lookup_int_array: " 4129 "invalid flag 0x%x (prop = %s, node = %s%d)", 4130 flags, name, ddi_driver_name(dip), 4131 ddi_get_instance(dip)); 4132 } 4133 #endif /* DEBUG */ 4134 flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4135 LDI_DEV_T_ANY | DDI_UNBND_DLPI2; 4136 } 4137 4138 return (ddi_prop_lookup_common(match_dev, dip, 4139 (flags | DDI_PROP_TYPE_INT), name, data, 4140 nelements, ddi_prop_fm_decode_ints)); 4141 } 4142 4143 /* 4144 * Get an array of 64 bit integer properties 4145 */ 4146 int 4147 ddi_prop_lookup_int64_array(dev_t match_dev, dev_info_t *dip, uint_t flags, 4148 char *name, int64_t **data, uint_t *nelements) 4149 { 4150 if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | 4151 LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) { 4152 #ifdef DEBUG 4153 if (dip != NULL) { 4154 cmn_err(CE_WARN, "ddi_prop_lookup_int64_array: " 4155 "invalid flag 0x%x (prop = %s, node = %s%d)", 4156 flags, name, ddi_driver_name(dip), 4157 ddi_get_instance(dip)); 4158 } 4159 #endif /* DEBUG */ 4160 return (DDI_PROP_INVAL_ARG); 4161 } 4162 4163 return (ddi_prop_lookup_common(match_dev, dip, 4164 (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM), 4165 name, data, nelements, ddi_prop_fm_decode_int64_array)); 4166 } 4167 4168 /* 4169 * Update a single integer property. If the property exists on the drivers 4170 * property list it updates, else it creates it. 4171 */ 4172 int 4173 ddi_prop_update_int(dev_t match_dev, dev_info_t *dip, 4174 char *name, int data) 4175 { 4176 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT, 4177 name, &data, 1, ddi_prop_fm_encode_ints)); 4178 } 4179 4180 /* 4181 * Update a single 64 bit integer property. 4182 * Update the driver property list if it exists, else create it. 4183 */ 4184 int 4185 ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip, 4186 char *name, int64_t data) 4187 { 4188 return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64, 4189 name, &data, 1, ddi_prop_fm_encode_int64)); 4190 } 4191 4192 int 4193 e_ddi_prop_update_int(dev_t match_dev, dev_info_t *dip, 4194 char *name, int data) 4195 { 4196 return (ddi_prop_update_common(match_dev, dip, 4197 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT, 4198 name, &data, 1, ddi_prop_fm_encode_ints)); 4199 } 4200 4201 int 4202 e_ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip, 4203 char *name, int64_t data) 4204 { 4205 return (ddi_prop_update_common(match_dev, dip, 4206 DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64, 4207 name, &data, 1, ddi_prop_fm_encode_int64)); 4208 } 4209 4210 /* 4211 * Update an array of integer property. If the property exists on the drivers 4212 * property list it updates, else it creates it. 4213 */ 4214 int 4215 ddi_prop_update_int_array(dev_t match_dev,