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