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