xref: /illumos-gate/usr/src/uts/common/os/sunddi.c (revision d083fed0)
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,
253*d083fed0SRichard Lowe     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,
268*d083fed0SRichard Lowe     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 
4367c478bd9Sstevel@tonic-gate int
ddi_poke8(dev_info_t * dip,int8_t * addr,int8_t val)4377c478bd9Sstevel@tonic-gate ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
4387c478bd9Sstevel@tonic-gate {
4397c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate int
ddi_poke16(dev_info_t * dip,int16_t * addr,int16_t val)4437c478bd9Sstevel@tonic-gate ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate int
ddi_poke32(dev_info_t * dip,int32_t * addr,int32_t val)4497c478bd9Sstevel@tonic-gate ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate int
ddi_poke64(dev_info_t * dip,int64_t * addr,int64_t val)4557c478bd9Sstevel@tonic-gate ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
4564ab75253Smrj {
4574ab75253Smrj 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
4584ab75253Smrj }
4594ab75253Smrj 
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate  * ddi_peekpokeio() is used primarily by the mem drivers for moving
4627c478bd9Sstevel@tonic-gate  * data to and from uio structures via peek and poke.  Note that we
4637c478bd9Sstevel@tonic-gate  * use "internal" routines ddi_peek and ddi_poke to make this go
4647c478bd9Sstevel@tonic-gate  * slightly faster, avoiding the call overhead ..
4657c478bd9Sstevel@tonic-gate  */
4667c478bd9Sstevel@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)4677c478bd9Sstevel@tonic-gate ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
4687c478bd9Sstevel@tonic-gate     caddr_t addr, size_t len, uint_t xfersize)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	int64_t	ibuffer;
4717c478bd9Sstevel@tonic-gate 	int8_t w8;
4727c478bd9Sstevel@tonic-gate 	size_t sz;
4737c478bd9Sstevel@tonic-gate 	int o;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (xfersize > sizeof (long))
4767c478bd9Sstevel@tonic-gate 		xfersize = sizeof (long);
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	while (len != 0) {
4797c478bd9Sstevel@tonic-gate 		if ((len | (uintptr_t)addr) & 1) {
4807c478bd9Sstevel@tonic-gate 			sz = sizeof (int8_t);
4817c478bd9Sstevel@tonic-gate 			if (rw == UIO_WRITE) {
4827c478bd9Sstevel@tonic-gate 				if ((o = uwritec(uio)) == -1)
4837c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
4847c478bd9Sstevel@tonic-gate 				if (ddi_poke8(devi, (int8_t *)addr,
4857c478bd9Sstevel@tonic-gate 				    (int8_t)o) != DDI_SUCCESS)
4867c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
4877c478bd9Sstevel@tonic-gate 			} else {
4887c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
4897c478bd9Sstevel@tonic-gate 				    (int8_t *)addr, &w8) != DDI_SUCCESS)
4907c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
4917c478bd9Sstevel@tonic-gate 				if (ureadc(w8, uio))
4927c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
4937c478bd9Sstevel@tonic-gate 			}
4947c478bd9Sstevel@tonic-gate 		} else {
4957c478bd9Sstevel@tonic-gate 			switch (xfersize) {
4967c478bd9Sstevel@tonic-gate 			case sizeof (int64_t):
4977c478bd9Sstevel@tonic-gate 				if (((len | (uintptr_t)addr) &
4987c478bd9Sstevel@tonic-gate 				    (sizeof (int64_t) - 1)) == 0) {
4997c478bd9Sstevel@tonic-gate 					sz = xfersize;
5007c478bd9Sstevel@tonic-gate 					break;
5017c478bd9Sstevel@tonic-gate 				}
5027c478bd9Sstevel@tonic-gate 				/*FALLTHROUGH*/
5037c478bd9Sstevel@tonic-gate 			case sizeof (int32_t):
5047c478bd9Sstevel@tonic-gate 				if (((len | (uintptr_t)addr) &
5057c478bd9Sstevel@tonic-gate 				    (sizeof (int32_t) - 1)) == 0) {
5067c478bd9Sstevel@tonic-gate 					sz = xfersize;
5077c478bd9Sstevel@tonic-gate 					break;
5087c478bd9Sstevel@tonic-gate 				}
5097c478bd9Sstevel@tonic-gate 				/*FALLTHROUGH*/
5107c478bd9Sstevel@tonic-gate 			default:
5117c478bd9Sstevel@tonic-gate 				/*
5127c478bd9Sstevel@tonic-gate 				 * This still assumes that we might have an
5137c478bd9Sstevel@tonic-gate 				 * I/O bus out there that permits 16-bit
5147c478bd9Sstevel@tonic-gate 				 * transfers (and that it would be upset by
5157c478bd9Sstevel@tonic-gate 				 * 32-bit transfers from such locations).
5167c478bd9Sstevel@tonic-gate 				 */
5177c478bd9Sstevel@tonic-gate 				sz = sizeof (int16_t);
5187c478bd9Sstevel@tonic-gate 				break;
5197c478bd9Sstevel@tonic-gate 			}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 			if (rw == UIO_READ) {
5227c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
5237c478bd9Sstevel@tonic-gate 				    addr, &ibuffer) != DDI_SUCCESS)
5247c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5257c478bd9Sstevel@tonic-gate 			}
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 			if (uiomove(&ibuffer, sz, rw, uio))
5287c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 			if (rw == UIO_WRITE) {
5317c478bd9Sstevel@tonic-gate 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
5327c478bd9Sstevel@tonic-gate 				    addr, &ibuffer) != DDI_SUCCESS)
5337c478bd9Sstevel@tonic-gate 					return (DDI_FAILURE);
5347c478bd9Sstevel@tonic-gate 			}
5357c478bd9Sstevel@tonic-gate 		}
5367c478bd9Sstevel@tonic-gate 		addr += sz;
5377c478bd9Sstevel@tonic-gate 		len -= sz;
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate /*
5437c478bd9Sstevel@tonic-gate  * These routines are used by drivers that do layered ioctls
5447c478bd9Sstevel@tonic-gate  * On sparc, they're implemented in assembler to avoid spilling
5457c478bd9Sstevel@tonic-gate  * register windows in the common (copyin) case ..
5467c478bd9Sstevel@tonic-gate  */
5477c478bd9Sstevel@tonic-gate #if !defined(__sparc)
5487c478bd9Sstevel@tonic-gate int
ddi_copyin(const void * buf,void * kernbuf,size_t size,int flags)5497c478bd9Sstevel@tonic-gate ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
5507c478bd9Sstevel@tonic-gate {
5517c478bd9Sstevel@tonic-gate 	if (flags & FKIOCTL)
5527c478bd9Sstevel@tonic-gate 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
5537c478bd9Sstevel@tonic-gate 	return (copyin(buf, kernbuf, size));
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate int
ddi_copyout(const void * buf,void * kernbuf,size_t size,int flags)5577c478bd9Sstevel@tonic-gate ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate 	if (flags & FKIOCTL)
5607c478bd9Sstevel@tonic-gate 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
5617c478bd9Sstevel@tonic-gate 	return (copyout(buf, kernbuf, size));
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate #endif	/* !__sparc */
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate  * Conversions in nexus pagesize units.  We don't duplicate the
5677c478bd9Sstevel@tonic-gate  * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
5687c478bd9Sstevel@tonic-gate  * routines anyway.
5697c478bd9Sstevel@tonic-gate  */
5707c478bd9Sstevel@tonic-gate unsigned long
ddi_btop(dev_info_t * dip,unsigned long bytes)5717c478bd9Sstevel@tonic-gate ddi_btop(dev_info_t *dip, unsigned long bytes)
5727c478bd9Sstevel@tonic-gate {
5737c478bd9Sstevel@tonic-gate 	unsigned long pages;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
5767c478bd9Sstevel@tonic-gate 	return (pages);
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate unsigned long
ddi_btopr(dev_info_t * dip,unsigned long bytes)5807c478bd9Sstevel@tonic-gate ddi_btopr(dev_info_t *dip, unsigned long bytes)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	unsigned long pages;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
5857c478bd9Sstevel@tonic-gate 	return (pages);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate unsigned long
ddi_ptob(dev_info_t * dip,unsigned long pages)5897c478bd9Sstevel@tonic-gate ddi_ptob(dev_info_t *dip, unsigned long pages)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	unsigned long bytes;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
5947c478bd9Sstevel@tonic-gate 	return (bytes);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate unsigned int
ddi_enter_critical(void)5987c478bd9Sstevel@tonic-gate ddi_enter_critical(void)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate 	return ((uint_t)spl7());
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate void
ddi_exit_critical(unsigned int spl)6047c478bd9Sstevel@tonic-gate ddi_exit_critical(unsigned int spl)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate 	splx((int)spl);
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate  * Nexus ctlops punter
6117c478bd9Sstevel@tonic-gate  */
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate #if !defined(__sparc)
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate  * Request bus_ctl parent to handle a bus_ctl request
6167c478bd9Sstevel@tonic-gate  *
6177c478bd9Sstevel@tonic-gate  * (The sparc version is in sparc_ddi.s)
6187c478bd9Sstevel@tonic-gate  */
6197c478bd9Sstevel@tonic-gate int
ddi_ctlops(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t op,void * a,void * v)6207c478bd9Sstevel@tonic-gate ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate 	int (*fp)();
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if (!d || !r)
6257c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
6287c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
6317c478bd9Sstevel@tonic-gate 	return ((*fp)(d, r, op, a, v));
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate #endif
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate  * DMA/DVMA setup
6387c478bd9Sstevel@tonic-gate  */
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate #if !defined(__sparc)
6417c478bd9Sstevel@tonic-gate /*
6427c478bd9Sstevel@tonic-gate  * Request bus_dma_ctl parent to fiddle with a dma request.
6437c478bd9Sstevel@tonic-gate  *
6447c478bd9Sstevel@tonic-gate  * (The sparc version is in sparc_subr.s)
6457c478bd9Sstevel@tonic-gate  */
6467c478bd9Sstevel@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)6477c478bd9Sstevel@tonic-gate ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
6487c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
6497c478bd9Sstevel@tonic-gate     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate 	int (*fp)();
6527c478bd9Sstevel@tonic-gate 
653b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
654b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
6557c478bd9Sstevel@tonic-gate 	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
6567c478bd9Sstevel@tonic-gate 	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate #endif
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate /*
6617c478bd9Sstevel@tonic-gate  * For all DMA control functions, call the DMA control
6627c478bd9Sstevel@tonic-gate  * routine and return status.
6637c478bd9Sstevel@tonic-gate  *
6647c478bd9Sstevel@tonic-gate  * Just plain assume that the parent is to be called.
6657c478bd9Sstevel@tonic-gate  * If a nexus driver or a thread outside the framework
6667c478bd9Sstevel@tonic-gate  * of a nexus driver or a leaf driver calls these functions,
6677c478bd9Sstevel@tonic-gate  * it is up to them to deal with the fact that the parent's
6687c478bd9Sstevel@tonic-gate  * bus_dma_ctl function will be the first one called.
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate #define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate /*
674cd21e7c5SGarrett D'Amore  * This routine is left in place to satisfy link dependencies
675cd21e7c5SGarrett D'Amore  * for any 3rd party nexus drivers that rely on it.  It is never
676cd21e7c5SGarrett D'Amore  * called, though.
6777c478bd9Sstevel@tonic-gate  */
678cd21e7c5SGarrett D'Amore /*ARGSUSED*/
6797c478bd9Sstevel@tonic-gate int
ddi_dma_map(dev_info_t * dip,dev_info_t * rdip,struct ddi_dma_req * dmareqp,ddi_dma_handle_t * handlep)680cd21e7c5SGarrett D'Amore ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
681b89e420aSGarrett D'Amore     struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
6827c478bd9Sstevel@tonic-gate {
683cd21e7c5SGarrett D'Amore 	return (DDI_FAILURE);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate #if !defined(__sparc)
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate /*
6897c478bd9Sstevel@tonic-gate  * The SPARC versions of these routines are done in assembler to
6907c478bd9Sstevel@tonic-gate  * save register windows, so they're in sparc_subr.s.
6917c478bd9Sstevel@tonic-gate  */
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@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)6947c478bd9Sstevel@tonic-gate ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
6957c478bd9Sstevel@tonic-gate     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
6967c478bd9Sstevel@tonic-gate {
6977c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
6987c478bd9Sstevel@tonic-gate 	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
6997c478bd9Sstevel@tonic-gate 
700b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
701b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
7027c478bd9Sstevel@tonic-gate 
703b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
704b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate int
ddi_dma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handlep)7087c478bd9Sstevel@tonic-gate ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
7117c478bd9Sstevel@tonic-gate 
712b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
713b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
7147c478bd9Sstevel@tonic-gate 
715b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
716b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handlep));
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@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)7207c478bd9Sstevel@tonic-gate ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
7217c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
7227c478bd9Sstevel@tonic-gate     ddi_dma_cookie_t *cp, uint_t *ccountp)
7237c478bd9Sstevel@tonic-gate {
7247c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
7257c478bd9Sstevel@tonic-gate 	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
7267c478bd9Sstevel@tonic-gate 
727b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
728b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
7297c478bd9Sstevel@tonic-gate 
730b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
731b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate int
ddi_dma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)7357c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
7367c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle)
7377c478bd9Sstevel@tonic-gate {
7387c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
7397c478bd9Sstevel@tonic-gate 
740b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
741b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
7427c478bd9Sstevel@tonic-gate 
743b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
744b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle));
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@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)7497c478bd9Sstevel@tonic-gate ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
7507c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, off_t off, size_t len,
7517c478bd9Sstevel@tonic-gate     uint_t cache_flags)
7527c478bd9Sstevel@tonic-gate {
7537c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
7547c478bd9Sstevel@tonic-gate 	    off_t, size_t, uint_t);
7557c478bd9Sstevel@tonic-gate 
756b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
757b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
7587c478bd9Sstevel@tonic-gate 
759b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
760b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@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)7647c478bd9Sstevel@tonic-gate ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
7657c478bd9Sstevel@tonic-gate     ddi_dma_handle_t handle, uint_t win, off_t *offp,
7667c478bd9Sstevel@tonic-gate     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
7677c478bd9Sstevel@tonic-gate {
7687c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
7697c478bd9Sstevel@tonic-gate 	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
7707c478bd9Sstevel@tonic-gate 
771b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
772b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
7737c478bd9Sstevel@tonic-gate 
774b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
775b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
7767c478bd9Sstevel@tonic-gate 	    cookiep, ccountp));
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate int
ddi_dma_sync(ddi_dma_handle_t h,off_t o,size_t l,uint_t whom)7807c478bd9Sstevel@tonic-gate ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
783b51bbbf5SVikram Hegde 	dev_info_t *dip, *rdip;
7847c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
785184cd04cScth 	    size_t, uint_t);
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	/*
7887c478bd9Sstevel@tonic-gate 	 * the DMA nexus driver will set DMP_NOSYNC if the
7897c478bd9Sstevel@tonic-gate 	 * platform does not require any sync operation. For
7907c478bd9Sstevel@tonic-gate 	 * example if the memory is uncached or consistent
7917c478bd9Sstevel@tonic-gate 	 * and without any I/O write buffers involved.
7927c478bd9Sstevel@tonic-gate 	 */
7937c478bd9Sstevel@tonic-gate 	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
7947c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
7957c478bd9Sstevel@tonic-gate 
796b51bbbf5SVikram Hegde 	dip = rdip = hp->dmai_rdip;
797b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
798b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
799b51bbbf5SVikram Hegde 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
800b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, h, o, l, whom));
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate int
ddi_dma_unbind_handle(ddi_dma_handle_t h)8047c478bd9Sstevel@tonic-gate ddi_dma_unbind_handle(ddi_dma_handle_t h)
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
807b51bbbf5SVikram Hegde 	dev_info_t *dip, *rdip;
8087c478bd9Sstevel@tonic-gate 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
8097c478bd9Sstevel@tonic-gate 
810b51bbbf5SVikram Hegde 	dip = rdip = hp->dmai_rdip;
811b51bbbf5SVikram Hegde 	if (dip != ddi_root_node())
812b51bbbf5SVikram Hegde 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
813b51bbbf5SVikram Hegde 	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
814b51bbbf5SVikram Hegde 	return ((*funcp)(dip, rdip, h));
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate #endif	/* !__sparc */
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate /*
820cd21e7c5SGarrett D'Amore  * DMA burst sizes, and transfer minimums
8217c478bd9Sstevel@tonic-gate  */
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate int
ddi_dma_burstsizes(ddi_dma_handle_t handle)8247c478bd9Sstevel@tonic-gate ddi_dma_burstsizes(ddi_dma_handle_t handle)
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	if (!dimp)
8297c478bd9Sstevel@tonic-gate 		return (0);
8307c478bd9Sstevel@tonic-gate 	else
8317c478bd9Sstevel@tonic-gate 		return (dimp->dmai_burstsizes);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate /*
8357c478bd9Sstevel@tonic-gate  * Given two DMA attribute structures, apply the attributes
8367c478bd9Sstevel@tonic-gate  * of one to the other, following the rules of attributes
8377c478bd9Sstevel@tonic-gate  * and the wishes of the caller.
8387c478bd9Sstevel@tonic-gate  *
8397c478bd9Sstevel@tonic-gate  * The rules of DMA attribute structures are that you cannot
8407c478bd9Sstevel@tonic-gate  * make things *less* restrictive as you apply one set
8417c478bd9Sstevel@tonic-gate  * of attributes to another.
8427c478bd9Sstevel@tonic-gate  *
8437c478bd9Sstevel@tonic-gate  */
8447c478bd9Sstevel@tonic-gate void
ddi_dma_attr_merge(ddi_dma_attr_t * attr,ddi_dma_attr_t * mod)8457c478bd9Sstevel@tonic-gate ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
8467c478bd9Sstevel@tonic-gate {
8477c478bd9Sstevel@tonic-gate 	attr->dma_attr_addr_lo =
8487c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
8497c478bd9Sstevel@tonic-gate 	attr->dma_attr_addr_hi =
8507c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
8517c478bd9Sstevel@tonic-gate 	attr->dma_attr_count_max =
8527c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
8537c478bd9Sstevel@tonic-gate 	attr->dma_attr_align =
8547c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
8557c478bd9Sstevel@tonic-gate 	attr->dma_attr_burstsizes =
8567c478bd9Sstevel@tonic-gate 	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
8577c478bd9Sstevel@tonic-gate 	attr->dma_attr_minxfer =
8587c478bd9Sstevel@tonic-gate 	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
8597c478bd9Sstevel@tonic-gate 	attr->dma_attr_maxxfer =
8607c478bd9Sstevel@tonic-gate 	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
8617c478bd9Sstevel@tonic-gate 	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
8627c478bd9Sstevel@tonic-gate 	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
8637c478bd9Sstevel@tonic-gate 	    (uint_t)mod->dma_attr_sgllen);
8647c478bd9Sstevel@tonic-gate 	attr->dma_attr_granular =
8657c478bd9Sstevel@tonic-gate 	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate /*
8697c478bd9Sstevel@tonic-gate  * mmap/segmap interface:
8707c478bd9Sstevel@tonic-gate  */
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate /*
8737c478bd9Sstevel@tonic-gate  * ddi_segmap:		setup the default segment driver. Calls the drivers
8747c478bd9Sstevel@tonic-gate  *			XXmmap routine to validate the range to be mapped.
8757c478bd9Sstevel@tonic-gate  *			Return ENXIO of the range is not valid.  Create
8767c478bd9Sstevel@tonic-gate  *			a seg_dev segment that contains all of the
8777c478bd9Sstevel@tonic-gate  *			necessary information and will reference the
8787c478bd9Sstevel@tonic-gate  *			default segment driver routines. It returns zero
8797c478bd9Sstevel@tonic-gate  *			on success or non-zero on failure.
8807c478bd9Sstevel@tonic-gate  */
8817c478bd9Sstevel@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)8827c478bd9Sstevel@tonic-gate ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
8837c478bd9Sstevel@tonic-gate     uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate 	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
8867c478bd9Sstevel@tonic-gate 	    off_t, uint_t, uint_t, uint_t, struct cred *);
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	return (spec_segmap(dev, offset, asp, addrp, len,
8897c478bd9Sstevel@tonic-gate 	    prot, maxprot, flags, credp));
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate /*
8937c478bd9Sstevel@tonic-gate  * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
8947c478bd9Sstevel@tonic-gate  *			drivers. Allows each successive parent to resolve
8957c478bd9Sstevel@tonic-gate  *			address translations and add its mappings to the
8967c478bd9Sstevel@tonic-gate  *			mapping list supplied in the page structure. It
8977c478bd9Sstevel@tonic-gate  *			returns zero on success	or non-zero on failure.
8987c478bd9Sstevel@tonic-gate  */
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@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)9017c478bd9Sstevel@tonic-gate ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
9027c478bd9Sstevel@tonic-gate     caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
9037c478bd9Sstevel@tonic-gate {
9047c478bd9Sstevel@tonic-gate 	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate /*
9087c478bd9Sstevel@tonic-gate  * ddi_device_mapping_check:	Called from ddi_segmap_setup.
9097c478bd9Sstevel@tonic-gate  *	Invokes platform specific DDI to determine whether attributes specified
9107c478bd9Sstevel@tonic-gate  *	in attr(9s) are	valid for the region of memory that will be made
9117c478bd9Sstevel@tonic-gate  *	available for direct access to user process via the mmap(2) system call.
9127c478bd9Sstevel@tonic-gate  */
9137c478bd9Sstevel@tonic-gate int
ddi_device_mapping_check(dev_t dev,ddi_device_acc_attr_t * accattrp,uint_t rnumber,uint_t * hat_flags)9147c478bd9Sstevel@tonic-gate ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
9157c478bd9Sstevel@tonic-gate     uint_t rnumber, uint_t *hat_flags)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t handle;
9187c478bd9Sstevel@tonic-gate 	ddi_map_req_t mr;
9197c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp;
9207c478bd9Sstevel@tonic-gate 	int result;
9217c478bd9Sstevel@tonic-gate 	dev_info_t *dip;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	/*
9247c478bd9Sstevel@tonic-gate 	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
9257c478bd9Sstevel@tonic-gate 	 * release it immediately since it should already be held by
9267c478bd9Sstevel@tonic-gate 	 * a devfs vnode.
9277c478bd9Sstevel@tonic-gate 	 */
9287c478bd9Sstevel@tonic-gate 	if ((dip =
9297c478bd9Sstevel@tonic-gate 	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
9307c478bd9Sstevel@tonic-gate 		return (-1);
9317c478bd9Sstevel@tonic-gate 	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	/*
9347c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the common elements of data
9357c478bd9Sstevel@tonic-gate 	 * access handle.
9367c478bd9Sstevel@tonic-gate 	 */
9377c478bd9Sstevel@tonic-gate 	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
9387c478bd9Sstevel@tonic-gate 	if (handle == NULL)
9397c478bd9Sstevel@tonic-gate 		return (-1);
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	hp = impl_acc_hdl_get(handle);
9427c478bd9Sstevel@tonic-gate 	hp->ah_vers = VERS_ACCHDL;
9437c478bd9Sstevel@tonic-gate 	hp->ah_dip = dip;
9447c478bd9Sstevel@tonic-gate 	hp->ah_rnumber = rnumber;
9457c478bd9Sstevel@tonic-gate 	hp->ah_offset = 0;
9467c478bd9Sstevel@tonic-gate 	hp->ah_len = 0;
9477c478bd9Sstevel@tonic-gate 	hp->ah_acc = *accattrp;
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	/*
9507c478bd9Sstevel@tonic-gate 	 * Set up the mapping request and call to parent.
9517c478bd9Sstevel@tonic-gate 	 */
9527c478bd9Sstevel@tonic-gate 	mr.map_op = DDI_MO_MAP_HANDLE;
9537c478bd9Sstevel@tonic-gate 	mr.map_type = DDI_MT_RNUMBER;
9547c478bd9Sstevel@tonic-gate 	mr.map_obj.rnumber = rnumber;
9557c478bd9Sstevel@tonic-gate 	mr.map_prot = PROT_READ | PROT_WRITE;
9567c478bd9Sstevel@tonic-gate 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
9577c478bd9Sstevel@tonic-gate 	mr.map_handlep = hp;
9587c478bd9Sstevel@tonic-gate 	mr.map_vers = DDI_MAP_VERSION;
9597c478bd9Sstevel@tonic-gate 	result = ddi_map(dip, &mr, 0, 0, NULL);
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	/*
9627c478bd9Sstevel@tonic-gate 	 * Region must be mappable, pick up flags from the framework.
9637c478bd9Sstevel@tonic-gate 	 */
9647c478bd9Sstevel@tonic-gate 	*hat_flags = hp->ah_hat_flags;
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	impl_acc_hdl_free(handle);
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	/*
9697c478bd9Sstevel@tonic-gate 	 * check for end result.
9707c478bd9Sstevel@tonic-gate 	 */
9717c478bd9Sstevel@tonic-gate 	if (result != DDI_SUCCESS)
9727c478bd9Sstevel@tonic-gate 		return (-1);
9737c478bd9Sstevel@tonic-gate 	return (0);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate /*
9787c478bd9Sstevel@tonic-gate  * Property functions:	 See also, ddipropdefs.h.
9797c478bd9Sstevel@tonic-gate  *
9807c478bd9Sstevel@tonic-gate  * These functions are the framework for the property functions,
9817c478bd9Sstevel@tonic-gate  * i.e. they support software defined properties.  All implementation
9827c478bd9Sstevel@tonic-gate  * specific property handling (i.e.: self-identifying devices and
9837c478bd9Sstevel@tonic-gate  * PROM defined properties are handled in the implementation specific
9847c478bd9Sstevel@tonic-gate  * functions (defined in ddi_implfuncs.h).
9857c478bd9Sstevel@tonic-gate  */
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate /*
9887c478bd9Sstevel@tonic-gate  * nopropop:	Shouldn't be called, right?
9897c478bd9Sstevel@tonic-gate  */
9907c478bd9Sstevel@tonic-gate int
nopropop(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)9917c478bd9Sstevel@tonic-gate nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
9927c478bd9Sstevel@tonic-gate     char *name, caddr_t valuep, int *lengthp)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp))
9957c478bd9Sstevel@tonic-gate 	return (DDI_PROP_NOT_FOUND);
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate #ifdef	DDI_PROP_DEBUG
9997c478bd9Sstevel@tonic-gate int ddi_prop_debug_flag = 0;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate int
ddi_prop_debug(int enable)10027c478bd9Sstevel@tonic-gate ddi_prop_debug(int enable)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate 	int prev = ddi_prop_debug_flag;
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	if ((enable != 0) || (prev != 0))
10077c478bd9Sstevel@tonic-gate 		printf("ddi_prop_debug: debugging %s\n",
10087c478bd9Sstevel@tonic-gate 		    enable ? "enabled" : "disabled");
10097c478bd9Sstevel@tonic-gate 	ddi_prop_debug_flag = enable;
10107c478bd9Sstevel@tonic-gate 	return (prev);
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate #endif	/* DDI_PROP_DEBUG */
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate /*
10167c478bd9Sstevel@tonic-gate  * Search a property list for a match, if found return pointer
10177c478bd9Sstevel@tonic-gate  * to matching prop struct, else return NULL.
10187c478bd9Sstevel@tonic-gate  */
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate ddi_prop_t *
i_ddi_prop_search(dev_t dev,char * name,uint_t flags,ddi_prop_t ** list_head)10217c478bd9Sstevel@tonic-gate i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head)
10227c478bd9Sstevel@tonic-gate {
10237c478bd9Sstevel@tonic-gate 	ddi_prop_t	*propp;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	/*
10267c478bd9Sstevel@tonic-gate 	 * find the property in child's devinfo:
10279ac2ddeaScth 	 * Search order defined by this search function is first matching
10289ac2ddeaScth 	 * property with input dev == DDI_DEV_T_ANY matching any dev or
10299ac2ddeaScth 	 * dev == propp->prop_dev, name == propp->name, and the correct
10309ac2ddeaScth 	 * data type as specified in the flags.  If a DDI_DEV_T_NONE dev
10319ac2ddeaScth 	 * value made it this far then it implies a DDI_DEV_T_ANY search.
10327c478bd9Sstevel@tonic-gate 	 */
10339ac2ddeaScth 	if (dev == DDI_DEV_T_NONE)
10349ac2ddeaScth 		dev = DDI_DEV_T_ANY;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
10377c478bd9Sstevel@tonic-gate 
10382cd7878fScth 		if (!DDI_STRSAME(propp->prop_name, name))
10397c478bd9Sstevel@tonic-gate 			continue;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 		if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev))
10427c478bd9Sstevel@tonic-gate 			continue;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
10457c478bd9Sstevel@tonic-gate 			continue;
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		return (propp);
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	return ((ddi_prop_t *)0);
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate  * Search for property within devnames structures
10557c478bd9Sstevel@tonic-gate  */
10567c478bd9Sstevel@tonic-gate ddi_prop_t *
i_ddi_search_global_prop(dev_t dev,char * name,uint_t flags)10577c478bd9Sstevel@tonic-gate i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags)
10587c478bd9Sstevel@tonic-gate {
10597c478bd9Sstevel@tonic-gate 	major_t		major;
10607c478bd9Sstevel@tonic-gate 	struct devnames	*dnp;
10617c478bd9Sstevel@tonic-gate 	ddi_prop_t	*propp;
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 	/*
10647c478bd9Sstevel@tonic-gate 	 * Valid dev_t value is needed to index into the
10657c478bd9Sstevel@tonic-gate 	 * correct devnames entry, therefore a dev_t
10667c478bd9Sstevel@tonic-gate 	 * value of DDI_DEV_T_ANY is not appropriate.
10677c478bd9Sstevel@tonic-gate 	 */
10687c478bd9Sstevel@tonic-gate 	ASSERT(dev != DDI_DEV_T_ANY);
10697c478bd9Sstevel@tonic-gate 	if (dev == DDI_DEV_T_ANY) {
10707c478bd9Sstevel@tonic-gate 		return ((ddi_prop_t *)0);
10717c478bd9Sstevel@tonic-gate 	}
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	major = getmajor(dev);
10747c478bd9Sstevel@tonic-gate 	dnp = &(devnamesp[major]);
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	if (dnp->dn_global_prop_ptr == NULL)
10777c478bd9Sstevel@tonic-gate 		return ((ddi_prop_t *)0);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	LOCK_DEV_OPS(&dnp->dn_lock);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	for (propp = dnp->dn_global_prop_ptr->prop_list;
10827c478bd9Sstevel@tonic-gate 	    propp != NULL;
10837c478bd9Sstevel@tonic-gate 	    propp = (ddi_prop_t *)propp->prop_next) {
10847c478bd9Sstevel@tonic-gate 
10852cd7878fScth 		if (!DDI_STRSAME(propp->prop_name, name))
10867c478bd9Sstevel@tonic-gate 			continue;
10877c478bd9Sstevel@tonic-gate 
108865cf7c95SVikram Hegde 		if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) &&
108965cf7c95SVikram Hegde 		    (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev))
10907c478bd9Sstevel@tonic-gate 			continue;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
10937c478bd9Sstevel@tonic-gate 			continue;
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 		/* Property found, return it */
10967c478bd9Sstevel@tonic-gate 		UNLOCK_DEV_OPS(&dnp->dn_lock);
10977c478bd9Sstevel@tonic-gate 		return (propp);
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	UNLOCK_DEV_OPS(&dnp->dn_lock);
11017c478bd9Sstevel@tonic-gate 	return ((ddi_prop_t *)0);
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate static char prop_no_mem_m