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