Home | History | Annotate | Download | only in os
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1106       mrj  * Common Development and Distribution License (the "License").
      6   1106       mrj  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21   1106       mrj 
     22      0    stevel /*
     23   8561     Scott  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0    stevel  * Use is subject to license terms.
     25      0    stevel  */
     26      0    stevel 
     27      0    stevel #include <sys/note.h>
     28      0    stevel #include <sys/types.h>
     29      0    stevel #include <sys/param.h>
     30      0    stevel #include <sys/systm.h>
     31      0    stevel #include <sys/buf.h>
     32      0    stevel #include <sys/uio.h>
     33      0    stevel #include <sys/cred.h>
     34      0    stevel #include <sys/poll.h>
     35      0    stevel #include <sys/mman.h>
     36      0    stevel #include <sys/kmem.h>
     37      0    stevel #include <sys/model.h>
     38      0    stevel #include <sys/file.h>
     39      0    stevel #include <sys/proc.h>
     40      0    stevel #include <sys/open.h>
     41      0    stevel #include <sys/user.h>
     42      0    stevel #include <sys/t_lock.h>
     43      0    stevel #include <sys/vm.h>
     44      0    stevel #include <sys/stat.h>
     45      0    stevel #include <vm/hat.h>
     46      0    stevel #include <vm/seg.h>
     47      0    stevel #include <vm/seg_vn.h>
     48      0    stevel #include <vm/seg_dev.h>
     49      0    stevel #include <vm/as.h>
     50      0    stevel #include <sys/cmn_err.h>
     51      0    stevel #include <sys/cpuvar.h>
     52      0    stevel #include <sys/debug.h>
     53      0    stevel #include <sys/autoconf.h>
     54      0    stevel #include <sys/sunddi.h>
     55      0    stevel #include <sys/esunddi.h>
     56      0    stevel #include <sys/sunndi.h>
     57      0    stevel #include <sys/kstat.h>
     58      0    stevel #include <sys/conf.h>
     59      0    stevel #include <sys/ddi_impldefs.h>	/* include implementation structure defs */
     60      0    stevel #include <sys/ndi_impldefs.h>	/* include prototypes */
     61   5107      eota #include <sys/ddi_timer.h>
     62      0    stevel #include <sys/hwconf.h>
     63      0    stevel #include <sys/pathname.h>
     64      0    stevel #include <sys/modctl.h>
     65      0    stevel #include <sys/epm.h>
     66      0    stevel #include <sys/devctl.h>
     67      0    stevel #include <sys/callb.h>
     68      0    stevel #include <sys/cladm.h>
     69      0    stevel #include <sys/sysevent.h>
     70      0    stevel #include <sys/dacf_impl.h>
     71      0    stevel #include <sys/ddidevmap.h>
     72      0    stevel #include <sys/bootconf.h>
     73      0    stevel #include <sys/disp.h>
     74      0    stevel #include <sys/atomic.h>
     75      0    stevel #include <sys/promif.h>
     76      0    stevel #include <sys/instance.h>
     77      0    stevel #include <sys/sysevent/eventdefs.h>
     78      0    stevel #include <sys/task.h>
     79      0    stevel #include <sys/project.h>
     80      0    stevel #include <sys/taskq.h>
     81      0    stevel #include <sys/devpolicy.h>
     82      0    stevel #include <sys/ctype.h>
     83      0    stevel #include <net/if.h>
     84   2768  sl108498 #include <sys/rctl.h>
     85   8662    Jordan #include <sys/zone.h>
     86  11066    rafael #include <sys/clock_impl.h>
     87  10696     David #include <sys/ddi.h>
     88      0    stevel 
     89      0    stevel extern	pri_t	minclsyspri;
     90      0    stevel 
     91   2768  sl108498 extern	rctl_hndl_t rc_project_locked_mem;
     92   2768  sl108498 extern	rctl_hndl_t rc_zone_locked_mem;
     93      0    stevel 
     94      0    stevel #ifdef DEBUG
     95      0    stevel static int sunddi_debug = 0;
     96      0    stevel #endif /* DEBUG */
     97      0    stevel 
     98      0    stevel /* ddi_umem_unlock miscellaneous */
     99      0    stevel 
    100      0    stevel static	void	i_ddi_umem_unlock_thread_start(void);
    101      0    stevel 
    102      0    stevel static	kmutex_t	ddi_umem_unlock_mutex; /* unlock list mutex */
    103      0    stevel static	kcondvar_t	ddi_umem_unlock_cv; /* unlock list block/unblock */
    104      0    stevel static	kthread_t	*ddi_umem_unlock_thread;
    105      0    stevel /*
    106      0    stevel  * The ddi_umem_unlock FIFO list.  NULL head pointer indicates empty list.
    107      0    stevel  */
    108      0    stevel static	struct	ddi_umem_cookie *ddi_umem_unlock_head = NULL;
    109      0    stevel static	struct	ddi_umem_cookie *ddi_umem_unlock_tail = NULL;
    110      0    stevel 
    111      0    stevel /*
    112      0    stevel  * DDI(Sun) Function and flag definitions:
    113      0    stevel  */
    114      0    stevel 
    115      0    stevel #if defined(__x86)
    116      0    stevel /*
    117      0    stevel  * Used to indicate which entries were chosen from a range.
    118      0    stevel  */
    119      0    stevel char	*chosen_reg = "chosen-reg";
    120      0    stevel #endif
    121      0    stevel 
    122      0    stevel /*
    123      0    stevel  * Function used to ring system console bell
    124      0    stevel  */
    125      0    stevel void (*ddi_console_bell_func)(clock_t duration);
    126      0    stevel 
    127      0    stevel /*
    128      0    stevel  * Creating register mappings and handling interrupts:
    129      0    stevel  */
    130      0    stevel 
    131      0    stevel /*
    132      0    stevel  * Generic ddi_map: Call parent to fulfill request...
    133      0    stevel  */
    134      0    stevel 
    135      0    stevel int
    136      0    stevel ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset,
    137      0    stevel     off_t len, caddr_t *addrp)
    138      0    stevel {
    139      0    stevel 	dev_info_t *pdip;
    140      0    stevel 
    141      0    stevel 	ASSERT(dp);
    142      0    stevel 	pdip = (dev_info_t *)DEVI(dp)->devi_parent;
    143      0    stevel 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
    144      0    stevel 	    dp, mp, offset, len, addrp));
    145      0    stevel }
    146      0    stevel 
    147      0    stevel /*
    148      0    stevel  * ddi_apply_range: (Called by nexi only.)
    149      0    stevel  * Apply ranges in parent node dp, to child regspec rp...
    150      0    stevel  */
    151      0    stevel 
    152      0    stevel int
    153      0    stevel ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp)
    154      0    stevel {
    155      0    stevel 	return (i_ddi_apply_range(dp, rdip, rp));
    156      0    stevel }
    157      0    stevel 
    158      0    stevel int
    159      0    stevel ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
    160      0    stevel     off_t len)
    161      0    stevel {
    162      0    stevel 	ddi_map_req_t mr;
    163      0    stevel #if defined(__x86)
    164      0    stevel 	struct {
    165      0    stevel 		int	bus;
    166      0    stevel 		int	addr;
    167      0    stevel 		int	size;
    168      0    stevel 	} reg, *reglist;
    169      0    stevel 	uint_t	length;
    170      0    stevel 	int	rc;
    171      0    stevel 
    172      0    stevel 	/*
    173      0    stevel 	 * get the 'registers' or the 'reg' property.
    174      0    stevel 	 * We look up the reg property as an array of
    175      0    stevel 	 * int's.
    176      0    stevel 	 */
    177      0    stevel 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
    178      0    stevel 	    DDI_PROP_DONTPASS, "registers", (int **)&reglist, &length);
    179      0    stevel 	if (rc != DDI_PROP_SUCCESS)
    180      0    stevel 		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
    181      0    stevel 		    DDI_PROP_DONTPASS, "reg", (int **)&reglist, &length);
    182      0    stevel 	if (rc == DDI_PROP_SUCCESS) {
    183      0    stevel 		/*
    184      0    stevel 		 * point to the required entry.
    185      0    stevel 		 */
    186      0    stevel 		reg = reglist[rnumber];
    187      0    stevel 		reg.addr += offset;
    188      0    stevel 		if (len != 0)
    189      0    stevel 			reg.size = len;
    190      0    stevel 		/*
    191      0    stevel 		 * make a new property containing ONLY the required tuple.
    192      0    stevel 		 */
    193      0    stevel 		if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
    194      0    stevel 		    chosen_reg, (int *)&reg, (sizeof (reg)/sizeof (int)))
    195      0    stevel 		    != DDI_PROP_SUCCESS) {
    196      0    stevel 			cmn_err(CE_WARN, "%s%d: cannot create '%s' "
    197      0    stevel 			    "property", DEVI(dip)->devi_name,
    198      0    stevel 			    DEVI(dip)->devi_instance, chosen_reg);
    199      0    stevel 		}
    200      0    stevel 		/*
    201      0    stevel 		 * free the memory allocated by
    202      0    stevel 		 * ddi_prop_lookup_int_array ().
    203      0    stevel 		 */
    204      0    stevel 		ddi_prop_free((void *)reglist);
    205      0    stevel 	}
    206      0    stevel #endif
    207      0    stevel 	mr.map_op = DDI_MO_MAP_LOCKED;
    208      0    stevel 	mr.map_type = DDI_MT_RNUMBER;
    209      0    stevel 	mr.map_obj.rnumber = rnumber;
    210      0    stevel 	mr.map_prot = PROT_READ | PROT_WRITE;
    211      0    stevel 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
    212      0    stevel 	mr.map_handlep = NULL;
    213      0    stevel 	mr.map_vers = DDI_MAP_VERSION;
    214      0    stevel 
    215      0    stevel 	/*
    216      0    stevel 	 * Call my parent to map in my regs.
    217      0    stevel 	 */
    218      0    stevel 
    219      0    stevel 	return (ddi_map(dip, &mr, offset, len, kaddrp));
    220      0    stevel }
    221      0    stevel 
    222      0    stevel void
    223      0    stevel ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
    224      0    stevel     off_t len)
    225      0    stevel {
    226      0    stevel 	ddi_map_req_t mr;
    227      0    stevel 
    228      0    stevel 	mr.map_op = DDI_MO_UNMAP;
    229      0    stevel 	mr.map_type = DDI_MT_RNUMBER;
    230      0    stevel 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
    231      0    stevel 	mr.map_prot = PROT_READ | PROT_WRITE;	/* who cares? */
    232      0    stevel 	mr.map_obj.rnumber = rnumber;
    233      0    stevel 	mr.map_handlep = NULL;
    234      0    stevel 	mr.map_vers = DDI_MAP_VERSION;
    235      0    stevel 
    236      0    stevel 	/*
    237      0    stevel 	 * Call my parent to unmap my regs.
    238      0    stevel 	 */
    239      0    stevel 
    240      0    stevel 	(void) ddi_map(dip, &mr, offset, len, kaddrp);
    241      0    stevel 	*kaddrp = (caddr_t)0;
    242      0    stevel #if defined(__x86)
    243      0    stevel 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg);
    244      0    stevel #endif
    245      0    stevel }
    246      0    stevel 
    247      0    stevel int
    248      0    stevel ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
    249      0    stevel 	off_t offset, off_t len, caddr_t *vaddrp)
    250      0    stevel {
    251      0    stevel 	return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
    252      0    stevel }
    253      0    stevel 
    254      0    stevel /*
    255      0    stevel  * nullbusmap:	The/DDI default bus_map entry point for nexi
    256      0    stevel  *		not conforming to the reg/range paradigm (i.e. scsi, etc.)
    257      0    stevel  *		with no HAT/MMU layer to be programmed at this level.
    258      0    stevel  *
    259      0    stevel  *		If the call is to map by rnumber, return an error,
    260      0    stevel  *		otherwise pass anything else up the tree to my parent.
    261      0    stevel  */
    262      0    stevel int
    263      0    stevel nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
    264      0    stevel 	off_t offset, off_t len, caddr_t *vaddrp)
    265      0    stevel {
    266      0    stevel 	_NOTE(ARGUNUSED(rdip))
    267      0    stevel 	if (mp->map_type == DDI_MT_RNUMBER)
    268      0    stevel 		return (DDI_ME_UNSUPPORTED);
    269      0    stevel 
    270      0    stevel 	return (ddi_map(dip, mp, offset, len, vaddrp));
    271      0    stevel }
    272      0    stevel 
    273      0    stevel /*
    274      0    stevel  * ddi_rnumber_to_regspec: Not for use by leaf drivers.
    275      0    stevel  *			   Only for use by nexi using the reg/range paradigm.
    276      0    stevel  */
    277      0    stevel struct regspec *
    278      0    stevel ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber)
    279      0    stevel {
    280      0    stevel 	return (i_ddi_rnumber_to_regspec(dip, rnumber));
    281      0    stevel }
    282      0    stevel 
    283      0    stevel 
    284      0    stevel /*
    285      0    stevel  * Note that we allow the dip to be nil because we may be called
    286      0    stevel  * prior even to the instantiation of the devinfo tree itself - all
    287      0    stevel  * regular leaf and nexus drivers should always use a non-nil dip!
    288      0    stevel  *
    289      0    stevel  * We treat peek in a somewhat cavalier fashion .. assuming that we'll
    290      0    stevel  * simply get a synchronous fault as soon as we touch a missing address.
    291      0    stevel  *
    292      0    stevel  * Poke is rather more carefully handled because we might poke to a write
    293      0    stevel  * buffer, "succeed", then only find some time later that we got an
    294      0    stevel  * asynchronous fault that indicated that the address we were writing to
    295      0    stevel  * was not really backed by hardware.
    296      0    stevel  */
    297      0    stevel 
    298      0    stevel static int
    299      0    stevel i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size,
    300      0    stevel     void *addr, void *value_p)
    301      0    stevel {
    302      0    stevel 	union {
    303      0    stevel 		uint64_t	u64;
    304      0    stevel 		uint32_t	u32;
    305      0    stevel 		uint16_t	u16;
    306      0    stevel 		uint8_t		u8;
    307      0    stevel 	} peekpoke_value;
    308      0    stevel 
    309      0    stevel 	peekpoke_ctlops_t peekpoke_args;
    310      0    stevel 	uint64_t dummy_result;
    311      0    stevel 	int rval;
    312      0    stevel 
    313      0    stevel 	/* Note: size is assumed to be correct;  it is not checked. */
    314      0    stevel 	peekpoke_args.size = size;
    315     42     agiri 	peekpoke_args.dev_addr = (uintptr_t)addr;
    316      0    stevel 	peekpoke_args.handle = NULL;
    317      0    stevel 	peekpoke_args.repcount = 1;
    318      0    stevel 	peekpoke_args.flags = 0;
    319      0    stevel 
    320      0    stevel 	if (cmd == DDI_CTLOPS_POKE) {
    321      0    stevel 		switch (size) {
    322      0    stevel 		case sizeof (uint8_t):
    323      0    stevel 			peekpoke_value.u8 = *(uint8_t *)value_p;
    324      0    stevel 			break;
    325      0    stevel 		case sizeof (uint16_t):
    326      0    stevel 			peekpoke_value.u16 = *(uint16_t *)value_p;
    327      0    stevel 			break;
    328      0    stevel 		case sizeof (uint32_t):
    329      0    stevel 			peekpoke_value.u32 = *(uint32_t *)value_p;
    330      0    stevel 			break;
    331      0    stevel 		case sizeof (uint64_t):
    332      0    stevel 			peekpoke_value.u64 = *(uint64_t *)value_p;
    333      0    stevel 			break;
    334      0    stevel 		}
    335      0    stevel 	}
    336      0    stevel 
    337     42     agiri 	peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64;
    338      0    stevel 
    339      0    stevel 	if (devi != NULL)
    340      0    stevel 		rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args,
    341      0    stevel 		    &dummy_result);
    342      0    stevel 	else
    343      0    stevel 		rval = peekpoke_mem(cmd, &peekpoke_args);
    344      0    stevel 
    345      0    stevel 	/*
    346      0    stevel 	 * A NULL value_p is permitted by ddi_peek(9F); discard the result.
    347      0    stevel 	 */
    348      0    stevel 	if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) {
    349      0    stevel 		switch (size) {
    350      0    stevel 		case sizeof (uint8_t):
    351      0    stevel 			*(uint8_t *)value_p = peekpoke_value.u8;
    352      0    stevel 			break;
    353      0    stevel 		case sizeof (uint16_t):
    354      0    stevel 			*(uint16_t *)value_p = peekpoke_value.u16;
    355      0    stevel 			break;
    356      0    stevel 		case sizeof (uint32_t):
    357      0    stevel 			*(uint32_t *)value_p = peekpoke_value.u32;
    358      0    stevel 			break;
    359      0    stevel 		case sizeof (uint64_t):
    360      0    stevel 			*(uint64_t *)value_p = peekpoke_value.u64;
    361      0    stevel 			break;
    362      0    stevel 		}
    363      0    stevel 	}
    364      0    stevel 
    365      0    stevel 	return (rval);
    366      0    stevel }
    367      0    stevel 
    368      0    stevel /*
    369      0    stevel  * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this.
    370      0    stevel  * they shouldn't be, but the 9f manpage kind of pseudo exposes it.
    371      0    stevel  */
    372      0    stevel int
    373      0    stevel ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p)
    374      0    stevel {
    375      0    stevel 	switch (size) {
    376      0    stevel 	case sizeof (uint8_t):
    377      0    stevel 	case sizeof (uint16_t):
    378      0    stevel 	case sizeof (uint32_t):
    379      0    stevel 	case sizeof (uint64_t):
    380      0    stevel 		break;
    381      0    stevel 	default:
    382      0    stevel 		return (DDI_FAILURE);
    383      0    stevel 	}
    384      0    stevel 
    385      0    stevel 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p));
    386      0    stevel }
    387      0    stevel 
    388      0    stevel int
    389      0    stevel ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p)
    390      0    stevel {
    391      0    stevel 	switch (size) {
    392      0    stevel 	case sizeof (uint8_t):
    393      0    stevel 	case sizeof (uint16_t):
    394      0    stevel 	case sizeof (uint32_t):
    395      0    stevel 	case sizeof (uint64_t):
    396      0    stevel 		break;
    397      0    stevel 	default:
    398      0    stevel 		return (DDI_FAILURE);
    399      0    stevel 	}
    400      0    stevel 
    401      0    stevel 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p));
    402      0    stevel }
    403      0    stevel 
    404      0    stevel int
    405      0    stevel ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p)
    406      0    stevel {
    407      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    408      0    stevel 	    val_p));
    409      0    stevel }
    410      0    stevel 
    411      0    stevel int
    412      0    stevel ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p)
    413      0    stevel {
    414      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    415      0    stevel 	    val_p));
    416      0    stevel }
    417      0    stevel 
    418      0    stevel int
    419      0    stevel ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p)
    420      0    stevel {
    421      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    422      0    stevel 	    val_p));
    423      0    stevel }
    424      0    stevel 
    425      0    stevel int
    426      0    stevel ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p)
    427      0    stevel {
    428      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    429      0    stevel 	    val_p));
    430      0    stevel }
    431      0    stevel 
    432   1106       mrj 
    433   1106       mrj /*
    434   1106       mrj  * We need to separate the old interfaces from the new ones and leave them
    435   1106       mrj  * in here for a while. Previous versions of the OS defined the new interfaces
    436   1106       mrj  * to the old interfaces. This way we can fix things up so that we can
    437   1106       mrj  * eventually remove these interfaces.
    438   1106       mrj  * e.g. A 3rd party module/driver using ddi_peek8 and built against S10
    439   1106       mrj  * or earlier will actually have a reference to ddi_peekc in the binary.
    440   1106       mrj  */
    441   1106       mrj #ifdef _ILP32
    442   1106       mrj int
    443   1106       mrj ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p)
    444   1106       mrj {
    445   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    446   1106       mrj 	    val_p));
    447   1106       mrj }
    448   1106       mrj 
    449   1106       mrj int
    450   1106       mrj ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p)
    451   1106       mrj {
    452   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    453   1106       mrj 	    val_p));
    454   1106       mrj }
    455   1106       mrj 
    456   1106       mrj int
    457   1106       mrj ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p)
    458   1106       mrj {
    459   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    460   1106       mrj 	    val_p));
    461   1106       mrj }
    462   1106       mrj 
    463   1106       mrj int
    464   1106       mrj ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p)
    465   1106       mrj {
    466   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
    467   1106       mrj 	    val_p));
    468   1106       mrj }
    469   1106       mrj #endif /* _ILP32 */
    470   1106       mrj 
    471      0    stevel int
    472      0    stevel ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
    473   1106       mrj {
    474   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    475   1106       mrj }
    476   1106       mrj 
    477   1106       mrj int
    478   1106       mrj ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
    479   1106       mrj {
    480   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    481   1106       mrj }
    482   1106       mrj 
    483   1106       mrj int
    484   1106       mrj ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
    485   1106       mrj {
    486   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    487   1106       mrj }
    488   1106       mrj 
    489   1106       mrj int
    490   1106       mrj ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
    491   1106       mrj {
    492   1106       mrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    493   1106       mrj }
    494   1106       mrj 
    495   1106       mrj /*
    496   1106       mrj  * We need to separate the old interfaces from the new ones and leave them
    497   1106       mrj  * in here for a while. Previous versions of the OS defined the new interfaces
    498   1106       mrj  * to the old interfaces. This way we can fix things up so that we can
    499   1106       mrj  * eventually remove these interfaces.
    500   1106       mrj  * e.g. A 3rd party module/driver using ddi_poke8 and built against S10
    501   1106       mrj  * or earlier will actually have a reference to ddi_pokec in the binary.
    502   1106       mrj  */
    503   1106       mrj #ifdef _ILP32
    504      0    stevel int
    505      0    stevel ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val)
    506      0    stevel {
    507      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    508      0    stevel }
    509      0    stevel 
    510      0    stevel int
    511      0    stevel ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val)
    512      0    stevel {
    513      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    514      0    stevel }
    515      0    stevel 
    516      0    stevel int
    517      0    stevel ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val)
    518      0    stevel {
    519      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    520      0    stevel }
    521      0    stevel 
    522      0    stevel int
    523      0    stevel ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val)
    524      0    stevel {
    525      0    stevel 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
    526      0    stevel }
    527   1106       mrj #endif /* _ILP32 */
    528      0    stevel 
    529      0    stevel /*
    530      0    stevel  * ddi_peekpokeio() is used primarily by the mem drivers for moving
    531      0    stevel  * data to and from uio structures via peek and poke.  Note that we
    532      0    stevel  * use "internal" routines ddi_peek and ddi_poke to make this go
    533      0    stevel  * slightly faster, avoiding the call overhead ..
    534      0    stevel  */
    535      0    stevel int
    536      0    stevel ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
    537      0    stevel     caddr_t addr, size_t len, uint_t xfersize)
    538      0    stevel {
    539      0    stevel 	int64_t	ibuffer;
    540      0    stevel 	int8_t w8;
    541      0    stevel 	size_t sz;
    542      0    stevel 	int o;
    543      0    stevel 
    544      0    stevel 	if (xfersize > sizeof (long))
    545      0    stevel 		xfersize = sizeof (long);
    546      0    stevel 
    547      0    stevel 	while (len != 0) {
    548      0    stevel 		if ((len | (uintptr_t)addr) & 1) {
    549      0    stevel 			sz = sizeof (int8_t);
    550      0    stevel 			if (rw == UIO_WRITE) {
    551      0    stevel 				if ((o = uwritec(uio)) == -1)
    552      0    stevel 					return (DDI_FAILURE);
    553      0    stevel 				if (ddi_poke8(devi, (int8_t *)addr,
    554      0    stevel 				    (int8_t)o) != DDI_SUCCESS)
    555      0    stevel 					return (DDI_FAILURE);
    556      0    stevel 			} else {
    557      0    stevel 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
    558      0    stevel 				    (int8_t *)addr, &w8) != DDI_SUCCESS)
    559      0    stevel 					return (DDI_FAILURE);
    560      0    stevel 				if (ureadc(w8, uio))
    561      0    stevel 					return (DDI_FAILURE);
    562      0    stevel 			}
    563      0    stevel 		} else {
    564      0    stevel 			switch (xfersize) {
    565      0    stevel 			case sizeof (int64_t):
    566      0    stevel 				if (((len | (uintptr_t)addr) &
    567      0    stevel 				    (sizeof (int64_t) - 1)) == 0) {
    568      0    stevel 					sz = xfersize;
    569      0    stevel 					break;
    570      0    stevel 				}
    571      0    stevel 				/*FALLTHROUGH*/
    572      0    stevel 			case sizeof (int32_t):
    573      0    stevel 				if (((len | (uintptr_t)addr) &
    574      0    stevel 				    (sizeof (int32_t) - 1)) == 0) {
    575      0    stevel 					sz = xfersize;
    576      0    stevel 					break;
    577      0    stevel 				}
    578      0    stevel 				/*FALLTHROUGH*/
    579      0    stevel 			default:
    580      0    stevel 				/*
    581      0    stevel 				 * This still assumes that we might have an
    582      0    stevel 				 * I/O bus out there that permits 16-bit
    583      0    stevel 				 * transfers (and that it would be upset by
    584      0    stevel 				 * 32-bit transfers from such locations).
    585      0    stevel 				 */
    586      0    stevel 				sz = sizeof (int16_t);
    587      0    stevel 				break;
    588      0    stevel 			}
    589      0    stevel 
    590      0    stevel 			if (rw == UIO_READ) {
    591      0    stevel 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
    592      0    stevel 				    addr, &ibuffer) != DDI_SUCCESS)
    593      0    stevel 					return (DDI_FAILURE);
    594      0    stevel 			}
    595      0    stevel 
    596      0    stevel 			if (uiomove(&ibuffer, sz, rw, uio))
    597      0    stevel 				return (DDI_FAILURE);
    598      0    stevel 
    599      0    stevel 			if (rw == UIO_WRITE) {
    600      0    stevel 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
    601      0    stevel 				    addr, &ibuffer) != DDI_SUCCESS)
    602      0    stevel 					return (DDI_FAILURE);
    603      0    stevel 			}
    604      0    stevel 		}
    605      0    stevel 		addr += sz;
    606      0    stevel 		len -= sz;
    607      0    stevel 	}
    608      0    stevel 	return (DDI_SUCCESS);
    609      0    stevel }
    610      0    stevel 
    611      0    stevel /*
    612      0    stevel  * These routines are used by drivers that do layered ioctls
    613      0    stevel  * On sparc, they're implemented in assembler to avoid spilling
    614      0    stevel  * register windows in the common (copyin) case ..
    615      0    stevel  */
    616      0    stevel #if !defined(__sparc)
    617      0    stevel int
    618      0    stevel ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
    619      0    stevel {
    620      0    stevel 	if (flags & FKIOCTL)
    621      0    stevel 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
    622      0    stevel 	return (copyin(buf, kernbuf, size));
    623      0    stevel }
    624      0    stevel 
    625      0    stevel int
    626      0    stevel ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
    627      0    stevel {
    628      0    stevel 	if (flags & FKIOCTL)
    629      0    stevel 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
    630      0    stevel 	return (copyout(buf, kernbuf, size));
    631      0    stevel }
    632      0    stevel #endif	/* !__sparc */
    633      0    stevel 
    634      0    stevel /*
    635      0    stevel  * Conversions in nexus pagesize units.  We don't duplicate the
    636      0    stevel  * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
    637      0    stevel  * routines anyway.
    638      0    stevel  */
    639      0    stevel unsigned long
    640      0    stevel ddi_btop(dev_info_t *dip, unsigned long bytes)
    641      0    stevel {
    642      0    stevel 	unsigned long pages;
    643      0    stevel 
    644      0    stevel 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
    645      0    stevel 	return (pages);
    646      0    stevel }
    647      0    stevel 
    648      0    stevel unsigned long
    649      0    stevel ddi_btopr(dev_info_t *dip, unsigned long bytes)
    650      0    stevel {
    651      0    stevel 	unsigned long pages;
    652      0    stevel 
    653      0    stevel 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
    654      0    stevel 	return (pages);
    655      0    stevel }
    656      0    stevel 
    657      0    stevel unsigned long
    658      0    stevel ddi_ptob(dev_info_t *dip, unsigned long pages)
    659      0    stevel {
    660      0    stevel 	unsigned long bytes;
    661      0    stevel 
    662      0    stevel 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
    663      0    stevel 	return (bytes);
    664      0    stevel }
    665      0    stevel 
    666      0    stevel unsigned int
    667      0    stevel ddi_enter_critical(void)
    668      0    stevel {
    669      0    stevel 	return ((uint_t)spl7());
    670      0    stevel }
    671      0    stevel 
    672      0    stevel void
    673      0    stevel ddi_exit_critical(unsigned int spl)
    674      0    stevel {
    675      0    stevel 	splx((int)spl);
    676      0    stevel }
    677      0    stevel 
    678      0    stevel /*
    679      0    stevel  * Nexus ctlops punter
    680      0    stevel  */
    681      0    stevel 
    682      0    stevel #if !defined(__sparc)
    683      0    stevel /*
    684      0    stevel  * Request bus_ctl parent to handle a bus_ctl request
    685      0    stevel  *
    686      0    stevel  * (The sparc version is in sparc_ddi.s)
    687      0    stevel  */
    688      0    stevel int
    689      0    stevel ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
    690      0    stevel {
    691      0    stevel 	int (*fp)();
    692      0    stevel 
    693      0    stevel 	if (!d || !r)
    694      0    stevel 		return (DDI_FAILURE);
    695      0    stevel 
    696      0    stevel 	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
    697      0    stevel 		return (DDI_FAILURE);
    698      0    stevel 
    699      0    stevel 	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
    700      0    stevel 	return ((*fp)(d, r, op, a, v));
    701      0    stevel }
    702      0    stevel 
    703      0    stevel #endif
    704      0    stevel 
    705      0    stevel /*
    706      0    stevel  * DMA/DVMA setup
    707      0    stevel  */
    708      0    stevel 
    709      0    stevel #if defined(__sparc)
    710      0    stevel static ddi_dma_lim_t standard_limits = {
    711      0    stevel 	(uint_t)0,	/* addr_t dlim_addr_lo */
    712      0    stevel 	(uint_t)-1,	/* addr_t dlim_addr_hi */
    713      0    stevel 	(uint_t)-1,	/* uint_t dlim_cntr_max */
    714      0    stevel 	(uint_t)1,	/* uint_t dlim_burstsizes */
    715      0    stevel 	(uint_t)1,	/* uint_t dlim_minxfer */
    716      0    stevel 	0		/* uint_t dlim_dmaspeed */
    717      0    stevel };
    718      0    stevel #elif defined(__x86)
    719      0    stevel static ddi_dma_lim_t standard_limits = {
    720      0    stevel 	(uint_t)0,		/* addr_t dlim_addr_lo */
    721      0    stevel 	(uint_t)0xffffff,	/* addr_t dlim_addr_hi */
    722      0    stevel 	(uint_t)0,		/* uint_t dlim_cntr_max */
    723      0    stevel 	(uint_t)0x00000001,	/* uint_t dlim_burstsizes */
    724      0    stevel 	(uint_t)DMA_UNIT_8,	/* uint_t dlim_minxfer */
    725      0    stevel 	(uint_t)0,		/* uint_t dlim_dmaspeed */
    726      0    stevel 	(uint_t)0x86<<24+0,	/* uint_t dlim_version */
    727      0    stevel 	(uint_t)0xffff,		/* uint_t dlim_adreg_max */
    728      0    stevel 	(uint_t)0xffff,		/* uint_t dlim_ctreg_max */
    729      0    stevel 	(uint_t)512,		/* uint_t dlim_granular */
    730      0    stevel 	(int)1,			/* int dlim_sgllen */
    731      0    stevel 	(uint_t)0xffffffff	/* uint_t dlim_reqsizes */
    732      0    stevel };
    733      0    stevel 
    734      0    stevel #endif
    735      0    stevel 
    736      0    stevel int
    737      0    stevel ddi_dma_setup(dev_info_t *dip, struct ddi_dma_req *dmareqp,
    738      0    stevel     ddi_dma_handle_t *handlep)
    739      0    stevel {
    740      0    stevel 	int (*funcp)() = ddi_dma_map;
    741      0    stevel 	struct bus_ops *bop;
    742      0    stevel #if defined(__sparc)
    743      0    stevel 	auto ddi_dma_lim_t dma_lim;
    744      0    stevel 
    745      0    stevel 	if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) {
    746      0    stevel 		dma_lim = standard_limits;
    747      0    stevel 	} else {
    748      0    stevel 		dma_lim = *dmareqp->dmar_limits;
    749      0    stevel 	}
    750      0    stevel 	dmareqp->dmar_limits = &dma_lim;
    751      0    stevel #endif
    752      0    stevel #if defined(__x86)
    753      0    stevel 	if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0)
    754      0    stevel 		return (DDI_FAILURE);
    755      0    stevel #endif
    756      0    stevel 
    757      0    stevel 	/*
    758      0    stevel 	 * Handle the case that the requester is both a leaf
    759      0    stevel 	 * and a nexus driver simultaneously by calling the
    760      0    stevel 	 * requester's bus_dma_map function directly instead
    761      0    stevel 	 * of ddi_dma_map.
    762      0    stevel 	 */
    763      0    stevel 	bop = DEVI(dip)->devi_ops->devo_bus_ops;
    764      0    stevel 	if (bop && bop->bus_dma_map)
    765      0    stevel 		funcp = bop->bus_dma_map;
    766      0    stevel 	return ((*funcp)(dip, dip, dmareqp, handlep));
    767      0    stevel }
    768      0    stevel 
    769      0    stevel int
    770      0    stevel ddi_dma_addr_setup(dev_info_t *dip, struct as *as, caddr_t addr, size_t len,
    771      0    stevel     uint_t flags, int (*waitfp)(), caddr_t arg,
    772      0    stevel     ddi_dma_lim_t *limits, ddi_dma_handle_t *handlep)
    773      0    stevel {
    774      0    stevel 	int (*funcp)() = ddi_dma_map;
    775      0    stevel 	ddi_dma_lim_t dma_lim;
    776      0    stevel 	struct ddi_dma_req dmareq;
    777      0    stevel 	struct bus_ops *bop;
    778      0    stevel 
    779      0    stevel 	if (len == 0) {
    780      0    stevel 		return (DDI_DMA_NOMAPPING);
    781      0    stevel 	}
    782      0    stevel 	if (limits == (ddi_dma_lim_t *)0) {
    783      0    stevel 		dma_lim = standard_limits;
    784      0    stevel 	} else {
    785      0    stevel 		dma_lim = *limits;
    786      0    stevel 	}
    787      0    stevel 	dmareq.dmar_limits = &dma_lim;
    788      0    stevel 	dmareq.dmar_flags = flags;
    789      0    stevel 	dmareq.dmar_fp = waitfp;
    790      0    stevel 	dmareq.dmar_arg = arg;
    791      0    stevel 	dmareq.dmar_object.dmao_size = len;
    792      0    stevel 	dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR;
    793      0    stevel 	dmareq.dmar_object.dmao_obj.virt_obj.v_as = as;
    794      0    stevel 	dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr;
    795      0    stevel 	dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL;
    796      0    stevel 
    797      0    stevel 	/*
    798      0    stevel 	 * Handle the case that the requester is both a leaf
    799      0    stevel 	 * and a nexus driver simultaneously by calling the
    800      0    stevel 	 * requester's bus_dma_map function directly instead
    801      0    stevel 	 * of ddi_dma_map.
    802      0    stevel 	 */
    803      0    stevel 	bop = DEVI(dip)->devi_ops->devo_bus_ops;
    804      0    stevel 	if (bop && bop->bus_dma_map)
    805      0    stevel 		funcp = bop->bus_dma_map;
    806      0    stevel 
    807      0    stevel 	return ((*funcp)(dip, dip, &dmareq, handlep));
    808      0    stevel }
    809      0    stevel 
    810      0    stevel int
    811      0    stevel ddi_dma_buf_setup(dev_info_t *dip, struct buf *bp, uint_t flags,
    812      0    stevel     int (*waitfp)(), caddr_t arg, ddi_dma_lim_t *limits,
    813      0    stevel     ddi_dma_handle_t *handlep)
    814      0    stevel {
    815      0    stevel 	int (*funcp)() = ddi_dma_map;
    816      0    stevel 	ddi_dma_lim_t dma_lim;
    817      0    stevel 	struct ddi_dma_req dmareq;
    818      0    stevel 	struct bus_ops *bop;
    819      0    stevel 
    820      0    stevel 	if (limits == (ddi_dma_lim_t *)0) {
    821      0    stevel 		dma_lim = standard_limits;
    822      0    stevel 	} else {
    823      0    stevel 		dma_lim = *limits;
    824      0    stevel 	}
    825      0    stevel 	dmareq.dmar_limits = &dma_lim;
    826      0    stevel 	dmareq.dmar_flags = flags;
    827      0    stevel 	dmareq.dmar_fp = waitfp;
    828      0    stevel 	dmareq.dmar_arg = arg;
    829      0    stevel 	dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount;
    830      0    stevel 
    831   1299       cth 	if (bp->b_flags & B_PAGEIO) {
    832      0    stevel 		dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES;
    833      0    stevel 		dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages;
    834      0    stevel 		dmareq.dmar_object.dmao_obj.pp_obj.pp_offset =
    835      0    stevel 		    (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET);
    836      0    stevel 	} else {
    837      0    stevel 		dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR;
    838      0    stevel 		dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr;
    839   1299       cth 		if (bp->b_flags & B_SHADOW) {
    840      0    stevel 			dmareq.dmar_object.dmao_obj.virt_obj.v_priv =
    841   4582       cth 			    bp->b_shadow;
    842      0    stevel 		} else {
    843      0    stevel 			dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL;
    844      0    stevel 		}
    845      0    stevel 
    846      0    stevel 		/*
    847      0    stevel 		 * If the buffer has no proc pointer, or the proc
    848      0    stevel 		 * struct has the kernel address space, or the buffer has
    849      0    stevel 		 * been marked B_REMAPPED (meaning that it is now
    850      0    stevel 		 * mapped into the kernel's address space), then
    851      0    stevel 		 * the address space is kas (kernel address space).
    852      0    stevel 		 */
    853   1299       cth 		if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) ||
    854   1299       cth 		    (bp->b_flags & B_REMAPPED)) {
    855      0    stevel 			dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0;
    856      0    stevel 		} else {
    857      0    stevel 			dmareq.dmar_object.dmao_obj.virt_obj.v_as =
    858      0    stevel 			    bp->b_proc->p_as;
    859      0    stevel 		}
    860      0    stevel 	}
    861      0    stevel 
    862      0    stevel 	/*
    863      0    stevel 	 * Handle the case that the requester is both a leaf
    864      0    stevel 	 * and a nexus driver simultaneously by calling the
    865      0    stevel 	 * requester's bus_dma_map function directly instead
    866      0    stevel 	 * of ddi_dma_map.
    867      0    stevel 	 */
    868      0    stevel 	bop = DEVI(dip)->devi_ops->devo_bus_ops;
    869      0    stevel 	if (bop && bop->bus_dma_map)
    870      0    stevel 		funcp = bop->bus_dma_map;
    871      0    stevel 
    872      0    stevel 	return ((*funcp)(dip, dip, &dmareq, handlep));
    873      0    stevel }
    874      0    stevel 
    875      0    stevel #if !defined(__sparc)
    876      0    stevel /*
    877      0    stevel  * Request bus_dma_ctl parent to fiddle with a dma request.
    878      0    stevel  *
    879      0    stevel  * (The sparc version is in sparc_subr.s)
    880      0    stevel  */
    881      0    stevel int
    882      0    stevel ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
    883      0    stevel     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
    884      0    stevel     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
    885      0    stevel {
    886      0    stevel 	int (*fp)();
    887      0    stevel 
    888  10216    Vikram 	if (dip != ddi_root_node())
    889  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
    890      0    stevel 	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
    891      0    stevel 	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
    892      0    stevel }
    893      0    stevel #endif
    894      0    stevel 
    895      0    stevel /*
    896      0    stevel  * For all DMA control functions, call the DMA control
    897      0    stevel  * routine and return status.
    898      0    stevel  *
    899      0    stevel  * Just plain assume that the parent is to be called.
    900      0    stevel  * If a nexus driver or a thread outside the framework
    901      0    stevel  * of a nexus driver or a leaf driver calls these functions,
    902      0    stevel  * it is up to them to deal with the fact that the parent's
    903      0    stevel  * bus_dma_ctl function will be the first one called.
    904      0    stevel  */
    905      0    stevel 
    906      0    stevel #define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
    907      0    stevel 
    908      0    stevel int
    909      0    stevel ddi_dma_kvaddrp(ddi_dma_handle_t h, off_t off, size_t len, caddr_t *kp)
    910      0    stevel {
    911      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_KVADDR, &off, &len, kp, 0));
    912      0    stevel }
    913      0    stevel 
    914      0    stevel int
    915      0    stevel ddi_dma_htoc(ddi_dma_handle_t h, off_t o, ddi_dma_cookie_t *c)
    916      0    stevel {
    917      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_HTOC, &o, 0, (caddr_t *)c, 0));
    918      0    stevel }
    919      0    stevel 
    920      0    stevel int
    921      0    stevel ddi_dma_coff(ddi_dma_handle_t h, ddi_dma_cookie_t *c, off_t *o)
    922      0    stevel {
    923      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_COFF,
    924      0    stevel 	    (off_t *)c, 0, (caddr_t *)o, 0));
    925      0    stevel }
    926      0    stevel 
    927      0    stevel int
    928      0    stevel ddi_dma_movwin(ddi_dma_handle_t h, off_t *o, size_t *l, ddi_dma_cookie_t *c)
    929      0    stevel {
    930      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_MOVWIN, o,
    931      0    stevel 	    l, (caddr_t *)c, 0));
    932      0    stevel }
    933      0    stevel 
    934      0    stevel int
    935      0    stevel ddi_dma_curwin(ddi_dma_handle_t h, off_t *o, size_t *l)
    936      0    stevel {
    937      0    stevel 	if ((((ddi_dma_impl_t *)h)->dmai_rflags & DDI_DMA_PARTIAL) == 0)
    938      0    stevel 		return (DDI_FAILURE);
    939      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_REPWIN, o, l, 0, 0));
    940      0    stevel }
    941      0    stevel 
    942      0    stevel int
    943      0    stevel ddi_dma_nextwin(ddi_dma_handle_t h, ddi_dma_win_t win,
    944      0    stevel     ddi_dma_win_t *nwin)
    945      0    stevel {
    946      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTWIN, (off_t *)&win, 0,
    947      0    stevel 	    (caddr_t *)nwin, 0));
    948      0    stevel }
    949      0    stevel 
    950      0    stevel int
    951      0    stevel ddi_dma_nextseg(ddi_dma_win_t win, ddi_dma_seg_t seg, ddi_dma_seg_t *nseg)
    952      0    stevel {
    953      0    stevel 	ddi_dma_handle_t h = (ddi_dma_handle_t)win;
    954      0    stevel 
    955      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTSEG, (off_t *)&win,
    956      0    stevel 	    (size_t *)&seg, (caddr_t *)nseg, 0));
    957      0    stevel }
    958      0    stevel 
    959      0    stevel #if (defined(__i386) && !defined(__amd64)) || defined(__sparc)
    960      0    stevel /*
    961      0    stevel  * This routine is Obsolete and should be removed from ALL architectures
    962      0    stevel  * in a future release of Solaris.
    963      0    stevel  *
    964      0    stevel  * It is deliberately NOT ported to amd64; please fix the code that
    965      0    stevel  * depends on this routine to use ddi_dma_nextcookie(9F).
    966    509       mrj  *
    967    509       mrj  * NOTE: even though we fixed the pointer through a 32-bit param issue (the fix
    968    509       mrj  * is a side effect to some other cleanup), we're still not going to support
    969    509       mrj  * this interface on x64.
    970      0    stevel  */
    971      0    stevel int
    972      0    stevel ddi_dma_segtocookie(ddi_dma_seg_t seg, off_t *o, off_t *l,
    973      0    stevel     ddi_dma_cookie_t *cookiep)
    974      0    stevel {
    975      0    stevel 	ddi_dma_handle_t h = (ddi_dma_handle_t)seg;
    976      0    stevel 
    977      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SEGTOC, o, (size_t *)l,
    978      0    stevel 	    (caddr_t *)cookiep, 0));
    979      0    stevel }
    980      0    stevel #endif	/* (__i386 && !__amd64) || __sparc */
    981      0    stevel 
    982      0    stevel #if !defined(__sparc)
    983      0    stevel 
    984      0    stevel /*
    985      0    stevel  * The SPARC versions of these routines are done in assembler to
    986      0    stevel  * save register windows, so they're in sparc_subr.s.
    987      0    stevel  */
    988      0    stevel 
    989      0    stevel int
    990      0    stevel ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
    991      0    stevel 	struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
    992      0    stevel {
    993      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, struct ddi_dma_req *,
    994      0    stevel 	    ddi_dma_handle_t *);
    995      0    stevel 
    996  10216    Vikram 	if (dip != ddi_root_node())
    997  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_map;
    998  10216    Vikram 
    999  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_map;
   1000  10216    Vikram 	return ((*funcp)(dip, rdip, dmareqp, handlep));
   1001      0    stevel }
   1002      0    stevel 
   1003      0    stevel int
   1004      0    stevel ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
   1005      0    stevel     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
   1006      0    stevel {
   1007      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
   1008      0    stevel 	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
   1009      0    stevel 
   1010  10216    Vikram 	if (dip != ddi_root_node())
   1011  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
   1012  10216    Vikram 
   1013  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
   1014  10216    Vikram 	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
   1015      0    stevel }
   1016      0    stevel 
   1017      0    stevel int
   1018      0    stevel ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
   1019      0    stevel {
   1020      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
   1021      0    stevel 
   1022  10216    Vikram 	if (dip != ddi_root_node())
   1023  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
   1024  10216    Vikram 
   1025  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
   1026  10216    Vikram 	return ((*funcp)(dip, rdip, handlep));
   1027      0    stevel }
   1028      0    stevel 
   1029      0    stevel int
   1030      0    stevel ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
   1031      0    stevel     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
   1032      0    stevel     ddi_dma_cookie_t *cp, uint_t *ccountp)
   1033      0    stevel {
   1034      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
   1035      0    stevel 	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
   1036      0    stevel 
   1037  10216    Vikram 	if (dip != ddi_root_node())
   1038  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
   1039  10216    Vikram 
   1040  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
   1041  10216    Vikram 	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
   1042      0    stevel }
   1043      0    stevel 
   1044      0    stevel int
   1045      0    stevel ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
   1046      0    stevel     ddi_dma_handle_t handle)
   1047      0    stevel {
   1048      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
   1049      0    stevel 
   1050  10216    Vikram 	if (dip != ddi_root_node())
   1051  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
   1052  10216    Vikram 
   1053  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
   1054  10216    Vikram 	return ((*funcp)(dip, rdip, handle));
   1055      0    stevel }
   1056      0    stevel 
   1057      0    stevel 
   1058      0    stevel int
   1059      0    stevel ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
   1060      0    stevel     ddi_dma_handle_t handle, off_t off, size_t len,
   1061      0    stevel     uint_t cache_flags)
   1062      0    stevel {
   1063      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
   1064      0    stevel 	    off_t, size_t, uint_t);
   1065      0    stevel 
   1066  10216    Vikram 	if (dip != ddi_root_node())
   1067  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
   1068  10216    Vikram 
   1069  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
   1070  10216    Vikram 	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
   1071      0    stevel }
   1072      0    stevel 
   1073      0    stevel int
   1074      0    stevel ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
   1075      0    stevel     ddi_dma_handle_t handle, uint_t win, off_t *offp,
   1076      0    stevel     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
   1077      0    stevel {
   1078      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
   1079      0    stevel 	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
   1080      0    stevel 
   1081  10216    Vikram 	if (dip != ddi_root_node())
   1082  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
   1083  10216    Vikram 
   1084  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
   1085  10216    Vikram 	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
   1086      0    stevel 	    cookiep, ccountp));
   1087      0    stevel }
   1088      0    stevel 
   1089      0    stevel int
   1090      0    stevel ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
   1091      0    stevel {
   1092      0    stevel 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
   1093  10216    Vikram 	dev_info_t *dip, *rdip;
   1094      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
   1095   4582       cth 	    size_t, uint_t);
   1096      0    stevel 
   1097      0    stevel 	/*
   1098      0    stevel 	 * the DMA nexus driver will set DMP_NOSYNC if the
   1099      0    stevel 	 * platform does not require any sync operation. For
   1100      0    stevel 	 * example if the memory is uncached or consistent
   1101      0    stevel 	 * and without any I/O write buffers involved.
   1102      0    stevel 	 */
   1103      0    stevel 	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
   1104      0    stevel 		return (DDI_SUCCESS);
   1105      0    stevel 
   1106  10216    Vikram 	dip = rdip = hp->dmai_rdip;
   1107  10216    Vikram 	if (dip != ddi_root_node())
   1108  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
   1109  10216    Vikram 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
   1110  10216    Vikram 	return ((*funcp)(dip, rdip, h, o, l, whom));
   1111      0    stevel }
   1112      0    stevel 
   1113      0    stevel int
   1114      0    stevel ddi_dma_unbind_handle(ddi_dma_handle_t h)
   1115      0    stevel {
   1116      0    stevel 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
   1117  10216    Vikram 	dev_info_t *dip, *rdip;
   1118      0    stevel 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
   1119      0    stevel 
   1120  10216    Vikram 	dip = rdip = hp->dmai_rdip;
   1121  10216    Vikram 	if (dip != ddi_root_node())
   1122  10216    Vikram 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
   1123  10216    Vikram 	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
   1124  10216    Vikram 	return ((*funcp)(dip, rdip, h));
   1125      0    stevel }
   1126      0    stevel 
   1127      0    stevel #endif	/* !__sparc */
   1128      0    stevel 
   1129      0    stevel int
   1130      0    stevel ddi_dma_free(ddi_dma_handle_t h)
   1131      0    stevel {
   1132      0    stevel 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_FREE, 0, 0, 0, 0));
   1133      0    stevel }
   1134      0    stevel 
   1135      0    stevel int
   1136      0    stevel ddi_iopb_alloc(dev_info_t *dip, ddi_dma_lim_t *limp, uint_t len, caddr_t *iopbp)
   1137      0    stevel {
   1138      0    stevel 	ddi_dma_lim_t defalt;
   1139      0    stevel 	size_t size = len;
   1140      0    stevel 
   1141      0    stevel 	if (!limp) {
   1142      0    stevel 		defalt = standard_limits;
   1143      0    stevel 		limp = &defalt;
   1144      0    stevel 	}
   1145      0    stevel 	return (i_ddi_mem_alloc_lim(dip, limp, size, 0, 0, 0,
   1146      0    stevel 	    iopbp, NULL, NULL));
   1147      0    stevel }
   1148      0    stevel 
   1149      0    stevel void
   1150      0    stevel ddi_iopb_free(caddr_t iopb)
   1151      0    stevel {
   1152   1900      eota 	i_ddi_mem_free(iopb, NULL);
   1153      0    stevel }
   1154      0    stevel 
   1155      0    stevel int
   1156      0    stevel ddi_mem_alloc(dev_info_t *dip, ddi_dma_lim_t *limits, uint_t length,
   1157      0    stevel 	uint_t flags, caddr_t *kaddrp, uint_t *real_length)
   1158      0    stevel {
   1159      0    stevel 	ddi_dma_lim_t defalt;
   1160      0    stevel 	size_t size = length;
   1161      0    stevel 
   1162      0    stevel 	if (!limits) {
   1163      0    stevel 		defalt = standard_limits;
   1164      0    stevel 		limits = &defalt;
   1165      0    stevel 	}
   1166      0    stevel 	return (i_ddi_mem_alloc_lim(dip, limits, size, flags & 0x1,
   1167      0    stevel 	    1, 0, kaddrp, real_length, NULL));
   1168      0    stevel }
   1169      0    stevel 
   1170      0    stevel void
   1171      0    stevel ddi_mem_free(caddr_t kaddr)
   1172      0    stevel {
   1173   1900      eota 	i_ddi_mem_free(kaddr, NULL);
   1174      0    stevel }
   1175      0    stevel 
   1176      0    stevel /*
   1177      0    stevel  * DMA attributes, alignment, burst sizes, and transfer minimums
   1178      0    stevel  */
   1179      0    stevel int
   1180      0    stevel ddi_dma_get_attr(ddi_dma_handle_t handle, ddi_dma_attr_t *attrp)
   1181      0    stevel {
   1182      0    stevel 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
   1183      0    stevel 
   1184      0    stevel 	if (attrp == NULL)
   1185      0    stevel 		return (DDI_FAILURE);
   1186      0    stevel 	*attrp = dimp->dmai_attr;
   1187      0    stevel 	return (DDI_SUCCESS);
   1188      0    stevel }
   1189      0    stevel 
   1190      0    stevel int
   1191      0    stevel ddi_dma_burstsizes(ddi_dma_handle_t handle)
   1192      0    stevel {
   1193      0    stevel 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
   1194      0    stevel 
   1195      0    stevel 	if (!dimp)
   1196      0    stevel 		return (0);
   1197      0    stevel 	else
   1198      0    stevel 		return (dimp->dmai_burstsizes);
   1199      0    stevel }
   1200      0    stevel 
   1201      0    stevel int
   1202      0    stevel ddi_dma_devalign(ddi_dma_handle_t handle, uint_t *alignment, uint_t *mineffect)
   1203      0    stevel {
   1204      0    stevel 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
   1205      0    stevel 
   1206      0    stevel 	if (!dimp || !alignment || !mineffect)
   1207      0    stevel 		return (DDI_FAILURE);
   1208      0    stevel 	if (!(dimp->dmai_rflags & DDI_DMA_SBUS_64BIT)) {
   1209      0    stevel 		*alignment = 1 << ddi_ffs(dimp->dmai_burstsizes);
   1210      0    stevel 	} else {
   1211      0    stevel 		if (dimp->dmai_burstsizes & 0xff0000) {
   1212      0    stevel 			*alignment = 1 << ddi_ffs(dimp->dmai_burstsizes >> 16);
   1213      0    stevel 		} else {
   1214      0    stevel 			*alignment = 1 << ddi_ffs(dimp->dmai_burstsizes);
   1215      0    stevel 		}
   1216      0    stevel 	}
   1217      0    stevel 	*mineffect = dimp->dmai_minxfer;
   1218      0    stevel 	return (DDI_SUCCESS);
   1219      0    stevel }
   1220      0    stevel 
   1221      0    stevel int
   1222      0    stevel ddi_iomin(dev_info_t *a, int i, int stream)
   1223      0    stevel {
   1224      0    stevel 	int r;
   1225      0    stevel 
   1226      0    stevel 	/*
   1227      0    stevel 	 * Make sure that the initial value is sane
   1228      0    stevel 	 */
   1229      0    stevel 	if (i & (i - 1))
   1230      0    stevel 		return (0);
   1231      0    stevel 	if (i == 0)
   1232      0    stevel 		i = (stream) ? 4 : 1;
   1233      0    stevel 
   1234      0    stevel 	r = ddi_ctlops(a, a,
   1235      0    stevel 	    DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i);
   1236      0    stevel 	if (r != DDI_SUCCESS || (i & (i - 1)))
   1237      0    stevel 		return (0);
   1238      0    stevel 	return (i);
   1239      0    stevel }
   1240      0    stevel 
   1241      0    stevel /*
   1242      0    stevel  * Given two DMA attribute structures, apply the attributes
   1243      0    stevel  * of one to the other, following the rules of attributes
   1244      0    stevel  * and the wishes of the caller.
   1245      0    stevel  *
   1246      0    stevel  * The rules of DMA attribute structures are that you cannot
   1247      0    stevel  * make things *less* restrictive as you apply one set
   1248      0    stevel  * of attributes to another.
   1249      0    stevel  *
   1250      0    stevel  */
   1251      0    stevel void
   1252      0    stevel ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
   1253      0    stevel {
   1254      0    stevel 	attr->dma_attr_addr_lo =
   1255      0    stevel 	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
   1256      0    stevel 	attr->dma_attr_addr_hi =
   1257      0    stevel 	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
   1258      0    stevel 	attr->dma_attr_count_max =
   1259      0    stevel 	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
   1260      0    stevel 	attr->dma_attr_align =
   1261      0    stevel 	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
   1262      0    stevel 	attr->dma_attr_burstsizes =
   1263      0    stevel 	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
   1264      0    stevel 	attr->dma_attr_minxfer =
   1265      0    stevel 	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
   1266      0    stevel 	attr->dma_attr_maxxfer =
   1267      0    stevel 	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
   1268      0    stevel 	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
   1269      0    stevel 	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
   1270      0    stevel 	    (uint_t)mod->dma_attr_sgllen);
   1271      0    stevel 	attr->dma_attr_granular =
   1272      0    stevel 	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
   1273      0    stevel }
   1274      0    stevel 
   1275      0    stevel /*
   1276      0    stevel  * mmap/segmap interface:
   1277      0    stevel  */
   1278      0    stevel 
   1279      0    stevel /*
   1280      0    stevel  * ddi_segmap:		setup the default segment driver. Calls the drivers
   1281      0    stevel  *			XXmmap routine to validate the range to be mapped.
   1282      0    stevel  *			Return ENXIO of the range is not valid.  Create
   1283      0    stevel  *			a seg_dev segment that contains all of the
   1284      0    stevel  *			necessary information and will reference the
   1285      0    stevel  *			default segment driver routines. It returns zero
   1286      0    stevel  *			on success or non-zero on failure.
   1287      0    stevel  */
   1288      0    stevel int
   1289      0    stevel ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
   1290      0    stevel     uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
   1291      0    stevel {
   1292      0    stevel 	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
   1293      0    stevel 	    off_t, uint_t, uint_t, uint_t, struct cred *);
   1294      0    stevel 
   1295      0    stevel 	return (spec_segmap(dev, offset, asp, addrp, len,
   1296      0    stevel 	    prot, maxprot, flags, credp));
   1297      0    stevel }
   1298      0    stevel 
   1299      0    stevel /*
   1300      0    stevel  * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
   1301      0    stevel  *			drivers. Allows each successive parent to resolve
   1302      0    stevel  *			address translations and add its mappings to the
   1303      0    stevel  *			mapping list supplied in the page structure. It
   1304      0    stevel  *			returns zero on success	or non-zero on failure.
   1305      0    stevel  */
   1306      0    stevel 
   1307      0    stevel int
   1308      0    stevel ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
   1309      0    stevel     caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
   1310      0    stevel {
   1311      0    stevel 	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
   1312      0    stevel }
   1313      0    stevel 
   1314      0    stevel /*
   1315      0    stevel  * ddi_device_mapping_check:	Called from ddi_segmap_setup.
   1316      0    stevel  *	Invokes platform specific DDI to determine whether attributes specified
   1317      0    stevel  *	in attr(9s) are	valid for the region of memory that will be made
   1318      0    stevel  *	available for direct access to user process via the mmap(2) system call.
   1319      0    stevel  */
   1320      0    stevel int
   1321      0    stevel ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
   1322      0    stevel     uint_t rnumber, uint_t *hat_flags)
   1323      0    stevel {
   1324      0    stevel 	ddi_acc_handle_t handle;
   1325      0    stevel 	ddi_map_req_t mr;
   1326      0    stevel 	ddi_acc_hdl_t *hp;
   1327      0    stevel 	int result;
   1328      0    stevel 	dev_info_t *dip;
   1329      0    stevel 
   1330      0    stevel 	/*
   1331      0    stevel 	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
   1332      0    stevel 	 * release it immediately since it should already be held by
   1333      0    stevel 	 * a devfs vnode.
   1334      0    stevel 	 */
   1335      0    stevel 	if ((dip =
   1336      0    stevel 	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
   1337      0    stevel 		return (-1);
   1338      0    stevel 	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
   1339      0    stevel 
   1340      0    stevel 	/*
   1341      0    stevel 	 * Allocate and initialize the common elements of data
   1342      0    stevel 	 * access handle.
   1343      0    stevel 	 */
   1344      0    stevel 	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
   1345      0    stevel 	if (handle == NULL)
   1346      0    stevel 		return (-1);
   1347      0    stevel 
   1348      0    stevel 	hp = impl_acc_hdl_get(handle);
   1349      0    stevel 	hp->ah_vers = VERS_ACCHDL;
   1350      0    stevel 	hp->ah_dip = dip;
   1351      0    stevel 	hp->ah_rnumber = rnumber;
   1352      0    stevel 	hp->ah_offset = 0;
   1353      0    stevel 	hp->ah_len = 0;
   1354      0    stevel 	hp->ah_acc = *accattrp;
   1355      0    stevel 
   1356      0    stevel 	/*
   1357      0    stevel 	 * Set up the mapping request and call to parent.
   1358      0    stevel 	 */
   1359      0    stevel 	mr.map_op = DDI_MO_MAP_HANDLE;
   1360      0    stevel 	mr.map_type = DDI_MT_RNUMBER;
   1361      0    stevel 	mr.map_obj.rnumber = rnumber;
   1362      0    stevel 	mr.map_prot = PROT_READ | PROT_WRITE;
   1363      0    stevel 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
   1364      0    stevel 	mr.map_handlep = hp;
   1365      0    stevel 	mr.map_vers = DDI_MAP_VERSION;
   1366      0    stevel 	result = ddi_map(dip, &mr, 0, 0, NULL);
   1367      0    stevel 
   1368      0    stevel 	/*
   1369      0    stevel 	 * Region must be mappable, pick up flags from the framework.
   1370      0    stevel 	 */
   1371      0    stevel 	*hat_flags = hp->ah_hat_flags;
   1372      0    stevel 
   1373      0    stevel 	impl_acc_hdl_free(handle);
   1374      0    stevel 
   1375      0    stevel 	/*
   1376      0    stevel 	 * check for end result.
   1377      0    stevel 	 */
   1378      0    stevel 	if (result != DDI_SUCCESS)
   1379      0    stevel 		return (-1);
   1380      0    stevel 	return (0);
   1381      0    stevel }
   1382      0    stevel 
   1383      0    stevel 
   1384      0    stevel /*
   1385      0    stevel  * Property functions:	 See also, ddipropdefs.h.
   1386      0    stevel  *
   1387      0    stevel  * These functions are the framework for the property functions,
   1388      0    stevel  * i.e. they support software defined properties.  All implementation
   1389      0    stevel  * specific property handling (i.e.: self-identifying devices and
   1390      0    stevel  * PROM defined properties are handled in the implementation specific
   1391      0    stevel  * functions (defined in ddi_implfuncs.h).
   1392      0    stevel  */
   1393      0    stevel 
   1394      0    stevel /*
   1395      0    stevel  * nopropop:	Shouldn't be called, right?
   1396      0    stevel  */
   1397      0    stevel int
   1398      0    stevel nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
   1399      0    stevel     char *name, caddr_t valuep, int *lengthp)
   1400      0    stevel {
   1401      0    stevel 	_NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp))
   1402      0    stevel 	return (DDI_PROP_NOT_FOUND);
   1403      0    stevel }
   1404      0    stevel 
   1405      0    stevel #ifdef	DDI_PROP_DEBUG
   1406      0    stevel int ddi_prop_debug_flag = 0;
   1407      0    stevel 
   1408      0    stevel int
   1409      0    stevel ddi_prop_debug(int enable)
   1410      0    stevel {
   1411      0    stevel 	int prev = ddi_prop_debug_flag;
   1412      0    stevel 
   1413      0    stevel 	if ((enable != 0) || (prev != 0))
   1414      0    stevel 		printf("ddi_prop_debug: debugging %s\n",
   1415      0    stevel 		    enable ? "enabled" : "disabled");
   1416      0    stevel 	ddi_prop_debug_flag = enable;
   1417      0    stevel 	return (prev);
   1418      0    stevel }
   1419      0    stevel 
   1420      0    stevel #endif	/* DDI_PROP_DEBUG */
   1421      0    stevel 
   1422      0    stevel /*
   1423      0    stevel  * Search a property list for a match, if found return pointer
   1424      0    stevel  * to matching prop struct, else return NULL.
   1425      0    stevel  */
   1426      0    stevel 
   1427      0    stevel ddi_prop_t *
   1428      0    stevel i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head)
   1429      0    stevel {
   1430      0    stevel 	ddi_prop_t	*propp;
   1431      0    stevel 
   1432      0    stevel 	/*
   1433      0    stevel 	 * find the property in child's devinfo:
   1434    168       cth 	 * Search order defined by this search function is first matching
   1435    168       cth 	 * property with input dev == DDI_DEV_T_ANY matching any dev or
   1436    168       cth 	 * dev == propp->prop_dev, name == propp->name, and the correct
   1437    168       cth 	 * data type as specified in the flags.  If a DDI_DEV_T_NONE dev
   1438    168       cth 	 * value made it this far then it implies a DDI_DEV_T_ANY search.
   1439    168       cth 	 */
   1440    168       cth 	if (dev == DDI_DEV_T_NONE)
   1441    168       cth 		dev = DDI_DEV_T_ANY;
   1442      0    stevel 
   1443      0    stevel 	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
   1444      0    stevel 
   1445    164       cth 		if (!DDI_STRSAME(propp->prop_name, name))
   1446      0    stevel 			continue;
   1447      0    stevel 
   1448      0    stevel 		if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev))
   1449      0    stevel 			continue;
   1450      0    stevel 
   1451      0    stevel 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
   1452      0    stevel 			continue;
   1453      0    stevel 
   1454      0    stevel 		return (propp);
   1455      0    stevel 	}
   1456      0    stevel 
   1457      0    stevel 	return ((ddi_prop_t *)0);
   1458      0    stevel }
   1459      0    stevel 
   1460      0    stevel /*
   1461      0    stevel  * Search for property within devnames structures
   1462      0    stevel  */
   1463      0    stevel ddi_prop_t *
   1464      0    stevel i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags)
   1465      0    stevel {
   1466      0    stevel 	major_t		major;
   1467      0    stevel 	struct devnames	*dnp;
   1468      0    stevel 	ddi_prop_t	*propp;
   1469      0    stevel 
   1470      0    stevel 	/*
   1471      0    stevel 	 * Valid dev_t value is needed to index into the
   1472      0    stevel 	 * correct devnames entry, therefore a dev_t
   1473      0    stevel 	 * value of DDI_DEV_T_ANY is not appropriate.
   1474      0    stevel 	 */
   1475      0    stevel 	ASSERT(dev != DDI_DEV_T_ANY);
   1476      0    stevel 	if (dev == DDI_DEV_T_ANY) {
   1477      0    stevel 		return ((ddi_prop_t *)0);
   1478      0    stevel 	}
   1479      0    stevel 
   1480      0    stevel 	major = getmajor(dev);
   1481      0    stevel 	dnp = &(devnamesp[major]);
   1482      0    stevel 
   1483      0    stevel 	if (dnp->dn_global_prop_ptr == NULL)
   1484      0    stevel 		return ((ddi_prop_t *)0);
   1485      0    stevel 
   1486      0    stevel 	LOCK_DEV_OPS(&dnp->dn_lock);
   1487      0    stevel 
   1488      0    stevel 	for (propp = dnp->dn_global_prop_ptr->prop_list;
   1489      0    stevel 	    propp != NULL;
   1490      0    stevel 	    propp = (ddi_prop_t *)propp->prop_next) {
   1491      0    stevel 
   1492    164       cth 		if (!DDI_STRSAME(propp->prop_name, name))
   1493      0    stevel 			continue;
   1494      0    stevel 
   1495   8371    Vikram 		if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) &&
   1496   8371    Vikram 		    (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev))
   1497      0    stevel 			continue;
   1498      0    stevel 
   1499      0    stevel 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
   1500      0    stevel 			continue;
   1501      0    stevel 
   1502      0    stevel 		/* Property found, return it */
   1503      0    stevel 		UNLOCK_DEV_OPS(&dnp->dn_lock);
   1504      0    stevel 		return (propp);
   1505      0    stevel 	}
   1506      0    stevel 
   1507      0    stevel 	UNLOCK_DEV_OPS(&dnp->dn_lock);
   1508      0    stevel 	return ((ddi_prop_t *)0);
   1509      0    stevel }
   1510      0    stevel 
   1511      0    stevel static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>";
   1512      0    stevel 
   1513      0    stevel /*
   1514      0    stevel  * ddi_prop_search_global:
   1515      0    stevel  *	Search the global property list within devnames
   1516      0    stevel  *	for the named property.  Return the encoded value.
   1517      0    stevel  */
   1518      0    stevel static int
   1519      0    stevel i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name,
   1520      0    stevel     void *valuep, uint_t *lengthp)
   1521      0    stevel {
   1522      0    stevel 	ddi_prop_t	*propp;
   1523      0    stevel 	caddr_t		buffer;
   1524      0    stevel 
   1525      0    stevel 	propp =  i_ddi_search_global_prop(dev, name, flags);
   1526      0    stevel 
   1527      0    stevel 	/* Property NOT found, bail */
   1528      0    stevel 	if (propp == (ddi_prop_t *)0)
   1529      0    stevel 		return (DDI_PROP_NOT_FOUND);
   1530      0    stevel 
   1531      0    stevel 	if (propp->prop_flags & DDI_PROP_UNDEF_IT)
   1532      0    stevel 		return (DDI_PROP_UNDEFINED);
   1533      0    stevel 
   1534    497       cth 	if ((buffer = kmem_alloc(propp->prop_len,
   1535    497       cth 	    (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) {
   1536      0    stevel 		cmn_err(CE_CONT, prop_no_mem_msg, name);
   1537      0    stevel 		return (DDI_PROP_NO_MEMORY);
   1538      0    stevel 	}
   1539      0    stevel 
   1540      0    stevel 	/*
   1541      0    stevel 	 * Return the encoded data
   1542      0    stevel 	 */
   1543      0    stevel 	*(caddr_t *)valuep = buffer;
   1544      0    stevel 	*lengthp = propp->prop_len;
   1545      0    stevel 	bcopy(propp->prop_val, buffer, propp->prop_len);
   1546      0    stevel 
   1547      0    stevel 	return (DDI_PROP_SUCCESS);
   1548      0    stevel }
   1549      0    stevel 
   1550      0    stevel /*
   1551      0    stevel  * ddi_prop_search_common:	Lookup and return the encoded value
   1552      0    stevel  */
   1553      0    stevel int
   1554      0    stevel ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
   1555      0    stevel     uint_t flags, char *name, void *valuep, uint_t *lengthp)
   1556      0    stevel {
   1557      0    stevel 	ddi_prop_t	*propp;
   1558      0    stevel 	int		i;
   1559      0    stevel 	caddr_t		buffer;
   1560      0    stevel 	caddr_t		prealloc = NULL;
   1561      0    stevel 	int		plength = 0;
   1562      0    stevel 	dev_info_t	*pdip;
   1563      0    stevel 	int		(*bop)();
   1564      0    stevel 
   1565      0    stevel 	/*CONSTANTCONDITION*/
   1566      0    stevel 	while (1)  {
   1567      0    stevel 
   1568      0    stevel 		mutex_enter(&(DEVI(dip)->devi_lock));
   1569      0    stevel 
   1570      0    stevel 
   1571      0    stevel 		/*
   1572      0    stevel 		 * find the property in child's devinfo:
   1573      0    stevel 		 * Search order is:
   1574      0    stevel 		 *	1. driver defined properties
   1575      0    stevel 		 *	2. system defined properties
   1576      0    stevel 		 *	3. driver global properties
   1577      0    stevel 		 *	4. boot defined properties
   1578      0    stevel 		 */
   1579      0    stevel 
   1580      0    stevel 		propp = i_ddi_prop_search(dev, name, flags,
   1581      0    stevel 		    &(DEVI(dip)->devi_drv_prop_ptr));
   1582      0    stevel 		if (propp == NULL)  {
   1583      0    stevel 			propp = i_ddi_prop_search(dev, name, flags,
   1584      0    stevel 			    &(DEVI(dip)->devi_sys_prop_ptr));
   1585      0    stevel 		}
   1586      0    stevel 		if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) {
   1587      0    stevel 			propp = i_ddi_prop_search(dev, name, flags,
   1588      0    stevel 			    &DEVI(dip)->devi_global_prop_list->prop_list);
   1589      0    stevel 		}
   1590      0    stevel 
   1591      0    stevel 		if (propp == NULL)  {
   1592      0    stevel 			propp = i_ddi_prop_search(dev, name, flags,
   1593      0    stevel 			    &(DEVI(dip)->devi_hw_prop_ptr));
   1594      0    stevel 		}
   1595      0    stevel 
   1596      0    stevel 		/*
   1597      0    stevel 		 * Software property found?
   1598      0    stevel 		 */
   1599      0    stevel 		if (propp != (ddi_prop_t *)0)	{
   1600      0    stevel 
   1601      0    stevel 			/*
   1602      0    stevel 			 * If explicit undefine, return now.
   1603      0    stevel 			 */
   1604      0    stevel 			if (propp->prop_flags & DDI_PROP_UNDEF_IT) {
   1605      0    stevel 				mutex_exit(&(DEVI(dip)->devi_lock));
   1606      0    stevel 				if (prealloc)
   1607      0    stevel 					kmem_free(prealloc, plength);
   1608      0    stevel 				return (DDI_PROP_UNDEFINED);
   1609      0    stevel 			}
   1610      0    stevel 
   1611      0    stevel 			/*
   1612      0    stevel 			 * If we only want to know if it exists, return now
   1613      0    stevel 			 */
   1614      0    stevel 			if (prop_op == PROP_EXISTS) {
   1615      0    stevel 				mutex_exit(&(DEVI(dip)->devi_lock));
   1616      0    stevel 				ASSERT(prealloc == NULL);
   1617      0    stevel 				return (DDI_PROP_SUCCESS);
   1618      0    stevel 			}
   1619      0    stevel 
   1620      0    stevel 			/*
   1621      0    stevel 			 * If length only request or prop length == 0,
   1622      0    stevel 			 * service request and return now.
   1623      0    stevel 			 */
   1624      0    stevel 			if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) {
   1625      0    stevel 				*lengthp = propp->prop_len;
   1626      0    stevel 
   1627      0    stevel 				/*
   1628      0    stevel 				 * if prop_op is PROP_LEN_AND_VAL_ALLOC
   1629      0    stevel 				 * that means prop_len is 0, so set valuep
   1630      0    stevel 				 * also to NULL
   1631      0    stevel 				 */
   1632      0    stevel 				if (prop_op == PROP_LEN_AND_VAL_ALLOC)
   1633      0    stevel 					*(caddr_t *)valuep = NULL;
   1634      0    stevel 
   1635      0    stevel 				mutex_exit(&(DEVI(dip)->devi_lock));
   1636      0    stevel 				if (prealloc)
   1637      0    stevel 					kmem_free(prealloc, plength);
   1638      0    stevel 				return (DDI_PROP_SUCCESS);
   1639      0    stevel 			}
   1640      0    stevel 
   1641      0    stevel 			/*
   1642      0    stevel 			 * If LEN_AND_VAL_ALLOC and the request can sleep,
   1643      0    stevel 			 * drop the mutex, allocate the buffer, and go
   1644      0    stevel 			 * through the loop again.  If we already allocated
   1645      0    stevel 			 * the buffer, and the size of the property changed,
   1646      0    stevel 			 * keep trying...
   1647      0    stevel 			 */
   1648      0    stevel 			if ((prop_op == PROP_LEN_AND_VAL_ALLOC) &&
   1649      0    stevel 			    (flags & DDI_PROP_CANSLEEP))  {
   1650      0    stevel 				if (prealloc && (propp->prop_len != plength)) {
   1651      0    stevel 					kmem_free(prealloc, plength);
   1652      0    stevel 					prealloc = NULL;
   1653      0    stevel 				}
   1654      0    stevel 				if (prealloc == NULL)  {
   1655      0    stevel 					plength = propp->prop_len;
   1656      0    stevel 					mutex_exit(&(DEVI(dip)->devi_lock));
   1657      0    stevel 					prealloc = kmem_alloc(plength,
   1658      0    stevel 					    KM_SLEEP);
   1659      0    stevel 					continue;
   1660      0    stevel 				}
   1661      0    stevel 			}
   1662      0    stevel 
   1663      0    stevel 			/*
   1664      0    stevel 			 * Allocate buffer, if required.  Either way,
   1665      0    stevel 			 * set `buffer' variable.
   1666      0    stevel 			 */
   1667      0    stevel 			i = *lengthp;			/* Get callers length */
   1668      0    stevel 			*lengthp = propp->prop_len;	/* Set callers length */
   1669      0    stevel 
   1670      0    stevel 			switch (prop_op) {
   1671      0    stevel 
   1672      0    stevel 			case PROP_LEN_AND_VAL_ALLOC:
   1673      0    stevel 
   1674      0    stevel 				if (prealloc == NULL) {
   1675      0    stevel 					buffer = kmem_alloc(propp->prop_len,
   1676      0    stevel 					    KM_NOSLEEP);
   1677      0    stevel 				} else {
   1678      0    stevel 					buffer = prealloc;
   1679      0    stevel 				}
   1680      0    stevel 
   1681      0    stevel 				if (buffer == NULL)  {
   1682      0    stevel 					mutex_exit(&(DEVI(dip)->devi_lock));
   1683      0    stevel 					cmn_err(CE_CONT, prop_no_mem_msg, name);
   1684      0    stevel 					return (DDI_PROP_NO_MEMORY);
   1685      0    stevel 				}
   1686      0    stevel 				/* Set callers buf ptr */
   1687      0    stevel 				*(caddr_t *)valuep = buffer;
   1688      0    stevel 				break;
   1689      0    stevel 
   1690      0    stevel 			case PROP_LEN_AND_VAL_BUF:
   1691      0    stevel 
   1692      0    stevel 				if (propp->prop_len > (i)) {
   1693      0    stevel 					mutex_exit(&(DEVI(dip)->devi_lock));
   1694      0    stevel 					return (DDI_PROP_BUF_TOO_SMALL);
   1695      0    stevel 				}
   1696      0    stevel 
   1697      0    stevel 				buffer = valuep;  /* Get callers buf ptr */
   1698      0    stevel 				break;
   1699      0    stevel 
   1700      0    stevel 			default:
   1701      0    stevel 				break;
   1702      0    stevel 			}
   1703      0    stevel 
   1704      0    stevel 			/*
   1705      0    stevel 			 * Do the copy.
   1706      0    stevel 			 */
   1707      0    stevel 			bcopy(propp->prop_val, buffer, propp->prop_len);
   1708      0    stevel 			mutex_exit(&(DEVI(dip)->devi_lock));
   1709      0    stevel 			return (DDI_PROP_SUCCESS);
   1710      0    stevel 		}
   1711      0    stevel 
   1712      0    stevel 		mutex_exit(&(DEVI(dip)->devi_lock));
   1713      0    stevel 		if (prealloc)
   1714      0    stevel 			kmem_free(prealloc, plength);
   1715      0    stevel 		prealloc = NULL;
   1716      0    stevel 
   1717      0    stevel 		/*
   1718      0    stevel 		 * Prop not found, call parent bus_ops to deal with possible
   1719      0    stevel 		 * h/w layer (possible PROM defined props, etc.) and to
   1720      0    stevel 		 * possibly ascend the hierarchy, if allowed by flags.
   1721      0    stevel 		 */
   1722      0    stevel 		pdip = (dev_info_t *)DEVI(dip)->devi_parent;
   1723      0    stevel 
   1724      0    stevel 		/*
   1725      0    stevel 		 * One last call for the root driver PROM props?
   1726      0    stevel 		 */
   1727      0    stevel 		if (dip == ddi_root_node())  {
   1728      0    stevel 			return (ddi_bus_prop_op(dev, dip, dip, prop_op,
   1729      0    stevel 			    flags, name, valuep, (int *)lengthp));
   1730      0    stevel 		}
   1731      0    stevel 
   1732      0    stevel 		/*
   1733      0    stevel 		 * We may have been called to check for properties
   1734      0    stevel 		 * within a single devinfo node that has no parent -
   1735      0    stevel 		 * see make_prop()
   1736      0    stevel 		 */
   1737      0    stevel 		if (pdip == NULL) {
   1738      0    stevel 			ASSERT((flags &
   1739      0    stevel 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) ==
   1740      0    stevel 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM));
   1741      0    stevel 			return (DDI_PROP_NOT_FOUND);
   1742      0    stevel 		}
   1743      0    stevel 
   1744      0    stevel 		/*
   1745      0    stevel 		 * Instead of recursing, we do iterative calls up the tree.
   1746      0    stevel 		 * As a bit of optimization, skip the bus_op level if the
   1747      0    stevel 		 * node is a s/w node and if the parent's bus_prop_op function
   1748      0    stevel 		 * is `ddi_bus_prop_op', because we know that in this case,
   1749      0    stevel 		 * this function does nothing.
   1750      0    stevel 		 *
   1751      0    stevel 		 * 4225415: If the parent isn't attached, or the child
   1752      0    stevel 		 * hasn't been named by the parent yet, use the default
   1753      0    stevel 		 * ddi_bus_prop_op as a proxy for the parent.  This
   1754      0    stevel 		 * allows property lookups in any child/parent state to
   1755      0    stevel 		 * include 'prom' and inherited properties, even when
   1756      0    stevel 		 * there are no drivers attached to the child or parent.
   1757      0    stevel 		 */
   1758      0    stevel 
   1759      0    stevel 		bop = ddi_bus_prop_op;
   1760   1333       cth 		if (i_ddi_devi_attached(pdip) &&
   1761      0    stevel 		    (i_ddi_node_state(dip) >= DS_INITIALIZED))
   1762      0    stevel 			bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op;
   1763      0    stevel 
   1764      0    stevel 		i = DDI_PROP_NOT_FOUND;
   1765      0    stevel 
   1766      0    stevel 		if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) {
   1767      0    stevel 			i = (*bop)(dev, pdip, dip, prop_op,
   1768      0    stevel 			    flags | DDI_PROP_DONTPASS,
   1769      0    stevel 			    name, valuep, lengthp);
   1770      0    stevel 		}
   1771      0    stevel 
   1772      0    stevel 		if ((flags & DDI_PROP_DONTPASS) ||
   1773      0    stevel 		    (i != DDI_PROP_NOT_FOUND))
   1774      0    stevel 			return (i);
   1775      0    stevel 
   1776      0    stevel 		dip = pdip;
   1777      0    stevel 	}
   1778      0    stevel 	/*NOTREACHED*/
   1779      0    stevel }
   1780      0    stevel 
   1781      0    stevel 
   1782      0    stevel /*
   1783      0    stevel  * ddi_prop_op: The basic property operator for drivers.
   1784      0    stevel  *
   1785      0    stevel  * In ddi_prop_op, the type of valuep is interpreted based on prop_op:
   1786      0    stevel  *
   1787      0    stevel  *	prop_op			valuep
   1788      0    stevel  *	------			------
   1789      0    stevel  *
   1790      0    stevel  *	PROP_LEN		<unused>
   1791      0    stevel  *
   1792      0    stevel  *	PROP_LEN_AND_VAL_BUF	Pointer to callers buffer
   1793      0    stevel  *
   1794      0    stevel  *	PROP_LEN_AND_VAL_ALLOC	Address of callers pointer (will be set to
   1795      0    stevel  *				address of allocated buffer, if successful)
   1796      0    stevel  */
   1797      0    stevel int
   1798      0    stevel ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
   1799      0    stevel     char *name, caddr_t valuep, int *lengthp)
   1800      0    stevel {
   1801      0    stevel 	int	i;
   1802      0    stevel 
   1803      0    stevel 	ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0);
   1804      0    stevel 
   1805      0    stevel 	/*
   1806      0    stevel 	 * If this was originally an LDI prop lookup then we bail here.
   1807      0    stevel 	 * The reason is that the LDI property lookup interfaces first call
   1808      0    stevel 	 * a drivers prop_op() entry point to allow it to override
   1809      0    stevel 	 * properties.  But if we've made it here, then the driver hasn't
   1810      0    stevel 	 * overriden any properties.  We don't want to continue with the
   1811      0    stevel 	 * property search here because we don't have any type inforamtion.
   1812      0    stevel 	 * When we return failure, the LDI interfaces will then proceed to
   1813      0    stevel 	 * call the typed property interfaces to look up the property.
   1814      0    stevel 	 */
   1815      0    stevel 	if (mod_flags & DDI_PROP_DYNAMIC)
   1816      0    stevel 		return (DDI_PROP_NOT_FOUND);
   1817      0    stevel 
   1818      0    stevel 	/*
   1819      0    stevel 	 * check for pre-typed property consumer asking for typed property:
   1820      0    stevel 	 * see e_ddi_getprop_int64.
   1821      0    stevel 	 */
   1822      0    stevel 	if (mod_flags & DDI_PROP_CONSUMER_TYPED)
   1823      0    stevel 		mod_flags |= DDI_PROP_TYPE_INT64;
   1824      0    stevel 	mod_flags |= DDI_PROP_TYPE_ANY;
   1825      0    stevel 
   1826      0    stevel 	i = ddi_prop_search_common(dev, dip, prop_op,
   1827   4582       cth 	    mod_flags, name, valuep, (uint_t *)lengthp);
   1828      0    stevel 	if (i == DDI_PROP_FOUND_1275)
   1829      0    stevel 		return (DDI_PROP_SUCCESS);
   1830      0    stevel 	return (i);
   1831      0    stevel }
   1832      0    stevel 
   1833      0    stevel /*
   1834   4582       cth  * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that
   1835   4582       cth  * maintain size in number of blksize blocks.  Provides a dynamic property
   1836   4582       cth  * implementation for size oriented properties based on nblocks64 and blksize
   1837   4582       cth  * values passed in by the driver.  Fallback to ddi_prop_op if the nblocks64
   1838   4582       cth  * is too large.  This interface should not be used with a nblocks64 that
   1839   4582       cth  * represents the driver's idea of how to represent unknown, if nblocks is
   1840   4582       cth  * unknown use ddi_prop_op.
   1841   4582       cth  */
   1842   4582       cth int
   1843   4582       cth ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
   1844   4582       cth     int mod_flags, char *name, caddr_t valuep, int *lengthp,
   1845   4582       cth     uint64_t nblocks64, uint_t blksize)
   1846   4582       cth {
   1847   4582       cth 	uint64_t size64;
   1848   4582       cth 	int	blkshift;
   1849   4582       cth 
   1850   4582       cth 	/* convert block size to shift value */
   1851   4582       cth 	ASSERT(BIT_ONLYONESET(blksize));
   1852   4582       cth 	blkshift = highbit(blksize) - 1;
   1853   4582       cth 
   1854   4582       cth 	/*
   1855   4582       cth 	 * There is no point in supporting nblocks64 values that don't have
   1856   4582       cth 	 * an accurate uint64_t byte count representation.
   1857   4582       cth 	 */
   1858   4582       cth 	if (nblocks64 >= (UINT64_MAX >> blkshift))
   1859   4582       cth 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
   1860   4582       cth 		    name, valuep, lengthp));
   1861   4582       cth 
   1862   4582       cth 	size64 = nblocks64 << blkshift;
   1863   4582       cth 	return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags,
   1864   4582       cth 	    name, valuep, lengthp, size64, blksize));
   1865   4582       cth }
   1866   4582       cth 
   1867   4582       cth /*
   1868   4582       cth  * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize.
   1869      0    stevel  */
   1870      0    stevel int
   1871      0    stevel ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
   1872      0    stevel     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64)
   1873      0    stevel {
   1874   4582       cth 	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op,
   1875   4582       cth 	    mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE));
   1876   4582       cth }
   1877   4582       cth 
   1878   4582       cth /*
   1879   4582       cth  * ddi_prop_op_size_blksize: The basic property operator for block drivers that
   1880   4582       cth  * maintain size in bytes. Provides a of dynamic property implementation for
   1881   4582       cth  * size oriented properties based on size64 value and blksize passed in by the
   1882   4582       cth  * driver.  Fallback to ddi_prop_op if the size64 is too large. This interface
   1883   4582       cth  * should not be used with a size64 that represents the driver's idea of how
   1884   4582       cth  * to represent unknown, if size is unknown use ddi_prop_op.
   1885      0    stevel  *
   1886      0    stevel  * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned
   1887      0    stevel  * integers. While the most likely interface to request them ([bc]devi_size)
   1888      0    stevel  * is declared int (signed) there is no enforcement of this, which means we
   1889      0    stevel  * can't enforce limitations here without risking regression.
   1890      0    stevel  */
   1891      0    stevel int
   1892   4582       cth ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
   1893   4582       cth     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64,
   1894   4582       cth     uint_t blksize)
   1895      0    stevel {
   1896      0    stevel 	uint64_t nblocks64;
   1897      0    stevel 	int	callers_length;
   1898      0    stevel 	caddr_t	buffer;
   1899   4582       cth 	int	blkshift;
   1900   4582       cth 
   1901   7224       cth 	/*
   1902   7224       cth 	 * This is a kludge to support capture of size(9P) pure dynamic
   1903   7224       cth 	 * properties in snapshots for non-cmlb code (without exposing
   1904   7224       cth 	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
   1905   7224       cth 	 * should be removed.
   1906   7224       cth 	 */
   1907   7224       cth 	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
   1908   7224       cth 		static i_ddi_prop_dyn_t prop_dyn_size[] = {
   1909   7224       cth 		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
   1910   7224       cth 		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
   1911   7224       cth 		    {NULL}
   1912   7224       cth 		};
   1913   7224       cth 		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
   1914   7224       cth 	}
   1915   7224       cth 
   1916   4582       cth 	/* convert block size to shift value */
   1917   4582       cth 	ASSERT(BIT_ONLYONESET(blksize));
   1918   4582       cth 	blkshift = highbit(blksize) - 1;
   1919      0    stevel 
   1920      0    stevel 	/* compute DEV_BSIZE nblocks value */
   1921   4582       cth 	nblocks64 = size64 >> blkshift;
   1922      0    stevel 
   1923      0    stevel 	/* get callers length, establish length of our dynamic properties */
   1924      0    stevel 	callers_length = *lengthp;
   1925      0    stevel 
   1926      0    stevel 	if (strcmp(name, "Nblocks") == 0)
   1927      0    stevel 		*lengthp = sizeof (uint64_t);
   1928      0    stevel 	else if (strcmp(name, "Size") == 0)
   1929      0    stevel 		*lengthp = sizeof (uint64_t);
   1930      0    stevel 	else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX))
   1931      0    stevel 		*lengthp = sizeof (uint32_t);
   1932      0    stevel 	else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX))
   1933   4582       cth 		*lengthp = sizeof (uint32_t);
   1934   4582       cth 	else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX))
   1935      0    stevel 		*lengthp = sizeof (uint32_t);
   1936      0    stevel 	else {
   1937      0    stevel 		/* fallback to ddi_prop_op */
   1938      0    stevel 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
   1939      0    stevel 		    name, valuep, lengthp));
   1940      0    stevel 	}
   1941      0    stevel 
   1942      0    stevel 	/* service request for the length of the property */
   1943      0    stevel 	if (prop_op == PROP_LEN)
   1944      0    stevel 		return (DDI_PROP_SUCCESS);
   1945      0    stevel 
   1946      0    stevel 	switch (prop_op) {
   1947      0    stevel 	case PROP_LEN_AND_VAL_ALLOC:
   1948      0    stevel 		if ((buffer = kmem_alloc(*lengthp,
   1949      0    stevel 		    (mod_flags & DDI_PROP_CANSLEEP) ?
   1950      0    stevel 		    KM_SLEEP : KM_NOSLEEP)) == NULL)
   1951      0    stevel 			return (DDI_PROP_NO_MEMORY);
   1952      0    stevel 
   1953      0    stevel 		*(caddr_t *)valuep = buffer;	/* set callers buf ptr */
   1954      0    stevel 		break;
   1955      0    stevel 
   1956      0    stevel 	case PROP_LEN_AND_VAL_BUF:
   1957   7224       cth 		/* the length of the property and the request must match */
   1958   7224       cth 		if (callers_length != *lengthp)
   1959   7224       cth 			return (DDI_PROP_INVAL_ARG);
   1960   7224       cth 
   1961      0    stevel 		buffer = valuep;		/* get callers buf ptr */
   1962      0    stevel 		break;
   1963      0    stevel 
   1964      0    stevel 	default:
   1965      0    stevel 		return (DDI_PROP_INVAL_ARG);
   1966      0    stevel 	}
   1967      0    stevel 
   1968      0    stevel 	/* transfer the value into the buffer */
   1969      0    stevel 	if (strcmp(name, "Nblocks") == 0)
   1970      0    stevel 		*((uint64_t *)buffer) = nblocks64;
   1971      0    stevel 	else if (strcmp(name, "Size") == 0)
   1972      0    stevel 		*((uint64_t *)buffer) = size64;
   1973      0    stevel 	else if (strcmp(name, "nblocks") == 0)
   1974      0    stevel 		*((uint32_t *)buffer) = (uint32_t)nblocks64;
   1975      0    stevel 	else if (strcmp(name, "size") == 0)
   1976      0    stevel 		*((uint32_t *)buffer) = (uint32_t)size64;
   1977   4582       cth 	else if (strcmp(name, "blksize") == 0)
   1978   4582       cth 		*((uint32_t *)buffer) = (uint32_t)blksize;
   1979   4582       cth 	return (DDI_PROP_SUCCESS);
   1980   4582       cth }
   1981   4582       cth 
   1982   4582       cth /*
   1983   4582       cth  * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size.
   1984   4582       cth  */
   1985   4582       cth int
   1986   4582       cth ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
   1987   4582       cth     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64)
   1988   4582       cth {
   1989   4582       cth 	return (ddi_prop_op_size_blksize(dev, dip, prop_op,
   1990   4582       cth 	    mod_flags, name, valuep, lengthp, size64, DEV_BSIZE));
   1991      0    stevel }
   1992      0    stevel 
   1993      0    stevel /*
   1994      0    stevel  * Variable length props...
   1995      0    stevel  */
   1996      0    stevel 
   1997      0    stevel /*
   1998      0    stevel  * ddi_getlongprop:	Get variable length property len+val into a buffer
   1999      0    stevel  *		allocated by property provider via kmem_alloc. Requester
   2000      0    stevel  *		is responsible for freeing returned property via kmem_free.
   2001      0    stevel  *
   2002      0    stevel  *	Arguments:
   2003      0    stevel  *
   2004      0    stevel  *	dev_t:	Input:	dev_t of property.
   2005      0    stevel  *	dip:	Input:	dev_info_t pointer of child.
   2006      0    stevel  *	flags:	Input:	Possible flag modifiers are:
   2007      0    stevel  *		DDI_PROP_DONTPASS:	Don't pass to parent if prop not found.
   2008      0    stevel  *		DDI_PROP_CANSLEEP:	Memory allocation may sleep.
   2009      0    stevel  *	name:	Input:	name of property.
   2010      0    stevel  *	valuep:	Output:	Addr of callers buffer pointer.
   2011      0    stevel  *	lengthp:Output:	*lengthp will contain prop length on exit.
   2012      0    stevel  *
   2013      0    stevel  *	Possible Returns:
   2014      0    stevel  *
   2015      0    stevel  *		DDI_PROP_SUCCESS:	Prop found and returned.
   2016      0    stevel  *		DDI_PROP_NOT_FOUND:	Prop not found
   2017      0    stevel  *		DDI_PROP_UNDEFINED:	Prop explicitly undefined.
   2018      0    stevel  *		DDI_PROP_NO_MEMORY:	Prop found, but unable to alloc mem.
   2019      0    stevel  */
   2020      0    stevel 
   2021      0    stevel int
   2022      0    stevel ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags,
   2023      0    stevel     char *name, caddr_t valuep, int *lengthp)
   2024      0    stevel {
   2025      0    stevel 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC,
   2026      0    stevel 	    flags, name, valuep, lengthp));
   2027      0    stevel }
   2028      0    stevel 
   2029      0    stevel /*
   2030      0    stevel  *
   2031      0    stevel  * ddi_getlongprop_buf:		Get long prop into pre-allocated callers
   2032      0    stevel  *				buffer. (no memory allocation by provider).
   2033      0    stevel  *
   2034      0    stevel  *	dev_t:	Input:	dev_t of property.
   2035      0    stevel  *	dip:	Input:	dev_info_t pointer of child.
   2036      0    stevel  *	flags:	Input:	DDI_PROP_DONTPASS or NULL
   2037      0    stevel  *	name:	Input:	name of property
   2038      0    stevel  *	valuep:	Input:	ptr to callers buffer.
   2039      0    stevel  *	lengthp:I/O:	ptr to length of callers buffer on entry,
   2040      0    stevel  *			actual length of property on exit.
   2041      0    stevel  *
   2042      0    stevel  *	Possible returns:
   2043      0    stevel  *
   2044      0    stevel  *		DDI_PROP_SUCCESS	Prop found and returned
   2045      0    stevel  *		DDI_PROP_NOT_FOUND	Prop not found
   2046      0    stevel  *		DDI_PROP_UNDEFINED	Prop explicitly undefined.
   2047      0    stevel  *		DDI_PROP_BUF_TOO_SMALL	Prop found, callers buf too small,
   2048      0    stevel  *					no value returned, but actual prop
   2049      0    stevel  *					length returned in *lengthp
   2050      0    stevel  *
   2051      0    stevel  */
   2052      0    stevel 
   2053      0    stevel int
   2054      0    stevel ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags,
   2055      0    stevel     char *name, caddr_t valuep, int *lengthp)
   2056      0    stevel {
   2057      0    stevel 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
   2058      0    stevel 	    flags, name, valuep, lengthp));
   2059      0    stevel }
   2060      0    stevel 
   2061      0    stevel /*
   2062      0    stevel  * Integer/boolean sized props.
   2063      0    stevel  *
   2064      0    stevel  * Call is value only... returns found boolean or int sized prop value or
   2065      0    stevel  * defvalue if prop not found or is wrong length or is explicitly undefined.
   2066      0    stevel  * Only flag is DDI_PROP_DONTPASS...
   2067      0    stevel  *
   2068      0    stevel  * By convention, this interface returns boolean (0) sized properties
   2069      0    stevel  * as value (int)1.
   2070      0    stevel  *
   2071      0    stevel  * This never returns an error, if property not found or specifically
   2072      0    stevel  * undefined, the input `defvalue' is returned.
   2073      0    stevel  */
   2074      0    stevel 
   2075      0    stevel int
   2076      0    stevel ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue)
   2077      0    stevel {
   2078      0    stevel 	int	propvalue = defvalue;
   2079      0    stevel 	int	proplength = sizeof (int);
   2080      0    stevel 	int	error;
   2081      0    stevel 
   2082      0    stevel 	error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
   2083      0    stevel 	    flags, name, (caddr_t)&propvalue, &proplength);
   2084      0    stevel 
   2085      0    stevel 	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
   2086      0    stevel 		propvalue = 1;
   2087      0    stevel 
   2088      0    stevel 	return (propvalue);
   2089      0    stevel }
   2090      0    stevel 
   2091      0    stevel /*
   2092      0    stevel  * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS
   2093      0    stevel  * if returns DDI_PROP_SUCCESS, length returned in *lengthp.
   2094      0    stevel  */
   2095      0    stevel 
   2096      0    stevel int
   2097      0    stevel ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp)
   2098      0    stevel {
   2099      0    stevel 	return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp));
   2100      0    stevel }
   2101      0    stevel 
   2102      0    stevel /*
   2103      0    stevel  * Allocate a struct prop_driver_data, along with 'size' bytes
   2104      0    stevel  * for decoded property data.  This structure is freed by
   2105      0    stevel  * calling ddi_prop_free(9F).
   2106      0    stevel  */
   2107      0    stevel static void *
   2108      0    stevel ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *))
   2109      0    stevel {
   2110      0    stevel 	struct prop_driver_data *pdd;
   2111      0    stevel 
   2112      0    stevel 	/*
   2113      0    stevel 	 * Allocate a structure with enough memory to store the decoded data.
   2114      0    stevel 	 */
   2115      0    stevel 	pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP);
   2116      0    stevel 	pdd->pdd_size = (sizeof (struct prop_driver_data) + size);
   2117      0    stevel 	pdd->pdd_prop_free = prop_free;
   2118      0    stevel 
   2119      0    stevel 	/*
   2120      0    stevel 	 * Return a pointer to the location to put the decoded data.
   2121      0    stevel 	 */
   2122      0    stevel 	return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data)));
   2123      0    stevel }
   2124      0    stevel 
   2125      0    stevel /*
   2126      0    stevel  * Allocated the memory needed to store the encoded data in the property
   2127      0    stevel  * handle.
   2128      0    stevel  */
   2129      0    stevel static int
   2130      0    stevel ddi_prop_encode_alloc(prop_handle_t *ph, size_t size)
   2131      0    stevel {
   2132      0    stevel 	/*
   2133      0    stevel 	 * If size is zero, then set data to NULL and size to 0.  This
   2134      0    stevel 	 * is a boolean property.
   2135      0    stevel 	 */
   2136      0    stevel 	if (size == 0) {
   2137      0    stevel 		ph->ph_size = 0;
   2138      0    stevel 		ph->ph_data = NULL;
   2139      0    stevel 		ph->ph_cur_pos = NULL;
   2140      0    stevel 		ph->ph_save_pos = NULL;
   2141      0    stevel 	} else {
   2142      0    stevel 		if (ph->ph_flags == DDI_PROP_DONTSLEEP) {
   2143      0    stevel 			ph->ph_data = kmem_zalloc(size, KM_NOSLEEP);
   2144      0    stevel 			if (ph->ph_data == NULL)
   2145      0    stevel 				return (DDI_PROP_NO_MEMORY);
   2146      0    stevel 		} else
   2147      0    stevel 			ph->ph_data = kmem_zalloc(size, KM_SLEEP);
   2148      0    stevel 		ph->ph_size = size;
   2149      0    stevel 		ph->ph_cur_pos = ph->ph_data;
   2150      0    stevel 		ph->ph_save_pos = ph->ph_data;
   2151      0    stevel 	}
   2152      0    stevel 	return (DDI_PROP_SUCCESS);
   2153      0    stevel }
   2154      0    stevel 
   2155      0    stevel /*
   2156      0    stevel  * Free the space allocated by the lookup routines.  Each lookup routine
   2157      0    stevel  * returns a pointer to the decoded data to the driver.  The driver then
   2158      0    stevel  * passes this pointer back to us.  This data actually lives in a struct
   2159      0    stevel  * prop_driver_data.  We use negative indexing to find the beginning of
   2160      0    stevel  * the structure and then free the entire structure using the size and
   2161      0    stevel  * the free routine stored in the structure.
   2162      0    stevel  */
   2163      0    stevel void
   2164      0    stevel ddi_prop_free(void *datap)
   2165      0    stevel {
   2166      0    stevel 	struct prop_driver_data *pdd;
   2167      0    stevel 
   2168      0    stevel 	/*
   2169      0    stevel 	 * Get the structure
   2170      0    stevel 	 */
   2171      0    stevel 	pdd = (struct prop_driver_data *)
   2172   4582       cth 	    ((caddr_t)datap - sizeof (struct prop_driver_data));
   2173      0    stevel 	/*
   2174      0    stevel 	 * Call the free routine to free it
   2175      0    stevel 	 */
   2176      0    stevel 	(*pdd->pdd_prop_free)(pdd);
   2177      0    stevel }
   2178      0    stevel 
   2179      0    stevel /*
   2180      0    stevel  * Free the data associated with an array of ints,
   2181      0    stevel  * allocated with ddi_prop_decode_alloc().
   2182      0    stevel  */
   2183      0    stevel static void
   2184      0    stevel ddi_prop_free_ints(struct prop_driver_data *pdd)
   2185      0    stevel {
   2186      0    stevel 	kmem_free(pdd, pdd->pdd_size);
   2187      0    stevel }
   2188      0    stevel 
   2189      0    stevel /*
   2190      0    stevel  * Free a single string property or a single string contained within
   2191      0    stevel  * the argv style return value of an array of strings.
   2192      0    stevel  */
   2193      0    stevel static void
   2194      0    stevel ddi_prop_free_string(struct prop_driver_data *pdd)
   2195      0    stevel {
   2196      0    stevel 	kmem_free(pdd, pdd->pdd_size);
   2197      0    stevel 
   2198      0    stevel }
   2199      0    stevel 
   2200      0    stevel /*
   2201      0    stevel  * Free an array of strings.
   2202      0    stevel  */
   2203      0    stevel static void
   2204      0    stevel ddi_prop_free_strings(struct prop_driver_data *pdd)
   2205      0    stevel {
   2206      0    stevel 	kmem_free(pdd, pdd->pdd_size);
   2207      0    stevel }
   2208      0    stevel 
   2209      0    stevel /*
   2210      0    stevel  * Free the data associated with an array of bytes.
   2211      0    stevel  */
   2212      0    stevel static void
   2213      0    stevel ddi_prop_free_bytes(struct prop_driver_data *pdd)
   2214      0    stevel {
   2215      0    stevel 	kmem_free(pdd, pdd->pdd_size);
   2216      0    stevel }
   2217      0    stevel 
   2218      0    stevel /*
   2219      0    stevel  * Reset the current location pointer in the property handle to the
   2220      0    stevel  * beginning of the data.
   2221      0    stevel  */
   2222      0    stevel void
   2223      0    stevel ddi_prop_reset_pos(prop_handle_t *ph)
   2224      0    stevel {
   2225      0    stevel 	ph->ph_cur_pos = ph->ph_data;
   2226      0    stevel 	ph->ph_save_pos = ph->ph_data;
   2227      0    stevel }
   2228      0    stevel 
   2229      0    stevel /*
   2230      0    stevel  * Restore the current location pointer in the property handle to the
   2231      0    stevel  * saved position.
   2232      0    stevel  */
   2233      0    stevel void
   2234      0    stevel ddi_prop_save_pos(prop_handle_t *ph)
   2235      0    stevel {
   2236      0    stevel 	ph->ph_save_pos = ph->ph_cur_pos;
   2237      0    stevel }
   2238      0    stevel 
   2239      0    stevel /*
   2240      0    stevel  * Save the location that the current location pointer is pointing to..
   2241      0    stevel  */
   2242      0    stevel void
   2243      0    stevel ddi_prop_restore_pos(prop_handle_t *ph)
   2244      0    stevel {
   2245      0    stevel 	ph->ph_cur_pos = ph->ph_save_pos;
   2246      0    stevel }
   2247      0    stevel 
   2248      0    stevel /*
   2249      0    stevel  * Property encode/decode functions
   2250      0    stevel  */
   2251      0    stevel 
   2252      0    stevel /*
   2253      0    stevel  * Decode a single integer property
   2254      0    stevel  */
   2255      0    stevel static int
   2256      0    stevel ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements)
   2257      0    stevel {
   2258      0    stevel 	int	i;
   2259      0    stevel 	int	tmp;
   2260      0    stevel 
   2261      0    stevel 	/*
   2262      0    stevel 	 * If there is nothing to decode return an error
   2263      0    stevel 	 */
   2264      0    stevel 	if (ph->ph_size == 0)
   2265      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2266      0    stevel 
   2267      0    stevel 	/*
   2268      0    stevel 	 * Decode the property as a single integer and return it
   2269      0    stevel 	 * in data if we were able to decode it.
   2270      0    stevel 	 */
   2271      0    stevel 	i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp);
   2272      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   2273      0    stevel 		switch (i) {
   2274      0    stevel 		case DDI_PROP_RESULT_EOF:
   2275      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2276      0    stevel 
   2277      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2278      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2279      0    stevel 		}
   2280      0    stevel 	}
   2281      0    stevel 
   2282      0    stevel 	*(int *)data = tmp;
   2283      0    stevel 	*nelements = 1;
   2284      0    stevel 	return (DDI_PROP_SUCCESS);
   2285      0    stevel }
   2286      0    stevel 
   2287      0    stevel /*
   2288      0    stevel  * Decode a single 64 bit integer property
   2289      0    stevel  */
   2290      0    stevel static int
   2291      0    stevel ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements)
   2292      0    stevel {
   2293      0    stevel 	int	i;
   2294      0    stevel 	int64_t	tmp;
   2295      0    stevel 
   2296      0    stevel 	/*
   2297      0    stevel 	 * If there is nothing to decode return an error
   2298      0    stevel 	 */
   2299      0    stevel 	if (ph->ph_size == 0)
   2300      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2301      0    stevel 
   2302      0    stevel 	/*
   2303      0    stevel 	 * Decode the property as a single integer and return it
   2304      0    stevel 	 * in data if we were able to decode it.
   2305      0    stevel 	 */
   2306      0    stevel 	i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp);
   2307      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   2308      0    stevel 		switch (i) {
   2309      0    stevel 		case DDI_PROP_RESULT_EOF:
   2310      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2311      0    stevel 
   2312      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2313      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2314      0    stevel 		}
   2315      0    stevel 	}
   2316      0    stevel 
   2317      0    stevel 	*(int64_t *)data = tmp;
   2318      0    stevel 	*nelements = 1;
   2319      0    stevel 	return (DDI_PROP_SUCCESS);
   2320      0    stevel }
   2321      0    stevel 
   2322      0    stevel /*
   2323      0    stevel  * Decode an array of integers property
   2324      0    stevel  */
   2325      0    stevel static int
   2326      0    stevel ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
   2327      0    stevel {
   2328      0    stevel 	int	i;
   2329      0    stevel 	int	cnt = 0;
   2330      0    stevel 	int	*tmp;
   2331      0    stevel 	int	*intp;
   2332      0    stevel 	int	n;
   2333      0    stevel 
   2334      0    stevel 	/*
   2335      0    stevel 	 * Figure out how many array elements there are by going through the
   2336      0    stevel 	 * data without decoding it first and counting.
   2337      0    stevel 	 */
   2338      0    stevel 	for (;;) {
   2339      0    stevel 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
   2340      0    stevel 		if (i < 0)
   2341      0    stevel 			break;
   2342      0    stevel 		cnt++;
   2343      0    stevel 	}
   2344      0    stevel 
   2345      0    stevel 	/*
   2346      0    stevel 	 * If there are no elements return an error
   2347      0    stevel 	 */
   2348      0    stevel 	if (cnt == 0)
   2349      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2350      0    stevel 
   2351      0    stevel 	/*
   2352      0    stevel 	 * If we cannot skip through the data, we cannot decode it
   2353      0    stevel 	 */
   2354      0    stevel 	if (i == DDI_PROP_RESULT_ERROR)
   2355      0    stevel 		return (DDI_PROP_CANNOT_DECODE);
   2356      0    stevel 
   2357      0    stevel 	/*
   2358      0    stevel 	 * Reset the data pointer to the beginning of the encoded data
   2359      0    stevel 	 */
   2360      0    stevel 	ddi_prop_reset_pos(ph);
   2361      0    stevel 
   2362      0    stevel 	/*
   2363      0    stevel 	 * Allocated memory to store the decoded value in.
   2364      0    stevel 	 */
   2365      0    stevel 	intp = ddi_prop_decode_alloc((cnt * sizeof (int)),
   2366   4582       cth 	    ddi_prop_free_ints);
   2367      0    stevel 
   2368      0    stevel 	/*
   2369      0    stevel 	 * Decode each element and place it in the space we just allocated
   2370      0    stevel 	 */
   2371      0    stevel 	tmp = intp;
   2372      0    stevel 	for (n = 0; n < cnt; n++, tmp++) {
   2373      0    stevel 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
   2374      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2375      0    stevel 			/*
   2376      0    stevel 			 * Free the space we just allocated
   2377      0    stevel 			 * and return an error.
   2378      0    stevel 			 */
   2379      0    stevel 			ddi_prop_free(intp);
   2380      0    stevel 			switch (i) {
   2381      0    stevel 			case DDI_PROP_RESULT_EOF:
   2382      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2383      0    stevel 
   2384      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2385      0    stevel 				return (DDI_PROP_CANNOT_DECODE);
   2386      0    stevel 			}
   2387      0    stevel 		}
   2388      0    stevel 	}
   2389      0    stevel 
   2390      0    stevel 	*nelements = cnt;
   2391      0    stevel 	*(int **)data = intp;
   2392      0    stevel 
   2393      0    stevel 	return (DDI_PROP_SUCCESS);
   2394      0    stevel }
   2395      0    stevel 
   2396      0    stevel /*
   2397      0    stevel  * Decode a 64 bit integer array property
   2398      0    stevel  */
   2399      0    stevel static int
   2400      0    stevel ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements)
   2401      0    stevel {
   2402      0    stevel 	int	i;
   2403      0    stevel 	int	n;
   2404      0    stevel 	int	cnt = 0;
   2405      0    stevel 	int64_t	*tmp;
   2406      0    stevel 	int64_t	*intp;
   2407      0    stevel 
   2408      0    stevel 	/*
   2409      0    stevel 	 * Count the number of array elements by going
   2410      0    stevel 	 * through the data without decoding it.
   2411      0    stevel 	 */
   2412      0    stevel 	for (;;) {
   2413      0    stevel 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL);
   2414      0    stevel 		if (i < 0)
   2415      0    stevel 			break;
   2416      0    stevel 		cnt++;
   2417      0    stevel 	}
   2418      0    stevel 
   2419      0    stevel 	/*
   2420      0    stevel 	 * If there are no elements return an error
   2421      0    stevel 	 */
   2422      0    stevel 	if (cnt == 0)
   2423      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2424      0    stevel 
   2425      0    stevel 	/*
   2426      0    stevel 	 * If we cannot skip through the data, we cannot decode it
   2427      0    stevel 	 */
   2428      0    stevel 	if (i == DDI_PROP_RESULT_ERROR)
   2429      0    stevel 		return (DDI_PROP_CANNOT_DECODE);
   2430      0    stevel 
   2431      0    stevel 	/*
   2432      0    stevel 	 * Reset the data pointer to the beginning of the encoded data
   2433      0    stevel 	 */
   2434      0    stevel 	ddi_prop_reset_pos(ph);
   2435      0    stevel 
   2436      0    stevel 	/*
   2437      0    stevel 	 * Allocate memory to store the decoded value.
   2438      0    stevel 	 */
   2439      0    stevel 	intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)),
   2440   4582       cth 	    ddi_prop_free_ints);
   2441      0    stevel 
   2442      0    stevel 	/*
   2443      0    stevel 	 * Decode each element and place it in the space allocated
   2444      0    stevel 	 */
   2445      0    stevel 	tmp = intp;
   2446      0    stevel 	for (n = 0; n < cnt; n++, tmp++) {
   2447      0    stevel 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp);
   2448      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2449      0    stevel 			/*
   2450      0    stevel 			 * Free the space we just allocated
   2451      0    stevel 			 * and return an error.
   2452      0    stevel 			 */
   2453      0    stevel 			ddi_prop_free(intp);
   2454      0    stevel 			switch (i) {
   2455      0    stevel 			case DDI_PROP_RESULT_EOF:
   2456      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2457      0    stevel 
   2458      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2459      0    stevel 				return (DDI_PROP_CANNOT_DECODE);
   2460      0    stevel 			}
   2461      0    stevel 		}
   2462      0    stevel 	}
   2463      0    stevel 
   2464      0    stevel 	*nelements = cnt;
   2465      0    stevel 	*(int64_t **)data = intp;
   2466      0    stevel 
   2467      0    stevel 	return (DDI_PROP_SUCCESS);
   2468      0    stevel }
   2469      0    stevel 
   2470      0    stevel /*
   2471      0    stevel  * Encode an array of integers property (Can be one element)
   2472      0    stevel  */
   2473      0    stevel int
   2474      0    stevel ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements)
   2475      0    stevel {
   2476      0    stevel 	int	i;
   2477      0    stevel 	int	*tmp;
   2478      0    stevel 	int	cnt;
   2479      0    stevel 	int	size;
   2480      0    stevel 
   2481      0    stevel 	/*
   2482      0    stevel 	 * If there is no data, we cannot do anything
   2483      0    stevel 	 */
   2484      0    stevel 	if (nelements == 0)
   2485      0    stevel 		return (DDI_PROP_CANNOT_ENCODE);
   2486      0    stevel 
   2487      0    stevel 	/*
   2488      0    stevel 	 * Get the size of an encoded int.
   2489      0    stevel 	 */
   2490      0    stevel 	size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
   2491      0    stevel 
   2492      0    stevel 	if (size < DDI_PROP_RESULT_OK) {
   2493      0    stevel 		switch (size) {
   2494      0    stevel 		case DDI_PROP_RESULT_EOF:
   2495      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2496      0    stevel 
   2497      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2498      0    stevel 			return (DDI_PROP_CANNOT_ENCODE);
   2499      0    stevel 		}
   2500      0    stevel 	}
   2501      0    stevel 
   2502      0    stevel 	/*
   2503      0    stevel 	 * Allocate space in the handle to store the encoded int.
   2504      0    stevel 	 */
   2505      0    stevel 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
   2506   4582       cth 	    DDI_PROP_SUCCESS)
   2507      0    stevel 		return (DDI_PROP_NO_MEMORY);
   2508      0    stevel 
   2509      0    stevel 	/*
   2510      0    stevel 	 * Encode the array of ints.
   2511      0    stevel 	 */
   2512      0    stevel 	tmp = (int *)data;
   2513      0    stevel 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
   2514      0    stevel 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp);
   2515      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2516      0    stevel 			switch (i) {
   2517      0    stevel 			case DDI_PROP_RESULT_EOF:
   2518      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2519      0    stevel 
   2520      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2521      0    stevel 				return (DDI_PROP_CANNOT_ENCODE);
   2522      0    stevel 			}
   2523      0    stevel 		}
   2524      0    stevel 	}
   2525      0    stevel 
   2526      0    stevel 	return (DDI_PROP_SUCCESS);
   2527      0    stevel }
   2528      0    stevel 
   2529      0    stevel 
   2530      0    stevel /*
   2531      0    stevel  * Encode a 64 bit integer array property
   2532      0    stevel  */
   2533      0    stevel int
   2534      0    stevel ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements)
   2535      0    stevel {
   2536      0    stevel 	int i;
   2537      0    stevel 	int cnt;
   2538      0    stevel 	int size;
   2539      0    stevel 	int64_t *tmp;
   2540      0    stevel 
   2541      0    stevel 	/*
   2542      0    stevel 	 * If there is no data, we cannot do anything
   2543      0    stevel 	 */
   2544      0    stevel 	if (nelements == 0)
   2545      0    stevel 		return (DDI_PROP_CANNOT_ENCODE);
   2546      0    stevel 
   2547      0    stevel 	/*
   2548      0    stevel 	 * Get the size of an encoded 64 bit int.
   2549      0    stevel 	 */
   2550      0    stevel 	size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
   2551      0    stevel 
   2552      0    stevel 	if (size < DDI_PROP_RESULT_OK) {
   2553      0    stevel 		switch (size) {
   2554      0    stevel 		case DDI_PROP_RESULT_EOF:
   2555      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2556      0    stevel 
   2557      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2558      0    stevel 			return (DDI_PROP_CANNOT_ENCODE);
   2559      0    stevel 		}
   2560      0    stevel 	}
   2561      0    stevel 
   2562      0    stevel 	/*
   2563      0    stevel 	 * Allocate space in the handle to store the encoded int.
   2564      0    stevel 	 */
   2565      0    stevel 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
   2566      0    stevel 	    DDI_PROP_SUCCESS)
   2567      0    stevel 		return (DDI_PROP_NO_MEMORY);
   2568      0    stevel 
   2569      0    stevel 	/*
   2570      0    stevel 	 * Encode the array of ints.
   2571      0    stevel 	 */
   2572      0    stevel 	tmp = (int64_t *)data;
   2573      0    stevel 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
   2574      0    stevel 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp);
   2575      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2576      0    stevel 			switch (i) {
   2577      0    stevel 			case DDI_PROP_RESULT_EOF:
   2578      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2579      0    stevel 
   2580      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2581      0    stevel 				return (DDI_PROP_CANNOT_ENCODE);
   2582      0    stevel 			}
   2583      0    stevel 		}
   2584      0    stevel 	}
   2585      0    stevel 
   2586      0    stevel 	return (DDI_PROP_SUCCESS);
   2587      0    stevel }
   2588      0    stevel 
   2589      0    stevel /*
   2590      0    stevel  * Decode a single string property
   2591      0    stevel  */
   2592      0    stevel static int
   2593      0    stevel ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements)
   2594      0    stevel {
   2595      0    stevel 	char		*tmp;
   2596      0    stevel 	char		*str;
   2597      0    stevel 	int		i;
   2598      0    stevel 	int		size;
   2599      0    stevel 
   2600      0    stevel 	/*
   2601      0    stevel 	 * If there is nothing to decode return an error
   2602      0    stevel 	 */
   2603      0    stevel 	if (ph->ph_size == 0)
   2604      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2605      0    stevel 
   2606      0    stevel 	/*
   2607      0    stevel 	 * Get the decoded size of the encoded string.
   2608      0    stevel 	 */
   2609      0    stevel 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
   2610      0    stevel 	if (size < DDI_PROP_RESULT_OK) {
   2611      0    stevel 		switch (size) {
   2612      0    stevel 		case DDI_PROP_RESULT_EOF:
   2613      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2614      0    stevel 
   2615      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2616      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2617      0    stevel 		}
   2618      0    stevel 	}
   2619      0    stevel 
   2620      0    stevel 	/*
   2621      0    stevel 	 * Allocated memory to store the decoded value in.
   2622      0    stevel 	 */
   2623      0    stevel 	str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string);
   2624      0    stevel 
   2625      0    stevel 	ddi_prop_reset_pos(ph);
   2626      0    stevel 
   2627      0    stevel 	/*
   2628      0    stevel 	 * Decode the str and place it in the space we just allocated
   2629      0    stevel 	 */
   2630      0    stevel 	tmp = str;
   2631      0    stevel 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
   2632      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   2633      0    stevel 		/*
   2634      0    stevel 		 * Free the space we just allocated
   2635      0    stevel 		 * and return an error.
   2636      0    stevel 		 */
   2637      0    stevel 		ddi_prop_free(str);
   2638      0    stevel 		switch (i) {
   2639      0    stevel 		case DDI_PROP_RESULT_EOF:
   2640      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2641      0    stevel 
   2642      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2643      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2644      0    stevel 		}
   2645      0    stevel 	}
   2646      0    stevel 
   2647      0    stevel 	*(char **)data = str;
   2648      0    stevel 	*nelements = 1;
   2649      0    stevel 
   2650      0    stevel 	return (DDI_PROP_SUCCESS);
   2651      0    stevel }
   2652      0    stevel 
   2653      0    stevel /*
   2654      0    stevel  * Decode an array of strings.
   2655      0    stevel  */
   2656      0    stevel int
   2657      0    stevel ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
   2658      0    stevel {
   2659      0    stevel 	int		cnt = 0;
   2660      0    stevel 	char		**strs;
   2661      0    stevel 	char		**tmp;
   2662      0    stevel 	char		*ptr;
   2663      0    stevel 	int		i;
   2664      0    stevel 	int		n;
   2665      0    stevel 	int		size;
   2666      0    stevel 	size_t		nbytes;
   2667      0    stevel 
   2668      0    stevel 	/*
   2669      0    stevel 	 * Figure out how many array elements there are by going through the
   2670      0    stevel 	 * data without decoding it first and counting.
   2671      0    stevel 	 */
   2672      0    stevel 	for (;;) {
   2673      0    stevel 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL);
   2674      0    stevel 		if (i < 0)
   2675      0    stevel 			break;
   2676      0    stevel 		cnt++;
   2677      0    stevel 	}
   2678      0    stevel 
   2679      0    stevel 	/*
   2680      0    stevel 	 * If there are no elements return an error
   2681      0    stevel 	 */
   2682      0    stevel 	if (cnt == 0)
   2683      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2684      0    stevel 
   2685      0    stevel 	/*
   2686      0    stevel 	 * If we cannot skip through the data, we cannot decode it
   2687      0    stevel 	 */
   2688      0    stevel 	if (i == DDI_PROP_RESULT_ERROR)
   2689      0    stevel 		return (DDI_PROP_CANNOT_DECODE);
   2690      0    stevel 
   2691      0    stevel 	/*
   2692      0    stevel 	 * Reset the data pointer to the beginning of the encoded data
   2693      0    stevel 	 */
   2694      0    stevel 	ddi_prop_reset_pos(ph);
   2695      0    stevel 
   2696      0    stevel 	/*
   2697      0    stevel 	 * Figure out how much memory we need for the sum total
   2698      0    stevel 	 */
   2699      0    stevel 	nbytes = (cnt + 1) * sizeof (char *);
   2700      0    stevel 
   2701      0    stevel 	for (n = 0; n < cnt; n++) {
   2702      0    stevel 		/*
   2703      0    stevel 		 * Get the decoded size of the current encoded string.
   2704      0    stevel 		 */
   2705      0    stevel 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
   2706      0    stevel 		if (size < DDI_PROP_RESULT_OK) {
   2707      0    stevel 			switch (size) {
   2708      0    stevel 			case DDI_PROP_RESULT_EOF:
   2709      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2710      0    stevel 
   2711      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2712      0    stevel 				return (DDI_PROP_CANNOT_DECODE);
   2713      0    stevel 			}
   2714      0    stevel 		}
   2715      0    stevel 
   2716      0    stevel 		nbytes += size;
   2717      0    stevel 	}
   2718      0    stevel 
   2719      0    stevel 	/*
   2720      0    stevel 	 * Allocate memory in which to store the decoded strings.
   2721      0    stevel 	 */
   2722      0    stevel 	strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings);
   2723      0    stevel 
   2724      0    stevel 	/*
   2725      0    stevel 	 * Set up pointers for each string by figuring out yet
   2726      0    stevel 	 * again how long each string is.
   2727      0    stevel 	 */
   2728      0    stevel 	ddi_prop_reset_pos(ph);
   2729      0    stevel 	ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *));
   2730      0    stevel 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
   2731      0    stevel 		/*
   2732      0    stevel 		 * Get the decoded size of the current encoded string.
   2733      0    stevel 		 */
   2734      0    stevel 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
   2735      0    stevel 		if (size < DDI_PROP_RESULT_OK) {
   2736      0    stevel 			ddi_prop_free(strs);
   2737      0    stevel 			switch (size) {
   2738      0    stevel 			case DDI_PROP_RESULT_EOF:
   2739      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2740      0    stevel 
   2741      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2742      0    stevel 				return (DDI_PROP_CANNOT_DECODE);
   2743      0    stevel 			}
   2744      0    stevel 		}
   2745      0    stevel 
   2746      0    stevel 		*tmp = ptr;
   2747      0    stevel 		ptr += size;
   2748      0    stevel 	}
   2749      0    stevel 
   2750      0    stevel 	/*
   2751      0    stevel 	 * String array is terminated by a NULL
   2752      0    stevel 	 */
   2753      0    stevel 	*tmp = NULL;
   2754      0    stevel 
   2755      0    stevel 	/*
   2756      0    stevel 	 * Finally, we can decode each string
   2757      0    stevel 	 */
   2758      0    stevel 	ddi_prop_reset_pos(ph);
   2759      0    stevel 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
   2760      0    stevel 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp);
   2761      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2762      0    stevel 			/*
   2763      0    stevel 			 * Free the space we just allocated
   2764      0    stevel 			 * and return an error
   2765      0    stevel 			 */
   2766      0    stevel 			ddi_prop_free(strs);
   2767      0    stevel 			switch (i) {
   2768      0    stevel 			case DDI_PROP_RESULT_EOF:
   2769      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2770      0    stevel 
   2771      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2772      0    stevel 				return (DDI_PROP_CANNOT_DECODE);
   2773      0    stevel 			}
   2774      0    stevel 		}
   2775      0    stevel 	}
   2776      0    stevel 
   2777      0    stevel 	*(char ***)data = strs;
   2778      0    stevel 	*nelements = cnt;
   2779      0    stevel 
   2780      0    stevel 	return (DDI_PROP_SUCCESS);
   2781      0    stevel }
   2782      0    stevel 
   2783      0    stevel /*
   2784      0    stevel  * Encode a string.
   2785      0    stevel  */
   2786      0    stevel int
   2787      0    stevel ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements)
   2788      0    stevel {
   2789      0    stevel 	char		**tmp;
   2790      0    stevel 	int		size;
   2791      0    stevel 	int		i;
   2792      0    stevel 
   2793      0    stevel 	/*
   2794      0    stevel 	 * If there is no data, we cannot do anything
   2795      0    stevel 	 */
   2796      0    stevel 	if (nelements == 0)
   2797      0    stevel 		return (DDI_PROP_CANNOT_ENCODE);
   2798      0    stevel 
   2799      0    stevel 	/*
   2800      0    stevel 	 * Get the size of the encoded string.
   2801      0    stevel 	 */
   2802      0    stevel 	tmp = (char **)data;
   2803      0    stevel 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
   2804      0    stevel 	if (size < DDI_PROP_RESULT_OK) {
   2805      0    stevel 		switch (size) {
   2806      0    stevel 		case DDI_PROP_RESULT_EOF:
   2807      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2808      0    stevel 
   2809      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2810      0    stevel 			return (DDI_PROP_CANNOT_ENCODE);
   2811      0    stevel 		}
   2812      0    stevel 	}
   2813      0    stevel 
   2814      0    stevel 	/*
   2815      0    stevel 	 * Allocate space in the handle to store the encoded string.
   2816      0    stevel 	 */
   2817      0    stevel 	if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS)
   2818      0    stevel 		return (DDI_PROP_NO_MEMORY);
   2819      0    stevel 
   2820      0    stevel 	ddi_prop_reset_pos(ph);
   2821      0    stevel 
   2822      0    stevel 	/*
   2823      0    stevel 	 * Encode the string.
   2824      0    stevel 	 */
   2825      0    stevel 	tmp = (char **)data;
   2826      0    stevel 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
   2827      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   2828      0    stevel 		switch (i) {
   2829      0    stevel 		case DDI_PROP_RESULT_EOF:
   2830      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2831      0    stevel 
   2832      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2833      0    stevel 			return (DDI_PROP_CANNOT_ENCODE);
   2834      0    stevel 		}
   2835      0    stevel 	}
   2836      0    stevel 
   2837      0    stevel 	return (DDI_PROP_SUCCESS);
   2838      0    stevel }
   2839      0    stevel 
   2840      0    stevel 
   2841      0    stevel /*
   2842      0    stevel  * Encode an array of strings.
   2843      0    stevel  */
   2844      0    stevel int
   2845      0    stevel ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements)
   2846      0    stevel {
   2847      0    stevel 	int		cnt = 0;
   2848      0    stevel 	char		**tmp;
   2849      0    stevel 	int		size;
   2850      0    stevel 	uint_t		total_size;
   2851      0    stevel 	int		i;
   2852      0    stevel 
   2853      0    stevel 	/*
   2854      0    stevel 	 * If there is no data, we cannot do anything
   2855      0    stevel 	 */
   2856      0    stevel 	if (nelements == 0)
   2857      0    stevel 		return (DDI_PROP_CANNOT_ENCODE);
   2858      0    stevel 
   2859      0    stevel 	/*
   2860      0    stevel 	 * Get the total size required to encode all the strings.
   2861      0    stevel 	 */
   2862      0    stevel 	total_size = 0;
   2863      0    stevel 	tmp = (char **)data;
   2864      0    stevel 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
   2865      0    stevel 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
   2866      0    stevel 		if (size < DDI_PROP_RESULT_OK) {
   2867      0    stevel 			switch (size) {
   2868      0    stevel 			case DDI_PROP_RESULT_EOF:
   2869      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2870      0    stevel 
   2871      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2872      0    stevel 				return (DDI_PROP_CANNOT_ENCODE);
   2873      0    stevel 			}
   2874      0    stevel 		}
   2875      0    stevel 		total_size += (uint_t)size;
   2876      0    stevel 	}
   2877      0    stevel 
   2878      0    stevel 	/*
   2879      0    stevel 	 * Allocate space in the handle to store the encoded strings.
   2880      0    stevel 	 */
   2881      0    stevel 	if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS)
   2882      0    stevel 		return (DDI_PROP_NO_MEMORY);
   2883      0    stevel 
   2884      0    stevel 	ddi_prop_reset_pos(ph);
   2885      0    stevel 
   2886      0    stevel 	/*
   2887      0    stevel 	 * Encode the array of strings.
   2888      0    stevel 	 */
   2889      0    stevel 	tmp = (char **)data;
   2890      0    stevel 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
   2891      0    stevel 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
   2892      0    stevel 		if (i < DDI_PROP_RESULT_OK) {
   2893      0    stevel 			switch (i) {
   2894      0    stevel 			case DDI_PROP_RESULT_EOF:
   2895      0    stevel 				return (DDI_PROP_END_OF_DATA);
   2896      0    stevel 
   2897      0    stevel 			case DDI_PROP_RESULT_ERROR:
   2898      0    stevel 				return (DDI_PROP_CANNOT_ENCODE);
   2899      0    stevel 			}
   2900      0    stevel 		}
   2901      0    stevel 	}
   2902      0    stevel 
   2903      0    stevel 	return (DDI_PROP_SUCCESS);
   2904      0    stevel }
   2905      0    stevel 
   2906      0    stevel 
   2907      0    stevel /*
   2908      0    stevel  * Decode an array of bytes.
   2909      0    stevel  */
   2910      0    stevel static int
   2911      0    stevel ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
   2912      0    stevel {
   2913      0    stevel 	uchar_t		*tmp;
   2914      0    stevel 	int		nbytes;
   2915      0    stevel 	int		i;
   2916      0    stevel 
   2917      0    stevel 	/*
   2918      0    stevel 	 * If there are no elements return an error
   2919      0    stevel 	 */
   2920      0    stevel 	if (ph->ph_size == 0)
   2921      0    stevel 		return (DDI_PROP_END_OF_DATA);
   2922      0    stevel 
   2923      0    stevel 	/*
   2924      0    stevel 	 * Get the size of the encoded array of bytes.
   2925      0    stevel 	 */
   2926      0    stevel 	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
   2927   4582       cth 	    data, ph->ph_size);
   2928      0    stevel 	if (nbytes < DDI_PROP_RESULT_OK) {
   2929      0    stevel 		switch (nbytes) {
   2930      0    stevel 		case DDI_PROP_RESULT_EOF:
   2931      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2932      0    stevel 
   2933      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2934      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2935      0    stevel 		}
   2936      0    stevel 	}
   2937      0    stevel 
   2938      0    stevel 	/*
   2939      0    stevel 	 * Allocated memory to store the decoded value in.
   2940      0    stevel 	 */
   2941      0    stevel 	tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes);
   2942      0    stevel 
   2943      0    stevel 	/*
   2944      0    stevel 	 * Decode each element and place it in the space we just allocated
   2945      0    stevel 	 */
   2946      0    stevel 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
   2947      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   2948      0    stevel 		/*
   2949      0    stevel 		 * Free the space we just allocated
   2950      0    stevel 		 * and return an error
   2951      0    stevel 		 */
   2952      0    stevel 		ddi_prop_free(tmp);
   2953      0    stevel 		switch (i) {
   2954      0    stevel 		case DDI_PROP_RESULT_EOF:
   2955      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2956      0    stevel 
   2957      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2958      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2959      0    stevel 		}
   2960      0    stevel 	}
   2961      0    stevel 
   2962      0    stevel 	*(uchar_t **)data = tmp;
   2963      0    stevel 	*nelements = nbytes;
   2964      0    stevel 
   2965      0    stevel 	return (DDI_PROP_SUCCESS);
   2966      0    stevel }
   2967      0    stevel 
   2968      0    stevel /*
   2969      0    stevel  * Encode an array of bytes.
   2970      0    stevel  */
   2971      0    stevel int
   2972      0    stevel ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements)
   2973      0    stevel {
   2974      0    stevel 	int		size;
   2975      0    stevel 	int		i;
   2976      0    stevel 
   2977      0    stevel 	/*
   2978      0    stevel 	 * If there are no elements, then this is a boolean property,
   2979      0    stevel 	 * so just create a property handle with no data and return.
   2980      0    stevel 	 */
   2981      0    stevel 	if (nelements == 0) {
   2982      0    stevel 		(void) ddi_prop_encode_alloc(ph, 0);
   2983      0    stevel 		return (DDI_PROP_SUCCESS);
   2984      0    stevel 	}
   2985      0    stevel 
   2986      0    stevel 	/*
   2987      0    stevel 	 * Get the size of the encoded array of bytes.
   2988      0    stevel 	 */
   2989      0    stevel 	size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data,
   2990   4582       cth 	    nelements);
   2991      0    stevel 	if (size < DDI_PROP_RESULT_OK) {
   2992      0    stevel 		switch (size) {
   2993      0    stevel 		case DDI_PROP_RESULT_EOF:
   2994      0    stevel 			return (DDI_PROP_END_OF_DATA);
   2995      0    stevel 
   2996      0    stevel 		case DDI_PROP_RESULT_ERROR:
   2997      0    stevel 			return (DDI_PROP_CANNOT_DECODE);
   2998      0    stevel 		}
   2999      0    stevel 	}
   3000      0    stevel 
   3001      0    stevel 	/*
   3002      0    stevel 	 * Allocate space in the handle to store the encoded bytes.
   3003      0    stevel 	 */
   3004      0    stevel 	if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS)
   3005      0    stevel 		return (DDI_PROP_NO_MEMORY);
   3006      0    stevel 
   3007      0    stevel 	/*
   3008      0    stevel 	 * Encode the array of bytes.
   3009      0    stevel 	 */
   3010      0    stevel 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data,
   3011   4582       cth 	    nelements);
   3012      0    stevel 	if (i < DDI_PROP_RESULT_OK) {
   3013      0    stevel 		switch (i) {
   3014      0    stevel 		case DDI_PROP_RESULT_EOF:
   3015      0    stevel 			return (DDI_PROP_END_OF_DATA);
   3016      0    stevel 
   3017      0    stevel 		case DDI_PROP_RESULT_ERROR:
   3018      0    stevel 			return (DDI_PROP_CANNOT_ENCODE);
   3019      0    stevel 		}
   3020      0    stevel 	}
   3021      0    stevel 
   3022      0    stevel 	return (DDI_PROP_SUCCESS);
   3023      0    stevel }
   3024      0    stevel 
   3025      0    stevel /*
   3026      0    stevel  * OBP 1275 integer, string and byte operators.
   3027      0    stevel  *
   3028      0    stevel  * DDI_PROP_CMD_DECODE:
   3029      0    stevel  *
   3030      0    stevel  *	DDI_PROP_RESULT_ERROR:		cannot decode the data
   3031      0    stevel  *	DDI_PROP_RESULT_EOF:		end of data
   3032      0    stevel  *	DDI_PROP_OK:			data was decoded
   3033      0    stevel  *
   3034      0    stevel  * DDI_PROP_CMD_ENCODE:
   3035      0    stevel  *
   3036      0    stevel  *	DDI_PROP_RESULT_ERROR:		cannot encode the data
   3037      0    stevel  *	DDI_PROP_RESULT_EOF:		end of data
   3038      0    stevel  *	DDI_PROP_OK:			data was encoded
   3039      0    stevel  *
   3040      0    stevel  * DDI_PROP_CMD_SKIP:
   3041      0    stevel  *
   3042      0    stevel  *	DDI_PROP_RESULT_ERROR:		cannot skip the data
   3043      0    stevel  *	DDI_PROP_RESULT_EOF:		end of data
   3044      0    stevel  *	DDI_PROP_OK:			data was skipped
   3045      0    stevel  *
   3046      0    stevel  * DDI_PROP_CMD_GET_ESIZE:
   3047      0    stevel  *
   3048      0    stevel  *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
   3049      0    stevel  *	DDI_PROP_RESULT_EOF:		end of data
   3050      0    stevel  *	> 0:				the encoded size
   3051      0    stevel  *
   3052      0    stevel  * DDI_PROP_CMD_GET_DSIZE:
   3053      0    stevel  *
   3054      0    stevel  *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
   3055      0    stevel  *	DDI_PROP_RESULT_EOF:		end of data
   3056      0    stevel  *	> 0:				the decoded size
   3057      0    stevel  */
   3058      0    stevel 
   3059      0    stevel /*
   3060      0    stevel  * OBP 1275 integer operator
   3061      0    stevel  *
   3062      0    stevel  * OBP properties are a byte stream of data, so integers may not be
   3063      0    stevel  * properly aligned.  Therefore we need to copy them one byte at a time.
   3064      0    stevel  */
   3065      0    stevel int
   3066      0    stevel ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
   3067      0    stevel {
   3068      0    stevel 	int	i;
   3069      0    stevel 
   3070      0    stevel 	switch (cmd) {
   3071      0    stevel 	case DDI_PROP_CMD_DECODE:
   3072      0    stevel 		/*
   3073      0    stevel 		 * Check that there is encoded data
   3074      0    stevel 		 */
   3075      0    stevel 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
   3076      0    stevel 			return (DDI_PROP_RESULT_ERROR);
   3077      0    stevel 		if (ph->ph_flags & PH_FROM_PROM) {
   3078      0    stevel 			i = MIN(ph->ph_size, PROP_1275_INT_SIZE);
   3079      0    stevel 			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
   3080   4582       cth 			    ph->ph_size - i))
   3081      0    stevel 				return (DDI_PROP_RESULT_ERROR);
   3082      0    stevel 		} else {
   3083      0    stevel 			if (ph->ph_size < sizeof (int) ||
   3084   4582       cth 			    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
   3085   4582       cth 			    ph->ph_size - sizeof (int))))
   3086   4582       cth 				return (DDI_PROP_RESULT_ERROR);
   3087      0    stevel 		}
   3088      0    stevel 
   3089      0    stevel 		/*
   3090      0    stevel 		 * Copy the integer, using the implementation-specific
   3091      0    stevel 		 * copy function if the property is coming from the PROM.
   3092      0    stevel 		 */
   3093      0    stevel 		if (ph->ph_flags & PH_FROM_PROM) {
   3094      0    stevel 			*data = impl_ddi_prop_int_from_prom(
   3095   4582       cth 			    (uchar_t *)ph->ph_cur_pos,
   3096   4582       cth 			    (ph->ph_size < PROP_1275_INT_SIZE) ?
   3097   4582       cth 			    ph->ph_size : PROP_1275_INT_SIZE);
   3098      0    stevel 		} else {
   3099      0    stevel 			bcopy(ph->ph_cur_pos, data, sizeof (int));
   3100      0    stevel 		}
   3101      0    stevel 
   3102      0    stevel 		/*
   3103      0    stevel 		 * Move the current location to the start of the next
   3104      0    stevel 		 * bit of undecoded data.
   3105      0    stevel 		 */
   3106      0    stevel 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
   3107   4582       cth 		    PROP_1275_INT_SIZE;
   3108      0    stevel 		return (DDI_PROP_RESULT_OK);
   3109      0    stevel 
   3110      0    stevel 	case DDI_PROP_CMD_ENCODE:
   3111      0    stevel 		/*
   3112      0    stevel 		 * Check that there is room to encoded the data
   3113      0    stevel 		 */
   3114      0    stevel 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
   3115   4582       cth 		    ph->ph_size < PROP_1275_INT_SIZE ||
   3116   4582       cth 		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
   3117   4582       cth 		    ph->ph_size - sizeof (int))))
   3118      0    stevel 			return (DDI_PROP_RESULT_ERROR);
   3119      0    stevel 
   3120      0    stevel 		/*
   3121      0    stevel 		 * Encode the integer into the byte stream one byte at a
   3122      0    stevel 		 * time.
   3123      0    stevel 		 */
   3124      0    stevel 		bcopy(data, ph->ph_cur_pos, sizeof (int));
   3125      0    stevel 
   3126      0    stevel 		/*
   3127      0    stevel 		 * Move the current location to the start of the next bit of
   3128      0    stevel 		 * space where we can store encoded data.
   3129      0    stevel 		 */
   3130      0    stevel 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
   3131      0    stevel 		return (DDI_PROP_RESULT_OK);
   3132      0    stevel 
   3133      0    stevel 	case DDI_PROP_CMD_SKIP:
   3134      0    stevel 		/*
   3135      0    stevel 		 * Check that there is encoded data
   3136      0    stevel 		 */
   3137      0    stevel 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
   3138   4582       cth 		    ph->ph_size < PROP_1275_INT_SIZE)
   3139   4582       cth 			return (DDI_PROP_RESULT_ERROR);
   3140   4582       cth 
   3141      0    stevel 
   3142      0    stevel 		if ((caddr_t)ph->ph_cur_pos ==
   3143      0    stevel 		    (caddr_t)ph->ph_data + ph->ph_size) {
   3144      0    stevel 			return (DDI_PROP_RESULT_EOF);
   3145      0    stevel 		} else if ((caddr_t)ph->ph_cur_pos >
   3146      0    stevel 		    (caddr_t)ph->ph_data + ph->ph_size) {
   3147      0    stevel 			return (DDI_PROP_RESULT_EOF);
   3148      0    stevel 		}
   3149      0    stevel 
   3150      0    stevel 		/*
   3151   4582       cth 		 * Move the current location to the start of the next bit of
   3152   4582       cth 		 * undecoded data.
   3153   4582       cth 		 */
   3154   4582       cth 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
   3155   4582       cth 		return (DDI_PROP_RESULT_OK);
   3156   4582       cth 
   3157   4582       cth 	case DDI_PROP_CMD_GET_ESIZE:
   3158   4582       cth 		/*
   3159   4582       cth 		 * Return the size of an encoded integer on OBP
   3160   4582       cth 		 */
   3161   4582       cth 		return (PROP_1275_INT_SIZE);
   3162   4582       cth 
   3163   4582       cth 	case DDI_PROP_CMD_GET_DSIZE:
   3164   4582       cth 		/*
   3165   4582       cth 		 * Return the size of a decoded integer on the system.
   3166   4582       cth 		 */
   3167   4582       cth 		return (sizeof (int));
   3168   4582       cth 
   3169   4582       cth 	default:
   3170   4582       cth #ifdef DEBUG
   3171   4582       cth 		panic("ddi_prop_1275_int: %x impossible", cmd);
   3172   4582       cth 		/*NOTREACHED*/
   3173   4582       cth #else
   3174   4582       cth 		return (DDI_PROP_RESULT_ERROR);
   3175   4582       cth #endif	/* DEBUG */
   3176   4582       cth 	}
   3177   4582       cth }
   3178   4582       cth 
   3179   4582       cth /*
   3180   4582       cth  * 64 bit integer operator.
   3181   4582       cth  *
   3182   4582       cth  * This is an extension, defined by Sun, to the 1275 integer
   3183   4582       cth  * operator.  This routine handles the encoding/decoding of
   3184   4582       cth  * 64 bit integer properties.
   3185   4582       cth  */
   3186   4582       cth int
   3187   4582       cth ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
   3188   4582       cth {
   3189   4582       cth 
   3190   4582       cth 	switch (cmd) {
   3191   4582       cth 	case DDI_PROP_CMD_DECODE:
   3192   4582       cth 		/*
   3193   4582       cth 		 * Check that there is encoded data
   3194   4582       cth 		 */
   3195   4582       cth 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
   3196   4582       cth 			return (DDI_PROP_RESULT_ERROR);
   3197   4582       cth 		if (ph->ph_flags & PH_FROM_PROM) {
   3198   4582       cth 			return (DDI_PROP_RESULT_ERROR);
   3199   4582       cth 		} else {
   3200   4582       cth 			if (ph->ph_size < sizeof (int64_t) ||
   3201   4582       cth 			    ((int64_t *)ph->ph_cur_pos >
   3202   4582       cth 			    ((int64_t *)ph->ph_data +
   3203   4582       cth 			    ph->ph_size - sizeof (