1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/dma_i8237A.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/isadma.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/nexusdebug.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* Bitfield debugging definitions for this file */ 38*7c478bd9Sstevel@tonic-gate #define ISADMA_MAP_DEBUG 0x1 39*7c478bd9Sstevel@tonic-gate #define ISADMA_REGACCESS_DEBUG 0x2 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * The isadam nexus serves two functions. The first is to represent a 43*7c478bd9Sstevel@tonic-gate * a placeholder in the device tree for a shared dma controller register 44*7c478bd9Sstevel@tonic-gate * for the SuperIO floppy and parallel ports. 45*7c478bd9Sstevel@tonic-gate * The second function is to virtualize the shared dma controller register 46*7c478bd9Sstevel@tonic-gate * for those two drivers. Rather than creating new ddi routines to manage 47*7c478bd9Sstevel@tonic-gate * the shared register, we will use the ddi register mapping functions to 48*7c478bd9Sstevel@tonic-gate * do this. The two child devices will use ddi_regs_map_setup to map in 49*7c478bd9Sstevel@tonic-gate * their device registers. The isadma nexus will have an aliased entry in 50*7c478bd9Sstevel@tonic-gate * it's own registers property for the shared dma controller register. When 51*7c478bd9Sstevel@tonic-gate * the isadma detects the fact that it's children are trying to map the shared 52*7c478bd9Sstevel@tonic-gate * register, it will intercept this mapping and provide it's own register 53*7c478bd9Sstevel@tonic-gate * access routine to be used to access the register when the child devices 54*7c478bd9Sstevel@tonic-gate * use the ddi_{get,put} calls. 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * Sigh, the 82C37 has a weird quirk (BUG?) where when DMA is active on the 57*7c478bd9Sstevel@tonic-gate * the bus, PIO's cannot happen. If they do, they generate bus faults and 58*7c478bd9Sstevel@tonic-gate * cause the system to panic. On PC's, the Intel processor has special 59*7c478bd9Sstevel@tonic-gate * req/grnt lines that prevent PIO's from occuring while DMA is in flight, 60*7c478bd9Sstevel@tonic-gate * unfortunately, hummingbird doesn't support this special req/grnt pair. 61*7c478bd9Sstevel@tonic-gate * I'm going to try and work around this by implementing a cv to stop PIO's 62*7c478bd9Sstevel@tonic-gate * from occuring while DMA is in flight. When each child wants to do DMA, 63*7c478bd9Sstevel@tonic-gate * they need to mask out all other channels using the allmask register. 64*7c478bd9Sstevel@tonic-gate * This nexus keys on this access and locks down the hardware using a cv. 65*7c478bd9Sstevel@tonic-gate * Once the driver's interrupt handler is called it needs to clear 66*7c478bd9Sstevel@tonic-gate * the allmask register. The nexus keys off of this an issues cv wakeups 67*7c478bd9Sstevel@tonic-gate * if necessary. 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * Function prototypes for busops routines: 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate static int isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 73*7c478bd9Sstevel@tonic-gate off_t off, off_t len, caddr_t *addrp); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * function prototypes for dev ops routines: 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate static int isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 79*7c478bd9Sstevel@tonic-gate static int isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * general function prototypes: 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * bus ops and dev ops structures: 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate static struct bus_ops isadma_bus_ops = { 89*7c478bd9Sstevel@tonic-gate BUSO_REV, 90*7c478bd9Sstevel@tonic-gate isadma_map, 91*7c478bd9Sstevel@tonic-gate NULL, 92*7c478bd9Sstevel@tonic-gate NULL, 93*7c478bd9Sstevel@tonic-gate NULL, 94*7c478bd9Sstevel@tonic-gate i_ddi_map_fault, 95*7c478bd9Sstevel@tonic-gate ddi_dma_map, 96*7c478bd9Sstevel@tonic-gate ddi_dma_allochdl, 97*7c478bd9Sstevel@tonic-gate ddi_dma_freehdl, 98*7c478bd9Sstevel@tonic-gate ddi_dma_bindhdl, 99*7c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl, 100*7c478bd9Sstevel@tonic-gate ddi_dma_flush, 101*7c478bd9Sstevel@tonic-gate ddi_dma_win, 102*7c478bd9Sstevel@tonic-gate ddi_dma_mctl, 103*7c478bd9Sstevel@tonic-gate ddi_ctlops, 104*7c478bd9Sstevel@tonic-gate ddi_bus_prop_op, 105*7c478bd9Sstevel@tonic-gate 0, /* (*bus_get_eventcookie)(); */ 106*7c478bd9Sstevel@tonic-gate 0, /* (*bus_add_eventcall)(); */ 107*7c478bd9Sstevel@tonic-gate 0, /* (*bus_remove_eventcall)(); */ 108*7c478bd9Sstevel@tonic-gate 0, /* (*bus_post_event)(); */ 109*7c478bd9Sstevel@tonic-gate 0, /* (*bus_intr_control)(); */ 110*7c478bd9Sstevel@tonic-gate 0, /* (*bus_config)(); */ 111*7c478bd9Sstevel@tonic-gate 0, /* (*bus_unconfig)(); */ 112*7c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_init)(); */ 113*7c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_fini)(); */ 114*7c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_access_enter)(); */ 115*7c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_access_exit)(); */ 116*7c478bd9Sstevel@tonic-gate 0, /* (*bus_power)(); */ 117*7c478bd9Sstevel@tonic-gate i_ddi_intr_ops /* (*bus_intr_op(); */ 118*7c478bd9Sstevel@tonic-gate }; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate static struct dev_ops isadma_ops = { 121*7c478bd9Sstevel@tonic-gate DEVO_REV, 122*7c478bd9Sstevel@tonic-gate 0, 123*7c478bd9Sstevel@tonic-gate ddi_no_info, 124*7c478bd9Sstevel@tonic-gate nulldev, 125*7c478bd9Sstevel@tonic-gate 0, 126*7c478bd9Sstevel@tonic-gate isadma_attach, 127*7c478bd9Sstevel@tonic-gate isadma_detach, 128*7c478bd9Sstevel@tonic-gate nodev, 129*7c478bd9Sstevel@tonic-gate (struct cb_ops *)0, 130*7c478bd9Sstevel@tonic-gate &isadma_bus_ops 131*7c478bd9Sstevel@tonic-gate }; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * module definitions: 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 139*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a driver */ 140*7c478bd9Sstevel@tonic-gate "isadma nexus driver", /* Name of module. */ 141*7c478bd9Sstevel@tonic-gate &isadma_ops, /* driver ops */ 142*7c478bd9Sstevel@tonic-gate }; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 145*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 146*7c478bd9Sstevel@tonic-gate }; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * driver global data: 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate static void *per_isadma_state; /* per-isadma soft state pointer */ 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate /* Global debug data */ 154*7c478bd9Sstevel@tonic-gate uint64_t isadma_sleep_cnt = 0; 155*7c478bd9Sstevel@tonic-gate uint64_t isadma_wakeup_cnt = 0; 156*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 157*7c478bd9Sstevel@tonic-gate int64_t isadma_max_waiter = 0; 158*7c478bd9Sstevel@tonic-gate int64_t isadma_min_waiter = 0xffffll; 159*7c478bd9Sstevel@tonic-gate uint64_t isadma_punt = 0; 160*7c478bd9Sstevel@tonic-gate uint64_t isadma_setting_wdip = 0; 161*7c478bd9Sstevel@tonic-gate uint64_t isadma_clearing_wdip = 0; 162*7c478bd9Sstevel@tonic-gate #endif 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate int 165*7c478bd9Sstevel@tonic-gate _init(void) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate int e; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * Initialize per-isadma soft state pointer. 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate e = ddi_soft_state_init(&per_isadma_state, 173*7c478bd9Sstevel@tonic-gate sizeof (isadma_devstate_t), 1); 174*7c478bd9Sstevel@tonic-gate if (e != 0) 175*7c478bd9Sstevel@tonic-gate return (e); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate /* 178*7c478bd9Sstevel@tonic-gate * Install the module. 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate e = mod_install(&modlinkage); 181*7c478bd9Sstevel@tonic-gate if (e != 0) 182*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&per_isadma_state); 183*7c478bd9Sstevel@tonic-gate return (e); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate int 187*7c478bd9Sstevel@tonic-gate _fini(void) 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate int e; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * Remove the module. 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate e = mod_remove(&modlinkage); 195*7c478bd9Sstevel@tonic-gate if (e != 0) 196*7c478bd9Sstevel@tonic-gate return (e); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * Free the soft state info. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&per_isadma_state); 202*7c478bd9Sstevel@tonic-gate return (e); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate int 206*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 207*7c478bd9Sstevel@tonic-gate { 208*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* device driver entry points */ 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * attach entry point: 215*7c478bd9Sstevel@tonic-gate */ 216*7c478bd9Sstevel@tonic-gate static int 217*7c478bd9Sstevel@tonic-gate isadma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap; /* per isadma state pointer */ 220*7c478bd9Sstevel@tonic-gate int32_t instance; 221*7c478bd9Sstevel@tonic-gate int ret = DDI_SUCCESS; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 224*7c478bd9Sstevel@tonic-gate debug_print_level = 0; 225*7c478bd9Sstevel@tonic-gate debug_info = 1; 226*7c478bd9Sstevel@tonic-gate #endif 227*7c478bd9Sstevel@tonic-gate switch (cmd) { 228*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: { 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * Allocate soft state for this instance. 231*7c478bd9Sstevel@tonic-gate */ 232*7c478bd9Sstevel@tonic-gate instance = ddi_get_instance(dip); 233*7c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(per_isadma_state, instance) 234*7c478bd9Sstevel@tonic-gate != DDI_SUCCESS) { 235*7c478bd9Sstevel@tonic-gate ret = DDI_FAILURE; 236*7c478bd9Sstevel@tonic-gate goto exit; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate isadmap = ddi_get_soft_state(per_isadma_state, instance); 239*7c478bd9Sstevel@tonic-gate isadmap->isadma_dip = dip; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* Cache our register property */ 242*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 243*7c478bd9Sstevel@tonic-gate "reg", (caddr_t)&isadmap->isadma_regp, 244*7c478bd9Sstevel@tonic-gate &isadmap->isadma_reglen) != DDI_SUCCESS) { 245*7c478bd9Sstevel@tonic-gate ret = DDI_FAILURE; 246*7c478bd9Sstevel@tonic-gate goto fail_get_prop; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* Initialize our mutex */ 250*7c478bd9Sstevel@tonic-gate mutex_init(&isadmap->isadma_access_lock, NULL, MUTEX_DRIVER, 251*7c478bd9Sstevel@tonic-gate NULL); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* Initialize our condition variable */ 254*7c478bd9Sstevel@tonic-gate cv_init(&isadmap->isadma_access_cv, NULL, CV_DRIVER, NULL); 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 257*7c478bd9Sstevel@tonic-gate goto exit; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate case DDI_RESUME: 261*7c478bd9Sstevel@tonic-gate default: 262*7c478bd9Sstevel@tonic-gate goto exit; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate fail_get_prop: 266*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(per_isadma_state, instance); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate exit: 269*7c478bd9Sstevel@tonic-gate return (ret); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * detach entry point: 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate static int 276*7c478bd9Sstevel@tonic-gate isadma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 279*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = 280*7c478bd9Sstevel@tonic-gate ddi_get_soft_state(per_isadma_state, instance); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate switch (cmd) { 283*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 284*7c478bd9Sstevel@tonic-gate cv_destroy(&isadmap->isadma_access_cv); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate mutex_destroy(&isadmap->isadma_access_lock); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* free the cached register property */ 289*7c478bd9Sstevel@tonic-gate kmem_free(isadmap->isadma_regp, isadmap->isadma_reglen); 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(per_isadma_state, instance); 292*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 295*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 302*7c478bd9Sstevel@tonic-gate static void 303*7c478bd9Sstevel@tonic-gate isadma_check_waiters(isadma_devstate_t *isadmap) 304*7c478bd9Sstevel@tonic-gate { 305*7c478bd9Sstevel@tonic-gate if (isadmap->isadma_want > isadma_max_waiter) 306*7c478bd9Sstevel@tonic-gate isadma_max_waiter = isadmap->isadma_want; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (isadmap->isadma_want < isadma_min_waiter) 309*7c478bd9Sstevel@tonic-gate isadma_min_waiter = isadmap->isadma_want; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate #endif 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate static void 314*7c478bd9Sstevel@tonic-gate isadma_dmawait(isadma_devstate_t *isadmap) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&isadmap->isadma_access_lock)); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* Wait loop, if the locking dip is set, we wait. */ 320*7c478bd9Sstevel@tonic-gate while (isadmap->isadma_ldip != NULL) { 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate isadmap->isadma_want++; 323*7c478bd9Sstevel@tonic-gate cv_wait(&isadmap->isadma_access_cv, 324*7c478bd9Sstevel@tonic-gate &isadmap->isadma_access_lock); 325*7c478bd9Sstevel@tonic-gate isadmap->isadma_want--; 326*7c478bd9Sstevel@tonic-gate isadma_sleep_cnt++; 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate static void 331*7c478bd9Sstevel@tonic-gate isadma_wakeup(isadma_devstate_t *isadmap) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&isadmap->isadma_access_lock)); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * If somebody wants register access and the lock dip is not set 338*7c478bd9Sstevel@tonic-gate * signal the waiters. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate if (isadmap->isadma_want > 0 && isadmap->isadma_ldip == NULL) { 341*7c478bd9Sstevel@tonic-gate cv_signal(&isadmap->isadma_access_cv); 342*7c478bd9Sstevel@tonic-gate isadma_wakeup_cnt++; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Register access vectors 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 352*7c478bd9Sstevel@tonic-gate void 353*7c478bd9Sstevel@tonic-gate isadma_norep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr, 354*7c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 359*7c478bd9Sstevel@tonic-gate void 360*7c478bd9Sstevel@tonic-gate isadma_norep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr, 361*7c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags) 362*7c478bd9Sstevel@tonic-gate { 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 366*7c478bd9Sstevel@tonic-gate void 367*7c478bd9Sstevel@tonic-gate isadma_norep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr, 368*7c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 373*7c478bd9Sstevel@tonic-gate void 374*7c478bd9Sstevel@tonic-gate isadma_norep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr, 375*7c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 380*7c478bd9Sstevel@tonic-gate void 381*7c478bd9Sstevel@tonic-gate isadma_norep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr, 382*7c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags) 383*7c478bd9Sstevel@tonic-gate { 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 387*7c478bd9Sstevel@tonic-gate void 388*7c478bd9Sstevel@tonic-gate isadma_norep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr, 389*7c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags) 390*7c478bd9Sstevel@tonic-gate { 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 394*7c478bd9Sstevel@tonic-gate void 395*7c478bd9Sstevel@tonic-gate isadma_norep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr, 396*7c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags) 397*7c478bd9Sstevel@tonic-gate { 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 401*7c478bd9Sstevel@tonic-gate void 402*7c478bd9Sstevel@tonic-gate isadma_norep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr, 403*7c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags) 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 408*7c478bd9Sstevel@tonic-gate uint8_t 409*7c478bd9Sstevel@tonic-gate isadma_get8(ddi_acc_impl_t *hdlp, uint8_t *addr) 410*7c478bd9Sstevel@tonic-gate { 411*7c478bd9Sstevel@tonic-gate ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; 412*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; 413*7c478bd9Sstevel@tonic-gate off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; 414*7c478bd9Sstevel@tonic-gate uint8_t ret = 0xff; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ 417*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 418*7c478bd9Sstevel@tonic-gate isadma_punt++; 419*7c478bd9Sstevel@tonic-gate #endif 420*7c478bd9Sstevel@tonic-gate return (ddi_get8(phdl, addr)); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 423*7c478bd9Sstevel@tonic-gate isadma_check_waiters(isadmap); 424*7c478bd9Sstevel@tonic-gate #endif 425*7c478bd9Sstevel@tonic-gate mutex_enter(&isadmap->isadma_access_lock); 426*7c478bd9Sstevel@tonic-gate isadma_dmawait(isadmap); /* wait until on-going dma completes */ 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* No 8 bit access to 16 bit address or count registers */ 429*7c478bd9Sstevel@tonic-gate if (IN_16BIT_SPACE(offset)) 430*7c478bd9Sstevel@tonic-gate goto exit; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* No 8 bit access to first/last flip-flop registers */ 433*7c478bd9Sstevel@tonic-gate if (IS_SEQREG(offset)) 434*7c478bd9Sstevel@tonic-gate goto exit; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate ret = ddi_get8(phdl, addr); /* Pass to parent */ 437*7c478bd9Sstevel@tonic-gate exit: 438*7c478bd9Sstevel@tonic-gate isadma_wakeup(isadmap); 439*7c478bd9Sstevel@tonic-gate mutex_exit(&isadmap->isadma_access_lock); 440*7c478bd9Sstevel@tonic-gate return (ret); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate /* 444*7c478bd9Sstevel@tonic-gate * Allow child devices to access this shared register set as if it were 445*7c478bd9Sstevel@tonic-gate * a real 16 bit register. The ISA bridge defines the access to this 446*7c478bd9Sstevel@tonic-gate * 16 bit dma controller & count register by programming an 8 byte register. 447*7c478bd9Sstevel@tonic-gate */ 448*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 449*7c478bd9Sstevel@tonic-gate uint16_t 450*7c478bd9Sstevel@tonic-gate isadma_get16(ddi_acc_impl_t *hdlp, uint16_t *addr) 451*7c478bd9Sstevel@tonic-gate { 452*7c478bd9Sstevel@tonic-gate ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; 453*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; 454*7c478bd9Sstevel@tonic-gate off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; 455*7c478bd9Sstevel@tonic-gate uint16_t ret = 0xffff; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ 458*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 459*7c478bd9Sstevel@tonic-gate isadma_punt++; 460*7c478bd9Sstevel@tonic-gate #endif 461*7c478bd9Sstevel@tonic-gate return (ddi_get16(phdl, addr)); 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 464*7c478bd9Sstevel@tonic-gate isadma_check_waiters(isadmap); 465*7c478bd9Sstevel@tonic-gate #endif 466*7c478bd9Sstevel@tonic-gate mutex_enter(&isadmap->isadma_access_lock); 467*7c478bd9Sstevel@tonic-gate isadma_dmawait(isadmap); /* wait until on-going dma completes */ 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* Only Allow access to the 16 bit count and address registers */ 470*7c478bd9Sstevel@tonic-gate if (!IN_16BIT_SPACE(offset)) 471*7c478bd9Sstevel@tonic-gate goto exit; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* Set the sequencing register to the low byte */ 474*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate /* Read the low byte, then high byte */ 477*7c478bd9Sstevel@tonic-gate ret = ddi_get8(phdl, (uint8_t *)addr); 478*7c478bd9Sstevel@tonic-gate ret = (ddi_get8(phdl, (uint8_t *)addr) << 8) | ret; 479*7c478bd9Sstevel@tonic-gate exit: 480*7c478bd9Sstevel@tonic-gate isadma_wakeup(isadmap); 481*7c478bd9Sstevel@tonic-gate mutex_exit(&isadmap->isadma_access_lock); 482*7c478bd9Sstevel@tonic-gate return (ret); 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 486*7c478bd9Sstevel@tonic-gate uint32_t 487*7c478bd9Sstevel@tonic-gate isadma_noget32(ddi_acc_impl_t *hdlp, uint32_t *addr) 488*7c478bd9Sstevel@tonic-gate { 489*7c478bd9Sstevel@tonic-gate return (UINT32_MAX); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 493*7c478bd9Sstevel@tonic-gate uint64_t 494*7c478bd9Sstevel@tonic-gate isadma_noget64(ddi_acc_impl_t *hdlp, uint64_t *addr) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate return (UINT64_MAX); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* 500*7c478bd9Sstevel@tonic-gate * Here's where we do our locking magic. The dma all mask register is an 8 501*7c478bd9Sstevel@tonic-gate * bit register in the dma space, so we look for the access to the 502*7c478bd9Sstevel@tonic-gate * DMAC1_ALLMASK register. When somebody is masking out the dma channels 503*7c478bd9Sstevel@tonic-gate * we lock down the dma engine from further PIO accesses. When the driver 504*7c478bd9Sstevel@tonic-gate * calls back into this routine to clear the allmask register, we wakeup 505*7c478bd9Sstevel@tonic-gate * any blocked threads. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 508*7c478bd9Sstevel@tonic-gate void 509*7c478bd9Sstevel@tonic-gate isadma_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) 510*7c478bd9Sstevel@tonic-gate { 511*7c478bd9Sstevel@tonic-gate ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; 512*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; 513*7c478bd9Sstevel@tonic-gate off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ 516*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 517*7c478bd9Sstevel@tonic-gate isadma_punt++; 518*7c478bd9Sstevel@tonic-gate #endif 519*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, addr, value); 520*7c478bd9Sstevel@tonic-gate return; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 523*7c478bd9Sstevel@tonic-gate isadma_check_waiters(isadmap); 524*7c478bd9Sstevel@tonic-gate #endif 525*7c478bd9Sstevel@tonic-gate mutex_enter(&isadmap->isadma_access_lock); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate if (isadmap->isadma_ldip == hdlp->ahi_common.ah_dip) { /* owned lock? */ 528*7c478bd9Sstevel@tonic-gate if (END_ISADMA(offset, value)) { 529*7c478bd9Sstevel@tonic-gate isadmap->isadma_ldip = NULL; /* reset lock owner */ 530*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 531*7c478bd9Sstevel@tonic-gate isadma_clearing_wdip++; 532*7c478bd9Sstevel@tonic-gate #endif 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate } else { /* we don't own the lock */ 535*7c478bd9Sstevel@tonic-gate /* wait until on-going dma completes */ 536*7c478bd9Sstevel@tonic-gate isadma_dmawait(isadmap); 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate if (BEGIN_ISADMA(offset, value)) { 539*7c478bd9Sstevel@tonic-gate isadmap->isadma_ldip = hdlp->ahi_common.ah_dip; 540*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 541*7c478bd9Sstevel@tonic-gate isadma_setting_wdip++; 542*7c478bd9Sstevel@tonic-gate #endif 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate /* No 8 bit access to 16 bit address or count registers */ 547*7c478bd9Sstevel@tonic-gate if (IN_16BIT_SPACE(offset)) 548*7c478bd9Sstevel@tonic-gate goto exit; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* No 8 bit access to first/last flip-flop registers */ 551*7c478bd9Sstevel@tonic-gate if (IS_SEQREG(offset)) 552*7c478bd9Sstevel@tonic-gate goto exit; 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, addr, value); /* Pass to parent */ 555*7c478bd9Sstevel@tonic-gate exit: 556*7c478bd9Sstevel@tonic-gate isadma_wakeup(isadmap); 557*7c478bd9Sstevel@tonic-gate mutex_exit(&isadmap->isadma_access_lock); 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* 561*7c478bd9Sstevel@tonic-gate * Allow child devices to access this shared register set as if it were 562*7c478bd9Sstevel@tonic-gate * a real 16 bit register. The ISA bridge defines the access to this 563*7c478bd9Sstevel@tonic-gate * 16 bit dma controller & count register by programming an 8 byte register. 564*7c478bd9Sstevel@tonic-gate */ 565*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 566*7c478bd9Sstevel@tonic-gate void 567*7c478bd9Sstevel@tonic-gate isadma_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; 570*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; 571*7c478bd9Sstevel@tonic-gate off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ 574*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 575*7c478bd9Sstevel@tonic-gate isadma_punt++; 576*7c478bd9Sstevel@tonic-gate #endif 577*7c478bd9Sstevel@tonic-gate ddi_put16(phdl, addr, value); 578*7c478bd9Sstevel@tonic-gate return; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 581*7c478bd9Sstevel@tonic-gate isadma_check_waiters(isadmap); 582*7c478bd9Sstevel@tonic-gate #endif 583*7c478bd9Sstevel@tonic-gate mutex_enter(&isadmap->isadma_access_lock); 584*7c478bd9Sstevel@tonic-gate isadma_dmawait(isadmap); /* wait until on-going dma completes */ 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* Only Allow access to the 16 bit count and address registers */ 587*7c478bd9Sstevel@tonic-gate if (!IN_16BIT_SPACE(offset)) 588*7c478bd9Sstevel@tonic-gate goto exit; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* Set the sequencing register to the low byte */ 591*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0); 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* Write the low byte, then the high byte */ 594*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, (uint8_t *)addr, value & 0xff); 595*7c478bd9Sstevel@tonic-gate ddi_put8(phdl, (uint8_t *)addr, (value >> 8) & 0xff); 596*7c478bd9Sstevel@tonic-gate exit: 597*7c478bd9Sstevel@tonic-gate isadma_wakeup(isadmap); 598*7c478bd9Sstevel@tonic-gate mutex_exit(&isadmap->isadma_access_lock); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 602*7c478bd9Sstevel@tonic-gate void 603*7c478bd9Sstevel@tonic-gate isadma_noput32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) {} 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 606*7c478bd9Sstevel@tonic-gate void 607*7c478bd9Sstevel@tonic-gate isadma_noput64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) {} 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate #define IS_SAME_REG(r1, r2) (((r1)->ebus_addr_hi == (r2)->ebus_addr_hi) && \ 610*7c478bd9Sstevel@tonic-gate ((r1)->ebus_addr_low == (r2)->ebus_addr_low)) 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * The isadma_map routine determines if it's child is attempting to map a 614*7c478bd9Sstevel@tonic-gate * shared reg. If it is, it installs it's own vectors and bus private pointer 615*7c478bd9Sstevel@tonic-gate * and stacks those ops that were already defined. 616*7c478bd9Sstevel@tonic-gate */ 617*7c478bd9Sstevel@tonic-gate static int 618*7c478bd9Sstevel@tonic-gate isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 619*7c478bd9Sstevel@tonic-gate off_t off, off_t len, caddr_t *addrp) 620*7c478bd9Sstevel@tonic-gate { 621*7c478bd9Sstevel@tonic-gate isadma_devstate_t *isadmap = ddi_get_soft_state(per_isadma_state, 622*7c478bd9Sstevel@tonic-gate ddi_get_instance(dip)); 623*7c478bd9Sstevel@tonic-gate dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; 624*7c478bd9Sstevel@tonic-gate ebus_regspec_t *child_regp, *regp; 625*7c478bd9Sstevel@tonic-gate int32_t rnumber = mp->map_obj.rnumber; 626*7c478bd9Sstevel@tonic-gate int32_t reglen; 627*7c478bd9Sstevel@tonic-gate int ret; 628*7c478bd9Sstevel@tonic-gate ddi_acc_impl_t *hp; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate /* 631*7c478bd9Sstevel@tonic-gate * Get child regspec since the mapping struct may not have it yet 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS, 634*7c478bd9Sstevel@tonic-gate "reg", (caddr_t)®p, ®len) != DDI_SUCCESS) { 635*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate child_regp = regp + rnumber; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate DPRINTF(ISADMA_MAP_DEBUG, ("isadma_map: child regp %p " 641*7c478bd9Sstevel@tonic-gate "parent regp %p Child reg array %p\n", child_regp, 642*7c478bd9Sstevel@tonic-gate isadmap->isadma_regp, regp)); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate /* Figure out if we're mapping or unmapping */ 645*7c478bd9Sstevel@tonic-gate switch (mp->map_op) { 646*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_LOCKED: 647*7c478bd9Sstevel@tonic-gate /* Call up device tree to establish mapping */ 648*7c478bd9Sstevel@tonic-gate ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map) 649*7c478bd9Sstevel@tonic-gate (pdip, rdip, mp, off, len, addrp); 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate if ((ret != DDI_SUCCESS) || 652*7c478bd9Sstevel@tonic-gate !IS_SAME_REG(child_regp, isadmap->isadma_regp)) 653*7c478bd9Sstevel@tonic-gate break; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* Post-process the mapping request. */ 656*7c478bd9Sstevel@tonic-gate hp = kmem_alloc(sizeof (ddi_acc_impl_t), KM_SLEEP); 657*7c478bd9Sstevel@tonic-gate *hp = *(ddi_acc_impl_t *)mp->map_handlep; 658*7c478bd9Sstevel@tonic-gate impl_acc_hdl_get((ddi_acc_handle_t)mp->map_handlep)-> 659*7c478bd9Sstevel@tonic-gate ah_platform_private = hp; 660*7c478bd9Sstevel@tonic-gate hp = (ddi_acc_impl_t *)mp->map_handlep; 661*7c478bd9Sstevel@tonic-gate hp->ahi_common.ah_bus_private = isadmap; 662*7c478bd9Sstevel@tonic-gate hp->ahi_get8 = isadma_get8; 663*7c478bd9Sstevel@tonic-gate hp->ahi_get16 = isadma_get16; 664*7c478bd9Sstevel@tonic-gate hp->ahi_get32 = isadma_noget32; 665*7c478bd9Sstevel@tonic-gate hp->ahi_get64 = isadma_noget64; 666*7c478bd9Sstevel@tonic-gate hp->ahi_put8 = isadma_put8; 667*7c478bd9Sstevel@tonic-gate hp->ahi_put16 = isadma_put16; 668*7c478bd9Sstevel@tonic-gate hp->ahi_put32 = isadma_noput32; 669*7c478bd9Sstevel@tonic-gate hp->ahi_put64 = isadma_noput64; 670*7c478bd9Sstevel@tonic-gate hp->ahi_rep_get8 = isadma_norep_get8; 671*7c478bd9Sstevel@tonic-gate hp->ahi_rep_get16 = isadma_norep_get16; 672*7c478bd9Sstevel@tonic-gate hp->ahi_rep_get32 = isadma_norep_get32; 673*7c478bd9Sstevel@tonic-gate hp->ahi_rep_get64 = isadma_norep_get64; 674*7c478bd9Sstevel@tonic-gate hp->ahi_rep_put8 = isadma_norep_put8; 675*7c478bd9Sstevel@tonic-gate hp->ahi_rep_put16 = isadma_norep_put16; 676*7c478bd9Sstevel@tonic-gate hp->ahi_rep_put32 = isadma_norep_put32; 677*7c478bd9Sstevel@tonic-gate hp->ahi_rep_put64 = isadma_norep_put64; 678*7c478bd9Sstevel@tonic-gate break; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate case DDI_MO_UNMAP: 681*7c478bd9Sstevel@tonic-gate if (IS_SAME_REG(child_regp, isadmap->isadma_regp)) { 682*7c478bd9Sstevel@tonic-gate hp = impl_acc_hdl_get( 683*7c478bd9Sstevel@tonic-gate (ddi_acc_handle_t)mp->map_handlep)-> 684*7c478bd9Sstevel@tonic-gate ah_platform_private; 685*7c478bd9Sstevel@tonic-gate *(ddi_acc_impl_t *)mp->map_handlep = *hp; 686*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (ddi_acc_impl_t)); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* Call up tree to tear down mapping */ 690*7c478bd9Sstevel@tonic-gate ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map) 691*7c478bd9Sstevel@tonic-gate (pdip, rdip, mp, off, len, addrp); 692*7c478bd9Sstevel@tonic-gate break; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate default: 695*7c478bd9Sstevel@tonic-gate ret = DDI_FAILURE; 696*7c478bd9Sstevel@tonic-gate break; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate kmem_free(regp, reglen); 700*7c478bd9Sstevel@tonic-gate return (ret); 701*7c478bd9Sstevel@tonic-gate } 702