xref: /titanic_52/usr/src/lib/storage/liba5k/common/lhot.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte /*LINTLIBRARY*/
28*fcf3ce44SJohn Forte 
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte /*
31*fcf3ce44SJohn Forte  *	This module is part of the photon library
32*fcf3ce44SJohn Forte  */
33*fcf3ce44SJohn Forte 
34*fcf3ce44SJohn Forte /*
35*fcf3ce44SJohn Forte  * I18N message number ranges
36*fcf3ce44SJohn Forte  *  This file: 8500 - 8999
37*fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
38*fcf3ce44SJohn Forte  */
39*fcf3ce44SJohn Forte 
40*fcf3ce44SJohn Forte /* #define		_POSIX_SOURCE 1 */
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte /*	Includes	*/
43*fcf3ce44SJohn Forte #include	<stdlib.h>
44*fcf3ce44SJohn Forte #include	<stdio.h>
45*fcf3ce44SJohn Forte #include	<sys/file.h>
46*fcf3ce44SJohn Forte #include	<sys/types.h>
47*fcf3ce44SJohn Forte #include	<sys/stat.h>
48*fcf3ce44SJohn Forte #include	<sys/param.h>
49*fcf3ce44SJohn Forte #include	<fcntl.h>
50*fcf3ce44SJohn Forte #include	<unistd.h>
51*fcf3ce44SJohn Forte #include	<errno.h>
52*fcf3ce44SJohn Forte #include	<string.h>
53*fcf3ce44SJohn Forte #include	<time.h>
54*fcf3ce44SJohn Forte #include	<sys/scsi/scsi.h>
55*fcf3ce44SJohn Forte #include	<sys/vtoc.h>
56*fcf3ce44SJohn Forte #include	<nl_types.h>
57*fcf3ce44SJohn Forte #include	<strings.h>
58*fcf3ce44SJohn Forte #include	<sys/ddi.h>		/* for max */
59*fcf3ce44SJohn Forte #include	<l_common.h>
60*fcf3ce44SJohn Forte #include	<stgcom.h>
61*fcf3ce44SJohn Forte #include	<l_error.h>
62*fcf3ce44SJohn Forte #include	<rom.h>
63*fcf3ce44SJohn Forte #include	<a_state.h>
64*fcf3ce44SJohn Forte #include	<a5k.h>
65*fcf3ce44SJohn Forte 
66*fcf3ce44SJohn Forte 
67*fcf3ce44SJohn Forte /*	Global variables	*/
68*fcf3ce44SJohn Forte extern	uchar_t		g_switch_to_alpa[];
69*fcf3ce44SJohn Forte extern	uchar_t		g_sf_alpa_to_switch[];
70*fcf3ce44SJohn Forte 
71*fcf3ce44SJohn Forte 
72*fcf3ce44SJohn Forte /*
73*fcf3ce44SJohn Forte  * This function checks if the passed char pointer has WWN_SIZE nulls (zeroes).
74*fcf3ce44SJohn Forte  *
75*fcf3ce44SJohn Forte  * This is only a convenience function.
76*fcf3ce44SJohn Forte  *
77*fcf3ce44SJohn Forte  * INPUT:
78*fcf3ce44SJohn Forte  * wwn_ptr -	pointer to a character string of length WWN_SIZE
79*fcf3ce44SJohn Forte  *		It is expected to be holding the WWN
80*fcf3ce44SJohn Forte  *		Ex: A WWN like 508002000000ddc1 is expected to be stored as
81*fcf3ce44SJohn Forte  *		the following 8 bytes -
82*fcf3ce44SJohn Forte  *		0x50, 0x80, 0x00, 0x20, ... etc
83*fcf3ce44SJohn Forte  *
84*fcf3ce44SJohn Forte  * RETURNS:
85*fcf3ce44SJohn Forte  * 0 - if there is atleast one of WWN_SIZE bytes is != '\0'
86*fcf3ce44SJohn Forte  * non-zero - if all WWN_SIZE bytes are '\0'
87*fcf3ce44SJohn Forte  */
88*fcf3ce44SJohn Forte int
89*fcf3ce44SJohn Forte is_null_wwn(uchar_t *wwn_ptr)
90*fcf3ce44SJohn Forte {
91*fcf3ce44SJohn Forte 	int i;
92*fcf3ce44SJohn Forte 
93*fcf3ce44SJohn Forte 	for (i = 0; i < WWN_SIZE; i++) {
94*fcf3ce44SJohn Forte 		if (wwn_ptr[i] != '\0' || wwn_ptr[i] != '0')
95*fcf3ce44SJohn Forte 			return (0);
96*fcf3ce44SJohn Forte 	}
97*fcf3ce44SJohn Forte 	return (1);
98*fcf3ce44SJohn Forte }
99*fcf3ce44SJohn Forte 
100*fcf3ce44SJohn Forte 
101*fcf3ce44SJohn Forte /*
102*fcf3ce44SJohn Forte  * This functions constructs a device path of the device/enclosure with the
103*fcf3ce44SJohn Forte  * given tid and, for public/fabric cases, on the same area and domain as
104*fcf3ce44SJohn Forte  * the given ses_path.
105*fcf3ce44SJohn Forte  *
106*fcf3ce44SJohn Forte  * INPUT:
107*fcf3ce44SJohn Forte  * ses_path	- pointer to the ses_path
108*fcf3ce44SJohn Forte  * tid		- tid of the device/enclosure whose path is to be constructed
109*fcf3ce44SJohn Forte  * map		- pointer to the map
110*fcf3ce44SJohn Forte  * dtype	- dtype of the device whose path is to be constructed
111*fcf3ce44SJohn Forte  *
112*fcf3ce44SJohn Forte  * OUTPUT:
113*fcf3ce44SJohn Forte  * dev_path	- pointer to the device path of type dtype and with tid
114*fcf3ce44SJohn Forte  *		- Caller has to free this after use
115*fcf3ce44SJohn Forte  *
116*fcf3ce44SJohn Forte  * RETURNS:
117*fcf3ce44SJohn Forte  * 0 - on success
118*fcf3ce44SJohn Forte  * non-zero - otherwise
119*fcf3ce44SJohn Forte  */
120*fcf3ce44SJohn Forte int
121*fcf3ce44SJohn Forte l_make_node(char *ses_path, int tid, char *dev_path,
122*fcf3ce44SJohn Forte 			gfc_map_t *map, int dtype)
123*fcf3ce44SJohn Forte {
124*fcf3ce44SJohn Forte int			len, i, err;
125*fcf3ce44SJohn Forte int			this_pid, ses_pid;
126*fcf3ce44SJohn Forte char			ssd[40], wwn[20];
127*fcf3ce44SJohn Forte gfc_port_dev_info_t	*dev_addr_ptr;
128*fcf3ce44SJohn Forte struct stat		stat_buf;
129*fcf3ce44SJohn Forte WWN_list		*wwnlp, *wwn_list;
130*fcf3ce44SJohn Forte int			found = 0;
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	if ((ses_path == NULL) || (dev_path == NULL) || (map == NULL)) {
133*fcf3ce44SJohn Forte 		return (L_INVALID_PATH_FORMAT);
134*fcf3ce44SJohn Forte 	}
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte 	switch (map->hba_addr.port_topology) {
137*fcf3ce44SJohn Forte 	case FC_TOP_PRIVATE_LOOP:
138*fcf3ce44SJohn Forte 		for (i = 0, dev_addr_ptr = map->dev_addr;
139*fcf3ce44SJohn Forte 			i < map->count; i++, dev_addr_ptr++) {
140*fcf3ce44SJohn Forte 			if (dev_addr_ptr->gfc_port_dev.priv_port.
141*fcf3ce44SJohn Forte 				sf_al_pa == g_switch_to_alpa[tid])
142*fcf3ce44SJohn Forte 				break;
143*fcf3ce44SJohn Forte 		}
144*fcf3ce44SJohn Forte 		if (i >= map->count) {
145*fcf3ce44SJohn Forte 			*dev_path = '\0';
146*fcf3ce44SJohn Forte 			return (L_INVALID_LOOP_MAP);
147*fcf3ce44SJohn Forte 		}
148*fcf3ce44SJohn Forte 
149*fcf3ce44SJohn Forte 		/* Make sure that the port WWN is valid */
150*fcf3ce44SJohn Forte 		if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
151*fcf3ce44SJohn Forte 			priv_port.sf_port_wwn)) {
152*fcf3ce44SJohn Forte 			*dev_path = '\0';
153*fcf3ce44SJohn Forte 			return (L_INVLD_WWN_FORMAT);
154*fcf3ce44SJohn Forte 		}
155*fcf3ce44SJohn Forte 
156*fcf3ce44SJohn Forte 		(void) g_ll_to_str(dev_addr_ptr->gfc_port_dev.
157*fcf3ce44SJohn Forte 			priv_port.sf_port_wwn, wwn);
158*fcf3ce44SJohn Forte 
159*fcf3ce44SJohn Forte 		if (strstr(ses_path, SCSI_VHCI) != NULL) {
160*fcf3ce44SJohn Forte 			if (err = g_get_wwn_list(&wwn_list, 0)) {
161*fcf3ce44SJohn Forte 				return (err);
162*fcf3ce44SJohn Forte 			}
163*fcf3ce44SJohn Forte 			for (wwnlp = wwn_list, found = 0;
164*fcf3ce44SJohn Forte 				wwnlp != NULL;
165*fcf3ce44SJohn Forte 				wwnlp = wwnlp->wwn_next) {
166*fcf3ce44SJohn Forte 				if (strcmp(wwnlp->port_wwn_s,
167*fcf3ce44SJohn Forte 					wwn) == 0) {
168*fcf3ce44SJohn Forte 					found = 1;
169*fcf3ce44SJohn Forte 					break;
170*fcf3ce44SJohn Forte 				}
171*fcf3ce44SJohn Forte 			}
172*fcf3ce44SJohn Forte 			if (found) {
173*fcf3ce44SJohn Forte 				(void) strcpy(dev_path,
174*fcf3ce44SJohn Forte 					wwnlp->physical_path);
175*fcf3ce44SJohn Forte 			} else {
176*fcf3ce44SJohn Forte 				return (L_INVALID_PATH);
177*fcf3ce44SJohn Forte 			}
178*fcf3ce44SJohn Forte 		} else {
179*fcf3ce44SJohn Forte 
180*fcf3ce44SJohn Forte 			len = strlen(ses_path) -
181*fcf3ce44SJohn Forte 			strlen(strrchr(ses_path, '/'));
182*fcf3ce44SJohn Forte 
183*fcf3ce44SJohn Forte 			if (dtype != DTYPE_ESI) {
184*fcf3ce44SJohn Forte 				(void) sprintf(ssd,
185*fcf3ce44SJohn Forte 					"/ssd@w%s,0:c", wwn);
186*fcf3ce44SJohn Forte 			} else {
187*fcf3ce44SJohn Forte 				(void) sprintf(ssd,
188*fcf3ce44SJohn Forte 					"/ses@w%s,0:c", wwn);
189*fcf3ce44SJohn Forte 			}
190*fcf3ce44SJohn Forte 
191*fcf3ce44SJohn Forte 			/* TBD: Must find path, not just use :c */
192*fcf3ce44SJohn Forte 			(void) strncpy(dev_path, ses_path, len);
193*fcf3ce44SJohn Forte 			dev_path[len] = '\0';
194*fcf3ce44SJohn Forte 			(void) strcat(dev_path, ssd);
195*fcf3ce44SJohn Forte 		}
196*fcf3ce44SJohn Forte 		break;
197*fcf3ce44SJohn Forte 	case FC_TOP_FABRIC:
198*fcf3ce44SJohn Forte 	case FC_TOP_PUBLIC_LOOP:
199*fcf3ce44SJohn Forte 		/* First lets get the PA from the ses path passed in */
200*fcf3ce44SJohn Forte 		if (err = l_get_pid_from_path(ses_path, map, &ses_pid)) {
201*fcf3ce44SJohn Forte 			return (err);
202*fcf3ce44SJohn Forte 		}
203*fcf3ce44SJohn Forte 
204*fcf3ce44SJohn Forte 		/*
205*fcf3ce44SJohn Forte 		 * Now we go through every entry in the map and match the
206*fcf3ce44SJohn Forte 		 * area and domain ids with the PA of the passed ses path.
207*fcf3ce44SJohn Forte 		 * If we find a match, we then match the low order byte
208*fcf3ce44SJohn Forte 		 */
209*fcf3ce44SJohn Forte 		for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
210*fcf3ce44SJohn Forte 							i++, dev_addr_ptr++) {
211*fcf3ce44SJohn Forte 			this_pid = dev_addr_ptr->gfc_port_dev.pub_port.
212*fcf3ce44SJohn Forte 								dev_did.port_id;
213*fcf3ce44SJohn Forte 			if ((this_pid & AREA_DOMAIN_ID) ==
214*fcf3ce44SJohn Forte 						(ses_pid & AREA_DOMAIN_ID)) {
215*fcf3ce44SJohn Forte 			    if ((uchar_t)(this_pid & 0xFF) ==
216*fcf3ce44SJohn Forte 							g_switch_to_alpa[tid])
217*fcf3ce44SJohn Forte 				break;
218*fcf3ce44SJohn Forte 			}
219*fcf3ce44SJohn Forte 		}
220*fcf3ce44SJohn Forte 		if (i >= map->count) {
221*fcf3ce44SJohn Forte 			*dev_path = '\0';
222*fcf3ce44SJohn Forte 			return (L_INVALID_LOOP_MAP);
223*fcf3ce44SJohn Forte 		}
224*fcf3ce44SJohn Forte 		/* Make sure that the port WWN is valid */
225*fcf3ce44SJohn Forte 		if (is_null_wwn(dev_addr_ptr->gfc_port_dev.pub_port.
226*fcf3ce44SJohn Forte 							dev_pwwn.raw_wwn)) {
227*fcf3ce44SJohn Forte 			*dev_path = '\0';
228*fcf3ce44SJohn Forte 			return (L_INVLD_WWN_FORMAT);
229*fcf3ce44SJohn Forte 		}
230*fcf3ce44SJohn Forte 		(void) g_ll_to_str(dev_addr_ptr->gfc_port_dev.
231*fcf3ce44SJohn Forte 						pub_port.dev_pwwn.raw_wwn, wwn);
232*fcf3ce44SJohn Forte 
233*fcf3ce44SJohn Forte 
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 		if (strstr(ses_path, SCSI_VHCI) != NULL) {
236*fcf3ce44SJohn Forte 			if (err = g_get_wwn_list(&wwn_list, 0)) {
237*fcf3ce44SJohn Forte 				return (err);
238*fcf3ce44SJohn Forte 			}
239*fcf3ce44SJohn Forte 			for (wwnlp = wwn_list, found = 0; wwnlp != NULL;
240*fcf3ce44SJohn Forte 				wwnlp = wwnlp->wwn_next) {
241*fcf3ce44SJohn Forte 				if (strcmp(wwnlp->port_wwn_s,
242*fcf3ce44SJohn Forte 					wwn) == 0) {
243*fcf3ce44SJohn Forte 						found = 1;
244*fcf3ce44SJohn Forte 				}
245*fcf3ce44SJohn Forte 			}
246*fcf3ce44SJohn Forte 			if (found) {
247*fcf3ce44SJohn Forte 				(void) strcpy(dev_path,
248*fcf3ce44SJohn Forte 					wwnlp->physical_path);
249*fcf3ce44SJohn Forte 			} else {
250*fcf3ce44SJohn Forte 				return (L_INVALID_PATH);
251*fcf3ce44SJohn Forte 			}
252*fcf3ce44SJohn Forte 		} else {
253*fcf3ce44SJohn Forte 			len = strlen(ses_path) -
254*fcf3ce44SJohn Forte 				strlen(strrchr(ses_path, '/'));
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte 			if (dtype != DTYPE_ESI) {
257*fcf3ce44SJohn Forte 				(void) sprintf(ssd, "/ssd@w%s,0:c", wwn);
258*fcf3ce44SJohn Forte 			} else {
259*fcf3ce44SJohn Forte 				(void) sprintf(ssd, "/ses@w%s,0:c", wwn);
260*fcf3ce44SJohn Forte 			}
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte 			/* TBD: Must find path, not just use :c */
263*fcf3ce44SJohn Forte 			(void) strncpy(dev_path, ses_path, len);
264*fcf3ce44SJohn Forte 			dev_path[len] = '\0';
265*fcf3ce44SJohn Forte 			(void) strcat(dev_path, ssd);
266*fcf3ce44SJohn Forte 		}
267*fcf3ce44SJohn Forte 
268*fcf3ce44SJohn Forte 		if (stat(dev_path, &stat_buf) == -1) {
269*fcf3ce44SJohn Forte 			return (errno);
270*fcf3ce44SJohn Forte 		}
271*fcf3ce44SJohn Forte 
272*fcf3ce44SJohn Forte 		break;
273*fcf3ce44SJohn Forte 	case FC_TOP_PT_PT:
274*fcf3ce44SJohn Forte 		return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
275*fcf3ce44SJohn Forte 	default:
276*fcf3ce44SJohn Forte 		return (L_UNEXPECTED_FC_TOPOLOGY);
277*fcf3ce44SJohn Forte 	}	/* End of switch on port_topology */
278*fcf3ce44SJohn Forte 	return (0);
279*fcf3ce44SJohn Forte }
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 
282*fcf3ce44SJohn Forte 
283*fcf3ce44SJohn Forte /*
284*fcf3ce44SJohn Forte  * checks for null wwn to a disk.
285*fcf3ce44SJohn Forte  * and returns -1 if found, 0
286*fcf3ce44SJohn Forte  * otherwise.
287*fcf3ce44SJohn Forte  *
288*fcf3ce44SJohn Forte  * OUTPUT:
289*fcf3ce44SJohn Forte  *	char	*ses_path
290*fcf3ce44SJohn Forte  *
291*fcf3ce44SJohn Forte  * RETURNS:
292*fcf3ce44SJohn Forte  *	0	 if OK
293*fcf3ce44SJohn Forte  *	non-zero otherwise
294*fcf3ce44SJohn Forte  */
295*fcf3ce44SJohn Forte int
296*fcf3ce44SJohn Forte l_chk_null_wwn(Path_struct *path_struct, char *ses_path,
297*fcf3ce44SJohn Forte 				L_state *l_state, int verbose)
298*fcf3ce44SJohn Forte {
299*fcf3ce44SJohn Forte char		*ptr, boxname[MAXPATHLEN];
300*fcf3ce44SJohn Forte char		node_wwn_s[WWN_SIZE * 2 + 1];
301*fcf3ce44SJohn Forte Box_list	*boxlist;
302*fcf3ce44SJohn Forte 
303*fcf3ce44SJohn Forte 
304*fcf3ce44SJohn Forte 	if ((path_struct == NULL) || (ses_path == NULL) ||
305*fcf3ce44SJohn Forte 	    (l_state == NULL)) {
306*fcf3ce44SJohn Forte 		return (L_INVALID_PATH_FORMAT);
307*fcf3ce44SJohn Forte 	}
308*fcf3ce44SJohn Forte 
309*fcf3ce44SJohn Forte 	/*
310*fcf3ce44SJohn Forte 	 * verify and continue only if the argv
311*fcf3ce44SJohn Forte 	 * has a format like box,{f/r}<slot #>.
312*fcf3ce44SJohn Forte 	 * Otherwise, return to the caller.
313*fcf3ce44SJohn Forte 	 * The only way to address null wwn disk
314*fcf3ce44SJohn Forte 	 * is using the box,{f/r}<slot#> format.
315*fcf3ce44SJohn Forte 	 */
316*fcf3ce44SJohn Forte /* add support for new {f/r/s}<slot#> support for DPM */
317*fcf3ce44SJohn Forte 	(void) strcpy(boxname, path_struct->argv);
318*fcf3ce44SJohn Forte 	if (((ptr = strstr(boxname, ",")) != NULL) &&
319*fcf3ce44SJohn Forte 	    ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') ||
320*fcf3ce44SJohn Forte 	    (*(ptr + 1) == 's'))) {
321*fcf3ce44SJohn Forte 		*ptr = NULL;
322*fcf3ce44SJohn Forte 	} else {
323*fcf3ce44SJohn Forte 		return (0);
324*fcf3ce44SJohn Forte 	}
325*fcf3ce44SJohn Forte 
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte 	/*
328*fcf3ce44SJohn Forte 	 * Get the list of enclosures
329*fcf3ce44SJohn Forte 	 * connected to the system.
330*fcf3ce44SJohn Forte 	 */
331*fcf3ce44SJohn Forte 	if (l_get_box_list(&boxlist, verbose) != 0) {
332*fcf3ce44SJohn Forte 		return (L_NO_ENCL_LIST_FOUND);
333*fcf3ce44SJohn Forte 	}
334*fcf3ce44SJohn Forte 
335*fcf3ce44SJohn Forte 	*ses_path = NULL;
336*fcf3ce44SJohn Forte 
337*fcf3ce44SJohn Forte 	/*
338*fcf3ce44SJohn Forte 	 * The following method is safer to get an ses path
339*fcf3ce44SJohn Forte 	 * to the enclosure than calling l_get_ses_path(),
340*fcf3ce44SJohn Forte 	 * with physical path to null WWN disk.
341*fcf3ce44SJohn Forte 	 * Because, l_get_ses_path uses the disk's
342*fcf3ce44SJohn Forte 	 * al_pa to get the box id and then ses path
343*fcf3ce44SJohn Forte 	 * to the box. When a disk has null wwn, it may
344*fcf3ce44SJohn Forte 	 * not have a valid al_pa, and hard address.
345*fcf3ce44SJohn Forte 	 * There is a possibility that l_get_ses_path()
346*fcf3ce44SJohn Forte 	 * not returning ses path to the correct enclosure.
347*fcf3ce44SJohn Forte 	 */
348*fcf3ce44SJohn Forte 	while (boxlist != NULL) {
349*fcf3ce44SJohn Forte 		if ((strcmp(boxname, (char *)boxlist->b_name) == 0)) {
350*fcf3ce44SJohn Forte 			(void) strcpy(ses_path, boxlist->b_physical_path);
351*fcf3ce44SJohn Forte 			break;
352*fcf3ce44SJohn Forte 		}
353*fcf3ce44SJohn Forte 		boxlist = boxlist->box_next;
354*fcf3ce44SJohn Forte 	}
355*fcf3ce44SJohn Forte 
356*fcf3ce44SJohn Forte 	/* free the box list */
357*fcf3ce44SJohn Forte 	(void) l_free_box_list(&boxlist);
358*fcf3ce44SJohn Forte 
359*fcf3ce44SJohn Forte 	if ((ses_path != NULL) && (strstr(ses_path, "ses") != NULL)) {
360*fcf3ce44SJohn Forte 		if (l_get_status(ses_path, l_state,
361*fcf3ce44SJohn Forte 				verbose) != 0) {
362*fcf3ce44SJohn Forte 			return (L_GET_STATUS_FAILED);
363*fcf3ce44SJohn Forte 		}
364*fcf3ce44SJohn Forte 		if (path_struct->f_flag) {
365*fcf3ce44SJohn Forte 			(void) strcpy(node_wwn_s,
366*fcf3ce44SJohn Forte 		l_state->drv_front[path_struct->slot].g_disk_state.node_wwn_s);
367*fcf3ce44SJohn Forte 		} else {
368*fcf3ce44SJohn Forte 			(void) strcpy(node_wwn_s,
369*fcf3ce44SJohn Forte 		l_state->drv_rear[path_struct->slot].g_disk_state.node_wwn_s);
370*fcf3ce44SJohn Forte 		}
371*fcf3ce44SJohn Forte 
372*fcf3ce44SJohn Forte 		W_DPRINTF("Found ses path: %s\n"
373*fcf3ce44SJohn Forte 			"and Node WWN: %s\n", ses_path, node_wwn_s);
374*fcf3ce44SJohn Forte 
375*fcf3ce44SJohn Forte 		/* check for null WWN */
376*fcf3ce44SJohn Forte 		if (is_null_wwn((uchar_t *)node_wwn_s) == 0) {
377*fcf3ce44SJohn Forte 			return (0);	/* Non-null wwn */
378*fcf3ce44SJohn Forte 		}
379*fcf3ce44SJohn Forte 		W_DPRINTF("Found NULL WWN: %s\n", node_wwn_s);
380*fcf3ce44SJohn Forte 		return (1);
381*fcf3ce44SJohn Forte 	}
382*fcf3ce44SJohn Forte 
383*fcf3ce44SJohn Forte 	return (0);
384*fcf3ce44SJohn Forte 
385*fcf3ce44SJohn Forte }
386*fcf3ce44SJohn Forte 
387*fcf3ce44SJohn Forte 
388*fcf3ce44SJohn Forte 
389*fcf3ce44SJohn Forte /*
390*fcf3ce44SJohn Forte  * If OVERALL_STATUS is sent as the "func",
391*fcf3ce44SJohn Forte  *	the code pointer must be valid (non NULL).
392*fcf3ce44SJohn Forte  * Otherwise NULL is a valid input for the code pointer.
393*fcf3ce44SJohn Forte  *
394*fcf3ce44SJohn Forte  * RETURNS:
395*fcf3ce44SJohn Forte  *	0	 if OK
396*fcf3ce44SJohn Forte  *	non-zero otherwise
397*fcf3ce44SJohn Forte  */
398*fcf3ce44SJohn Forte int
399*fcf3ce44SJohn Forte l_encl_status_page_funcs(int func, char *code, int todo, char *ses_path,
400*fcf3ce44SJohn Forte 					struct l_state_struct  *l_state,
401*fcf3ce44SJohn Forte 				int f_flag, int slot, int verbose_flag)
402*fcf3ce44SJohn Forte {
403*fcf3ce44SJohn Forte uchar_t	*page_buf;
404*fcf3ce44SJohn Forte int 	fd, front_index, rear_index, offset, err;
405*fcf3ce44SJohn Forte unsigned short	page_len;
406*fcf3ce44SJohn Forte struct	device_element *elem;
407*fcf3ce44SJohn Forte 
408*fcf3ce44SJohn Forte 	if ((ses_path == NULL) || (l_state == NULL)) {
409*fcf3ce44SJohn Forte 		return (L_INVALID_PATH_FORMAT);
410*fcf3ce44SJohn Forte 	}
411*fcf3ce44SJohn Forte 
412*fcf3ce44SJohn Forte 	if ((page_buf = (uchar_t *)g_zalloc(MAX_REC_DIAG_LENGTH)) == NULL) {
413*fcf3ce44SJohn Forte 		return (L_MALLOC_FAILED);
414*fcf3ce44SJohn Forte 	}
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) {
417*fcf3ce44SJohn Forte 		(void) g_destroy_data(page_buf);
418*fcf3ce44SJohn Forte 		return (L_OPEN_PATH_FAIL);
419*fcf3ce44SJohn Forte 	}
420*fcf3ce44SJohn Forte 
421*fcf3ce44SJohn Forte 	if ((err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
422*fcf3ce44SJohn Forte 					L_PAGE_2, verbose_flag)) != 0) {
423*fcf3ce44SJohn Forte 		(void) g_destroy_data(page_buf);
424*fcf3ce44SJohn Forte 		(void) close(fd);
425*fcf3ce44SJohn Forte 		return (err);
426*fcf3ce44SJohn Forte 	}
427*fcf3ce44SJohn Forte 
428*fcf3ce44SJohn Forte 	page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN;
429*fcf3ce44SJohn Forte 
430*fcf3ce44SJohn Forte 	if ((err = l_get_disk_element_index(l_state, &front_index,
431*fcf3ce44SJohn Forte 							&rear_index)) != 0) {
432*fcf3ce44SJohn Forte 		(void) g_destroy_data(page_buf);
433*fcf3ce44SJohn Forte 		(void) close(fd);
434*fcf3ce44SJohn Forte 		return (err);
435*fcf3ce44SJohn Forte 	}
436*fcf3ce44SJohn Forte 	/* Skip global element */
437*fcf3ce44SJohn Forte 	front_index++;
438*fcf3ce44SJohn Forte 	if ((strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_OFF_NAME,
439*fcf3ce44SJohn Forte 						strlen(DAK_OFF_NAME)) == 0) ||
440*fcf3ce44SJohn Forte 		(strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_PROD_STR,
441*fcf3ce44SJohn Forte 						strlen(DAK_OFF_NAME)) == 0)) {
442*fcf3ce44SJohn Forte 		rear_index += l_state->total_num_drv/2 + 1;
443*fcf3ce44SJohn Forte 	} else
444*fcf3ce44SJohn Forte 		rear_index++;
445*fcf3ce44SJohn Forte 
446*fcf3ce44SJohn Forte 	if (f_flag) {
447*fcf3ce44SJohn Forte 		offset = (8 + (front_index + slot)*4);
448*fcf3ce44SJohn Forte 	} else {
449*fcf3ce44SJohn Forte 		offset = (8 + (rear_index  + slot)*4);
450*fcf3ce44SJohn Forte 	}
451*fcf3ce44SJohn Forte 
452*fcf3ce44SJohn Forte 	elem = (struct device_element *)(page_buf + offset);
453*fcf3ce44SJohn Forte 
454*fcf3ce44SJohn Forte 	switch (func) {
455*fcf3ce44SJohn Forte 		case OVERALL_STATUS:
456*fcf3ce44SJohn Forte 		    if (code == NULL) {
457*fcf3ce44SJohn Forte 			return (L_INVALID_ARG);
458*fcf3ce44SJohn Forte 		    }
459*fcf3ce44SJohn Forte 		    switch (todo) {
460*fcf3ce44SJohn Forte 			case INSERT_DEVICE:
461*fcf3ce44SJohn Forte 				*code = (elem->code != S_OK) ? elem->code : 0;
462*fcf3ce44SJohn Forte 				(void) g_destroy_data(page_buf);
463*fcf3ce44SJohn Forte 				(void) close(fd);
464*fcf3ce44SJohn Forte 				return (0);
465*fcf3ce44SJohn Forte 			case REMOVE_DEVICE:
466*fcf3ce44SJohn Forte 				*code = (elem->code != S_NOT_INSTALLED) ?
467*fcf3ce44SJohn Forte 					elem->code : 0;
468*fcf3ce44SJohn Forte 				(void) g_destroy_data(page_buf);
469*fcf3ce44SJohn Forte 				(void) close(fd);
470*fcf3ce44SJohn Forte 				return (0);
471*fcf3ce44SJohn Forte 		    }
472*fcf3ce44SJohn Forte 		    /* NOTREACHED */
473*fcf3ce44SJohn Forte 		case SET_RQST_INSRT:
474*fcf3ce44SJohn Forte 			bzero(elem, sizeof (struct device_element));
475*fcf3ce44SJohn Forte 			elem->select = 1;
476*fcf3ce44SJohn Forte 			elem->rdy_to_ins = 1;
477*fcf3ce44SJohn Forte 			break;
478*fcf3ce44SJohn Forte 		case SET_RQST_RMV:
479*fcf3ce44SJohn Forte 			bzero(elem, sizeof (struct device_element));
480*fcf3ce44SJohn Forte 			elem->select = 1;
481*fcf3ce44SJohn Forte 			elem->rmv = 1;
482*fcf3ce44SJohn Forte 			elem->dev_off = 1;
483*fcf3ce44SJohn Forte 			elem->en_bypass_a = 1;
484*fcf3ce44SJohn Forte 			elem->en_bypass_b = 1;
485*fcf3ce44SJohn Forte 			break;
486*fcf3ce44SJohn Forte 		case SET_FAULT:
487*fcf3ce44SJohn Forte 			bzero(elem, sizeof (struct device_element));
488*fcf3ce44SJohn Forte 			elem->select = 1;
489*fcf3ce44SJohn Forte 			elem->fault_req = 1;
490*fcf3ce44SJohn Forte 			elem->dev_off = 1;
491*fcf3ce44SJohn Forte 			elem->en_bypass_a = 1;
492*fcf3ce44SJohn Forte 			elem->en_bypass_b = 1;
493*fcf3ce44SJohn Forte 			break;
494*fcf3ce44SJohn Forte 		case SET_DRV_ON:
495*fcf3ce44SJohn Forte 			bzero(elem, sizeof (struct device_element));
496*fcf3ce44SJohn Forte 			elem->select = 1;
497*fcf3ce44SJohn Forte 			break;
498*fcf3ce44SJohn Forte 	}
499*fcf3ce44SJohn Forte 
500*fcf3ce44SJohn Forte 	err = g_scsi_send_diag_cmd(fd, (uchar_t *)page_buf, page_len);
501*fcf3ce44SJohn Forte 	(void) g_destroy_data(page_buf);
502*fcf3ce44SJohn Forte 	(void) close(fd);
503*fcf3ce44SJohn Forte 	return (err);
504*fcf3ce44SJohn Forte }
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte 
507*fcf3ce44SJohn Forte 
508*fcf3ce44SJohn Forte /*
509*fcf3ce44SJohn Forte  * Finds whether device id (tid) exists in the
510*fcf3ce44SJohn Forte  * Arbitrated loop map or not.
511*fcf3ce44SJohn Forte  *
512*fcf3ce44SJohn Forte  * INPUT:
513*fcf3ce44SJohn Forte  * ses_path	- pointer to a ses path
514*fcf3ce44SJohn Forte  * tid		- the target id of the device we want to check on
515*fcf3ce44SJohn Forte  *		- only the low order 8 bits has the tid
516*fcf3ce44SJohn Forte  * map		- pointer to a map of the system
517*fcf3ce44SJohn Forte  * verbose_flag - self explanatory
518*fcf3ce44SJohn Forte  *
519*fcf3ce44SJohn Forte  * OUTPUT:
520*fcf3ce44SJohn Forte  * dev_path	- the device path of the device with "tid".
521*fcf3ce44SJohn Forte  *                Caller is responsible for freeing it
522*fcf3ce44SJohn Forte  *
523*fcf3ce44SJohn Forte  * RETURNS:
524*fcf3ce44SJohn Forte  *	1	 if device present
525*fcf3ce44SJohn Forte  *	0	 otherwise
526*fcf3ce44SJohn Forte  */
527*fcf3ce44SJohn Forte int
528*fcf3ce44SJohn Forte l_device_present(char *ses_path, int tid, gfc_map_t *map,
529*fcf3ce44SJohn Forte 				int verbose_flag, char **dev_path)
530*fcf3ce44SJohn Forte {
531*fcf3ce44SJohn Forte char			sf_path[MAXPATHLEN];
532*fcf3ce44SJohn Forte uchar_t			wwn[40], c;
533*fcf3ce44SJohn Forte int			len, i, j, k, fnib, snib, this_pid;
534*fcf3ce44SJohn Forte int			fd, ses_pid, al_pa, err;
535*fcf3ce44SJohn Forte char			ssd[30];
536*fcf3ce44SJohn Forte gfc_port_dev_info_t	*dev_addr_ptr;
537*fcf3ce44SJohn Forte WWN_list		*wwnlp, *wwn_list;
538*fcf3ce44SJohn Forte 
539*fcf3ce44SJohn Forte 
540*fcf3ce44SJohn Forte 	if (dev_path == NULL)
541*fcf3ce44SJohn Forte 		return (0);
542*fcf3ce44SJohn Forte 
543*fcf3ce44SJohn Forte 	if ((ses_path == NULL) || (map == NULL)) {
544*fcf3ce44SJohn Forte 		return (L_NO_SES_PATH);
545*fcf3ce44SJohn Forte 	}
546*fcf3ce44SJohn Forte 
547*fcf3ce44SJohn Forte 	*dev_path = NULL;
548*fcf3ce44SJohn Forte 
549*fcf3ce44SJohn Forte 	switch (map->hba_addr.port_topology) {
550*fcf3ce44SJohn Forte 	case FC_TOP_PRIVATE_LOOP:
551*fcf3ce44SJohn Forte 		for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
552*fcf3ce44SJohn Forte 						i++, dev_addr_ptr++) {
553*fcf3ce44SJohn Forte 			if (dev_addr_ptr->gfc_port_dev.
554*fcf3ce44SJohn Forte 				priv_port.sf_inq_dtype != DTYPE_ESI) {
555*fcf3ce44SJohn Forte 				al_pa = dev_addr_ptr->gfc_port_dev.
556*fcf3ce44SJohn Forte 						priv_port.sf_al_pa;
557*fcf3ce44SJohn Forte 				if (tid == g_sf_alpa_to_switch[al_pa]) {
558*fcf3ce44SJohn Forte 					break;
559*fcf3ce44SJohn Forte 				}
560*fcf3ce44SJohn Forte 			}
561*fcf3ce44SJohn Forte 		}
562*fcf3ce44SJohn Forte 		if (i >= map->count)
563*fcf3ce44SJohn Forte 			return (0);
564*fcf3ce44SJohn Forte 		/*
565*fcf3ce44SJohn Forte 		 * Make sure that the port WWN is valid
566*fcf3ce44SJohn Forte 		 */
567*fcf3ce44SJohn Forte 		if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
568*fcf3ce44SJohn Forte 						priv_port.sf_port_wwn)) {
569*fcf3ce44SJohn Forte 			return (0);
570*fcf3ce44SJohn Forte 		}
571*fcf3ce44SJohn Forte 		for (j = 0, k = 0; j < WWN_SIZE; j++) {
572*fcf3ce44SJohn Forte 			c = dev_addr_ptr->gfc_port_dev.priv_port.sf_port_wwn[j];
573*fcf3ce44SJohn Forte 			fnib = (((int)(c & 0xf0)) >> 4);
574*fcf3ce44SJohn Forte 			snib = (c & 0x0f);
575*fcf3ce44SJohn Forte 			if (fnib >= 0 && fnib <= 9)
576*fcf3ce44SJohn Forte 				wwn[k++] = '0' + fnib;
577*fcf3ce44SJohn Forte 			else if (fnib >= 10 && fnib <= 15)
578*fcf3ce44SJohn Forte 				wwn[k++] = 'a' + fnib - 10;
579*fcf3ce44SJohn Forte 			if (snib >= 0 && snib <= 9)
580*fcf3ce44SJohn Forte 				wwn[k++] = '0' + snib;
581*fcf3ce44SJohn Forte 			else if (snib >= 10 && snib <= 15)
582*fcf3ce44SJohn Forte 				wwn[k++] = 'a' + snib - 10;
583*fcf3ce44SJohn Forte 		}
584*fcf3ce44SJohn Forte 		wwn[k] = '\0';
585*fcf3ce44SJohn Forte 		break;
586*fcf3ce44SJohn Forte 	case FC_TOP_PUBLIC_LOOP:
587*fcf3ce44SJohn Forte 	case FC_TOP_FABRIC:
588*fcf3ce44SJohn Forte 		/*
589*fcf3ce44SJohn Forte 		 * Get the phys address (port id) of this ses device
590*fcf3ce44SJohn Forte 		 */
591*fcf3ce44SJohn Forte 		if (err = l_get_pid_from_path(ses_path, map, &ses_pid))
592*fcf3ce44SJohn Forte 			return (err);
593*fcf3ce44SJohn Forte 
594*fcf3ce44SJohn Forte 		for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
595*fcf3ce44SJohn Forte 							i++, dev_addr_ptr++) {
596*fcf3ce44SJohn Forte 			if (dev_addr_ptr->gfc_port_dev.pub_port.dev_dtype !=
597*fcf3ce44SJohn Forte 								DTYPE_ESI) {
598*fcf3ce44SJohn Forte 				/*
599*fcf3ce44SJohn Forte 				 * We have a device. First match the area and
600*fcf3ce44SJohn Forte 				 * domain ids and if they match, then see if
601*fcf3ce44SJohn Forte 				 * the 8bit tid matches the last 8 bits of
602*fcf3ce44SJohn Forte 				 * 'this_pid'
603*fcf3ce44SJohn Forte 				 */
604*fcf3ce44SJohn Forte 				this_pid = dev_addr_ptr->gfc_port_dev.
605*fcf3ce44SJohn Forte 						pub_port.dev_did.port_id;
606*fcf3ce44SJohn Forte 				if ((this_pid & AREA_DOMAIN_ID) ==
607*fcf3ce44SJohn Forte 						(ses_pid & AREA_DOMAIN_ID)) {
608*fcf3ce44SJohn Forte 					if (tid == g_sf_alpa_to_switch[
609*fcf3ce44SJohn Forte 							this_pid & 0xFF])
610*fcf3ce44SJohn Forte 						break;
611*fcf3ce44SJohn Forte 				}
612*fcf3ce44SJohn Forte 			}
613*fcf3ce44SJohn Forte 		}
614*fcf3ce44SJohn Forte 
615*fcf3ce44SJohn Forte 		if (i >= map->count)
616*fcf3ce44SJohn Forte 			return (0);
617*fcf3ce44SJohn Forte 		/*
618*fcf3ce44SJohn Forte 		 * Make sure that the port WWN is valid
619*fcf3ce44SJohn Forte 		 */
620*fcf3ce44SJohn Forte 		if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
621*fcf3ce44SJohn Forte 						pub_port.dev_pwwn.raw_wwn)) {
622*fcf3ce44SJohn Forte 			return (0);
623*fcf3ce44SJohn Forte 		}
624*fcf3ce44SJohn Forte 		for (j = 0, k = 0; j < WWN_SIZE; j++) {
625*fcf3ce44SJohn Forte 			c = dev_addr_ptr->gfc_port_dev.pub_port.
626*fcf3ce44SJohn Forte 							dev_pwwn.raw_wwn[j];
627*fcf3ce44SJohn Forte 			fnib = (((int)(c & 0xf0)) >> 4);
628*fcf3ce44SJohn Forte 			snib = (c & 0x0f);
629*fcf3ce44SJohn Forte 			if (fnib >= 0 && fnib <= 9)
630*fcf3ce44SJohn Forte 				wwn[k++] = '0' + fnib;
631*fcf3ce44SJohn Forte 			else if (fnib >= 10 && fnib <= 15)
632*fcf3ce44SJohn Forte 				wwn[k++] = 'a' + fnib - 10;
633*fcf3ce44SJohn Forte 			if (snib >= 0 && snib <= 9)
634*fcf3ce44SJohn Forte 				wwn[k++] = '0' + snib;
635*fcf3ce44SJohn Forte 			else if (snib >= 10 && snib <= 15)
636*fcf3ce44SJohn Forte 				wwn[k++] = 'a' + snib - 10;
637*fcf3ce44SJohn Forte 		}
638*fcf3ce44SJohn Forte 		wwn[k] = '\0';
639*fcf3ce44SJohn Forte 		break;
640*fcf3ce44SJohn Forte 	case FC_TOP_PT_PT:
641*fcf3ce44SJohn Forte 		return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
642*fcf3ce44SJohn Forte 	default:
643*fcf3ce44SJohn Forte 		return (L_UNEXPECTED_FC_TOPOLOGY);
644*fcf3ce44SJohn Forte 	}	/* End of switch on port_topology */
645*fcf3ce44SJohn Forte 
646*fcf3ce44SJohn Forte 	if (strstr(ses_path, SCSI_VHCI) != NULL) {
647*fcf3ce44SJohn Forte 		if (err = g_get_wwn_list(&wwn_list, 0)) {
648*fcf3ce44SJohn Forte 			return (err);
649*fcf3ce44SJohn Forte 		}
650*fcf3ce44SJohn Forte 		for (wwnlp = wwn_list; wwnlp != NULL;
651*fcf3ce44SJohn Forte 						wwnlp = wwnlp->wwn_next) {
652*fcf3ce44SJohn Forte 			if (memcmp(wwnlp->port_wwn_s, wwn, WWN_S_LEN) == 0) {
653*fcf3ce44SJohn Forte 				break;
654*fcf3ce44SJohn Forte 			}
655*fcf3ce44SJohn Forte 		}
656*fcf3ce44SJohn Forte 		if (wwnlp != NULL) {
657*fcf3ce44SJohn Forte 			if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
658*fcf3ce44SJohn Forte 				g_free_wwn_list(&wwn_list);
659*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
660*fcf3ce44SJohn Forte 			}
661*fcf3ce44SJohn Forte 			(void) strcpy(*dev_path, wwnlp->physical_path);
662*fcf3ce44SJohn Forte 		} else {
663*fcf3ce44SJohn Forte 			g_free_wwn_list(&wwn_list);
664*fcf3ce44SJohn Forte 			return (0);
665*fcf3ce44SJohn Forte 		}
666*fcf3ce44SJohn Forte 	} else {
667*fcf3ce44SJohn Forte 
668*fcf3ce44SJohn Forte 		len = strlen(ses_path) - strlen(strrchr(ses_path, '/'));
669*fcf3ce44SJohn Forte 
670*fcf3ce44SJohn Forte 		(void) sprintf(ssd, "ssd@w%s,0", wwn);
671*fcf3ce44SJohn Forte 
672*fcf3ce44SJohn Forte 		(void) strncpy(sf_path, ses_path, len);
673*fcf3ce44SJohn Forte 		sf_path[len] = '\0';
674*fcf3ce44SJohn Forte 		P_DPRINTF("  l_device_present: wwn=%s, sf_path=%s\n",
675*fcf3ce44SJohn Forte 			wwn, sf_path);
676*fcf3ce44SJohn Forte 
677*fcf3ce44SJohn Forte 		if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
678*fcf3ce44SJohn Forte 			return (L_MALLOC_FAILED);
679*fcf3ce44SJohn Forte 		}
680*fcf3ce44SJohn Forte 		(void) sprintf(*dev_path, "%s/%s", sf_path, ssd);
681*fcf3ce44SJohn Forte 		P_DPRINTF("  l_device_present: dev_path=%s\n", *dev_path);
682*fcf3ce44SJohn Forte 
683*fcf3ce44SJohn Forte 		(void) strcat(*dev_path, ":c");
684*fcf3ce44SJohn Forte 	}
685*fcf3ce44SJohn Forte 	if ((fd = open(*dev_path, O_RDONLY)) == -1) {
686*fcf3ce44SJohn Forte 		free(*dev_path);
687*fcf3ce44SJohn Forte 		*dev_path = NULL;
688*fcf3ce44SJohn Forte 		return (0);
689*fcf3ce44SJohn Forte 	}
690*fcf3ce44SJohn Forte 	(void) close(fd);
691*fcf3ce44SJohn Forte 	return (1);
692*fcf3ce44SJohn Forte }
693*fcf3ce44SJohn Forte 
694*fcf3ce44SJohn Forte 
695*fcf3ce44SJohn Forte 
696*fcf3ce44SJohn Forte /*
697*fcf3ce44SJohn Forte  * onlines the given list of devices
698*fcf3ce44SJohn Forte  * and free up the allocated memory.
699*fcf3ce44SJohn Forte  *
700*fcf3ce44SJohn Forte  * RETURNS:
701*fcf3ce44SJohn Forte  *	N/A
702*fcf3ce44SJohn Forte  */
703*fcf3ce44SJohn Forte static void
704*fcf3ce44SJohn Forte online_dev(struct dlist *dl_head, int force_flag)
705*fcf3ce44SJohn Forte {
706*fcf3ce44SJohn Forte struct dlist	*dl, *dl1;
707*fcf3ce44SJohn Forte 
708*fcf3ce44SJohn Forte 	for (dl = dl_head; dl != NULL; ) {
709*fcf3ce44SJohn Forte 		(void) g_online_drive(dl->multipath, force_flag);
710*fcf3ce44SJohn Forte 		(void) g_free_multipath(dl->multipath);
711*fcf3ce44SJohn Forte 		dl1 = dl;
712*fcf3ce44SJohn Forte 		dl = dl->next;
713*fcf3ce44SJohn Forte 		(void) g_destroy_data(dl1);
714*fcf3ce44SJohn Forte 	}
715*fcf3ce44SJohn Forte }
716*fcf3ce44SJohn Forte 
717*fcf3ce44SJohn Forte 
718*fcf3ce44SJohn Forte 
719*fcf3ce44SJohn Forte /*
720*fcf3ce44SJohn Forte  * offlines all the disks in a
721*fcf3ce44SJohn Forte  * SENA enclosure.
722*fcf3ce44SJohn Forte  *
723*fcf3ce44SJohn Forte  * RETURNS:
724*fcf3ce44SJohn Forte  *	0	 if O.K.
725*fcf3ce44SJohn Forte  *	non-zero otherwise
726*fcf3ce44SJohn Forte  */
727*fcf3ce44SJohn Forte int
728*fcf3ce44SJohn Forte l_offline_photon(struct hotplug_disk_list *hotplug_sena,
729*fcf3ce44SJohn Forte 				struct wwn_list_struct *wwn_list,
730*fcf3ce44SJohn Forte 				int force_flag, int verbose_flag)
731*fcf3ce44SJohn Forte {
732*fcf3ce44SJohn Forte int		i, err;
733*fcf3ce44SJohn Forte struct dlist	*dl_head, *dl_tail, *dl, *dl_ses;
734*fcf3ce44SJohn Forte char		*dev_path, ses_path[MAXPATHLEN];
735*fcf3ce44SJohn Forte L_state		*l_state = NULL;
736*fcf3ce44SJohn Forte 
737*fcf3ce44SJohn Forte 	if (hotplug_sena == NULL) {
738*fcf3ce44SJohn Forte 		return (L_INVALID_PATH_FORMAT);
739*fcf3ce44SJohn Forte 	}
740*fcf3ce44SJohn Forte 
741*fcf3ce44SJohn Forte 	dl_head = dl_tail = NULL;
742*fcf3ce44SJohn Forte 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
743*fcf3ce44SJohn Forte 		return (L_MALLOC_FAILED);
744*fcf3ce44SJohn Forte 	}
745*fcf3ce44SJohn Forte 
746*fcf3ce44SJohn Forte 	/* Get global status for this Photon */
747*fcf3ce44SJohn Forte 	dl_ses = hotplug_sena->seslist;
748*fcf3ce44SJohn Forte 	while (dl_ses) {
749*fcf3ce44SJohn Forte 		(void) strcpy(ses_path, dl_ses->dev_path);
750*fcf3ce44SJohn Forte 		if (l_get_status(ses_path, l_state, verbose_flag) == 0)
751*fcf3ce44SJohn Forte 			break;
752*fcf3ce44SJohn Forte 		dl_ses = dl_ses->next;
753*fcf3ce44SJohn Forte 	}
754*fcf3ce44SJohn Forte 
755*fcf3ce44SJohn Forte 	if (dl_ses == NULL) {
756*fcf3ce44SJohn Forte 		(void) l_free_lstate(&l_state);
757*fcf3ce44SJohn Forte 		return (L_ENCL_INVALID_PATH);
758*fcf3ce44SJohn Forte 	}
759*fcf3ce44SJohn Forte 
760*fcf3ce44SJohn Forte 	for (i = 0; i < l_state->total_num_drv/2; i++) {
761*fcf3ce44SJohn Forte 		if (*l_state->drv_front[i].g_disk_state.physical_path) {
762*fcf3ce44SJohn Forte 			if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
763*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
764*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
765*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
766*fcf3ce44SJohn Forte 			}
767*fcf3ce44SJohn Forte 			(void) strcpy(dev_path,
768*fcf3ce44SJohn Forte 		(char *)&l_state->drv_front[i].g_disk_state.physical_path);
769*fcf3ce44SJohn Forte 			if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) {
770*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
771*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
772*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
773*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
774*fcf3ce44SJohn Forte 			}
775*fcf3ce44SJohn Forte 			dl->dev_path = dev_path;
776*fcf3ce44SJohn Forte 			if ((err = g_get_multipath(dev_path,
777*fcf3ce44SJohn Forte 					&(dl->multipath), wwn_list,  0)) != 0) {
778*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
779*fcf3ce44SJohn Forte 				if (dl->multipath != NULL) {
780*fcf3ce44SJohn Forte 					(void) g_free_multipath(dl->multipath);
781*fcf3ce44SJohn Forte 				}
782*fcf3ce44SJohn Forte 				(void) g_destroy_data(dl);
783*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
784*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
785*fcf3ce44SJohn Forte 				return (err);
786*fcf3ce44SJohn Forte 			}
787*fcf3ce44SJohn Forte 			if ((err = g_offline_drive(dl->multipath,
788*fcf3ce44SJohn Forte 					force_flag)) != 0) {
789*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
790*fcf3ce44SJohn Forte 				(void) g_free_multipath(dl->multipath);
791*fcf3ce44SJohn Forte 				(void) g_destroy_data(dl);
792*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
793*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
794*fcf3ce44SJohn Forte 				return (err);
795*fcf3ce44SJohn Forte 			}
796*fcf3ce44SJohn Forte 			if (dl_head == NULL) {
797*fcf3ce44SJohn Forte 				dl_head = dl_tail = dl;
798*fcf3ce44SJohn Forte 			} else {
799*fcf3ce44SJohn Forte 				dl_tail->next = dl;
800*fcf3ce44SJohn Forte 				dl->prev = dl_tail;
801*fcf3ce44SJohn Forte 				dl_tail = dl;
802*fcf3ce44SJohn Forte 			}
803*fcf3ce44SJohn Forte 			(void) g_destroy_data(dev_path);
804*fcf3ce44SJohn Forte 		}
805*fcf3ce44SJohn Forte 		if (*l_state->drv_rear[i].g_disk_state.physical_path) {
806*fcf3ce44SJohn Forte 			if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
807*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
808*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
809*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
810*fcf3ce44SJohn Forte 			}
811*fcf3ce44SJohn Forte 			(void) strcpy(dev_path,
812*fcf3ce44SJohn Forte 		(char *)&l_state->drv_rear[i].g_disk_state.physical_path);
813*fcf3ce44SJohn Forte 			if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) {
814*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
815*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
816*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
817*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
818*fcf3ce44SJohn Forte 			}
819*fcf3ce44SJohn Forte 			dl->dev_path = dev_path;
820*fcf3ce44SJohn Forte 			if ((err = g_get_multipath(dev_path,
821*fcf3ce44SJohn Forte 					&(dl->multipath), wwn_list, 0)) != 0) {
822*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
823*fcf3ce44SJohn Forte 				if (dl->multipath != NULL) {
824*fcf3ce44SJohn Forte 					(void) g_free_multipath(dl->multipath);
825*fcf3ce44SJohn Forte 				}
826*fcf3ce44SJohn Forte 				(void) g_destroy_data(dl);
827*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
828*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
829*fcf3ce44SJohn Forte 				return (err);
830*fcf3ce44SJohn Forte 			}
831*fcf3ce44SJohn Forte 			if ((err = g_offline_drive(dl->multipath,
832*fcf3ce44SJohn Forte 				force_flag)) != 0) {
833*fcf3ce44SJohn Forte 				(void) g_destroy_data(dev_path);
834*fcf3ce44SJohn Forte 				(void) g_free_multipath(dl->multipath);
835*fcf3ce44SJohn Forte 				(void) g_destroy_data(dl);
836*fcf3ce44SJohn Forte 				(void) online_dev(dl_head, force_flag);
837*fcf3ce44SJohn Forte 				(void) l_free_lstate(&l_state);
838*fcf3ce44SJohn Forte 				return (err);
839*fcf3ce44SJohn Forte 			}
840*fcf3ce44SJohn Forte 			if (dl_head == NULL) {
841*fcf3ce44SJohn Forte 				dl_head = dl_tail = dl;
842*fcf3ce44SJohn Forte 			} else {
843*fcf3ce44SJohn Forte 				dl_tail->next = dl;
844*fcf3ce44SJohn Forte 				dl->prev = dl_tail;
845*fcf3ce44SJohn Forte 				dl_tail = dl;
846*fcf3ce44SJohn Forte 			}
847*fcf3ce44SJohn Forte 			(void) g_destroy_data(dev_path);
848*fcf3ce44SJohn Forte 		}
849*fcf3ce44SJohn Forte 	}
850*fcf3ce44SJohn Forte 	hotplug_sena->dlhead = dl_head;
851*fcf3ce44SJohn Forte 	(void) l_free_lstate(&l_state);
852*fcf3ce44SJohn Forte 	return (0);
853*fcf3ce44SJohn Forte 
854*fcf3ce44SJohn Forte }
855*fcf3ce44SJohn Forte 
856*fcf3ce44SJohn Forte 
857*fcf3ce44SJohn Forte 
858*fcf3ce44SJohn Forte /*
859*fcf3ce44SJohn Forte  * prepares a char string
860*fcf3ce44SJohn Forte  * containing the name of the
861*fcf3ce44SJohn Forte  * device which will be hotplugged.
862*fcf3ce44SJohn Forte  *
863*fcf3ce44SJohn Forte  * RETURNS:
864*fcf3ce44SJohn Forte  *	N/A
865*fcf3ce44SJohn Forte  */
866*fcf3ce44SJohn Forte void
867*fcf3ce44SJohn Forte l_get_drive_name(char *drive_name, int slot, int f_flag, char *box_name)
868*fcf3ce44SJohn Forte {
869*fcf3ce44SJohn Forte int	    enc_type = 0;
870*fcf3ce44SJohn Forte L_inquiry   inq;
871*fcf3ce44SJohn Forte char	    *physpath;
872*fcf3ce44SJohn Forte Path_struct *p_pathstruct;
873*fcf3ce44SJohn Forte 
874*fcf3ce44SJohn Forte 	if ((drive_name == NULL) || (box_name == NULL)) {
875*fcf3ce44SJohn Forte 		return;
876*fcf3ce44SJohn Forte 	}
877*fcf3ce44SJohn Forte 
878*fcf3ce44SJohn Forte 	if (!l_convert_name(box_name, &physpath, &p_pathstruct, 0)) {
879*fcf3ce44SJohn Forte 	    if (!g_get_inquiry(physpath, &inq)) {
880*fcf3ce44SJohn Forte 		enc_type = l_get_enc_type(inq);
881*fcf3ce44SJohn Forte 	    }
882*fcf3ce44SJohn Forte 	}
883*fcf3ce44SJohn Forte 	/* If either of the above fail, we use the default value of 0 */
884*fcf3ce44SJohn Forte 	free(physpath);
885*fcf3ce44SJohn Forte 	free(p_pathstruct);
886*fcf3ce44SJohn Forte 	switch (enc_type) {
887*fcf3ce44SJohn Forte 	case DAK_ENC_TYPE:
888*fcf3ce44SJohn Forte 	    if (f_flag != NULL) {
889*fcf3ce44SJohn Forte 		(void) sprintf(drive_name, MSGSTR(8502,
890*fcf3ce44SJohn Forte 			"Drive in \"%s\" slot %d"), box_name, slot);
891*fcf3ce44SJohn Forte 	    } else {
892*fcf3ce44SJohn Forte 		(void) sprintf(drive_name, MSGSTR(8502,
893*fcf3ce44SJohn Forte 			"Drive in \"%s\" slot %d"), box_name,
894*fcf3ce44SJohn Forte 			slot + (MAX_DRIVES_DAK/2));
895*fcf3ce44SJohn Forte 	    }
896*fcf3ce44SJohn Forte 	    break;
897*fcf3ce44SJohn Forte 	default:
898*fcf3ce44SJohn Forte 	    if (f_flag != NULL) {
899*fcf3ce44SJohn Forte 		(void) sprintf(drive_name, MSGSTR(8500,
900*fcf3ce44SJohn Forte 		    "Drive in \"%s\" front slot %d"), box_name, slot);
901*fcf3ce44SJohn Forte 	    } else {
902*fcf3ce44SJohn Forte 		(void) sprintf(drive_name, MSGSTR(8501,
903*fcf3ce44SJohn Forte 		    "Drive in \"%s\" rear slot %d"), box_name, slot);
904*fcf3ce44SJohn Forte 	    }
905*fcf3ce44SJohn Forte 	    break;
906*fcf3ce44SJohn Forte 	}
907*fcf3ce44SJohn Forte }
908