The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/common/os/sunddi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a8f75c0b9def2529681b2c532b90f605


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.