xref: /onnv-gate/usr/src/lib/storage/liba5k/common/mon.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  * I18N message number ranges
31*7836SJohn.Forte@Sun.COM  *  This file: 9000 - 9499
32*7836SJohn.Forte@Sun.COM  *  Shared common messages: 1 - 1999
33*7836SJohn.Forte@Sun.COM  */
34*7836SJohn.Forte@Sun.COM 
35*7836SJohn.Forte@Sun.COM /*
36*7836SJohn.Forte@Sun.COM  *	This module is part of the photon library
37*7836SJohn.Forte@Sun.COM  */
38*7836SJohn.Forte@Sun.COM /*	Includes	*/
39*7836SJohn.Forte@Sun.COM #include	<stdlib.h>
40*7836SJohn.Forte@Sun.COM #include	<stdio.h>
41*7836SJohn.Forte@Sun.COM #include	<sys/file.h>
42*7836SJohn.Forte@Sun.COM #include	<sys/types.h>
43*7836SJohn.Forte@Sun.COM #include	<sys/stat.h>
44*7836SJohn.Forte@Sun.COM #include	<sys/param.h>
45*7836SJohn.Forte@Sun.COM #include	<fcntl.h>
46*7836SJohn.Forte@Sun.COM #include	<unistd.h>
47*7836SJohn.Forte@Sun.COM #include	<errno.h>
48*7836SJohn.Forte@Sun.COM #include	<string.h>
49*7836SJohn.Forte@Sun.COM #include	<assert.h>
50*7836SJohn.Forte@Sun.COM #include	<sys/scsi/scsi.h>
51*7836SJohn.Forte@Sun.COM #include	<dirent.h>		/* for DIR */
52*7836SJohn.Forte@Sun.COM #include	<sys/vtoc.h>
53*7836SJohn.Forte@Sun.COM #include	<sys/dkio.h>
54*7836SJohn.Forte@Sun.COM #include	<nl_types.h>
55*7836SJohn.Forte@Sun.COM #include	<strings.h>
56*7836SJohn.Forte@Sun.COM #include	<sys/ddi.h>		/* for max */
57*7836SJohn.Forte@Sun.COM #include	<l_common.h>
58*7836SJohn.Forte@Sun.COM #include	<stgcom.h>
59*7836SJohn.Forte@Sun.COM #include	<l_error.h>
60*7836SJohn.Forte@Sun.COM #include	<rom.h>
61*7836SJohn.Forte@Sun.COM #include	<exec.h>
62*7836SJohn.Forte@Sun.COM #include	<a_state.h>
63*7836SJohn.Forte@Sun.COM #include	<a5k.h>
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM 
66*7836SJohn.Forte@Sun.COM /*	Defines 	*/
67*7836SJohn.Forte@Sun.COM #define	PLNDEF		"SUNW,pln"	/* check if box name starts with 'c' */
68*7836SJohn.Forte@Sun.COM #define	DOWNLOAD_RETRIES	60*5	/* 5 minutes */
69*7836SJohn.Forte@Sun.COM #define	IBFIRMWARE_FILE		"/usr/lib/locale/C/LC_MESSAGES/ibfirmware"
70*7836SJohn.Forte@Sun.COM 
71*7836SJohn.Forte@Sun.COM /*	Global variables	*/
72*7836SJohn.Forte@Sun.COM extern	uchar_t		g_switch_to_alpa[];
73*7836SJohn.Forte@Sun.COM extern	uchar_t		g_sf_alpa_to_switch[];
74*7836SJohn.Forte@Sun.COM 
75*7836SJohn.Forte@Sun.COM /*	Forward declarations	*/
76*7836SJohn.Forte@Sun.COM static	int pwr_up_down(char *, L_state *, int, int, int, int);
77*7836SJohn.Forte@Sun.COM static	int load_flds_if_enc_disk(char *, struct path_struct **);
78*7836SJohn.Forte@Sun.COM static	int copy_config_page(struct l_state_struct *, uchar_t *);
79*7836SJohn.Forte@Sun.COM static	void copy_page_7(struct l_state_struct *, uchar_t *);
80*7836SJohn.Forte@Sun.COM static	int l_get_node_status(char *, struct l_disk_state_struct *,
81*7836SJohn.Forte@Sun.COM 	int *, WWN_list *, int);
82*7836SJohn.Forte@Sun.COM static	int check_file(int, int, uchar_t **, int);
83*7836SJohn.Forte@Sun.COM static	int check_dpm_file(int);
84*7836SJohn.Forte@Sun.COM static	int ib_download_code_cmd(int, int, int, uchar_t *, int, int);
85*7836SJohn.Forte@Sun.COM static	int dak_download_code_cmd(int, uchar_t *, int);
86*7836SJohn.Forte@Sun.COM static	void free_mp_dev_map(struct gfc_map_mp **);
87*7836SJohn.Forte@Sun.COM static	int get_mp_dev_map(char *, struct gfc_map_mp **, int);
88*7836SJohn.Forte@Sun.COM 
89*7836SJohn.Forte@Sun.COM /*
90*7836SJohn.Forte@Sun.COM  * l_get_mode_pg() - Read all mode pages.
91*7836SJohn.Forte@Sun.COM  *
92*7836SJohn.Forte@Sun.COM  * RETURNS:
93*7836SJohn.Forte@Sun.COM  *	0        O.K.
94*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
95*7836SJohn.Forte@Sun.COM  *
96*7836SJohn.Forte@Sun.COM  * INPUTS:
97*7836SJohn.Forte@Sun.COM  *	path     pointer to device path
98*7836SJohn.Forte@Sun.COM  *	pg_buf   ptr to mode pages
99*7836SJohn.Forte@Sun.COM  *
100*7836SJohn.Forte@Sun.COM  */
101*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
102*7836SJohn.Forte@Sun.COM int
l_get_mode_pg(char * path,uchar_t ** pg_buf,int verbose)103*7836SJohn.Forte@Sun.COM l_get_mode_pg(char *path, uchar_t **pg_buf, int verbose)
104*7836SJohn.Forte@Sun.COM {
105*7836SJohn.Forte@Sun.COM Mode_header_10	*mode_header_ptr;
106*7836SJohn.Forte@Sun.COM int		status, size, fd;
107*7836SJohn.Forte@Sun.COM 
108*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  l_get_mode_pg: Reading Mode Sense pages.\n");
109*7836SJohn.Forte@Sun.COM 
110*7836SJohn.Forte@Sun.COM 	/* do not do mode sense if this is a tape device */
111*7836SJohn.Forte@Sun.COM 	/* mode sense will rewind the tape */
112*7836SJohn.Forte@Sun.COM 	if (strstr(path, SLSH_DRV_NAME_ST)) {
113*7836SJohn.Forte@Sun.COM 		return (-1);
114*7836SJohn.Forte@Sun.COM 	}
115*7836SJohn.Forte@Sun.COM 
116*7836SJohn.Forte@Sun.COM 	/* open controller */
117*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path, O_NDELAY | O_RDWR)) == -1)
118*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM 	/*
121*7836SJohn.Forte@Sun.COM 	 * Read the first part of the page to get the page size
122*7836SJohn.Forte@Sun.COM 	 */
123*7836SJohn.Forte@Sun.COM 	size = 20;
124*7836SJohn.Forte@Sun.COM 	if ((*pg_buf = (uchar_t *)g_zalloc(size)) == NULL) {
125*7836SJohn.Forte@Sun.COM 	    (void) close(fd);
126*7836SJohn.Forte@Sun.COM 	    return (L_MALLOC_FAILED);
127*7836SJohn.Forte@Sun.COM 	}
128*7836SJohn.Forte@Sun.COM 	/* read page */
129*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_mode_sense_cmd(fd, *pg_buf, size,
130*7836SJohn.Forte@Sun.COM 	    0, MODEPAGE_ALLPAGES)) {
131*7836SJohn.Forte@Sun.COM 	    (void) close(fd);
132*7836SJohn.Forte@Sun.COM 	    (void) g_destroy_data((char *)*pg_buf);
133*7836SJohn.Forte@Sun.COM 	    return (status);
134*7836SJohn.Forte@Sun.COM 	}
135*7836SJohn.Forte@Sun.COM 	/* Now get the size for all pages */
136*7836SJohn.Forte@Sun.COM 	mode_header_ptr = (struct mode_header_10_struct *)(void *)*pg_buf;
137*7836SJohn.Forte@Sun.COM 	size = mode_header_ptr->length + sizeof (mode_header_ptr->length);
138*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data((char *)*pg_buf);
139*7836SJohn.Forte@Sun.COM 	if ((*pg_buf = (uchar_t *)g_zalloc(size)) == NULL) {
140*7836SJohn.Forte@Sun.COM 	    (void) close(fd);
141*7836SJohn.Forte@Sun.COM 	    return (L_MALLOC_FAILED);
142*7836SJohn.Forte@Sun.COM 	}
143*7836SJohn.Forte@Sun.COM 	/* read all pages */
144*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_mode_sense_cmd(fd, *pg_buf, size,
145*7836SJohn.Forte@Sun.COM 					0, MODEPAGE_ALLPAGES)) {
146*7836SJohn.Forte@Sun.COM 	    (void) close(fd);
147*7836SJohn.Forte@Sun.COM 	    (void) g_destroy_data((char *)*pg_buf);
148*7836SJohn.Forte@Sun.COM 	    return (status);
149*7836SJohn.Forte@Sun.COM 	}
150*7836SJohn.Forte@Sun.COM 	(void) close(fd);
151*7836SJohn.Forte@Sun.COM 	return (0);
152*7836SJohn.Forte@Sun.COM }
153*7836SJohn.Forte@Sun.COM 
154*7836SJohn.Forte@Sun.COM 
155*7836SJohn.Forte@Sun.COM 
156*7836SJohn.Forte@Sun.COM /*
157*7836SJohn.Forte@Sun.COM  * Format QLA21xx status
158*7836SJohn.Forte@Sun.COM  *
159*7836SJohn.Forte@Sun.COM  * INPUTS: message buffer
160*7836SJohn.Forte@Sun.COM  *         Count
161*7836SJohn.Forte@Sun.COM  *         status
162*7836SJohn.Forte@Sun.COM  *
163*7836SJohn.Forte@Sun.COM  * OUTPUT: Message of this format in message buffer
164*7836SJohn.Forte@Sun.COM  *         "status type:            0xstatus        count"
165*7836SJohn.Forte@Sun.COM  */
166*7836SJohn.Forte@Sun.COM int
l_format_ifp_status_msg(char * status_msg_buf,int count,int status)167*7836SJohn.Forte@Sun.COM l_format_ifp_status_msg(char *status_msg_buf, int count, int status)
168*7836SJohn.Forte@Sun.COM {
169*7836SJohn.Forte@Sun.COM 	if (status_msg_buf == NULL) {
170*7836SJohn.Forte@Sun.COM 		return (0);
171*7836SJohn.Forte@Sun.COM 	}
172*7836SJohn.Forte@Sun.COM 
173*7836SJohn.Forte@Sun.COM 	switch (status) {
174*7836SJohn.Forte@Sun.COM 	case IFP_CMD_CMPLT:
175*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
176*7836SJohn.Forte@Sun.COM 			MSGSTR(9000, "O.K.                          0x%-2x"
177*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
178*7836SJohn.Forte@Sun.COM 		break;
179*7836SJohn.Forte@Sun.COM 	case IFP_CMD_INCOMPLETE:
180*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
181*7836SJohn.Forte@Sun.COM 			MSGSTR(9001, "Cmd incomplete                0x%-2x"
182*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
183*7836SJohn.Forte@Sun.COM 		break;
184*7836SJohn.Forte@Sun.COM 	case IFP_CMD_DMA_DERR:
185*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
186*7836SJohn.Forte@Sun.COM 			MSGSTR(9002, "DMA direction error           0x%-2x"
187*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
188*7836SJohn.Forte@Sun.COM 		break;
189*7836SJohn.Forte@Sun.COM 	case IFP_CMD_TRAN_ERR:
190*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
191*7836SJohn.Forte@Sun.COM 			MSGSTR(9003, "Unspecified transport error   0x%-2x"
192*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
193*7836SJohn.Forte@Sun.COM 		break;
194*7836SJohn.Forte@Sun.COM 	case IFP_CMD_RESET:
195*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
196*7836SJohn.Forte@Sun.COM 			MSGSTR(9004, "Reset aborted transport       0x%-2x"
197*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
198*7836SJohn.Forte@Sun.COM 		break;
199*7836SJohn.Forte@Sun.COM 	case IFP_CMD_ABORTED:
200*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
201*7836SJohn.Forte@Sun.COM 			MSGSTR(9005, "Cmd aborted                   0x%-2x"
202*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
203*7836SJohn.Forte@Sun.COM 		break;
204*7836SJohn.Forte@Sun.COM 	case IFP_CMD_TIMEOUT:
205*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
206*7836SJohn.Forte@Sun.COM 			MSGSTR(9006, "Cmd Timeout                   0x%-2x"
207*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
208*7836SJohn.Forte@Sun.COM 		break;
209*7836SJohn.Forte@Sun.COM 	case IFP_CMD_DATA_OVR:
210*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
211*7836SJohn.Forte@Sun.COM 			MSGSTR(9007, "Data Overrun                  0x%-2x"
212*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
213*7836SJohn.Forte@Sun.COM 		break;
214*7836SJohn.Forte@Sun.COM 	case IFP_CMD_ABORT_REJECTED:
215*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
216*7836SJohn.Forte@Sun.COM 			MSGSTR(9008, "Target rejected abort msg     0x%-2x"
217*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
218*7836SJohn.Forte@Sun.COM 		break;
219*7836SJohn.Forte@Sun.COM 	case IFP_CMD_RESET_REJECTED:
220*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
221*7836SJohn.Forte@Sun.COM 			MSGSTR(9009, "Target rejected reset msg     0x%-2x"
222*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
223*7836SJohn.Forte@Sun.COM 		break;
224*7836SJohn.Forte@Sun.COM 	case IFP_CMD_DATA_UNDER:
225*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
226*7836SJohn.Forte@Sun.COM 			MSGSTR(9010, "Data underrun                 0x%-2x"
227*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
228*7836SJohn.Forte@Sun.COM 		break;
229*7836SJohn.Forte@Sun.COM 	case IFP_CMD_QUEUE_FULL:
230*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
231*7836SJohn.Forte@Sun.COM 			MSGSTR(9011, "Queue full SCSI status        0x%-2x"
232*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
233*7836SJohn.Forte@Sun.COM 		break;
234*7836SJohn.Forte@Sun.COM 	case IFP_CMD_PORT_UNAVAIL:
235*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
236*7836SJohn.Forte@Sun.COM 			MSGSTR(9012, "Port unavailable              0x%-2x"
237*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
238*7836SJohn.Forte@Sun.COM 		break;
239*7836SJohn.Forte@Sun.COM 	case IFP_CMD_PORT_LOGGED_OUT:
240*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
241*7836SJohn.Forte@Sun.COM 			MSGSTR(9013, "Port loged out                0x%-2x"
242*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
243*7836SJohn.Forte@Sun.COM 		break;
244*7836SJohn.Forte@Sun.COM 	case IFP_CMD_PORT_CONFIG_CHANGED:
245*7836SJohn.Forte@Sun.COM 		/* Not enough packets for given request */
246*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
247*7836SJohn.Forte@Sun.COM 			MSGSTR(9014, "Port name changed             0x%-2x"
248*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
249*7836SJohn.Forte@Sun.COM 		break;
250*7836SJohn.Forte@Sun.COM 	default:
251*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
252*7836SJohn.Forte@Sun.COM 			"%s                0x%-2x"
253*7836SJohn.Forte@Sun.COM 			"            %d", MSGSTR(4, "Unknown status"),
254*7836SJohn.Forte@Sun.COM 			status, count);
255*7836SJohn.Forte@Sun.COM 
256*7836SJohn.Forte@Sun.COM 	} /* End of switch() */
257*7836SJohn.Forte@Sun.COM 
258*7836SJohn.Forte@Sun.COM 	return (0);
259*7836SJohn.Forte@Sun.COM 
260*7836SJohn.Forte@Sun.COM }
261*7836SJohn.Forte@Sun.COM 
262*7836SJohn.Forte@Sun.COM 
263*7836SJohn.Forte@Sun.COM 
264*7836SJohn.Forte@Sun.COM /*
265*7836SJohn.Forte@Sun.COM  * Format Fibre Channel status
266*7836SJohn.Forte@Sun.COM  *
267*7836SJohn.Forte@Sun.COM  * INPUTS: message buffer
268*7836SJohn.Forte@Sun.COM  *         Count
269*7836SJohn.Forte@Sun.COM  *         status
270*7836SJohn.Forte@Sun.COM  *
271*7836SJohn.Forte@Sun.COM  * OUTPUT: Message of this format in message buffer
272*7836SJohn.Forte@Sun.COM  *         "status type:            0xstatus        count"
273*7836SJohn.Forte@Sun.COM  */
274*7836SJohn.Forte@Sun.COM int
l_format_fc_status_msg(char * status_msg_buf,int count,int status)275*7836SJohn.Forte@Sun.COM l_format_fc_status_msg(char *status_msg_buf, int count, int status)
276*7836SJohn.Forte@Sun.COM {
277*7836SJohn.Forte@Sun.COM 	if (status_msg_buf == NULL) {
278*7836SJohn.Forte@Sun.COM 		return (0);
279*7836SJohn.Forte@Sun.COM 	}
280*7836SJohn.Forte@Sun.COM 
281*7836SJohn.Forte@Sun.COM 	switch (status) {
282*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_OK:
283*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
284*7836SJohn.Forte@Sun.COM 			MSGSTR(9015, "O.K.                          0x%-2x"
285*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
286*7836SJohn.Forte@Sun.COM 		break;
287*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_P_RJT:
288*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
289*7836SJohn.Forte@Sun.COM 			MSGSTR(9016, "P_RJT (Frame Rejected)        0x%-2x"
290*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
291*7836SJohn.Forte@Sun.COM 		break;
292*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_F_RJT:
293*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
294*7836SJohn.Forte@Sun.COM 			MSGSTR(9017, "F_RJT (Frame Rejected)        0x%-2x"
295*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
296*7836SJohn.Forte@Sun.COM 		break;
297*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_P_BSY:
298*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
299*7836SJohn.Forte@Sun.COM 			MSGSTR(9018, "P_BSY (Port Busy)             0x%-2x"
300*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
301*7836SJohn.Forte@Sun.COM 		break;
302*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_F_BSY:
303*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
304*7836SJohn.Forte@Sun.COM 			MSGSTR(9019, "F_BSY (Port Busy)             0x%-2x"
305*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
306*7836SJohn.Forte@Sun.COM 		break;
307*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_OLDPORT_ONLINE:
308*7836SJohn.Forte@Sun.COM 		/* Should not happen. */
309*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
310*7836SJohn.Forte@Sun.COM 			MSGSTR(9020, "Old port Online               0x%-2x"
311*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
312*7836SJohn.Forte@Sun.COM 		break;
313*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ERR_OFFLINE:
314*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
315*7836SJohn.Forte@Sun.COM 			MSGSTR(9021, "Link Offline                  0x%-2x"
316*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
317*7836SJohn.Forte@Sun.COM 		break;
318*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_TIMEOUT:
319*7836SJohn.Forte@Sun.COM 		/* Should not happen. */
320*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
321*7836SJohn.Forte@Sun.COM 			MSGSTR(9022, "Sequence Timeout              0x%-2x"
322*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
323*7836SJohn.Forte@Sun.COM 		break;
324*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ERR_OVERRUN:
325*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
326*7836SJohn.Forte@Sun.COM 			MSGSTR(9023, "Sequence Payload Overrun      0x%-2x"
327*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
328*7836SJohn.Forte@Sun.COM 		break;
329*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_LOOP_ONLINE:
330*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
331*7836SJohn.Forte@Sun.COM 			MSGSTR(9060, "Loop Online                   0x%-2x"
332*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
333*7836SJohn.Forte@Sun.COM 		break;
334*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_OLD_PORT:
335*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
336*7836SJohn.Forte@Sun.COM 			MSGSTR(9061, "Old port                      0x%-2x"
337*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
338*7836SJohn.Forte@Sun.COM 		break;
339*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_AL_PORT:
340*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
341*7836SJohn.Forte@Sun.COM 			MSGSTR(9062, "AL port                       0x%-2x"
342*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
343*7836SJohn.Forte@Sun.COM 		break;
344*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_UNKNOWN_CQ_TYPE:
345*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
346*7836SJohn.Forte@Sun.COM 			MSGSTR(9024, "Unknown request type          0x%-2x"
347*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
348*7836SJohn.Forte@Sun.COM 		break;
349*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_BAD_SEG_CNT:
350*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
351*7836SJohn.Forte@Sun.COM 			MSGSTR(9025, "Bad segment count             0x%-2x"
352*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
353*7836SJohn.Forte@Sun.COM 		break;
354*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_MAX_XCHG_EXCEEDED:
355*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
356*7836SJohn.Forte@Sun.COM 			MSGSTR(9026, "Maximum exchanges exceeded    0x%-2x"
357*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
358*7836SJohn.Forte@Sun.COM 		break;
359*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_BAD_XID:
360*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
361*7836SJohn.Forte@Sun.COM 			MSGSTR(9027, "Bad exchange identifier       0x%-2x"
362*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
363*7836SJohn.Forte@Sun.COM 		break;
364*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_XCHG_BUSY:
365*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
366*7836SJohn.Forte@Sun.COM 			MSGSTR(9028, "Duplicate exchange request    0x%-2x"
367*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
368*7836SJohn.Forte@Sun.COM 		break;
369*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_BAD_POOL_ID:
370*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
371*7836SJohn.Forte@Sun.COM 			MSGSTR(9029, "Bad memory pool ID            0x%-2x"
372*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
373*7836SJohn.Forte@Sun.COM 		break;
374*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_INSUFFICIENT_CQES:
375*7836SJohn.Forte@Sun.COM 		/* Not enough packets for given request */
376*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
377*7836SJohn.Forte@Sun.COM 			MSGSTR(9030, "Invalid # of segments for req 0x%-2x"
378*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
379*7836SJohn.Forte@Sun.COM 		break;
380*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ALLOC_FAIL:
381*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
382*7836SJohn.Forte@Sun.COM 			MSGSTR(9031, "Resource allocation failure   0x%-2x"
383*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
384*7836SJohn.Forte@Sun.COM 		break;
385*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_BAD_SID:
386*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
387*7836SJohn.Forte@Sun.COM 			MSGSTR(9032, "Bad Source Identifier(S_ID)   0x%-2x"
388*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
389*7836SJohn.Forte@Sun.COM 		break;
390*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_NO_SEQ_INIT:
391*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
392*7836SJohn.Forte@Sun.COM 			MSGSTR(9033, "No sequence initiative        0x%-2x"
393*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
394*7836SJohn.Forte@Sun.COM 		break;
395*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_BAD_DID:
396*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
397*7836SJohn.Forte@Sun.COM 			MSGSTR(9034, "Bad Destination ID(D_ID)      0x%-2x"
398*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
399*7836SJohn.Forte@Sun.COM 		break;
400*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ABORTED:
401*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
402*7836SJohn.Forte@Sun.COM 			MSGSTR(9035, "Received BA_ACC from abort    0x%-2x"
403*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
404*7836SJohn.Forte@Sun.COM 		break;
405*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ABORT_FAILED:
406*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
407*7836SJohn.Forte@Sun.COM 			MSGSTR(9036, "Received BA_RJT from abort    0x%-2x"
408*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
409*7836SJohn.Forte@Sun.COM 		break;
410*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_DIAG_BUSY:
411*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
412*7836SJohn.Forte@Sun.COM 			MSGSTR(9037, "Diagnostics currently busy    0x%-2x"
413*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
414*7836SJohn.Forte@Sun.COM 		break;
415*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_DIAG_INVALID:
416*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
417*7836SJohn.Forte@Sun.COM 			MSGSTR(9038, "Diagnostics illegal request   0x%-2x"
418*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
419*7836SJohn.Forte@Sun.COM 		break;
420*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_INCOMPLETE_DMA_ERR:
421*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
422*7836SJohn.Forte@Sun.COM 			MSGSTR(9039, "SBus DMA did not complete     0x%-2x"
423*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
424*7836SJohn.Forte@Sun.COM 		break;
425*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_CRC_ERR:
426*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
427*7836SJohn.Forte@Sun.COM 			MSGSTR(9040, "CRC error detected            0x%-2x"
428*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
429*7836SJohn.Forte@Sun.COM 		break;
430*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_OPEN_FAIL:
431*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
432*7836SJohn.Forte@Sun.COM 			MSGSTR(9063, "Open failure                  0x%-2x"
433*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
434*7836SJohn.Forte@Sun.COM 		break;
435*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ERROR:
436*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
437*7836SJohn.Forte@Sun.COM 			MSGSTR(9041, "Invalid status error          0x%-2x"
438*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
439*7836SJohn.Forte@Sun.COM 		break;
440*7836SJohn.Forte@Sun.COM 	case FCAL_STATUS_ONLINE_TIMEOUT:
441*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
442*7836SJohn.Forte@Sun.COM 			MSGSTR(9042, "Timed out before ONLINE       0x%-2x"
443*7836SJohn.Forte@Sun.COM 			"            %d"), status, count);
444*7836SJohn.Forte@Sun.COM 		break;
445*7836SJohn.Forte@Sun.COM 	default:
446*7836SJohn.Forte@Sun.COM 		(void) sprintf(status_msg_buf,
447*7836SJohn.Forte@Sun.COM 			"%s                0x%-2x"
448*7836SJohn.Forte@Sun.COM 			"            %d", MSGSTR(4, "Unknown status"),
449*7836SJohn.Forte@Sun.COM 			status, count);
450*7836SJohn.Forte@Sun.COM 
451*7836SJohn.Forte@Sun.COM 	} /* End of switch() */
452*7836SJohn.Forte@Sun.COM 
453*7836SJohn.Forte@Sun.COM 	return (0);
454*7836SJohn.Forte@Sun.COM 
455*7836SJohn.Forte@Sun.COM }
456*7836SJohn.Forte@Sun.COM 
457*7836SJohn.Forte@Sun.COM 
458*7836SJohn.Forte@Sun.COM 
459*7836SJohn.Forte@Sun.COM /*
460*7836SJohn.Forte@Sun.COM  * Get the indexes to the disk device elements in page 2,
461*7836SJohn.Forte@Sun.COM  * based on the locations found in page 1.
462*7836SJohn.Forte@Sun.COM  *
463*7836SJohn.Forte@Sun.COM  * RETURNS:
464*7836SJohn.Forte@Sun.COM  *	0	 O.K.
465*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
466*7836SJohn.Forte@Sun.COM  */
467*7836SJohn.Forte@Sun.COM int
l_get_disk_element_index(struct l_state_struct * l_state,int * front_index,int * rear_index)468*7836SJohn.Forte@Sun.COM l_get_disk_element_index(struct l_state_struct *l_state, int *front_index,
469*7836SJohn.Forte@Sun.COM 						int *rear_index)
470*7836SJohn.Forte@Sun.COM {
471*7836SJohn.Forte@Sun.COM int	index = 0, front_flag = 0, local_front = 0, local_rear = 0;
472*7836SJohn.Forte@Sun.COM int	i, rear_flag = 0;
473*7836SJohn.Forte@Sun.COM 
474*7836SJohn.Forte@Sun.COM 	if ((l_state == NULL) || (front_index == NULL) ||
475*7836SJohn.Forte@Sun.COM 	    (rear_index == NULL)) {
476*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
477*7836SJohn.Forte@Sun.COM 	}
478*7836SJohn.Forte@Sun.COM 
479*7836SJohn.Forte@Sun.COM 	*front_index = *rear_index = 0;
480*7836SJohn.Forte@Sun.COM 	/* Get the indexes to the disk device elements */
481*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)l_state->ib_tbl.config.enc_num_elem; i++) {
482*7836SJohn.Forte@Sun.COM 		if (l_state->ib_tbl.config.type_hdr[i].type == ELM_TYP_DD) {
483*7836SJohn.Forte@Sun.COM 			if (front_flag) {
484*7836SJohn.Forte@Sun.COM 				local_rear = index;
485*7836SJohn.Forte@Sun.COM 				rear_flag = 1;
486*7836SJohn.Forte@Sun.COM 				break;
487*7836SJohn.Forte@Sun.COM 			} else {
488*7836SJohn.Forte@Sun.COM 				local_front = index;
489*7836SJohn.Forte@Sun.COM 				front_flag = 1;
490*7836SJohn.Forte@Sun.COM 			}
491*7836SJohn.Forte@Sun.COM 		}
492*7836SJohn.Forte@Sun.COM 		index += l_state->ib_tbl.config.type_hdr[i].num;
493*7836SJohn.Forte@Sun.COM 		index++;		/* for global element */
494*7836SJohn.Forte@Sun.COM 	}
495*7836SJohn.Forte@Sun.COM 
496*7836SJohn.Forte@Sun.COM 	D_DPRINTF("  l_get_disk_element_index:"
497*7836SJohn.Forte@Sun.COM 		" Index to front disk elements 0x%x\n"
498*7836SJohn.Forte@Sun.COM 		"  l_get_disk_element_index:"
499*7836SJohn.Forte@Sun.COM 		" Index to rear disk elements 0x%x\n",
500*7836SJohn.Forte@Sun.COM 		local_front, local_rear);
501*7836SJohn.Forte@Sun.COM 
502*7836SJohn.Forte@Sun.COM 	if (!front_flag && !rear_flag) {    /* neither is found */
503*7836SJohn.Forte@Sun.COM 		return (L_RD_NO_DISK_ELEM);
504*7836SJohn.Forte@Sun.COM 	}
505*7836SJohn.Forte@Sun.COM 	*front_index = local_front;
506*7836SJohn.Forte@Sun.COM 	*rear_index = local_rear;
507*7836SJohn.Forte@Sun.COM 	return (0);
508*7836SJohn.Forte@Sun.COM }
509*7836SJohn.Forte@Sun.COM 
510*7836SJohn.Forte@Sun.COM 
511*7836SJohn.Forte@Sun.COM 
512*7836SJohn.Forte@Sun.COM /*
513*7836SJohn.Forte@Sun.COM  * l_led() manage the device led's
514*7836SJohn.Forte@Sun.COM  *
515*7836SJohn.Forte@Sun.COM  * RETURNS:
516*7836SJohn.Forte@Sun.COM  *	0	 O.K.
517*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
518*7836SJohn.Forte@Sun.COM  */
519*7836SJohn.Forte@Sun.COM int
l_led(struct path_struct * path_struct,int led_action,struct device_element * status,int verbose)520*7836SJohn.Forte@Sun.COM l_led(struct path_struct *path_struct, int led_action,
521*7836SJohn.Forte@Sun.COM 	struct device_element *status,
522*7836SJohn.Forte@Sun.COM 	int verbose)
523*7836SJohn.Forte@Sun.COM {
524*7836SJohn.Forte@Sun.COM gfc_map_t		map;
525*7836SJohn.Forte@Sun.COM char			ses_path[MAXPATHLEN];
526*7836SJohn.Forte@Sun.COM uchar_t			*page_buf;
527*7836SJohn.Forte@Sun.COM int 			err, write, fd, front_index, rear_index, offset;
528*7836SJohn.Forte@Sun.COM unsigned short		page_len;
529*7836SJohn.Forte@Sun.COM struct	device_element 	*elem;
530*7836SJohn.Forte@Sun.COM L_state			*l_state;
531*7836SJohn.Forte@Sun.COM int			enc_type;
532*7836SJohn.Forte@Sun.COM 
533*7836SJohn.Forte@Sun.COM 	if ((path_struct == NULL) || (status == NULL)) {
534*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
535*7836SJohn.Forte@Sun.COM 	}
536*7836SJohn.Forte@Sun.COM 
537*7836SJohn.Forte@Sun.COM 	/*
538*7836SJohn.Forte@Sun.COM 	 * Need to get a valid location, front/rear & slot.
539*7836SJohn.Forte@Sun.COM 	 *
540*7836SJohn.Forte@Sun.COM 	 * The path_struct will return a valid slot
541*7836SJohn.Forte@Sun.COM 	 * and the IB path or a disk path.
542*7836SJohn.Forte@Sun.COM 	 */
543*7836SJohn.Forte@Sun.COM 
544*7836SJohn.Forte@Sun.COM 	map.dev_addr = (gfc_port_dev_info_t *)NULL;
545*7836SJohn.Forte@Sun.COM 	if (!path_struct->ib_path_flag) {
546*7836SJohn.Forte@Sun.COM 		if ((err = g_get_dev_map(path_struct->p_physical_path,
547*7836SJohn.Forte@Sun.COM 							&map, verbose)) != 0)
548*7836SJohn.Forte@Sun.COM 			return (err);
549*7836SJohn.Forte@Sun.COM 		if ((err = l_get_ses_path(path_struct->p_physical_path,
550*7836SJohn.Forte@Sun.COM 					ses_path, &map, verbose)) != 0) {
551*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
552*7836SJohn.Forte@Sun.COM 			return (err);
553*7836SJohn.Forte@Sun.COM 		}
554*7836SJohn.Forte@Sun.COM 	} else {
555*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path, path_struct->p_physical_path);
556*7836SJohn.Forte@Sun.COM 	}
557*7836SJohn.Forte@Sun.COM 
558*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
559*7836SJohn.Forte@Sun.COM 		free((void *)map.dev_addr);
560*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
561*7836SJohn.Forte@Sun.COM 	}
562*7836SJohn.Forte@Sun.COM 
563*7836SJohn.Forte@Sun.COM 	if (!path_struct->slot_valid) {
564*7836SJohn.Forte@Sun.COM 		if ((map.dev_addr != NULL) &&
565*7836SJohn.Forte@Sun.COM 			(err = g_get_dev_map(path_struct->p_physical_path,
566*7836SJohn.Forte@Sun.COM 							&map, verbose)) != 0) {
567*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
568*7836SJohn.Forte@Sun.COM 			return (err);
569*7836SJohn.Forte@Sun.COM 		}
570*7836SJohn.Forte@Sun.COM 		if ((err = l_get_ses_path(path_struct->p_physical_path,
571*7836SJohn.Forte@Sun.COM 			ses_path, &map, verbose)) != 0) {
572*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
573*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
574*7836SJohn.Forte@Sun.COM 			return (err);
575*7836SJohn.Forte@Sun.COM 		}
576*7836SJohn.Forte@Sun.COM 		if ((err = l_get_status(ses_path, l_state, verbose)) != 0) {
577*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
578*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
579*7836SJohn.Forte@Sun.COM 			return (err);
580*7836SJohn.Forte@Sun.COM 		}
581*7836SJohn.Forte@Sun.COM 
582*7836SJohn.Forte@Sun.COM 		/* We are passing the disks path */
583*7836SJohn.Forte@Sun.COM 		if (err = l_get_slot(path_struct, l_state, verbose)) {
584*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
585*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
586*7836SJohn.Forte@Sun.COM 			return (err);
587*7836SJohn.Forte@Sun.COM 		}
588*7836SJohn.Forte@Sun.COM 	}
589*7836SJohn.Forte@Sun.COM 	if (map.dev_addr != NULL)
590*7836SJohn.Forte@Sun.COM 		free((void *)map.dev_addr);	/* Not used anymore */
591*7836SJohn.Forte@Sun.COM 
592*7836SJohn.Forte@Sun.COM 	if ((page_buf = (uchar_t *)calloc(1,
593*7836SJohn.Forte@Sun.COM 				MAX_REC_DIAG_LENGTH)) == NULL) {
594*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
595*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
596*7836SJohn.Forte@Sun.COM 	}
597*7836SJohn.Forte@Sun.COM 
598*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) {
599*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
600*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
601*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
602*7836SJohn.Forte@Sun.COM 	}
603*7836SJohn.Forte@Sun.COM 
604*7836SJohn.Forte@Sun.COM 	if (err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
605*7836SJohn.Forte@Sun.COM 						L_PAGE_2, verbose)) {
606*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
607*7836SJohn.Forte@Sun.COM 		(void) close(fd);
608*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
609*7836SJohn.Forte@Sun.COM 		return (err);
610*7836SJohn.Forte@Sun.COM 	}
611*7836SJohn.Forte@Sun.COM 
612*7836SJohn.Forte@Sun.COM 	page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN;
613*7836SJohn.Forte@Sun.COM 
614*7836SJohn.Forte@Sun.COM 	/* Get index to the disk we are interested in */
615*7836SJohn.Forte@Sun.COM 	if (err = l_get_status(ses_path, l_state, verbose)) {
616*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
617*7836SJohn.Forte@Sun.COM 		(void) close(fd);
618*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
619*7836SJohn.Forte@Sun.COM 		return (err);
620*7836SJohn.Forte@Sun.COM 	}
621*7836SJohn.Forte@Sun.COM 
622*7836SJohn.Forte@Sun.COM 	/* find enclosure type */
623*7836SJohn.Forte@Sun.COM 	if ((strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_OFF_NAME,
624*7836SJohn.Forte@Sun.COM 						strlen(DAK_OFF_NAME)) == 0) ||
625*7836SJohn.Forte@Sun.COM 		(strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_PROD_STR,
626*7836SJohn.Forte@Sun.COM 						strlen(DAK_PROD_STR)) == 0)) {
627*7836SJohn.Forte@Sun.COM 		enc_type = DAK_ENC_TYPE;
628*7836SJohn.Forte@Sun.COM 	} else {
629*7836SJohn.Forte@Sun.COM 		enc_type = SENA_ENC_TYPE;
630*7836SJohn.Forte@Sun.COM 	}
631*7836SJohn.Forte@Sun.COM 
632*7836SJohn.Forte@Sun.COM 	/* Double check slot. */
633*7836SJohn.Forte@Sun.COM 	if (path_struct->slot >= l_state->total_num_drv/2) {
634*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
635*7836SJohn.Forte@Sun.COM 		return (L_INVALID_SLOT);
636*7836SJohn.Forte@Sun.COM 	}
637*7836SJohn.Forte@Sun.COM 
638*7836SJohn.Forte@Sun.COM 	if (err = l_get_disk_element_index(l_state, &front_index,
639*7836SJohn.Forte@Sun.COM 	    &rear_index)) {
640*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
641*7836SJohn.Forte@Sun.COM 		return (err);
642*7836SJohn.Forte@Sun.COM 	}
643*7836SJohn.Forte@Sun.COM 
644*7836SJohn.Forte@Sun.COM 	/* Skip global element */
645*7836SJohn.Forte@Sun.COM 	front_index++;
646*7836SJohn.Forte@Sun.COM 	if (enc_type == DAK_ENC_TYPE) {
647*7836SJohn.Forte@Sun.COM 		rear_index += l_state->total_num_drv/2 + 1;
648*7836SJohn.Forte@Sun.COM 	} else {
649*7836SJohn.Forte@Sun.COM 		rear_index++;
650*7836SJohn.Forte@Sun.COM 	}
651*7836SJohn.Forte@Sun.COM 
652*7836SJohn.Forte@Sun.COM 	if (path_struct->f_flag) {
653*7836SJohn.Forte@Sun.COM 		offset = (8 + (front_index + path_struct->slot)*4);
654*7836SJohn.Forte@Sun.COM 	} else {
655*7836SJohn.Forte@Sun.COM 		offset = (8 + (rear_index + path_struct->slot)*4);
656*7836SJohn.Forte@Sun.COM 	}
657*7836SJohn.Forte@Sun.COM 
658*7836SJohn.Forte@Sun.COM 	elem = (struct device_element *)(page_buf + offset);
659*7836SJohn.Forte@Sun.COM 	/*
660*7836SJohn.Forte@Sun.COM 	 * now do requested action.
661*7836SJohn.Forte@Sun.COM 	 */
662*7836SJohn.Forte@Sun.COM 	bcopy((const void *)elem, (void *)status,
663*7836SJohn.Forte@Sun.COM 		sizeof (struct device_element));	/* save status */
664*7836SJohn.Forte@Sun.COM 	bzero(elem, sizeof (struct device_element));
665*7836SJohn.Forte@Sun.COM 	elem->select = 1;
666*7836SJohn.Forte@Sun.COM 	elem->dev_off = status->dev_off;
667*7836SJohn.Forte@Sun.COM 	elem->en_bypass_a = status->en_bypass_a;
668*7836SJohn.Forte@Sun.COM 	elem->en_bypass_b = status->en_bypass_b;
669*7836SJohn.Forte@Sun.COM 	write = 1;
670*7836SJohn.Forte@Sun.COM 
671*7836SJohn.Forte@Sun.COM 	switch (led_action) {
672*7836SJohn.Forte@Sun.COM 	case	L_LED_STATUS:
673*7836SJohn.Forte@Sun.COM 		write = 0;
674*7836SJohn.Forte@Sun.COM 		break;
675*7836SJohn.Forte@Sun.COM 	case	L_LED_RQST_IDENTIFY:
676*7836SJohn.Forte@Sun.COM 		elem->ident = 1;
677*7836SJohn.Forte@Sun.COM 		if (verbose) {
678*7836SJohn.Forte@Sun.COM 		    if (enc_type == DAK_ENC_TYPE) {
679*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
680*7836SJohn.Forte@Sun.COM 			MSGSTR(9043, "  Blinking LED for slot %d in enclosure"
681*7836SJohn.Forte@Sun.COM 			" %s\n"), path_struct->f_flag ? path_struct->slot :
682*7836SJohn.Forte@Sun.COM 			path_struct->slot + (MAX_DRIVES_DAK/2),
683*7836SJohn.Forte@Sun.COM 			l_state->ib_tbl.enclosure_name);
684*7836SJohn.Forte@Sun.COM 		    } else {
685*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
686*7836SJohn.Forte@Sun.COM 			MSGSTR(9043, "  Blinking LED for slot %d in enclosure"
687*7836SJohn.Forte@Sun.COM 			" %s\n"), path_struct->slot,
688*7836SJohn.Forte@Sun.COM 			l_state->ib_tbl.enclosure_name);
689*7836SJohn.Forte@Sun.COM 		    }
690*7836SJohn.Forte@Sun.COM 		}
691*7836SJohn.Forte@Sun.COM 		break;
692*7836SJohn.Forte@Sun.COM 	case	L_LED_OFF:
693*7836SJohn.Forte@Sun.COM 		if (verbose) {
694*7836SJohn.Forte@Sun.COM 		    if (enc_type == DAK_ENC_TYPE) {
695*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
696*7836SJohn.Forte@Sun.COM 			MSGSTR(9044,
697*7836SJohn.Forte@Sun.COM 			"  Turning off LED for slot %d in enclosure"
698*7836SJohn.Forte@Sun.COM 			" %s\n"), path_struct->f_flag ? path_struct->slot
699*7836SJohn.Forte@Sun.COM 			: path_struct->slot + (MAX_DRIVES_DAK/2),
700*7836SJohn.Forte@Sun.COM 			l_state->ib_tbl.enclosure_name);
701*7836SJohn.Forte@Sun.COM 		    } else {
702*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
703*7836SJohn.Forte@Sun.COM 			MSGSTR(9044,
704*7836SJohn.Forte@Sun.COM 			"  Turning off LED for slot %d in enclosure"
705*7836SJohn.Forte@Sun.COM 			" %s\n"), path_struct->slot,
706*7836SJohn.Forte@Sun.COM 			l_state->ib_tbl.enclosure_name);
707*7836SJohn.Forte@Sun.COM 		    }
708*7836SJohn.Forte@Sun.COM 		}
709*7836SJohn.Forte@Sun.COM 		break;
710*7836SJohn.Forte@Sun.COM 	default:
711*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
712*7836SJohn.Forte@Sun.COM 		return (L_INVALID_LED_RQST);
713*7836SJohn.Forte@Sun.COM 	} /* End of switch */
714*7836SJohn.Forte@Sun.COM 
715*7836SJohn.Forte@Sun.COM 	if (write) {
716*7836SJohn.Forte@Sun.COM 		if (getenv("_LUX_D_DEBUG") != NULL) {
717*7836SJohn.Forte@Sun.COM 			g_dump("  l_led: Updating led state: "
718*7836SJohn.Forte@Sun.COM 			"Device Status Element ",
719*7836SJohn.Forte@Sun.COM 			(uchar_t *)elem, sizeof (struct device_element),
720*7836SJohn.Forte@Sun.COM 			HEX_ONLY);
721*7836SJohn.Forte@Sun.COM 		}
722*7836SJohn.Forte@Sun.COM 		if (err = g_scsi_send_diag_cmd(fd,
723*7836SJohn.Forte@Sun.COM 			(uchar_t *)page_buf, page_len)) {
724*7836SJohn.Forte@Sun.COM 			(void) close(fd);
725*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(page_buf);
726*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
727*7836SJohn.Forte@Sun.COM 			return (err);
728*7836SJohn.Forte@Sun.COM 		}
729*7836SJohn.Forte@Sun.COM 
730*7836SJohn.Forte@Sun.COM 		bzero(page_buf, MAX_REC_DIAG_LENGTH);
731*7836SJohn.Forte@Sun.COM 		if (err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
732*7836SJohn.Forte@Sun.COM 					L_PAGE_2, verbose)) {
733*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(page_buf);
734*7836SJohn.Forte@Sun.COM 			(void) close(fd);
735*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
736*7836SJohn.Forte@Sun.COM 			return (err);
737*7836SJohn.Forte@Sun.COM 		}
738*7836SJohn.Forte@Sun.COM 		elem = (struct device_element *)(page_buf + offset);
739*7836SJohn.Forte@Sun.COM 		bcopy((const void *)elem, (void *)status,
740*7836SJohn.Forte@Sun.COM 			sizeof (struct device_element));
741*7836SJohn.Forte@Sun.COM 	}
742*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_D_DEBUG") != NULL) {
743*7836SJohn.Forte@Sun.COM 		g_dump("  l_led: Device Status Element ",
744*7836SJohn.Forte@Sun.COM 		(uchar_t *)status, sizeof (struct device_element),
745*7836SJohn.Forte@Sun.COM 		HEX_ONLY);
746*7836SJohn.Forte@Sun.COM 	}
747*7836SJohn.Forte@Sun.COM 
748*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
749*7836SJohn.Forte@Sun.COM 	(void) close(fd);
750*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(page_buf);
751*7836SJohn.Forte@Sun.COM 	return (0);
752*7836SJohn.Forte@Sun.COM }
753*7836SJohn.Forte@Sun.COM 
754*7836SJohn.Forte@Sun.COM 
755*7836SJohn.Forte@Sun.COM /*
756*7836SJohn.Forte@Sun.COM  * frees the previously alloced l_state
757*7836SJohn.Forte@Sun.COM  * structure.
758*7836SJohn.Forte@Sun.COM  *
759*7836SJohn.Forte@Sun.COM  * RETURNS:
760*7836SJohn.Forte@Sun.COM  *	0	O.K.
761*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
762*7836SJohn.Forte@Sun.COM  */
763*7836SJohn.Forte@Sun.COM int
l_free_lstate(L_state ** l_state)764*7836SJohn.Forte@Sun.COM l_free_lstate(L_state **l_state)
765*7836SJohn.Forte@Sun.COM {
766*7836SJohn.Forte@Sun.COM int	i;
767*7836SJohn.Forte@Sun.COM 
768*7836SJohn.Forte@Sun.COM 	if ((l_state == NULL) || (*l_state == NULL))
769*7836SJohn.Forte@Sun.COM 		return (0);
770*7836SJohn.Forte@Sun.COM 
771*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)(*l_state)->total_num_drv/2; i++) {
772*7836SJohn.Forte@Sun.COM 	if ((*l_state)->drv_front[i].g_disk_state.multipath_list != NULL)
773*7836SJohn.Forte@Sun.COM 		(void) g_free_multipath(
774*7836SJohn.Forte@Sun.COM 		(*l_state)->drv_front[i].g_disk_state.multipath_list);
775*7836SJohn.Forte@Sun.COM 	if ((*l_state)->drv_rear[i].g_disk_state.multipath_list != NULL)
776*7836SJohn.Forte@Sun.COM 		(void) g_free_multipath(
777*7836SJohn.Forte@Sun.COM 		(*l_state)->drv_rear[i].g_disk_state.multipath_list);
778*7836SJohn.Forte@Sun.COM 	}
779*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data (*l_state);
780*7836SJohn.Forte@Sun.COM 	l_state = NULL;
781*7836SJohn.Forte@Sun.COM 
782*7836SJohn.Forte@Sun.COM 	return (0);
783*7836SJohn.Forte@Sun.COM }
784*7836SJohn.Forte@Sun.COM 
785*7836SJohn.Forte@Sun.COM 
786*7836SJohn.Forte@Sun.COM 
787*7836SJohn.Forte@Sun.COM /*
788*7836SJohn.Forte@Sun.COM  * Set the state of an individual disk
789*7836SJohn.Forte@Sun.COM  * in the Photon enclosure the powered
790*7836SJohn.Forte@Sun.COM  * up/down mode. The path must point to
791*7836SJohn.Forte@Sun.COM  * a disk or the ib_path_flag must be set.
792*7836SJohn.Forte@Sun.COM  *
793*7836SJohn.Forte@Sun.COM  * RETURNS:
794*7836SJohn.Forte@Sun.COM  *	0	 O.K.
795*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
796*7836SJohn.Forte@Sun.COM  */
797*7836SJohn.Forte@Sun.COM int
l_dev_pwr_up_down(char * path_phys,struct path_struct * path_struct,int power_off_flag,int verbose,int force_flag)798*7836SJohn.Forte@Sun.COM l_dev_pwr_up_down(char *path_phys, struct path_struct *path_struct,
799*7836SJohn.Forte@Sun.COM 		int power_off_flag, int verbose, int force_flag)
800*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
801*7836SJohn.Forte@Sun.COM {
802*7836SJohn.Forte@Sun.COM gfc_map_t		map;
803*7836SJohn.Forte@Sun.COM char			ses_path[MAXPATHLEN], dev_path[MAXPATHLEN];
804*7836SJohn.Forte@Sun.COM int			slot, err = 0;
805*7836SJohn.Forte@Sun.COM L_state			*l_state = NULL;
806*7836SJohn.Forte@Sun.COM struct l_disk_state_struct	*drive;
807*7836SJohn.Forte@Sun.COM struct dlist		*dl, *dl1;
808*7836SJohn.Forte@Sun.COM devctl_hdl_t		devhdl;
809*7836SJohn.Forte@Sun.COM WWN_list		*wwn_list = NULL;
810*7836SJohn.Forte@Sun.COM L_inquiry		inq;
811*7836SJohn.Forte@Sun.COM 
812*7836SJohn.Forte@Sun.COM 	if (path_struct == NULL) {
813*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
814*7836SJohn.Forte@Sun.COM 	}
815*7836SJohn.Forte@Sun.COM 
816*7836SJohn.Forte@Sun.COM 	dl = (struct dlist *)NULL;
817*7836SJohn.Forte@Sun.COM 	map.dev_addr = (gfc_port_dev_info_t *)NULL;
818*7836SJohn.Forte@Sun.COM 
819*7836SJohn.Forte@Sun.COM 	if (err = g_get_dev_map(path_struct->p_physical_path,
820*7836SJohn.Forte@Sun.COM 					&map, verbose))
821*7836SJohn.Forte@Sun.COM 		return (err);
822*7836SJohn.Forte@Sun.COM 
823*7836SJohn.Forte@Sun.COM 	if (err = l_get_ses_path(path_struct->p_physical_path,
824*7836SJohn.Forte@Sun.COM 				ses_path, &map, verbose)) {
825*7836SJohn.Forte@Sun.COM 		free((void *)map.dev_addr);
826*7836SJohn.Forte@Sun.COM 		return (err);
827*7836SJohn.Forte@Sun.COM 	}
828*7836SJohn.Forte@Sun.COM 	free((void *)map.dev_addr);	/* Not used anymore */
829*7836SJohn.Forte@Sun.COM 
830*7836SJohn.Forte@Sun.COM 	/*
831*7836SJohn.Forte@Sun.COM 	 * Check to see if we have a photon, and if not, don't allow
832*7836SJohn.Forte@Sun.COM 	 * this operation
833*7836SJohn.Forte@Sun.COM 	 */
834*7836SJohn.Forte@Sun.COM 	if (err = g_get_inquiry(ses_path, &inq)) {
835*7836SJohn.Forte@Sun.COM 	    return (err);
836*7836SJohn.Forte@Sun.COM 	}
837*7836SJohn.Forte@Sun.COM 	if (l_get_enc_type(inq) != SENA_ENC_TYPE) {
838*7836SJohn.Forte@Sun.COM 	    return (L_ENCL_INVALID_PATH);
839*7836SJohn.Forte@Sun.COM 	}
840*7836SJohn.Forte@Sun.COM 	/*
841*7836SJohn.Forte@Sun.COM 	 * OK, so we have a photon... we can continue
842*7836SJohn.Forte@Sun.COM 	 */
843*7836SJohn.Forte@Sun.COM 
844*7836SJohn.Forte@Sun.COM 
845*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
846*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
847*7836SJohn.Forte@Sun.COM 	}
848*7836SJohn.Forte@Sun.COM 
849*7836SJohn.Forte@Sun.COM 	if (err = l_get_status(ses_path, l_state, verbose)) {
850*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
851*7836SJohn.Forte@Sun.COM 		return (err);
852*7836SJohn.Forte@Sun.COM 	}
853*7836SJohn.Forte@Sun.COM 
854*7836SJohn.Forte@Sun.COM 	if (!path_struct->slot_valid) {
855*7836SJohn.Forte@Sun.COM 		/* We are passing the disks path */
856*7836SJohn.Forte@Sun.COM 		if (err = l_get_slot(path_struct, l_state, verbose)) {
857*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
858*7836SJohn.Forte@Sun.COM 			return (err);
859*7836SJohn.Forte@Sun.COM 		}
860*7836SJohn.Forte@Sun.COM 	}
861*7836SJohn.Forte@Sun.COM 
862*7836SJohn.Forte@Sun.COM 	slot = path_struct->slot;
863*7836SJohn.Forte@Sun.COM 	(void) strcpy(dev_path, path_struct->p_physical_path);
864*7836SJohn.Forte@Sun.COM 
865*7836SJohn.Forte@Sun.COM 	/*
866*7836SJohn.Forte@Sun.COM 	 * Either front or rear drive
867*7836SJohn.Forte@Sun.COM 	 */
868*7836SJohn.Forte@Sun.COM 	if (path_struct->f_flag) {
869*7836SJohn.Forte@Sun.COM 		drive = &l_state->drv_front[slot];
870*7836SJohn.Forte@Sun.COM 	} else {
871*7836SJohn.Forte@Sun.COM 		drive = &l_state->drv_rear[slot];
872*7836SJohn.Forte@Sun.COM 	}
873*7836SJohn.Forte@Sun.COM 
874*7836SJohn.Forte@Sun.COM 	/*
875*7836SJohn.Forte@Sun.COM 	 * Check for drive presence always
876*7836SJohn.Forte@Sun.COM 	 */
877*7836SJohn.Forte@Sun.COM 	if (drive->ib_status.code == S_NOT_INSTALLED) {
878*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
879*7836SJohn.Forte@Sun.COM 		return (L_SLOT_EMPTY);
880*7836SJohn.Forte@Sun.COM 	}
881*7836SJohn.Forte@Sun.COM 
882*7836SJohn.Forte@Sun.COM 	/*
883*7836SJohn.Forte@Sun.COM 	 * Check disk state
884*7836SJohn.Forte@Sun.COM 	 * before the power off.
885*7836SJohn.Forte@Sun.COM 	 *
886*7836SJohn.Forte@Sun.COM 	 */
887*7836SJohn.Forte@Sun.COM 	if (power_off_flag && !force_flag) {
888*7836SJohn.Forte@Sun.COM 		goto pre_pwr_dwn;
889*7836SJohn.Forte@Sun.COM 	} else {
890*7836SJohn.Forte@Sun.COM 		goto pwr_up_dwn;
891*7836SJohn.Forte@Sun.COM 	}
892*7836SJohn.Forte@Sun.COM 
893*7836SJohn.Forte@Sun.COM pre_pwr_dwn:
894*7836SJohn.Forte@Sun.COM 
895*7836SJohn.Forte@Sun.COM 	/*
896*7836SJohn.Forte@Sun.COM 	 * Check whether disk
897*7836SJohn.Forte@Sun.COM 	 * is reserved by another
898*7836SJohn.Forte@Sun.COM 	 * host
899*7836SJohn.Forte@Sun.COM 	 */
900*7836SJohn.Forte@Sun.COM 	if ((drive->g_disk_state.d_state_flags[PORT_A] & L_RESERVED) ||
901*7836SJohn.Forte@Sun.COM 		(drive->g_disk_state.d_state_flags[PORT_B] &
902*7836SJohn.Forte@Sun.COM 		L_RESERVED)) {
903*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
904*7836SJohn.Forte@Sun.COM 		return (L_DEVICE_RESERVED);
905*7836SJohn.Forte@Sun.COM 	}
906*7836SJohn.Forte@Sun.COM 
907*7836SJohn.Forte@Sun.COM 
908*7836SJohn.Forte@Sun.COM 	if ((dl = (struct dlist *)g_zalloc(sizeof (struct dlist))) == NULL) {
909*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
910*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
911*7836SJohn.Forte@Sun.COM 	}
912*7836SJohn.Forte@Sun.COM 
913*7836SJohn.Forte@Sun.COM 	/*
914*7836SJohn.Forte@Sun.COM 	 * NOTE: It is not necessary to get the multipath list here as ------
915*7836SJohn.Forte@Sun.COM 	 * we alread have it after getting the status earlier.
916*7836SJohn.Forte@Sun.COM 	 * - REWRITE -
917*7836SJohn.Forte@Sun.COM 	 */
918*7836SJohn.Forte@Sun.COM 
919*7836SJohn.Forte@Sun.COM 	/*
920*7836SJohn.Forte@Sun.COM 	 * Get path to all the FC disk and tape devices.
921*7836SJohn.Forte@Sun.COM 	 *
922*7836SJohn.Forte@Sun.COM 	 * I get this now and pass down for performance
923*7836SJohn.Forte@Sun.COM 	 * reasons.
924*7836SJohn.Forte@Sun.COM 	 * If for some reason the list can become invalid,
925*7836SJohn.Forte@Sun.COM 	 * i.e. device being offlined, then the list
926*7836SJohn.Forte@Sun.COM 	 * must be re-gotten.
927*7836SJohn.Forte@Sun.COM 	 */
928*7836SJohn.Forte@Sun.COM 	if (err = g_get_wwn_list(&wwn_list, verbose)) {
929*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(dl);
930*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
931*7836SJohn.Forte@Sun.COM 		return (err);   /* Failure */
932*7836SJohn.Forte@Sun.COM 	}
933*7836SJohn.Forte@Sun.COM 
934*7836SJohn.Forte@Sun.COM 	dl->dev_path = dev_path;
935*7836SJohn.Forte@Sun.COM 	if ((err = g_get_multipath(dev_path,
936*7836SJohn.Forte@Sun.COM 			&(dl->multipath), wwn_list, verbose)) != 0) {
937*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(dl);
938*7836SJohn.Forte@Sun.COM 		(void) g_free_wwn_list(&wwn_list);
939*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
940*7836SJohn.Forte@Sun.COM 		return (err);
941*7836SJohn.Forte@Sun.COM 	}
942*7836SJohn.Forte@Sun.COM 
943*7836SJohn.Forte@Sun.COM 	for (dl1 = dl->multipath; dl1 != NULL; dl1 = dl1->next) {
944*7836SJohn.Forte@Sun.COM 		if ((devhdl = devctl_device_acquire(dl1->dev_path,
945*7836SJohn.Forte@Sun.COM 						DC_EXCL)) == NULL) {
946*7836SJohn.Forte@Sun.COM 			if (errno != EBUSY) {
947*7836SJohn.Forte@Sun.COM 				ER_DPRINTF("%s could not acquire"
948*7836SJohn.Forte@Sun.COM 				" the device: %s\n\n",
949*7836SJohn.Forte@Sun.COM 				strerror(errno), dl1->dev_path);
950*7836SJohn.Forte@Sun.COM 				continue;
951*7836SJohn.Forte@Sun.COM 			}
952*7836SJohn.Forte@Sun.COM 		}
953*7836SJohn.Forte@Sun.COM 		if (devctl_device_offline(devhdl) != 0) {
954*7836SJohn.Forte@Sun.COM 			(void) devctl_release(devhdl);
955*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(dl->multipath);
956*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(dl);
957*7836SJohn.Forte@Sun.COM 			(void) g_free_wwn_list(&wwn_list);
958*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
959*7836SJohn.Forte@Sun.COM 			return (L_POWER_OFF_FAIL_BUSY);
960*7836SJohn.Forte@Sun.COM 		}
961*7836SJohn.Forte@Sun.COM 		(void) devctl_release(devhdl);
962*7836SJohn.Forte@Sun.COM 	}
963*7836SJohn.Forte@Sun.COM 
964*7836SJohn.Forte@Sun.COM pwr_up_dwn:
965*7836SJohn.Forte@Sun.COM 	err = pwr_up_down(ses_path, l_state, path_struct->f_flag,
966*7836SJohn.Forte@Sun.COM 			path_struct->slot, power_off_flag, verbose);
967*7836SJohn.Forte@Sun.COM 
968*7836SJohn.Forte@Sun.COM 	if (dl != NULL) {
969*7836SJohn.Forte@Sun.COM 		(void) g_free_multipath(dl->multipath);
970*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(dl);
971*7836SJohn.Forte@Sun.COM 	}
972*7836SJohn.Forte@Sun.COM 	(void) g_free_wwn_list(&wwn_list);
973*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
974*7836SJohn.Forte@Sun.COM 	if (err) {
975*7836SJohn.Forte@Sun.COM 		return (err);
976*7836SJohn.Forte@Sun.COM 	}
977*7836SJohn.Forte@Sun.COM 	return (0);
978*7836SJohn.Forte@Sun.COM }
979*7836SJohn.Forte@Sun.COM 
980*7836SJohn.Forte@Sun.COM 
981*7836SJohn.Forte@Sun.COM 
982*7836SJohn.Forte@Sun.COM /*
983*7836SJohn.Forte@Sun.COM  * l_pho_pwr_up_down() Set the state of the Photon enclosure
984*7836SJohn.Forte@Sun.COM  * the powered up/down mode.
985*7836SJohn.Forte@Sun.COM  * The path must point to an IB.
986*7836SJohn.Forte@Sun.COM  *
987*7836SJohn.Forte@Sun.COM  * RETURNS:
988*7836SJohn.Forte@Sun.COM  *	0	 O.K.
989*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
990*7836SJohn.Forte@Sun.COM  */
991*7836SJohn.Forte@Sun.COM int
l_pho_pwr_up_down(char * dev_name,char * path_phys,int power_off_flag,int verbose,int force_flag)992*7836SJohn.Forte@Sun.COM l_pho_pwr_up_down(char *dev_name, char *path_phys, int power_off_flag,
993*7836SJohn.Forte@Sun.COM 	int verbose, int force_flag)
994*7836SJohn.Forte@Sun.COM {
995*7836SJohn.Forte@Sun.COM L_state		*l_state = NULL;
996*7836SJohn.Forte@Sun.COM int		i, err = 0;
997*7836SJohn.Forte@Sun.COM struct dlist	*dl, *dl1;
998*7836SJohn.Forte@Sun.COM char		dev_path[MAXPATHLEN];
999*7836SJohn.Forte@Sun.COM devctl_hdl_t	devhdl;
1000*7836SJohn.Forte@Sun.COM WWN_list	*wwn_list = NULL;
1001*7836SJohn.Forte@Sun.COM 
1002*7836SJohn.Forte@Sun.COM 	if (path_phys == NULL) {
1003*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
1004*7836SJohn.Forte@Sun.COM 	}
1005*7836SJohn.Forte@Sun.COM 
1006*7836SJohn.Forte@Sun.COM 	dl = (struct dlist *)NULL;
1007*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
1008*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
1009*7836SJohn.Forte@Sun.COM 	}
1010*7836SJohn.Forte@Sun.COM 	if (err = l_get_status(path_phys, l_state, verbose)) {
1011*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
1012*7836SJohn.Forte@Sun.COM 		return (err);
1013*7836SJohn.Forte@Sun.COM 	}
1014*7836SJohn.Forte@Sun.COM 	if (power_off_flag && !force_flag) {
1015*7836SJohn.Forte@Sun.COM 		goto pre_pwr_dwn;
1016*7836SJohn.Forte@Sun.COM 	} else {
1017*7836SJohn.Forte@Sun.COM 		goto pwr_up_dwn;
1018*7836SJohn.Forte@Sun.COM 	}
1019*7836SJohn.Forte@Sun.COM 
1020*7836SJohn.Forte@Sun.COM pre_pwr_dwn:
1021*7836SJohn.Forte@Sun.COM 
1022*7836SJohn.Forte@Sun.COM 	/*
1023*7836SJohn.Forte@Sun.COM 	 * Check if any disk in this enclosure
1024*7836SJohn.Forte@Sun.COM 	 * is reserved by another host before
1025*7836SJohn.Forte@Sun.COM 	 * the power off.
1026*7836SJohn.Forte@Sun.COM 	 */
1027*7836SJohn.Forte@Sun.COM 	for (i = 0; i < l_state->total_num_drv/2; i++) {
1028*7836SJohn.Forte@Sun.COM 		if ((l_state->drv_front[i].g_disk_state.d_state_flags[PORT_A] &
1029*7836SJohn.Forte@Sun.COM 						L_RESERVED) ||
1030*7836SJohn.Forte@Sun.COM 		(l_state->drv_front[i].g_disk_state.d_state_flags[PORT_B] &
1031*7836SJohn.Forte@Sun.COM 						L_RESERVED) ||
1032*7836SJohn.Forte@Sun.COM 		(l_state->drv_rear[i].g_disk_state.d_state_flags[PORT_A] &
1033*7836SJohn.Forte@Sun.COM 						L_RESERVED) ||
1034*7836SJohn.Forte@Sun.COM 		(l_state->drv_rear[i].g_disk_state.d_state_flags[PORT_B] &
1035*7836SJohn.Forte@Sun.COM 						L_RESERVED)) {
1036*7836SJohn.Forte@Sun.COM 				return (L_DISKS_RESERVED);
1037*7836SJohn.Forte@Sun.COM 		}
1038*7836SJohn.Forte@Sun.COM 	}
1039*7836SJohn.Forte@Sun.COM 
1040*7836SJohn.Forte@Sun.COM 	/*
1041*7836SJohn.Forte@Sun.COM 	 * Check if any disk in this enclosure
1042*7836SJohn.Forte@Sun.COM 	 * Get path to all the FC disk and tape devices.
1043*7836SJohn.Forte@Sun.COM 	 *
1044*7836SJohn.Forte@Sun.COM 	 * I get this now and pass down for performance
1045*7836SJohn.Forte@Sun.COM 	 * reasons.
1046*7836SJohn.Forte@Sun.COM 	 * If for some reason the list can become invalid,
1047*7836SJohn.Forte@Sun.COM 	 * i.e. device being offlined, then the list
1048*7836SJohn.Forte@Sun.COM 	 * must be re-gotten.
1049*7836SJohn.Forte@Sun.COM 	 */
1050*7836SJohn.Forte@Sun.COM 	if (err = g_get_wwn_list(&wwn_list, verbose)) {
1051*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
1052*7836SJohn.Forte@Sun.COM 		return (err);   /* Failure */
1053*7836SJohn.Forte@Sun.COM 	}
1054*7836SJohn.Forte@Sun.COM 	for (i = 0; i < l_state->total_num_drv/2; i++) {
1055*7836SJohn.Forte@Sun.COM 		if (*l_state->drv_front[i].g_disk_state.physical_path) {
1056*7836SJohn.Forte@Sun.COM 			(void) memset(dev_path, 0, MAXPATHLEN);
1057*7836SJohn.Forte@Sun.COM 			(void) strcpy(dev_path,
1058*7836SJohn.Forte@Sun.COM 		(char *)&l_state->drv_front[i].g_disk_state.physical_path);
1059*7836SJohn.Forte@Sun.COM 
1060*7836SJohn.Forte@Sun.COM 			if ((dl = (struct dlist *)
1061*7836SJohn.Forte@Sun.COM 				g_zalloc(sizeof (struct dlist))) == NULL) {
1062*7836SJohn.Forte@Sun.COM 				(void) g_free_wwn_list(&wwn_list);
1063*7836SJohn.Forte@Sun.COM 				(void) l_free_lstate(&l_state);
1064*7836SJohn.Forte@Sun.COM 				return (L_MALLOC_FAILED);
1065*7836SJohn.Forte@Sun.COM 			}
1066*7836SJohn.Forte@Sun.COM 			dl->dev_path = dev_path;
1067*7836SJohn.Forte@Sun.COM 			if (g_get_multipath(dev_path, &(dl->multipath),
1068*7836SJohn.Forte@Sun.COM 				wwn_list, verbose) != 0) {
1069*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(dl);
1070*7836SJohn.Forte@Sun.COM 				continue;
1071*7836SJohn.Forte@Sun.COM 			}
1072*7836SJohn.Forte@Sun.COM 
1073*7836SJohn.Forte@Sun.COM 			for (dl1 = dl->multipath;
1074*7836SJohn.Forte@Sun.COM 			    dl1 != NULL;
1075*7836SJohn.Forte@Sun.COM 			    dl1 = dl1->next) {
1076*7836SJohn.Forte@Sun.COM 
1077*7836SJohn.Forte@Sun.COM 				/* attempt to acquire the device */
1078*7836SJohn.Forte@Sun.COM 				if ((devhdl = devctl_device_acquire(
1079*7836SJohn.Forte@Sun.COM 					dl1->dev_path, DC_EXCL)) == NULL) {
1080*7836SJohn.Forte@Sun.COM 					if (errno != EBUSY) {
1081*7836SJohn.Forte@Sun.COM 						ER_DPRINTF("%s: Could not "
1082*7836SJohn.Forte@Sun.COM 						"acquire the device: %s\n\n",
1083*7836SJohn.Forte@Sun.COM 						strerror(errno),
1084*7836SJohn.Forte@Sun.COM 						dl1->dev_path);
1085*7836SJohn.Forte@Sun.COM 						continue;
1086*7836SJohn.Forte@Sun.COM 					}
1087*7836SJohn.Forte@Sun.COM 				}
1088*7836SJohn.Forte@Sun.COM 
1089*7836SJohn.Forte@Sun.COM 				/* attempt to offline the device */
1090*7836SJohn.Forte@Sun.COM 				if (devctl_device_offline(devhdl) != 0) {
1091*7836SJohn.Forte@Sun.COM 					(void) devctl_release(devhdl);
1092*7836SJohn.Forte@Sun.COM 					(void) g_free_multipath(
1093*7836SJohn.Forte@Sun.COM 						dl->multipath);
1094*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(dl);
1095*7836SJohn.Forte@Sun.COM 					(void) g_free_wwn_list(&wwn_list);
1096*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
1097*7836SJohn.Forte@Sun.COM 					return (L_POWER_OFF_FAIL_BUSY);
1098*7836SJohn.Forte@Sun.COM 				}
1099*7836SJohn.Forte@Sun.COM 
1100*7836SJohn.Forte@Sun.COM 				/* release handle acquired above */
1101*7836SJohn.Forte@Sun.COM 				(void) devctl_release(devhdl);
1102*7836SJohn.Forte@Sun.COM 			}
1103*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(dl->multipath);
1104*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(dl);
1105*7836SJohn.Forte@Sun.COM 
1106*7836SJohn.Forte@Sun.COM 		}
1107*7836SJohn.Forte@Sun.COM 		if (*l_state->drv_rear[i].g_disk_state.physical_path) {
1108*7836SJohn.Forte@Sun.COM 			(void) memset(dev_path, 0, MAXPATHLEN);
1109*7836SJohn.Forte@Sun.COM 			(void) strcpy(dev_path,
1110*7836SJohn.Forte@Sun.COM 		(char *)&l_state->drv_rear[i].g_disk_state.physical_path);
1111*7836SJohn.Forte@Sun.COM 
1112*7836SJohn.Forte@Sun.COM 			if ((dl = (struct dlist *)
1113*7836SJohn.Forte@Sun.COM 				g_zalloc(sizeof (struct dlist))) == NULL) {
1114*7836SJohn.Forte@Sun.COM 				(void) g_free_wwn_list(&wwn_list);
1115*7836SJohn.Forte@Sun.COM 				(void) l_free_lstate(&l_state);
1116*7836SJohn.Forte@Sun.COM 				return (L_MALLOC_FAILED);
1117*7836SJohn.Forte@Sun.COM 			}
1118*7836SJohn.Forte@Sun.COM 			dl->dev_path = dev_path;
1119*7836SJohn.Forte@Sun.COM 			if (g_get_multipath(dev_path, &(dl->multipath),
1120*7836SJohn.Forte@Sun.COM 				wwn_list, verbose) != 0) {
1121*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(dl);
1122*7836SJohn.Forte@Sun.COM 				continue;
1123*7836SJohn.Forte@Sun.COM 			}
1124*7836SJohn.Forte@Sun.COM 
1125*7836SJohn.Forte@Sun.COM 
1126*7836SJohn.Forte@Sun.COM 			for (dl1 = dl->multipath;
1127*7836SJohn.Forte@Sun.COM 			    dl1 != NULL;
1128*7836SJohn.Forte@Sun.COM 			    dl1 = dl1->next) {
1129*7836SJohn.Forte@Sun.COM 
1130*7836SJohn.Forte@Sun.COM 				/* attempt to acquire the device */
1131*7836SJohn.Forte@Sun.COM 				if ((devhdl = devctl_device_acquire(
1132*7836SJohn.Forte@Sun.COM 					dl1->dev_path, DC_EXCL)) == NULL) {
1133*7836SJohn.Forte@Sun.COM 					if (errno != EBUSY) {
1134*7836SJohn.Forte@Sun.COM 						ER_DPRINTF("%s: Could not "
1135*7836SJohn.Forte@Sun.COM 						"acquire the device: %s\n\n",
1136*7836SJohn.Forte@Sun.COM 						strerror(errno),
1137*7836SJohn.Forte@Sun.COM 						dl1->dev_path);
1138*7836SJohn.Forte@Sun.COM 						continue;
1139*7836SJohn.Forte@Sun.COM 					}
1140*7836SJohn.Forte@Sun.COM 				}
1141*7836SJohn.Forte@Sun.COM 				/* attempt to offline the device */
1142*7836SJohn.Forte@Sun.COM 				if (devctl_device_offline(devhdl) != 0) {
1143*7836SJohn.Forte@Sun.COM 					(void) devctl_release(devhdl);
1144*7836SJohn.Forte@Sun.COM 					(void) g_free_multipath(
1145*7836SJohn.Forte@Sun.COM 							dl->multipath);
1146*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(dl);
1147*7836SJohn.Forte@Sun.COM 					(void) g_free_wwn_list(&wwn_list);
1148*7836SJohn.Forte@Sun.COM 					(void) l_free_lstate(&l_state);
1149*7836SJohn.Forte@Sun.COM 					return (L_POWER_OFF_FAIL_BUSY);
1150*7836SJohn.Forte@Sun.COM 				}
1151*7836SJohn.Forte@Sun.COM 
1152*7836SJohn.Forte@Sun.COM 				/* release handle acquired above */
1153*7836SJohn.Forte@Sun.COM 				(void) devctl_release(devhdl);
1154*7836SJohn.Forte@Sun.COM 			}
1155*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(dl->multipath);
1156*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(dl);
1157*7836SJohn.Forte@Sun.COM 
1158*7836SJohn.Forte@Sun.COM 		}
1159*7836SJohn.Forte@Sun.COM 	}
1160*7836SJohn.Forte@Sun.COM 
1161*7836SJohn.Forte@Sun.COM pwr_up_dwn:
1162*7836SJohn.Forte@Sun.COM 
1163*7836SJohn.Forte@Sun.COM 	(void) g_free_wwn_list(&wwn_list);
1164*7836SJohn.Forte@Sun.COM 	if ((err = pwr_up_down(path_phys, l_state, 0, -1,
1165*7836SJohn.Forte@Sun.COM 		power_off_flag, verbose)) != 0) {
1166*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
1167*7836SJohn.Forte@Sun.COM 		return (err);
1168*7836SJohn.Forte@Sun.COM 	}
1169*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
1170*7836SJohn.Forte@Sun.COM 	return (0);
1171*7836SJohn.Forte@Sun.COM }
1172*7836SJohn.Forte@Sun.COM 
1173*7836SJohn.Forte@Sun.COM 
1174*7836SJohn.Forte@Sun.COM /*
1175*7836SJohn.Forte@Sun.COM  * Set the state of the Photon enclosure or disk
1176*7836SJohn.Forte@Sun.COM  * powered up/down mode.
1177*7836SJohn.Forte@Sun.COM  * The path must point to an IB.
1178*7836SJohn.Forte@Sun.COM  * slot == -1 implies entire enclosure.
1179*7836SJohn.Forte@Sun.COM  *
1180*7836SJohn.Forte@Sun.COM  * RETURNS:
1181*7836SJohn.Forte@Sun.COM  *	0	 O.K.
1182*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
1183*7836SJohn.Forte@Sun.COM  */
1184*7836SJohn.Forte@Sun.COM static int
pwr_up_down(char * path_phys,L_state * l_state,int front,int slot,int power_off_flag,int verbose)1185*7836SJohn.Forte@Sun.COM pwr_up_down(char *path_phys, L_state *l_state, int front, int slot,
1186*7836SJohn.Forte@Sun.COM 		int power_off_flag, int verbose)
1187*7836SJohn.Forte@Sun.COM {
1188*7836SJohn.Forte@Sun.COM L_inquiry		inq;
1189*7836SJohn.Forte@Sun.COM int			fd, status, err;
1190*7836SJohn.Forte@Sun.COM uchar_t			*page_buf;
1191*7836SJohn.Forte@Sun.COM int 			front_index, rear_index, front_offset, rear_offset;
1192*7836SJohn.Forte@Sun.COM unsigned short		page_len;
1193*7836SJohn.Forte@Sun.COM struct	device_element	*front_elem, *rear_elem;
1194*7836SJohn.Forte@Sun.COM 
1195*7836SJohn.Forte@Sun.COM 	(void) memset(&inq, 0, sizeof (inq));
1196*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path_phys, O_NDELAY | O_RDONLY)) == -1) {
1197*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
1198*7836SJohn.Forte@Sun.COM 	}
1199*7836SJohn.Forte@Sun.COM 	/* Verify it is a Photon */
1200*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_inquiry_cmd(fd,
1201*7836SJohn.Forte@Sun.COM 		(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
1202*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1203*7836SJohn.Forte@Sun.COM 		return (status);
1204*7836SJohn.Forte@Sun.COM 	}
1205*7836SJohn.Forte@Sun.COM 	if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) &&
1206*7836SJohn.Forte@Sun.COM 		(!(strncmp((char *)inq.inq_vid, "SUN     ",
1207*7836SJohn.Forte@Sun.COM 		sizeof (inq.inq_vid)) &&
1208*7836SJohn.Forte@Sun.COM 		((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)))) {
1209*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1210*7836SJohn.Forte@Sun.COM 		return (L_ENCL_INVALID_PATH);
1211*7836SJohn.Forte@Sun.COM 	}
1212*7836SJohn.Forte@Sun.COM 
1213*7836SJohn.Forte@Sun.COM 	/*
1214*7836SJohn.Forte@Sun.COM 	 * To power up/down a Photon we use the Driver Off
1215*7836SJohn.Forte@Sun.COM 	 * bit in the global device control element.
1216*7836SJohn.Forte@Sun.COM 	 */
1217*7836SJohn.Forte@Sun.COM 	if ((page_buf = (uchar_t *)malloc(MAX_REC_DIAG_LENGTH)) == NULL) {
1218*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
1219*7836SJohn.Forte@Sun.COM 	}
1220*7836SJohn.Forte@Sun.COM 	if (err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
1221*7836SJohn.Forte@Sun.COM 				L_PAGE_2, verbose)) {
1222*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1223*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
1224*7836SJohn.Forte@Sun.COM 		return (err);
1225*7836SJohn.Forte@Sun.COM 	}
1226*7836SJohn.Forte@Sun.COM 
1227*7836SJohn.Forte@Sun.COM 	page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN;
1228*7836SJohn.Forte@Sun.COM 
1229*7836SJohn.Forte@Sun.COM 	/* Double check slot as convert_name only does gross check */
1230*7836SJohn.Forte@Sun.COM 	if (slot >= l_state->total_num_drv/2) {
1231*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1232*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
1233*7836SJohn.Forte@Sun.COM 		return (L_INVALID_SLOT);
1234*7836SJohn.Forte@Sun.COM 	}
1235*7836SJohn.Forte@Sun.COM 
1236*7836SJohn.Forte@Sun.COM 	if (err = l_get_disk_element_index(l_state, &front_index,
1237*7836SJohn.Forte@Sun.COM 		&rear_index)) {
1238*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1239*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
1240*7836SJohn.Forte@Sun.COM 		return (err);
1241*7836SJohn.Forte@Sun.COM 	}
1242*7836SJohn.Forte@Sun.COM 	/* Skip global element */
1243*7836SJohn.Forte@Sun.COM 	front_index++;
1244*7836SJohn.Forte@Sun.COM 	rear_index++;
1245*7836SJohn.Forte@Sun.COM 
1246*7836SJohn.Forte@Sun.COM 	front_offset = (8 + (front_index + slot)*4);
1247*7836SJohn.Forte@Sun.COM 	rear_offset = (8 + (rear_index + slot)*4);
1248*7836SJohn.Forte@Sun.COM 
1249*7836SJohn.Forte@Sun.COM 	front_elem = (struct device_element *)(page_buf + front_offset);
1250*7836SJohn.Forte@Sun.COM 	rear_elem = (struct device_element *)(page_buf + rear_offset);
1251*7836SJohn.Forte@Sun.COM 
1252*7836SJohn.Forte@Sun.COM 	if (front || slot == -1) {
1253*7836SJohn.Forte@Sun.COM 		/*
1254*7836SJohn.Forte@Sun.COM 		 * now do requested action.
1255*7836SJohn.Forte@Sun.COM 		 */
1256*7836SJohn.Forte@Sun.COM 		bzero(front_elem, sizeof (struct device_element));
1257*7836SJohn.Forte@Sun.COM 		/* Set/reset power off bit */
1258*7836SJohn.Forte@Sun.COM 		front_elem->dev_off = power_off_flag;
1259*7836SJohn.Forte@Sun.COM 		front_elem->select = 1;
1260*7836SJohn.Forte@Sun.COM 	}
1261*7836SJohn.Forte@Sun.COM 	if (!front || slot == -1) {
1262*7836SJohn.Forte@Sun.COM 		/* Now do rear */
1263*7836SJohn.Forte@Sun.COM 		bzero(rear_elem, sizeof (struct device_element));
1264*7836SJohn.Forte@Sun.COM 		/* Set/reset power off bit */
1265*7836SJohn.Forte@Sun.COM 		rear_elem->dev_off = power_off_flag;
1266*7836SJohn.Forte@Sun.COM 		rear_elem->select = 1;
1267*7836SJohn.Forte@Sun.COM 	}
1268*7836SJohn.Forte@Sun.COM 
1269*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_D_DEBUG") != NULL) {
1270*7836SJohn.Forte@Sun.COM 		if (front || slot == -1) {
1271*7836SJohn.Forte@Sun.COM 			g_dump("  pwr_up_down: "
1272*7836SJohn.Forte@Sun.COM 				"Front Device Status Element ",
1273*7836SJohn.Forte@Sun.COM 				(uchar_t *)front_elem,
1274*7836SJohn.Forte@Sun.COM 				sizeof (struct device_element),
1275*7836SJohn.Forte@Sun.COM 				HEX_ONLY);
1276*7836SJohn.Forte@Sun.COM 		}
1277*7836SJohn.Forte@Sun.COM 		if (!front || slot == -1) {
1278*7836SJohn.Forte@Sun.COM 			g_dump("  pwr_up_down: "
1279*7836SJohn.Forte@Sun.COM 				"Rear Device Status Element ",
1280*7836SJohn.Forte@Sun.COM 				(uchar_t *)rear_elem,
1281*7836SJohn.Forte@Sun.COM 				sizeof (struct device_element),
1282*7836SJohn.Forte@Sun.COM 				HEX_ONLY);
1283*7836SJohn.Forte@Sun.COM 		}
1284*7836SJohn.Forte@Sun.COM 	}
1285*7836SJohn.Forte@Sun.COM 	if (err = g_scsi_send_diag_cmd(fd,
1286*7836SJohn.Forte@Sun.COM 		(uchar_t *)page_buf, page_len)) {
1287*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1288*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(page_buf);
1289*7836SJohn.Forte@Sun.COM 		return (err);
1290*7836SJohn.Forte@Sun.COM 	}
1291*7836SJohn.Forte@Sun.COM 	(void) close(fd);
1292*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(page_buf);
1293*7836SJohn.Forte@Sun.COM 	return (0);
1294*7836SJohn.Forte@Sun.COM }
1295*7836SJohn.Forte@Sun.COM 
1296*7836SJohn.Forte@Sun.COM /*
1297*7836SJohn.Forte@Sun.COM  * Set the password of the FPM by sending the password
1298*7836SJohn.Forte@Sun.COM  * in page 4 of the Send Diagnostic command.
1299*7836SJohn.Forte@Sun.COM  *
1300*7836SJohn.Forte@Sun.COM  * The path must point to an IB.
1301*7836SJohn.Forte@Sun.COM  *
1302*7836SJohn.Forte@Sun.COM  * The size of the password string must be <= 8 bytes.
1303*7836SJohn.Forte@Sun.COM  * The string can also be NULL. This is the way the user
1304*7836SJohn.Forte@Sun.COM  * chooses to not have a password.
1305*7836SJohn.Forte@Sun.COM  *
1306*7836SJohn.Forte@Sun.COM  * I then tell the photon by giving him 4 NULL bytes.
1307*7836SJohn.Forte@Sun.COM  *
1308*7836SJohn.Forte@Sun.COM  * RETURNS:
1309*7836SJohn.Forte@Sun.COM  *	0	 O.K.
1310*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
1311*7836SJohn.Forte@Sun.COM  */
1312*7836SJohn.Forte@Sun.COM int
l_new_password(char * path_phys,char * password)1313*7836SJohn.Forte@Sun.COM l_new_password(char *path_phys, char *password)
1314*7836SJohn.Forte@Sun.COM {
1315*7836SJohn.Forte@Sun.COM Page4_name	page4;
1316*7836SJohn.Forte@Sun.COM L_inquiry	inq;
1317*7836SJohn.Forte@Sun.COM int		fd, status;
1318*7836SJohn.Forte@Sun.COM 
1319*7836SJohn.Forte@Sun.COM 	(void) memset(&inq, 0, sizeof (inq));
1320*7836SJohn.Forte@Sun.COM 	(void) memset(&page4, 0, sizeof (page4));
1321*7836SJohn.Forte@Sun.COM 
1322*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path_phys, O_NDELAY | O_RDONLY)) == -1) {
1323*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
1324*7836SJohn.Forte@Sun.COM 	}
1325*7836SJohn.Forte@Sun.COM 	/* Verify it is a Photon */
1326*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_inquiry_cmd(fd,
1327*7836SJohn.Forte@Sun.COM 		(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
1328*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1329*7836SJohn.Forte@Sun.COM 		return (status);
1330*7836SJohn.Forte@Sun.COM 	}
1331*7836SJohn.Forte@Sun.COM 	if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) &&
1332*7836SJohn.Forte@Sun.COM 		(!(strncmp((char *)inq.inq_vid, "SUN     ",
1333*7836SJohn.Forte@Sun.COM 		sizeof (inq.inq_vid)) &&
1334*7836SJohn.Forte@Sun.COM 		((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)))) {
1335*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1336*7836SJohn.Forte@Sun.COM 		return (L_ENCL_INVALID_PATH);
1337*7836SJohn.Forte@Sun.COM 	}
1338*7836SJohn.Forte@Sun.COM 
1339*7836SJohn.Forte@Sun.COM 	page4.page_code = L_PAGE_4;
1340*7836SJohn.Forte@Sun.COM 	page4.page_len = (ushort_t)max((strlen(password) + 4), 8);
1341*7836SJohn.Forte@Sun.COM 	/* Double check */
1342*7836SJohn.Forte@Sun.COM 	if (strlen(password) > 8) {
1343*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PASSWORD_LEN);
1344*7836SJohn.Forte@Sun.COM 	}
1345*7836SJohn.Forte@Sun.COM 	page4.string_code = L_PASSWORD;
1346*7836SJohn.Forte@Sun.COM 	page4.enable = 1;
1347*7836SJohn.Forte@Sun.COM 	(void) strcpy((char *)page4.name, password);
1348*7836SJohn.Forte@Sun.COM 
1349*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_send_diag_cmd(fd, (uchar_t *)&page4,
1350*7836SJohn.Forte@Sun.COM 		page4.page_len + HEADER_LEN)) {
1351*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1352*7836SJohn.Forte@Sun.COM 		return (status);
1353*7836SJohn.Forte@Sun.COM 	}
1354*7836SJohn.Forte@Sun.COM 
1355*7836SJohn.Forte@Sun.COM 	(void) close(fd);
1356*7836SJohn.Forte@Sun.COM 	return (0);
1357*7836SJohn.Forte@Sun.COM }
1358*7836SJohn.Forte@Sun.COM 
1359*7836SJohn.Forte@Sun.COM 
1360*7836SJohn.Forte@Sun.COM 
1361*7836SJohn.Forte@Sun.COM /*
1362*7836SJohn.Forte@Sun.COM  * Set the name of the enclosure by sending the name
1363*7836SJohn.Forte@Sun.COM  * in page 4 of the Send Diagnostic command.
1364*7836SJohn.Forte@Sun.COM  *
1365*7836SJohn.Forte@Sun.COM  * The path must point to an IB.
1366*7836SJohn.Forte@Sun.COM  *
1367*7836SJohn.Forte@Sun.COM  * RETURNS:
1368*7836SJohn.Forte@Sun.COM  *	0	 O.K.
1369*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
1370*7836SJohn.Forte@Sun.COM  */
1371*7836SJohn.Forte@Sun.COM int
l_new_name(char * path_phys,char * name)1372*7836SJohn.Forte@Sun.COM l_new_name(char *path_phys, char *name)
1373*7836SJohn.Forte@Sun.COM {
1374*7836SJohn.Forte@Sun.COM Page4_name	page4;
1375*7836SJohn.Forte@Sun.COM L_inquiry	inq;
1376*7836SJohn.Forte@Sun.COM int		fd, status;
1377*7836SJohn.Forte@Sun.COM 
1378*7836SJohn.Forte@Sun.COM 	if ((path_phys == NULL) || (name == NULL)) {
1379*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
1380*7836SJohn.Forte@Sun.COM 	}
1381*7836SJohn.Forte@Sun.COM 
1382*7836SJohn.Forte@Sun.COM 	(void) memset(&inq, 0, sizeof (inq));
1383*7836SJohn.Forte@Sun.COM 	(void) memset(&page4, 0, sizeof (page4));
1384*7836SJohn.Forte@Sun.COM 
1385*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path_phys, O_NDELAY | O_RDONLY)) == -1) {
1386*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
1387*7836SJohn.Forte@Sun.COM 	}
1388*7836SJohn.Forte@Sun.COM 	/* Verify it is a Photon */
1389*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_inquiry_cmd(fd,
1390*7836SJohn.Forte@Sun.COM 		(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
1391*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1392*7836SJohn.Forte@Sun.COM 		return (status);
1393*7836SJohn.Forte@Sun.COM 	}
1394*7836SJohn.Forte@Sun.COM 	if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) &&
1395*7836SJohn.Forte@Sun.COM 		(!(strncmp((char *)inq.inq_vid, "SUN     ",
1396*7836SJohn.Forte@Sun.COM 		sizeof (inq.inq_vid)) &&
1397*7836SJohn.Forte@Sun.COM 		((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)))) {
1398*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1399*7836SJohn.Forte@Sun.COM 		return (L_ENCL_INVALID_PATH);
1400*7836SJohn.Forte@Sun.COM 	}
1401*7836SJohn.Forte@Sun.COM 
1402*7836SJohn.Forte@Sun.COM 	page4.page_code = L_PAGE_4;
1403*7836SJohn.Forte@Sun.COM 	page4.page_len = (ushort_t)((sizeof (struct page4_name) - 4));
1404*7836SJohn.Forte@Sun.COM 	page4.string_code = L_ENCL_NAME;
1405*7836SJohn.Forte@Sun.COM 	page4.enable = 1;
1406*7836SJohn.Forte@Sun.COM 	strncpy((char *)page4.name, name, sizeof (page4.name));
1407*7836SJohn.Forte@Sun.COM 
1408*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_send_diag_cmd(fd, (uchar_t *)&page4,
1409*7836SJohn.Forte@Sun.COM 		sizeof (page4))) {
1410*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1411*7836SJohn.Forte@Sun.COM 		return (status);
1412*7836SJohn.Forte@Sun.COM 	}
1413*7836SJohn.Forte@Sun.COM 
1414*7836SJohn.Forte@Sun.COM 	/*
1415*7836SJohn.Forte@Sun.COM 	 * Check the name really changed.
1416*7836SJohn.Forte@Sun.COM 	 */
1417*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_inquiry_cmd(fd,
1418*7836SJohn.Forte@Sun.COM 		(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
1419*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1420*7836SJohn.Forte@Sun.COM 		return (status);
1421*7836SJohn.Forte@Sun.COM 	}
1422*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)inq.inq_box_name, name, sizeof (page4.name)) != 0) {
1423*7836SJohn.Forte@Sun.COM 		char	name_buf[MAXNAMELEN];
1424*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1425*7836SJohn.Forte@Sun.COM 		strncpy((char *)name_buf, (char *)inq.inq_box_name,
1426*7836SJohn.Forte@Sun.COM 			sizeof (inq.inq_box_name));
1427*7836SJohn.Forte@Sun.COM 		return (L_ENCL_NAME_CHANGE_FAIL);
1428*7836SJohn.Forte@Sun.COM 	}
1429*7836SJohn.Forte@Sun.COM 
1430*7836SJohn.Forte@Sun.COM 	(void) close(fd);
1431*7836SJohn.Forte@Sun.COM 	return (0);
1432*7836SJohn.Forte@Sun.COM }
1433*7836SJohn.Forte@Sun.COM 
1434*7836SJohn.Forte@Sun.COM 
1435*7836SJohn.Forte@Sun.COM 
1436*7836SJohn.Forte@Sun.COM /*
1437*7836SJohn.Forte@Sun.COM  * Issue a Loop Port enable Primitive sequence
1438*7836SJohn.Forte@Sun.COM  * to the device specified by the pathname.
1439*7836SJohn.Forte@Sun.COM  */
1440*7836SJohn.Forte@Sun.COM int
l_enable(char * path,int verbose)1441*7836SJohn.Forte@Sun.COM l_enable(char *path, int verbose)
1442*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
1443*7836SJohn.Forte@Sun.COM {
1444*7836SJohn.Forte@Sun.COM 
1445*7836SJohn.Forte@Sun.COM 	return (0);
1446*7836SJohn.Forte@Sun.COM }
1447*7836SJohn.Forte@Sun.COM 
1448*7836SJohn.Forte@Sun.COM /*
1449*7836SJohn.Forte@Sun.COM  * Issue a Loop Port Bypass Primitive sequence
1450*7836SJohn.Forte@Sun.COM  * to the device specified by the pathname. This requests the
1451*7836SJohn.Forte@Sun.COM  * device to set its L_Port into the bypass mode.
1452*7836SJohn.Forte@Sun.COM  */
1453*7836SJohn.Forte@Sun.COM int
l_bypass(char * path,int verbose)1454*7836SJohn.Forte@Sun.COM l_bypass(char *path, int verbose)
1455*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
1456*7836SJohn.Forte@Sun.COM {
1457*7836SJohn.Forte@Sun.COM 
1458*7836SJohn.Forte@Sun.COM 	return (0);
1459*7836SJohn.Forte@Sun.COM }
1460*7836SJohn.Forte@Sun.COM 
1461*7836SJohn.Forte@Sun.COM 
1462*7836SJohn.Forte@Sun.COM 
1463*7836SJohn.Forte@Sun.COM /*
1464*7836SJohn.Forte@Sun.COM  * Create a linked list of all the Photon enclosures that
1465*7836SJohn.Forte@Sun.COM  * are attached to this host.
1466*7836SJohn.Forte@Sun.COM  *
1467*7836SJohn.Forte@Sun.COM  * RETURN VALUES: 0 O.K.
1468*7836SJohn.Forte@Sun.COM  *
1469*7836SJohn.Forte@Sun.COM  * box_list pointer:
1470*7836SJohn.Forte@Sun.COM  *			NULL: No enclosures found.
1471*7836SJohn.Forte@Sun.COM  *			!NULL: Enclosures found
1472*7836SJohn.Forte@Sun.COM  *                      box_list points to a linked list of boxes.
1473*7836SJohn.Forte@Sun.COM  */
1474*7836SJohn.Forte@Sun.COM int
l_get_box_list(struct box_list_struct ** box_list_ptr,int verbose)1475*7836SJohn.Forte@Sun.COM l_get_box_list(struct box_list_struct **box_list_ptr, int verbose)
1476*7836SJohn.Forte@Sun.COM {
1477*7836SJohn.Forte@Sun.COM char		*dev_name;
1478*7836SJohn.Forte@Sun.COM DIR		*dirp;
1479*7836SJohn.Forte@Sun.COM struct dirent	*entp;
1480*7836SJohn.Forte@Sun.COM char		namebuf[MAXPATHLEN];
1481*7836SJohn.Forte@Sun.COM struct stat	sb;
1482*7836SJohn.Forte@Sun.COM char		*result = NULL;
1483*7836SJohn.Forte@Sun.COM int		fd, status;
1484*7836SJohn.Forte@Sun.COM L_inquiry	inq;
1485*7836SJohn.Forte@Sun.COM Box_list	*box_list, *l1, *l2;
1486*7836SJohn.Forte@Sun.COM IB_page_config	page1;
1487*7836SJohn.Forte@Sun.COM uchar_t		node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
1488*7836SJohn.Forte@Sun.COM int		al_pa;
1489*7836SJohn.Forte@Sun.COM 
1490*7836SJohn.Forte@Sun.COM 	if (box_list_ptr == NULL) {
1491*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
1492*7836SJohn.Forte@Sun.COM 	}
1493*7836SJohn.Forte@Sun.COM 
1494*7836SJohn.Forte@Sun.COM 	box_list = *box_list_ptr = NULL;
1495*7836SJohn.Forte@Sun.COM 	if ((dev_name = (char *)g_zalloc(sizeof ("/dev/es"))) == NULL) {
1496*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
1497*7836SJohn.Forte@Sun.COM 	}
1498*7836SJohn.Forte@Sun.COM 	(void) sprintf((char *)dev_name, "/dev/es");
1499*7836SJohn.Forte@Sun.COM 
1500*7836SJohn.Forte@Sun.COM 	if (verbose) {
1501*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
1502*7836SJohn.Forte@Sun.COM 		MSGSTR(9045,
1503*7836SJohn.Forte@Sun.COM 			"  Searching directory %s for links to enclosures\n"),
1504*7836SJohn.Forte@Sun.COM 			dev_name);
1505*7836SJohn.Forte@Sun.COM 	}
1506*7836SJohn.Forte@Sun.COM 
1507*7836SJohn.Forte@Sun.COM 	if ((dirp = opendir(dev_name)) == NULL) {
1508*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(dev_name);
1509*7836SJohn.Forte@Sun.COM 		/* No Photons found */
1510*7836SJohn.Forte@Sun.COM 		B_DPRINTF("  l_get_box_list: No Photons found\n");
1511*7836SJohn.Forte@Sun.COM 		return (0);
1512*7836SJohn.Forte@Sun.COM 	}
1513*7836SJohn.Forte@Sun.COM 
1514*7836SJohn.Forte@Sun.COM 
1515*7836SJohn.Forte@Sun.COM 	while ((entp = readdir(dirp)) != NULL) {
1516*7836SJohn.Forte@Sun.COM 		if (strcmp(entp->d_name, ".") == 0 ||
1517*7836SJohn.Forte@Sun.COM 			strcmp(entp->d_name, "..") == 0)
1518*7836SJohn.Forte@Sun.COM 			continue;
1519*7836SJohn.Forte@Sun.COM 
1520*7836SJohn.Forte@Sun.COM 		(void) sprintf(namebuf, "%s/%s", dev_name, entp->d_name);
1521*7836SJohn.Forte@Sun.COM 
1522*7836SJohn.Forte@Sun.COM 		if ((lstat(namebuf, &sb)) < 0) {
1523*7836SJohn.Forte@Sun.COM 			ER_DPRINTF("Warning: Cannot stat %s\n",
1524*7836SJohn.Forte@Sun.COM 							namebuf);
1525*7836SJohn.Forte@Sun.COM 			continue;
1526*7836SJohn.Forte@Sun.COM 		}
1527*7836SJohn.Forte@Sun.COM 
1528*7836SJohn.Forte@Sun.COM 		if (!S_ISLNK(sb.st_mode)) {
1529*7836SJohn.Forte@Sun.COM 			ER_DPRINTF("Warning: %s is not a symbolic link\n",
1530*7836SJohn.Forte@Sun.COM 								namebuf);
1531*7836SJohn.Forte@Sun.COM 			continue;
1532*7836SJohn.Forte@Sun.COM 		}
1533*7836SJohn.Forte@Sun.COM 		if ((result = g_get_physical_name_from_link(namebuf)) == NULL) {
1534*7836SJohn.Forte@Sun.COM 			ER_DPRINTF("  Warning: Get physical name from"
1535*7836SJohn.Forte@Sun.COM 			" link failed. Link=%s\n", namebuf);
1536*7836SJohn.Forte@Sun.COM 			continue;
1537*7836SJohn.Forte@Sun.COM 		}
1538*7836SJohn.Forte@Sun.COM 
1539*7836SJohn.Forte@Sun.COM 		/* Found a SES card. */
1540*7836SJohn.Forte@Sun.COM 		B_DPRINTF("  l_get_box_list: Link to SES Card found: %s/%s\n",
1541*7836SJohn.Forte@Sun.COM 			dev_name, entp->d_name);
1542*7836SJohn.Forte@Sun.COM 		if ((fd = g_object_open(result, O_NDELAY | O_RDONLY)) == -1) {
1543*7836SJohn.Forte@Sun.COM 			g_destroy_data(result);
1544*7836SJohn.Forte@Sun.COM 			continue;	/* Ignore errors */
1545*7836SJohn.Forte@Sun.COM 		}
1546*7836SJohn.Forte@Sun.COM 		/* Get the box name */
1547*7836SJohn.Forte@Sun.COM 		if (status = g_scsi_inquiry_cmd(fd,
1548*7836SJohn.Forte@Sun.COM 			(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
1549*7836SJohn.Forte@Sun.COM 			(void) close(fd);
1550*7836SJohn.Forte@Sun.COM 			g_destroy_data(result);
1551*7836SJohn.Forte@Sun.COM 			continue;	/* Ignore errors */
1552*7836SJohn.Forte@Sun.COM 		}
1553*7836SJohn.Forte@Sun.COM 
1554*7836SJohn.Forte@Sun.COM 		if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) != NULL) ||
1555*7836SJohn.Forte@Sun.COM 			(((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI) &&
1556*7836SJohn.Forte@Sun.COM 				(l_get_enc_type(inq) == DAK_ENC_TYPE))) {
1557*7836SJohn.Forte@Sun.COM 			/*
1558*7836SJohn.Forte@Sun.COM 			 * Found Photon/Daktari
1559*7836SJohn.Forte@Sun.COM 			 */
1560*7836SJohn.Forte@Sun.COM 
1561*7836SJohn.Forte@Sun.COM 			/* Get the port WWN from the IB, page 1 */
1562*7836SJohn.Forte@Sun.COM 			if ((status = l_get_envsen_page(fd, (uchar_t *)&page1,
1563*7836SJohn.Forte@Sun.COM 				sizeof (page1), 1, 0)) != NULL) {
1564*7836SJohn.Forte@Sun.COM 				(void) close(fd);
1565*7836SJohn.Forte@Sun.COM 				g_destroy_data(result);
1566*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(dev_name);
1567*7836SJohn.Forte@Sun.COM 				closedir(dirp);
1568*7836SJohn.Forte@Sun.COM 				return (status);
1569*7836SJohn.Forte@Sun.COM 			}
1570*7836SJohn.Forte@Sun.COM 
1571*7836SJohn.Forte@Sun.COM 			/*
1572*7836SJohn.Forte@Sun.COM 			 * Build list of names.
1573*7836SJohn.Forte@Sun.COM 			 */
1574*7836SJohn.Forte@Sun.COM 			if ((l2 = (struct  box_list_struct *)
1575*7836SJohn.Forte@Sun.COM 				g_zalloc(sizeof (struct  box_list_struct)))
1576*7836SJohn.Forte@Sun.COM 				== NULL) {
1577*7836SJohn.Forte@Sun.COM 				(void) close(fd);
1578*7836SJohn.Forte@Sun.COM 				g_destroy_data(result);
1579*7836SJohn.Forte@Sun.COM 				g_destroy_data(dev_name);
1580*7836SJohn.Forte@Sun.COM 				closedir(dirp);
1581*7836SJohn.Forte@Sun.COM 				return (L_MALLOC_FAILED);
1582*7836SJohn.Forte@Sun.COM 			}
1583*7836SJohn.Forte@Sun.COM 
1584*7836SJohn.Forte@Sun.COM 			/* Fill in structure */
1585*7836SJohn.Forte@Sun.COM 			(void) strcpy((char *)l2->b_physical_path,
1586*7836SJohn.Forte@Sun.COM 				(char *)result);
1587*7836SJohn.Forte@Sun.COM 			(void) strcpy((char *)l2->logical_path,
1588*7836SJohn.Forte@Sun.COM 				(char *)namebuf);
1589*7836SJohn.Forte@Sun.COM 			bcopy((void *)page1.enc_node_wwn,
1590*7836SJohn.Forte@Sun.COM 				(void *)l2->b_node_wwn, WWN_SIZE);
1591*7836SJohn.Forte@Sun.COM 			(void) sprintf(l2->b_node_wwn_s,
1592*7836SJohn.Forte@Sun.COM 			"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
1593*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[0],
1594*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[1],
1595*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[2],
1596*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[3],
1597*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[4],
1598*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[5],
1599*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[6],
1600*7836SJohn.Forte@Sun.COM 				page1.enc_node_wwn[7]);
1601*7836SJohn.Forte@Sun.COM 			strncpy((char *)l2->prod_id_s,
1602*7836SJohn.Forte@Sun.COM 				(char *)inq.inq_pid,
1603*7836SJohn.Forte@Sun.COM 				sizeof (inq.inq_pid));
1604*7836SJohn.Forte@Sun.COM 			strncpy((char *)l2->b_name,
1605*7836SJohn.Forte@Sun.COM 				(char *)inq.inq_box_name,
1606*7836SJohn.Forte@Sun.COM 				sizeof (inq.inq_box_name));
1607*7836SJohn.Forte@Sun.COM 			/* make sure null terminated */
1608*7836SJohn.Forte@Sun.COM 			l2->b_name[sizeof (l2->b_name) - 1] = NULL;
1609*7836SJohn.Forte@Sun.COM 
1610*7836SJohn.Forte@Sun.COM 			/*
1611*7836SJohn.Forte@Sun.COM 			 * Now get the port WWN for the port
1612*7836SJohn.Forte@Sun.COM 			 * we are connected to.
1613*7836SJohn.Forte@Sun.COM 			 */
1614*7836SJohn.Forte@Sun.COM 			status = g_get_wwn(result, port_wwn, node_wwn,
1615*7836SJohn.Forte@Sun.COM 					&al_pa, verbose);
1616*7836SJohn.Forte@Sun.COM 			if (status == 0) {
1617*7836SJohn.Forte@Sun.COM 				(void) sprintf(l2->b_port_wwn_s,
1618*7836SJohn.Forte@Sun.COM 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
1619*7836SJohn.Forte@Sun.COM 				port_wwn[0], port_wwn[1], port_wwn[2],
1620*7836SJohn.Forte@Sun.COM 				port_wwn[3], port_wwn[4], port_wwn[5],
1621*7836SJohn.Forte@Sun.COM 				port_wwn[6], port_wwn[7]);
1622*7836SJohn.Forte@Sun.COM 				bcopy((void *)port_wwn,
1623*7836SJohn.Forte@Sun.COM 					(void *)l2->b_port_wwn, WWN_SIZE);
1624*7836SJohn.Forte@Sun.COM 
1625*7836SJohn.Forte@Sun.COM 				B_DPRINTF("  l_get_box_list:"
1626*7836SJohn.Forte@Sun.COM 				" Found enclosure named:%s\n", l2->b_name);
1627*7836SJohn.Forte@Sun.COM 
1628*7836SJohn.Forte@Sun.COM 				if (box_list == NULL) {
1629*7836SJohn.Forte@Sun.COM 					l1 = box_list = l2;
1630*7836SJohn.Forte@Sun.COM 				} else {
1631*7836SJohn.Forte@Sun.COM 					l2->box_prev = l1;
1632*7836SJohn.Forte@Sun.COM 					l1 = l1->box_next = l2;
1633*7836SJohn.Forte@Sun.COM 				}
1634*7836SJohn.Forte@Sun.COM 			} else {
1635*7836SJohn.Forte@Sun.COM 				(void) close(fd);
1636*7836SJohn.Forte@Sun.COM 				g_destroy_data(result);
1637*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(dev_name);
1638*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(l2);
1639*7836SJohn.Forte@Sun.COM 				closedir(dirp);
1640*7836SJohn.Forte@Sun.COM 				return (status);
1641*7836SJohn.Forte@Sun.COM 			}
1642*7836SJohn.Forte@Sun.COM 
1643*7836SJohn.Forte@Sun.COM 		}
1644*7836SJohn.Forte@Sun.COM 		g_destroy_data(result);
1645*7836SJohn.Forte@Sun.COM 		(void) close(fd);
1646*7836SJohn.Forte@Sun.COM 		*box_list_ptr = box_list; /* pass back ptr to list */
1647*7836SJohn.Forte@Sun.COM 	}
1648*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(dev_name);
1649*7836SJohn.Forte@Sun.COM 	closedir(dirp);
1650*7836SJohn.Forte@Sun.COM 	return (0);
1651*7836SJohn.Forte@Sun.COM }
1652*7836SJohn.Forte@Sun.COM 
1653*7836SJohn.Forte@Sun.COM void
l_free_box_list(struct box_list_struct ** box_list)1654*7836SJohn.Forte@Sun.COM l_free_box_list(struct box_list_struct **box_list)
1655*7836SJohn.Forte@Sun.COM {
1656*7836SJohn.Forte@Sun.COM Box_list	*next = NULL;
1657*7836SJohn.Forte@Sun.COM 
1658*7836SJohn.Forte@Sun.COM 	if (box_list == NULL) {
1659*7836SJohn.Forte@Sun.COM 		return;
1660*7836SJohn.Forte@Sun.COM 	}
1661*7836SJohn.Forte@Sun.COM 
1662*7836SJohn.Forte@Sun.COM 	for (; *box_list != NULL; *box_list = next) {
1663*7836SJohn.Forte@Sun.COM 		next = (*box_list)->box_next;
1664*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(*box_list);
1665*7836SJohn.Forte@Sun.COM 	}
1666*7836SJohn.Forte@Sun.COM 
1667*7836SJohn.Forte@Sun.COM 	*box_list = NULL;
1668*7836SJohn.Forte@Sun.COM }
1669*7836SJohn.Forte@Sun.COM 
1670*7836SJohn.Forte@Sun.COM 
1671*7836SJohn.Forte@Sun.COM 
1672*7836SJohn.Forte@Sun.COM /*
1673*7836SJohn.Forte@Sun.COM  * Finds out if there are any other boxes
1674*7836SJohn.Forte@Sun.COM  * with the same name as "name".
1675*7836SJohn.Forte@Sun.COM  *
1676*7836SJohn.Forte@Sun.COM  * RETURNS:
1677*7836SJohn.Forte@Sun.COM  *	0   There are no other boxes with the same name.
1678*7836SJohn.Forte@Sun.COM  *	>0  if duplicate names found
1679*7836SJohn.Forte@Sun.COM  */
1680*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
1681*7836SJohn.Forte@Sun.COM int
l_duplicate_names(Box_list * b_list,char wwn[],char * name,int verbose)1682*7836SJohn.Forte@Sun.COM l_duplicate_names(Box_list *b_list, char wwn[], char *name, int verbose)
1683*7836SJohn.Forte@Sun.COM {
1684*7836SJohn.Forte@Sun.COM int		dup_flag = 0;
1685*7836SJohn.Forte@Sun.COM Box_list	*box_list_ptr = NULL;
1686*7836SJohn.Forte@Sun.COM 
1687*7836SJohn.Forte@Sun.COM 	if ((name == NULL) || (wwn == NULL))
1688*7836SJohn.Forte@Sun.COM 		return (0);
1689*7836SJohn.Forte@Sun.COM 
1690*7836SJohn.Forte@Sun.COM 	box_list_ptr = b_list;
1691*7836SJohn.Forte@Sun.COM 	while (box_list_ptr != NULL) {
1692*7836SJohn.Forte@Sun.COM 		if ((strcmp(name, (const char *)box_list_ptr->b_name) == 0) &&
1693*7836SJohn.Forte@Sun.COM 			(strcmp(box_list_ptr->b_node_wwn_s, wwn) != 0)) {
1694*7836SJohn.Forte@Sun.COM 			dup_flag++;
1695*7836SJohn.Forte@Sun.COM 			break;
1696*7836SJohn.Forte@Sun.COM 		}
1697*7836SJohn.Forte@Sun.COM 		box_list_ptr = box_list_ptr->box_next;
1698*7836SJohn.Forte@Sun.COM 	}
1699*7836SJohn.Forte@Sun.COM 	return (dup_flag);
1700*7836SJohn.Forte@Sun.COM }
1701*7836SJohn.Forte@Sun.COM 
1702*7836SJohn.Forte@Sun.COM 
1703*7836SJohn.Forte@Sun.COM 
1704*7836SJohn.Forte@Sun.COM /*
1705*7836SJohn.Forte@Sun.COM  * Checks for a name conflict with an SSA cN type name.
1706*7836SJohn.Forte@Sun.COM  */
1707*7836SJohn.Forte@Sun.COM int
l_get_conflict(char * name,char ** result,int verbose)1708*7836SJohn.Forte@Sun.COM l_get_conflict(char *name, char **result, int verbose)
1709*7836SJohn.Forte@Sun.COM {
1710*7836SJohn.Forte@Sun.COM char		s[MAXPATHLEN];
1711*7836SJohn.Forte@Sun.COM char		*p = NULL;
1712*7836SJohn.Forte@Sun.COM char		*pp = NULL;
1713*7836SJohn.Forte@Sun.COM Box_list	*box_list = NULL;
1714*7836SJohn.Forte@Sun.COM int		found_box = 0, err = 0;
1715*7836SJohn.Forte@Sun.COM 
1716*7836SJohn.Forte@Sun.COM 	(void) strcpy(s, name);
1717*7836SJohn.Forte@Sun.COM 	if ((*result = g_get_physical_name(s)) == NULL) {
1718*7836SJohn.Forte@Sun.COM 		return (0);
1719*7836SJohn.Forte@Sun.COM 	}
1720*7836SJohn.Forte@Sun.COM 	if ((strstr((const char *)*result, PLNDEF)) == NULL) {
1721*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(*result);
1722*7836SJohn.Forte@Sun.COM 		*result = NULL;
1723*7836SJohn.Forte@Sun.COM 		return (0);
1724*7836SJohn.Forte@Sun.COM 	}
1725*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  l_get_conflict: Found "
1726*7836SJohn.Forte@Sun.COM 		"SSA path using %s\n", s);
1727*7836SJohn.Forte@Sun.COM 	/* Find path to IB */
1728*7836SJohn.Forte@Sun.COM 	if ((err = l_get_box_list(&box_list, verbose)) != 0) {
1729*7836SJohn.Forte@Sun.COM 		return (err);	/* Failure */
1730*7836SJohn.Forte@Sun.COM 	}
1731*7836SJohn.Forte@Sun.COM 	/*
1732*7836SJohn.Forte@Sun.COM 	 * Valid cN type name found.
1733*7836SJohn.Forte@Sun.COM 	 */
1734*7836SJohn.Forte@Sun.COM 	while (box_list != NULL) {
1735*7836SJohn.Forte@Sun.COM 		if ((strcmp((char *)s,
1736*7836SJohn.Forte@Sun.COM 			(char *)box_list->b_name)) == 0) {
1737*7836SJohn.Forte@Sun.COM 			found_box = 1;
1738*7836SJohn.Forte@Sun.COM 			if (p == NULL) {
1739*7836SJohn.Forte@Sun.COM 				if ((p = g_zalloc(strlen(
1740*7836SJohn.Forte@Sun.COM 				box_list->b_physical_path)
1741*7836SJohn.Forte@Sun.COM 				+ 2)) == NULL) {
1742*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&box_list);
1743*7836SJohn.Forte@Sun.COM 				return (errno);
1744*7836SJohn.Forte@Sun.COM 				}
1745*7836SJohn.Forte@Sun.COM 			} else {
1746*7836SJohn.Forte@Sun.COM 				if ((pp = g_zalloc(strlen(
1747*7836SJohn.Forte@Sun.COM 				box_list->b_physical_path)
1748*7836SJohn.Forte@Sun.COM 				+ strlen(p)
1749*7836SJohn.Forte@Sun.COM 				+ 2)) == NULL) {
1750*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&box_list);
1751*7836SJohn.Forte@Sun.COM 				return (errno);
1752*7836SJohn.Forte@Sun.COM 				}
1753*7836SJohn.Forte@Sun.COM 				(void) strcpy(pp, p);
1754*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(p);
1755*7836SJohn.Forte@Sun.COM 				p = pp;
1756*7836SJohn.Forte@Sun.COM 			}
1757*7836SJohn.Forte@Sun.COM 			(void) strcat(p, box_list->b_physical_path);
1758*7836SJohn.Forte@Sun.COM 			(void) strcat(p, "\n");
1759*7836SJohn.Forte@Sun.COM 		}
1760*7836SJohn.Forte@Sun.COM 		box_list = box_list->box_next;
1761*7836SJohn.Forte@Sun.COM 	}
1762*7836SJohn.Forte@Sun.COM 	if (found_box) {
1763*7836SJohn.Forte@Sun.COM 		D_DPRINTF("There is a conflict between the "
1764*7836SJohn.Forte@Sun.COM 			"enclosure\nwith this name, %s, "
1765*7836SJohn.Forte@Sun.COM 			"and a SSA name of the same form.\n"
1766*7836SJohn.Forte@Sun.COM 			"Please use one of the following physical "
1767*7836SJohn.Forte@Sun.COM 			"pathnames:\n%s\n%s\n",
1768*7836SJohn.Forte@Sun.COM 			s, *result, p);
1769*7836SJohn.Forte@Sun.COM 
1770*7836SJohn.Forte@Sun.COM 		(void) l_free_box_list(&box_list);
1771*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(p);
1772*7836SJohn.Forte@Sun.COM 		return (L_SSA_CONFLICT);	/* failure */
1773*7836SJohn.Forte@Sun.COM 	}
1774*7836SJohn.Forte@Sun.COM 	(void) l_free_box_list(&box_list);
1775*7836SJohn.Forte@Sun.COM 	return (0);
1776*7836SJohn.Forte@Sun.COM }
1777*7836SJohn.Forte@Sun.COM 
1778*7836SJohn.Forte@Sun.COM /*
1779*7836SJohn.Forte@Sun.COM  * This function sets the "slot", "slot_valid" and "f_flag" fields of the
1780*7836SJohn.Forte@Sun.COM  * path_struct that is passed in IFF the device path passed in ("phys_path")
1781*7836SJohn.Forte@Sun.COM  * is a disk in an A5K or a Daktari. This is achieved by calling l_get_slot().
1782*7836SJohn.Forte@Sun.COM  *
1783*7836SJohn.Forte@Sun.COM  * INPUT  :
1784*7836SJohn.Forte@Sun.COM  *	phys_path - physical path to a device
1785*7836SJohn.Forte@Sun.COM  *	path_sturct - Pointer to pointer to a path_struct data structure
1786*7836SJohn.Forte@Sun.COM  *
1787*7836SJohn.Forte@Sun.COM  * OUTPUT :
1788*7836SJohn.Forte@Sun.COM  *	if phys_path is that of an A5K/Daktari disk
1789*7836SJohn.Forte@Sun.COM  *		path_struct->slot is set to the slot position in enclosure
1790*7836SJohn.Forte@Sun.COM  *		path_struct->slot_valid is set to 1
1791*7836SJohn.Forte@Sun.COM  *		path_struct->f_flag is set to 1 if in the front of an A5k
1792*7836SJohn.Forte@Sun.COM  *			    or if among the first 6 disks on a Daktari
1793*7836SJohn.Forte@Sun.COM  *	else
1794*7836SJohn.Forte@Sun.COM  *		they are left as they were
1795*7836SJohn.Forte@Sun.COM  * RETURNS:
1796*7836SJohn.Forte@Sun.COM  *	0 on SUCCESS
1797*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
1798*7836SJohn.Forte@Sun.COM  */
1799*7836SJohn.Forte@Sun.COM static int
load_flds_if_enc_disk(char * phys_path,struct path_struct ** path_struct)1800*7836SJohn.Forte@Sun.COM load_flds_if_enc_disk(char *phys_path, struct path_struct **path_struct)
1801*7836SJohn.Forte@Sun.COM {
1802*7836SJohn.Forte@Sun.COM 	int		err = 0, verbose = 0;
1803*7836SJohn.Forte@Sun.COM 	char		ses_path[MAXPATHLEN];
1804*7836SJohn.Forte@Sun.COM 	gfc_map_t	map;
1805*7836SJohn.Forte@Sun.COM 	L_inquiry	inq;
1806*7836SJohn.Forte@Sun.COM 	L_state		*l_state = NULL;
1807*7836SJohn.Forte@Sun.COM 
1808*7836SJohn.Forte@Sun.COM 	if ((path_struct == NULL) || (*path_struct == NULL) ||
1809*7836SJohn.Forte@Sun.COM 				(phys_path == NULL) || (*phys_path == NULL)) {
1810*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
1811*7836SJohn.Forte@Sun.COM 	}
1812*7836SJohn.Forte@Sun.COM 
1813*7836SJohn.Forte@Sun.COM 	if ((strstr(phys_path, SLSH_DRV_NAME_SSD) == NULL) ||
1814*7836SJohn.Forte@Sun.COM 	    (g_get_path_type(phys_path) == 0)) {
1815*7836SJohn.Forte@Sun.COM 		/*
1816*7836SJohn.Forte@Sun.COM 		 * Don't proceed when not a disk device or if it is not a
1817*7836SJohn.Forte@Sun.COM 		 * valid FC device on which g_get_dev_map() can be done
1818*7836SJohn.Forte@Sun.COM 		 * (for example, g_get_dev_map() will fail on SSAs).
1819*7836SJohn.Forte@Sun.COM 		 *
1820*7836SJohn.Forte@Sun.COM 		 * Just return success
1821*7836SJohn.Forte@Sun.COM 		 */
1822*7836SJohn.Forte@Sun.COM 		return (0);
1823*7836SJohn.Forte@Sun.COM 	}
1824*7836SJohn.Forte@Sun.COM 
1825*7836SJohn.Forte@Sun.COM 	if ((*path_struct)->ib_path_flag) {
1826*7836SJohn.Forte@Sun.COM 		/*
1827*7836SJohn.Forte@Sun.COM 		 * If this flag is set, l_get_slot() should not be called
1828*7836SJohn.Forte@Sun.COM 		 * So, no point in proceeding. Just return success.
1829*7836SJohn.Forte@Sun.COM 		 */
1830*7836SJohn.Forte@Sun.COM 		return (0);
1831*7836SJohn.Forte@Sun.COM 	}
1832*7836SJohn.Forte@Sun.COM 
1833*7836SJohn.Forte@Sun.COM 	if ((err = g_get_dev_map(phys_path, &map, verbose)) != 0) {
1834*7836SJohn.Forte@Sun.COM 		return (err);
1835*7836SJohn.Forte@Sun.COM 	}
1836*7836SJohn.Forte@Sun.COM 
1837*7836SJohn.Forte@Sun.COM 	if ((err = l_get_ses_path(phys_path, ses_path, &map, verbose)) != 0) {
1838*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1839*7836SJohn.Forte@Sun.COM 		if (err == L_NO_SES_PATH) {
1840*7836SJohn.Forte@Sun.COM 			/*
1841*7836SJohn.Forte@Sun.COM 			 * This is not an error since this could be a device
1842*7836SJohn.Forte@Sun.COM 			 * which does not have SES nodes
1843*7836SJohn.Forte@Sun.COM 			 */
1844*7836SJohn.Forte@Sun.COM 			return (0);
1845*7836SJohn.Forte@Sun.COM 		}
1846*7836SJohn.Forte@Sun.COM 		return (err);
1847*7836SJohn.Forte@Sun.COM 	}
1848*7836SJohn.Forte@Sun.COM 
1849*7836SJohn.Forte@Sun.COM 	/*
1850*7836SJohn.Forte@Sun.COM 	 * There is a SES path on the same FCA as the given disk. But if the
1851*7836SJohn.Forte@Sun.COM 	 * SES node is not of a photon/Daktari, we dont proceed
1852*7836SJohn.Forte@Sun.COM 	 */
1853*7836SJohn.Forte@Sun.COM 	if ((err = g_get_inquiry(ses_path, &inq)) != 0) {
1854*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1855*7836SJohn.Forte@Sun.COM 		return (err);
1856*7836SJohn.Forte@Sun.COM 	}
1857*7836SJohn.Forte@Sun.COM 
1858*7836SJohn.Forte@Sun.COM 	/*
1859*7836SJohn.Forte@Sun.COM 	 * only want to continue if this is a photon or a Daktari
1860*7836SJohn.Forte@Sun.COM 	 *
1861*7836SJohn.Forte@Sun.COM 	 * if product ID is not SENA or VID is not "SUN" (checks for photon)
1862*7836SJohn.Forte@Sun.COM 	 * and if enclosure type is not a Daktari, then I return
1863*7836SJohn.Forte@Sun.COM 	 */
1864*7836SJohn.Forte@Sun.COM 	if (((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) ||
1865*7836SJohn.Forte@Sun.COM 		    (strncmp((char *)inq.inq_vid, "SUN     ",
1866*7836SJohn.Forte@Sun.COM 			sizeof (inq.inq_vid)) != 0)) &&
1867*7836SJohn.Forte@Sun.COM 	    ((l_get_enc_type(inq) != DAK_ENC_TYPE))) {
1868*7836SJohn.Forte@Sun.COM 		/* Not a photon/Daktari */
1869*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1870*7836SJohn.Forte@Sun.COM 		return (0);
1871*7836SJohn.Forte@Sun.COM 	}
1872*7836SJohn.Forte@Sun.COM 
1873*7836SJohn.Forte@Sun.COM 	/* Now, set some fields that l_get_slot() uses and then call it */
1874*7836SJohn.Forte@Sun.COM 	if ((l_state = (L_state *)g_zalloc(sizeof (L_state))) == NULL) {
1875*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1876*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
1877*7836SJohn.Forte@Sun.COM 	}
1878*7836SJohn.Forte@Sun.COM 
1879*7836SJohn.Forte@Sun.COM 	if ((err = l_get_ib_status(ses_path, l_state, verbose)) != 0) {
1880*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1881*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
1882*7836SJohn.Forte@Sun.COM 		return (err);
1883*7836SJohn.Forte@Sun.COM 	}
1884*7836SJohn.Forte@Sun.COM 
1885*7836SJohn.Forte@Sun.COM 	if ((err = l_get_slot(*path_struct, l_state, verbose)) != 0) {
1886*7836SJohn.Forte@Sun.COM 		(void) free(map.dev_addr);
1887*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
1888*7836SJohn.Forte@Sun.COM 		return (err);
1889*7836SJohn.Forte@Sun.COM 	}
1890*7836SJohn.Forte@Sun.COM 
1891*7836SJohn.Forte@Sun.COM 	(void) free(map.dev_addr);
1892*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&l_state);
1893*7836SJohn.Forte@Sun.COM 	return (0);
1894*7836SJohn.Forte@Sun.COM }
1895*7836SJohn.Forte@Sun.COM 
1896*7836SJohn.Forte@Sun.COM /*
1897*7836SJohn.Forte@Sun.COM  * convert box name or WWN or logical path to physical path.
1898*7836SJohn.Forte@Sun.COM  *
1899*7836SJohn.Forte@Sun.COM  *	OUTPUT:
1900*7836SJohn.Forte@Sun.COM  *		path_struct:
1901*7836SJohn.Forte@Sun.COM  *		- This structure is used to return more detailed
1902*7836SJohn.Forte@Sun.COM  *		  information about the path.
1903*7836SJohn.Forte@Sun.COM  *		- *p_physical_path
1904*7836SJohn.Forte@Sun.COM  *		  Normally this is the requested physical path.
1905*7836SJohn.Forte@Sun.COM  *		  If the requested path is not found then iff the
1906*7836SJohn.Forte@Sun.COM  *		  ib_path_flag is set this is the IB path.
1907*7836SJohn.Forte@Sun.COM  *		- *argv
1908*7836SJohn.Forte@Sun.COM  *		This is the argument variable input. e.g. Bob,f1
1909*7836SJohn.Forte@Sun.COM  *              - slot_valid
1910*7836SJohn.Forte@Sun.COM  *              - slot
1911*7836SJohn.Forte@Sun.COM  *		This is the slot number that was entered when using
1912*7836SJohn.Forte@Sun.COM  *		  the box,[fr]slot format. It is only valid if the
1913*7836SJohn.Forte@Sun.COM  *		  slot_valid flag is set.
1914*7836SJohn.Forte@Sun.COM  *		- f_flag
1915*7836SJohn.Forte@Sun.COM  *		  Front flag - If set, the requested device is located in the
1916*7836SJohn.Forte@Sun.COM  *		  front of the enclosure.
1917*7836SJohn.Forte@Sun.COM  *		- ib_path_flag
1918*7836SJohn.Forte@Sun.COM  *		  If this flag is set it means a devices path was requested
1919*7836SJohn.Forte@Sun.COM  *		  but could not be found but an IB's path was found and
1920*7836SJohn.Forte@Sun.COM  *		  the p_physical_path points to that path.
1921*7836SJohn.Forte@Sun.COM  *		- **phys_path
1922*7836SJohn.Forte@Sun.COM  *		  physical path to the device.
1923*7836SJohn.Forte@Sun.COM  *	RETURNS:
1924*7836SJohn.Forte@Sun.COM  *		- 0  if O.K.
1925*7836SJohn.Forte@Sun.COM  *		- error otherwise.
1926*7836SJohn.Forte@Sun.COM  */
1927*7836SJohn.Forte@Sun.COM int
l_convert_name(char * name,char ** phys_path,struct path_struct ** path_struct,int verbose)1928*7836SJohn.Forte@Sun.COM l_convert_name(char *name, char **phys_path,
1929*7836SJohn.Forte@Sun.COM 		struct path_struct **path_struct, int verbose)
1930*7836SJohn.Forte@Sun.COM {
1931*7836SJohn.Forte@Sun.COM char		tmp_name[MAXPATHLEN], ses_path[MAXPATHLEN];
1932*7836SJohn.Forte@Sun.COM char		*char_ptr, *ptr = NULL;
1933*7836SJohn.Forte@Sun.COM char		*result = NULL;
1934*7836SJohn.Forte@Sun.COM char		*env = NULL;
1935*7836SJohn.Forte@Sun.COM char		save_frd;	    /* which designator was it? */
1936*7836SJohn.Forte@Sun.COM int		slot = 0, slot_flag = 0, found_box = 0, found_comma = 0;
1937*7836SJohn.Forte@Sun.COM int		err = 0, enc_type = 0;
1938*7836SJohn.Forte@Sun.COM hrtime_t	start_time, end_time;
1939*7836SJohn.Forte@Sun.COM Box_list	*box_list = NULL, *box_list_ptr = NULL;
1940*7836SJohn.Forte@Sun.COM L_inquiry	inq;
1941*7836SJohn.Forte@Sun.COM L_state		*l_state = NULL;
1942*7836SJohn.Forte@Sun.COM Path_struct	*path_ptr = NULL;
1943*7836SJohn.Forte@Sun.COM WWN_list	*wwn_list, *wwn_list_ptr;
1944*7836SJohn.Forte@Sun.COM 
1945*7836SJohn.Forte@Sun.COM 	if ((name == NULL) || (phys_path == NULL) ||
1946*7836SJohn.Forte@Sun.COM 	    (path_struct == NULL)) {
1947*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
1948*7836SJohn.Forte@Sun.COM 	}
1949*7836SJohn.Forte@Sun.COM 
1950*7836SJohn.Forte@Sun.COM 	if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
1951*7836SJohn.Forte@Sun.COM 		start_time = gethrtime();
1952*7836SJohn.Forte@Sun.COM 	}
1953*7836SJohn.Forte@Sun.COM 
1954*7836SJohn.Forte@Sun.COM 	if ((*path_struct = path_ptr = (struct path_struct *)
1955*7836SJohn.Forte@Sun.COM 		g_zalloc(sizeof (struct path_struct))) == NULL) {
1956*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
1957*7836SJohn.Forte@Sun.COM 	}
1958*7836SJohn.Forte@Sun.COM 
1959*7836SJohn.Forte@Sun.COM 	*phys_path = NULL;
1960*7836SJohn.Forte@Sun.COM 	/*
1961*7836SJohn.Forte@Sun.COM 	 * If the path contains a "/" then assume
1962*7836SJohn.Forte@Sun.COM 	 * it is a logical or physical path as the
1963*7836SJohn.Forte@Sun.COM 	 * box name or wwn can not contain "/"s.
1964*7836SJohn.Forte@Sun.COM 	 */
1965*7836SJohn.Forte@Sun.COM 	if (strchr(name, '/') != NULL) {
1966*7836SJohn.Forte@Sun.COM 		if ((result = g_get_physical_name(name)) == NULL) {
1967*7836SJohn.Forte@Sun.COM 			return (L_NO_PHYS_PATH);
1968*7836SJohn.Forte@Sun.COM 		}
1969*7836SJohn.Forte@Sun.COM 
1970*7836SJohn.Forte@Sun.COM 		path_ptr->p_physical_path = result;
1971*7836SJohn.Forte@Sun.COM 		/*
1972*7836SJohn.Forte@Sun.COM 		 * Make sure it's a disk or tape path
1973*7836SJohn.Forte@Sun.COM 		 */
1974*7836SJohn.Forte@Sun.COM 		if (strstr(name, DEV_RDIR) || strstr(name, SLSH_DRV_NAME_SSD) ||
1975*7836SJohn.Forte@Sun.COM 			strstr(name, DEV_TAPE_DIR) ||
1976*7836SJohn.Forte@Sun.COM 			strstr(name, SLSH_DRV_NAME_ST)) {
1977*7836SJohn.Forte@Sun.COM 			if ((err = g_get_inquiry(result, &inq)) != 0) {
1978*7836SJohn.Forte@Sun.COM 				(void) free(result);
1979*7836SJohn.Forte@Sun.COM 				return (L_SCSI_ERROR);
1980*7836SJohn.Forte@Sun.COM 			}
1981*7836SJohn.Forte@Sun.COM 			/*
1982*7836SJohn.Forte@Sun.COM 			 * Check to see if it is not a
1983*7836SJohn.Forte@Sun.COM 			 * A5K/v880/v890 disk
1984*7836SJohn.Forte@Sun.COM 			 *
1985*7836SJohn.Forte@Sun.COM 			 */
1986*7836SJohn.Forte@Sun.COM 			if (!g_enclDiskChk((char *)inq.inq_vid,
1987*7836SJohn.Forte@Sun.COM 				    (char *)inq.inq_pid)) {
1988*7836SJohn.Forte@Sun.COM 				path_ptr->argv = name;
1989*7836SJohn.Forte@Sun.COM 				*phys_path = result;
1990*7836SJohn.Forte@Sun.COM 				return (0);
1991*7836SJohn.Forte@Sun.COM 			}
1992*7836SJohn.Forte@Sun.COM 		}
1993*7836SJohn.Forte@Sun.COM 
1994*7836SJohn.Forte@Sun.COM 		if (err = load_flds_if_enc_disk(result, path_struct)) {
1995*7836SJohn.Forte@Sun.COM 			(void) free(result);
1996*7836SJohn.Forte@Sun.COM 			return (err);
1997*7836SJohn.Forte@Sun.COM 		}
1998*7836SJohn.Forte@Sun.COM 		goto done;
1999*7836SJohn.Forte@Sun.COM 	}
2000*7836SJohn.Forte@Sun.COM 
2001*7836SJohn.Forte@Sun.COM 	(void) strcpy(tmp_name, name);
2002*7836SJohn.Forte@Sun.COM 	if ((tmp_name[0] == 'c') &&
2003*7836SJohn.Forte@Sun.COM 		((int)strlen(tmp_name) > 1) && ((int)strlen(tmp_name) < 5)) {
2004*7836SJohn.Forte@Sun.COM 		if ((err = l_get_conflict(tmp_name, &result, verbose)) != 0) {
2005*7836SJohn.Forte@Sun.COM 			if (result != NULL) {
2006*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(result);
2007*7836SJohn.Forte@Sun.COM 			}
2008*7836SJohn.Forte@Sun.COM 			return (err);
2009*7836SJohn.Forte@Sun.COM 		}
2010*7836SJohn.Forte@Sun.COM 		if (result != NULL) {
2011*7836SJohn.Forte@Sun.COM 			path_ptr->p_physical_path = result;
2012*7836SJohn.Forte@Sun.COM 			if ((err = g_get_inquiry(result, &inq)) != 0) {
2013*7836SJohn.Forte@Sun.COM 				(void) free(result);
2014*7836SJohn.Forte@Sun.COM 				return (L_SCSI_ERROR);
2015*7836SJohn.Forte@Sun.COM 			}
2016*7836SJohn.Forte@Sun.COM 			/*
2017*7836SJohn.Forte@Sun.COM 			 * Check to see if it is a supported
2018*7836SJohn.Forte@Sun.COM 			 * A5K/v880/v890 storage subsystem disk
2019*7836SJohn.Forte@Sun.COM 			 */
2020*7836SJohn.Forte@Sun.COM 			if (g_enclDiskChk((char *)inq.inq_vid,
2021*7836SJohn.Forte@Sun.COM 				    (char *)inq.inq_pid)) {
2022*7836SJohn.Forte@Sun.COM 				if (err = load_flds_if_enc_disk(
2023*7836SJohn.Forte@Sun.COM 					    result, path_struct)) {
2024*7836SJohn.Forte@Sun.COM 					(void) free(result);
2025*7836SJohn.Forte@Sun.COM 					return (err);
2026*7836SJohn.Forte@Sun.COM 				}
2027*7836SJohn.Forte@Sun.COM 			}
2028*7836SJohn.Forte@Sun.COM 			goto done;
2029*7836SJohn.Forte@Sun.COM 		}
2030*7836SJohn.Forte@Sun.COM 	}
2031*7836SJohn.Forte@Sun.COM 
2032*7836SJohn.Forte@Sun.COM 	/*
2033*7836SJohn.Forte@Sun.COM 	 * Check to see if we have a box or WWN name.
2034*7836SJohn.Forte@Sun.COM 	 *
2035*7836SJohn.Forte@Sun.COM 	 * If it contains a , then the format must be
2036*7836SJohn.Forte@Sun.COM 	 *    box_name,f1 where f is front and 1 is the slot number
2037*7836SJohn.Forte@Sun.COM 	 * or it is a format like
2038*7836SJohn.Forte@Sun.COM 	 * ssd@w2200002037049adf,0:h,raw
2039*7836SJohn.Forte@Sun.COM 	 * or
2040*7836SJohn.Forte@Sun.COM 	 * SUNW,pln@a0000000,77791d:ctlr
2041*7836SJohn.Forte@Sun.COM 	 */
2042*7836SJohn.Forte@Sun.COM 	if (((char_ptr = strstr(tmp_name, ",")) != NULL) &&
2043*7836SJohn.Forte@Sun.COM 		((*(char_ptr + 1) == 'f') || (*(char_ptr + 1) == 'r') ||
2044*7836SJohn.Forte@Sun.COM 		    (*(char_ptr + 1) == 's'))) {
2045*7836SJohn.Forte@Sun.COM 		char_ptr++;	/* point to f/r */
2046*7836SJohn.Forte@Sun.COM 		if ((*char_ptr == 'f') || (*char_ptr == 's')) {
2047*7836SJohn.Forte@Sun.COM 			path_ptr->f_flag = 1;
2048*7836SJohn.Forte@Sun.COM 		} else if (*char_ptr != 'r') {
2049*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH_FORMAT);
2050*7836SJohn.Forte@Sun.COM 		}
2051*7836SJohn.Forte@Sun.COM 		save_frd = (char)*char_ptr;	/* save it */
2052*7836SJohn.Forte@Sun.COM 		char_ptr++;
2053*7836SJohn.Forte@Sun.COM 		slot = strtol(char_ptr, &ptr, 10);
2054*7836SJohn.Forte@Sun.COM 		/*
2055*7836SJohn.Forte@Sun.COM 		 * NOTE: Need to double check the slot when we get
2056*7836SJohn.Forte@Sun.COM 		 * the number of the devices actually in the box.
2057*7836SJohn.Forte@Sun.COM 		 */
2058*7836SJohn.Forte@Sun.COM 		if ((slot < 0) || (ptr == char_ptr) ||
2059*7836SJohn.Forte@Sun.COM 		    ((save_frd == 's' && slot >= MAX_DRIVES_DAK) ||
2060*7836SJohn.Forte@Sun.COM 		    ((save_frd != 's' && slot >= (MAX_DRIVES_PER_BOX/2))))) {
2061*7836SJohn.Forte@Sun.COM 			return (L_INVALID_SLOT);
2062*7836SJohn.Forte@Sun.COM 		}
2063*7836SJohn.Forte@Sun.COM 		/* Say slot valid. */
2064*7836SJohn.Forte@Sun.COM 		slot_flag = path_ptr->slot_valid = 1;
2065*7836SJohn.Forte@Sun.COM 		if (save_frd == 's' && slot >= (MAX_DRIVES_DAK/2)) {
2066*7836SJohn.Forte@Sun.COM 			path_ptr->slot = slot = slot % (MAX_DRIVES_DAK/2);
2067*7836SJohn.Forte@Sun.COM 			path_ptr->f_flag = 0;
2068*7836SJohn.Forte@Sun.COM 		} else
2069*7836SJohn.Forte@Sun.COM 			path_ptr->slot = slot;
2070*7836SJohn.Forte@Sun.COM 	}
2071*7836SJohn.Forte@Sun.COM 
2072*7836SJohn.Forte@Sun.COM 	if (((char_ptr = strstr(tmp_name, ",")) != NULL) &&
2073*7836SJohn.Forte@Sun.COM 		((*(char_ptr + 1) == 'f') || (*(char_ptr + 1) == 'r') ||
2074*7836SJohn.Forte@Sun.COM 		    (*(char_ptr + 1) == 's'))) {
2075*7836SJohn.Forte@Sun.COM 		*char_ptr = NULL; /* make just box name */
2076*7836SJohn.Forte@Sun.COM 		found_comma = 1;
2077*7836SJohn.Forte@Sun.COM 	}
2078*7836SJohn.Forte@Sun.COM 	/* Find path to IB */
2079*7836SJohn.Forte@Sun.COM 	if ((err = l_get_box_list(&box_list, verbose)) != 0) {
2080*7836SJohn.Forte@Sun.COM 		(void) l_free_box_list(&box_list);
2081*7836SJohn.Forte@Sun.COM 		return (err);
2082*7836SJohn.Forte@Sun.COM 	}
2083*7836SJohn.Forte@Sun.COM 	box_list_ptr = box_list;
2084*7836SJohn.Forte@Sun.COM 	/* Look for box name. */
2085*7836SJohn.Forte@Sun.COM 	while (box_list != NULL) {
2086*7836SJohn.Forte@Sun.COM 	    if ((strcmp((char *)tmp_name, (char *)box_list->b_name)) == 0) {
2087*7836SJohn.Forte@Sun.COM 			result =
2088*7836SJohn.Forte@Sun.COM 				g_alloc_string(box_list->b_physical_path);
2089*7836SJohn.Forte@Sun.COM 			L_DPRINTF("  l_convert_name:"
2090*7836SJohn.Forte@Sun.COM 			" Found subsystem: name %s  WWN %s\n",
2091*7836SJohn.Forte@Sun.COM 			box_list->b_name, box_list->b_node_wwn_s);
2092*7836SJohn.Forte@Sun.COM 			/*
2093*7836SJohn.Forte@Sun.COM 			 * Check for another box with this name.
2094*7836SJohn.Forte@Sun.COM 			 */
2095*7836SJohn.Forte@Sun.COM 			if (l_duplicate_names(box_list_ptr,
2096*7836SJohn.Forte@Sun.COM 				box_list->b_node_wwn_s,
2097*7836SJohn.Forte@Sun.COM 				(char *)box_list->b_name,
2098*7836SJohn.Forte@Sun.COM 				verbose)) {
2099*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&box_list_ptr);
2100*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(result);
2101*7836SJohn.Forte@Sun.COM 				return (L_DUPLICATE_ENCLOSURES);
2102*7836SJohn.Forte@Sun.COM 			}
2103*7836SJohn.Forte@Sun.COM 			found_box = 1;
2104*7836SJohn.Forte@Sun.COM 			break;
2105*7836SJohn.Forte@Sun.COM 		}
2106*7836SJohn.Forte@Sun.COM 		box_list = box_list->box_next;
2107*7836SJohn.Forte@Sun.COM 	}
2108*7836SJohn.Forte@Sun.COM 	/*
2109*7836SJohn.Forte@Sun.COM 	 * Check to see if we must get individual disks path.
2110*7836SJohn.Forte@Sun.COM 	 */
2111*7836SJohn.Forte@Sun.COM 
2112*7836SJohn.Forte@Sun.COM 	if (found_box && slot_flag) {
2113*7836SJohn.Forte@Sun.COM 		if ((l_state = (L_state *)g_zalloc(sizeof (L_state))) == NULL) {
2114*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(result);
2115*7836SJohn.Forte@Sun.COM 			(void) l_free_box_list(&box_list_ptr);
2116*7836SJohn.Forte@Sun.COM 			return (L_MALLOC_FAILED);
2117*7836SJohn.Forte@Sun.COM 		}
2118*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path, result);
2119*7836SJohn.Forte@Sun.COM 		if ((err = l_get_status(ses_path, l_state,
2120*7836SJohn.Forte@Sun.COM 			verbose)) != 0) {
2121*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(result);
2122*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(l_state);
2123*7836SJohn.Forte@Sun.COM 			(void) l_free_box_list(&box_list_ptr);
2124*7836SJohn.Forte@Sun.COM 			return (err);
2125*7836SJohn.Forte@Sun.COM 		}
2126*7836SJohn.Forte@Sun.COM 		/*
2127*7836SJohn.Forte@Sun.COM 		 * Now double check the slot number.
2128*7836SJohn.Forte@Sun.COM 		 */
2129*7836SJohn.Forte@Sun.COM 		if (slot >= l_state->total_num_drv/2) {
2130*7836SJohn.Forte@Sun.COM 			path_ptr->slot_valid = 0;
2131*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(result);
2132*7836SJohn.Forte@Sun.COM 			(void) l_free_box_list(&box_list_ptr);
2133*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
2134*7836SJohn.Forte@Sun.COM 			return (L_INVALID_SLOT);
2135*7836SJohn.Forte@Sun.COM 		}
2136*7836SJohn.Forte@Sun.COM 
2137*7836SJohn.Forte@Sun.COM 		/* Only allow the single slot version for Daktari */
2138*7836SJohn.Forte@Sun.COM 		if (g_get_inquiry(ses_path, &inq)) {
2139*7836SJohn.Forte@Sun.COM 		    return (L_SCSI_ERROR);
2140*7836SJohn.Forte@Sun.COM 		}
2141*7836SJohn.Forte@Sun.COM 		enc_type = l_get_enc_type(inq);
2142*7836SJohn.Forte@Sun.COM 		if (((enc_type == DAK_ENC_TYPE) && (save_frd != 's')) ||
2143*7836SJohn.Forte@Sun.COM 			((enc_type != DAK_ENC_TYPE) && (save_frd == 's'))) {
2144*7836SJohn.Forte@Sun.COM 			path_ptr->slot_valid = 0;
2145*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data(result);
2146*7836SJohn.Forte@Sun.COM 			(void) l_free_box_list(&box_list_ptr);
2147*7836SJohn.Forte@Sun.COM 			(void) l_free_lstate(&l_state);
2148*7836SJohn.Forte@Sun.COM 			return (L_INVALID_SLOT);
2149*7836SJohn.Forte@Sun.COM 		}
2150*7836SJohn.Forte@Sun.COM 
2151*7836SJohn.Forte@Sun.COM 		if (path_ptr->f_flag) {
2152*7836SJohn.Forte@Sun.COM 		if (*l_state->drv_front[slot].g_disk_state.physical_path) {
2153*7836SJohn.Forte@Sun.COM 				result =
2154*7836SJohn.Forte@Sun.COM 	g_alloc_string(l_state->drv_front[slot].g_disk_state.physical_path);
2155*7836SJohn.Forte@Sun.COM 			} else {
2156*7836SJohn.Forte@Sun.COM 				/* Result is the IB path */
2157*7836SJohn.Forte@Sun.COM 				path_ptr->ib_path_flag = 1;
2158*7836SJohn.Forte@Sun.COM 				path_ptr->p_physical_path =
2159*7836SJohn.Forte@Sun.COM 					g_alloc_string(result);
2160*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(result);
2161*7836SJohn.Forte@Sun.COM 				result = NULL;
2162*7836SJohn.Forte@Sun.COM 			}
2163*7836SJohn.Forte@Sun.COM 		} else {
2164*7836SJohn.Forte@Sun.COM 		if (*l_state->drv_rear[slot].g_disk_state.physical_path) {
2165*7836SJohn.Forte@Sun.COM 				result =
2166*7836SJohn.Forte@Sun.COM 	g_alloc_string(l_state->drv_rear[slot].g_disk_state.physical_path);
2167*7836SJohn.Forte@Sun.COM 			} else {
2168*7836SJohn.Forte@Sun.COM 				/* Result is the IB path */
2169*7836SJohn.Forte@Sun.COM 				path_ptr->ib_path_flag = 1;
2170*7836SJohn.Forte@Sun.COM 				path_ptr->p_physical_path =
2171*7836SJohn.Forte@Sun.COM 					g_alloc_string(result);
2172*7836SJohn.Forte@Sun.COM 				(void) g_destroy_data(result);
2173*7836SJohn.Forte@Sun.COM 				result = NULL;
2174*7836SJohn.Forte@Sun.COM 			}
2175*7836SJohn.Forte@Sun.COM 		}
2176*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&l_state);
2177*7836SJohn.Forte@Sun.COM 		goto done;
2178*7836SJohn.Forte@Sun.COM 	}
2179*7836SJohn.Forte@Sun.COM 	if (found_box || found_comma) {
2180*7836SJohn.Forte@Sun.COM 		goto done;
2181*7836SJohn.Forte@Sun.COM 	}
2182*7836SJohn.Forte@Sun.COM 	/*
2183*7836SJohn.Forte@Sun.COM 	 * No luck with the box name.
2184*7836SJohn.Forte@Sun.COM 	 *
2185*7836SJohn.Forte@Sun.COM 	 * Try WWN's
2186*7836SJohn.Forte@Sun.COM 	 */
2187*7836SJohn.Forte@Sun.COM 	/* Look for the SES's WWN */
2188*7836SJohn.Forte@Sun.COM 	box_list = box_list_ptr;
2189*7836SJohn.Forte@Sun.COM 	while (box_list != NULL) {
2190*7836SJohn.Forte@Sun.COM 		if (((strcasecmp((char *)tmp_name,
2191*7836SJohn.Forte@Sun.COM 			(char *)box_list->b_port_wwn_s)) == 0) ||
2192*7836SJohn.Forte@Sun.COM 			((strcasecmp((char *)tmp_name,
2193*7836SJohn.Forte@Sun.COM 			(char *)box_list->b_node_wwn_s)) == 0)) {
2194*7836SJohn.Forte@Sun.COM 				result =
2195*7836SJohn.Forte@Sun.COM 				g_alloc_string(box_list->b_physical_path);
2196*7836SJohn.Forte@Sun.COM 				L_DPRINTF("  l_convert_name:"
2197*7836SJohn.Forte@Sun.COM 				" Found subsystem using the WWN"
2198*7836SJohn.Forte@Sun.COM 				": name %s  WWN %s\n",
2199*7836SJohn.Forte@Sun.COM 				box_list->b_name, box_list->b_node_wwn_s);
2200*7836SJohn.Forte@Sun.COM 				goto done;
2201*7836SJohn.Forte@Sun.COM 		}
2202*7836SJohn.Forte@Sun.COM 		box_list = box_list->box_next;
2203*7836SJohn.Forte@Sun.COM 	}
2204*7836SJohn.Forte@Sun.COM 	/* Look for a device's WWN */
2205*7836SJohn.Forte@Sun.COM 	if (strlen(tmp_name) <= L_WWN_LENGTH) {
2206*7836SJohn.Forte@Sun.COM 		if ((err = g_get_wwn_list(&wwn_list, verbose)) != 0) {
2207*7836SJohn.Forte@Sun.COM 			(void) l_free_box_list(&box_list_ptr);
2208*7836SJohn.Forte@Sun.COM 			return (err);
2209*7836SJohn.Forte@Sun.COM 		}
2210*7836SJohn.Forte@Sun.COM 		for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
2211*7836SJohn.Forte@Sun.COM 				wwn_list_ptr = wwn_list_ptr->wwn_next) {
2212*7836SJohn.Forte@Sun.COM 			if (((strcasecmp((char *)tmp_name,
2213*7836SJohn.Forte@Sun.COM 				(char *)wwn_list_ptr->node_wwn_s)) == 0) ||
2214*7836SJohn.Forte@Sun.COM 				((strcasecmp((char *)tmp_name,
2215*7836SJohn.Forte@Sun.COM 				(char *)wwn_list_ptr->port_wwn_s)) == 0)) {
2216*7836SJohn.Forte@Sun.COM 			/*
2217*7836SJohn.Forte@Sun.COM 			 * Found the device's WWN in the global WWN list.
2218*7836SJohn.Forte@Sun.COM 			 * It MAY be in a photon/Daktari. If it is, we'll set
2219*7836SJohn.Forte@Sun.COM 			 * additional fields in path_struct.
2220*7836SJohn.Forte@Sun.COM 			 */
2221*7836SJohn.Forte@Sun.COM 			result = g_alloc_string(wwn_list_ptr->physical_path);
2222*7836SJohn.Forte@Sun.COM 			L_DPRINTF("  l_convert_name:"
2223*7836SJohn.Forte@Sun.COM 					"  Found device: WWN %s Path %s\n",
2224*7836SJohn.Forte@Sun.COM 					tmp_name, wwn_list_ptr->logical_path);
2225*7836SJohn.Forte@Sun.COM 
2226*7836SJohn.Forte@Sun.COM 			(void) g_free_wwn_list(&wwn_list);
2227*7836SJohn.Forte@Sun.COM 
2228*7836SJohn.Forte@Sun.COM 			/*
2229*7836SJohn.Forte@Sun.COM 			 * Now check if it is a disk in an A5K and set
2230*7836SJohn.Forte@Sun.COM 			 * path_struct fields
2231*7836SJohn.Forte@Sun.COM 			 */
2232*7836SJohn.Forte@Sun.COM 			path_ptr->p_physical_path = result;
2233*7836SJohn.Forte@Sun.COM 			if ((err = g_get_inquiry(result, &inq)) != 0) {
2234*7836SJohn.Forte@Sun.COM 				(void) free(result);
2235*7836SJohn.Forte@Sun.COM 				return (L_SCSI_ERROR);
2236*7836SJohn.Forte@Sun.COM 			}
2237*7836SJohn.Forte@Sun.COM 			/*
2238*7836SJohn.Forte@Sun.COM 			 * Check to see if it is a supported
2239*7836SJohn.Forte@Sun.COM 			 * A5K/v880/v890 storage subsystem disk
2240*7836SJohn.Forte@Sun.COM 			 */
2241*7836SJohn.Forte@Sun.COM 			if (g_enclDiskChk((char *)inq.inq_vid,
2242*7836SJohn.Forte@Sun.COM 				    (char *)inq.inq_pid)) {
2243*7836SJohn.Forte@Sun.COM 				if (err = load_flds_if_enc_disk(
2244*7836SJohn.Forte@Sun.COM 					    result, path_struct)) {
2245*7836SJohn.Forte@Sun.COM 					(void) free(result);
2246*7836SJohn.Forte@Sun.COM 					return (err);
2247*7836SJohn.Forte@Sun.COM 				}
2248*7836SJohn.Forte@Sun.COM 			}
2249*7836SJohn.Forte@Sun.COM 			goto done;
2250*7836SJohn.Forte@Sun.COM 		    }
2251*7836SJohn.Forte@Sun.COM 		}
2252*7836SJohn.Forte@Sun.COM 	}
2253*7836SJohn.Forte@Sun.COM 
2254*7836SJohn.Forte@Sun.COM 	/*
2255*7836SJohn.Forte@Sun.COM 	 * Try again in case we were in the /dev
2256*7836SJohn.Forte@Sun.COM 	 * or /devices directory.
2257*7836SJohn.Forte@Sun.COM 	 */
2258*7836SJohn.Forte@Sun.COM 	result = g_get_physical_name(name);
2259*7836SJohn.Forte@Sun.COM 
2260*7836SJohn.Forte@Sun.COM done:
2261*7836SJohn.Forte@Sun.COM 	(void) l_free_box_list(&box_list_ptr);
2262*7836SJohn.Forte@Sun.COM 	path_ptr->argv = name;
2263*7836SJohn.Forte@Sun.COM 	if (result == NULL) {
2264*7836SJohn.Forte@Sun.COM 		if (!path_ptr->ib_path_flag)
2265*7836SJohn.Forte@Sun.COM 			return (-1);
2266*7836SJohn.Forte@Sun.COM 	} else {
2267*7836SJohn.Forte@Sun.COM 		path_ptr->p_physical_path = result;
2268*7836SJohn.Forte@Sun.COM 	}
2269*7836SJohn.Forte@Sun.COM 
2270*7836SJohn.Forte@Sun.COM 	L_DPRINTF("  l_convert_name: path_struct:\n\tphysical_path:\n\t %s\n"
2271*7836SJohn.Forte@Sun.COM 		"\targv:\t\t%s"
2272*7836SJohn.Forte@Sun.COM 		"\n\tslot_valid\t%d"
2273*7836SJohn.Forte@Sun.COM 		"\n\tslot\t\t%d"
2274*7836SJohn.Forte@Sun.COM 		"\n\tf_flag\t\t%d"
2275*7836SJohn.Forte@Sun.COM 		"\n\tib_path_flag\t%d\n",
2276*7836SJohn.Forte@Sun.COM 		path_ptr->p_physical_path,
2277*7836SJohn.Forte@Sun.COM 		path_ptr->argv,
2278*7836SJohn.Forte@Sun.COM 		path_ptr->slot_valid,
2279*7836SJohn.Forte@Sun.COM 		path_ptr->slot,
2280*7836SJohn.Forte@Sun.COM 		path_ptr->f_flag,
2281*7836SJohn.Forte@Sun.COM 		path_ptr->ib_path_flag);
2282*7836SJohn.Forte@Sun.COM 	if (env != NULL) {
2283*7836SJohn.Forte@Sun.COM 		end_time = gethrtime();
2284*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "  l_convert_name: "
2285*7836SJohn.Forte@Sun.COM 		"Time = %lld millisec\n",
2286*7836SJohn.Forte@Sun.COM 		(end_time - start_time)/1000000);
2287*7836SJohn.Forte@Sun.COM 	}
2288*7836SJohn.Forte@Sun.COM 
2289*7836SJohn.Forte@Sun.COM 	if (path_ptr->ib_path_flag)
2290*7836SJohn.Forte@Sun.COM 		return (-1);
2291*7836SJohn.Forte@Sun.COM 	*phys_path = result;
2292*7836SJohn.Forte@Sun.COM 	return (0);
2293*7836SJohn.Forte@Sun.COM }
2294*7836SJohn.Forte@Sun.COM 
2295*7836SJohn.Forte@Sun.COM 
2296*7836SJohn.Forte@Sun.COM /*
2297*7836SJohn.Forte@Sun.COM  * Gets envsen information of an enclosure from IB
2298*7836SJohn.Forte@Sun.COM  *
2299*7836SJohn.Forte@Sun.COM  * RETURNS:
2300*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2301*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2302*7836SJohn.Forte@Sun.COM  */
2303*7836SJohn.Forte@Sun.COM int
l_get_envsen_page(int fd,uchar_t * buf,int buf_size,uchar_t page_code,int verbose)2304*7836SJohn.Forte@Sun.COM l_get_envsen_page(int fd, uchar_t *buf, int buf_size, uchar_t page_code,
2305*7836SJohn.Forte@Sun.COM 	int verbose)
2306*7836SJohn.Forte@Sun.COM {
2307*7836SJohn.Forte@Sun.COM Rec_diag_hdr	hdr;
2308*7836SJohn.Forte@Sun.COM uchar_t	*pg;
2309*7836SJohn.Forte@Sun.COM int	size, new_size, status;
2310*7836SJohn.Forte@Sun.COM 
2311*7836SJohn.Forte@Sun.COM 	if (buf == NULL) {
2312*7836SJohn.Forte@Sun.COM 		return (L_INVALID_BUF_LEN);
2313*7836SJohn.Forte@Sun.COM 	}
2314*7836SJohn.Forte@Sun.COM 
2315*7836SJohn.Forte@Sun.COM 	if (verbose) {
2316*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
2317*7836SJohn.Forte@Sun.COM 		MSGSTR(9046, "  Reading SES page %x\n"), page_code);
2318*7836SJohn.Forte@Sun.COM 	}
2319*7836SJohn.Forte@Sun.COM 
2320*7836SJohn.Forte@Sun.COM 	(void) memset(&hdr, 0, sizeof (struct rec_diag_hdr));
2321*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_rec_diag_cmd(fd, (uchar_t *)&hdr,
2322*7836SJohn.Forte@Sun.COM 		sizeof (struct rec_diag_hdr), page_code)) {
2323*7836SJohn.Forte@Sun.COM 		return (status);
2324*7836SJohn.Forte@Sun.COM 	}
2325*7836SJohn.Forte@Sun.COM 
2326*7836SJohn.Forte@Sun.COM 	/* Check */
2327*7836SJohn.Forte@Sun.COM 	if ((hdr.page_code != page_code) || (hdr.page_len == 0)) {
2328*7836SJohn.Forte@Sun.COM 		return (L_RD_PG_INVLD_CODE);
2329*7836SJohn.Forte@Sun.COM 	}
2330*7836SJohn.Forte@Sun.COM 	size = HEADER_LEN + hdr.page_len;
2331*7836SJohn.Forte@Sun.COM 	/*
2332*7836SJohn.Forte@Sun.COM 	 * Because of a hardware restriction in the soc+ chip
2333*7836SJohn.Forte@Sun.COM 	 * the transfers must be word aligned.
2334*7836SJohn.Forte@Sun.COM 	 */
2335*7836SJohn.Forte@Sun.COM 	while (size & 0x03) {
2336*7836SJohn.Forte@Sun.COM 		size++;
2337*7836SJohn.Forte@Sun.COM 		if (size > buf_size) {
2338*7836SJohn.Forte@Sun.COM 			return (L_RD_PG_MIN_BUFF);
2339*7836SJohn.Forte@Sun.COM 		}
2340*7836SJohn.Forte@Sun.COM 		P_DPRINTF("  l_get_envsen_page: Adjusting size of the "
2341*7836SJohn.Forte@Sun.COM 			"g_scsi_rec_diag_cmd buffer.\n");
2342*7836SJohn.Forte@Sun.COM 	}
2343*7836SJohn.Forte@Sun.COM 
2344*7836SJohn.Forte@Sun.COM 	if ((pg = (uchar_t *)g_zalloc(size)) == NULL) {
2345*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
2346*7836SJohn.Forte@Sun.COM 	}
2347*7836SJohn.Forte@Sun.COM 
2348*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  l_get_envsen_page: Reading page %x of size 0x%x\n",
2349*7836SJohn.Forte@Sun.COM 		page_code, size);
2350*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_rec_diag_cmd(fd, pg, size, page_code)) {
2351*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((char *)pg);
2352*7836SJohn.Forte@Sun.COM 		return (status);
2353*7836SJohn.Forte@Sun.COM 	}
2354*7836SJohn.Forte@Sun.COM 
2355*7836SJohn.Forte@Sun.COM 	new_size = MIN(size, buf_size);
2356*7836SJohn.Forte@Sun.COM 	bcopy((const void *)pg, (void *)buf, (size_t)new_size);
2357*7836SJohn.Forte@Sun.COM 
2358*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(pg);
2359*7836SJohn.Forte@Sun.COM 	return (0);
2360*7836SJohn.Forte@Sun.COM }
2361*7836SJohn.Forte@Sun.COM 
2362*7836SJohn.Forte@Sun.COM 
2363*7836SJohn.Forte@Sun.COM 
2364*7836SJohn.Forte@Sun.COM /*
2365*7836SJohn.Forte@Sun.COM  * Get consolidated copy of all environmental information
2366*7836SJohn.Forte@Sun.COM  * into buf structure.
2367*7836SJohn.Forte@Sun.COM  *
2368*7836SJohn.Forte@Sun.COM  * RETURNS:
2369*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2370*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2371*7836SJohn.Forte@Sun.COM  */
2372*7836SJohn.Forte@Sun.COM 
2373*7836SJohn.Forte@Sun.COM int
l_get_envsen(char * path_phys,uchar_t * buf,int size,int verbose)2374*7836SJohn.Forte@Sun.COM l_get_envsen(char *path_phys, uchar_t *buf, int size, int verbose)
2375*7836SJohn.Forte@Sun.COM {
2376*7836SJohn.Forte@Sun.COM int		fd, rval;
2377*7836SJohn.Forte@Sun.COM uchar_t		*page_list_ptr, page_code, *local_buf_ptr = buf;
2378*7836SJohn.Forte@Sun.COM Rec_diag_hdr	*hdr = (struct rec_diag_hdr *)(void *)buf;
2379*7836SJohn.Forte@Sun.COM ushort_t	num_pages;
2380*7836SJohn.Forte@Sun.COM 
2381*7836SJohn.Forte@Sun.COM 	if ((path_phys == NULL) || (buf == NULL)) {
2382*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
2383*7836SJohn.Forte@Sun.COM 	}
2384*7836SJohn.Forte@Sun.COM 
2385*7836SJohn.Forte@Sun.COM 	page_code = L_PAGE_PAGE_LIST;
2386*7836SJohn.Forte@Sun.COM 
2387*7836SJohn.Forte@Sun.COM 	/* open IB */
2388*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path_phys, O_NDELAY | O_RDONLY)) == -1)
2389*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
2390*7836SJohn.Forte@Sun.COM 
2391*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  l_get_envsen: Getting list of supported"
2392*7836SJohn.Forte@Sun.COM 		" pages from IB\n");
2393*7836SJohn.Forte@Sun.COM 	if (verbose) {
2394*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
2395*7836SJohn.Forte@Sun.COM 		MSGSTR(9047, "  Getting list of supported pages from IB\n"));
2396*7836SJohn.Forte@Sun.COM 	}
2397*7836SJohn.Forte@Sun.COM 
2398*7836SJohn.Forte@Sun.COM 	/* Get page 0 */
2399*7836SJohn.Forte@Sun.COM 	if ((rval = l_get_envsen_page(fd, local_buf_ptr,
2400*7836SJohn.Forte@Sun.COM 		size, page_code, verbose)) != NULL) {
2401*7836SJohn.Forte@Sun.COM 		(void) close(fd);
2402*7836SJohn.Forte@Sun.COM 		return (rval);
2403*7836SJohn.Forte@Sun.COM 	}
2404*7836SJohn.Forte@Sun.COM 
2405*7836SJohn.Forte@Sun.COM 	page_list_ptr = buf + HEADER_LEN + 1; /* +1 to skip page 0 */
2406*7836SJohn.Forte@Sun.COM 
2407*7836SJohn.Forte@Sun.COM 	num_pages = hdr->page_len - 1;
2408*7836SJohn.Forte@Sun.COM 
2409*7836SJohn.Forte@Sun.COM 	/*
2410*7836SJohn.Forte@Sun.COM 	 * check whether the number of pages received
2411*7836SJohn.Forte@Sun.COM 	 * from IB are valid. SENA enclosure
2412*7836SJohn.Forte@Sun.COM 	 * supports only 8 pages of sense information.
2413*7836SJohn.Forte@Sun.COM 	 * According to SES specification dpANS X3.xxx-1997
2414*7836SJohn.Forte@Sun.COM 	 * X3T10/Project 1212-D/Rev 8a, the enclosure supported
2415*7836SJohn.Forte@Sun.COM 	 * pages can go upto L_MAX_POSSIBLE_PAGES (0xFF).
2416*7836SJohn.Forte@Sun.COM 	 * Return an error if no. of pages exceeds L_MAX_POSSIBLE_PAGES.
2417*7836SJohn.Forte@Sun.COM 	 * See if (num_pages >= L_MAX_POSSIBLE_PAGES) since 1 page (page 0)
2418*7836SJohn.Forte@Sun.COM 	 * was already subtracted from the total number of pages before.
2419*7836SJohn.Forte@Sun.COM 	 */
2420*7836SJohn.Forte@Sun.COM 	if (num_pages < 1 || num_pages >= L_MAX_POSSIBLE_PAGES) {
2421*7836SJohn.Forte@Sun.COM 		return (L_INVALID_NO_OF_ENVSEN_PAGES);
2422*7836SJohn.Forte@Sun.COM 	}
2423*7836SJohn.Forte@Sun.COM 	/*
2424*7836SJohn.Forte@Sun.COM 	 * Buffer size of MAX_REC_DIAG_LENGTH can be small if the
2425*7836SJohn.Forte@Sun.COM 	 * number of pages exceed more than L_MAX_SENAIB_PAGES
2426*7836SJohn.Forte@Sun.COM 	 * but less than L_MAX_POSSIBLE_PAGES.
2427*7836SJohn.Forte@Sun.COM 	 */
2428*7836SJohn.Forte@Sun.COM 	if (size == MAX_REC_DIAG_LENGTH &&
2429*7836SJohn.Forte@Sun.COM 			num_pages >= L_MAX_SENAIB_PAGES) {
2430*7836SJohn.Forte@Sun.COM 		return (L_INVALID_BUF_LEN);
2431*7836SJohn.Forte@Sun.COM 	}
2432*7836SJohn.Forte@Sun.COM 	/* Align buffer */
2433*7836SJohn.Forte@Sun.COM 	while (hdr->page_len & 0x03) {
2434*7836SJohn.Forte@Sun.COM 		hdr->page_len++;
2435*7836SJohn.Forte@Sun.COM 	}
2436*7836SJohn.Forte@Sun.COM 	local_buf_ptr += HEADER_LEN + hdr->page_len;
2437*7836SJohn.Forte@Sun.COM 
2438*7836SJohn.Forte@Sun.COM 	/*
2439*7836SJohn.Forte@Sun.COM 	 * Getting all pages and appending to buf
2440*7836SJohn.Forte@Sun.COM 	 */
2441*7836SJohn.Forte@Sun.COM 	for (; num_pages--; page_list_ptr++) {
2442*7836SJohn.Forte@Sun.COM 		/*
2443*7836SJohn.Forte@Sun.COM 		 * The fifth byte of page 0 is the start
2444*7836SJohn.Forte@Sun.COM 		 * of the list of pages not including page 0.
2445*7836SJohn.Forte@Sun.COM 		 */
2446*7836SJohn.Forte@Sun.COM 		page_code = *page_list_ptr;
2447*7836SJohn.Forte@Sun.COM 
2448*7836SJohn.Forte@Sun.COM 		if ((rval = l_get_envsen_page(fd, local_buf_ptr,
2449*7836SJohn.Forte@Sun.COM 			size, page_code, verbose)) != NULL) {
2450*7836SJohn.Forte@Sun.COM 			(void) close(fd);
2451*7836SJohn.Forte@Sun.COM 			return (rval);
2452*7836SJohn.Forte@Sun.COM 		}
2453*7836SJohn.Forte@Sun.COM 		hdr = (struct rec_diag_hdr *)(void *)local_buf_ptr;
2454*7836SJohn.Forte@Sun.COM 		local_buf_ptr += HEADER_LEN + hdr->page_len;
2455*7836SJohn.Forte@Sun.COM 	}
2456*7836SJohn.Forte@Sun.COM 
2457*7836SJohn.Forte@Sun.COM 	(void) close(fd);
2458*7836SJohn.Forte@Sun.COM 	return (0);
2459*7836SJohn.Forte@Sun.COM }
2460*7836SJohn.Forte@Sun.COM 
2461*7836SJohn.Forte@Sun.COM 
2462*7836SJohn.Forte@Sun.COM 
2463*7836SJohn.Forte@Sun.COM /*
2464*7836SJohn.Forte@Sun.COM  * Get the individual disk status.
2465*7836SJohn.Forte@Sun.COM  * Path must be physical and point to a disk.
2466*7836SJohn.Forte@Sun.COM  *
2467*7836SJohn.Forte@Sun.COM  * This function updates the d_state_flags, port WWN's
2468*7836SJohn.Forte@Sun.COM  * and num_blocks for all accessiable ports
2469*7836SJohn.Forte@Sun.COM  * in l_disk_state->g_disk_state structure.
2470*7836SJohn.Forte@Sun.COM  *
2471*7836SJohn.Forte@Sun.COM  * RETURNS:
2472*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2473*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2474*7836SJohn.Forte@Sun.COM  */
2475*7836SJohn.Forte@Sun.COM int
l_get_disk_status(char * path,struct l_disk_state_struct * l_disk_state,WWN_list * wwn_list,int verbose)2476*7836SJohn.Forte@Sun.COM l_get_disk_status(char *path, struct l_disk_state_struct *l_disk_state,
2477*7836SJohn.Forte@Sun.COM 	WWN_list *wwn_list, int verbose)
2478*7836SJohn.Forte@Sun.COM {
2479*7836SJohn.Forte@Sun.COM struct dlist	*ml;
2480*7836SJohn.Forte@Sun.COM char		path_a[MAXPATHLEN], path_b[MAXPATHLEN], ses_path[MAXPATHLEN];
2481*7836SJohn.Forte@Sun.COM gfc_map_t	map;
2482*7836SJohn.Forte@Sun.COM int		path_a_found = 0, path_b_found = 0, local_port_a_flag;
2483*7836SJohn.Forte@Sun.COM uchar_t		node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
2484*7836SJohn.Forte@Sun.COM int		al_pa, err, pathcnt = 1;
2485*7836SJohn.Forte@Sun.COM int		i = 0;
2486*7836SJohn.Forte@Sun.COM char		temppath[MAXPATHLEN];
2487*7836SJohn.Forte@Sun.COM mp_pathlist_t	pathlist;
2488*7836SJohn.Forte@Sun.COM char		pwwn[WWN_S_LEN];
2489*7836SJohn.Forte@Sun.COM struct		stat sbuf;
2490*7836SJohn.Forte@Sun.COM 
2491*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (l_disk_state == NULL)) {
2492*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
2493*7836SJohn.Forte@Sun.COM 	}
2494*7836SJohn.Forte@Sun.COM 
2495*7836SJohn.Forte@Sun.COM 	/* Check device name */
2496*7836SJohn.Forte@Sun.COM 	if (stat(path, &sbuf) || (sbuf.st_rdev == NODEV)) {
2497*7836SJohn.Forte@Sun.COM 		G_DPRINTF("  l_get_disk_status: invalid device %s\n", path);
2498*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH);
2499*7836SJohn.Forte@Sun.COM 	}
2500*7836SJohn.Forte@Sun.COM 
2501*7836SJohn.Forte@Sun.COM 	/* Initialize */
2502*7836SJohn.Forte@Sun.COM 	*path_a = *path_b = NULL;
2503*7836SJohn.Forte@Sun.COM 	l_disk_state->g_disk_state.num_blocks = 0;
2504*7836SJohn.Forte@Sun.COM 
2505*7836SJohn.Forte@Sun.COM 	/* Get paths. */
2506*7836SJohn.Forte@Sun.COM 	g_get_multipath(path,
2507*7836SJohn.Forte@Sun.COM 		&(l_disk_state->g_disk_state.multipath_list),
2508*7836SJohn.Forte@Sun.COM 		wwn_list, verbose);
2509*7836SJohn.Forte@Sun.COM 	ml = l_disk_state->g_disk_state.multipath_list;
2510*7836SJohn.Forte@Sun.COM 	if (ml == NULL) {
2511*7836SJohn.Forte@Sun.COM 		l_disk_state->l_state_flag = L_NO_PATH_FOUND;
2512*7836SJohn.Forte@Sun.COM 		G_DPRINTF("  l_get_disk_status: Error finding a "
2513*7836SJohn.Forte@Sun.COM 			"multipath to the disk.\n");
2514*7836SJohn.Forte@Sun.COM 		return (0);
2515*7836SJohn.Forte@Sun.COM 	}
2516*7836SJohn.Forte@Sun.COM 
2517*7836SJohn.Forte@Sun.COM 	if (strstr(path, SCSI_VHCI) != NULL) {
2518*7836SJohn.Forte@Sun.COM 		/*
2519*7836SJohn.Forte@Sun.COM 		 * It is an MPXIO Path
2520*7836SJohn.Forte@Sun.COM 		 */
2521*7836SJohn.Forte@Sun.COM 		(void) strcpy(temppath, path);
2522*7836SJohn.Forte@Sun.COM 		if (g_get_pathlist(temppath, &pathlist)) {
2523*7836SJohn.Forte@Sun.COM 			return (0);
2524*7836SJohn.Forte@Sun.COM 		}
2525*7836SJohn.Forte@Sun.COM 		pathcnt = pathlist.path_count;
2526*7836SJohn.Forte@Sun.COM 		for (i = 0; i < pathcnt; i++) {
2527*7836SJohn.Forte@Sun.COM 			/*
2528*7836SJohn.Forte@Sun.COM 			 * Skip inactive paths.
2529*7836SJohn.Forte@Sun.COM 			 * A path that is not in either
2530*7836SJohn.Forte@Sun.COM 			 * MDI_PATHINFO_STATE_ONLINE or
2531*7836SJohn.Forte@Sun.COM 			 * MDI_PATHINFO_STATE_STANDBY state is not
2532*7836SJohn.Forte@Sun.COM 			 * an active path.
2533*7836SJohn.Forte@Sun.COM 			 *
2534*7836SJohn.Forte@Sun.COM 			 * When a disk port is bypassed and mpxio is
2535*7836SJohn.Forte@Sun.COM 			 * enabled, the path_state for that path goes to the
2536*7836SJohn.Forte@Sun.COM 			 * offline state
2537*7836SJohn.Forte@Sun.COM 			 */
2538*7836SJohn.Forte@Sun.COM 			if (pathlist.path_info[i].path_state !=
2539*7836SJohn.Forte@Sun.COM 			    MDI_PATHINFO_STATE_ONLINE &&
2540*7836SJohn.Forte@Sun.COM 			    pathlist.path_info[i].path_state !=
2541*7836SJohn.Forte@Sun.COM 			    MDI_PATHINFO_STATE_STANDBY) {
2542*7836SJohn.Forte@Sun.COM 				continue;
2543*7836SJohn.Forte@Sun.COM 			}
2544*7836SJohn.Forte@Sun.COM 			(void) strncpy(pwwn, pathlist.path_info[i].path_addr,
2545*7836SJohn.Forte@Sun.COM 								L_WWN_LENGTH);
2546*7836SJohn.Forte@Sun.COM 			pwwn[L_WWN_LENGTH] = '\0';
2547*7836SJohn.Forte@Sun.COM 			if (!(path_a_found || path_b_found)) {
2548*7836SJohn.Forte@Sun.COM 				if (pwwn[1] == '1') {
2549*7836SJohn.Forte@Sun.COM 					local_port_a_flag = 1;
2550*7836SJohn.Forte@Sun.COM 				} else {
2551*7836SJohn.Forte@Sun.COM 					local_port_a_flag = 0;
2552*7836SJohn.Forte@Sun.COM 				}
2553*7836SJohn.Forte@Sun.COM 			} else if (path_a_found &&
2554*7836SJohn.Forte@Sun.COM 				(strstr(l_disk_state->g_disk_state.port_a_wwn_s,
2555*7836SJohn.Forte@Sun.COM 							pwwn) == NULL)) {
2556*7836SJohn.Forte@Sun.COM 				/* do port b */
2557*7836SJohn.Forte@Sun.COM 				local_port_a_flag = 0;
2558*7836SJohn.Forte@Sun.COM 			} else if (path_b_found &&
2559*7836SJohn.Forte@Sun.COM 				(strstr(l_disk_state->g_disk_state.port_b_wwn_s,
2560*7836SJohn.Forte@Sun.COM 							pwwn) == NULL)) {
2561*7836SJohn.Forte@Sun.COM 				/* do port a */
2562*7836SJohn.Forte@Sun.COM 				local_port_a_flag = 1;
2563*7836SJohn.Forte@Sun.COM 			}
2564*7836SJohn.Forte@Sun.COM 
2565*7836SJohn.Forte@Sun.COM 			if (err = l_get_disk_port_status(path,
2566*7836SJohn.Forte@Sun.COM 				l_disk_state, local_port_a_flag, verbose)) {
2567*7836SJohn.Forte@Sun.COM 				return (err);
2568*7836SJohn.Forte@Sun.COM 			}
2569*7836SJohn.Forte@Sun.COM 
2570*7836SJohn.Forte@Sun.COM 			if (local_port_a_flag && (!path_a_found)) {
2571*7836SJohn.Forte@Sun.COM 				(void) strcpy(l_disk_state->
2572*7836SJohn.Forte@Sun.COM 					g_disk_state.port_a_wwn_s, pwwn);
2573*7836SJohn.Forte@Sun.COM 				l_disk_state->g_disk_state.port_a_valid++;
2574*7836SJohn.Forte@Sun.COM 				path_a_found++;
2575*7836SJohn.Forte@Sun.COM 			}
2576*7836SJohn.Forte@Sun.COM 
2577*7836SJohn.Forte@Sun.COM 			if ((!local_port_a_flag) && (!path_b_found)) {
2578*7836SJohn.Forte@Sun.COM 				(void) strcpy(l_disk_state->
2579*7836SJohn.Forte@Sun.COM 					g_disk_state.port_b_wwn_s, pwwn);
2580*7836SJohn.Forte@Sun.COM 				l_disk_state->g_disk_state.port_b_valid++;
2581*7836SJohn.Forte@Sun.COM 				path_b_found++;
2582*7836SJohn.Forte@Sun.COM 			}
2583*7836SJohn.Forte@Sun.COM 		}
2584*7836SJohn.Forte@Sun.COM 		free(pathlist.path_info);
2585*7836SJohn.Forte@Sun.COM 		return (0);
2586*7836SJohn.Forte@Sun.COM 	}
2587*7836SJohn.Forte@Sun.COM 
2588*7836SJohn.Forte@Sun.COM 	while (ml && (!(path_a_found && path_b_found))) {
2589*7836SJohn.Forte@Sun.COM 		if (err = g_get_dev_map(ml->dev_path, &map, verbose)) {
2590*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(ml);
2591*7836SJohn.Forte@Sun.COM 			return (err);
2592*7836SJohn.Forte@Sun.COM 		}
2593*7836SJohn.Forte@Sun.COM 		if ((err = l_get_ses_path(ml->dev_path, ses_path,
2594*7836SJohn.Forte@Sun.COM 			&map, verbose)) != 0) {
2595*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(ml);
2596*7836SJohn.Forte@Sun.COM 			free((void *)map.dev_addr);
2597*7836SJohn.Forte@Sun.COM 			return (err);
2598*7836SJohn.Forte@Sun.COM 		}
2599*7836SJohn.Forte@Sun.COM 		free((void *)map.dev_addr);	/* Not used anymore */
2600*7836SJohn.Forte@Sun.COM 
2601*7836SJohn.Forte@Sun.COM 		/*
2602*7836SJohn.Forte@Sun.COM 		 * Get the port, A or B, of the disk,
2603*7836SJohn.Forte@Sun.COM 		 * by passing the IB path.
2604*7836SJohn.Forte@Sun.COM 		 */
2605*7836SJohn.Forte@Sun.COM 		if (err = l_get_port(ses_path, &local_port_a_flag, verbose)) {
2606*7836SJohn.Forte@Sun.COM 			(void) g_free_multipath(ml);
2607*7836SJohn.Forte@Sun.COM 			return (err);
2608*7836SJohn.Forte@Sun.COM 		}
2609*7836SJohn.Forte@Sun.COM 		if (local_port_a_flag && (!path_a_found)) {
2610*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_disk_status: Path to Port A "
2611*7836SJohn.Forte@Sun.COM 				"found: %s\n", ml->dev_path);
2612*7836SJohn.Forte@Sun.COM 			if (err = l_get_disk_port_status(ml->dev_path,
2613*7836SJohn.Forte@Sun.COM 				l_disk_state, local_port_a_flag, verbose)) {
2614*7836SJohn.Forte@Sun.COM 				(void) g_free_multipath(ml);
2615*7836SJohn.Forte@Sun.COM 				return (err);
2616*7836SJohn.Forte@Sun.COM 			}
2617*7836SJohn.Forte@Sun.COM 			if (err = g_get_wwn(ml->dev_path,
2618*7836SJohn.Forte@Sun.COM 				port_wwn, node_wwn,
2619*7836SJohn.Forte@Sun.COM 				&al_pa, verbose)) {
2620*7836SJohn.Forte@Sun.COM 				(void) g_free_multipath(ml);
2621*7836SJohn.Forte@Sun.COM 				return (err);
2622*7836SJohn.Forte@Sun.COM 			}
2623*7836SJohn.Forte@Sun.COM 			(void) sprintf(l_disk_state->g_disk_state.port_a_wwn_s,
2624*7836SJohn.Forte@Sun.COM 			"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
2625*7836SJohn.Forte@Sun.COM 			port_wwn[0], port_wwn[1], port_wwn[2], port_wwn[3],
2626*7836SJohn.Forte@Sun.COM 			port_wwn[4], port_wwn[5], port_wwn[6], port_wwn[7]);
2627*7836SJohn.Forte@Sun.COM 
2628*7836SJohn.Forte@Sun.COM 			l_disk_state->g_disk_state.port_a_valid++;
2629*7836SJohn.Forte@Sun.COM 			path_a_found++;
2630*7836SJohn.Forte@Sun.COM 		}
2631*7836SJohn.Forte@Sun.COM 		if ((!local_port_a_flag) && (!path_b_found)) {
2632*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_disk_status: Path to Port B "
2633*7836SJohn.Forte@Sun.COM 				"found: %s\n", ml->dev_path);
2634*7836SJohn.Forte@Sun.COM 			if (err = l_get_disk_port_status(ml->dev_path,
2635*7836SJohn.Forte@Sun.COM 				l_disk_state, local_port_a_flag, verbose)) {
2636*7836SJohn.Forte@Sun.COM 				return (err);
2637*7836SJohn.Forte@Sun.COM 			}
2638*7836SJohn.Forte@Sun.COM 			if (err = g_get_wwn(ml->dev_path,
2639*7836SJohn.Forte@Sun.COM 				port_wwn, node_wwn,
2640*7836SJohn.Forte@Sun.COM 				&al_pa, verbose)) {
2641*7836SJohn.Forte@Sun.COM 				(void) g_free_multipath(ml);
2642*7836SJohn.Forte@Sun.COM 				return (err);
2643*7836SJohn.Forte@Sun.COM 			}
2644*7836SJohn.Forte@Sun.COM 			(void) sprintf(l_disk_state->g_disk_state.port_b_wwn_s,
2645*7836SJohn.Forte@Sun.COM 			"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
2646*7836SJohn.Forte@Sun.COM 			port_wwn[0], port_wwn[1], port_wwn[2], port_wwn[3],
2647*7836SJohn.Forte@Sun.COM 			port_wwn[4], port_wwn[5], port_wwn[6], port_wwn[7]);
2648*7836SJohn.Forte@Sun.COM 
2649*7836SJohn.Forte@Sun.COM 			l_disk_state->g_disk_state.port_b_valid++;
2650*7836SJohn.Forte@Sun.COM 			path_b_found++;
2651*7836SJohn.Forte@Sun.COM 		}
2652*7836SJohn.Forte@Sun.COM 		ml = ml->next;
2653*7836SJohn.Forte@Sun.COM 	}
2654*7836SJohn.Forte@Sun.COM 	return (0);
2655*7836SJohn.Forte@Sun.COM 
2656*7836SJohn.Forte@Sun.COM 
2657*7836SJohn.Forte@Sun.COM }
2658*7836SJohn.Forte@Sun.COM 
2659*7836SJohn.Forte@Sun.COM 
2660*7836SJohn.Forte@Sun.COM 
2661*7836SJohn.Forte@Sun.COM /*
2662*7836SJohn.Forte@Sun.COM  * Check for Persistent Reservations.
2663*7836SJohn.Forte@Sun.COM  */
2664*7836SJohn.Forte@Sun.COM int
l_persistent_check(int fd,struct l_disk_state_struct * l_disk_state,int verbose)2665*7836SJohn.Forte@Sun.COM l_persistent_check(int fd, struct l_disk_state_struct *l_disk_state,
2666*7836SJohn.Forte@Sun.COM 	int verbose)
2667*7836SJohn.Forte@Sun.COM {
2668*7836SJohn.Forte@Sun.COM int	status;
2669*7836SJohn.Forte@Sun.COM Read_keys	read_key_buf;
2670*7836SJohn.Forte@Sun.COM Read_reserv	read_reserv_buf;
2671*7836SJohn.Forte@Sun.COM 
2672*7836SJohn.Forte@Sun.COM 	(void) memset(&read_key_buf, 0, sizeof (struct  read_keys_struct));
2673*7836SJohn.Forte@Sun.COM 	if ((status = g_scsi_persistent_reserve_in_cmd(fd,
2674*7836SJohn.Forte@Sun.COM 		(uchar_t *)&read_key_buf, sizeof (struct  read_keys_struct),
2675*7836SJohn.Forte@Sun.COM 		ACTION_READ_KEYS))) {
2676*7836SJohn.Forte@Sun.COM 		return (status);
2677*7836SJohn.Forte@Sun.COM 	}
2678*7836SJohn.Forte@Sun.COM 	/* This means persistent reservations are supported by the disk. */
2679*7836SJohn.Forte@Sun.COM 	l_disk_state->g_disk_state.persistent_reserv_flag = 1;
2680*7836SJohn.Forte@Sun.COM 
2681*7836SJohn.Forte@Sun.COM 	if (read_key_buf.rk_length) {
2682*7836SJohn.Forte@Sun.COM 		l_disk_state->g_disk_state.persistent_registered = 1;
2683*7836SJohn.Forte@Sun.COM 	}
2684*7836SJohn.Forte@Sun.COM 
2685*7836SJohn.Forte@Sun.COM 	(void) memset(&read_reserv_buf, 0,
2686*7836SJohn.Forte@Sun.COM 			sizeof (struct  read_reserv_struct));
2687*7836SJohn.Forte@Sun.COM 	if ((status = g_scsi_persistent_reserve_in_cmd(fd,
2688*7836SJohn.Forte@Sun.COM 		(uchar_t *)&read_reserv_buf,
2689*7836SJohn.Forte@Sun.COM 		sizeof (struct  read_reserv_struct),
2690*7836SJohn.Forte@Sun.COM 		ACTION_READ_RESERV))) {
2691*7836SJohn.Forte@Sun.COM 		return (status);
2692*7836SJohn.Forte@Sun.COM 	}
2693*7836SJohn.Forte@Sun.COM 	if (read_reserv_buf.rr_length) {
2694*7836SJohn.Forte@Sun.COM 		l_disk_state->g_disk_state.persistent_active = 1;
2695*7836SJohn.Forte@Sun.COM 	}
2696*7836SJohn.Forte@Sun.COM 	if (verbose) {
2697*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
2698*7836SJohn.Forte@Sun.COM 		MSGSTR(9048, "  Checking for Persistent "
2699*7836SJohn.Forte@Sun.COM 			"Reservations:"));
2700*7836SJohn.Forte@Sun.COM 		if (l_disk_state->g_disk_state.persistent_reserv_flag) {
2701*7836SJohn.Forte@Sun.COM 		    if (l_disk_state->g_disk_state.persistent_active != NULL) {
2702*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, MSGSTR(39, "Active"));
2703*7836SJohn.Forte@Sun.COM 		    } else {
2704*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout, MSGSTR(9049, "Registered"));
2705*7836SJohn.Forte@Sun.COM 		    }
2706*7836SJohn.Forte@Sun.COM 		} else {
2707*7836SJohn.Forte@Sun.COM 			(void) fprintf(stdout,
2708*7836SJohn.Forte@Sun.COM 			MSGSTR(87,
2709*7836SJohn.Forte@Sun.COM 			"Not being used"));
2710*7836SJohn.Forte@Sun.COM 		}
2711*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "\n");
2712*7836SJohn.Forte@Sun.COM 	}
2713*7836SJohn.Forte@Sun.COM 	return (0);
2714*7836SJohn.Forte@Sun.COM }
2715*7836SJohn.Forte@Sun.COM 
2716*7836SJohn.Forte@Sun.COM 
2717*7836SJohn.Forte@Sun.COM 
2718*7836SJohn.Forte@Sun.COM /*
2719*7836SJohn.Forte@Sun.COM  * Gets the disk status and
2720*7836SJohn.Forte@Sun.COM  * updates the l_disk_state_struct structure.
2721*7836SJohn.Forte@Sun.COM  * Checks for open fail, Reservation Conflicts,
2722*7836SJohn.Forte@Sun.COM  * Not Ready and so on.
2723*7836SJohn.Forte@Sun.COM  *
2724*7836SJohn.Forte@Sun.COM  * RETURNS:
2725*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2726*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2727*7836SJohn.Forte@Sun.COM  */
2728*7836SJohn.Forte@Sun.COM int
l_get_disk_port_status(char * path,struct l_disk_state_struct * l_disk_state,int port_a_flag,int verbose)2729*7836SJohn.Forte@Sun.COM l_get_disk_port_status(char *path, struct l_disk_state_struct *l_disk_state,
2730*7836SJohn.Forte@Sun.COM 	int port_a_flag, int verbose)
2731*7836SJohn.Forte@Sun.COM {
2732*7836SJohn.Forte@Sun.COM int		fd, status = 0, local_state = 0;
2733*7836SJohn.Forte@Sun.COM Read_capacity_data	capacity;	/* local read capacity buffer */
2734*7836SJohn.Forte@Sun.COM struct vtoc	vtoc;
2735*7836SJohn.Forte@Sun.COM 
2736*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (l_disk_state == NULL)) {
2737*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
2738*7836SJohn.Forte@Sun.COM 	}
2739*7836SJohn.Forte@Sun.COM 
2740*7836SJohn.Forte@Sun.COM 	/*
2741*7836SJohn.Forte@Sun.COM 	 * Try to open drive.
2742*7836SJohn.Forte@Sun.COM 	 */
2743*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path, O_RDONLY)) == -1) {
2744*7836SJohn.Forte@Sun.COM 	    if ((fd = g_object_open(path,
2745*7836SJohn.Forte@Sun.COM 		O_RDONLY | O_NDELAY)) == -1) {
2746*7836SJohn.Forte@Sun.COM 		G_DPRINTF("  l_get_disk_port_status: Error "
2747*7836SJohn.Forte@Sun.COM 			"opening drive %s\n", path);
2748*7836SJohn.Forte@Sun.COM 		local_state = L_OPEN_FAIL;
2749*7836SJohn.Forte@Sun.COM 	    } else {
2750*7836SJohn.Forte@Sun.COM 		/* See if drive ready */
2751*7836SJohn.Forte@Sun.COM 		if (status = g_scsi_tur(fd)) {
2752*7836SJohn.Forte@Sun.COM 			if ((status & L_SCSI_ERROR) &&
2753*7836SJohn.Forte@Sun.COM 				((status & ~L_SCSI_ERROR) == STATUS_CHECK)) {
2754*7836SJohn.Forte@Sun.COM 				/*
2755*7836SJohn.Forte@Sun.COM 				 * TBD
2756*7836SJohn.Forte@Sun.COM 				 * This is where I should figure out
2757*7836SJohn.Forte@Sun.COM 				 * if the device is Not Ready or whatever.
2758*7836SJohn.Forte@Sun.COM 				 */
2759*7836SJohn.Forte@Sun.COM 				local_state = L_NOT_READY;
2760*7836SJohn.Forte@Sun.COM 			} else if ((status & L_SCSI_ERROR) &&
2761*7836SJohn.Forte@Sun.COM 			    ((status & ~L_SCSI_ERROR) ==
2762*7836SJohn.Forte@Sun.COM 			    STATUS_RESERVATION_CONFLICT)) {
2763*7836SJohn.Forte@Sun.COM 			    /* mark reserved */
2764*7836SJohn.Forte@Sun.COM 			    local_state = L_RESERVED;
2765*7836SJohn.Forte@Sun.COM 			} else {
2766*7836SJohn.Forte@Sun.COM 				local_state = L_SCSI_ERR;
2767*7836SJohn.Forte@Sun.COM 			}
2768*7836SJohn.Forte@Sun.COM 
2769*7836SJohn.Forte@Sun.COM 		/*
2770*7836SJohn.Forte@Sun.COM 		 * There may not be a label on the drive - check
2771*7836SJohn.Forte@Sun.COM 		 */
2772*7836SJohn.Forte@Sun.COM 		} else if (ioctl(fd, DKIOCGVTOC, &vtoc) == 0) {
2773*7836SJohn.Forte@Sun.COM 			/*
2774*7836SJohn.Forte@Sun.COM 			 * Sanity-check the vtoc
2775*7836SJohn.Forte@Sun.COM 			 */
2776*7836SJohn.Forte@Sun.COM 		    if (vtoc.v_sanity != VTOC_SANE ||
2777*7836SJohn.Forte@Sun.COM 			vtoc.v_sectorsz != DEV_BSIZE) {
2778*7836SJohn.Forte@Sun.COM 			local_state = L_NO_LABEL;
2779*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_disk_port_status: "
2780*7836SJohn.Forte@Sun.COM 				"Checking vtoc - No Label found.\n");
2781*7836SJohn.Forte@Sun.COM 		    }
2782*7836SJohn.Forte@Sun.COM 		} else if (errno != ENOTSUP) {
2783*7836SJohn.Forte@Sun.COM 		    I_DPRINTF("\t- DKIOCGVTOC ioctl failed: "
2784*7836SJohn.Forte@Sun.COM 		    " invalid geometry\n");
2785*7836SJohn.Forte@Sun.COM 		    local_state = L_NO_LABEL;
2786*7836SJohn.Forte@Sun.COM 		}
2787*7836SJohn.Forte@Sun.COM 	    }
2788*7836SJohn.Forte@Sun.COM 	}
2789*7836SJohn.Forte@Sun.COM 	/*
2790*7836SJohn.Forte@Sun.COM 	 * Need an extra check for tape devices
2791*7836SJohn.Forte@Sun.COM 	 * read capacity should not be run on tape devices.
2792*7836SJohn.Forte@Sun.COM 	 * It will always return Not Readable
2793*7836SJohn.Forte@Sun.COM 	 */
2794*7836SJohn.Forte@Sun.COM 	if (((local_state == 0) || (local_state == L_NO_LABEL)) &&
2795*7836SJohn.Forte@Sun.COM 		! (strstr(path, SLSH_DRV_NAME_ST))) {
2796*7836SJohn.Forte@Sun.COM 
2797*7836SJohn.Forte@Sun.COM 	    if (status = g_scsi_read_capacity_cmd(fd, (uchar_t *)&capacity,
2798*7836SJohn.Forte@Sun.COM 		sizeof (capacity))) {
2799*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_disk_port_status: "
2800*7836SJohn.Forte@Sun.COM 				"Read Capacity failed.\n");
2801*7836SJohn.Forte@Sun.COM 		if (status & L_SCSI_ERROR) {
2802*7836SJohn.Forte@Sun.COM 		    if ((status & ~L_SCSI_ERROR) ==
2803*7836SJohn.Forte@Sun.COM 			STATUS_RESERVATION_CONFLICT) {
2804*7836SJohn.Forte@Sun.COM 			/* mark reserved */
2805*7836SJohn.Forte@Sun.COM 			local_state |= L_RESERVED;
2806*7836SJohn.Forte@Sun.COM 		    } else
2807*7836SJohn.Forte@Sun.COM 			/* mark bad */
2808*7836SJohn.Forte@Sun.COM 			local_state |= L_NOT_READABLE;
2809*7836SJohn.Forte@Sun.COM 		} else {
2810*7836SJohn.Forte@Sun.COM 			/*
2811*7836SJohn.Forte@Sun.COM 			 * TBD
2812*7836SJohn.Forte@Sun.COM 			 * Need a more complete state definition here.
2813*7836SJohn.Forte@Sun.COM 			 */
2814*7836SJohn.Forte@Sun.COM 			l_disk_state->g_disk_state.d_state_flags[port_a_flag] =
2815*7836SJohn.Forte@Sun.COM 								L_SCSI_ERR;
2816*7836SJohn.Forte@Sun.COM 			(void) close(fd);
2817*7836SJohn.Forte@Sun.COM 			return (0);
2818*7836SJohn.Forte@Sun.COM 		}
2819*7836SJohn.Forte@Sun.COM 	    } else {
2820*7836SJohn.Forte@Sun.COM 		/* save capacity */
2821*7836SJohn.Forte@Sun.COM 		l_disk_state->g_disk_state.num_blocks =
2822*7836SJohn.Forte@Sun.COM 					capacity.last_block_addr + 1;
2823*7836SJohn.Forte@Sun.COM 	    }
2824*7836SJohn.Forte@Sun.COM 
2825*7836SJohn.Forte@Sun.COM 	}
2826*7836SJohn.Forte@Sun.COM 	(void) close(fd);
2827*7836SJohn.Forte@Sun.COM 
2828*7836SJohn.Forte@Sun.COM 	l_disk_state->g_disk_state.d_state_flags[port_a_flag] = local_state;
2829*7836SJohn.Forte@Sun.COM 	G_DPRINTF("  l_get_disk_port_status: Individual Disk"
2830*7836SJohn.Forte@Sun.COM 		" Status: 0x%x for"
2831*7836SJohn.Forte@Sun.COM 		" port %s for path:"
2832*7836SJohn.Forte@Sun.COM 		" %s\n", local_state,
2833*7836SJohn.Forte@Sun.COM 		port_a_flag ? "A" : "B", path);
2834*7836SJohn.Forte@Sun.COM 
2835*7836SJohn.Forte@Sun.COM 	return (0);
2836*7836SJohn.Forte@Sun.COM }
2837*7836SJohn.Forte@Sun.COM 
2838*7836SJohn.Forte@Sun.COM 
2839*7836SJohn.Forte@Sun.COM 
2840*7836SJohn.Forte@Sun.COM /*
2841*7836SJohn.Forte@Sun.COM  * Copy and format page 1 from big buffer to state structure.
2842*7836SJohn.Forte@Sun.COM  *
2843*7836SJohn.Forte@Sun.COM  * RETURNS:
2844*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2845*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2846*7836SJohn.Forte@Sun.COM  */
2847*7836SJohn.Forte@Sun.COM 
2848*7836SJohn.Forte@Sun.COM static int
copy_config_page(struct l_state_struct * l_state,uchar_t * from_ptr)2849*7836SJohn.Forte@Sun.COM copy_config_page(struct l_state_struct *l_state, uchar_t *from_ptr)
2850*7836SJohn.Forte@Sun.COM {
2851*7836SJohn.Forte@Sun.COM IB_page_config	*encl_ptr;
2852*7836SJohn.Forte@Sun.COM int		size, i;
2853*7836SJohn.Forte@Sun.COM 
2854*7836SJohn.Forte@Sun.COM 
2855*7836SJohn.Forte@Sun.COM 	encl_ptr = (struct ib_page_config *)(void *)from_ptr;
2856*7836SJohn.Forte@Sun.COM 
2857*7836SJohn.Forte@Sun.COM 	/* Sanity check. */
2858*7836SJohn.Forte@Sun.COM 	if ((encl_ptr->enc_len > MAX_VEND_SPECIFIC_ENC) ||
2859*7836SJohn.Forte@Sun.COM 		(encl_ptr->enc_len == 0)) {
2860*7836SJohn.Forte@Sun.COM 		return (L_REC_DIAG_PG1);
2861*7836SJohn.Forte@Sun.COM 	}
2862*7836SJohn.Forte@Sun.COM 	if ((encl_ptr->enc_num_elem > MAX_IB_ELEMENTS) ||
2863*7836SJohn.Forte@Sun.COM 		(encl_ptr->enc_num_elem == 0)) {
2864*7836SJohn.Forte@Sun.COM 		return (L_REC_DIAG_PG1);
2865*7836SJohn.Forte@Sun.COM 	}
2866*7836SJohn.Forte@Sun.COM 
2867*7836SJohn.Forte@Sun.COM 	size = HEADER_LEN + 4 + HEADER_LEN + encl_ptr->enc_len;
2868*7836SJohn.Forte@Sun.COM 	bcopy((void *)(from_ptr),
2869*7836SJohn.Forte@Sun.COM 		(void *)&l_state->ib_tbl.config, (size_t)size);
2870*7836SJohn.Forte@Sun.COM 	/*
2871*7836SJohn.Forte@Sun.COM 	 * Copy Type Descriptors seperately to get aligned.
2872*7836SJohn.Forte@Sun.COM 	 */
2873*7836SJohn.Forte@Sun.COM 	from_ptr += size;
2874*7836SJohn.Forte@Sun.COM 	size = (sizeof (struct	type_desc_hdr))*encl_ptr->enc_num_elem;
2875*7836SJohn.Forte@Sun.COM 	bcopy((void *)(from_ptr),
2876*7836SJohn.Forte@Sun.COM 		(void *)&l_state->ib_tbl.config.type_hdr, (size_t)size);
2877*7836SJohn.Forte@Sun.COM 
2878*7836SJohn.Forte@Sun.COM 	/*
2879*7836SJohn.Forte@Sun.COM 	 * Copy Text Descriptors seperately to get aligned.
2880*7836SJohn.Forte@Sun.COM 	 *
2881*7836SJohn.Forte@Sun.COM 	 * Must use the text size from the Type Descriptors.
2882*7836SJohn.Forte@Sun.COM 	 */
2883*7836SJohn.Forte@Sun.COM 	from_ptr += size;
2884*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)l_state->ib_tbl.config.enc_num_elem; i++) {
2885*7836SJohn.Forte@Sun.COM 		size = l_state->ib_tbl.config.type_hdr[i].text_len;
2886*7836SJohn.Forte@Sun.COM 		bcopy((void *)(from_ptr),
2887*7836SJohn.Forte@Sun.COM 			(void *)&l_state->ib_tbl.config.text[i], (size_t)size);
2888*7836SJohn.Forte@Sun.COM 		from_ptr += size;
2889*7836SJohn.Forte@Sun.COM 	}
2890*7836SJohn.Forte@Sun.COM 	return (0);
2891*7836SJohn.Forte@Sun.COM }
2892*7836SJohn.Forte@Sun.COM 
2893*7836SJohn.Forte@Sun.COM 
2894*7836SJohn.Forte@Sun.COM 
2895*7836SJohn.Forte@Sun.COM /*
2896*7836SJohn.Forte@Sun.COM  * Copy page 7 (Element Descriptor page) to state structure.
2897*7836SJohn.Forte@Sun.COM  * Copy header then copy each element descriptor
2898*7836SJohn.Forte@Sun.COM  * seperately.
2899*7836SJohn.Forte@Sun.COM  *
2900*7836SJohn.Forte@Sun.COM  * RETURNS:
2901*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2902*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2903*7836SJohn.Forte@Sun.COM  */
2904*7836SJohn.Forte@Sun.COM static void
copy_page_7(struct l_state_struct * l_state,uchar_t * from_ptr)2905*7836SJohn.Forte@Sun.COM copy_page_7(struct l_state_struct *l_state, uchar_t *from_ptr)
2906*7836SJohn.Forte@Sun.COM {
2907*7836SJohn.Forte@Sun.COM uchar_t	*my_from_ptr;
2908*7836SJohn.Forte@Sun.COM int	size, j, k, p7_index;
2909*7836SJohn.Forte@Sun.COM 
2910*7836SJohn.Forte@Sun.COM 	size = HEADER_LEN +
2911*7836SJohn.Forte@Sun.COM 		sizeof (l_state->ib_tbl.p7_s.gen_code);
2912*7836SJohn.Forte@Sun.COM 	bcopy((void *)(from_ptr),
2913*7836SJohn.Forte@Sun.COM 		(void *)&l_state->ib_tbl.p7_s, (size_t)size);
2914*7836SJohn.Forte@Sun.COM 	my_from_ptr = from_ptr + size;
2915*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_D_DEBUG") != NULL) {
2916*7836SJohn.Forte@Sun.COM 		g_dump("  copy_page_7: Page 7 header:  ",
2917*7836SJohn.Forte@Sun.COM 		(uchar_t *)&l_state->ib_tbl.p7_s, size,
2918*7836SJohn.Forte@Sun.COM 		HEX_ASCII);
2919*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
2920*7836SJohn.Forte@Sun.COM 			"  copy_page_7: Elements being stored "
2921*7836SJohn.Forte@Sun.COM 			"in state table\n"
2922*7836SJohn.Forte@Sun.COM 			"              ");
2923*7836SJohn.Forte@Sun.COM 	}
2924*7836SJohn.Forte@Sun.COM 	/* I am assuming page 1 has been read. */
2925*7836SJohn.Forte@Sun.COM 	for (j = 0, p7_index = 0;
2926*7836SJohn.Forte@Sun.COM 		j < (int)l_state->ib_tbl.config.enc_num_elem; j++) {
2927*7836SJohn.Forte@Sun.COM 		/* Copy global element */
2928*7836SJohn.Forte@Sun.COM 		size = HEADER_LEN +
2929*7836SJohn.Forte@Sun.COM 			((*(my_from_ptr + 2) << 8) | *(my_from_ptr + 3));
2930*7836SJohn.Forte@Sun.COM 		bcopy((void *)(my_from_ptr),
2931*7836SJohn.Forte@Sun.COM 		(void *)&l_state->ib_tbl.p7_s.element_desc[p7_index++],
2932*7836SJohn.Forte@Sun.COM 			(size_t)size);
2933*7836SJohn.Forte@Sun.COM 		my_from_ptr += size;
2934*7836SJohn.Forte@Sun.COM 		for (k = 0; k < (int)l_state->ib_tbl.config.type_hdr[j].num;
2935*7836SJohn.Forte@Sun.COM 			k++) {
2936*7836SJohn.Forte@Sun.COM 			/* Copy individual elements */
2937*7836SJohn.Forte@Sun.COM 			size = HEADER_LEN +
2938*7836SJohn.Forte@Sun.COM 				((*(my_from_ptr + 2) << 8) |
2939*7836SJohn.Forte@Sun.COM 					*(my_from_ptr + 3));
2940*7836SJohn.Forte@Sun.COM 			bcopy((void *)(my_from_ptr),
2941*7836SJohn.Forte@Sun.COM 			(void *)&l_state->ib_tbl.p7_s.element_desc[p7_index++],
2942*7836SJohn.Forte@Sun.COM 				(size_t)size);
2943*7836SJohn.Forte@Sun.COM 			my_from_ptr += size;
2944*7836SJohn.Forte@Sun.COM 			D_DPRINTF(".");
2945*7836SJohn.Forte@Sun.COM 		}
2946*7836SJohn.Forte@Sun.COM 	}
2947*7836SJohn.Forte@Sun.COM 	D_DPRINTF("\n");
2948*7836SJohn.Forte@Sun.COM }
2949*7836SJohn.Forte@Sun.COM 
2950*7836SJohn.Forte@Sun.COM 
2951*7836SJohn.Forte@Sun.COM /*
2952*7836SJohn.Forte@Sun.COM  * Gets IB diagnostic pages on a given pathname from l_get_envsen().
2953*7836SJohn.Forte@Sun.COM  * It also fills up the individual device element of l_state_struct using
2954*7836SJohn.Forte@Sun.COM  * diagnostics pages.
2955*7836SJohn.Forte@Sun.COM  * Gets IB diagnostic pages on a given pathname from l_get_envsen().
2956*7836SJohn.Forte@Sun.COM  * It also fills up the individual device element of l_state_struct using
2957*7836SJohn.Forte@Sun.COM  * diagnostics pages.
2958*7836SJohn.Forte@Sun.COM  *
2959*7836SJohn.Forte@Sun.COM  * The path must be of the ses driver.
2960*7836SJohn.Forte@Sun.COM  * e.g.
2961*7836SJohn.Forte@Sun.COM  * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
2962*7836SJohn.Forte@Sun.COM  * or
2963*7836SJohn.Forte@Sun.COM  * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@WWN,0:0
2964*7836SJohn.Forte@Sun.COM  *
2965*7836SJohn.Forte@Sun.COM  *
2966*7836SJohn.Forte@Sun.COM  * RETURNS:
2967*7836SJohn.Forte@Sun.COM  *	0	 O.K.
2968*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
2969*7836SJohn.Forte@Sun.COM  */
2970*7836SJohn.Forte@Sun.COM int
l_get_ib_status(char * path,struct l_state_struct * l_state,int verbose)2971*7836SJohn.Forte@Sun.COM l_get_ib_status(char *path, struct l_state_struct *l_state,
2972*7836SJohn.Forte@Sun.COM 	int verbose)
2973*7836SJohn.Forte@Sun.COM {
2974*7836SJohn.Forte@Sun.COM L_inquiry	inq;
2975*7836SJohn.Forte@Sun.COM uchar_t		*ib_buf, *from_ptr;
2976*7836SJohn.Forte@Sun.COM int		num_pages, i, size, err;
2977*7836SJohn.Forte@Sun.COM IB_page_2	*encl_ptr;
2978*7836SJohn.Forte@Sun.COM int		front_index, rear_index;
2979*7836SJohn.Forte@Sun.COM int		enc_type = 0;
2980*7836SJohn.Forte@Sun.COM 
2981*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (l_state == NULL)) {
2982*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
2983*7836SJohn.Forte@Sun.COM 	}
2984*7836SJohn.Forte@Sun.COM 
2985*7836SJohn.Forte@Sun.COM 	/*
2986*7836SJohn.Forte@Sun.COM 	 * get big buffer
2987*7836SJohn.Forte@Sun.COM 	 */
2988*7836SJohn.Forte@Sun.COM 	if ((ib_buf = (uchar_t *)calloc(1,
2989*7836SJohn.Forte@Sun.COM 				MAX_REC_DIAG_LENGTH)) == NULL) {
2990*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
2991*7836SJohn.Forte@Sun.COM 	}
2992*7836SJohn.Forte@Sun.COM 
2993*7836SJohn.Forte@Sun.COM 	/*
2994*7836SJohn.Forte@Sun.COM 	 * Get IB information
2995*7836SJohn.Forte@Sun.COM 	 * Even if there are 2 IB's in this box on this loop don't bother
2996*7836SJohn.Forte@Sun.COM 	 * talking to the other one as both IB's in a box
2997*7836SJohn.Forte@Sun.COM 	 * are supposed to report the same information.
2998*7836SJohn.Forte@Sun.COM 	 */
2999*7836SJohn.Forte@Sun.COM 	if (err = l_get_envsen(path, ib_buf, MAX_REC_DIAG_LENGTH,
3000*7836SJohn.Forte@Sun.COM 		verbose)) {
3001*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(ib_buf);
3002*7836SJohn.Forte@Sun.COM 		return (err);
3003*7836SJohn.Forte@Sun.COM 	}
3004*7836SJohn.Forte@Sun.COM 
3005*7836SJohn.Forte@Sun.COM 	/*
3006*7836SJohn.Forte@Sun.COM 	 * Set up state structure
3007*7836SJohn.Forte@Sun.COM 	 */
3008*7836SJohn.Forte@Sun.COM 	bcopy((void *)ib_buf, (void *)&l_state->ib_tbl.p0,
3009*7836SJohn.Forte@Sun.COM 		(size_t)sizeof (struct  ib_page_0));
3010*7836SJohn.Forte@Sun.COM 
3011*7836SJohn.Forte@Sun.COM 	num_pages = l_state->ib_tbl.p0.page_len;
3012*7836SJohn.Forte@Sun.COM 	from_ptr = ib_buf + HEADER_LEN + l_state->ib_tbl.p0.page_len;
3013*7836SJohn.Forte@Sun.COM 
3014*7836SJohn.Forte@Sun.COM 	for (i = 1; i < num_pages; i++) {
3015*7836SJohn.Forte@Sun.COM 		if (l_state->ib_tbl.p0.sup_page_codes[i] == L_PAGE_1) {
3016*7836SJohn.Forte@Sun.COM 			if (err = copy_config_page(l_state, from_ptr)) {
3017*7836SJohn.Forte@Sun.COM 				return (err);
3018*7836SJohn.Forte@Sun.COM 			}
3019*7836SJohn.Forte@Sun.COM 		} else if (l_state->ib_tbl.p0.sup_page_codes[i] ==
3020*7836SJohn.Forte@Sun.COM 								L_PAGE_2) {
3021*7836SJohn.Forte@Sun.COM 			encl_ptr = (struct ib_page_2 *)(void *)from_ptr;
3022*7836SJohn.Forte@Sun.COM 			size = HEADER_LEN + encl_ptr->page_len;
3023*7836SJohn.Forte@Sun.COM 			bcopy((void *)(from_ptr),
3024*7836SJohn.Forte@Sun.COM 				(void *)&l_state->ib_tbl.p2_s, (size_t)size);
3025*7836SJohn.Forte@Sun.COM 			if (getenv("_LUX_D_DEBUG") != NULL) {
3026*7836SJohn.Forte@Sun.COM 				g_dump("  l_get_ib_status: Page 2:  ",
3027*7836SJohn.Forte@Sun.COM 				(uchar_t *)&l_state->ib_tbl.p2_s, size,
3028*7836SJohn.Forte@Sun.COM 				HEX_ONLY);
3029*7836SJohn.Forte@Sun.COM 			}
3030*7836SJohn.Forte@Sun.COM 
3031*7836SJohn.Forte@Sun.COM 		} else if (l_state->ib_tbl.p0.sup_page_codes[i] ==
3032*7836SJohn.Forte@Sun.COM 								L_PAGE_7) {
3033*7836SJohn.Forte@Sun.COM 			(void) copy_page_7(l_state, from_ptr);
3034*7836SJohn.Forte@Sun.COM 		}
3035*7836SJohn.Forte@Sun.COM 		from_ptr += ((*(from_ptr + 2) << 8) | *(from_ptr + 3));
3036*7836SJohn.Forte@Sun.COM 		from_ptr += HEADER_LEN;
3037*7836SJohn.Forte@Sun.COM 	}
3038*7836SJohn.Forte@Sun.COM 	(void) g_destroy_data(ib_buf);
3039*7836SJohn.Forte@Sun.COM 	G_DPRINTF("  l_get_ib_status: Read %d Receive Diagnostic pages "
3040*7836SJohn.Forte@Sun.COM 		"from the IB.\n", num_pages);
3041*7836SJohn.Forte@Sun.COM 
3042*7836SJohn.Forte@Sun.COM 	if (err = g_get_inquiry(path, &inq)) {
3043*7836SJohn.Forte@Sun.COM 		return (err);
3044*7836SJohn.Forte@Sun.COM 	}
3045*7836SJohn.Forte@Sun.COM 	enc_type = l_get_enc_type(inq);
3046*7836SJohn.Forte@Sun.COM 	/*
3047*7836SJohn.Forte@Sun.COM 	 * Get the total number of drives per box.
3048*7836SJohn.Forte@Sun.COM 	 * This assumes front & rear are the same.
3049*7836SJohn.Forte@Sun.COM 	 */
3050*7836SJohn.Forte@Sun.COM 	l_state->total_num_drv = 0; /* default to use as a flag */
3051*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)l_state->ib_tbl.config.enc_num_elem; i++) {
3052*7836SJohn.Forte@Sun.COM 		if (l_state->ib_tbl.config.type_hdr[i].type == ELM_TYP_DD) {
3053*7836SJohn.Forte@Sun.COM 			if (l_state->total_num_drv) {
3054*7836SJohn.Forte@Sun.COM 				if (l_state->total_num_drv !=
3055*7836SJohn.Forte@Sun.COM 				(l_state->ib_tbl.config.type_hdr[i].num * 2)) {
3056*7836SJohn.Forte@Sun.COM 					return (L_INVALID_NUM_DISKS_ENCL);
3057*7836SJohn.Forte@Sun.COM 				}
3058*7836SJohn.Forte@Sun.COM 			} else {
3059*7836SJohn.Forte@Sun.COM 				if (enc_type == DAK_ENC_TYPE) {
3060*7836SJohn.Forte@Sun.COM 				    l_state->total_num_drv =
3061*7836SJohn.Forte@Sun.COM 				    l_state->ib_tbl.config.type_hdr[i].num;
3062*7836SJohn.Forte@Sun.COM 				} else {
3063*7836SJohn.Forte@Sun.COM 				    l_state->total_num_drv =
3064*7836SJohn.Forte@Sun.COM 				    l_state->ib_tbl.config.type_hdr[i].num * 2;
3065*7836SJohn.Forte@Sun.COM 				}
3066*7836SJohn.Forte@Sun.COM 			}
3067*7836SJohn.Forte@Sun.COM 		}
3068*7836SJohn.Forte@Sun.COM 	}
3069*7836SJohn.Forte@Sun.COM 
3070*7836SJohn.Forte@Sun.COM 	/*
3071*7836SJohn.Forte@Sun.COM 	 * transfer the individual drive Device Element information
3072*7836SJohn.Forte@Sun.COM 	 * from IB state to drive state.
3073*7836SJohn.Forte@Sun.COM 	 */
3074*7836SJohn.Forte@Sun.COM 	if (err = l_get_disk_element_index(l_state, &front_index,
3075*7836SJohn.Forte@Sun.COM 		&rear_index)) {
3076*7836SJohn.Forte@Sun.COM 		return (err);
3077*7836SJohn.Forte@Sun.COM 	}
3078*7836SJohn.Forte@Sun.COM 	/* Skip global element */
3079*7836SJohn.Forte@Sun.COM 	front_index++;
3080*7836SJohn.Forte@Sun.COM 	if (enc_type == DAK_ENC_TYPE) {
3081*7836SJohn.Forte@Sun.COM 		rear_index += l_state->total_num_drv/2 + 1;
3082*7836SJohn.Forte@Sun.COM 	} else {
3083*7836SJohn.Forte@Sun.COM 		rear_index++;
3084*7836SJohn.Forte@Sun.COM 	}
3085*7836SJohn.Forte@Sun.COM 
3086*7836SJohn.Forte@Sun.COM 	for (i = 0; i < l_state->total_num_drv/2; i++) {
3087*7836SJohn.Forte@Sun.COM 		bcopy((void *)&l_state->ib_tbl.p2_s.element[front_index + i],
3088*7836SJohn.Forte@Sun.COM 			(void *)&l_state->drv_front[i].ib_status,
3089*7836SJohn.Forte@Sun.COM 			(size_t)sizeof (struct device_element));
3090*7836SJohn.Forte@Sun.COM 		bcopy((void *)&l_state->ib_tbl.p2_s.element[rear_index + i],
3091*7836SJohn.Forte@Sun.COM 			(void *)&l_state->drv_rear[i].ib_status,
3092*7836SJohn.Forte@Sun.COM 			(size_t)sizeof (struct device_element));
3093*7836SJohn.Forte@Sun.COM 	}
3094*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_G_DEBUG") != NULL) {
3095*7836SJohn.Forte@Sun.COM 		g_dump("  l_get_ib_status: disk elements:  ",
3096*7836SJohn.Forte@Sun.COM 		(uchar_t *)&l_state->ib_tbl.p2_s.element[front_index],
3097*7836SJohn.Forte@Sun.COM 		((sizeof (struct device_element)) * (l_state->total_num_drv)),
3098*7836SJohn.Forte@Sun.COM 		HEX_ONLY);
3099*7836SJohn.Forte@Sun.COM 	}
3100*7836SJohn.Forte@Sun.COM 
3101*7836SJohn.Forte@Sun.COM 	return (0);
3102*7836SJohn.Forte@Sun.COM }
3103*7836SJohn.Forte@Sun.COM 
3104*7836SJohn.Forte@Sun.COM 
3105*7836SJohn.Forte@Sun.COM 
3106*7836SJohn.Forte@Sun.COM /*
3107*7836SJohn.Forte@Sun.COM  * Given an IB path get the port, A or B.
3108*7836SJohn.Forte@Sun.COM  *
3109*7836SJohn.Forte@Sun.COM  * OUTPUT:
3110*7836SJohn.Forte@Sun.COM  *	port_a:	sets to 1 for port A
3111*7836SJohn.Forte@Sun.COM  *		and 0 for port B.
3112*7836SJohn.Forte@Sun.COM  * RETURNS:
3113*7836SJohn.Forte@Sun.COM  *	err:	0 O.k.
3114*7836SJohn.Forte@Sun.COM  *		non-zero otherwise
3115*7836SJohn.Forte@Sun.COM  */
3116*7836SJohn.Forte@Sun.COM int
l_get_port(char * ses_path,int * port_a,int verbose)3117*7836SJohn.Forte@Sun.COM l_get_port(char *ses_path, int *port_a, int verbose)
3118*7836SJohn.Forte@Sun.COM {
3119*7836SJohn.Forte@Sun.COM L_state	*ib_state = NULL;
3120*7836SJohn.Forte@Sun.COM Ctlr_elem_st	ctlr;
3121*7836SJohn.Forte@Sun.COM int	i, err, elem_index = 0;
3122*7836SJohn.Forte@Sun.COM 
3123*7836SJohn.Forte@Sun.COM 	if ((ses_path == NULL) || (port_a == NULL)) {
3124*7836SJohn.Forte@Sun.COM 		return (L_NO_SES_PATH);
3125*7836SJohn.Forte@Sun.COM 	}
3126*7836SJohn.Forte@Sun.COM 
3127*7836SJohn.Forte@Sun.COM 	if ((ib_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
3128*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
3129*7836SJohn.Forte@Sun.COM 	}
3130*7836SJohn.Forte@Sun.COM 
3131*7836SJohn.Forte@Sun.COM 	bzero(&ctlr, sizeof (ctlr));
3132*7836SJohn.Forte@Sun.COM 	if (err = l_get_ib_status(ses_path, ib_state, verbose)) {
3133*7836SJohn.Forte@Sun.COM 		(void) l_free_lstate(&ib_state);
3134*7836SJohn.Forte@Sun.COM 		return (err);
3135*7836SJohn.Forte@Sun.COM 	}
3136*7836SJohn.Forte@Sun.COM 
3137*7836SJohn.Forte@Sun.COM 	for (i = 0; i < (int)ib_state->ib_tbl.config.enc_num_elem; i++) {
3138*7836SJohn.Forte@Sun.COM 	    elem_index++;		/* skip global */
3139*7836SJohn.Forte@Sun.COM 	    if (ib_state->ib_tbl.config.type_hdr[i].type == ELM_TYP_IB) {
3140*7836SJohn.Forte@Sun.COM 		bcopy((const void *)
3141*7836SJohn.Forte@Sun.COM 			&ib_state->ib_tbl.p2_s.element[elem_index],
3142*7836SJohn.Forte@Sun.COM 			(void *)&ctlr, sizeof (ctlr));
3143*7836SJohn.Forte@Sun.COM 		break;
3144*7836SJohn.Forte@Sun.COM 	    }
3145*7836SJohn.Forte@Sun.COM 	    elem_index += ib_state->ib_tbl.config.type_hdr[i].num;
3146*7836SJohn.Forte@Sun.COM 	}
3147*7836SJohn.Forte@Sun.COM 	*port_a = ctlr.report;
3148*7836SJohn.Forte@Sun.COM 	G_DPRINTF("  l_get_port: Found ses is the %s card.\n",
3149*7836SJohn.Forte@Sun.COM 		ctlr.report ? "A" : "B");
3150*7836SJohn.Forte@Sun.COM 	(void) l_free_lstate(&ib_state);
3151*7836SJohn.Forte@Sun.COM 	return (0);
3152*7836SJohn.Forte@Sun.COM }
3153*7836SJohn.Forte@Sun.COM 
3154*7836SJohn.Forte@Sun.COM /*
3155*7836SJohn.Forte@Sun.COM  * This function expects a pointer to a device path ending in the form
3156*7836SJohn.Forte@Sun.COM  * .../ses@w<NODEWWN>,<something> or .../ssd@w<NODEWWN>,<something>
3157*7836SJohn.Forte@Sun.COM  *
3158*7836SJohn.Forte@Sun.COM  * No validity checking of the path is done by the function.
3159*7836SJohn.Forte@Sun.COM  *
3160*7836SJohn.Forte@Sun.COM  * It gets the wwn (node wwn) out of the passed string, searches the passed
3161*7836SJohn.Forte@Sun.COM  * map for a match, gets the corresponding phys addr (port id) for that entry
3162*7836SJohn.Forte@Sun.COM  * and stores in the pointer the caller has passed as an argument (pid)
3163*7836SJohn.Forte@Sun.COM  *
3164*7836SJohn.Forte@Sun.COM  * This function is to be called only for public/fabric topologies
3165*7836SJohn.Forte@Sun.COM  *
3166*7836SJohn.Forte@Sun.COM  * If this interface is going to get exported, one point to be
3167*7836SJohn.Forte@Sun.COM  * considered is if a call to g_get_path_type() has to be made.
3168*7836SJohn.Forte@Sun.COM  *
3169*7836SJohn.Forte@Sun.COM  * INPUT:
3170*7836SJohn.Forte@Sun.COM  * path - pointer to the enclosure/disk device path
3171*7836SJohn.Forte@Sun.COM  * map - pointer to the map
3172*7836SJohn.Forte@Sun.COM  *
3173*7836SJohn.Forte@Sun.COM  * OUTPUT:
3174*7836SJohn.Forte@Sun.COM  * pid - the physical address associated for the node WWN that was found
3175*7836SJohn.Forte@Sun.COM  *       in the map
3176*7836SJohn.Forte@Sun.COM  *
3177*7836SJohn.Forte@Sun.COM  * RETURNS:
3178*7836SJohn.Forte@Sun.COM  * 0 - on success
3179*7836SJohn.Forte@Sun.COM  * non-zero - otherwise
3180*7836SJohn.Forte@Sun.COM  */
3181*7836SJohn.Forte@Sun.COM int
l_get_pid_from_path(const char * path,const gfc_map_t * map,int * pid)3182*7836SJohn.Forte@Sun.COM l_get_pid_from_path(const char *path, const gfc_map_t *map, int *pid)
3183*7836SJohn.Forte@Sun.COM {
3184*7836SJohn.Forte@Sun.COM int			i;
3185*7836SJohn.Forte@Sun.COM unsigned long long	ll_wwn;
3186*7836SJohn.Forte@Sun.COM char			*char_ptr, wwn_str[WWN_SIZE * 2 + 1];
3187*7836SJohn.Forte@Sun.COM char			*byte_ptr, *temp_ptr;
3188*7836SJohn.Forte@Sun.COM gfc_port_dev_info_t	*dev_addr_ptr;
3189*7836SJohn.Forte@Sun.COM mp_pathlist_t		pathlist;
3190*7836SJohn.Forte@Sun.COM char			path0[MAXPATHLEN], pwwn0[WWN_S_LEN];
3191*7836SJohn.Forte@Sun.COM 
3192*7836SJohn.Forte@Sun.COM 	/* if mpxio device */
3193*7836SJohn.Forte@Sun.COM 	if (strstr(path, SCSI_VHCI) != NULL) {
3194*7836SJohn.Forte@Sun.COM 		(void) strcpy(path0, path);
3195*7836SJohn.Forte@Sun.COM 		if (g_get_pathlist(path0, &pathlist)) {
3196*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH);
3197*7836SJohn.Forte@Sun.COM 		} else {
3198*7836SJohn.Forte@Sun.COM 			(void) strncpy(pwwn0, pathlist.path_info[0].
3199*7836SJohn.Forte@Sun.COM 				path_addr, L_WWN_LENGTH);
3200*7836SJohn.Forte@Sun.COM 			pwwn0[L_WWN_LENGTH] = '\0';
3201*7836SJohn.Forte@Sun.COM 			free(pathlist.path_info);
3202*7836SJohn.Forte@Sun.COM 			char_ptr = pwwn0;
3203*7836SJohn.Forte@Sun.COM 		}
3204*7836SJohn.Forte@Sun.COM 	} else {
3205*7836SJohn.Forte@Sun.COM 		/* First a quick check on the path */
3206*7836SJohn.Forte@Sun.COM 		if (((char_ptr = strrchr(path, '@')) == NULL) ||
3207*7836SJohn.Forte@Sun.COM 					(*++char_ptr != 'w')) {
3208*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH);
3209*7836SJohn.Forte@Sun.COM 		} else {
3210*7836SJohn.Forte@Sun.COM 			char_ptr++;
3211*7836SJohn.Forte@Sun.COM 		}
3212*7836SJohn.Forte@Sun.COM 	}
3213*7836SJohn.Forte@Sun.COM 
3214*7836SJohn.Forte@Sun.COM 	if (strlen(char_ptr) < (WWN_SIZE * 2)) {
3215*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH);
3216*7836SJohn.Forte@Sun.COM 	}
3217*7836SJohn.Forte@Sun.COM 	(void) strncpy(wwn_str, char_ptr, WWN_SIZE * 2);
3218*7836SJohn.Forte@Sun.COM 	wwn_str[WWN_SIZE * 2] = '\0';
3219*7836SJohn.Forte@Sun.COM 	errno = 0;	/* For error checking */
3220*7836SJohn.Forte@Sun.COM 	ll_wwn = strtoull(wwn_str, &temp_ptr, L_WWN_LENGTH);
3221*7836SJohn.Forte@Sun.COM 
3222*7836SJohn.Forte@Sun.COM 	if (errno || (temp_ptr != (wwn_str + (WWN_SIZE * 2)))) {
3223*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH);
3224*7836SJohn.Forte@Sun.COM 	}
3225*7836SJohn.Forte@Sun.COM 
3226*7836SJohn.Forte@Sun.COM 	byte_ptr = (char *)&ll_wwn;
3227*7836SJohn.Forte@Sun.COM 
3228*7836SJohn.Forte@Sun.COM 	/*
3229*7836SJohn.Forte@Sun.COM 	 * Search for the ses's node wwn in map to get the area and
3230*7836SJohn.Forte@Sun.COM 	 * domain ids from the corresponding port id (phys address).
3231*7836SJohn.Forte@Sun.COM 	 */
3232*7836SJohn.Forte@Sun.COM 	for (dev_addr_ptr = map->dev_addr, i = 0; i < map->count;
3233*7836SJohn.Forte@Sun.COM 						dev_addr_ptr++, i++) {
3234*7836SJohn.Forte@Sun.COM 		if (bcmp((char *)dev_addr_ptr->gfc_port_dev.
3235*7836SJohn.Forte@Sun.COM 			pub_port.dev_nwwn.raw_wwn, byte_ptr, WWN_SIZE) == 0)
3236*7836SJohn.Forte@Sun.COM 			break;
3237*7836SJohn.Forte@Sun.COM 	}
3238*7836SJohn.Forte@Sun.COM 	if (i >= map->count)
3239*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH);
3240*7836SJohn.Forte@Sun.COM 	*pid = dev_addr_ptr->gfc_port_dev.pub_port.dev_did.port_id;
3241*7836SJohn.Forte@Sun.COM 	return (0);
3242*7836SJohn.Forte@Sun.COM }
3243*7836SJohn.Forte@Sun.COM 
3244*7836SJohn.Forte@Sun.COM 
3245*7836SJohn.Forte@Sun.COM /*
3246*7836SJohn.Forte@Sun.COM  * Finds the disk's node wwn string, and
3247*7836SJohn.Forte@Sun.COM  * port A and B's WWNs and their port status.
3248*7836SJohn.Forte@Sun.COM  *
3249*7836SJohn.Forte@Sun.COM  * INPUT:
3250*7836SJohn.Forte@Sun.COM  * path		- pointer to a ses path
3251*7836SJohn.Forte@Sun.COM  * wwn_list	- pointer to the wwn_list
3252*7836SJohn.Forte@Sun.COM  *
3253*7836SJohn.Forte@Sun.COM  * OUTPUT:
3254*7836SJohn.Forte@Sun.COM  * state	- node_wwn and wwn of ports A & B of disk, etc are inited
3255*7836SJohn.Forte@Sun.COM  *		- by l_get_disk_status()
3256*7836SJohn.Forte@Sun.COM  * found_flag	- incremented after each examined element in the map
3257*7836SJohn.Forte@Sun.COM  *
3258*7836SJohn.Forte@Sun.COM  * RETURNS:
3259*7836SJohn.Forte@Sun.COM  *	0	 O.K.
3260*7836SJohn.Forte@Sun.COM  *	non-zero otherwise.
3261*7836SJohn.Forte@Sun.COM  */
3262*7836SJohn.Forte@Sun.COM static int
l_get_node_status(char * path,struct l_disk_state_struct * state,int * found_flag,WWN_list * wwn_list,int verbose)3263*7836SJohn.Forte@Sun.COM l_get_node_status(char *path, struct l_disk_state_struct *state,
3264*7836SJohn.Forte@Sun.COM 	int *found_flag, WWN_list *wwn_list, int verbose)
3265*7836SJohn.Forte@Sun.COM {
3266*7836SJohn.Forte@Sun.COM int		j, select_id, err;
3267*7836SJohn.Forte@Sun.COM int		path_pid;
3268*7836SJohn.Forte@Sun.COM char		temp_path[MAXPATHLEN];
3269*7836SJohn.Forte@Sun.COM char		sbuf[MAXPATHLEN], *char_ptr;
3270*7836SJohn.Forte@Sun.COM gfc_map_mp_t	*map_mp, *map_ptr;
3271*7836SJohn.Forte@Sun.COM struct stat	stat_buf;
3272*7836SJohn.Forte@Sun.COM WWN_list	*wwnlp;
3273*7836SJohn.Forte@Sun.COM char		wwnp[WWN_S_LEN];
3274*7836SJohn.Forte@Sun.COM 
3275*7836SJohn.Forte@Sun.COM 	/*
3276*7836SJohn.Forte@Sun.COM 	 * Get a new map.
3277*7836SJohn.Forte@Sun.COM 	 */
3278*7836SJohn.Forte@Sun.COM 	map_mp = NULL;
3279*7836SJohn.Forte@Sun.COM 	if (err = get_mp_dev_map(path, &map_mp, verbose))
3280*7836SJohn.Forte@Sun.COM 		return (err);
3281*7836SJohn.Forte@Sun.COM 
3282*7836SJohn.Forte@Sun.COM 	for (map_ptr = map_mp; map_ptr != NULL; map_ptr = map_ptr->map_next) {
3283*7836SJohn.Forte@Sun.COM 	    switch (map_ptr->map.hba_addr.port_topology) {
3284*7836SJohn.Forte@Sun.COM 		case FC_TOP_PRIVATE_LOOP:
3285*7836SJohn.Forte@Sun.COM 		    for (j = 0; j < map_ptr->map.count; j++) {
3286*7836SJohn.Forte@Sun.COM 			/*
3287*7836SJohn.Forte@Sun.COM 			 * Get a generic path to a device
3288*7836SJohn.Forte@Sun.COM 			 *
3289*7836SJohn.Forte@Sun.COM 			 * This assumes the path looks something like this
3290*7836SJohn.Forte@Sun.COM 			 * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/...
3291*7836SJohn.Forte@Sun.COM 			 *					...ses@x,0:0
3292*7836SJohn.Forte@Sun.COM 			 * then creates a path that looks like
3293*7836SJohn.Forte@Sun.COM 			 * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ssd@
3294*7836SJohn.Forte@Sun.COM 			 */
3295*7836SJohn.Forte@Sun.COM 			(void) strcpy(temp_path, path);
3296*7836SJohn.Forte@Sun.COM 			if ((char_ptr = strrchr(temp_path, '/')) == NULL) {
3297*7836SJohn.Forte@Sun.COM 				free_mp_dev_map(&map_mp);
3298*7836SJohn.Forte@Sun.COM 				return (L_INVALID_PATH);
3299*7836SJohn.Forte@Sun.COM 			}
3300*7836SJohn.Forte@Sun.COM 			*char_ptr = '\0';   /* Terminate sting  */
3301*7836SJohn.Forte@Sun.COM 			(void) strcat(temp_path, SLSH_DRV_NAME_SSD);
3302*7836SJohn.Forte@Sun.COM 			/*
3303*7836SJohn.Forte@Sun.COM 			 * Create complete path.
3304*7836SJohn.Forte@Sun.COM 			 *
3305*7836SJohn.Forte@Sun.COM 			 * Build entry ssd@xx,0:c,raw
3306*7836SJohn.Forte@Sun.COM 			 * where xx is the WWN.
3307*7836SJohn.Forte@Sun.COM 			 */
3308*7836SJohn.Forte@Sun.COM 			select_id = g_sf_alpa_to_switch[map_ptr->map.
3309*7836SJohn.Forte@Sun.COM 			    dev_addr[j].gfc_port_dev.priv_port.sf_al_pa];
3310*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_node_status: Searching loop map "
3311*7836SJohn.Forte@Sun.COM 				"to find disk: ID:0x%x"
3312*7836SJohn.Forte@Sun.COM 				" AL_PA:0x%x\n", select_id,
3313*7836SJohn.Forte@Sun.COM 				state->ib_status.sel_id);
3314*7836SJohn.Forte@Sun.COM 
3315*7836SJohn.Forte@Sun.COM 		if (strstr(path, SCSI_VHCI) == NULL) {
3316*7836SJohn.Forte@Sun.COM 
3317*7836SJohn.Forte@Sun.COM 			(void) sprintf(sbuf,
3318*7836SJohn.Forte@Sun.COM 			"w%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x,0:c,raw",
3319*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3320*7836SJohn.Forte@Sun.COM 								sf_port_wwn[0],
3321*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3322*7836SJohn.Forte@Sun.COM 								sf_port_wwn[1],
3323*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3324*7836SJohn.Forte@Sun.COM 								sf_port_wwn[2],
3325*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3326*7836SJohn.Forte@Sun.COM 								sf_port_wwn[3],
3327*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3328*7836SJohn.Forte@Sun.COM 								sf_port_wwn[4],
3329*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3330*7836SJohn.Forte@Sun.COM 								sf_port_wwn[5],
3331*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3332*7836SJohn.Forte@Sun.COM 								sf_port_wwn[6],
3333*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3334*7836SJohn.Forte@Sun.COM 								sf_port_wwn[7]);
3335*7836SJohn.Forte@Sun.COM 			(void) strcat(temp_path, sbuf);
3336*7836SJohn.Forte@Sun.COM 
3337*7836SJohn.Forte@Sun.COM 		}
3338*7836SJohn.Forte@Sun.COM 			/*
3339*7836SJohn.Forte@Sun.COM 			 * If we find a device on this loop in this box
3340*7836SJohn.Forte@Sun.COM 			 * update its status.
3341*7836SJohn.Forte@Sun.COM 			 */
3342*7836SJohn.Forte@Sun.COM 			if (state->ib_status.sel_id == select_id) {
3343*7836SJohn.Forte@Sun.COM 				/*
3344*7836SJohn.Forte@Sun.COM 				 * Found a device on this loop in this box.
3345*7836SJohn.Forte@Sun.COM 				 *
3346*7836SJohn.Forte@Sun.COM 				 * Update state.
3347*7836SJohn.Forte@Sun.COM 				 */
3348*7836SJohn.Forte@Sun.COM 				(void) sprintf(state->g_disk_state.node_wwn_s,
3349*7836SJohn.Forte@Sun.COM 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
3350*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3351*7836SJohn.Forte@Sun.COM 								sf_node_wwn[0],
3352*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3353*7836SJohn.Forte@Sun.COM 								sf_node_wwn[1],
3354*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3355*7836SJohn.Forte@Sun.COM 								sf_node_wwn[2],
3356*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3357*7836SJohn.Forte@Sun.COM 								sf_node_wwn[3],
3358*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3359*7836SJohn.Forte@Sun.COM 								sf_node_wwn[4],
3360*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3361*7836SJohn.Forte@Sun.COM 								sf_node_wwn[5],
3362*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3363*7836SJohn.Forte@Sun.COM 								sf_node_wwn[6],
3364*7836SJohn.Forte@Sun.COM 				map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3365*7836SJohn.Forte@Sun.COM 								sf_node_wwn[7]);
3366*7836SJohn.Forte@Sun.COM 
3367*7836SJohn.Forte@Sun.COM 	if (strstr(path, SCSI_VHCI) != NULL) {
3368*7836SJohn.Forte@Sun.COM 		(void) g_ll_to_str(map_ptr->map.dev_addr[j].gfc_port_dev.
3369*7836SJohn.Forte@Sun.COM 			priv_port.sf_node_wwn, wwnp);
3370*7836SJohn.Forte@Sun.COM 		for (wwnlp = wwn_list; wwnlp != NULL;
3371*7836SJohn.Forte@Sun.COM 			wwnlp = wwnlp->wwn_next) {
3372*7836SJohn.Forte@Sun.COM 			if (strcmp(wwnlp->node_wwn_s, wwnp) == 0) {
3373*7836SJohn.Forte@Sun.COM 			(void) strcpy(temp_path, wwnlp->physical_path);
3374*7836SJohn.Forte@Sun.COM 				break;
3375*7836SJohn.Forte@Sun.COM 			}
3376*7836SJohn.Forte@Sun.COM 		}
3377*7836SJohn.Forte@Sun.COM 		if (wwnlp == NULL) {
3378*7836SJohn.Forte@Sun.COM 			(void) sprintf(sbuf,
3379*7836SJohn.Forte@Sun.COM 		"g%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x:c,raw",
3380*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3381*7836SJohn.Forte@Sun.COM 							sf_node_wwn[0],
3382*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3383*7836SJohn.Forte@Sun.COM 							sf_node_wwn[1],
3384*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3385*7836SJohn.Forte@Sun.COM 							sf_node_wwn[2],
3386*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3387*7836SJohn.Forte@Sun.COM 							sf_node_wwn[3],
3388*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3389*7836SJohn.Forte@Sun.COM 							sf_node_wwn[4],
3390*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3391*7836SJohn.Forte@Sun.COM 							sf_node_wwn[5],
3392*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3393*7836SJohn.Forte@Sun.COM 							sf_node_wwn[6],
3394*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.priv_port.
3395*7836SJohn.Forte@Sun.COM 							sf_node_wwn[7]);
3396*7836SJohn.Forte@Sun.COM 			(void) strcat(temp_path, sbuf);
3397*7836SJohn.Forte@Sun.COM 			/*
3398*7836SJohn.Forte@Sun.COM 			 * check to make sure this is a valid path.
3399*7836SJohn.Forte@Sun.COM 			 * Paths may not always be created on the
3400*7836SJohn.Forte@Sun.COM 			 * host. So, we make a quick check.
3401*7836SJohn.Forte@Sun.COM 			 */
3402*7836SJohn.Forte@Sun.COM 			if (stat(temp_path, &stat_buf) == -1) {
3403*7836SJohn.Forte@Sun.COM 				free_mp_dev_map(&map_mp);
3404*7836SJohn.Forte@Sun.COM 				return (errno);
3405*7836SJohn.Forte@Sun.COM 			}
3406*7836SJohn.Forte@Sun.COM 
3407*7836SJohn.Forte@Sun.COM 		}
3408*7836SJohn.Forte@Sun.COM 	}
3409*7836SJohn.Forte@Sun.COM 		(void) strcpy(state->g_disk_state.physical_path,
3410*7836SJohn.Forte@Sun.COM 			temp_path);
3411*7836SJohn.Forte@Sun.COM 
3412*7836SJohn.Forte@Sun.COM 
3413*7836SJohn.Forte@Sun.COM 				/* Bad if WWN is all zeros. */
3414*7836SJohn.Forte@Sun.COM 				if (is_null_wwn(map_ptr->map.dev_addr[j].
3415*7836SJohn.Forte@Sun.COM 					    gfc_port_dev.priv_port.
3416*7836SJohn.Forte@Sun.COM 					    sf_node_wwn)) {
3417*7836SJohn.Forte@Sun.COM 					state->l_state_flag = L_INVALID_WWN;
3418*7836SJohn.Forte@Sun.COM 					G_DPRINTF("  l_get_node_status: "
3419*7836SJohn.Forte@Sun.COM 						"Disk state was "
3420*7836SJohn.Forte@Sun.COM 						" Invalid WWN.\n");
3421*7836SJohn.Forte@Sun.COM 					(*found_flag)++;
3422*7836SJohn.Forte@Sun.COM 					free_mp_dev_map(&map_mp);
3423*7836SJohn.Forte@Sun.COM 					return (0);
3424*7836SJohn.Forte@Sun.COM 				}
3425*7836SJohn.Forte@Sun.COM 
3426*7836SJohn.Forte@Sun.COM 				/* get device status */
3427*7836SJohn.Forte@Sun.COM 				if (err = l_get_disk_status(temp_path, state,
3428*7836SJohn.Forte@Sun.COM 							wwn_list, verbose)) {
3429*7836SJohn.Forte@Sun.COM 					free_mp_dev_map(&map_mp);
3430*7836SJohn.Forte@Sun.COM 					return (err);
3431*7836SJohn.Forte@Sun.COM 				}
3432*7836SJohn.Forte@Sun.COM 				/*
3433*7836SJohn.Forte@Sun.COM 				 * found device in map.  Don't need to look
3434*7836SJohn.Forte@Sun.COM 				 * any further
3435*7836SJohn.Forte@Sun.COM 				 */
3436*7836SJohn.Forte@Sun.COM 				(*found_flag)++;
3437*7836SJohn.Forte@Sun.COM 				free_mp_dev_map(&map_mp);
3438*7836SJohn.Forte@Sun.COM 				return (0);
3439*7836SJohn.Forte@Sun.COM 			}
3440*7836SJohn.Forte@Sun.COM 		    }	/* for loop */
3441*7836SJohn.Forte@Sun.COM 		break;
3442*7836SJohn.Forte@Sun.COM 	case FC_TOP_PUBLIC_LOOP:
3443*7836SJohn.Forte@Sun.COM 	case FC_TOP_FABRIC:
3444*7836SJohn.Forte@Sun.COM 		/*
3445*7836SJohn.Forte@Sun.COM 		 * Get a generic path to a device
3446*7836SJohn.Forte@Sun.COM 		 * This assumes the path looks something like this
3447*7836SJohn.Forte@Sun.COM 		 * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@wWWN,0:0
3448*7836SJohn.Forte@Sun.COM 		 * then creates a path that looks like
3449*7836SJohn.Forte@Sun.COM 		 * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ssd@
3450*7836SJohn.Forte@Sun.COM 		 */
3451*7836SJohn.Forte@Sun.COM 		(void) strcpy(temp_path, path);
3452*7836SJohn.Forte@Sun.COM 		if ((char_ptr = strrchr(temp_path, '/')) == NULL) {
3453*7836SJohn.Forte@Sun.COM 			free_mp_dev_map(&map_mp);
3454*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH);
3455*7836SJohn.Forte@Sun.COM 		}
3456*7836SJohn.Forte@Sun.COM 		*char_ptr = '\0';   /* Terminate sting  */
3457*7836SJohn.Forte@Sun.COM 
3458*7836SJohn.Forte@Sun.COM 		if (err = l_get_pid_from_path(path, &map_ptr->map, &path_pid)) {
3459*7836SJohn.Forte@Sun.COM 			free_mp_dev_map(&map_mp);
3460*7836SJohn.Forte@Sun.COM 			return (err);
3461*7836SJohn.Forte@Sun.COM 		}
3462*7836SJohn.Forte@Sun.COM 
3463*7836SJohn.Forte@Sun.COM 		/* Now append the ssd string */
3464*7836SJohn.Forte@Sun.COM 		(void) strcat(temp_path, SLSH_DRV_NAME_SSD);
3465*7836SJohn.Forte@Sun.COM 
3466*7836SJohn.Forte@Sun.COM 		/*
3467*7836SJohn.Forte@Sun.COM 		 * Create complete path.
3468*7836SJohn.Forte@Sun.COM 		 *
3469*7836SJohn.Forte@Sun.COM 		 * Build entry ssd@WWN,0:c,raw
3470*7836SJohn.Forte@Sun.COM 		 *
3471*7836SJohn.Forte@Sun.COM 		 * First, search the map for a device with the area code and
3472*7836SJohn.Forte@Sun.COM 		 * domain as in 'path_pid'.
3473*7836SJohn.Forte@Sun.COM 		 */
3474*7836SJohn.Forte@Sun.COM 		for (j = 0; j < map_ptr->map.count; j++) {
3475*7836SJohn.Forte@Sun.COM 			if (map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3476*7836SJohn.Forte@Sun.COM 			    dev_dtype != DTYPE_ESI) {
3477*7836SJohn.Forte@Sun.COM 				select_id = g_sf_alpa_to_switch[map_ptr->map.
3478*7836SJohn.Forte@Sun.COM 				    dev_addr[j].gfc_port_dev.pub_port.dev_did.
3479*7836SJohn.Forte@Sun.COM 				    port_id & 0xFF];
3480*7836SJohn.Forte@Sun.COM 
3481*7836SJohn.Forte@Sun.COM 				if (((map_ptr->map.dev_addr[j].gfc_port_dev.
3482*7836SJohn.Forte@Sun.COM 						    pub_port.dev_did.port_id &
3483*7836SJohn.Forte@Sun.COM 						    AREA_DOMAIN_ID) ==
3484*7836SJohn.Forte@Sun.COM 					    (path_pid & AREA_DOMAIN_ID)) &&
3485*7836SJohn.Forte@Sun.COM 				    (state->ib_status.sel_id == select_id)) {
3486*7836SJohn.Forte@Sun.COM 					/*
3487*7836SJohn.Forte@Sun.COM 					 * Found the device. Update state.
3488*7836SJohn.Forte@Sun.COM 					 */
3489*7836SJohn.Forte@Sun.COM 		if (strstr(temp_path, SCSI_VHCI) == NULL) {
3490*7836SJohn.Forte@Sun.COM 					(void) sprintf(sbuf,
3491*7836SJohn.Forte@Sun.COM 			"w%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x,0:c,raw",
3492*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3493*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[0],
3494*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3495*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[1],
3496*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3497*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[2],
3498*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3499*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[3],
3500*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3501*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[4],
3502*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3503*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[5],
3504*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3505*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[6],
3506*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3507*7836SJohn.Forte@Sun.COM 					pub_port.dev_pwwn.raw_wwn[7]);
3508*7836SJohn.Forte@Sun.COM 					(void) strcat(temp_path, sbuf);
3509*7836SJohn.Forte@Sun.COM 
3510*7836SJohn.Forte@Sun.COM 					/*
3511*7836SJohn.Forte@Sun.COM 					 * Paths for fabric cases may not always
3512*7836SJohn.Forte@Sun.COM 					 * be created on the host. So, we make a
3513*7836SJohn.Forte@Sun.COM 					 * quick check.
3514*7836SJohn.Forte@Sun.COM 					 */
3515*7836SJohn.Forte@Sun.COM 					if (stat(temp_path, &stat_buf) == -1) {
3516*7836SJohn.Forte@Sun.COM 						free_mp_dev_map(&map_mp);
3517*7836SJohn.Forte@Sun.COM 						return (errno);
3518*7836SJohn.Forte@Sun.COM 					}
3519*7836SJohn.Forte@Sun.COM 
3520*7836SJohn.Forte@Sun.COM 					(void) sprintf(state->
3521*7836SJohn.Forte@Sun.COM 							g_disk_state.node_wwn_s,
3522*7836SJohn.Forte@Sun.COM 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
3523*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3524*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[0],
3525*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3526*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[1],
3527*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3528*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[2],
3529*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3530*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[3],
3531*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3532*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[4],
3533*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3534*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[5],
3535*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3536*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[6],
3537*7836SJohn.Forte@Sun.COM 					map_ptr->map.dev_addr[j].gfc_port_dev.
3538*7836SJohn.Forte@Sun.COM 					pub_port.dev_nwwn.raw_wwn[7]);
3539*7836SJohn.Forte@Sun.COM 
3540*7836SJohn.Forte@Sun.COM 		} else {
3541*7836SJohn.Forte@Sun.COM 		(void) g_ll_to_str(map_ptr->map.dev_addr[j].gfc_port_dev.
3542*7836SJohn.Forte@Sun.COM 			priv_port.sf_node_wwn, wwnp);
3543*7836SJohn.Forte@Sun.COM 		for (wwnlp = wwn_list; wwnlp != NULL;
3544*7836SJohn.Forte@Sun.COM 		wwnlp = wwnlp->wwn_next) {
3545*7836SJohn.Forte@Sun.COM 			if (strcmp(wwnlp->node_wwn_s, wwnp) == 0) {
3546*7836SJohn.Forte@Sun.COM 			(void) strcpy(temp_path, wwnlp->physical_path);
3547*7836SJohn.Forte@Sun.COM 			break;
3548*7836SJohn.Forte@Sun.COM 			}
3549*7836SJohn.Forte@Sun.COM 		}
3550*7836SJohn.Forte@Sun.COM 		if (wwnlp == NULL) {
3551*7836SJohn.Forte@Sun.COM 			(void) sprintf(sbuf,
3552*7836SJohn.Forte@Sun.COM 		"w%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x,0:c,raw",
3553*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3554*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[0],
3555*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3556*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[1],
3557*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3558*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[2],
3559*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3560*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[3],
3561*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3562*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[4],
3563*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3564*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[5],
3565*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3566*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[6],
3567*7836SJohn.Forte@Sun.COM 			map_ptr->map.dev_addr[j].gfc_port_dev.pub_port.
3568*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn[7]);
3569*7836SJohn.Forte@Sun.COM 				(void) strcat(temp_path, sbuf);
3570*7836SJohn.Forte@Sun.COM 		}
3571*7836SJohn.Forte@Sun.COM 		}
3572*7836SJohn.Forte@Sun.COM 		(void) strcpy(state->g_disk_state.physical_path,
3573*7836SJohn.Forte@Sun.COM 		temp_path);
3574*7836SJohn.Forte@Sun.COM 
3575*7836SJohn.Forte@Sun.COM 					/* Bad if WWN is all zeros. */
3576*7836SJohn.Forte@Sun.COM 					if (is_null_wwn(map_ptr->map.
3577*7836SJohn.Forte@Sun.COM 						    dev_addr[j].gfc_port_dev.
3578*7836SJohn.Forte@Sun.COM 						    pub_port.dev_nwwn.
3579*7836SJohn.Forte@Sun.COM 						    raw_wwn)) {
3580*7836SJohn.Forte@Sun.COM 						state->l_state_flag =
3581*7836SJohn.Forte@Sun.COM 								L_INVALID_WWN;
3582*7836SJohn.Forte@Sun.COM 						G_DPRINTF(
3583*7836SJohn.Forte@Sun.COM 						"  l_get_node_status: "
3584*7836SJohn.Forte@Sun.COM 						"Disk state was "
3585*7836SJohn.Forte@Sun.COM 						" Invalid WWN.\n");
3586*7836SJohn.Forte@Sun.COM 						(*found_flag)++;
3587*7836SJohn.Forte@Sun.COM 						free_mp_dev_map(&map_mp);
3588*7836SJohn.Forte@Sun.COM 						return (0);
3589*7836SJohn.Forte@Sun.COM 					}
3590*7836SJohn.Forte@Sun.COM 
3591*7836SJohn.Forte@Sun.COM 					/* get device status */
3592*7836SJohn.Forte@Sun.COM 					if (err = l_get_disk_status(temp_path,
3593*7836SJohn.Forte@Sun.COM 						state, wwn_list, verbose)) {
3594*7836SJohn.Forte@Sun.COM 						free_mp_dev_map(&map_mp);
3595*7836SJohn.Forte@Sun.COM 						return (err);
3596*7836SJohn.Forte@Sun.COM 					}
3597*7836SJohn.Forte@Sun.COM 
3598*7836SJohn.Forte@Sun.COM 					(*found_flag)++;
3599*7836SJohn.Forte@Sun.COM 					free_mp_dev_map(&map_mp);
3600*7836SJohn.Forte@Sun.COM 					return (0);
3601*7836SJohn.Forte@Sun.COM 				}	/* if select_id match */
3602*7836SJohn.Forte@Sun.COM 			}	/* if !DTYPE_ESI */
3603*7836SJohn.Forte@Sun.COM 		}		/* for loop */
3604*7836SJohn.Forte@Sun.COM 		break;
3605*7836SJohn.Forte@Sun.COM 	case FC_TOP_PT_PT:
3606*7836SJohn.Forte@Sun.COM 		free_mp_dev_map(&map_mp);
3607*7836SJohn.Forte@Sun.COM 		return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
3608*7836SJohn.Forte@Sun.COM 	default:
3609*7836SJohn.Forte@Sun.COM 		free_mp_dev_map(&map_mp);
3610*7836SJohn.Forte@Sun.COM 		return (L_UNEXPECTED_FC_TOPOLOGY);
3611*7836SJohn.Forte@Sun.COM 	    }	/* End of switch on port_topology */
3612*7836SJohn.Forte@Sun.COM 
3613*7836SJohn.Forte@Sun.COM 	}
3614*7836SJohn.Forte@Sun.COM 	free_mp_dev_map(&map_mp);
3615*7836SJohn.Forte@Sun.COM 	return (0);
3616*7836SJohn.Forte@Sun.COM }
3617*7836SJohn.Forte@Sun.COM 
3618*7836SJohn.Forte@Sun.COM 
3619*7836SJohn.Forte@Sun.COM /*
3620*7836SJohn.Forte@Sun.COM  * Get the individual drives status for the device specified by the index.
3621*7836SJohn.Forte@Sun.COM  * device at the path where the path is of the IB and updates the
3622*7836SJohn.Forte@Sun.COM  * g_disk_state_struct structure.
3623*7836SJohn.Forte@Sun.COM  *
3624*7836SJohn.Forte@Sun.COM  * If the disk's port is bypassed,  it gets the
3625*7836SJohn.Forte@Sun.COM  * drive status such as node WWN from the second port.
3626*7836SJohn.Forte@Sun.COM  *
3627*7836SJohn.Forte@Sun.COM  * RETURNS:
3628*7836SJohn.Forte@Sun.COM  *	0	 O.K.
3629*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
3630*7836SJohn.Forte@Sun.COM  */
3631*7836SJohn.Forte@Sun.COM int
l_get_individual_state(char * path,struct l_disk_state_struct * state,Ib_state * ib_state,int front_flag,struct box_list_struct * box_list,struct wwn_list_struct * wwn_list,int verbose)3632*7836SJohn.Forte@Sun.COM l_get_individual_state(char *path,
3633*7836SJohn.Forte@Sun.COM 	struct l_disk_state_struct *state, Ib_state *ib_state,
3634*7836SJohn.Forte@Sun.COM 	int front_flag, struct box_list_struct *box_list,
3635*7836SJohn.Forte@Sun.COM 	struct wwn_list_struct *wwn_list, int verbose)
3636*7836SJohn.Forte@Sun.COM {
3637*7836SJohn.Forte@Sun.COM int		found_flag = 0, elem_index = 0;
3638*7836SJohn.Forte@Sun.COM int		port_a_flag, err, j;
3639*7836SJohn.Forte@Sun.COM struct dlist	*seslist = NULL;
3640*7836SJohn.Forte@Sun.COM Bp_elem_st	bpf, bpr;
3641*7836SJohn.Forte@Sun.COM hrtime_t	start_time, end_time;
3642*7836SJohn.Forte@Sun.COM 
3643*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (state == NULL) ||
3644*7836SJohn.Forte@Sun.COM 	    (ib_state == NULL) || (box_list == NULL)) {
3645*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
3646*7836SJohn.Forte@Sun.COM 	}
3647*7836SJohn.Forte@Sun.COM 
3648*7836SJohn.Forte@Sun.COM 	start_time = gethrtime();
3649*7836SJohn.Forte@Sun.COM 
3650*7836SJohn.Forte@Sun.COM 
3651*7836SJohn.Forte@Sun.COM 	if ((state->ib_status.code != S_NOT_INSTALLED) &&
3652*7836SJohn.Forte@Sun.COM 		(state->ib_status.code != S_NOT_AVAILABLE)) {
3653*7836SJohn.Forte@Sun.COM 
3654*7836SJohn.Forte@Sun.COM 		/*
3655*7836SJohn.Forte@Sun.COM 		 * Disk could have been bypassed on this loop.
3656*7836SJohn.Forte@Sun.COM 		 * Check the port state before l_state_flag
3657*7836SJohn.Forte@Sun.COM 		 * is set to L_INVALID_MAP.
3658*7836SJohn.Forte@Sun.COM 		 */
3659*7836SJohn.Forte@Sun.COM 		for (j = 0;
3660*7836SJohn.Forte@Sun.COM 		j < (int)ib_state->config.enc_num_elem;
3661*7836SJohn.Forte@Sun.COM 		j++) {
3662*7836SJohn.Forte@Sun.COM 			elem_index++;
3663*7836SJohn.Forte@Sun.COM 			if (ib_state->config.type_hdr[j].type ==
3664*7836SJohn.Forte@Sun.COM 							ELM_TYP_BP)
3665*7836SJohn.Forte@Sun.COM 				break;
3666*7836SJohn.Forte@Sun.COM 			elem_index +=
3667*7836SJohn.Forte@Sun.COM 				ib_state->config.type_hdr[j].num;
3668*7836SJohn.Forte@Sun.COM 		}
3669*7836SJohn.Forte@Sun.COM 
3670*7836SJohn.Forte@Sun.COM 		/*
3671*7836SJohn.Forte@Sun.COM 		 * check if port A & B of backplane are bypassed.
3672*7836SJohn.Forte@Sun.COM 		 * If so, do not bother.
3673*7836SJohn.Forte@Sun.COM 		 */
3674*7836SJohn.Forte@Sun.COM 		if (front_flag) {
3675*7836SJohn.Forte@Sun.COM 			bcopy((const void *)
3676*7836SJohn.Forte@Sun.COM 			&(ib_state->p2_s.element[elem_index]),
3677*7836SJohn.Forte@Sun.COM 			(void *)&bpf, sizeof (bpf));
3678*7836SJohn.Forte@Sun.COM 
3679*7836SJohn.Forte@Sun.COM 			if ((bpf.byp_a_enabled || bpf.en_bypass_a) &&
3680*7836SJohn.Forte@Sun.COM 				(bpf.byp_b_enabled || bpf.en_bypass_b))
3681*7836SJohn.Forte@Sun.COM 				return (0);
3682*7836SJohn.Forte@Sun.COM 		} else {
3683*7836SJohn.Forte@Sun.COM 			/* if disk is in rear slot */
3684*7836SJohn.Forte@Sun.COM 			bcopy((const void *)
3685*7836SJohn.Forte@Sun.COM 			&(ib_state->p2_s.element[elem_index+1]),
3686*7836SJohn.Forte@Sun.COM 			(void *)&bpr, sizeof (bpr));
3687*7836SJohn.Forte@Sun.COM 
3688*7836SJohn.Forte@Sun.COM 			if ((bpr.byp_b_enabled || bpr.en_bypass_b) &&
3689*7836SJohn.Forte@Sun.COM 				(bpr.byp_a_enabled || bpr.en_bypass_a))
3690*7836SJohn.Forte@Sun.COM 				return (0);
3691*7836SJohn.Forte@Sun.COM 		}
3692*7836SJohn.Forte@Sun.COM 
3693*7836SJohn.Forte@Sun.COM 		if ((err = l_get_node_status(path, state,
3694*7836SJohn.Forte@Sun.COM 				&found_flag, wwn_list, verbose)) != 0)
3695*7836SJohn.Forte@Sun.COM 			return (err);
3696*7836SJohn.Forte@Sun.COM 
3697*7836SJohn.Forte@Sun.COM 		if (!found_flag) {
3698*7836SJohn.Forte@Sun.COM 			if ((err = l_get_allses(path, box_list,
3699*7836SJohn.Forte@Sun.COM 						&seslist, 0)) != 0) {
3700*7836SJohn.Forte@Sun.COM 				return (err);
3701*7836SJohn.Forte@Sun.COM 			}
3702*7836SJohn.Forte@Sun.COM 
3703*7836SJohn.Forte@Sun.COM 			if (err = l_get_port(path, &port_a_flag, verbose))
3704*7836SJohn.Forte@Sun.COM 				goto done;
3705*7836SJohn.Forte@Sun.COM 
3706*7836SJohn.Forte@Sun.COM 			if (port_a_flag) {
3707*7836SJohn.Forte@Sun.COM 				if ((state->ib_status.bypass_a_en &&
3708*7836SJohn.Forte@Sun.COM 					!(state->ib_status.bypass_b_en)) ||
3709*7836SJohn.Forte@Sun.COM 					!(state->ib_status.bypass_b_en)) {
3710*7836SJohn.Forte@Sun.COM 					while (seslist != NULL && !found_flag) {
3711*7836SJohn.Forte@Sun.COM 						if (err = l_get_port(
3712*7836SJohn.Forte@Sun.COM 							seslist->dev_path,
3713*7836SJohn.Forte@Sun.COM 						&port_a_flag, verbose)) {
3714*7836SJohn.Forte@Sun.COM 							goto done;
3715*7836SJohn.Forte@Sun.COM 						}
3716*7836SJohn.Forte@Sun.COM 						if ((strcmp(seslist->dev_path,
3717*7836SJohn.Forte@Sun.COM 							path) != 0) &&
3718*7836SJohn.Forte@Sun.COM 							!port_a_flag) {
3719*7836SJohn.Forte@Sun.COM 							*path = NULL;
3720*7836SJohn.Forte@Sun.COM 							(void) strcpy(path,
3721*7836SJohn.Forte@Sun.COM 							seslist->dev_path);
3722*7836SJohn.Forte@Sun.COM 							if (err =
3723*7836SJohn.Forte@Sun.COM 							l_get_node_status(path,
3724*7836SJohn.Forte@Sun.COM 							state, &found_flag,
3725*7836SJohn.Forte@Sun.COM 							wwn_list, verbose)) {
3726*7836SJohn.Forte@Sun.COM 								goto done;
3727*7836SJohn.Forte@Sun.COM 							}
3728*7836SJohn.Forte@Sun.COM 						}
3729*7836SJohn.Forte@Sun.COM 						seslist = seslist->next;
3730*7836SJohn.Forte@Sun.COM 					}
3731*7836SJohn.Forte@Sun.COM 				}
3732*7836SJohn.Forte@Sun.COM 			} else {
3733*7836SJohn.Forte@Sun.COM 				if ((state->ib_status.bypass_b_en &&
3734*7836SJohn.Forte@Sun.COM 					!(state->ib_status.bypass_a_en)) ||
3735*7836SJohn.Forte@Sun.COM 					!(state->ib_status.bypass_a_en)) {
3736*7836SJohn.Forte@Sun.COM 					while (seslist != NULL && !found_flag) {
3737*7836SJohn.Forte@Sun.COM 						if (err = l_get_port(
3738*7836SJohn.Forte@Sun.COM 							seslist->dev_path,
3739*7836SJohn.Forte@Sun.COM 						&port_a_flag, verbose)) {
3740*7836SJohn.Forte@Sun.COM 							goto done;
3741*7836SJohn.Forte@Sun.COM 						}
3742*7836SJohn.Forte@Sun.COM 						if ((strcmp(seslist->dev_path,
3743*7836SJohn.Forte@Sun.COM 						path) != 0) && port_a_flag) {
3744*7836SJohn.Forte@Sun.COM 							*path = NULL;
3745*7836SJohn.Forte@Sun.COM 							(void) strcpy(path,
3746*7836SJohn.Forte@Sun.COM 							seslist->dev_path);
3747*7836SJohn.Forte@Sun.COM 							if (err =
3748*7836SJohn.Forte@Sun.COM 							l_get_node_status(path,
3749*7836SJohn.Forte@Sun.COM 							state, &found_flag,
3750*7836SJohn.Forte@Sun.COM 							wwn_list, verbose)) {
3751*7836SJohn.Forte@Sun.COM 								goto done;
3752*7836SJohn.Forte@Sun.COM 							}
3753*7836SJohn.Forte@Sun.COM 						}
3754*7836SJohn.Forte@Sun.COM 						seslist = seslist->next;
3755*7836SJohn.Forte@Sun.COM 					}
3756*7836SJohn.Forte@Sun.COM 				}
3757*7836SJohn.Forte@Sun.COM 			}
3758*7836SJohn.Forte@Sun.COM 			if (!found_flag) {
3759*7836SJohn.Forte@Sun.COM 				state->l_state_flag = L_INVALID_MAP;
3760*7836SJohn.Forte@Sun.COM 				G_DPRINTF("  l_get_individual_state: "
3761*7836SJohn.Forte@Sun.COM 					"Disk state was "
3762*7836SJohn.Forte@Sun.COM 					"Not in map.\n");
3763*7836SJohn.Forte@Sun.COM 			} else {
3764*7836SJohn.Forte@Sun.COM 				G_DPRINTF("  l_get_individual_state: "
3765*7836SJohn.Forte@Sun.COM 					"Disk was found in the map.\n");
3766*7836SJohn.Forte@Sun.COM 			}
3767*7836SJohn.Forte@Sun.COM 
3768*7836SJohn.Forte@Sun.COM 			if (seslist != NULL)
3769*7836SJohn.Forte@Sun.COM 				(void) g_free_multipath(seslist);
3770*7836SJohn.Forte@Sun.COM 
3771*7836SJohn.Forte@Sun.COM 		}
3772*7836SJohn.Forte@Sun.COM 
3773*7836SJohn.Forte@Sun.COM 	} else {
3774*7836SJohn.Forte@Sun.COM 		G_DPRINTF("  l_get_individual_state: Disk state was %s.\n",
3775*7836SJohn.Forte@Sun.COM 			(state->ib_status.code == S_NOT_INSTALLED) ?
3776*7836SJohn.Forte@Sun.COM 			"Not Installed" : "Not Available");
3777*7836SJohn.Forte@Sun.COM 	}
3778*7836SJohn.Forte@Sun.COM 
3779*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_T_DEBUG") != NULL) {
3780*7836SJohn.Forte@Sun.COM 		end_time = gethrtime();
3781*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "    l_get_individual_state:"
3782*7836SJohn.Forte@Sun.COM 		"\tTime = %lld millisec\n",
3783*7836SJohn.Forte@Sun.COM 		(end_time - start_time)/1000000);
3784*7836SJohn.Forte@Sun.COM 	}
3785*7836SJohn.Forte@Sun.COM 
3786*7836SJohn.Forte@Sun.COM 	return (0);
3787*7836SJohn.Forte@Sun.COM done:
3788*7836SJohn.Forte@Sun.COM 	(void) g_free_multipath(seslist);
3789*7836SJohn.Forte@Sun.COM 	return (err);
3790*7836SJohn.Forte@Sun.COM }
3791*7836SJohn.Forte@Sun.COM 
3792*7836SJohn.Forte@Sun.COM 
3793*7836SJohn.Forte@Sun.COM 
3794*7836SJohn.Forte@Sun.COM /*
3795*7836SJohn.Forte@Sun.COM  * Get the global state of the photon.
3796*7836SJohn.Forte@Sun.COM  *
3797*7836SJohn.Forte@Sun.COM  * INPUT:
3798*7836SJohn.Forte@Sun.COM  * path and verbose flag
3799*7836SJohn.Forte@Sun.COM  *
3800*7836SJohn.Forte@Sun.COM  * "path" must be of the ses driver.
3801*7836SJohn.Forte@Sun.COM  * e.g.
3802*7836SJohn.Forte@Sun.COM  * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
3803*7836SJohn.Forte@Sun.COM  * or
3804*7836SJohn.Forte@Sun.COM  * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@WWN,0:0
3805*7836SJohn.Forte@Sun.COM  *
3806*7836SJohn.Forte@Sun.COM  * OUTPUT:
3807*7836SJohn.Forte@Sun.COM  * The struct l_state (which was passed in) has the status info
3808*7836SJohn.Forte@Sun.COM  *
3809*7836SJohn.Forte@Sun.COM  * RETURNS:
3810*7836SJohn.Forte@Sun.COM  *	0	 O.K.
3811*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
3812*7836SJohn.Forte@Sun.COM  */
3813*7836SJohn.Forte@Sun.COM int
l_get_status(char * path,struct l_state_struct * l_state,int verbose)3814*7836SJohn.Forte@Sun.COM l_get_status(char *path, struct l_state_struct *l_state, int verbose)
3815*7836SJohn.Forte@Sun.COM {
3816*7836SJohn.Forte@Sun.COM int		err = 0, i, count;
3817*7836SJohn.Forte@Sun.COM L_inquiry	inq;
3818*7836SJohn.Forte@Sun.COM uchar_t		node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
3819*7836SJohn.Forte@Sun.COM int		al_pa, found_front, found_rear, front_flag, enc_type;
3820*7836SJohn.Forte@Sun.COM char		ses_path_front[MAXPATHLEN];
3821*7836SJohn.Forte@Sun.COM char		ses_path_rear[MAXPATHLEN];
3822*7836SJohn.Forte@Sun.COM Box_list	*b_list = NULL;
3823*7836SJohn.Forte@Sun.COM Box_list	*o_list = NULL;
3824*7836SJohn.Forte@Sun.COM char		node_wwn_s[(WWN_SIZE*2)+1];
3825*7836SJohn.Forte@Sun.COM uint_t		select_id;
3826*7836SJohn.Forte@Sun.COM hrtime_t	start_time, end_time;
3827*7836SJohn.Forte@Sun.COM WWN_list		*wwn_list = NULL;
3828*7836SJohn.Forte@Sun.COM 
3829*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (l_state == NULL)) {
3830*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
3831*7836SJohn.Forte@Sun.COM 	}
3832*7836SJohn.Forte@Sun.COM 
3833*7836SJohn.Forte@Sun.COM 	start_time = gethrtime();
3834*7836SJohn.Forte@Sun.COM 
3835*7836SJohn.Forte@Sun.COM 	G_DPRINTF("  l_get_status: Get Status for enclosure at: "
3836*7836SJohn.Forte@Sun.COM 		" %s\n", path);
3837*7836SJohn.Forte@Sun.COM 
3838*7836SJohn.Forte@Sun.COM 	/* initialization */
3839*7836SJohn.Forte@Sun.COM 	(void) memset(l_state, 0, sizeof (struct l_state_struct));
3840*7836SJohn.Forte@Sun.COM 
3841*7836SJohn.Forte@Sun.COM 	if (err = g_get_inquiry(path, &inq)) {
3842*7836SJohn.Forte@Sun.COM 		return (err);
3843*7836SJohn.Forte@Sun.COM 	}
3844*7836SJohn.Forte@Sun.COM 	if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) &&
3845*7836SJohn.Forte@Sun.COM 		(!(strncmp((char *)inq.inq_vid, "SUN     ",
3846*7836SJohn.Forte@Sun.COM 		sizeof (inq.inq_vid)) &&
3847*7836SJohn.Forte@Sun.COM 		((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)))) {
3848*7836SJohn.Forte@Sun.COM 		return (L_ENCL_INVALID_PATH);
3849*7836SJohn.Forte@Sun.COM 	}
3850*7836SJohn.Forte@Sun.COM 
3851*7836SJohn.Forte@Sun.COM 	(void) strncpy((char *)l_state->ib_tbl.enclosure_name,
3852*7836SJohn.Forte@Sun.COM 		(char *)inq.inq_box_name, sizeof (inq.inq_box_name));
3853*7836SJohn.Forte@Sun.COM 
3854*7836SJohn.Forte@Sun.COM 	/*
3855*7836SJohn.Forte@Sun.COM 	 * Get all of the IB Receive Diagnostic pages.
3856*7836SJohn.Forte@Sun.COM 	 */
3857*7836SJohn.Forte@Sun.COM 	if (err = l_get_ib_status(path, l_state, verbose)) {
3858*7836SJohn.Forte@Sun.COM 		return (err);
3859*7836SJohn.Forte@Sun.COM 	}
3860*7836SJohn.Forte@Sun.COM 
3861*7836SJohn.Forte@Sun.COM 	/*
3862*7836SJohn.Forte@Sun.COM 	 * Now get the individual devices information from
3863*7836SJohn.Forte@Sun.COM 	 * the device itself.
3864*7836SJohn.Forte@Sun.COM 	 *
3865*7836SJohn.Forte@Sun.COM 	 * May need to use multiple paths to get to the
3866*7836SJohn.Forte@Sun.COM 	 * front and rear drives in the box.
3867*7836SJohn.Forte@Sun.COM 	 * If the loop is split some drives may not even be available
3868*7836SJohn.Forte@Sun.COM 	 * from this host.
3869*7836SJohn.Forte@Sun.COM 	 *
3870*7836SJohn.Forte@Sun.COM 	 * The way this works is in the select ID the front disks
3871*7836SJohn.Forte@Sun.COM 	 * are accessed via the IB with the bit 4 = 0
3872*7836SJohn.Forte@Sun.COM 	 * and the rear disks by the IB with bit 4 = 1.
3873*7836SJohn.Forte@Sun.COM 	 *
3874*7836SJohn.Forte@Sun.COM 	 * First get device map from fc nexus driver for this loop.
3875*7836SJohn.Forte@Sun.COM 	 */
3876*7836SJohn.Forte@Sun.COM 	/*
3877*7836SJohn.Forte@Sun.COM 	 * Get the boxes node WWN & al_pa for this path.
3878*7836SJohn.Forte@Sun.COM 	 */
3879*7836SJohn.Forte@Sun.COM 	if (err = g_get_wwn(path, port_wwn, node_wwn, &al_pa, verbose)) {
3880*7836SJohn.Forte@Sun.COM 		return (err);
3881*7836SJohn.Forte@Sun.COM 	}
3882*7836SJohn.Forte@Sun.COM 	if (err = l_get_box_list(&o_list, verbose)) {
3883*7836SJohn.Forte@Sun.COM 		(void) l_free_box_list(&o_list);
3884*7836SJohn.Forte@Sun.COM 		return (err);	/* Failure */
3885*7836SJohn.Forte@Sun.COM 	}
3886*7836SJohn.Forte@Sun.COM 
3887*7836SJohn.Forte@Sun.COM 	found_front = found_rear = 0;
3888*7836SJohn.Forte@Sun.COM 	for (i = 0; i < WWN_SIZE; i++) {
3889*7836SJohn.Forte@Sun.COM 		(void) sprintf(&node_wwn_s[i << 1], "%02x", node_wwn[i]);
3890*7836SJohn.Forte@Sun.COM 	}
3891*7836SJohn.Forte@Sun.COM 
3892*7836SJohn.Forte@Sun.COM 	/*
3893*7836SJohn.Forte@Sun.COM 	 * The al_pa (or pa) can be 24 bits in size for fabric loops.
3894*7836SJohn.Forte@Sun.COM 	 * But we will take only the low order byte to get the select_id.
3895*7836SJohn.Forte@Sun.COM 	 * Private loops have al_pa which is only a byte in size.
3896*7836SJohn.Forte@Sun.COM 	 */
3897*7836SJohn.Forte@Sun.COM 	select_id = g_sf_alpa_to_switch[al_pa & 0xFF];
3898*7836SJohn.Forte@Sun.COM 	l_state->ib_tbl.box_id = (select_id & BOX_ID_MASK) >> 5;
3899*7836SJohn.Forte@Sun.COM 
3900*7836SJohn.Forte@Sun.COM 	G_DPRINTF("  l_get_status: Using this select_id 0x%x "
3901*7836SJohn.Forte@Sun.COM 		"and node WWN %s\n",
3902*7836SJohn.Forte@Sun.COM 		select_id, node_wwn_s);
3903*7836SJohn.Forte@Sun.COM 
3904*7836SJohn.Forte@Sun.COM 	if (strstr(path, SCSI_VHCI) != NULL) {
3905*7836SJohn.Forte@Sun.COM 		/* there is no way to obtain all the al_pa with */
3906*7836SJohn.Forte@Sun.COM 		/*  current implementation. assume both front   */
3907*7836SJohn.Forte@Sun.COM 		/*  and rear. need changes later on. */
3908*7836SJohn.Forte@Sun.COM 		found_rear = 1;
3909*7836SJohn.Forte@Sun.COM 		found_front = 1;
3910*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path_rear, path);
3911*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path_front, path);
3912*7836SJohn.Forte@Sun.COM 	} else {
3913*7836SJohn.Forte@Sun.COM 
3914*7836SJohn.Forte@Sun.COM 	if (select_id & ALT_BOX_ID) {
3915*7836SJohn.Forte@Sun.COM 		found_rear = 1;
3916*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path_rear, path);
3917*7836SJohn.Forte@Sun.COM 		b_list = o_list;
3918*7836SJohn.Forte@Sun.COM 		while (b_list) {
3919*7836SJohn.Forte@Sun.COM 			if (strcmp(b_list->b_node_wwn_s, node_wwn_s) == 0) {
3920*7836SJohn.Forte@Sun.COM 				if (err = g_get_wwn(b_list->b_physical_path,
3921*7836SJohn.Forte@Sun.COM 					port_wwn, node_wwn,
3922*7836SJohn.Forte@Sun.COM 					&al_pa, verbose)) {
3923*7836SJohn.Forte@Sun.COM 					(void) l_free_box_list(&o_list);
3924*7836SJohn.Forte@Sun.COM 					return (err);
3925*7836SJohn.Forte@Sun.COM 				}
3926*7836SJohn.Forte@Sun.COM 
3927*7836SJohn.Forte@Sun.COM 				/* Take the low order byte of al_pa */
3928*7836SJohn.Forte@Sun.COM 				select_id = g_sf_alpa_to_switch[al_pa & 0xFF];
3929*7836SJohn.Forte@Sun.COM 				if (!(select_id & ALT_BOX_ID)) {
3930*7836SJohn.Forte@Sun.COM 					(void) strcpy(ses_path_front,
3931*7836SJohn.Forte@Sun.COM 					b_list->b_physical_path);
3932*7836SJohn.Forte@Sun.COM 					found_front = 1;
3933*7836SJohn.Forte@Sun.COM 					break;
3934*7836SJohn.Forte@Sun.COM 				}
3935*7836SJohn.Forte@Sun.COM 			}
3936*7836SJohn.Forte@Sun.COM 			b_list = b_list->box_next;
3937*7836SJohn.Forte@Sun.COM 		}
3938*7836SJohn.Forte@Sun.COM 	} else {
3939*7836SJohn.Forte@Sun.COM 		(void) strcpy(ses_path_front, path);
3940*7836SJohn.Forte@Sun.COM 		found_front = 1;
3941*7836SJohn.Forte@Sun.COM 		b_list = o_list;
3942*7836SJohn.Forte@Sun.COM 		while (b_list) {
3943*7836SJohn.Forte@Sun.COM 			if (strcmp(b_list->b_node_wwn_s, node_wwn_s) == 0) {
3944*7836SJohn.Forte@Sun.COM 				if (err = g_get_wwn(b_list->b_physical_path,
3945*7836SJohn.Forte@Sun.COM 					port_wwn, node_wwn,
3946*7836SJohn.Forte@Sun.COM 					&al_pa, verbose)) {
3947*7836SJohn.Forte@Sun.COM 					(void) l_free_box_list(&o_list);
3948*7836SJohn.Forte@Sun.COM 					return (err);
3949*7836SJohn.Forte@Sun.COM 				}
3950*7836SJohn.Forte@Sun.COM 				select_id = g_sf_alpa_to_switch[al_pa & 0xFF];
3951*7836SJohn.Forte@Sun.COM 				if (select_id & ALT_BOX_ID) {
3952*7836SJohn.Forte@Sun.COM 					(void) strcpy(ses_path_rear,
3953*7836SJohn.Forte@Sun.COM 					b_list->b_physical_path);
3954*7836SJohn.Forte@Sun.COM 					found_rear = 1;
3955*7836SJohn.Forte@Sun.COM 					break;
3956*7836SJohn.Forte@Sun.COM 				}
3957*7836SJohn.Forte@Sun.COM 			}
3958*7836SJohn.Forte@Sun.COM 			b_list = b_list->box_next;
3959*7836SJohn.Forte@Sun.COM 		}
3960*7836SJohn.Forte@Sun.COM 	}
3961*7836SJohn.Forte@Sun.COM 	}
3962*7836SJohn.Forte@Sun.COM 
3963*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_G_DEBUG") != NULL) {
3964*7836SJohn.Forte@Sun.COM 		if (!found_front) {
3965*7836SJohn.Forte@Sun.COM 		(void) printf("l_get_status: Loop to front disks not found.\n");
3966*7836SJohn.Forte@Sun.COM 		}
3967*7836SJohn.Forte@Sun.COM 		if (!found_rear) {
3968*7836SJohn.Forte@Sun.COM 		(void) printf("l_get_status: Loop to rear disks not found.\n");
3969*7836SJohn.Forte@Sun.COM 		}
3970*7836SJohn.Forte@Sun.COM 	}
3971*7836SJohn.Forte@Sun.COM 
3972*7836SJohn.Forte@Sun.COM 	/*
3973*7836SJohn.Forte@Sun.COM 	 * Get path to all the FC disk and tape devices.
3974*7836SJohn.Forte@Sun.COM 	 *
3975*7836SJohn.Forte@Sun.COM 	 * I get this now and pass down for performance
3976*7836SJohn.Forte@Sun.COM 	 * reasons.
3977*7836SJohn.Forte@Sun.COM 	 * If for some reason the list can become invalid,
3978*7836SJohn.Forte@Sun.COM 	 * i.e. device being offlined, then the list
3979*7836SJohn.Forte@Sun.COM 	 * must be re-gotten.
3980*7836SJohn.Forte@Sun.COM 	 */
3981*7836SJohn.Forte@Sun.COM 	if (err = g_get_wwn_list(&wwn_list, verbose)) {
3982*7836SJohn.Forte@Sun.COM 		return (err);   /* Failure */
3983*7836SJohn.Forte@Sun.COM 	}
3984*7836SJohn.Forte@Sun.COM 
3985*7836SJohn.Forte@Sun.COM 	enc_type = l_get_enc_type(inq);
3986*7836SJohn.Forte@Sun.COM 	if (found_front) {
3987*7836SJohn.Forte@Sun.COM 		front_flag = 1;
3988*7836SJohn.Forte@Sun.COM 		for (i = 0, count = 0; i < l_state->total_num_drv/2;
3989*7836SJohn.Forte@Sun.COM 							count++, i++) {
3990*7836SJohn.Forte@Sun.COM 			if (enc_type == DAK_ENC_TYPE) {
3991*7836SJohn.Forte@Sun.COM 				G_DPRINTF("  l_get_status: Getting individual"
3992*7836SJohn.Forte@Sun.COM 				    " State for disk in slot %d\n", count);
3993*7836SJohn.Forte@Sun.COM 			} else {
3994*7836SJohn.Forte@Sun.COM 				G_DPRINTF("  l_get_status: Getting individual"
3995*7836SJohn.Forte@Sun.COM 				    " State for front disk in slot %d\n", i);
3996*7836SJohn.Forte@Sun.COM 			}
3997*7836SJohn.Forte@Sun.COM 			if (err = l_get_individual_state(ses_path_front,
3998*7836SJohn.Forte@Sun.COM 			(struct l_disk_state_struct *)&l_state->drv_front[i],
3999*7836SJohn.Forte@Sun.COM 					&l_state->ib_tbl, front_flag, o_list,
4000*7836SJohn.Forte@Sun.COM 					wwn_list, verbose)) {
4001*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&o_list);
4002*7836SJohn.Forte@Sun.COM 				(void) g_free_wwn_list(&wwn_list);
4003*7836SJohn.Forte@Sun.COM 				return (err);
4004*7836SJohn.Forte@Sun.COM 			}
4005*7836SJohn.Forte@Sun.COM 		}
4006*7836SJohn.Forte@Sun.COM 	} else {
4007*7836SJohn.Forte@Sun.COM 		/* Set to loop not accessable. */
4008*7836SJohn.Forte@Sun.COM 		for (i = 0; i < l_state->total_num_drv/2; i++) {
4009*7836SJohn.Forte@Sun.COM 			l_state->drv_front[i].l_state_flag = L_NO_LOOP;
4010*7836SJohn.Forte@Sun.COM 		}
4011*7836SJohn.Forte@Sun.COM 	}
4012*7836SJohn.Forte@Sun.COM 	/*
4013*7836SJohn.Forte@Sun.COM 	 * For Daktari's, disk 0-5 information are located in the
4014*7836SJohn.Forte@Sun.COM 	 * l_state->drv_front array
4015*7836SJohn.Forte@Sun.COM 	 * For Daktari's, disk 6-11 information are located in the
4016*7836SJohn.Forte@Sun.COM 	 * l_state->drv_rear array
4017*7836SJohn.Forte@Sun.COM 	 *
4018*7836SJohn.Forte@Sun.COM 	 * For this reason, on daktari's, I ignore the found_front and
4019*7836SJohn.Forte@Sun.COM 	 * found_rear flags and check both the drv_front and drv_rear
4020*7836SJohn.Forte@Sun.COM 	 */
4021*7836SJohn.Forte@Sun.COM 
4022*7836SJohn.Forte@Sun.COM 	if (enc_type == DAK_ENC_TYPE && found_front) {
4023*7836SJohn.Forte@Sun.COM 		front_flag = 1;
4024*7836SJohn.Forte@Sun.COM 		for (i = 0; i < l_state->total_num_drv/2; i++, count++) {
4025*7836SJohn.Forte@Sun.COM 			G_DPRINTF("  l_get_status: Getting individual"
4026*7836SJohn.Forte@Sun.COM 				    " State for disk in slot %d\n", count);
4027*7836SJohn.Forte@Sun.COM 			if (err = l_get_individual_state(ses_path_front,
4028*7836SJohn.Forte@Sun.COM 			(struct l_disk_state_struct *)&l_state->drv_rear[i],
4029*7836SJohn.Forte@Sun.COM 					&l_state->ib_tbl, front_flag, o_list,
4030*7836SJohn.Forte@Sun.COM 					wwn_list, verbose)) {
4031*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&o_list);
4032*7836SJohn.Forte@Sun.COM 				(void) g_free_wwn_list(&wwn_list);
4033*7836SJohn.Forte@Sun.COM 				return (err);
4034*7836SJohn.Forte@Sun.COM 			}
4035*7836SJohn.Forte@Sun.COM 		}
4036*7836SJohn.Forte@Sun.COM 	} else if (enc_type != DAK_ENC_TYPE && found_rear) {
4037*7836SJohn.Forte@Sun.COM 		for (i = 0; i < l_state->total_num_drv/2; i++, count++) {
4038*7836SJohn.Forte@Sun.COM 				G_DPRINTF("  l_get_status: Getting individual"
4039*7836SJohn.Forte@Sun.COM 					" State for rear disk in slot %d\n", i);
4040*7836SJohn.Forte@Sun.COM 			if (err = l_get_individual_state(ses_path_rear,
4041*7836SJohn.Forte@Sun.COM 			    (struct l_disk_state_struct *)&l_state->drv_rear[i],
4042*7836SJohn.Forte@Sun.COM 			    &l_state->ib_tbl, front_flag, o_list,
4043*7836SJohn.Forte@Sun.COM 			    wwn_list, verbose)) {
4044*7836SJohn.Forte@Sun.COM 				(void) l_free_box_list(&o_list);
4045*7836SJohn.Forte@Sun.COM 				(void) g_free_wwn_list(&wwn_list);
4046*7836SJohn.Forte@Sun.COM 				return (err);
4047*7836SJohn.Forte@Sun.COM 			}
4048*7836SJohn.Forte@Sun.COM 		}
4049*7836SJohn.Forte@Sun.COM 	} else if (enc_type != DAK_ENC_TYPE) {
4050*7836SJohn.Forte@Sun.COM 		/* Set to loop not accessable. */
4051*7836SJohn.Forte@Sun.COM 		for (i = 0; i < l_state->total_num_drv/2; i++) {
4052*7836SJohn.Forte@Sun.COM 			l_state->drv_rear[i].l_state_flag = L_NO_LOOP;
4053*7836SJohn.Forte@Sun.COM 		}
4054*7836SJohn.Forte@Sun.COM 	}
4055*7836SJohn.Forte@Sun.COM 
4056*7836SJohn.Forte@Sun.COM 	(void) l_free_box_list(&o_list);
4057*7836SJohn.Forte@Sun.COM 	(void) g_free_wwn_list(&wwn_list);
4058*7836SJohn.Forte@Sun.COM 	if (getenv("_LUX_T_DEBUG") != NULL) {
4059*7836SJohn.Forte@Sun.COM 		end_time = gethrtime();
4060*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "  l_get_status:   "
4061*7836SJohn.Forte@Sun.COM 		"Time = %lld millisec\n",
4062*7836SJohn.Forte@Sun.COM 		(end_time - start_time)/1000000);
4063*7836SJohn.Forte@Sun.COM 	}
4064*7836SJohn.Forte@Sun.COM 
4065*7836SJohn.Forte@Sun.COM 	return (0);
4066*7836SJohn.Forte@Sun.COM }
4067*7836SJohn.Forte@Sun.COM 
4068*7836SJohn.Forte@Sun.COM 
4069*7836SJohn.Forte@Sun.COM 
4070*7836SJohn.Forte@Sun.COM /*
4071*7836SJohn.Forte@Sun.COM  * Check the SENA file for validity:
4072*7836SJohn.Forte@Sun.COM  *	- verify the size is that of 3 proms worth of text.
4073*7836SJohn.Forte@Sun.COM  *	- verify PROM_MAGIC.
4074*7836SJohn.Forte@Sun.COM  *	- verify (and print) the date.
4075*7836SJohn.Forte@Sun.COM  *	- verify the checksum.
4076*7836SJohn.Forte@Sun.COM  *	- verify the WWN == 0.
4077*7836SJohn.Forte@Sun.COM  * Since this requires reading the entire file, do it now and pass a pointer
4078*7836SJohn.Forte@Sun.COM  * to the allocated buffer back to the calling routine (which is responsible
4079*7836SJohn.Forte@Sun.COM  * for freeing it).  If the buffer is not allocated it will be NULL.
4080*7836SJohn.Forte@Sun.COM  *
4081*7836SJohn.Forte@Sun.COM  * RETURNS:
4082*7836SJohn.Forte@Sun.COM  *	0	 O.K.
4083*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4084*7836SJohn.Forte@Sun.COM  */
4085*7836SJohn.Forte@Sun.COM 
4086*7836SJohn.Forte@Sun.COM static int
check_file(int fd,int verbose,uchar_t ** buf_ptr,int dl_info_offset)4087*7836SJohn.Forte@Sun.COM check_file(int fd, int verbose, uchar_t **buf_ptr, int dl_info_offset)
4088*7836SJohn.Forte@Sun.COM {
4089*7836SJohn.Forte@Sun.COM struct	exec	the_exec;
4090*7836SJohn.Forte@Sun.COM int		temp, i, j, *p, size, *start;
4091*7836SJohn.Forte@Sun.COM uchar_t		*buf;
4092*7836SJohn.Forte@Sun.COM char		*date_str;
4093*7836SJohn.Forte@Sun.COM struct	dl_info	*dl_info;
4094*7836SJohn.Forte@Sun.COM 
4095*7836SJohn.Forte@Sun.COM 	*buf_ptr = NULL;
4096*7836SJohn.Forte@Sun.COM 
4097*7836SJohn.Forte@Sun.COM 	/* read exec header */
4098*7836SJohn.Forte@Sun.COM 	if (lseek(fd, 0, SEEK_SET) == -1)
4099*7836SJohn.Forte@Sun.COM 		return (errno);
4100*7836SJohn.Forte@Sun.COM 	if ((temp = read(fd, (char *)&the_exec, sizeof (the_exec))) == -1) {
4101*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4102*7836SJohn.Forte@Sun.COM 	}
4103*7836SJohn.Forte@Sun.COM 	if (temp != sizeof (the_exec)) {
4104*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_INCORRECT_BYTES);
4105*7836SJohn.Forte@Sun.COM 	}
4106*7836SJohn.Forte@Sun.COM 
4107*7836SJohn.Forte@Sun.COM 	if (the_exec.a_text != PROMSIZE) {
4108*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_INVALID_TEXT_SIZE);
4109*7836SJohn.Forte@Sun.COM 	}
4110*7836SJohn.Forte@Sun.COM 
4111*7836SJohn.Forte@Sun.COM 	if (!(buf = (uchar_t *)g_zalloc(PROMSIZE)))
4112*7836SJohn.Forte@Sun.COM 	    return (L_MALLOC_FAILED);
4113*7836SJohn.Forte@Sun.COM 
4114*7836SJohn.Forte@Sun.COM 	if ((temp = read(fd, buf, PROMSIZE)) == -1) {
4115*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_ERROR);
4116*7836SJohn.Forte@Sun.COM 	}
4117*7836SJohn.Forte@Sun.COM 
4118*7836SJohn.Forte@Sun.COM 	if (temp != PROMSIZE) {
4119*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_INCORRECT_BYTES);
4120*7836SJohn.Forte@Sun.COM 	}
4121*7836SJohn.Forte@Sun.COM 
4122*7836SJohn.Forte@Sun.COM 
4123*7836SJohn.Forte@Sun.COM 
4124*7836SJohn.Forte@Sun.COM 	/* check the IB firmware MAGIC */
4125*7836SJohn.Forte@Sun.COM 	dl_info = (struct dl_info *)(unsigned long)(buf + dl_info_offset);
4126*7836SJohn.Forte@Sun.COM 	if (dl_info->magic != PROM_MAGIC) {
4127*7836SJohn.Forte@Sun.COM 		return (L_DWNLD_BAD_FRMWARE);
4128*7836SJohn.Forte@Sun.COM 	}
4129*7836SJohn.Forte@Sun.COM 
4130*7836SJohn.Forte@Sun.COM 	/*
4131*7836SJohn.Forte@Sun.COM 	 * Get the date
4132*7836SJohn.Forte@Sun.COM 	 */
4133*7836SJohn.Forte@Sun.COM 
4134*7836SJohn.Forte@Sun.COM 	date_str = ctime(&dl_info->datecode);
4135*7836SJohn.Forte@Sun.COM 
4136*7836SJohn.Forte@Sun.COM 	if (verbose) {
4137*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
4138*7836SJohn.Forte@Sun.COM 		MSGSTR(9050, "  IB Prom Date: %s"),
4139*7836SJohn.Forte@Sun.COM 		date_str);
4140*7836SJohn.Forte@Sun.COM 	}
4141*7836SJohn.Forte@Sun.COM 
4142*7836SJohn.Forte@Sun.COM 	/*
4143*7836SJohn.Forte@Sun.COM 	 * verify checksum
4144*7836SJohn.Forte@Sun.COM 	 */
4145*7836SJohn.Forte@Sun.COM 
4146*7836SJohn.Forte@Sun.COM 	if (dl_info_offset == FPM_DL_INFO) {
4147*7836SJohn.Forte@Sun.COM 		start = (int *)(long)(buf + FPM_OFFSET);
4148*7836SJohn.Forte@Sun.COM 		size = FPM_SZ;
4149*7836SJohn.Forte@Sun.COM 	} else {
4150*7836SJohn.Forte@Sun.COM 		start = (int *)(long)buf;
4151*7836SJohn.Forte@Sun.COM 		size = TEXT_SZ + IDATA_SZ;
4152*7836SJohn.Forte@Sun.COM 	}
4153*7836SJohn.Forte@Sun.COM 
4154*7836SJohn.Forte@Sun.COM 	for (j = 0, p = start, i = 0; i < (size/ 4); i++, j ^= *p++);
4155*7836SJohn.Forte@Sun.COM 
4156*7836SJohn.Forte@Sun.COM 	if (j != 0) {
4157*7836SJohn.Forte@Sun.COM 		return (L_DWNLD_CHKSUM_FAILED);
4158*7836SJohn.Forte@Sun.COM 	}
4159*7836SJohn.Forte@Sun.COM 
4160*7836SJohn.Forte@Sun.COM 	/* file verified */
4161*7836SJohn.Forte@Sun.COM 	*buf_ptr = buf;
4162*7836SJohn.Forte@Sun.COM 
4163*7836SJohn.Forte@Sun.COM 	return (0);
4164*7836SJohn.Forte@Sun.COM }
4165*7836SJohn.Forte@Sun.COM 
4166*7836SJohn.Forte@Sun.COM /*
4167*7836SJohn.Forte@Sun.COM  * Check the DPM file for validity:
4168*7836SJohn.Forte@Sun.COM  *
4169*7836SJohn.Forte@Sun.COM  * RETURNS:
4170*7836SJohn.Forte@Sun.COM  *	0	 O.K.
4171*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4172*7836SJohn.Forte@Sun.COM  */
4173*7836SJohn.Forte@Sun.COM #define	dakstring	"64616B74617269"
4174*7836SJohn.Forte@Sun.COM #define	dakoffs		"BFC00000"
4175*7836SJohn.Forte@Sun.COM 
4176*7836SJohn.Forte@Sun.COM static int
check_dpm_file(int fd)4177*7836SJohn.Forte@Sun.COM check_dpm_file(int fd)
4178*7836SJohn.Forte@Sun.COM {
4179*7836SJohn.Forte@Sun.COM 	struct s3hdr {
4180*7836SJohn.Forte@Sun.COM 	    char	rtype[2];
4181*7836SJohn.Forte@Sun.COM 	    char	rlen[2];
4182*7836SJohn.Forte@Sun.COM 	    char	data[255];
4183*7836SJohn.Forte@Sun.COM 	} theRec;
4184*7836SJohn.Forte@Sun.COM 	int nread;
4185*7836SJohn.Forte@Sun.COM 	int reclen;
4186*7836SJohn.Forte@Sun.COM 
4187*7836SJohn.Forte@Sun.COM 	if (fd < 0) {
4188*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_ERROR);
4189*7836SJohn.Forte@Sun.COM 	}
4190*7836SJohn.Forte@Sun.COM 	lseek(fd, 0, SEEK_SET);
4191*7836SJohn.Forte@Sun.COM 
4192*7836SJohn.Forte@Sun.COM 	/* First record */
4193*7836SJohn.Forte@Sun.COM 	memset((void*)&theRec, 0, sizeof (struct s3hdr));
4194*7836SJohn.Forte@Sun.COM 	nread = read(fd, (void *)&theRec, 4);
4195*7836SJohn.Forte@Sun.COM 	if (nread != 4) {
4196*7836SJohn.Forte@Sun.COM 	    /* error reading first record/length */
4197*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_ERROR);
4198*7836SJohn.Forte@Sun.COM 	}
4199*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)&theRec.rtype[0], "S0", 2) != 0) {
4200*7836SJohn.Forte@Sun.COM 	    /* error in first record type */
4201*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4202*7836SJohn.Forte@Sun.COM 	}
4203*7836SJohn.Forte@Sun.COM 	reclen = strtol(&theRec.rlen[0], (char **)NULL, 16);
4204*7836SJohn.Forte@Sun.COM 	if (reclen == 0) {
4205*7836SJohn.Forte@Sun.COM 	    /* error in length == 0 */
4206*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4207*7836SJohn.Forte@Sun.COM 	}
4208*7836SJohn.Forte@Sun.COM 	nread = read(fd, (void *)&theRec.data[0], ((reclen*2) +1));
4209*7836SJohn.Forte@Sun.COM 	if (nread != ((reclen*2) +1)) {
4210*7836SJohn.Forte@Sun.COM 	    /* error in trying to read data */
4211*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4212*7836SJohn.Forte@Sun.COM 	}
4213*7836SJohn.Forte@Sun.COM 	if (strncmp(&theRec.data[4], dakstring, 14) != 0) {
4214*7836SJohn.Forte@Sun.COM 	    /* error in compiled file name */
4215*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4216*7836SJohn.Forte@Sun.COM 	}
4217*7836SJohn.Forte@Sun.COM 
4218*7836SJohn.Forte@Sun.COM 	/* Second record */
4219*7836SJohn.Forte@Sun.COM 	memset((void*)&theRec, 0, sizeof (struct s3hdr));
4220*7836SJohn.Forte@Sun.COM 	nread = read(fd, (void *)&theRec, 4);
4221*7836SJohn.Forte@Sun.COM 	if (nread != 4) {
4222*7836SJohn.Forte@Sun.COM 	    /* error reading second record/length */
4223*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_ERROR);
4224*7836SJohn.Forte@Sun.COM 	}
4225*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)&theRec.rtype[0], "S3", 2) != 0) {
4226*7836SJohn.Forte@Sun.COM 	    /* error in second record type */
4227*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4228*7836SJohn.Forte@Sun.COM 	}
4229*7836SJohn.Forte@Sun.COM 	reclen = strtol(&theRec.rlen[0], (char **)NULL, 16);
4230*7836SJohn.Forte@Sun.COM 	if (reclen == 0) {
4231*7836SJohn.Forte@Sun.COM 	    /* error in length == 0 */
4232*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4233*7836SJohn.Forte@Sun.COM 	}
4234*7836SJohn.Forte@Sun.COM 	nread = read(fd, (void *)&theRec.data[0], ((reclen*2) +1));
4235*7836SJohn.Forte@Sun.COM 	if (nread != ((reclen*2) +1)) {
4236*7836SJohn.Forte@Sun.COM 	    /* error in trying to read data */
4237*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4238*7836SJohn.Forte@Sun.COM 	}
4239*7836SJohn.Forte@Sun.COM 	if (strncmp(&theRec.data[0], dakoffs, 8) != 0) {
4240*7836SJohn.Forte@Sun.COM 	    /* error in SSC100 offset pointer */
4241*7836SJohn.Forte@Sun.COM 	    return (L_DWNLD_READ_HEADER_FAIL);
4242*7836SJohn.Forte@Sun.COM 	}
4243*7836SJohn.Forte@Sun.COM 	lseek(fd, 0, SEEK_SET);
4244*7836SJohn.Forte@Sun.COM 	return (0);
4245*7836SJohn.Forte@Sun.COM }
4246*7836SJohn.Forte@Sun.COM 
4247*7836SJohn.Forte@Sun.COM 
4248*7836SJohn.Forte@Sun.COM 
4249*7836SJohn.Forte@Sun.COM int
l_check_file(char * file,int verbose)4250*7836SJohn.Forte@Sun.COM l_check_file(char *file, int verbose)
4251*7836SJohn.Forte@Sun.COM {
4252*7836SJohn.Forte@Sun.COM int	file_fd;
4253*7836SJohn.Forte@Sun.COM int	err;
4254*7836SJohn.Forte@Sun.COM uchar_t	*buf;
4255*7836SJohn.Forte@Sun.COM 
4256*7836SJohn.Forte@Sun.COM 	if ((file_fd = g_object_open(file, O_RDONLY)) == -1) {
4257*7836SJohn.Forte@Sun.COM 	    return (L_OPEN_PATH_FAIL);
4258*7836SJohn.Forte@Sun.COM 	}
4259*7836SJohn.Forte@Sun.COM 	err = check_file(file_fd, verbose, &buf, FW_DL_INFO);
4260*7836SJohn.Forte@Sun.COM 	if (buf)
4261*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((char *)buf);
4262*7836SJohn.Forte@Sun.COM 	return (err);
4263*7836SJohn.Forte@Sun.COM }
4264*7836SJohn.Forte@Sun.COM 
4265*7836SJohn.Forte@Sun.COM 
4266*7836SJohn.Forte@Sun.COM 
4267*7836SJohn.Forte@Sun.COM /*
4268*7836SJohn.Forte@Sun.COM  * Write buffer command set up to download
4269*7836SJohn.Forte@Sun.COM  * firmware to the Photon IB.
4270*7836SJohn.Forte@Sun.COM  *
4271*7836SJohn.Forte@Sun.COM  * RETURNS:
4272*7836SJohn.Forte@Sun.COM  *	status
4273*7836SJohn.Forte@Sun.COM  */
4274*7836SJohn.Forte@Sun.COM static int
ib_download_code_cmd(int fd,int promid,int off,uchar_t * buf_ptr,int buf_len,int sp)4275*7836SJohn.Forte@Sun.COM ib_download_code_cmd(int fd, int promid, int off, uchar_t *buf_ptr,
4276*7836SJohn.Forte@Sun.COM 						int buf_len, int sp)
4277*7836SJohn.Forte@Sun.COM {
4278*7836SJohn.Forte@Sun.COM int	status, sz;
4279*7836SJohn.Forte@Sun.COM 
4280*7836SJohn.Forte@Sun.COM 	while (buf_len) {
4281*7836SJohn.Forte@Sun.COM 		sz = MIN(256, buf_len);
4282*7836SJohn.Forte@Sun.COM 		buf_len -= sz;
4283*7836SJohn.Forte@Sun.COM 		status = g_scsi_writebuffer_cmd(fd, off, buf_ptr, sz,
4284*7836SJohn.Forte@Sun.COM 						(sp) ? 3 : 2, promid);
4285*7836SJohn.Forte@Sun.COM 		if (status)
4286*7836SJohn.Forte@Sun.COM 			return (status);
4287*7836SJohn.Forte@Sun.COM 		buf_ptr += sz;
4288*7836SJohn.Forte@Sun.COM 		off += sz;
4289*7836SJohn.Forte@Sun.COM 	}
4290*7836SJohn.Forte@Sun.COM 
4291*7836SJohn.Forte@Sun.COM 	return (status);
4292*7836SJohn.Forte@Sun.COM }
4293*7836SJohn.Forte@Sun.COM 
4294*7836SJohn.Forte@Sun.COM /*
4295*7836SJohn.Forte@Sun.COM  *
4296*7836SJohn.Forte@Sun.COM  * Downloads the code to the DAKTARI/DPM with the hdr set correctly
4297*7836SJohn.Forte@Sun.COM  *
4298*7836SJohn.Forte@Sun.COM  *
4299*7836SJohn.Forte@Sun.COM  * Inputs:
4300*7836SJohn.Forte@Sun.COM  *	fd - int for the file descriptor
4301*7836SJohn.Forte@Sun.COM  *	buf_ptr - uchar_t pointer to the firmware itself
4302*7836SJohn.Forte@Sun.COM  *	buf_len - int for the length of the data
4303*7836SJohn.Forte@Sun.COM  *
4304*7836SJohn.Forte@Sun.COM  * Returns:
4305*7836SJohn.Forte@Sun.COM  *	status:  0 indicates success, != 0 failure, returned from writebuffer
4306*7836SJohn.Forte@Sun.COM  *
4307*7836SJohn.Forte@Sun.COM  */
4308*7836SJohn.Forte@Sun.COM 
4309*7836SJohn.Forte@Sun.COM static int
dak_download_code_cmd(int fd,uchar_t * buf_ptr,int buf_len)4310*7836SJohn.Forte@Sun.COM dak_download_code_cmd(int fd, uchar_t *buf_ptr, int buf_len)
4311*7836SJohn.Forte@Sun.COM {
4312*7836SJohn.Forte@Sun.COM 	int 	status = 0;
4313*7836SJohn.Forte@Sun.COM 	int	sz = 0;
4314*7836SJohn.Forte@Sun.COM 	int	offs = 0;
4315*7836SJohn.Forte@Sun.COM 
4316*7836SJohn.Forte@Sun.COM 	while (buf_len > 0) {
4317*7836SJohn.Forte@Sun.COM 		sz = MIN(256, buf_len);
4318*7836SJohn.Forte@Sun.COM 		buf_len -= sz;
4319*7836SJohn.Forte@Sun.COM 		status = g_scsi_writebuffer_cmd(fd, offs, buf_ptr, sz, 0x07, 0);
4320*7836SJohn.Forte@Sun.COM 		if (status != 0) {
4321*7836SJohn.Forte@Sun.COM 		    return (status);
4322*7836SJohn.Forte@Sun.COM 		}
4323*7836SJohn.Forte@Sun.COM 		buf_ptr += sz;
4324*7836SJohn.Forte@Sun.COM 		offs += sz;
4325*7836SJohn.Forte@Sun.COM 	}
4326*7836SJohn.Forte@Sun.COM 	return (status);
4327*7836SJohn.Forte@Sun.COM }
4328*7836SJohn.Forte@Sun.COM 
4329*7836SJohn.Forte@Sun.COM 
4330*7836SJohn.Forte@Sun.COM 
4331*7836SJohn.Forte@Sun.COM 
4332*7836SJohn.Forte@Sun.COM /*
4333*7836SJohn.Forte@Sun.COM  * Downloads the new prom image to IB.
4334*7836SJohn.Forte@Sun.COM  *
4335*7836SJohn.Forte@Sun.COM  * INPUTS:
4336*7836SJohn.Forte@Sun.COM  * 	path		- physical path of Photon SES card
4337*7836SJohn.Forte@Sun.COM  * 	file		- input file for new code (may be NULL)
4338*7836SJohn.Forte@Sun.COM  * 	ps		- whether the "save" bit should be set
4339*7836SJohn.Forte@Sun.COM  * 	verbose		- to be verbose or not
4340*7836SJohn.Forte@Sun.COM  *
4341*7836SJohn.Forte@Sun.COM  * RETURNS:
4342*7836SJohn.Forte@Sun.COM  *	0	 O.K.
4343*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4344*7836SJohn.Forte@Sun.COM  */
4345*7836SJohn.Forte@Sun.COM int
l_download(char * path_phys,char * file,int ps,int verbose)4346*7836SJohn.Forte@Sun.COM l_download(char *path_phys, char *file, int ps, int verbose)
4347*7836SJohn.Forte@Sun.COM {
4348*7836SJohn.Forte@Sun.COM int		file_fd, controller_fd;
4349*7836SJohn.Forte@Sun.COM int		err, status;
4350*7836SJohn.Forte@Sun.COM uchar_t		*buf_ptr;
4351*7836SJohn.Forte@Sun.COM char		printbuf[MAXPATHLEN];
4352*7836SJohn.Forte@Sun.COM int		retry;
4353*7836SJohn.Forte@Sun.COM char		file_path[MAXPATHLEN];
4354*7836SJohn.Forte@Sun.COM struct stat	statbuf;
4355*7836SJohn.Forte@Sun.COM int		enc_type;
4356*7836SJohn.Forte@Sun.COM L_inquiry	inq;
4357*7836SJohn.Forte@Sun.COM 
4358*7836SJohn.Forte@Sun.COM 	if (path_phys == NULL) {
4359*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
4360*7836SJohn.Forte@Sun.COM 	}
4361*7836SJohn.Forte@Sun.COM 
4362*7836SJohn.Forte@Sun.COM 	if (!file) {
4363*7836SJohn.Forte@Sun.COM 		(void) strcpy(file_path, IBFIRMWARE_FILE);
4364*7836SJohn.Forte@Sun.COM 	} else {
4365*7836SJohn.Forte@Sun.COM 		(void) strncpy(file_path, file, sizeof (file_path));
4366*7836SJohn.Forte@Sun.COM 	}
4367*7836SJohn.Forte@Sun.COM 	if (verbose)
4368*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n",
4369*7836SJohn.Forte@Sun.COM 			MSGSTR(9051, "  Opening the IB for I/O."));
4370*7836SJohn.Forte@Sun.COM 
4371*7836SJohn.Forte@Sun.COM 	if ((controller_fd = g_object_open(path_phys, O_NDELAY | O_RDWR)) == -1)
4372*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
4373*7836SJohn.Forte@Sun.COM 
4374*7836SJohn.Forte@Sun.COM 	(void) sprintf(printbuf, MSGSTR(9052, "  Doing download to:"
4375*7836SJohn.Forte@Sun.COM 			"\n\t%s.\n  From file: %s."), path_phys, file_path);
4376*7836SJohn.Forte@Sun.COM 
4377*7836SJohn.Forte@Sun.COM 	if (verbose)
4378*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n", printbuf);
4379*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  Doing download to:"
4380*7836SJohn.Forte@Sun.COM 			"\n\t%s\n  From file: %s\n", path_phys, file_path);
4381*7836SJohn.Forte@Sun.COM 
4382*7836SJohn.Forte@Sun.COM 	if ((file_fd = g_object_open(file_path, O_NDELAY | O_RDONLY)) == -1) {
4383*7836SJohn.Forte@Sun.COM 		/*
4384*7836SJohn.Forte@Sun.COM 		 * Return a different error code here to differentiate between
4385*7836SJohn.Forte@Sun.COM 		 * this failure in g_object_open() and the one above.
4386*7836SJohn.Forte@Sun.COM 		 */
4387*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH);
4388*7836SJohn.Forte@Sun.COM 	}
4389*7836SJohn.Forte@Sun.COM 
4390*7836SJohn.Forte@Sun.COM 	if (g_scsi_inquiry_cmd(controller_fd, (uchar_t *)&inq, sizeof (inq))) {
4391*7836SJohn.Forte@Sun.COM 	    return (L_SCSI_ERROR);
4392*7836SJohn.Forte@Sun.COM 	}
4393*7836SJohn.Forte@Sun.COM 	enc_type = l_get_enc_type(inq);
4394*7836SJohn.Forte@Sun.COM 	switch (enc_type) {
4395*7836SJohn.Forte@Sun.COM 	case DAK_ENC_TYPE:
4396*7836SJohn.Forte@Sun.COM 	/*
4397*7836SJohn.Forte@Sun.COM 	 * We don't have a default daktari file location, so
4398*7836SJohn.Forte@Sun.COM 	 * the user must specify the firmware file on the command line
4399*7836SJohn.Forte@Sun.COM 	 */
4400*7836SJohn.Forte@Sun.COM 	    if (!file) {
4401*7836SJohn.Forte@Sun.COM 		return (L_REQUIRE_FILE);
4402*7836SJohn.Forte@Sun.COM 	    }
4403*7836SJohn.Forte@Sun.COM 	    /* Validate the file */
4404*7836SJohn.Forte@Sun.COM 	    if ((err = check_dpm_file(file_fd))) {
4405*7836SJohn.Forte@Sun.COM 		return (err);
4406*7836SJohn.Forte@Sun.COM 	    }
4407*7836SJohn.Forte@Sun.COM 	    /* Now go ahead and load up the data */
4408*7836SJohn.Forte@Sun.COM 	    if (fstat(file_fd, &statbuf) == -1) {
4409*7836SJohn.Forte@Sun.COM 		err = errno;
4410*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s  %s\n",
4411*7836SJohn.Forte@Sun.COM 		    MSGSTR(9101, "  Stat'ing the F/W file:"), strerror(err));
4412*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
4413*7836SJohn.Forte@Sun.COM 	    }
4414*7836SJohn.Forte@Sun.COM 	    buf_ptr = (uchar_t *)g_zalloc(statbuf.st_size);
4415*7836SJohn.Forte@Sun.COM 	    if (buf_ptr == NULL) {
4416*7836SJohn.Forte@Sun.COM 		err = errno;
4417*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s  %s\n",
4418*7836SJohn.Forte@Sun.COM 		    MSGSTR(9102, "  Cannot alloc mem to read F/W file:"),
4419*7836SJohn.Forte@Sun.COM 		    strerror(err));
4420*7836SJohn.Forte@Sun.COM 		return (L_MALLOC_FAILED);
4421*7836SJohn.Forte@Sun.COM 	    }
4422*7836SJohn.Forte@Sun.COM 	    if (read(file_fd, buf_ptr, statbuf.st_size) == -1) {
4423*7836SJohn.Forte@Sun.COM 		err = errno;
4424*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s  %s\n",
4425*7836SJohn.Forte@Sun.COM 		    MSGSTR(9103, "  Reading F/W file:"), strerror(err));
4426*7836SJohn.Forte@Sun.COM 		g_destroy_data((char *)buf_ptr);
4427*7836SJohn.Forte@Sun.COM 		return (L_DWNLD_READ_ERROR);
4428*7836SJohn.Forte@Sun.COM 	    }
4429*7836SJohn.Forte@Sun.COM 	    break;
4430*7836SJohn.Forte@Sun.COM 	default:
4431*7836SJohn.Forte@Sun.COM 	    if (err = check_file(file_fd, verbose, &buf_ptr, FW_DL_INFO)) {
4432*7836SJohn.Forte@Sun.COM 		if (buf_ptr) {
4433*7836SJohn.Forte@Sun.COM 		    (void) g_destroy_data((char *)buf_ptr);
4434*7836SJohn.Forte@Sun.COM 		    return (err);
4435*7836SJohn.Forte@Sun.COM 		}
4436*7836SJohn.Forte@Sun.COM 	    }
4437*7836SJohn.Forte@Sun.COM 	    break;
4438*7836SJohn.Forte@Sun.COM 	}
4439*7836SJohn.Forte@Sun.COM 
4440*7836SJohn.Forte@Sun.COM 	if (verbose) {
4441*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "  ");
4442*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, MSGSTR(127, "Checkfile O.K."));
4443*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "\n");
4444*7836SJohn.Forte@Sun.COM 	}
4445*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  Checkfile OK.\n");
4446*7836SJohn.Forte@Sun.COM 	(void) close(file_fd);
4447*7836SJohn.Forte@Sun.COM 
4448*7836SJohn.Forte@Sun.COM 	if (verbose) {
4449*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, MSGSTR(9053,
4450*7836SJohn.Forte@Sun.COM 			"  Verifying the IB is available.\n"));
4451*7836SJohn.Forte@Sun.COM 	}
4452*7836SJohn.Forte@Sun.COM 
4453*7836SJohn.Forte@Sun.COM 	retry = DOWNLOAD_RETRIES;
4454*7836SJohn.Forte@Sun.COM 	while (retry) {
4455*7836SJohn.Forte@Sun.COM 		if ((status = g_scsi_tur(controller_fd)) == 0) {
4456*7836SJohn.Forte@Sun.COM 			break;
4457*7836SJohn.Forte@Sun.COM 		} else {
4458*7836SJohn.Forte@Sun.COM 			if ((retry % 30) == 0) {
4459*7836SJohn.Forte@Sun.COM 				ER_DPRINTF(" Waiting for the IB to be"
4460*7836SJohn.Forte@Sun.COM 						" available.\n");
4461*7836SJohn.Forte@Sun.COM 			}
4462*7836SJohn.Forte@Sun.COM 			(void) sleep(1);
4463*7836SJohn.Forte@Sun.COM 		}
4464*7836SJohn.Forte@Sun.COM 	}
4465*7836SJohn.Forte@Sun.COM 	if (!retry) {
4466*7836SJohn.Forte@Sun.COM 		if (buf_ptr)
4467*7836SJohn.Forte@Sun.COM 			(void) g_destroy_data((char *)buf_ptr);
4468*7836SJohn.Forte@Sun.COM 		(void) close(controller_fd);
4469*7836SJohn.Forte@Sun.COM 		return (status);
4470*7836SJohn.Forte@Sun.COM 	}
4471*7836SJohn.Forte@Sun.COM 
4472*7836SJohn.Forte@Sun.COM 	if (verbose)
4473*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n",
4474*7836SJohn.Forte@Sun.COM 			MSGSTR(9054, "  Writing new text image to IB."));
4475*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  Writing new image to IB\n");
4476*7836SJohn.Forte@Sun.COM 	switch (enc_type) {
4477*7836SJohn.Forte@Sun.COM 	case DAK_ENC_TYPE:
4478*7836SJohn.Forte@Sun.COM 	    status = dak_download_code_cmd(controller_fd, buf_ptr,
4479*7836SJohn.Forte@Sun.COM 		statbuf.st_size);
4480*7836SJohn.Forte@Sun.COM 	    if (status != 0) {
4481*7836SJohn.Forte@Sun.COM 		if (buf_ptr != NULL) {
4482*7836SJohn.Forte@Sun.COM 		    g_destroy_data((char *)buf_ptr);
4483*7836SJohn.Forte@Sun.COM 		}
4484*7836SJohn.Forte@Sun.COM 		(void) close(controller_fd);
4485*7836SJohn.Forte@Sun.COM 		return (status);
4486*7836SJohn.Forte@Sun.COM 	    }
4487*7836SJohn.Forte@Sun.COM 	    break;
4488*7836SJohn.Forte@Sun.COM 	default:
4489*7836SJohn.Forte@Sun.COM 	    status = ib_download_code_cmd(controller_fd, IBEEPROM, TEXT_OFFSET,
4490*7836SJohn.Forte@Sun.COM 		(uchar_t *)(buf_ptr + TEXT_OFFSET), TEXT_SZ, ps);
4491*7836SJohn.Forte@Sun.COM 	    if (status) {
4492*7836SJohn.Forte@Sun.COM 		(void) close(controller_fd);
4493*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((char *)buf_ptr);
4494*7836SJohn.Forte@Sun.COM 		return (status);
4495*7836SJohn.Forte@Sun.COM 	    }
4496*7836SJohn.Forte@Sun.COM 	    if (verbose) {
4497*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n",
4498*7836SJohn.Forte@Sun.COM 		    MSGSTR(9055, "  Writing new data image to IB."));
4499*7836SJohn.Forte@Sun.COM 	    }
4500*7836SJohn.Forte@Sun.COM 	    status = ib_download_code_cmd(controller_fd, IBEEPROM, IDATA_OFFSET,
4501*7836SJohn.Forte@Sun.COM 		(uchar_t *)(buf_ptr + IDATA_OFFSET), IDATA_SZ, ps);
4502*7836SJohn.Forte@Sun.COM 	    if (status) {
4503*7836SJohn.Forte@Sun.COM 		(void) close(controller_fd);
4504*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((char *)buf_ptr);
4505*7836SJohn.Forte@Sun.COM 		return (status);
4506*7836SJohn.Forte@Sun.COM 	    }
4507*7836SJohn.Forte@Sun.COM 	    break;
4508*7836SJohn.Forte@Sun.COM 	}
4509*7836SJohn.Forte@Sun.COM 
4510*7836SJohn.Forte@Sun.COM 
4511*7836SJohn.Forte@Sun.COM 	if (verbose) {
4512*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, MSGSTR(9056,
4513*7836SJohn.Forte@Sun.COM 			"  Re-verifying the IB is available.\n"));
4514*7836SJohn.Forte@Sun.COM 	}
4515*7836SJohn.Forte@Sun.COM 
4516*7836SJohn.Forte@Sun.COM 	retry = DOWNLOAD_RETRIES;
4517*7836SJohn.Forte@Sun.COM 	while (retry) {
4518*7836SJohn.Forte@Sun.COM 		if ((status = g_scsi_tur(controller_fd)) == 0) {
4519*7836SJohn.Forte@Sun.COM 			break;
4520*7836SJohn.Forte@Sun.COM 		} else {
4521*7836SJohn.Forte@Sun.COM 			if ((retry % 30) == 0) {
4522*7836SJohn.Forte@Sun.COM 				ER_DPRINTF("  Waiting for the IB to be"
4523*7836SJohn.Forte@Sun.COM 					" available.\n");
4524*7836SJohn.Forte@Sun.COM 			}
4525*7836SJohn.Forte@Sun.COM 			(void) sleep(1);
4526*7836SJohn.Forte@Sun.COM 		}
4527*7836SJohn.Forte@Sun.COM 		retry--;
4528*7836SJohn.Forte@Sun.COM 	}
4529*7836SJohn.Forte@Sun.COM 	if (!retry) {
4530*7836SJohn.Forte@Sun.COM 		(void) close(controller_fd);
4531*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((char *)buf_ptr);
4532*7836SJohn.Forte@Sun.COM 		return (L_DWNLD_TIMED_OUT);
4533*7836SJohn.Forte@Sun.COM 	}
4534*7836SJohn.Forte@Sun.COM 
4535*7836SJohn.Forte@Sun.COM 	switch (enc_type) {
4536*7836SJohn.Forte@Sun.COM 	case DAK_ENC_TYPE:
4537*7836SJohn.Forte@Sun.COM 	    break;
4538*7836SJohn.Forte@Sun.COM 	default:
4539*7836SJohn.Forte@Sun.COM 	    if (verbose) {
4540*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout, "%s\n",
4541*7836SJohn.Forte@Sun.COM 		    MSGSTR(9057, "  Writing new image to FPM."));
4542*7836SJohn.Forte@Sun.COM 	    }
4543*7836SJohn.Forte@Sun.COM 	    status = ib_download_code_cmd(controller_fd, MBEEPROM, FPM_OFFSET,
4544*7836SJohn.Forte@Sun.COM 	    (uchar_t *)(buf_ptr + FPM_OFFSET), FPM_SZ, ps);
4545*7836SJohn.Forte@Sun.COM 	    break;
4546*7836SJohn.Forte@Sun.COM 	}
4547*7836SJohn.Forte@Sun.COM 
4548*7836SJohn.Forte@Sun.COM 	if ((!status) && ps) {
4549*7836SJohn.Forte@Sun.COM 		/*
4550*7836SJohn.Forte@Sun.COM 		 * Reset the IB
4551*7836SJohn.Forte@Sun.COM 		 */
4552*7836SJohn.Forte@Sun.COM 		status = g_scsi_reset(controller_fd);
4553*7836SJohn.Forte@Sun.COM 	}
4554*7836SJohn.Forte@Sun.COM 
4555*7836SJohn.Forte@Sun.COM 	(void) close(controller_fd);
4556*7836SJohn.Forte@Sun.COM 	return (status);
4557*7836SJohn.Forte@Sun.COM }
4558*7836SJohn.Forte@Sun.COM 
4559*7836SJohn.Forte@Sun.COM /*
4560*7836SJohn.Forte@Sun.COM  * Set the World Wide Name
4561*7836SJohn.Forte@Sun.COM  * in page 4 of the Send Diagnostic command.
4562*7836SJohn.Forte@Sun.COM  *
4563*7836SJohn.Forte@Sun.COM  * Is it allowed to change the wwn ???
4564*7836SJohn.Forte@Sun.COM  * The path must point to an IB.
4565*7836SJohn.Forte@Sun.COM  *
4566*7836SJohn.Forte@Sun.COM  */
4567*7836SJohn.Forte@Sun.COM int
l_set_wwn(char * path_phys,char * wwn)4568*7836SJohn.Forte@Sun.COM l_set_wwn(char *path_phys, char *wwn)
4569*7836SJohn.Forte@Sun.COM {
4570*7836SJohn.Forte@Sun.COM Page4_name	page4;
4571*7836SJohn.Forte@Sun.COM L_inquiry	inq;
4572*7836SJohn.Forte@Sun.COM int		fd, status;
4573*7836SJohn.Forte@Sun.COM char		wwnp[WWN_SIZE];
4574*7836SJohn.Forte@Sun.COM 
4575*7836SJohn.Forte@Sun.COM 	(void) memset(&inq, 0, sizeof (inq));
4576*7836SJohn.Forte@Sun.COM 	(void) memset(&page4, 0, sizeof (page4));
4577*7836SJohn.Forte@Sun.COM 
4578*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(path_phys, O_NDELAY | O_RDONLY)) == -1) {
4579*7836SJohn.Forte@Sun.COM 		return (L_OPEN_PATH_FAIL);
4580*7836SJohn.Forte@Sun.COM 	}
4581*7836SJohn.Forte@Sun.COM 	/* Verify it is a Photon */
4582*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_inquiry_cmd(fd,
4583*7836SJohn.Forte@Sun.COM 		(uchar_t *)&inq, sizeof (struct l_inquiry_struct))) {
4584*7836SJohn.Forte@Sun.COM 		(void) close(fd);
4585*7836SJohn.Forte@Sun.COM 		return (status);
4586*7836SJohn.Forte@Sun.COM 	}
4587*7836SJohn.Forte@Sun.COM 	if ((strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) == 0) &&
4588*7836SJohn.Forte@Sun.COM 		(!(strncmp((char *)inq.inq_vid, "SUN     ",
4589*7836SJohn.Forte@Sun.COM 		sizeof (inq.inq_vid)) &&
4590*7836SJohn.Forte@Sun.COM 		((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)))) {
4591*7836SJohn.Forte@Sun.COM 		(void) close(fd);
4592*7836SJohn.Forte@Sun.COM 		return (L_ENCL_INVALID_PATH);
4593*7836SJohn.Forte@Sun.COM 	}
4594*7836SJohn.Forte@Sun.COM 
4595*7836SJohn.Forte@Sun.COM 	page4.page_code = L_PAGE_4;
4596*7836SJohn.Forte@Sun.COM 	page4.page_len = (ushort_t)((sizeof (struct page4_name) - 4));
4597*7836SJohn.Forte@Sun.COM 	page4.string_code = L_WWN;
4598*7836SJohn.Forte@Sun.COM 	page4.enable = 1;
4599*7836SJohn.Forte@Sun.COM 	if (g_string_to_wwn((uchar_t *)wwn, (uchar_t *)&page4.name)) {
4600*7836SJohn.Forte@Sun.COM 		close(fd);
4601*7836SJohn.Forte@Sun.COM 		return (EINVAL);
4602*7836SJohn.Forte@Sun.COM 	}
4603*7836SJohn.Forte@Sun.COM 	bcopy((void *)wwnp, (void *)page4.name, (size_t)WWN_SIZE);
4604*7836SJohn.Forte@Sun.COM 
4605*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_send_diag_cmd(fd, (uchar_t *)&page4,
4606*7836SJohn.Forte@Sun.COM 		sizeof (page4))) {
4607*7836SJohn.Forte@Sun.COM 		(void) close(fd);
4608*7836SJohn.Forte@Sun.COM 		return (status);
4609*7836SJohn.Forte@Sun.COM 	}
4610*7836SJohn.Forte@Sun.COM 
4611*7836SJohn.Forte@Sun.COM 	/*
4612*7836SJohn.Forte@Sun.COM 	 * Check the wwn really changed.
4613*7836SJohn.Forte@Sun.COM 	 */
4614*7836SJohn.Forte@Sun.COM 	bzero((char *)page4.name, 32);
4615*7836SJohn.Forte@Sun.COM 	if (status = g_scsi_rec_diag_cmd(fd, (uchar_t *)&page4,
4616*7836SJohn.Forte@Sun.COM 				sizeof (page4), L_PAGE_4)) {
4617*7836SJohn.Forte@Sun.COM 		(void) close(fd);
4618*7836SJohn.Forte@Sun.COM 		return (status);
4619*7836SJohn.Forte@Sun.COM 	}
4620*7836SJohn.Forte@Sun.COM 	if (bcmp((char *)page4.name, wwnp, WWN_SIZE)) {
4621*7836SJohn.Forte@Sun.COM 		(void) close(fd);
4622*7836SJohn.Forte@Sun.COM 		return (L_WARNING);
4623*7836SJohn.Forte@Sun.COM 	}
4624*7836SJohn.Forte@Sun.COM 
4625*7836SJohn.Forte@Sun.COM 	(void) close(fd);
4626*7836SJohn.Forte@Sun.COM 	return (0);
4627*7836SJohn.Forte@Sun.COM }
4628*7836SJohn.Forte@Sun.COM 
4629*7836SJohn.Forte@Sun.COM 
4630*7836SJohn.Forte@Sun.COM 
4631*7836SJohn.Forte@Sun.COM /*
4632*7836SJohn.Forte@Sun.COM  * Use a physical path to a disk in a Photon box
4633*7836SJohn.Forte@Sun.COM  * as the base to genererate a path to a SES
4634*7836SJohn.Forte@Sun.COM  * card in this box.
4635*7836SJohn.Forte@Sun.COM  *
4636*7836SJohn.Forte@Sun.COM  * path_phys: Physical path to a Photon disk.
4637*7836SJohn.Forte@Sun.COM  * ses_path:  This must be a pointer to an already allocated path string.
4638*7836SJohn.Forte@Sun.COM  *
4639*7836SJohn.Forte@Sun.COM  * RETURNS:
4640*7836SJohn.Forte@Sun.COM  *	0	 O.K.
4641*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4642*7836SJohn.Forte@Sun.COM  */
4643*7836SJohn.Forte@Sun.COM int
l_get_ses_path(char * path_phys,char * ses_path,gfc_map_t * map,int verbose)4644*7836SJohn.Forte@Sun.COM l_get_ses_path(char *path_phys, char *ses_path, gfc_map_t *map,
4645*7836SJohn.Forte@Sun.COM 	int verbose)
4646*7836SJohn.Forte@Sun.COM {
4647*7836SJohn.Forte@Sun.COM char	*char_ptr, id_buf[MAXPATHLEN], wwn[20];
4648*7836SJohn.Forte@Sun.COM uchar_t	t_wwn[20], *ses_wwn, *ses_wwn1, *ses_nwwn;
4649*7836SJohn.Forte@Sun.COM int	j, al_pa, al_pa1, box_id, fd, disk_flag = 0;
4650*7836SJohn.Forte@Sun.COM int	err, found = 0;
4651*7836SJohn.Forte@Sun.COM gfc_port_dev_info_t	*dev_addr_ptr;
4652*7836SJohn.Forte@Sun.COM 
4653*7836SJohn.Forte@Sun.COM 	if ((path_phys == NULL) || (ses_path == NULL) || (map == NULL)) {
4654*7836SJohn.Forte@Sun.COM 		return (L_NO_SES_PATH);
4655*7836SJohn.Forte@Sun.COM 	}
4656*7836SJohn.Forte@Sun.COM 
4657*7836SJohn.Forte@Sun.COM 	(void) strcpy(ses_path, path_phys);
4658*7836SJohn.Forte@Sun.COM 	if ((char_ptr = strrchr(ses_path, '/')) == NULL) {
4659*7836SJohn.Forte@Sun.COM 			return (L_INVLD_PATH_NO_SLASH_FND);
4660*7836SJohn.Forte@Sun.COM 	}
4661*7836SJohn.Forte@Sun.COM 	disk_flag++;
4662*7836SJohn.Forte@Sun.COM 	*char_ptr = '\0';   /* Terminate sting  */
4663*7836SJohn.Forte@Sun.COM 	(void) strcat(ses_path, SLSH_SES_NAME);
4664*7836SJohn.Forte@Sun.COM 
4665*7836SJohn.Forte@Sun.COM 	/*
4666*7836SJohn.Forte@Sun.COM 	 * Figure out and create the boxes pathname.
4667*7836SJohn.Forte@Sun.COM 	 *
4668*7836SJohn.Forte@Sun.COM 	 * NOTE: This uses the fact that the disks's
4669*7836SJohn.Forte@Sun.COM 	 * AL_PA and the boxes AL_PA must match
4670*7836SJohn.Forte@Sun.COM 	 * the assigned hard address in the current
4671*7836SJohn.Forte@Sun.COM 	 * implementations. This may not be true in the
4672*7836SJohn.Forte@Sun.COM 	 * future.
4673*7836SJohn.Forte@Sun.COM 	 */
4674*7836SJohn.Forte@Sun.COM 	if ((char_ptr = strrchr(path_phys, '@')) == NULL) {
4675*7836SJohn.Forte@Sun.COM 		return (L_INVLD_PATH_NO_ATSIGN_FND);
4676*7836SJohn.Forte@Sun.COM 	}
4677*7836SJohn.Forte@Sun.COM 	char_ptr++;	/* point to the loop identifier */
4678*7836SJohn.Forte@Sun.COM 
4679*7836SJohn.Forte@Sun.COM 	if ((err = g_get_wwn(path_phys, t_wwn, t_wwn,
4680*7836SJohn.Forte@Sun.COM 		&al_pa, verbose)) != 0) {
4681*7836SJohn.Forte@Sun.COM 		return (err);
4682*7836SJohn.Forte@Sun.COM 	}
4683*7836SJohn.Forte@Sun.COM 	box_id = g_sf_alpa_to_switch[al_pa & 0xFF] & BOX_ID_MASK;
4684*7836SJohn.Forte@Sun.COM 
4685*7836SJohn.Forte@Sun.COM 	switch (map->hba_addr.port_topology) {
4686*7836SJohn.Forte@Sun.COM 	case FC_TOP_PRIVATE_LOOP:
4687*7836SJohn.Forte@Sun.COM 		for (j = 0, dev_addr_ptr = map->dev_addr;
4688*7836SJohn.Forte@Sun.COM 			j < map->count; j++, dev_addr_ptr++) {
4689*7836SJohn.Forte@Sun.COM 		    if (dev_addr_ptr->gfc_port_dev.priv_port.
4690*7836SJohn.Forte@Sun.COM 			sf_inq_dtype == DTYPE_ESI) {
4691*7836SJohn.Forte@Sun.COM 			al_pa1 = dev_addr_ptr->gfc_port_dev.
4692*7836SJohn.Forte@Sun.COM 				priv_port.sf_al_pa;
4693*7836SJohn.Forte@Sun.COM 			if (box_id == (g_sf_alpa_to_switch[al_pa1] &
4694*7836SJohn.Forte@Sun.COM 				BOX_ID_MASK)) {
4695*7836SJohn.Forte@Sun.COM 			    if (!found) {
4696*7836SJohn.Forte@Sun.COM 				ses_wwn = dev_addr_ptr->
4697*7836SJohn.Forte@Sun.COM 					gfc_port_dev.priv_port.sf_port_wwn;
4698*7836SJohn.Forte@Sun.COM 				ses_nwwn = dev_addr_ptr->
4699*7836SJohn.Forte@Sun.COM 					gfc_port_dev.priv_port.sf_node_wwn;
4700*7836SJohn.Forte@Sun.COM 				if (getenv("_LUX_P_DEBUG")) {
4701*7836SJohn.Forte@Sun.COM 					(void) g_ll_to_str(ses_wwn,
4702*7836SJohn.Forte@Sun.COM 						(char *)t_wwn);
4703*7836SJohn.Forte@Sun.COM 					(void) printf(
4704*7836SJohn.Forte@Sun.COM 					"  l_get_ses_path: "
4705*7836SJohn.Forte@Sun.COM 					"Found ses wwn = %s "
4706*7836SJohn.Forte@Sun.COM 					"al_pa 0x%x\n", t_wwn, al_pa1);
4707*7836SJohn.Forte@Sun.COM 				}
4708*7836SJohn.Forte@Sun.COM 			} else {
4709*7836SJohn.Forte@Sun.COM 				ses_wwn1 = dev_addr_ptr->
4710*7836SJohn.Forte@Sun.COM 				    gfc_port_dev.priv_port.sf_port_wwn;
4711*7836SJohn.Forte@Sun.COM 				if (getenv("_LUX_P_DEBUG")) {
4712*7836SJohn.Forte@Sun.COM 					(void) g_ll_to_str(ses_wwn1,
4713*7836SJohn.Forte@Sun.COM 							(char *)t_wwn);
4714*7836SJohn.Forte@Sun.COM 					(void) printf(
4715*7836SJohn.Forte@Sun.COM 						"  l_get_ses_path: "
4716*7836SJohn.Forte@Sun.COM 						"Found second ses " "wwn = %s "
4717*7836SJohn.Forte@Sun.COM 						"al_pa 0x%x\n", t_wwn, al_pa1);
4718*7836SJohn.Forte@Sun.COM 				}
4719*7836SJohn.Forte@Sun.COM 			    }
4720*7836SJohn.Forte@Sun.COM 			    found++;
4721*7836SJohn.Forte@Sun.COM 			}
4722*7836SJohn.Forte@Sun.COM 		    }
4723*7836SJohn.Forte@Sun.COM 		}
4724*7836SJohn.Forte@Sun.COM 		break;
4725*7836SJohn.Forte@Sun.COM 	case FC_TOP_FABRIC:
4726*7836SJohn.Forte@Sun.COM 	case FC_TOP_PUBLIC_LOOP:
4727*7836SJohn.Forte@Sun.COM 		for (j = 0, dev_addr_ptr = map->dev_addr;
4728*7836SJohn.Forte@Sun.COM 			j < map->count; j++, dev_addr_ptr++) {
4729*7836SJohn.Forte@Sun.COM 		    if (dev_addr_ptr->gfc_port_dev.pub_port.dev_dtype ==
4730*7836SJohn.Forte@Sun.COM 				DTYPE_ESI) {
4731*7836SJohn.Forte@Sun.COM 			/*
4732*7836SJohn.Forte@Sun.COM 			 * We found an enclosure, lets match the
4733*7836SJohn.Forte@Sun.COM 			 * area and domain codes for this enclosure with
4734*7836SJohn.Forte@Sun.COM 			 * that of the ses path since there may be
4735*7836SJohn.Forte@Sun.COM 			 * multiple enclosures with same box id on a
4736*7836SJohn.Forte@Sun.COM 			 * fabric
4737*7836SJohn.Forte@Sun.COM 			 */
4738*7836SJohn.Forte@Sun.COM 			al_pa1 = dev_addr_ptr->gfc_port_dev.
4739*7836SJohn.Forte@Sun.COM 				pub_port.dev_did.port_id;
4740*7836SJohn.Forte@Sun.COM 			if ((al_pa & AREA_DOMAIN_ID) ==
4741*7836SJohn.Forte@Sun.COM 				(al_pa1 & AREA_DOMAIN_ID)) {
4742*7836SJohn.Forte@Sun.COM 				/*
4743*7836SJohn.Forte@Sun.COM 				 * The area and domain matched. Now, we
4744*7836SJohn.Forte@Sun.COM 				 * match the box id of the disk with
4745*7836SJohn.Forte@Sun.COM 				 * this enclosure
4746*7836SJohn.Forte@Sun.COM 				 */
4747*7836SJohn.Forte@Sun.COM 				if (box_id ==
4748*7836SJohn.Forte@Sun.COM 				    (g_sf_alpa_to_switch[al_pa1 &
4749*7836SJohn.Forte@Sun.COM 					0xFF] & BOX_ID_MASK)) {
4750*7836SJohn.Forte@Sun.COM 				    if (!found) {
4751*7836SJohn.Forte@Sun.COM 					ses_wwn = dev_addr_ptr->
4752*7836SJohn.Forte@Sun.COM 						gfc_port_dev.pub_port.
4753*7836SJohn.Forte@Sun.COM 						    dev_pwwn.raw_wwn;
4754*7836SJohn.Forte@Sun.COM 					ses_nwwn = dev_addr_ptr->
4755*7836SJohn.Forte@Sun.COM 						gfc_port_dev.pub_port.
4756*7836SJohn.Forte@Sun.COM 						dev_nwwn.raw_wwn;
4757*7836SJohn.Forte@Sun.COM 					if (getenv("_LUX_P_DEBUG")) {
4758*7836SJohn.Forte@Sun.COM 					    (void) g_ll_to_str(ses_wwn,
4759*7836SJohn.Forte@Sun.COM 							(char *)t_wwn);
4760*7836SJohn.Forte@Sun.COM 					    (void) printf(
4761*7836SJohn.Forte@Sun.COM 						    "  l_get_ses_path: "
4762*7836SJohn.Forte@Sun.COM 						    "Found ses wwn = %s "
4763*7836SJohn.Forte@Sun.COM 						    "al_pa 0x%x\n", t_wwn,
4764*7836SJohn.Forte@Sun.COM 						    al_pa1);
4765*7836SJohn.Forte@Sun.COM 					}
4766*7836SJohn.Forte@Sun.COM 				    } else {
4767*7836SJohn.Forte@Sun.COM 					ses_wwn1 = dev_addr_ptr->
4768*7836SJohn.Forte@Sun.COM 						gfc_port_dev.pub_port.
4769*7836SJohn.Forte@Sun.COM 						    dev_pwwn.raw_wwn;
4770*7836SJohn.Forte@Sun.COM 					if (getenv("_LUX_P_DEBUG")) {
4771*7836SJohn.Forte@Sun.COM 					    (void) g_ll_to_str(ses_wwn1,
4772*7836SJohn.Forte@Sun.COM 						(char *)t_wwn);
4773*7836SJohn.Forte@Sun.COM 					    (void) printf(
4774*7836SJohn.Forte@Sun.COM 						"  l_get_ses_path: "
4775*7836SJohn.Forte@Sun.COM 						"Found second ses "
4776*7836SJohn.Forte@Sun.COM 						"wwn = %s "
4777*7836SJohn.Forte@Sun.COM 						"al_pa 0x%x\n", t_wwn,
4778*7836SJohn.Forte@Sun.COM 						al_pa1);
4779*7836SJohn.Forte@Sun.COM 					}
4780*7836SJohn.Forte@Sun.COM 				    }
4781*7836SJohn.Forte@Sun.COM 				    found++;
4782*7836SJohn.Forte@Sun.COM 				}
4783*7836SJohn.Forte@Sun.COM 			    }
4784*7836SJohn.Forte@Sun.COM 			}
4785*7836SJohn.Forte@Sun.COM 		    }
4786*7836SJohn.Forte@Sun.COM 		    break;
4787*7836SJohn.Forte@Sun.COM 	case FC_TOP_PT_PT:
4788*7836SJohn.Forte@Sun.COM 		return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
4789*7836SJohn.Forte@Sun.COM 	default:
4790*7836SJohn.Forte@Sun.COM 		return (L_UNEXPECTED_FC_TOPOLOGY);
4791*7836SJohn.Forte@Sun.COM 	}	/* End of switch on port_topology */
4792*7836SJohn.Forte@Sun.COM 
4793*7836SJohn.Forte@Sun.COM 	if (!found) {
4794*7836SJohn.Forte@Sun.COM 		return (L_NO_SES_PATH);
4795*7836SJohn.Forte@Sun.COM 	}
4796*7836SJohn.Forte@Sun.COM 
4797*7836SJohn.Forte@Sun.COM 	if (strstr(path_phys, SCSI_VHCI) != NULL) {
4798*7836SJohn.Forte@Sun.COM 		(void) g_ll_to_str(ses_nwwn, wwn);
4799*7836SJohn.Forte@Sun.COM 		(void) sprintf(id_buf, "g%s:0", wwn);
4800*7836SJohn.Forte@Sun.COM 	} else {
4801*7836SJohn.Forte@Sun.COM 		(void) g_ll_to_str(ses_wwn, wwn);
4802*7836SJohn.Forte@Sun.COM 		(void) sprintf(id_buf, "w%s,0:0", wwn);
4803*7836SJohn.Forte@Sun.COM 	}
4804*7836SJohn.Forte@Sun.COM 	(void) strcat(ses_path, id_buf);
4805*7836SJohn.Forte@Sun.COM 	if (verbose) {
4806*7836SJohn.Forte@Sun.COM 		(void) fprintf(stdout,
4807*7836SJohn.Forte@Sun.COM 			MSGSTR(9058, "  Creating enclosure path:\n    %s\n"),
4808*7836SJohn.Forte@Sun.COM 			ses_path);
4809*7836SJohn.Forte@Sun.COM 	}
4810*7836SJohn.Forte@Sun.COM 
4811*7836SJohn.Forte@Sun.COM 	/*
4812*7836SJohn.Forte@Sun.COM 	 * see if these paths exist.
4813*7836SJohn.Forte@Sun.COM 	 */
4814*7836SJohn.Forte@Sun.COM 	if ((fd = g_object_open(ses_path, O_NDELAY | O_RDONLY)) == -1) {
4815*7836SJohn.Forte@Sun.COM 
4816*7836SJohn.Forte@Sun.COM 		if (strstr(path_phys, SCSI_VHCI) != NULL) {
4817*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH);
4818*7836SJohn.Forte@Sun.COM 		}
4819*7836SJohn.Forte@Sun.COM 
4820*7836SJohn.Forte@Sun.COM 		char_ptr = strrchr(ses_path, '/');
4821*7836SJohn.Forte@Sun.COM 		*char_ptr = '\0';
4822*7836SJohn.Forte@Sun.COM 		(void) strcat(ses_path, SLSH_SES_NAME);
4823*7836SJohn.Forte@Sun.COM 		if (found > 1) {
4824*7836SJohn.Forte@Sun.COM 			(void) g_ll_to_str(ses_wwn1, wwn);
4825*7836SJohn.Forte@Sun.COM 			P_DPRINTF("  l_get_ses_path: "
4826*7836SJohn.Forte@Sun.COM 				"Using second path, ses wwn1 = %s\n",
4827*7836SJohn.Forte@Sun.COM 				wwn);
4828*7836SJohn.Forte@Sun.COM 			(void) sprintf(id_buf, "w%s,0:0", wwn);
4829*7836SJohn.Forte@Sun.COM 			strcat(ses_path, id_buf);
4830*7836SJohn.Forte@Sun.COM 			return (0);
4831*7836SJohn.Forte@Sun.COM 		} else {
4832*7836SJohn.Forte@Sun.COM 			return (L_NO_SES_PATH);
4833*7836SJohn.Forte@Sun.COM 		}
4834*7836SJohn.Forte@Sun.COM 	}
4835*7836SJohn.Forte@Sun.COM 	close(fd);
4836*7836SJohn.Forte@Sun.COM 	return (0);
4837*7836SJohn.Forte@Sun.COM }
4838*7836SJohn.Forte@Sun.COM 
4839*7836SJohn.Forte@Sun.COM 
4840*7836SJohn.Forte@Sun.COM 
4841*7836SJohn.Forte@Sun.COM /*
4842*7836SJohn.Forte@Sun.COM  * Get a valid location, front/rear & slot.
4843*7836SJohn.Forte@Sun.COM  *
4844*7836SJohn.Forte@Sun.COM  * path_struct->p_physical_path must be of a disk.
4845*7836SJohn.Forte@Sun.COM  *
4846*7836SJohn.Forte@Sun.COM  * OUTPUT: path_struct->slot_valid
4847*7836SJohn.Forte@Sun.COM  *	path_struct->slot
4848*7836SJohn.Forte@Sun.COM  *	path_struct->f_flag
4849*7836SJohn.Forte@Sun.COM  *
4850*7836SJohn.Forte@Sun.COM  * RETURN:
4851*7836SJohn.Forte@Sun.COM  *	0	 O.K.
4852*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4853*7836SJohn.Forte@Sun.COM  */
4854*7836SJohn.Forte@Sun.COM int
l_get_slot(struct path_struct * path_struct,L_state * l_state,int verbose)4855*7836SJohn.Forte@Sun.COM l_get_slot(struct path_struct *path_struct, L_state *l_state, int verbose)
4856*7836SJohn.Forte@Sun.COM {
4857*7836SJohn.Forte@Sun.COM int		err, al_pa, slot, found = 0;
4858*7836SJohn.Forte@Sun.COM uchar_t		node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
4859*7836SJohn.Forte@Sun.COM uint_t		select_id;
4860*7836SJohn.Forte@Sun.COM 
4861*7836SJohn.Forte@Sun.COM 	if ((path_struct == NULL) || (l_state == NULL)) {
4862*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
4863*7836SJohn.Forte@Sun.COM 	}
4864*7836SJohn.Forte@Sun.COM 
4865*7836SJohn.Forte@Sun.COM 	/* Double check to see if we need to calculate. */
4866*7836SJohn.Forte@Sun.COM 	if (path_struct->slot_valid)
4867*7836SJohn.Forte@Sun.COM 		return (0);
4868*7836SJohn.Forte@Sun.COM 
4869*7836SJohn.Forte@Sun.COM 	/* Programming error if this occures */
4870*7836SJohn.Forte@Sun.COM 	assert(path_struct->ib_path_flag == 0);
4871*7836SJohn.Forte@Sun.COM 
4872*7836SJohn.Forte@Sun.COM 	if (strstr(path_struct->p_physical_path, "ssd") == NULL) {
4873*7836SJohn.Forte@Sun.COM 		return (L_INVLD_PHYS_PATH_TO_DISK);
4874*7836SJohn.Forte@Sun.COM 	}
4875*7836SJohn.Forte@Sun.COM 	if (err = g_get_wwn(path_struct->p_physical_path, port_wwn, node_wwn,
4876*7836SJohn.Forte@Sun.COM 		&al_pa, verbose)) {
4877*7836SJohn.Forte@Sun.COM 		return (err);
4878*7836SJohn.Forte@Sun.COM 	}
4879*7836SJohn.Forte@Sun.COM 
4880*7836SJohn.Forte@Sun.COM 	/*
4881*7836SJohn.Forte@Sun.COM 	 * Find the slot by searching for the matching hard address.
4882*7836SJohn.Forte@Sun.COM 	 * Take only the low order byte ignoring area and domain code in
4883*7836SJohn.Forte@Sun.COM 	 * fabric devices' 24 bit al_pa
4884*7836SJohn.Forte@Sun.COM 	 */
4885*7836SJohn.Forte@Sun.COM 	select_id = g_sf_alpa_to_switch[al_pa & 0xFF];
4886*7836SJohn.Forte@Sun.COM 	P_DPRINTF("  l_get_slot: Searching Receive Diagnostic page 2, "
4887*7836SJohn.Forte@Sun.COM 		"to find the slot number with this ID:0x%x\n",
4888*7836SJohn.Forte@Sun.COM 		select_id);
4889*7836SJohn.Forte@Sun.COM 
4890*7836SJohn.Forte@Sun.COM 	for (slot = 0; slot < l_state->total_num_drv/2; slot++) {
4891*7836SJohn.Forte@Sun.COM 		if (l_state->drv_front[slot].ib_status.sel_id ==
4892*7836SJohn.Forte@Sun.COM 			select_id) {
4893*7836SJohn.Forte@Sun.COM 			path_struct->f_flag = 1;
4894*7836SJohn.Forte@Sun.COM 			found = 1;
4895*7836SJohn.Forte@Sun.COM 			break;
4896*7836SJohn.Forte@Sun.COM 		} else if (l_state->drv_rear[slot].ib_status.sel_id ==
4897*7836SJohn.Forte@Sun.COM 			select_id) {
4898*7836SJohn.Forte@Sun.COM 			path_struct->f_flag = 0;
4899*7836SJohn.Forte@Sun.COM 			found = 1;
4900*7836SJohn.Forte@Sun.COM 			break;
4901*7836SJohn.Forte@Sun.COM 		}
4902*7836SJohn.Forte@Sun.COM 	}
4903*7836SJohn.Forte@Sun.COM 	if (!found) {
4904*7836SJohn.Forte@Sun.COM 		return (L_INVALID_SLOT);	/* Failure */
4905*7836SJohn.Forte@Sun.COM 	}
4906*7836SJohn.Forte@Sun.COM 	if ((strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_OFF_NAME,
4907*7836SJohn.Forte@Sun.COM 						strlen(DAK_OFF_NAME)) == 0) ||
4908*7836SJohn.Forte@Sun.COM 		(strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_PROD_STR,
4909*7836SJohn.Forte@Sun.COM 						strlen(DAK_OFF_NAME)) == 0)) {
4910*7836SJohn.Forte@Sun.COM 		P_DPRINTF("  l_get_slot: Found slot %d.\n",
4911*7836SJohn.Forte@Sun.COM 			path_struct->f_flag ? slot : slot + (MAX_DRIVES_DAK/2));
4912*7836SJohn.Forte@Sun.COM 	} else {
4913*7836SJohn.Forte@Sun.COM 		P_DPRINTF("  l_get_slot: Found slot %d %s.\n", slot,
4914*7836SJohn.Forte@Sun.COM 			path_struct->f_flag ? "Front" : "Rear");
4915*7836SJohn.Forte@Sun.COM 	}
4916*7836SJohn.Forte@Sun.COM 	path_struct->slot = slot;
4917*7836SJohn.Forte@Sun.COM 	path_struct->slot_valid = 1;
4918*7836SJohn.Forte@Sun.COM 	return (0);
4919*7836SJohn.Forte@Sun.COM }
4920*7836SJohn.Forte@Sun.COM 
4921*7836SJohn.Forte@Sun.COM 
4922*7836SJohn.Forte@Sun.COM void
l_element_msg_string(uchar_t code,char * es)4923*7836SJohn.Forte@Sun.COM l_element_msg_string(uchar_t code, char *es)
4924*7836SJohn.Forte@Sun.COM {
4925*7836SJohn.Forte@Sun.COM 	if (code == S_OK) {
4926*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(29, "O.K."));
4927*7836SJohn.Forte@Sun.COM 	} else if (code == S_NOT_AVAILABLE) {
4928*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(34, "Disabled"));
4929*7836SJohn.Forte@Sun.COM 	} else if (code == S_NOT_INSTALLED) {
4930*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(30, "Not Installed"));
4931*7836SJohn.Forte@Sun.COM 	} else if (code == S_NONCRITICAL) {
4932*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(9059, "Noncritical failure"));
4933*7836SJohn.Forte@Sun.COM 	} else if (code == S_CRITICAL) {
4934*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(122, "Critical failure"));
4935*7836SJohn.Forte@Sun.COM 	} else {
4936*7836SJohn.Forte@Sun.COM 		(void) sprintf(es, MSGSTR(4, "Unknown status"));
4937*7836SJohn.Forte@Sun.COM 	}
4938*7836SJohn.Forte@Sun.COM }
4939*7836SJohn.Forte@Sun.COM 
4940*7836SJohn.Forte@Sun.COM 
4941*7836SJohn.Forte@Sun.COM /*
4942*7836SJohn.Forte@Sun.COM  * Get all ses paths paths to a given box.
4943*7836SJohn.Forte@Sun.COM  * The arg should be the physical path to one of the box's IB.
4944*7836SJohn.Forte@Sun.COM  * NOTE: The caller must free the allocated lists.
4945*7836SJohn.Forte@Sun.COM  *
4946*7836SJohn.Forte@Sun.COM  * OUTPUT:
4947*7836SJohn.Forte@Sun.COM  *	a pointer to a list of ses paths if found
4948*7836SJohn.Forte@Sun.COM  *	NULL on error.
4949*7836SJohn.Forte@Sun.COM  *
4950*7836SJohn.Forte@Sun.COM  * RETURNS:
4951*7836SJohn.Forte@Sun.COM  *	0	 if O.K.
4952*7836SJohn.Forte@Sun.COM  *	non-zero otherwise
4953*7836SJohn.Forte@Sun.COM  */
4954*7836SJohn.Forte@Sun.COM int
l_get_allses(char * path,struct box_list_struct * box_list,struct dlist ** ses_list,int verbose)4955*7836SJohn.Forte@Sun.COM l_get_allses(char *path, struct box_list_struct *box_list,
4956*7836SJohn.Forte@Sun.COM 			struct dlist **ses_list, int verbose)
4957*7836SJohn.Forte@Sun.COM {
4958*7836SJohn.Forte@Sun.COM struct box_list_struct 	*box_list_ptr;
4959*7836SJohn.Forte@Sun.COM char			node_wwn_s[WWN_S_LEN];
4960*7836SJohn.Forte@Sun.COM struct dlist		*dlt, *dl;
4961*7836SJohn.Forte@Sun.COM 
4962*7836SJohn.Forte@Sun.COM 	if ((path == NULL) || (box_list == NULL) || (ses_list == NULL)) {
4963*7836SJohn.Forte@Sun.COM 		return (L_INVALID_PATH_FORMAT);
4964*7836SJohn.Forte@Sun.COM 	}
4965*7836SJohn.Forte@Sun.COM 
4966*7836SJohn.Forte@Sun.COM 	/* Initialize lists/arrays */
4967*7836SJohn.Forte@Sun.COM 	*ses_list = dlt = dl = (struct dlist *)NULL;
4968*7836SJohn.Forte@Sun.COM 	node_wwn_s[0] = '\0';
4969*7836SJohn.Forte@Sun.COM 
4970*7836SJohn.Forte@Sun.COM 	H_DPRINTF("  l_get_allses: Looking for all ses paths for"
4971*7836SJohn.Forte@Sun.COM 		" box at path: %s\n", path);
4972*7836SJohn.Forte@Sun.COM 
4973*7836SJohn.Forte@Sun.COM 	for (box_list_ptr = box_list; box_list_ptr != NULL;
4974*7836SJohn.Forte@Sun.COM 				box_list_ptr = box_list_ptr->box_next) {
4975*7836SJohn.Forte@Sun.COM 		H_DPRINTF("  l_get_allses: physical_path= %s\n",
4976*7836SJohn.Forte@Sun.COM 				box_list_ptr->b_physical_path);
4977*7836SJohn.Forte@Sun.COM 		if (strcmp(path, box_list_ptr->b_physical_path) == 0) {
4978*7836SJohn.Forte@Sun.COM 			(void) strcpy(node_wwn_s, box_list_ptr->b_node_wwn_s);
4979*7836SJohn.Forte@Sun.COM 			break;
4980*7836SJohn.Forte@Sun.COM 		}
4981*7836SJohn.Forte@Sun.COM 	}
4982*7836SJohn.Forte@Sun.COM 	if (node_wwn_s[0] == '\0') {
4983*7836SJohn.Forte@Sun.COM 		H_DPRINTF("node_wwn_s is NULL!\n");
4984*7836SJohn.Forte@Sun.COM 		return (L_NO_NODE_WWN_IN_BOXLIST);
4985*7836SJohn.Forte@Sun.COM 	}
4986*7836SJohn.Forte@Sun.COM 	H_DPRINTF("  l_get_allses: node_wwn=%s\n", node_wwn_s);
4987*7836SJohn.Forte@Sun.COM 	for (box_list_ptr = box_list; box_list_ptr != NULL;
4988*7836SJohn.Forte@Sun.COM 				box_list_ptr = box_list_ptr->box_next) {
4989*7836SJohn.Forte@Sun.COM 		if (strcmp(node_wwn_s, box_list_ptr->b_node_wwn_s) == 0) {
4990*7836SJohn.Forte@Sun.COM 			if ((dl = (struct dlist *)
4991*7836SJohn.Forte@Sun.COM 				g_zalloc(sizeof (struct dlist))) == NULL) {
4992*7836SJohn.Forte@Sun.COM 				while (*ses_list != NULL) {
4993*7836SJohn.Forte@Sun.COM 					dl = dlt->next;
4994*7836SJohn.Forte@Sun.COM 					(void) g_destroy_data(dlt);
4995*7836SJohn.Forte@Sun.COM 					dlt = dl;
4996*7836SJohn.Forte@Sun.COM 				}
4997*7836SJohn.Forte@Sun.COM 				return (L_MALLOC_FAILED);
4998*7836SJohn.Forte@Sun.COM 			}
4999*7836SJohn.Forte@Sun.COM 			H_DPRINTF("  l_get_allses: Found ses=%s\n",
5000*7836SJohn.Forte@Sun.COM 					box_list_ptr->b_physical_path);
5001*7836SJohn.Forte@Sun.COM 			dl->dev_path = strdup(box_list_ptr->b_physical_path);
5002*7836SJohn.Forte@Sun.COM 			dl->logical_path = strdup(box_list_ptr->logical_path);
5003*7836SJohn.Forte@Sun.COM 			if (*ses_list == NULL) {
5004*7836SJohn.Forte@Sun.COM 				*ses_list = dlt = dl;
5005*7836SJohn.Forte@Sun.COM 			} else {
5006*7836SJohn.Forte@Sun.COM 				dlt->next = dl;
5007*7836SJohn.Forte@Sun.COM 				dl->prev = dlt;
5008*7836SJohn.Forte@Sun.COM 				dlt = dl;
5009*7836SJohn.Forte@Sun.COM 			}
5010*7836SJohn.Forte@Sun.COM 		}
5011*7836SJohn.Forte@Sun.COM 	}
5012*7836SJohn.Forte@Sun.COM 
5013*7836SJohn.Forte@Sun.COM 	return (0);
5014*7836SJohn.Forte@Sun.COM }
5015*7836SJohn.Forte@Sun.COM 
5016*7836SJohn.Forte@Sun.COM /*
5017*7836SJohn.Forte@Sun.COM  *	Routine to return the enclosure type pointed to by the path.
5018*7836SJohn.Forte@Sun.COM  *	Inputs:	The inquiry data for the device in question
5019*7836SJohn.Forte@Sun.COM  *
5020*7836SJohn.Forte@Sun.COM  *	Return:  >= 0 is the type:
5021*7836SJohn.Forte@Sun.COM  *
5022*7836SJohn.Forte@Sun.COM  *	Types are defined in storage/libg_fc/common/hdrs/g_state.h:
5023*7836SJohn.Forte@Sun.COM  *
5024*7836SJohn.Forte@Sun.COM  *		0 -> default (SENA)
5025*7836SJohn.Forte@Sun.COM  *		1 -> Daktari
5026*7836SJohn.Forte@Sun.COM  *		2 -> Other Enclosures
5027*7836SJohn.Forte@Sun.COM  *
5028*7836SJohn.Forte@Sun.COM  */
5029*7836SJohn.Forte@Sun.COM int
l_get_enc_type(L_inquiry inq)5030*7836SJohn.Forte@Sun.COM l_get_enc_type(L_inquiry inq)
5031*7836SJohn.Forte@Sun.COM {
5032*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)&inq.inq_pid[0], ENCLOSURE_PROD_ID,
5033*7836SJohn.Forte@Sun.COM 		    strlen(ENCLOSURE_PROD_ID)) == 0) {
5034*7836SJohn.Forte@Sun.COM 		return (SENA_ENC_TYPE);
5035*7836SJohn.Forte@Sun.COM 	}
5036*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)&inq.inq_pid[0], DAK_OFF_NAME,
5037*7836SJohn.Forte@Sun.COM 		strlen(DAK_OFF_NAME)) == 0) {
5038*7836SJohn.Forte@Sun.COM 	    return (DAK_ENC_TYPE);
5039*7836SJohn.Forte@Sun.COM 	}
5040*7836SJohn.Forte@Sun.COM 	if (strncmp((char *)&inq.inq_pid[0], DAK_PROD_STR,
5041*7836SJohn.Forte@Sun.COM 		strlen(DAK_PROD_STR)) == 0) {
5042*7836SJohn.Forte@Sun.COM 	    return (DAK_ENC_TYPE);
5043*7836SJohn.Forte@Sun.COM 	}
5044*7836SJohn.Forte@Sun.COM 	/*
5045*7836SJohn.Forte@Sun.COM 	 *  ADD OTHERS here if ever needed/wanted, and add to def's
5046*7836SJohn.Forte@Sun.COM 	 * 	as noted above
5047*7836SJohn.Forte@Sun.COM 	 */
5048*7836SJohn.Forte@Sun.COM 	return (UNDEF_ENC_TYPE);
5049*7836SJohn.Forte@Sun.COM }
5050*7836SJohn.Forte@Sun.COM 
5051*7836SJohn.Forte@Sun.COM void
free_mp_dev_map(gfc_map_mp_t ** map_mp_ptr)5052*7836SJohn.Forte@Sun.COM free_mp_dev_map(gfc_map_mp_t **map_mp_ptr) {
5053*7836SJohn.Forte@Sun.COM 	gfc_map_mp_t	    *next = NULL;
5054*7836SJohn.Forte@Sun.COM 
5055*7836SJohn.Forte@Sun.COM 	for (; *map_mp_ptr != NULL; *map_mp_ptr = next) {
5056*7836SJohn.Forte@Sun.COM 		next = (*map_mp_ptr)->map_next;
5057*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data((*map_mp_ptr)->map.dev_addr);
5058*7836SJohn.Forte@Sun.COM 		(void) g_destroy_data(*map_mp_ptr);
5059*7836SJohn.Forte@Sun.COM 	}
5060*7836SJohn.Forte@Sun.COM 	*map_mp_ptr = NULL;
5061*7836SJohn.Forte@Sun.COM }
5062*7836SJohn.Forte@Sun.COM /*
5063*7836SJohn.Forte@Sun.COM  * This function will return a linked list of device maps
5064*7836SJohn.Forte@Sun.COM  * An example of when this will be used is when we want to return the device
5065*7836SJohn.Forte@Sun.COM  * map of a vhci path.
5066*7836SJohn.Forte@Sun.COM  */
5067*7836SJohn.Forte@Sun.COM 
5068*7836SJohn.Forte@Sun.COM int
get_mp_dev_map(char * path,gfc_map_mp_t ** map_mp_ptr,int verbose)5069*7836SJohn.Forte@Sun.COM get_mp_dev_map(char *path, gfc_map_mp_t **map_mp_ptr, int verbose) {
5070*7836SJohn.Forte@Sun.COM 
5071*7836SJohn.Forte@Sun.COM 	int		pathcnt, i, err;
5072*7836SJohn.Forte@Sun.COM 	mp_pathlist_t	pathlist;
5073*7836SJohn.Forte@Sun.COM 	gfc_map_mp_t	*new_map_mp_ptr;
5074*7836SJohn.Forte@Sun.COM 	char		drvr_path[MAXPATHLEN];
5075*7836SJohn.Forte@Sun.COM 	if (strstr(path, SCSI_VHCI)) {
5076*7836SJohn.Forte@Sun.COM 		if (g_get_pathlist(path, &pathlist)) {
5077*7836SJohn.Forte@Sun.COM 			return (L_INVALID_PATH);
5078*7836SJohn.Forte@Sun.COM 		}
5079*7836SJohn.Forte@Sun.COM 		pathcnt = pathlist.path_count;
5080*7836SJohn.Forte@Sun.COM 		for (i = 0; i < pathcnt; i++) {
5081*7836SJohn.Forte@Sun.COM 			if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
5082*7836SJohn.Forte@Sun.COM 				/*
5083*7836SJohn.Forte@Sun.COM 				 * only pay attention to paths that are either
5084*7836SJohn.Forte@Sun.COM 				 * ONLINE or STANDBY
5085*7836SJohn.Forte@Sun.COM 				 */
5086*7836SJohn.Forte@Sun.COM 				if ((pathlist.path_info[i].path_state ==
5087*7836SJohn.Forte@Sun.COM 					MDI_PATHINFO_STATE_ONLINE) ||
5088*7836SJohn.Forte@Sun.COM 				    (pathlist.path_info[i].path_state ==
5089*7836SJohn.Forte@Sun.COM 					MDI_PATHINFO_STATE_STANDBY)) {
5090*7836SJohn.Forte@Sun.COM 					if ((new_map_mp_ptr = (gfc_map_mp_t *)
5091*7836SJohn.Forte@Sun.COM 					    g_zalloc(sizeof (gfc_map_mp_t)))
5092*7836SJohn.Forte@Sun.COM 								== NULL) {
5093*7836SJohn.Forte@Sun.COM 						free(pathlist.path_info);
5094*7836SJohn.Forte@Sun.COM 						free_mp_dev_map(map_mp_ptr);
5095*7836SJohn.Forte@Sun.COM 						return (L_MALLOC_FAILED);
5096*7836SJohn.Forte@Sun.COM 					}
5097*7836SJohn.Forte@Sun.COM 					(void) strcpy(drvr_path,
5098*7836SJohn.Forte@Sun.COM 						pathlist.path_info[i].path_hba);
5099*7836SJohn.Forte@Sun.COM 					(void) strcat(drvr_path, FC_CTLR);
5100*7836SJohn.Forte@Sun.COM 					if (err = g_get_dev_map(drvr_path,
5101*7836SJohn.Forte@Sun.COM 					    &(new_map_mp_ptr->map),
5102*7836SJohn.Forte@Sun.COM 					    verbose)) {
5103*7836SJohn.Forte@Sun.COM 						free(pathlist.path_info);
5104*7836SJohn.Forte@Sun.COM 						free_mp_dev_map(map_mp_ptr);
5105*7836SJohn.Forte@Sun.COM 						return (err);
5106*7836SJohn.Forte@Sun.COM 					}
5107*7836SJohn.Forte@Sun.COM 					/* add newly created map onto list */
5108*7836SJohn.Forte@Sun.COM 					if (*map_mp_ptr == NULL) {
5109*7836SJohn.Forte@Sun.COM 						new_map_mp_ptr->map_next = NULL;
5110*7836SJohn.Forte@Sun.COM 						*map_mp_ptr = new_map_mp_ptr;
5111*7836SJohn.Forte@Sun.COM 					} else {
5112*7836SJohn.Forte@Sun.COM 						new_map_mp_ptr->map_next =
5113*7836SJohn.Forte@Sun.COM 						    *map_mp_ptr;
5114*7836SJohn.Forte@Sun.COM 						*map_mp_ptr = new_map_mp_ptr;
5115*7836SJohn.Forte@Sun.COM 					}
5116*7836SJohn.Forte@Sun.COM 				}
5117*7836SJohn.Forte@Sun.COM 			}
5118*7836SJohn.Forte@Sun.COM 		}
5119*7836SJohn.Forte@Sun.COM 		free(pathlist.path_info);
5120*7836SJohn.Forte@Sun.COM 	} else {
5121*7836SJohn.Forte@Sun.COM 		if ((new_map_mp_ptr = (gfc_map_mp_t *)g_zalloc
5122*7836SJohn.Forte@Sun.COM 			    (sizeof (gfc_map_mp_t))) == NULL) {
5123*7836SJohn.Forte@Sun.COM 			return (L_MALLOC_FAILED);
5124*7836SJohn.Forte@Sun.COM 		}
5125*7836SJohn.Forte@Sun.COM 		g_get_dev_map(path, &(new_map_mp_ptr->map), verbose);
5126*7836SJohn.Forte@Sun.COM 		*map_mp_ptr = new_map_mp_ptr;
5127*7836SJohn.Forte@Sun.COM 	}
5128*7836SJohn.Forte@Sun.COM 	return (0);
5129*7836SJohn.Forte@Sun.COM }
5130