xref: /illumos-gate/usr/src/uts/sun4u/io/isadma.c (revision cd21e7c5)
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
5903a11ebSrh  * Common Development and Distribution License (the "License").
6903a11ebSrh  * 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  */
217c478bd9Sstevel@tonic-gate /*
22903a11ebSrh  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
25*cd21e7c5SGarrett D'Amore /*
26*cd21e7c5SGarrett D'Amore  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
27*cd21e7c5SGarrett D'Amore  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/conf.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
337c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
347c478bd9Sstevel@tonic-gate #include <sys/dma_i8237A.h>
357c478bd9Sstevel@tonic-gate #include <sys/isadma.h>
367c478bd9Sstevel@tonic-gate #include <sys/nexusdebug.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* Bitfield debugging definitions for this file */
397c478bd9Sstevel@tonic-gate #define	ISADMA_MAP_DEBUG	0x1
407c478bd9Sstevel@tonic-gate #define	ISADMA_REGACCESS_DEBUG	0x2
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * The isadam nexus serves two functions.  The first is to represent a
447c478bd9Sstevel@tonic-gate  * a placeholder in the device tree for a shared dma controller register
457c478bd9Sstevel@tonic-gate  * for the SuperIO floppy and parallel ports.
467c478bd9Sstevel@tonic-gate  * The second function is to virtualize the shared dma controller register
477c478bd9Sstevel@tonic-gate  * for those two drivers.  Rather than creating new ddi routines to manage
487c478bd9Sstevel@tonic-gate  * the shared register, we will use the ddi register mapping functions to
497c478bd9Sstevel@tonic-gate  * do this.  The two child devices will use ddi_regs_map_setup to map in
507c478bd9Sstevel@tonic-gate  * their device registers.  The isadma nexus will have an aliased entry in
517c478bd9Sstevel@tonic-gate  * it's own registers property for the shared dma controller register.  When
527c478bd9Sstevel@tonic-gate  * the isadma detects the fact that it's children are trying to map the shared
537c478bd9Sstevel@tonic-gate  * register, it will intercept this mapping and provide it's own register
547c478bd9Sstevel@tonic-gate  * access routine to be used to access the register when the child devices
557c478bd9Sstevel@tonic-gate  * use the ddi_{get,put} calls.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * Sigh, the 82C37 has a weird quirk (BUG?) where when DMA is active on the
587c478bd9Sstevel@tonic-gate  * the bus, PIO's cannot happen.  If they do, they generate bus faults and
597c478bd9Sstevel@tonic-gate  * cause the system to panic.  On PC's, the Intel processor has special
607c478bd9Sstevel@tonic-gate  * req/grnt lines that prevent PIO's from occuring while DMA is in flight,
617c478bd9Sstevel@tonic-gate  * unfortunately, hummingbird doesn't support this special req/grnt pair.
627c478bd9Sstevel@tonic-gate  * I'm going to try and work around this by implementing a cv to stop PIO's
637c478bd9Sstevel@tonic-gate  * from occuring while DMA is in flight.  When each child wants to do DMA,
647c478bd9Sstevel@tonic-gate  * they need to mask out all other channels using the allmask register.
657c478bd9Sstevel@tonic-gate  * This nexus keys on this access and locks down the hardware using a cv.
667c478bd9Sstevel@tonic-gate  * Once the driver's interrupt handler is called it needs to clear
677c478bd9Sstevel@tonic-gate  * the allmask register.  The nexus keys off of this an issues cv wakeups
687c478bd9Sstevel@tonic-gate  * if necessary.
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * Function prototypes for busops routines:
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate static int isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
747c478bd9Sstevel@tonic-gate     off_t off, off_t len, caddr_t *addrp);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * function prototypes for dev ops routines:
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate static int isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
807c478bd9Sstevel@tonic-gate static int isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * general function prototypes:
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * bus ops and dev ops structures:
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate static struct bus_ops isadma_bus_ops = {
907c478bd9Sstevel@tonic-gate 	BUSO_REV,
917c478bd9Sstevel@tonic-gate 	isadma_map,
927c478bd9Sstevel@tonic-gate 	NULL,
937c478bd9Sstevel@tonic-gate 	NULL,
947c478bd9Sstevel@tonic-gate 	NULL,
957c478bd9Sstevel@tonic-gate 	i_ddi_map_fault,
96*cd21e7c5SGarrett D'Amore 	NULL,
977c478bd9Sstevel@tonic-gate 	ddi_dma_allochdl,
987c478bd9Sstevel@tonic-gate 	ddi_dma_freehdl,
997c478bd9Sstevel@tonic-gate 	ddi_dma_bindhdl,
1007c478bd9Sstevel@tonic-gate 	ddi_dma_unbindhdl,
1017c478bd9Sstevel@tonic-gate 	ddi_dma_flush,
1027c478bd9Sstevel@tonic-gate 	ddi_dma_win,
1037c478bd9Sstevel@tonic-gate 	ddi_dma_mctl,
1047c478bd9Sstevel@tonic-gate 	ddi_ctlops,
1057c478bd9Sstevel@tonic-gate 	ddi_bus_prop_op,
1067c478bd9Sstevel@tonic-gate 	0,			/* (*bus_get_eventcookie)();	*/
1077c478bd9Sstevel@tonic-gate 	0,			/* (*bus_add_eventcall)();	*/
1087c478bd9Sstevel@tonic-gate 	0,			/* (*bus_remove_eventcall)();	*/
1097c478bd9Sstevel@tonic-gate 	0,			/* (*bus_post_event)();		*/
1107c478bd9Sstevel@tonic-gate 	0,			/* (*bus_intr_control)();	*/
1117c478bd9Sstevel@tonic-gate 	0,			/* (*bus_config)();		*/
1127c478bd9Sstevel@tonic-gate 	0,			/* (*bus_unconfig)();		*/
1137c478bd9Sstevel@tonic-gate 	0,			/* (*bus_fm_init)();		*/
1147c478bd9Sstevel@tonic-gate 	0,			/* (*bus_fm_fini)();		*/
1157c478bd9Sstevel@tonic-gate 	0,			/* (*bus_fm_access_enter)();	*/
1167c478bd9Sstevel@tonic-gate 	0,			/* (*bus_fm_access_exit)();	*/
1177c478bd9Sstevel@tonic-gate 	0,			/* (*bus_power)();		*/
1187c478bd9Sstevel@tonic-gate 	i_ddi_intr_ops		/* (*bus_intr_op();		*/
1197c478bd9Sstevel@tonic-gate };
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate static struct dev_ops isadma_ops = {
1227c478bd9Sstevel@tonic-gate 	DEVO_REV,
1237c478bd9Sstevel@tonic-gate 	0,
1247c478bd9Sstevel@tonic-gate 	ddi_no_info,
1257c478bd9Sstevel@tonic-gate 	nulldev,
1267c478bd9Sstevel@tonic-gate 	0,
1277c478bd9Sstevel@tonic-gate 	isadma_attach,
1287c478bd9Sstevel@tonic-gate 	isadma_detach,
1297c478bd9Sstevel@tonic-gate 	nodev,
1307c478bd9Sstevel@tonic-gate 	(struct cb_ops *)0,
13119397407SSherry Moore 	&isadma_bus_ops,
13219397407SSherry Moore 	NULL,
13319397407SSherry Moore 	ddi_quiesce_not_needed,		/* quiesce */
1347c478bd9Sstevel@tonic-gate };
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * module definitions:
1387c478bd9Sstevel@tonic-gate  */
1397c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1427c478bd9Sstevel@tonic-gate 	&mod_driverops, 	/* Type of module.  This one is a driver */
1437c478bd9Sstevel@tonic-gate 	"isadma nexus driver",	/* Name of module. */
1447c478bd9Sstevel@tonic-gate 	&isadma_ops,		/* driver ops */
1457c478bd9Sstevel@tonic-gate };
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1487c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1497c478bd9Sstevel@tonic-gate };
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * driver global data:
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate static void *per_isadma_state;		/* per-isadma soft state pointer */
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /* Global debug data */
1577c478bd9Sstevel@tonic-gate uint64_t isadma_sleep_cnt = 0;
1587c478bd9Sstevel@tonic-gate uint64_t isadma_wakeup_cnt = 0;
1597c478bd9Sstevel@tonic-gate #ifdef DEBUG
1607c478bd9Sstevel@tonic-gate int64_t isadma_max_waiter = 0;
1617c478bd9Sstevel@tonic-gate int64_t isadma_min_waiter = 0xffffll;
1627c478bd9Sstevel@tonic-gate uint64_t isadma_punt = 0;
1637c478bd9Sstevel@tonic-gate uint64_t isadma_setting_wdip = 0;
1647c478bd9Sstevel@tonic-gate uint64_t isadma_clearing_wdip = 0;
1657c478bd9Sstevel@tonic-gate #endif
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate int
_init(void)1687c478bd9Sstevel@tonic-gate _init(void)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	int e;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	/*
1737c478bd9Sstevel@tonic-gate 	 * Initialize per-isadma soft state pointer.
1747c478bd9Sstevel@tonic-gate 	 */
1757c478bd9Sstevel@tonic-gate 	e = ddi_soft_state_init(&per_isadma_state,
1767c478bd9Sstevel@tonic-gate 	    sizeof (isadma_devstate_t), 1);
1777c478bd9Sstevel@tonic-gate 	if (e != 0)
1787c478bd9Sstevel@tonic-gate 		return (e);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/*
1817c478bd9Sstevel@tonic-gate 	 * Install the module.
1827c478bd9Sstevel@tonic-gate 	 */
1837c478bd9Sstevel@tonic-gate 	e = mod_install(&modlinkage);
1847c478bd9Sstevel@tonic-gate 	if (e != 0)
1857c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&per_isadma_state);
1867c478bd9Sstevel@tonic-gate 	return (e);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate int
_fini(void)1907c478bd9Sstevel@tonic-gate _fini(void)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	int e;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	/*
1957c478bd9Sstevel@tonic-gate 	 * Remove the module.
1967c478bd9Sstevel@tonic-gate 	 */
1977c478bd9Sstevel@tonic-gate 	e = mod_remove(&modlinkage);
1987c478bd9Sstevel@tonic-gate 	if (e != 0)
1997c478bd9Sstevel@tonic-gate 		return (e);
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	/*
2027c478bd9Sstevel@tonic-gate 	 * Free the soft state info.
2037c478bd9Sstevel@tonic-gate 	 */
2047c478bd9Sstevel@tonic-gate 	ddi_soft_state_fini(&per_isadma_state);
2057c478bd9Sstevel@tonic-gate 	return (e);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2097c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /* device driver entry points */
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate  * attach entry point:
2187c478bd9Sstevel@tonic-gate  */
2197c478bd9Sstevel@tonic-gate static int
isadma_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2207c478bd9Sstevel@tonic-gate isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2217c478bd9Sstevel@tonic-gate {
2227c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap;	/* per isadma state pointer */
2237c478bd9Sstevel@tonic-gate 	int32_t instance;
2247c478bd9Sstevel@tonic-gate 	int ret = DDI_SUCCESS;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate #ifdef DEBUG
2277c478bd9Sstevel@tonic-gate 	debug_print_level = 0;
2287c478bd9Sstevel@tonic-gate 	debug_info = 1;
2297c478bd9Sstevel@tonic-gate #endif
2307c478bd9Sstevel@tonic-gate 	switch (cmd) {
2317c478bd9Sstevel@tonic-gate 	case DDI_ATTACH: {
2327c478bd9Sstevel@tonic-gate 		/*
2337c478bd9Sstevel@tonic-gate 		 * Allocate soft state for this instance.
2347c478bd9Sstevel@tonic-gate 		 */
2357c478bd9Sstevel@tonic-gate 		instance = ddi_get_instance(dip);
2367c478bd9Sstevel@tonic-gate 		if (ddi_soft_state_zalloc(per_isadma_state, instance)
237903a11ebSrh 		    != DDI_SUCCESS) {
2387c478bd9Sstevel@tonic-gate 			ret = DDI_FAILURE;
2397c478bd9Sstevel@tonic-gate 			goto exit;
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 		isadmap = ddi_get_soft_state(per_isadma_state, instance);
2427c478bd9Sstevel@tonic-gate 		isadmap->isadma_dip = dip;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		/* Cache our register property */
245a3282898Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2467c478bd9Sstevel@tonic-gate 		    "reg", (caddr_t)&isadmap->isadma_regp,
2477c478bd9Sstevel@tonic-gate 		    &isadmap->isadma_reglen) != DDI_SUCCESS) {
2487c478bd9Sstevel@tonic-gate 			ret = DDI_FAILURE;
2497c478bd9Sstevel@tonic-gate 			goto fail_get_prop;
2507c478bd9Sstevel@tonic-gate 		}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 		/* Initialize our mutex */
2537c478bd9Sstevel@tonic-gate 		mutex_init(&isadmap->isadma_access_lock, NULL, MUTEX_DRIVER,
2547c478bd9Sstevel@tonic-gate 		    NULL);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		/* Initialize our condition variable */
2577c478bd9Sstevel@tonic-gate 		cv_init(&isadmap->isadma_access_cv, NULL, CV_DRIVER, NULL);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		ddi_report_dev(dip);
2607c478bd9Sstevel@tonic-gate 		goto exit;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
2647c478bd9Sstevel@tonic-gate 	default:
2657c478bd9Sstevel@tonic-gate 		goto exit;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate fail_get_prop:
2697c478bd9Sstevel@tonic-gate 	ddi_soft_state_free(per_isadma_state, instance);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate exit:
2727c478bd9Sstevel@tonic-gate 	return (ret);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate  * detach entry point:
2777c478bd9Sstevel@tonic-gate  */
2787c478bd9Sstevel@tonic-gate static int
isadma_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2797c478bd9Sstevel@tonic-gate isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
2827c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap =
283903a11ebSrh 	    ddi_get_soft_state(per_isadma_state, instance);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	switch (cmd) {
2867c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
2877c478bd9Sstevel@tonic-gate 		cv_destroy(&isadmap->isadma_access_cv);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		mutex_destroy(&isadmap->isadma_access_lock);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		/* free the cached register property */
2927c478bd9Sstevel@tonic-gate 		kmem_free(isadmap->isadma_regp, isadmap->isadma_reglen);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 		ddi_soft_state_free(per_isadma_state, instance);
2957c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
2987c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate #ifdef DEBUG
3057c478bd9Sstevel@tonic-gate static void
isadma_check_waiters(isadma_devstate_t * isadmap)3067c478bd9Sstevel@tonic-gate isadma_check_waiters(isadma_devstate_t *isadmap)
3077c478bd9Sstevel@tonic-gate {
3087c478bd9Sstevel@tonic-gate 	if (isadmap->isadma_want > isadma_max_waiter)
3097c478bd9Sstevel@tonic-gate 		isadma_max_waiter = isadmap->isadma_want;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if (isadmap->isadma_want < isadma_min_waiter)
3127c478bd9Sstevel@tonic-gate 		isadma_min_waiter = isadmap->isadma_want;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate #endif
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate static void
isadma_dmawait(isadma_devstate_t * isadmap)3177c478bd9Sstevel@tonic-gate isadma_dmawait(isadma_devstate_t *isadmap)
3187c478bd9Sstevel@tonic-gate {
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&isadmap->isadma_access_lock));
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/* Wait loop, if the locking dip is set, we wait. */
3237c478bd9Sstevel@tonic-gate 	while (isadmap->isadma_ldip != NULL) {
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 		isadmap->isadma_want++;
3267c478bd9Sstevel@tonic-gate 		cv_wait(&isadmap->isadma_access_cv,
3277c478bd9Sstevel@tonic-gate 		    &isadmap->isadma_access_lock);
3287c478bd9Sstevel@tonic-gate 		isadmap->isadma_want--;
3297c478bd9Sstevel@tonic-gate 		isadma_sleep_cnt++;
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate static void
isadma_wakeup(isadma_devstate_t * isadmap)3347c478bd9Sstevel@tonic-gate isadma_wakeup(isadma_devstate_t *isadmap)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&isadmap->isadma_access_lock));
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	/*
3407c478bd9Sstevel@tonic-gate 	 * If somebody wants register access and the lock dip is not set
3417c478bd9Sstevel@tonic-gate 	 * signal the waiters.
3427c478bd9Sstevel@tonic-gate 	 */
3437c478bd9Sstevel@tonic-gate 	if (isadmap->isadma_want > 0 && isadmap->isadma_ldip == NULL) {
3447c478bd9Sstevel@tonic-gate 		cv_signal(&isadmap->isadma_access_cv);
3457c478bd9Sstevel@tonic-gate 		isadma_wakeup_cnt++;
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate  * Register access vectors
3527c478bd9Sstevel@tonic-gate  */
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3557c478bd9Sstevel@tonic-gate void
isadma_norep_get8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)3567c478bd9Sstevel@tonic-gate isadma_norep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3577c478bd9Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3627c478bd9Sstevel@tonic-gate void
isadma_norep_get16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)3637c478bd9Sstevel@tonic-gate isadma_norep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3647c478bd9Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3697c478bd9Sstevel@tonic-gate void
isadma_norep_get32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)3707c478bd9Sstevel@tonic-gate isadma_norep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3717c478bd9Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3767c478bd9Sstevel@tonic-gate void
isadma_norep_get64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)3777c478bd9Sstevel@tonic-gate isadma_norep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3787c478bd9Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3837c478bd9Sstevel@tonic-gate void
isadma_norep_put8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)3847c478bd9Sstevel@tonic-gate isadma_norep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3857c478bd9Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3907c478bd9Sstevel@tonic-gate void
isadma_norep_put16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)3917c478bd9Sstevel@tonic-gate isadma_norep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3927c478bd9Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3977c478bd9Sstevel@tonic-gate void
isadma_norep_put32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)3987c478bd9Sstevel@tonic-gate isadma_norep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3997c478bd9Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4047c478bd9Sstevel@tonic-gate void
isadma_norep_put64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)4057c478bd9Sstevel@tonic-gate isadma_norep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
4067c478bd9Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4117c478bd9Sstevel@tonic-gate uint8_t
isadma_get8(ddi_acc_impl_t * hdlp,uint8_t * addr)4127c478bd9Sstevel@tonic-gate isadma_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
4157c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
4167c478bd9Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
4177c478bd9Sstevel@tonic-gate 	uint8_t ret = 0xff;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
4207c478bd9Sstevel@tonic-gate #ifdef DEBUG
4217c478bd9Sstevel@tonic-gate 		isadma_punt++;
4227c478bd9Sstevel@tonic-gate #endif
4237c478bd9Sstevel@tonic-gate 		return (ddi_get8(phdl, addr));
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate #ifdef DEBUG
4267c478bd9Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
4277c478bd9Sstevel@tonic-gate #endif
4287c478bd9Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
4297c478bd9Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/* No 8 bit access to 16 bit address or count registers */
4327c478bd9Sstevel@tonic-gate 	if (IN_16BIT_SPACE(offset))
4337c478bd9Sstevel@tonic-gate 		goto exit;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	/* No 8 bit access to first/last flip-flop registers */
4367c478bd9Sstevel@tonic-gate 	if (IS_SEQREG(offset))
4377c478bd9Sstevel@tonic-gate 		goto exit;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	ret = ddi_get8(phdl, addr);	/* Pass to parent */
4407c478bd9Sstevel@tonic-gate exit:
4417c478bd9Sstevel@tonic-gate 	isadma_wakeup(isadmap);
4427c478bd9Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
4437c478bd9Sstevel@tonic-gate 	return (ret);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * Allow child devices to access this shared register set as if it were
4487c478bd9Sstevel@tonic-gate  * a real 16 bit register.  The ISA bridge defines the access to this
4497c478bd9Sstevel@tonic-gate  * 16 bit dma controller & count register by programming an 8 byte register.
4507c478bd9Sstevel@tonic-gate  */
4517c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4527c478bd9Sstevel@tonic-gate uint16_t
isadma_get16(ddi_acc_impl_t * hdlp,uint16_t * addr)4537c478bd9Sstevel@tonic-gate isadma_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
4567c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
4577c478bd9Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
4587c478bd9Sstevel@tonic-gate 	uint16_t ret = 0xffff;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
4617c478bd9Sstevel@tonic-gate #ifdef DEBUG
4627c478bd9Sstevel@tonic-gate 		isadma_punt++;
4637c478bd9Sstevel@tonic-gate #endif
4647c478bd9Sstevel@tonic-gate 		return (ddi_get16(phdl, addr));
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate #ifdef DEBUG
4677c478bd9Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
4687c478bd9Sstevel@tonic-gate #endif
4697c478bd9Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
4707c478bd9Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/* Only Allow access to the 16 bit count and address registers */
4737c478bd9Sstevel@tonic-gate 	if (!IN_16BIT_SPACE(offset))
4747c478bd9Sstevel@tonic-gate 		goto exit;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	/* Set the sequencing register to the low byte */
4777c478bd9Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0);
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	/* Read the low byte, then high byte */
4807c478bd9Sstevel@tonic-gate 	ret = ddi_get8(phdl, (uint8_t *)addr);
4817c478bd9Sstevel@tonic-gate 	ret = (ddi_get8(phdl, (uint8_t *)addr) << 8) | ret;
4827c478bd9Sstevel@tonic-gate exit:
4837c478bd9Sstevel@tonic-gate 	isadma_wakeup(isadmap);
4847c478bd9Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
4857c478bd9Sstevel@tonic-gate 	return (ret);
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4897c478bd9Sstevel@tonic-gate uint32_t
isadma_noget32(ddi_acc_impl_t * hdlp,uint32_t * addr)4907c478bd9Sstevel@tonic-gate isadma_noget32(ddi_acc_impl_t *hdlp, uint32_t *addr)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate 	return (UINT32_MAX);
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4967c478bd9Sstevel@tonic-gate uint64_t
isadma_noget64(ddi_acc_impl_t * hdlp,uint64_t * addr)4977c478bd9Sstevel@tonic-gate isadma_noget64(ddi_acc_impl_t *hdlp, uint64_t *addr)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate 	return (UINT64_MAX);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate  * Here's where we do our locking magic.  The dma all mask register is an 8
5047c478bd9Sstevel@tonic-gate  * bit register in the dma space, so we look for the access to the
5057c478bd9Sstevel@tonic-gate  * DMAC1_ALLMASK register.  When somebody is masking out the dma channels
5067c478bd9Sstevel@tonic-gate  * we lock down the dma engine from further PIO accesses.  When the driver
5077c478bd9Sstevel@tonic-gate  * calls back into this routine to clear the allmask register, we wakeup
5087c478bd9Sstevel@tonic-gate  * any blocked threads.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5117c478bd9Sstevel@tonic-gate void
isadma_put8(ddi_acc_impl_t * hdlp,uint8_t * addr,uint8_t value)5127c478bd9Sstevel@tonic-gate isadma_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
5157c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
5167c478bd9Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
5197c478bd9Sstevel@tonic-gate #ifdef DEBUG
5207c478bd9Sstevel@tonic-gate 		isadma_punt++;
5217c478bd9Sstevel@tonic-gate #endif
5227c478bd9Sstevel@tonic-gate 		ddi_put8(phdl, addr, value);
5237c478bd9Sstevel@tonic-gate 		return;
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate #ifdef DEBUG
5267c478bd9Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
5277c478bd9Sstevel@tonic-gate #endif
5287c478bd9Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if (isadmap->isadma_ldip == hdlp->ahi_common.ah_dip) { /* owned lock? */
5317c478bd9Sstevel@tonic-gate 		if (END_ISADMA(offset, value)) {
5327c478bd9Sstevel@tonic-gate 			isadmap->isadma_ldip = NULL;	/* reset lock owner */
5337c478bd9Sstevel@tonic-gate #ifdef DEBUG
5347c478bd9Sstevel@tonic-gate 			isadma_clearing_wdip++;
5357c478bd9Sstevel@tonic-gate #endif
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 	} else	{	/* we don't own the lock */
5387c478bd9Sstevel@tonic-gate 		/* wait until on-going dma completes */
5397c478bd9Sstevel@tonic-gate 		isadma_dmawait(isadmap);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		if (BEGIN_ISADMA(offset, value)) {
5427c478bd9Sstevel@tonic-gate 			isadmap->isadma_ldip = hdlp->ahi_common.ah_dip;
5437c478bd9Sstevel@tonic-gate #ifdef DEBUG
5447c478bd9Sstevel@tonic-gate 			isadma_setting_wdip++;
5457c478bd9Sstevel@tonic-gate #endif
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	/* No 8 bit access to 16 bit address or count registers */
5507c478bd9Sstevel@tonic-gate 	if (IN_16BIT_SPACE(offset))
5517c478bd9Sstevel@tonic-gate 		goto exit;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/* No 8 bit access to first/last flip-flop registers */
5547c478bd9Sstevel@tonic-gate 	if (IS_SEQREG(offset))
5557c478bd9Sstevel@tonic-gate 		goto exit;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	ddi_put8(phdl, addr, value);	/* Pass to parent */
5587c478bd9Sstevel@tonic-gate exit:
5597c478bd9Sstevel@tonic-gate 	isadma_wakeup(isadmap);
5607c478bd9Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate /*
5647c478bd9Sstevel@tonic-gate  * Allow child devices to access this shared register set as if it were
5657c478bd9Sstevel@tonic-gate  * a real 16 bit register.  The ISA bridge defines the access to this
5667c478bd9Sstevel@tonic-gate  * 16 bit dma controller & count register by programming an 8 byte register.
5677c478bd9Sstevel@tonic-gate  */
5687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5697c478bd9Sstevel@tonic-gate void
isadma_put16(ddi_acc_impl_t * hdlp,uint16_t * addr,uint16_t value)5707c478bd9Sstevel@tonic-gate isadma_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
5737c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
5747c478bd9Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
5777c478bd9Sstevel@tonic-gate #ifdef DEBUG
5787c478bd9Sstevel@tonic-gate 		isadma_punt++;
5797c478bd9Sstevel@tonic-gate #endif
5807c478bd9Sstevel@tonic-gate 		ddi_put16(phdl, addr, value);
5817c478bd9Sstevel@tonic-gate 		return;
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate #ifdef DEBUG
5847c478bd9Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
5857c478bd9Sstevel@tonic-gate #endif
5867c478bd9Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
5877c478bd9Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/* Only Allow access to the 16 bit count and address registers */
5907c478bd9Sstevel@tonic-gate 	if (!IN_16BIT_SPACE(offset))
5917c478bd9Sstevel@tonic-gate 		goto exit;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/* Set the sequencing register to the low byte */
5947c478bd9Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/* Write the low byte, then the high byte */
5977c478bd9Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)addr, value & 0xff);
5987c478bd9Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)addr, (value >> 8) & 0xff);
5997c478bd9Sstevel@tonic-gate exit:
6007c478bd9Sstevel@tonic-gate 	isadma_wakeup(isadmap);
6017c478bd9Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6057c478bd9Sstevel@tonic-gate void
isadma_noput32(ddi_acc_impl_t * hdlp,uint32_t * addr,uint32_t value)6067c478bd9Sstevel@tonic-gate isadma_noput32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6097c478bd9Sstevel@tonic-gate void
isadma_noput64(ddi_acc_impl_t * hdlp,uint64_t * addr,uint64_t value)6107c478bd9Sstevel@tonic-gate isadma_noput64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate #define	IS_SAME_REG(r1, r2) (((r1)->ebus_addr_hi == (r2)->ebus_addr_hi) && \
6137c478bd9Sstevel@tonic-gate 	((r1)->ebus_addr_low == (r2)->ebus_addr_low))
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  * The isadma_map routine determines if it's child is attempting to map a
6177c478bd9Sstevel@tonic-gate  * shared reg.  If it is, it installs it's own vectors and bus private pointer
6187c478bd9Sstevel@tonic-gate  * and stacks those ops that were already defined.
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate static int
isadma_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t off,off_t len,caddr_t * addrp)6217c478bd9Sstevel@tonic-gate isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
6227c478bd9Sstevel@tonic-gate 	off_t off, off_t len, caddr_t *addrp)
6237c478bd9Sstevel@tonic-gate {
6247c478bd9Sstevel@tonic-gate 	isadma_devstate_t *isadmap = ddi_get_soft_state(per_isadma_state,
6257c478bd9Sstevel@tonic-gate 	    ddi_get_instance(dip));
6267c478bd9Sstevel@tonic-gate 	dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent;
6277c478bd9Sstevel@tonic-gate 	ebus_regspec_t *child_regp, *regp;
6287c478bd9Sstevel@tonic-gate 	int32_t rnumber = mp->map_obj.rnumber;
6297c478bd9Sstevel@tonic-gate 	int32_t reglen;
6307c478bd9Sstevel@tonic-gate 	int ret;
6317c478bd9Sstevel@tonic-gate 	ddi_acc_impl_t *hp;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	/*
6347c478bd9Sstevel@tonic-gate 	 * Get child regspec since the mapping struct may not have it yet
6357c478bd9Sstevel@tonic-gate 	 */
636a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
6377c478bd9Sstevel@tonic-gate 	    "reg", (caddr_t)&regp, &reglen) != DDI_SUCCESS) {
6387c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	child_regp = regp + rnumber;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	DPRINTF(ISADMA_MAP_DEBUG, ("isadma_map: child regp %p "
644903a11ebSrh 	    "parent regp %p Child reg array %p\n", (void *)child_regp,
645903a11ebSrh 	    (void *)isadmap->isadma_regp, (void *)regp));
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	/* Figure out if we're mapping or unmapping */
6487c478bd9Sstevel@tonic-gate 	switch (mp->map_op) {
6497c478bd9Sstevel@tonic-gate 	case DDI_MO_MAP_LOCKED:
6507c478bd9Sstevel@tonic-gate 		/* Call up device tree to establish mapping */
6517c478bd9Sstevel@tonic-gate 		ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
6527c478bd9Sstevel@tonic-gate 		    (pdip, rdip, mp, off, len, addrp);
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 		if ((ret != DDI_SUCCESS) ||
6557c478bd9Sstevel@tonic-gate 		    !IS_SAME_REG(child_regp, isadmap->isadma_regp))
6567c478bd9Sstevel@tonic-gate 			break;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 		/* Post-process the mapping request. */
6597c478bd9Sstevel@tonic-gate 		hp = kmem_alloc(sizeof (ddi_acc_impl_t), KM_SLEEP);
6607c478bd9Sstevel@tonic-gate 		*hp = *(ddi_acc_impl_t *)mp->map_handlep;
6617c478bd9Sstevel@tonic-gate 		impl_acc_hdl_get((ddi_acc_handle_t)mp->map_handlep)->
6627c478bd9Sstevel@tonic-gate 		    ah_platform_private = hp;
6637c478bd9Sstevel@tonic-gate 		hp = (ddi_acc_impl_t *)mp->map_handlep;
6647c478bd9Sstevel@tonic-gate 		hp->ahi_common.ah_bus_private = isadmap;
6657c478bd9Sstevel@tonic-gate 		hp->ahi_get8 = isadma_get8;
6667c478bd9Sstevel@tonic-gate 		hp->ahi_get16 = isadma_get16;
6677c478bd9Sstevel@tonic-gate 		hp->ahi_get32 = isadma_noget32;
6687c478bd9Sstevel@tonic-gate 		hp->ahi_get64 = isadma_noget64;
6697c478bd9Sstevel@tonic-gate 		hp->ahi_put8 = isadma_put8;
6707c478bd9Sstevel@tonic-gate 		hp->ahi_put16 = isadma_put16;
6717c478bd9Sstevel@tonic-gate 		hp->ahi_put32 = isadma_noput32;
6727c478bd9Sstevel@tonic-gate 		hp->ahi_put64 = isadma_noput64;
6737c478bd9Sstevel@tonic-gate 		hp->ahi_rep_get8 = isadma_norep_get8;
6747c478bd9Sstevel@tonic-gate 		hp->ahi_rep_get16 = isadma_norep_get16;
6757c478bd9Sstevel@tonic-gate 		hp->ahi_rep_get32 = isadma_norep_get32;
6767c478bd9Sstevel@tonic-gate 		hp->ahi_rep_get64 = isadma_norep_get64;
6777c478bd9Sstevel@tonic-gate 		hp->ahi_rep_put8 = isadma_norep_put8;
6787c478bd9Sstevel@tonic-gate 		hp->ahi_rep_put16 = isadma_norep_put16;
6797c478bd9Sstevel@tonic-gate 		hp->ahi_rep_put32 = isadma_norep_put32;
6807c478bd9Sstevel@tonic-gate 		hp->ahi_rep_put64 = isadma_norep_put64;
6817c478bd9Sstevel@tonic-gate 		break;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	case DDI_MO_UNMAP:
6847c478bd9Sstevel@tonic-gate 		if (IS_SAME_REG(child_regp, isadmap->isadma_regp)) {
6857c478bd9Sstevel@tonic-gate 			hp = impl_acc_hdl_get(
6867c478bd9Sstevel@tonic-gate 			    (ddi_acc_handle_t)mp->map_handlep)->
6877c478bd9Sstevel@tonic-gate 			    ah_platform_private;
6887c478bd9Sstevel@tonic-gate 			*(ddi_acc_impl_t *)mp->map_handlep = *hp;
6897c478bd9Sstevel@tonic-gate 			kmem_free(hp, sizeof (ddi_acc_impl_t));
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 		/* Call up tree to tear down mapping */
6937c478bd9Sstevel@tonic-gate 		ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
694903a11ebSrh 		    (pdip, rdip, mp, off, len, addrp);
6957c478bd9Sstevel@tonic-gate 		break;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	default:
6987c478bd9Sstevel@tonic-gate 		ret = DDI_FAILURE;
6997c478bd9Sstevel@tonic-gate 		break;
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	kmem_free(regp, reglen);
7037c478bd9Sstevel@tonic-gate 	return (ret);
7047c478bd9Sstevel@tonic-gate }
705