1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/debug.h> 30*0Sstevel@tonic-gate #include <sys/types.h> 31*0Sstevel@tonic-gate #include <sys/errno.h> 32*0Sstevel@tonic-gate #include <sys/cred.h> 33*0Sstevel@tonic-gate #include <sys/dditypes.h> 34*0Sstevel@tonic-gate #include <sys/sunddi.h> 35*0Sstevel@tonic-gate #include <sys/sunndi.h> 36*0Sstevel@tonic-gate #include <sys/ddi.h> 37*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 38*0Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 39*0Sstevel@tonic-gate #include <sys/kmem.h> 40*0Sstevel@tonic-gate #include <sys/note.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include <sys/sbdpriv.h> 43*0Sstevel@tonic-gate #include <sys/sbd_io.h> 44*0Sstevel@tonic-gate #include <sys/machsystm.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate extern void sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip); 48*0Sstevel@tonic-gate extern sbd_state_t ostate_cvt(sbd_istate_t); 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* 51*0Sstevel@tonic-gate * Given a dev_info_t of a branch root, walk down the 52*0Sstevel@tonic-gate * branch to attach drivers 53*0Sstevel@tonic-gate */ 54*0Sstevel@tonic-gate /*ARGSUSED*/ 55*0Sstevel@tonic-gate void 56*0Sstevel@tonic-gate sbd_attach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate (void) e_ddi_branch_configure(dip, NULL, 0); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate ASSERT(sbp->sb_iopath[unit] != NULL); 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate (void) ddi_pathname(dip, sbp->sb_iopath[unit]); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * remove device nodes for the branch indicated by dip 71*0Sstevel@tonic-gate * Hold the status lock so that status can safely do ddi_pathname(). 72*0Sstevel@tonic-gate */ 73*0Sstevel@tonic-gate /*ARGSUSED*/ 74*0Sstevel@tonic-gate void 75*0Sstevel@tonic-gate sbd_detach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 76*0Sstevel@tonic-gate { 77*0Sstevel@tonic-gate int rv; 78*0Sstevel@tonic-gate dev_info_t *fdip = NULL; 79*0Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 82*0Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 83*0Sstevel@tonic-gate rv = e_ddi_branch_unconfigure(dip, &fdip, DEVI_BRANCH_EVENT); 84*0Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 85*0Sstevel@tonic-gate if (rv) { 86*0Sstevel@tonic-gate /* 87*0Sstevel@tonic-gate * If non-NULL, fdip is returned held and must be released. 88*0Sstevel@tonic-gate */ 89*0Sstevel@tonic-gate if (fdip != NULL) { 90*0Sstevel@tonic-gate sbd_errno_decode(rv, ep, fdip); 91*0Sstevel@tonic-gate ddi_release_devi(fdip); 92*0Sstevel@tonic-gate } else { 93*0Sstevel@tonic-gate sbd_errno_decode(rv, ep, dip); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /*ARGSUSED*/ 99*0Sstevel@tonic-gate void 100*0Sstevel@tonic-gate sbd_init_io_unit(sbd_board_t *sbp, int unit) 101*0Sstevel@tonic-gate { 102*0Sstevel@tonic-gate sbd_istate_t new_state; 103*0Sstevel@tonic-gate sbd_io_unit_t *ip; 104*0Sstevel@tonic-gate dev_info_t *dip; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit); 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_IO, unit)) { 109*0Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 110*0Sstevel@tonic-gate } else if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, unit)) { 111*0Sstevel@tonic-gate new_state = SBD_STATE_CONNECTED; 112*0Sstevel@tonic-gate } else { 113*0Sstevel@tonic-gate new_state = SBD_STATE_EMPTY; 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][unit]; 116*0Sstevel@tonic-gate ip->sbi_cm.sbdev_cond = sbd_get_comp_cond(dip); 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * Any changes to this io component should be performed above 120*0Sstevel@tonic-gate * this call to ensure the component is fully initialized 121*0Sstevel@tonic-gate * before transitioning to the new state. 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, unit, new_state); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /*ARGSUSED*/ 127*0Sstevel@tonic-gate int 128*0Sstevel@tonic-gate sbd_disconnect_io(sbd_handle_t *hp, int unit) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate return (0); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate int 134*0Sstevel@tonic-gate sbd_pre_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 135*0Sstevel@tonic-gate { 136*0Sstevel@tonic-gate _NOTE(ARGUNUSED(hp)) 137*0Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist)) 138*0Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum)) 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate return (0); 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate /*ARGSUSED*/ 144*0Sstevel@tonic-gate int 145*0Sstevel@tonic-gate sbd_pre_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 146*0Sstevel@tonic-gate { 147*0Sstevel@tonic-gate fn_t f = "sbd_pre_detach_io"; 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate PR_IO("%s...\n", f); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (devnum <= 0) 152*0Sstevel@tonic-gate return (-1); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* fail if any I/O devices are referenced */ 155*0Sstevel@tonic-gate if (sbd_check_io_refs(hp, devlist, devnum) > 0) { 156*0Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f); 157*0Sstevel@tonic-gate return (-1); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate return (0); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /*ARGSUSED*/ 164*0Sstevel@tonic-gate int 165*0Sstevel@tonic-gate sbd_post_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate _NOTE(ARGUNUSED(hp)) 168*0Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist)) 169*0Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum)) 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate return (0); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /*ARGSUSED*/ 175*0Sstevel@tonic-gate int 176*0Sstevel@tonic-gate sbd_post_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 177*0Sstevel@tonic-gate { 178*0Sstevel@tonic-gate return (0); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate /*ARGSUSED*/ 182*0Sstevel@tonic-gate int 183*0Sstevel@tonic-gate sbd_io_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp) 184*0Sstevel@tonic-gate { 185*0Sstevel@tonic-gate int i, ix; 186*0Sstevel@tonic-gate sbd_board_t *sbp; 187*0Sstevel@tonic-gate sbd_io_stat_t *isp; 188*0Sstevel@tonic-gate sbd_io_unit_t *ip; 189*0Sstevel@tonic-gate sbd_istate_t dstate; 190*0Sstevel@tonic-gate sbdp_handle_t *hdp; 191*0Sstevel@tonic-gate sbderror_t *ep; 192*0Sstevel@tonic-gate sbd_error_t *sep; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate /* 195*0Sstevel@tonic-gate * Only look for requested devices that are actually present. 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate ep = HD2MACHERR(hp); 200*0Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 201*0Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate /* 204*0Sstevel@tonic-gate * Concurrent status and unconfigure, disconnect are allowed. 205*0Sstevel@tonic-gate * To prevent DR code from accessing stale dips, check the 206*0Sstevel@tonic-gate * present devset and access the dips with status lock held. 207*0Sstevel@tonic-gate * Disconnect and unconfigure code change dip state with 208*0Sstevel@tonic-gate * status lock (sb_slock) held. 209*0Sstevel@tonic-gate */ 210*0Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 215*0Sstevel@tonic-gate dev_info_t *dip; 216*0Sstevel@tonic-gate int unit; 217*0Sstevel@tonic-gate int namelen; 218*0Sstevel@tonic-gate int refcount = 0; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0) 221*0Sstevel@tonic-gate continue; 222*0Sstevel@tonic-gate /* 223*0Sstevel@tonic-gate * Check to make sure the io component is in a state 224*0Sstevel@tonic-gate * where its fully initialized. 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_IO, i) == SBD_STATE_EMPTY) 227*0Sstevel@tonic-gate continue; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 230*0Sstevel@tonic-gate if (dip == NULL) 231*0Sstevel@tonic-gate continue; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate isp = &dsp->d_io; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate bzero((caddr_t)isp, sizeof (*isp)); 236*0Sstevel@tonic-gate namelen = sizeof (isp->is_name); 237*0Sstevel@tonic-gate (void) ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 238*0Sstevel@tonic-gate DDI_PROP_DONTPASS, OBP_DEVICETYPE, 239*0Sstevel@tonic-gate (caddr_t)isp->is_name, &namelen); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate isp->is_unit = sbdp_get_unit_num(hdp, dip); 242*0Sstevel@tonic-gate if (isp->is_unit < 0) { 243*0Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 244*0Sstevel@tonic-gate continue; 245*0Sstevel@tonic-gate else { 246*0Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 247*0Sstevel@tonic-gate break; 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate unit = isp->is_unit; 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate dstate = SBD_DEVICE_STATE(sbp, SBD_COMP_IO, unit); 253*0Sstevel@tonic-gate isp->is_ostate = ostate_cvt(dstate); 254*0Sstevel@tonic-gate isp->is_type = SBD_COMP_IO; 255*0Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit); 256*0Sstevel@tonic-gate isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond; 257*0Sstevel@tonic-gate isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy; 258*0Sstevel@tonic-gate isp->is_cm.c_time = ip->sbi_cm.sbdev_time; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * This is safe to do as unconfigure and disconnect 263*0Sstevel@tonic-gate * hold the status lock while changing dip state. 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate (void) ddi_pathname(dip, isp->is_pathname); 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate /* 268*0Sstevel@tonic-gate * We use a dummy handle in which to collect 269*0Sstevel@tonic-gate * the major numbers of unsafe devices. 270*0Sstevel@tonic-gate */ 271*0Sstevel@tonic-gate sbdp_check_devices(dip, &refcount, sep); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate isp->is_referenced = (refcount == 0) ? 0 : 1; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate isp->is_unsafe_count = 0; 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * Reset error field since we don't care about 279*0Sstevel@tonic-gate * errors at this level. The unsafe devices 280*0Sstevel@tonic-gate * will be reported in the structure. 281*0Sstevel@tonic-gate */ 282*0Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NOERROR); 283*0Sstevel@tonic-gate ep->e_rsc[0] = '\0'; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate ix++; 286*0Sstevel@tonic-gate dsp++; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t)); 292*0Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate return (ix); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /*ARGSUSED*/ 298*0Sstevel@tonic-gate int 299*0Sstevel@tonic-gate sbd_io_cnt(sbd_handle_t *hp, sbd_devset_t devset) 300*0Sstevel@tonic-gate { 301*0Sstevel@tonic-gate int i, ix; 302*0Sstevel@tonic-gate sbd_board_t *sbp; 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /* 307*0Sstevel@tonic-gate * Only look for requested devices that are actually present. 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 312*0Sstevel@tonic-gate dev_info_t *dip; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0) 315*0Sstevel@tonic-gate continue; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 318*0Sstevel@tonic-gate if (dip == NULL) 319*0Sstevel@tonic-gate continue; 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate ix++; 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate return (ix); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate int 328*0Sstevel@tonic-gate sbd_check_io_refs(sbd_handle_t *hp, sbd_devlist_t devlist[], int devnum) 329*0Sstevel@tonic-gate { 330*0Sstevel@tonic-gate register int i, reftotal = 0; 331*0Sstevel@tonic-gate fn_t f = "sbd_check_io_refs"; 332*0Sstevel@tonic-gate sbd_error_t *sep; 333*0Sstevel@tonic-gate sbderror_t *ep; 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 336*0Sstevel@tonic-gate ep = HD2MACHERR(hp); 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 339*0Sstevel@tonic-gate dev_info_t *dip; 340*0Sstevel@tonic-gate int ref; 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate dip = devlist[i].dv_dip; 343*0Sstevel@tonic-gate ref = 0; 344*0Sstevel@tonic-gate sbdp_check_devices(dip, &ref, sep); 345*0Sstevel@tonic-gate if (ref) { 346*0Sstevel@tonic-gate if (SBD_GET_ERR(ep) == 0) { 347*0Sstevel@tonic-gate SBD_GET_PERR(sep, ep); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate SBD_GET_PERR(sep, &devlist[i].dv_error); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate PR_IO("%s: dip(%s) ref = %d\n", 352*0Sstevel@tonic-gate f, ddi_get_name(dip), ref); 353*0Sstevel@tonic-gate reftotal += ref; 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t)); 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate return (reftotal); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate int 362*0Sstevel@tonic-gate sbd_check_io_attached(dev_info_t *dip, void *arg) 363*0Sstevel@tonic-gate { 364*0Sstevel@tonic-gate dev_info_t **tdip; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate tdip = (dev_info_t **)arg; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (dip == *tdip) { 369*0Sstevel@tonic-gate int state; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate state = ddi_get_devstate(dip); 372*0Sstevel@tonic-gate if (i_ddi_node_state(dip) >= DS_ATTACHED || 373*0Sstevel@tonic-gate (state == DDI_DEVSTATE_UP)) { 374*0Sstevel@tonic-gate *tdip = NULL; 375*0Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate int 382*0Sstevel@tonic-gate sbd_pre_release_io(sbd_handle_t *hp, 383*0Sstevel@tonic-gate sbd_devlist_t *devlist, int devnum) 384*0Sstevel@tonic-gate { 385*0Sstevel@tonic-gate fn_t f = "sbd_pre_release_io"; 386*0Sstevel@tonic-gate int rv = 0; 387*0Sstevel@tonic-gate int i; 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate ASSERT(devnum > 0); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate /* fail if any I/O devices are referenced */ 392*0Sstevel@tonic-gate if ((rv = sbd_check_io_refs(hp, devlist, devnum)) > 0) { 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * One of the devices may have failed check to see which 395*0Sstevel@tonic-gate * and set in the main handle 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 398*0Sstevel@tonic-gate if (SBD_GET_ERR(&devlist[i].dv_error) != 0) { 399*0Sstevel@tonic-gate (void) sbd_set_err_in_hdl(hp, 400*0Sstevel@tonic-gate &devlist[i].dv_error); 401*0Sstevel@tonic-gate break; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate return (rv); 408*0Sstevel@tonic-gate } 409