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