xref: /illumos-gate/usr/src/uts/common/os/sunddi.c (revision 7bcaeddb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54ab75253Smrj  * Common Development and Distribution License (the "License").
64ab75253Smrj  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
214ab75253Smrj 
227c478bd9Sstevel@tonic-gate /*
234f1e984dSReed  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24b89e420aSGarrett D'Amore  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/note.h>
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/param.h>
307c478bd9Sstevel@tonic-gate #include <sys/systm.h>
317c478bd9Sstevel@tonic-gate #include <sys/buf.h>
327c478bd9Sstevel@tonic-gate #include <sys/uio.h>
337c478bd9Sstevel@tonic-gate #include <sys/cred.h>
347c478bd9Sstevel@tonic-gate #include <sys/poll.h>
357c478bd9Sstevel@tonic-gate #include <sys/mman.h>
367c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
377c478bd9Sstevel@tonic-gate #include <sys/model.h>
387c478bd9Sstevel@tonic-gate #include <sys/file.h>
397c478bd9Sstevel@tonic-gate #include <sys/proc.h>
407c478bd9Sstevel@tonic-gate #include <sys/open.h>
417c478bd9Sstevel@tonic-gate #include <sys/user.h>
427c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
437c478bd9Sstevel@tonic-gate #include <sys/vm.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <vm/hat.h>
467c478bd9Sstevel@tonic-gate #include <vm/seg.h>
477c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
487c478bd9Sstevel@tonic-gate #include <vm/seg_dev.h>
497c478bd9Sstevel@tonic-gate #include <vm/as.h>
507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
517c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
527c478bd9Sstevel@tonic-gate #include <sys/debug.h>
537c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
547c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
557c478bd9Sstevel@tonic-gate #include <sys/esunddi.h>
567c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
577c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
587c478bd9Sstevel@tonic-gate #include <sys/conf.h>
597c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>	/* include implementation structure defs */
607c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h>	/* include prototypes */
61a288e5a9SJoshua M. Clulow #include <sys/ddi_periodic.h>
627c478bd9Sstevel@tonic-gate #include <sys/hwconf.h>
637c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
647c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
657c478bd9Sstevel@tonic-gate #include <sys/epm.h>
667c478bd9Sstevel@tonic-gate #include <sys/devctl.h>
677c478bd9Sstevel@tonic-gate #include <sys/callb.h>
687c478bd9Sstevel@tonic-gate #include <sys/cladm.h>
697c478bd9Sstevel@tonic-gate #include <sys/sysevent.h>
707c478bd9Sstevel@tonic-gate #include <sys/dacf_impl.h>
717c478bd9Sstevel@tonic-gate #include <sys/ddidevmap.h>
727c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
737c478bd9Sstevel@tonic-gate #include <sys/disp.h>
747c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
757c478bd9Sstevel@tonic-gate #include <sys/promif.h>
767c478bd9Sstevel@tonic-gate #include <sys/instance.h>
777c478bd9Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
787c478bd9Sstevel@tonic-gate #include <sys/task.h>
797c478bd9Sstevel@tonic-gate #include <sys/project.h>
807c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
817c478bd9Sstevel@tonic-gate #include <sys/devpolicy.h>
827c478bd9Sstevel@tonic-gate #include <sys/ctype.h>
837c478bd9Sstevel@tonic-gate #include <net/if.h>
84c6939658Ssl #include <sys/rctl.h>
855679c89fSjv #include <sys/zone.h>
86d3d50737SRafael Vanoni #include <sys/clock_impl.h>
874c06356bSdh #include <sys/ddi.h>
88a3114836SGerry Liu #include <sys/modhash.h>
89a3114836SGerry Liu #include <sys/sunldi_impl.h>
90a3114836SGerry Liu #include <sys/fs/dv_node.h>
91a3114836SGerry Liu #include <sys/fs/snode.h>
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate extern	pri_t	minclsyspri;
947c478bd9Sstevel@tonic-gate 
95c6939658Ssl extern	rctl_hndl_t rc_project_locked_mem;
96c6939658Ssl extern	rctl_hndl_t rc_zone_locked_mem;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #ifdef DEBUG
997c478bd9Sstevel@tonic-gate static int sunddi_debug = 0;
1007c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /* ddi_umem_unlock miscellaneous */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate static	void	i_ddi_umem_unlock_thread_start(void);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate static	kmutex_t	ddi_umem_unlock_mutex; /* unlock list mutex */
1077c478bd9Sstevel@tonic-gate static	kcondvar_t	ddi_umem_unlock_cv; /* unlock list block/unblock */
1087c478bd9Sstevel@tonic-gate static	kthread_t	*ddi_umem_unlock_thread;
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  * The ddi_umem_unlock FIFO list.  NULL head pointer indicates empty list.
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate static	struct	ddi_umem_cookie *ddi_umem_unlock_head = NULL;
1137c478bd9Sstevel@tonic-gate static	struct	ddi_umem_cookie *ddi_umem_unlock_tail = NULL;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  * DDI(Sun) Function and flag definitions:
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #if defined(__x86)
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * Used to indicate which entries were chosen from a range.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate char	*chosen_reg = "chosen-reg";
1247c478bd9Sstevel@tonic-gate #endif
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate  * Function used to ring system console bell
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate void (*ddi_console_bell_func)(clock_t duration);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * Creating register mappings and handling interrupts:
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate /*
1367c478bd9Sstevel@tonic-gate  * Generic ddi_map: Call parent to fulfill request...
1377c478bd9Sstevel@tonic-gate  */
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate int
ddi_map(dev_info_t * dp,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * addrp)1407c478bd9Sstevel@tonic-gate ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset,
1417c478bd9Sstevel@tonic-gate     off_t len, caddr_t *addrp)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	dev_info_t *pdip;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	ASSERT(dp);
1467c478bd9Sstevel@tonic-gate 	pdip = (dev_info_t *)DEVI(dp)->devi_parent;
1477c478bd9Sstevel@tonic-gate 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
1487c478bd9Sstevel@tonic-gate 	    dp, mp, offset, len, addrp));
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * ddi_apply_range: (Called by nexi only.)
1537c478bd9Sstevel@tonic-gate  * Apply ranges in parent node dp, to child regspec rp...
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate int
ddi_apply_range(dev_info_t * dp,dev_info_t * rdip,struct regspec * rp)1577c478bd9Sstevel@tonic-gate ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate 	return (i_ddi_apply_range(dp, rdip, rp));
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate int
ddi_map_regs(dev_info_t * dip,uint_t rnumber,caddr_t * kaddrp,off_t offset,off_t len)1637c478bd9Sstevel@tonic-gate ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
1647c478bd9Sstevel@tonic-gate     off_t len)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	ddi_map_req_t mr;
1677c478bd9Sstevel@tonic-gate #if defined(__x86)
1687c478bd9Sstevel@tonic-gate 	struct {
1697c478bd9Sstevel@tonic-gate 		int	bus;
1707c478bd9Sstevel@tonic-gate 		int	addr;
1717c478bd9Sstevel@tonic-gate 		int	size;
1727c478bd9Sstevel@tonic-gate 	} reg, *reglist;
1737c478bd9Sstevel@tonic-gate 	uint_t	length;
1747c478bd9Sstevel@tonic-gate 	int	rc;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/*
1777c478bd9Sstevel@tonic-gate 	 * get the 'registers' or the 'reg' property.
1787c478bd9Sstevel@tonic-gate 	 * We look up the reg property as an array of
1797c478bd9Sstevel@tonic-gate 	 * int's.
1807c478bd9Sstevel@tonic-gate 	 */
1817c478bd9Sstevel@tonic-gate 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
1827c478bd9Sstevel@tonic-gate 	    DDI_PROP_DONTPASS, "registers", (int **)&reglist, &length);
1837c478bd9Sstevel@tonic-gate 	if (rc != DDI_PROP_SUCCESS)
1847c478bd9Sstevel@tonic-gate 		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
1857c478bd9Sstevel@tonic-gate 		    DDI_PROP_DONTPASS, "reg", (int **)&reglist, &length);
1867c478bd9Sstevel@tonic-gate 	if (rc == DDI_PROP_SUCCESS) {
1877c478bd9Sstevel@tonic-gate 		/*
1887c478bd9Sstevel@tonic-gate 		 * point to the required entry.
1897c478bd9Sstevel@tonic-gate 		 */
1907c478bd9Sstevel@tonic-gate 		reg = reglist[rnumber];
1917c478bd9Sstevel@tonic-gate 		reg.addr += offset;
1927c478bd9Sstevel@tonic-gate 		if (len != 0)
1937c478bd9Sstevel@tonic-gate 			reg.size = len;
1947c478bd9Sstevel@tonic-gate 		/*
1957c478bd9Sstevel@tonic-gate 		 * make a new property containing ONLY the required tuple.
1967c478bd9Sstevel@tonic-gate 		 */
1977c478bd9Sstevel@tonic-gate 		if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1987c478bd9Sstevel@tonic-gate 		    chosen_reg, (int *)&reg, (sizeof (reg)/sizeof (int)))
1997c478bd9Sstevel@tonic-gate 		    != DDI_PROP_SUCCESS) {
2007c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: cannot create '%s' "
2017c478bd9Sstevel@tonic-gate 			    "property", DEVI(dip)->devi_name,
2027c478bd9Sstevel@tonic-gate 			    DEVI(dip)->devi_instance, chosen_reg);
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 		/*
2057c478bd9Sstevel@tonic-gate 		 * free the memory allocated by
2067c478bd9Sstevel@tonic-gate 		 * ddi_prop_lookup_int_array ().
2077c478bd9Sstevel@tonic-gate 		 */
2087c478bd9Sstevel@tonic-gate 		ddi_prop_free((void *)reglist);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate #endif
2117c478bd9Sstevel@tonic-gate 	mr.map_op = DDI_MO_MAP_LOCKED;
2127c478bd9Sstevel@tonic-gate 	mr.map_type = DDI_MT_RNUMBER;
2137c478bd9Sstevel@tonic-gate 	mr.map_obj.rnumber = rnumber;
2147c478bd9Sstevel@tonic-gate 	mr.map_prot = PROT_READ | PROT_WRITE;
2157c478bd9Sstevel@tonic-gate 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
2167c478bd9Sstevel@tonic-gate 	mr.map_handlep = NULL;
2177c478bd9Sstevel@tonic-gate 	mr.map_vers = DDI_MAP_VERSION;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	/*
2207c478bd9Sstevel@tonic-gate 	 * Call my parent to map in my regs.
2217c478bd9Sstevel@tonic-gate 	 */
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	return (ddi_map(dip, &mr, offset, len, kaddrp));
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate void
ddi_unmap_regs(dev_info_t * dip,uint_t rnumber,caddr_t * kaddrp,off_t offset,off_t len)2277c478bd9Sstevel@tonic-gate ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
2287c478bd9Sstevel@tonic-gate     off_t len)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	ddi_map_req_t mr;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	mr.map_op = DDI_MO_UNMAP;
2337c478bd9Sstevel@tonic-gate 	mr.map_type = DDI_MT_RNUMBER;
2347c478bd9Sstevel@tonic-gate 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
2357c478bd9Sstevel@tonic-gate 	mr.map_prot = PROT_READ | PROT_WRITE;	/* who cares? */
2367c478bd9Sstevel@tonic-gate 	mr.map_obj.rnumber = rnumber;
2377c478bd9Sstevel@tonic-gate 	mr.map_handlep = NULL;
2387c478bd9Sstevel@tonic-gate 	mr.map_vers = DDI_MAP_VERSION;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	/*
2417c478bd9Sstevel@tonic-gate 	 * Call my parent to unmap my regs.
2427c478bd9Sstevel@tonic-gate 	 */
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	(void) ddi_map(dip, &mr, offset, len, kaddrp);
2457c478bd9Sstevel@tonic-gate 	*kaddrp = (caddr_t)0;
2467c478bd9Sstevel@tonic-gate #if defined(__x86)
2477c478bd9Sstevel@tonic-gate 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg);
2487c478bd9Sstevel@tonic-gate #endif
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate int
ddi_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)2527c478bd9Sstevel@tonic-gate ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2537c478bd9Sstevel@tonic-gate 	off_t offset, off_t len, caddr_t *vaddrp)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate  * nullbusmap:	The/DDI default bus_map entry point for nexi
2607c478bd9Sstevel@tonic-gate  *		not conforming to the reg/range paradigm (i.e. scsi, etc.)
2617c478bd9Sstevel@tonic-gate  *		with no HAT/MMU layer to be programmed at this level.
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  *		If the call is to map by rnumber, return an error,
2647c478bd9Sstevel@tonic-gate  *		otherwise pass anything else up the tree to my parent.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate int
nullbusmap(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)2677c478bd9Sstevel@tonic-gate nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2687c478bd9Sstevel@tonic-gate 	off_t offset, off_t len, caddr_t *vaddrp)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(rdip))
2717c478bd9Sstevel@tonic-gate 	if (mp->map_type == DDI_MT_RNUMBER)
2727c478bd9Sstevel@tonic-gate 		return (DDI_ME_UNSUPPORTED);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	return (ddi_map(dip, mp, offset, len, vaddrp));
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate  * ddi_rnumber_to_regspec: Not for use by leaf drivers.
2797c478bd9Sstevel@tonic-gate  *			   Only for use by nexi using the reg/range paradigm.
2807c478bd9Sstevel@tonic-gate  */
2817c478bd9Sstevel@tonic-gate struct regspec *
ddi_rnumber_to_regspec(dev_info_t * dip,int rnumber)2827c478bd9Sstevel@tonic-gate ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	return (i_ddi_rnumber_to_regspec(dip, rnumber));
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate /*
2897c478bd9Sstevel@tonic-gate  * Note that we allow the dip to be nil because we may be called
2907c478bd9Sstevel@tonic-gate  * prior even to the instantiation of the devinfo tree itself - all
2917c478bd9Sstevel@tonic-gate  * regular leaf and nexus drivers should always use a non-nil dip!
2927c478bd9Sstevel@tonic-gate  *
2937c478bd9Sstevel@tonic-gate  * We treat peek in a somewhat cavalier fashion .. assuming that we'll
2947c478bd9Sstevel@tonic-gate  * simply get a synchronous fault as soon as we touch a missing address.
2957c478bd9Sstevel@tonic-gate  *
2967c478bd9Sstevel@tonic-gate  * Poke is rather more carefully handled because we might poke to a write
2977c478bd9Sstevel@tonic-gate  * buffer, "succeed", then only find some time later that we got an
2987c478bd9Sstevel@tonic-gate  * asynchronous fault that indicated that the address we were writing to
2997c478bd9Sstevel@tonic-gate  * was not really backed by hardware.
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int
i_ddi_peekpoke(dev_info_t * devi,ddi_ctl_enum_t cmd,size_t size,void * addr,void * value_p)3037c478bd9Sstevel@tonic-gate i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size,
3047c478bd9Sstevel@tonic-gate     void *addr, void *value_p)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	union {
3077c478bd9Sstevel@tonic-gate 		uint64_t	u64;
3087c478bd9Sstevel@tonic-gate 		uint32_t	u32;
3097c478bd9Sstevel@tonic-gate 		uint16_t	u16;
3107c478bd9Sstevel@tonic-gate 		uint8_t		u8;
3117c478bd9Sstevel@tonic-gate 	} peekpoke_value;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	peekpoke_ctlops_t peekpoke_args;
3147c478bd9Sstevel@tonic-gate 	uint64_t dummy_result;
3157c478bd9Sstevel@tonic-gate 	int rval;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	/* Note: size is assumed to be correct;  it is not checked. */
3187c478bd9Sstevel@tonic-gate 	peekpoke_args.size = size;
319abdbd06dSagiri 	peekpoke_args.dev_addr = (uintptr_t)addr;
3207c478bd9Sstevel@tonic-gate 	peekpoke_args.handle = NULL;
3217c478bd9Sstevel@tonic-gate 	peekpoke_args.repcount = 1;
3227c478bd9Sstevel@tonic-gate 	peekpoke_args.flags = 0;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	if (cmd == DDI_CTLOPS_POKE) {
3257c478bd9Sstevel@tonic-gate 		switch (size) {
3267c478bd9Sstevel@tonic-gate 		case sizeof (uint8_t):
3277c478bd9Sstevel@tonic-gate 			peekpoke_value.u8 = *(uint8_t *)value_p;
3287c478bd9Sstevel@tonic-gate 			break;
3297c478bd9Sstevel@tonic-gate 		case sizeof (uint16_t):
3307c478bd9Sstevel@tonic-gate 			peekpoke_value.u16 = *(uint16_t *)value_p;
3317c478bd9Sstevel@tonic-gate 			break;
3327c478bd9Sstevel@tonic-gate 		case sizeof (uint32_t):
3337c478bd9Sstevel@tonic-gate 			peekpoke_value.u32 = *(uint32_t *)value_p;
3347c478bd9Sstevel@tonic-gate 			break;
3357c478bd9Sstevel@tonic-gate 		case sizeof (uint64_t):
3367c478bd9Sstevel@tonic-gate 			peekpoke_value.u64 = *(uint64_t *)value_p;
3377c478bd9Sstevel@tonic-gate 			break;
3387c478bd9Sstevel@tonic-gate 		}
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 
341abdbd06dSagiri 	peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if (devi != NULL)
3447c478bd9Sstevel@tonic-gate 		rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args,
3457c478bd9Sstevel@tonic-gate 		    &dummy_result);
3467c478bd9Sstevel@tonic-gate 	else
3477c478bd9Sstevel@tonic-gate 		rval = peekpoke_mem(cmd, &peekpoke_args);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	/*
3507c478bd9Sstevel@tonic-gate 	 * A NULL value_p is permitted by ddi_peek(9F); discard the result.
3517c478bd9Sstevel@tonic-gate 	 */
3527c478bd9Sstevel@tonic-gate 	if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) {
3537c478bd9Sstevel@tonic-gate 		switch (size) {
3547c478bd9Sstevel@tonic-gate 		case sizeof (uint8_t):
3557c478bd9Sstevel@tonic-gate 			*(uint8_t *)value_p = peekpoke_value.u8;
3567c478bd9Sstevel@tonic-gate 			break;
3577c478bd9Sstevel@tonic-gate 		case sizeof (uint16_t):
3587c478bd9Sstevel@tonic-gate 			*(uint16_t *)value_p = peekpoke_value.u16;
3597c478bd9Sstevel@tonic-gate 			break;
3607c478bd9Sstevel@tonic-gate 		case sizeof (uint32_t):
3617c478bd9Sstevel@tonic-gate 			*(uint32_t *)value_p = peekpoke_value.u32;
3627c478bd9Sstevel@tonic-gate 			break;
3637c478bd9Sstevel@tonic-gate 		case sizeof (uint64_t):
3647c478bd9Sstevel@tonic-gate 			*(uint64_t *)value_p = peekpoke_value.u64;
3657c478bd9Sstevel@tonic-gate 			break;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	return (rval);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate  * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this.
3747c478bd9Sstevel@tonic-gate  * they shouldn't be, but the 9f manpage kind of pseudo exposes it.
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate int
ddi_peek(dev_info_t * devi,size_t size,void * addr,void * value_p)3777c478bd9Sstevel@tonic-gate ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	switch (size) {
3807c478bd9Sstevel@tonic-gate 	case sizeof (uint8_t):
3817c478bd9Sstevel@tonic-gate 	case sizeof (uint16_t):
3827c478bd9Sstevel@tonic-gate 	case sizeof (uint32_t):
3837c478bd9Sstevel@tonic-gate 	case sizeof (uint64_t):
3847c478bd9Sstevel@tonic-gate 		break;
3857c478bd9Sstevel@tonic-gate 	default:
3867c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p));
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate int
ddi_poke(dev_info_t * devi,size_t size,void * addr,void * value_p)3937c478bd9Sstevel@tonic-gate ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate 	switch (size) {
3967c478bd9Sstevel@tonic-gate 	case sizeof (uint8_t):
3977c478bd9Sstevel@tonic-gate 	case sizeof (uint16_t):
3987c478bd9Sstevel@tonic-gate 	case sizeof (uint32_t):
3997c478bd9Sstevel@tonic-gate 	case sizeof (uint64_t):
4007c478bd9Sstevel@tonic-gate 		break;
4017c478bd9Sstevel@tonic-gate 	default:
4027c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p));
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate int
ddi_peek8(dev_info_t * dip,int8_t * addr,int8_t * val_p)4097c478bd9Sstevel@tonic-gate ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p)
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4127c478bd9Sstevel@tonic-gate 	    val_p));
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate int
ddi_peek16(dev_info_t * dip,int16_t * addr,int16_t * val_p)4167c478bd9Sstevel@tonic-gate ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4197c478bd9Sstevel@tonic-gate 	    val_p));
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate int
ddi_peek32(dev_info_t * dip,int32_t * addr,int32_t * val_p)4237c478bd9Sstevel@tonic-gate ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4267c478bd9Sstevel@tonic-gate 	    val_p));
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate int
ddi_peek64(dev_info_t * dip,int64_t * addr,int64_t * val_p)4307c478bd9Sstevel@tonic-gate ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p)
4314ab75253Smrj {
4324ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4334ab75253Smrj 	    val_p));
4344ab75253Smrj }
4354ab75253Smrj 
4364ab75253Smrj 
4374ab75253Smrj /*
4384ab75253Smrj  * We need to separate the old interfaces from the new ones and leave them
4394ab75253Smrj  * in here for a while. Previous versions of the OS defined the new interfaces
4404ab75253Smrj  * to the old interfaces. This way we can fix things up so that we can
4414ab75253Smrj  * eventually remove these interfaces.
4424ab75253Smrj  * e.g. A 3rd party module/driver using ddi_peek8 and built against S10
4434ab75253Smrj  * or earlier will actually have a reference to ddi_peekc in the binary.
4444ab75253Smrj  */
4454ab75253Smrj #ifdef _ILP32
4464ab75253Smrj int
ddi_peekc(dev_info_t * dip,int8_t * addr,int8_t * val_p)4474ab75253Smrj ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p)
4484ab75253Smrj {
4494ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4504ab75253Smrj 	    val_p));
4514ab75253Smrj }
4524ab75253Smrj 
4534ab75253Smrj int
ddi_peeks(dev_info_t * dip,int16_t * addr,int16_t * val_p)4544ab75253Smrj ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p)
4554ab75253Smrj {
4564ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4574ab75253Smrj 	    val_p));
4584ab75253Smrj }
4594ab75253Smrj 
4604ab75253Smrj int
ddi_peekl(dev_info_t * dip,int32_t * addr,int32_t * val_p)4614ab75253Smrj ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p)
4624ab75253Smrj {
4634ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4644ab75253Smrj 	    val_p));
4654ab75253Smrj }
4664ab75253Smrj 
4677c478bd9Sstevel@tonic-gate int
ddi_peekd(dev_info_t * dip,int64_t * addr,int64_t * val_p)4687c478bd9Sstevel@tonic-gate ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
4717c478bd9Sstevel@tonic-gate 	    val_p));
4727c478bd9Sstevel@tonic-gate }
4734ab75253Smrj #endif /* _ILP32 */
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate int
ddi_poke8(dev_info_t * dip,int8_t * addr,int8_t val)4767c478bd9Sstevel@tonic-gate ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate int
ddi_poke16(dev_info_t * dip,int16_t * addr,int16_t val)4827c478bd9Sstevel@tonic-gate ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate int
ddi_poke32(dev_info_t * dip,int32_t * addr,int32_t val)4887c478bd9Sstevel@tonic-gate ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate int
ddi_poke64(dev_info_t * dip,int64_t * addr,int64_t val)4947c478bd9Sstevel@tonic-gate ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
4954ab75253Smrj {
4964ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4974ab75253Smrj }
4984ab75253Smrj 
4994ab75253Smrj /*
5004ab75253Smrj  * We need to separate the old interfaces from the new ones and leave them
5014ab75253Smrj  * in here for a while. Previous versions of the OS defined the new interfaces
5024ab75253Smrj  * to the old interfaces. This way we can fix things up so that we can
5034ab75253Smrj  * eventually remove these interfaces.
5044ab75253Smrj  * e.g. A 3rd party module/driver using ddi_poke8 and built against S10
5054ab75253Smrj  * or earlier will actually have a reference to ddi_pokec in the binary.
5064ab75253Smrj  */
5074ab75253Smrj #ifdef _ILP32
5084ab75253Smrj int
ddi_pokec(dev_info_t * dip,int8_t * addr,int8_t val)5094ab75253Smrj ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val)
5104ab75253Smrj {
5114ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
5124ab75253Smrj }
5134ab75253Smrj 
5144ab75253Smrj int
ddi_pokes(dev_info_t * dip,int16_t * addr,int16_t val)5154ab75253Smrj ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val)
5164ab75253Smrj {
5174ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
5184ab75253Smrj }
5194ab75253Smrj 
5204ab75253Smrj int
ddi_pokel(dev_info_t * dip,int32_t * addr,int32_t val)5214ab75253Smrj ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val)
5224ab75253Smrj {
5234ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
5244ab75253Smrj }
5254ab75253Smrj 
5267c478bd9Sstevel@tonic-gate int
ddi_poked(dev_info_t * dip,int64_t * addr,int64_t val)5277c478bd9Sstevel@tonic-gate ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val)
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
5307c478bd9Sstevel@tonic-gate }
5314ab75253Smrj #endif /* _ILP32 */
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  * ddi_peekpokeio() is used primarily by the mem drivers for moving
5357c478bd9Sstevel@tonic-gate  * data to and from uio structures via peek and poke.  Note that we
5367c478bd9Sstevel@tonic-gate  * use "internal" routines ddi_peek and ddi_poke to make this go
5377c478bd9Sstevel@tonic-gate  * slightly faster, avoiding the call overhead ..
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate int
ddi_peekpokeio(dev_info_t * devi,struct uio * uio,enum uio_rw rw,caddr_t addr,size_t len,uint_t xfersize)5407c478bd9Sstevel@tonic-gate ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
5417c478bd9Sstevel@tonic-gate     caddr_t addr, size_t len, uint_t xfersize)
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate 	int64_t	ibuffer;
5447c478bd9Sstevel@tonic-gate 	int8_t w8;
5457c478bd9Sstevel@tonic-gate 	size_t sz;
5467c478bd9Sstevel@tonic-gate 	int o;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	if (xfersize > sizeof (long))
5497c478bd9Sstevel@tonic-gate 		xfersize = sizeof (long);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	while (len != 0) {
5527c478bd9Sstevel@tonic-gate 		if ((len | (uintptr_t)addr) & 1) {
5537c478bd9Sstevel@tonic-gate 			sz = sizeof (int8_t);
5547c478bd9Sstevel@tonic-gate 			if (rw == UIO_WRITE) {
5557c478bd9Sstevel@tonic-gate 				if ((o = uwritec(uio)) == -1)
5567c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5577c478bd9Sstevel@tonic-gate 				if (ddi_poke8(devi, (int8_t *)addr,
5587c478bd9Sstevel@tonic-gate 				    (int8_t)o) != DDI_SUCCESS)
5597c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5607c478bd9Sstevel@tonic-gate 			} else {
5617c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
5627c478bd9Sstevel@tonic-gate 				    (int8_t *)addr, &w8) != DDI_SUCCESS)
5637c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5647c478bd9Sstevel@tonic-gate 				if (ureadc(w8, uio))
5657c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5667c478bd9Sstevel@tonic-gate 			}
5677c478bd9Sstevel@tonic-gate 		} else {
5687c478bd9Sstevel@tonic-gate 			switch (xfersize) {
5697c478bd9Sstevel@tonic-gate 			case sizeof (int64_t):
5707c478bd9Sstevel@tonic-gate 				if (((len | (uintptr_t)addr) &
5717c478bd9Sstevel@tonic-gate 				    (sizeof (int64_t) - 1)) == 0) {
5727c478bd9Sstevel@tonic-gate 					sz = xfersize;
5737c478bd9Sstevel@tonic-gate 					break;
5747c478bd9Sstevel@tonic-gate 				}
5757c478bd9Sstevel@tonic-gate 				/*FALLTHROUGH*/
5767c478bd9Sstevel@tonic-gate 			case sizeof (int32_t):
5777c478bd9Sstevel@tonic-gate 				if (((len | (uintptr_t)addr) &
5787c478bd9Sstevel@tonic-gate 				    (sizeof (int32_t) - 1)) == 0) {
5797c478bd9Sstevel@tonic-gate 					sz = xfersize;
5807c478bd9Sstevel@tonic-gate 					break;
5817c478bd9Sstevel@tonic-gate 				}
5827c478bd9Sstevel@tonic-gate 				/*FALLTHROUGH*/
5837c478bd9Sstevel@tonic-gate 			default:
5847c478bd9Sstevel@tonic-gate 				/*
5857c478bd9Sstevel@tonic-gate 				 * This still assumes that we might have an
5867c478bd9Sstevel@tonic-gate 				 * I/O bus out there that permits 16-bit
5877c478bd9Sstevel@tonic-gate 				 * transfers (and that it would be upset by
5887c478bd9Sstevel@tonic-gate 				 * 32-bit transfers from such locations).
5897c478bd9Sstevel@tonic-gate 				 */
5907c478bd9Sstevel@tonic-gate 				sz = sizeof (int16_t);
5917c478bd9Sstevel@tonic-gate 				break;
5927c478bd9Sstevel@tonic-gate 			}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 			if (rw == UIO_READ) {
5957c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
5967c478bd9Sstevel@tonic-gate 				    addr, &ibuffer) != DDI_SUCCESS)
5977c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5987c478bd9Sstevel@tonic-gate 			}
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 			if (uiomove(&ibuffer, sz, rw, uio))
6017c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 			if (rw == UIO_WRITE) {
6047c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
6057c478bd9Sstevel@tonic-gate 				    addr, &ibuffer) != DDI_SUCCESS)
6067c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
6077c478bd9Sstevel@tonic-gate 			}
6087c478bd9Sstevel@tonic-gate 		}
6097c478bd9Sstevel@tonic-gate 		addr += sz;
6107c478bd9Sstevel@tonic-gate 		len -= sz;
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  * These routines are used by drivers that do layered ioctls
6177c478bd9Sstevel@tonic-gate  * On sparc, they're implemented in assembler to avoid spilling
6187c478bd9Sstevel@tonic-gate  * register windows in the common (copyin) case ..
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate #if !defined(__sparc)
6217c478bd9Sstevel@tonic-gate int
ddi_copyin(const void * buf,void * kernbuf,size_t size,int flags)6227c478bd9Sstevel@tonic-gate ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
6237c478bd9Sstevel@tonic-gate {
6247c478bd9Sstevel@tonic-gate 	if (flags & FKIOCTL)
6257c478bd9Sstevel@tonic-gate 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
6267c478bd9Sstevel@tonic-gate 	return (copyin(buf, kernbuf, size));
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate int
ddi_copyout(const void * buf,void * kernbuf,size_t size,int flags)6307c478bd9Sstevel@tonic-gate ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate 	if (flags & FKIOCTL)
6337c478bd9Sstevel@tonic-gate 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
6347c478bd9Sstevel@tonic-gate 	return (copyout(buf, kernbuf, size));
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate #endif	/* !__sparc */
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate  * Conversions in nexus pagesize units.  We don't duplicate the
6407c478bd9Sstevel@tonic-gate  * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
6417c478bd9Sstevel@tonic-gate  * routines anyway.
6427c478bd9Sstevel@tonic-gate  */
6437c478bd9Sstevel@tonic-gate unsigned long
ddi_btop(dev_info_t * dip,unsigned long bytes)6447c478bd9Sstevel@tonic-gate ddi_btop(dev_info_t *dip, unsigned long bytes)
6457c478bd9Sstevel@tonic-gate {
6467c478bd9Sstevel@tonic-gate 	unsigned long pages;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
6497c478bd9Sstevel@tonic-gate 	return (pages);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate unsigned long
ddi_btopr(dev_info_t * dip,unsigned long bytes)6537c478bd9Sstevel@tonic-gate ddi_btopr(dev_info_t *dip, unsigned long bytes)
6547c478bd9Sstevel@tonic-gate {
6557c478bd9Sstevel@tonic-gate 	unsigned long pages;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
6587c478bd9Sstevel@tonic-gate 	return (pages);
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate unsigned long
ddi_ptob(dev_info_t * dip,unsigned long pages)6627c478bd9Sstevel@tonic-gate ddi_ptob(dev_info_t *dip, unsigned long pages)
6637c478bd9Sstevel@tonic-gate {
6647c478bd9Sstevel@tonic-gate 	unsigned long bytes;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
6677c478bd9Sstevel@tonic-gate 	return (bytes);
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate unsigned int
ddi_enter_critical(void)6717c478bd9Sstevel@tonic-gate ddi_enter_critical(void)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate 	return ((uint_t)spl7());
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate void
ddi_exit_critical(unsigned int spl)6777c478bd9Sstevel@tonic-gate ddi_exit_critical(unsigned int spl)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate 	splx((int)spl);
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate /*
6837c478bd9Sstevel@tonic-gate  * Nexus ctlops punter
6847c478bd9Sstevel@tonic-gate  */
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate #if !defined(__sparc)
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate  * Request bus_ctl parent to handle a bus_ctl request
6897c478bd9Sstevel@tonic-gate  *
6907c478bd9Sstevel@tonic-gate  * (The sparc version is in sparc_ddi.s)
6917c478bd9Sstevel@tonic-gate  */
6927c478bd9Sstevel@tonic-gate int
ddi_ctlops(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t op,void * a,void * v)6937c478bd9Sstevel@tonic-gate ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	int (*fp)();
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	if (!d || !r)
6987c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
7017c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
7047c478bd9Sstevel@tonic-gate 	return ((*fp)(d, r, op, a, v));
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate #endif
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /*
7107c478bd9Sstevel@tonic-gate  * DMA/DVMA setup
7117c478bd9Sstevel@tonic-gate  */
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate #if !defined(__sparc)
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate  * Request bus_dma_ctl parent to fiddle with a dma request.
7167c478bd9Sstevel@tonic-gate  *
7177c478bd9Sstevel@tonic-gate  * (The sparc version is in sparc_subr.s)
7187c478bd9Sstevel@tonic-gate  */
7197c478bd9Sstevel@tonic-gate int
ddi_dma_mctl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,enum ddi_dma_ctlops request,off_t * offp,size_t * lenp,caddr_t * objp,uint_t flags)7207c478bd9Sstevel@tonic-gate ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
7217c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
7227c478bd9Sstevel@tonic-gate     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
7237c478bd9Sstevel@tonic-gate {
7247c478bd9Sstevel@tonic-gate 	int (*fp)();
7257c478bd9Sstevel@tonic-gate 
726b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
727b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
7287c478bd9Sstevel@tonic-gate 	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
7297c478bd9Sstevel@tonic-gate 	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
7307c478bd9Sstevel@tonic-gate }
7317c478bd9Sstevel@tonic-gate #endif
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /*
7347c478bd9Sstevel@tonic-gate  * For all DMA control functions, call the DMA control
7357c478bd9Sstevel@tonic-gate  * routine and return status.
7367c478bd9Sstevel@tonic-gate  *
7377c478bd9Sstevel@tonic-gate  * Just plain assume that the parent is to be called.
7387c478bd9Sstevel@tonic-gate  * If a nexus driver or a thread outside the framework
7397c478bd9Sstevel@tonic-gate  * of a nexus driver or a leaf driver calls these functions,
7407c478bd9Sstevel@tonic-gate  * it is up to them to deal with the fact that the parent's
7417c478bd9Sstevel@tonic-gate  * bus_dma_ctl function will be the first one called.
7427c478bd9Sstevel@tonic-gate  */
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate #define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate /*
747cd21e7c5SGarrett D'Amore  * This routine is left in place to satisfy link dependencies
748cd21e7c5SGarrett D'Amore  * for any 3rd party nexus drivers that rely on it.  It is never
749cd21e7c5SGarrett D'Amore  * called, though.
7507c478bd9Sstevel@tonic-gate  */
751cd21e7c5SGarrett D'Amore /*ARGSUSED*/
7527c478bd9Sstevel@tonic-gate int
ddi_dma_map(dev_info_t * dip,dev_info_t * rdip,struct ddi_dma_req * dmareqp,ddi_dma_handle_t * handlep)753cd21e7c5SGarrett D'Amore ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
754b89e420aSGarrett D'Amore     struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
7557c478bd9Sstevel@tonic-gate {
756cd21e7c5SGarrett D'Amore 	return (DDI_FAILURE);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate #if !defined(__sparc)
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate /*
7627c478bd9Sstevel@tonic-gate  * The SPARC versions of these routines are done in assembler to
7637c478bd9Sstevel@tonic-gate  * save register windows, so they're in sparc_subr.s.
7647c478bd9Sstevel@tonic-gate  */
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate int
ddi_dma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfp)(caddr_t),caddr_t arg,ddi_dma_handle_t * handlep)7677c478bd9Sstevel@tonic-gate ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
7687c478bd9Sstevel@tonic-gate     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
7697c478bd9Sstevel@tonic-gate {
7707c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
7717c478bd9Sstevel@tonic-gate 	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
7727c478bd9Sstevel@tonic-gate 
773b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
774b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
7757c478bd9Sstevel@tonic-gate 
776b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
777b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate int
ddi_dma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handlep)7817c478bd9Sstevel@tonic-gate ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
7847c478bd9Sstevel@tonic-gate 
785b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
786b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
7877c478bd9Sstevel@tonic-gate 
788b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
789b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handlep));
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate int
ddi_dma_bindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,struct ddi_dma_req * dmareq,ddi_dma_cookie_t * cp,uint_t * ccountp)7937c478bd9Sstevel@tonic-gate ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
7947c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
7957c478bd9Sstevel@tonic-gate     ddi_dma_cookie_t *cp, uint_t *ccountp)
7967c478bd9Sstevel@tonic-gate {
7977c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
7987c478bd9Sstevel@tonic-gate 	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
7997c478bd9Sstevel@tonic-gate 
800b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
801b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
8027c478bd9Sstevel@tonic-gate 
803b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
804b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate int
ddi_dma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)8087c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
8097c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
8127c478bd9Sstevel@tonic-gate 
813b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
814b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
8157c478bd9Sstevel@tonic-gate 
816b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
817b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle));
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate int
ddi_dma_flush(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)8227c478bd9Sstevel@tonic-gate ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
8237c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, off_t off, size_t len,
8247c478bd9Sstevel@tonic-gate     uint_t cache_flags)
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
8277c478bd9Sstevel@tonic-gate 	    off_t, size_t, uint_t);
8287c478bd9Sstevel@tonic-gate 
829b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
830b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
8317c478bd9Sstevel@tonic-gate 
832b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
833b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate int
ddi_dma_win(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,uint_t win,off_t * offp,size_t * lenp,ddi_dma_cookie_t * cookiep,uint_t * ccountp)8377c478bd9Sstevel@tonic-gate ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
8387c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, uint_t win, off_t *offp,
8397c478bd9Sstevel@tonic-gate     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
8427c478bd9Sstevel@tonic-gate 	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
8437c478bd9Sstevel@tonic-gate 
844b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
845b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
8467c478bd9Sstevel@tonic-gate 
847b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
848b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
8497c478bd9Sstevel@tonic-gate 	    cookiep, ccountp));
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate int
ddi_dma_sync(ddi_dma_handle_t h,off_t o,size_t l,uint_t whom)8537c478bd9Sstevel@tonic-gate ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
856b51bbbf5SVikram Hegde 	dev_info_t *dip, *rdip;
8577c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
858184cd04cScth 	    size_t, uint_t);
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	/*
8617c478bd9Sstevel@tonic-gate 	 * the DMA nexus driver will set DMP_NOSYNC if the
8627c478bd9Sstevel@tonic-gate 	 * platform does not require any sync operation. For
8637c478bd9Sstevel@tonic-gate 	 * example if the memory is uncached or consistent
8647c478bd9Sstevel@tonic-gate 	 * and without any I/O write buffers involved.
8657c478bd9Sstevel@tonic-gate 	 */
8667c478bd9Sstevel@tonic-gate 	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
8677c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8687c478bd9Sstevel@tonic-gate 
869b51bbbf5SVikram Hegde 	dip = rdip = hp->dmai_rdip;
870b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
871b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
872b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
873b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, h, o, l, whom));
8747c478bd9Sstevel@tonic-gate }
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate int
ddi_dma_unbind_handle(ddi_dma_handle_t h)8777c478bd9Sstevel@tonic-gate ddi_dma_unbind_handle(ddi_dma_handle_t h)
8787c478bd9Sstevel@tonic-gate {
8797c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
880b51bbbf5SVikram Hegde 	dev_info_t *dip, *rdip;
8817c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
8827c478bd9Sstevel@tonic-gate 
883b51bbbf5SVikram Hegde 	dip = rdip = hp->dmai_rdip;
884b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
885b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
886b51bbbf5SVikram Hegde 	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
887b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, h));
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate #endif	/* !__sparc */
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate /*
893cd21e7c5SGarrett D'Amore  * DMA burst sizes, and transfer minimums
8947c478bd9Sstevel@tonic-gate  */
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate int
ddi_dma_burstsizes(ddi_dma_handle_t handle)8977c478bd9Sstevel@tonic-gate ddi_dma_burstsizes(ddi_dma_handle_t handle)
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	if (!dimp)
9027c478bd9Sstevel@tonic-gate 		return (0);
9037c478bd9Sstevel@tonic-gate 	else
9047c478bd9Sstevel@tonic-gate 		return (dimp->dmai_burstsizes);
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate /*
9087c478bd9Sstevel@tonic-gate  * Given two DMA attribute structures, apply the attributes
9097c478bd9Sstevel@tonic-gate  * of one to the other, following the rules of attributes
9107c478bd9Sstevel@tonic-gate  * and the wishes of the caller.
9117c478bd9Sstevel@tonic-gate  *
9127c478bd9Sstevel@tonic-gate  * The rules of DMA attribute structures are that you cannot
9137c478bd9Sstevel@tonic-gate  * make things *less* restrictive as you apply one set
9147c478bd9Sstevel@tonic-gate  * of attributes to another.
9157c478bd9Sstevel@tonic-gate  *
9167c478bd9Sstevel@tonic-gate  */
9177c478bd9Sstevel@tonic-gate void
ddi_dma_attr_merge(ddi_dma_attr_t * attr,ddi_dma_attr_t * mod)9187c478bd9Sstevel@tonic-gate ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
9197c478bd9Sstevel@tonic-gate {
9207c478bd9Sstevel@tonic-gate 	attr->dma_attr_addr_lo =
9217c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
9227c478bd9Sstevel@tonic-gate 	attr->dma_attr_addr_hi =
9237c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
9247c478bd9Sstevel@tonic-gate 	attr->dma_attr_count_max =
9257c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
9267c478bd9Sstevel@tonic-gate 	attr->dma_attr_align =
9277c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
9287c478bd9Sstevel@tonic-gate 	attr->dma_attr_burstsizes =
9297c478bd9Sstevel@tonic-gate 	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
9307c478bd9Sstevel@tonic-gate 	attr->dma_attr_minxfer =
9317c478bd9Sstevel@tonic-gate 	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
9327c478bd9Sstevel@tonic-gate 	attr->dma_attr_maxxfer =
9337c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
9347c478bd9Sstevel@tonic-gate 	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
9357c478bd9Sstevel@tonic-gate 	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
9367c478bd9Sstevel@tonic-gate 	    (uint_t)mod->dma_attr_sgllen);
9377c478bd9Sstevel@tonic-gate 	attr->dma_attr_granular =
9387c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate  * mmap/segmap interface:
9437c478bd9Sstevel@tonic-gate  */
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate /*
9467c478bd9Sstevel@tonic-gate  * ddi_segmap:		setup the default segment driver. Calls the drivers
9477c478bd9Sstevel@tonic-gate  *			XXmmap routine to validate the range to be mapped.
9487c478bd9Sstevel@tonic-gate  *			Return ENXIO of the range is not valid.  Create
9497c478bd9Sstevel@tonic-gate  *			a seg_dev segment that contains all of the
9507c478bd9Sstevel@tonic-gate  *			necessary information and will reference the
9517c478bd9Sstevel@tonic-gate  *			default segment driver routines. It returns zero
9527c478bd9Sstevel@tonic-gate  *			on success or non-zero on failure.
9537c478bd9Sstevel@tonic-gate  */
9547c478bd9Sstevel@tonic-gate int
ddi_segmap(dev_t dev,off_t offset,struct as * asp,caddr_t * addrp,off_t len,uint_t prot,uint_t maxprot,uint_t flags,cred_t * credp)9557c478bd9Sstevel@tonic-gate ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
9567c478bd9Sstevel@tonic-gate     uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
9577c478bd9Sstevel@tonic-gate {
9587c478bd9Sstevel@tonic-gate 	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
9597c478bd9Sstevel@tonic-gate 	    off_t, uint_t, uint_t, uint_t, struct cred *);
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	return (spec_segmap(dev, offset, asp, addrp, len,
9627c478bd9Sstevel@tonic-gate 	    prot, maxprot, flags, credp));
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate /*
9667c478bd9Sstevel@tonic-gate  * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
9677c478bd9Sstevel@tonic-gate  *			drivers. Allows each successive parent to resolve
9687c478bd9Sstevel@tonic-gate  *			address translations and add its mappings to the
9697c478bd9Sstevel@tonic-gate  *			mapping list supplied in the page structure. It
9707c478bd9Sstevel@tonic-gate  *			returns zero on success	or non-zero on failure.
9717c478bd9Sstevel@tonic-gate  */
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate int
ddi_map_fault(dev_info_t * dip,struct hat * hat,struct seg * seg,caddr_t addr,struct devpage * dp,pfn_t pfn,uint_t prot,uint_t lock)9747c478bd9Sstevel@tonic-gate ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
9757c478bd9Sstevel@tonic-gate     caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
9767c478bd9Sstevel@tonic-gate {
9777c478bd9Sstevel@tonic-gate 	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate /*
9817c478bd9Sstevel@tonic-gate  * ddi_device_mapping_check:	Called from ddi_segmap_setup.
9827c478bd9Sstevel@tonic-gate  *	Invokes platform specific DDI to determine whether attributes specified
9837c478bd9Sstevel@tonic-gate  *	in attr(9s) are	valid for the region of memory that will be made
9847c478bd9Sstevel@tonic-gate  *	available for direct access to user process via the mmap(2) system call.
9857c478bd9Sstevel@tonic-gate  */
9867c478bd9Sstevel@tonic-gate int
ddi_device_mapping_check(dev_t dev,ddi_device_acc_attr_t * accattrp,uint_t rnumber,uint_t * hat_flags)9877c478bd9Sstevel@tonic-gate ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
9887c478bd9Sstevel@tonic-gate     uint_t rnumber, uint_t *hat_flags)
9897c478bd9Sstevel@tonic-gate {
9907c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t handle;
9917c478bd9Sstevel@tonic-gate 	ddi_map_req_t mr;
9927c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp;
9937c478bd9Sstevel@tonic-gate 	int result;
9947c478bd9Sstevel@tonic-gate 	dev_info_t *dip;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	/*
9977c478bd9Sstevel@tonic-gate 	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
9987c478bd9Sstevel@tonic-gate 	 * release it immediately since it should already be held by
9997c478bd9Sstevel@tonic-gate 	 * a devfs vnode.
10007c478bd9Sstevel@tonic-gate 	 */
10017c478bd9Sstevel@tonic-gate 	if ((dip =
10027c478bd9Sstevel@tonic-gate 	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
10037c478bd9Sstevel@tonic-gate 		return (-1);
10047c478bd9Sstevel@tonic-gate 	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	/*
10077c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the common elements of data
10087c478bd9Sstevel@tonic-gate 	 * access handle.
10097c478bd9Sstevel@tonic-gate 	 */
10107c478bd9Sstevel@tonic-gate 	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
10117c478bd9Sstevel@tonic-gate 	if (handle == NULL)
10127c478bd9Sstevel@tonic-gate 		return (-1);
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	hp = impl_acc_hdl_get(handle);
10157c478bd9Sstevel@tonic-gate 	hp->ah_vers = VERS_ACCHDL;
10167c478bd9Sstevel@tonic-gate 	hp->ah_dip = dip;
10177c478bd9Sstevel@tonic-gate 	hp->ah_rnumber = rnumber;
10187c478bd9Sstevel@tonic-gate 	hp->ah_offset = 0;
10197c478bd9Sstevel@tonic-gate 	hp->ah_len = 0;
10207c478bd9Sstevel@tonic-gate 	hp->ah_acc = *accattrp;
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	/*
1023