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/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/bofi.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/dvma.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/bofi_impl.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * Testing the resilience of a hardened device driver requires a suitably wide 50*7c478bd9Sstevel@tonic-gate * range of different types of "typical" hardware faults to be injected, 51*7c478bd9Sstevel@tonic-gate * preferably in a controlled and repeatable fashion. This is not in general 52*7c478bd9Sstevel@tonic-gate * possible via hardware, so the "fault injection test harness" is provided. 53*7c478bd9Sstevel@tonic-gate * This works by intercepting calls from the driver to various DDI routines, 54*7c478bd9Sstevel@tonic-gate * and then corrupting the result of those DDI routine calls as if the 55*7c478bd9Sstevel@tonic-gate * hardware had caused the corruption. 56*7c478bd9Sstevel@tonic-gate * 57*7c478bd9Sstevel@tonic-gate * Conceptually, the bofi driver consists of two parts: 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * A driver interface that supports a number of ioctls which allow error 60*7c478bd9Sstevel@tonic-gate * definitions ("errdefs") to be defined and subsequently managed. The 61*7c478bd9Sstevel@tonic-gate * driver is a clone driver, so each open will create a separate 62*7c478bd9Sstevel@tonic-gate * invocation. Any errdefs created by using ioctls to that invocation 63*7c478bd9Sstevel@tonic-gate * will automatically be deleted when that invocation is closed. 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * Intercept routines: When the bofi driver is attached, it edits the 66*7c478bd9Sstevel@tonic-gate * bus_ops structure of the bus nexus specified by the "bofi-nexus" 67*7c478bd9Sstevel@tonic-gate * field in the "bofi.conf" file, thus allowing the 68*7c478bd9Sstevel@tonic-gate * bofi driver to intercept various ddi functions. These intercept 69*7c478bd9Sstevel@tonic-gate * routines primarily carry out fault injections based on the errdefs 70*7c478bd9Sstevel@tonic-gate * created for that device. 71*7c478bd9Sstevel@tonic-gate * 72*7c478bd9Sstevel@tonic-gate * Faults can be injected into: 73*7c478bd9Sstevel@tonic-gate * 74*7c478bd9Sstevel@tonic-gate * DMA (corrupting data for DMA to/from memory areas defined by 75*7c478bd9Sstevel@tonic-gate * ddi_dma_setup(), ddi_dma_bind_handle(), etc) 76*7c478bd9Sstevel@tonic-gate * 77*7c478bd9Sstevel@tonic-gate * Physical IO (corrupting data sent/received via ddi_get8(), ddi_put8(), 78*7c478bd9Sstevel@tonic-gate * etc), 79*7c478bd9Sstevel@tonic-gate * 80*7c478bd9Sstevel@tonic-gate * Interrupts (generating spurious interrupts, losing interrupts, 81*7c478bd9Sstevel@tonic-gate * delaying interrupts). 82*7c478bd9Sstevel@tonic-gate * 83*7c478bd9Sstevel@tonic-gate * By default, ddi routines called from all drivers will be intercepted 84*7c478bd9Sstevel@tonic-gate * and faults potentially injected. However, the "bofi-to-test" field in 85*7c478bd9Sstevel@tonic-gate * the "bofi.conf" file can be set to a space-separated list of drivers to 86*7c478bd9Sstevel@tonic-gate * test (or by preceding each driver name in the list with an "!", a list 87*7c478bd9Sstevel@tonic-gate * of drivers not to test). 88*7c478bd9Sstevel@tonic-gate * 89*7c478bd9Sstevel@tonic-gate * In addition to fault injection, the bofi driver does a number of static 90*7c478bd9Sstevel@tonic-gate * checks which are controlled by properties in the "bofi.conf" file. 91*7c478bd9Sstevel@tonic-gate * 92*7c478bd9Sstevel@tonic-gate * "bofi-ddi-check" - if set will validate that there are no PIO access 93*7c478bd9Sstevel@tonic-gate * other than those using the DDI routines (ddi_get8(), ddi_put8(), etc). 94*7c478bd9Sstevel@tonic-gate * 95*7c478bd9Sstevel@tonic-gate * "bofi-range-check" - if set to values 1 (warning) or 2 (panic), will 96*7c478bd9Sstevel@tonic-gate * validate that calls to ddi_get8(), ddi_put8(), etc are not made 97*7c478bd9Sstevel@tonic-gate * specifying addresses outside the range of the access_handle. 98*7c478bd9Sstevel@tonic-gate * 99*7c478bd9Sstevel@tonic-gate * "bofi-sync-check" - if set will validate that calls to ddi_dma_sync() 100*7c478bd9Sstevel@tonic-gate * are being made correctly. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate extern void *bp_mapin_common(struct buf *, int); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static int bofi_ddi_check; 106*7c478bd9Sstevel@tonic-gate static int bofi_sync_check; 107*7c478bd9Sstevel@tonic-gate static int bofi_range_check; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static struct bofi_link bofi_link_array[BOFI_NLINKS], *bofi_link_freelist; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #define LLSZMASK (sizeof (uint64_t)-1) 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #define HDL_HASH_TBL_SIZE 64 114*7c478bd9Sstevel@tonic-gate static struct bofi_shadow hhash_table[HDL_HASH_TBL_SIZE]; 115*7c478bd9Sstevel@tonic-gate static struct bofi_shadow dhash_table[HDL_HASH_TBL_SIZE]; 116*7c478bd9Sstevel@tonic-gate #define HDL_DHASH(x) \ 117*7c478bd9Sstevel@tonic-gate (&dhash_table[((uintptr_t)(x) >> 3) & (HDL_HASH_TBL_SIZE-1)]) 118*7c478bd9Sstevel@tonic-gate #define HDL_HHASH(x) \ 119*7c478bd9Sstevel@tonic-gate (&hhash_table[((uintptr_t)(x) >> 5) & (HDL_HASH_TBL_SIZE-1)]) 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static struct bofi_shadow shadow_list; 122*7c478bd9Sstevel@tonic-gate static struct bofi_errent *errent_listp; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate static char driver_list[NAMESIZE]; 125*7c478bd9Sstevel@tonic-gate static int driver_list_size; 126*7c478bd9Sstevel@tonic-gate static int driver_list_neg; 127*7c478bd9Sstevel@tonic-gate static char nexus_name[NAMESIZE]; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate static int initialized = 0; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate #define NCLONES 256 132*7c478bd9Sstevel@tonic-gate static int clone_tab[NCLONES]; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate static dev_info_t *our_dip; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate static kmutex_t bofi_mutex; 137*7c478bd9Sstevel@tonic-gate static kmutex_t clone_tab_mutex; 138*7c478bd9Sstevel@tonic-gate static kmutex_t bofi_low_mutex; 139*7c478bd9Sstevel@tonic-gate static ddi_iblock_cookie_t bofi_low_cookie; 140*7c478bd9Sstevel@tonic-gate static uint_t bofi_signal(caddr_t arg); 141*7c478bd9Sstevel@tonic-gate static int bofi_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 142*7c478bd9Sstevel@tonic-gate static int bofi_attach(dev_info_t *, ddi_attach_cmd_t); 143*7c478bd9Sstevel@tonic-gate static int bofi_detach(dev_info_t *, ddi_detach_cmd_t); 144*7c478bd9Sstevel@tonic-gate static int bofi_open(dev_t *, int, int, cred_t *); 145*7c478bd9Sstevel@tonic-gate static int bofi_close(dev_t, int, int, cred_t *); 146*7c478bd9Sstevel@tonic-gate static int bofi_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 147*7c478bd9Sstevel@tonic-gate static int bofi_errdef_alloc(struct bofi_errdef *, char *, 148*7c478bd9Sstevel@tonic-gate struct bofi_errent *); 149*7c478bd9Sstevel@tonic-gate static int bofi_errdef_free(struct bofi_errent *); 150*7c478bd9Sstevel@tonic-gate static void bofi_start(struct bofi_errctl *, char *); 151*7c478bd9Sstevel@tonic-gate static void bofi_stop(struct bofi_errctl *, char *); 152*7c478bd9Sstevel@tonic-gate static void bofi_broadcast(struct bofi_errctl *, char *); 153*7c478bd9Sstevel@tonic-gate static void bofi_clear_acc_chk(struct bofi_errctl *, char *); 154*7c478bd9Sstevel@tonic-gate static void bofi_clear_errors(struct bofi_errctl *, char *); 155*7c478bd9Sstevel@tonic-gate static void bofi_clear_errdefs(struct bofi_errctl *, char *); 156*7c478bd9Sstevel@tonic-gate static int bofi_errdef_check(struct bofi_errstate *, 157*7c478bd9Sstevel@tonic-gate struct acc_log_elem **); 158*7c478bd9Sstevel@tonic-gate static int bofi_errdef_check_w(struct bofi_errstate *, 159*7c478bd9Sstevel@tonic-gate struct acc_log_elem **); 160*7c478bd9Sstevel@tonic-gate static int bofi_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 161*7c478bd9Sstevel@tonic-gate off_t, off_t, caddr_t *); 162*7c478bd9Sstevel@tonic-gate static int bofi_dma_map(dev_info_t *, dev_info_t *, 163*7c478bd9Sstevel@tonic-gate struct ddi_dma_req *, ddi_dma_handle_t *); 164*7c478bd9Sstevel@tonic-gate static int bofi_dma_allochdl(dev_info_t *, dev_info_t *, 165*7c478bd9Sstevel@tonic-gate ddi_dma_attr_t *, int (*)(caddr_t), caddr_t, 166*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t *); 167*7c478bd9Sstevel@tonic-gate static int bofi_dma_freehdl(dev_info_t *, dev_info_t *, 168*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t); 169*7c478bd9Sstevel@tonic-gate static int bofi_dma_bindhdl(dev_info_t *, dev_info_t *, 170*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t, struct ddi_dma_req *, ddi_dma_cookie_t *, 171*7c478bd9Sstevel@tonic-gate uint_t *); 172*7c478bd9Sstevel@tonic-gate static int bofi_dma_unbindhdl(dev_info_t *, dev_info_t *, 173*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t); 174*7c478bd9Sstevel@tonic-gate static int bofi_dma_flush(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 175*7c478bd9Sstevel@tonic-gate off_t, size_t, uint_t); 176*7c478bd9Sstevel@tonic-gate static int bofi_dma_ctl(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 177*7c478bd9Sstevel@tonic-gate enum ddi_dma_ctlops, off_t *, size_t *, caddr_t *, uint_t); 178*7c478bd9Sstevel@tonic-gate static int bofi_dma_win(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 179*7c478bd9Sstevel@tonic-gate uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *); 180*7c478bd9Sstevel@tonic-gate static int bofi_intr_ops(dev_info_t *dip, dev_info_t *rdip, 181*7c478bd9Sstevel@tonic-gate ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, 182*7c478bd9Sstevel@tonic-gate void *result); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 185*7c478bd9Sstevel@tonic-gate static void bofi_dvma_kaddr_load(ddi_dma_handle_t, caddr_t, uint_t, 186*7c478bd9Sstevel@tonic-gate uint_t, ddi_dma_cookie_t *); 187*7c478bd9Sstevel@tonic-gate static void bofi_dvma_unload(ddi_dma_handle_t, uint_t, uint_t); 188*7c478bd9Sstevel@tonic-gate static void bofi_dvma_sync(ddi_dma_handle_t, uint_t, uint_t); 189*7c478bd9Sstevel@tonic-gate static void bofi_dvma_reserve(dev_info_t *, ddi_dma_handle_t); 190*7c478bd9Sstevel@tonic-gate #endif 191*7c478bd9Sstevel@tonic-gate static int driver_under_test(dev_info_t *); 192*7c478bd9Sstevel@tonic-gate static int bofi_check_acc_hdl(ddi_acc_impl_t *); 193*7c478bd9Sstevel@tonic-gate static int bofi_check_dma_hdl(ddi_dma_impl_t *); 194*7c478bd9Sstevel@tonic-gate static int bofi_post_event(dev_info_t *dip, dev_info_t *rdip, 195*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void *impl_data); 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate static struct bus_ops bofi_bus_ops = { 198*7c478bd9Sstevel@tonic-gate BUSO_REV, 199*7c478bd9Sstevel@tonic-gate bofi_map, 200*7c478bd9Sstevel@tonic-gate NULL, 201*7c478bd9Sstevel@tonic-gate NULL, 202*7c478bd9Sstevel@tonic-gate NULL, 203*7c478bd9Sstevel@tonic-gate i_ddi_map_fault, 204*7c478bd9Sstevel@tonic-gate bofi_dma_map, 205*7c478bd9Sstevel@tonic-gate bofi_dma_allochdl, 206*7c478bd9Sstevel@tonic-gate bofi_dma_freehdl, 207*7c478bd9Sstevel@tonic-gate bofi_dma_bindhdl, 208*7c478bd9Sstevel@tonic-gate bofi_dma_unbindhdl, 209*7c478bd9Sstevel@tonic-gate bofi_dma_flush, 210*7c478bd9Sstevel@tonic-gate bofi_dma_win, 211*7c478bd9Sstevel@tonic-gate bofi_dma_ctl, 212*7c478bd9Sstevel@tonic-gate NULL, 213*7c478bd9Sstevel@tonic-gate ddi_bus_prop_op, 214*7c478bd9Sstevel@tonic-gate ndi_busop_get_eventcookie, 215*7c478bd9Sstevel@tonic-gate ndi_busop_add_eventcall, 216*7c478bd9Sstevel@tonic-gate ndi_busop_remove_eventcall, 217*7c478bd9Sstevel@tonic-gate bofi_post_event, 218*7c478bd9Sstevel@tonic-gate NULL, 219*7c478bd9Sstevel@tonic-gate 0, 220*7c478bd9Sstevel@tonic-gate 0, 221*7c478bd9Sstevel@tonic-gate 0, 222*7c478bd9Sstevel@tonic-gate 0, 223*7c478bd9Sstevel@tonic-gate 0, 224*7c478bd9Sstevel@tonic-gate 0, 225*7c478bd9Sstevel@tonic-gate 0, 226*7c478bd9Sstevel@tonic-gate bofi_intr_ops 227*7c478bd9Sstevel@tonic-gate }; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate static struct cb_ops bofi_cb_ops = { 230*7c478bd9Sstevel@tonic-gate bofi_open, 231*7c478bd9Sstevel@tonic-gate bofi_close, 232*7c478bd9Sstevel@tonic-gate nodev, 233*7c478bd9Sstevel@tonic-gate nodev, 234*7c478bd9Sstevel@tonic-gate nodev, /* dump */ 235*7c478bd9Sstevel@tonic-gate nodev, 236*7c478bd9Sstevel@tonic-gate nodev, 237*7c478bd9Sstevel@tonic-gate bofi_ioctl, 238*7c478bd9Sstevel@tonic-gate nodev, /* devmap */ 239*7c478bd9Sstevel@tonic-gate nodev, 240*7c478bd9Sstevel@tonic-gate nodev, /* segmap */ 241*7c478bd9Sstevel@tonic-gate nochpoll, 242*7c478bd9Sstevel@tonic-gate nodev, 243*7c478bd9Sstevel@tonic-gate NULL, /* for STREAMS drivers */ 244*7c478bd9Sstevel@tonic-gate D_NEW | D_MP /* driver compatibility flag */ 245*7c478bd9Sstevel@tonic-gate }; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static struct dev_ops bofi_ops = { 248*7c478bd9Sstevel@tonic-gate DEVO_REV, /* driver build version */ 249*7c478bd9Sstevel@tonic-gate 0, /* device reference count */ 250*7c478bd9Sstevel@tonic-gate bofi_getinfo, 251*7c478bd9Sstevel@tonic-gate nulldev, 252*7c478bd9Sstevel@tonic-gate nulldev, /* probe */ 253*7c478bd9Sstevel@tonic-gate bofi_attach, 254*7c478bd9Sstevel@tonic-gate bofi_detach, 255*7c478bd9Sstevel@tonic-gate nulldev, /* reset */ 256*7c478bd9Sstevel@tonic-gate &bofi_cb_ops, 257*7c478bd9Sstevel@tonic-gate (struct bus_ops *)NULL, 258*7c478bd9Sstevel@tonic-gate nulldev /* power */ 259*7c478bd9Sstevel@tonic-gate }; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate /* module configuration stuff */ 262*7c478bd9Sstevel@tonic-gate static void *statep; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 265*7c478bd9Sstevel@tonic-gate &mod_driverops, 266*7c478bd9Sstevel@tonic-gate "bofi driver %I%", 267*7c478bd9Sstevel@tonic-gate &bofi_ops 268*7c478bd9Sstevel@tonic-gate }; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 271*7c478bd9Sstevel@tonic-gate MODREV_1, 272*7c478bd9Sstevel@tonic-gate &modldrv, 273*7c478bd9Sstevel@tonic-gate 0 274*7c478bd9Sstevel@tonic-gate }; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate static struct bus_ops save_bus_ops; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 279*7c478bd9Sstevel@tonic-gate static struct dvma_ops bofi_dvma_ops = { 280*7c478bd9Sstevel@tonic-gate DVMAO_REV, 281*7c478bd9Sstevel@tonic-gate bofi_dvma_kaddr_load, 282*7c478bd9Sstevel@tonic-gate bofi_dvma_unload, 283*7c478bd9Sstevel@tonic-gate bofi_dvma_sync 284*7c478bd9Sstevel@tonic-gate }; 285*7c478bd9Sstevel@tonic-gate #endif 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * support routine - map user page into kernel virtual 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate static caddr_t 291*7c478bd9Sstevel@tonic-gate dmareq_mapin(offset_t len, caddr_t addr, struct as *as, int flag) 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate struct buf buf; 294*7c478bd9Sstevel@tonic-gate struct proc proc; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * mock up a buf structure so we can call bp_mapin_common() 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate buf.b_flags = B_PHYS; 300*7c478bd9Sstevel@tonic-gate buf.b_un.b_addr = (caddr_t)addr; 301*7c478bd9Sstevel@tonic-gate buf.b_bcount = (size_t)len; 302*7c478bd9Sstevel@tonic-gate proc.p_as = as; 303*7c478bd9Sstevel@tonic-gate buf.b_proc = &proc; 304*7c478bd9Sstevel@tonic-gate return (bp_mapin_common(&buf, flag)); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * support routine - map page chain into kernel virtual 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate static caddr_t 312*7c478bd9Sstevel@tonic-gate dmareq_pp_mapin(offset_t len, uint_t offset, page_t *pp, int flag) 313*7c478bd9Sstevel@tonic-gate { 314*7c478bd9Sstevel@tonic-gate struct buf buf; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * mock up a buf structure so we can call bp_mapin_common() 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate buf.b_flags = B_PAGEIO; 320*7c478bd9Sstevel@tonic-gate buf.b_un.b_addr = (caddr_t)(uintptr_t)offset; 321*7c478bd9Sstevel@tonic-gate buf.b_bcount = (size_t)len; 322*7c478bd9Sstevel@tonic-gate buf.b_pages = pp; 323*7c478bd9Sstevel@tonic-gate return (bp_mapin_common(&buf, flag)); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * support routine - map page array into kernel virtual 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate static caddr_t 331*7c478bd9Sstevel@tonic-gate dmareq_pplist_mapin(uint_t len, caddr_t addr, page_t **pplist, struct as *as, 332*7c478bd9Sstevel@tonic-gate int flag) 333*7c478bd9Sstevel@tonic-gate { 334*7c478bd9Sstevel@tonic-gate struct buf buf; 335*7c478bd9Sstevel@tonic-gate struct proc proc; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * mock up a buf structure so we can call bp_mapin_common() 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate buf.b_flags = B_PHYS|B_SHADOW; 341*7c478bd9Sstevel@tonic-gate buf.b_un.b_addr = addr; 342*7c478bd9Sstevel@tonic-gate buf.b_bcount = len; 343*7c478bd9Sstevel@tonic-gate buf.b_shadow = pplist; 344*7c478bd9Sstevel@tonic-gate proc.p_as = as; 345*7c478bd9Sstevel@tonic-gate buf.b_proc = &proc; 346*7c478bd9Sstevel@tonic-gate return (bp_mapin_common(&buf, flag)); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * support routine - map dmareq into kernel virtual if not already 352*7c478bd9Sstevel@tonic-gate * fills in *lenp with length 353*7c478bd9Sstevel@tonic-gate * *mapaddr will be new kernel virtual address - or null if no mapping needed 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate static caddr_t 356*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapin(struct ddi_dma_req *dmareqp, caddr_t *mapaddrp, 357*7c478bd9Sstevel@tonic-gate offset_t *lenp) 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate int sleep = (dmareqp->dmar_fp == DDI_DMA_SLEEP) ? VM_SLEEP: VM_NOSLEEP; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate *lenp = dmareqp->dmar_object.dmao_size; 362*7c478bd9Sstevel@tonic-gate if (dmareqp->dmar_object.dmao_type == DMA_OTYP_PAGES) { 363*7c478bd9Sstevel@tonic-gate *mapaddrp = dmareq_pp_mapin(dmareqp->dmar_object.dmao_size, 364*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.pp_obj.pp_offset, 365*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.pp_obj.pp_pp, sleep); 366*7c478bd9Sstevel@tonic-gate return (*mapaddrp); 367*7c478bd9Sstevel@tonic-gate } else if (dmareqp->dmar_object.dmao_obj.virt_obj.v_priv != NULL) { 368*7c478bd9Sstevel@tonic-gate *mapaddrp = dmareq_pplist_mapin(dmareqp->dmar_object.dmao_size, 369*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.virt_obj.v_addr, 370*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.virt_obj.v_priv, 371*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.virt_obj.v_as, sleep); 372*7c478bd9Sstevel@tonic-gate return (*mapaddrp); 373*7c478bd9Sstevel@tonic-gate } else if (dmareqp->dmar_object.dmao_obj.virt_obj.v_as == &kas) { 374*7c478bd9Sstevel@tonic-gate *mapaddrp = NULL; 375*7c478bd9Sstevel@tonic-gate return (dmareqp->dmar_object.dmao_obj.virt_obj.v_addr); 376*7c478bd9Sstevel@tonic-gate } else if (dmareqp->dmar_object.dmao_obj.virt_obj.v_as == NULL) { 377*7c478bd9Sstevel@tonic-gate *mapaddrp = NULL; 378*7c478bd9Sstevel@tonic-gate return (dmareqp->dmar_object.dmao_obj.virt_obj.v_addr); 379*7c478bd9Sstevel@tonic-gate } else { 380*7c478bd9Sstevel@tonic-gate *mapaddrp = dmareq_mapin(dmareqp->dmar_object.dmao_size, 381*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.virt_obj.v_addr, 382*7c478bd9Sstevel@tonic-gate dmareqp->dmar_object.dmao_obj.virt_obj.v_as, sleep); 383*7c478bd9Sstevel@tonic-gate return (*mapaddrp); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate /* 389*7c478bd9Sstevel@tonic-gate * support routine - free off kernel virtual mapping as allocated by 390*7c478bd9Sstevel@tonic-gate * ddi_dmareq_mapin() 391*7c478bd9Sstevel@tonic-gate */ 392*7c478bd9Sstevel@tonic-gate static void 393*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapout(caddr_t addr, offset_t len) 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate struct buf buf; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (addr == NULL) 398*7c478bd9Sstevel@tonic-gate return; 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * mock up a buf structure 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate buf.b_flags = B_REMAPPED; 403*7c478bd9Sstevel@tonic-gate buf.b_un.b_addr = addr; 404*7c478bd9Sstevel@tonic-gate buf.b_bcount = (size_t)len; 405*7c478bd9Sstevel@tonic-gate bp_mapout(&buf); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate static time_t 409*7c478bd9Sstevel@tonic-gate bofi_gettime() 410*7c478bd9Sstevel@tonic-gate { 411*7c478bd9Sstevel@tonic-gate timestruc_t ts; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate gethrestime(&ts); 414*7c478bd9Sstevel@tonic-gate return (ts.tv_sec); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * reset the bus_ops structure of the specified nexus to point to 419*7c478bd9Sstevel@tonic-gate * the original values in the save_bus_ops structure. 420*7c478bd9Sstevel@tonic-gate * 421*7c478bd9Sstevel@tonic-gate * Note that both this routine and modify_bus_ops() rely on the current 422*7c478bd9Sstevel@tonic-gate * behavior of the framework in that nexus drivers are not unloadable 423*7c478bd9Sstevel@tonic-gate * 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate reset_bus_ops(char *name, struct bus_ops *bop) 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate struct modctl *modp; 430*7c478bd9Sstevel@tonic-gate struct modldrv *mp; 431*7c478bd9Sstevel@tonic-gate struct bus_ops *bp; 432*7c478bd9Sstevel@tonic-gate struct dev_ops *ops; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate mutex_enter(&mod_lock); 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * find specified module 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate modp = &modules; 439*7c478bd9Sstevel@tonic-gate do { 440*7c478bd9Sstevel@tonic-gate if (strcmp(name, modp->mod_modname) == 0) { 441*7c478bd9Sstevel@tonic-gate if (!modp->mod_linkage) { 442*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 443*7c478bd9Sstevel@tonic-gate return (0); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate mp = modp->mod_linkage->ml_linkage[0]; 446*7c478bd9Sstevel@tonic-gate if (!mp || !mp->drv_dev_ops) { 447*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 448*7c478bd9Sstevel@tonic-gate return (0); 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate ops = mp->drv_dev_ops; 451*7c478bd9Sstevel@tonic-gate bp = ops->devo_bus_ops; 452*7c478bd9Sstevel@tonic-gate if (!bp) { 453*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 454*7c478bd9Sstevel@tonic-gate return (0); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate if (ops->devo_refcnt > 0) { 457*7c478bd9Sstevel@tonic-gate /* 458*7c478bd9Sstevel@tonic-gate * As long as devices are active with modified 459*7c478bd9Sstevel@tonic-gate * bus ops bofi must not go away. There may be 460*7c478bd9Sstevel@tonic-gate * drivers with modified access or dma handles. 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 463*7c478bd9Sstevel@tonic-gate return (0); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "bofi reset bus_ops for %s", 466*7c478bd9Sstevel@tonic-gate mp->drv_linkinfo); 467*7c478bd9Sstevel@tonic-gate bp->bus_intr_op = bop->bus_intr_op; 468*7c478bd9Sstevel@tonic-gate bp->bus_post_event = bop->bus_post_event; 469*7c478bd9Sstevel@tonic-gate bp->bus_map = bop->bus_map; 470*7c478bd9Sstevel@tonic-gate bp->bus_dma_map = bop->bus_dma_map; 471*7c478bd9Sstevel@tonic-gate bp->bus_dma_allochdl = bop->bus_dma_allochdl; 472*7c478bd9Sstevel@tonic-gate bp->bus_dma_freehdl = bop->bus_dma_freehdl; 473*7c478bd9Sstevel@tonic-gate bp->bus_dma_bindhdl = bop->bus_dma_bindhdl; 474*7c478bd9Sstevel@tonic-gate bp->bus_dma_unbindhdl = bop->bus_dma_unbindhdl; 475*7c478bd9Sstevel@tonic-gate bp->bus_dma_flush = bop->bus_dma_flush; 476*7c478bd9Sstevel@tonic-gate bp->bus_dma_win = bop->bus_dma_win; 477*7c478bd9Sstevel@tonic-gate bp->bus_dma_ctl = bop->bus_dma_ctl; 478*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 479*7c478bd9Sstevel@tonic-gate return (1); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } while ((modp = modp->mod_next) != &modules); 482*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 483*7c478bd9Sstevel@tonic-gate return (0); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * modify the bus_ops structure of the specified nexus to point to bofi 488*7c478bd9Sstevel@tonic-gate * routines, saving the original values in the save_bus_ops structure 489*7c478bd9Sstevel@tonic-gate */ 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate static int 492*7c478bd9Sstevel@tonic-gate modify_bus_ops(char *name, struct bus_ops *bop) 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate struct modctl *modp; 495*7c478bd9Sstevel@tonic-gate struct modldrv *mp; 496*7c478bd9Sstevel@tonic-gate struct bus_ops *bp; 497*7c478bd9Sstevel@tonic-gate struct dev_ops *ops; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(name) == -1) 500*7c478bd9Sstevel@tonic-gate return (0); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate mutex_enter(&mod_lock); 503*7c478bd9Sstevel@tonic-gate /* 504*7c478bd9Sstevel@tonic-gate * find specified module 505*7c478bd9Sstevel@tonic-gate */ 506*7c478bd9Sstevel@tonic-gate modp = &modules; 507*7c478bd9Sstevel@tonic-gate do { 508*7c478bd9Sstevel@tonic-gate if (strcmp(name, modp->mod_modname) == 0) { 509*7c478bd9Sstevel@tonic-gate if (!modp->mod_linkage) { 510*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 511*7c478bd9Sstevel@tonic-gate return (0); 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate mp = modp->mod_linkage->ml_linkage[0]; 514*7c478bd9Sstevel@tonic-gate if (!mp || !mp->drv_dev_ops) { 515*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 516*7c478bd9Sstevel@tonic-gate return (0); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate ops = mp->drv_dev_ops; 519*7c478bd9Sstevel@tonic-gate bp = ops->devo_bus_ops; 520*7c478bd9Sstevel@tonic-gate if (!bp) { 521*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 522*7c478bd9Sstevel@tonic-gate return (0); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate if (ops->devo_refcnt == 0) { 525*7c478bd9Sstevel@tonic-gate /* 526*7c478bd9Sstevel@tonic-gate * If there is no device active for this 527*7c478bd9Sstevel@tonic-gate * module then there is nothing to do for bofi. 528*7c478bd9Sstevel@tonic-gate */ 529*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 530*7c478bd9Sstevel@tonic-gate return (0); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "bofi modify bus_ops for %s", 533*7c478bd9Sstevel@tonic-gate mp->drv_linkinfo); 534*7c478bd9Sstevel@tonic-gate save_bus_ops = *bp; 535*7c478bd9Sstevel@tonic-gate bp->bus_intr_op = bop->bus_intr_op; 536*7c478bd9Sstevel@tonic-gate bp->bus_post_event = bop->bus_post_event; 537*7c478bd9Sstevel@tonic-gate bp->bus_map = bop->bus_map; 538*7c478bd9Sstevel@tonic-gate bp->bus_dma_map = bop->bus_dma_map; 539*7c478bd9Sstevel@tonic-gate bp->bus_dma_allochdl = bop->bus_dma_allochdl; 540*7c478bd9Sstevel@tonic-gate bp->bus_dma_freehdl = bop->bus_dma_freehdl; 541*7c478bd9Sstevel@tonic-gate bp->bus_dma_bindhdl = bop->bus_dma_bindhdl; 542*7c478bd9Sstevel@tonic-gate bp->bus_dma_unbindhdl = bop->bus_dma_unbindhdl; 543*7c478bd9Sstevel@tonic-gate bp->bus_dma_flush = bop->bus_dma_flush; 544*7c478bd9Sstevel@tonic-gate bp->bus_dma_win = bop->bus_dma_win; 545*7c478bd9Sstevel@tonic-gate bp->bus_dma_ctl = bop->bus_dma_ctl; 546*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 547*7c478bd9Sstevel@tonic-gate return (1); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate } while ((modp = modp->mod_next) != &modules); 550*7c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 551*7c478bd9Sstevel@tonic-gate return (0); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate int 556*7c478bd9Sstevel@tonic-gate _init(void) 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate int e; 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate e = ddi_soft_state_init(&statep, sizeof (struct bofi_errent), 1); 561*7c478bd9Sstevel@tonic-gate if (e != 0) 562*7c478bd9Sstevel@tonic-gate return (e); 563*7c478bd9Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0) 564*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 565*7c478bd9Sstevel@tonic-gate return (e); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate int 570*7c478bd9Sstevel@tonic-gate _fini(void) 571*7c478bd9Sstevel@tonic-gate { 572*7c478bd9Sstevel@tonic-gate int e; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if ((e = mod_remove(&modlinkage)) != 0) 575*7c478bd9Sstevel@tonic-gate return (e); 576*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 577*7c478bd9Sstevel@tonic-gate return (e); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate int 582*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 583*7c478bd9Sstevel@tonic-gate { 584*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate static int 589*7c478bd9Sstevel@tonic-gate bofi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate char *name; 592*7c478bd9Sstevel@tonic-gate char buf[80]; 593*7c478bd9Sstevel@tonic-gate int i; 594*7c478bd9Sstevel@tonic-gate int s, ss; 595*7c478bd9Sstevel@tonic-gate int size = NAMESIZE; 596*7c478bd9Sstevel@tonic-gate int new_string; 597*7c478bd9Sstevel@tonic-gate char *ptr; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) 600*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 601*7c478bd9Sstevel@tonic-gate /* 602*7c478bd9Sstevel@tonic-gate * only one instance - but we clone using the open routine 603*7c478bd9Sstevel@tonic-gate */ 604*7c478bd9Sstevel@tonic-gate if (ddi_get_instance(dip) > 0) 605*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if (!initialized) { 608*7c478bd9Sstevel@tonic-gate if ((name = ddi_get_name(dip)) == NULL) 609*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 610*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s,ctl", name); 611*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, buf, S_IFCHR, 0, 612*7c478bd9Sstevel@tonic-gate DDI_PSEUDO, NULL) == DDI_FAILURE) 613*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_MED, 616*7c478bd9Sstevel@tonic-gate &bofi_low_cookie) != DDI_SUCCESS) { 617*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, buf); 618*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); /* fail attach */ 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * get nexus name (from conf file) 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 0, 624*7c478bd9Sstevel@tonic-gate "bofi-nexus", nexus_name, &size) != DDI_PROP_SUCCESS) { 625*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, buf); 626*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate /* 629*7c478bd9Sstevel@tonic-gate * get whether to do dma map kmem private checking 630*7c478bd9Sstevel@tonic-gate */ 631*7c478bd9Sstevel@tonic-gate if ((bofi_range_check = ddi_prop_lookup_string(DDI_DEV_T_ANY, 632*7c478bd9Sstevel@tonic-gate dip, 0, "bofi-range-check", &ptr)) != DDI_PROP_SUCCESS) 633*7c478bd9Sstevel@tonic-gate bofi_range_check = 0; 634*7c478bd9Sstevel@tonic-gate else if (strcmp(ptr, "panic") == 0) 635*7c478bd9Sstevel@tonic-gate bofi_range_check = 2; 636*7c478bd9Sstevel@tonic-gate else if (strcmp(ptr, "warn") == 0) 637*7c478bd9Sstevel@tonic-gate bofi_range_check = 1; 638*7c478bd9Sstevel@tonic-gate else 639*7c478bd9Sstevel@tonic-gate bofi_range_check = 0; 640*7c478bd9Sstevel@tonic-gate ddi_prop_free(ptr); 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate /* 643*7c478bd9Sstevel@tonic-gate * get whether to prevent direct access to register 644*7c478bd9Sstevel@tonic-gate */ 645*7c478bd9Sstevel@tonic-gate if ((bofi_ddi_check = ddi_prop_lookup_string(DDI_DEV_T_ANY, 646*7c478bd9Sstevel@tonic-gate dip, 0, "bofi-ddi-check", &ptr)) != DDI_PROP_SUCCESS) 647*7c478bd9Sstevel@tonic-gate bofi_ddi_check = 0; 648*7c478bd9Sstevel@tonic-gate else if (strcmp(ptr, "on") == 0) 649*7c478bd9Sstevel@tonic-gate bofi_ddi_check = 1; 650*7c478bd9Sstevel@tonic-gate else 651*7c478bd9Sstevel@tonic-gate bofi_ddi_check = 0; 652*7c478bd9Sstevel@tonic-gate ddi_prop_free(ptr); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * get whether to do copy on ddi_dma_sync 656*7c478bd9Sstevel@tonic-gate */ 657*7c478bd9Sstevel@tonic-gate if ((bofi_sync_check = ddi_prop_lookup_string(DDI_DEV_T_ANY, 658*7c478bd9Sstevel@tonic-gate dip, 0, "bofi-sync-check", &ptr)) != DDI_PROP_SUCCESS) 659*7c478bd9Sstevel@tonic-gate bofi_sync_check = 0; 660*7c478bd9Sstevel@tonic-gate else if (strcmp(ptr, "on") == 0) 661*7c478bd9Sstevel@tonic-gate bofi_sync_check = 1; 662*7c478bd9Sstevel@tonic-gate else 663*7c478bd9Sstevel@tonic-gate bofi_sync_check = 0; 664*7c478bd9Sstevel@tonic-gate ddi_prop_free(ptr); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* 667*7c478bd9Sstevel@tonic-gate * get driver-under-test names (from conf file) 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate size = NAMESIZE; 670*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 0, 671*7c478bd9Sstevel@tonic-gate "bofi-to-test", driver_list, &size) != DDI_PROP_SUCCESS) 672*7c478bd9Sstevel@tonic-gate driver_list[0] = 0; 673*7c478bd9Sstevel@tonic-gate /* 674*7c478bd9Sstevel@tonic-gate * and convert into a sequence of strings 675*7c478bd9Sstevel@tonic-gate */ 676*7c478bd9Sstevel@tonic-gate driver_list_neg = 1; 677*7c478bd9Sstevel@tonic-gate new_string = 1; 678*7c478bd9Sstevel@tonic-gate driver_list_size = strlen(driver_list); 679*7c478bd9Sstevel@tonic-gate for (i = 0; i < driver_list_size; i++) { 680*7c478bd9Sstevel@tonic-gate if (driver_list[i] == ' ') { 681*7c478bd9Sstevel@tonic-gate driver_list[i] = '\0'; 682*7c478bd9Sstevel@tonic-gate new_string = 1; 683*7c478bd9Sstevel@tonic-gate } else if (new_string) { 684*7c478bd9Sstevel@tonic-gate if (driver_list[i] != '!') 685*7c478bd9Sstevel@tonic-gate driver_list_neg = 0; 686*7c478bd9Sstevel@tonic-gate new_string = 0; 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * initialize mutex, lists 691*7c478bd9Sstevel@tonic-gate */ 692*7c478bd9Sstevel@tonic-gate mutex_init(&clone_tab_mutex, NULL, MUTEX_DRIVER, 693*7c478bd9Sstevel@tonic-gate NULL); 694*7c478bd9Sstevel@tonic-gate /* 695*7c478bd9Sstevel@tonic-gate * fake up iblock cookie - need to protect outselves 696*7c478bd9Sstevel@tonic-gate * against drivers that use hilevel interrupts 697*7c478bd9Sstevel@tonic-gate */ 698*7c478bd9Sstevel@tonic-gate ss = spl8(); 699*7c478bd9Sstevel@tonic-gate s = spl8(); 700*7c478bd9Sstevel@tonic-gate splx(ss); 701*7c478bd9Sstevel@tonic-gate mutex_init(&bofi_mutex, NULL, MUTEX_SPIN, (void *)(uintptr_t)s); 702*7c478bd9Sstevel@tonic-gate mutex_init(&bofi_low_mutex, NULL, MUTEX_DRIVER, 703*7c478bd9Sstevel@tonic-gate (void *)bofi_low_cookie); 704*7c478bd9Sstevel@tonic-gate shadow_list.next = &shadow_list; 705*7c478bd9Sstevel@tonic-gate shadow_list.prev = &shadow_list; 706*7c478bd9Sstevel@tonic-gate for (i = 0; i < HDL_HASH_TBL_SIZE; i++) { 707*7c478bd9Sstevel@tonic-gate hhash_table[i].hnext = &hhash_table[i]; 708*7c478bd9Sstevel@tonic-gate hhash_table[i].hprev = &hhash_table[i]; 709*7c478bd9Sstevel@tonic-gate dhash_table[i].dnext = &dhash_table[i]; 710*7c478bd9Sstevel@tonic-gate dhash_table[i].dprev = &dhash_table[i]; 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate for (i = 1; i < BOFI_NLINKS; i++) 713*7c478bd9Sstevel@tonic-gate bofi_link_array[i].link = &bofi_link_array[i-1]; 714*7c478bd9Sstevel@tonic-gate bofi_link_freelist = &bofi_link_array[BOFI_NLINKS - 1]; 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * overlay bus_ops structure 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate if (modify_bus_ops(nexus_name, &bofi_bus_ops) == 0) { 719*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, buf); 720*7c478bd9Sstevel@tonic-gate mutex_destroy(&clone_tab_mutex); 721*7c478bd9Sstevel@tonic-gate mutex_destroy(&bofi_mutex); 722*7c478bd9Sstevel@tonic-gate mutex_destroy(&bofi_low_mutex); 723*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate /* 726*7c478bd9Sstevel@tonic-gate * save dip for getinfo 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate our_dip = dip; 729*7c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 730*7c478bd9Sstevel@tonic-gate initialized = 1; 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate static int 737*7c478bd9Sstevel@tonic-gate bofi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 738*7c478bd9Sstevel@tonic-gate { 739*7c478bd9Sstevel@tonic-gate char *name; 740*7c478bd9Sstevel@tonic-gate char buf[80]; 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (cmd != DDI_DETACH) 743*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 744*7c478bd9Sstevel@tonic-gate if (ddi_get_instance(dip) > 0) 745*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 746*7c478bd9Sstevel@tonic-gate if ((name = ddi_get_name(dip)) == NULL) 747*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 748*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s,ctl", name); 749*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 750*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * make sure test bofi is no longer in use 753*7c478bd9Sstevel@tonic-gate */ 754*7c478bd9Sstevel@tonic-gate if (shadow_list.next != &shadow_list || errent_listp != NULL) { 755*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 756*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 757*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 760*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * restore bus_ops structure 764*7c478bd9Sstevel@tonic-gate */ 765*7c478bd9Sstevel@tonic-gate if (reset_bus_ops(nexus_name, &save_bus_ops) == 0) 766*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate mutex_destroy(&clone_tab_mutex); 769*7c478bd9Sstevel@tonic-gate mutex_destroy(&bofi_mutex); 770*7c478bd9Sstevel@tonic-gate mutex_destroy(&bofi_low_mutex); 771*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, buf); 772*7c478bd9Sstevel@tonic-gate our_dip = NULL; 773*7c478bd9Sstevel@tonic-gate initialized = 0; 774*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 779*7c478bd9Sstevel@tonic-gate static int 780*7c478bd9Sstevel@tonic-gate bofi_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 781*7c478bd9Sstevel@tonic-gate { 782*7c478bd9Sstevel@tonic-gate dev_t dev = (dev_t)arg; 783*7c478bd9Sstevel@tonic-gate int minor = (int)getminor(dev); 784*7c478bd9Sstevel@tonic-gate int retval; 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate switch (cmd) { 787*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 788*7c478bd9Sstevel@tonic-gate if (minor != 0 || our_dip == NULL) { 789*7c478bd9Sstevel@tonic-gate *result = (void *)NULL; 790*7c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 791*7c478bd9Sstevel@tonic-gate } else { 792*7c478bd9Sstevel@tonic-gate *result = (void *)our_dip; 793*7c478bd9Sstevel@tonic-gate retval = DDI_SUCCESS; 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate break; 796*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 797*7c478bd9Sstevel@tonic-gate *result = (void *)0; 798*7c478bd9Sstevel@tonic-gate retval = DDI_SUCCESS; 799*7c478bd9Sstevel@tonic-gate break; 800*7c478bd9Sstevel@tonic-gate default: 801*7c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate return (retval); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 808*7c478bd9Sstevel@tonic-gate static int 809*7c478bd9Sstevel@tonic-gate bofi_open(dev_t *devp, int flag, int otyp, cred_t *credp) 810*7c478bd9Sstevel@tonic-gate { 811*7c478bd9Sstevel@tonic-gate int minor = (int)getminor(*devp); 812*7c478bd9Sstevel@tonic-gate struct bofi_errent *softc; 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate /* 815*7c478bd9Sstevel@tonic-gate * only allow open on minor=0 - the clone device 816*7c478bd9Sstevel@tonic-gate */ 817*7c478bd9Sstevel@tonic-gate if (minor != 0) 818*7c478bd9Sstevel@tonic-gate return (ENXIO); 819*7c478bd9Sstevel@tonic-gate /* 820*7c478bd9Sstevel@tonic-gate * fail if not attached 821*7c478bd9Sstevel@tonic-gate */ 822*7c478bd9Sstevel@tonic-gate if (!initialized) 823*7c478bd9Sstevel@tonic-gate return (ENXIO); 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * find a free slot and grab it 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate mutex_enter(&clone_tab_mutex); 828*7c478bd9Sstevel@tonic-gate for (minor = 1; minor < NCLONES; minor++) { 829*7c478bd9Sstevel@tonic-gate if (clone_tab[minor] == 0) { 830*7c478bd9Sstevel@tonic-gate clone_tab[minor] = 1; 831*7c478bd9Sstevel@tonic-gate break; 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate mutex_exit(&clone_tab_mutex); 835*7c478bd9Sstevel@tonic-gate if (minor == NCLONES) 836*7c478bd9Sstevel@tonic-gate return (EAGAIN); 837*7c478bd9Sstevel@tonic-gate /* 838*7c478bd9Sstevel@tonic-gate * soft state structure for this clone is used to maintain a list 839*7c478bd9Sstevel@tonic-gate * of allocated errdefs so they can be freed on close 840*7c478bd9Sstevel@tonic-gate */ 841*7c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(statep, minor) != DDI_SUCCESS) { 842*7c478bd9Sstevel@tonic-gate mutex_enter(&clone_tab_mutex); 843*7c478bd9Sstevel@tonic-gate clone_tab[minor] = 0; 844*7c478bd9Sstevel@tonic-gate mutex_exit(&clone_tab_mutex); 845*7c478bd9Sstevel@tonic-gate return (EAGAIN); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate softc = ddi_get_soft_state(statep, minor); 848*7c478bd9Sstevel@tonic-gate softc->cnext = softc; 849*7c478bd9Sstevel@tonic-gate softc->cprev = softc; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate *devp = makedevice(getmajor(*devp), minor); 852*7c478bd9Sstevel@tonic-gate return (0); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 857*7c478bd9Sstevel@tonic-gate static int 858*7c478bd9Sstevel@tonic-gate bofi_close(dev_t dev, int flag, int otyp, cred_t *credp) 859*7c478bd9Sstevel@tonic-gate { 860*7c478bd9Sstevel@tonic-gate int minor = (int)getminor(dev); 861*7c478bd9Sstevel@tonic-gate struct bofi_errent *softc; 862*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep, *next_ep; 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate softc = ddi_get_soft_state(statep, minor); 865*7c478bd9Sstevel@tonic-gate if (softc == NULL) 866*7c478bd9Sstevel@tonic-gate return (ENXIO); 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * find list of errdefs and free them off 869*7c478bd9Sstevel@tonic-gate */ 870*7c478bd9Sstevel@tonic-gate for (ep = softc->cnext; ep != softc; ) { 871*7c478bd9Sstevel@tonic-gate next_ep = ep->cnext; 872*7c478bd9Sstevel@tonic-gate (void) bofi_errdef_free(ep); 873*7c478bd9Sstevel@tonic-gate ep = next_ep; 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * free clone tab slot 877*7c478bd9Sstevel@tonic-gate */ 878*7c478bd9Sstevel@tonic-gate mutex_enter(&clone_tab_mutex); 879*7c478bd9Sstevel@tonic-gate clone_tab[minor] = 0; 880*7c478bd9Sstevel@tonic-gate mutex_exit(&clone_tab_mutex); 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(statep, minor); 883*7c478bd9Sstevel@tonic-gate return (0); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 888*7c478bd9Sstevel@tonic-gate static int 889*7c478bd9Sstevel@tonic-gate bofi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 890*7c478bd9Sstevel@tonic-gate int *rvalp) 891*7c478bd9Sstevel@tonic-gate { 892*7c478bd9Sstevel@tonic-gate struct bofi_errent *softc; 893*7c478bd9Sstevel@tonic-gate int minor = (int)getminor(dev); 894*7c478bd9Sstevel@tonic-gate struct bofi_errdef errdef; 895*7c478bd9Sstevel@tonic-gate struct bofi_errctl errctl; 896*7c478bd9Sstevel@tonic-gate struct bofi_errstate errstate; 897*7c478bd9Sstevel@tonic-gate void *ed_handle; 898*7c478bd9Sstevel@tonic-gate struct bofi_get_handles get_handles; 899*7c478bd9Sstevel@tonic-gate struct bofi_get_hdl_info hdl_info; 900*7c478bd9Sstevel@tonic-gate struct handle_info *hdlip; 901*7c478bd9Sstevel@tonic-gate struct handle_info *hib; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate char *buffer; 904*7c478bd9Sstevel@tonic-gate char *bufptr; 905*7c478bd9Sstevel@tonic-gate char *endbuf; 906*7c478bd9Sstevel@tonic-gate int req_count, count, err; 907*7c478bd9Sstevel@tonic-gate char *namep; 908*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 909*7c478bd9Sstevel@tonic-gate int retval; 910*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 911*7c478bd9Sstevel@tonic-gate int i; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate switch (cmd) { 914*7c478bd9Sstevel@tonic-gate case BOFI_ADD_DEF: 915*7c478bd9Sstevel@tonic-gate /* 916*7c478bd9Sstevel@tonic-gate * add a new error definition 917*7c478bd9Sstevel@tonic-gate */ 918*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 919*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 920*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 921*7c478bd9Sstevel@tonic-gate { 922*7c478bd9Sstevel@tonic-gate /* 923*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 924*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 925*7c478bd9Sstevel@tonic-gate */ 926*7c478bd9Sstevel@tonic-gate struct bofi_errdef32 errdef_32; 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errdef_32, 929*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef32), mode)) { 930*7c478bd9Sstevel@tonic-gate return (EFAULT); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate errdef.namesize = errdef_32.namesize; 933*7c478bd9Sstevel@tonic-gate (void) strncpy(errdef.name, errdef_32.name, NAMESIZE); 934*7c478bd9Sstevel@tonic-gate errdef.instance = errdef_32.instance; 935*7c478bd9Sstevel@tonic-gate errdef.rnumber = errdef_32.rnumber; 936*7c478bd9Sstevel@tonic-gate errdef.offset = errdef_32.offset; 937*7c478bd9Sstevel@tonic-gate errdef.len = errdef_32.len; 938*7c478bd9Sstevel@tonic-gate errdef.access_type = errdef_32.access_type; 939*7c478bd9Sstevel@tonic-gate errdef.access_count = errdef_32.access_count; 940*7c478bd9Sstevel@tonic-gate errdef.fail_count = errdef_32.fail_count; 941*7c478bd9Sstevel@tonic-gate errdef.acc_chk = errdef_32.acc_chk; 942*7c478bd9Sstevel@tonic-gate errdef.optype = errdef_32.optype; 943*7c478bd9Sstevel@tonic-gate errdef.operand = errdef_32.operand; 944*7c478bd9Sstevel@tonic-gate errdef.log.logsize = errdef_32.log.logsize; 945*7c478bd9Sstevel@tonic-gate errdef.log.entries = errdef_32.log.entries; 946*7c478bd9Sstevel@tonic-gate errdef.log.flags = errdef_32.log.flags; 947*7c478bd9Sstevel@tonic-gate errdef.log.wrapcnt = errdef_32.log.wrapcnt; 948*7c478bd9Sstevel@tonic-gate errdef.log.start_time = errdef_32.log.start_time; 949*7c478bd9Sstevel@tonic-gate errdef.log.stop_time = errdef_32.log.stop_time; 950*7c478bd9Sstevel@tonic-gate errdef.log.logbase = 951*7c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)errdef_32.log.logbase; 952*7c478bd9Sstevel@tonic-gate errdef.errdef_handle = errdef_32.errdef_handle; 953*7c478bd9Sstevel@tonic-gate break; 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 956*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errdef, 957*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef), mode)) 958*7c478bd9Sstevel@tonic-gate return (EFAULT); 959*7c478bd9Sstevel@tonic-gate break; 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 962*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errdef, 963*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef), mode) != 0) 964*7c478bd9Sstevel@tonic-gate return (EFAULT); 965*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 966*7c478bd9Sstevel@tonic-gate /* 967*7c478bd9Sstevel@tonic-gate * do some validation 968*7c478bd9Sstevel@tonic-gate */ 969*7c478bd9Sstevel@tonic-gate if (errdef.fail_count == 0) 970*7c478bd9Sstevel@tonic-gate errdef.optype = 0; 971*7c478bd9Sstevel@tonic-gate if (errdef.optype != 0) { 972*7c478bd9Sstevel@tonic-gate if (errdef.access_type & BOFI_INTR && 973*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_DELAY_INTR && 974*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_LOSE_INTR && 975*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_EXTRA_INTR) 976*7c478bd9Sstevel@tonic-gate return (EINVAL); 977*7c478bd9Sstevel@tonic-gate if ((errdef.access_type & (BOFI_DMA_RW|BOFI_PIO_R)) && 978*7c478bd9Sstevel@tonic-gate errdef.optype == BOFI_NO_TRANSFER) 979*7c478bd9Sstevel@tonic-gate return (EINVAL); 980*7c478bd9Sstevel@tonic-gate if ((errdef.access_type & (BOFI_PIO_RW)) && 981*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_EQUAL && 982*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_OR && 983*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_XOR && 984*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_AND && 985*7c478bd9Sstevel@tonic-gate errdef.optype != BOFI_NO_TRANSFER) 986*7c478bd9Sstevel@tonic-gate return (EINVAL); 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate /* 989*7c478bd9Sstevel@tonic-gate * find softstate for this clone, so we can tag 990*7c478bd9Sstevel@tonic-gate * new errdef on to it 991*7c478bd9Sstevel@tonic-gate */ 992*7c478bd9Sstevel@tonic-gate softc = ddi_get_soft_state(statep, minor); 993*7c478bd9Sstevel@tonic-gate if (softc == NULL) 994*7c478bd9Sstevel@tonic-gate return (ENXIO); 995*7c478bd9Sstevel@tonic-gate /* 996*7c478bd9Sstevel@tonic-gate * read in name 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate if (errdef.namesize > NAMESIZE) 999*7c478bd9Sstevel@tonic-gate return (EINVAL); 1000*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errdef.namesize+1, KM_SLEEP); 1001*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errdef.name, errdef.namesize); 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate if (bofi_errdef_alloc(&errdef, namep, softc) != DDI_SUCCESS) { 1004*7c478bd9Sstevel@tonic-gate (void) bofi_errdef_free((struct bofi_errent *) 1005*7c478bd9Sstevel@tonic-gate (uintptr_t)errdef.errdef_handle); 1006*7c478bd9Sstevel@tonic-gate kmem_free(namep, errdef.namesize+1); 1007*7c478bd9Sstevel@tonic-gate return (EINVAL); 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate /* 1010*7c478bd9Sstevel@tonic-gate * copy out errdef again, including filled in errdef_handle 1011*7c478bd9Sstevel@tonic-gate */ 1012*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1013*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1014*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1015*7c478bd9Sstevel@tonic-gate { 1016*7c478bd9Sstevel@tonic-gate /* 1017*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1018*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1019*7c478bd9Sstevel@tonic-gate */ 1020*7c478bd9Sstevel@tonic-gate struct bofi_errdef32 errdef_32; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate errdef_32.namesize = errdef.namesize; 1023*7c478bd9Sstevel@tonic-gate (void) strncpy(errdef_32.name, errdef.name, NAMESIZE); 1024*7c478bd9Sstevel@tonic-gate errdef_32.instance = errdef.instance; 1025*7c478bd9Sstevel@tonic-gate errdef_32.rnumber = errdef.rnumber; 1026*7c478bd9Sstevel@tonic-gate errdef_32.offset = errdef.offset; 1027*7c478bd9Sstevel@tonic-gate errdef_32.len = errdef.len; 1028*7c478bd9Sstevel@tonic-gate errdef_32.access_type = errdef.access_type; 1029*7c478bd9Sstevel@tonic-gate errdef_32.access_count = errdef.access_count; 1030*7c478bd9Sstevel@tonic-gate errdef_32.fail_count = errdef.fail_count; 1031*7c478bd9Sstevel@tonic-gate errdef_32.acc_chk = errdef.acc_chk; 1032*7c478bd9Sstevel@tonic-gate errdef_32.optype = errdef.optype; 1033*7c478bd9Sstevel@tonic-gate errdef_32.operand = errdef.operand; 1034*7c478bd9Sstevel@tonic-gate errdef_32.log.logsize = errdef.log.logsize; 1035*7c478bd9Sstevel@tonic-gate errdef_32.log.entries = errdef.log.entries; 1036*7c478bd9Sstevel@tonic-gate errdef_32.log.flags = errdef.log.flags; 1037*7c478bd9Sstevel@tonic-gate errdef_32.log.wrapcnt = errdef.log.wrapcnt; 1038*7c478bd9Sstevel@tonic-gate errdef_32.log.start_time = errdef.log.start_time; 1039*7c478bd9Sstevel@tonic-gate errdef_32.log.stop_time = errdef.log.stop_time; 1040*7c478bd9Sstevel@tonic-gate errdef_32.log.logbase = 1041*7c478bd9Sstevel@tonic-gate (caddr32_t)(uintptr_t)errdef.log.logbase; 1042*7c478bd9Sstevel@tonic-gate errdef_32.errdef_handle = errdef.errdef_handle; 1043*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errdef_32, (void *)arg, 1044*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef32), mode) != 0) { 1045*7c478bd9Sstevel@tonic-gate (void) bofi_errdef_free((struct bofi_errent *) 1046*7c478bd9Sstevel@tonic-gate errdef.errdef_handle); 1047*7c478bd9Sstevel@tonic-gate kmem_free(namep, errdef.namesize+1); 1048*7c478bd9Sstevel@tonic-gate return (EFAULT); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate break; 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1053*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errdef, (void *)arg, 1054*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef), mode) != 0) { 1055*7c478bd9Sstevel@tonic-gate (void) bofi_errdef_free((struct bofi_errent *) 1056*7c478bd9Sstevel@tonic-gate errdef.errdef_handle); 1057*7c478bd9Sstevel@tonic-gate kmem_free(namep, errdef.namesize+1); 1058*7c478bd9Sstevel@tonic-gate return (EFAULT); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate break; 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1063*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errdef, (void *)arg, 1064*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errdef), mode) != 0) { 1065*7c478bd9Sstevel@tonic-gate (void) bofi_errdef_free((struct bofi_errent *) 1066*7c478bd9Sstevel@tonic-gate (uintptr_t)errdef.errdef_handle); 1067*7c478bd9Sstevel@tonic-gate kmem_free(namep, errdef.namesize+1); 1068*7c478bd9Sstevel@tonic-gate return (EFAULT); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1071*7c478bd9Sstevel@tonic-gate return (0); 1072*7c478bd9Sstevel@tonic-gate case BOFI_DEL_DEF: 1073*7c478bd9Sstevel@tonic-gate /* 1074*7c478bd9Sstevel@tonic-gate * delete existing errdef 1075*7c478bd9Sstevel@tonic-gate */ 1076*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &ed_handle, 1077*7c478bd9Sstevel@tonic-gate sizeof (void *), mode) != 0) 1078*7c478bd9Sstevel@tonic-gate return (EFAULT); 1079*7c478bd9Sstevel@tonic-gate return (bofi_errdef_free((struct bofi_errent *)ed_handle)); 1080*7c478bd9Sstevel@tonic-gate case BOFI_START: 1081*7c478bd9Sstevel@tonic-gate /* 1082*7c478bd9Sstevel@tonic-gate * start all errdefs corresponding to 1083*7c478bd9Sstevel@tonic-gate * this name and instance 1084*7c478bd9Sstevel@tonic-gate */ 1085*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1086*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1087*7c478bd9Sstevel@tonic-gate return (EFAULT); 1088*7c478bd9Sstevel@tonic-gate /* 1089*7c478bd9Sstevel@tonic-gate * copy in name 1090*7c478bd9Sstevel@tonic-gate */ 1091*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1092*7c478bd9Sstevel@tonic-gate return (EINVAL); 1093*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1094*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1095*7c478bd9Sstevel@tonic-gate bofi_start(&errctl, namep); 1096*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1097*7c478bd9Sstevel@tonic-gate return (0); 1098*7c478bd9Sstevel@tonic-gate case BOFI_STOP: 1099*7c478bd9Sstevel@tonic-gate /* 1100*7c478bd9Sstevel@tonic-gate * stop all errdefs corresponding to 1101*7c478bd9Sstevel@tonic-gate * this name and instance 1102*7c478bd9Sstevel@tonic-gate */ 1103*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1104*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1105*7c478bd9Sstevel@tonic-gate return (EFAULT); 1106*7c478bd9Sstevel@tonic-gate /* 1107*7c478bd9Sstevel@tonic-gate * copy in name 1108*7c478bd9Sstevel@tonic-gate */ 1109*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1110*7c478bd9Sstevel@tonic-gate return (EINVAL); 1111*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1112*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1113*7c478bd9Sstevel@tonic-gate bofi_stop(&errctl, namep); 1114*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1115*7c478bd9Sstevel@tonic-gate return (0); 1116*7c478bd9Sstevel@tonic-gate case BOFI_BROADCAST: 1117*7c478bd9Sstevel@tonic-gate /* 1118*7c478bd9Sstevel@tonic-gate * wakeup all errdefs corresponding to 1119*7c478bd9Sstevel@tonic-gate * this name and instance 1120*7c478bd9Sstevel@tonic-gate */ 1121*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1122*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1123*7c478bd9Sstevel@tonic-gate return (EFAULT); 1124*7c478bd9Sstevel@tonic-gate /* 1125*7c478bd9Sstevel@tonic-gate * copy in name 1126*7c478bd9Sstevel@tonic-gate */ 1127*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1128*7c478bd9Sstevel@tonic-gate return (EINVAL); 1129*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1130*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1131*7c478bd9Sstevel@tonic-gate bofi_broadcast(&errctl, namep); 1132*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1133*7c478bd9Sstevel@tonic-gate return (0); 1134*7c478bd9Sstevel@tonic-gate case BOFI_CLEAR_ACC_CHK: 1135*7c478bd9Sstevel@tonic-gate /* 1136*7c478bd9Sstevel@tonic-gate * clear "acc_chk" for all errdefs corresponding to 1137*7c478bd9Sstevel@tonic-gate * this name and instance 1138*7c478bd9Sstevel@tonic-gate */ 1139*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1140*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1141*7c478bd9Sstevel@tonic-gate return (EFAULT); 1142*7c478bd9Sstevel@tonic-gate /* 1143*7c478bd9Sstevel@tonic-gate * copy in name 1144*7c478bd9Sstevel@tonic-gate */ 1145*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1146*7c478bd9Sstevel@tonic-gate return (EINVAL); 1147*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1148*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1149*7c478bd9Sstevel@tonic-gate bofi_clear_acc_chk(&errctl, namep); 1150*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1151*7c478bd9Sstevel@tonic-gate return (0); 1152*7c478bd9Sstevel@tonic-gate case BOFI_CLEAR_ERRORS: 1153*7c478bd9Sstevel@tonic-gate /* 1154*7c478bd9Sstevel@tonic-gate * set "fail_count" to 0 for all errdefs corresponding to 1155*7c478bd9Sstevel@tonic-gate * this name and instance whose "access_count" 1156*7c478bd9Sstevel@tonic-gate * has expired. 1157*7c478bd9Sstevel@tonic-gate */ 1158*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1159*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1160*7c478bd9Sstevel@tonic-gate return (EFAULT); 1161*7c478bd9Sstevel@tonic-gate /* 1162*7c478bd9Sstevel@tonic-gate * copy in name 1163*7c478bd9Sstevel@tonic-gate */ 1164*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1165*7c478bd9Sstevel@tonic-gate return (EINVAL); 1166*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1167*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1168*7c478bd9Sstevel@tonic-gate bofi_clear_errors(&errctl, namep); 1169*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1170*7c478bd9Sstevel@tonic-gate return (0); 1171*7c478bd9Sstevel@tonic-gate case BOFI_CLEAR_ERRDEFS: 1172*7c478bd9Sstevel@tonic-gate /* 1173*7c478bd9Sstevel@tonic-gate * set "access_count" and "fail_count" to 0 for all errdefs 1174*7c478bd9Sstevel@tonic-gate * corresponding to this name and instance 1175*7c478bd9Sstevel@tonic-gate */ 1176*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errctl, 1177*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errctl), mode) != 0) 1178*7c478bd9Sstevel@tonic-gate return (EFAULT); 1179*7c478bd9Sstevel@tonic-gate /* 1180*7c478bd9Sstevel@tonic-gate * copy in name 1181*7c478bd9Sstevel@tonic-gate */ 1182*7c478bd9Sstevel@tonic-gate if (errctl.namesize > NAMESIZE) 1183*7c478bd9Sstevel@tonic-gate return (EINVAL); 1184*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(errctl.namesize+1, KM_SLEEP); 1185*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, errctl.name, errctl.namesize); 1186*7c478bd9Sstevel@tonic-gate bofi_clear_errdefs(&errctl, namep); 1187*7c478bd9Sstevel@tonic-gate kmem_free(namep, errctl.namesize+1); 1188*7c478bd9Sstevel@tonic-gate return (0); 1189*7c478bd9Sstevel@tonic-gate case BOFI_CHK_STATE: 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate struct acc_log_elem *klg; 1192*7c478bd9Sstevel@tonic-gate size_t uls; 1193*7c478bd9Sstevel@tonic-gate /* 1194*7c478bd9Sstevel@tonic-gate * get state for this errdef - read in dummy errstate 1195*7c478bd9Sstevel@tonic-gate * with just the errdef_handle filled in 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1198*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1199*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1200*7c478bd9Sstevel@tonic-gate { 1201*7c478bd9Sstevel@tonic-gate /* 1202*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1203*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1204*7c478bd9Sstevel@tonic-gate */ 1205*7c478bd9Sstevel@tonic-gate struct bofi_errstate32 errstate_32; 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate_32, 1208*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate32), mode) != 0) { 1209*7c478bd9Sstevel@tonic-gate return (EFAULT); 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate errstate.fail_time = errstate_32.fail_time; 1212*7c478bd9Sstevel@tonic-gate errstate.msg_time = errstate_32.msg_time; 1213*7c478bd9Sstevel@tonic-gate errstate.access_count = errstate_32.access_count; 1214*7c478bd9Sstevel@tonic-gate errstate.fail_count = errstate_32.fail_count; 1215*7c478bd9Sstevel@tonic-gate errstate.acc_chk = errstate_32.acc_chk; 1216*7c478bd9Sstevel@tonic-gate errstate.errmsg_count = errstate_32.errmsg_count; 1217*7c478bd9Sstevel@tonic-gate (void) strncpy(errstate.buffer, errstate_32.buffer, 1218*7c478bd9Sstevel@tonic-gate ERRMSGSIZE); 1219*7c478bd9Sstevel@tonic-gate errstate.severity = errstate_32.severity; 1220*7c478bd9Sstevel@tonic-gate errstate.log.logsize = errstate_32.log.logsize; 1221*7c478bd9Sstevel@tonic-gate errstate.log.entries = errstate_32.log.entries; 1222*7c478bd9Sstevel@tonic-gate errstate.log.flags = errstate_32.log.flags; 1223*7c478bd9Sstevel@tonic-gate errstate.log.wrapcnt = errstate_32.log.wrapcnt; 1224*7c478bd9Sstevel@tonic-gate errstate.log.start_time = errstate_32.log.start_time; 1225*7c478bd9Sstevel@tonic-gate errstate.log.stop_time = errstate_32.log.stop_time; 1226*7c478bd9Sstevel@tonic-gate errstate.log.logbase = 1227*7c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)errstate_32.log.logbase; 1228*7c478bd9Sstevel@tonic-gate errstate.errdef_handle = errstate_32.errdef_handle; 1229*7c478bd9Sstevel@tonic-gate break; 1230*7c478bd9Sstevel@tonic-gate } 1231*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1232*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate, 1233*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1234*7c478bd9Sstevel@tonic-gate return (EFAULT); 1235*7c478bd9Sstevel@tonic-gate break; 1236*7c478bd9Sstevel@tonic-gate } 1237*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1238*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate, 1239*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1240*7c478bd9Sstevel@tonic-gate return (EFAULT); 1241*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1242*7c478bd9Sstevel@tonic-gate if ((retval = bofi_errdef_check(&errstate, &klg)) == EINVAL) 1243*7c478bd9Sstevel@tonic-gate return (EINVAL); 1244*7c478bd9Sstevel@tonic-gate /* 1245*7c478bd9Sstevel@tonic-gate * copy out real errstate structure 1246*7c478bd9Sstevel@tonic-gate */ 1247*7c478bd9Sstevel@tonic-gate uls = errstate.log.logsize; 1248*7c478bd9Sstevel@tonic-gate if (errstate.log.entries > uls && uls) 1249*7c478bd9Sstevel@tonic-gate /* insufficient user memory */ 1250*7c478bd9Sstevel@tonic-gate errstate.log.entries = uls; 1251*7c478bd9Sstevel@tonic-gate /* always pass back a time */ 1252*7c478bd9Sstevel@tonic-gate if (errstate.log.stop_time == 0ul) 1253*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, &(errstate.log.stop_time)); 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1256*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1257*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1258*7c478bd9Sstevel@tonic-gate { 1259*7c478bd9Sstevel@tonic-gate /* 1260*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1261*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1262*7c478bd9Sstevel@tonic-gate */ 1263*7c478bd9Sstevel@tonic-gate struct bofi_errstate32 errstate_32; 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate errstate_32.fail_time = errstate.fail_time; 1266*7c478bd9Sstevel@tonic-gate errstate_32.msg_time = errstate.msg_time; 1267*7c478bd9Sstevel@tonic-gate errstate_32.access_count = errstate.access_count; 1268*7c478bd9Sstevel@tonic-gate errstate_32.fail_count = errstate.fail_count; 1269*7c478bd9Sstevel@tonic-gate errstate_32.acc_chk = errstate.acc_chk; 1270*7c478bd9Sstevel@tonic-gate errstate_32.errmsg_count = errstate.errmsg_count; 1271*7c478bd9Sstevel@tonic-gate (void) strncpy(errstate_32.buffer, errstate.buffer, 1272*7c478bd9Sstevel@tonic-gate ERRMSGSIZE); 1273*7c478bd9Sstevel@tonic-gate errstate_32.severity = errstate.severity; 1274*7c478bd9Sstevel@tonic-gate errstate_32.log.logsize = errstate.log.logsize; 1275*7c478bd9Sstevel@tonic-gate errstate_32.log.entries = errstate.log.entries; 1276*7c478bd9Sstevel@tonic-gate errstate_32.log.flags = errstate.log.flags; 1277*7c478bd9Sstevel@tonic-gate errstate_32.log.wrapcnt = errstate.log.wrapcnt; 1278*7c478bd9Sstevel@tonic-gate errstate_32.log.start_time = errstate.log.start_time; 1279*7c478bd9Sstevel@tonic-gate errstate_32.log.stop_time = errstate.log.stop_time; 1280*7c478bd9Sstevel@tonic-gate errstate_32.log.logbase = 1281*7c478bd9Sstevel@tonic-gate (caddr32_t)(uintptr_t)errstate.log.logbase; 1282*7c478bd9Sstevel@tonic-gate errstate_32.errdef_handle = errstate.errdef_handle; 1283*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate_32, (void *)arg, 1284*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate32), mode) != 0) 1285*7c478bd9Sstevel@tonic-gate return (EFAULT); 1286*7c478bd9Sstevel@tonic-gate break; 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1289*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate, (void *)arg, 1290*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1291*7c478bd9Sstevel@tonic-gate return (EFAULT); 1292*7c478bd9Sstevel@tonic-gate break; 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1295*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate, (void *)arg, 1296*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1297*7c478bd9Sstevel@tonic-gate return (EFAULT); 1298*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1299*7c478bd9Sstevel@tonic-gate if (uls && errstate.log.entries && 1300*7c478bd9Sstevel@tonic-gate ddi_copyout(klg, errstate.log.logbase, 1301*7c478bd9Sstevel@tonic-gate errstate.log.entries * sizeof (struct acc_log_elem), 1302*7c478bd9Sstevel@tonic-gate mode) != 0) { 1303*7c478bd9Sstevel@tonic-gate return (EFAULT); 1304*7c478bd9Sstevel@tonic-gate } 1305*7c478bd9Sstevel@tonic-gate return (retval); 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate case BOFI_CHK_STATE_W: 1308*7c478bd9Sstevel@tonic-gate { 1309*7c478bd9Sstevel@tonic-gate struct acc_log_elem *klg; 1310*7c478bd9Sstevel@tonic-gate size_t uls; 1311*7c478bd9Sstevel@tonic-gate /* 1312*7c478bd9Sstevel@tonic-gate * get state for this errdef - read in dummy errstate 1313*7c478bd9Sstevel@tonic-gate * with just the errdef_handle filled in. Then wait for 1314*7c478bd9Sstevel@tonic-gate * a ddi_report_fault message to come back 1315*7c478bd9Sstevel@tonic-gate */ 1316*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1317*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1318*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1319*7c478bd9Sstevel@tonic-gate { 1320*7c478bd9Sstevel@tonic-gate /* 1321*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1322*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1323*7c478bd9Sstevel@tonic-gate */ 1324*7c478bd9Sstevel@tonic-gate struct bofi_errstate32 errstate_32; 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate_32, 1327*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate32), mode) != 0) { 1328*7c478bd9Sstevel@tonic-gate return (EFAULT); 1329*7c478bd9Sstevel@tonic-gate } 1330*7c478bd9Sstevel@tonic-gate errstate.fail_time = errstate_32.fail_time; 1331*7c478bd9Sstevel@tonic-gate errstate.msg_time = errstate_32.msg_time; 1332*7c478bd9Sstevel@tonic-gate errstate.access_count = errstate_32.access_count; 1333*7c478bd9Sstevel@tonic-gate errstate.fail_count = errstate_32.fail_count; 1334*7c478bd9Sstevel@tonic-gate errstate.acc_chk = errstate_32.acc_chk; 1335*7c478bd9Sstevel@tonic-gate errstate.errmsg_count = errstate_32.errmsg_count; 1336*7c478bd9Sstevel@tonic-gate (void) strncpy(errstate.buffer, errstate_32.buffer, 1337*7c478bd9Sstevel@tonic-gate ERRMSGSIZE); 1338*7c478bd9Sstevel@tonic-gate errstate.severity = errstate_32.severity; 1339*7c478bd9Sstevel@tonic-gate errstate.log.logsize = errstate_32.log.logsize; 1340*7c478bd9Sstevel@tonic-gate errstate.log.entries = errstate_32.log.entries; 1341*7c478bd9Sstevel@tonic-gate errstate.log.flags = errstate_32.log.flags; 1342*7c478bd9Sstevel@tonic-gate errstate.log.wrapcnt = errstate_32.log.wrapcnt; 1343*7c478bd9Sstevel@tonic-gate errstate.log.start_time = errstate_32.log.start_time; 1344*7c478bd9Sstevel@tonic-gate errstate.log.stop_time = errstate_32.log.stop_time; 1345*7c478bd9Sstevel@tonic-gate errstate.log.logbase = 1346*7c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)errstate_32.log.logbase; 1347*7c478bd9Sstevel@tonic-gate errstate.errdef_handle = errstate_32.errdef_handle; 1348*7c478bd9Sstevel@tonic-gate break; 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1351*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate, 1352*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1353*7c478bd9Sstevel@tonic-gate return (EFAULT); 1354*7c478bd9Sstevel@tonic-gate break; 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1357*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &errstate, 1358*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1359*7c478bd9Sstevel@tonic-gate return (EFAULT); 1360*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1361*7c478bd9Sstevel@tonic-gate if ((retval = bofi_errdef_check_w(&errstate, &klg)) == EINVAL) 1362*7c478bd9Sstevel@tonic-gate return (EINVAL); 1363*7c478bd9Sstevel@tonic-gate /* 1364*7c478bd9Sstevel@tonic-gate * copy out real errstate structure 1365*7c478bd9Sstevel@tonic-gate */ 1366*7c478bd9Sstevel@tonic-gate uls = errstate.log.logsize; 1367*7c478bd9Sstevel@tonic-gate uls = errstate.log.logsize; 1368*7c478bd9Sstevel@tonic-gate if (errstate.log.entries > uls && uls) 1369*7c478bd9Sstevel@tonic-gate /* insufficient user memory */ 1370*7c478bd9Sstevel@tonic-gate errstate.log.entries = uls; 1371*7c478bd9Sstevel@tonic-gate /* always pass back a time */ 1372*7c478bd9Sstevel@tonic-gate if (errstate.log.stop_time == 0ul) 1373*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, &(errstate.log.stop_time)); 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1376*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1377*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1378*7c478bd9Sstevel@tonic-gate { 1379*7c478bd9Sstevel@tonic-gate /* 1380*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1381*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1382*7c478bd9Sstevel@tonic-gate */ 1383*7c478bd9Sstevel@tonic-gate struct bofi_errstate32 errstate_32; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate errstate_32.fail_time = errstate.fail_time; 1386*7c478bd9Sstevel@tonic-gate errstate_32.msg_time = errstate.msg_time; 1387*7c478bd9Sstevel@tonic-gate errstate_32.access_count = errstate.access_count; 1388*7c478bd9Sstevel@tonic-gate errstate_32.fail_count = errstate.fail_count; 1389*7c478bd9Sstevel@tonic-gate errstate_32.acc_chk = errstate.acc_chk; 1390*7c478bd9Sstevel@tonic-gate errstate_32.errmsg_count = errstate.errmsg_count; 1391*7c478bd9Sstevel@tonic-gate (void) strncpy(errstate_32.buffer, errstate.buffer, 1392*7c478bd9Sstevel@tonic-gate ERRMSGSIZE); 1393*7c478bd9Sstevel@tonic-gate errstate_32.severity = errstate.severity; 1394*7c478bd9Sstevel@tonic-gate errstate_32.log.logsize = errstate.log.logsize; 1395*7c478bd9Sstevel@tonic-gate errstate_32.log.entries = errstate.log.entries; 1396*7c478bd9Sstevel@tonic-gate errstate_32.log.flags = errstate.log.flags; 1397*7c478bd9Sstevel@tonic-gate errstate_32.log.wrapcnt = errstate.log.wrapcnt; 1398*7c478bd9Sstevel@tonic-gate errstate_32.log.start_time = errstate.log.start_time; 1399*7c478bd9Sstevel@tonic-gate errstate_32.log.stop_time = errstate.log.stop_time; 1400*7c478bd9Sstevel@tonic-gate errstate_32.log.logbase = 1401*7c478bd9Sstevel@tonic-gate (caddr32_t)(uintptr_t)errstate.log.logbase; 1402*7c478bd9Sstevel@tonic-gate errstate_32.errdef_handle = errstate.errdef_handle; 1403*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate_32, (void *)arg, 1404*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate32), mode) != 0) 1405*7c478bd9Sstevel@tonic-gate return (EFAULT); 1406*7c478bd9Sstevel@tonic-gate break; 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1409*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate, (void *)arg, 1410*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1411*7c478bd9Sstevel@tonic-gate return (EFAULT); 1412*7c478bd9Sstevel@tonic-gate break; 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1415*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&errstate, (void *)arg, 1416*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_errstate), mode) != 0) 1417*7c478bd9Sstevel@tonic-gate return (EFAULT); 1418*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate if (uls && errstate.log.entries && 1421*7c478bd9Sstevel@tonic-gate ddi_copyout(klg, errstate.log.logbase, 1422*7c478bd9Sstevel@tonic-gate errstate.log.entries * sizeof (struct acc_log_elem), 1423*7c478bd9Sstevel@tonic-gate mode) != 0) { 1424*7c478bd9Sstevel@tonic-gate return (EFAULT); 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate return (retval); 1427*7c478bd9Sstevel@tonic-gate } 1428*7c478bd9Sstevel@tonic-gate case BOFI_GET_HANDLES: 1429*7c478bd9Sstevel@tonic-gate /* 1430*7c478bd9Sstevel@tonic-gate * display existing handles 1431*7c478bd9Sstevel@tonic-gate */ 1432*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1433*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1434*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1435*7c478bd9Sstevel@tonic-gate { 1436*7c478bd9Sstevel@tonic-gate /* 1437*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1438*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1439*7c478bd9Sstevel@tonic-gate */ 1440*7c478bd9Sstevel@tonic-gate struct bofi_get_handles32 get_handles_32; 1441*7c478bd9Sstevel@tonic-gate 1442*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &get_handles_32, 1443*7c478bd9Sstevel@tonic-gate sizeof (get_handles_32), mode) != 0) { 1444*7c478bd9Sstevel@tonic-gate return (EFAULT); 1445*7c478bd9Sstevel@tonic-gate } 1446*7c478bd9Sstevel@tonic-gate get_handles.namesize = get_handles_32.namesize; 1447*7c478bd9Sstevel@tonic-gate (void) strncpy(get_handles.name, get_handles_32.name, 1448*7c478bd9Sstevel@tonic-gate NAMESIZE); 1449*7c478bd9Sstevel@tonic-gate get_handles.instance = get_handles_32.instance; 1450*7c478bd9Sstevel@tonic-gate get_handles.count = get_handles_32.count; 1451*7c478bd9Sstevel@tonic-gate get_handles.buffer = 1452*7c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)get_handles_32.buffer; 1453*7c478bd9Sstevel@tonic-gate break; 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1456*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &get_handles, 1457*7c478bd9Sstevel@tonic-gate sizeof (get_handles), mode) != 0) 1458*7c478bd9Sstevel@tonic-gate return (EFAULT); 1459*7c478bd9Sstevel@tonic-gate break; 1460*7c478bd9Sstevel@tonic-gate } 1461*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1462*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &get_handles, 1463*7c478bd9Sstevel@tonic-gate sizeof (get_handles), mode) != 0) 1464*7c478bd9Sstevel@tonic-gate return (EFAULT); 1465*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1466*7c478bd9Sstevel@tonic-gate /* 1467*7c478bd9Sstevel@tonic-gate * read in name 1468*7c478bd9Sstevel@tonic-gate */ 1469*7c478bd9Sstevel@tonic-gate if (get_handles.namesize > NAMESIZE) 1470*7c478bd9Sstevel@tonic-gate return (EINVAL); 1471*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(get_handles.namesize+1, KM_SLEEP); 1472*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, get_handles.name, get_handles.namesize); 1473*7c478bd9Sstevel@tonic-gate req_count = get_handles.count; 1474*7c478bd9Sstevel@tonic-gate bufptr = buffer = kmem_zalloc(req_count, KM_SLEEP); 1475*7c478bd9Sstevel@tonic-gate endbuf = bufptr + req_count; 1476*7c478bd9Sstevel@tonic-gate /* 1477*7c478bd9Sstevel@tonic-gate * display existing handles 1478*7c478bd9Sstevel@tonic-gate */ 1479*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1480*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 1481*7c478bd9Sstevel@tonic-gate for (i = 0; i < HDL_HASH_TBL_SIZE; i++) { 1482*7c478bd9Sstevel@tonic-gate hhashp = &hhash_table[i]; 1483*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) { 1484*7c478bd9Sstevel@tonic-gate if (!driver_under_test(hp->dip)) 1485*7c478bd9Sstevel@tonic-gate continue; 1486*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(ddi_get_name(hp->dip)) != 1487*7c478bd9Sstevel@tonic-gate ddi_name_to_major(namep)) 1488*7c478bd9Sstevel@tonic-gate continue; 1489*7c478bd9Sstevel@tonic-gate if (hp->instance != get_handles.instance) 1490*7c478bd9Sstevel@tonic-gate continue; 1491*7c478bd9Sstevel@tonic-gate /* 1492*7c478bd9Sstevel@tonic-gate * print information per handle - note that 1493*7c478bd9Sstevel@tonic-gate * DMA* means an unbound DMA handle 1494*7c478bd9Sstevel@tonic-gate */ 1495*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, (size_t)(endbuf-bufptr), 1496*7c478bd9Sstevel@tonic-gate " %s %d %s ", hp->name, hp->instance, 1497*7c478bd9Sstevel@tonic-gate (hp->type == BOFI_INT_HDL) ? "INTR" : 1498*7c478bd9Sstevel@tonic-gate (hp->type == BOFI_ACC_HDL) ? "PIO" : 1499*7c478bd9Sstevel@tonic-gate (hp->type == BOFI_DMA_HDL) ? "DMA" : 1500*7c478bd9Sstevel@tonic-gate (hp->hparrayp != NULL) ? "DVMA" : "DMA*"); 1501*7c478bd9Sstevel@tonic-gate bufptr += strlen(bufptr); 1502*7c478bd9Sstevel@tonic-gate if (hp->type == BOFI_ACC_HDL) { 1503*7c478bd9Sstevel@tonic-gate if (hp->len == INT_MAX - hp->offset) 1504*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, 1505*7c478bd9Sstevel@tonic-gate (size_t)(endbuf-bufptr), 1506*7c478bd9Sstevel@tonic-gate "reg set %d off 0x%llx\n", 1507*7c478bd9Sstevel@tonic-gate hp->rnumber, hp->offset); 1508*7c478bd9Sstevel@tonic-gate else 1509*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, 1510*7c478bd9Sstevel@tonic-gate (size_t)(endbuf-bufptr), 1511*7c478bd9Sstevel@tonic-gate "reg set %d off 0x%llx" 1512*7c478bd9Sstevel@tonic-gate " len 0x%llx\n", 1513*7c478bd9Sstevel@tonic-gate hp->rnumber, hp->offset, 1514*7c478bd9Sstevel@tonic-gate hp->len); 1515*7c478bd9Sstevel@tonic-gate } else if (hp->type == BOFI_DMA_HDL) 1516*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, 1517*7c478bd9Sstevel@tonic-gate (size_t)(endbuf-bufptr), 1518*7c478bd9Sstevel@tonic-gate "handle no %d len 0x%llx" 1519*7c478bd9Sstevel@tonic-gate " addr 0x%p\n", hp->rnumber, 1520*7c478bd9Sstevel@tonic-gate hp->len, (void *)hp->addr); 1521*7c478bd9Sstevel@tonic-gate else if (hp->type == BOFI_NULL && 1522*7c478bd9Sstevel@tonic-gate hp->hparrayp == NULL) 1523*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, 1524*7c478bd9Sstevel@tonic-gate (size_t)(endbuf-bufptr), 1525*7c478bd9Sstevel@tonic-gate "handle no %d\n", hp->rnumber); 1526*7c478bd9Sstevel@tonic-gate else 1527*7c478bd9Sstevel@tonic-gate (void) snprintf(bufptr, 1528*7c478bd9Sstevel@tonic-gate (size_t)(endbuf-bufptr), "\n"); 1529*7c478bd9Sstevel@tonic-gate bufptr += strlen(bufptr); 1530*7c478bd9Sstevel@tonic-gate } 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 1533*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1534*7c478bd9Sstevel@tonic-gate err = ddi_copyout(buffer, get_handles.buffer, req_count, mode); 1535*7c478bd9Sstevel@tonic-gate kmem_free(namep, get_handles.namesize+1); 1536*7c478bd9Sstevel@tonic-gate kmem_free(buffer, req_count); 1537*7c478bd9Sstevel@tonic-gate if (err != 0) 1538*7c478bd9Sstevel@tonic-gate return (EFAULT); 1539*7c478bd9Sstevel@tonic-gate else 1540*7c478bd9Sstevel@tonic-gate return (0); 1541*7c478bd9Sstevel@tonic-gate case BOFI_GET_HANDLE_INFO: 1542*7c478bd9Sstevel@tonic-gate /* 1543*7c478bd9Sstevel@tonic-gate * display existing handles 1544*7c478bd9Sstevel@tonic-gate */ 1545*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1546*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1547*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1548*7c478bd9Sstevel@tonic-gate { 1549*7c478bd9Sstevel@tonic-gate /* 1550*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1551*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1552*7c478bd9Sstevel@tonic-gate */ 1553*7c478bd9Sstevel@tonic-gate struct bofi_get_hdl_info32 hdl_info_32; 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &hdl_info_32, 1556*7c478bd9Sstevel@tonic-gate sizeof (hdl_info_32), mode)) { 1557*7c478bd9Sstevel@tonic-gate return (EFAULT); 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate hdl_info.namesize = hdl_info_32.namesize; 1560*7c478bd9Sstevel@tonic-gate (void) strncpy(hdl_info.name, hdl_info_32.name, 1561*7c478bd9Sstevel@tonic-gate NAMESIZE); 1562*7c478bd9Sstevel@tonic-gate hdl_info.count = hdl_info_32.count; 1563*7c478bd9Sstevel@tonic-gate hdl_info.hdli = (caddr_t)(uintptr_t)hdl_info_32.hdli; 1564*7c478bd9Sstevel@tonic-gate break; 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1567*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &hdl_info, 1568*7c478bd9Sstevel@tonic-gate sizeof (hdl_info), mode)) 1569*7c478bd9Sstevel@tonic-gate return (EFAULT); 1570*7c478bd9Sstevel@tonic-gate break; 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1573*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &hdl_info, 1574*7c478bd9Sstevel@tonic-gate sizeof (hdl_info), mode)) 1575*7c478bd9Sstevel@tonic-gate return (EFAULT); 1576*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1577*7c478bd9Sstevel@tonic-gate if (hdl_info.namesize > NAMESIZE) 1578*7c478bd9Sstevel@tonic-gate return (EINVAL); 1579*7c478bd9Sstevel@tonic-gate namep = kmem_zalloc(hdl_info.namesize + 1, KM_SLEEP); 1580*7c478bd9Sstevel@tonic-gate (void) strncpy(namep, hdl_info.name, hdl_info.namesize); 1581*7c478bd9Sstevel@tonic-gate req_count = hdl_info.count; 1582*7c478bd9Sstevel@tonic-gate count = hdl_info.count = 0; /* the actual no of handles */ 1583*7c478bd9Sstevel@tonic-gate if (req_count > 0) { 1584*7c478bd9Sstevel@tonic-gate hib = hdlip = 1585*7c478bd9Sstevel@tonic-gate kmem_zalloc(req_count * sizeof (struct handle_info), 1586*7c478bd9Sstevel@tonic-gate KM_SLEEP); 1587*7c478bd9Sstevel@tonic-gate } else { 1588*7c478bd9Sstevel@tonic-gate hib = hdlip = 0; 1589*7c478bd9Sstevel@tonic-gate req_count = hdl_info.count = 0; 1590*7c478bd9Sstevel@tonic-gate } 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate /* 1593*7c478bd9Sstevel@tonic-gate * display existing handles 1594*7c478bd9Sstevel@tonic-gate */ 1595*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1596*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 1597*7c478bd9Sstevel@tonic-gate for (i = 0; i < HDL_HASH_TBL_SIZE; i++) { 1598*7c478bd9Sstevel@tonic-gate hhashp = &hhash_table[i]; 1599*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) { 1600*7c478bd9Sstevel@tonic-gate if (!driver_under_test(hp->dip) || 1601*7c478bd9Sstevel@tonic-gate ddi_name_to_major(ddi_get_name(hp->dip)) != 1602*7c478bd9Sstevel@tonic-gate ddi_name_to_major(namep) || 1603*7c478bd9Sstevel@tonic-gate ++(hdl_info.count) > req_count || 1604*7c478bd9Sstevel@tonic-gate count == req_count) 1605*7c478bd9Sstevel@tonic-gate continue; 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate hdlip->instance = hp->instance; 1608*7c478bd9Sstevel@tonic-gate hdlip->rnumber = hp->rnumber; 1609*7c478bd9Sstevel@tonic-gate switch (hp->type) { 1610*7c478bd9Sstevel@tonic-gate case BOFI_ACC_HDL: 1611*7c478bd9Sstevel@tonic-gate hdlip->access_type = BOFI_PIO_RW; 1612*7c478bd9Sstevel@tonic-gate hdlip->offset = hp->offset; 1613*7c478bd9Sstevel@tonic-gate hdlip->len = hp->len; 1614*7c478bd9Sstevel@tonic-gate break; 1615*7c478bd9Sstevel@tonic-gate case BOFI_DMA_HDL: 1616*7c478bd9Sstevel@tonic-gate hdlip->access_type = 0; 1617*7c478bd9Sstevel@tonic-gate if (hp->flags & DDI_DMA_WRITE) 1618*7c478bd9Sstevel@tonic-gate hdlip->access_type |= 1619*7c478bd9Sstevel@tonic-gate BOFI_DMA_W; 1620*7c478bd9Sstevel@tonic-gate if (hp->flags & DDI_DMA_READ) 1621*7c478bd9Sstevel@tonic-gate hdlip->access_type |= 1622*7c478bd9Sstevel@tonic-gate BOFI_DMA_R; 1623*7c478bd9Sstevel@tonic-gate hdlip->len = hp->len; 1624*7c478bd9Sstevel@tonic-gate hdlip->addr_cookie = 1625*7c478bd9Sstevel@tonic-gate (uint64_t)(uintptr_t)hp->addr; 1626*7c478bd9Sstevel@tonic-gate break; 1627*7c478bd9Sstevel@tonic-gate case BOFI_INT_HDL: 1628*7c478bd9Sstevel@tonic-gate hdlip->access_type = BOFI_INTR; 1629*7c478bd9Sstevel@tonic-gate break; 1630*7c478bd9Sstevel@tonic-gate default: 1631*7c478bd9Sstevel@tonic-gate hdlip->access_type = 0; 1632*7c478bd9Sstevel@tonic-gate break; 1633*7c478bd9Sstevel@tonic-gate } 1634*7c478bd9Sstevel@tonic-gate hdlip++; 1635*7c478bd9Sstevel@tonic-gate count++; 1636*7c478bd9Sstevel@tonic-gate } 1637*7c478bd9Sstevel@tonic-gate } 1638*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 1639*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1640*7c478bd9Sstevel@tonic-gate err = 0; 1641*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1642*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 1643*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1644*7c478bd9Sstevel@tonic-gate { 1645*7c478bd9Sstevel@tonic-gate /* 1646*7c478bd9Sstevel@tonic-gate * For use when a 32 bit app makes a call into a 1647*7c478bd9Sstevel@tonic-gate * 64 bit ioctl 1648*7c478bd9Sstevel@tonic-gate */ 1649*7c478bd9Sstevel@tonic-gate struct bofi_get_hdl_info32 hdl_info_32; 1650*7c478bd9Sstevel@tonic-gate 1651*7c478bd9Sstevel@tonic-gate hdl_info_32.namesize = hdl_info.namesize; 1652*7c478bd9Sstevel@tonic-gate (void) strncpy(hdl_info_32.name, hdl_info.name, 1653*7c478bd9Sstevel@tonic-gate NAMESIZE); 1654*7c478bd9Sstevel@tonic-gate hdl_info_32.count = hdl_info.count; 1655*7c478bd9Sstevel@tonic-gate hdl_info_32.hdli = (caddr32_t)(uintptr_t)hdl_info.hdli; 1656*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&hdl_info_32, (void *)arg, 1657*7c478bd9Sstevel@tonic-gate sizeof (hdl_info_32), mode) != 0) { 1658*7c478bd9Sstevel@tonic-gate kmem_free(namep, hdl_info.namesize+1); 1659*7c478bd9Sstevel@tonic-gate if (req_count > 0) 1660*7c478bd9Sstevel@tonic-gate kmem_free(hib, 1661*7c478bd9Sstevel@tonic-gate req_count * sizeof (*hib)); 1662*7c478bd9Sstevel@tonic-gate return (EFAULT); 1663*7c478bd9Sstevel@tonic-gate } 1664*7c478bd9Sstevel@tonic-gate break; 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1667*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&hdl_info, (void *)arg, 1668*7c478bd9Sstevel@tonic-gate sizeof (hdl_info), mode) != 0) { 1669*7c478bd9Sstevel@tonic-gate kmem_free(namep, hdl_info.namesize+1); 1670*7c478bd9Sstevel@tonic-gate if (req_count > 0) 1671*7c478bd9Sstevel@tonic-gate kmem_free(hib, 1672*7c478bd9Sstevel@tonic-gate req_count * sizeof (*hib)); 1673*7c478bd9Sstevel@tonic-gate return (EFAULT); 1674*7c478bd9Sstevel@tonic-gate } 1675*7c478bd9Sstevel@tonic-gate break; 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate #else /* ! _MULTI_DATAMODEL */ 1678*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&hdl_info, (void *)arg, 1679*7c478bd9Sstevel@tonic-gate sizeof (hdl_info), mode) != 0) { 1680*7c478bd9Sstevel@tonic-gate kmem_free(namep, hdl_info.namesize+1); 1681*7c478bd9Sstevel@tonic-gate if (req_count > 0) 1682*7c478bd9Sstevel@tonic-gate kmem_free(hib, req_count * sizeof (*hib)); 1683*7c478bd9Sstevel@tonic-gate return (EFAULT); 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate #endif /* ! _MULTI_DATAMODEL */ 1686*7c478bd9Sstevel@tonic-gate if (count > 0) { 1687*7c478bd9Sstevel@tonic-gate if (ddi_copyout(hib, hdl_info.hdli, 1688*7c478bd9Sstevel@tonic-gate count * sizeof (*hib), mode) != 0) { 1689*7c478bd9Sstevel@tonic-gate kmem_free(namep, hdl_info.namesize+1); 1690*7c478bd9Sstevel@tonic-gate if (req_count > 0) 1691*7c478bd9Sstevel@tonic-gate kmem_free(hib, 1692*7c478bd9Sstevel@tonic-gate req_count * sizeof (*hib)); 1693*7c478bd9Sstevel@tonic-gate return (EFAULT); 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate } 1696*7c478bd9Sstevel@tonic-gate kmem_free(namep, hdl_info.namesize+1); 1697*7c478bd9Sstevel@tonic-gate if (req_count > 0) 1698*7c478bd9Sstevel@tonic-gate kmem_free(hib, req_count * sizeof (*hib)); 1699*7c478bd9Sstevel@tonic-gate return (err); 1700*7c478bd9Sstevel@tonic-gate default: 1701*7c478bd9Sstevel@tonic-gate return (ENOTTY); 1702*7c478bd9Sstevel@tonic-gate } 1703*7c478bd9Sstevel@tonic-gate } 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate /* 1707*7c478bd9Sstevel@tonic-gate * add a new error definition 1708*7c478bd9Sstevel@tonic-gate */ 1709*7c478bd9Sstevel@tonic-gate static int 1710*7c478bd9Sstevel@tonic-gate bofi_errdef_alloc(struct bofi_errdef *errdefp, char *namep, 1711*7c478bd9Sstevel@tonic-gate struct bofi_errent *softc) 1712*7c478bd9Sstevel@tonic-gate { 1713*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 1714*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 1715*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 1716*7c478bd9Sstevel@tonic-gate 1717*7c478bd9Sstevel@tonic-gate /* 1718*7c478bd9Sstevel@tonic-gate * allocate errdef structure and put on in-use list 1719*7c478bd9Sstevel@tonic-gate */ 1720*7c478bd9Sstevel@tonic-gate ep = kmem_zalloc(sizeof (struct bofi_errent), KM_SLEEP); 1721*7c478bd9Sstevel@tonic-gate ep->errdef = *errdefp; 1722*7c478bd9Sstevel@tonic-gate ep->name = namep; 1723*7c478bd9Sstevel@tonic-gate ep->errdef.errdef_handle = (uint64_t)(uintptr_t)ep; 1724*7c478bd9Sstevel@tonic-gate ep->errstate.errdef_handle = (uint64_t)(uintptr_t)ep; 1725*7c478bd9Sstevel@tonic-gate cv_init(&ep->cv, NULL, CV_DRIVER, NULL); 1726*7c478bd9Sstevel@tonic-gate /* 1727*7c478bd9Sstevel@tonic-gate * allocate space for logging 1728*7c478bd9Sstevel@tonic-gate */ 1729*7c478bd9Sstevel@tonic-gate ep->errdef.log.entries = 0; 1730*7c478bd9Sstevel@tonic-gate ep->errdef.log.wrapcnt = 0; 1731*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_type & BOFI_LOG) 1732*7c478bd9Sstevel@tonic-gate ep->logbase = kmem_alloc(sizeof (struct acc_log_elem) * 1733*7c478bd9Sstevel@tonic-gate ep->errdef.log.logsize, KM_SLEEP); 1734*7c478bd9Sstevel@tonic-gate else 1735*7c478bd9Sstevel@tonic-gate ep->logbase = NULL; 1736*7c478bd9Sstevel@tonic-gate /* 1737*7c478bd9Sstevel@tonic-gate * put on in-use list 1738*7c478bd9Sstevel@tonic-gate */ 1739*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1740*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 1741*7c478bd9Sstevel@tonic-gate ep->next = errent_listp; 1742*7c478bd9Sstevel@tonic-gate errent_listp = ep; 1743*7c478bd9Sstevel@tonic-gate /* 1744*7c478bd9Sstevel@tonic-gate * and add it to the per-clone list 1745*7c478bd9Sstevel@tonic-gate */ 1746*7c478bd9Sstevel@tonic-gate ep->cnext = softc->cnext; 1747*7c478bd9Sstevel@tonic-gate softc->cnext->cprev = ep; 1748*7c478bd9Sstevel@tonic-gate ep->cprev = softc; 1749*7c478bd9Sstevel@tonic-gate softc->cnext = ep; 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate /* 1752*7c478bd9Sstevel@tonic-gate * look for corresponding shadow handle structures and if we find any 1753*7c478bd9Sstevel@tonic-gate * tag this errdef structure on to their link lists. 1754*7c478bd9Sstevel@tonic-gate */ 1755*7c478bd9Sstevel@tonic-gate for (hp = shadow_list.next; hp != &shadow_list; hp = hp->next) { 1756*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(hp->name) == ddi_name_to_major(namep) && 1757*7c478bd9Sstevel@tonic-gate hp->instance == errdefp->instance && 1758*7c478bd9Sstevel@tonic-gate (((errdefp->access_type & BOFI_DMA_RW) && 1759*7c478bd9Sstevel@tonic-gate (ep->errdef.rnumber == -1 || 1760*7c478bd9Sstevel@tonic-gate hp->rnumber == ep->errdef.rnumber) && 1761*7c478bd9Sstevel@tonic-gate hp->type == BOFI_DMA_HDL && 1762*7c478bd9Sstevel@tonic-gate (((uintptr_t)(hp->addr + ep->errdef.offset + 1763*7c478bd9Sstevel@tonic-gate ep->errdef.len) & ~LLSZMASK) > 1764*7c478bd9Sstevel@tonic-gate ((uintptr_t)((hp->addr + ep->errdef.offset) + 1765*7c478bd9Sstevel@tonic-gate LLSZMASK) & ~LLSZMASK))) || 1766*7c478bd9Sstevel@tonic-gate ((errdefp->access_type & BOFI_INTR) && 1767*7c478bd9Sstevel@tonic-gate hp->type == BOFI_INT_HDL) || 1768*7c478bd9Sstevel@tonic-gate ((errdefp->access_type & BOFI_PIO_RW) && 1769*7c478bd9Sstevel@tonic-gate hp->type == BOFI_ACC_HDL && 1770*7c478bd9Sstevel@tonic-gate (errdefp->rnumber == -1 || 1771*7c478bd9Sstevel@tonic-gate hp->rnumber == errdefp->rnumber) && 1772*7c478bd9Sstevel@tonic-gate (errdefp->len == 0 || 1773*7c478bd9Sstevel@tonic-gate hp->offset < errdefp->offset + errdefp->len) && 1774*7c478bd9Sstevel@tonic-gate hp->offset + hp->len > errdefp->offset))) { 1775*7c478bd9Sstevel@tonic-gate lp = bofi_link_freelist; 1776*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 1777*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp->link; 1778*7c478bd9Sstevel@tonic-gate lp->errentp = ep; 1779*7c478bd9Sstevel@tonic-gate lp->link = hp->link; 1780*7c478bd9Sstevel@tonic-gate hp->link = lp; 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate } 1783*7c478bd9Sstevel@tonic-gate } 1784*7c478bd9Sstevel@tonic-gate errdefp->errdef_handle = (uint64_t)(uintptr_t)ep; 1785*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 1786*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1787*7c478bd9Sstevel@tonic-gate ep->softintr_id = NULL; 1788*7c478bd9Sstevel@tonic-gate return (ddi_add_softintr(our_dip, DDI_SOFTINT_MED, &ep->softintr_id, 1789*7c478bd9Sstevel@tonic-gate NULL, NULL, bofi_signal, (caddr_t)&ep->errdef)); 1790*7c478bd9Sstevel@tonic-gate } 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate /* 1794*7c478bd9Sstevel@tonic-gate * delete existing errdef 1795*7c478bd9Sstevel@tonic-gate */ 1796*7c478bd9Sstevel@tonic-gate static int 1797*7c478bd9Sstevel@tonic-gate bofi_errdef_free(struct bofi_errent *ep) 1798*7c478bd9Sstevel@tonic-gate { 1799*7c478bd9Sstevel@tonic-gate struct bofi_errent *hep, *prev_hep; 1800*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *prev_lp, *next_lp; 1801*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 1802*7c478bd9Sstevel@tonic-gate 1803*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1804*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 1805*7c478bd9Sstevel@tonic-gate /* 1806*7c478bd9Sstevel@tonic-gate * don't just assume its a valid ep - check that its on the 1807*7c478bd9Sstevel@tonic-gate * in-use list 1808*7c478bd9Sstevel@tonic-gate */ 1809*7c478bd9Sstevel@tonic-gate prev_hep = NULL; 1810*7c478bd9Sstevel@tonic-gate for (hep = errent_listp; hep != NULL; ) { 1811*7c478bd9Sstevel@tonic-gate if (hep == ep) 1812*7c478bd9Sstevel@tonic-gate break; 1813*7c478bd9Sstevel@tonic-gate prev_hep = hep; 1814*7c478bd9Sstevel@tonic-gate hep = hep->next; 1815*7c478bd9Sstevel@tonic-gate } 1816*7c478bd9Sstevel@tonic-gate if (hep == NULL) { 1817*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 1818*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1819*7c478bd9Sstevel@tonic-gate return (EINVAL); 1820*7c478bd9Sstevel@tonic-gate } 1821*7c478bd9Sstevel@tonic-gate /* 1822*7c478bd9Sstevel@tonic-gate * found it - delete from in-use list 1823*7c478bd9Sstevel@tonic-gate */ 1824*7c478bd9Sstevel@tonic-gate 1825*7c478bd9Sstevel@tonic-gate if (prev_hep) 1826*7c478bd9Sstevel@tonic-gate prev_hep->next = hep->next; 1827*7c478bd9Sstevel@tonic-gate else 1828*7c478bd9Sstevel@tonic-gate errent_listp = hep->next; 1829*7c478bd9Sstevel@tonic-gate /* 1830*7c478bd9Sstevel@tonic-gate * and take it off the per-clone list 1831*7c478bd9Sstevel@tonic-gate */ 1832*7c478bd9Sstevel@tonic-gate hep->cnext->cprev = hep->cprev; 1833*7c478bd9Sstevel@tonic-gate hep->cprev->cnext = hep->cnext; 1834*7c478bd9Sstevel@tonic-gate /* 1835*7c478bd9Sstevel@tonic-gate * see if we are on any shadow handle link lists - and if we 1836*7c478bd9Sstevel@tonic-gate * are then take us off 1837*7c478bd9Sstevel@tonic-gate */ 1838*7c478bd9Sstevel@tonic-gate for (hp = shadow_list.next; hp != &shadow_list; hp = hp->next) { 1839*7c478bd9Sstevel@tonic-gate prev_lp = NULL; 1840*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 1841*7c478bd9Sstevel@tonic-gate if (lp->errentp == ep) { 1842*7c478bd9Sstevel@tonic-gate if (prev_lp) 1843*7c478bd9Sstevel@tonic-gate prev_lp->link = lp->link; 1844*7c478bd9Sstevel@tonic-gate else 1845*7c478bd9Sstevel@tonic-gate hp->link = lp->link; 1846*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 1847*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 1848*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 1849*7c478bd9Sstevel@tonic-gate lp = next_lp; 1850*7c478bd9Sstevel@tonic-gate } else { 1851*7c478bd9Sstevel@tonic-gate prev_lp = lp; 1852*7c478bd9Sstevel@tonic-gate lp = lp->link; 1853*7c478bd9Sstevel@tonic-gate } 1854*7c478bd9Sstevel@tonic-gate } 1855*7c478bd9Sstevel@tonic-gate } 1856*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 1857*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate cv_destroy(&ep->cv); 1860*7c478bd9Sstevel@tonic-gate kmem_free(ep->name, ep->errdef.namesize+1); 1861*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_LOG) && 1862*7c478bd9Sstevel@tonic-gate ep->errdef.log.logsize && ep->logbase) /* double check */ 1863*7c478bd9Sstevel@tonic-gate kmem_free(ep->logbase, 1864*7c478bd9Sstevel@tonic-gate sizeof (struct acc_log_elem) * ep->errdef.log.logsize); 1865*7c478bd9Sstevel@tonic-gate 1866*7c478bd9Sstevel@tonic-gate if (ep->softintr_id) 1867*7c478bd9Sstevel@tonic-gate ddi_remove_softintr(ep->softintr_id); 1868*7c478bd9Sstevel@tonic-gate kmem_free(ep, sizeof (struct bofi_errent)); 1869*7c478bd9Sstevel@tonic-gate return (0); 1870*7c478bd9Sstevel@tonic-gate } 1871*7c478bd9Sstevel@tonic-gate 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* 1874*7c478bd9Sstevel@tonic-gate * start all errdefs corresponding to this name and instance 1875*7c478bd9Sstevel@tonic-gate */ 1876*7c478bd9Sstevel@tonic-gate static void 1877*7c478bd9Sstevel@tonic-gate bofi_start(struct bofi_errctl *errctlp, char *namep) 1878*7c478bd9Sstevel@tonic-gate { 1879*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate /* 1882*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 1883*7c478bd9Sstevel@tonic-gate */ 1884*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1885*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 1886*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 1887*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 1888*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_DEV_ACTIVE; 1889*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, &(ep->errdef.log.start_time)); 1890*7c478bd9Sstevel@tonic-gate ep->errdef.log.stop_time = 0ul; 1891*7c478bd9Sstevel@tonic-gate } 1892*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1893*7c478bd9Sstevel@tonic-gate } 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate 1896*7c478bd9Sstevel@tonic-gate /* 1897*7c478bd9Sstevel@tonic-gate * stop all errdefs corresponding to this name and instance 1898*7c478bd9Sstevel@tonic-gate */ 1899*7c478bd9Sstevel@tonic-gate static void 1900*7c478bd9Sstevel@tonic-gate bofi_stop(struct bofi_errctl *errctlp, char *namep) 1901*7c478bd9Sstevel@tonic-gate { 1902*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate /* 1905*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 1906*7c478bd9Sstevel@tonic-gate */ 1907*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1908*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 1909*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 1910*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 1911*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_DEV_ACTIVE; 1912*7c478bd9Sstevel@tonic-gate if (ep->errdef.log.stop_time == 0ul) 1913*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, 1914*7c478bd9Sstevel@tonic-gate &(ep->errdef.log.stop_time)); 1915*7c478bd9Sstevel@tonic-gate } 1916*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate 1920*7c478bd9Sstevel@tonic-gate /* 1921*7c478bd9Sstevel@tonic-gate * wake up any thread waiting on this errdefs 1922*7c478bd9Sstevel@tonic-gate */ 1923*7c478bd9Sstevel@tonic-gate static uint_t 1924*7c478bd9Sstevel@tonic-gate bofi_signal(caddr_t arg) 1925*7c478bd9Sstevel@tonic-gate { 1926*7c478bd9Sstevel@tonic-gate struct bofi_errdef *edp = (struct bofi_errdef *)arg; 1927*7c478bd9Sstevel@tonic-gate struct bofi_errent *hep; 1928*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep = 1929*7c478bd9Sstevel@tonic-gate (struct bofi_errent *)(uintptr_t)edp->errdef_handle; 1930*7c478bd9Sstevel@tonic-gate 1931*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1932*7c478bd9Sstevel@tonic-gate for (hep = errent_listp; hep != NULL; ) { 1933*7c478bd9Sstevel@tonic-gate if (hep == ep) 1934*7c478bd9Sstevel@tonic-gate break; 1935*7c478bd9Sstevel@tonic-gate hep = hep->next; 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate if (hep == NULL) { 1938*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1939*7c478bd9Sstevel@tonic-gate return (DDI_INTR_UNCLAIMED); 1940*7c478bd9Sstevel@tonic-gate } 1941*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_LOG) && 1942*7c478bd9Sstevel@tonic-gate (edp->log.flags & BOFI_LOG_FULL)) { 1943*7c478bd9Sstevel@tonic-gate edp->log.stop_time = bofi_gettime(); 1944*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 1945*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 1946*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 1947*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 1948*7c478bd9Sstevel@tonic-gate } 1949*7c478bd9Sstevel@tonic-gate if (ep->errstate.msg_time != 0) { 1950*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 1951*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 1952*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 1953*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 1954*7c478bd9Sstevel@tonic-gate } 1955*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1956*7c478bd9Sstevel@tonic-gate return (DDI_INTR_CLAIMED); 1957*7c478bd9Sstevel@tonic-gate } 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate /* 1961*7c478bd9Sstevel@tonic-gate * wake up all errdefs corresponding to this name and instance 1962*7c478bd9Sstevel@tonic-gate */ 1963*7c478bd9Sstevel@tonic-gate static void 1964*7c478bd9Sstevel@tonic-gate bofi_broadcast(struct bofi_errctl *errctlp, char *namep) 1965*7c478bd9Sstevel@tonic-gate { 1966*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate /* 1969*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 1970*7c478bd9Sstevel@tonic-gate */ 1971*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 1972*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 1973*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 1974*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 1975*7c478bd9Sstevel@tonic-gate /* 1976*7c478bd9Sstevel@tonic-gate * wake up sleepers 1977*7c478bd9Sstevel@tonic-gate */ 1978*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 1979*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 1980*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 1981*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 1982*7c478bd9Sstevel@tonic-gate } 1983*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 1984*7c478bd9Sstevel@tonic-gate } 1985*7c478bd9Sstevel@tonic-gate 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate /* 1988*7c478bd9Sstevel@tonic-gate * clear "acc_chk" for all errdefs corresponding to this name and instance 1989*7c478bd9Sstevel@tonic-gate * and wake them up. 1990*7c478bd9Sstevel@tonic-gate */ 1991*7c478bd9Sstevel@tonic-gate static void 1992*7c478bd9Sstevel@tonic-gate bofi_clear_acc_chk(struct bofi_errctl *errctlp, char *namep) 1993*7c478bd9Sstevel@tonic-gate { 1994*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate /* 1997*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 1998*7c478bd9Sstevel@tonic-gate */ 1999*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 2000*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 2001*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 2002*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 2003*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 2004*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count == 0 && 2005*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count == 0) 2006*7c478bd9Sstevel@tonic-gate ep->errdef.acc_chk = 0; 2007*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2008*7c478bd9Sstevel@tonic-gate /* 2009*7c478bd9Sstevel@tonic-gate * wake up sleepers 2010*7c478bd9Sstevel@tonic-gate */ 2011*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 2012*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 2013*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 2014*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 2015*7c478bd9Sstevel@tonic-gate } 2016*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2017*7c478bd9Sstevel@tonic-gate } 2018*7c478bd9Sstevel@tonic-gate 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate /* 2021*7c478bd9Sstevel@tonic-gate * set "fail_count" to 0 for all errdefs corresponding to this name and instance 2022*7c478bd9Sstevel@tonic-gate * whose "access_count" has expired, set "acc_chk" to 0 and wake them up. 2023*7c478bd9Sstevel@tonic-gate */ 2024*7c478bd9Sstevel@tonic-gate static void 2025*7c478bd9Sstevel@tonic-gate bofi_clear_errors(struct bofi_errctl *errctlp, char *namep) 2026*7c478bd9Sstevel@tonic-gate { 2027*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2028*7c478bd9Sstevel@tonic-gate 2029*7c478bd9Sstevel@tonic-gate /* 2030*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 2031*7c478bd9Sstevel@tonic-gate */ 2032*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 2033*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 2034*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 2035*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 2036*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 2037*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count == 0) { 2038*7c478bd9Sstevel@tonic-gate ep->errdef.acc_chk = 0; 2039*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count = 0; 2040*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2041*7c478bd9Sstevel@tonic-gate if (ep->errdef.log.stop_time == 0ul) 2042*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, 2043*7c478bd9Sstevel@tonic-gate &(ep->errdef.log.stop_time)); 2044*7c478bd9Sstevel@tonic-gate } else 2045*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2046*7c478bd9Sstevel@tonic-gate /* 2047*7c478bd9Sstevel@tonic-gate * wake up sleepers 2048*7c478bd9Sstevel@tonic-gate */ 2049*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 2050*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 2051*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 2052*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 2053*7c478bd9Sstevel@tonic-gate } 2054*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2055*7c478bd9Sstevel@tonic-gate } 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate /* 2059*7c478bd9Sstevel@tonic-gate * set "access_count" and "fail_count" to 0 for all errdefs corresponding to 2060*7c478bd9Sstevel@tonic-gate * this name and instance, set "acc_chk" to 0, and wake them up. 2061*7c478bd9Sstevel@tonic-gate */ 2062*7c478bd9Sstevel@tonic-gate static void 2063*7c478bd9Sstevel@tonic-gate bofi_clear_errdefs(struct bofi_errctl *errctlp, char *namep) 2064*7c478bd9Sstevel@tonic-gate { 2065*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2066*7c478bd9Sstevel@tonic-gate 2067*7c478bd9Sstevel@tonic-gate /* 2068*7c478bd9Sstevel@tonic-gate * look for any errdefs with matching name and instance 2069*7c478bd9Sstevel@tonic-gate */ 2070*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 2071*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) 2072*7c478bd9Sstevel@tonic-gate if (strncmp(namep, ep->name, NAMESIZE) == 0 && 2073*7c478bd9Sstevel@tonic-gate errctlp->instance == ep->errdef.instance) { 2074*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 2075*7c478bd9Sstevel@tonic-gate ep->errdef.acc_chk = 0; 2076*7c478bd9Sstevel@tonic-gate ep->errdef.access_count = 0; 2077*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count = 0; 2078*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2079*7c478bd9Sstevel@tonic-gate if (ep->errdef.log.stop_time == 0ul) 2080*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, 2081*7c478bd9Sstevel@tonic-gate &(ep->errdef.log.stop_time)); 2082*7c478bd9Sstevel@tonic-gate /* 2083*7c478bd9Sstevel@tonic-gate * wake up sleepers 2084*7c478bd9Sstevel@tonic-gate */ 2085*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_NEW_MESSAGE; 2086*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_MESSAGE_WAIT) 2087*7c478bd9Sstevel@tonic-gate cv_broadcast(&ep->cv); 2088*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_MESSAGE_WAIT; 2089*7c478bd9Sstevel@tonic-gate } 2090*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2091*7c478bd9Sstevel@tonic-gate } 2092*7c478bd9Sstevel@tonic-gate 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate /* 2095*7c478bd9Sstevel@tonic-gate * get state for this errdef 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate static int 2098*7c478bd9Sstevel@tonic-gate bofi_errdef_check(struct bofi_errstate *errstatep, struct acc_log_elem **logpp) 2099*7c478bd9Sstevel@tonic-gate { 2100*7c478bd9Sstevel@tonic-gate struct bofi_errent *hep; 2101*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate ep = (struct bofi_errent *)(uintptr_t)errstatep->errdef_handle; 2104*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 2105*7c478bd9Sstevel@tonic-gate /* 2106*7c478bd9Sstevel@tonic-gate * don't just assume its a valid ep - check that its on the 2107*7c478bd9Sstevel@tonic-gate * in-use list 2108*7c478bd9Sstevel@tonic-gate */ 2109*7c478bd9Sstevel@tonic-gate for (hep = errent_listp; hep != NULL; hep = hep->next) 2110*7c478bd9Sstevel@tonic-gate if (hep == ep) 2111*7c478bd9Sstevel@tonic-gate break; 2112*7c478bd9Sstevel@tonic-gate if (hep == NULL) { 2113*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2114*7c478bd9Sstevel@tonic-gate return (EINVAL); 2115*7c478bd9Sstevel@tonic-gate } 2116*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 2117*7c478bd9Sstevel@tonic-gate ep->errstate.access_count = ep->errdef.access_count; 2118*7c478bd9Sstevel@tonic-gate ep->errstate.fail_count = ep->errdef.fail_count; 2119*7c478bd9Sstevel@tonic-gate ep->errstate.acc_chk = ep->errdef.acc_chk; 2120*7c478bd9Sstevel@tonic-gate ep->errstate.log = ep->errdef.log; 2121*7c478bd9Sstevel@tonic-gate *logpp = ep->logbase; 2122*7c478bd9Sstevel@tonic-gate *errstatep = ep->errstate; 2123*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2124*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2125*7c478bd9Sstevel@tonic-gate return (0); 2126*7c478bd9Sstevel@tonic-gate } 2127*7c478bd9Sstevel@tonic-gate 2128*7c478bd9Sstevel@tonic-gate 2129*7c478bd9Sstevel@tonic-gate /* 2130*7c478bd9Sstevel@tonic-gate * Wait for a ddi_report_fault message to come back for this errdef 2131*7c478bd9Sstevel@tonic-gate * Then return state for this errdef. 2132*7c478bd9Sstevel@tonic-gate * fault report is intercepted by bofi_post_event, which triggers 2133*7c478bd9Sstevel@tonic-gate * bofi_signal via a softint, which will wake up this routine if 2134*7c478bd9Sstevel@tonic-gate * we are waiting 2135*7c478bd9Sstevel@tonic-gate */ 2136*7c478bd9Sstevel@tonic-gate static int 2137*7c478bd9Sstevel@tonic-gate bofi_errdef_check_w(struct bofi_errstate *errstatep, 2138*7c478bd9Sstevel@tonic-gate struct acc_log_elem **logpp) 2139*7c478bd9Sstevel@tonic-gate { 2140*7c478bd9Sstevel@tonic-gate struct bofi_errent *hep; 2141*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2142*7c478bd9Sstevel@tonic-gate int rval = 0; 2143*7c478bd9Sstevel@tonic-gate 2144*7c478bd9Sstevel@tonic-gate ep = (struct bofi_errent *)(uintptr_t)errstatep->errdef_handle; 2145*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 2146*7c478bd9Sstevel@tonic-gate retry: 2147*7c478bd9Sstevel@tonic-gate /* 2148*7c478bd9Sstevel@tonic-gate * don't just assume its a valid ep - check that its on the 2149*7c478bd9Sstevel@tonic-gate * in-use list 2150*7c478bd9Sstevel@tonic-gate */ 2151*7c478bd9Sstevel@tonic-gate for (hep = errent_listp; hep != NULL; hep = hep->next) 2152*7c478bd9Sstevel@tonic-gate if (hep == ep) 2153*7c478bd9Sstevel@tonic-gate break; 2154*7c478bd9Sstevel@tonic-gate if (hep == NULL) { 2155*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2156*7c478bd9Sstevel@tonic-gate return (EINVAL); 2157*7c478bd9Sstevel@tonic-gate } 2158*7c478bd9Sstevel@tonic-gate /* 2159*7c478bd9Sstevel@tonic-gate * wait for ddi_report_fault for the devinfo corresponding 2160*7c478bd9Sstevel@tonic-gate * to this errdef 2161*7c478bd9Sstevel@tonic-gate */ 2162*7c478bd9Sstevel@tonic-gate if (rval == 0 && !(ep->state & BOFI_NEW_MESSAGE)) { 2163*7c478bd9Sstevel@tonic-gate ep->state |= BOFI_MESSAGE_WAIT; 2164*7c478bd9Sstevel@tonic-gate if (cv_wait_sig(&ep->cv, &bofi_low_mutex) == 0) 2165*7c478bd9Sstevel@tonic-gate rval = EINTR; 2166*7c478bd9Sstevel@tonic-gate goto retry; 2167*7c478bd9Sstevel@tonic-gate } 2168*7c478bd9Sstevel@tonic-gate ep->state &= ~BOFI_NEW_MESSAGE; 2169*7c478bd9Sstevel@tonic-gate /* 2170*7c478bd9Sstevel@tonic-gate * we either didn't need to sleep, we've been woken up or we've been 2171*7c478bd9Sstevel@tonic-gate * signaled - either way return state now 2172*7c478bd9Sstevel@tonic-gate */ 2173*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 2174*7c478bd9Sstevel@tonic-gate ep->errstate.access_count = ep->errdef.access_count; 2175*7c478bd9Sstevel@tonic-gate ep->errstate.fail_count = ep->errdef.fail_count; 2176*7c478bd9Sstevel@tonic-gate ep->errstate.acc_chk = ep->errdef.acc_chk; 2177*7c478bd9Sstevel@tonic-gate ep->errstate.log = ep->errdef.log; 2178*7c478bd9Sstevel@tonic-gate *logpp = ep->logbase; 2179*7c478bd9Sstevel@tonic-gate *errstatep = ep->errstate; 2180*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2181*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 2182*7c478bd9Sstevel@tonic-gate return (rval); 2183*7c478bd9Sstevel@tonic-gate } 2184*7c478bd9Sstevel@tonic-gate 2185*7c478bd9Sstevel@tonic-gate 2186*7c478bd9Sstevel@tonic-gate /* 2187*7c478bd9Sstevel@tonic-gate * support routine - check if requested driver is defined as under test in the 2188*7c478bd9Sstevel@tonic-gate * conf file. 2189*7c478bd9Sstevel@tonic-gate */ 2190*7c478bd9Sstevel@tonic-gate static int 2191*7c478bd9Sstevel@tonic-gate driver_under_test(dev_info_t *rdip) 2192*7c478bd9Sstevel@tonic-gate { 2193*7c478bd9Sstevel@tonic-gate int i; 2194*7c478bd9Sstevel@tonic-gate char *rname; 2195*7c478bd9Sstevel@tonic-gate major_t rmaj; 2196*7c478bd9Sstevel@tonic-gate 2197*7c478bd9Sstevel@tonic-gate rname = ddi_get_name(rdip); 2198*7c478bd9Sstevel@tonic-gate rmaj = ddi_name_to_major(rname); 2199*7c478bd9Sstevel@tonic-gate 2200*7c478bd9Sstevel@tonic-gate /* 2201*7c478bd9Sstevel@tonic-gate * Enforce the user to specifically request the following drivers. 2202*7c478bd9Sstevel@tonic-gate */ 2203*7c478bd9Sstevel@tonic-gate for (i = 0; i < driver_list_size; i += (1 + strlen(&driver_list[i]))) { 2204*7c478bd9Sstevel@tonic-gate if (driver_list_neg == 0) { 2205*7c478bd9Sstevel@tonic-gate if (rmaj == ddi_name_to_major(&driver_list[i])) 2206*7c478bd9Sstevel@tonic-gate return (1); 2207*7c478bd9Sstevel@tonic-gate } else { 2208*7c478bd9Sstevel@tonic-gate if (rmaj == ddi_name_to_major(&driver_list[i+1])) 2209*7c478bd9Sstevel@tonic-gate return (0); 2210*7c478bd9Sstevel@tonic-gate } 2211*7c478bd9Sstevel@tonic-gate } 2212*7c478bd9Sstevel@tonic-gate if (driver_list_neg == 0) 2213*7c478bd9Sstevel@tonic-gate return (0); 2214*7c478bd9Sstevel@tonic-gate else 2215*7c478bd9Sstevel@tonic-gate return (1); 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate } 2218*7c478bd9Sstevel@tonic-gate 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate static void 2221*7c478bd9Sstevel@tonic-gate log_acc_event(struct bofi_errent *ep, uint_t at, offset_t offset, off_t len, 2222*7c478bd9Sstevel@tonic-gate size_t repcount, uint64_t *valuep) 2223*7c478bd9Sstevel@tonic-gate { 2224*7c478bd9Sstevel@tonic-gate struct bofi_errdef *edp = &(ep->errdef); 2225*7c478bd9Sstevel@tonic-gate struct acc_log *log = &edp->log; 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate ASSERT(log != NULL); 2228*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&bofi_mutex)); 2229*7c478bd9Sstevel@tonic-gate 2230*7c478bd9Sstevel@tonic-gate if (log->flags & BOFI_LOG_REPIO) 2231*7c478bd9Sstevel@tonic-gate repcount = 1; 2232*7c478bd9Sstevel@tonic-gate else if (repcount == 0 && edp->access_count > 0 && 2233*7c478bd9Sstevel@tonic-gate (log->flags & BOFI_LOG_FULL) == 0) 2234*7c478bd9Sstevel@tonic-gate edp->access_count += 1; 2235*7c478bd9Sstevel@tonic-gate 2236*7c478bd9Sstevel@tonic-gate if (repcount && log->entries < log->logsize) { 2237*7c478bd9Sstevel@tonic-gate struct acc_log_elem *elem = ep->logbase + log->entries; 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate if (log->flags & BOFI_LOG_TIMESTAMP) 2240*7c478bd9Sstevel@tonic-gate elem->access_time = bofi_gettime(); 2241*7c478bd9Sstevel@tonic-gate elem->access_type = at; 2242*7c478bd9Sstevel@tonic-gate elem->offset = offset; 2243*7c478bd9Sstevel@tonic-gate elem->value = valuep ? *valuep : 0ll; 2244*7c478bd9Sstevel@tonic-gate elem->size = len; 2245*7c478bd9Sstevel@tonic-gate elem->repcount = repcount; 2246*7c478bd9Sstevel@tonic-gate ++log->entries; 2247*7c478bd9Sstevel@tonic-gate if (log->entries == log->logsize) { 2248*7c478bd9Sstevel@tonic-gate log->flags |= BOFI_LOG_FULL; 2249*7c478bd9Sstevel@tonic-gate ddi_trigger_softintr(((struct bofi_errent *) 2250*7c478bd9Sstevel@tonic-gate (uintptr_t)edp->errdef_handle)->softintr_id); 2251*7c478bd9Sstevel@tonic-gate } 2252*7c478bd9Sstevel@tonic-gate } 2253*7c478bd9Sstevel@tonic-gate if ((log->flags & BOFI_LOG_WRAP) && edp->access_count <= 1) { 2254*7c478bd9Sstevel@tonic-gate log->wrapcnt++; 2255*7c478bd9Sstevel@tonic-gate edp->access_count = log->logsize; 2256*7c478bd9Sstevel@tonic-gate log->entries = 0; /* wrap back to the start */ 2257*7c478bd9Sstevel@tonic-gate } 2258*7c478bd9Sstevel@tonic-gate } 2259*7c478bd9Sstevel@tonic-gate 2260*7c478bd9Sstevel@tonic-gate 2261*7c478bd9Sstevel@tonic-gate /* 2262*7c478bd9Sstevel@tonic-gate * got a condition match on dma read/write - check counts and corrupt 2263*7c478bd9Sstevel@tonic-gate * data if necessary 2264*7c478bd9Sstevel@tonic-gate * 2265*7c478bd9Sstevel@tonic-gate * bofi_mutex always held when this is called. 2266*7c478bd9Sstevel@tonic-gate */ 2267*7c478bd9Sstevel@tonic-gate static void 2268*7c478bd9Sstevel@tonic-gate do_dma_corrupt(struct bofi_shadow *hp, struct bofi_errent *ep, 2269*7c478bd9Sstevel@tonic-gate uint_t synctype, off_t off, off_t length) 2270*7c478bd9Sstevel@tonic-gate { 2271*7c478bd9Sstevel@tonic-gate uint64_t operand; 2272*7c478bd9Sstevel@tonic-gate int i; 2273*7c478bd9Sstevel@tonic-gate off_t len; 2274*7c478bd9Sstevel@tonic-gate caddr_t logaddr; 2275*7c478bd9Sstevel@tonic-gate uint64_t *addr; 2276*7c478bd9Sstevel@tonic-gate uint64_t *endaddr; 2277*7c478bd9Sstevel@tonic-gate 2278*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&bofi_mutex)); 2279*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_count || 2280*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count) && 2281*7c478bd9Sstevel@tonic-gate (ep->errdef.access_type & BOFI_LOG)) { 2282*7c478bd9Sstevel@tonic-gate uint_t atype; 2283*7c478bd9Sstevel@tonic-gate 2284*7c478bd9Sstevel@tonic-gate if (synctype == DDI_DMA_SYNC_FORDEV) 2285*7c478bd9Sstevel@tonic-gate atype = BOFI_DMA_W; 2286*7c478bd9Sstevel@tonic-gate else if (synctype == DDI_DMA_SYNC_FORCPU || 2287*7c478bd9Sstevel@tonic-gate synctype == DDI_DMA_SYNC_FORKERNEL) 2288*7c478bd9Sstevel@tonic-gate atype = BOFI_DMA_R; 2289*7c478bd9Sstevel@tonic-gate else 2290*7c478bd9Sstevel@tonic-gate atype = 0; 2291*7c478bd9Sstevel@tonic-gate if ((off <= ep->errdef.offset && 2292*7c478bd9Sstevel@tonic-gate off + length > ep->errdef.offset) || 2293*7c478bd9Sstevel@tonic-gate (off > ep->errdef.offset && 2294*7c478bd9Sstevel@tonic-gate off < ep->errdef.offset + ep->errdef.len)) { 2295*7c478bd9Sstevel@tonic-gate logaddr = (caddr_t)((uintptr_t)(hp->addr + 2296*7c478bd9Sstevel@tonic-gate off + LLSZMASK) & ~LLSZMASK); 2297*7c478bd9Sstevel@tonic-gate 2298*7c478bd9Sstevel@tonic-gate log_acc_event(ep, atype, logaddr - hp->addr, 2299*7c478bd9Sstevel@tonic-gate length, 1, 0); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate } 2302*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count > 1) { 2303*7c478bd9Sstevel@tonic-gate ep->errdef.access_count--; 2304*7c478bd9Sstevel@tonic-gate } else if (ep->errdef.fail_count > 0) { 2305*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count--; 2306*7c478bd9Sstevel@tonic-gate ep->errdef.access_count = 0; 2307*7c478bd9Sstevel@tonic-gate /* 2308*7c478bd9Sstevel@tonic-gate * OK do the corruption 2309*7c478bd9Sstevel@tonic-gate */ 2310*7c478bd9Sstevel@tonic-gate if (ep->errstate.fail_time == 0) 2311*7c478bd9Sstevel@tonic-gate ep->errstate.fail_time = bofi_gettime(); 2312*7c478bd9Sstevel@tonic-gate /* 2313*7c478bd9Sstevel@tonic-gate * work out how much to corrupt 2314*7c478bd9Sstevel@tonic-gate * 2315*7c478bd9Sstevel@tonic-gate * Make sure endaddr isn't greater than hp->addr + hp->len. 2316*7c478bd9Sstevel@tonic-gate * If endaddr becomes less than addr len becomes negative 2317*7c478bd9Sstevel@tonic-gate * and the following loop isn't entered. 2318*7c478bd9Sstevel@tonic-gate */ 2319*7c478bd9Sstevel@tonic-gate addr = (uint64_t *)((uintptr_t)((hp->addr + 2320*7c478bd9Sstevel@tonic-gate ep->errdef.offset) + LLSZMASK) & ~LLSZMASK); 2321*7c478bd9Sstevel@tonic-gate endaddr = (uint64_t *)((uintptr_t)(hp->addr + min(hp->len, 2322*7c478bd9Sstevel@tonic-gate ep->errdef.offset + ep->errdef.len)) & ~LLSZMASK); 2323*7c478bd9Sstevel@tonic-gate len = endaddr - addr; 2324*7c478bd9Sstevel@tonic-gate operand = ep->errdef.operand; 2325*7c478bd9Sstevel@tonic-gate switch (ep->errdef.optype) { 2326*7c478bd9Sstevel@tonic-gate case BOFI_EQUAL : 2327*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 2328*7c478bd9Sstevel@tonic-gate *(addr + i) = operand; 2329*7c478bd9Sstevel@tonic-gate break; 2330*7c478bd9Sstevel@tonic-gate case BOFI_AND : 2331*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 2332*7c478bd9Sstevel@tonic-gate *(addr + i) &= operand; 2333*7c478bd9Sstevel@tonic-gate break; 2334*7c478bd9Sstevel@tonic-gate case BOFI_OR : 2335*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 2336*7c478bd9Sstevel@tonic-gate *(addr + i) |= operand; 2337*7c478bd9Sstevel@tonic-gate break; 2338*7c478bd9Sstevel@tonic-gate case BOFI_XOR : 2339*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 2340*7c478bd9Sstevel@tonic-gate *(addr + i) ^= operand; 2341*7c478bd9Sstevel@tonic-gate break; 2342*7c478bd9Sstevel@tonic-gate default: 2343*7c478bd9Sstevel@tonic-gate /* do nothing */ 2344*7c478bd9Sstevel@tonic-gate break; 2345*7c478bd9Sstevel@tonic-gate } 2346*7c478bd9Sstevel@tonic-gate } 2347*7c478bd9Sstevel@tonic-gate } 2348*7c478bd9Sstevel@tonic-gate 2349*7c478bd9Sstevel@tonic-gate 2350*7c478bd9Sstevel@tonic-gate static uint64_t do_bofi_rd8(struct bofi_shadow *, caddr_t); 2351*7c478bd9Sstevel@tonic-gate static uint64_t do_bofi_rd16(struct bofi_shadow *, caddr_t); 2352*7c478bd9Sstevel@tonic-gate static uint64_t do_bofi_rd32(struct bofi_shadow *, caddr_t); 2353*7c478bd9Sstevel@tonic-gate static uint64_t do_bofi_rd64(struct bofi_shadow *, caddr_t); 2354*7c478bd9Sstevel@tonic-gate 2355*7c478bd9Sstevel@tonic-gate 2356*7c478bd9Sstevel@tonic-gate /* 2357*7c478bd9Sstevel@tonic-gate * check all errdefs linked to this shadow handle. If we've got a condition 2358*7c478bd9Sstevel@tonic-gate * match check counts and corrupt data if necessary 2359*7c478bd9Sstevel@tonic-gate * 2360*7c478bd9Sstevel@tonic-gate * bofi_mutex always held when this is called. 2361*7c478bd9Sstevel@tonic-gate * 2362*7c478bd9Sstevel@tonic-gate * because of possibility of BOFI_NO_TRANSFER, we couldn't get data 2363*7c478bd9Sstevel@tonic-gate * from io-space before calling this, so we pass in the func to do the 2364*7c478bd9Sstevel@tonic-gate * transfer as a parameter. 2365*7c478bd9Sstevel@tonic-gate */ 2366*7c478bd9Sstevel@tonic-gate static uint64_t 2367*7c478bd9Sstevel@tonic-gate do_pior_corrupt(struct bofi_shadow *hp, caddr_t addr, 2368*7c478bd9Sstevel@tonic-gate uint64_t (*func)(), size_t repcount, size_t accsize) 2369*7c478bd9Sstevel@tonic-gate { 2370*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2371*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 2372*7c478bd9Sstevel@tonic-gate uint64_t operand; 2373*7c478bd9Sstevel@tonic-gate uintptr_t minlen; 2374*7c478bd9Sstevel@tonic-gate intptr_t base; 2375*7c478bd9Sstevel@tonic-gate int done_get = 0; 2376*7c478bd9Sstevel@tonic-gate uint64_t get_val, gv; 2377*7c478bd9Sstevel@tonic-gate 2378*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&bofi_mutex)); 2379*7c478bd9Sstevel@tonic-gate /* 2380*7c478bd9Sstevel@tonic-gate * check through all errdefs associated with this shadow handle 2381*7c478bd9Sstevel@tonic-gate */ 2382*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 2383*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 2384*7c478bd9Sstevel@tonic-gate if (ep->errdef.len == 0) 2385*7c478bd9Sstevel@tonic-gate minlen = hp->len; 2386*7c478bd9Sstevel@tonic-gate else 2387*7c478bd9Sstevel@tonic-gate minlen = min(hp->len, ep->errdef.len); 2388*7c478bd9Sstevel@tonic-gate base = addr - hp->addr - ep->errdef.offset + hp->offset; 2389*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_PIO_R) && 2390*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE) && 2391*7c478bd9Sstevel@tonic-gate base >= 0 && base < minlen) { 2392*7c478bd9Sstevel@tonic-gate /* 2393*7c478bd9Sstevel@tonic-gate * condition match for pio read 2394*7c478bd9Sstevel@tonic-gate */ 2395*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count > 1) { 2396*7c478bd9Sstevel@tonic-gate ep->errdef.access_count--; 2397*7c478bd9Sstevel@tonic-gate if (done_get == 0) { 2398*7c478bd9Sstevel@tonic-gate done_get = 1; 2399*7c478bd9Sstevel@tonic-gate gv = get_val = func(hp, addr); 2400*7c478bd9Sstevel@tonic-gate } 2401*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_type & BOFI_LOG) { 2402*7c478bd9Sstevel@tonic-gate log_acc_event(ep, BOFI_PIO_R, 2403*7c478bd9Sstevel@tonic-gate addr - hp->addr, 2404*7c478bd9Sstevel@tonic-gate accsize, repcount, &gv); 2405*7c478bd9Sstevel@tonic-gate } 2406*7c478bd9Sstevel@tonic-gate } else if (ep->errdef.fail_count > 0) { 2407*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count--; 2408*7c478bd9Sstevel@tonic-gate ep->errdef.access_count = 0; 2409*7c478bd9Sstevel@tonic-gate /* 2410*7c478bd9Sstevel@tonic-gate * OK do corruption 2411*7c478bd9Sstevel@tonic-gate */ 2412*7c478bd9Sstevel@tonic-gate if (ep->errstate.fail_time == 0) 2413*7c478bd9Sstevel@tonic-gate ep->errstate.fail_time = bofi_gettime(); 2414*7c478bd9Sstevel@tonic-gate operand = ep->errdef.operand; 2415*7c478bd9Sstevel@tonic-gate if (done_get == 0) { 2416*7c478bd9Sstevel@tonic-gate if (ep->errdef.optype == 2417*7c478bd9Sstevel@tonic-gate BOFI_NO_TRANSFER) 2418*7c478bd9Sstevel@tonic-gate /* 2419*7c478bd9Sstevel@tonic-gate * no transfer - bomb out 2420*7c478bd9Sstevel@tonic-gate */ 2421*7c478bd9Sstevel@tonic-gate return (operand); 2422*7c478bd9Sstevel@tonic-gate done_get = 1; 2423*7c478bd9Sstevel@tonic-gate gv = get_val = func(hp, addr); 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate } 2426*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_type & BOFI_LOG) { 2427*7c478bd9Sstevel@tonic-gate log_acc_event(ep, BOFI_PIO_R, 2428*7c478bd9Sstevel@tonic-gate addr - hp->addr, 2429*7c478bd9Sstevel@tonic-gate accsize, repcount, &gv); 2430*7c478bd9Sstevel@tonic-gate } 2431*7c478bd9Sstevel@tonic-gate switch (ep->errdef.optype) { 2432*7c478bd9Sstevel@tonic-gate case BOFI_EQUAL : 2433*7c478bd9Sstevel@tonic-gate get_val = operand; 2434*7c478bd9Sstevel@tonic-gate break; 2435*7c478bd9Sstevel@tonic-gate case BOFI_AND : 2436*7c478bd9Sstevel@tonic-gate get_val &= operand; 2437*7c478bd9Sstevel@tonic-gate break; 2438*7c478bd9Sstevel@tonic-gate case BOFI_OR : 2439*7c478bd9Sstevel@tonic-gate get_val |= operand; 2440*7c478bd9Sstevel@tonic-gate break; 2441*7c478bd9Sstevel@tonic-gate case BOFI_XOR : 2442*7c478bd9Sstevel@tonic-gate get_val ^= operand; 2443*7c478bd9Sstevel@tonic-gate break; 2444*7c478bd9Sstevel@tonic-gate default: 2445*7c478bd9Sstevel@tonic-gate /* do nothing */ 2446*7c478bd9Sstevel@tonic-gate break; 2447*7c478bd9Sstevel@tonic-gate } 2448*7c478bd9Sstevel@tonic-gate } 2449*7c478bd9Sstevel@tonic-gate } 2450*7c478bd9Sstevel@tonic-gate } 2451*7c478bd9Sstevel@tonic-gate if (done_get == 0) 2452*7c478bd9Sstevel@tonic-gate return (func(hp, addr)); 2453*7c478bd9Sstevel@tonic-gate else 2454*7c478bd9Sstevel@tonic-gate return (get_val); 2455*7c478bd9Sstevel@tonic-gate } 2456*7c478bd9Sstevel@tonic-gate 2457*7c478bd9Sstevel@tonic-gate 2458*7c478bd9Sstevel@tonic-gate /* 2459*7c478bd9Sstevel@tonic-gate * check all errdefs linked to this shadow handle. If we've got a condition 2460*7c478bd9Sstevel@tonic-gate * match check counts and corrupt data if necessary 2461*7c478bd9Sstevel@tonic-gate * 2462*7c478bd9Sstevel@tonic-gate * bofi_mutex always held when this is called. 2463*7c478bd9Sstevel@tonic-gate * 2464*7c478bd9Sstevel@tonic-gate * because of possibility of BOFI_NO_TRANSFER, we return 0 if no data 2465*7c478bd9Sstevel@tonic-gate * is to be written out to io-space, 1 otherwise 2466*7c478bd9Sstevel@tonic-gate */ 2467*7c478bd9Sstevel@tonic-gate static int 2468*7c478bd9Sstevel@tonic-gate do_piow_corrupt(struct bofi_shadow *hp, caddr_t addr, uint64_t *valuep, 2469*7c478bd9Sstevel@tonic-gate size_t size, size_t repcount) 2470*7c478bd9Sstevel@tonic-gate { 2471*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 2472*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 2473*7c478bd9Sstevel@tonic-gate uintptr_t minlen; 2474*7c478bd9Sstevel@tonic-gate intptr_t base; 2475*7c478bd9Sstevel@tonic-gate uint64_t v = *valuep; 2476*7c478bd9Sstevel@tonic-gate 2477*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&bofi_mutex)); 2478*7c478bd9Sstevel@tonic-gate /* 2479*7c478bd9Sstevel@tonic-gate * check through all errdefs associated with this shadow handle 2480*7c478bd9Sstevel@tonic-gate */ 2481*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 2482*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 2483*7c478bd9Sstevel@tonic-gate if (ep->errdef.len == 0) 2484*7c478bd9Sstevel@tonic-gate minlen = hp->len; 2485*7c478bd9Sstevel@tonic-gate else 2486*7c478bd9Sstevel@tonic-gate minlen = min(hp->len, ep->errdef.len); 2487*7c478bd9Sstevel@tonic-gate base = (caddr_t)addr - hp->addr - ep->errdef.offset +hp->offset; 2488*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_PIO_W) && 2489*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE) && 2490*7c478bd9Sstevel@tonic-gate base >= 0 && base < minlen) { 2491*7c478bd9Sstevel@tonic-gate /* 2492*7c478bd9Sstevel@tonic-gate * condition match for pio write 2493*7c478bd9Sstevel@tonic-gate */ 2494*7c478bd9Sstevel@tonic-gate 2495*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count > 1) { 2496*7c478bd9Sstevel@tonic-gate ep->errdef.access_count--; 2497*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_type & BOFI_LOG) 2498*7c478bd9Sstevel@tonic-gate log_acc_event(ep, BOFI_PIO_W, 2499*7c478bd9Sstevel@tonic-gate addr - hp->addr, size, 2500*7c478bd9Sstevel@tonic-gate repcount, &v); 2501*7c478bd9Sstevel@tonic-gate } else if (ep->errdef.fail_count > 0) { 2502*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count--; 2503*7c478bd9Sstevel@tonic-gate ep->errdef.access_count = 0; 2504*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_type & BOFI_LOG) 2505*7c478bd9Sstevel@tonic-gate log_acc_event(ep, BOFI_PIO_W, 2506*7c478bd9Sstevel@tonic-gate addr - hp->addr, size, 2507*7c478bd9Sstevel@tonic-gate repcount, &v); 2508*7c478bd9Sstevel@tonic-gate /* 2509*7c478bd9Sstevel@tonic-gate * OK do corruption 2510*7c478bd9Sstevel@tonic-gate */ 2511*7c478bd9Sstevel@tonic-gate if (ep->errstate.fail_time == 0) 2512*7c478bd9Sstevel@tonic-gate ep->errstate.fail_time = bofi_gettime(); 2513*7c478bd9Sstevel@tonic-gate switch (ep->errdef.optype) { 2514*7c478bd9Sstevel@tonic-gate case BOFI_EQUAL : 2515*7c478bd9Sstevel@tonic-gate *valuep = ep->errdef.operand; 2516*7c478bd9Sstevel@tonic-gate break; 2517*7c478bd9Sstevel@tonic-gate case BOFI_AND : 2518*7c478bd9Sstevel@tonic-gate *valuep &= ep->errdef.operand; 2519*7c478bd9Sstevel@tonic-gate break; 2520*7c478bd9Sstevel@tonic-gate case BOFI_OR : 2521*7c478bd9Sstevel@tonic-gate *valuep |= ep->errdef.operand; 2522*7c478bd9Sstevel@tonic-gate break; 2523*7c478bd9Sstevel@tonic-gate case BOFI_XOR : 2524*7c478bd9Sstevel@tonic-gate *valuep ^= ep->errdef.operand; 2525*7c478bd9Sstevel@tonic-gate break; 2526*7c478bd9Sstevel@tonic-gate case BOFI_NO_TRANSFER : 2527*7c478bd9Sstevel@tonic-gate /* 2528*7c478bd9Sstevel@tonic-gate * no transfer - bomb out 2529*7c478bd9Sstevel@tonic-gate */ 2530*7c478bd9Sstevel@tonic-gate return (0); 2531*7c478bd9Sstevel@tonic-gate default: 2532*7c478bd9Sstevel@tonic-gate /* do nothing */ 2533*7c478bd9Sstevel@tonic-gate break; 2534*7c478bd9Sstevel@tonic-gate } 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate } 2537*7c478bd9Sstevel@tonic-gate } 2538*7c478bd9Sstevel@tonic-gate return (1); 2539*7c478bd9Sstevel@tonic-gate } 2540*7c478bd9Sstevel@tonic-gate 2541*7c478bd9Sstevel@tonic-gate 2542*7c478bd9Sstevel@tonic-gate static uint64_t 2543*7c478bd9Sstevel@tonic-gate do_bofi_rd8(struct bofi_shadow *hp, caddr_t addr) 2544*7c478bd9Sstevel@tonic-gate { 2545*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get8(&hp->save.acc, (uint8_t *)addr)); 2546*7c478bd9Sstevel@tonic-gate } 2547*7c478bd9Sstevel@tonic-gate 2548*7c478bd9Sstevel@tonic-gate #define BOFI_READ_CHECKS(type) \ 2549*7c478bd9Sstevel@tonic-gate if (bofi_ddi_check) \ 2550*7c478bd9Sstevel@tonic-gate addr = (type *)((uintptr_t)addr - 64 + hp->addr); \ 2551*7c478bd9Sstevel@tonic-gate if (bofi_range_check && ((caddr_t)addr < hp->addr || \ 2552*7c478bd9Sstevel@tonic-gate (caddr_t)addr - hp->addr >= hp->len)) { \ 2553*7c478bd9Sstevel@tonic-gate cmn_err((bofi_range_check == 2) ? CE_PANIC : CE_WARN, \ 2554*7c478bd9Sstevel@tonic-gate "ddi_get() out of range addr %p not in %p/%llx", \ 2555*7c478bd9Sstevel@tonic-gate (void *)addr, (void *)hp->addr, hp->len); \ 2556*7c478bd9Sstevel@tonic-gate return (0); \ 2557*7c478bd9Sstevel@tonic-gate } 2558*7c478bd9Sstevel@tonic-gate 2559*7c478bd9Sstevel@tonic-gate /* 2560*7c478bd9Sstevel@tonic-gate * our getb() routine - use tryenter 2561*7c478bd9Sstevel@tonic-gate */ 2562*7c478bd9Sstevel@tonic-gate static uint8_t 2563*7c478bd9Sstevel@tonic-gate bofi_rd8(ddi_acc_impl_t *handle, uint8_t *addr) 2564*7c478bd9Sstevel@tonic-gate { 2565*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2566*7c478bd9Sstevel@tonic-gate uint8_t retval; 2567*7c478bd9Sstevel@tonic-gate 2568*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2569*7c478bd9Sstevel@tonic-gate BOFI_READ_CHECKS(uint8_t) 2570*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) 2571*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get8(&hp->save.acc, addr)); 2572*7c478bd9Sstevel@tonic-gate retval = (uint8_t)do_pior_corrupt(hp, (caddr_t)addr, do_bofi_rd8, 1, 2573*7c478bd9Sstevel@tonic-gate 1); 2574*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2575*7c478bd9Sstevel@tonic-gate return (retval); 2576*7c478bd9Sstevel@tonic-gate } 2577*7c478bd9Sstevel@tonic-gate 2578*7c478bd9Sstevel@tonic-gate 2579*7c478bd9Sstevel@tonic-gate static uint64_t 2580*7c478bd9Sstevel@tonic-gate do_bofi_rd16(struct bofi_shadow *hp, caddr_t addr) 2581*7c478bd9Sstevel@tonic-gate { 2582*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get16(&hp->save.acc, (uint16_t *)addr)); 2583*7c478bd9Sstevel@tonic-gate } 2584*7c478bd9Sstevel@tonic-gate 2585*7c478bd9Sstevel@tonic-gate 2586*7c478bd9Sstevel@tonic-gate /* 2587*7c478bd9Sstevel@tonic-gate * our getw() routine - use tryenter 2588*7c478bd9Sstevel@tonic-gate */ 2589*7c478bd9Sstevel@tonic-gate static uint16_t 2590*7c478bd9Sstevel@tonic-gate bofi_rd16(ddi_acc_impl_t *handle, uint16_t *addr) 2591*7c478bd9Sstevel@tonic-gate { 2592*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2593*7c478bd9Sstevel@tonic-gate uint16_t retval; 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2596*7c478bd9Sstevel@tonic-gate BOFI_READ_CHECKS(uint16_t) 2597*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) 2598*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get16(&hp->save.acc, addr)); 2599*7c478bd9Sstevel@tonic-gate retval = (uint16_t)do_pior_corrupt(hp, (caddr_t)addr, do_bofi_rd16, 1, 2600*7c478bd9Sstevel@tonic-gate 2); 2601*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2602*7c478bd9Sstevel@tonic-gate return (retval); 2603*7c478bd9Sstevel@tonic-gate } 2604*7c478bd9Sstevel@tonic-gate 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate static uint64_t 2607*7c478bd9Sstevel@tonic-gate do_bofi_rd32(struct bofi_shadow *hp, caddr_t addr) 2608*7c478bd9Sstevel@tonic-gate { 2609*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get32(&hp->save.acc, (uint32_t *)addr)); 2610*7c478bd9Sstevel@tonic-gate } 2611*7c478bd9Sstevel@tonic-gate 2612*7c478bd9Sstevel@tonic-gate 2613*7c478bd9Sstevel@tonic-gate /* 2614*7c478bd9Sstevel@tonic-gate * our getl() routine - use tryenter 2615*7c478bd9Sstevel@tonic-gate */ 2616*7c478bd9Sstevel@tonic-gate static uint32_t 2617*7c478bd9Sstevel@tonic-gate bofi_rd32(ddi_acc_impl_t *handle, uint32_t *addr) 2618*7c478bd9Sstevel@tonic-gate { 2619*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2620*7c478bd9Sstevel@tonic-gate uint32_t retval; 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2623*7c478bd9Sstevel@tonic-gate BOFI_READ_CHECKS(uint32_t) 2624*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) 2625*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get32(&hp->save.acc, addr)); 2626*7c478bd9Sstevel@tonic-gate retval = (uint32_t)do_pior_corrupt(hp, (caddr_t)addr, do_bofi_rd32, 1, 2627*7c478bd9Sstevel@tonic-gate 4); 2628*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2629*7c478bd9Sstevel@tonic-gate return (retval); 2630*7c478bd9Sstevel@tonic-gate } 2631*7c478bd9Sstevel@tonic-gate 2632*7c478bd9Sstevel@tonic-gate 2633*7c478bd9Sstevel@tonic-gate static uint64_t 2634*7c478bd9Sstevel@tonic-gate do_bofi_rd64(struct bofi_shadow *hp, caddr_t addr) 2635*7c478bd9Sstevel@tonic-gate { 2636*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get64(&hp->save.acc, (uint64_t *)addr)); 2637*7c478bd9Sstevel@tonic-gate } 2638*7c478bd9Sstevel@tonic-gate 2639*7c478bd9Sstevel@tonic-gate 2640*7c478bd9Sstevel@tonic-gate /* 2641*7c478bd9Sstevel@tonic-gate * our getll() routine - use tryenter 2642*7c478bd9Sstevel@tonic-gate */ 2643*7c478bd9Sstevel@tonic-gate static uint64_t 2644*7c478bd9Sstevel@tonic-gate bofi_rd64(ddi_acc_impl_t *handle, uint64_t *addr) 2645*7c478bd9Sstevel@tonic-gate { 2646*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2647*7c478bd9Sstevel@tonic-gate uint64_t retval; 2648*7c478bd9Sstevel@tonic-gate 2649*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2650*7c478bd9Sstevel@tonic-gate BOFI_READ_CHECKS(uint64_t) 2651*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) 2652*7c478bd9Sstevel@tonic-gate return (hp->save.acc.ahi_get64(&hp->save.acc, addr)); 2653*7c478bd9Sstevel@tonic-gate retval = (uint64_t)do_pior_corrupt(hp, (caddr_t)addr, do_bofi_rd64, 1, 2654*7c478bd9Sstevel@tonic-gate 8); 2655*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2656*7c478bd9Sstevel@tonic-gate return (retval); 2657*7c478bd9Sstevel@tonic-gate } 2658*7c478bd9Sstevel@tonic-gate 2659*7c478bd9Sstevel@tonic-gate #define BOFI_WRITE_TESTS(type) \ 2660*7c478bd9Sstevel@tonic-gate if (bofi_ddi_check) \ 2661*7c478bd9Sstevel@tonic-gate addr = (type *)((uintptr_t)addr - 64 + hp->addr); \ 2662*7c478bd9Sstevel@tonic-gate if (bofi_range_check && ((caddr_t)addr < hp->addr || \ 2663*7c478bd9Sstevel@tonic-gate (caddr_t)addr - hp->addr >= hp->len)) { \ 2664*7c478bd9Sstevel@tonic-gate cmn_err((bofi_range_check == 2) ? CE_PANIC : CE_WARN, \ 2665*7c478bd9Sstevel@tonic-gate "ddi_put() out of range addr %p not in %p/%llx\n", \ 2666*7c478bd9Sstevel@tonic-gate (void *)addr, (void *)hp->addr, hp->len); \ 2667*7c478bd9Sstevel@tonic-gate return; \ 2668*7c478bd9Sstevel@tonic-gate } 2669*7c478bd9Sstevel@tonic-gate 2670*7c478bd9Sstevel@tonic-gate /* 2671*7c478bd9Sstevel@tonic-gate * our putb() routine - use tryenter 2672*7c478bd9Sstevel@tonic-gate */ 2673*7c478bd9Sstevel@tonic-gate static void 2674*7c478bd9Sstevel@tonic-gate bofi_wr8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t value) 2675*7c478bd9Sstevel@tonic-gate { 2676*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2677*7c478bd9Sstevel@tonic-gate uint64_t llvalue = value; 2678*7c478bd9Sstevel@tonic-gate 2679*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2680*7c478bd9Sstevel@tonic-gate BOFI_WRITE_TESTS(uint8_t) 2681*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2682*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put8(&hp->save.acc, addr, (uint8_t)llvalue); 2683*7c478bd9Sstevel@tonic-gate return; 2684*7c478bd9Sstevel@tonic-gate } 2685*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 1, 1)) 2686*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put8(&hp->save.acc, addr, (uint8_t)llvalue); 2687*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2688*7c478bd9Sstevel@tonic-gate } 2689*7c478bd9Sstevel@tonic-gate 2690*7c478bd9Sstevel@tonic-gate 2691*7c478bd9Sstevel@tonic-gate /* 2692*7c478bd9Sstevel@tonic-gate * our putw() routine - use tryenter 2693*7c478bd9Sstevel@tonic-gate */ 2694*7c478bd9Sstevel@tonic-gate static void 2695*7c478bd9Sstevel@tonic-gate bofi_wr16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t value) 2696*7c478bd9Sstevel@tonic-gate { 2697*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2698*7c478bd9Sstevel@tonic-gate uint64_t llvalue = value; 2699*7c478bd9Sstevel@tonic-gate 2700*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2701*7c478bd9Sstevel@tonic-gate BOFI_WRITE_TESTS(uint16_t) 2702*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2703*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put16(&hp->save.acc, addr, (uint16_t)llvalue); 2704*7c478bd9Sstevel@tonic-gate return; 2705*7c478bd9Sstevel@tonic-gate } 2706*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 2, 1)) 2707*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put16(&hp->save.acc, addr, (uint16_t)llvalue); 2708*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2709*7c478bd9Sstevel@tonic-gate } 2710*7c478bd9Sstevel@tonic-gate 2711*7c478bd9Sstevel@tonic-gate 2712*7c478bd9Sstevel@tonic-gate /* 2713*7c478bd9Sstevel@tonic-gate * our putl() routine - use tryenter 2714*7c478bd9Sstevel@tonic-gate */ 2715*7c478bd9Sstevel@tonic-gate static void 2716*7c478bd9Sstevel@tonic-gate bofi_wr32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t value) 2717*7c478bd9Sstevel@tonic-gate { 2718*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2719*7c478bd9Sstevel@tonic-gate uint64_t llvalue = value; 2720*7c478bd9Sstevel@tonic-gate 2721*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2722*7c478bd9Sstevel@tonic-gate BOFI_WRITE_TESTS(uint32_t) 2723*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2724*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put32(&hp->save.acc, addr, (uint32_t)llvalue); 2725*7c478bd9Sstevel@tonic-gate return; 2726*7c478bd9Sstevel@tonic-gate } 2727*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 4, 1)) 2728*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put32(&hp->save.acc, addr, (uint32_t)llvalue); 2729*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2730*7c478bd9Sstevel@tonic-gate } 2731*7c478bd9Sstevel@tonic-gate 2732*7c478bd9Sstevel@tonic-gate 2733*7c478bd9Sstevel@tonic-gate /* 2734*7c478bd9Sstevel@tonic-gate * our putll() routine - use tryenter 2735*7c478bd9Sstevel@tonic-gate */ 2736*7c478bd9Sstevel@tonic-gate static void 2737*7c478bd9Sstevel@tonic-gate bofi_wr64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t value) 2738*7c478bd9Sstevel@tonic-gate { 2739*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2740*7c478bd9Sstevel@tonic-gate uint64_t llvalue = value; 2741*7c478bd9Sstevel@tonic-gate 2742*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2743*7c478bd9Sstevel@tonic-gate BOFI_WRITE_TESTS(uint64_t) 2744*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2745*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put64(&hp->save.acc, addr, (uint64_t)llvalue); 2746*7c478bd9Sstevel@tonic-gate return; 2747*7c478bd9Sstevel@tonic-gate } 2748*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 8, 1)) 2749*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put64(&hp->save.acc, addr, (uint64_t)llvalue); 2750*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2751*7c478bd9Sstevel@tonic-gate } 2752*7c478bd9Sstevel@tonic-gate 2753*7c478bd9Sstevel@tonic-gate #define BOFI_REP_READ_TESTS(type) \ 2754*7c478bd9Sstevel@tonic-gate if (bofi_ddi_check) \ 2755*7c478bd9Sstevel@tonic-gate dev_addr = (type *)((uintptr_t)dev_addr - 64 + hp->addr); \ 2756*7c478bd9Sstevel@tonic-gate if (bofi_range_check && ((caddr_t)dev_addr < hp->addr || \ 2757*7c478bd9Sstevel@tonic-gate (caddr_t)(dev_addr + repcount) - hp->addr > hp->len)) { \ 2758*7c478bd9Sstevel@tonic-gate cmn_err((bofi_range_check == 2) ? CE_PANIC : CE_WARN, \ 2759*7c478bd9Sstevel@tonic-gate "ddi_rep_get() out of range addr %p not in %p/%llx\n", \ 2760*7c478bd9Sstevel@tonic-gate (void *)dev_addr, (void *)hp->addr, hp->len); \ 2761*7c478bd9Sstevel@tonic-gate if ((caddr_t)dev_addr < hp->addr || \ 2762*7c478bd9Sstevel@tonic-gate (caddr_t)dev_addr - hp->addr >= hp->len) \ 2763*7c478bd9Sstevel@tonic-gate return; \ 2764*7c478bd9Sstevel@tonic-gate repcount = (type *)(hp->addr + hp->len) - dev_addr; \ 2765*7c478bd9Sstevel@tonic-gate } 2766*7c478bd9Sstevel@tonic-gate 2767*7c478bd9Sstevel@tonic-gate /* 2768*7c478bd9Sstevel@tonic-gate * our rep_getb() routine - use tryenter 2769*7c478bd9Sstevel@tonic-gate */ 2770*7c478bd9Sstevel@tonic-gate static void 2771*7c478bd9Sstevel@tonic-gate bofi_rep_rd8(ddi_acc_impl_t *handle, uint8_t *host_addr, uint8_t *dev_addr, 2772*7c478bd9Sstevel@tonic-gate size_t repcount, uint_t flags) 2773*7c478bd9Sstevel@tonic-gate { 2774*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2775*7c478bd9Sstevel@tonic-gate int i; 2776*7c478bd9Sstevel@tonic-gate uint8_t *addr; 2777*7c478bd9Sstevel@tonic-gate 2778*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2779*7c478bd9Sstevel@tonic-gate BOFI_REP_READ_TESTS(uint8_t) 2780*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2781*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_get8(&hp->save.acc, host_addr, dev_addr, 2782*7c478bd9Sstevel@tonic-gate repcount, flags); 2783*7c478bd9Sstevel@tonic-gate return; 2784*7c478bd9Sstevel@tonic-gate } 2785*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2786*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2787*7c478bd9Sstevel@tonic-gate *(host_addr + i) = (uint8_t)do_pior_corrupt(hp, (caddr_t)addr, 2788*7c478bd9Sstevel@tonic-gate do_bofi_rd8, i ? 0 : repcount, 1); 2789*7c478bd9Sstevel@tonic-gate } 2790*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2791*7c478bd9Sstevel@tonic-gate } 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate 2794*7c478bd9Sstevel@tonic-gate /* 2795*7c478bd9Sstevel@tonic-gate * our rep_getw() routine - use tryenter 2796*7c478bd9Sstevel@tonic-gate */ 2797*7c478bd9Sstevel@tonic-gate static void 2798*7c478bd9Sstevel@tonic-gate bofi_rep_rd16(ddi_acc_impl_t *handle, uint16_t *host_addr, 2799*7c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags) 2800*7c478bd9Sstevel@tonic-gate { 2801*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2802*7c478bd9Sstevel@tonic-gate int i; 2803*7c478bd9Sstevel@tonic-gate uint16_t *addr; 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2806*7c478bd9Sstevel@tonic-gate BOFI_REP_READ_TESTS(uint16_t) 2807*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2808*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_get16(&hp->save.acc, host_addr, dev_addr, 2809*7c478bd9Sstevel@tonic-gate repcount, flags); 2810*7c478bd9Sstevel@tonic-gate return; 2811*7c478bd9Sstevel@tonic-gate } 2812*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2813*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2814*7c478bd9Sstevel@tonic-gate *(host_addr + i) = (uint16_t)do_pior_corrupt(hp, (caddr_t)addr, 2815*7c478bd9Sstevel@tonic-gate do_bofi_rd16, i ? 0 : repcount, 2); 2816*7c478bd9Sstevel@tonic-gate } 2817*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2818*7c478bd9Sstevel@tonic-gate } 2819*7c478bd9Sstevel@tonic-gate 2820*7c478bd9Sstevel@tonic-gate 2821*7c478bd9Sstevel@tonic-gate /* 2822*7c478bd9Sstevel@tonic-gate * our rep_getl() routine - use tryenter 2823*7c478bd9Sstevel@tonic-gate */ 2824*7c478bd9Sstevel@tonic-gate static void 2825*7c478bd9Sstevel@tonic-gate bofi_rep_rd32(ddi_acc_impl_t *handle, uint32_t *host_addr, 2826*7c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags) 2827*7c478bd9Sstevel@tonic-gate { 2828*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2829*7c478bd9Sstevel@tonic-gate int i; 2830*7c478bd9Sstevel@tonic-gate uint32_t *addr; 2831*7c478bd9Sstevel@tonic-gate 2832*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2833*7c478bd9Sstevel@tonic-gate BOFI_REP_READ_TESTS(uint32_t) 2834*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2835*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_get32(&hp->save.acc, host_addr, dev_addr, 2836*7c478bd9Sstevel@tonic-gate repcount, flags); 2837*7c478bd9Sstevel@tonic-gate return; 2838*7c478bd9Sstevel@tonic-gate } 2839*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2840*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2841*7c478bd9Sstevel@tonic-gate *(host_addr + i) = (uint32_t)do_pior_corrupt(hp, (caddr_t)addr, 2842*7c478bd9Sstevel@tonic-gate do_bofi_rd32, i ? 0 : repcount, 4); 2843*7c478bd9Sstevel@tonic-gate } 2844*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2845*7c478bd9Sstevel@tonic-gate } 2846*7c478bd9Sstevel@tonic-gate 2847*7c478bd9Sstevel@tonic-gate 2848*7c478bd9Sstevel@tonic-gate /* 2849*7c478bd9Sstevel@tonic-gate * our rep_getll() routine - use tryenter 2850*7c478bd9Sstevel@tonic-gate */ 2851*7c478bd9Sstevel@tonic-gate static void 2852*7c478bd9Sstevel@tonic-gate bofi_rep_rd64(ddi_acc_impl_t *handle, uint64_t *host_addr, 2853*7c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags) 2854*7c478bd9Sstevel@tonic-gate { 2855*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2856*7c478bd9Sstevel@tonic-gate int i; 2857*7c478bd9Sstevel@tonic-gate uint64_t *addr; 2858*7c478bd9Sstevel@tonic-gate 2859*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2860*7c478bd9Sstevel@tonic-gate BOFI_REP_READ_TESTS(uint64_t) 2861*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2862*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_get64(&hp->save.acc, host_addr, dev_addr, 2863*7c478bd9Sstevel@tonic-gate repcount, flags); 2864*7c478bd9Sstevel@tonic-gate return; 2865*7c478bd9Sstevel@tonic-gate } 2866*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2867*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2868*7c478bd9Sstevel@tonic-gate *(host_addr + i) = (uint64_t)do_pior_corrupt(hp, (caddr_t)addr, 2869*7c478bd9Sstevel@tonic-gate do_bofi_rd64, i ? 0 : repcount, 8); 2870*7c478bd9Sstevel@tonic-gate } 2871*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2872*7c478bd9Sstevel@tonic-gate } 2873*7c478bd9Sstevel@tonic-gate 2874*7c478bd9Sstevel@tonic-gate #define BOFI_REP_WRITE_TESTS(type) \ 2875*7c478bd9Sstevel@tonic-gate if (bofi_ddi_check) \ 2876*7c478bd9Sstevel@tonic-gate dev_addr = (type *)((uintptr_t)dev_addr - 64 + hp->addr); \ 2877*7c478bd9Sstevel@tonic-gate if (bofi_range_check && ((caddr_t)dev_addr < hp->addr || \ 2878*7c478bd9Sstevel@tonic-gate (caddr_t)(dev_addr + repcount) - hp->addr > hp->len)) { \ 2879*7c478bd9Sstevel@tonic-gate cmn_err((bofi_range_check == 2) ? CE_PANIC : CE_WARN, \ 2880*7c478bd9Sstevel@tonic-gate "ddi_rep_put() out of range addr %p not in %p/%llx\n", \ 2881*7c478bd9Sstevel@tonic-gate (void *)dev_addr, (void *)hp->addr, hp->len); \ 2882*7c478bd9Sstevel@tonic-gate if ((caddr_t)dev_addr < hp->addr || \ 2883*7c478bd9Sstevel@tonic-gate (caddr_t)dev_addr - hp->addr >= hp->len) \ 2884*7c478bd9Sstevel@tonic-gate return; \ 2885*7c478bd9Sstevel@tonic-gate repcount = (type *)(hp->addr + hp->len) - dev_addr; \ 2886*7c478bd9Sstevel@tonic-gate } 2887*7c478bd9Sstevel@tonic-gate 2888*7c478bd9Sstevel@tonic-gate /* 2889*7c478bd9Sstevel@tonic-gate * our rep_putb() routine - use tryenter 2890*7c478bd9Sstevel@tonic-gate */ 2891*7c478bd9Sstevel@tonic-gate static void 2892*7c478bd9Sstevel@tonic-gate bofi_rep_wr8(ddi_acc_impl_t *handle, uint8_t *host_addr, uint8_t *dev_addr, 2893*7c478bd9Sstevel@tonic-gate size_t repcount, uint_t flags) 2894*7c478bd9Sstevel@tonic-gate { 2895*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2896*7c478bd9Sstevel@tonic-gate int i; 2897*7c478bd9Sstevel@tonic-gate uint64_t llvalue; 2898*7c478bd9Sstevel@tonic-gate uint8_t *addr; 2899*7c478bd9Sstevel@tonic-gate 2900*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2901*7c478bd9Sstevel@tonic-gate BOFI_REP_WRITE_TESTS(uint8_t) 2902*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2903*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_put8(&hp->save.acc, host_addr, dev_addr, 2904*7c478bd9Sstevel@tonic-gate repcount, flags); 2905*7c478bd9Sstevel@tonic-gate return; 2906*7c478bd9Sstevel@tonic-gate } 2907*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2908*7c478bd9Sstevel@tonic-gate llvalue = *(host_addr + i); 2909*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2910*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 1, i ? 0 : 2911*7c478bd9Sstevel@tonic-gate repcount)) 2912*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put8(&hp->save.acc, addr, 2913*7c478bd9Sstevel@tonic-gate (uint8_t)llvalue); 2914*7c478bd9Sstevel@tonic-gate } 2915*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2916*7c478bd9Sstevel@tonic-gate } 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate 2919*7c478bd9Sstevel@tonic-gate /* 2920*7c478bd9Sstevel@tonic-gate * our rep_putw() routine - use tryenter 2921*7c478bd9Sstevel@tonic-gate */ 2922*7c478bd9Sstevel@tonic-gate static void 2923*7c478bd9Sstevel@tonic-gate bofi_rep_wr16(ddi_acc_impl_t *handle, uint16_t *host_addr, 2924*7c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags) 2925*7c478bd9Sstevel@tonic-gate { 2926*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2927*7c478bd9Sstevel@tonic-gate int i; 2928*7c478bd9Sstevel@tonic-gate uint64_t llvalue; 2929*7c478bd9Sstevel@tonic-gate uint16_t *addr; 2930*7c478bd9Sstevel@tonic-gate 2931*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2932*7c478bd9Sstevel@tonic-gate BOFI_REP_WRITE_TESTS(uint16_t) 2933*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2934*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_put16(&hp->save.acc, host_addr, dev_addr, 2935*7c478bd9Sstevel@tonic-gate repcount, flags); 2936*7c478bd9Sstevel@tonic-gate return; 2937*7c478bd9Sstevel@tonic-gate } 2938*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2939*7c478bd9Sstevel@tonic-gate llvalue = *(host_addr + i); 2940*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2941*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 2, i ? 0 : 2942*7c478bd9Sstevel@tonic-gate repcount)) 2943*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put16(&hp->save.acc, addr, 2944*7c478bd9Sstevel@tonic-gate (uint16_t)llvalue); 2945*7c478bd9Sstevel@tonic-gate } 2946*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2947*7c478bd9Sstevel@tonic-gate } 2948*7c478bd9Sstevel@tonic-gate 2949*7c478bd9Sstevel@tonic-gate 2950*7c478bd9Sstevel@tonic-gate /* 2951*7c478bd9Sstevel@tonic-gate * our rep_putl() routine - use tryenter 2952*7c478bd9Sstevel@tonic-gate */ 2953*7c478bd9Sstevel@tonic-gate static void 2954*7c478bd9Sstevel@tonic-gate bofi_rep_wr32(ddi_acc_impl_t *handle, uint32_t *host_addr, 2955*7c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags) 2956*7c478bd9Sstevel@tonic-gate { 2957*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2958*7c478bd9Sstevel@tonic-gate int i; 2959*7c478bd9Sstevel@tonic-gate uint64_t llvalue; 2960*7c478bd9Sstevel@tonic-gate uint32_t *addr; 2961*7c478bd9Sstevel@tonic-gate 2962*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2963*7c478bd9Sstevel@tonic-gate BOFI_REP_WRITE_TESTS(uint32_t) 2964*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2965*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_put32(&hp->save.acc, host_addr, dev_addr, 2966*7c478bd9Sstevel@tonic-gate repcount, flags); 2967*7c478bd9Sstevel@tonic-gate return; 2968*7c478bd9Sstevel@tonic-gate } 2969*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 2970*7c478bd9Sstevel@tonic-gate llvalue = *(host_addr + i); 2971*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 2972*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 4, i ? 0 : 2973*7c478bd9Sstevel@tonic-gate repcount)) 2974*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put32(&hp->save.acc, addr, 2975*7c478bd9Sstevel@tonic-gate (uint32_t)llvalue); 2976*7c478bd9Sstevel@tonic-gate } 2977*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 2978*7c478bd9Sstevel@tonic-gate } 2979*7c478bd9Sstevel@tonic-gate 2980*7c478bd9Sstevel@tonic-gate 2981*7c478bd9Sstevel@tonic-gate /* 2982*7c478bd9Sstevel@tonic-gate * our rep_putll() routine - use tryenter 2983*7c478bd9Sstevel@tonic-gate */ 2984*7c478bd9Sstevel@tonic-gate static void 2985*7c478bd9Sstevel@tonic-gate bofi_rep_wr64(ddi_acc_impl_t *handle, uint64_t *host_addr, 2986*7c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags) 2987*7c478bd9Sstevel@tonic-gate { 2988*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 2989*7c478bd9Sstevel@tonic-gate int i; 2990*7c478bd9Sstevel@tonic-gate uint64_t llvalue; 2991*7c478bd9Sstevel@tonic-gate uint64_t *addr; 2992*7c478bd9Sstevel@tonic-gate 2993*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 2994*7c478bd9Sstevel@tonic-gate BOFI_REP_WRITE_TESTS(uint64_t) 2995*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 2996*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_rep_put64(&hp->save.acc, host_addr, dev_addr, 2997*7c478bd9Sstevel@tonic-gate repcount, flags); 2998*7c478bd9Sstevel@tonic-gate return; 2999*7c478bd9Sstevel@tonic-gate } 3000*7c478bd9Sstevel@tonic-gate for (i = 0; i < repcount; i++) { 3001*7c478bd9Sstevel@tonic-gate llvalue = *(host_addr + i); 3002*7c478bd9Sstevel@tonic-gate addr = dev_addr + ((flags == DDI_DEV_AUTOINCR) ? i : 0); 3003*7c478bd9Sstevel@tonic-gate if (do_piow_corrupt(hp, (caddr_t)addr, &llvalue, 8, i ? 0 : 3004*7c478bd9Sstevel@tonic-gate repcount)) 3005*7c478bd9Sstevel@tonic-gate hp->save.acc.ahi_put64(&hp->save.acc, addr, 3006*7c478bd9Sstevel@tonic-gate (uint64_t)llvalue); 3007*7c478bd9Sstevel@tonic-gate } 3008*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3009*7c478bd9Sstevel@tonic-gate } 3010*7c478bd9Sstevel@tonic-gate 3011*7c478bd9Sstevel@tonic-gate 3012*7c478bd9Sstevel@tonic-gate /* 3013*7c478bd9Sstevel@tonic-gate * our ddi_map routine 3014*7c478bd9Sstevel@tonic-gate */ 3015*7c478bd9Sstevel@tonic-gate static int 3016*7c478bd9Sstevel@tonic-gate bofi_map(dev_info_t *dip, dev_info_t *rdip, 3017*7c478bd9Sstevel@tonic-gate ddi_map_req_t *reqp, off_t offset, off_t len, caddr_t *vaddrp) 3018*7c478bd9Sstevel@tonic-gate { 3019*7c478bd9Sstevel@tonic-gate ddi_acc_impl_t *ap; 3020*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3021*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 3022*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *next_lp; 3023*7c478bd9Sstevel@tonic-gate int retval; 3024*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 3025*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3026*7c478bd9Sstevel@tonic-gate 3027*7c478bd9Sstevel@tonic-gate switch (reqp->map_op) { 3028*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_LOCKED: 3029*7c478bd9Sstevel@tonic-gate /* 3030*7c478bd9Sstevel@tonic-gate * for this case get nexus to do real work first 3031*7c478bd9Sstevel@tonic-gate */ 3032*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_map(dip, rdip, reqp, offset, len, 3033*7c478bd9Sstevel@tonic-gate vaddrp); 3034*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3035*7c478bd9Sstevel@tonic-gate return (retval); 3036*7c478bd9Sstevel@tonic-gate 3037*7c478bd9Sstevel@tonic-gate ap = (ddi_acc_impl_t *)reqp->map_handlep; 3038*7c478bd9Sstevel@tonic-gate if (ap == NULL) 3039*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3040*7c478bd9Sstevel@tonic-gate /* 3041*7c478bd9Sstevel@tonic-gate * if driver_list is set, only intercept those drivers 3042*7c478bd9Sstevel@tonic-gate */ 3043*7c478bd9Sstevel@tonic-gate if (!driver_under_test(ap->ahi_common.ah_dip)) 3044*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3045*7c478bd9Sstevel@tonic-gate 3046*7c478bd9Sstevel@tonic-gate /* 3047*7c478bd9Sstevel@tonic-gate * support for ddi_regs_map_setup() 3048*7c478bd9Sstevel@tonic-gate * - allocate shadow handle structure and fill it in 3049*7c478bd9Sstevel@tonic-gate */ 3050*7c478bd9Sstevel@tonic-gate hp = kmem_zalloc(sizeof (struct bofi_shadow), KM_SLEEP); 3051*7c478bd9Sstevel@tonic-gate (void) strncpy(hp->name, ddi_get_name(ap->ahi_common.ah_dip), 3052*7c478bd9Sstevel@tonic-gate NAMESIZE); 3053*7c478bd9Sstevel@tonic-gate hp->instance = ddi_get_instance(ap->ahi_common.ah_dip); 3054*7c478bd9Sstevel@tonic-gate hp->dip = ap->ahi_common.ah_dip; 3055*7c478bd9Sstevel@tonic-gate hp->addr = *vaddrp; 3056*7c478bd9Sstevel@tonic-gate /* 3057*7c478bd9Sstevel@tonic-gate * return spurious value to catch direct access to registers 3058*7c478bd9Sstevel@tonic-gate */ 3059*7c478bd9Sstevel@tonic-gate if (bofi_ddi_check) 3060*7c478bd9Sstevel@tonic-gate *vaddrp = (caddr_t)64; 3061*7c478bd9Sstevel@tonic-gate hp->rnumber = ((ddi_acc_hdl_t *)ap)->ah_rnumber; 3062*7c478bd9Sstevel@tonic-gate hp->offset = offset; 3063*7c478bd9Sstevel@tonic-gate if (len == 0) 3064*7c478bd9Sstevel@tonic-gate hp->len = INT_MAX - offset; 3065*7c478bd9Sstevel@tonic-gate else 3066*7c478bd9Sstevel@tonic-gate hp->len = min(len, INT_MAX - offset); 3067*7c478bd9Sstevel@tonic-gate hp->hdl.acc_handle = (ddi_acc_handle_t)ap; 3068*7c478bd9Sstevel@tonic-gate hp->link = NULL; 3069*7c478bd9Sstevel@tonic-gate hp->type = BOFI_ACC_HDL; 3070*7c478bd9Sstevel@tonic-gate /* 3071*7c478bd9Sstevel@tonic-gate * save existing function pointers and plug in our own 3072*7c478bd9Sstevel@tonic-gate */ 3073*7c478bd9Sstevel@tonic-gate hp->save.acc = *ap; 3074*7c478bd9Sstevel@tonic-gate ap->ahi_get8 = bofi_rd8; 3075*7c478bd9Sstevel@tonic-gate ap->ahi_get16 = bofi_rd16; 3076*7c478bd9Sstevel@tonic-gate ap->ahi_get32 = bofi_rd32; 3077*7c478bd9Sstevel@tonic-gate ap->ahi_get64 = bofi_rd64; 3078*7c478bd9Sstevel@tonic-gate ap->ahi_put8 = bofi_wr8; 3079*7c478bd9Sstevel@tonic-gate ap->ahi_put16 = bofi_wr16; 3080*7c478bd9Sstevel@tonic-gate ap->ahi_put32 = bofi_wr32; 3081*7c478bd9Sstevel@tonic-gate ap->ahi_put64 = bofi_wr64; 3082*7c478bd9Sstevel@tonic-gate ap->ahi_rep_get8 = bofi_rep_rd8; 3083*7c478bd9Sstevel@tonic-gate ap->ahi_rep_get16 = bofi_rep_rd16; 3084*7c478bd9Sstevel@tonic-gate ap->ahi_rep_get32 = bofi_rep_rd32; 3085*7c478bd9Sstevel@tonic-gate ap->ahi_rep_get64 = bofi_rep_rd64; 3086*7c478bd9Sstevel@tonic-gate ap->ahi_rep_put8 = bofi_rep_wr8; 3087*7c478bd9Sstevel@tonic-gate ap->ahi_rep_put16 = bofi_rep_wr16; 3088*7c478bd9Sstevel@tonic-gate ap->ahi_rep_put32 = bofi_rep_wr32; 3089*7c478bd9Sstevel@tonic-gate ap->ahi_rep_put64 = bofi_rep_wr64; 3090*7c478bd9Sstevel@tonic-gate ap->ahi_fault_check = bofi_check_acc_hdl; 3091*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 3092*7c478bd9Sstevel@tonic-gate #else 3093*7c478bd9Sstevel@tonic-gate ap->ahi_acc_attr &= ~DDI_ACCATTR_DIRECT; 3094*7c478bd9Sstevel@tonic-gate #endif 3095*7c478bd9Sstevel@tonic-gate /* 3096*7c478bd9Sstevel@tonic-gate * stick in a pointer to our shadow handle 3097*7c478bd9Sstevel@tonic-gate */ 3098*7c478bd9Sstevel@tonic-gate ap->ahi_common.ah_bus_private = hp; 3099*7c478bd9Sstevel@tonic-gate /* 3100*7c478bd9Sstevel@tonic-gate * add to dhash, hhash and inuse lists 3101*7c478bd9Sstevel@tonic-gate */ 3102*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3103*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3104*7c478bd9Sstevel@tonic-gate hp->next = shadow_list.next; 3105*7c478bd9Sstevel@tonic-gate shadow_list.next->prev = hp; 3106*7c478bd9Sstevel@tonic-gate hp->prev = &shadow_list; 3107*7c478bd9Sstevel@tonic-gate shadow_list.next = hp; 3108*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(ap); 3109*7c478bd9Sstevel@tonic-gate hp->hnext = hhashp->hnext; 3110*7c478bd9Sstevel@tonic-gate hhashp->hnext->hprev = hp; 3111*7c478bd9Sstevel@tonic-gate hp->hprev = hhashp; 3112*7c478bd9Sstevel@tonic-gate hhashp->hnext = hp; 3113*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 3114*7c478bd9Sstevel@tonic-gate hp->dnext = dhashp->dnext; 3115*7c478bd9Sstevel@tonic-gate dhashp->dnext->dprev = hp; 3116*7c478bd9Sstevel@tonic-gate hp->dprev = dhashp; 3117*7c478bd9Sstevel@tonic-gate dhashp->dnext = hp; 3118*7c478bd9Sstevel@tonic-gate /* 3119*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this 3120*7c478bd9Sstevel@tonic-gate * acc_handle 3121*7c478bd9Sstevel@tonic-gate */ 3122*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) { 3123*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(hp->name) == 3124*7c478bd9Sstevel@tonic-gate ddi_name_to_major(ep->name) && 3125*7c478bd9Sstevel@tonic-gate hp->instance == ep->errdef.instance && 3126*7c478bd9Sstevel@tonic-gate (ep->errdef.access_type & BOFI_PIO_RW) && 3127*7c478bd9Sstevel@tonic-gate (ep->errdef.rnumber == -1 || 3128*7c478bd9Sstevel@tonic-gate hp->rnumber == ep->errdef.rnumber) && 3129*7c478bd9Sstevel@tonic-gate (ep->errdef.len == 0 || 3130*7c478bd9Sstevel@tonic-gate offset < ep->errdef.offset + ep->errdef.len) && 3131*7c478bd9Sstevel@tonic-gate offset + hp->len > ep->errdef.offset) { 3132*7c478bd9Sstevel@tonic-gate lp = bofi_link_freelist; 3133*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 3134*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp->link; 3135*7c478bd9Sstevel@tonic-gate lp->errentp = ep; 3136*7c478bd9Sstevel@tonic-gate lp->link = hp->link; 3137*7c478bd9Sstevel@tonic-gate hp->link = lp; 3138*7c478bd9Sstevel@tonic-gate } 3139*7c478bd9Sstevel@tonic-gate } 3140*7c478bd9Sstevel@tonic-gate } 3141*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3142*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3143*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3144*7c478bd9Sstevel@tonic-gate case DDI_MO_UNMAP: 3145*7c478bd9Sstevel@tonic-gate 3146*7c478bd9Sstevel@tonic-gate ap = (ddi_acc_impl_t *)reqp->map_handlep; 3147*7c478bd9Sstevel@tonic-gate if (ap == NULL) 3148*7c478bd9Sstevel@tonic-gate break; 3149*7c478bd9Sstevel@tonic-gate /* 3150*7c478bd9Sstevel@tonic-gate * support for ddi_regs_map_free() 3151*7c478bd9Sstevel@tonic-gate * - check we really have a shadow handle for this one 3152*7c478bd9Sstevel@tonic-gate */ 3153*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3154*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3155*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(ap); 3156*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3157*7c478bd9Sstevel@tonic-gate if (hp->hdl.acc_handle == (ddi_acc_handle_t)ap) 3158*7c478bd9Sstevel@tonic-gate break; 3159*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 3160*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3161*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3162*7c478bd9Sstevel@tonic-gate break; 3163*7c478bd9Sstevel@tonic-gate } 3164*7c478bd9Sstevel@tonic-gate /* 3165*7c478bd9Sstevel@tonic-gate * got a shadow handle - restore original pointers 3166*7c478bd9Sstevel@tonic-gate */ 3167*7c478bd9Sstevel@tonic-gate *ap = hp->save.acc; 3168*7c478bd9Sstevel@tonic-gate *vaddrp = hp->addr; 3169*7c478bd9Sstevel@tonic-gate /* 3170*7c478bd9Sstevel@tonic-gate * remove from dhash, hhash and inuse lists 3171*7c478bd9Sstevel@tonic-gate */ 3172*7c478bd9Sstevel@tonic-gate hp->hnext->hprev = hp->hprev; 3173*7c478bd9Sstevel@tonic-gate hp->hprev->hnext = hp->hnext; 3174*7c478bd9Sstevel@tonic-gate hp->dnext->dprev = hp->dprev; 3175*7c478bd9Sstevel@tonic-gate hp->dprev->dnext = hp->dnext; 3176*7c478bd9Sstevel@tonic-gate hp->next->prev = hp->prev; 3177*7c478bd9Sstevel@tonic-gate hp->prev->next = hp->next; 3178*7c478bd9Sstevel@tonic-gate /* 3179*7c478bd9Sstevel@tonic-gate * free any errdef link structures tagged onto the shadow handle 3180*7c478bd9Sstevel@tonic-gate */ 3181*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 3182*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 3183*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 3184*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 3185*7c478bd9Sstevel@tonic-gate lp = next_lp; 3186*7c478bd9Sstevel@tonic-gate } 3187*7c478bd9Sstevel@tonic-gate hp->link = NULL; 3188*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3189*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3190*7c478bd9Sstevel@tonic-gate /* 3191*7c478bd9Sstevel@tonic-gate * finally delete shadow handle 3192*7c478bd9Sstevel@tonic-gate */ 3193*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 3194*7c478bd9Sstevel@tonic-gate break; 3195*7c478bd9Sstevel@tonic-gate default: 3196*7c478bd9Sstevel@tonic-gate break; 3197*7c478bd9Sstevel@tonic-gate } 3198*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_map(dip, rdip, reqp, offset, len, vaddrp)); 3199*7c478bd9Sstevel@tonic-gate } 3200*7c478bd9Sstevel@tonic-gate 3201*7c478bd9Sstevel@tonic-gate 3202*7c478bd9Sstevel@tonic-gate /* 3203*7c478bd9Sstevel@tonic-gate * chain any pre-existing errdefs on to newly created dma handle 3204*7c478bd9Sstevel@tonic-gate * if required call do_dma_corrupt() to corrupt data 3205*7c478bd9Sstevel@tonic-gate */ 3206*7c478bd9Sstevel@tonic-gate static void 3207*7c478bd9Sstevel@tonic-gate chain_on_errdefs(struct bofi_shadow *hp) 3208*7c478bd9Sstevel@tonic-gate { 3209*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 3210*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 3211*7c478bd9Sstevel@tonic-gate 3212*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&bofi_mutex)); 3213*7c478bd9Sstevel@tonic-gate /* 3214*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this dma_handle 3215*7c478bd9Sstevel@tonic-gate */ 3216*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) { 3217*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(hp->name) == 3218*7c478bd9Sstevel@tonic-gate ddi_name_to_major(ep->name) && 3219*7c478bd9Sstevel@tonic-gate hp->instance == ep->errdef.instance && 3220*7c478bd9Sstevel@tonic-gate (ep->errdef.rnumber == -1 || 3221*7c478bd9Sstevel@tonic-gate hp->rnumber == ep->errdef.rnumber) && 3222*7c478bd9Sstevel@tonic-gate ((ep->errdef.access_type & BOFI_DMA_RW) && 3223*7c478bd9Sstevel@tonic-gate (((uintptr_t)(hp->addr + ep->errdef.offset + 3224*7c478bd9Sstevel@tonic-gate ep->errdef.len) & ~LLSZMASK) > 3225*7c478bd9Sstevel@tonic-gate ((uintptr_t)((hp->addr + ep->errdef.offset) + 3226*7c478bd9Sstevel@tonic-gate LLSZMASK) & ~LLSZMASK)))) { 3227*7c478bd9Sstevel@tonic-gate /* 3228*7c478bd9Sstevel@tonic-gate * got a match - link it on 3229*7c478bd9Sstevel@tonic-gate */ 3230*7c478bd9Sstevel@tonic-gate lp = bofi_link_freelist; 3231*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 3232*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp->link; 3233*7c478bd9Sstevel@tonic-gate lp->errentp = ep; 3234*7c478bd9Sstevel@tonic-gate lp->link = hp->link; 3235*7c478bd9Sstevel@tonic-gate hp->link = lp; 3236*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_DMA_W) && 3237*7c478bd9Sstevel@tonic-gate (hp->flags & DDI_DMA_WRITE) && 3238*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 3239*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, 3240*7c478bd9Sstevel@tonic-gate DDI_DMA_SYNC_FORDEV, 3241*7c478bd9Sstevel@tonic-gate 0, hp->len); 3242*7c478bd9Sstevel@tonic-gate } 3243*7c478bd9Sstevel@tonic-gate } 3244*7c478bd9Sstevel@tonic-gate } 3245*7c478bd9Sstevel@tonic-gate } 3246*7c478bd9Sstevel@tonic-gate } 3247*7c478bd9Sstevel@tonic-gate 3248*7c478bd9Sstevel@tonic-gate 3249*7c478bd9Sstevel@tonic-gate /* 3250*7c478bd9Sstevel@tonic-gate * need to do copy byte-by-byte in case one of pages is little-endian 3251*7c478bd9Sstevel@tonic-gate */ 3252*7c478bd9Sstevel@tonic-gate static void 3253*7c478bd9Sstevel@tonic-gate xbcopy(void *from, void *to, u_longlong_t len) 3254*7c478bd9Sstevel@tonic-gate { 3255*7c478bd9Sstevel@tonic-gate uchar_t *f = from; 3256*7c478bd9Sstevel@tonic-gate uchar_t *t = to; 3257*7c478bd9Sstevel@tonic-gate 3258*7c478bd9Sstevel@tonic-gate while (len--) 3259*7c478bd9Sstevel@tonic-gate *t++ = *f++; 3260*7c478bd9Sstevel@tonic-gate } 3261*7c478bd9Sstevel@tonic-gate 3262*7c478bd9Sstevel@tonic-gate 3263*7c478bd9Sstevel@tonic-gate /* 3264*7c478bd9Sstevel@tonic-gate * our ddi_dma_map routine 3265*7c478bd9Sstevel@tonic-gate */ 3266*7c478bd9Sstevel@tonic-gate static int 3267*7c478bd9Sstevel@tonic-gate bofi_dma_map(dev_info_t *dip, dev_info_t *rdip, 3268*7c478bd9Sstevel@tonic-gate struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 3269*7c478bd9Sstevel@tonic-gate { 3270*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp, *xhp; 3271*7c478bd9Sstevel@tonic-gate int maxrnumber = 0; 3272*7c478bd9Sstevel@tonic-gate int retval = DDI_DMA_NORESOURCES; 3273*7c478bd9Sstevel@tonic-gate auto struct ddi_dma_req dmareq; 3274*7c478bd9Sstevel@tonic-gate int sleep; 3275*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 3276*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3277*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 3278*7c478bd9Sstevel@tonic-gate unsigned long pagemask = ddi_ptob(rdip, 1) - 1; 3279*7c478bd9Sstevel@tonic-gate 3280*7c478bd9Sstevel@tonic-gate /* 3281*7c478bd9Sstevel@tonic-gate * if driver_list is set, only intercept those drivers 3282*7c478bd9Sstevel@tonic-gate */ 3283*7c478bd9Sstevel@tonic-gate if (handlep == NULL || !driver_under_test(rdip)) 3284*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_dma_map(dip, rdip, dmareqp, handlep)); 3285*7c478bd9Sstevel@tonic-gate 3286*7c478bd9Sstevel@tonic-gate sleep = (dmareqp->dmar_fp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP; 3287*7c478bd9Sstevel@tonic-gate /* 3288*7c478bd9Sstevel@tonic-gate * allocate shadow handle structure and fill it in 3289*7c478bd9Sstevel@tonic-gate */ 3290*7c478bd9Sstevel@tonic-gate hp = kmem_zalloc(sizeof (struct bofi_shadow), sleep); 3291*7c478bd9Sstevel@tonic-gate if (hp == NULL) 3292*7c478bd9Sstevel@tonic-gate goto error; 3293*7c478bd9Sstevel@tonic-gate (void) strncpy(hp->name, ddi_get_name(rdip), NAMESIZE); 3294*7c478bd9Sstevel@tonic-gate hp->instance = ddi_get_instance(rdip); 3295*7c478bd9Sstevel@tonic-gate hp->dip = rdip; 3296*7c478bd9Sstevel@tonic-gate hp->flags = dmareqp->dmar_flags; 3297*7c478bd9Sstevel@tonic-gate hp->link = NULL; 3298*7c478bd9Sstevel@tonic-gate hp->type = BOFI_DMA_HDL; 3299*7c478bd9Sstevel@tonic-gate /* 3300*7c478bd9Sstevel@tonic-gate * get a kernel virtual mapping 3301*7c478bd9Sstevel@tonic-gate */ 3302*7c478bd9Sstevel@tonic-gate hp->addr = ddi_dmareq_mapin(dmareqp, &hp->mapaddr, &hp->len); 3303*7c478bd9Sstevel@tonic-gate if (hp->addr == NULL) 3304*7c478bd9Sstevel@tonic-gate goto error; 3305*7c478bd9Sstevel@tonic-gate if (bofi_sync_check) { 3306*7c478bd9Sstevel@tonic-gate /* 3307*7c478bd9Sstevel@tonic-gate * Take a copy and pass pointers to this up to nexus instead. 3308*7c478bd9Sstevel@tonic-gate * Data will be copied from the original on explicit 3309*7c478bd9Sstevel@tonic-gate * and implicit ddi_dma_sync() 3310*7c478bd9Sstevel@tonic-gate * 3311*7c478bd9Sstevel@tonic-gate * - maintain page alignment because some devices assume it. 3312*7c478bd9Sstevel@tonic-gate */ 3313*7c478bd9Sstevel@tonic-gate hp->origaddr = hp->addr; 3314*7c478bd9Sstevel@tonic-gate hp->allocaddr = ddi_umem_alloc( 3315*7c478bd9Sstevel@tonic-gate ((uintptr_t)hp->addr & pagemask) + hp->len, sleep, 3316*7c478bd9Sstevel@tonic-gate &hp->umem_cookie); 3317*7c478bd9Sstevel@tonic-gate if (hp->allocaddr == NULL) 3318*7c478bd9Sstevel@tonic-gate goto error; 3319*7c478bd9Sstevel@tonic-gate hp->addr = hp->allocaddr + ((uintptr_t)hp->addr & pagemask); 3320*7c478bd9Sstevel@tonic-gate if (dmareqp->dmar_flags & DDI_DMA_WRITE) 3321*7c478bd9Sstevel@tonic-gate xbcopy(hp->origaddr, hp->addr, hp->len); 3322*7c478bd9Sstevel@tonic-gate dmareq = *dmareqp; 3323*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_size = hp->len; 3324*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 3325*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_as = &kas; 3326*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_addr = hp->addr; 3327*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 3328*7c478bd9Sstevel@tonic-gate dmareqp = &dmareq; 3329*7c478bd9Sstevel@tonic-gate } 3330*7c478bd9Sstevel@tonic-gate /* 3331*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3332*7c478bd9Sstevel@tonic-gate */ 3333*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_map(dip, rdip, dmareqp, handlep); 3334*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3335*7c478bd9Sstevel@tonic-gate goto error2; 3336*7c478bd9Sstevel@tonic-gate /* 3337*7c478bd9Sstevel@tonic-gate * now set dma_handle to point to real handle 3338*7c478bd9Sstevel@tonic-gate */ 3339*7c478bd9Sstevel@tonic-gate hp->hdl.dma_handle = *handlep; 3340*7c478bd9Sstevel@tonic-gate /* 3341*7c478bd9Sstevel@tonic-gate * unset DMP_NOSYNC 3342*7c478bd9Sstevel@tonic-gate */ 3343*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)*handlep; 3344*7c478bd9Sstevel@tonic-gate mp->dmai_rflags &= ~DMP_NOSYNC; 3345*7c478bd9Sstevel@tonic-gate mp->dmai_fault_check = bofi_check_dma_hdl; 3346*7c478bd9Sstevel@tonic-gate /* 3347*7c478bd9Sstevel@tonic-gate * bind and unbind are cached in devinfo - must overwrite them 3348*7c478bd9Sstevel@tonic-gate * - note that our bind and unbind are quite happy dealing with 3349*7c478bd9Sstevel@tonic-gate * any handles for this devinfo that were previously allocated 3350*7c478bd9Sstevel@tonic-gate */ 3351*7c478bd9Sstevel@tonic-gate if (save_bus_ops.bus_dma_bindhdl == DEVI(rdip)->devi_bus_dma_bindfunc) 3352*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_bindfunc = bofi_dma_bindhdl; 3353*7c478bd9Sstevel@tonic-gate if (save_bus_ops.bus_dma_unbindhdl == 3354*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_unbindfunc) 3355*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_unbindfunc = bofi_dma_unbindhdl; 3356*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3357*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3358*7c478bd9Sstevel@tonic-gate /* 3359*7c478bd9Sstevel@tonic-gate * get an "rnumber" for this handle - really just seeking to 3360*7c478bd9Sstevel@tonic-gate * get a unique number - generally only care for early allocated 3361*7c478bd9Sstevel@tonic-gate * handles - so we get as far as INT_MAX, just stay there 3362*7c478bd9Sstevel@tonic-gate */ 3363*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 3364*7c478bd9Sstevel@tonic-gate for (xhp = dhashp->dnext; xhp != dhashp; xhp = xhp->dnext) 3365*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(xhp->name) == 3366*7c478bd9Sstevel@tonic-gate ddi_name_to_major(hp->name) && 3367*7c478bd9Sstevel@tonic-gate xhp->instance == hp->instance && 3368*7c478bd9Sstevel@tonic-gate xhp->type == BOFI_DMA_HDL) 3369*7c478bd9Sstevel@tonic-gate if (xhp->rnumber >= maxrnumber) { 3370*7c478bd9Sstevel@tonic-gate if (xhp->rnumber == INT_MAX) 3371*7c478bd9Sstevel@tonic-gate maxrnumber = INT_MAX; 3372*7c478bd9Sstevel@tonic-gate else 3373*7c478bd9Sstevel@tonic-gate maxrnumber = xhp->rnumber + 1; 3374*7c478bd9Sstevel@tonic-gate } 3375*7c478bd9Sstevel@tonic-gate hp->rnumber = maxrnumber; 3376*7c478bd9Sstevel@tonic-gate /* 3377*7c478bd9Sstevel@tonic-gate * add to dhash, hhash and inuse lists 3378*7c478bd9Sstevel@tonic-gate */ 3379*7c478bd9Sstevel@tonic-gate hp->next = shadow_list.next; 3380*7c478bd9Sstevel@tonic-gate shadow_list.next->prev = hp; 3381*7c478bd9Sstevel@tonic-gate hp->prev = &shadow_list; 3382*7c478bd9Sstevel@tonic-gate shadow_list.next = hp; 3383*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(*handlep); 3384*7c478bd9Sstevel@tonic-gate hp->hnext = hhashp->hnext; 3385*7c478bd9Sstevel@tonic-gate hhashp->hnext->hprev = hp; 3386*7c478bd9Sstevel@tonic-gate hp->hprev = hhashp; 3387*7c478bd9Sstevel@tonic-gate hhashp->hnext = hp; 3388*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 3389*7c478bd9Sstevel@tonic-gate hp->dnext = dhashp->dnext; 3390*7c478bd9Sstevel@tonic-gate dhashp->dnext->dprev = hp; 3391*7c478bd9Sstevel@tonic-gate hp->dprev = dhashp; 3392*7c478bd9Sstevel@tonic-gate dhashp->dnext = hp; 3393*7c478bd9Sstevel@tonic-gate /* 3394*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this 3395*7c478bd9Sstevel@tonic-gate * acc_handle and corrupt if required (as there is an implicit 3396*7c478bd9Sstevel@tonic-gate * ddi_dma_sync() in this call) 3397*7c478bd9Sstevel@tonic-gate */ 3398*7c478bd9Sstevel@tonic-gate chain_on_errdefs(hp); 3399*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3400*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3401*7c478bd9Sstevel@tonic-gate return (retval); 3402*7c478bd9Sstevel@tonic-gate error: 3403*7c478bd9Sstevel@tonic-gate if (dmareqp->dmar_fp != DDI_DMA_DONTWAIT) { 3404*7c478bd9Sstevel@tonic-gate /* 3405*7c478bd9Sstevel@tonic-gate * what to do here? Wait a bit and try again 3406*7c478bd9Sstevel@tonic-gate */ 3407*7c478bd9Sstevel@tonic-gate (void) timeout((void (*)())dmareqp->dmar_fp, 3408*7c478bd9Sstevel@tonic-gate dmareqp->dmar_arg, 10); 3409*7c478bd9Sstevel@tonic-gate } 3410*7c478bd9Sstevel@tonic-gate error2: 3411*7c478bd9Sstevel@tonic-gate if (hp) { 3412*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapout(hp->mapaddr, hp->len); 3413*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) 3414*7c478bd9Sstevel@tonic-gate ddi_umem_free(hp->umem_cookie); 3415*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 3416*7c478bd9Sstevel@tonic-gate } 3417*7c478bd9Sstevel@tonic-gate return (retval); 3418*7c478bd9Sstevel@tonic-gate } 3419*7c478bd9Sstevel@tonic-gate 3420*7c478bd9Sstevel@tonic-gate 3421*7c478bd9Sstevel@tonic-gate /* 3422*7c478bd9Sstevel@tonic-gate * our ddi_dma_allochdl routine 3423*7c478bd9Sstevel@tonic-gate */ 3424*7c478bd9Sstevel@tonic-gate static int 3425*7c478bd9Sstevel@tonic-gate bofi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp, 3426*7c478bd9Sstevel@tonic-gate int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 3427*7c478bd9Sstevel@tonic-gate { 3428*7c478bd9Sstevel@tonic-gate int retval = DDI_DMA_NORESOURCES; 3429*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp, *xhp; 3430*7c478bd9Sstevel@tonic-gate int maxrnumber = 0; 3431*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 3432*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3433*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 3434*7c478bd9Sstevel@tonic-gate 3435*7c478bd9Sstevel@tonic-gate /* 3436*7c478bd9Sstevel@tonic-gate * if driver_list is set, only intercept those drivers 3437*7c478bd9Sstevel@tonic-gate */ 3438*7c478bd9Sstevel@tonic-gate if (!driver_under_test(rdip)) 3439*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_dma_allochdl(dip, rdip, attrp, 3440*7c478bd9Sstevel@tonic-gate waitfp, arg, handlep)); 3441*7c478bd9Sstevel@tonic-gate 3442*7c478bd9Sstevel@tonic-gate /* 3443*7c478bd9Sstevel@tonic-gate * allocate shadow handle structure and fill it in 3444*7c478bd9Sstevel@tonic-gate */ 3445*7c478bd9Sstevel@tonic-gate hp = kmem_zalloc(sizeof (struct bofi_shadow), 3446*7c478bd9Sstevel@tonic-gate ((waitfp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP)); 3447*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 3448*7c478bd9Sstevel@tonic-gate /* 3449*7c478bd9Sstevel@tonic-gate * what to do here? Wait a bit and try again 3450*7c478bd9Sstevel@tonic-gate */ 3451*7c478bd9Sstevel@tonic-gate if (waitfp != DDI_DMA_DONTWAIT) 3452*7c478bd9Sstevel@tonic-gate (void) timeout((void (*)())waitfp, arg, 10); 3453*7c478bd9Sstevel@tonic-gate return (retval); 3454*7c478bd9Sstevel@tonic-gate } 3455*7c478bd9Sstevel@tonic-gate (void) strncpy(hp->name, ddi_get_name(rdip), NAMESIZE); 3456*7c478bd9Sstevel@tonic-gate hp->instance = ddi_get_instance(rdip); 3457*7c478bd9Sstevel@tonic-gate hp->dip = rdip; 3458*7c478bd9Sstevel@tonic-gate hp->link = NULL; 3459*7c478bd9Sstevel@tonic-gate hp->type = BOFI_NULL; 3460*7c478bd9Sstevel@tonic-gate /* 3461*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3462*7c478bd9Sstevel@tonic-gate */ 3463*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_allochdl(dip, rdip, attrp, waitfp, arg, 3464*7c478bd9Sstevel@tonic-gate handlep); 3465*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) { 3466*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 3467*7c478bd9Sstevel@tonic-gate return (retval); 3468*7c478bd9Sstevel@tonic-gate } 3469*7c478bd9Sstevel@tonic-gate /* 3470*7c478bd9Sstevel@tonic-gate * now point set dma_handle to point to real handle 3471*7c478bd9Sstevel@tonic-gate */ 3472*7c478bd9Sstevel@tonic-gate hp->hdl.dma_handle = *handlep; 3473*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)*handlep; 3474*7c478bd9Sstevel@tonic-gate mp->dmai_fault_check = bofi_check_dma_hdl; 3475*7c478bd9Sstevel@tonic-gate /* 3476*7c478bd9Sstevel@tonic-gate * bind and unbind are cached in devinfo - must overwrite them 3477*7c478bd9Sstevel@tonic-gate * - note that our bind and unbind are quite happy dealing with 3478*7c478bd9Sstevel@tonic-gate * any handles for this devinfo that were previously allocated 3479*7c478bd9Sstevel@tonic-gate */ 3480*7c478bd9Sstevel@tonic-gate if (save_bus_ops.bus_dma_bindhdl == DEVI(rdip)->devi_bus_dma_bindfunc) 3481*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_bindfunc = bofi_dma_bindhdl; 3482*7c478bd9Sstevel@tonic-gate if (save_bus_ops.bus_dma_unbindhdl == 3483*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_unbindfunc) 3484*7c478bd9Sstevel@tonic-gate DEVI(rdip)->devi_bus_dma_unbindfunc = bofi_dma_unbindhdl; 3485*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3486*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3487*7c478bd9Sstevel@tonic-gate /* 3488*7c478bd9Sstevel@tonic-gate * get an "rnumber" for this handle - really just seeking to 3489*7c478bd9Sstevel@tonic-gate * get a unique number - generally only care for early allocated 3490*7c478bd9Sstevel@tonic-gate * handles - so we get as far as INT_MAX, just stay there 3491*7c478bd9Sstevel@tonic-gate */ 3492*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 3493*7c478bd9Sstevel@tonic-gate for (xhp = dhashp->dnext; xhp != dhashp; xhp = xhp->dnext) 3494*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(xhp->name) == 3495*7c478bd9Sstevel@tonic-gate ddi_name_to_major(hp->name) && 3496*7c478bd9Sstevel@tonic-gate xhp->instance == hp->instance && 3497*7c478bd9Sstevel@tonic-gate (xhp->type == BOFI_DMA_HDL || 3498*7c478bd9Sstevel@tonic-gate xhp->type == BOFI_NULL)) 3499*7c478bd9Sstevel@tonic-gate if (xhp->rnumber >= maxrnumber) { 3500*7c478bd9Sstevel@tonic-gate if (xhp->rnumber == INT_MAX) 3501*7c478bd9Sstevel@tonic-gate maxrnumber = INT_MAX; 3502*7c478bd9Sstevel@tonic-gate else 3503*7c478bd9Sstevel@tonic-gate maxrnumber = xhp->rnumber + 1; 3504*7c478bd9Sstevel@tonic-gate } 3505*7c478bd9Sstevel@tonic-gate hp->rnumber = maxrnumber; 3506*7c478bd9Sstevel@tonic-gate /* 3507*7c478bd9Sstevel@tonic-gate * add to dhash, hhash and inuse lists 3508*7c478bd9Sstevel@tonic-gate */ 3509*7c478bd9Sstevel@tonic-gate hp->next = shadow_list.next; 3510*7c478bd9Sstevel@tonic-gate shadow_list.next->prev = hp; 3511*7c478bd9Sstevel@tonic-gate hp->prev = &shadow_list; 3512*7c478bd9Sstevel@tonic-gate shadow_list.next = hp; 3513*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(*handlep); 3514*7c478bd9Sstevel@tonic-gate hp->hnext = hhashp->hnext; 3515*7c478bd9Sstevel@tonic-gate hhashp->hnext->hprev = hp; 3516*7c478bd9Sstevel@tonic-gate hp->hprev = hhashp; 3517*7c478bd9Sstevel@tonic-gate hhashp->hnext = hp; 3518*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 3519*7c478bd9Sstevel@tonic-gate hp->dnext = dhashp->dnext; 3520*7c478bd9Sstevel@tonic-gate dhashp->dnext->dprev = hp; 3521*7c478bd9Sstevel@tonic-gate hp->dprev = dhashp; 3522*7c478bd9Sstevel@tonic-gate dhashp->dnext = hp; 3523*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3524*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3525*7c478bd9Sstevel@tonic-gate return (retval); 3526*7c478bd9Sstevel@tonic-gate } 3527*7c478bd9Sstevel@tonic-gate 3528*7c478bd9Sstevel@tonic-gate 3529*7c478bd9Sstevel@tonic-gate /* 3530*7c478bd9Sstevel@tonic-gate * our ddi_dma_freehdl routine 3531*7c478bd9Sstevel@tonic-gate */ 3532*7c478bd9Sstevel@tonic-gate static int 3533*7c478bd9Sstevel@tonic-gate bofi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) 3534*7c478bd9Sstevel@tonic-gate { 3535*7c478bd9Sstevel@tonic-gate int retval; 3536*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3537*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3538*7c478bd9Sstevel@tonic-gate 3539*7c478bd9Sstevel@tonic-gate /* 3540*7c478bd9Sstevel@tonic-gate * find shadow for this handle 3541*7c478bd9Sstevel@tonic-gate */ 3542*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3543*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3544*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3545*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3546*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle) 3547*7c478bd9Sstevel@tonic-gate break; 3548*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3549*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3550*7c478bd9Sstevel@tonic-gate /* 3551*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3552*7c478bd9Sstevel@tonic-gate */ 3553*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_freehdl(dip, rdip, handle); 3554*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) { 3555*7c478bd9Sstevel@tonic-gate return (retval); 3556*7c478bd9Sstevel@tonic-gate } 3557*7c478bd9Sstevel@tonic-gate /* 3558*7c478bd9Sstevel@tonic-gate * did we really have a shadow for this handle 3559*7c478bd9Sstevel@tonic-gate */ 3560*7c478bd9Sstevel@tonic-gate if (hp == hhashp) 3561*7c478bd9Sstevel@tonic-gate return (retval); 3562*7c478bd9Sstevel@tonic-gate /* 3563*7c478bd9Sstevel@tonic-gate * yes we have - see if it's still bound 3564*7c478bd9Sstevel@tonic-gate */ 3565*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3566*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3567*7c478bd9Sstevel@tonic-gate if (hp->type != BOFI_NULL) 3568*7c478bd9Sstevel@tonic-gate panic("driver freeing bound dma_handle"); 3569*7c478bd9Sstevel@tonic-gate /* 3570*7c478bd9Sstevel@tonic-gate * remove from dhash, hhash and inuse lists 3571*7c478bd9Sstevel@tonic-gate */ 3572*7c478bd9Sstevel@tonic-gate hp->hnext->hprev = hp->hprev; 3573*7c478bd9Sstevel@tonic-gate hp->hprev->hnext = hp->hnext; 3574*7c478bd9Sstevel@tonic-gate hp->dnext->dprev = hp->dprev; 3575*7c478bd9Sstevel@tonic-gate hp->dprev->dnext = hp->dnext; 3576*7c478bd9Sstevel@tonic-gate hp->next->prev = hp->prev; 3577*7c478bd9Sstevel@tonic-gate hp->prev->next = hp->next; 3578*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3579*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3580*7c478bd9Sstevel@tonic-gate 3581*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 3582*7c478bd9Sstevel@tonic-gate return (retval); 3583*7c478bd9Sstevel@tonic-gate } 3584*7c478bd9Sstevel@tonic-gate 3585*7c478bd9Sstevel@tonic-gate 3586*7c478bd9Sstevel@tonic-gate /* 3587*7c478bd9Sstevel@tonic-gate * our ddi_dma_bindhdl routine 3588*7c478bd9Sstevel@tonic-gate */ 3589*7c478bd9Sstevel@tonic-gate static int 3590*7c478bd9Sstevel@tonic-gate bofi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 3591*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t handle, struct ddi_dma_req *dmareqp, 3592*7c478bd9Sstevel@tonic-gate ddi_dma_cookie_t *cookiep, uint_t *ccountp) 3593*7c478bd9Sstevel@tonic-gate { 3594*7c478bd9Sstevel@tonic-gate int retval = DDI_DMA_NORESOURCES; 3595*7c478bd9Sstevel@tonic-gate auto struct ddi_dma_req dmareq; 3596*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3597*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3598*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 3599*7c478bd9Sstevel@tonic-gate unsigned long pagemask = ddi_ptob(rdip, 1) - 1; 3600*7c478bd9Sstevel@tonic-gate 3601*7c478bd9Sstevel@tonic-gate /* 3602*7c478bd9Sstevel@tonic-gate * check we really have a shadow for this handle 3603*7c478bd9Sstevel@tonic-gate */ 3604*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3605*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3606*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3607*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3608*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle) 3609*7c478bd9Sstevel@tonic-gate break; 3610*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3611*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3612*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 3613*7c478bd9Sstevel@tonic-gate /* 3614*7c478bd9Sstevel@tonic-gate * no we don't - just call nexus to do the real work 3615*7c478bd9Sstevel@tonic-gate */ 3616*7c478bd9Sstevel@tonic-gate return save_bus_ops.bus_dma_bindhdl(dip, rdip, handle, dmareqp, 3617*7c478bd9Sstevel@tonic-gate cookiep, ccountp); 3618*7c478bd9Sstevel@tonic-gate } 3619*7c478bd9Sstevel@tonic-gate /* 3620*7c478bd9Sstevel@tonic-gate * yes we have - see if it's already bound 3621*7c478bd9Sstevel@tonic-gate */ 3622*7c478bd9Sstevel@tonic-gate if (hp->type != BOFI_NULL) 3623*7c478bd9Sstevel@tonic-gate return (DDI_DMA_INUSE); 3624*7c478bd9Sstevel@tonic-gate 3625*7c478bd9Sstevel@tonic-gate hp->flags = dmareqp->dmar_flags; 3626*7c478bd9Sstevel@tonic-gate /* 3627*7c478bd9Sstevel@tonic-gate * get a kernel virtual mapping 3628*7c478bd9Sstevel@tonic-gate */ 3629*7c478bd9Sstevel@tonic-gate hp->addr = ddi_dmareq_mapin(dmareqp, &hp->mapaddr, &hp->len); 3630*7c478bd9Sstevel@tonic-gate if (hp->addr == NULL) 3631*7c478bd9Sstevel@tonic-gate goto error; 3632*7c478bd9Sstevel@tonic-gate if (bofi_sync_check) { 3633*7c478bd9Sstevel@tonic-gate /* 3634*7c478bd9Sstevel@tonic-gate * Take a copy and pass pointers to this up to nexus instead. 3635*7c478bd9Sstevel@tonic-gate * Data will be copied from the original on explicit 3636*7c478bd9Sstevel@tonic-gate * and implicit ddi_dma_sync() 3637*7c478bd9Sstevel@tonic-gate * 3638*7c478bd9Sstevel@tonic-gate * - maintain page alignment because some devices assume it. 3639*7c478bd9Sstevel@tonic-gate */ 3640*7c478bd9Sstevel@tonic-gate hp->origaddr = hp->addr; 3641*7c478bd9Sstevel@tonic-gate hp->allocaddr = ddi_umem_alloc( 3642*7c478bd9Sstevel@tonic-gate ((uintptr_t)hp->addr & pagemask) + hp->len, 3643*7c478bd9Sstevel@tonic-gate (dmareqp->dmar_fp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP, 3644*7c478bd9Sstevel@tonic-gate &hp->umem_cookie); 3645*7c478bd9Sstevel@tonic-gate if (hp->allocaddr == NULL) 3646*7c478bd9Sstevel@tonic-gate goto error; 3647*7c478bd9Sstevel@tonic-gate hp->addr = hp->allocaddr + ((uintptr_t)hp->addr & pagemask); 3648*7c478bd9Sstevel@tonic-gate if (dmareqp->dmar_flags & DDI_DMA_WRITE) 3649*7c478bd9Sstevel@tonic-gate xbcopy(hp->origaddr, hp->addr, hp->len); 3650*7c478bd9Sstevel@tonic-gate dmareq = *dmareqp; 3651*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_size = hp->len; 3652*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 3653*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_as = &kas; 3654*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_addr = hp->addr; 3655*7c478bd9Sstevel@tonic-gate dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 3656*7c478bd9Sstevel@tonic-gate dmareqp = &dmareq; 3657*7c478bd9Sstevel@tonic-gate } 3658*7c478bd9Sstevel@tonic-gate /* 3659*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3660*7c478bd9Sstevel@tonic-gate */ 3661*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_bindhdl(dip, rdip, handle, dmareqp, 3662*7c478bd9Sstevel@tonic-gate cookiep, ccountp); 3663*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3664*7c478bd9Sstevel@tonic-gate goto error2; 3665*7c478bd9Sstevel@tonic-gate /* 3666*7c478bd9Sstevel@tonic-gate * unset DMP_NOSYNC 3667*7c478bd9Sstevel@tonic-gate */ 3668*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)handle; 3669*7c478bd9Sstevel@tonic-gate mp->dmai_rflags &= ~DMP_NOSYNC; 3670*7c478bd9Sstevel@tonic-gate /* 3671*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this 3672*7c478bd9Sstevel@tonic-gate * acc_handle and corrupt if required (as there is an implicit 3673*7c478bd9Sstevel@tonic-gate * ddi_dma_sync() in this call) 3674*7c478bd9Sstevel@tonic-gate */ 3675*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3676*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3677*7c478bd9Sstevel@tonic-gate hp->type = BOFI_DMA_HDL; 3678*7c478bd9Sstevel@tonic-gate chain_on_errdefs(hp); 3679*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3680*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3681*7c478bd9Sstevel@tonic-gate return (retval); 3682*7c478bd9Sstevel@tonic-gate 3683*7c478bd9Sstevel@tonic-gate error: 3684*7c478bd9Sstevel@tonic-gate if (dmareqp->dmar_fp != DDI_DMA_DONTWAIT) { 3685*7c478bd9Sstevel@tonic-gate /* 3686*7c478bd9Sstevel@tonic-gate * what to do here? Wait a bit and try again 3687*7c478bd9Sstevel@tonic-gate */ 3688*7c478bd9Sstevel@tonic-gate (void) timeout((void (*)())dmareqp->dmar_fp, 3689*7c478bd9Sstevel@tonic-gate dmareqp->dmar_arg, 10); 3690*7c478bd9Sstevel@tonic-gate } 3691*7c478bd9Sstevel@tonic-gate error2: 3692*7c478bd9Sstevel@tonic-gate if (hp) { 3693*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapout(hp->mapaddr, hp->len); 3694*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) 3695*7c478bd9Sstevel@tonic-gate ddi_umem_free(hp->umem_cookie); 3696*7c478bd9Sstevel@tonic-gate hp->mapaddr = NULL; 3697*7c478bd9Sstevel@tonic-gate hp->allocaddr = NULL; 3698*7c478bd9Sstevel@tonic-gate hp->origaddr = NULL; 3699*7c478bd9Sstevel@tonic-gate } 3700*7c478bd9Sstevel@tonic-gate return (retval); 3701*7c478bd9Sstevel@tonic-gate } 3702*7c478bd9Sstevel@tonic-gate 3703*7c478bd9Sstevel@tonic-gate 3704*7c478bd9Sstevel@tonic-gate /* 3705*7c478bd9Sstevel@tonic-gate * our ddi_dma_unbindhdl routine 3706*7c478bd9Sstevel@tonic-gate */ 3707*7c478bd9Sstevel@tonic-gate static int 3708*7c478bd9Sstevel@tonic-gate bofi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) 3709*7c478bd9Sstevel@tonic-gate { 3710*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *next_lp; 3711*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 3712*7c478bd9Sstevel@tonic-gate int retval; 3713*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3714*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3715*7c478bd9Sstevel@tonic-gate 3716*7c478bd9Sstevel@tonic-gate /* 3717*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3718*7c478bd9Sstevel@tonic-gate */ 3719*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_unbindhdl(dip, rdip, handle); 3720*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3721*7c478bd9Sstevel@tonic-gate return (retval); 3722*7c478bd9Sstevel@tonic-gate /* 3723*7c478bd9Sstevel@tonic-gate * check we really have a shadow for this handle 3724*7c478bd9Sstevel@tonic-gate */ 3725*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3726*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3727*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3728*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3729*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle) 3730*7c478bd9Sstevel@tonic-gate break; 3731*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 3732*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3733*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3734*7c478bd9Sstevel@tonic-gate return (retval); 3735*7c478bd9Sstevel@tonic-gate } 3736*7c478bd9Sstevel@tonic-gate /* 3737*7c478bd9Sstevel@tonic-gate * yes we have - see if it's already unbound 3738*7c478bd9Sstevel@tonic-gate */ 3739*7c478bd9Sstevel@tonic-gate if (hp->type == BOFI_NULL) 3740*7c478bd9Sstevel@tonic-gate panic("driver unbinding unbound dma_handle"); 3741*7c478bd9Sstevel@tonic-gate /* 3742*7c478bd9Sstevel@tonic-gate * free any errdef link structures tagged on to this 3743*7c478bd9Sstevel@tonic-gate * shadow handle 3744*7c478bd9Sstevel@tonic-gate */ 3745*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 3746*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 3747*7c478bd9Sstevel@tonic-gate /* 3748*7c478bd9Sstevel@tonic-gate * there is an implicit sync_for_cpu on free - 3749*7c478bd9Sstevel@tonic-gate * may need to corrupt 3750*7c478bd9Sstevel@tonic-gate */ 3751*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 3752*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_DMA_R) && 3753*7c478bd9Sstevel@tonic-gate (hp->flags & DDI_DMA_READ) && 3754*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 3755*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, DDI_DMA_SYNC_FORCPU, 0, hp->len); 3756*7c478bd9Sstevel@tonic-gate } 3757*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 3758*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 3759*7c478bd9Sstevel@tonic-gate lp = next_lp; 3760*7c478bd9Sstevel@tonic-gate } 3761*7c478bd9Sstevel@tonic-gate hp->link = NULL; 3762*7c478bd9Sstevel@tonic-gate hp->type = BOFI_NULL; 3763*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3764*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3765*7c478bd9Sstevel@tonic-gate 3766*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && (hp->flags & DDI_DMA_READ)) 3767*7c478bd9Sstevel@tonic-gate /* 3768*7c478bd9Sstevel@tonic-gate * implicit sync_for_cpu - copy data back 3769*7c478bd9Sstevel@tonic-gate */ 3770*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 3771*7c478bd9Sstevel@tonic-gate xbcopy(hp->addr, hp->origaddr, hp->len); 3772*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapout(hp->mapaddr, hp->len); 3773*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) 3774*7c478bd9Sstevel@tonic-gate ddi_umem_free(hp->umem_cookie); 3775*7c478bd9Sstevel@tonic-gate hp->mapaddr = NULL; 3776*7c478bd9Sstevel@tonic-gate hp->allocaddr = NULL; 3777*7c478bd9Sstevel@tonic-gate hp->origaddr = NULL; 3778*7c478bd9Sstevel@tonic-gate return (retval); 3779*7c478bd9Sstevel@tonic-gate } 3780*7c478bd9Sstevel@tonic-gate 3781*7c478bd9Sstevel@tonic-gate 3782*7c478bd9Sstevel@tonic-gate /* 3783*7c478bd9Sstevel@tonic-gate * our ddi_dma_sync routine 3784*7c478bd9Sstevel@tonic-gate */ 3785*7c478bd9Sstevel@tonic-gate static int 3786*7c478bd9Sstevel@tonic-gate bofi_dma_flush(dev_info_t *dip, dev_info_t *rdip, 3787*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t handle, off_t off, size_t len, uint_t flags) 3788*7c478bd9Sstevel@tonic-gate { 3789*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 3790*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 3791*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3792*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3793*7c478bd9Sstevel@tonic-gate int retval; 3794*7c478bd9Sstevel@tonic-gate 3795*7c478bd9Sstevel@tonic-gate if (flags == DDI_DMA_SYNC_FORCPU || flags == DDI_DMA_SYNC_FORKERNEL) { 3796*7c478bd9Sstevel@tonic-gate /* 3797*7c478bd9Sstevel@tonic-gate * in this case get nexus driver to do sync first 3798*7c478bd9Sstevel@tonic-gate */ 3799*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_flush(dip, rdip, handle, off, 3800*7c478bd9Sstevel@tonic-gate len, flags); 3801*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3802*7c478bd9Sstevel@tonic-gate return (retval); 3803*7c478bd9Sstevel@tonic-gate } 3804*7c478bd9Sstevel@tonic-gate /* 3805*7c478bd9Sstevel@tonic-gate * check we really have a shadow for this handle 3806*7c478bd9Sstevel@tonic-gate */ 3807*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3808*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3809*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3810*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3811*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle && 3812*7c478bd9Sstevel@tonic-gate hp->type == BOFI_DMA_HDL) 3813*7c478bd9Sstevel@tonic-gate break; 3814*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3815*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3816*7c478bd9Sstevel@tonic-gate if (hp != hhashp) { 3817*7c478bd9Sstevel@tonic-gate /* 3818*7c478bd9Sstevel@tonic-gate * yes - do we need to copy data from original 3819*7c478bd9Sstevel@tonic-gate */ 3820*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && flags == DDI_DMA_SYNC_FORDEV) 3821*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 3822*7c478bd9Sstevel@tonic-gate xbcopy(hp->origaddr+off, hp->addr+off, 3823*7c478bd9Sstevel@tonic-gate len ? len : (hp->len - off)); 3824*7c478bd9Sstevel@tonic-gate /* 3825*7c478bd9Sstevel@tonic-gate * yes - check if we need to corrupt the data 3826*7c478bd9Sstevel@tonic-gate */ 3827*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3828*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3829*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 3830*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 3831*7c478bd9Sstevel@tonic-gate if ((((ep->errdef.access_type & BOFI_DMA_R) && 3832*7c478bd9Sstevel@tonic-gate (flags == DDI_DMA_SYNC_FORCPU || 3833*7c478bd9Sstevel@tonic-gate flags == DDI_DMA_SYNC_FORKERNEL)) || 3834*7c478bd9Sstevel@tonic-gate ((ep->errdef.access_type & BOFI_DMA_W) && 3835*7c478bd9Sstevel@tonic-gate (flags == DDI_DMA_SYNC_FORDEV))) && 3836*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 3837*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, flags, off, 3838*7c478bd9Sstevel@tonic-gate len ? len : (hp->len - off)); 3839*7c478bd9Sstevel@tonic-gate } 3840*7c478bd9Sstevel@tonic-gate } 3841*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3842*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3843*7c478bd9Sstevel@tonic-gate /* 3844*7c478bd9Sstevel@tonic-gate * do we need to copy data to original 3845*7c478bd9Sstevel@tonic-gate */ 3846*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && (flags == DDI_DMA_SYNC_FORCPU || 3847*7c478bd9Sstevel@tonic-gate flags == DDI_DMA_SYNC_FORKERNEL)) 3848*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 3849*7c478bd9Sstevel@tonic-gate xbcopy(hp->addr+off, hp->origaddr+off, 3850*7c478bd9Sstevel@tonic-gate len ? len : (hp->len - off)); 3851*7c478bd9Sstevel@tonic-gate } 3852*7c478bd9Sstevel@tonic-gate if (flags == DDI_DMA_SYNC_FORDEV) 3853*7c478bd9Sstevel@tonic-gate /* 3854*7c478bd9Sstevel@tonic-gate * in this case get nexus driver to do sync last 3855*7c478bd9Sstevel@tonic-gate */ 3856*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_flush(dip, rdip, handle, off, 3857*7c478bd9Sstevel@tonic-gate len, flags); 3858*7c478bd9Sstevel@tonic-gate return (retval); 3859*7c478bd9Sstevel@tonic-gate } 3860*7c478bd9Sstevel@tonic-gate 3861*7c478bd9Sstevel@tonic-gate 3862*7c478bd9Sstevel@tonic-gate /* 3863*7c478bd9Sstevel@tonic-gate * our dma_win routine 3864*7c478bd9Sstevel@tonic-gate */ 3865*7c478bd9Sstevel@tonic-gate static int 3866*7c478bd9Sstevel@tonic-gate bofi_dma_win(dev_info_t *dip, dev_info_t *rdip, 3867*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t handle, uint_t win, off_t *offp, 3868*7c478bd9Sstevel@tonic-gate size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 3869*7c478bd9Sstevel@tonic-gate { 3870*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3871*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3872*7c478bd9Sstevel@tonic-gate int retval; 3873*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 3874*7c478bd9Sstevel@tonic-gate 3875*7c478bd9Sstevel@tonic-gate /* 3876*7c478bd9Sstevel@tonic-gate * call nexus to do the real work 3877*7c478bd9Sstevel@tonic-gate */ 3878*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_win(dip, rdip, handle, win, offp, lenp, 3879*7c478bd9Sstevel@tonic-gate cookiep, ccountp); 3880*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3881*7c478bd9Sstevel@tonic-gate return (retval); 3882*7c478bd9Sstevel@tonic-gate /* 3883*7c478bd9Sstevel@tonic-gate * check we really have a shadow for this handle 3884*7c478bd9Sstevel@tonic-gate */ 3885*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3886*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3887*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3888*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3889*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle) 3890*7c478bd9Sstevel@tonic-gate break; 3891*7c478bd9Sstevel@tonic-gate if (hp != hhashp) { 3892*7c478bd9Sstevel@tonic-gate /* 3893*7c478bd9Sstevel@tonic-gate * yes - make sure DMP_NOSYNC is unset 3894*7c478bd9Sstevel@tonic-gate */ 3895*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)handle; 3896*7c478bd9Sstevel@tonic-gate mp->dmai_rflags &= ~DMP_NOSYNC; 3897*7c478bd9Sstevel@tonic-gate } 3898*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3899*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3900*7c478bd9Sstevel@tonic-gate return (retval); 3901*7c478bd9Sstevel@tonic-gate } 3902*7c478bd9Sstevel@tonic-gate 3903*7c478bd9Sstevel@tonic-gate 3904*7c478bd9Sstevel@tonic-gate /* 3905*7c478bd9Sstevel@tonic-gate * our dma_ctl routine 3906*7c478bd9Sstevel@tonic-gate */ 3907*7c478bd9Sstevel@tonic-gate static int 3908*7c478bd9Sstevel@tonic-gate bofi_dma_ctl(dev_info_t *dip, dev_info_t *rdip, 3909*7c478bd9Sstevel@tonic-gate ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 3910*7c478bd9Sstevel@tonic-gate off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags) 3911*7c478bd9Sstevel@tonic-gate { 3912*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *next_lp; 3913*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 3914*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 3915*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 3916*7c478bd9Sstevel@tonic-gate int retval; 3917*7c478bd9Sstevel@tonic-gate int i; 3918*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dummyhp; 3919*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 3920*7c478bd9Sstevel@tonic-gate 3921*7c478bd9Sstevel@tonic-gate /* 3922*7c478bd9Sstevel@tonic-gate * get nexus to do real work 3923*7c478bd9Sstevel@tonic-gate */ 3924*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_dma_ctl(dip, rdip, handle, request, offp, 3925*7c478bd9Sstevel@tonic-gate lenp, objp, flags); 3926*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) 3927*7c478bd9Sstevel@tonic-gate return (retval); 3928*7c478bd9Sstevel@tonic-gate /* 3929*7c478bd9Sstevel@tonic-gate * if driver_list is set, only intercept those drivers 3930*7c478bd9Sstevel@tonic-gate */ 3931*7c478bd9Sstevel@tonic-gate if (!driver_under_test(rdip)) 3932*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3933*7c478bd9Sstevel@tonic-gate 3934*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 3935*7c478bd9Sstevel@tonic-gate /* 3936*7c478bd9Sstevel@tonic-gate * check if this is a dvma_reserve - that one's like a 3937*7c478bd9Sstevel@tonic-gate * dma_allochdl and needs to be handled separately 3938*7c478bd9Sstevel@tonic-gate */ 3939*7c478bd9Sstevel@tonic-gate if (request == DDI_DMA_RESERVE) { 3940*7c478bd9Sstevel@tonic-gate bofi_dvma_reserve(rdip, *(ddi_dma_handle_t *)objp); 3941*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3942*7c478bd9Sstevel@tonic-gate } 3943*7c478bd9Sstevel@tonic-gate #endif 3944*7c478bd9Sstevel@tonic-gate /* 3945*7c478bd9Sstevel@tonic-gate * check we really have a shadow for this handle 3946*7c478bd9Sstevel@tonic-gate */ 3947*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3948*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3949*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 3950*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 3951*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == handle) 3952*7c478bd9Sstevel@tonic-gate break; 3953*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 3954*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3955*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3956*7c478bd9Sstevel@tonic-gate return (retval); 3957*7c478bd9Sstevel@tonic-gate } 3958*7c478bd9Sstevel@tonic-gate /* 3959*7c478bd9Sstevel@tonic-gate * yes we have - see what kind of command this is 3960*7c478bd9Sstevel@tonic-gate */ 3961*7c478bd9Sstevel@tonic-gate switch (request) { 3962*7c478bd9Sstevel@tonic-gate case DDI_DMA_RELEASE: 3963*7c478bd9Sstevel@tonic-gate /* 3964*7c478bd9Sstevel@tonic-gate * dvma release - release dummy handle and all the index handles 3965*7c478bd9Sstevel@tonic-gate */ 3966*7c478bd9Sstevel@tonic-gate dummyhp = hp; 3967*7c478bd9Sstevel@tonic-gate dummyhp->hnext->hprev = dummyhp->hprev; 3968*7c478bd9Sstevel@tonic-gate dummyhp->hprev->hnext = dummyhp->hnext; 3969*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3970*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3971*7c478bd9Sstevel@tonic-gate for (i = 0; i < dummyhp->len; i++) { 3972*7c478bd9Sstevel@tonic-gate hp = dummyhp->hparrayp[i]; 3973*7c478bd9Sstevel@tonic-gate /* 3974*7c478bd9Sstevel@tonic-gate * chek none of the index handles were still loaded 3975*7c478bd9Sstevel@tonic-gate */ 3976*7c478bd9Sstevel@tonic-gate if (hp->type != BOFI_NULL) 3977*7c478bd9Sstevel@tonic-gate panic("driver releasing loaded dvma"); 3978*7c478bd9Sstevel@tonic-gate /* 3979*7c478bd9Sstevel@tonic-gate * remove from dhash and inuse lists 3980*7c478bd9Sstevel@tonic-gate */ 3981*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 3982*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 3983*7c478bd9Sstevel@tonic-gate hp->dnext->dprev = hp->dprev; 3984*7c478bd9Sstevel@tonic-gate hp->dprev->dnext = hp->dnext; 3985*7c478bd9Sstevel@tonic-gate hp->next->prev = hp->prev; 3986*7c478bd9Sstevel@tonic-gate hp->prev->next = hp->next; 3987*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 3988*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 3989*7c478bd9Sstevel@tonic-gate 3990*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) 3991*7c478bd9Sstevel@tonic-gate ddi_umem_free(hp->umem_cookie); 3992*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 3993*7c478bd9Sstevel@tonic-gate } 3994*7c478bd9Sstevel@tonic-gate kmem_free(dummyhp->hparrayp, dummyhp->len * 3995*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_shadow *)); 3996*7c478bd9Sstevel@tonic-gate kmem_free(dummyhp, sizeof (struct bofi_shadow)); 3997*7c478bd9Sstevel@tonic-gate return (retval); 3998*7c478bd9Sstevel@tonic-gate case DDI_DMA_FREE: 3999*7c478bd9Sstevel@tonic-gate /* 4000*7c478bd9Sstevel@tonic-gate * ddi_dma_free case - remove from dhash, hhash and inuse lists 4001*7c478bd9Sstevel@tonic-gate */ 4002*7c478bd9Sstevel@tonic-gate hp->hnext->hprev = hp->hprev; 4003*7c478bd9Sstevel@tonic-gate hp->hprev->hnext = hp->hnext; 4004*7c478bd9Sstevel@tonic-gate hp->dnext->dprev = hp->dprev; 4005*7c478bd9Sstevel@tonic-gate hp->dprev->dnext = hp->dnext; 4006*7c478bd9Sstevel@tonic-gate hp->next->prev = hp->prev; 4007*7c478bd9Sstevel@tonic-gate hp->prev->next = hp->next; 4008*7c478bd9Sstevel@tonic-gate /* 4009*7c478bd9Sstevel@tonic-gate * free any errdef link structures tagged on to this 4010*7c478bd9Sstevel@tonic-gate * shadow handle 4011*7c478bd9Sstevel@tonic-gate */ 4012*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 4013*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 4014*7c478bd9Sstevel@tonic-gate /* 4015*7c478bd9Sstevel@tonic-gate * there is an implicit sync_for_cpu on free - 4016*7c478bd9Sstevel@tonic-gate * may need to corrupt 4017*7c478bd9Sstevel@tonic-gate */ 4018*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 4019*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_DMA_R) && 4020*7c478bd9Sstevel@tonic-gate (hp->flags & DDI_DMA_READ) && 4021*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 4022*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, DDI_DMA_SYNC_FORCPU, 4023*7c478bd9Sstevel@tonic-gate 0, hp->len); 4024*7c478bd9Sstevel@tonic-gate } 4025*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 4026*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 4027*7c478bd9Sstevel@tonic-gate lp = next_lp; 4028*7c478bd9Sstevel@tonic-gate } 4029*7c478bd9Sstevel@tonic-gate hp->link = NULL; 4030*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4031*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4032*7c478bd9Sstevel@tonic-gate 4033*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && (hp->flags & DDI_DMA_READ)) 4034*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 4035*7c478bd9Sstevel@tonic-gate xbcopy(hp->addr, hp->origaddr, hp->len); 4036*7c478bd9Sstevel@tonic-gate ddi_dmareq_mapout(hp->mapaddr, hp->len); 4037*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) 4038*7c478bd9Sstevel@tonic-gate ddi_umem_free(hp->umem_cookie); 4039*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 4040*7c478bd9Sstevel@tonic-gate return (retval); 4041*7c478bd9Sstevel@tonic-gate case DDI_DMA_MOVWIN: 4042*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)handle; 4043*7c478bd9Sstevel@tonic-gate mp->dmai_rflags &= ~DMP_NOSYNC; 4044*7c478bd9Sstevel@tonic-gate break; 4045*7c478bd9Sstevel@tonic-gate case DDI_DMA_NEXTWIN: 4046*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)handle; 4047*7c478bd9Sstevel@tonic-gate mp->dmai_rflags &= ~DMP_NOSYNC; 4048*7c478bd9Sstevel@tonic-gate break; 4049*7c478bd9Sstevel@tonic-gate default: 4050*7c478bd9Sstevel@tonic-gate break; 4051*7c478bd9Sstevel@tonic-gate } 4052*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4053*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4054*7c478bd9Sstevel@tonic-gate return (retval); 4055*7c478bd9Sstevel@tonic-gate } 4056*7c478bd9Sstevel@tonic-gate 4057*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 4058*7c478bd9Sstevel@tonic-gate /* 4059*7c478bd9Sstevel@tonic-gate * dvma reserve case from bofi_dma_ctl() 4060*7c478bd9Sstevel@tonic-gate */ 4061*7c478bd9Sstevel@tonic-gate static void 4062*7c478bd9Sstevel@tonic-gate bofi_dvma_reserve(dev_info_t *rdip, ddi_dma_handle_t handle) 4063*7c478bd9Sstevel@tonic-gate { 4064*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4065*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dummyhp; 4066*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 4067*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4068*7c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp; 4069*7c478bd9Sstevel@tonic-gate struct fast_dvma *nexus_private; 4070*7c478bd9Sstevel@tonic-gate int i, count; 4071*7c478bd9Sstevel@tonic-gate 4072*7c478bd9Sstevel@tonic-gate mp = (ddi_dma_impl_t *)handle; 4073*7c478bd9Sstevel@tonic-gate count = mp->dmai_ndvmapages; 4074*7c478bd9Sstevel@tonic-gate /* 4075*7c478bd9Sstevel@tonic-gate * allocate dummy shadow handle structure 4076*7c478bd9Sstevel@tonic-gate */ 4077*7c478bd9Sstevel@tonic-gate dummyhp = kmem_zalloc(sizeof (*dummyhp), KM_SLEEP); 4078*7c478bd9Sstevel@tonic-gate if (mp->dmai_rflags & DMP_BYPASSNEXUS) { 4079*7c478bd9Sstevel@tonic-gate /* 4080*7c478bd9Sstevel@tonic-gate * overlay our routines over the nexus's dvma routines 4081*7c478bd9Sstevel@tonic-gate */ 4082*7c478bd9Sstevel@tonic-gate nexus_private = (struct fast_dvma *)mp->dmai_nexus_private; 4083*7c478bd9Sstevel@tonic-gate dummyhp->save.dvma_ops = *(nexus_private->ops); 4084*7c478bd9Sstevel@tonic-gate nexus_private->ops = &bofi_dvma_ops; 4085*7c478bd9Sstevel@tonic-gate } 4086*7c478bd9Sstevel@tonic-gate /* 4087*7c478bd9Sstevel@tonic-gate * now fill in the dummy handle. This just gets put on hhash queue 4088*7c478bd9Sstevel@tonic-gate * so our dvma routines can find and index off to the handle they 4089*7c478bd9Sstevel@tonic-gate * really want. 4090*7c478bd9Sstevel@tonic-gate */ 4091*7c478bd9Sstevel@tonic-gate (void) strncpy(dummyhp->name, ddi_get_name(rdip), NAMESIZE); 4092*7c478bd9Sstevel@tonic-gate dummyhp->instance = ddi_get_instance(rdip); 4093*7c478bd9Sstevel@tonic-gate dummyhp->rnumber = -1; 4094*7c478bd9Sstevel@tonic-gate dummyhp->dip = rdip; 4095*7c478bd9Sstevel@tonic-gate dummyhp->len = count; 4096*7c478bd9Sstevel@tonic-gate dummyhp->hdl.dma_handle = handle; 4097*7c478bd9Sstevel@tonic-gate dummyhp->link = NULL; 4098*7c478bd9Sstevel@tonic-gate dummyhp->type = BOFI_NULL; 4099*7c478bd9Sstevel@tonic-gate /* 4100*7c478bd9Sstevel@tonic-gate * allocate space for real handles 4101*7c478bd9Sstevel@tonic-gate */ 4102*7c478bd9Sstevel@tonic-gate dummyhp->hparrayp = kmem_alloc(count * 4103*7c478bd9Sstevel@tonic-gate sizeof (struct bofi_shadow *), KM_SLEEP); 4104*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 4105*7c478bd9Sstevel@tonic-gate /* 4106*7c478bd9Sstevel@tonic-gate * allocate shadow handle structures and fill them in 4107*7c478bd9Sstevel@tonic-gate */ 4108*7c478bd9Sstevel@tonic-gate hp = kmem_zalloc(sizeof (*hp), KM_SLEEP); 4109*7c478bd9Sstevel@tonic-gate (void) strncpy(hp->name, ddi_get_name(rdip), NAMESIZE); 4110*7c478bd9Sstevel@tonic-gate hp->instance = ddi_get_instance(rdip); 4111*7c478bd9Sstevel@tonic-gate hp->rnumber = -1; 4112*7c478bd9Sstevel@tonic-gate hp->dip = rdip; 4113*7c478bd9Sstevel@tonic-gate hp->hdl.dma_handle = 0; 4114*7c478bd9Sstevel@tonic-gate hp->link = NULL; 4115*7c478bd9Sstevel@tonic-gate hp->type = BOFI_NULL; 4116*7c478bd9Sstevel@tonic-gate if (bofi_sync_check) { 4117*7c478bd9Sstevel@tonic-gate unsigned long pagemask = ddi_ptob(rdip, 1) - 1; 4118*7c478bd9Sstevel@tonic-gate /* 4119*7c478bd9Sstevel@tonic-gate * Take a copy and set this to be hp->addr 4120*7c478bd9Sstevel@tonic-gate * Data will be copied to and from the original on 4121*7c478bd9Sstevel@tonic-gate * explicit and implicit ddi_dma_sync() 4122*7c478bd9Sstevel@tonic-gate * 4123*7c478bd9Sstevel@tonic-gate * - maintain page alignment because some devices 4124*7c478bd9Sstevel@tonic-gate * assume it. 4125*7c478bd9Sstevel@tonic-gate */ 4126*7c478bd9Sstevel@tonic-gate hp->allocaddr = ddi_umem_alloc( 4127*7c478bd9Sstevel@tonic-gate ((int)hp->addr & pagemask) + pagemask + 1, 4128*7c478bd9Sstevel@tonic-gate KM_SLEEP, &hp->umem_cookie); 4129*7c478bd9Sstevel@tonic-gate hp->addr = hp->allocaddr + ((int)hp->addr & pagemask); 4130*7c478bd9Sstevel@tonic-gate } 4131*7c478bd9Sstevel@tonic-gate /* 4132*7c478bd9Sstevel@tonic-gate * add to dhash and inuse lists. 4133*7c478bd9Sstevel@tonic-gate * these don't go on hhash queue. 4134*7c478bd9Sstevel@tonic-gate */ 4135*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4136*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4137*7c478bd9Sstevel@tonic-gate hp->next = shadow_list.next; 4138*7c478bd9Sstevel@tonic-gate shadow_list.next->prev = hp; 4139*7c478bd9Sstevel@tonic-gate hp->prev = &shadow_list; 4140*7c478bd9Sstevel@tonic-gate shadow_list.next = hp; 4141*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 4142*7c478bd9Sstevel@tonic-gate hp->dnext = dhashp->dnext; 4143*7c478bd9Sstevel@tonic-gate dhashp->dnext->dprev = hp; 4144*7c478bd9Sstevel@tonic-gate hp->dprev = dhashp; 4145*7c478bd9Sstevel@tonic-gate dhashp->dnext = hp; 4146*7c478bd9Sstevel@tonic-gate dummyhp->hparrayp[i] = hp; 4147*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4148*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4149*7c478bd9Sstevel@tonic-gate } 4150*7c478bd9Sstevel@tonic-gate /* 4151*7c478bd9Sstevel@tonic-gate * add dummy handle to hhash list only 4152*7c478bd9Sstevel@tonic-gate */ 4153*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4154*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4155*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 4156*7c478bd9Sstevel@tonic-gate dummyhp->hnext = hhashp->hnext; 4157*7c478bd9Sstevel@tonic-gate hhashp->hnext->hprev = dummyhp; 4158*7c478bd9Sstevel@tonic-gate dummyhp->hprev = hhashp; 4159*7c478bd9Sstevel@tonic-gate hhashp->hnext = dummyhp; 4160*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4161*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4162*7c478bd9Sstevel@tonic-gate } 4163*7c478bd9Sstevel@tonic-gate 4164*7c478bd9Sstevel@tonic-gate /* 4165*7c478bd9Sstevel@tonic-gate * our dvma_kaddr_load() 4166*7c478bd9Sstevel@tonic-gate */ 4167*7c478bd9Sstevel@tonic-gate static void 4168*7c478bd9Sstevel@tonic-gate bofi_dvma_kaddr_load(ddi_dma_handle_t h, caddr_t a, uint_t len, uint_t index, 4169*7c478bd9Sstevel@tonic-gate ddi_dma_cookie_t *cp) 4170*7c478bd9Sstevel@tonic-gate { 4171*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dummyhp; 4172*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4173*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4174*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4175*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4176*7c478bd9Sstevel@tonic-gate 4177*7c478bd9Sstevel@tonic-gate /* 4178*7c478bd9Sstevel@tonic-gate * check we really have a dummy shadow for this handle 4179*7c478bd9Sstevel@tonic-gate */ 4180*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4181*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4182*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(h); 4183*7c478bd9Sstevel@tonic-gate for (dummyhp = hhashp->hnext; dummyhp != hhashp; 4184*7c478bd9Sstevel@tonic-gate dummyhp = dummyhp->hnext) 4185*7c478bd9Sstevel@tonic-gate if (dummyhp->hdl.dma_handle == h) 4186*7c478bd9Sstevel@tonic-gate break; 4187*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4188*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4189*7c478bd9Sstevel@tonic-gate if (dummyhp == hhashp) { 4190*7c478bd9Sstevel@tonic-gate /* 4191*7c478bd9Sstevel@tonic-gate * no dummy shadow - panic 4192*7c478bd9Sstevel@tonic-gate */ 4193*7c478bd9Sstevel@tonic-gate panic("driver dvma_kaddr_load with no reserve"); 4194*7c478bd9Sstevel@tonic-gate } 4195*7c478bd9Sstevel@tonic-gate 4196*7c478bd9Sstevel@tonic-gate /* 4197*7c478bd9Sstevel@tonic-gate * find real hp 4198*7c478bd9Sstevel@tonic-gate */ 4199*7c478bd9Sstevel@tonic-gate hp = dummyhp->hparrayp[index]; 4200*7c478bd9Sstevel@tonic-gate /* 4201*7c478bd9Sstevel@tonic-gate * check its not already loaded 4202*7c478bd9Sstevel@tonic-gate */ 4203*7c478bd9Sstevel@tonic-gate if (hp->type != BOFI_NULL) 4204*7c478bd9Sstevel@tonic-gate panic("driver loading loaded dvma"); 4205*7c478bd9Sstevel@tonic-gate /* 4206*7c478bd9Sstevel@tonic-gate * if were doing copying, just need to change origaddr and get 4207*7c478bd9Sstevel@tonic-gate * nexus to map hp->addr again 4208*7c478bd9Sstevel@tonic-gate * if not, set hp->addr to new address. 4209*7c478bd9Sstevel@tonic-gate * - note these are always kernel virtual addresses - no need to map 4210*7c478bd9Sstevel@tonic-gate */ 4211*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && hp->allocaddr) { 4212*7c478bd9Sstevel@tonic-gate hp->origaddr = a; 4213*7c478bd9Sstevel@tonic-gate a = hp->addr; 4214*7c478bd9Sstevel@tonic-gate } else 4215*7c478bd9Sstevel@tonic-gate hp->addr = a; 4216*7c478bd9Sstevel@tonic-gate hp->len = len; 4217*7c478bd9Sstevel@tonic-gate /* 4218*7c478bd9Sstevel@tonic-gate * get nexus to do the real work 4219*7c478bd9Sstevel@tonic-gate */ 4220*7c478bd9Sstevel@tonic-gate dummyhp->save.dvma_ops.dvma_kaddr_load(h, a, len, index, cp); 4221*7c478bd9Sstevel@tonic-gate /* 4222*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this dma_handle 4223*7c478bd9Sstevel@tonic-gate * no need to corrupt - there's no implicit dma_sync on this one 4224*7c478bd9Sstevel@tonic-gate */ 4225*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4226*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4227*7c478bd9Sstevel@tonic-gate hp->type = BOFI_DMA_HDL; 4228*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) { 4229*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(hp->name) == 4230*7c478bd9Sstevel@tonic-gate ddi_name_to_major(ep->name) && 4231*7c478bd9Sstevel@tonic-gate hp->instance == ep->errdef.instance && 4232*7c478bd9Sstevel@tonic-gate (ep->errdef.rnumber == -1 || 4233*7c478bd9Sstevel@tonic-gate hp->rnumber == ep->errdef.rnumber) && 4234*7c478bd9Sstevel@tonic-gate ((ep->errdef.access_type & BOFI_DMA_RW) && 4235*7c478bd9Sstevel@tonic-gate (((uintptr_t)(hp->addr + ep->errdef.offset + 4236*7c478bd9Sstevel@tonic-gate ep->errdef.len) & ~LLSZMASK) > 4237*7c478bd9Sstevel@tonic-gate ((uintptr_t)((hp->addr + ep->errdef.offset) + 4238*7c478bd9Sstevel@tonic-gate LLSZMASK) & ~LLSZMASK)))) { 4239*7c478bd9Sstevel@tonic-gate lp = bofi_link_freelist; 4240*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 4241*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp->link; 4242*7c478bd9Sstevel@tonic-gate lp->errentp = ep; 4243*7c478bd9Sstevel@tonic-gate lp->link = hp->link; 4244*7c478bd9Sstevel@tonic-gate hp->link = lp; 4245*7c478bd9Sstevel@tonic-gate } 4246*7c478bd9Sstevel@tonic-gate } 4247*7c478bd9Sstevel@tonic-gate } 4248*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4249*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4250*7c478bd9Sstevel@tonic-gate } 4251*7c478bd9Sstevel@tonic-gate 4252*7c478bd9Sstevel@tonic-gate /* 4253*7c478bd9Sstevel@tonic-gate * our dvma_unload() 4254*7c478bd9Sstevel@tonic-gate */ 4255*7c478bd9Sstevel@tonic-gate static void 4256*7c478bd9Sstevel@tonic-gate bofi_dvma_unload(ddi_dma_handle_t h, uint_t index, uint_t view) 4257*7c478bd9Sstevel@tonic-gate { 4258*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *next_lp; 4259*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4260*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dummyhp; 4261*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4262*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4263*7c478bd9Sstevel@tonic-gate 4264*7c478bd9Sstevel@tonic-gate /* 4265*7c478bd9Sstevel@tonic-gate * check we really have a dummy shadow for this handle 4266*7c478bd9Sstevel@tonic-gate */ 4267*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4268*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4269*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(h); 4270*7c478bd9Sstevel@tonic-gate for (dummyhp = hhashp->hnext; dummyhp != hhashp; 4271*7c478bd9Sstevel@tonic-gate dummyhp = dummyhp->hnext) 4272*7c478bd9Sstevel@tonic-gate if (dummyhp->hdl.dma_handle == h) 4273*7c478bd9Sstevel@tonic-gate break; 4274*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4275*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4276*7c478bd9Sstevel@tonic-gate if (dummyhp == hhashp) { 4277*7c478bd9Sstevel@tonic-gate /* 4278*7c478bd9Sstevel@tonic-gate * no dummy shadow - panic 4279*7c478bd9Sstevel@tonic-gate */ 4280*7c478bd9Sstevel@tonic-gate panic("driver dvma_unload with no reserve"); 4281*7c478bd9Sstevel@tonic-gate } 4282*7c478bd9Sstevel@tonic-gate dummyhp->save.dvma_ops.dvma_unload(h, index, view); 4283*7c478bd9Sstevel@tonic-gate /* 4284*7c478bd9Sstevel@tonic-gate * find real hp 4285*7c478bd9Sstevel@tonic-gate */ 4286*7c478bd9Sstevel@tonic-gate hp = dummyhp->hparrayp[index]; 4287*7c478bd9Sstevel@tonic-gate /* 4288*7c478bd9Sstevel@tonic-gate * check its not already unloaded 4289*7c478bd9Sstevel@tonic-gate */ 4290*7c478bd9Sstevel@tonic-gate if (hp->type == BOFI_NULL) 4291*7c478bd9Sstevel@tonic-gate panic("driver unloading unloaded dvma"); 4292*7c478bd9Sstevel@tonic-gate /* 4293*7c478bd9Sstevel@tonic-gate * free any errdef link structures tagged on to this 4294*7c478bd9Sstevel@tonic-gate * shadow handle - do corruption if necessary 4295*7c478bd9Sstevel@tonic-gate */ 4296*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4297*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4298*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 4299*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 4300*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 4301*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_type & BOFI_DMA_R) && 4302*7c478bd9Sstevel@tonic-gate (view == DDI_DMA_SYNC_FORCPU || 4303*7c478bd9Sstevel@tonic-gate view == DDI_DMA_SYNC_FORKERNEL) && 4304*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 4305*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, view, 0, hp->len); 4306*7c478bd9Sstevel@tonic-gate } 4307*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 4308*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 4309*7c478bd9Sstevel@tonic-gate lp = next_lp; 4310*7c478bd9Sstevel@tonic-gate } 4311*7c478bd9Sstevel@tonic-gate hp->link = NULL; 4312*7c478bd9Sstevel@tonic-gate hp->type = BOFI_NULL; 4313*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4314*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4315*7c478bd9Sstevel@tonic-gate /* 4316*7c478bd9Sstevel@tonic-gate * if there is an explicit sync_for_cpu, then do copy to original 4317*7c478bd9Sstevel@tonic-gate */ 4318*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && 4319*7c478bd9Sstevel@tonic-gate (view == DDI_DMA_SYNC_FORCPU || view == DDI_DMA_SYNC_FORKERNEL)) 4320*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 4321*7c478bd9Sstevel@tonic-gate xbcopy(hp->addr, hp->origaddr, hp->len); 4322*7c478bd9Sstevel@tonic-gate } 4323*7c478bd9Sstevel@tonic-gate 4324*7c478bd9Sstevel@tonic-gate /* 4325*7c478bd9Sstevel@tonic-gate * our dvma_unload() 4326*7c478bd9Sstevel@tonic-gate */ 4327*7c478bd9Sstevel@tonic-gate static void 4328*7c478bd9Sstevel@tonic-gate bofi_dvma_sync(ddi_dma_handle_t h, uint_t index, uint_t view) 4329*7c478bd9Sstevel@tonic-gate { 4330*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4331*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4332*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4333*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dummyhp; 4334*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4335*7c478bd9Sstevel@tonic-gate 4336*7c478bd9Sstevel@tonic-gate /* 4337*7c478bd9Sstevel@tonic-gate * check we really have a dummy shadow for this handle 4338*7c478bd9Sstevel@tonic-gate */ 4339*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4340*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4341*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(h); 4342*7c478bd9Sstevel@tonic-gate for (dummyhp = hhashp->hnext; dummyhp != hhashp; 4343*7c478bd9Sstevel@tonic-gate dummyhp = dummyhp->hnext) 4344*7c478bd9Sstevel@tonic-gate if (dummyhp->hdl.dma_handle == h) 4345*7c478bd9Sstevel@tonic-gate break; 4346*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4347*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4348*7c478bd9Sstevel@tonic-gate if (dummyhp == hhashp) { 4349*7c478bd9Sstevel@tonic-gate /* 4350*7c478bd9Sstevel@tonic-gate * no dummy shadow - panic 4351*7c478bd9Sstevel@tonic-gate */ 4352*7c478bd9Sstevel@tonic-gate panic("driver dvma_sync with no reserve"); 4353*7c478bd9Sstevel@tonic-gate } 4354*7c478bd9Sstevel@tonic-gate /* 4355*7c478bd9Sstevel@tonic-gate * find real hp 4356*7c478bd9Sstevel@tonic-gate */ 4357*7c478bd9Sstevel@tonic-gate hp = dummyhp->hparrayp[index]; 4358*7c478bd9Sstevel@tonic-gate /* 4359*7c478bd9Sstevel@tonic-gate * check its already loaded 4360*7c478bd9Sstevel@tonic-gate */ 4361*7c478bd9Sstevel@tonic-gate if (hp->type == BOFI_NULL) 4362*7c478bd9Sstevel@tonic-gate panic("driver syncing unloaded dvma"); 4363*7c478bd9Sstevel@tonic-gate if (view == DDI_DMA_SYNC_FORCPU || view == DDI_DMA_SYNC_FORKERNEL) 4364*7c478bd9Sstevel@tonic-gate /* 4365*7c478bd9Sstevel@tonic-gate * in this case do sync first 4366*7c478bd9Sstevel@tonic-gate */ 4367*7c478bd9Sstevel@tonic-gate dummyhp->save.dvma_ops.dvma_sync(h, index, view); 4368*7c478bd9Sstevel@tonic-gate /* 4369*7c478bd9Sstevel@tonic-gate * if there is an explicit sync_for_dev, then do copy from original 4370*7c478bd9Sstevel@tonic-gate */ 4371*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && view == DDI_DMA_SYNC_FORDEV) { 4372*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 4373*7c478bd9Sstevel@tonic-gate xbcopy(hp->origaddr, hp->addr, hp->len); 4374*7c478bd9Sstevel@tonic-gate } 4375*7c478bd9Sstevel@tonic-gate /* 4376*7c478bd9Sstevel@tonic-gate * do corruption if necessary 4377*7c478bd9Sstevel@tonic-gate */ 4378*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4379*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4380*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 4381*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 4382*7c478bd9Sstevel@tonic-gate if ((((ep->errdef.access_type & BOFI_DMA_R) && 4383*7c478bd9Sstevel@tonic-gate (view == DDI_DMA_SYNC_FORCPU || 4384*7c478bd9Sstevel@tonic-gate view == DDI_DMA_SYNC_FORKERNEL)) || 4385*7c478bd9Sstevel@tonic-gate ((ep->errdef.access_type & BOFI_DMA_W) && 4386*7c478bd9Sstevel@tonic-gate (view == DDI_DMA_SYNC_FORDEV))) && 4387*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 4388*7c478bd9Sstevel@tonic-gate do_dma_corrupt(hp, ep, view, 0, hp->len); 4389*7c478bd9Sstevel@tonic-gate } 4390*7c478bd9Sstevel@tonic-gate } 4391*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4392*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4393*7c478bd9Sstevel@tonic-gate /* 4394*7c478bd9Sstevel@tonic-gate * if there is an explicit sync_for_cpu, then do copy to original 4395*7c478bd9Sstevel@tonic-gate */ 4396*7c478bd9Sstevel@tonic-gate if (bofi_sync_check && 4397*7c478bd9Sstevel@tonic-gate (view == DDI_DMA_SYNC_FORCPU || view == DDI_DMA_SYNC_FORKERNEL)) { 4398*7c478bd9Sstevel@tonic-gate if (hp->allocaddr) 4399*7c478bd9Sstevel@tonic-gate xbcopy(hp->addr, hp->origaddr, hp->len); 4400*7c478bd9Sstevel@tonic-gate } 4401*7c478bd9Sstevel@tonic-gate if (view == DDI_DMA_SYNC_FORDEV) 4402*7c478bd9Sstevel@tonic-gate /* 4403*7c478bd9Sstevel@tonic-gate * in this case do sync last 4404*7c478bd9Sstevel@tonic-gate */ 4405*7c478bd9Sstevel@tonic-gate dummyhp->save.dvma_ops.dvma_sync(h, index, view); 4406*7c478bd9Sstevel@tonic-gate } 4407*7c478bd9Sstevel@tonic-gate #endif 4408*7c478bd9Sstevel@tonic-gate 4409*7c478bd9Sstevel@tonic-gate /* 4410*7c478bd9Sstevel@tonic-gate * bofi intercept routine - gets called instead of users interrupt routine 4411*7c478bd9Sstevel@tonic-gate */ 4412*7c478bd9Sstevel@tonic-gate static uint_t 4413*7c478bd9Sstevel@tonic-gate bofi_intercept_intr(caddr_t xp) 4414*7c478bd9Sstevel@tonic-gate { 4415*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4416*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4417*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4418*7c478bd9Sstevel@tonic-gate int intr_count = 1; 4419*7c478bd9Sstevel@tonic-gate int i; 4420*7c478bd9Sstevel@tonic-gate uint_t retval = DDI_INTR_UNCLAIMED; 4421*7c478bd9Sstevel@tonic-gate uint_t result; 4422*7c478bd9Sstevel@tonic-gate int unclaimed_counter = 0; 4423*7c478bd9Sstevel@tonic-gate int jabber_detected = 0; 4424*7c478bd9Sstevel@tonic-gate 4425*7c478bd9Sstevel@tonic-gate hp = (struct bofi_shadow *)xp; 4426*7c478bd9Sstevel@tonic-gate /* 4427*7c478bd9Sstevel@tonic-gate * check if nothing to do 4428*7c478bd9Sstevel@tonic-gate */ 4429*7c478bd9Sstevel@tonic-gate if (hp->link == NULL) 4430*7c478bd9Sstevel@tonic-gate return (hp->save.intr.int_handler 4431*7c478bd9Sstevel@tonic-gate (hp->save.intr.int_handler_arg1, NULL)); 4432*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4433*7c478bd9Sstevel@tonic-gate /* 4434*7c478bd9Sstevel@tonic-gate * look for any errdefs 4435*7c478bd9Sstevel@tonic-gate */ 4436*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 4437*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 4438*7c478bd9Sstevel@tonic-gate if (ep->state & BOFI_DEV_ACTIVE) { 4439*7c478bd9Sstevel@tonic-gate /* 4440*7c478bd9Sstevel@tonic-gate * got one 4441*7c478bd9Sstevel@tonic-gate */ 4442*7c478bd9Sstevel@tonic-gate if ((ep->errdef.access_count || 4443*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count) && 4444*7c478bd9Sstevel@tonic-gate (ep->errdef.access_type & BOFI_LOG)) 4445*7c478bd9Sstevel@tonic-gate log_acc_event(ep, BOFI_INTR, 0, 0, 1, 0); 4446*7c478bd9Sstevel@tonic-gate if (ep->errdef.access_count > 1) { 4447*7c478bd9Sstevel@tonic-gate ep->errdef.access_count--; 4448*7c478bd9Sstevel@tonic-gate } else if (ep->errdef.fail_count > 0) { 4449*7c478bd9Sstevel@tonic-gate ep->errdef.fail_count--; 4450*7c478bd9Sstevel@tonic-gate ep->errdef.access_count = 0; 4451*7c478bd9Sstevel@tonic-gate /* 4452*7c478bd9Sstevel@tonic-gate * OK do "corruption" 4453*7c478bd9Sstevel@tonic-gate */ 4454*7c478bd9Sstevel@tonic-gate if (ep->errstate.fail_time == 0) 4455*7c478bd9Sstevel@tonic-gate ep->errstate.fail_time = bofi_gettime(); 4456*7c478bd9Sstevel@tonic-gate switch (ep->errdef.optype) { 4457*7c478bd9Sstevel@tonic-gate case BOFI_DELAY_INTR: 4458*7c478bd9Sstevel@tonic-gate if (!hp->hilevel) { 4459*7c478bd9Sstevel@tonic-gate drv_usecwait 4460*7c478bd9Sstevel@tonic-gate (ep->errdef.operand); 4461*7c478bd9Sstevel@tonic-gate } 4462*7c478bd9Sstevel@tonic-gate break; 4463*7c478bd9Sstevel@tonic-gate case BOFI_LOSE_INTR: 4464*7c478bd9Sstevel@tonic-gate intr_count = 0; 4465*7c478bd9Sstevel@tonic-gate break; 4466*7c478bd9Sstevel@tonic-gate case BOFI_EXTRA_INTR: 4467*7c478bd9Sstevel@tonic-gate intr_count += ep->errdef.operand; 4468*7c478bd9Sstevel@tonic-gate break; 4469*7c478bd9Sstevel@tonic-gate default: 4470*7c478bd9Sstevel@tonic-gate break; 4471*7c478bd9Sstevel@tonic-gate } 4472*7c478bd9Sstevel@tonic-gate } 4473*7c478bd9Sstevel@tonic-gate } 4474*7c478bd9Sstevel@tonic-gate } 4475*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4476*7c478bd9Sstevel@tonic-gate /* 4477*7c478bd9Sstevel@tonic-gate * send extra or fewer interrupts as requested 4478*7c478bd9Sstevel@tonic-gate */ 4479*7c478bd9Sstevel@tonic-gate for (i = 0; i < intr_count; i++) { 4480*7c478bd9Sstevel@tonic-gate result = hp->save.intr.int_handler 4481*7c478bd9Sstevel@tonic-gate (hp->save.intr.int_handler_arg1, NULL); 4482*7c478bd9Sstevel@tonic-gate if (result == DDI_INTR_CLAIMED) 4483*7c478bd9Sstevel@tonic-gate unclaimed_counter >>= 1; 4484*7c478bd9Sstevel@tonic-gate else if (++unclaimed_counter >= 20) 4485*7c478bd9Sstevel@tonic-gate jabber_detected = 1; 4486*7c478bd9Sstevel@tonic-gate if (i == 0) 4487*7c478bd9Sstevel@tonic-gate retval = result; 4488*7c478bd9Sstevel@tonic-gate } 4489*7c478bd9Sstevel@tonic-gate /* 4490*7c478bd9Sstevel@tonic-gate * if more than 1000 spurious interrupts requested and 4491*7c478bd9Sstevel@tonic-gate * jabber not detected - give warning 4492*7c478bd9Sstevel@tonic-gate */ 4493*7c478bd9Sstevel@tonic-gate if (intr_count > 1000 && !jabber_detected) 4494*7c478bd9Sstevel@tonic-gate panic("undetected interrupt jabber: %s%d", 4495*7c478bd9Sstevel@tonic-gate hp->name, hp->instance); 4496*7c478bd9Sstevel@tonic-gate /* 4497*7c478bd9Sstevel@tonic-gate * return first response - or "unclaimed" if none 4498*7c478bd9Sstevel@tonic-gate */ 4499*7c478bd9Sstevel@tonic-gate return (retval); 4500*7c478bd9Sstevel@tonic-gate } 4501*7c478bd9Sstevel@tonic-gate 4502*7c478bd9Sstevel@tonic-gate 4503*7c478bd9Sstevel@tonic-gate /* 4504*7c478bd9Sstevel@tonic-gate * our ddi_check_acc_hdl 4505*7c478bd9Sstevel@tonic-gate */ 4506*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4507*7c478bd9Sstevel@tonic-gate static int 4508*7c478bd9Sstevel@tonic-gate bofi_check_acc_hdl(ddi_acc_impl_t *handle) 4509*7c478bd9Sstevel@tonic-gate { 4510*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4511*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4512*7c478bd9Sstevel@tonic-gate uint_t result = 0; 4513*7c478bd9Sstevel@tonic-gate 4514*7c478bd9Sstevel@tonic-gate hp = handle->ahi_common.ah_bus_private; 4515*7c478bd9Sstevel@tonic-gate if (!hp->link || !mutex_tryenter(&bofi_mutex)) { 4516*7c478bd9Sstevel@tonic-gate return (0); 4517*7c478bd9Sstevel@tonic-gate } 4518*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 4519*7c478bd9Sstevel@tonic-gate /* 4520*7c478bd9Sstevel@tonic-gate * OR in error state from all associated 4521*7c478bd9Sstevel@tonic-gate * errdef structures 4522*7c478bd9Sstevel@tonic-gate */ 4523*7c478bd9Sstevel@tonic-gate if (lp->errentp->errdef.access_count == 0 && 4524*7c478bd9Sstevel@tonic-gate (lp->errentp->state & BOFI_DEV_ACTIVE)) { 4525*7c478bd9Sstevel@tonic-gate result = (lp->errentp->errdef.acc_chk & 1); 4526*7c478bd9Sstevel@tonic-gate } 4527*7c478bd9Sstevel@tonic-gate } 4528*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4529*7c478bd9Sstevel@tonic-gate return (result); 4530*7c478bd9Sstevel@tonic-gate } 4531*7c478bd9Sstevel@tonic-gate 4532*7c478bd9Sstevel@tonic-gate /* 4533*7c478bd9Sstevel@tonic-gate * our ddi_check_dma_hdl 4534*7c478bd9Sstevel@tonic-gate */ 4535*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4536*7c478bd9Sstevel@tonic-gate static int 4537*7c478bd9Sstevel@tonic-gate bofi_check_dma_hdl(ddi_dma_impl_t *handle) 4538*7c478bd9Sstevel@tonic-gate { 4539*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4540*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4541*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4542*7c478bd9Sstevel@tonic-gate uint_t result = 0; 4543*7c478bd9Sstevel@tonic-gate 4544*7c478bd9Sstevel@tonic-gate if (!mutex_tryenter(&bofi_mutex)) { 4545*7c478bd9Sstevel@tonic-gate return (0); 4546*7c478bd9Sstevel@tonic-gate } 4547*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(handle); 4548*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) 4549*7c478bd9Sstevel@tonic-gate if (hp->hdl.dma_handle == (ddi_dma_handle_t)handle) 4550*7c478bd9Sstevel@tonic-gate break; 4551*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 4552*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4553*7c478bd9Sstevel@tonic-gate return (0); 4554*7c478bd9Sstevel@tonic-gate } 4555*7c478bd9Sstevel@tonic-gate if (!hp->link) { 4556*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4557*7c478bd9Sstevel@tonic-gate return (0); 4558*7c478bd9Sstevel@tonic-gate } 4559*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 4560*7c478bd9Sstevel@tonic-gate /* 4561*7c478bd9Sstevel@tonic-gate * OR in error state from all associated 4562*7c478bd9Sstevel@tonic-gate * errdef structures 4563*7c478bd9Sstevel@tonic-gate */ 4564*7c478bd9Sstevel@tonic-gate if (lp->errentp->errdef.access_count == 0 && 4565*7c478bd9Sstevel@tonic-gate (lp->errentp->state & BOFI_DEV_ACTIVE)) { 4566*7c478bd9Sstevel@tonic-gate result = ((lp->errentp->errdef.acc_chk & 2) ? 1 : 0); 4567*7c478bd9Sstevel@tonic-gate } 4568*7c478bd9Sstevel@tonic-gate } 4569*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4570*7c478bd9Sstevel@tonic-gate return (result); 4571*7c478bd9Sstevel@tonic-gate } 4572*7c478bd9Sstevel@tonic-gate 4573*7c478bd9Sstevel@tonic-gate 4574*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4575*7c478bd9Sstevel@tonic-gate static int 4576*7c478bd9Sstevel@tonic-gate bofi_post_event(dev_info_t *dip, dev_info_t *rdip, 4577*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void *impl_data) 4578*7c478bd9Sstevel@tonic-gate { 4579*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t ec; 4580*7c478bd9Sstevel@tonic-gate struct ddi_fault_event_data *arg; 4581*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4582*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4583*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 4584*7c478bd9Sstevel@tonic-gate struct bofi_link *lp; 4585*7c478bd9Sstevel@tonic-gate 4586*7c478bd9Sstevel@tonic-gate ASSERT(eventhdl); 4587*7c478bd9Sstevel@tonic-gate if (ddi_get_eventcookie(dip, DDI_DEVI_FAULT_EVENT, &ec) != DDI_SUCCESS) 4588*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4589*7c478bd9Sstevel@tonic-gate 4590*7c478bd9Sstevel@tonic-gate if (ec != eventhdl) 4591*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_post_event(dip, rdip, eventhdl, 4592*7c478bd9Sstevel@tonic-gate impl_data)); 4593*7c478bd9Sstevel@tonic-gate 4594*7c478bd9Sstevel@tonic-gate arg = (struct ddi_fault_event_data *)impl_data; 4595*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4596*7c478bd9Sstevel@tonic-gate /* 4597*7c478bd9Sstevel@tonic-gate * find shadow handles with appropriate dev_infos 4598*7c478bd9Sstevel@tonic-gate * and set error reported on all associated errdef structures 4599*7c478bd9Sstevel@tonic-gate */ 4600*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(arg->f_dip); 4601*7c478bd9Sstevel@tonic-gate for (hp = dhashp->dnext; hp != dhashp; hp = hp->dnext) { 4602*7c478bd9Sstevel@tonic-gate if (hp->dip == arg->f_dip) { 4603*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; lp = lp->link) { 4604*7c478bd9Sstevel@tonic-gate ep = lp->errentp; 4605*7c478bd9Sstevel@tonic-gate ep->errstate.errmsg_count++; 4606*7c478bd9Sstevel@tonic-gate if ((ep->errstate.msg_time == NULL || 4607*7c478bd9Sstevel@tonic-gate ep->errstate.severity > arg->f_impact) && 4608*7c478bd9Sstevel@tonic-gate (ep->state & BOFI_DEV_ACTIVE)) { 4609*7c478bd9Sstevel@tonic-gate ep->errstate.msg_time = bofi_gettime(); 4610*7c478bd9Sstevel@tonic-gate ep->errstate.severity = arg->f_impact; 4611*7c478bd9Sstevel@tonic-gate (void) strncpy(ep->errstate.buffer, 4612*7c478bd9Sstevel@tonic-gate arg->f_message, ERRMSGSIZE); 4613*7c478bd9Sstevel@tonic-gate ddi_trigger_softintr(ep->softintr_id); 4614*7c478bd9Sstevel@tonic-gate } 4615*7c478bd9Sstevel@tonic-gate } 4616*7c478bd9Sstevel@tonic-gate } 4617*7c478bd9Sstevel@tonic-gate } 4618*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4619*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_post_event(dip, rdip, eventhdl, impl_data)); 4620*7c478bd9Sstevel@tonic-gate } 4621*7c478bd9Sstevel@tonic-gate 4622*7c478bd9Sstevel@tonic-gate /* 4623*7c478bd9Sstevel@tonic-gate * our intr_ops routine 4624*7c478bd9Sstevel@tonic-gate */ 4625*7c478bd9Sstevel@tonic-gate static int 4626*7c478bd9Sstevel@tonic-gate bofi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 4627*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 4628*7c478bd9Sstevel@tonic-gate { 4629*7c478bd9Sstevel@tonic-gate int retval; 4630*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hp; 4631*7c478bd9Sstevel@tonic-gate struct bofi_shadow *dhashp; 4632*7c478bd9Sstevel@tonic-gate struct bofi_shadow *hhashp; 4633*7c478bd9Sstevel@tonic-gate struct bofi_errent *ep; 4634*7c478bd9Sstevel@tonic-gate struct bofi_link *lp, *next_lp; 4635*7c478bd9Sstevel@tonic-gate 4636*7c478bd9Sstevel@tonic-gate switch (intr_op) { 4637*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ADDISR: 4638*7c478bd9Sstevel@tonic-gate /* 4639*7c478bd9Sstevel@tonic-gate * if driver_list is set, only intercept those drivers 4640*7c478bd9Sstevel@tonic-gate */ 4641*7c478bd9Sstevel@tonic-gate if (!driver_under_test(rdip)) 4642*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_intr_op(dip, rdip, 4643*7c478bd9Sstevel@tonic-gate intr_op, hdlp, result)); 4644*7c478bd9Sstevel@tonic-gate /* 4645*7c478bd9Sstevel@tonic-gate * allocate shadow handle structure and fill in 4646*7c478bd9Sstevel@tonic-gate */ 4647*7c478bd9Sstevel@tonic-gate hp = kmem_zalloc(sizeof (struct bofi_shadow), KM_SLEEP); 4648*7c478bd9Sstevel@tonic-gate (void) strncpy(hp->name, ddi_get_name(rdip), NAMESIZE); 4649*7c478bd9Sstevel@tonic-gate hp->instance = ddi_get_instance(rdip); 4650*7c478bd9Sstevel@tonic-gate hp->save.intr.int_handler = hdlp->ih_cb_func; 4651*7c478bd9Sstevel@tonic-gate hp->save.intr.int_handler_arg1 = hdlp->ih_cb_arg1; 4652*7c478bd9Sstevel@tonic-gate hdlp->ih_cb_func = (ddi_intr_handler_t *)bofi_intercept_intr; 4653*7c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg1 = (caddr_t)hp; 4654*7c478bd9Sstevel@tonic-gate hp->bofi_inum = hdlp->ih_inum; 4655*7c478bd9Sstevel@tonic-gate hp->dip = rdip; 4656*7c478bd9Sstevel@tonic-gate hp->link = NULL; 4657*7c478bd9Sstevel@tonic-gate hp->type = BOFI_INT_HDL; 4658*7c478bd9Sstevel@tonic-gate /* 4659*7c478bd9Sstevel@tonic-gate * save whether hilevel or not 4660*7c478bd9Sstevel@tonic-gate */ 4661*7c478bd9Sstevel@tonic-gate 4662*7c478bd9Sstevel@tonic-gate if (hdlp->ih_pri >= ddi_intr_get_hilevel_pri()) 4663*7c478bd9Sstevel@tonic-gate hp->hilevel = 1; 4664*7c478bd9Sstevel@tonic-gate else 4665*7c478bd9Sstevel@tonic-gate hp->hilevel = 0; 4666*7c478bd9Sstevel@tonic-gate 4667*7c478bd9Sstevel@tonic-gate /* 4668*7c478bd9Sstevel@tonic-gate * call nexus to do real work, but specifying our handler, and 4669*7c478bd9Sstevel@tonic-gate * our shadow handle as argument 4670*7c478bd9Sstevel@tonic-gate */ 4671*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_intr_op(dip, rdip, 4672*7c478bd9Sstevel@tonic-gate intr_op, hdlp, result); 4673*7c478bd9Sstevel@tonic-gate if (retval != DDI_SUCCESS) { 4674*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 4675*7c478bd9Sstevel@tonic-gate return (retval); 4676*7c478bd9Sstevel@tonic-gate } 4677*7c478bd9Sstevel@tonic-gate /* 4678*7c478bd9Sstevel@tonic-gate * add to dhash, hhash and inuse lists 4679*7c478bd9Sstevel@tonic-gate */ 4680*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4681*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4682*7c478bd9Sstevel@tonic-gate hp->next = shadow_list.next; 4683*7c478bd9Sstevel@tonic-gate shadow_list.next->prev = hp; 4684*7c478bd9Sstevel@tonic-gate hp->prev = &shadow_list; 4685*7c478bd9Sstevel@tonic-gate shadow_list.next = hp; 4686*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(hdlp->ih_inum); 4687*7c478bd9Sstevel@tonic-gate hp->hnext = hhashp->hnext; 4688*7c478bd9Sstevel@tonic-gate hhashp->hnext->hprev = hp; 4689*7c478bd9Sstevel@tonic-gate hp->hprev = hhashp; 4690*7c478bd9Sstevel@tonic-gate hhashp->hnext = hp; 4691*7c478bd9Sstevel@tonic-gate dhashp = HDL_DHASH(hp->dip); 4692*7c478bd9Sstevel@tonic-gate hp->dnext = dhashp->dnext; 4693*7c478bd9Sstevel@tonic-gate dhashp->dnext->dprev = hp; 4694*7c478bd9Sstevel@tonic-gate hp->dprev = dhashp; 4695*7c478bd9Sstevel@tonic-gate dhashp->dnext = hp; 4696*7c478bd9Sstevel@tonic-gate /* 4697*7c478bd9Sstevel@tonic-gate * chain on any pre-existing errdefs that apply to this 4698*7c478bd9Sstevel@tonic-gate * acc_handle 4699*7c478bd9Sstevel@tonic-gate */ 4700*7c478bd9Sstevel@tonic-gate for (ep = errent_listp; ep != NULL; ep = ep->next) { 4701*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(hp->name) == 4702*7c478bd9Sstevel@tonic-gate ddi_name_to_major(ep->name) && 4703*7c478bd9Sstevel@tonic-gate hp->instance == ep->errdef.instance && 4704*7c478bd9Sstevel@tonic-gate (ep->errdef.access_type & BOFI_INTR)) { 4705*7c478bd9Sstevel@tonic-gate lp = bofi_link_freelist; 4706*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 4707*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp->link; 4708*7c478bd9Sstevel@tonic-gate lp->errentp = ep; 4709*7c478bd9Sstevel@tonic-gate lp->link = hp->link; 4710*7c478bd9Sstevel@tonic-gate hp->link = lp; 4711*7c478bd9Sstevel@tonic-gate } 4712*7c478bd9Sstevel@tonic-gate } 4713*7c478bd9Sstevel@tonic-gate } 4714*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4715*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4716*7c478bd9Sstevel@tonic-gate return (retval); 4717*7c478bd9Sstevel@tonic-gate case DDI_INTROP_REMISR: 4718*7c478bd9Sstevel@tonic-gate /* 4719*7c478bd9Sstevel@tonic-gate * call nexus routine first 4720*7c478bd9Sstevel@tonic-gate */ 4721*7c478bd9Sstevel@tonic-gate retval = save_bus_ops.bus_intr_op(dip, rdip, 4722*7c478bd9Sstevel@tonic-gate intr_op, hdlp, result); 4723*7c478bd9Sstevel@tonic-gate /* 4724*7c478bd9Sstevel@tonic-gate * find shadow handle 4725*7c478bd9Sstevel@tonic-gate */ 4726*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_low_mutex); 4727*7c478bd9Sstevel@tonic-gate mutex_enter(&bofi_mutex); 4728*7c478bd9Sstevel@tonic-gate hhashp = HDL_HHASH(hdlp->ih_inum); 4729*7c478bd9Sstevel@tonic-gate for (hp = hhashp->hnext; hp != hhashp; hp = hp->hnext) { 4730*7c478bd9Sstevel@tonic-gate if (hp->dip == rdip && 4731*7c478bd9Sstevel@tonic-gate hp->type == BOFI_INT_HDL && 4732*7c478bd9Sstevel@tonic-gate hp->bofi_inum == hdlp->ih_inum) { 4733*7c478bd9Sstevel@tonic-gate break; 4734*7c478bd9Sstevel@tonic-gate } 4735*7c478bd9Sstevel@tonic-gate } 4736*7c478bd9Sstevel@tonic-gate if (hp == hhashp) { 4737*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4738*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4739*7c478bd9Sstevel@tonic-gate return (retval); 4740*7c478bd9Sstevel@tonic-gate } 4741*7c478bd9Sstevel@tonic-gate /* 4742*7c478bd9Sstevel@tonic-gate * found one - remove from dhash, hhash and inuse lists 4743*7c478bd9Sstevel@tonic-gate */ 4744*7c478bd9Sstevel@tonic-gate hp->hnext->hprev = hp->hprev; 4745*7c478bd9Sstevel@tonic-gate hp->hprev->hnext = hp->hnext; 4746*7c478bd9Sstevel@tonic-gate hp->dnext->dprev = hp->dprev; 4747*7c478bd9Sstevel@tonic-gate hp->dprev->dnext = hp->dnext; 4748*7c478bd9Sstevel@tonic-gate hp->next->prev = hp->prev; 4749*7c478bd9Sstevel@tonic-gate hp->prev->next = hp->next; 4750*7c478bd9Sstevel@tonic-gate /* 4751*7c478bd9Sstevel@tonic-gate * free any errdef link structures 4752*7c478bd9Sstevel@tonic-gate * tagged on to this shadow handle 4753*7c478bd9Sstevel@tonic-gate */ 4754*7c478bd9Sstevel@tonic-gate for (lp = hp->link; lp != NULL; ) { 4755*7c478bd9Sstevel@tonic-gate next_lp = lp->link; 4756*7c478bd9Sstevel@tonic-gate lp->link = bofi_link_freelist; 4757*7c478bd9Sstevel@tonic-gate bofi_link_freelist = lp; 4758*7c478bd9Sstevel@tonic-gate lp = next_lp; 4759*7c478bd9Sstevel@tonic-gate } 4760*7c478bd9Sstevel@tonic-gate hp->link = NULL; 4761*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_mutex); 4762*7c478bd9Sstevel@tonic-gate mutex_exit(&bofi_low_mutex); 4763*7c478bd9Sstevel@tonic-gate kmem_free(hp, sizeof (struct bofi_shadow)); 4764*7c478bd9Sstevel@tonic-gate return (retval); 4765*7c478bd9Sstevel@tonic-gate default: 4766*7c478bd9Sstevel@tonic-gate return (save_bus_ops.bus_intr_op(dip, rdip, 4767*7c478bd9Sstevel@tonic-gate intr_op, hdlp, result)); 4768*7c478bd9Sstevel@tonic-gate } 4769*7c478bd9Sstevel@tonic-gate } 4770