xref: /onnv-gate/usr/src/uts/i86pc/io/dr/dr_io.c (revision 12004:93f274d4a367)
1*12004Sjiang.liu@intel.com /*
2*12004Sjiang.liu@intel.com  * CDDL HEADER START
3*12004Sjiang.liu@intel.com  *
4*12004Sjiang.liu@intel.com  * The contents of this file are subject to the terms of the
5*12004Sjiang.liu@intel.com  * Common Development and Distribution License (the "License").
6*12004Sjiang.liu@intel.com  * You may not use this file except in compliance with the License.
7*12004Sjiang.liu@intel.com  *
8*12004Sjiang.liu@intel.com  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12004Sjiang.liu@intel.com  * or http://www.opensolaris.org/os/licensing.
10*12004Sjiang.liu@intel.com  * See the License for the specific language governing permissions
11*12004Sjiang.liu@intel.com  * and limitations under the License.
12*12004Sjiang.liu@intel.com  *
13*12004Sjiang.liu@intel.com  * When distributing Covered Code, include this CDDL HEADER in each
14*12004Sjiang.liu@intel.com  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12004Sjiang.liu@intel.com  * If applicable, add the following below this CDDL HEADER, with the
16*12004Sjiang.liu@intel.com  * fields enclosed by brackets "[]" replaced with your own identifying
17*12004Sjiang.liu@intel.com  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12004Sjiang.liu@intel.com  *
19*12004Sjiang.liu@intel.com  * CDDL HEADER END
20*12004Sjiang.liu@intel.com  */
21*12004Sjiang.liu@intel.com 
22*12004Sjiang.liu@intel.com /*
23*12004Sjiang.liu@intel.com  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*12004Sjiang.liu@intel.com  * Use is subject to license terms.
25*12004Sjiang.liu@intel.com  */
26*12004Sjiang.liu@intel.com 
27*12004Sjiang.liu@intel.com /*
28*12004Sjiang.liu@intel.com  * I/O support routines for DR
29*12004Sjiang.liu@intel.com  */
30*12004Sjiang.liu@intel.com 
31*12004Sjiang.liu@intel.com #include <sys/types.h>
32*12004Sjiang.liu@intel.com #include <sys/cmn_err.h>
33*12004Sjiang.liu@intel.com #include <sys/debug.h>
34*12004Sjiang.liu@intel.com #include <sys/errno.h>
35*12004Sjiang.liu@intel.com #include <sys/dditypes.h>
36*12004Sjiang.liu@intel.com #include <sys/ddi.h>
37*12004Sjiang.liu@intel.com #include <sys/sunddi.h>
38*12004Sjiang.liu@intel.com #include <sys/sunndi.h>
39*12004Sjiang.liu@intel.com #include <sys/ndi_impldefs.h>
40*12004Sjiang.liu@intel.com #include <sys/kmem.h>
41*12004Sjiang.liu@intel.com #include <sys/promif.h>
42*12004Sjiang.liu@intel.com #include <sys/sysmacros.h>
43*12004Sjiang.liu@intel.com #include <sys/archsystm.h>
44*12004Sjiang.liu@intel.com #include <sys/machsystm.h>
45*12004Sjiang.liu@intel.com 
46*12004Sjiang.liu@intel.com #include <sys/dr.h>
47*12004Sjiang.liu@intel.com #include <sys/dr_util.h>
48*12004Sjiang.liu@intel.com #include <sys/drmach.h>
49*12004Sjiang.liu@intel.com 
50*12004Sjiang.liu@intel.com void
dr_init_io_unit(dr_io_unit_t * ip)51*12004Sjiang.liu@intel.com dr_init_io_unit(dr_io_unit_t *ip)
52*12004Sjiang.liu@intel.com {
53*12004Sjiang.liu@intel.com 	dr_state_t	new_state;
54*12004Sjiang.liu@intel.com 
55*12004Sjiang.liu@intel.com 	if (DR_DEV_IS_ATTACHED(&ip->sbi_cm)) {
56*12004Sjiang.liu@intel.com 		new_state = DR_STATE_CONFIGURED;
57*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
58*12004Sjiang.liu@intel.com 	} else if (DR_DEV_IS_PRESENT(&ip->sbi_cm)) {
59*12004Sjiang.liu@intel.com 		new_state = DR_STATE_CONNECTED;
60*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
61*12004Sjiang.liu@intel.com 	} else {
62*12004Sjiang.liu@intel.com 		new_state = DR_STATE_EMPTY;
63*12004Sjiang.liu@intel.com 	}
64*12004Sjiang.liu@intel.com 	dr_device_transition(&ip->sbi_cm, new_state);
65*12004Sjiang.liu@intel.com }
66*12004Sjiang.liu@intel.com 
67*12004Sjiang.liu@intel.com /*ARGSUSED*/
68*12004Sjiang.liu@intel.com void
dr_attach_io(dr_handle_t * hp,dr_common_unit_t * cp)69*12004Sjiang.liu@intel.com dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp)
70*12004Sjiang.liu@intel.com {
71*12004Sjiang.liu@intel.com 	sbd_error_t *err;
72*12004Sjiang.liu@intel.com 
73*12004Sjiang.liu@intel.com 	dr_lock_status(hp->h_bd);
74*12004Sjiang.liu@intel.com 	err = drmach_configure(cp->sbdev_id, 0);
75*12004Sjiang.liu@intel.com 	dr_unlock_status(hp->h_bd);
76*12004Sjiang.liu@intel.com 
77*12004Sjiang.liu@intel.com 	if (!err)
78*12004Sjiang.liu@intel.com 		err = drmach_io_post_attach(cp->sbdev_id);
79*12004Sjiang.liu@intel.com 
80*12004Sjiang.liu@intel.com 	if (err)
81*12004Sjiang.liu@intel.com 		DRERR_SET_C(&cp->sbdev_error, &err);
82*12004Sjiang.liu@intel.com }
83*12004Sjiang.liu@intel.com 
84*12004Sjiang.liu@intel.com /*
85*12004Sjiang.liu@intel.com  * remove device nodes for the branch indicated by cp
86*12004Sjiang.liu@intel.com  */
87*12004Sjiang.liu@intel.com /*ARGSUSED*/
88*12004Sjiang.liu@intel.com void
dr_detach_io(dr_handle_t * hp,dr_common_unit_t * cp)89*12004Sjiang.liu@intel.com dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp)
90*12004Sjiang.liu@intel.com {
91*12004Sjiang.liu@intel.com 	sbd_error_t *err;
92*12004Sjiang.liu@intel.com 
93*12004Sjiang.liu@intel.com 	err = drmach_unconfigure(cp->sbdev_id, 0);
94*12004Sjiang.liu@intel.com 
95*12004Sjiang.liu@intel.com 	if (!err)
96*12004Sjiang.liu@intel.com 		err = drmach_unconfigure(cp->sbdev_id, DEVI_BRANCH_DESTROY);
97*12004Sjiang.liu@intel.com 
98*12004Sjiang.liu@intel.com 	if (!err)
99*12004Sjiang.liu@intel.com 		err = drmach_io_post_release(cp->sbdev_id);
100*12004Sjiang.liu@intel.com 
101*12004Sjiang.liu@intel.com 	if (err) {
102*12004Sjiang.liu@intel.com 		dr_device_transition(cp, DR_STATE_CONFIGURED);
103*12004Sjiang.liu@intel.com 		DRERR_SET_C(&cp->sbdev_error, &err);
104*12004Sjiang.liu@intel.com 	}
105*12004Sjiang.liu@intel.com }
106*12004Sjiang.liu@intel.com 
107*12004Sjiang.liu@intel.com /*ARGSUSED*/
108*12004Sjiang.liu@intel.com int
dr_disconnect_io(dr_io_unit_t * ip)109*12004Sjiang.liu@intel.com dr_disconnect_io(dr_io_unit_t *ip)
110*12004Sjiang.liu@intel.com {
111*12004Sjiang.liu@intel.com 	return (0);
112*12004Sjiang.liu@intel.com }
113*12004Sjiang.liu@intel.com 
114*12004Sjiang.liu@intel.com /*ARGSUSED*/
115*12004Sjiang.liu@intel.com int
dr_pre_attach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)116*12004Sjiang.liu@intel.com dr_pre_attach_io(dr_handle_t *hp,
117*12004Sjiang.liu@intel.com 	dr_common_unit_t **devlist, int devnum)
118*12004Sjiang.liu@intel.com {
119*12004Sjiang.liu@intel.com 	int		d;
120*12004Sjiang.liu@intel.com 
121*12004Sjiang.liu@intel.com 	for (d = 0; d < devnum; d++) {
122*12004Sjiang.liu@intel.com 		dr_common_unit_t *cp = devlist[d];
123*12004Sjiang.liu@intel.com 
124*12004Sjiang.liu@intel.com 		cmn_err(CE_CONT, "OS configure %s", cp->sbdev_path);
125*12004Sjiang.liu@intel.com 	}
126*12004Sjiang.liu@intel.com 
127*12004Sjiang.liu@intel.com 	return (0);
128*12004Sjiang.liu@intel.com }
129*12004Sjiang.liu@intel.com 
130*12004Sjiang.liu@intel.com /*ARGSUSED*/
131*12004Sjiang.liu@intel.com int
dr_post_attach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)132*12004Sjiang.liu@intel.com dr_post_attach_io(dr_handle_t *hp,
133*12004Sjiang.liu@intel.com 	dr_common_unit_t **devlist, int devnum)
134*12004Sjiang.liu@intel.com {
135*12004Sjiang.liu@intel.com 	return (0);
136*12004Sjiang.liu@intel.com }
137*12004Sjiang.liu@intel.com 
138*12004Sjiang.liu@intel.com static int
dr_check_io_refs(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)139*12004Sjiang.liu@intel.com dr_check_io_refs(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
140*12004Sjiang.liu@intel.com {
141*12004Sjiang.liu@intel.com 	register int	i, reftotal = 0;
142*12004Sjiang.liu@intel.com 	static fn_t	f = "dr_check_io_refs";
143*12004Sjiang.liu@intel.com 
144*12004Sjiang.liu@intel.com 	for (i = 0; i < devnum; i++) {
145*12004Sjiang.liu@intel.com 		dr_io_unit_t	*ip = (dr_io_unit_t *)devlist[i];
146*12004Sjiang.liu@intel.com 		dev_info_t	*dip;
147*12004Sjiang.liu@intel.com 		int		ref;
148*12004Sjiang.liu@intel.com 		int		refcount_non_gldv3;
149*12004Sjiang.liu@intel.com 		sbd_error_t	*err;
150*12004Sjiang.liu@intel.com 
151*12004Sjiang.liu@intel.com 		err = drmach_get_dip(ip->sbi_cm.sbdev_id, &dip);
152*12004Sjiang.liu@intel.com 		if (err)
153*12004Sjiang.liu@intel.com 			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
154*12004Sjiang.liu@intel.com 		else if (dip != NULL) {
155*12004Sjiang.liu@intel.com 			ref = 0;
156*12004Sjiang.liu@intel.com 			refcount_non_gldv3 = 0;
157*12004Sjiang.liu@intel.com 			ASSERT(e_ddi_branch_held(dip));
158*12004Sjiang.liu@intel.com 			dr_check_devices(dip, &ref, hp, NULL, NULL,
159*12004Sjiang.liu@intel.com 			    0, &refcount_non_gldv3);
160*12004Sjiang.liu@intel.com 			ASSERT(refcount_non_gldv3 >= 0);
161*12004Sjiang.liu@intel.com 			ASSERT(ref >= refcount_non_gldv3);
162*12004Sjiang.liu@intel.com 			/*
163*12004Sjiang.liu@intel.com 			 * Ignore reference counts of non-gldv3 network devices
164*12004Sjiang.liu@intel.com 			 * as Crossbow creates reference counts for non-active
165*12004Sjiang.liu@intel.com 			 * (unplumbed) instances.  Reference count check in
166*12004Sjiang.liu@intel.com 			 * detach() known to prevent device from detaching
167*12004Sjiang.liu@intel.com 			 * as necessary.
168*12004Sjiang.liu@intel.com 			 */
169*12004Sjiang.liu@intel.com 			ref -= refcount_non_gldv3;
170*12004Sjiang.liu@intel.com 			hp->h_err = NULL;
171*12004Sjiang.liu@intel.com 			if (ref) {
172*12004Sjiang.liu@intel.com 				dr_dev_err(CE_WARN, &ip->sbi_cm, ESBD_BUSY);
173*12004Sjiang.liu@intel.com 			}
174*12004Sjiang.liu@intel.com 			PR_IO("%s: dip(%s) ref = %d\n",
175*12004Sjiang.liu@intel.com 			    f, ddi_get_name(dip), ref);
176*12004Sjiang.liu@intel.com 			reftotal += ref;
177*12004Sjiang.liu@intel.com 		} else {
178*12004Sjiang.liu@intel.com 			PR_IO("%s: NO dip for id (0x%x)\n",
179*12004Sjiang.liu@intel.com 			    f, (uint_t)(uintptr_t)ip->sbi_cm.sbdev_id);
180*12004Sjiang.liu@intel.com 		}
181*12004Sjiang.liu@intel.com 	}
182*12004Sjiang.liu@intel.com 
183*12004Sjiang.liu@intel.com 	return (reftotal);
184*12004Sjiang.liu@intel.com }
185*12004Sjiang.liu@intel.com 
186*12004Sjiang.liu@intel.com int
dr_pre_release_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)187*12004Sjiang.liu@intel.com dr_pre_release_io(dr_handle_t *hp,
188*12004Sjiang.liu@intel.com 	dr_common_unit_t **devlist, int devnum)
189*12004Sjiang.liu@intel.com {
190*12004Sjiang.liu@intel.com 	static fn_t	f = "dr_pre_release_io";
191*12004Sjiang.liu@intel.com 	int	d;
192*12004Sjiang.liu@intel.com 
193*12004Sjiang.liu@intel.com 	ASSERT(devnum > 0);
194*12004Sjiang.liu@intel.com 
195*12004Sjiang.liu@intel.com 	/* fail if any I/O device pre-release fails */
196*12004Sjiang.liu@intel.com 	for (d = 0; d < devnum; d++) {
197*12004Sjiang.liu@intel.com 		dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
198*12004Sjiang.liu@intel.com 
199*12004Sjiang.liu@intel.com 		if ((hp->h_err = drmach_io_pre_release(
200*12004Sjiang.liu@intel.com 		    ip->sbi_cm.sbdev_id)) != 0) {
201*12004Sjiang.liu@intel.com 			return (-1);
202*12004Sjiang.liu@intel.com 		}
203*12004Sjiang.liu@intel.com 	}
204*12004Sjiang.liu@intel.com 
205*12004Sjiang.liu@intel.com 	for (d = 0; d < devnum; d++) {
206*12004Sjiang.liu@intel.com 		dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
207*12004Sjiang.liu@intel.com 		sbd_error_t *err;
208*12004Sjiang.liu@intel.com 
209*12004Sjiang.liu@intel.com 		err = drmach_release(ip->sbi_cm.sbdev_id);
210*12004Sjiang.liu@intel.com 		if (err) {
211*12004Sjiang.liu@intel.com 			DRERR_SET_C(&ip->sbi_cm.sbdev_error,
212*12004Sjiang.liu@intel.com 			    &err);
213*12004Sjiang.liu@intel.com 			return (-1);
214*12004Sjiang.liu@intel.com 		}
215*12004Sjiang.liu@intel.com 	}
216*12004Sjiang.liu@intel.com 
217*12004Sjiang.liu@intel.com 	/* fail if any I/O devices are still referenced */
218*12004Sjiang.liu@intel.com 	if (dr_check_io_refs(hp, devlist, devnum) > 0) {
219*12004Sjiang.liu@intel.com 		PR_IO("%s: failed - I/O devices ref'd\n", f);
220*12004Sjiang.liu@intel.com 
221*12004Sjiang.liu@intel.com 		/* recover before return error */
222*12004Sjiang.liu@intel.com 		for (d = 0; d < devnum; d++) {
223*12004Sjiang.liu@intel.com 			dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
224*12004Sjiang.liu@intel.com 			sbd_error_t *err;
225*12004Sjiang.liu@intel.com 			err = drmach_io_unrelease(ip->sbi_cm.sbdev_id);
226*12004Sjiang.liu@intel.com 			if (err) {
227*12004Sjiang.liu@intel.com 				DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
228*12004Sjiang.liu@intel.com 				return (-1);
229*12004Sjiang.liu@intel.com 			}
230*12004Sjiang.liu@intel.com 		}
231*12004Sjiang.liu@intel.com 		return (-1);
232*12004Sjiang.liu@intel.com 	}
233*12004Sjiang.liu@intel.com 	return (0);
234*12004Sjiang.liu@intel.com }
235*12004Sjiang.liu@intel.com 
236*12004Sjiang.liu@intel.com /*ARGSUSED*/
237*12004Sjiang.liu@intel.com int
dr_pre_detach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)238*12004Sjiang.liu@intel.com dr_pre_detach_io(dr_handle_t *hp,
239*12004Sjiang.liu@intel.com 	dr_common_unit_t **devlist, int devnum)
240*12004Sjiang.liu@intel.com {
241*12004Sjiang.liu@intel.com 	int		d;
242*12004Sjiang.liu@intel.com 
243*12004Sjiang.liu@intel.com 	ASSERT(devnum > 0);
244*12004Sjiang.liu@intel.com 
245*12004Sjiang.liu@intel.com 	for (d = 0; d < devnum; d++) {
246*12004Sjiang.liu@intel.com 		dr_common_unit_t *cp = devlist[d];
247*12004Sjiang.liu@intel.com 
248*12004Sjiang.liu@intel.com 		cmn_err(CE_CONT, "OS unconfigure %s", cp->sbdev_path);
249*12004Sjiang.liu@intel.com 	}
250*12004Sjiang.liu@intel.com 
251*12004Sjiang.liu@intel.com 	return (0);
252*12004Sjiang.liu@intel.com }
253*12004Sjiang.liu@intel.com 
254*12004Sjiang.liu@intel.com /*ARGSUSED*/
255*12004Sjiang.liu@intel.com int
dr_post_detach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)256*12004Sjiang.liu@intel.com dr_post_detach_io(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
257*12004Sjiang.liu@intel.com {
258*12004Sjiang.liu@intel.com 	register int	i;
259*12004Sjiang.liu@intel.com 	int		rv = 0;
260*12004Sjiang.liu@intel.com 	static fn_t	f = "dr_post_detach_io";
261*12004Sjiang.liu@intel.com 
262*12004Sjiang.liu@intel.com 	ASSERT(devnum > 0);
263*12004Sjiang.liu@intel.com 	for (i = 0; i < devnum; i++) {
264*12004Sjiang.liu@intel.com 		dr_common_unit_t	*cp = devlist[i];
265*12004Sjiang.liu@intel.com 		if (cp->sbdev_error != NULL) {
266*12004Sjiang.liu@intel.com 			PR_IO("%s: Failed\n", f);
267*12004Sjiang.liu@intel.com 			rv = -1;
268*12004Sjiang.liu@intel.com 			break;
269*12004Sjiang.liu@intel.com 		}
270*12004Sjiang.liu@intel.com 	}
271*12004Sjiang.liu@intel.com 	return (rv);
272*12004Sjiang.liu@intel.com }
273*12004Sjiang.liu@intel.com 
274*12004Sjiang.liu@intel.com static void
dr_get_comp_cond(dr_io_unit_t * ip,dev_info_t * dip)275*12004Sjiang.liu@intel.com dr_get_comp_cond(dr_io_unit_t *ip, dev_info_t *dip)
276*12004Sjiang.liu@intel.com {
277*12004Sjiang.liu@intel.com 	if (dip == NULL) {
278*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_UNKNOWN;
279*12004Sjiang.liu@intel.com 		return;
280*12004Sjiang.liu@intel.com 	}
281*12004Sjiang.liu@intel.com 
282*12004Sjiang.liu@intel.com 	if (DEVI(dip)->devi_flags & DEVI_RETIRED) {
283*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_FAILED;
284*12004Sjiang.liu@intel.com 		return;
285*12004Sjiang.liu@intel.com 	}
286*12004Sjiang.liu@intel.com 
287*12004Sjiang.liu@intel.com 	if (DR_DEV_IS_ATTACHED(&ip->sbi_cm)) {
288*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
289*12004Sjiang.liu@intel.com 	} else if (DR_DEV_IS_PRESENT(&ip->sbi_cm)) {
290*12004Sjiang.liu@intel.com 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
291*12004Sjiang.liu@intel.com 	}
292*12004Sjiang.liu@intel.com }
293*12004Sjiang.liu@intel.com 
294*12004Sjiang.liu@intel.com int
dr_io_status(dr_handle_t * hp,dr_devset_t devset,sbd_dev_stat_t * dsp)295*12004Sjiang.liu@intel.com dr_io_status(dr_handle_t *hp, dr_devset_t devset, sbd_dev_stat_t *dsp)
296*12004Sjiang.liu@intel.com {
297*12004Sjiang.liu@intel.com 	int		i, ix;
298*12004Sjiang.liu@intel.com 	dr_board_t	*bp;
299*12004Sjiang.liu@intel.com 	sbd_io_stat_t	*isp;
300*12004Sjiang.liu@intel.com 	dr_io_unit_t	*ip;
301*12004Sjiang.liu@intel.com 
302*12004Sjiang.liu@intel.com 	bp = hp->h_bd;
303*12004Sjiang.liu@intel.com 
304*12004Sjiang.liu@intel.com 	/*
305*12004Sjiang.liu@intel.com 	 * Only look for requested devices that are actually present.
306*12004Sjiang.liu@intel.com 	 */
307*12004Sjiang.liu@intel.com 	devset &= DR_DEVS_PRESENT(bp);
308*12004Sjiang.liu@intel.com 
309*12004Sjiang.liu@intel.com 	for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) {
310*12004Sjiang.liu@intel.com 		drmachid_t	 id;
311*12004Sjiang.liu@intel.com 		dev_info_t	*dip;
312*12004Sjiang.liu@intel.com 		sbd_error_t	*err;
313*12004Sjiang.liu@intel.com 		drmach_status_t	 pstat;
314*12004Sjiang.liu@intel.com 
315*12004Sjiang.liu@intel.com 		if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0)
316*12004Sjiang.liu@intel.com 			continue;
317*12004Sjiang.liu@intel.com 
318*12004Sjiang.liu@intel.com 		ip = dr_get_io_unit(bp, i);
319*12004Sjiang.liu@intel.com 
320*12004Sjiang.liu@intel.com 		if (ip->sbi_cm.sbdev_state == DR_STATE_EMPTY) {
321*12004Sjiang.liu@intel.com 			/* present, but not fully initialized */
322*12004Sjiang.liu@intel.com 			continue;
323*12004Sjiang.liu@intel.com 		}
324*12004Sjiang.liu@intel.com 
325*12004Sjiang.liu@intel.com 		id = ip->sbi_cm.sbdev_id;
326*12004Sjiang.liu@intel.com 		if (id == (drmachid_t)0)
327*12004Sjiang.liu@intel.com 			continue;
328*12004Sjiang.liu@intel.com 
329*12004Sjiang.liu@intel.com 		err = drmach_status(ip->sbi_cm.sbdev_id, &pstat);
330*12004Sjiang.liu@intel.com 		if (err) {
331*12004Sjiang.liu@intel.com 			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
332*12004Sjiang.liu@intel.com 			return (-1);
333*12004Sjiang.liu@intel.com 		}
334*12004Sjiang.liu@intel.com 
335*12004Sjiang.liu@intel.com 		dip = NULL;
336*12004Sjiang.liu@intel.com 		err = drmach_get_dip(id, &dip);
337*12004Sjiang.liu@intel.com 		if (err) {
338*12004Sjiang.liu@intel.com 			/* catch this in debug kernels */
339*12004Sjiang.liu@intel.com 			ASSERT(0);
340*12004Sjiang.liu@intel.com 
341*12004Sjiang.liu@intel.com 			sbd_err_clear(&err);
342*12004Sjiang.liu@intel.com 			continue;
343*12004Sjiang.liu@intel.com 		}
344*12004Sjiang.liu@intel.com 
345*12004Sjiang.liu@intel.com 		isp = &dsp->d_io;
346*12004Sjiang.liu@intel.com 		bzero((caddr_t)isp, sizeof (*isp));
347*12004Sjiang.liu@intel.com 
348*12004Sjiang.liu@intel.com 		isp->is_cm.c_id.c_type = ip->sbi_cm.sbdev_type;
349*12004Sjiang.liu@intel.com 		isp->is_cm.c_id.c_unit = ip->sbi_cm.sbdev_unum;
350*12004Sjiang.liu@intel.com 		(void) strlcpy(isp->is_cm.c_id.c_name, pstat.type,
351*12004Sjiang.liu@intel.com 		    sizeof (isp->is_cm.c_id.c_name));
352*12004Sjiang.liu@intel.com 
353*12004Sjiang.liu@intel.com 		dr_get_comp_cond(ip, dip);
354*12004Sjiang.liu@intel.com 		isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond;
355*12004Sjiang.liu@intel.com 		isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy | pstat.busy;
356*12004Sjiang.liu@intel.com 		isp->is_cm.c_time = ip->sbi_cm.sbdev_time;
357*12004Sjiang.liu@intel.com 		isp->is_cm.c_ostate = ip->sbi_cm.sbdev_ostate;
358*12004Sjiang.liu@intel.com 		isp->is_cm.c_sflags = 0;
359*12004Sjiang.liu@intel.com 
360*12004Sjiang.liu@intel.com 		if (dip == NULL) {
361*12004Sjiang.liu@intel.com 			isp->is_pathname[0] = '\0';
362*12004Sjiang.liu@intel.com 			isp->is_referenced = 0;
363*12004Sjiang.liu@intel.com 			isp->is_unsafe_count = 0;
364*12004Sjiang.liu@intel.com 		} else {
365*12004Sjiang.liu@intel.com 			int		refcount = 0, idx = 0;
366*12004Sjiang.liu@intel.com 			uint64_t	unsafe_devs[SBD_MAX_UNSAFE];
367*12004Sjiang.liu@intel.com 
368*12004Sjiang.liu@intel.com 			ASSERT(e_ddi_branch_held(dip));
369*12004Sjiang.liu@intel.com 			(void) ddi_pathname(dip, isp->is_pathname);
370*12004Sjiang.liu@intel.com 
371*12004Sjiang.liu@intel.com 			/* check reference and unsafe counts on devices */
372*12004Sjiang.liu@intel.com 			isp->is_unsafe_count = 0;
373*12004Sjiang.liu@intel.com 			dr_check_devices(dip, &refcount, hp, unsafe_devs,
374*12004Sjiang.liu@intel.com 			    &idx, SBD_MAX_UNSAFE, NULL);
375*12004Sjiang.liu@intel.com 			while (idx > 0) {
376*12004Sjiang.liu@intel.com 				isp->is_unsafe_list[idx-1] = unsafe_devs[idx-1];
377*12004Sjiang.liu@intel.com 				--idx;
378*12004Sjiang.liu@intel.com 			}
379*12004Sjiang.liu@intel.com 
380*12004Sjiang.liu@intel.com 			isp->is_referenced = (refcount == 0) ? 0 : 1;
381*12004Sjiang.liu@intel.com 
382*12004Sjiang.liu@intel.com 			hp->h_err = NULL;
383*12004Sjiang.liu@intel.com 		}
384*12004Sjiang.liu@intel.com 		ix++;
385*12004Sjiang.liu@intel.com 		dsp++;
386*12004Sjiang.liu@intel.com 	}
387*12004Sjiang.liu@intel.com 
388*12004Sjiang.liu@intel.com 	return (ix);
389*12004Sjiang.liu@intel.com }
390