17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
525e8c5aaSvikram * Common Development and Distribution License (the "License").
625e8c5aaSvikram * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*df3cd224SVijay S Balakrishna * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/debug.h>
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/errno.h>
297c478bd9Sstevel@tonic-gate #include <sys/cred.h>
307c478bd9Sstevel@tonic-gate #include <sys/dditypes.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
337c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
357c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h>
367c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
377c478bd9Sstevel@tonic-gate #include <sys/note.h>
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #include <sys/sbdpriv.h>
407c478bd9Sstevel@tonic-gate #include <sys/sbd_io.h>
417c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate extern void sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip);
457c478bd9Sstevel@tonic-gate extern sbd_state_t ostate_cvt(sbd_istate_t);
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate * Given a dev_info_t of a branch root, walk down the
497c478bd9Sstevel@tonic-gate * branch to attach drivers
507c478bd9Sstevel@tonic-gate */
517c478bd9Sstevel@tonic-gate /*ARGSUSED*/
527c478bd9Sstevel@tonic-gate void
sbd_attach_io(sbd_handle_t * hp,sbderror_t * ep,dev_info_t * dip,int unit)537c478bd9Sstevel@tonic-gate sbd_attach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd);
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip));
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate (void) e_ddi_branch_configure(dip, NULL, 0);
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_iopath[unit] != NULL);
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, sbp->sb_iopath[unit]);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate * remove device nodes for the branch indicated by dip
687c478bd9Sstevel@tonic-gate * Hold the status lock so that status can safely do ddi_pathname().
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate /*ARGSUSED*/
717c478bd9Sstevel@tonic-gate void
sbd_detach_io(sbd_handle_t * hp,sbderror_t * ep,dev_info_t * dip,int unit)727c478bd9Sstevel@tonic-gate sbd_detach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate int rv;
757c478bd9Sstevel@tonic-gate dev_info_t *fdip = NULL;
767c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd);
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip));
797c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock);
807c478bd9Sstevel@tonic-gate rv = e_ddi_branch_unconfigure(dip, &fdip, DEVI_BRANCH_EVENT);
817c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock);
827c478bd9Sstevel@tonic-gate if (rv) {
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate * If non-NULL, fdip is returned held and must be released.
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate if (fdip != NULL) {
877c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, fdip);
887c478bd9Sstevel@tonic-gate ddi_release_devi(fdip);
897c478bd9Sstevel@tonic-gate } else {
907c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, dip);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
967c478bd9Sstevel@tonic-gate void
sbd_init_io_unit(sbd_board_t * sbp,int unit)977c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbd_board_t *sbp, int unit)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate sbd_istate_t new_state;
1007c478bd9Sstevel@tonic-gate sbd_io_unit_t *ip;
1017c478bd9Sstevel@tonic-gate dev_info_t *dip;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit);
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_IO, unit)) {
1067c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED;
1077c478bd9Sstevel@tonic-gate } else if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, unit)) {
1087c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONNECTED;
1097c478bd9Sstevel@tonic-gate } else {
1107c478bd9Sstevel@tonic-gate new_state = SBD_STATE_EMPTY;
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][unit];
1137c478bd9Sstevel@tonic-gate ip->sbi_cm.sbdev_cond = sbd_get_comp_cond(dip);
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate * Any changes to this io component should be performed above
1177c478bd9Sstevel@tonic-gate * this call to ensure the component is fully initialized
1187c478bd9Sstevel@tonic-gate * before transitioning to the new state.
1197c478bd9Sstevel@tonic-gate */
1207c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, unit, new_state);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1247c478bd9Sstevel@tonic-gate int
sbd_disconnect_io(sbd_handle_t * hp,int unit)1257c478bd9Sstevel@tonic-gate sbd_disconnect_io(sbd_handle_t *hp, int unit)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate return (0);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate int
sbd_pre_attach_io(sbd_handle_t * hp,sbd_devlist_t * devlist,int devnum)1317c478bd9Sstevel@tonic-gate sbd_pre_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(hp))
1347c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist))
1357c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum))
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate return (0);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1417c478bd9Sstevel@tonic-gate int
sbd_pre_detach_io(sbd_handle_t * hp,sbd_devlist_t * devlist,int devnum)1427c478bd9Sstevel@tonic-gate sbd_pre_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate fn_t f = "sbd_pre_detach_io";
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate PR_IO("%s...\n", f);
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate if (devnum <= 0)
1497c478bd9Sstevel@tonic-gate return (-1);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /* fail if any I/O devices are referenced */
1527c478bd9Sstevel@tonic-gate if (sbd_check_io_refs(hp, devlist, devnum) > 0) {
1537c478bd9Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f);
1547c478bd9Sstevel@tonic-gate return (-1);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate return (0);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1617c478bd9Sstevel@tonic-gate int
sbd_post_attach_io(sbd_handle_t * hp,sbd_devlist_t * devlist,int devnum)1627c478bd9Sstevel@tonic-gate sbd_post_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(hp))
1657c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist))
1667c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum))
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate return (0);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1727c478bd9Sstevel@tonic-gate int
sbd_post_detach_io(sbd_handle_t * hp,sbd_devlist_t * devlist,int devnum)1737c478bd9Sstevel@tonic-gate sbd_post_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate return (0);
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1797c478bd9Sstevel@tonic-gate int
sbd_io_status(sbd_handle_t * hp,sbd_devset_t devset,sbd_dev_stat_t * dsp)1807c478bd9Sstevel@tonic-gate sbd_io_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate int i, ix;
1837c478bd9Sstevel@tonic-gate sbd_board_t *sbp;
1847c478bd9Sstevel@tonic-gate sbd_io_stat_t *isp;
1857c478bd9Sstevel@tonic-gate sbd_io_unit_t *ip;
1867c478bd9Sstevel@tonic-gate sbd_istate_t dstate;
1877c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp;
1887c478bd9Sstevel@tonic-gate sbderror_t *ep;
1897c478bd9Sstevel@tonic-gate sbd_error_t *sep;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present.
1937c478bd9Sstevel@tonic-gate */
1947c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd);
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp);
1977c478bd9Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP);
1987c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp);
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate * Concurrent status and unconfigure, disconnect are allowed.
2027c478bd9Sstevel@tonic-gate * To prevent DR code from accessing stale dips, check the
2037c478bd9Sstevel@tonic-gate * present devset and access the dips with status lock held.
2047c478bd9Sstevel@tonic-gate * Disconnect and unconfigure code change dip state with
2057c478bd9Sstevel@tonic-gate * status lock (sb_slock) held.
2067c478bd9Sstevel@tonic-gate */
2077c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock);
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp);
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) {
2127c478bd9Sstevel@tonic-gate dev_info_t *dip;
2137c478bd9Sstevel@tonic-gate int unit;
2147c478bd9Sstevel@tonic-gate int namelen;
2157c478bd9Sstevel@tonic-gate int refcount = 0;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0)
2187c478bd9Sstevel@tonic-gate continue;
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * Check to make sure the io component is in a state
2217c478bd9Sstevel@tonic-gate * where its fully initialized.
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_IO, i) == SBD_STATE_EMPTY)
2247c478bd9Sstevel@tonic-gate continue;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i];
2277c478bd9Sstevel@tonic-gate if (dip == NULL)
2287c478bd9Sstevel@tonic-gate continue;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate isp = &dsp->d_io;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate bzero((caddr_t)isp, sizeof (*isp));
2337c478bd9Sstevel@tonic-gate namelen = sizeof (isp->is_name);
2347c478bd9Sstevel@tonic-gate (void) ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
2357c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, OBP_DEVICETYPE,
2367c478bd9Sstevel@tonic-gate (caddr_t)isp->is_name, &namelen);
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate isp->is_unit = sbdp_get_unit_num(hdp, dip);
2397c478bd9Sstevel@tonic-gate if (isp->is_unit < 0) {
2407c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE)
2417c478bd9Sstevel@tonic-gate continue;
2427c478bd9Sstevel@tonic-gate else {
2437c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp));
2447c478bd9Sstevel@tonic-gate break;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate unit = isp->is_unit;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate dstate = SBD_DEVICE_STATE(sbp, SBD_COMP_IO, unit);
2507c478bd9Sstevel@tonic-gate isp->is_ostate = ostate_cvt(dstate);
2517c478bd9Sstevel@tonic-gate isp->is_type = SBD_COMP_IO;
2527c478bd9Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit);
25325e8c5aaSvikram ip->sbi_cm.sbdev_cond = sbd_get_comp_cond(dip);
2547c478bd9Sstevel@tonic-gate isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond;
2557c478bd9Sstevel@tonic-gate isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy;
2567c478bd9Sstevel@tonic-gate isp->is_cm.c_time = ip->sbi_cm.sbdev_time;
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate /*
2607c478bd9Sstevel@tonic-gate * This is safe to do as unconfigure and disconnect
2617c478bd9Sstevel@tonic-gate * hold the status lock while changing dip state.
2627c478bd9Sstevel@tonic-gate */
2637c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, isp->is_pathname);
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate * We use a dummy handle in which to collect
2677c478bd9Sstevel@tonic-gate * the major numbers of unsafe devices.
2687c478bd9Sstevel@tonic-gate */
269*df3cd224SVijay S Balakrishna sbdp_check_devices(dip, &refcount, sep, NULL);
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate isp->is_referenced = (refcount == 0) ? 0 : 1;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate isp->is_unsafe_count = 0;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Reset error field since we don't care about
2777c478bd9Sstevel@tonic-gate * errors at this level. The unsafe devices
2787c478bd9Sstevel@tonic-gate * will be reported in the structure.
2797c478bd9Sstevel@tonic-gate */
2807c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NOERROR);
2817c478bd9Sstevel@tonic-gate ep->e_rsc[0] = '\0';
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate ix++;
2847c478bd9Sstevel@tonic-gate dsp++;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock);
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t));
2907c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp);
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate return (ix);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2967c478bd9Sstevel@tonic-gate int
sbd_io_cnt(sbd_handle_t * hp,sbd_devset_t devset)2977c478bd9Sstevel@tonic-gate sbd_io_cnt(sbd_handle_t *hp, sbd_devset_t devset)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate int i, ix;
3007c478bd9Sstevel@tonic-gate sbd_board_t *sbp;
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd);
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp);
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) {
3107c478bd9Sstevel@tonic-gate dev_info_t *dip;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0)
3137c478bd9Sstevel@tonic-gate continue;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i];
3167c478bd9Sstevel@tonic-gate if (dip == NULL)
3177c478bd9Sstevel@tonic-gate continue;
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate ix++;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate return (ix);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate int
sbd_check_io_refs(sbd_handle_t * hp,sbd_devlist_t devlist[],int devnum)3267c478bd9Sstevel@tonic-gate sbd_check_io_refs(sbd_handle_t *hp, sbd_devlist_t devlist[], int devnum)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate register int i, reftotal = 0;
3297c478bd9Sstevel@tonic-gate fn_t f = "sbd_check_io_refs";
3307c478bd9Sstevel@tonic-gate sbd_error_t *sep;
3317c478bd9Sstevel@tonic-gate sbderror_t *ep;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP);
3347c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp);
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) {
3377c478bd9Sstevel@tonic-gate dev_info_t *dip;
3387c478bd9Sstevel@tonic-gate int ref;
339*df3cd224SVijay S Balakrishna int refcount_non_gldv3;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip;
3427c478bd9Sstevel@tonic-gate ref = 0;
343*df3cd224SVijay S Balakrishna refcount_non_gldv3 = 0;
344*df3cd224SVijay S Balakrishna sbdp_check_devices(dip, &ref, sep, &refcount_non_gldv3);
345*df3cd224SVijay S Balakrishna ASSERT(refcount_non_gldv3 >= 0);
346*df3cd224SVijay S Balakrishna ASSERT(ref >= refcount_non_gldv3);
347*df3cd224SVijay S Balakrishna /*
348*df3cd224SVijay S Balakrishna * Ignore reference counts of non-gldv3 network devices
349*df3cd224SVijay S Balakrishna * as Crossbow creates reference counts for non-active
350*df3cd224SVijay S Balakrishna * (unplumbed) instances. Reference count check in
351*df3cd224SVijay S Balakrishna * detach() known to prevent device from detaching
352*df3cd224SVijay S Balakrishna * as necessary.
353*df3cd224SVijay S Balakrishna */
354*df3cd224SVijay S Balakrishna ref -= refcount_non_gldv3;
3557c478bd9Sstevel@tonic-gate if (ref) {
3567c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == 0) {
3577c478bd9Sstevel@tonic-gate SBD_GET_PERR(sep, ep);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate SBD_GET_PERR(sep, &devlist[i].dv_error);
3607c478bd9Sstevel@tonic-gate }
361*df3cd224SVijay S Balakrishna PR_IO("%s: dip(%s) ref = %d\n", f, ddi_get_name(dip), ref);
3627c478bd9Sstevel@tonic-gate reftotal += ref;
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t));
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate return (reftotal);
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate int
sbd_check_io_attached(dev_info_t * dip,void * arg)3717c478bd9Sstevel@tonic-gate sbd_check_io_attached(dev_info_t *dip, void *arg)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate dev_info_t **tdip;
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate tdip = (dev_info_t **)arg;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate if (dip == *tdip) {
3787c478bd9Sstevel@tonic-gate int state;
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate state = ddi_get_devstate(dip);
381737d277aScth if (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP)) {
3827c478bd9Sstevel@tonic-gate *tdip = NULL;
3837c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate int
sbd_pre_release_io(sbd_handle_t * hp,sbd_devlist_t * devlist,int devnum)3907c478bd9Sstevel@tonic-gate sbd_pre_release_io(sbd_handle_t *hp,
3917c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int devnum)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate fn_t f = "sbd_pre_release_io";
3947c478bd9Sstevel@tonic-gate int rv = 0;
3957c478bd9Sstevel@tonic-gate int i;
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate ASSERT(devnum > 0);
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate /* fail if any I/O devices are referenced */
4007c478bd9Sstevel@tonic-gate if ((rv = sbd_check_io_refs(hp, devlist, devnum)) > 0) {
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate * One of the devices may have failed check to see which
4037c478bd9Sstevel@tonic-gate * and set in the main handle
4047c478bd9Sstevel@tonic-gate */
4057c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) {
4067c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(&devlist[i].dv_error) != 0) {
4077c478bd9Sstevel@tonic-gate (void) sbd_set_err_in_hdl(hp,
4087c478bd9Sstevel@tonic-gate &devlist[i].dv_error);
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f);
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate return (rv);
4167c478bd9Sstevel@tonic-gate }
417