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 2004 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/param.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/poll.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/model.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/open.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/vm.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 46*7c478bd9Sstevel@tonic-gate #include <vm/hat.h> 47*7c478bd9Sstevel@tonic-gate #include <vm/seg.h> 48*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/avintr.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> /* include implementation structure defs */ 60*7c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/epm.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/devctl.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/dacf_impl.h> 69*7c478bd9Sstevel@tonic-gate #include <sys/nvpair.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/fs/dv_node.h> 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #ifdef __sparc 74*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> /* getpil/setpil */ 75*7c478bd9Sstevel@tonic-gate #include <sys/membar.h> /* membar_sync */ 76*7c478bd9Sstevel@tonic-gate #endif 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * ndi property handling 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate int 82*7c478bd9Sstevel@tonic-gate ndi_prop_update_int(dev_t match_dev, dev_info_t *dip, 83*7c478bd9Sstevel@tonic-gate char *name, int data) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 86*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_INT | DDI_PROP_DONTSLEEP, 87*7c478bd9Sstevel@tonic-gate name, &data, 1, ddi_prop_fm_encode_ints)); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate int 91*7c478bd9Sstevel@tonic-gate ndi_prop_update_int64(dev_t match_dev, dev_info_t *dip, 92*7c478bd9Sstevel@tonic-gate char *name, int64_t data) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 95*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_INT64 | DDI_PROP_DONTSLEEP, 96*7c478bd9Sstevel@tonic-gate name, &data, 1, ddi_prop_fm_encode_int64)); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate int 100*7c478bd9Sstevel@tonic-gate ndi_prop_create_boolean(dev_t match_dev, dev_info_t *dip, 101*7c478bd9Sstevel@tonic-gate char *name) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 104*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_ANY | DDI_PROP_DONTSLEEP, 105*7c478bd9Sstevel@tonic-gate name, NULL, 0, ddi_prop_fm_encode_bytes)); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate int 109*7c478bd9Sstevel@tonic-gate ndi_prop_update_int_array(dev_t match_dev, dev_info_t *dip, 110*7c478bd9Sstevel@tonic-gate char *name, int *data, uint_t nelements) 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 113*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_INT | DDI_PROP_DONTSLEEP, 114*7c478bd9Sstevel@tonic-gate name, data, nelements, ddi_prop_fm_encode_ints)); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate int 118*7c478bd9Sstevel@tonic-gate ndi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip, 119*7c478bd9Sstevel@tonic-gate char *name, int64_t *data, uint_t nelements) 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 122*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_INT64 | DDI_PROP_DONTSLEEP, 123*7c478bd9Sstevel@tonic-gate name, data, nelements, ddi_prop_fm_encode_int64)); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate int 127*7c478bd9Sstevel@tonic-gate ndi_prop_update_string(dev_t match_dev, dev_info_t *dip, 128*7c478bd9Sstevel@tonic-gate char *name, char *data) 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 131*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_STRING | DDI_PROP_DONTSLEEP, 132*7c478bd9Sstevel@tonic-gate name, &data, 1, ddi_prop_fm_encode_string)); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate int 136*7c478bd9Sstevel@tonic-gate ndi_prop_update_string_array(dev_t match_dev, dev_info_t *dip, 137*7c478bd9Sstevel@tonic-gate char *name, char **data, uint_t nelements) 138*7c478bd9Sstevel@tonic-gate { 139*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 140*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_STRING | DDI_PROP_DONTSLEEP, 141*7c478bd9Sstevel@tonic-gate name, data, nelements, 142*7c478bd9Sstevel@tonic-gate ddi_prop_fm_encode_strings)); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate int 146*7c478bd9Sstevel@tonic-gate ndi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip, 147*7c478bd9Sstevel@tonic-gate char *name, uchar_t *data, uint_t nelements) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate if (nelements == 0) 150*7c478bd9Sstevel@tonic-gate return (DDI_PROP_INVAL_ARG); 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate return (ddi_prop_update_common(match_dev, dip, 153*7c478bd9Sstevel@tonic-gate DDI_PROP_HW_DEF | DDI_PROP_TYPE_BYTE | DDI_PROP_DONTSLEEP, 154*7c478bd9Sstevel@tonic-gate name, data, nelements, ddi_prop_fm_encode_bytes)); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate int 158*7c478bd9Sstevel@tonic-gate ndi_prop_remove(dev_t dev, dev_info_t *dip, char *name) 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate return (ddi_prop_remove_common(dev, dip, name, DDI_PROP_HW_DEF)); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate void 164*7c478bd9Sstevel@tonic-gate ndi_prop_remove_all(dev_info_t *dip) 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate ddi_prop_remove_all_common(dip, (int)DDI_PROP_HW_DEF); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * Post an event notification to nexus driver responsible for handling 171*7c478bd9Sstevel@tonic-gate * the event. The responsible nexus is defined in the cookie passed in as 172*7c478bd9Sstevel@tonic-gate * the third parameter. 173*7c478bd9Sstevel@tonic-gate * The dip parameter is an artifact of an older implementation in which all 174*7c478bd9Sstevel@tonic-gate * requests to remove an eventcall would bubble up the tree. Today, this 175*7c478bd9Sstevel@tonic-gate * parameter is ignored. 176*7c478bd9Sstevel@tonic-gate * Input Parameters: 177*7c478bd9Sstevel@tonic-gate * dip - Ignored. 178*7c478bd9Sstevel@tonic-gate * rdip - device driver posting the event 179*7c478bd9Sstevel@tonic-gate * cookie - valid ddi_eventcookie_t, obtained by caller prior to 180*7c478bd9Sstevel@tonic-gate * invocation of this routine 181*7c478bd9Sstevel@tonic-gate * impl_data - used by framework 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 184*7c478bd9Sstevel@tonic-gate int 185*7c478bd9Sstevel@tonic-gate ndi_post_event(dev_info_t *dip, dev_info_t *rdip, 186*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, void *impl_data) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate dev_info_t *ddip; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate ASSERT(cookie); 191*7c478bd9Sstevel@tonic-gate ddip = NDI_EVENT_DDIP(cookie); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * perform sanity checks. These conditions should never be true. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops != NULL); 198*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops->busops_rev >= BUSO_REV_6); 199*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops->bus_post_event != NULL); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * post the event to the responsible ancestor 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_post_event)) 205*7c478bd9Sstevel@tonic-gate (ddip, rdip, cookie, impl_data)); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * Calls the bus nexus driver's implementation of the 210*7c478bd9Sstevel@tonic-gate * (*bus_remove_eventcall)() interface. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate int 213*7c478bd9Sstevel@tonic-gate ndi_busop_remove_eventcall(dev_info_t *ddip, ddi_callback_id_t id) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate ASSERT(id); 217*7c478bd9Sstevel@tonic-gate /* check for a correct revno before calling up the device tree. */ 218*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops != NULL); 219*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops->busops_rev >= BUSO_REV_6); 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (DEVI(ddip)->devi_ops->devo_bus_ops->bus_remove_eventcall == NULL) 222*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * request responsible nexus to remove the eventcall 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_remove_eventcall)) 228*7c478bd9Sstevel@tonic-gate (ddip, id)); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* 232*7c478bd9Sstevel@tonic-gate * Calls the bus nexus driver's implementation of the 233*7c478bd9Sstevel@tonic-gate * (*bus_add_eventcall)() interface. The dip parameter is an 234*7c478bd9Sstevel@tonic-gate * artifact of an older implementation in which all requests to 235*7c478bd9Sstevel@tonic-gate * add an eventcall would bubble up the tree. Today, this parameter is 236*7c478bd9Sstevel@tonic-gate * ignored. 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 239*7c478bd9Sstevel@tonic-gate int 240*7c478bd9Sstevel@tonic-gate ndi_busop_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 241*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, void (*callback)(), void *arg, 242*7c478bd9Sstevel@tonic-gate ddi_callback_id_t *cb_id) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate dev_info_t *ddip = (dev_info_t *)NDI_EVENT_DDIP(cookie); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * check for a correct revno before calling up the device tree. 248*7c478bd9Sstevel@tonic-gate */ 249*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops != NULL); 250*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(ddip)->devi_ops->devo_bus_ops->busops_rev >= BUSO_REV_6); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if (DEVI(ddip)->devi_ops->devo_bus_ops->bus_add_eventcall == NULL) 253*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * request responsible ancestor to add the eventcall 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_add_eventcall)) 259*7c478bd9Sstevel@tonic-gate (ddip, rdip, cookie, callback, arg, cb_id)); 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Calls the bus nexus driver's implementation of the 264*7c478bd9Sstevel@tonic-gate * (*bus_get_eventcookie)() interface up the device tree hierarchy. 265*7c478bd9Sstevel@tonic-gate */ 266*7c478bd9Sstevel@tonic-gate int 267*7c478bd9Sstevel@tonic-gate ndi_busop_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 268*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t *event_cookiep) 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* Can not be called from rootnex. */ 273*7c478bd9Sstevel@tonic-gate ASSERT(pdip); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * check for a correct revno before calling up the device tree. 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate ASSERT(DEVI(pdip)->devi_ops->devo_bus_ops != NULL); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate if ((DEVI(pdip)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_6) || 281*7c478bd9Sstevel@tonic-gate (DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie == NULL)) { 282*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 283*7c478bd9Sstevel@tonic-gate if ((DEVI(pdip)->devi_ops->devo_bus_ops->busops_rev >= 284*7c478bd9Sstevel@tonic-gate BUSO_REV_3) && 285*7c478bd9Sstevel@tonic-gate (DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie)) { 286*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 287*7c478bd9Sstevel@tonic-gate "Warning: %s%d busops_rev=%d no longer supported" 288*7c478bd9Sstevel@tonic-gate " by the NDI event framework.\nBUSO_REV_6 or " 289*7c478bd9Sstevel@tonic-gate "greater must be used.", 290*7c478bd9Sstevel@tonic-gate DEVI(pdip)->devi_binding_name, 291*7c478bd9Sstevel@tonic-gate DEVI(pdip)->devi_instance, 292*7c478bd9Sstevel@tonic-gate DEVI(pdip)->devi_ops->devo_bus_ops->busops_rev); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate return (ndi_busop_get_eventcookie(pdip, rdip, name, 297*7c478bd9Sstevel@tonic-gate event_cookiep)); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate return ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie)) 301*7c478bd9Sstevel@tonic-gate (pdip, rdip, name, event_cookiep)); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Copy in the devctl IOCTL data and return a handle to 306*7c478bd9Sstevel@tonic-gate * the data. 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate int 309*7c478bd9Sstevel@tonic-gate ndi_dc_allochdl(void *iocarg, struct devctl_iocdata **rdcp) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate struct devctl_iocdata *dcp; 312*7c478bd9Sstevel@tonic-gate char *cpybuf; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate ASSERT(rdcp != NULL); 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate dcp = kmem_zalloc(sizeof (*dcp), KM_SLEEP); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 319*7c478bd9Sstevel@tonic-gate if (copyin(iocarg, dcp, sizeof (*dcp)) != 0) { 320*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 321*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 325*7c478bd9Sstevel@tonic-gate else { 326*7c478bd9Sstevel@tonic-gate struct devctl_iocdata32 dcp32; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (copyin(iocarg, &dcp32, sizeof (dcp32)) != 0) { 329*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 330*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate dcp->cmd = (uint_t)dcp32.cmd; 333*7c478bd9Sstevel@tonic-gate dcp->flags = (uint_t)dcp32.flags; 334*7c478bd9Sstevel@tonic-gate dcp->cpyout_buf = (uint_t *)(uintptr_t)dcp32.cpyout_buf; 335*7c478bd9Sstevel@tonic-gate dcp->nvl_user = (nvlist_t *)(uintptr_t)dcp32.nvl_user; 336*7c478bd9Sstevel@tonic-gate dcp->nvl_usersz = (size_t)dcp32.nvl_usersz; 337*7c478bd9Sstevel@tonic-gate dcp->c_nodename = (char *)(uintptr_t)dcp32.c_nodename; 338*7c478bd9Sstevel@tonic-gate dcp->c_unitaddr = (char *)(uintptr_t)dcp32.c_unitaddr; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate #endif 341*7c478bd9Sstevel@tonic-gate if (dcp->c_nodename != NULL) { 342*7c478bd9Sstevel@tonic-gate cpybuf = kmem_alloc(MAXNAMELEN, KM_SLEEP); 343*7c478bd9Sstevel@tonic-gate if (copyinstr(dcp->c_nodename, cpybuf, MAXNAMELEN, 0) != 0) { 344*7c478bd9Sstevel@tonic-gate kmem_free(cpybuf, MAXNAMELEN); 345*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 346*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate cpybuf[MAXNAMELEN - 1] = '\0'; 349*7c478bd9Sstevel@tonic-gate dcp->c_nodename = cpybuf; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate if (dcp->c_unitaddr != NULL) { 353*7c478bd9Sstevel@tonic-gate cpybuf = kmem_alloc(MAXNAMELEN, KM_SLEEP); 354*7c478bd9Sstevel@tonic-gate if (copyinstr(dcp->c_unitaddr, cpybuf, MAXNAMELEN, 0) != 0) { 355*7c478bd9Sstevel@tonic-gate kmem_free(cpybuf, MAXNAMELEN); 356*7c478bd9Sstevel@tonic-gate if (dcp->c_nodename != NULL) 357*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_nodename, MAXNAMELEN); 358*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 359*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate cpybuf[MAXNAMELEN - 1] = '\0'; 362*7c478bd9Sstevel@tonic-gate dcp->c_unitaddr = cpybuf; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * copyin and unpack a user defined nvlist if one was passed 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate if (dcp->nvl_user != NULL) { 369*7c478bd9Sstevel@tonic-gate cpybuf = kmem_alloc(dcp->nvl_usersz, KM_SLEEP); 370*7c478bd9Sstevel@tonic-gate if (copyin(dcp->nvl_user, cpybuf, dcp->nvl_usersz) != 0) { 371*7c478bd9Sstevel@tonic-gate kmem_free(cpybuf, dcp->nvl_usersz); 372*7c478bd9Sstevel@tonic-gate if (dcp->c_nodename != NULL) 373*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_nodename, MAXNAMELEN); 374*7c478bd9Sstevel@tonic-gate if (dcp->c_unitaddr != NULL) 375*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_unitaddr, MAXNAMELEN); 376*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 377*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (nvlist_unpack(cpybuf, dcp->nvl_usersz, &dcp->nvl_user, 381*7c478bd9Sstevel@tonic-gate KM_SLEEP)) { 382*7c478bd9Sstevel@tonic-gate kmem_free(cpybuf, dcp->nvl_usersz); 383*7c478bd9Sstevel@tonic-gate if (dcp->c_nodename != NULL) 384*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_nodename, MAXNAMELEN); 385*7c478bd9Sstevel@tonic-gate if (dcp->c_unitaddr != NULL) 386*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_unitaddr, MAXNAMELEN); 387*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 388*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate * free the buffer containing the packed nvlist 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate kmem_free(cpybuf, dcp->nvl_usersz); 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate *rdcp = dcp; 398*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * free all space allocated to a handle. 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate void 405*7c478bd9Sstevel@tonic-gate ndi_dc_freehdl(struct devctl_iocdata *dcp) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate ASSERT(dcp != NULL); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate if (dcp->c_nodename != NULL) 410*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_nodename, MAXNAMELEN); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate if (dcp->c_unitaddr != NULL) 413*7c478bd9Sstevel@tonic-gate kmem_free(dcp->c_unitaddr, MAXNAMELEN); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (dcp->nvl_user != NULL) 416*7c478bd9Sstevel@tonic-gate nvlist_free(dcp->nvl_user); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate kmem_free(dcp, sizeof (*dcp)); 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate char * 422*7c478bd9Sstevel@tonic-gate ndi_dc_getname(struct devctl_iocdata *dcp) 423*7c478bd9Sstevel@tonic-gate { 424*7c478bd9Sstevel@tonic-gate ASSERT(dcp != NULL); 425*7c478bd9Sstevel@tonic-gate return (dcp->c_nodename); 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate char * 430*7c478bd9Sstevel@tonic-gate ndi_dc_getaddr(struct devctl_iocdata *dcp) 431*7c478bd9Sstevel@tonic-gate { 432*7c478bd9Sstevel@tonic-gate ASSERT(dcp != NULL); 433*7c478bd9Sstevel@tonic-gate return (dcp->c_unitaddr); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate nvlist_t * 437*7c478bd9Sstevel@tonic-gate ndi_dc_get_ap_data(struct devctl_iocdata *dcp) 438*7c478bd9Sstevel@tonic-gate { 439*7c478bd9Sstevel@tonic-gate ASSERT(dcp != NULL); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate return (dcp->nvl_user); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * Transition the child named by "devname@devaddr" to the online state. 446*7c478bd9Sstevel@tonic-gate * For use by a driver's DEVCTL_DEVICE_ONLINE handler. 447*7c478bd9Sstevel@tonic-gate */ 448*7c478bd9Sstevel@tonic-gate int 449*7c478bd9Sstevel@tonic-gate ndi_devctl_device_online(dev_info_t *dip, struct devctl_iocdata *dcp, 450*7c478bd9Sstevel@tonic-gate uint_t flags) 451*7c478bd9Sstevel@tonic-gate { 452*7c478bd9Sstevel@tonic-gate int rval; 453*7c478bd9Sstevel@tonic-gate char *name; 454*7c478bd9Sstevel@tonic-gate dev_info_t *rdip; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (ndi_dc_getname(dcp) == NULL || ndi_dc_getaddr(dcp) == NULL) 457*7c478bd9Sstevel@tonic-gate return (EINVAL); 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 460*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s@%s", 461*7c478bd9Sstevel@tonic-gate ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if ((rval = ndi_devi_config_one(dip, name, &rdip, 464*7c478bd9Sstevel@tonic-gate flags | NDI_DEVI_ONLINE | NDI_CONFIG)) == NDI_SUCCESS) { 465*7c478bd9Sstevel@tonic-gate ndi_rele_devi(rdip); 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Invalidate devfs cached directory contents. For the checks 469*7c478bd9Sstevel@tonic-gate * in the "if" condition see the comment in ndi_devi_online(). 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate if (i_ddi_node_state(dip) == DS_READY && !DEVI_BUSY_OWNED(dip)) 472*7c478bd9Sstevel@tonic-gate (void) devfs_clean(dip, NULL, 0); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate } else if (rval == NDI_BUSY) { 475*7c478bd9Sstevel@tonic-gate rval = EBUSY; 476*7c478bd9Sstevel@tonic-gate } else if (rval == NDI_FAILURE) { 477*7c478bd9Sstevel@tonic-gate rval = EIO; 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate NDI_DEBUG(flags, (CE_CONT, "%s%d: online: %s: %s\n", 481*7c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), name, 482*7c478bd9Sstevel@tonic-gate ((rval == NDI_SUCCESS) ? "ok" : "failed"))); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate kmem_free(name, MAXNAMELEN); 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate return (rval); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * Transition the child named by "devname@devaddr" to the offline state. 491*7c478bd9Sstevel@tonic-gate * For use by a driver's DEVCTL_DEVICE_OFFLINE handler. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate int 494*7c478bd9Sstevel@tonic-gate ndi_devctl_device_offline(dev_info_t *dip, struct devctl_iocdata *dcp, 495*7c478bd9Sstevel@tonic-gate uint_t flags) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate int rval; 498*7c478bd9Sstevel@tonic-gate char *name; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate if (ndi_dc_getname(dcp) == NULL || ndi_dc_getaddr(dcp) == NULL) 501*7c478bd9Sstevel@tonic-gate return (EINVAL); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 504*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s@%s", 505*7c478bd9Sstevel@tonic-gate ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate rval = devfs_clean(dip, name, DV_CLEAN_FORCE); 508*7c478bd9Sstevel@tonic-gate if (rval) { 509*7c478bd9Sstevel@tonic-gate rval = EBUSY; 510*7c478bd9Sstevel@tonic-gate } else { 511*7c478bd9Sstevel@tonic-gate rval = ndi_devi_unconfig_one(dip, name, NULL, 512*7c478bd9Sstevel@tonic-gate flags | NDI_DEVI_OFFLINE); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate if (rval == NDI_BUSY) { 515*7c478bd9Sstevel@tonic-gate rval = EBUSY; 516*7c478bd9Sstevel@tonic-gate } else if (rval == NDI_FAILURE) { 517*7c478bd9Sstevel@tonic-gate rval = EIO; 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate NDI_DEBUG(flags, (CE_CONT, "%s%d: offline: %s: %s\n", 522*7c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), name, 523*7c478bd9Sstevel@tonic-gate (rval == NDI_SUCCESS) ? "ok" : "failed")); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate kmem_free(name, MAXNAMELEN); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate return (rval); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * Remove the child named by "devname@devaddr". 532*7c478bd9Sstevel@tonic-gate * For use by a driver's DEVCTL_DEVICE_REMOVE handler. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate int 535*7c478bd9Sstevel@tonic-gate ndi_devctl_device_remove(dev_info_t *dip, struct devctl_iocdata *dcp, 536*7c478bd9Sstevel@tonic-gate uint_t flags) 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate int rval; 539*7c478bd9Sstevel@tonic-gate char *name; 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate if (ndi_dc_getname(dcp) == NULL || ndi_dc_getaddr(dcp) == NULL) 542*7c478bd9Sstevel@tonic-gate return (EINVAL); 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 545*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s@%s", 546*7c478bd9Sstevel@tonic-gate ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate (void) devfs_clean(dip, name, DV_CLEAN_FORCE); 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate rval = ndi_devi_unconfig_one(dip, name, NULL, flags | NDI_DEVI_REMOVE); 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate if (rval == NDI_BUSY) { 553*7c478bd9Sstevel@tonic-gate rval = EBUSY; 554*7c478bd9Sstevel@tonic-gate } else if (rval == NDI_FAILURE) { 555*7c478bd9Sstevel@tonic-gate rval = EIO; 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate NDI_DEBUG(flags, (CE_CONT, "%s%d: remove: %s: %s\n", 559*7c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), name, 560*7c478bd9Sstevel@tonic-gate (rval == NDI_SUCCESS) ? "ok" : "failed")); 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate kmem_free(name, MAXNAMELEN); 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate return (rval); 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * Return devctl state of the child named by "name@addr". 569*7c478bd9Sstevel@tonic-gate * For use by a driver's DEVCTL_DEVICE_GETSTATE handler. 570*7c478bd9Sstevel@tonic-gate */ 571*7c478bd9Sstevel@tonic-gate int 572*7c478bd9Sstevel@tonic-gate ndi_devctl_device_getstate(dev_info_t *parent, struct devctl_iocdata *dcp, 573*7c478bd9Sstevel@tonic-gate uint_t *state) 574*7c478bd9Sstevel@tonic-gate { 575*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 576*7c478bd9Sstevel@tonic-gate char *name, *addr; 577*7c478bd9Sstevel@tonic-gate char *devname; 578*7c478bd9Sstevel@tonic-gate int devnamelen; 579*7c478bd9Sstevel@tonic-gate int circ; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate if (parent == NULL || 582*7c478bd9Sstevel@tonic-gate ((name = ndi_dc_getname(dcp)) == NULL) || 583*7c478bd9Sstevel@tonic-gate ((addr = ndi_dc_getaddr(dcp)) == NULL)) 584*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate devnamelen = strlen(name) + strlen(addr) + 2; 587*7c478bd9Sstevel@tonic-gate devname = kmem_alloc(devnamelen, KM_SLEEP); 588*7c478bd9Sstevel@tonic-gate if (strlen(addr) > 0) { 589*7c478bd9Sstevel@tonic-gate (void) snprintf(devname, devnamelen, "%s@%s", name, addr); 590*7c478bd9Sstevel@tonic-gate } else { 591*7c478bd9Sstevel@tonic-gate (void) snprintf(devname, devnamelen, "%s", name); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate dip = ndi_devi_findchild(parent, devname); 597*7c478bd9Sstevel@tonic-gate kmem_free(devname, devnamelen); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 600*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 601*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate mutex_enter(&(DEVI(dip)->devi_lock)); 605*7c478bd9Sstevel@tonic-gate if (DEVI_IS_DEVICE_OFFLINE(dip)) { 606*7c478bd9Sstevel@tonic-gate *state = DEVICE_OFFLINE; 607*7c478bd9Sstevel@tonic-gate } else if (DEVI_IS_DEVICE_DOWN(dip)) { 608*7c478bd9Sstevel@tonic-gate *state = DEVICE_DOWN; 609*7c478bd9Sstevel@tonic-gate } else { 610*7c478bd9Sstevel@tonic-gate *state = DEVICE_ONLINE; 611*7c478bd9Sstevel@tonic-gate if (devi_stillreferenced(dip) == DEVI_REFERENCED) 612*7c478bd9Sstevel@tonic-gate *state |= DEVICE_BUSY; 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate mutex_exit(&(DEVI(dip)->devi_lock)); 616*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate /* 622*7c478bd9Sstevel@tonic-gate * return the current state of the device "dip" 623*7c478bd9Sstevel@tonic-gate * 624*7c478bd9Sstevel@tonic-gate * recommend using ndi_devctl_ioctl() or 625*7c478bd9Sstevel@tonic-gate * ndi_devctl_device_getstate() instead 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate int 628*7c478bd9Sstevel@tonic-gate ndi_dc_return_dev_state(dev_info_t *dip, struct devctl_iocdata *dcp) 629*7c478bd9Sstevel@tonic-gate { 630*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 631*7c478bd9Sstevel@tonic-gate uint_t devstate = 0; 632*7c478bd9Sstevel@tonic-gate int circ; 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate if ((dip == NULL) || (dcp == NULL)) 635*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(dip); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circ); 640*7c478bd9Sstevel@tonic-gate mutex_enter(&(DEVI(dip)->devi_lock)); 641*7c478bd9Sstevel@tonic-gate if (DEVI_IS_DEVICE_OFFLINE(dip)) { 642*7c478bd9Sstevel@tonic-gate devstate = DEVICE_OFFLINE; 643*7c478bd9Sstevel@tonic-gate } else if (DEVI_IS_DEVICE_DOWN(dip)) { 644*7c478bd9Sstevel@tonic-gate devstate = DEVICE_DOWN; 645*7c478bd9Sstevel@tonic-gate } else { 646*7c478bd9Sstevel@tonic-gate devstate = DEVICE_ONLINE; 647*7c478bd9Sstevel@tonic-gate if (devi_stillreferenced(dip) == DEVI_REFERENCED) 648*7c478bd9Sstevel@tonic-gate devstate |= DEVICE_BUSY; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate mutex_exit(&(DEVI(dip)->devi_lock)); 652*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circ); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate if (copyout(&devstate, dcp->cpyout_buf, sizeof (uint_t)) != 0) 655*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate /* 661*7c478bd9Sstevel@tonic-gate * Return device's bus state 662*7c478bd9Sstevel@tonic-gate * For use by a driver's DEVCTL_BUS_GETSTATE handler. 663*7c478bd9Sstevel@tonic-gate */ 664*7c478bd9Sstevel@tonic-gate int 665*7c478bd9Sstevel@tonic-gate ndi_devctl_bus_getstate(dev_info_t *dip, struct devctl_iocdata *dcp, 666*7c478bd9Sstevel@tonic-gate uint_t *state) 667*7c478bd9Sstevel@tonic-gate { 668*7c478bd9Sstevel@tonic-gate if ((dip == NULL) || (dcp == NULL)) 669*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate return (ndi_get_bus_state(dip, state)); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* 675*7c478bd9Sstevel@tonic-gate * Generic devctl ioctl handler 676*7c478bd9Sstevel@tonic-gate */ 677*7c478bd9Sstevel@tonic-gate int 678*7c478bd9Sstevel@tonic-gate ndi_devctl_ioctl(dev_info_t *dip, int cmd, intptr_t arg, int mode, uint_t flags) 679*7c478bd9Sstevel@tonic-gate { 680*7c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(mode)) 681*7c478bd9Sstevel@tonic-gate struct devctl_iocdata *dcp; 682*7c478bd9Sstevel@tonic-gate uint_t state; 683*7c478bd9Sstevel@tonic-gate int rval = ENOTTY; 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * read devctl ioctl data 687*7c478bd9Sstevel@tonic-gate */ 688*7c478bd9Sstevel@tonic-gate if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) 689*7c478bd9Sstevel@tonic-gate return (EFAULT); 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate switch (cmd) { 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_GETSTATE: 694*7c478bd9Sstevel@tonic-gate rval = ndi_devctl_bus_getstate(dip, dcp, &state); 695*7c478bd9Sstevel@tonic-gate if (rval == NDI_SUCCESS) { 696*7c478bd9Sstevel@tonic-gate if (copyout(&state, dcp->cpyout_buf, 697*7c478bd9Sstevel@tonic-gate sizeof (uint_t)) != 0) 698*7c478bd9Sstevel@tonic-gate rval = NDI_FAULT; 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate break; 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_ONLINE: 703*7c478bd9Sstevel@tonic-gate rval = ndi_devctl_device_online(dip, dcp, flags); 704*7c478bd9Sstevel@tonic-gate break; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_OFFLINE: 707*7c478bd9Sstevel@tonic-gate rval = ndi_devctl_device_offline(dip, dcp, flags); 708*7c478bd9Sstevel@tonic-gate break; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_GETSTATE: 711*7c478bd9Sstevel@tonic-gate rval = ndi_devctl_device_getstate(dip, dcp, &state); 712*7c478bd9Sstevel@tonic-gate if (rval == NDI_SUCCESS) { 713*7c478bd9Sstevel@tonic-gate if (copyout(&state, dcp->cpyout_buf, 714*7c478bd9Sstevel@tonic-gate sizeof (uint_t)) != 0) 715*7c478bd9Sstevel@tonic-gate rval = NDI_FAULT; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate break; 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_REMOVE: 720*7c478bd9Sstevel@tonic-gate rval = ndi_devctl_device_remove(dip, dcp, flags); 721*7c478bd9Sstevel@tonic-gate break; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_DEV_CREATE: 724*7c478bd9Sstevel@tonic-gate rval = ndi_dc_devi_create(dcp, dip, 0, NULL); 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate /* 728*7c478bd9Sstevel@tonic-gate * ioctls for which a generic implementation makes no sense 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_RESET: 731*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_RESETALL: 732*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_RESET: 733*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_CONNECT: 734*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_DISCONNECT: 735*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_INSERT: 736*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_REMOVE: 737*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_CONFIGURE: 738*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_UNCONFIGURE: 739*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_GETSTATE: 740*7c478bd9Sstevel@tonic-gate case DEVCTL_AP_CONTROL: 741*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_QUIESCE: 742*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS_UNQUIESCE: 743*7c478bd9Sstevel@tonic-gate rval = ENOTSUP; 744*7c478bd9Sstevel@tonic-gate break; 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate ndi_dc_freehdl(dcp); 748*7c478bd9Sstevel@tonic-gate return (rval); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * Copyout the state of the Attachment Point "ap" to the requesting 753*7c478bd9Sstevel@tonic-gate * user process. 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate int 756*7c478bd9Sstevel@tonic-gate ndi_dc_return_ap_state(devctl_ap_state_t *ap, struct devctl_iocdata *dcp) 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate if ((ap == NULL) || (dcp == NULL)) 759*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 763*7c478bd9Sstevel@tonic-gate if (copyout(ap, dcp->cpyout_buf, 764*7c478bd9Sstevel@tonic-gate sizeof (devctl_ap_state_t)) != 0) 765*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 768*7c478bd9Sstevel@tonic-gate else { 769*7c478bd9Sstevel@tonic-gate struct devctl_ap_state32 ap_state32; 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate ap_state32.ap_rstate = ap->ap_rstate; 772*7c478bd9Sstevel@tonic-gate ap_state32.ap_ostate = ap->ap_ostate; 773*7c478bd9Sstevel@tonic-gate ap_state32.ap_condition = ap->ap_condition; 774*7c478bd9Sstevel@tonic-gate ap_state32.ap_error_code = ap->ap_error_code; 775*7c478bd9Sstevel@tonic-gate ap_state32.ap_in_transition = ap->ap_in_transition; 776*7c478bd9Sstevel@tonic-gate ap_state32.ap_last_change = (time32_t)ap->ap_last_change; 777*7c478bd9Sstevel@tonic-gate if (copyout(&ap_state32, dcp->cpyout_buf, 778*7c478bd9Sstevel@tonic-gate sizeof (devctl_ap_state32_t)) != 0) 779*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate #endif 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* 787*7c478bd9Sstevel@tonic-gate * Copyout the bus state of the bus nexus device "dip" to the requesting 788*7c478bd9Sstevel@tonic-gate * user process. 789*7c478bd9Sstevel@tonic-gate */ 790*7c478bd9Sstevel@tonic-gate int 791*7c478bd9Sstevel@tonic-gate ndi_dc_return_bus_state(dev_info_t *dip, struct devctl_iocdata *dcp) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate uint_t devstate = 0; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate if ((dip == NULL) || (dcp == NULL)) 796*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate if (ndi_get_bus_state(dip, &devstate) != NDI_SUCCESS) 799*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate if (copyout(&devstate, dcp->cpyout_buf, sizeof (uint_t)) != 0) 802*7c478bd9Sstevel@tonic-gate return (NDI_FAULT); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate static int 808*7c478bd9Sstevel@tonic-gate i_dc_devi_create(struct devctl_iocdata *, dev_info_t *, dev_info_t **); 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate /* 811*7c478bd9Sstevel@tonic-gate * create a child device node given the property definitions 812*7c478bd9Sstevel@tonic-gate * supplied by the userland process 813*7c478bd9Sstevel@tonic-gate */ 814*7c478bd9Sstevel@tonic-gate int 815*7c478bd9Sstevel@tonic-gate ndi_dc_devi_create(struct devctl_iocdata *dcp, dev_info_t *pdip, int flags, 816*7c478bd9Sstevel@tonic-gate dev_info_t **rdip) 817*7c478bd9Sstevel@tonic-gate { 818*7c478bd9Sstevel@tonic-gate dev_info_t *cdip; 819*7c478bd9Sstevel@tonic-gate int rv, circular = 0; 820*7c478bd9Sstevel@tonic-gate char devnm[MAXNAMELEN]; 821*7c478bd9Sstevel@tonic-gate int nmlen; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate /* 824*7c478bd9Sstevel@tonic-gate * The child device may have been pre-constructed by an earlier 825*7c478bd9Sstevel@tonic-gate * call to this function with the flag DEVCTL_CONSTRUCT set. 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate if ((cdip = (rdip != NULL) ? *rdip : NULL) == NULL) 829*7c478bd9Sstevel@tonic-gate if ((rv = i_dc_devi_create(dcp, pdip, &cdip)) != 0) 830*7c478bd9Sstevel@tonic-gate return (rv); 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate ASSERT(cdip != NULL); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * Return the device node partially constructed if the 836*7c478bd9Sstevel@tonic-gate * DEVCTL_CONSTRUCT flag is set. 837*7c478bd9Sstevel@tonic-gate */ 838*7c478bd9Sstevel@tonic-gate if (flags & DEVCTL_CONSTRUCT) { 839*7c478bd9Sstevel@tonic-gate if (rdip == NULL) { 840*7c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 841*7c478bd9Sstevel@tonic-gate return (EINVAL); 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate *rdip = cdip; 844*7c478bd9Sstevel@tonic-gate return (0); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* 848*7c478bd9Sstevel@tonic-gate * Bring the node up to a named but OFFLINE state. The calling 849*7c478bd9Sstevel@tonic-gate * application will need to manage the node from here on. 850*7c478bd9Sstevel@tonic-gate */ 851*7c478bd9Sstevel@tonic-gate if (dcp->flags & DEVCTL_OFFLINE) { 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * hand set the OFFLINE flag to prevent any asynchronous 854*7c478bd9Sstevel@tonic-gate * autoconfiguration operations from attaching this node. 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate DEVI(cdip)->devi_state |= DEVI_DEVICE_OFFLINE; 857*7c478bd9Sstevel@tonic-gate rv = ndi_devi_bind_driver(cdip, flags); 858*7c478bd9Sstevel@tonic-gate if (rv != NDI_SUCCESS) { 859*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 860*7c478bd9Sstevel@tonic-gate return (ENXIO); 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate /* 864*7c478bd9Sstevel@tonic-gate * remove the dev_info node if it failed to bind to a 865*7c478bd9Sstevel@tonic-gate * driver above. 866*7c478bd9Sstevel@tonic-gate */ 867*7c478bd9Sstevel@tonic-gate if (i_ddi_node_state(cdip) < DS_BOUND) { 868*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 869*7c478bd9Sstevel@tonic-gate return (ENXIO); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * add the node to the per-driver list and INITCHILD it 874*7c478bd9Sstevel@tonic-gate * to give it a name. 875*7c478bd9Sstevel@tonic-gate */ 876*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circular); 877*7c478bd9Sstevel@tonic-gate if ((rv = ddi_initchild(pdip, cdip)) != DDI_SUCCESS) { 878*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 879*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circular); 880*7c478bd9Sstevel@tonic-gate return (EINVAL); 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circular); 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate } else { 885*7c478bd9Sstevel@tonic-gate /* 886*7c478bd9Sstevel@tonic-gate * Attempt to bring the device ONLINE. If the request to 887*7c478bd9Sstevel@tonic-gate * fails, remove the dev_info node. 888*7c478bd9Sstevel@tonic-gate */ 889*7c478bd9Sstevel@tonic-gate if (ndi_devi_online(cdip, NDI_ONLINE_ATTACH) != NDI_SUCCESS) { 890*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 891*7c478bd9Sstevel@tonic-gate return (ENXIO); 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate /* 895*7c478bd9Sstevel@tonic-gate * if the node was successfully added but there was 896*7c478bd9Sstevel@tonic-gate * no driver available for the device, remove the node 897*7c478bd9Sstevel@tonic-gate */ 898*7c478bd9Sstevel@tonic-gate if (i_ddi_node_state(cdip) < DS_BOUND) { 899*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 900*7c478bd9Sstevel@tonic-gate return (ENODEV); 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * return a handle to the child device 906*7c478bd9Sstevel@tonic-gate * copy out the name of the newly attached child device if 907*7c478bd9Sstevel@tonic-gate * the IOCTL request has provided a copyout buffer. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate if (rdip != NULL) 910*7c478bd9Sstevel@tonic-gate *rdip = cdip; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate if (dcp->cpyout_buf == NULL) 913*7c478bd9Sstevel@tonic-gate return (0); 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate ASSERT(ddi_node_name(cdip) != NULL); 916*7c478bd9Sstevel@tonic-gate ASSERT(ddi_get_name_addr(cdip) != NULL); 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 919*7c478bd9Sstevel@tonic-gate ddi_node_name(cdip), ddi_get_name_addr(cdip)); 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 0) { 922*7c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(cdip, NDI_DEVI_REMOVE); 923*7c478bd9Sstevel@tonic-gate return (EFAULT); 924*7c478bd9Sstevel@tonic-gate } 925*7c478bd9Sstevel@tonic-gate return (0); 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate static int 929*7c478bd9Sstevel@tonic-gate i_dc_devi_create(struct devctl_iocdata *dcp, dev_info_t *pdip, 930*7c478bd9Sstevel@tonic-gate dev_info_t **rdip) 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate dev_info_t *cdip; 934*7c478bd9Sstevel@tonic-gate char *cname = NULL; 935*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp = dcp->nvl_user; 936*7c478bd9Sstevel@tonic-gate nvpair_t *npp; 937*7c478bd9Sstevel@tonic-gate char *np; 938*7c478bd9Sstevel@tonic-gate int rv = 0; 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate ASSERT(rdip != NULL && *rdip == NULL); 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate if ((nvlp == NULL) || 943*7c478bd9Sstevel@tonic-gate (nvlist_lookup_string(nvlp, DC_DEVI_NODENAME, &cname) != 0)) 944*7c478bd9Sstevel@tonic-gate return (EINVAL); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate /* 947*7c478bd9Sstevel@tonic-gate * construct a new dev_info node with a user-provided nodename 948*7c478bd9Sstevel@tonic-gate */ 949*7c478bd9Sstevel@tonic-gate ndi_devi_alloc_sleep(pdip, cname, (dnode_t)DEVI_SID_NODEID, &cdip); 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate /* 952*7c478bd9Sstevel@tonic-gate * create hardware properties for each member in the property 953*7c478bd9Sstevel@tonic-gate * list. 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate for (npp = nvlist_next_nvpair(nvlp, NULL); (npp != NULL && !rv); 956*7c478bd9Sstevel@tonic-gate npp = nvlist_next_nvpair(nvlp, npp)) { 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate np = nvpair_name(npp); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate /* 961*7c478bd9Sstevel@tonic-gate * skip the nodename property 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate if (strcmp(np, DC_DEVI_NODENAME) == 0) 964*7c478bd9Sstevel@tonic-gate continue; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate switch (nvpair_type(npp)) { 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32: { 969*7c478bd9Sstevel@tonic-gate int32_t prop_val; 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate if ((rv = nvpair_value_int32(npp, &prop_val)) != 0) 972*7c478bd9Sstevel@tonic-gate break; 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip, np, 975*7c478bd9Sstevel@tonic-gate (int)prop_val); 976*7c478bd9Sstevel@tonic-gate break; 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING: { 980*7c478bd9Sstevel@tonic-gate char *prop_val; 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate if ((rv = nvpair_value_string(npp, &prop_val)) != 0) 983*7c478bd9Sstevel@tonic-gate break; 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate (void) ndi_prop_update_string(DDI_DEV_T_NONE, cdip, 986*7c478bd9Sstevel@tonic-gate np, prop_val); 987*7c478bd9Sstevel@tonic-gate break; 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate case DATA_TYPE_BYTE_ARRAY: { 991*7c478bd9Sstevel@tonic-gate uchar_t *val; 992*7c478bd9Sstevel@tonic-gate uint_t nelms; 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate if ((rv = nvpair_value_byte_array(npp, &val, 995*7c478bd9Sstevel@tonic-gate &nelms)) != 0) 996*7c478bd9Sstevel@tonic-gate break; 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 999*7c478bd9Sstevel@tonic-gate cdip, np, (uchar_t *)val, nelms); 1000*7c478bd9Sstevel@tonic-gate break; 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32_ARRAY: { 1004*7c478bd9Sstevel@tonic-gate int32_t *val; 1005*7c478bd9Sstevel@tonic-gate uint_t nelms; 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate if ((rv = nvpair_value_int32_array(npp, &val, 1008*7c478bd9Sstevel@tonic-gate &nelms)) != 0) 1009*7c478bd9Sstevel@tonic-gate break; 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 1012*7c478bd9Sstevel@tonic-gate cdip, np, val, nelms); 1013*7c478bd9Sstevel@tonic-gate break; 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING_ARRAY: { 1017*7c478bd9Sstevel@tonic-gate char **val; 1018*7c478bd9Sstevel@tonic-gate uint_t nelms; 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate if ((rv = nvpair_value_string_array(npp, &val, 1021*7c478bd9Sstevel@tonic-gate &nelms)) != 0) 1022*7c478bd9Sstevel@tonic-gate break; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, 1025*7c478bd9Sstevel@tonic-gate cdip, np, val, nelms); 1026*7c478bd9Sstevel@tonic-gate break; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate /* 1030*7c478bd9Sstevel@tonic-gate * unsupported property data type 1031*7c478bd9Sstevel@tonic-gate */ 1032*7c478bd9Sstevel@tonic-gate default: 1033*7c478bd9Sstevel@tonic-gate rv = EINVAL; 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate /* 1038*7c478bd9Sstevel@tonic-gate * something above failed 1039*7c478bd9Sstevel@tonic-gate * destroy the partially child device and abort the request 1040*7c478bd9Sstevel@tonic-gate */ 1041*7c478bd9Sstevel@tonic-gate if (rv != 0) { 1042*7c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 1043*7c478bd9Sstevel@tonic-gate return (rv); 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate *rdip = cdip; 1047*7c478bd9Sstevel@tonic-gate return (0); 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate /* 1051*7c478bd9Sstevel@tonic-gate * return current soft bus state of bus nexus "dip" 1052*7c478bd9Sstevel@tonic-gate */ 1053*7c478bd9Sstevel@tonic-gate int 1054*7c478bd9Sstevel@tonic-gate ndi_get_bus_state(dev_info_t *dip, uint_t *rstate) 1055*7c478bd9Sstevel@tonic-gate { 1056*7c478bd9Sstevel@tonic-gate if (dip == NULL || rstate == NULL) 1057*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate if (DEVI(dip)->devi_ops->devo_bus_ops == NULL) 1060*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate mutex_enter(&(DEVI(dip)->devi_lock)); 1063*7c478bd9Sstevel@tonic-gate if (DEVI_IS_BUS_QUIESCED(dip)) 1064*7c478bd9Sstevel@tonic-gate *rstate = BUS_QUIESCED; 1065*7c478bd9Sstevel@tonic-gate else if (DEVI_IS_BUS_DOWN(dip)) 1066*7c478bd9Sstevel@tonic-gate *rstate = BUS_SHUTDOWN; 1067*7c478bd9Sstevel@tonic-gate else 1068*7c478bd9Sstevel@tonic-gate *rstate = BUS_ACTIVE; 1069*7c478bd9Sstevel@tonic-gate mutex_exit(&(DEVI(dip)->devi_lock)); 1070*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate /* 1074*7c478bd9Sstevel@tonic-gate * Set the soft state of bus nexus "dip" 1075*7c478bd9Sstevel@tonic-gate */ 1076*7c478bd9Sstevel@tonic-gate int 1077*7c478bd9Sstevel@tonic-gate ndi_set_bus_state(dev_info_t *dip, uint_t state) 1078*7c478bd9Sstevel@tonic-gate { 1079*7c478bd9Sstevel@tonic-gate int rv = NDI_SUCCESS; 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate if (dip == NULL) 1082*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate mutex_enter(&(DEVI(dip)->devi_lock)); 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate switch (state) { 1087*7c478bd9Sstevel@tonic-gate case BUS_QUIESCED: 1088*7c478bd9Sstevel@tonic-gate DEVI_SET_BUS_QUIESCE(dip); 1089*7c478bd9Sstevel@tonic-gate break; 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate case BUS_ACTIVE: 1092*7c478bd9Sstevel@tonic-gate DEVI_SET_BUS_ACTIVE(dip); 1093*7c478bd9Sstevel@tonic-gate DEVI_SET_BUS_UP(dip); 1094*7c478bd9Sstevel@tonic-gate break; 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate case BUS_SHUTDOWN: 1097*7c478bd9Sstevel@tonic-gate DEVI_SET_BUS_DOWN(dip); 1098*7c478bd9Sstevel@tonic-gate break; 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate default: 1101*7c478bd9Sstevel@tonic-gate rv = NDI_FAILURE; 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate mutex_exit(&(DEVI(dip)->devi_lock)); 1105*7c478bd9Sstevel@tonic-gate return (rv); 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate /* 1109*7c478bd9Sstevel@tonic-gate * These dummy functions are obsolete and may be removed. 1110*7c478bd9Sstevel@tonic-gate * Retained for existing driver compatibility only. 1111*7c478bd9Sstevel@tonic-gate * Drivers should be fixed not to use these functions. 1112*7c478bd9Sstevel@tonic-gate * Don't write new code using these obsolete interfaces. 1113*7c478bd9Sstevel@tonic-gate */ 1114*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1115*7c478bd9Sstevel@tonic-gate void 1116*7c478bd9Sstevel@tonic-gate i_ndi_block_device_tree_changes(uint_t *lkcnt) /* obsolete */ 1117*7c478bd9Sstevel@tonic-gate { 1118*7c478bd9Sstevel@tonic-gate /* obsolete dummy function */ 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1122*7c478bd9Sstevel@tonic-gate void 1123*7c478bd9Sstevel@tonic-gate i_ndi_allow_device_tree_changes(uint_t lkcnt) /* obsolete */ 1124*7c478bd9Sstevel@tonic-gate { 1125*7c478bd9Sstevel@tonic-gate /* obsolete dummy function */ 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate /* 1129*7c478bd9Sstevel@tonic-gate * Single thread entry into per-driver list 1130*7c478bd9Sstevel@tonic-gate */ 1131*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1132*7c478bd9Sstevel@tonic-gate void 1133*7c478bd9Sstevel@tonic-gate e_ddi_enter_driver_list(struct devnames *dnp, int *listcnt) /* obsolete */ 1134*7c478bd9Sstevel@tonic-gate { 1135*7c478bd9Sstevel@tonic-gate /* obsolete dummy function */ 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate /* 1139*7c478bd9Sstevel@tonic-gate * release the per-driver list 1140*7c478bd9Sstevel@tonic-gate */ 1141*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1142*7c478bd9Sstevel@tonic-gate void 1143*7c478bd9Sstevel@tonic-gate e_ddi_exit_driver_list(struct devnames *dnp, int listcnt) /* obsolete */ 1144*7c478bd9Sstevel@tonic-gate { 1145*7c478bd9Sstevel@tonic-gate /* obsolete dummy function */ 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate /* 1149*7c478bd9Sstevel@tonic-gate * Attempt to enter driver list 1150*7c478bd9Sstevel@tonic-gate */ 1151*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1152*7c478bd9Sstevel@tonic-gate int 1153*7c478bd9Sstevel@tonic-gate e_ddi_tryenter_driver_list(struct devnames *dnp, int *listcnt) /* obsolete */ 1154*7c478bd9Sstevel@tonic-gate { 1155*7c478bd9Sstevel@tonic-gate return (1); /* obsolete dummy function */ 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate 1158*7c478bd9Sstevel@tonic-gate /* 1159*7c478bd9Sstevel@tonic-gate * ndi event handling support functions: 1160*7c478bd9Sstevel@tonic-gate * The NDI event support model is as follows: 1161*7c478bd9Sstevel@tonic-gate * 1162*7c478bd9Sstevel@tonic-gate * The nexus driver defines a set of events using some static structures (so 1163*7c478bd9Sstevel@tonic-gate * these structures can be shared by all instances of the nexus driver). 1164*7c478bd9Sstevel@tonic-gate * The nexus driver allocates an event handle and binds the event set 1165*7c478bd9Sstevel@tonic-gate * to this handle. The nexus driver's event busop functions can just 1166*7c478bd9Sstevel@tonic-gate * call the appropriate NDI event support function using this handle 1167*7c478bd9Sstevel@tonic-gate * as the first argument. 1168*7c478bd9Sstevel@tonic-gate * 1169*7c478bd9Sstevel@tonic-gate * The reasoning for tying events to the device tree is that the entity 1170*7c478bd9Sstevel@tonic-gate * generating the callback will typically be one of the device driver's 1171*7c478bd9Sstevel@tonic-gate * ancestors in the tree. 1172*7c478bd9Sstevel@tonic-gate */ 1173*7c478bd9Sstevel@tonic-gate static int ndi_event_debug = 0; 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1176*7c478bd9Sstevel@tonic-gate #define NDI_EVENT_DEBUG ndi_event_debug 1177*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate /* 1180*7c478bd9Sstevel@tonic-gate * allocate a new ndi event handle 1181*7c478bd9Sstevel@tonic-gate */ 1182*7c478bd9Sstevel@tonic-gate int 1183*7c478bd9Sstevel@tonic-gate ndi_event_alloc_hdl(dev_info_t *dip, ddi_iblock_cookie_t cookie, 1184*7c478bd9Sstevel@tonic-gate ndi_event_hdl_t *handle, uint_t flag) 1185*7c478bd9Sstevel@tonic-gate { 1186*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl; 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate ndi_event_hdl = kmem_zalloc(sizeof (struct ndi_event_hdl), 1189*7c478bd9Sstevel@tonic-gate ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP)); 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate if (!ndi_event_hdl) { 1192*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_dip = dip; 1196*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_iblock_cookie = cookie; 1197*7c478bd9Sstevel@tonic-gate mutex_init(&ndi_event_hdl->ndi_evthdl_mutex, NULL, 1198*7c478bd9Sstevel@tonic-gate MUTEX_DRIVER, (void *)cookie); 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate mutex_init(&ndi_event_hdl->ndi_evthdl_cb_mutex, NULL, 1201*7c478bd9Sstevel@tonic-gate MUTEX_DRIVER, (void *)cookie); 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate *handle = (ndi_event_hdl_t)ndi_event_hdl; 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1206*7c478bd9Sstevel@tonic-gate } 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate /* 1209*7c478bd9Sstevel@tonic-gate * free the ndi event handle 1210*7c478bd9Sstevel@tonic-gate */ 1211*7c478bd9Sstevel@tonic-gate int 1212*7c478bd9Sstevel@tonic-gate ndi_event_free_hdl(ndi_event_hdl_t handle) 1213*7c478bd9Sstevel@tonic-gate { 1214*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1215*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *cookie; 1216*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *free; 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate ASSERT(handle); 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1221*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate cookie = ndi_event_hdl->ndi_evthdl_cookie_list; 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate /* deallocate all defined cookies */ 1226*7c478bd9Sstevel@tonic-gate while (cookie != NULL) { 1227*7c478bd9Sstevel@tonic-gate ASSERT(cookie->callback_list == NULL); 1228*7c478bd9Sstevel@tonic-gate free = cookie; 1229*7c478bd9Sstevel@tonic-gate cookie = cookie->next_cookie; 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate kmem_free(free, sizeof (ndi_event_cookie_t)); 1232*7c478bd9Sstevel@tonic-gate } 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1236*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate /* destroy mutexes */ 1239*7c478bd9Sstevel@tonic-gate mutex_destroy(&ndi_event_hdl->ndi_evthdl_mutex); 1240*7c478bd9Sstevel@tonic-gate mutex_destroy(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* free event handle */ 1243*7c478bd9Sstevel@tonic-gate kmem_free(ndi_event_hdl, sizeof (struct ndi_event_hdl)); 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate /* 1250*7c478bd9Sstevel@tonic-gate * ndi_event_bind_set() adds a set of events to the NDI event 1251*7c478bd9Sstevel@tonic-gate * handle. 1252*7c478bd9Sstevel@tonic-gate * 1253*7c478bd9Sstevel@tonic-gate * Events generated by high level interrupts should not 1254*7c478bd9Sstevel@tonic-gate * be mixed in the same event set with events generated by 1255*7c478bd9Sstevel@tonic-gate * normal interrupts or kernel events. 1256*7c478bd9Sstevel@tonic-gate * 1257*7c478bd9Sstevel@tonic-gate * This function can be called multiple times to bind 1258*7c478bd9Sstevel@tonic-gate * additional sets to the event handle. 1259*7c478bd9Sstevel@tonic-gate * However, events generated by high level interrupts cannot 1260*7c478bd9Sstevel@tonic-gate * be bound to a handle that already has bound events generated 1261*7c478bd9Sstevel@tonic-gate * by normal interrupts or from kernel context and vice versa. 1262*7c478bd9Sstevel@tonic-gate */ 1263*7c478bd9Sstevel@tonic-gate int 1264*7c478bd9Sstevel@tonic-gate ndi_event_bind_set(ndi_event_hdl_t handle, 1265*7c478bd9Sstevel@tonic-gate ndi_event_set_t *ndi_events, 1266*7c478bd9Sstevel@tonic-gate uint_t flag) 1267*7c478bd9Sstevel@tonic-gate { 1268*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl; 1269*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *next, *prev, *new_cookie; 1270*7c478bd9Sstevel@tonic-gate uint_t i, len; 1271*7c478bd9Sstevel@tonic-gate uint_t dup = 0; 1272*7c478bd9Sstevel@tonic-gate uint_t high_plevels, other_plevels; 1273*7c478bd9Sstevel@tonic-gate ndi_event_definition_t *ndi_event_defs; 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate int km_flag = ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP); 1276*7c478bd9Sstevel@tonic-gate 1277*7c478bd9Sstevel@tonic-gate ASSERT(handle); 1278*7c478bd9Sstevel@tonic-gate ASSERT(ndi_events); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate /* 1281*7c478bd9Sstevel@tonic-gate * binding must be performed during attach/detach 1282*7c478bd9Sstevel@tonic-gate */ 1283*7c478bd9Sstevel@tonic-gate if (!DEVI_IS_ATTACHING(handle->ndi_evthdl_dip) && 1284*7c478bd9Sstevel@tonic-gate !DEVI_IS_DETACHING(handle->ndi_evthdl_dip)) { 1285*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ndi_event_bind_set must be called within " 1286*7c478bd9Sstevel@tonic-gate "attach or detach"); 1287*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* 1291*7c478bd9Sstevel@tonic-gate * if it is not the correct version or the event set is 1292*7c478bd9Sstevel@tonic-gate * empty, bail out 1293*7c478bd9Sstevel@tonic-gate */ 1294*7c478bd9Sstevel@tonic-gate if (ndi_events->ndi_events_version != NDI_EVENTS_REV1) 1295*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate ndi_event_hdl = (struct ndi_event_hdl *)handle; 1298*7c478bd9Sstevel@tonic-gate ndi_event_defs = ndi_events->ndi_event_defs; 1299*7c478bd9Sstevel@tonic-gate high_plevels = other_plevels = 0; 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1302*7c478bd9Sstevel@tonic-gate 1303*7c478bd9Sstevel@tonic-gate /* check for mixing events at high level with the other types */ 1304*7c478bd9Sstevel@tonic-gate for (i = 0; i < ndi_events->ndi_n_events; i++) { 1305*7c478bd9Sstevel@tonic-gate if (ndi_event_defs[i].ndi_event_plevel == EPL_HIGHLEVEL) { 1306*7c478bd9Sstevel@tonic-gate high_plevels++; 1307*7c478bd9Sstevel@tonic-gate } else { 1308*7c478bd9Sstevel@tonic-gate other_plevels++; 1309*7c478bd9Sstevel@tonic-gate } 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate /* 1313*7c478bd9Sstevel@tonic-gate * bail out if high level events are mixed with other types in this 1314*7c478bd9Sstevel@tonic-gate * event set or the set is incompatible with the set in the handle 1315*7c478bd9Sstevel@tonic-gate */ 1316*7c478bd9Sstevel@tonic-gate if ((high_plevels && other_plevels) || 1317*7c478bd9Sstevel@tonic-gate (other_plevels && ndi_event_hdl->ndi_evthdl_high_plevels) || 1318*7c478bd9Sstevel@tonic-gate (high_plevels && ndi_event_hdl->ndi_evthdl_other_plevels)) { 1319*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1320*7c478bd9Sstevel@tonic-gate 1321*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate /* 1325*7c478bd9Sstevel@tonic-gate * check for duplicate events in both the existing handle 1326*7c478bd9Sstevel@tonic-gate * and the event set, add events if not duplicates 1327*7c478bd9Sstevel@tonic-gate */ 1328*7c478bd9Sstevel@tonic-gate next = ndi_event_hdl->ndi_evthdl_cookie_list; 1329*7c478bd9Sstevel@tonic-gate for (i = 0; i < ndi_events->ndi_n_events; i++) { 1330*7c478bd9Sstevel@tonic-gate while (next != NULL) { 1331*7c478bd9Sstevel@tonic-gate len = strlen(NDI_EVENT_NAME(next)) + 1; 1332*7c478bd9Sstevel@tonic-gate if (strncmp(NDI_EVENT_NAME(next), 1333*7c478bd9Sstevel@tonic-gate ndi_event_defs[i].ndi_event_name, len) == 0) { 1334*7c478bd9Sstevel@tonic-gate dup = 1; 1335*7c478bd9Sstevel@tonic-gate break; 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate prev = next; 1339*7c478bd9Sstevel@tonic-gate next = next->next_cookie; 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate if (dup == 0) { 1343*7c478bd9Sstevel@tonic-gate new_cookie = kmem_zalloc(sizeof (ndi_event_cookie_t), 1344*7c478bd9Sstevel@tonic-gate km_flag); 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate if (!new_cookie) 1347*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate if (ndi_event_hdl->ndi_evthdl_n_events == 0) { 1350*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_cookie_list = 1351*7c478bd9Sstevel@tonic-gate new_cookie; 1352*7c478bd9Sstevel@tonic-gate } else { 1353*7c478bd9Sstevel@tonic-gate prev->next_cookie = new_cookie; 1354*7c478bd9Sstevel@tonic-gate } 1355*7c478bd9Sstevel@tonic-gate 1356*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_n_events++; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate /* 1359*7c478bd9Sstevel@tonic-gate * set up new cookie 1360*7c478bd9Sstevel@tonic-gate */ 1361*7c478bd9Sstevel@tonic-gate new_cookie->definition = &ndi_event_defs[i]; 1362*7c478bd9Sstevel@tonic-gate new_cookie->ddip = ndi_event_hdl->ndi_evthdl_dip; 1363*7c478bd9Sstevel@tonic-gate 1364*7c478bd9Sstevel@tonic-gate } else { 1365*7c478bd9Sstevel@tonic-gate /* 1366*7c478bd9Sstevel@tonic-gate * event not added, must correct plevel numbers 1367*7c478bd9Sstevel@tonic-gate */ 1368*7c478bd9Sstevel@tonic-gate if (ndi_event_defs[i].ndi_event_plevel == 1369*7c478bd9Sstevel@tonic-gate EPL_HIGHLEVEL) { 1370*7c478bd9Sstevel@tonic-gate high_plevels--; 1371*7c478bd9Sstevel@tonic-gate } else { 1372*7c478bd9Sstevel@tonic-gate other_plevels--; 1373*7c478bd9Sstevel@tonic-gate } 1374*7c478bd9Sstevel@tonic-gate } 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate dup = 0; 1377*7c478bd9Sstevel@tonic-gate next = ndi_event_hdl->ndi_evthdl_cookie_list; 1378*7c478bd9Sstevel@tonic-gate prev = NULL; 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_high_plevels += high_plevels; 1383*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_other_plevels += other_plevels; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate ASSERT((ndi_event_hdl->ndi_evthdl_high_plevels == 0) || 1386*7c478bd9Sstevel@tonic-gate (ndi_event_hdl->ndi_evthdl_other_plevels == 0)); 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1389*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1390*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(ndi_event_hdl, "ndi_event_bind_set"); 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate #endif /* NDI_EVENT_DEBUG */ 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate /* 1400*7c478bd9Sstevel@tonic-gate * ndi_event_unbind_set() unbinds a set of events, previously 1401*7c478bd9Sstevel@tonic-gate * bound using ndi_event_bind_set(), from the NDI event 1402*7c478bd9Sstevel@tonic-gate * handle. 1403*7c478bd9Sstevel@tonic-gate * 1404*7c478bd9Sstevel@tonic-gate * This routine will unbind all events in the event set. If an event, 1405*7c478bd9Sstevel@tonic-gate * specified in the event set, is not found in the handle, this 1406*7c478bd9Sstevel@tonic-gate * routine will proceed onto the next member of the set as if the event 1407*7c478bd9Sstevel@tonic-gate * was never specified. 1408*7c478bd9Sstevel@tonic-gate * 1409*7c478bd9Sstevel@tonic-gate * The event set may be a subset of the set of events that 1410*7c478bd9Sstevel@tonic-gate * was previously bound to the handle. For example, events 1411*7c478bd9Sstevel@tonic-gate * can be individually unbound. 1412*7c478bd9Sstevel@tonic-gate * 1413*7c478bd9Sstevel@tonic-gate * An event cannot be unbound if callbacks are still 1414*7c478bd9Sstevel@tonic-gate * registered against the event. 1415*7c478bd9Sstevel@tonic-gate */ 1416*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1417*7c478bd9Sstevel@tonic-gate int 1418*7c478bd9Sstevel@tonic-gate ndi_event_unbind_set(ndi_event_hdl_t handle, ndi_event_set_t *ndi_events, 1419*7c478bd9Sstevel@tonic-gate uint_t flag) 1420*7c478bd9Sstevel@tonic-gate { 1421*7c478bd9Sstevel@tonic-gate ndi_event_definition_t *ndi_event_defs; 1422*7c478bd9Sstevel@tonic-gate int len; 1423*7c478bd9Sstevel@tonic-gate uint_t i; 1424*7c478bd9Sstevel@tonic-gate int rval; 1425*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *cookie_list; 1426*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *prev = NULL; 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate ASSERT(ndi_events); 1429*7c478bd9Sstevel@tonic-gate ASSERT(handle); 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate /* 1432*7c478bd9Sstevel@tonic-gate * binding must be performed during attach/detac 1433*7c478bd9Sstevel@tonic-gate */ 1434*7c478bd9Sstevel@tonic-gate if (!DEVI_IS_ATTACHING(handle->ndi_evthdl_dip) && 1435*7c478bd9Sstevel@tonic-gate !DEVI_IS_DETACHING(handle->ndi_evthdl_dip)) { 1436*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ndi_event_bind_set must be called within " 1437*7c478bd9Sstevel@tonic-gate "attach or detach"); 1438*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1439*7c478bd9Sstevel@tonic-gate } 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate /* bail out if ndi_event_set is outdated */ 1442*7c478bd9Sstevel@tonic-gate if (ndi_events->ndi_events_version != NDI_EVENTS_REV1) { 1443*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1444*7c478bd9Sstevel@tonic-gate } 1445*7c478bd9Sstevel@tonic-gate 1446*7c478bd9Sstevel@tonic-gate ASSERT(ndi_events->ndi_event_defs); 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate ndi_event_defs = ndi_events->ndi_event_defs; 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate mutex_enter(&handle->ndi_evthdl_mutex); 1451*7c478bd9Sstevel@tonic-gate mutex_enter(&handle->ndi_evthdl_cb_mutex); 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate /* 1454*7c478bd9Sstevel@tonic-gate * Verify that all events in the event set are eligible 1455*7c478bd9Sstevel@tonic-gate * for unbinding(ie. there are no outstanding callbacks). 1456*7c478bd9Sstevel@tonic-gate * If any one of the events are ineligible, fail entire 1457*7c478bd9Sstevel@tonic-gate * operation. 1458*7c478bd9Sstevel@tonic-gate */ 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate for (i = 0; i < ndi_events->ndi_n_events; i++) { 1461*7c478bd9Sstevel@tonic-gate cookie_list = handle->ndi_evthdl_cookie_list; 1462*7c478bd9Sstevel@tonic-gate while (cookie_list != NULL) { 1463*7c478bd9Sstevel@tonic-gate len = strlen(NDI_EVENT_NAME(cookie_list)) + 1; 1464*7c478bd9Sstevel@tonic-gate if (strncmp(NDI_EVENT_NAME(cookie_list), 1465*7c478bd9Sstevel@tonic-gate ndi_event_defs[i].ndi_event_name, len) == 0) { 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate ASSERT(cookie_list->callback_list == NULL); 1468*7c478bd9Sstevel@tonic-gate if (cookie_list->callback_list) { 1469*7c478bd9Sstevel@tonic-gate rval = NDI_FAILURE; 1470*7c478bd9Sstevel@tonic-gate goto done; 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate break; 1473*7c478bd9Sstevel@tonic-gate } else { 1474*7c478bd9Sstevel@tonic-gate cookie_list = cookie_list->next_cookie; 1475*7c478bd9Sstevel@tonic-gate } 1476*7c478bd9Sstevel@tonic-gate } 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate /* 1480*7c478bd9Sstevel@tonic-gate * remove all events found within the handle 1481*7c478bd9Sstevel@tonic-gate * If an event is not found, this function will proceed as if the event 1482*7c478bd9Sstevel@tonic-gate * was never specified. 1483*7c478bd9Sstevel@tonic-gate */ 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate for (i = 0; i < ndi_events->ndi_n_events; i++) { 1486*7c478bd9Sstevel@tonic-gate cookie_list = handle->ndi_evthdl_cookie_list; 1487*7c478bd9Sstevel@tonic-gate prev = NULL; 1488*7c478bd9Sstevel@tonic-gate while (cookie_list != NULL) { 1489*7c478bd9Sstevel@tonic-gate len = strlen(NDI_EVENT_NAME(cookie_list)) + 1; 1490*7c478bd9Sstevel@tonic-gate if (strncmp(NDI_EVENT_NAME(cookie_list), 1491*7c478bd9Sstevel@tonic-gate ndi_event_defs[i].ndi_event_name, len) == 0) { 1492*7c478bd9Sstevel@tonic-gate 1493*7c478bd9Sstevel@tonic-gate /* 1494*7c478bd9Sstevel@tonic-gate * can not unbind an event definition with 1495*7c478bd9Sstevel@tonic-gate * outstanding callbacks 1496*7c478bd9Sstevel@tonic-gate */ 1497*7c478bd9Sstevel@tonic-gate if (cookie_list->callback_list) { 1498*7c478bd9Sstevel@tonic-gate rval = NDI_FAILURE; 1499*7c478bd9Sstevel@tonic-gate goto done; 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate 1502*7c478bd9Sstevel@tonic-gate /* remove this cookie from the list */ 1503*7c478bd9Sstevel@tonic-gate if (prev != NULL) { 1504*7c478bd9Sstevel@tonic-gate prev->next_cookie = 1505*7c478bd9Sstevel@tonic-gate cookie_list->next_cookie; 1506*7c478bd9Sstevel@tonic-gate } else { 1507*7c478bd9Sstevel@tonic-gate handle->ndi_evthdl_cookie_list = 1508*7c478bd9Sstevel@tonic-gate cookie_list->next_cookie; 1509*7c478bd9Sstevel@tonic-gate } 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate /* adjust plevel counts */ 1512*7c478bd9Sstevel@tonic-gate if (NDI_EVENT_PLEVEL(cookie_list) == 1513*7c478bd9Sstevel@tonic-gate EPL_HIGHLEVEL) { 1514*7c478bd9Sstevel@tonic-gate handle->ndi_evthdl_high_plevels--; 1515*7c478bd9Sstevel@tonic-gate } else { 1516*7c478bd9Sstevel@tonic-gate handle->ndi_evthdl_other_plevels--; 1517*7c478bd9Sstevel@tonic-gate } 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate /* adjust cookie count */ 1520*7c478bd9Sstevel@tonic-gate handle->ndi_evthdl_n_events--; 1521*7c478bd9Sstevel@tonic-gate 1522*7c478bd9Sstevel@tonic-gate /* free the cookie */ 1523*7c478bd9Sstevel@tonic-gate kmem_free(cookie_list, 1524*7c478bd9Sstevel@tonic-gate sizeof (ndi_event_cookie_t)); 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate cookie_list = handle->ndi_evthdl_cookie_list; 1527*7c478bd9Sstevel@tonic-gate break; 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate } else { 1530*7c478bd9Sstevel@tonic-gate prev = cookie_list; 1531*7c478bd9Sstevel@tonic-gate cookie_list = cookie_list->next_cookie; 1532*7c478bd9Sstevel@tonic-gate } 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate } 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1539*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1540*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(handle, "ndi_event_unbind_set"); 1541*7c478bd9Sstevel@tonic-gate } 1542*7c478bd9Sstevel@tonic-gate #endif /* NDI_EVENT_DEBUG */ 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate rval = NDI_SUCCESS; 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate done: 1547*7c478bd9Sstevel@tonic-gate mutex_exit(&handle->ndi_evthdl_cb_mutex); 1548*7c478bd9Sstevel@tonic-gate mutex_exit(&handle->ndi_evthdl_mutex); 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate return (rval); 1551*7c478bd9Sstevel@tonic-gate } 1552*7c478bd9Sstevel@tonic-gate 1553*7c478bd9Sstevel@tonic-gate /* 1554*7c478bd9Sstevel@tonic-gate * ndi_event_retrieve_cookie(): 1555*7c478bd9Sstevel@tonic-gate * Return an event cookie for eventname if this nexus driver 1556*7c478bd9Sstevel@tonic-gate * has defined the named event. The event cookie returned 1557*7c478bd9Sstevel@tonic-gate * by this function is used to register callback handlers 1558*7c478bd9Sstevel@tonic-gate * for the event. 1559*7c478bd9Sstevel@tonic-gate * 1560*7c478bd9Sstevel@tonic-gate * ndi_event_retrieve_cookie() is intended to be used in the 1561*7c478bd9Sstevel@tonic-gate * nexus driver's bus_get_eventcookie busop routine. 1562*7c478bd9Sstevel@tonic-gate * 1563*7c478bd9Sstevel@tonic-gate * If the event is not defined by this bus nexus driver, and flag 1564*7c478bd9Sstevel@tonic-gate * does not include NDI_EVENT_NOPASS, then ndi_event_retrieve_cookie() 1565*7c478bd9Sstevel@tonic-gate * will pass the request up the device tree hierarchy by calling 1566*7c478bd9Sstevel@tonic-gate * ndi_busop_get_eventcookie(9N). 1567*7c478bd9Sstevel@tonic-gate * If the event is not defined by this bus nexus driver, and flag 1568*7c478bd9Sstevel@tonic-gate * does include NDI_EVENT_NOPASS, ndi_event_retrieve_cookie() 1569*7c478bd9Sstevel@tonic-gate * will return NDI_FAILURE. The caller may then determine what further 1570*7c478bd9Sstevel@tonic-gate * action to take, such as using a different handle, passing the 1571*7c478bd9Sstevel@tonic-gate * request up the device tree using ndi_busop_get_eventcookie(9N), 1572*7c478bd9Sstevel@tonic-gate * or returning the failure to the caller, thus blocking the 1573*7c478bd9Sstevel@tonic-gate * progress of the request up the tree. 1574*7c478bd9Sstevel@tonic-gate */ 1575*7c478bd9Sstevel@tonic-gate int 1576*7c478bd9Sstevel@tonic-gate ndi_event_retrieve_cookie(ndi_event_hdl_t handle, 1577*7c478bd9Sstevel@tonic-gate dev_info_t *rdip, 1578*7c478bd9Sstevel@tonic-gate char *eventname, 1579*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t *cookiep, 1580*7c478bd9Sstevel@tonic-gate uint_t flag) 1581*7c478bd9Sstevel@tonic-gate { 1582*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1583*7c478bd9Sstevel@tonic-gate int len; 1584*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *cookie_list; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1587*7c478bd9Sstevel@tonic-gate 1588*7c478bd9Sstevel@tonic-gate cookie_list = ndi_event_hdl->ndi_evthdl_cookie_list; 1589*7c478bd9Sstevel@tonic-gate /* 1590*7c478bd9Sstevel@tonic-gate * search the cookie list for the event name and return 1591*7c478bd9Sstevel@tonic-gate * cookie if found. 1592*7c478bd9Sstevel@tonic-gate */ 1593*7c478bd9Sstevel@tonic-gate while (cookie_list != NULL) { 1594*7c478bd9Sstevel@tonic-gate 1595*7c478bd9Sstevel@tonic-gate len = strlen(NDI_EVENT_NAME(cookie_list)) + 1; 1596*7c478bd9Sstevel@tonic-gate if (strncmp(NDI_EVENT_NAME(cookie_list), eventname, 1597*7c478bd9Sstevel@tonic-gate len) == 0) { 1598*7c478bd9Sstevel@tonic-gate *cookiep = (ddi_eventcookie_t)cookie_list; 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1601*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1602*7c478bd9Sstevel@tonic-gate } 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate cookie_list = cookie_list->next_cookie; 1605*7c478bd9Sstevel@tonic-gate } 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1608*7c478bd9Sstevel@tonic-gate /* 1609*7c478bd9Sstevel@tonic-gate * event was not found, pass up or return failure 1610*7c478bd9Sstevel@tonic-gate */ 1611*7c478bd9Sstevel@tonic-gate if ((flag & NDI_EVENT_NOPASS) == 0) { 1612*7c478bd9Sstevel@tonic-gate return (ndi_busop_get_eventcookie( 1613*7c478bd9Sstevel@tonic-gate ndi_event_hdl->ndi_evthdl_dip, rdip, 1614*7c478bd9Sstevel@tonic-gate eventname, cookiep)); 1615*7c478bd9Sstevel@tonic-gate } else { 1616*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1617*7c478bd9Sstevel@tonic-gate } 1618*7c478bd9Sstevel@tonic-gate } 1619*7c478bd9Sstevel@tonic-gate 1620*7c478bd9Sstevel@tonic-gate /* 1621*7c478bd9Sstevel@tonic-gate * check whether this nexus defined this event and look up attributes 1622*7c478bd9Sstevel@tonic-gate */ 1623*7c478bd9Sstevel@tonic-gate static int 1624*7c478bd9Sstevel@tonic-gate ndi_event_is_defined(ndi_event_hdl_t handle, 1625*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, int *attributes) 1626*7c478bd9Sstevel@tonic-gate { 1627*7c478bd9Sstevel@tonic-gate 1628*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1629*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *cookie_list; 1630*7c478bd9Sstevel@tonic-gate 1631*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&handle->ndi_evthdl_mutex)); 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate cookie_list = ndi_event_hdl->ndi_evthdl_cookie_list; 1634*7c478bd9Sstevel@tonic-gate while (cookie_list != NULL) { 1635*7c478bd9Sstevel@tonic-gate if (cookie_list == NDI_EVENT(cookie)) { 1636*7c478bd9Sstevel@tonic-gate if (attributes) 1637*7c478bd9Sstevel@tonic-gate *attributes = 1638*7c478bd9Sstevel@tonic-gate NDI_EVENT_ATTRIBUTES(cookie_list); 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1641*7c478bd9Sstevel@tonic-gate } 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate cookie_list = cookie_list->next_cookie; 1644*7c478bd9Sstevel@tonic-gate } 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1647*7c478bd9Sstevel@tonic-gate } 1648*7c478bd9Sstevel@tonic-gate 1649*7c478bd9Sstevel@tonic-gate /* 1650*7c478bd9Sstevel@tonic-gate * ndi_event_add_callback(): adds an event callback registration 1651*7c478bd9Sstevel@tonic-gate * to the event cookie defining this event. 1652*7c478bd9Sstevel@tonic-gate * 1653*7c478bd9Sstevel@tonic-gate * Refer also to bus_add_eventcall(9n) and ndi_busop_add_eventcall(9n). 1654*7c478bd9Sstevel@tonic-gate * 1655*7c478bd9Sstevel@tonic-gate * ndi_event_add_callback(9n) is intended to be used in 1656*7c478bd9Sstevel@tonic-gate * the nexus driver's bus_add_eventcall(9n) busop function. 1657*7c478bd9Sstevel@tonic-gate * 1658*7c478bd9Sstevel@tonic-gate * If the event is not defined by this bus nexus driver, 1659*7c478bd9Sstevel@tonic-gate * ndi_event_add_callback() will return NDI_FAILURE. 1660*7c478bd9Sstevel@tonic-gate */ 1661*7c478bd9Sstevel@tonic-gate int 1662*7c478bd9Sstevel@tonic-gate ndi_event_add_callback(ndi_event_hdl_t handle, dev_info_t *child_dip, 1663*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, 1664*7c478bd9Sstevel@tonic-gate void (*event_callback)(dev_info_t *, 1665*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t, void *arg, void *impldata), 1666*7c478bd9Sstevel@tonic-gate void *arg, 1667*7c478bd9Sstevel@tonic-gate uint_t flag, 1668*7c478bd9Sstevel@tonic-gate ddi_callback_id_t *cb_id) 1669*7c478bd9Sstevel@tonic-gate { 1670*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1671*7c478bd9Sstevel@tonic-gate int km_flag = ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP); 1672*7c478bd9Sstevel@tonic-gate ndi_event_callbacks_t *cb; 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1675*7c478bd9Sstevel@tonic-gate 1676*7c478bd9Sstevel@tonic-gate /* 1677*7c478bd9Sstevel@tonic-gate * if the event was not bound to this handle, return failure 1678*7c478bd9Sstevel@tonic-gate */ 1679*7c478bd9Sstevel@tonic-gate if (ndi_event_is_defined(handle, cookie, NULL) != NDI_SUCCESS) { 1680*7c478bd9Sstevel@tonic-gate 1681*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1682*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1687*7c478bd9Sstevel@tonic-gate 1688*7c478bd9Sstevel@tonic-gate /* 1689*7c478bd9Sstevel@tonic-gate * allocate space for a callback structure 1690*7c478bd9Sstevel@tonic-gate */ 1691*7c478bd9Sstevel@tonic-gate cb = kmem_zalloc(sizeof (ndi_event_callbacks_t), km_flag); 1692*7c478bd9Sstevel@tonic-gate if (cb == NULL) { 1693*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate /* initialize callback structure */ 1699*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_dip = child_dip; 1700*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_callback = event_callback; 1701*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_arg = arg; 1702*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_cookie = cookie; 1703*7c478bd9Sstevel@tonic-gate cb->devname = (char *)ddi_driver_name(child_dip); 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate *cb_id = (ddi_callback_id_t)cb; 1706*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate /* add this callback structure to the list */ 1709*7c478bd9Sstevel@tonic-gate if (NDI_EVENT(cookie)->callback_list) { 1710*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_next = NDI_EVENT(cookie)->callback_list; 1711*7c478bd9Sstevel@tonic-gate NDI_EVENT(cookie)->callback_list->ndi_evtcb_prev = cb; 1712*7c478bd9Sstevel@tonic-gate NDI_EVENT(cookie)->callback_list = cb; 1713*7c478bd9Sstevel@tonic-gate } else { 1714*7c478bd9Sstevel@tonic-gate NDI_EVENT(cookie)->callback_list = cb; 1715*7c478bd9Sstevel@tonic-gate } 1716*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1717*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1718*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(ndi_event_hdl, "ndi_event_add_callback"); 1719*7c478bd9Sstevel@tonic-gate } 1720*7c478bd9Sstevel@tonic-gate #endif /* NDI_EVENT_DEBUG */ 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1723*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1726*7c478bd9Sstevel@tonic-gate } 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate /* 1729*7c478bd9Sstevel@tonic-gate * ndi_event_remove_callback(): 1730*7c478bd9Sstevel@tonic-gate * 1731*7c478bd9Sstevel@tonic-gate * ndi_event_remove_callback() removes a callback that was 1732*7c478bd9Sstevel@tonic-gate * previously registered using ndi_event_add_callback(9N). 1733*7c478bd9Sstevel@tonic-gate * Refer also to bus_remove_eventcall(9n) and 1734*7c478bd9Sstevel@tonic-gate * ndi_busop_remove_eventcall(9n). 1735*7c478bd9Sstevel@tonic-gate * ndi_event_remove_callback(9n) is intended to be used in 1736*7c478bd9Sstevel@tonic-gate * the nexus driver's bus_remove_eventcall (9n) busop function. 1737*7c478bd9Sstevel@tonic-gate * If the event is not defined by this bus nexus driver, 1738*7c478bd9Sstevel@tonic-gate * ndi_event_remove_callback() will return NDI_FAILURE. 1739*7c478bd9Sstevel@tonic-gate */ 1740*7c478bd9Sstevel@tonic-gate static void do_ndi_event_remove_callback(struct ndi_event_hdl *ndi_event_hdl, 1741*7c478bd9Sstevel@tonic-gate ddi_callback_id_t cb_id); 1742*7c478bd9Sstevel@tonic-gate 1743*7c478bd9Sstevel@tonic-gate int 1744*7c478bd9Sstevel@tonic-gate ndi_event_remove_callback(ndi_event_hdl_t handle, ddi_callback_id_t cb_id) 1745*7c478bd9Sstevel@tonic-gate { 1746*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate ASSERT(cb_id); 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1751*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate do_ndi_event_remove_callback(ndi_event_hdl, cb_id); 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1756*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1759*7c478bd9Sstevel@tonic-gate } 1760*7c478bd9Sstevel@tonic-gate 1761*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1762*7c478bd9Sstevel@tonic-gate static void 1763*7c478bd9Sstevel@tonic-gate do_ndi_event_remove_callback(struct ndi_event_hdl *ndi_event_hdl, 1764*7c478bd9Sstevel@tonic-gate ddi_callback_id_t cb_id) 1765*7c478bd9Sstevel@tonic-gate { 1766*7c478bd9Sstevel@tonic-gate ndi_event_callbacks_t *cb = (ndi_event_callbacks_t *)cb_id; 1767*7c478bd9Sstevel@tonic-gate ASSERT(cb); 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&ndi_event_hdl->ndi_evthdl_mutex)); 1770*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&ndi_event_hdl->ndi_evthdl_cb_mutex)); 1771*7c478bd9Sstevel@tonic-gate 1772*7c478bd9Sstevel@tonic-gate /* remove from callback linked list */ 1773*7c478bd9Sstevel@tonic-gate if (cb->ndi_evtcb_prev) { 1774*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_prev->ndi_evtcb_next = cb->ndi_evtcb_next; 1775*7c478bd9Sstevel@tonic-gate } 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate if (cb->ndi_evtcb_next) { 1778*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_next->ndi_evtcb_prev = cb->ndi_evtcb_prev; 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate if (NDI_EVENT(cb->ndi_evtcb_cookie)->callback_list == cb) { 1782*7c478bd9Sstevel@tonic-gate NDI_EVENT(cb->ndi_evtcb_cookie)->callback_list = 1783*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_next; 1784*7c478bd9Sstevel@tonic-gate } 1785*7c478bd9Sstevel@tonic-gate 1786*7c478bd9Sstevel@tonic-gate kmem_free(cb, sizeof (ndi_event_callbacks_t)); 1787*7c478bd9Sstevel@tonic-gate } 1788*7c478bd9Sstevel@tonic-gate 1789*7c478bd9Sstevel@tonic-gate /* 1790*7c478bd9Sstevel@tonic-gate * ndi_event_run_callbacks() performs event callbacks for the event 1791*7c478bd9Sstevel@tonic-gate * specified by cookie, if this is among those bound to the 1792*7c478bd9Sstevel@tonic-gate * supplied handle. 1793*7c478bd9Sstevel@tonic-gate * If the event is among those bound to the handle, none, 1794*7c478bd9Sstevel@tonic-gate * some, or all of the handlers registered for the event 1795*7c478bd9Sstevel@tonic-gate * will be called, according to the delivery attributes of 1796*7c478bd9Sstevel@tonic-gate * the event. 1797*7c478bd9Sstevel@tonic-gate * If the event attributes include NDI_EVENT_POST_TO_ALL 1798*7c478bd9Sstevel@tonic-gate * (the default), all the handlers for the event will be 1799*7c478bd9Sstevel@tonic-gate * called in an unspecified order. 1800*7c478bd9Sstevel@tonic-gate * If the event attributes include NDI_EVENT_POST_TO_TGT, only 1801*7c478bd9Sstevel@tonic-gate * the handlers (if any) registered by the driver identified by 1802*7c478bd9Sstevel@tonic-gate * rdip will be called. 1803*7c478bd9Sstevel@tonic-gate * If the event identified by cookie is not bound to the handle, 1804*7c478bd9Sstevel@tonic-gate * NDI_FAILURE will be returned. 1805*7c478bd9Sstevel@tonic-gate */ 1806*7c478bd9Sstevel@tonic-gate int 1807*7c478bd9Sstevel@tonic-gate ndi_event_run_callbacks(ndi_event_hdl_t handle, dev_info_t *child_dip, 1808*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, void *bus_impldata) 1809*7c478bd9Sstevel@tonic-gate { 1810*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1811*7c478bd9Sstevel@tonic-gate ndi_event_callbacks_t *next, *cb; 1812*7c478bd9Sstevel@tonic-gate int attributes; 1813*7c478bd9Sstevel@tonic-gate 1814*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate /* if this is not our event, fail */ 1817*7c478bd9Sstevel@tonic-gate if (ndi_event_is_defined(handle, cookie, &attributes) != 1818*7c478bd9Sstevel@tonic-gate NDI_SUCCESS) { 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1821*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1822*7c478bd9Sstevel@tonic-gate } 1823*7c478bd9Sstevel@tonic-gate 1824*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1825*7c478bd9Sstevel@tonic-gate 1826*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1827*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1828*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ndi_event_run_callbacks:\n\t" 1829*7c478bd9Sstevel@tonic-gate "producer dip=%p (%s%d): cookie = %p, name = %s\n", 1830*7c478bd9Sstevel@tonic-gate (void *)ndi_event_hdl->ndi_evthdl_dip, 1831*7c478bd9Sstevel@tonic-gate ddi_node_name(ndi_event_hdl->ndi_evthdl_dip), 1832*7c478bd9Sstevel@tonic-gate ddi_get_instance(ndi_event_hdl->ndi_evthdl_dip), 1833*7c478bd9Sstevel@tonic-gate (void *)cookie, 1834*7c478bd9Sstevel@tonic-gate ndi_event_cookie_to_name(handle, cookie)); 1835*7c478bd9Sstevel@tonic-gate } 1836*7c478bd9Sstevel@tonic-gate #endif /* #ifdef NDI_EVENT_DEBUG */ 1837*7c478bd9Sstevel@tonic-gate 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate /* 1840*7c478bd9Sstevel@tonic-gate * The callback handlers may call conversion functions. The conversion 1841*7c478bd9Sstevel@tonic-gate * functions may hold the ndi_evthdl_mutex during execution. Thus, to 1842*7c478bd9Sstevel@tonic-gate * avoid a recursive mutex problem, only the ndi_evthdl_cb_mutex is 1843*7c478bd9Sstevel@tonic-gate * held. The ndi_evthdl_mutex is not held when running the callbacks. 1844*7c478bd9Sstevel@tonic-gate */ 1845*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1846*7c478bd9Sstevel@tonic-gate 1847*7c478bd9Sstevel@tonic-gate /* perform callbacks */ 1848*7c478bd9Sstevel@tonic-gate next = NDI_EVENT(cookie)->callback_list; 1849*7c478bd9Sstevel@tonic-gate while (next != NULL) { 1850*7c478bd9Sstevel@tonic-gate 1851*7c478bd9Sstevel@tonic-gate cb = next; 1852*7c478bd9Sstevel@tonic-gate next = next->ndi_evtcb_next; 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate ASSERT(cb->ndi_evtcb_cookie == cookie); 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate if (attributes == NDI_EVENT_POST_TO_TGT && 1857*7c478bd9Sstevel@tonic-gate child_dip != cb->ndi_evtcb_dip) { 1858*7c478bd9Sstevel@tonic-gate continue; 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_callback(cb->ndi_evtcb_dip, cb->ndi_evtcb_cookie, 1862*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_arg, bus_impldata); 1863*7c478bd9Sstevel@tonic-gate 1864*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1865*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1866*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1867*7c478bd9Sstevel@tonic-gate "\t\tconsumer dip=%p (%s%d)\n", 1868*7c478bd9Sstevel@tonic-gate (void *)cb->ndi_evtcb_dip, 1869*7c478bd9Sstevel@tonic-gate ddi_node_name(cb->ndi_evtcb_dip), 1870*7c478bd9Sstevel@tonic-gate ddi_get_instance(cb->ndi_evtcb_dip)); 1871*7c478bd9Sstevel@tonic-gate } 1872*7c478bd9Sstevel@tonic-gate #endif 1873*7c478bd9Sstevel@tonic-gate 1874*7c478bd9Sstevel@tonic-gate } 1875*7c478bd9Sstevel@tonic-gate 1876*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1879*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1880*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1881*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(ndi_event_hdl, "ndi_event_run_callbacks"); 1882*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate #endif /* NDI_EVENT_DEBUG */ 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1887*7c478bd9Sstevel@tonic-gate } 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate 1890*7c478bd9Sstevel@tonic-gate /* 1891*7c478bd9Sstevel@tonic-gate * perform one callback for a specified cookie and just one target 1892*7c478bd9Sstevel@tonic-gate */ 1893*7c478bd9Sstevel@tonic-gate int 1894*7c478bd9Sstevel@tonic-gate ndi_event_do_callback(ndi_event_hdl_t handle, dev_info_t *child_dip, 1895*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, void *bus_impldata) 1896*7c478bd9Sstevel@tonic-gate { 1897*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1898*7c478bd9Sstevel@tonic-gate ndi_event_callbacks_t *next, *cb; 1899*7c478bd9Sstevel@tonic-gate int attributes; 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1902*7c478bd9Sstevel@tonic-gate 1903*7c478bd9Sstevel@tonic-gate /* if this is not our event, fail */ 1904*7c478bd9Sstevel@tonic-gate if (ndi_event_is_defined(handle, cookie, &attributes) != 1905*7c478bd9Sstevel@tonic-gate NDI_SUCCESS) { 1906*7c478bd9Sstevel@tonic-gate 1907*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 1910*7c478bd9Sstevel@tonic-gate } 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1915*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1916*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ndi_event_run_callbacks:\n\t" 1917*7c478bd9Sstevel@tonic-gate "producer dip=%p (%s%d): cookie = %p, name = %s\n", 1918*7c478bd9Sstevel@tonic-gate (void *)ndi_event_hdl->ndi_evthdl_dip, 1919*7c478bd9Sstevel@tonic-gate ddi_node_name(ndi_event_hdl->ndi_evthdl_dip), 1920*7c478bd9Sstevel@tonic-gate ddi_get_instance(ndi_event_hdl->ndi_evthdl_dip), 1921*7c478bd9Sstevel@tonic-gate (void *)cookie, 1922*7c478bd9Sstevel@tonic-gate ndi_event_cookie_to_name(handle, cookie)); 1923*7c478bd9Sstevel@tonic-gate } 1924*7c478bd9Sstevel@tonic-gate #endif 1925*7c478bd9Sstevel@tonic-gate 1926*7c478bd9Sstevel@tonic-gate 1927*7c478bd9Sstevel@tonic-gate /* 1928*7c478bd9Sstevel@tonic-gate * we only grab the cb mutex because the callback handlers 1929*7c478bd9Sstevel@tonic-gate * may call the conversion functions which would cause a recursive 1930*7c478bd9Sstevel@tonic-gate * mutex problem 1931*7c478bd9Sstevel@tonic-gate */ 1932*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate /* perform callbacks */ 1935*7c478bd9Sstevel@tonic-gate for (next = NDI_EVENT(cookie)->callback_list; next != NULL; ) { 1936*7c478bd9Sstevel@tonic-gate cb = next; 1937*7c478bd9Sstevel@tonic-gate next = next->ndi_evtcb_next; 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate if (cb->ndi_evtcb_dip == child_dip) { 1940*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_callback(cb->ndi_evtcb_dip, 1941*7c478bd9Sstevel@tonic-gate cb->ndi_evtcb_cookie, cb->ndi_evtcb_arg, 1942*7c478bd9Sstevel@tonic-gate bus_impldata); 1943*7c478bd9Sstevel@tonic-gate 1944*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1945*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1946*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1947*7c478bd9Sstevel@tonic-gate "\t\tconsumer dip=%p (%s%d)\n", 1948*7c478bd9Sstevel@tonic-gate (void *)cb->ndi_evtcb_dip, 1949*7c478bd9Sstevel@tonic-gate ddi_node_name(cb->ndi_evtcb_dip), 1950*7c478bd9Sstevel@tonic-gate ddi_get_instance(cb->ndi_evtcb_dip)); 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate #endif 1953*7c478bd9Sstevel@tonic-gate break; 1954*7c478bd9Sstevel@tonic-gate } 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_cb_mutex); 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 1960*7c478bd9Sstevel@tonic-gate if (ndi_event_debug) { 1961*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1962*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(ndi_event_hdl, "ndi_event_run_callbacks"); 1963*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1964*7c478bd9Sstevel@tonic-gate } 1965*7c478bd9Sstevel@tonic-gate #endif /* NDI_EVENT_DEBUG */ 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate return (NDI_SUCCESS); 1968*7c478bd9Sstevel@tonic-gate } 1969*7c478bd9Sstevel@tonic-gate 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate /* 1972*7c478bd9Sstevel@tonic-gate * ndi_event_tag_to_cookie: utility function to find an event cookie 1973*7c478bd9Sstevel@tonic-gate * given an event tag 1974*7c478bd9Sstevel@tonic-gate */ 1975*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t 1976*7c478bd9Sstevel@tonic-gate ndi_event_tag_to_cookie(ndi_event_hdl_t handle, int event_tag) 1977*7c478bd9Sstevel@tonic-gate { 1978*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 1979*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *list; 1980*7c478bd9Sstevel@tonic-gate 1981*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 1982*7c478bd9Sstevel@tonic-gate 1983*7c478bd9Sstevel@tonic-gate list = ndi_event_hdl->ndi_evthdl_cookie_list; 1984*7c478bd9Sstevel@tonic-gate while (list != NULL) { 1985*7c478bd9Sstevel@tonic-gate if (NDI_EVENT_TAG(list) == event_tag) { 1986*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1987*7c478bd9Sstevel@tonic-gate return ((ddi_eventcookie_t)list); 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate list = list->next_cookie; 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate 1993*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 1994*7c478bd9Sstevel@tonic-gate return (NULL); 1995*7c478bd9Sstevel@tonic-gate } 1996*7c478bd9Sstevel@tonic-gate 1997*7c478bd9Sstevel@tonic-gate /* 1998*7c478bd9Sstevel@tonic-gate * ndi_event_cookie_to_tag: utility function to find a event tag 1999*7c478bd9Sstevel@tonic-gate * given an event_cookie 2000*7c478bd9Sstevel@tonic-gate */ 2001*7c478bd9Sstevel@tonic-gate int 2002*7c478bd9Sstevel@tonic-gate ndi_event_cookie_to_tag(ndi_event_hdl_t handle, ddi_eventcookie_t cookie) 2003*7c478bd9Sstevel@tonic-gate { 2004*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 2005*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *list; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate list = ndi_event_hdl->ndi_evthdl_cookie_list; 2010*7c478bd9Sstevel@tonic-gate 2011*7c478bd9Sstevel@tonic-gate while (list != NULL) { 2012*7c478bd9Sstevel@tonic-gate if ((ddi_eventcookie_t)list == cookie) { 2013*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2014*7c478bd9Sstevel@tonic-gate return (NDI_EVENT_TAG(list)); 2015*7c478bd9Sstevel@tonic-gate } 2016*7c478bd9Sstevel@tonic-gate 2017*7c478bd9Sstevel@tonic-gate list = list->next_cookie; 2018*7c478bd9Sstevel@tonic-gate } 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2021*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate } 2024*7c478bd9Sstevel@tonic-gate 2025*7c478bd9Sstevel@tonic-gate /* 2026*7c478bd9Sstevel@tonic-gate * ndi_event_cookie_to_name: utility function to find an event name 2027*7c478bd9Sstevel@tonic-gate * given an event_cookie 2028*7c478bd9Sstevel@tonic-gate */ 2029*7c478bd9Sstevel@tonic-gate char * 2030*7c478bd9Sstevel@tonic-gate ndi_event_cookie_to_name(ndi_event_hdl_t handle, ddi_eventcookie_t cookie) 2031*7c478bd9Sstevel@tonic-gate { 2032*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 2033*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *list; 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 2036*7c478bd9Sstevel@tonic-gate 2037*7c478bd9Sstevel@tonic-gate list = ndi_event_hdl->ndi_evthdl_cookie_list; 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate while (list != NULL) { 2040*7c478bd9Sstevel@tonic-gate if (list == NDI_EVENT(cookie)) { 2041*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2042*7c478bd9Sstevel@tonic-gate return (NDI_EVENT_NAME(list)); 2043*7c478bd9Sstevel@tonic-gate } 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate list = list->next_cookie; 2046*7c478bd9Sstevel@tonic-gate } 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2049*7c478bd9Sstevel@tonic-gate return (NULL); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate /* 2053*7c478bd9Sstevel@tonic-gate * ndi_event_tag_to_name: utility function to find an event name 2054*7c478bd9Sstevel@tonic-gate * given an event tag 2055*7c478bd9Sstevel@tonic-gate */ 2056*7c478bd9Sstevel@tonic-gate char * 2057*7c478bd9Sstevel@tonic-gate ndi_event_tag_to_name(ndi_event_hdl_t handle, int event_tag) 2058*7c478bd9Sstevel@tonic-gate { 2059*7c478bd9Sstevel@tonic-gate struct ndi_event_hdl *ndi_event_hdl = (struct ndi_event_hdl *)handle; 2060*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *list; 2061*7c478bd9Sstevel@tonic-gate 2062*7c478bd9Sstevel@tonic-gate mutex_enter(&ndi_event_hdl->ndi_evthdl_mutex); 2063*7c478bd9Sstevel@tonic-gate 2064*7c478bd9Sstevel@tonic-gate list = ndi_event_hdl->ndi_evthdl_cookie_list; 2065*7c478bd9Sstevel@tonic-gate 2066*7c478bd9Sstevel@tonic-gate while (list) { 2067*7c478bd9Sstevel@tonic-gate if (NDI_EVENT_TAG(list) == event_tag) { 2068*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2069*7c478bd9Sstevel@tonic-gate return (NDI_EVENT_NAME(list)); 2070*7c478bd9Sstevel@tonic-gate } 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate list = list->next_cookie; 2073*7c478bd9Sstevel@tonic-gate } 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate mutex_exit(&ndi_event_hdl->ndi_evthdl_mutex); 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate return (NULL); 2078*7c478bd9Sstevel@tonic-gate } 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate #ifdef NDI_EVENT_DEBUG 2081*7c478bd9Sstevel@tonic-gate void 2082*7c478bd9Sstevel@tonic-gate ndi_event_dump_hdl(struct ndi_event_hdl *hdl, char *location) 2083*7c478bd9Sstevel@tonic-gate { 2084*7c478bd9Sstevel@tonic-gate 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate ndi_event_callbacks_t *next; 2087*7c478bd9Sstevel@tonic-gate ndi_event_cookie_t *list; 2088*7c478bd9Sstevel@tonic-gate 2089*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&hdl->ndi_evthdl_mutex)); 2090*7c478bd9Sstevel@tonic-gate list = hdl->ndi_evthdl_cookie_list; 2091*7c478bd9Sstevel@tonic-gate 2092*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: event handle (%p): dip = %p (%s%d)\n", 2093*7c478bd9Sstevel@tonic-gate location, (void *)hdl, 2094*7c478bd9Sstevel@tonic-gate (void *)hdl->ndi_evthdl_dip, 2095*7c478bd9Sstevel@tonic-gate ddi_node_name(hdl->ndi_evthdl_dip), 2096*7c478bd9Sstevel@tonic-gate ddi_get_instance(hdl->ndi_evthdl_dip)); 2097*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\thigh=%d other=%d n=%d\n", 2098*7c478bd9Sstevel@tonic-gate hdl->ndi_evthdl_high_plevels, 2099*7c478bd9Sstevel@tonic-gate hdl->ndi_evthdl_other_plevels, 2100*7c478bd9Sstevel@tonic-gate hdl->ndi_evthdl_n_events); 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\tevent cookies:\n"); 2104*7c478bd9Sstevel@tonic-gate while (list) { 2105*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2106*7c478bd9Sstevel@tonic-gate "\t\ttag=%d name=%s p=%d a=%x dd=%p\n", 2107*7c478bd9Sstevel@tonic-gate NDI_EVENT_TAG(list), 2108*7c478bd9Sstevel@tonic-gate NDI_EVENT_NAME(list), 2109*7c478bd9Sstevel@tonic-gate NDI_EVENT_PLEVEL(list), 2110*7c478bd9Sstevel@tonic-gate NDI_EVENT_ATTRIBUTES(list), 2111*7c478bd9Sstevel@tonic-gate (void *)NDI_EVENT_DDIP(list)); 2112*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t\tcallbacks:\n"); 2113*7c478bd9Sstevel@tonic-gate for (next = list->callback_list; next != NULL; 2114*7c478bd9Sstevel@tonic-gate next = next->ndi_evtcb_next) { 2115*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2116*7c478bd9Sstevel@tonic-gate "\t\t dip=%p (%s%d) cookie=%p arg=%p\n", 2117*7c478bd9Sstevel@tonic-gate (void*)next->ndi_evtcb_dip, 2118*7c478bd9Sstevel@tonic-gate ddi_driver_name(next->ndi_evtcb_dip), 2119*7c478bd9Sstevel@tonic-gate ddi_get_instance(next->ndi_evtcb_dip), 2120*7c478bd9Sstevel@tonic-gate (void *)next->ndi_evtcb_cookie, 2121*7c478bd9Sstevel@tonic-gate next->ndi_evtcb_arg); 2122*7c478bd9Sstevel@tonic-gate } 2123*7c478bd9Sstevel@tonic-gate 2124*7c478bd9Sstevel@tonic-gate list = list->next_cookie; 2125*7c478bd9Sstevel@tonic-gate } 2126*7c478bd9Sstevel@tonic-gate 2127*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2128*7c478bd9Sstevel@tonic-gate } 2129*7c478bd9Sstevel@tonic-gate #endif 2130*7c478bd9Sstevel@tonic-gate 2131*7c478bd9Sstevel@tonic-gate int 2132*7c478bd9Sstevel@tonic-gate ndi_dev_is_prom_node(dev_info_t *dip) 2133*7c478bd9Sstevel@tonic-gate { 2134*7c478bd9Sstevel@tonic-gate return (DEVI(dip)->devi_node_class == DDI_NC_PROM); 2135*7c478bd9Sstevel@tonic-gate } 2136*7c478bd9Sstevel@tonic-gate 2137*7c478bd9Sstevel@tonic-gate int 2138*7c478bd9Sstevel@tonic-gate ndi_dev_is_pseudo_node(dev_info_t *dip) 2139*7c478bd9Sstevel@tonic-gate { 2140*7c478bd9Sstevel@tonic-gate /* 2141*7c478bd9Sstevel@tonic-gate * NOTE: this does NOT mean the pseudo branch of the device tree, 2142*7c478bd9Sstevel@tonic-gate * it means the node was created by software (DEVI_SID_NODEID | 2143*7c478bd9Sstevel@tonic-gate * DEVI_PSEUDO_NODEID) instead of being generated from a PROM node. 2144*7c478bd9Sstevel@tonic-gate */ 2145*7c478bd9Sstevel@tonic-gate return (DEVI(dip)->devi_node_class == DDI_NC_PSEUDO); 2146*7c478bd9Sstevel@tonic-gate } 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate int 2149*7c478bd9Sstevel@tonic-gate ndi_dev_is_persistent_node(dev_info_t *dip) 2150*7c478bd9Sstevel@tonic-gate { 2151*7c478bd9Sstevel@tonic-gate return ((DEVI(dip)->devi_node_attributes & DDI_PERSISTENT) != 0); 2152*7c478bd9Sstevel@tonic-gate } 2153*7c478bd9Sstevel@tonic-gate 2154*7c478bd9Sstevel@tonic-gate int 2155*7c478bd9Sstevel@tonic-gate i_ndi_dev_is_auto_assigned_node(dev_info_t *dip) 2156*7c478bd9Sstevel@tonic-gate { 2157*7c478bd9Sstevel@tonic-gate return ((DEVI(dip)->devi_node_attributes & 2158*7c478bd9Sstevel@tonic-gate DDI_AUTO_ASSIGNED_NODEID) != 0); 2159*7c478bd9Sstevel@tonic-gate } 2160*7c478bd9Sstevel@tonic-gate 2161*7c478bd9Sstevel@tonic-gate void 2162*7c478bd9Sstevel@tonic-gate i_ndi_set_node_class(dev_info_t *dip, ddi_node_class_t c) 2163*7c478bd9Sstevel@tonic-gate { 2164*7c478bd9Sstevel@tonic-gate DEVI(dip)->devi_node_class = c; 2165*7c478bd9Sstevel@tonic-gate } 2166*7c478bd9Sstevel@tonic-gate 2167*7c478bd9Sstevel@tonic-gate ddi_node_class_t 2168*7c478bd9Sstevel@tonic-gate i_ndi_get_node_class(dev_info_t *dip) 2169*7c478bd9Sstevel@tonic-gate { 2170*7c478bd9Sstevel@tonic-gate return (DEVI(dip)->devi_node_class); 2171*7c478bd9Sstevel@tonic-gate } 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate void 2174*7c478bd9Sstevel@tonic-gate i_ndi_set_node_attributes(dev_info_t *dip, int p) 2175*7c478bd9Sstevel@tonic-gate { 2176*7c478bd9Sstevel@tonic-gate DEVI(dip)->devi_node_attributes = p; 2177*7c478bd9Sstevel@tonic-gate } 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate int 2180*7c478bd9Sstevel@tonic-gate i_ndi_get_node_attributes(dev_info_t *dip) 2181*7c478bd9Sstevel@tonic-gate { 2182*7c478bd9Sstevel@tonic-gate return (DEVI(dip)->devi_node_attributes); 2183*7c478bd9Sstevel@tonic-gate } 2184*7c478bd9Sstevel@tonic-gate 2185*7c478bd9Sstevel@tonic-gate void 2186*7c478bd9Sstevel@tonic-gate i_ndi_set_nodeid(dev_info_t *dip, int n) 2187*7c478bd9Sstevel@tonic-gate { 2188*7c478bd9Sstevel@tonic-gate DEVI(dip)->devi_nodeid = n; 2189*7c478bd9Sstevel@tonic-gate } 2190*7c478bd9Sstevel@tonic-gate 2191*7c478bd9Sstevel@tonic-gate void 2192*7c478bd9Sstevel@tonic-gate ndi_set_acc_fault(ddi_acc_handle_t ah) 2193*7c478bd9Sstevel@tonic-gate { 2194*7c478bd9Sstevel@tonic-gate i_ddi_acc_set_fault(ah); 2195*7c478bd9Sstevel@tonic-gate } 2196*7c478bd9Sstevel@tonic-gate 2197*7c478bd9Sstevel@tonic-gate void 2198*7c478bd9Sstevel@tonic-gate ndi_clr_acc_fault(ddi_acc_handle_t ah) 2199*7c478bd9Sstevel@tonic-gate { 2200*7c478bd9Sstevel@tonic-gate i_ddi_acc_clr_fault(ah); 2201*7c478bd9Sstevel@tonic-gate } 2202*7c478bd9Sstevel@tonic-gate 2203*7c478bd9Sstevel@tonic-gate void 2204*7c478bd9Sstevel@tonic-gate ndi_set_dma_fault(ddi_dma_handle_t dh) 2205*7c478bd9Sstevel@tonic-gate { 2206*7c478bd9Sstevel@tonic-gate i_ddi_dma_set_fault(dh); 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate 2209*7c478bd9Sstevel@tonic-gate void 2210*7c478bd9Sstevel@tonic-gate ndi_clr_dma_fault(ddi_dma_handle_t dh) 2211*7c478bd9Sstevel@tonic-gate { 2212*7c478bd9Sstevel@tonic-gate i_ddi_dma_clr_fault(dh); 2213*7c478bd9Sstevel@tonic-gate } 2214*7c478bd9Sstevel@tonic-gate 2215*7c478bd9Sstevel@tonic-gate /* 2216*7c478bd9Sstevel@tonic-gate * The default fault-handler, called when the event posted by 2217*7c478bd9Sstevel@tonic-gate * ddi_dev_report_fault() reaches rootnex. 2218*7c478bd9Sstevel@tonic-gate */ 2219*7c478bd9Sstevel@tonic-gate static void 2220*7c478bd9Sstevel@tonic-gate i_ddi_fault_handler(dev_info_t *dip, struct ddi_fault_event_data *fedp) 2221*7c478bd9Sstevel@tonic-gate { 2222*7c478bd9Sstevel@tonic-gate ASSERT(fedp); 2223*7c478bd9Sstevel@tonic-gate 2224*7c478bd9Sstevel@tonic-gate mutex_enter(&(DEVI(dip)->devi_lock)); 2225*7c478bd9Sstevel@tonic-gate if (!DEVI_IS_DEVICE_OFFLINE(dip)) { 2226*7c478bd9Sstevel@tonic-gate switch (fedp->f_impact) { 2227*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_LOST: 2228*7c478bd9Sstevel@tonic-gate DEVI_SET_DEVICE_DOWN(dip); 2229*7c478bd9Sstevel@tonic-gate break; 2230*7c478bd9Sstevel@tonic-gate 2231*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_DEGRADED: 2232*7c478bd9Sstevel@tonic-gate DEVI_SET_DEVICE_DEGRADED(dip); 2233*7c478bd9Sstevel@tonic-gate break; 2234*7c478bd9Sstevel@tonic-gate 2235*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_UNAFFECTED: 2236*7c478bd9Sstevel@tonic-gate default: 2237*7c478bd9Sstevel@tonic-gate break; 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_RESTORED: 2240*7c478bd9Sstevel@tonic-gate DEVI_SET_DEVICE_UP(dip); 2241*7c478bd9Sstevel@tonic-gate break; 2242*7c478bd9Sstevel@tonic-gate } 2243*7c478bd9Sstevel@tonic-gate } 2244*7c478bd9Sstevel@tonic-gate mutex_exit(&(DEVI(dip)->devi_lock)); 2245*7c478bd9Sstevel@tonic-gate } 2246*7c478bd9Sstevel@tonic-gate 2247*7c478bd9Sstevel@tonic-gate /* 2248*7c478bd9Sstevel@tonic-gate * The default fault-logger, called when the event posted by 2249*7c478bd9Sstevel@tonic-gate * ddi_dev_report_fault() reaches rootnex. 2250*7c478bd9Sstevel@tonic-gate */ 2251*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2252*7c478bd9Sstevel@tonic-gate static void 2253*7c478bd9Sstevel@tonic-gate i_ddi_fault_logger(dev_info_t *rdip, struct ddi_fault_event_data *fedp) 2254*7c478bd9Sstevel@tonic-gate { 2255*7c478bd9Sstevel@tonic-gate ddi_devstate_t newstate; 2256*7c478bd9Sstevel@tonic-gate const char *action; 2257*7c478bd9Sstevel@tonic-gate const char *servstate; 2258*7c478bd9Sstevel@tonic-gate const char *location; 2259*7c478bd9Sstevel@tonic-gate int bad; 2260*7c478bd9Sstevel@tonic-gate int changed; 2261*7c478bd9Sstevel@tonic-gate int level; 2262*7c478bd9Sstevel@tonic-gate int still; 2263*7c478bd9Sstevel@tonic-gate 2264*7c478bd9Sstevel@tonic-gate ASSERT(fedp); 2265*7c478bd9Sstevel@tonic-gate 2266*7c478bd9Sstevel@tonic-gate bad = 0; 2267*7c478bd9Sstevel@tonic-gate switch (fedp->f_location) { 2268*7c478bd9Sstevel@tonic-gate case DDI_DATAPATH_FAULT: 2269*7c478bd9Sstevel@tonic-gate location = "in datapath to"; 2270*7c478bd9Sstevel@tonic-gate break; 2271*7c478bd9Sstevel@tonic-gate case DDI_DEVICE_FAULT: 2272*7c478bd9Sstevel@tonic-gate location = "in"; 2273*7c478bd9Sstevel@tonic-gate break; 2274*7c478bd9Sstevel@tonic-gate case DDI_EXTERNAL_FAULT: 2275*7c478bd9Sstevel@tonic-gate location = "external to"; 2276*7c478bd9Sstevel@tonic-gate break; 2277*7c478bd9Sstevel@tonic-gate default: 2278*7c478bd9Sstevel@tonic-gate location = "somewhere near"; 2279*7c478bd9Sstevel@tonic-gate bad = 1; 2280*7c478bd9Sstevel@tonic-gate break; 2281*7c478bd9Sstevel@tonic-gate } 2282*7c478bd9Sstevel@tonic-gate 2283*7c478bd9Sstevel@tonic-gate newstate = ddi_get_devstate(fedp->f_dip); 2284*7c478bd9Sstevel@tonic-gate switch (newstate) { 2285*7c478bd9Sstevel@tonic-gate case DDI_DEVSTATE_OFFLINE: 2286*7c478bd9Sstevel@tonic-gate servstate = "unavailable"; 2287*7c478bd9Sstevel@tonic-gate break; 2288*7c478bd9Sstevel@tonic-gate case DDI_DEVSTATE_DOWN: 2289*7c478bd9Sstevel@tonic-gate servstate = "unavailable"; 2290*7c478bd9Sstevel@tonic-gate break; 2291*7c478bd9Sstevel@tonic-gate case DDI_DEVSTATE_QUIESCED: 2292*7c478bd9Sstevel@tonic-gate servstate = "suspended"; 2293*7c478bd9Sstevel@tonic-gate break; 2294*7c478bd9Sstevel@tonic-gate case DDI_DEVSTATE_DEGRADED: 2295*7c478bd9Sstevel@tonic-gate servstate = "degraded"; 2296*7c478bd9Sstevel@tonic-gate break; 2297*7c478bd9Sstevel@tonic-gate default: 2298*7c478bd9Sstevel@tonic-gate servstate = "available"; 2299*7c478bd9Sstevel@tonic-gate break; 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate changed = (newstate != fedp->f_oldstate); 2303*7c478bd9Sstevel@tonic-gate level = (newstate < fedp->f_oldstate) ? CE_WARN : CE_NOTE; 2304*7c478bd9Sstevel@tonic-gate switch (fedp->f_impact) { 2305*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_LOST: 2306*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_DEGRADED: 2307*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_UNAFFECTED: 2308*7c478bd9Sstevel@tonic-gate /* fault detected; service [still] <servstate> */ 2309*7c478bd9Sstevel@tonic-gate action = "fault detected"; 2310*7c478bd9Sstevel@tonic-gate still = !changed; 2311*7c478bd9Sstevel@tonic-gate break; 2312*7c478bd9Sstevel@tonic-gate 2313*7c478bd9Sstevel@tonic-gate case DDI_SERVICE_RESTORED: 2314*7c478bd9Sstevel@tonic-gate if (newstate != DDI_DEVSTATE_UP) { 2315*7c478bd9Sstevel@tonic-gate /* fault cleared; service still <servstate> */ 2316*7c478bd9Sstevel@tonic-gate action = "fault cleared"; 2317*7c478bd9Sstevel@tonic-gate still = 1; 2318*7c478bd9Sstevel@tonic-gate } else if (changed) { 2319*7c478bd9Sstevel@tonic-gate /* fault cleared; service <servstate> */ 2320*7c478bd9Sstevel@tonic-gate action = "fault cleared"; 2321*7c478bd9Sstevel@tonic-gate still = 0; 2322*7c478bd9Sstevel@tonic-gate } else { 2323*7c478bd9Sstevel@tonic-gate /* no fault; service <servstate> */ 2324*7c478bd9Sstevel@tonic-gate action = "no fault"; 2325*7c478bd9Sstevel@tonic-gate still = 0; 2326*7c478bd9Sstevel@tonic-gate } 2327*7c478bd9Sstevel@tonic-gate break; 2328*7c478bd9Sstevel@tonic-gate 2329*7c478bd9Sstevel@tonic-gate default: 2330*7c478bd9Sstevel@tonic-gate bad = 1; 2331*7c478bd9Sstevel@tonic-gate break; 2332*7c478bd9Sstevel@tonic-gate } 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate cmn_err(level, "!%s%d: %s %s device; service %s%s"+(bad|changed), 2335*7c478bd9Sstevel@tonic-gate ddi_driver_name(fedp->f_dip), 2336*7c478bd9Sstevel@tonic-gate ddi_get_instance(fedp->f_dip), 2337*7c478bd9Sstevel@tonic-gate bad ? "invalid report of fault" : action, 2338*7c478bd9Sstevel@tonic-gate location, still ? "still " : "", servstate); 2339*7c478bd9Sstevel@tonic-gate 2340*7c478bd9Sstevel@tonic-gate cmn_err(level, "!%s%d: %s"+(bad|changed), 2341*7c478bd9Sstevel@tonic-gate ddi_driver_name(fedp->f_dip), 2342*7c478bd9Sstevel@tonic-gate ddi_get_instance(fedp->f_dip), 2343*7c478bd9Sstevel@tonic-gate fedp->f_message); 2344*7c478bd9Sstevel@tonic-gate } 2345*7c478bd9Sstevel@tonic-gate 2346*7c478bd9Sstevel@tonic-gate /* 2347*7c478bd9Sstevel@tonic-gate * Platform-settable pointers to fault handler and logger functions. 2348*7c478bd9Sstevel@tonic-gate * These are called by the default rootnex event-posting code when 2349*7c478bd9Sstevel@tonic-gate * a fault event reaches rootnex. 2350*7c478bd9Sstevel@tonic-gate */ 2351*7c478bd9Sstevel@tonic-gate void (*plat_fault_handler)(dev_info_t *, struct ddi_fault_event_data *) = 2352*7c478bd9Sstevel@tonic-gate i_ddi_fault_handler; 2353*7c478bd9Sstevel@tonic-gate void (*plat_fault_logger)(dev_info_t *, struct ddi_fault_event_data *) = 2354*7c478bd9Sstevel@tonic-gate i_ddi_fault_logger; 2355*7c478bd9Sstevel@tonic-gate 2356*7c478bd9Sstevel@tonic-gate /* 2357*7c478bd9Sstevel@tonic-gate * Rootnex event definitions ... 2358*7c478bd9Sstevel@tonic-gate */ 2359*7c478bd9Sstevel@tonic-gate enum rootnex_event_tags { 2360*7c478bd9Sstevel@tonic-gate ROOTNEX_FAULT_EVENT 2361*7c478bd9Sstevel@tonic-gate }; 2362*7c478bd9Sstevel@tonic-gate static ndi_event_hdl_t rootnex_event_hdl; 2363*7c478bd9Sstevel@tonic-gate static ndi_event_definition_t rootnex_event_set[] = { 2364*7c478bd9Sstevel@tonic-gate { 2365*7c478bd9Sstevel@tonic-gate ROOTNEX_FAULT_EVENT, 2366*7c478bd9Sstevel@tonic-gate DDI_DEVI_FAULT_EVENT, 2367*7c478bd9Sstevel@tonic-gate EPL_INTERRUPT, 2368*7c478bd9Sstevel@tonic-gate NDI_EVENT_POST_TO_ALL 2369*7c478bd9Sstevel@tonic-gate } 2370*7c478bd9Sstevel@tonic-gate }; 2371*7c478bd9Sstevel@tonic-gate static ndi_event_set_t rootnex_events = { 2372*7c478bd9Sstevel@tonic-gate NDI_EVENTS_REV1, 2373*7c478bd9Sstevel@tonic-gate sizeof (rootnex_event_set) / sizeof (rootnex_event_set[0]), 2374*7c478bd9Sstevel@tonic-gate rootnex_event_set 2375*7c478bd9Sstevel@tonic-gate }; 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate /* 2378*7c478bd9Sstevel@tonic-gate * Initialize rootnex event handle 2379*7c478bd9Sstevel@tonic-gate */ 2380*7c478bd9Sstevel@tonic-gate void 2381*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_init_events(dev_info_t *dip) 2382*7c478bd9Sstevel@tonic-gate { 2383*7c478bd9Sstevel@tonic-gate if (ndi_event_alloc_hdl(dip, (ddi_iblock_cookie_t)(LOCK_LEVEL-1), 2384*7c478bd9Sstevel@tonic-gate &rootnex_event_hdl, NDI_SLEEP) == NDI_SUCCESS) { 2385*7c478bd9Sstevel@tonic-gate if (ndi_event_bind_set(rootnex_event_hdl, 2386*7c478bd9Sstevel@tonic-gate &rootnex_events, NDI_SLEEP) != NDI_SUCCESS) { 2387*7c478bd9Sstevel@tonic-gate (void) ndi_event_free_hdl(rootnex_event_hdl); 2388*7c478bd9Sstevel@tonic-gate rootnex_event_hdl = NULL; 2389*7c478bd9Sstevel@tonic-gate } 2390*7c478bd9Sstevel@tonic-gate } 2391*7c478bd9Sstevel@tonic-gate } 2392*7c478bd9Sstevel@tonic-gate 2393*7c478bd9Sstevel@tonic-gate /* 2394*7c478bd9Sstevel@tonic-gate * Event-handling functions for rootnex 2395*7c478bd9Sstevel@tonic-gate * These provide the standard implementation of fault handling 2396*7c478bd9Sstevel@tonic-gate */ 2397*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2398*7c478bd9Sstevel@tonic-gate int 2399*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 2400*7c478bd9Sstevel@tonic-gate char *eventname, ddi_eventcookie_t *cookiep) 2401*7c478bd9Sstevel@tonic-gate { 2402*7c478bd9Sstevel@tonic-gate if (rootnex_event_hdl == NULL) 2403*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 2404*7c478bd9Sstevel@tonic-gate return (ndi_event_retrieve_cookie(rootnex_event_hdl, rdip, eventname, 2405*7c478bd9Sstevel@tonic-gate cookiep, NDI_EVENT_NOPASS)); 2406*7c478bd9Sstevel@tonic-gate } 2407*7c478bd9Sstevel@tonic-gate 2408*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2409*7c478bd9Sstevel@tonic-gate int 2410*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 2411*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventid, void (*handler)(dev_info_t *dip, 2412*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t event, void *arg, void *impl_data), void *arg, 2413*7c478bd9Sstevel@tonic-gate ddi_callback_id_t *cb_id) 2414*7c478bd9Sstevel@tonic-gate { 2415*7c478bd9Sstevel@tonic-gate if (rootnex_event_hdl == NULL) 2416*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 2417*7c478bd9Sstevel@tonic-gate return (ndi_event_add_callback(rootnex_event_hdl, rdip, 2418*7c478bd9Sstevel@tonic-gate eventid, handler, arg, NDI_SLEEP, cb_id)); 2419*7c478bd9Sstevel@tonic-gate } 2420*7c478bd9Sstevel@tonic-gate 2421*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2422*7c478bd9Sstevel@tonic-gate int 2423*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 2424*7c478bd9Sstevel@tonic-gate { 2425*7c478bd9Sstevel@tonic-gate if (rootnex_event_hdl == NULL) 2426*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 2427*7c478bd9Sstevel@tonic-gate 2428*7c478bd9Sstevel@tonic-gate return (ndi_event_remove_callback(rootnex_event_hdl, cb_id)); 2429*7c478bd9Sstevel@tonic-gate } 2430*7c478bd9Sstevel@tonic-gate 2431*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2432*7c478bd9Sstevel@tonic-gate int 2433*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_post_event(dev_info_t *dip, dev_info_t *rdip, 2434*7c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventid, void *impl_data) 2435*7c478bd9Sstevel@tonic-gate { 2436*7c478bd9Sstevel@tonic-gate int tag; 2437*7c478bd9Sstevel@tonic-gate 2438*7c478bd9Sstevel@tonic-gate if (rootnex_event_hdl == NULL) 2439*7c478bd9Sstevel@tonic-gate return (NDI_FAILURE); 2440*7c478bd9Sstevel@tonic-gate 2441*7c478bd9Sstevel@tonic-gate tag = ndi_event_cookie_to_tag(rootnex_event_hdl, eventid); 2442*7c478bd9Sstevel@tonic-gate if (tag == ROOTNEX_FAULT_EVENT) { 2443*7c478bd9Sstevel@tonic-gate (*plat_fault_handler)(rdip, impl_data); 2444*7c478bd9Sstevel@tonic-gate (*plat_fault_logger)(rdip, impl_data); 2445*7c478bd9Sstevel@tonic-gate } 2446*7c478bd9Sstevel@tonic-gate return (ndi_event_run_callbacks(rootnex_event_hdl, rdip, 2447*7c478bd9Sstevel@tonic-gate eventid, impl_data)); 2448*7c478bd9Sstevel@tonic-gate } 2449