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