xref: /onnv-gate/usr/src/lib/storage/liba5k/common/diag.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM 
27*7836SJohn.Forte@Sun.COM /*LINTLIBRARY*/
28*7836SJohn.Forte@Sun.COM 
29*7836SJohn.Forte@Sun.COM 
30*7836SJohn.Forte@Sun.COM /*
31*7836SJohn.Forte@Sun.COM  *	This module is part of the photon library
32*7836SJohn.Forte@Sun.COM  */
33*7836SJohn.Forte@Sun.COM 
34*7836SJohn.Forte@Sun.COM /*
35*7836SJohn.Forte@Sun.COM  * I18N message number ranges
36*7836SJohn.Forte@Sun.COM  *  This file: 8000 - 8499
37*7836SJohn.Forte@Sun.COM  *  Shared common messages: 1 - 1999
38*7836SJohn.Forte@Sun.COM  */
39*7836SJohn.Forte@Sun.COM 
40*7836SJohn.Forte@Sun.COM /*	Includes	*/
41*7836SJohn.Forte@Sun.COM #include	<stdlib.h>
42*7836SJohn.Forte@Sun.COM #include	<stdio.h>
43*7836SJohn.Forte@Sun.COM #include	<sys/file.h>
44*7836SJohn.Forte@Sun.COM #include	<sys/types.h>
45*7836SJohn.Forte@Sun.COM #include	<sys/param.h>
46*7836SJohn.Forte@Sun.COM #include	<fcntl.h>
47*7836SJohn.Forte@Sun.COM #include	<unistd.h>
48*7836SJohn.Forte@Sun.COM #include	<errno.h>
49*7836SJohn.Forte@Sun.COM #include	<string.h>
50*7836SJohn.Forte@Sun.COM #include	<sys/scsi/scsi.h>
51*7836SJohn.Forte@Sun.COM #include	<nl_types.h>
52*7836SJohn.Forte@Sun.COM #include	<strings.h>
53*7836SJohn.Forte@Sun.COM #include	<sys/ddi.h>	/* for max */
54*7836SJohn.Forte@Sun.COM #include	<l_common.h>
55*7836SJohn.Forte@Sun.COM #include	<stgcom.h>
56*7836SJohn.Forte@Sun.COM #include	<l_error.h>
57*7836SJohn.Forte@Sun.COM #include	<a_state.h>
58*7836SJohn.Forte@Sun.COM #include	<a5k.h>
59*7836SJohn.Forte@Sun.COM 
60*7836SJohn.Forte@Sun.COM 
61*7836SJohn.Forte@Sun.COM 
62*7836SJohn.Forte@Sun.COM /*	Defines		*/
63*7836SJohn.Forte@Sun.COM #define	VERBPRINT	if (verbose) (void) printf
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM 
66*7836SJohn.Forte@Sun.COM /*
67*7836SJohn.Forte@Sun.COM  * take all paths supplied by dl offline.
68*7836SJohn.Forte@Sun.COM  *
69*7836SJohn.Forte@Sun.COM  * RETURNS:
70*7836SJohn.Forte@Sun.COM  *	0 = No error.
71*7836SJohn.Forte@Sun.COM  *	*bsy_res_flag_p: 1 = The device is "busy".
72*7836SJohn.Forte@Sun.COM  *
73*7836SJohn.Forte@Sun.COM  * In pre-2.6 we just return success
74*7836SJohn.Forte@Sun.COM  */
75*7836SJohn.Forte@Sun.COM static int
d_offline_drive(struct dlist * dl,int * bsy_res_flag_p,int verbose)76*7836SJohn.Forte@Sun.COM d_offline_drive(struct dlist *dl, int *bsy_res_flag_p, int verbose)
77*7836SJohn.Forte@Sun.COM {
78*7836SJohn.Forte@Sun.COM char			dev_path1[MAXPATHLEN];
79*7836SJohn.Forte@Sun.COM devctl_hdl_t		devhdl;
80*7836SJohn.Forte@Sun.COM 
81*7836SJohn.Forte@Sun.COM 
82*7836SJohn.Forte@Sun.COM 	/* for each path attempt to take it offline */
83*7836SJohn.Forte@Sun.COM 	for (; dl != NULL; dl = dl->next) {
84*7836SJohn.Forte@Sun.COM 
85*7836SJohn.Forte@Sun.COM 		/* save a copy of the pathname */
86*7836SJohn.Forte@Sun.COM 		(void) strcpy(dev_path1, dl->dev_path);
87*7836SJohn.Forte@Sun.COM 
88*7836SJohn.Forte@Sun.COM 		/* attempt to acquire the device */
89*7836SJohn.Forte@Sun.COM 		if ((devhdl = devctl_device_acquire(dev_path1,
90*7836SJohn.Forte@Sun.COM 			DC_EXCL)) == NULL) {
91*7836SJohn.Forte@Sun.COM 			if (errno != EBUSY) {
92*7836SJohn.Forte@Sun.COM 				return (L_ACQUIRE_FAIL);
93*7836SJohn.Forte@Sun.COM 			}
94*7836SJohn.Forte@Sun.COM 		}
95*7836SJohn.Forte@Sun.COM 
96*7836SJohn.Forte@Sun.COM 		/* attempt to offline the drive */
97*7836SJohn.Forte@Sun.COM 		if (devctl_device_offline(devhdl) != 0) {
98*7836SJohn.Forte@Sun.COM 			*bsy_res_flag_p = 1;
99*7836SJohn.Forte@Sun.COM 			(void) devctl_release(devhdl);
100*7836SJohn.Forte@Sun.COM 			return (0);
101*7836SJohn.Forte@Sun.COM 		}
102*7836SJohn.Forte@Sun.COM 
103*7836SJohn.Forte@Sun.COM 		E_DPRINTF("  d_offline_drive: Offline succeeded:/n    "
104*7836SJohn.Forte@Sun.COM 			"%s\n", dev_path1);
105*7836SJohn.Forte@Sun.COM 		/* offline succeeded -- release handle acquired above */
106*7836SJohn.Forte@Sun.COM 		(void) devctl_release(devhdl);
107*7836SJohn.Forte@Sun.COM 	}
108*7836SJohn.Forte@Sun.COM 	return (0);
109*7836SJohn.Forte@Sun.COM }
110*7836SJohn.Forte@Sun.COM 
111*7836SJohn.Forte@Sun.COM 
112*7836SJohn.Forte@Sun.COM 
113*7836SJohn.Forte@Sun.COM 
114*7836SJohn.Forte@Sun.COM /*
115*7836SJohn.Forte@Sun.COM  * Check to see if any of the disks that are attached
116*7836SJohn.Forte@Sun.COM  * to the selected port on this backplane are reserved or busy.
117*7836SJohn.Forte@Sun.COM  *
118*7836SJohn.Forte@Sun.COM  * INPUTS:
119*7836SJohn.Forte@Sun.COM  * RETURNS:
120*7836SJohn.Forte@Sun.COM  *	0 = No error.
121*7836SJohn.Forte@Sun.COM  *	*bsy_res_flag_p: 1 = The device is "busy".
122*7836SJohn.Forte@Sun.COM  */
123*7836SJohn.Forte@Sun.COM 
124*7836SJohn.Forte@Sun.COM int
l_check_busy_reserv_bp(char * ses_path,int front_flag,int port_a_flag,int * bsy_res_flag_p,int verbose)125*7836SJohn.Forte@Sun.COM l_check_busy_reserv_bp(char *ses_path, int front_flag,
126*7836SJohn.Forte@Sun.COM 	int port_a_flag, int *bsy_res_flag_p, int verbose)
127*7836SJohn.Forte@Sun.COM {
128*7836SJohn.Forte@Sun.COM int	err, i;
129*7836SJohn.Forte@Sun.COM L_state		*l_state = NULL;
130*7836SJohn.Forte@Sun.COM struct dlist	*p_list;
131*7836SJohn.Forte@Sun.COM 
132*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
133*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
134*7836SJohn.Forte@Sun.COM 	}
135*7836SJohn.Forte@Sun.COM 
136*7836SJohn.Forte@Sun.COM 	if (err = l_get_status(ses_path, l_state, verbose)) {
137*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
138*7836SJohn.Forte@Sun.COM 		return (err);
139*7836SJohn.Forte@Sun.COM 	}
140*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)l_state->total_num_drv/2; i++) {
141*7836SJohn.Forte@Sun.COM 		if ((front_flag &&
142*7836SJohn.Forte@Sun.COM 	(l_state->drv_front[i].g_disk_state.d_state_flags[port_a_flag] &
143*7836SJohn.Forte@Sun.COM 			L_RESERVED)) || (!front_flag &&
144*7836SJohn.Forte@Sun.COM 	(l_state->drv_rear[i].g_disk_state.d_state_flags[port_a_flag] &
145*7836SJohn.Forte@Sun.COM 			L_RESERVED))) {
146*7836SJohn.Forte@Sun.COM 			*bsy_res_flag_p = 1;
147*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
148*7836SJohn.Forte@Sun.COM 			return (0);
149*7836SJohn.Forte@Sun.COM 		}
150*7836SJohn.Forte@Sun.COM 	}
151*7836SJohn.Forte@Sun.COM 
152*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)l_state->total_num_drv/2; i++) {
153*7836SJohn.Forte@Sun.COM 		/* Get list of all paths to the requested port. */
154*7836SJohn.Forte@Sun.COM 		if (front_flag) {
155*7836SJohn.Forte@Sun.COM 			if (port_a_flag) {
156*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
157*7836SJohn.Forte@Sun.COM 				l_state->drv_front[i].g_disk_state.port_a_wwn_s,
158*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
159*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
160*7836SJohn.Forte@Sun.COM 					return (err);
161*7836SJohn.Forte@Sun.COM 				}
162*7836SJohn.Forte@Sun.COM 			} else {
163*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
164*7836SJohn.Forte@Sun.COM 				l_state->drv_front[i].g_disk_state.port_b_wwn_s,
165*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
166*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
167*7836SJohn.Forte@Sun.COM 					return (err);
168*7836SJohn.Forte@Sun.COM 				}
169*7836SJohn.Forte@Sun.COM 			}
170*7836SJohn.Forte@Sun.COM 		} else {
171*7836SJohn.Forte@Sun.COM 			if (port_a_flag) {
172*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
173*7836SJohn.Forte@Sun.COM 				l_state->drv_rear[i].g_disk_state.port_a_wwn_s,
174*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
175*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
176*7836SJohn.Forte@Sun.COM 					return (err);
177*7836SJohn.Forte@Sun.COM 				}
178*7836SJohn.Forte@Sun.COM 			} else {
179*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
180*7836SJohn.Forte@Sun.COM 				l_state->drv_rear[i].g_disk_state.port_b_wwn_s,
181*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
182*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
183*7836SJohn.Forte@Sun.COM 					return (err);
184*7836SJohn.Forte@Sun.COM 				}
185*7836SJohn.Forte@Sun.COM 			}
186*7836SJohn.Forte@Sun.COM 		}
187*7836SJohn.Forte@Sun.COM 		if (err = d_offline_drive(p_list,
188*7836SJohn.Forte@Sun.COM 			bsy_res_flag_p, verbose)) {
189*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(p_list);
190*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
191*7836SJohn.Forte@Sun.COM 			return (err);
192*7836SJohn.Forte@Sun.COM 		}
193*7836SJohn.Forte@Sun.COM 		(void) g_free_multipath(p_list);
194*7836SJohn.Forte@Sun.COM 	}
195*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
196*7836SJohn.Forte@Sun.COM 	return (0);
197*7836SJohn.Forte@Sun.COM }
198*7836SJohn.Forte@Sun.COM 
199*7836SJohn.Forte@Sun.COM 
200*7836SJohn.Forte@Sun.COM 
201*7836SJohn.Forte@Sun.COM /*
202*7836SJohn.Forte@Sun.COM  * Request the enclosure services controller (IB)
203*7836SJohn.Forte@Sun.COM  * to set the LRC (Loop Redundancy Circuit) to the
204*7836SJohn.Forte@Sun.COM  * bypassed/enabled state for the backplane specified by
205*7836SJohn.Forte@Sun.COM  * the a and f flag and the enclosure or pathname.
206*7836SJohn.Forte@Sun.COM  */
207*7836SJohn.Forte@Sun.COM int
l_bp_bypass_enable(char * ses_path,int bypass_flag,int port_a_flag,int front_flag,int force_flag,int verbose)208*7836SJohn.Forte@Sun.COM l_bp_bypass_enable(char *ses_path, int bypass_flag, int port_a_flag,
209*7836SJohn.Forte@Sun.COM 	int front_flag, int force_flag, int verbose)
210*7836SJohn.Forte@Sun.COM {
211*7836SJohn.Forte@Sun.COM 
212*7836SJohn.Forte@Sun.COM int		fd, i;
213*7836SJohn.Forte@Sun.COM int		nobj = 0;
214*7836SJohn.Forte@Sun.COM ses_objarg	obj;
215*7836SJohn.Forte@Sun.COM ses_object	*all_objp = NULL, *all_objp_save = NULL;
216*7836SJohn.Forte@Sun.COM int		found = 0;
217*7836SJohn.Forte@Sun.COM Bp_elem_st	*bp;
218*7836SJohn.Forte@Sun.COM char		msg[MAXPATHLEN];
219*7836SJohn.Forte@Sun.COM int		bsy_res_flag = 0;
220*7836SJohn.Forte@Sun.COM int		err;
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM 	if (ses_path == NULL) {
223*7836SJohn.Forte@Sun.COM 		return (L_NO_SES_PATH);
224*7836SJohn.Forte@Sun.COM 	}
225*7836SJohn.Forte@Sun.COM 
226*7836SJohn.Forte@Sun.COM 	/*
227*7836SJohn.Forte@Sun.COM 	 * Check for reservation and busy for all disks on this
228*7836SJohn.Forte@Sun.COM 	 * backplane.
229*7836SJohn.Forte@Sun.COM 	 */
230*7836SJohn.Forte@Sun.COM 
231*7836SJohn.Forte@Sun.COM 	if (!force_flag && bypass_flag) {
232*7836SJohn.Forte@Sun.COM 		if (err = l_check_busy_reserv_bp(ses_path,
233*7836SJohn.Forte@Sun.COM 			front_flag, port_a_flag, &bsy_res_flag, verbose)) {
234*7836SJohn.Forte@Sun.COM 			return (err);
235*7836SJohn.Forte@Sun.COM 		}
236*7836SJohn.Forte@Sun.COM 		if (bsy_res_flag) {
237*7836SJohn.Forte@Sun.COM 				return (L_BP_BUSY_RESERVED);
238*7836SJohn.Forte@Sun.COM 		}
239*7836SJohn.Forte@Sun.COM 	}
240*7836SJohn.Forte@Sun.COM 
241*7836SJohn.Forte@Sun.COM 
242*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) {
243*7836SJohn.Forte@Sun.COM 		return (errno);
244*7836SJohn.Forte@Sun.COM 	}
245*7836SJohn.Forte@Sun.COM 
246*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SESIOC_GETNOBJ, (caddr_t)&nobj) < 0) {
247*7836SJohn.Forte@Sun.COM 		(void) close(fd);
248*7836SJohn.Forte@Sun.COM 		return (errno);
249*7836SJohn.Forte@Sun.COM 	}
250*7836SJohn.Forte@Sun.COM 	if (nobj == 0) {
251*7836SJohn.Forte@Sun.COM 		(void) close(fd);
252*7836SJohn.Forte@Sun.COM 		return (L_IB_NO_ELEM_FOUND);
253*7836SJohn.Forte@Sun.COM 	}
254*7836SJohn.Forte@Sun.COM 
255*7836SJohn.Forte@Sun.COM 	E_DPRINTF("  l_ib_bypass_bp: Number of SES objects: 0x%x\n",
256*7836SJohn.Forte@Sun.COM 		nobj);
257*7836SJohn.Forte@Sun.COM 
258*7836SJohn.Forte@Sun.COM 	/* alloc some memory for the objmap */
259*7836SJohn.Forte@Sun.COM 	if ((all_objp = g_zalloc((nobj + 1) * sizeof (ses_object))) == NULL) {
260*7836SJohn.Forte@Sun.COM 		(void) close(fd);
261*7836SJohn.Forte@Sun.COM 		return (errno);
262*7836SJohn.Forte@Sun.COM 	}
263*7836SJohn.Forte@Sun.COM 
264*7836SJohn.Forte@Sun.COM 	all_objp_save = all_objp;
265*7836SJohn.Forte@Sun.COM 
266*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SESIOC_GETOBJMAP, (caddr_t)all_objp) < 0) {
267*7836SJohn.Forte@Sun.COM 		(void) close(fd);
268*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(all_objp_save);
269*7836SJohn.Forte@Sun.COM 		return (errno);
270*7836SJohn.Forte@Sun.COM 	}
271*7836SJohn.Forte@Sun.COM 
272*7836SJohn.Forte@Sun.COM 	for (i = 0; i < nobj; i++, all_objp++) {
273*7836SJohn.Forte@Sun.COM 			E_DPRINTF("  ID 0x%x\t Element type 0x%x\n",
274*7836SJohn.Forte@Sun.COM 			all_objp->obj_id, all_objp->elem_type);
275*7836SJohn.Forte@Sun.COM 		if (all_objp->elem_type == ELM_TYP_BP) {
276*7836SJohn.Forte@Sun.COM 			found++;
277*7836SJohn.Forte@Sun.COM 			break;
278*7836SJohn.Forte@Sun.COM 		}
279*7836SJohn.Forte@Sun.COM 	}
280*7836SJohn.Forte@Sun.COM 
281*7836SJohn.Forte@Sun.COM 	if (found == 0) {
282*7836SJohn.Forte@Sun.COM 		(void) close(fd);
283*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(all_objp_save);
284*7836SJohn.Forte@Sun.COM 		return (L_NO_BP_ELEM_FOUND);
285*7836SJohn.Forte@Sun.COM 	}
286*7836SJohn.Forte@Sun.COM 
287*7836SJohn.Forte@Sun.COM 	/*
288*7836SJohn.Forte@Sun.COM 	 * We found the backplane element.
289*7836SJohn.Forte@Sun.COM 	 */
290*7836SJohn.Forte@Sun.COM 
291*7836SJohn.Forte@Sun.COM 
292*7836SJohn.Forte@Sun.COM 	if (verbose) {
293*7836SJohn.Forte@Sun.COM 		/* Get the status for backplane #0 */
294*7836SJohn.Forte@Sun.COM 		obj.obj_id = all_objp->obj_id;
295*7836SJohn.Forte@Sun.COM 		if (ioctl(fd, SESIOC_GETOBJSTAT, (caddr_t)&obj) < 0) {
296*7836SJohn.Forte@Sun.COM 			(void) close(fd);
297*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(all_objp_save);
298*7836SJohn.Forte@Sun.COM 			return (errno);
299*7836SJohn.Forte@Sun.COM 		}
300*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, MSGSTR(8000,
301*7836SJohn.Forte@Sun.COM 			"  Front backplane status: "));
302*7836SJohn.Forte@Sun.COM 		bp = (struct  bp_element_status *)&obj.cstat[0];
303*7836SJohn.Forte@Sun.COM 		l_element_msg_string(bp->code, msg);
304*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n", msg);
305*7836SJohn.Forte@Sun.COM 		if (bp->byp_a_enabled || bp->en_bypass_a) {
306*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, "    ");
307*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
308*7836SJohn.Forte@Sun.COM 			MSGSTR(130, "Bypass A enabled"));
309*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, ".\n");
310*7836SJohn.Forte@Sun.COM 		}
311*7836SJohn.Forte@Sun.COM 		if (bp->byp_b_enabled || bp->en_bypass_b) {
312*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, "    ");
313*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
314*7836SJohn.Forte@Sun.COM 			MSGSTR(129, "Bypass B enabled"));
315*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, ".\n");
316*7836SJohn.Forte@Sun.COM 		}
317*7836SJohn.Forte@Sun.COM 
318*7836SJohn.Forte@Sun.COM 		all_objp++;
319*7836SJohn.Forte@Sun.COM 		obj.obj_id = all_objp->obj_id;
320*7836SJohn.Forte@Sun.COM 		all_objp--;
321*7836SJohn.Forte@Sun.COM 		if (ioctl(fd, SESIOC_GETOBJSTAT, (caddr_t)&obj) < 0) {
322*7836SJohn.Forte@Sun.COM 			(void) close(fd);
323*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(all_objp_save);
324*7836SJohn.Forte@Sun.COM 			return (errno);
325*7836SJohn.Forte@Sun.COM 		}
326*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, MSGSTR(8001,
327*7836SJohn.Forte@Sun.COM 			"  Rear backplane status: "));
328*7836SJohn.Forte@Sun.COM 		bp = (struct  bp_element_status *)&obj.cstat[0];
329*7836SJohn.Forte@Sun.COM 		l_element_msg_string(bp->code, msg);
330*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n", msg);
331*7836SJohn.Forte@Sun.COM 		if (bp->byp_a_enabled || bp->en_bypass_a) {
332*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, "    ");
333*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
334*7836SJohn.Forte@Sun.COM 			MSGSTR(130, "Bypass A enabled"));
335*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, ".\n");
336*7836SJohn.Forte@Sun.COM 		}
337*7836SJohn.Forte@Sun.COM 		if (bp->byp_b_enabled || bp->en_bypass_b) {
338*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, "    ");
339*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
340*7836SJohn.Forte@Sun.COM 			MSGSTR(129, "Bypass B enabled"));
341*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, ".\n");
342*7836SJohn.Forte@Sun.COM 		}
343*7836SJohn.Forte@Sun.COM 	}
344*7836SJohn.Forte@Sun.COM 
345*7836SJohn.Forte@Sun.COM 	/* Get the current status */
346*7836SJohn.Forte@Sun.COM 	if (!front_flag) {
347*7836SJohn.Forte@Sun.COM 		all_objp++;
348*7836SJohn.Forte@Sun.COM 	}
349*7836SJohn.Forte@Sun.COM 	obj.obj_id = all_objp->obj_id;
350*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SESIOC_GETOBJSTAT, (caddr_t)&obj) < 0) {
351*7836SJohn.Forte@Sun.COM 		(void) close(fd);
352*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(all_objp_save);
353*7836SJohn.Forte@Sun.COM 		return (errno);
354*7836SJohn.Forte@Sun.COM 	}
355*7836SJohn.Forte@Sun.COM 	/* Do the requested action. */
356*7836SJohn.Forte@Sun.COM 	bp = (struct  bp_element_status *)&obj.cstat[0];
357*7836SJohn.Forte@Sun.COM 	bp->select = 1;
358*7836SJohn.Forte@Sun.COM 	bp->code = 0;
359*7836SJohn.Forte@Sun.COM 	if (port_a_flag) {
360*7836SJohn.Forte@Sun.COM 		bp->en_bypass_a = bypass_flag;
361*7836SJohn.Forte@Sun.COM 	} else {
362*7836SJohn.Forte@Sun.COM 		bp->en_bypass_b = bypass_flag;
363*7836SJohn.Forte@Sun.COM 	}
364*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_E_DEBUG") != NULL) {
365*7836SJohn.Forte@Sun.COM 		(void) printf("  Sending this structure to ID 0x%x"
366*7836SJohn.Forte@Sun.COM 			" of type 0x%x\n",
367*7836SJohn.Forte@Sun.COM 			obj.obj_id, all_objp->elem_type);
368*7836SJohn.Forte@Sun.COM 		for (i = 0; i < 4; i++) {
369*7836SJohn.Forte@Sun.COM 			(void) printf("    Byte %d  0x%x\n", i,
370*7836SJohn.Forte@Sun.COM 			obj.cstat[i]);
371*7836SJohn.Forte@Sun.COM 		}
372*7836SJohn.Forte@Sun.COM 	}
373*7836SJohn.Forte@Sun.COM 
374*7836SJohn.Forte@Sun.COM 	if (ioctl(fd, SESIOC_SETOBJSTAT, (caddr_t)&obj) < 0) {
375*7836SJohn.Forte@Sun.COM 		(void) close(fd);
376*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(all_objp_save);
377*7836SJohn.Forte@Sun.COM 		return (errno);
378*7836SJohn.Forte@Sun.COM 	}
379*7836SJohn.Forte@Sun.COM 
380*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(all_objp_save);
381*7836SJohn.Forte@Sun.COM 	(void) close(fd);
382*7836SJohn.Forte@Sun.COM 
383*7836SJohn.Forte@Sun.COM 	return (0);
384*7836SJohn.Forte@Sun.COM }
385*7836SJohn.Forte@Sun.COM 
386*7836SJohn.Forte@Sun.COM 
387*7836SJohn.Forte@Sun.COM 
388*7836SJohn.Forte@Sun.COM 
389*7836SJohn.Forte@Sun.COM /*
390*7836SJohn.Forte@Sun.COM  * This function will request the enclosure services
391*7836SJohn.Forte@Sun.COM  * controller (IB) to set the LRC (Loop Redundancy Circuit) to the
392*7836SJohn.Forte@Sun.COM  * bypassed/enabled state for the device specified by the
393*7836SJohn.Forte@Sun.COM  * enclosure,dev or pathname and the port specified by the a
394*7836SJohn.Forte@Sun.COM  * flag.
395*7836SJohn.Forte@Sun.COM  */
396*7836SJohn.Forte@Sun.COM 
397*7836SJohn.Forte@Sun.COM int
l_dev_bypass_enable(struct path_struct * path_struct,int bypass_flag,int force_flag,int port_a_flag,int verbose)398*7836SJohn.Forte@Sun.COM l_dev_bypass_enable(struct path_struct *path_struct, int bypass_flag,
399*7836SJohn.Forte@Sun.COM 	int force_flag, int port_a_flag, int verbose)
400*7836SJohn.Forte@Sun.COM {
401*7836SJohn.Forte@Sun.COM gfc_map_t		map;
402*7836SJohn.Forte@Sun.COM char			ses_path[MAXPATHLEN];
403*7836SJohn.Forte@Sun.COM uchar_t			*page_buf;
404*7836SJohn.Forte@Sun.COM int 			err, fd, front_index, rear_index, offset;
405*7836SJohn.Forte@Sun.COM int			pathcnt = 1;
406*7836SJohn.Forte@Sun.COM unsigned short		page_len;
407*7836SJohn.Forte@Sun.COM struct	device_element 	*elem;
408*7836SJohn.Forte@Sun.COM L_state			*l_state = NULL;
409*7836SJohn.Forte@Sun.COM struct device_element 	status;
410*7836SJohn.Forte@Sun.COM int			bsy_flag = 0, i, f_flag;
411*7836SJohn.Forte@Sun.COM struct dlist		*p_list;
412*7836SJohn.Forte@Sun.COM char			temppath[MAXPATHLEN];
413*7836SJohn.Forte@Sun.COM mp_pathlist_t		pathlist;
414*7836SJohn.Forte@Sun.COM int			p_pw = 0, p_on = 0, p_st = 0;
415*7836SJohn.Forte@Sun.COM L_inquiry		inq;
416*7836SJohn.Forte@Sun.COM 
417*7836SJohn.Forte@Sun.COM 	if (path_struct == NULL) {
418*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
419*7836SJohn.Forte@Sun.COM 	}
420*7836SJohn.Forte@Sun.COM 
421*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
422*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
423*7836SJohn.Forte@Sun.COM 	}
424*7836SJohn.Forte@Sun.COM 	map.dev_addr = (gfc_port_dev_info_t *)NULL;
425*7836SJohn.Forte@Sun.COM 	(void) strcpy(temppath, path_struct->p_physical_path);
426*7836SJohn.Forte@Sun.COM 	if ((strstr(path_struct->p_physical_path, SCSI_VHCI) != NULL) &&
427*7836SJohn.Forte@Sun.COM 		(!g_get_pathlist(temppath, &pathlist))) {
428*7836SJohn.Forte@Sun.COM 			pathcnt = pathlist.path_count;
429*7836SJohn.Forte@Sun.COM 			p_pw = p_on = p_st = 0;
430*7836SJohn.Forte@Sun.COM 			for (i = 0; i < pathcnt; i++) {
431*7836SJohn.Forte@Sun.COM 				if (pathlist.path_info[i].path_state <
432*7836SJohn.Forte@Sun.COM 					MAXPATHSTATE) {
433*7836SJohn.Forte@Sun.COM 					if (strstr(pathlist.path_info[i].
434*7836SJohn.Forte@Sun.COM 						path_addr,
435*7836SJohn.Forte@Sun.COM 						path_struct->argv) != NULL) {
436*7836SJohn.Forte@Sun.COM 						p_pw = i;
437*7836SJohn.Forte@Sun.COM 						break;
438*7836SJohn.Forte@Sun.COM 					}
439*7836SJohn.Forte@Sun.COM 					if (pathlist.path_info[i].path_state ==
440*7836SJohn.Forte@Sun.COM 						MDI_PATHINFO_STATE_ONLINE) {
441*7836SJohn.Forte@Sun.COM 						p_on = i;
442*7836SJohn.Forte@Sun.COM 					}
443*7836SJohn.Forte@Sun.COM 					if (pathlist.path_info[i].path_state ==
444*7836SJohn.Forte@Sun.COM 						MDI_PATHINFO_STATE_STANDBY) {
445*7836SJohn.Forte@Sun.COM 						p_st = i;
446*7836SJohn.Forte@Sun.COM 					}
447*7836SJohn.Forte@Sun.COM 				}
448*7836SJohn.Forte@Sun.COM 			}
449*7836SJohn.Forte@Sun.COM 			if (strstr(pathlist.path_info[p_pw].path_addr,
450*7836SJohn.Forte@Sun.COM 				path_struct->argv) != NULL) {
451*7836SJohn.Forte@Sun.COM 				/* matching input pwwn */
452*7836SJohn.Forte@Sun.COM 				(void) strcpy(temppath,
453*7836SJohn.Forte@Sun.COM 					pathlist.path_info[p_pw].path_hba);
454*7836SJohn.Forte@Sun.COM 			} else if (pathlist.path_info[p_on].path_state ==
455*7836SJohn.Forte@Sun.COM 				MDI_PATHINFO_STATE_ONLINE) {
456*7836SJohn.Forte@Sun.COM 				/* on_line path */
457*7836SJohn.Forte@Sun.COM 				(void) strcpy(temppath,
458*7836SJohn.Forte@Sun.COM 					pathlist.path_info[p_on].path_hba);
459*7836SJohn.Forte@Sun.COM 			} else {
460*7836SJohn.Forte@Sun.COM 				/* standby or path0 */
461*7836SJohn.Forte@Sun.COM 				(void) strcpy(temppath,
462*7836SJohn.Forte@Sun.COM 					pathlist.path_info[p_st].path_hba);
463*7836SJohn.Forte@Sun.COM 			}
464*7836SJohn.Forte@Sun.COM 			free(pathlist.path_info);
465*7836SJohn.Forte@Sun.COM 			(void) strcat(temppath, FC_CTLR);
466*7836SJohn.Forte@Sun.COM 	}
467*7836SJohn.Forte@Sun.COM 
468*7836SJohn.Forte@Sun.COM 	/*
469*7836SJohn.Forte@Sun.COM 	 * Need to get a valid location, front/rear & slot.
470*7836SJohn.Forte@Sun.COM 	 *
471*7836SJohn.Forte@Sun.COM 	 * The path_struct will return a valid slot
472*7836SJohn.Forte@Sun.COM 	 * and the IB path or a disk path.
473*7836SJohn.Forte@Sun.COM 	 */
474*7836SJohn.Forte@Sun.COM 
475*7836SJohn.Forte@Sun.COM 	if (!path_struct->ib_path_flag) {
476*7836SJohn.Forte@Sun.COM 		if (err = g_get_dev_map(temppath, &map, verbose)) {
477*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
478*7836SJohn.Forte@Sun.COM 			return (err);
479*7836SJohn.Forte@Sun.COM 		}
480*7836SJohn.Forte@Sun.COM 		if (err = l_get_ses_path(path_struct->p_physical_path,
481*7836SJohn.Forte@Sun.COM 			ses_path, &map, verbose)) {
482*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
483*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
484*7836SJohn.Forte@Sun.COM 			return (err);
485*7836SJohn.Forte@Sun.COM 		}
486*7836SJohn.Forte@Sun.COM 	} else {
487*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path, path_struct->p_physical_path);
488*7836SJohn.Forte@Sun.COM 	}
489*7836SJohn.Forte@Sun.COM 	if (!path_struct->slot_valid) {
490*7836SJohn.Forte@Sun.COM 		if ((map.dev_addr == (gfc_port_dev_info_t *)NULL) &&
491*7836SJohn.Forte@Sun.COM 			((err = g_get_dev_map(temppath,
492*7836SJohn.Forte@Sun.COM 						&map, verbose)) != 0)) {
493*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
494*7836SJohn.Forte@Sun.COM 			return (err);
495*7836SJohn.Forte@Sun.COM 		}
496*7836SJohn.Forte@Sun.COM 		if ((err = l_get_ses_path(path_struct->p_physical_path,
497*7836SJohn.Forte@Sun.COM 			ses_path, &map, verbose)) != 0) {
498*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
499*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
500*7836SJohn.Forte@Sun.COM 			return (err);
501*7836SJohn.Forte@Sun.COM 		}
502*7836SJohn.Forte@Sun.COM 		if ((err = l_get_status(ses_path, l_state, verbose)) != 0) {
503*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
504*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
505*7836SJohn.Forte@Sun.COM 			return (err);
506*7836SJohn.Forte@Sun.COM 		}
507*7836SJohn.Forte@Sun.COM 
508*7836SJohn.Forte@Sun.COM 		/* We are passing the disks path */
509*7836SJohn.Forte@Sun.COM 		if ((err = l_get_slot(path_struct, l_state, verbose)) != 0) {
510*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
511*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
512*7836SJohn.Forte@Sun.COM 			return (err);
513*7836SJohn.Forte@Sun.COM 		}
514*7836SJohn.Forte@Sun.COM 	}
515*7836SJohn.Forte@Sun.COM 
516*7836SJohn.Forte@Sun.COM 	if (map.dev_addr != (gfc_port_dev_info_t *)NULL) {
517*7836SJohn.Forte@Sun.COM 		free((void *)map.dev_addr);
518*7836SJohn.Forte@Sun.COM 	}
519*7836SJohn.Forte@Sun.COM 
520*7836SJohn.Forte@Sun.COM 	if ((page_buf = (uchar_t *)malloc(MAX_REC_DIAG_LENGTH)) == NULL) {
521*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
522*7836SJohn.Forte@Sun.COM 		return (errno);
523*7836SJohn.Forte@Sun.COM 	}
524*7836SJohn.Forte@Sun.COM 
525*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) {
526*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
527*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
528*7836SJohn.Forte@Sun.COM 		return (errno);
529*7836SJohn.Forte@Sun.COM 	}
530*7836SJohn.Forte@Sun.COM 
531*7836SJohn.Forte@Sun.COM 	if (err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
532*7836SJohn.Forte@Sun.COM 				L_PAGE_2, verbose)) {
533*7836SJohn.Forte@Sun.COM 		(void) close(fd);
534*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
535*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
536*7836SJohn.Forte@Sun.COM 		return (err);
537*7836SJohn.Forte@Sun.COM 	}
538*7836SJohn.Forte@Sun.COM 
539*7836SJohn.Forte@Sun.COM 	page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN;
540*7836SJohn.Forte@Sun.COM 
541*7836SJohn.Forte@Sun.COM 	/* Get index to the disk we are interested in */
542*7836SJohn.Forte@Sun.COM 	if (err = l_get_status(ses_path, l_state, verbose)) {
543*7836SJohn.Forte@Sun.COM 		(void) close(fd);
544*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
545*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
546*7836SJohn.Forte@Sun.COM 		return (err);
547*7836SJohn.Forte@Sun.COM 	}
548*7836SJohn.Forte@Sun.COM 	/*
549*7836SJohn.Forte@Sun.COM 	 * Now that we have the status check to see if
550*7836SJohn.Forte@Sun.COM 	 * busy or reserved, if bypassing.
551*7836SJohn.Forte@Sun.COM 	 */
552*7836SJohn.Forte@Sun.COM 	if ((!(force_flag | path_struct->ib_path_flag)) &&
553*7836SJohn.Forte@Sun.COM 						bypass_flag) {
554*7836SJohn.Forte@Sun.COM 		i = path_struct->slot;
555*7836SJohn.Forte@Sun.COM 		f_flag = path_struct->f_flag;
556*7836SJohn.Forte@Sun.COM 
557*7836SJohn.Forte@Sun.COM 		/*
558*7836SJohn.Forte@Sun.COM 		 * Check for reservation and busy
559*7836SJohn.Forte@Sun.COM 		 */
560*7836SJohn.Forte@Sun.COM 		if ((f_flag &&
561*7836SJohn.Forte@Sun.COM 		(l_state->drv_front[i].g_disk_state.d_state_flags[port_a_flag] &
562*7836SJohn.Forte@Sun.COM 			L_RESERVED)) || (!f_flag &&
563*7836SJohn.Forte@Sun.COM 		(l_state->drv_rear[i].g_disk_state.d_state_flags[port_a_flag] &
564*7836SJohn.Forte@Sun.COM 			L_RESERVED))) {
565*7836SJohn.Forte@Sun.COM 			(void) close(fd);
566*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(page_buf);
567*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
568*7836SJohn.Forte@Sun.COM 			return (L_BP_RESERVED);
569*7836SJohn.Forte@Sun.COM 		}
570*7836SJohn.Forte@Sun.COM 		if (f_flag) {
571*7836SJohn.Forte@Sun.COM 			if (port_a_flag) {
572*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
573*7836SJohn.Forte@Sun.COM 				l_state->drv_front[i].g_disk_state.port_a_wwn_s,
574*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
575*7836SJohn.Forte@Sun.COM 					(void) close(fd);
576*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(page_buf);
577*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
578*7836SJohn.Forte@Sun.COM 					return (err);
579*7836SJohn.Forte@Sun.COM 				}
580*7836SJohn.Forte@Sun.COM 			} else {
581*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
582*7836SJohn.Forte@Sun.COM 				l_state->drv_front[i].g_disk_state.port_b_wwn_s,
583*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
584*7836SJohn.Forte@Sun.COM 					(void) close(fd);
585*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(page_buf);
586*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
587*7836SJohn.Forte@Sun.COM 					return (err);
588*7836SJohn.Forte@Sun.COM 				}
589*7836SJohn.Forte@Sun.COM 			}
590*7836SJohn.Forte@Sun.COM 		} else {
591*7836SJohn.Forte@Sun.COM 			if (port_a_flag) {
592*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
593*7836SJohn.Forte@Sun.COM 				l_state->drv_rear[i].g_disk_state.port_a_wwn_s,
594*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
595*7836SJohn.Forte@Sun.COM 					(void) close(fd);
596*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(page_buf);
597*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
598*7836SJohn.Forte@Sun.COM 					return (err);
599*7836SJohn.Forte@Sun.COM 				}
600*7836SJohn.Forte@Sun.COM 			} else {
601*7836SJohn.Forte@Sun.COM 				if ((err = g_get_port_multipath(
602*7836SJohn.Forte@Sun.COM 				l_state->drv_rear[i].g_disk_state.port_b_wwn_s,
603*7836SJohn.Forte@Sun.COM 					&p_list, verbose)) != 0) {
604*7836SJohn.Forte@Sun.COM 					(void) close(fd);
605*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(page_buf);
606*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
607*7836SJohn.Forte@Sun.COM 					return (err);
608*7836SJohn.Forte@Sun.COM 				}
609*7836SJohn.Forte@Sun.COM 			}
610*7836SJohn.Forte@Sun.COM 		}
611*7836SJohn.Forte@Sun.COM 		if (err = d_offline_drive(p_list,
612*7836SJohn.Forte@Sun.COM 			&bsy_flag, verbose)) {
613*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(p_list);
614*7836SJohn.Forte@Sun.COM 			(void) close(fd);
615*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(page_buf);
616*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
617*7836SJohn.Forte@Sun.COM 			return (err);
618*7836SJohn.Forte@Sun.COM 		}
619*7836SJohn.Forte@Sun.COM 		(void) g_free_multipath(p_list);
620*7836SJohn.Forte@Sun.COM 		if (bsy_flag) {
621*7836SJohn.Forte@Sun.COM 			(void) close(fd);
622*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(page_buf);
623*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
624*7836SJohn.Forte@Sun.COM 			return (L_BP_BUSY);
625*7836SJohn.Forte@Sun.COM 		}
626*7836SJohn.Forte@Sun.COM 	}
627*7836SJohn.Forte@Sun.COM 
628*7836SJohn.Forte@Sun.COM 	if (err = l_get_disk_element_index(l_state, &front_index,
629*7836SJohn.Forte@Sun.COM 		&rear_index)) {
630*7836SJohn.Forte@Sun.COM 		(void) close(fd);
631*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
632*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
633*7836SJohn.Forte@Sun.COM 		return (err);
634*7836SJohn.Forte@Sun.COM 	}
635*7836SJohn.Forte@Sun.COM 
636*7836SJohn.Forte@Sun.COM 	if (g_get_inquiry(ses_path, &inq)) {
637*7836SJohn.Forte@Sun.COM 		return (L_SCSI_ERROR);
638*7836SJohn.Forte@Sun.COM 	}
639*7836SJohn.Forte@Sun.COM 
640*7836SJohn.Forte@Sun.COM 	/* Skip global element */
641*7836SJohn.Forte@Sun.COM 	front_index++;
642*7836SJohn.Forte@Sun.COM 	if ((strncmp((char *)&inq.inq_pid[0], DAK_OFF_NAME,
643*7836SJohn.Forte@Sun.COM 						strlen(DAK_OFF_NAME)) == 0) ||
644*7836SJohn.Forte@Sun.COM 			(strncmp((char *)&inq.inq_pid[0], DAK_PROD_STR,
645*7836SJohn.Forte@Sun.COM 						strlen(DAK_PROD_STR)) == 0)) {
646*7836SJohn.Forte@Sun.COM 		rear_index += (MAX_DRIVES_DAK/2) + 1;
647*7836SJohn.Forte@Sun.COM 	} else {
648*7836SJohn.Forte@Sun.COM 		rear_index++;
649*7836SJohn.Forte@Sun.COM 	}
650*7836SJohn.Forte@Sun.COM 
651*7836SJohn.Forte@Sun.COM 	if (path_struct->f_flag) {
652*7836SJohn.Forte@Sun.COM 		offset = (8 + (front_index + path_struct->slot)*4);
653*7836SJohn.Forte@Sun.COM 	} else {
654*7836SJohn.Forte@Sun.COM 		offset = (8 + (rear_index + path_struct->slot)*4);
655*7836SJohn.Forte@Sun.COM 	}
656*7836SJohn.Forte@Sun.COM 
657*7836SJohn.Forte@Sun.COM 	elem = (struct device_element *)(page_buf + offset);
658*7836SJohn.Forte@Sun.COM 	/*
659*7836SJohn.Forte@Sun.COM 	 * now do requested action.
660*7836SJohn.Forte@Sun.COM 	 */
661*7836SJohn.Forte@Sun.COM 	bcopy((const void *)elem, (void *)&status,
662*7836SJohn.Forte@Sun.COM 		sizeof (struct device_element));	/* save status */
663*7836SJohn.Forte@Sun.COM 	bzero(elem, sizeof (struct device_element));
664*7836SJohn.Forte@Sun.COM 	elem->select = 1;
665*7836SJohn.Forte@Sun.COM 	elem->dev_off = status.dev_off;
666*7836SJohn.Forte@Sun.COM 	elem->en_bypass_a = status.en_bypass_a;
667*7836SJohn.Forte@Sun.COM 	elem->en_bypass_b = status.en_bypass_b;
668*7836SJohn.Forte@Sun.COM 
669*7836SJohn.Forte@Sun.COM 	/* Do requested action */
670*7836SJohn.Forte@Sun.COM 	if (port_a_flag) {
671*7836SJohn.Forte@Sun.COM 		elem->en_bypass_a = bypass_flag;
672*7836SJohn.Forte@Sun.COM 	} else {
673*7836SJohn.Forte@Sun.COM 		elem->en_bypass_b = bypass_flag;
674*7836SJohn.Forte@Sun.COM 	}
675*7836SJohn.Forte@Sun.COM 
676*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_E_DEBUG") != NULL) {
677*7836SJohn.Forte@Sun.COM 		g_dump("  l_dev_bypass_enable: Updating LRC circuit state:\n"
678*7836SJohn.Forte@Sun.COM 		"    Device Status Element ",
679*7836SJohn.Forte@Sun.COM 		(uchar_t *)elem, sizeof (struct device_element),
680*7836SJohn.Forte@Sun.COM 		HEX_ONLY);
681*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "    for device at location:"
682*7836SJohn.Forte@Sun.COM 			" enclosure:%s slot:%d %s\n",
683*7836SJohn.Forte@Sun.COM 			l_state->ib_tbl.enclosure_name,
684*7836SJohn.Forte@Sun.COM 			path_struct->slot,
685*7836SJohn.Forte@Sun.COM 			path_struct->f_flag ? "front" : "rear");
686*7836SJohn.Forte@Sun.COM 	}
687*7836SJohn.Forte@Sun.COM 	if (err = g_scsi_send_diag_cmd(fd,
688*7836SJohn.Forte@Sun.COM 		(uchar_t *)page_buf, page_len)) {
689*7836SJohn.Forte@Sun.COM 		(void) close(fd);
690*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
691*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
692*7836SJohn.Forte@Sun.COM 		return (err);
693*7836SJohn.Forte@Sun.COM 	}
694*7836SJohn.Forte@Sun.COM 
695*7836SJohn.Forte@Sun.COM 	(void) close(fd);
696*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(page_buf);
697*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
698*7836SJohn.Forte@Sun.COM 	return (0);
699*7836SJohn.Forte@Sun.COM }
700*7836SJohn.Forte@Sun.COM 
701*7836SJohn.Forte@Sun.COM 
702*7836SJohn.Forte@Sun.COM 
703*7836SJohn.Forte@Sun.COM /*
704*7836SJohn.Forte@Sun.COM  * Issue a Loop Port enable Primitive sequence
705*7836SJohn.Forte@Sun.COM  * to the device specified by the pathname.
706*7836SJohn.Forte@Sun.COM  */
707*7836SJohn.Forte@Sun.COM int
d_p_enable(char * path,int verbose)708*7836SJohn.Forte@Sun.COM d_p_enable(char *path, int verbose)
709*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
710*7836SJohn.Forte@Sun.COM {
711*7836SJohn.Forte@Sun.COM 
712*7836SJohn.Forte@Sun.COM 	return (0);
713*7836SJohn.Forte@Sun.COM }
714*7836SJohn.Forte@Sun.COM 
715*7836SJohn.Forte@Sun.COM /*
716*7836SJohn.Forte@Sun.COM  * Issue a Loop Port Bypass Primitive sequence
717*7836SJohn.Forte@Sun.COM  * to the device specified by the pathname. This requests the
718*7836SJohn.Forte@Sun.COM  * device to set its L_Port into the bypass mode.
719*7836SJohn.Forte@Sun.COM  */
720*7836SJohn.Forte@Sun.COM int
d_p_bypass(char * path,int verbose)721*7836SJohn.Forte@Sun.COM d_p_bypass(char *path, int verbose)
722*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
723*7836SJohn.Forte@Sun.COM {
724*7836SJohn.Forte@Sun.COM 
725*7836SJohn.Forte@Sun.COM 	return (0);
726*7836SJohn.Forte@Sun.COM }
727