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)®p, ®len) != 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