xref: /onnv-gate/usr/src/uts/sun4u/io/isadma.c (revision 7656:2621e50fdf4a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57240Srh87107  * Common Development and Distribution License (the "License").
67240Srh87107  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
227240Srh87107  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/conf.h>
280Sstevel@tonic-gate #include <sys/sunddi.h>
290Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
300Sstevel@tonic-gate #include <sys/kmem.h>
310Sstevel@tonic-gate #include <sys/dma_i8237A.h>
320Sstevel@tonic-gate #include <sys/isadma.h>
330Sstevel@tonic-gate #include <sys/nexusdebug.h>
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /* Bitfield debugging definitions for this file */
360Sstevel@tonic-gate #define	ISADMA_MAP_DEBUG	0x1
370Sstevel@tonic-gate #define	ISADMA_REGACCESS_DEBUG	0x2
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * The isadam nexus serves two functions.  The first is to represent a
410Sstevel@tonic-gate  * a placeholder in the device tree for a shared dma controller register
420Sstevel@tonic-gate  * for the SuperIO floppy and parallel ports.
430Sstevel@tonic-gate  * The second function is to virtualize the shared dma controller register
440Sstevel@tonic-gate  * for those two drivers.  Rather than creating new ddi routines to manage
450Sstevel@tonic-gate  * the shared register, we will use the ddi register mapping functions to
460Sstevel@tonic-gate  * do this.  The two child devices will use ddi_regs_map_setup to map in
470Sstevel@tonic-gate  * their device registers.  The isadma nexus will have an aliased entry in
480Sstevel@tonic-gate  * it's own registers property for the shared dma controller register.  When
490Sstevel@tonic-gate  * the isadma detects the fact that it's children are trying to map the shared
500Sstevel@tonic-gate  * register, it will intercept this mapping and provide it's own register
510Sstevel@tonic-gate  * access routine to be used to access the register when the child devices
520Sstevel@tonic-gate  * use the ddi_{get,put} calls.
530Sstevel@tonic-gate  *
540Sstevel@tonic-gate  * Sigh, the 82C37 has a weird quirk (BUG?) where when DMA is active on the
550Sstevel@tonic-gate  * the bus, PIO's cannot happen.  If they do, they generate bus faults and
560Sstevel@tonic-gate  * cause the system to panic.  On PC's, the Intel processor has special
570Sstevel@tonic-gate  * req/grnt lines that prevent PIO's from occuring while DMA is in flight,
580Sstevel@tonic-gate  * unfortunately, hummingbird doesn't support this special req/grnt pair.
590Sstevel@tonic-gate  * I'm going to try and work around this by implementing a cv to stop PIO's
600Sstevel@tonic-gate  * from occuring while DMA is in flight.  When each child wants to do DMA,
610Sstevel@tonic-gate  * they need to mask out all other channels using the allmask register.
620Sstevel@tonic-gate  * This nexus keys on this access and locks down the hardware using a cv.
630Sstevel@tonic-gate  * Once the driver's interrupt handler is called it needs to clear
640Sstevel@tonic-gate  * the allmask register.  The nexus keys off of this an issues cv wakeups
650Sstevel@tonic-gate  * if necessary.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate  * Function prototypes for busops routines:
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate static int isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
710Sstevel@tonic-gate     off_t off, off_t len, caddr_t *addrp);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate  * function prototypes for dev ops routines:
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate static int isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
770Sstevel@tonic-gate static int isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  * general function prototypes:
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * bus ops and dev ops structures:
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate static struct bus_ops isadma_bus_ops = {
870Sstevel@tonic-gate 	BUSO_REV,
880Sstevel@tonic-gate 	isadma_map,
890Sstevel@tonic-gate 	NULL,
900Sstevel@tonic-gate 	NULL,
910Sstevel@tonic-gate 	NULL,
920Sstevel@tonic-gate 	i_ddi_map_fault,
930Sstevel@tonic-gate 	ddi_dma_map,
940Sstevel@tonic-gate 	ddi_dma_allochdl,
950Sstevel@tonic-gate 	ddi_dma_freehdl,
960Sstevel@tonic-gate 	ddi_dma_bindhdl,
970Sstevel@tonic-gate 	ddi_dma_unbindhdl,
980Sstevel@tonic-gate 	ddi_dma_flush,
990Sstevel@tonic-gate 	ddi_dma_win,
1000Sstevel@tonic-gate 	ddi_dma_mctl,
1010Sstevel@tonic-gate 	ddi_ctlops,
1020Sstevel@tonic-gate 	ddi_bus_prop_op,
1030Sstevel@tonic-gate 	0,			/* (*bus_get_eventcookie)();	*/
1040Sstevel@tonic-gate 	0,			/* (*bus_add_eventcall)();	*/
1050Sstevel@tonic-gate 	0,			/* (*bus_remove_eventcall)();	*/
1060Sstevel@tonic-gate 	0,			/* (*bus_post_event)();		*/
1070Sstevel@tonic-gate 	0,			/* (*bus_intr_control)();	*/
1080Sstevel@tonic-gate 	0,			/* (*bus_config)();		*/
1090Sstevel@tonic-gate 	0,			/* (*bus_unconfig)();		*/
1100Sstevel@tonic-gate 	0,			/* (*bus_fm_init)();		*/
1110Sstevel@tonic-gate 	0,			/* (*bus_fm_fini)();		*/
1120Sstevel@tonic-gate 	0,			/* (*bus_fm_access_enter)();	*/
1130Sstevel@tonic-gate 	0,			/* (*bus_fm_access_exit)();	*/
1140Sstevel@tonic-gate 	0,			/* (*bus_power)();		*/
1150Sstevel@tonic-gate 	i_ddi_intr_ops		/* (*bus_intr_op();		*/
1160Sstevel@tonic-gate };
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate static struct dev_ops isadma_ops = {
1190Sstevel@tonic-gate 	DEVO_REV,
1200Sstevel@tonic-gate 	0,
1210Sstevel@tonic-gate 	ddi_no_info,
1220Sstevel@tonic-gate 	nulldev,
1230Sstevel@tonic-gate 	0,
1240Sstevel@tonic-gate 	isadma_attach,
1250Sstevel@tonic-gate 	isadma_detach,
1260Sstevel@tonic-gate 	nodev,
1270Sstevel@tonic-gate 	(struct cb_ops *)0,
128*7656SSherry.Moore@Sun.COM 	&isadma_bus_ops,
129*7656SSherry.Moore@Sun.COM 	NULL,
130*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
1310Sstevel@tonic-gate };
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * module definitions:
1350Sstevel@tonic-gate  */
1360Sstevel@tonic-gate #include <sys/modctl.h>
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate static struct modldrv modldrv = {
1390Sstevel@tonic-gate 	&mod_driverops, 	/* Type of module.  This one is a driver */
1400Sstevel@tonic-gate 	"isadma nexus driver",	/* Name of module. */
1410Sstevel@tonic-gate 	&isadma_ops,		/* driver ops */
1420Sstevel@tonic-gate };
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate static struct modlinkage modlinkage = {
1450Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1460Sstevel@tonic-gate };
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate  * driver global data:
1500Sstevel@tonic-gate  */
1510Sstevel@tonic-gate static void *per_isadma_state;		/* per-isadma soft state pointer */
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /* Global debug data */
1540Sstevel@tonic-gate uint64_t isadma_sleep_cnt = 0;
1550Sstevel@tonic-gate uint64_t isadma_wakeup_cnt = 0;
1560Sstevel@tonic-gate #ifdef DEBUG
1570Sstevel@tonic-gate int64_t isadma_max_waiter = 0;
1580Sstevel@tonic-gate int64_t isadma_min_waiter = 0xffffll;
1590Sstevel@tonic-gate uint64_t isadma_punt = 0;
1600Sstevel@tonic-gate uint64_t isadma_setting_wdip = 0;
1610Sstevel@tonic-gate uint64_t isadma_clearing_wdip = 0;
1620Sstevel@tonic-gate #endif
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate int
_init(void)1650Sstevel@tonic-gate _init(void)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	int e;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/*
1700Sstevel@tonic-gate 	 * Initialize per-isadma soft state pointer.
1710Sstevel@tonic-gate 	 */
1720Sstevel@tonic-gate 	e = ddi_soft_state_init(&per_isadma_state,
1730Sstevel@tonic-gate 	    sizeof (isadma_devstate_t), 1);
1740Sstevel@tonic-gate 	if (e != 0)
1750Sstevel@tonic-gate 		return (e);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/*
1780Sstevel@tonic-gate 	 * Install the module.
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 	e = mod_install(&modlinkage);
1810Sstevel@tonic-gate 	if (e != 0)
1820Sstevel@tonic-gate 		ddi_soft_state_fini(&per_isadma_state);
1830Sstevel@tonic-gate 	return (e);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate int
_fini(void)1870Sstevel@tonic-gate _fini(void)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	int e;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	/*
1920Sstevel@tonic-gate 	 * Remove the module.
1930Sstevel@tonic-gate 	 */
1940Sstevel@tonic-gate 	e = mod_remove(&modlinkage);
1950Sstevel@tonic-gate 	if (e != 0)
1960Sstevel@tonic-gate 		return (e);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	/*
1990Sstevel@tonic-gate 	 * Free the soft state info.
2000Sstevel@tonic-gate 	 */
2010Sstevel@tonic-gate 	ddi_soft_state_fini(&per_isadma_state);
2020Sstevel@tonic-gate 	return (e);
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2060Sstevel@tonic-gate _info(struct modinfo *modinfop)
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate /* device driver entry points */
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate  * attach entry point:
2150Sstevel@tonic-gate  */
2160Sstevel@tonic-gate static int
isadma_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2170Sstevel@tonic-gate isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	isadma_devstate_t *isadmap;	/* per isadma state pointer */
2200Sstevel@tonic-gate 	int32_t instance;
2210Sstevel@tonic-gate 	int ret = DDI_SUCCESS;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate #ifdef DEBUG
2240Sstevel@tonic-gate 	debug_print_level = 0;
2250Sstevel@tonic-gate 	debug_info = 1;
2260Sstevel@tonic-gate #endif
2270Sstevel@tonic-gate 	switch (cmd) {
2280Sstevel@tonic-gate 	case DDI_ATTACH: {
2290Sstevel@tonic-gate 		/*
2300Sstevel@tonic-gate 		 * Allocate soft state for this instance.
2310Sstevel@tonic-gate 		 */
2320Sstevel@tonic-gate 		instance = ddi_get_instance(dip);
2330Sstevel@tonic-gate 		if (ddi_soft_state_zalloc(per_isadma_state, instance)
2347240Srh87107 		    != DDI_SUCCESS) {
2350Sstevel@tonic-gate 			ret = DDI_FAILURE;
2360Sstevel@tonic-gate 			goto exit;
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 		isadmap = ddi_get_soft_state(per_isadma_state, instance);
2390Sstevel@tonic-gate 		isadmap->isadma_dip = dip;
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 		/* Cache our register property */
242506Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2430Sstevel@tonic-gate 		    "reg", (caddr_t)&isadmap->isadma_regp,
2440Sstevel@tonic-gate 		    &isadmap->isadma_reglen) != DDI_SUCCESS) {
2450Sstevel@tonic-gate 			ret = DDI_FAILURE;
2460Sstevel@tonic-gate 			goto fail_get_prop;
2470Sstevel@tonic-gate 		}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 		/* Initialize our mutex */
2500Sstevel@tonic-gate 		mutex_init(&isadmap->isadma_access_lock, NULL, MUTEX_DRIVER,
2510Sstevel@tonic-gate 		    NULL);
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		/* Initialize our condition variable */
2540Sstevel@tonic-gate 		cv_init(&isadmap->isadma_access_cv, NULL, CV_DRIVER, NULL);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 		ddi_report_dev(dip);
2570Sstevel@tonic-gate 		goto exit;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 	case DDI_RESUME:
2610Sstevel@tonic-gate 	default:
2620Sstevel@tonic-gate 		goto exit;
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate fail_get_prop:
2660Sstevel@tonic-gate 	ddi_soft_state_free(per_isadma_state, instance);
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate exit:
2690Sstevel@tonic-gate 	return (ret);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate  * detach entry point:
2740Sstevel@tonic-gate  */
2750Sstevel@tonic-gate static int
isadma_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2760Sstevel@tonic-gate isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
2790Sstevel@tonic-gate 	isadma_devstate_t *isadmap =
2807240Srh87107 	    ddi_get_soft_state(per_isadma_state, instance);
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	switch (cmd) {
2830Sstevel@tonic-gate 	case DDI_DETACH:
2840Sstevel@tonic-gate 		cv_destroy(&isadmap->isadma_access_cv);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 		mutex_destroy(&isadmap->isadma_access_lock);
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 		/* free the cached register property */
2890Sstevel@tonic-gate 		kmem_free(isadmap->isadma_regp, isadmap->isadma_reglen);
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 		ddi_soft_state_free(per_isadma_state, instance);
2920Sstevel@tonic-gate 		return (DDI_SUCCESS);
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	case DDI_SUSPEND:
2950Sstevel@tonic-gate 		return (DDI_SUCCESS);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	return (DDI_FAILURE);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate #ifdef DEBUG
3020Sstevel@tonic-gate static void
isadma_check_waiters(isadma_devstate_t * isadmap)3030Sstevel@tonic-gate isadma_check_waiters(isadma_devstate_t *isadmap)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate 	if (isadmap->isadma_want > isadma_max_waiter)
3060Sstevel@tonic-gate 		isadma_max_waiter = isadmap->isadma_want;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (isadmap->isadma_want < isadma_min_waiter)
3090Sstevel@tonic-gate 		isadma_min_waiter = isadmap->isadma_want;
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate #endif
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate static void
isadma_dmawait(isadma_devstate_t * isadmap)3140Sstevel@tonic-gate isadma_dmawait(isadma_devstate_t *isadmap)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	ASSERT(mutex_owned(&isadmap->isadma_access_lock));
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	/* Wait loop, if the locking dip is set, we wait. */
3200Sstevel@tonic-gate 	while (isadmap->isadma_ldip != NULL) {
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 		isadmap->isadma_want++;
3230Sstevel@tonic-gate 		cv_wait(&isadmap->isadma_access_cv,
3240Sstevel@tonic-gate 		    &isadmap->isadma_access_lock);
3250Sstevel@tonic-gate 		isadmap->isadma_want--;
3260Sstevel@tonic-gate 		isadma_sleep_cnt++;
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate static void
isadma_wakeup(isadma_devstate_t * isadmap)3310Sstevel@tonic-gate isadma_wakeup(isadma_devstate_t *isadmap)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	ASSERT(mutex_owned(&isadmap->isadma_access_lock));
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	/*
3370Sstevel@tonic-gate 	 * If somebody wants register access and the lock dip is not set
3380Sstevel@tonic-gate 	 * signal the waiters.
3390Sstevel@tonic-gate 	 */
3400Sstevel@tonic-gate 	if (isadmap->isadma_want > 0 && isadmap->isadma_ldip == NULL) {
3410Sstevel@tonic-gate 		cv_signal(&isadmap->isadma_access_cv);
3420Sstevel@tonic-gate 		isadma_wakeup_cnt++;
3430Sstevel@tonic-gate 	}
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate  * Register access vectors
3490Sstevel@tonic-gate  */
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate /*ARGSUSED*/
3520Sstevel@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)3530Sstevel@tonic-gate isadma_norep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3540Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate /*ARGSUSED*/
3590Sstevel@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)3600Sstevel@tonic-gate isadma_norep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3610Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate /*ARGSUSED*/
3660Sstevel@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)3670Sstevel@tonic-gate isadma_norep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3680Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate /*ARGSUSED*/
3730Sstevel@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)3740Sstevel@tonic-gate isadma_norep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3750Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate /*ARGSUSED*/
3800Sstevel@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)3810Sstevel@tonic-gate isadma_norep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3820Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate /*ARGSUSED*/
3870Sstevel@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)3880Sstevel@tonic-gate isadma_norep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3890Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate /*ARGSUSED*/
3940Sstevel@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)3950Sstevel@tonic-gate isadma_norep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3960Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
3970Sstevel@tonic-gate {
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate /*ARGSUSED*/
4010Sstevel@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)4020Sstevel@tonic-gate isadma_norep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
4030Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*ARGSUSED*/
4080Sstevel@tonic-gate uint8_t
isadma_get8(ddi_acc_impl_t * hdlp,uint8_t * addr)4090Sstevel@tonic-gate isadma_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
4120Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
4130Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
4140Sstevel@tonic-gate 	uint8_t ret = 0xff;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
4170Sstevel@tonic-gate #ifdef DEBUG
4180Sstevel@tonic-gate 		isadma_punt++;
4190Sstevel@tonic-gate #endif
4200Sstevel@tonic-gate 		return (ddi_get8(phdl, addr));
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate #ifdef DEBUG
4230Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
4240Sstevel@tonic-gate #endif
4250Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
4260Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	/* No 8 bit access to 16 bit address or count registers */
4290Sstevel@tonic-gate 	if (IN_16BIT_SPACE(offset))
4300Sstevel@tonic-gate 		goto exit;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/* No 8 bit access to first/last flip-flop registers */
4330Sstevel@tonic-gate 	if (IS_SEQREG(offset))
4340Sstevel@tonic-gate 		goto exit;
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	ret = ddi_get8(phdl, addr);	/* Pass to parent */
4370Sstevel@tonic-gate exit:
4380Sstevel@tonic-gate 	isadma_wakeup(isadmap);
4390Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
4400Sstevel@tonic-gate 	return (ret);
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate /*
4440Sstevel@tonic-gate  * Allow child devices to access this shared register set as if it were
4450Sstevel@tonic-gate  * a real 16 bit register.  The ISA bridge defines the access to this
4460Sstevel@tonic-gate  * 16 bit dma controller & count register by programming an 8 byte register.
4470Sstevel@tonic-gate  */
4480Sstevel@tonic-gate /*ARGSUSED*/
4490Sstevel@tonic-gate uint16_t
isadma_get16(ddi_acc_impl_t * hdlp,uint16_t * addr)4500Sstevel@tonic-gate isadma_get16(ddi_acc_impl_t *hdlp, uint16_t *addr)
4510Sstevel@tonic-gate {
4520Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
4530Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
4540Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
4550Sstevel@tonic-gate 	uint16_t ret = 0xffff;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
4580Sstevel@tonic-gate #ifdef DEBUG
4590Sstevel@tonic-gate 		isadma_punt++;
4600Sstevel@tonic-gate #endif
4610Sstevel@tonic-gate 		return (ddi_get16(phdl, addr));
4620Sstevel@tonic-gate 	}
4630Sstevel@tonic-gate #ifdef DEBUG
4640Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
4650Sstevel@tonic-gate #endif
4660Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
4670Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	/* Only Allow access to the 16 bit count and address registers */
4700Sstevel@tonic-gate 	if (!IN_16BIT_SPACE(offset))
4710Sstevel@tonic-gate 		goto exit;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	/* Set the sequencing register to the low byte */
4740Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0);
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	/* Read the low byte, then high byte */
4770Sstevel@tonic-gate 	ret = ddi_get8(phdl, (uint8_t *)addr);
4780Sstevel@tonic-gate 	ret = (ddi_get8(phdl, (uint8_t *)addr) << 8) | ret;
4790Sstevel@tonic-gate exit:
4800Sstevel@tonic-gate 	isadma_wakeup(isadmap);
4810Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
4820Sstevel@tonic-gate 	return (ret);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate /*ARGSUSED*/
4860Sstevel@tonic-gate uint32_t
isadma_noget32(ddi_acc_impl_t * hdlp,uint32_t * addr)4870Sstevel@tonic-gate isadma_noget32(ddi_acc_impl_t *hdlp, uint32_t *addr)
4880Sstevel@tonic-gate {
4890Sstevel@tonic-gate 	return (UINT32_MAX);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate /*ARGSUSED*/
4930Sstevel@tonic-gate uint64_t
isadma_noget64(ddi_acc_impl_t * hdlp,uint64_t * addr)4940Sstevel@tonic-gate isadma_noget64(ddi_acc_impl_t *hdlp, uint64_t *addr)
4950Sstevel@tonic-gate {
4960Sstevel@tonic-gate 	return (UINT64_MAX);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate /*
5000Sstevel@tonic-gate  * Here's where we do our locking magic.  The dma all mask register is an 8
5010Sstevel@tonic-gate  * bit register in the dma space, so we look for the access to the
5020Sstevel@tonic-gate  * DMAC1_ALLMASK register.  When somebody is masking out the dma channels
5030Sstevel@tonic-gate  * we lock down the dma engine from further PIO accesses.  When the driver
5040Sstevel@tonic-gate  * calls back into this routine to clear the allmask register, we wakeup
5050Sstevel@tonic-gate  * any blocked threads.
5060Sstevel@tonic-gate  */
5070Sstevel@tonic-gate /*ARGSUSED*/
5080Sstevel@tonic-gate void
isadma_put8(ddi_acc_impl_t * hdlp,uint8_t * addr,uint8_t value)5090Sstevel@tonic-gate isadma_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
5100Sstevel@tonic-gate {
5110Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
5120Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
5130Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
5160Sstevel@tonic-gate #ifdef DEBUG
5170Sstevel@tonic-gate 		isadma_punt++;
5180Sstevel@tonic-gate #endif
5190Sstevel@tonic-gate 		ddi_put8(phdl, addr, value);
5200Sstevel@tonic-gate 		return;
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate #ifdef DEBUG
5230Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
5240Sstevel@tonic-gate #endif
5250Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	if (isadmap->isadma_ldip == hdlp->ahi_common.ah_dip) { /* owned lock? */
5280Sstevel@tonic-gate 		if (END_ISADMA(offset, value)) {
5290Sstevel@tonic-gate 			isadmap->isadma_ldip = NULL;	/* reset lock owner */
5300Sstevel@tonic-gate #ifdef DEBUG
5310Sstevel@tonic-gate 			isadma_clearing_wdip++;
5320Sstevel@tonic-gate #endif
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 	} else	{	/* we don't own the lock */
5350Sstevel@tonic-gate 		/* wait until on-going dma completes */
5360Sstevel@tonic-gate 		isadma_dmawait(isadmap);
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 		if (BEGIN_ISADMA(offset, value)) {
5390Sstevel@tonic-gate 			isadmap->isadma_ldip = hdlp->ahi_common.ah_dip;
5400Sstevel@tonic-gate #ifdef DEBUG
5410Sstevel@tonic-gate 			isadma_setting_wdip++;
5420Sstevel@tonic-gate #endif
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	/* No 8 bit access to 16 bit address or count registers */
5470Sstevel@tonic-gate 	if (IN_16BIT_SPACE(offset))
5480Sstevel@tonic-gate 		goto exit;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	/* No 8 bit access to first/last flip-flop registers */
5510Sstevel@tonic-gate 	if (IS_SEQREG(offset))
5520Sstevel@tonic-gate 		goto exit;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	ddi_put8(phdl, addr, value);	/* Pass to parent */
5550Sstevel@tonic-gate exit:
5560Sstevel@tonic-gate 	isadma_wakeup(isadmap);
5570Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate /*
5610Sstevel@tonic-gate  * Allow child devices to access this shared register set as if it were
5620Sstevel@tonic-gate  * a real 16 bit register.  The ISA bridge defines the access to this
5630Sstevel@tonic-gate  * 16 bit dma controller & count register by programming an 8 byte register.
5640Sstevel@tonic-gate  */
5650Sstevel@tonic-gate /*ARGSUSED*/
5660Sstevel@tonic-gate void
isadma_put16(ddi_acc_impl_t * hdlp,uint16_t * addr,uint16_t value)5670Sstevel@tonic-gate isadma_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate 	ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private;
5700Sstevel@tonic-gate 	isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private;
5710Sstevel@tonic-gate 	off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	if (IN_CHILD_SPACE(offset)) {	/* Pass to parent */
5740Sstevel@tonic-gate #ifdef DEBUG
5750Sstevel@tonic-gate 		isadma_punt++;
5760Sstevel@tonic-gate #endif
5770Sstevel@tonic-gate 		ddi_put16(phdl, addr, value);
5780Sstevel@tonic-gate 		return;
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate #ifdef DEBUG
5810Sstevel@tonic-gate 	isadma_check_waiters(isadmap);
5820Sstevel@tonic-gate #endif
5830Sstevel@tonic-gate 	mutex_enter(&isadmap->isadma_access_lock);
5840Sstevel@tonic-gate 	isadma_dmawait(isadmap);	/* wait until on-going dma completes */
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	/* Only Allow access to the 16 bit count and address registers */
5870Sstevel@tonic-gate 	if (!IN_16BIT_SPACE(offset))
5880Sstevel@tonic-gate 		goto exit;
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	/* Set the sequencing register to the low byte */
5910Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0);
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	/* Write the low byte, then the high byte */
5940Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)addr, value & 0xff);
5950Sstevel@tonic-gate 	ddi_put8(phdl, (uint8_t *)addr, (value >> 8) & 0xff);
5960Sstevel@tonic-gate exit:
5970Sstevel@tonic-gate 	isadma_wakeup(isadmap);
5980Sstevel@tonic-gate 	mutex_exit(&isadmap->isadma_access_lock);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate /*ARGSUSED*/
6020Sstevel@tonic-gate void
isadma_noput32(ddi_acc_impl_t * hdlp,uint32_t * addr,uint32_t value)6030Sstevel@tonic-gate isadma_noput32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {}
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate /*ARGSUSED*/
6060Sstevel@tonic-gate void
isadma_noput64(ddi_acc_impl_t * hdlp,uint64_t * addr,uint64_t value)6070Sstevel@tonic-gate isadma_noput64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate #define	IS_SAME_REG(r1, r2) (((r1)->ebus_addr_hi == (r2)->ebus_addr_hi) && \
6100Sstevel@tonic-gate 	((r1)->ebus_addr_low == (r2)->ebus_addr_low))
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate /*
6130Sstevel@tonic-gate  * The isadma_map routine determines if it's child is attempting to map a
6140Sstevel@tonic-gate  * shared reg.  If it is, it installs it's own vectors and bus private pointer
6150Sstevel@tonic-gate  * and stacks those ops that were already defined.
6160Sstevel@tonic-gate  */
6170Sstevel@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)6180Sstevel@tonic-gate isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
6190Sstevel@tonic-gate 	off_t off, off_t len, caddr_t *addrp)
6200Sstevel@tonic-gate {
6210Sstevel@tonic-gate 	isadma_devstate_t *isadmap = ddi_get_soft_state(per_isadma_state,
6220Sstevel@tonic-gate 	    ddi_get_instance(dip));
6230Sstevel@tonic-gate 	dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent;
6240Sstevel@tonic-gate 	ebus_regspec_t *child_regp, *regp;
6250Sstevel@tonic-gate 	int32_t rnumber = mp->map_obj.rnumber;
6260Sstevel@tonic-gate 	int32_t reglen;
6270Sstevel@tonic-gate 	int ret;
6280Sstevel@tonic-gate 	ddi_acc_impl_t *hp;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	/*
6310Sstevel@tonic-gate 	 * Get child regspec since the mapping struct may not have it yet
6320Sstevel@tonic-gate 	 */
633506Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
6340Sstevel@tonic-gate 	    "reg", (caddr_t)&regp, &reglen) != DDI_SUCCESS) {
6350Sstevel@tonic-gate 		return (DDI_FAILURE);
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	child_regp = regp + rnumber;
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	DPRINTF(ISADMA_MAP_DEBUG, ("isadma_map: child regp %p "
6417240Srh87107 	    "parent regp %p Child reg array %p\n", (void *)child_regp,
6427240Srh87107 	    (void *)isadmap->isadma_regp, (void *)regp));
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 	/* Figure out if we're mapping or unmapping */
6450Sstevel@tonic-gate 	switch (mp->map_op) {
6460Sstevel@tonic-gate 	case DDI_MO_MAP_LOCKED:
6470Sstevel@tonic-gate 		/* Call up device tree to establish mapping */
6480Sstevel@tonic-gate 		ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
6490Sstevel@tonic-gate 		    (pdip, rdip, mp, off, len, addrp);
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 		if ((ret != DDI_SUCCESS) ||
6520Sstevel@tonic-gate 		    !IS_SAME_REG(child_regp, isadmap->isadma_regp))
6530Sstevel@tonic-gate 			break;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 		/* Post-process the mapping request. */
6560Sstevel@tonic-gate 		hp = kmem_alloc(sizeof (ddi_acc_impl_t), KM_SLEEP);
6570Sstevel@tonic-gate 		*hp = *(ddi_acc_impl_t *)mp->map_handlep;
6580Sstevel@tonic-gate 		impl_acc_hdl_get((ddi_acc_handle_t)mp->map_handlep)->
6590Sstevel@tonic-gate 		    ah_platform_private = hp;
6600Sstevel@tonic-gate 		hp = (ddi_acc_impl_t *)mp->map_handlep;
6610Sstevel@tonic-gate 		hp->ahi_common.ah_bus_private = isadmap;
6620Sstevel@tonic-gate 		hp->ahi_get8 = isadma_get8;
6630Sstevel@tonic-gate 		hp->ahi_get16 = isadma_get16;
6640Sstevel@tonic-gate 		hp->ahi_get32 = isadma_noget32;
6650Sstevel@tonic-gate 		hp->ahi_get64 = isadma_noget64;
6660Sstevel@tonic-gate 		hp->ahi_put8 = isadma_put8;
6670Sstevel@tonic-gate 		hp->ahi_put16 = isadma_put16;
6680Sstevel@tonic-gate 		hp->ahi_put32 = isadma_noput32;
6690Sstevel@tonic-gate 		hp->ahi_put64 = isadma_noput64;
6700Sstevel@tonic-gate 		hp->ahi_rep_get8 = isadma_norep_get8;
6710Sstevel@tonic-gate 		hp->ahi_rep_get16 = isadma_norep_get16;
6720Sstevel@tonic-gate 		hp->ahi_rep_get32 = isadma_norep_get32;
6730Sstevel@tonic-gate 		hp->ahi_rep_get64 = isadma_norep_get64;
6740Sstevel@tonic-gate 		hp->ahi_rep_put8 = isadma_norep_put8;
6750Sstevel@tonic-gate 		hp->ahi_rep_put16 = isadma_norep_put16;
6760Sstevel@tonic-gate 		hp->ahi_rep_put32 = isadma_norep_put32;
6770Sstevel@tonic-gate 		hp->ahi_rep_put64 = isadma_norep_put64;
6780Sstevel@tonic-gate 		break;
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	case DDI_MO_UNMAP:
6810Sstevel@tonic-gate 		if (IS_SAME_REG(child_regp, isadmap->isadma_regp)) {
6820Sstevel@tonic-gate 			hp = impl_acc_hdl_get(
6830Sstevel@tonic-gate 			    (ddi_acc_handle_t)mp->map_handlep)->
6840Sstevel@tonic-gate 			    ah_platform_private;
6850Sstevel@tonic-gate 			*(ddi_acc_impl_t *)mp->map_handlep = *hp;
6860Sstevel@tonic-gate 			kmem_free(hp, sizeof (ddi_acc_impl_t));
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 		/* Call up tree to tear down mapping */
6900Sstevel@tonic-gate 		ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
6917240Srh87107 		    (pdip, rdip, mp, off, len, addrp);
6920Sstevel@tonic-gate 		break;
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	default:
6950Sstevel@tonic-gate 		ret = DDI_FAILURE;
6960Sstevel@tonic-gate 		break;
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	kmem_free(regp, reglen);
7000Sstevel@tonic-gate 	return (ret);
7010Sstevel@tonic-gate }
702