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