xref: /titanic_51/usr/src/cmd/luxadm/hotplug.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 
28*fcf3ce44SJohn Forte /*LINTLIBRARY*/
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte 
31*fcf3ce44SJohn Forte /*
32*fcf3ce44SJohn Forte  * Hotplug program for SENA, RSM and SSA
33*fcf3ce44SJohn Forte  * subsystems and individual FC_AL devices.
34*fcf3ce44SJohn Forte  */
35*fcf3ce44SJohn Forte 
36*fcf3ce44SJohn Forte /* #define		 _POSIX_SOURCE 1 */
37*fcf3ce44SJohn Forte 
38*fcf3ce44SJohn Forte /*
39*fcf3ce44SJohn Forte  * I18N message number ranges
40*fcf3ce44SJohn Forte  *  This file: 5500 - 5999
41*fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
42*fcf3ce44SJohn Forte  */
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte 
45*fcf3ce44SJohn Forte /*	Includes	*/
46*fcf3ce44SJohn Forte #include	<stdlib.h>
47*fcf3ce44SJohn Forte #include	<stdio.h>
48*fcf3ce44SJohn Forte #include	<sys/file.h>
49*fcf3ce44SJohn Forte #include	<sys/errno.h>
50*fcf3ce44SJohn Forte #include	<sys/types.h>
51*fcf3ce44SJohn Forte #include	<sys/stat.h>
52*fcf3ce44SJohn Forte #include	<sys/utsname.h>
53*fcf3ce44SJohn Forte #include	<fcntl.h>
54*fcf3ce44SJohn Forte #include	<unistd.h>
55*fcf3ce44SJohn Forte #include	<errno.h>
56*fcf3ce44SJohn Forte #include	<string.h>
57*fcf3ce44SJohn Forte #include	<sys/sunddi.h>
58*fcf3ce44SJohn Forte #include	<sys/ddi.h>		/* for min */
59*fcf3ce44SJohn Forte #include	<sys/scsi/scsi.h>
60*fcf3ce44SJohn Forte #include	<nl_types.h>
61*fcf3ce44SJohn Forte #include	<dirent.h>
62*fcf3ce44SJohn Forte #include	<sys/wait.h>
63*fcf3ce44SJohn Forte #include	<l_common.h>
64*fcf3ce44SJohn Forte #include	<l_error.h>
65*fcf3ce44SJohn Forte #include	<stgcom.h>
66*fcf3ce44SJohn Forte #include	<a_state.h>
67*fcf3ce44SJohn Forte #include	<a5k.h>
68*fcf3ce44SJohn Forte #include	<rom.h>
69*fcf3ce44SJohn Forte #include	"hot.h"
70*fcf3ce44SJohn Forte #include	"common.h"
71*fcf3ce44SJohn Forte #include	"luxadm.h"
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte 
74*fcf3ce44SJohn Forte /* Internal variables. */
75*fcf3ce44SJohn Forte static char *cmdStrg[][4] = {
76*fcf3ce44SJohn Forte 		{ "disks", "-C", 0, 0 },
77*fcf3ce44SJohn Forte 		{ "disks", 0, 0, 0 },
78*fcf3ce44SJohn Forte 		{ "drvconfig", "-i", "ssd", 0 },
79*fcf3ce44SJohn Forte 		{ "drvconfig", 0, 0, 0 },
80*fcf3ce44SJohn Forte 		{ "devlinks", 0, 0, 0 },
81*fcf3ce44SJohn Forte 		{ "tapes", "-C", 0, 0 }
82*fcf3ce44SJohn Forte };
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte /*	External variables	*/
85*fcf3ce44SJohn Forte extern	char		*dtype[]; /* From adm.c */
86*fcf3ce44SJohn Forte extern	int		Options;
87*fcf3ce44SJohn Forte extern	const		int OPTION_CAPF;
88*fcf3ce44SJohn Forte 
89*fcf3ce44SJohn Forte /*	Internal functions	*/
90*fcf3ce44SJohn Forte /* SENA and Individual FC device Hotplug */
91*fcf3ce44SJohn Forte static	int	h_pre_insert_encl_dev(timestruc_t *, timestruc_t *,
92*fcf3ce44SJohn Forte 		timestruc_t *);
93*fcf3ce44SJohn Forte static	int	h_post_insert_dev(timestruc_t, timestruc_t);
94*fcf3ce44SJohn Forte static	int	h_pre_remove_dev(Hotplug_Devlist *,
95*fcf3ce44SJohn Forte 		WWN_list *wwn_list, int, int);
96*fcf3ce44SJohn Forte static	int	h_post_remove_dev(Hotplug_Devlist *, int, int);
97*fcf3ce44SJohn Forte static	int	h_pre_hotplug(Hotplug_Devlist **,
98*fcf3ce44SJohn Forte 		WWN_list *, int, int, int);
99*fcf3ce44SJohn Forte static	int	h_post_hotplug(Hotplug_Devlist *,
100*fcf3ce44SJohn Forte 		WWN_list *, int, int, int, int);
101*fcf3ce44SJohn Forte static	int	h_post_insert_encl(timestruc_t);
102*fcf3ce44SJohn Forte static	int	h_pre_hotplug_sena(Hotplug_Devlist *,
103*fcf3ce44SJohn Forte 		WWN_list *, int, int, int);
104*fcf3ce44SJohn Forte static	int	h_post_hotplug_sena(Hotplug_Devlist *,
105*fcf3ce44SJohn Forte 		WWN_list *, int, int, int, int);
106*fcf3ce44SJohn Forte static	int	h_remove_ses_nodes(struct dlist *);
107*fcf3ce44SJohn Forte static 	int	h_print_list_warn(Hotplug_Devlist *, int, int);
108*fcf3ce44SJohn Forte static	int	h_display_logical_nodes(struct dlist *);
109*fcf3ce44SJohn Forte static	void	h_print_logical_nodes(struct dlist *);
110*fcf3ce44SJohn Forte static	int	h_remove_nodes(struct dlist *);
111*fcf3ce44SJohn Forte static	int	h_print_list(Hotplug_Devlist *, int *, int);
112*fcf3ce44SJohn Forte static	int	h_get_fcdev_state(char *, char *, int, int *, int *, int);
113*fcf3ce44SJohn Forte static	int	h_chk_dev_busy(Hotplug_Devlist *,
114*fcf3ce44SJohn Forte 		WWN_list *, int *, int, int);
115*fcf3ce44SJohn Forte static	int	h_execCmnd(char **, int);
116*fcf3ce44SJohn Forte int		hotplug(int, char **, int, int);
117*fcf3ce44SJohn Forte int		h_insertSena_fcdev();
118*fcf3ce44SJohn Forte static	int	h_find_new_device_link(char *, timestruc_t);
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte 
122*fcf3ce44SJohn Forte /*
123*fcf3ce44SJohn Forte  * Assists the user in hot inserting FC_AL
124*fcf3ce44SJohn Forte  * individual device(s) and SENA enclosure(s).
125*fcf3ce44SJohn Forte  *
126*fcf3ce44SJohn Forte  * RETURNS:
127*fcf3ce44SJohn Forte  *	0	 if OK
128*fcf3ce44SJohn Forte  *	non-zero otherwise
129*fcf3ce44SJohn Forte  */
130*fcf3ce44SJohn Forte int
131*fcf3ce44SJohn Forte h_insertSena_fcdev()
132*fcf3ce44SJohn Forte {
133*fcf3ce44SJohn Forte timestruc_t	ses_time, dsk_time, rmt_time;
134*fcf3ce44SJohn Forte int		err;
135*fcf3ce44SJohn Forte struct stat	ses_stat;
136*fcf3ce44SJohn Forte 
137*fcf3ce44SJohn Forte 	if ((err = h_pre_insert_encl_dev(&ses_time, &dsk_time,
138*fcf3ce44SJohn Forte 							&rmt_time)) != 0) {
139*fcf3ce44SJohn Forte 		return (err);
140*fcf3ce44SJohn Forte 	}
141*fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(5500,
142*fcf3ce44SJohn Forte 			"Please hit <RETURN> when you have finished"
143*fcf3ce44SJohn Forte 			" adding Fibre Channel Enclosure(s)/Device(s): "));
144*fcf3ce44SJohn Forte 	(void) getchar();
145*fcf3ce44SJohn Forte 
146*fcf3ce44SJohn Forte 	if ((err = h_post_insert_dev(dsk_time, rmt_time)) != 0) {
147*fcf3ce44SJohn Forte 		return (err);
148*fcf3ce44SJohn Forte 	}
149*fcf3ce44SJohn Forte 
150*fcf3ce44SJohn Forte 	if (stat(SES_DIR, &ses_stat) < 0) {
151*fcf3ce44SJohn Forte 		/*
152*fcf3ce44SJohn Forte 		 * Non existence of /dev/es dir indicates
153*fcf3ce44SJohn Forte 		 * no ses devices inserted.
154*fcf3ce44SJohn Forte 		 * No need to call h_post_insert_encl().
155*fcf3ce44SJohn Forte 		 */
156*fcf3ce44SJohn Forte 		if (errno == ENOENT) {
157*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5662,
158*fcf3ce44SJohn Forte 				" No new enclosure(s) were added!!\n\n"));
159*fcf3ce44SJohn Forte 			return (0);
160*fcf3ce44SJohn Forte 		} else {
161*fcf3ce44SJohn Forte 			return (L_LSTAT_ES_DIR_ERROR);
162*fcf3ce44SJohn Forte 		}
163*fcf3ce44SJohn Forte 	}
164*fcf3ce44SJohn Forte 
165*fcf3ce44SJohn Forte 	/*
166*fcf3ce44SJohn Forte 	 * if the latest mod time of /dev/es is not newer than
167*fcf3ce44SJohn Forte 	 * the original mod time no need to call
168*fcf3ce44SJohn Forte 	 * h_post_insert_encl().
169*fcf3ce44SJohn Forte 	 */
170*fcf3ce44SJohn Forte 	if ((&ses_time != (timestruc_t *)NULL) &&
171*fcf3ce44SJohn Forte 			!(NEWER(ses_stat.st_ctim, ses_time))) {
172*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5662,
173*fcf3ce44SJohn Forte 			" No new enclosure(s) were added!!\n\n"));
174*fcf3ce44SJohn Forte 		return (0);
175*fcf3ce44SJohn Forte 	}
176*fcf3ce44SJohn Forte 	if ((err = h_post_insert_encl(ses_time)) != 0) {
177*fcf3ce44SJohn Forte 		return (err);
178*fcf3ce44SJohn Forte 	}
179*fcf3ce44SJohn Forte 	return (0);
180*fcf3ce44SJohn Forte }
181*fcf3ce44SJohn Forte 
182*fcf3ce44SJohn Forte 
183*fcf3ce44SJohn Forte 
184*fcf3ce44SJohn Forte /*
185*fcf3ce44SJohn Forte  * gets the devices state - check for disk's reservations.
186*fcf3ce44SJohn Forte  *
187*fcf3ce44SJohn Forte  * RETURNS:
188*fcf3ce44SJohn Forte  *	0	 if OK
189*fcf3ce44SJohn Forte  *	non-zero otherwise
190*fcf3ce44SJohn Forte  */
191*fcf3ce44SJohn Forte static	int
192*fcf3ce44SJohn Forte h_get_fcdev_state(char *fc_dev, char *path_phys, int force_flag,
193*fcf3ce44SJohn Forte 		int *busy_flag, int *reserve_flag, int verbose_flag)
194*fcf3ce44SJohn Forte {
195*fcf3ce44SJohn Forte int		err;
196*fcf3ce44SJohn Forte L_inquiry	inq;
197*fcf3ce44SJohn Forte L_disk_state	l_disk_state;
198*fcf3ce44SJohn Forte 
199*fcf3ce44SJohn Forte 
200*fcf3ce44SJohn Forte 	if ((err = g_get_inquiry(path_phys, &inq)) != 0) {
201*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
202*fcf3ce44SJohn Forte 				MSGSTR(5501,
203*fcf3ce44SJohn Forte 				"Inquiry failed for %s\n"),
204*fcf3ce44SJohn Forte 				path_phys);
205*fcf3ce44SJohn Forte 		return (err);
206*fcf3ce44SJohn Forte 	}
207*fcf3ce44SJohn Forte 	if (inq.inq_port) {
208*fcf3ce44SJohn Forte 		if ((err = l_get_disk_port_status(path_phys, &l_disk_state,
209*fcf3ce44SJohn Forte 					FC_PORT_B, verbose_flag)) != 0) {
210*fcf3ce44SJohn Forte 			return (err);
211*fcf3ce44SJohn Forte 		}
212*fcf3ce44SJohn Forte 	} else {
213*fcf3ce44SJohn Forte 		if ((err = l_get_disk_port_status(path_phys, &l_disk_state,
214*fcf3ce44SJohn Forte 					FC_PORT_A, verbose_flag)) != 0) {
215*fcf3ce44SJohn Forte 			return (err);
216*fcf3ce44SJohn Forte 		}
217*fcf3ce44SJohn Forte 	}
218*fcf3ce44SJohn Forte 
219*fcf3ce44SJohn Forte 	/*
220*fcf3ce44SJohn Forte 	 * Don't print error msg. if disk is reserved
221*fcf3ce44SJohn Forte 	 * and tried to be removed from the same port.
222*fcf3ce44SJohn Forte 	 * If force flag is set, remove the disk without
223*fcf3ce44SJohn Forte 	 * checking the disk reservations.
224*fcf3ce44SJohn Forte 	 */
225*fcf3ce44SJohn Forte 	if (!force_flag) {
226*fcf3ce44SJohn Forte 		if (((inq.inq_port) &&
227*fcf3ce44SJohn Forte 		(l_disk_state.g_disk_state.d_state_flags[FC_PORT_B] &
228*fcf3ce44SJohn Forte 				L_RESERVED)) ||
229*fcf3ce44SJohn Forte 			((!inq.inq_port) &&
230*fcf3ce44SJohn Forte 		(l_disk_state.g_disk_state.d_state_flags[FC_PORT_A] &
231*fcf3ce44SJohn Forte 				L_RESERVED))) {
232*fcf3ce44SJohn Forte 			*reserve_flag = 1;
233*fcf3ce44SJohn Forte 		}
234*fcf3ce44SJohn Forte 	}
235*fcf3ce44SJohn Forte 	return (0);
236*fcf3ce44SJohn Forte }
237*fcf3ce44SJohn Forte 
238*fcf3ce44SJohn Forte 
239*fcf3ce44SJohn Forte /*
240*fcf3ce44SJohn Forte  * Forks a child process and let the child to
241*fcf3ce44SJohn Forte  * execute a given command string by calling the
242*fcf3ce44SJohn Forte  * the execvp() function. Then, the parent process
243*fcf3ce44SJohn Forte  * waits for the child to exit. Once the parent process
244*fcf3ce44SJohn Forte  * is notified by the kernel with the termination of
245*fcf3ce44SJohn Forte  * the child, then the  parent checks for the exit
246*fcf3ce44SJohn Forte  * status of the child and return to the caller with -1 in case
247*fcf3ce44SJohn Forte  * of error and zero otherwise.
248*fcf3ce44SJohn Forte  *
249*fcf3ce44SJohn Forte  * RETURNS:
250*fcf3ce44SJohn Forte  *	0	 if OK
251*fcf3ce44SJohn Forte  *	non-zero otherwise
252*fcf3ce44SJohn Forte  */
253*fcf3ce44SJohn Forte int
254*fcf3ce44SJohn Forte h_execCmnd(char *argStr[], int nArg)
255*fcf3ce44SJohn Forte {
256*fcf3ce44SJohn Forte pid_t	pid;
257*fcf3ce44SJohn Forte int	ix, status;
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte 	if ((pid = fork()) < 0) {
260*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
261*fcf3ce44SJohn Forte 			MSGSTR(133,
262*fcf3ce44SJohn Forte 			"Error: Failed to fork a process.\n"));
263*fcf3ce44SJohn Forte 		return (-1);
264*fcf3ce44SJohn Forte 	} else if (pid == 0) {
265*fcf3ce44SJohn Forte 		/* child process */
266*fcf3ce44SJohn Forte 		if (execvp(argStr[0], argStr) < 0) {
267*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
268*fcf3ce44SJohn Forte 				MSGSTR(5502,
269*fcf3ce44SJohn Forte 				" Error: execvp() failed to run "
270*fcf3ce44SJohn Forte 				"the command:"));
271*fcf3ce44SJohn Forte 			for (ix = 0; ix < nArg; ix++) {
272*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
273*fcf3ce44SJohn Forte 					" %s", argStr[ix]);
274*fcf3ce44SJohn Forte 			}
275*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "\n");
276*fcf3ce44SJohn Forte 			/* let parent know about the error. */
277*fcf3ce44SJohn Forte 			exit(ENOEXEC);
278*fcf3ce44SJohn Forte 		}
279*fcf3ce44SJohn Forte 	}
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 	/* parent executes the following. */
282*fcf3ce44SJohn Forte 	if (waitpid(pid, &status, 0) != pid) {
283*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
284*fcf3ce44SJohn Forte 			MSGSTR(5503,
285*fcf3ce44SJohn Forte 			"Error: waitpid() failed.\n"));
286*fcf3ce44SJohn Forte 		return (-1);
287*fcf3ce44SJohn Forte 	}
288*fcf3ce44SJohn Forte 	if (WIFEXITED(status) &&
289*fcf3ce44SJohn Forte 			WEXITSTATUS(status) == ENOEXEC) {
290*fcf3ce44SJohn Forte 		/* child failed to run the command string. */
291*fcf3ce44SJohn Forte 		return (-1);
292*fcf3ce44SJohn Forte 	}
293*fcf3ce44SJohn Forte 	return (0);
294*fcf3ce44SJohn Forte 
295*fcf3ce44SJohn Forte }
296*fcf3ce44SJohn Forte 
297*fcf3ce44SJohn Forte 
298*fcf3ce44SJohn Forte 
299*fcf3ce44SJohn Forte 
300*fcf3ce44SJohn Forte /*
301*fcf3ce44SJohn Forte  * frees the hotplug disk list structure.
302*fcf3ce44SJohn Forte  *
303*fcf3ce44SJohn Forte  * RETURNS:
304*fcf3ce44SJohn Forte  *	N/A
305*fcf3ce44SJohn Forte  */
306*fcf3ce44SJohn Forte void
307*fcf3ce44SJohn Forte h_free_hotplug_dlist(Hotplug_Devlist **hotplug_dlist)
308*fcf3ce44SJohn Forte {
309*fcf3ce44SJohn Forte Hotplug_Devlist	*list = NULL;
310*fcf3ce44SJohn Forte 
311*fcf3ce44SJohn Forte 	while (*hotplug_dlist != NULL) {
312*fcf3ce44SJohn Forte 		list = *hotplug_dlist;
313*fcf3ce44SJohn Forte 		*hotplug_dlist = (*hotplug_dlist)->next;
314*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->seslist);
315*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->dlhead);
316*fcf3ce44SJohn Forte 		(void) free((void *)list);
317*fcf3ce44SJohn Forte 	}
318*fcf3ce44SJohn Forte }
319*fcf3ce44SJohn Forte 
320*fcf3ce44SJohn Forte 
321*fcf3ce44SJohn Forte /*
322*fcf3ce44SJohn Forte  * finds whether device (SENA or an FCAL device) is busy or not.
323*fcf3ce44SJohn Forte  *
324*fcf3ce44SJohn Forte  * OUTPUT:
325*fcf3ce44SJohn Forte  *	busy_flag = 1 (if device busy)
326*fcf3ce44SJohn Forte  *
327*fcf3ce44SJohn Forte  * RETURNS:
328*fcf3ce44SJohn Forte  *	0	 if O.K.
329*fcf3ce44SJohn Forte  *	non-zero otherwise
330*fcf3ce44SJohn Forte  */
331*fcf3ce44SJohn Forte static int
332*fcf3ce44SJohn Forte h_chk_dev_busy(Hotplug_Devlist *hotplug_dev, WWN_list *wwn_list,
333*fcf3ce44SJohn Forte 		int *busy_flag, int force_flag, int verbose_flag)
334*fcf3ce44SJohn Forte {
335*fcf3ce44SJohn Forte int	err;
336*fcf3ce44SJohn Forte struct dlist *dlist;
337*fcf3ce44SJohn Forte 
338*fcf3ce44SJohn Forte 	if (hotplug_dev->dev_type == DTYPE_ESI) {
339*fcf3ce44SJohn Forte 		if ((err = l_offline_photon(hotplug_dev, wwn_list,
340*fcf3ce44SJohn Forte 					force_flag, verbose_flag)) != 0) {
341*fcf3ce44SJohn Forte 			if (err == L_DEV_BUSY) {
342*fcf3ce44SJohn Forte 				*busy_flag = 1;
343*fcf3ce44SJohn Forte 			} else {
344*fcf3ce44SJohn Forte 				return (err);
345*fcf3ce44SJohn Forte 			}
346*fcf3ce44SJohn Forte 		}
347*fcf3ce44SJohn Forte 		for (dlist = hotplug_dev->dlhead;
348*fcf3ce44SJohn Forte 				dlist != NULL; dlist = dlist->next) {
349*fcf3ce44SJohn Forte 			(void) g_online_drive(dlist->multipath,
350*fcf3ce44SJohn Forte 							force_flag);
351*fcf3ce44SJohn Forte 		}
352*fcf3ce44SJohn Forte 	} else {
353*fcf3ce44SJohn Forte 		if ((err = g_offline_drive(hotplug_dev->dlhead,
354*fcf3ce44SJohn Forte 						force_flag)) != 0) {
355*fcf3ce44SJohn Forte 			if (err == L_DEV_BUSY) {
356*fcf3ce44SJohn Forte 				*busy_flag = 1;
357*fcf3ce44SJohn Forte 			} else {
358*fcf3ce44SJohn Forte 				return (err);
359*fcf3ce44SJohn Forte 			}
360*fcf3ce44SJohn Forte 		}
361*fcf3ce44SJohn Forte 		(void) g_online_drive(hotplug_dev->dlhead, force_flag);
362*fcf3ce44SJohn Forte 	}
363*fcf3ce44SJohn Forte 	return (0);
364*fcf3ce44SJohn Forte }
365*fcf3ce44SJohn Forte 
366*fcf3ce44SJohn Forte 
367*fcf3ce44SJohn Forte 
368*fcf3ce44SJohn Forte /*
369*fcf3ce44SJohn Forte  * prints the given list to stdout,
370*fcf3ce44SJohn Forte  * gets the input from user whether
371*fcf3ce44SJohn Forte  * to skip the busy devices or quit
372*fcf3ce44SJohn Forte  * and passes that input to the calling
373*fcf3ce44SJohn Forte  * function.
374*fcf3ce44SJohn Forte  *
375*fcf3ce44SJohn Forte  * OUTPUT:
376*fcf3ce44SJohn Forte  *	int	*action
377*fcf3ce44SJohn Forte  *		s = Skip
378*fcf3ce44SJohn Forte  *		q = Quit
379*fcf3ce44SJohn Forte  *
380*fcf3ce44SJohn Forte  * RETURNS:
381*fcf3ce44SJohn Forte  *	0	 if OK
382*fcf3ce44SJohn Forte  *	non-zero otherwise
383*fcf3ce44SJohn Forte  */
384*fcf3ce44SJohn Forte static	int
385*fcf3ce44SJohn Forte h_print_list(Hotplug_Devlist *bsyRsrv_disk_list, int *action, int enc_type)
386*fcf3ce44SJohn Forte {
387*fcf3ce44SJohn Forte Hotplug_Devlist *list;
388*fcf3ce44SJohn Forte int		i = 1;
389*fcf3ce44SJohn Forte char		choice[2];
390*fcf3ce44SJohn Forte 
391*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
392*fcf3ce44SJohn Forte 	    MSGSTR(5504, "The list of devices being used"
393*fcf3ce44SJohn Forte 	    " (either busy or reserved) by the host:\n"));
394*fcf3ce44SJohn Forte 	for (list = bsyRsrv_disk_list; list != NULL; list = list->next, i++) {
395*fcf3ce44SJohn Forte 	    if ((list->dev_type == DTYPE_DIRECT) &&
396*fcf3ce44SJohn Forte 		(list->dev_location == SENA)) {
397*fcf3ce44SJohn Forte 		if (list->f_flag != NULL) {
398*fcf3ce44SJohn Forte 		    if (enc_type == DAK_ENC_TYPE) {
399*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5663,
400*fcf3ce44SJohn Forte 			    "  %d: Box Name:    \"%s\"  slot %d\n"),
401*fcf3ce44SJohn Forte 			    i, list->box_name, list->slot);
402*fcf3ce44SJohn Forte 		    } else {
403*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(137,
404*fcf3ce44SJohn Forte 			    "  %d: Box Name:    \"%s\" front slot %d\n"),
405*fcf3ce44SJohn Forte 			    i, list->box_name, list->slot);
406*fcf3ce44SJohn Forte 		    }
407*fcf3ce44SJohn Forte 		} else {
408*fcf3ce44SJohn Forte 		    if (enc_type == DAK_ENC_TYPE) {
409*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5663,
410*fcf3ce44SJohn Forte 			    "  %d: Box Name:    \"%s\"  slot %d\n"),
411*fcf3ce44SJohn Forte 			    i, list->box_name, list->slot + (MAX_DRIVES_DAK/2));
412*fcf3ce44SJohn Forte 		    } else {
413*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(136,
414*fcf3ce44SJohn Forte 				"  %d: Box Name:    \"%s\" rear slot %d\n"),
415*fcf3ce44SJohn Forte 				i, list->box_name, list->slot);
416*fcf3ce44SJohn Forte 		    }
417*fcf3ce44SJohn Forte 		}
418*fcf3ce44SJohn Forte 	    } else if (((list->dev_type == DTYPE_DIRECT) ||
419*fcf3ce44SJohn Forte 			(list->dev_type == DTYPE_SEQUENTIAL)) &&
420*fcf3ce44SJohn Forte 			(list->dev_location == NON_SENA)) {
421*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5505,
422*fcf3ce44SJohn Forte 		    "  %d: Device %s\n"),
423*fcf3ce44SJohn Forte 		    i, list->dev_name);
424*fcf3ce44SJohn Forte 	    } else if (list->dev_type == DTYPE_ESI) {
425*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5506,
426*fcf3ce44SJohn Forte 		    "  %d: Box: %s\n"),
427*fcf3ce44SJohn Forte 		    i, list->box_name);
428*fcf3ce44SJohn Forte 	    }
429*fcf3ce44SJohn Forte 	}
430*fcf3ce44SJohn Forte 
431*fcf3ce44SJohn Forte 	/* Get the user input and continue accordingly. */
432*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
433*fcf3ce44SJohn Forte 		MSGSTR(5507,
434*fcf3ce44SJohn Forte 		"\n\nPlease enter 's' or <CR> to Skip the \"busy/reserved\""
435*fcf3ce44SJohn Forte 		" device(s) or\n'q' to Quit and run the"
436*fcf3ce44SJohn Forte 		" subcommand with\n-F (force) option. [Default: s]: "));
437*fcf3ce44SJohn Forte 	for (;;) {
438*fcf3ce44SJohn Forte 		(void) gets(choice);
439*fcf3ce44SJohn Forte 		if (choice[0] == 'q' || choice[0] == 'Q' ||
440*fcf3ce44SJohn Forte 			choice[0] == 's' || choice[0] == 'S' ||
441*fcf3ce44SJohn Forte 			choice[0] == '\0') {
442*fcf3ce44SJohn Forte 			break;
443*fcf3ce44SJohn Forte 		}
444*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5508,
445*fcf3ce44SJohn Forte 			" Enter an appropriate option [s,<CR>,q]: "));
446*fcf3ce44SJohn Forte 	}
447*fcf3ce44SJohn Forte 	if (choice[0] == 'q' || choice[0] == 'Q') {
448*fcf3ce44SJohn Forte 		*action = QUIT;
449*fcf3ce44SJohn Forte 	} else {
450*fcf3ce44SJohn Forte 		*action = SKIP;
451*fcf3ce44SJohn Forte 	}
452*fcf3ce44SJohn Forte 	(void) fprintf(stdout, "\n\n");
453*fcf3ce44SJohn Forte 	return (0);
454*fcf3ce44SJohn Forte }
455*fcf3ce44SJohn Forte 
456*fcf3ce44SJohn Forte 
457*fcf3ce44SJohn Forte 
458*fcf3ce44SJohn Forte /*
459*fcf3ce44SJohn Forte  * prints the warning message.
460*fcf3ce44SJohn Forte  *
461*fcf3ce44SJohn Forte  * RETURNS:
462*fcf3ce44SJohn Forte  *	None.
463*fcf3ce44SJohn Forte  */
464*fcf3ce44SJohn Forte static void
465*fcf3ce44SJohn Forte h_prt_warning()
466*fcf3ce44SJohn Forte {
467*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
468*fcf3ce44SJohn Forte 			MSGSTR(5509,
469*fcf3ce44SJohn Forte 			"\n WARNING!!! Please ensure that no"
470*fcf3ce44SJohn Forte 			" filesystems are mounted on these device(s).\n"
471*fcf3ce44SJohn Forte 			" All data on these devices should have been"
472*fcf3ce44SJohn Forte 			" backed up.\n\n\n"));
473*fcf3ce44SJohn Forte }
474*fcf3ce44SJohn Forte 
475*fcf3ce44SJohn Forte 
476*fcf3ce44SJohn Forte 
477*fcf3ce44SJohn Forte /*
478*fcf3ce44SJohn Forte  * handle helper-mode hotplug commands
479*fcf3ce44SJohn Forte  *
480*fcf3ce44SJohn Forte  * RETURNS:
481*fcf3ce44SJohn Forte  *	0	 if OK
482*fcf3ce44SJohn Forte  *	non-zero otherwise
483*fcf3ce44SJohn Forte  */
484*fcf3ce44SJohn Forte int
485*fcf3ce44SJohn Forte hotplug(int todo, char **argv, int verbose_flag, int force_flag)
486*fcf3ce44SJohn Forte {
487*fcf3ce44SJohn Forte char		ses_path[MAXPATHLEN], dev_path[MAXPATHLEN];
488*fcf3ce44SJohn Forte char		*path_phys = NULL, code, node_wwn_s[WWN_S_LEN];
489*fcf3ce44SJohn Forte char		inq_path[MAXNAMELEN], *ptr = NULL;
490*fcf3ce44SJohn Forte uchar_t		node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
491*fcf3ce44SJohn Forte int		tid, slot, path_index, dtype, f_r, err = 0;
492*fcf3ce44SJohn Forte int		al_pa, i, dev_location, found_nullwwn = 0;
493*fcf3ce44SJohn Forte int		busy_flag = 0, reserve_flag = 0, action = 0;
494*fcf3ce44SJohn Forte int		pathcnt = 1;
495*fcf3ce44SJohn Forte L_state		l_state;
496*fcf3ce44SJohn Forte gfc_map_t	map;
497*fcf3ce44SJohn Forte Path_struct	*path_struct;
498*fcf3ce44SJohn Forte WWN_list	*wwn_list = NULL;
499*fcf3ce44SJohn Forte Box_list	*box_list;
500*fcf3ce44SJohn Forte Hotplug_Devlist	*disk_list, *disk_list_head, *disk_list_tail;
501*fcf3ce44SJohn Forte Hotplug_Devlist	*bsyRsrv_dskLst_head, *bsyRsrv_dskLst_tail;
502*fcf3ce44SJohn Forte int		enc_type;
503*fcf3ce44SJohn Forte L_inquiry   inq;
504*fcf3ce44SJohn Forte char	    *physpath;
505*fcf3ce44SJohn Forte Path_struct *p_pathstruct;
506*fcf3ce44SJohn Forte char		temp2path[MAXPATHLEN];
507*fcf3ce44SJohn Forte mp_pathlist_t	pathlist;
508*fcf3ce44SJohn Forte int		p_pw = 0, p_on = 0, p_st = 0;
509*fcf3ce44SJohn Forte 
510*fcf3ce44SJohn Forte 	/* Initialize structures and pointers here */
511*fcf3ce44SJohn Forte 	disk_list_head = disk_list_tail = (Hotplug_Devlist *)NULL;
512*fcf3ce44SJohn Forte 	bsyRsrv_dskLst_head = (Hotplug_Devlist *)NULL;
513*fcf3ce44SJohn Forte 	bsyRsrv_dskLst_tail = (Hotplug_Devlist *)NULL;
514*fcf3ce44SJohn Forte 	map.dev_addr = NULL;
515*fcf3ce44SJohn Forte 
516*fcf3ce44SJohn Forte #ifdef	DEBUG
517*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
518*fcf3ce44SJohn Forte 			"DEBUG: luxadm: hotplug() entering for \"%s\" ...\n",
519*fcf3ce44SJohn Forte 			argv[0] ? argv[0] : "<null ptr>");
520*fcf3ce44SJohn Forte #endif
521*fcf3ce44SJohn Forte 	if ((err = l_get_box_list(&box_list, 0)) != 0) {
522*fcf3ce44SJohn Forte 		return (err);
523*fcf3ce44SJohn Forte 	}
524*fcf3ce44SJohn Forte 
525*fcf3ce44SJohn Forte 	if (todo == REMOVE_DEVICE) {
526*fcf3ce44SJohn Forte 		(void) h_prt_warning();
527*fcf3ce44SJohn Forte 	}
528*fcf3ce44SJohn Forte 
529*fcf3ce44SJohn Forte 	/*
530*fcf3ce44SJohn Forte 	 * At this point user want to insert or remove
531*fcf3ce44SJohn Forte 	 * one or more pathnames they've specified.
532*fcf3ce44SJohn Forte 	 */
533*fcf3ce44SJohn Forte 	if ((err = g_get_wwn_list(&wwn_list, verbose_flag)) != 0) {
534*fcf3ce44SJohn Forte 		(void) l_free_box_list(&box_list);
535*fcf3ce44SJohn Forte 		return (err);
536*fcf3ce44SJohn Forte 	}
537*fcf3ce44SJohn Forte 	for (path_index = 0; argv[path_index] != NULL; path_index++) {
538*fcf3ce44SJohn Forte 		if ((err = l_convert_name(argv[path_index], &path_phys,
539*fcf3ce44SJohn Forte 					&path_struct, verbose_flag)) != 0) {
540*fcf3ce44SJohn Forte 			/* Make sure we have a device path. */
541*fcf3ce44SJohn Forte 			(void) strcpy(inq_path, argv[path_index]);
542*fcf3ce44SJohn Forte 			if (((ptr = strstr(inq_path, ",")) != NULL) &&
543*fcf3ce44SJohn Forte 				((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') ||
544*fcf3ce44SJohn Forte 				    (*(ptr +1) == 's')) &&
545*fcf3ce44SJohn Forte 							todo == REMOVE_DEVICE) {
546*fcf3ce44SJohn Forte 				if (err != -1) {
547*fcf3ce44SJohn Forte 					(void) print_errString(err,
548*fcf3ce44SJohn Forte 							argv[path_index]);
549*fcf3ce44SJohn Forte 					err = 0;
550*fcf3ce44SJohn Forte 					continue;
551*fcf3ce44SJohn Forte 				}
552*fcf3ce44SJohn Forte 				*ptr = NULL;
553*fcf3ce44SJohn Forte 				slot = path_struct->slot;
554*fcf3ce44SJohn Forte 				f_r = path_struct->f_flag;
555*fcf3ce44SJohn Forte 				if ((err = l_convert_name(inq_path, &path_phys,
556*fcf3ce44SJohn Forte 					&path_struct, verbose_flag)) != 0) {
557*fcf3ce44SJohn Forte 					(void) fprintf(stderr, "\n");
558*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
559*fcf3ce44SJohn Forte 							MSGSTR(33,
560*fcf3ce44SJohn Forte 						" Error: converting"
561*fcf3ce44SJohn Forte 						" %s to physical path.\n"
562*fcf3ce44SJohn Forte 						" Invalid pathname.\n"),
563*fcf3ce44SJohn Forte 						argv[path_index]);
564*fcf3ce44SJohn Forte 					if (err != -1) {
565*fcf3ce44SJohn Forte 						(void) print_errString(err,
566*fcf3ce44SJohn Forte 							argv[path_index]);
567*fcf3ce44SJohn Forte 					}
568*fcf3ce44SJohn Forte 					err = 0;
569*fcf3ce44SJohn Forte 					continue;
570*fcf3ce44SJohn Forte 				}
571*fcf3ce44SJohn Forte 				if ((err = print_devState(argv[path_index],
572*fcf3ce44SJohn Forte 						path_struct->p_physical_path,
573*fcf3ce44SJohn Forte 					f_r, slot, verbose_flag)) != 0) {
574*fcf3ce44SJohn Forte 						err = 0;
575*fcf3ce44SJohn Forte 						continue;
576*fcf3ce44SJohn Forte 				}
577*fcf3ce44SJohn Forte 			}
578*fcf3ce44SJohn Forte 			if (path_struct->ib_path_flag) {
579*fcf3ce44SJohn Forte 				path_phys = path_struct->p_physical_path;
580*fcf3ce44SJohn Forte 			} else {
581*fcf3ce44SJohn Forte 				if (err != -1) {
582*fcf3ce44SJohn Forte 					(void) print_errString(err,
583*fcf3ce44SJohn Forte 							argv[path_index]);
584*fcf3ce44SJohn Forte 				} else {
585*fcf3ce44SJohn Forte 					(void) fprintf(stderr, "\n");
586*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
587*fcf3ce44SJohn Forte 						MSGSTR(33,
588*fcf3ce44SJohn Forte 						" Error: converting"
589*fcf3ce44SJohn Forte 						" %s to physical path.\n"
590*fcf3ce44SJohn Forte 						" Invalid pathname.\n"),
591*fcf3ce44SJohn Forte 						argv[path_index]);
592*fcf3ce44SJohn Forte 				}
593*fcf3ce44SJohn Forte 				err = 0;
594*fcf3ce44SJohn Forte 				continue;
595*fcf3ce44SJohn Forte 			}
596*fcf3ce44SJohn Forte 		}
597*fcf3ce44SJohn Forte 		if (path_struct->slot_valid ||
598*fcf3ce44SJohn Forte 					strstr(path_phys, DRV_NAME_SSD)) {
599*fcf3ce44SJohn Forte 			dtype = DTYPE_DIRECT;
600*fcf3ce44SJohn Forte 		} else if (strstr(path_phys, SLSH_DRV_NAME_ST)) {
601*fcf3ce44SJohn Forte 			dtype = DTYPE_SEQUENTIAL;
602*fcf3ce44SJohn Forte 		} else {
603*fcf3ce44SJohn Forte 			dtype = DTYPE_ESI;
604*fcf3ce44SJohn Forte 		}
605*fcf3ce44SJohn Forte 
606*fcf3ce44SJohn Forte 		if (strstr(path_phys, SCSI_VHCI) != NULL) {
607*fcf3ce44SJohn Forte 			/* obtain phci */
608*fcf3ce44SJohn Forte 			(void) strcpy(temp2path, path_phys);
609*fcf3ce44SJohn Forte 			if (err = g_get_pathlist(temp2path, &pathlist)) {
610*fcf3ce44SJohn Forte 				(void) print_errString(err, NULL);
611*fcf3ce44SJohn Forte 				exit(-1);
612*fcf3ce44SJohn Forte 			}
613*fcf3ce44SJohn Forte 			pathcnt = pathlist.path_count;
614*fcf3ce44SJohn Forte 			p_pw = p_on = p_st = 0;
615*fcf3ce44SJohn Forte 			for (i = 0; i < pathcnt; i++) {
616*fcf3ce44SJohn Forte 				if (pathlist.path_info[i].path_state <
617*fcf3ce44SJohn Forte 					MAXPATHSTATE) {
618*fcf3ce44SJohn Forte 					if (strstr(pathlist.path_info[i].
619*fcf3ce44SJohn Forte 						path_addr,
620*fcf3ce44SJohn Forte 						path_struct->argv) != NULL) {
621*fcf3ce44SJohn Forte 						p_pw = i;
622*fcf3ce44SJohn Forte 						break;
623*fcf3ce44SJohn Forte 					}
624*fcf3ce44SJohn Forte 					if (pathlist.path_info[i].path_state ==
625*fcf3ce44SJohn Forte 						MDI_PATHINFO_STATE_ONLINE) {
626*fcf3ce44SJohn Forte 						p_on = i;
627*fcf3ce44SJohn Forte 					}
628*fcf3ce44SJohn Forte 					if (pathlist.path_info[i].path_state ==
629*fcf3ce44SJohn Forte 						MDI_PATHINFO_STATE_STANDBY) {
630*fcf3ce44SJohn Forte 						p_st = i;
631*fcf3ce44SJohn Forte 					}
632*fcf3ce44SJohn Forte 				}
633*fcf3ce44SJohn Forte 			}
634*fcf3ce44SJohn Forte 			if (strstr(pathlist.path_info[p_pw].path_addr,
635*fcf3ce44SJohn Forte 				path_struct->argv) != NULL) {
636*fcf3ce44SJohn Forte 				/* matching input pwwn */
637*fcf3ce44SJohn Forte 				(void) strcpy(temp2path,
638*fcf3ce44SJohn Forte 					pathlist.path_info[p_pw].path_hba);
639*fcf3ce44SJohn Forte 			} else if (pathlist.path_info[p_on].path_state ==
640*fcf3ce44SJohn Forte 				MDI_PATHINFO_STATE_ONLINE) {
641*fcf3ce44SJohn Forte 				/* on_line path */
642*fcf3ce44SJohn Forte 				(void) strcpy(temp2path,
643*fcf3ce44SJohn Forte 					pathlist.path_info[p_on].path_hba);
644*fcf3ce44SJohn Forte 			} else {
645*fcf3ce44SJohn Forte 				/* standby or path0 */
646*fcf3ce44SJohn Forte 				(void) strcpy(temp2path,
647*fcf3ce44SJohn Forte 					pathlist.path_info[p_st].path_hba);
648*fcf3ce44SJohn Forte 			}
649*fcf3ce44SJohn Forte 			free(pathlist.path_info);
650*fcf3ce44SJohn Forte 			(void) strcat(temp2path, FC_CTLR);
651*fcf3ce44SJohn Forte 		} else {
652*fcf3ce44SJohn Forte 			(void) strcpy(temp2path, path_phys);
653*fcf3ce44SJohn Forte 		}
654*fcf3ce44SJohn Forte 
655*fcf3ce44SJohn Forte 		if ((err = g_get_dev_map(temp2path, &map, verbose_flag))
656*fcf3ce44SJohn Forte 			!= 0) {
657*fcf3ce44SJohn Forte 			return (err);
658*fcf3ce44SJohn Forte 		}
659*fcf3ce44SJohn Forte 
660*fcf3ce44SJohn Forte 		if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
661*fcf3ce44SJohn Forte 			(map.hba_addr.port_topology == FC_TOP_FABRIC)) {
662*fcf3ce44SJohn Forte 			/* public or fabric loop device */
663*fcf3ce44SJohn Forte 				free((void *)map.dev_addr);
664*fcf3ce44SJohn Forte 				(void) fprintf(stderr, MSGSTR(5540,
665*fcf3ce44SJohn Forte 				"This operation is not "
666*fcf3ce44SJohn Forte 				"supported in this topology.\n"));
667*fcf3ce44SJohn Forte 				exit(-1);
668*fcf3ce44SJohn Forte 		}
669*fcf3ce44SJohn Forte 
670*fcf3ce44SJohn Forte 		if (todo == REPLACE_DEVICE) {
671*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
672*fcf3ce44SJohn Forte 				MSGSTR(5511,
673*fcf3ce44SJohn Forte 				"Error:"
674*fcf3ce44SJohn Forte 				" replace_device is not supported"
675*fcf3ce44SJohn Forte 				" on this subsystem.\n"));
676*fcf3ce44SJohn Forte 			exit(-1);
677*fcf3ce44SJohn Forte 		}
678*fcf3ce44SJohn Forte 
679*fcf3ce44SJohn Forte 		if ((todo == REMOVE_DEVICE) &&
680*fcf3ce44SJohn Forte 				(dtype == DTYPE_DIRECT ||
681*fcf3ce44SJohn Forte 				dtype == DTYPE_SEQUENTIAL ||
682*fcf3ce44SJohn Forte 				dtype == DTYPE_UNKNOWN)) {
683*fcf3ce44SJohn Forte 			if (l_chk_null_wwn(path_struct, ses_path,
684*fcf3ce44SJohn Forte 				&l_state, verbose_flag) == 1) {
685*fcf3ce44SJohn Forte 				found_nullwwn = 1;
686*fcf3ce44SJohn Forte 				/*
687*fcf3ce44SJohn Forte 				 * set dev_path to NULL,
688*fcf3ce44SJohn Forte 				 * if disk has null wwn.
689*fcf3ce44SJohn Forte 				 */
690*fcf3ce44SJohn Forte 				*dev_path = NULL;
691*fcf3ce44SJohn Forte 				dev_location = SENA;
692*fcf3ce44SJohn Forte 				goto getinfo;
693*fcf3ce44SJohn Forte 			}
694*fcf3ce44SJohn Forte 		}
695*fcf3ce44SJohn Forte 
696*fcf3ce44SJohn Forte 		(void) strcpy(ses_path, path_phys);
697*fcf3ce44SJohn Forte 
698*fcf3ce44SJohn Forte 		if (strstr(ses_path, "ses") == NULL &&
699*fcf3ce44SJohn Forte 			l_get_ses_path(path_phys, ses_path, &map,
700*fcf3ce44SJohn Forte 					verbose_flag) != 0) {
701*fcf3ce44SJohn Forte 
702*fcf3ce44SJohn Forte 			/* Could be a non-photon disk device */
703*fcf3ce44SJohn Forte 			if ((todo == REMOVE_DEVICE) &&
704*fcf3ce44SJohn Forte 					(dtype == DTYPE_DIRECT ||
705*fcf3ce44SJohn Forte 					dtype == DTYPE_SEQUENTIAL)) {
706*fcf3ce44SJohn Forte 				dev_location = NON_SENA;
707*fcf3ce44SJohn Forte 
708*fcf3ce44SJohn Forte 				if ((err = h_get_fcdev_state(argv[path_index],
709*fcf3ce44SJohn Forte 						path_phys, force_flag,
710*fcf3ce44SJohn Forte 						&busy_flag, &reserve_flag,
711*fcf3ce44SJohn Forte 						verbose_flag)) != 0) {
712*fcf3ce44SJohn Forte 					goto done;
713*fcf3ce44SJohn Forte 				}
714*fcf3ce44SJohn Forte 				(void) strcpy(dev_path, path_phys);
715*fcf3ce44SJohn Forte 				if ((err = g_get_wwn(dev_path, port_wwn,
716*fcf3ce44SJohn Forte 						node_wwn, &al_pa,
717*fcf3ce44SJohn Forte 						verbose_flag)) != 0) {
718*fcf3ce44SJohn Forte 					goto done;
719*fcf3ce44SJohn Forte 				}
720*fcf3ce44SJohn Forte 				(void) sprintf(node_wwn_s,
721*fcf3ce44SJohn Forte 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
722*fcf3ce44SJohn Forte 				node_wwn[0], node_wwn[1], node_wwn[2],
723*fcf3ce44SJohn Forte 				node_wwn[3], node_wwn[4], node_wwn[5],
724*fcf3ce44SJohn Forte 				node_wwn[6], node_wwn[7]);
725*fcf3ce44SJohn Forte 				tid = g_sf_alpa_to_switch[al_pa];
726*fcf3ce44SJohn Forte 				goto loop;
727*fcf3ce44SJohn Forte 			}
728*fcf3ce44SJohn Forte 			continue;
729*fcf3ce44SJohn Forte 		}
730*fcf3ce44SJohn Forte 
731*fcf3ce44SJohn Forte 		if (strstr(ses_path, "ses") != NULL) {
732*fcf3ce44SJohn Forte 			dev_location = SENA;
733*fcf3ce44SJohn Forte 		    if ((err = l_convert_name(ses_path, &physpath,
734*fcf3ce44SJohn Forte 			    &p_pathstruct, 0)) != 0) {
735*fcf3ce44SJohn Forte 			free(physpath);
736*fcf3ce44SJohn Forte 			free(p_pathstruct);
737*fcf3ce44SJohn Forte 			goto done;
738*fcf3ce44SJohn Forte 
739*fcf3ce44SJohn Forte 		    }
740*fcf3ce44SJohn Forte 		    if ((err = g_get_inquiry(physpath, &inq)) != 0) {
741*fcf3ce44SJohn Forte 			free(physpath);
742*fcf3ce44SJohn Forte 			free(p_pathstruct);
743*fcf3ce44SJohn Forte 			goto done;
744*fcf3ce44SJohn Forte 		    }
745*fcf3ce44SJohn Forte 		    enc_type = l_get_enc_type(inq);
746*fcf3ce44SJohn Forte 
747*fcf3ce44SJohn Forte 		}
748*fcf3ce44SJohn Forte 		if ((err = l_get_status(ses_path,
749*fcf3ce44SJohn Forte 				&l_state, verbose_flag)) != 0) {
750*fcf3ce44SJohn Forte 			goto done;
751*fcf3ce44SJohn Forte 		}
752*fcf3ce44SJohn Forte 		if (dtype == DTYPE_ESI) {
753*fcf3ce44SJohn Forte 			/* could be removing a photon */
754*fcf3ce44SJohn Forte 			if (todo == REMOVE_DEVICE) {
755*fcf3ce44SJohn Forte 				/*
756*fcf3ce44SJohn Forte 				 * Need the select ID (tid) for the IB.
757*fcf3ce44SJohn Forte 				 */
758*fcf3ce44SJohn Forte 				if ((err = g_get_wwn(ses_path, port_wwn,
759*fcf3ce44SJohn Forte 						node_wwn, &al_pa,
760*fcf3ce44SJohn Forte 						verbose_flag)) != 0) {
761*fcf3ce44SJohn Forte 						goto done;
762*fcf3ce44SJohn Forte 				}
763*fcf3ce44SJohn Forte 				(void) sprintf(node_wwn_s,
764*fcf3ce44SJohn Forte 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
765*fcf3ce44SJohn Forte 				node_wwn[0], node_wwn[1], node_wwn[2],
766*fcf3ce44SJohn Forte 				node_wwn[3], node_wwn[4], node_wwn[5],
767*fcf3ce44SJohn Forte 				node_wwn[6], node_wwn[7]);
768*fcf3ce44SJohn Forte 				tid = g_sf_alpa_to_switch[al_pa];
769*fcf3ce44SJohn Forte 				*dev_path = '\0';
770*fcf3ce44SJohn Forte 				/*
771*fcf3ce44SJohn Forte 				 * Check if any disk in this photon
772*fcf3ce44SJohn Forte 				 * is reserved by another host
773*fcf3ce44SJohn Forte 				 */
774*fcf3ce44SJohn Forte 				if (!force_flag) {
775*fcf3ce44SJohn Forte 					for (
776*fcf3ce44SJohn Forte 					i = 0;
777*fcf3ce44SJohn Forte 					i < l_state.total_num_drv/2;
778*fcf3ce44SJohn Forte 					i++) {
779*fcf3ce44SJohn Forte 		if ((l_state.drv_front[i].g_disk_state.d_state_flags[PORT_A] &
780*fcf3ce44SJohn Forte 							L_RESERVED) ||
781*fcf3ce44SJohn Forte 		(l_state.drv_front[i].g_disk_state.d_state_flags[PORT_B] &
782*fcf3ce44SJohn Forte 						L_RESERVED) ||
783*fcf3ce44SJohn Forte 		(l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_A] &
784*fcf3ce44SJohn Forte 						L_RESERVED) ||
785*fcf3ce44SJohn Forte 		(l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_B] &
786*fcf3ce44SJohn Forte 						L_RESERVED)) {
787*fcf3ce44SJohn Forte 						reserve_flag = 1;
788*fcf3ce44SJohn Forte 						}
789*fcf3ce44SJohn Forte 					}
790*fcf3ce44SJohn Forte 				}
791*fcf3ce44SJohn Forte 				goto loop;
792*fcf3ce44SJohn Forte 			}
793*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
794*fcf3ce44SJohn Forte 				MSGSTR(5512,
795*fcf3ce44SJohn Forte 				"Error: %s already exists!!\n"),
796*fcf3ce44SJohn Forte 				argv[path_index]);
797*fcf3ce44SJohn Forte 			goto done;
798*fcf3ce44SJohn Forte 		}
799*fcf3ce44SJohn Forte getinfo:
800*fcf3ce44SJohn Forte 		if (!path_struct->slot_valid) {
801*fcf3ce44SJohn Forte 			/* We are passing the disks path */
802*fcf3ce44SJohn Forte 			if ((err = l_get_slot(path_struct, &l_state,
803*fcf3ce44SJohn Forte 					verbose_flag)) != 0) {
804*fcf3ce44SJohn Forte 				goto done;
805*fcf3ce44SJohn Forte 			}
806*fcf3ce44SJohn Forte 		}
807*fcf3ce44SJohn Forte 
808*fcf3ce44SJohn Forte 		slot = path_struct->slot;
809*fcf3ce44SJohn Forte 		if (path_struct->f_flag) {
810*fcf3ce44SJohn Forte 			tid = l_state.drv_front[slot].ib_status.sel_id;
811*fcf3ce44SJohn Forte 			code = l_state.drv_front[slot].ib_status.code;
812*fcf3ce44SJohn Forte 			(void) strcpy(node_wwn_s,
813*fcf3ce44SJohn Forte 			l_state.drv_front[slot].g_disk_state.node_wwn_s);
814*fcf3ce44SJohn Forte 		} else {
815*fcf3ce44SJohn Forte 			tid = l_state.drv_rear[slot].ib_status.sel_id;
816*fcf3ce44SJohn Forte 			code = l_state.drv_rear[slot].ib_status.code;
817*fcf3ce44SJohn Forte 			(void) strcpy(node_wwn_s,
818*fcf3ce44SJohn Forte 			l_state.drv_rear[slot].g_disk_state.node_wwn_s);
819*fcf3ce44SJohn Forte 		}
820*fcf3ce44SJohn Forte 
821*fcf3ce44SJohn Forte 		if (found_nullwwn) {
822*fcf3ce44SJohn Forte 			goto loop;
823*fcf3ce44SJohn Forte 		}
824*fcf3ce44SJohn Forte 
825*fcf3ce44SJohn Forte 		l_make_node(ses_path, tid, dev_path, &map, 0);
826*fcf3ce44SJohn Forte 
827*fcf3ce44SJohn Forte 		if ((todo == INSERT_DEVICE) &&
828*fcf3ce44SJohn Forte 			(g_device_in_map(&map, tid) ||
829*fcf3ce44SJohn Forte 			(code != S_NOT_INSTALLED))) {
830*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
831*fcf3ce44SJohn Forte 				MSGSTR(5513, "\nNotice: %s may "
832*fcf3ce44SJohn Forte 				"already be present.\n"),
833*fcf3ce44SJohn Forte 				argv[path_index]);
834*fcf3ce44SJohn Forte 			if (path_struct->f_flag) {
835*fcf3ce44SJohn Forte 				if ((l_state.drv_front[slot].l_state_flag
836*fcf3ce44SJohn Forte 						!= L_NO_PATH_FOUND) &&
837*fcf3ce44SJohn Forte 				(!l_state.drv_front[slot].ib_status.dev_off))
838*fcf3ce44SJohn Forte 					continue;
839*fcf3ce44SJohn Forte 			} else {
840*fcf3ce44SJohn Forte 				if ((l_state.drv_rear[slot].l_state_flag
841*fcf3ce44SJohn Forte 						!= L_NO_PATH_FOUND) &&
842*fcf3ce44SJohn Forte 				(!l_state.drv_rear[slot].ib_status.dev_off))
843*fcf3ce44SJohn Forte 					continue;
844*fcf3ce44SJohn Forte 			}
845*fcf3ce44SJohn Forte 		}
846*fcf3ce44SJohn Forte 
847*fcf3ce44SJohn Forte 		/* Check if disk is reserved */
848*fcf3ce44SJohn Forte 		if ((todo == REMOVE_DEVICE) && (!force_flag)) {
849*fcf3ce44SJohn Forte 			if (path_struct->f_flag) {
850*fcf3ce44SJohn Forte 	if ((l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_A] &
851*fcf3ce44SJohn Forte 						L_RESERVED) ||
852*fcf3ce44SJohn Forte 		(l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_B] &
853*fcf3ce44SJohn Forte 						L_RESERVED)) {
854*fcf3ce44SJohn Forte 					reserve_flag = 1;
855*fcf3ce44SJohn Forte 				}
856*fcf3ce44SJohn Forte 			} else {
857*fcf3ce44SJohn Forte 		if ((l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_A] &
858*fcf3ce44SJohn Forte 					L_RESERVED) ||
859*fcf3ce44SJohn Forte 		(l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_B] &
860*fcf3ce44SJohn Forte 						L_RESERVED)) {
861*fcf3ce44SJohn Forte 					reserve_flag = 1;
862*fcf3ce44SJohn Forte 				}
863*fcf3ce44SJohn Forte 			}
864*fcf3ce44SJohn Forte 		}
865*fcf3ce44SJohn Forte 
866*fcf3ce44SJohn Forte loop:
867*fcf3ce44SJohn Forte 		if ((disk_list = (Hotplug_Devlist *)
868*fcf3ce44SJohn Forte 			calloc(1, sizeof (Hotplug_Devlist))) == NULL) {
869*fcf3ce44SJohn Forte 			(void) print_errString(L_MALLOC_FAILED, NULL);
870*fcf3ce44SJohn Forte 			goto done;
871*fcf3ce44SJohn Forte 		}
872*fcf3ce44SJohn Forte 
873*fcf3ce44SJohn Forte 		/*
874*fcf3ce44SJohn Forte 		 * dev_path is NULL when removing a whole encloser. We
875*fcf3ce44SJohn Forte 		 * don't want to call g_get_multipath while removing whole
876*fcf3ce44SJohn Forte 		 * enclosure. Its being taken care later in the code path
877*fcf3ce44SJohn Forte 		 */
878*fcf3ce44SJohn Forte 
879*fcf3ce44SJohn Forte 		if ((todo != INSERT_DEVICE) && (dtype != DTYPE_ESI)) {
880*fcf3ce44SJohn Forte 			if ((err = g_get_multipath(dev_path,
881*fcf3ce44SJohn Forte 					&(disk_list->dlhead),
882*fcf3ce44SJohn Forte 					wwn_list, verbose_flag)) != 0) {
883*fcf3ce44SJohn Forte 				if (disk_list->dlhead != NULL) {
884*fcf3ce44SJohn Forte 					(void) g_free_multipath(
885*fcf3ce44SJohn Forte 							disk_list->dlhead);
886*fcf3ce44SJohn Forte 				}
887*fcf3ce44SJohn Forte 				goto done;
888*fcf3ce44SJohn Forte 			}
889*fcf3ce44SJohn Forte 		}
890*fcf3ce44SJohn Forte 		disk_list->dev_type = dtype;
891*fcf3ce44SJohn Forte 		disk_list->dev_location = dev_location;
892*fcf3ce44SJohn Forte 		(void) strcpy(disk_list->dev_name,
893*fcf3ce44SJohn Forte 					argv[path_index]);
894*fcf3ce44SJohn Forte 		disk_list->tid = tid;
895*fcf3ce44SJohn Forte 		(void) strcpy(disk_list->node_wwn_s, node_wwn_s);
896*fcf3ce44SJohn Forte 		if (dev_location == SENA) {
897*fcf3ce44SJohn Forte 			if ((err = l_get_allses(ses_path, box_list,
898*fcf3ce44SJohn Forte 				&(disk_list->seslist), 0)) != 0) {
899*fcf3ce44SJohn Forte 				if (disk_list->seslist != NULL) {
900*fcf3ce44SJohn Forte 				(void) g_free_multipath(disk_list->seslist);
901*fcf3ce44SJohn Forte 				}
902*fcf3ce44SJohn Forte 				goto done;
903*fcf3ce44SJohn Forte 			}
904*fcf3ce44SJohn Forte 			(void) strcpy(disk_list->box_name,
905*fcf3ce44SJohn Forte 				(char *)l_state.ib_tbl.enclosure_name);
906*fcf3ce44SJohn Forte 			disk_list->slot = slot;
907*fcf3ce44SJohn Forte 			disk_list->f_flag = path_struct->f_flag;
908*fcf3ce44SJohn Forte 		}
909*fcf3ce44SJohn Forte 		if (todo == REMOVE_DEVICE && !force_flag && !reserve_flag) {
910*fcf3ce44SJohn Forte 			if ((err = h_chk_dev_busy(disk_list, wwn_list,
911*fcf3ce44SJohn Forte 				&busy_flag, force_flag, verbose_flag)) != 0) {
912*fcf3ce44SJohn Forte 				goto done;
913*fcf3ce44SJohn Forte 			}
914*fcf3ce44SJohn Forte 		}
915*fcf3ce44SJohn Forte 
916*fcf3ce44SJohn Forte 		if (reserve_flag || busy_flag) {
917*fcf3ce44SJohn Forte 			if (reserve_flag)
918*fcf3ce44SJohn Forte 				disk_list->reserve_flag = 1;
919*fcf3ce44SJohn Forte 			if (busy_flag)
920*fcf3ce44SJohn Forte 				disk_list->busy_flag = 1;
921*fcf3ce44SJohn Forte 
922*fcf3ce44SJohn Forte 			if (bsyRsrv_dskLst_head == NULL) {
923*fcf3ce44SJohn Forte 				bsyRsrv_dskLst_head =
924*fcf3ce44SJohn Forte 					bsyRsrv_dskLst_tail = disk_list;
925*fcf3ce44SJohn Forte 			} else {
926*fcf3ce44SJohn Forte 				disk_list->prev = bsyRsrv_dskLst_tail;
927*fcf3ce44SJohn Forte 				bsyRsrv_dskLst_tail->next = disk_list;
928*fcf3ce44SJohn Forte 				bsyRsrv_dskLst_tail = disk_list;
929*fcf3ce44SJohn Forte 			}
930*fcf3ce44SJohn Forte 			reserve_flag = 0;
931*fcf3ce44SJohn Forte 			busy_flag = 0;
932*fcf3ce44SJohn Forte 
933*fcf3ce44SJohn Forte 		} else if (disk_list_head == NULL) {
934*fcf3ce44SJohn Forte 			disk_list_head = disk_list_tail = disk_list;
935*fcf3ce44SJohn Forte 		} else {
936*fcf3ce44SJohn Forte 			disk_list->prev = disk_list_tail;
937*fcf3ce44SJohn Forte 			disk_list_tail->next = disk_list;
938*fcf3ce44SJohn Forte 			disk_list_tail = disk_list;
939*fcf3ce44SJohn Forte 		}
940*fcf3ce44SJohn Forte 	}
941*fcf3ce44SJohn Forte 
942*fcf3ce44SJohn Forte 	if (bsyRsrv_dskLst_head != NULL) {
943*fcf3ce44SJohn Forte 		if ((err = h_print_list(bsyRsrv_dskLst_head,
944*fcf3ce44SJohn Forte 						&action, enc_type)) != 0) {
945*fcf3ce44SJohn Forte 			goto done;
946*fcf3ce44SJohn Forte 		}
947*fcf3ce44SJohn Forte 		if (action == SKIP) {
948*fcf3ce44SJohn Forte 			(void) h_free_hotplug_dlist(&bsyRsrv_dskLst_head);
949*fcf3ce44SJohn Forte 		} else if (action == QUIT) {
950*fcf3ce44SJohn Forte 			goto done;
951*fcf3ce44SJohn Forte 		}
952*fcf3ce44SJohn Forte 	}
953*fcf3ce44SJohn Forte 	if (disk_list_head != NULL) {
954*fcf3ce44SJohn Forte 		if ((h_print_list_warn(disk_list_head, todo, enc_type)) != 0) {
955*fcf3ce44SJohn Forte 			goto done;
956*fcf3ce44SJohn Forte 		}
957*fcf3ce44SJohn Forte 	if ((err = h_pre_hotplug(&disk_list_head, wwn_list, todo, verbose_flag,
958*fcf3ce44SJohn Forte 			    force_flag)) != 0) {
959*fcf3ce44SJohn Forte 			goto done;
960*fcf3ce44SJohn Forte 		}
961*fcf3ce44SJohn Forte 		if (disk_list_head != NULL) {
962*fcf3ce44SJohn Forte 			if (todo == REMOVE_DEVICE) {
963*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5514,
964*fcf3ce44SJohn Forte 					"\nHit <Return> after "
965*fcf3ce44SJohn Forte 					"removing the device(s)."));
966*fcf3ce44SJohn Forte 			} else {
967*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5515,
968*fcf3ce44SJohn Forte 					"\nHit <Return> after "
969*fcf3ce44SJohn Forte 					"inserting the device(s)."));
970*fcf3ce44SJohn Forte 			}
971*fcf3ce44SJohn Forte 			(void) getchar();
972*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
973*fcf3ce44SJohn Forte 			if ((err = h_post_hotplug(disk_list_head, wwn_list,
974*fcf3ce44SJohn Forte 					todo, verbose_flag, force_flag,
975*fcf3ce44SJohn Forte 					enc_type)) != 0) {
976*fcf3ce44SJohn Forte 				goto done;
977*fcf3ce44SJohn Forte 			}
978*fcf3ce44SJohn Forte 		}
979*fcf3ce44SJohn Forte 	}
980*fcf3ce44SJohn Forte done:
981*fcf3ce44SJohn Forte 	(void) l_free_box_list(&box_list);
982*fcf3ce44SJohn Forte 	(void) g_free_wwn_list(&wwn_list);
983*fcf3ce44SJohn Forte 	if (err && err != -1) {
984*fcf3ce44SJohn Forte 		return (err);
985*fcf3ce44SJohn Forte 	}
986*fcf3ce44SJohn Forte 	free((void *)map.dev_addr);
987*fcf3ce44SJohn Forte 	return (0);
988*fcf3ce44SJohn Forte }
989*fcf3ce44SJohn Forte 
990*fcf3ce44SJohn Forte 
991*fcf3ce44SJohn Forte 
992*fcf3ce44SJohn Forte 
993*fcf3ce44SJohn Forte /*
994*fcf3ce44SJohn Forte  * Internal routine to clean up ../'s in paths.
995*fcf3ce44SJohn Forte  * returns 0 if no "../" are left.
996*fcf3ce44SJohn Forte  *
997*fcf3ce44SJohn Forte  * Wouldn't it be nice if there was a standard system library
998*fcf3ce44SJohn Forte  * routine to do this...?
999*fcf3ce44SJohn Forte  */
1000*fcf3ce44SJohn Forte static int
1001*fcf3ce44SJohn Forte cleanup_dotdot_path(char *path)
1002*fcf3ce44SJohn Forte {
1003*fcf3ce44SJohn Forte 	char holder[MAXPATHLEN];
1004*fcf3ce44SJohn Forte 	char *dotdot;
1005*fcf3ce44SJohn Forte 	char *previous_slash;
1006*fcf3ce44SJohn Forte 
1007*fcf3ce44SJohn Forte 	/* Find the first "/../" in the string */
1008*fcf3ce44SJohn Forte 	dotdot = strstr(path, "/../");
1009*fcf3ce44SJohn Forte 	if (dotdot == NULL) {
1010*fcf3ce44SJohn Forte 		return (0);
1011*fcf3ce44SJohn Forte 	}
1012*fcf3ce44SJohn Forte 
1013*fcf3ce44SJohn Forte 
1014*fcf3ce44SJohn Forte 	/*
1015*fcf3ce44SJohn Forte 	 * If the [0] character is '/' and "../" immediatly
1016*fcf3ce44SJohn Forte 	 * follows it, then we can strip the ../
1017*fcf3ce44SJohn Forte 	 *
1018*fcf3ce44SJohn Forte 	 *	/../../foo/bar == /foo/bar
1019*fcf3ce44SJohn Forte 	 *
1020*fcf3ce44SJohn Forte 	 */
1021*fcf3ce44SJohn Forte 	if (dotdot == path) {
1022*fcf3ce44SJohn Forte 		strcpy(holder, &path[3]); /* strip "/.." */
1023*fcf3ce44SJohn Forte 		strcpy(path, holder);
1024*fcf3ce44SJohn Forte 		return (1);
1025*fcf3ce44SJohn Forte 	}
1026*fcf3ce44SJohn Forte 
1027*fcf3ce44SJohn Forte 	/*
1028*fcf3ce44SJohn Forte 	 * Now look for the LAST "/" before the "/../"
1029*fcf3ce44SJohn Forte 	 * as this is the parent dir we can get rid of.
1030*fcf3ce44SJohn Forte 	 * We do this by temporarily truncating the string
1031*fcf3ce44SJohn Forte 	 * at the '/' just before "../" using the dotdot pointer.
1032*fcf3ce44SJohn Forte 	 */
1033*fcf3ce44SJohn Forte 	*dotdot = '\0';
1034*fcf3ce44SJohn Forte 	previous_slash = strrchr(path, '/');
1035*fcf3ce44SJohn Forte 	if (previous_slash == NULL) {
1036*fcf3ce44SJohn Forte 		/*
1037*fcf3ce44SJohn Forte 		 * hmm, somethings wrong.  path looks something
1038*fcf3ce44SJohn Forte 		 * like "foo/../bar/" so we can't really deal with it.
1039*fcf3ce44SJohn Forte 		 */
1040*fcf3ce44SJohn Forte 		return (0);
1041*fcf3ce44SJohn Forte 	}
1042*fcf3ce44SJohn Forte 	/*
1043*fcf3ce44SJohn Forte 	 * Now truncate the path just after the previous '/'
1044*fcf3ce44SJohn Forte 	 * and slam everything after the "../" back on
1045*fcf3ce44SJohn Forte 	 */
1046*fcf3ce44SJohn Forte 	*(previous_slash+1) = '\0';
1047*fcf3ce44SJohn Forte 	(void) strcat(path, dotdot+4);
1048*fcf3ce44SJohn Forte 	return (1); /* We may have more "../"s */
1049*fcf3ce44SJohn Forte }
1050*fcf3ce44SJohn Forte 
1051*fcf3ce44SJohn Forte 
1052*fcf3ce44SJohn Forte /*
1053*fcf3ce44SJohn Forte  * Follow symbolic links from the logical device name to
1054*fcf3ce44SJohn Forte  * the /devfs physical device name.  To be complete, we
1055*fcf3ce44SJohn Forte  * handle the case of multiple links.  This function
1056*fcf3ce44SJohn Forte  * either returns NULL (no links, or some other error),
1057*fcf3ce44SJohn Forte  * or the physical device name, alloc'ed on the heap.
1058*fcf3ce44SJohn Forte  *
1059*fcf3ce44SJohn Forte  * For S10 the physical path may be non-existent.
1060*fcf3ce44SJohn Forte  *
1061*fcf3ce44SJohn Forte  * NOTE: If the path is relative, it will be forced into
1062*fcf3ce44SJohn Forte  * an absolute path by pre-pending the pwd to it.
1063*fcf3ce44SJohn Forte  */
1064*fcf3ce44SJohn Forte char *
1065*fcf3ce44SJohn Forte h_get_physical_name_from_link(char *path)
1066*fcf3ce44SJohn Forte {
1067*fcf3ce44SJohn Forte 	struct stat	stbuf;
1068*fcf3ce44SJohn Forte 	char		source[MAXPATHLEN];
1069*fcf3ce44SJohn Forte 	char		scratch[MAXPATHLEN];
1070*fcf3ce44SJohn Forte 	char		pwd[MAXPATHLEN];
1071*fcf3ce44SJohn Forte 	char		*tmp;
1072*fcf3ce44SJohn Forte 	int			cnt;
1073*fcf3ce44SJohn Forte 
1074*fcf3ce44SJohn Forte 	/* return NULL if path is NULL */
1075*fcf3ce44SJohn Forte 	if (path == NULL) {
1076*fcf3ce44SJohn Forte 		return (NULL);
1077*fcf3ce44SJohn Forte 	}
1078*fcf3ce44SJohn Forte 
1079*fcf3ce44SJohn Forte 	strcpy(source, path);
1080*fcf3ce44SJohn Forte 	for (;;) {
1081*fcf3ce44SJohn Forte 
1082*fcf3ce44SJohn Forte 		/*
1083*fcf3ce44SJohn Forte 		 * First make sure the path is absolute.  If not, make it.
1084*fcf3ce44SJohn Forte 		 * If it's already an absolute path, we have no need
1085*fcf3ce44SJohn Forte 		 * to determine the cwd, so the program should still
1086*fcf3ce44SJohn Forte 		 * function within security-by-obscurity directories.
1087*fcf3ce44SJohn Forte 		 */
1088*fcf3ce44SJohn Forte 		if (source[0] != '/') {
1089*fcf3ce44SJohn Forte 			tmp = getcwd(pwd, MAXPATHLEN);
1090*fcf3ce44SJohn Forte 			if (tmp == NULL) {
1091*fcf3ce44SJohn Forte 				O_DPRINTF("getcwd() failed - %s\n",
1092*fcf3ce44SJohn Forte 					strerror(errno));
1093*fcf3ce44SJohn Forte 				return (NULL);
1094*fcf3ce44SJohn Forte 			}
1095*fcf3ce44SJohn Forte 			/*
1096*fcf3ce44SJohn Forte 			 * Handle special case of "./foo/bar"
1097*fcf3ce44SJohn Forte 			 */
1098*fcf3ce44SJohn Forte 			if (source[0] == '.' && source[1] == '/') {
1099*fcf3ce44SJohn Forte 				strcpy(scratch, source+2);
1100*fcf3ce44SJohn Forte 			} else { /* no "./" so just take everything */
1101*fcf3ce44SJohn Forte 				strcpy(scratch, source);
1102*fcf3ce44SJohn Forte 			}
1103*fcf3ce44SJohn Forte 			strcpy(source, pwd);
1104*fcf3ce44SJohn Forte 			(void) strcat(source, "/");
1105*fcf3ce44SJohn Forte 			(void) strcat(source, scratch);
1106*fcf3ce44SJohn Forte 		}
1107*fcf3ce44SJohn Forte 
1108*fcf3ce44SJohn Forte 		/*
1109*fcf3ce44SJohn Forte 		 * Clean up any "../"s that are in the path
1110*fcf3ce44SJohn Forte 		 */
1111*fcf3ce44SJohn Forte 		while (cleanup_dotdot_path(source));
1112*fcf3ce44SJohn Forte 
1113*fcf3ce44SJohn Forte 		/*
1114*fcf3ce44SJohn Forte 		 * source is now an absolute path to the link we're
1115*fcf3ce44SJohn Forte 		 * concerned with
1116*fcf3ce44SJohn Forte 		 *
1117*fcf3ce44SJohn Forte 		 * S10: Do NOT ignore dangling links, pointing to devfs nodes.
1118*fcf3ce44SJohn Forte 		 */
1119*fcf3ce44SJohn Forte 		if (strstr(source, "/devices")) {
1120*fcf3ce44SJohn Forte 			return (g_alloc_string(source));
1121*fcf3ce44SJohn Forte 		}
1122*fcf3ce44SJohn Forte 
1123*fcf3ce44SJohn Forte 		if (lstat(source, &stbuf) == -1) {
1124*fcf3ce44SJohn Forte 			O_DPRINTF("lstat() failed for - %s\n",
1125*fcf3ce44SJohn Forte 				source, strerror(errno));
1126*fcf3ce44SJohn Forte 			return (NULL);
1127*fcf3ce44SJohn Forte 		}
1128*fcf3ce44SJohn Forte 		/*
1129*fcf3ce44SJohn Forte 		 * If the file is not a link, we're done one
1130*fcf3ce44SJohn Forte 		 * way or the other.  If there were links,
1131*fcf3ce44SJohn Forte 		 * return the full pathname of the resulting
1132*fcf3ce44SJohn Forte 		 * file.
1133*fcf3ce44SJohn Forte 		 *
1134*fcf3ce44SJohn Forte 		 * Note:  All of our temp's are on the stack,
1135*fcf3ce44SJohn Forte 		 * so we have to copy the final result to the heap.
1136*fcf3ce44SJohn Forte 		 */
1137*fcf3ce44SJohn Forte 		if (!S_ISLNK(stbuf.st_mode)) {
1138*fcf3ce44SJohn Forte 			return (g_alloc_string(source));
1139*fcf3ce44SJohn Forte 		}
1140*fcf3ce44SJohn Forte 		cnt = readlink(source, scratch, sizeof (scratch));
1141*fcf3ce44SJohn Forte 		if (cnt < 0) {
1142*fcf3ce44SJohn Forte 			O_DPRINTF("readlink() failed - %s\n",
1143*fcf3ce44SJohn Forte 				strerror(errno));
1144*fcf3ce44SJohn Forte 			return (NULL);
1145*fcf3ce44SJohn Forte 		}
1146*fcf3ce44SJohn Forte 		/*
1147*fcf3ce44SJohn Forte 		 * scratch is on the heap, and for some reason readlink
1148*fcf3ce44SJohn Forte 		 * doesn't always terminate things properly so we have
1149*fcf3ce44SJohn Forte 		 * to make certain we're properly terminated
1150*fcf3ce44SJohn Forte 		 */
1151*fcf3ce44SJohn Forte 		scratch[cnt] = '\0';
1152*fcf3ce44SJohn Forte 
1153*fcf3ce44SJohn Forte 		/*
1154*fcf3ce44SJohn Forte 		 * Now check to see if the link is relative.  If so,
1155*fcf3ce44SJohn Forte 		 * then we have to append it to the directory
1156*fcf3ce44SJohn Forte 		 * which the source was in. (This is non trivial)
1157*fcf3ce44SJohn Forte 		 */
1158*fcf3ce44SJohn Forte 		if (scratch[0] != '/') {
1159*fcf3ce44SJohn Forte 			tmp = strrchr(source, '/');
1160*fcf3ce44SJohn Forte 			if (tmp == NULL) { /* Whoa!  Something's hosed! */
1161*fcf3ce44SJohn Forte 				O_DPRINTF("Internal error... corrupt path.\n");
1162*fcf3ce44SJohn Forte 				return (NULL);
1163*fcf3ce44SJohn Forte 			}
1164*fcf3ce44SJohn Forte 			/* Now strip off just the directory path */
1165*fcf3ce44SJohn Forte 			*(tmp+1) = '\0'; /* Keeping the last '/' */
1166*fcf3ce44SJohn Forte 			/* and append the new link */
1167*fcf3ce44SJohn Forte 			(void) strcat(source, scratch);
1168*fcf3ce44SJohn Forte 			/*
1169*fcf3ce44SJohn Forte 			 * Note:  At this point, source should have "../"s
1170*fcf3ce44SJohn Forte 			 * but we'll clean it up in the next pass through
1171*fcf3ce44SJohn Forte 			 * the loop.
1172*fcf3ce44SJohn Forte 			 */
1173*fcf3ce44SJohn Forte 		} else {
1174*fcf3ce44SJohn Forte 			/* It's an absolute link so no worries */
1175*fcf3ce44SJohn Forte 			strcpy(source, scratch);
1176*fcf3ce44SJohn Forte 		}
1177*fcf3ce44SJohn Forte 	}
1178*fcf3ce44SJohn Forte 	/* Never reach here */
1179*fcf3ce44SJohn Forte }
1180*fcf3ce44SJohn Forte 
1181*fcf3ce44SJohn Forte /*
1182*fcf3ce44SJohn Forte  * Function for getting physical pathnames
1183*fcf3ce44SJohn Forte  *
1184*fcf3ce44SJohn Forte  * For S10 the physical path may not exist at the time devctl calls
1185*fcf3ce44SJohn Forte  * are made. So we should not return error if stat fails on /devices path.
1186*fcf3ce44SJohn Forte  *
1187*fcf3ce44SJohn Forte  * This function can handle 2 different inputs.
1188*fcf3ce44SJohn Forte  *
1189*fcf3ce44SJohn Forte  * 1) Inputs of the form /dev/rdsk/cNtNdNsN
1190*fcf3ce44SJohn Forte  *	These are identified by being a link
1191*fcf3ce44SJohn Forte  *	The physical path they are linked to is returned.
1192*fcf3ce44SJohn Forte  *
1193*fcf3ce44SJohn Forte  * 2) Inputs of the form /devices/...
1194*fcf3ce44SJohn Forte  *	These are actual physical names.
1195*fcf3ce44SJohn Forte  *	They are not converted.
1196*fcf3ce44SJohn Forte  */
1197*fcf3ce44SJohn Forte char *
1198*fcf3ce44SJohn Forte h_get_physical_name(char *path)
1199*fcf3ce44SJohn Forte {
1200*fcf3ce44SJohn Forte 	struct stat	stbuf;
1201*fcf3ce44SJohn Forte 	char		s[MAXPATHLEN];
1202*fcf3ce44SJohn Forte 	char		savedir[MAXPATHLEN];
1203*fcf3ce44SJohn Forte 	char		*result = NULL;
1204*fcf3ce44SJohn Forte 	int		status = 0;
1205*fcf3ce44SJohn Forte 
1206*fcf3ce44SJohn Forte 	/* return invalid path if path NULL */
1207*fcf3ce44SJohn Forte 	if (path == NULL) {
1208*fcf3ce44SJohn Forte 		return (NULL);
1209*fcf3ce44SJohn Forte 	}
1210*fcf3ce44SJohn Forte 
1211*fcf3ce44SJohn Forte 	(void) strcpy(s, path);
1212*fcf3ce44SJohn Forte 
1213*fcf3ce44SJohn Forte 	status = lstat(s, &stbuf);
1214*fcf3ce44SJohn Forte 
1215*fcf3ce44SJohn Forte 	/*
1216*fcf3ce44SJohn Forte 	 * S10: If string is devfs node we allow failed lstat.
1217*fcf3ce44SJohn Forte 	 */
1218*fcf3ce44SJohn Forte 	if ((status == -1) || !S_ISLNK(stbuf.st_mode)) {
1219*fcf3ce44SJohn Forte 		/* Make sure a full path as that is required. */
1220*fcf3ce44SJohn Forte 		if (strstr(s, "/devices")) {
1221*fcf3ce44SJohn Forte 			result = g_alloc_string(s);
1222*fcf3ce44SJohn Forte 		} else {
1223*fcf3ce44SJohn Forte 			if (getcwd(savedir,
1224*fcf3ce44SJohn Forte 				sizeof (savedir)) == NULL) {
1225*fcf3ce44SJohn Forte 				return (NULL);
1226*fcf3ce44SJohn Forte 			}
1227*fcf3ce44SJohn Forte 			/*
1228*fcf3ce44SJohn Forte 			 * Check for this format:
1229*fcf3ce44SJohn Forte 			 * ./ssd@0,1:g,raw
1230*fcf3ce44SJohn Forte 			 */
1231*fcf3ce44SJohn Forte 			if (s[0] == '.') {
1232*fcf3ce44SJohn Forte 				(void) strcat(savedir, &s[1]);
1233*fcf3ce44SJohn Forte 			} else {
1234*fcf3ce44SJohn Forte 				(void) strcat(savedir, "/");
1235*fcf3ce44SJohn Forte 				(void) strcat(savedir, s);
1236*fcf3ce44SJohn Forte 			}
1237*fcf3ce44SJohn Forte 			if ((status != -1) || strstr(s, "/devices")) {
1238*fcf3ce44SJohn Forte 				result = g_alloc_string(savedir);
1239*fcf3ce44SJohn Forte 			}
1240*fcf3ce44SJohn Forte 		}
1241*fcf3ce44SJohn Forte 	} else {
1242*fcf3ce44SJohn Forte 		/*
1243*fcf3ce44SJohn Forte 		 * Entry is linked file
1244*fcf3ce44SJohn Forte 		 * so follow link to physical name
1245*fcf3ce44SJohn Forte 		 */
1246*fcf3ce44SJohn Forte 		result = h_get_physical_name_from_link(path);
1247*fcf3ce44SJohn Forte 	}
1248*fcf3ce44SJohn Forte 
1249*fcf3ce44SJohn Forte exit:
1250*fcf3ce44SJohn Forte 	return (result);
1251*fcf3ce44SJohn Forte }
1252*fcf3ce44SJohn Forte 
1253*fcf3ce44SJohn Forte 
1254*fcf3ce44SJohn Forte /*
1255*fcf3ce44SJohn Forte  * handle expert-mode hotplug commands
1256*fcf3ce44SJohn Forte  *
1257*fcf3ce44SJohn Forte  * return 0 iff all is okay
1258*fcf3ce44SJohn Forte  */
1259*fcf3ce44SJohn Forte int
1260*fcf3ce44SJohn Forte hotplug_e(int todo, char **argv, int verbose_flag, int force_flag)
1261*fcf3ce44SJohn Forte {
1262*fcf3ce44SJohn Forte char		*path_phys = NULL;
1263*fcf3ce44SJohn Forte char		bus_path[MAXPATHLEN];
1264*fcf3ce44SJohn Forte char		*ptr;
1265*fcf3ce44SJohn Forte int		exit_code;
1266*fcf3ce44SJohn Forte devctl_hdl_t	dcp;
1267*fcf3ce44SJohn Forte uint_t		devstate;
1268*fcf3ce44SJohn Forte int		i = 0, pathcnt = 1;
1269*fcf3ce44SJohn Forte mp_pathlist_t	pathlist;
1270*fcf3ce44SJohn Forte int		p_pw = 0, p_on = 0, p_st = 0;
1271*fcf3ce44SJohn Forte 
1272*fcf3ce44SJohn Forte 
1273*fcf3ce44SJohn Forte 	switch (todo) {
1274*fcf3ce44SJohn Forte 	case DEV_ONLINE:
1275*fcf3ce44SJohn Forte 	case DEV_OFFLINE:
1276*fcf3ce44SJohn Forte 	case DEV_GETSTATE:
1277*fcf3ce44SJohn Forte 	case DEV_RESET:
1278*fcf3ce44SJohn Forte 		/* get physical name */
1279*fcf3ce44SJohn Forte 		if ((path_phys = h_get_physical_name(argv[0])) == NULL) {
1280*fcf3ce44SJohn Forte 
1281*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1282*fcf3ce44SJohn Forte 				MSGSTR(112, "Error: Invalid pathname (%s)"),
1283*fcf3ce44SJohn Forte 				argv[0]);
1284*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "\n");
1285*fcf3ce44SJohn Forte 			return (1);
1286*fcf3ce44SJohn Forte 		}
1287*fcf3ce44SJohn Forte 
1288*fcf3ce44SJohn Forte 		if (verbose_flag) {
1289*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1290*fcf3ce44SJohn Forte 					MSGSTR(5516,
1291*fcf3ce44SJohn Forte 					"phys path = \"%s\"\n"),
1292*fcf3ce44SJohn Forte 					path_phys);
1293*fcf3ce44SJohn Forte 		}
1294*fcf3ce44SJohn Forte 
1295*fcf3ce44SJohn Forte 		/* acquire rights to hack on device */
1296*fcf3ce44SJohn Forte 		if ((dcp = devctl_device_acquire(path_phys,
1297*fcf3ce44SJohn Forte 			force_flag ? 0 : DC_EXCL)) == NULL) {
1298*fcf3ce44SJohn Forte 
1299*fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(5517,
1300*fcf3ce44SJohn Forte 			    "Error: can't acquire \"%s\": %s\n"),
1301*fcf3ce44SJohn Forte 			    path_phys, strerror(errno));
1302*fcf3ce44SJohn Forte 			return (1);
1303*fcf3ce44SJohn Forte 		}
1304*fcf3ce44SJohn Forte 
1305*fcf3ce44SJohn Forte 		switch (todo) {
1306*fcf3ce44SJohn Forte 		case DEV_ONLINE:
1307*fcf3ce44SJohn Forte 			exit_code = devctl_device_online(dcp);
1308*fcf3ce44SJohn Forte 			break;
1309*fcf3ce44SJohn Forte 		case DEV_OFFLINE:
1310*fcf3ce44SJohn Forte 			exit_code = devctl_device_offline(dcp);
1311*fcf3ce44SJohn Forte 			break;
1312*fcf3ce44SJohn Forte 		case DEV_GETSTATE:
1313*fcf3ce44SJohn Forte 			if ((exit_code = devctl_device_getstate(dcp,
1314*fcf3ce44SJohn Forte 				&devstate)) == 0) {
1315*fcf3ce44SJohn Forte 				print_dev_state(argv[0], devstate);
1316*fcf3ce44SJohn Forte 			}
1317*fcf3ce44SJohn Forte 			break;
1318*fcf3ce44SJohn Forte 		case DEV_RESET:
1319*fcf3ce44SJohn Forte 			exit_code = devctl_device_reset(dcp);
1320*fcf3ce44SJohn Forte 			break;
1321*fcf3ce44SJohn Forte 		}
1322*fcf3ce44SJohn Forte 
1323*fcf3ce44SJohn Forte 		if (exit_code != 0) {
1324*fcf3ce44SJohn Forte 			perror(MSGSTR(5518, "devctl"));
1325*fcf3ce44SJohn Forte 		}
1326*fcf3ce44SJohn Forte 
1327*fcf3ce44SJohn Forte 		/* all done now -- release device */
1328*fcf3ce44SJohn Forte 		devctl_release(dcp);
1329*fcf3ce44SJohn Forte 		break;
1330*fcf3ce44SJohn Forte 
1331*fcf3ce44SJohn Forte 	/* for hotplugging bus operations */
1332*fcf3ce44SJohn Forte 	case BUS_QUIESCE:
1333*fcf3ce44SJohn Forte 	case BUS_UNQUIESCE:
1334*fcf3ce44SJohn Forte 	case BUS_GETSTATE:
1335*fcf3ce44SJohn Forte 	case BUS_RESET:
1336*fcf3ce44SJohn Forte 	case BUS_RESETALL:
1337*fcf3ce44SJohn Forte 		/* get physical name */
1338*fcf3ce44SJohn Forte 		if ((path_phys = h_get_physical_name(argv[0])) ==
1339*fcf3ce44SJohn Forte 			NULL) {
1340*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1341*fcf3ce44SJohn Forte 				MSGSTR(112, "Error: Invalid pathname (%s)"),
1342*fcf3ce44SJohn Forte 				argv[0]);
1343*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "\n");
1344*fcf3ce44SJohn Forte 			return (1);
1345*fcf3ce44SJohn Forte 		}
1346*fcf3ce44SJohn Forte 		if (verbose_flag) {
1347*fcf3ce44SJohn Forte 			printf(MSGSTR(5519, "phys path = \"%s\"\n"), path_phys);
1348*fcf3ce44SJohn Forte 		}
1349*fcf3ce44SJohn Forte 
1350*fcf3ce44SJohn Forte 		/* acquire rights to hack on device */
1351*fcf3ce44SJohn Forte 		/* delete leaf part from path_phys. */
1352*fcf3ce44SJohn Forte 		if (strstr(path_phys, SCSI_VHCI) != NULL) {
1353*fcf3ce44SJohn Forte 			/* obtain phci */
1354*fcf3ce44SJohn Forte 			(void) strcpy(bus_path, path_phys);
1355*fcf3ce44SJohn Forte 			if (g_get_pathlist(bus_path, &pathlist)) {
1356*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1357*fcf3ce44SJohn Forte 			MSGSTR(112, "Error: Invalid pathname (%s)"),
1358*fcf3ce44SJohn Forte 				path_phys);
1359*fcf3ce44SJohn Forte 				(void) fprintf(stderr, "\n");
1360*fcf3ce44SJohn Forte 				return (1);
1361*fcf3ce44SJohn Forte 			}
1362*fcf3ce44SJohn Forte 			pathcnt = pathlist.path_count;
1363*fcf3ce44SJohn Forte 			p_pw = p_on = p_st = 0;
1364*fcf3ce44SJohn Forte 			for (i = 0; i < pathcnt; i++) {
1365*fcf3ce44SJohn Forte 				if (pathlist.path_info[i].path_state <
1366*fcf3ce44SJohn Forte 					MAXPATHSTATE) {
1367*fcf3ce44SJohn Forte 					if (strstr(pathlist.path_info[i].
1368*fcf3ce44SJohn Forte 						path_addr,
1369*fcf3ce44SJohn Forte 						argv[0]) != NULL) {
1370*fcf3ce44SJohn Forte 						p_pw = i;
1371*fcf3ce44SJohn Forte 						break;
1372*fcf3ce44SJohn Forte 					}
1373*fcf3ce44SJohn Forte 					if (pathlist.path_info[i].path_state ==
1374*fcf3ce44SJohn Forte 						MDI_PATHINFO_STATE_ONLINE) {
1375*fcf3ce44SJohn Forte 						p_on = i;
1376*fcf3ce44SJohn Forte 					}
1377*fcf3ce44SJohn Forte 					if (pathlist.path_info[i].path_state ==
1378*fcf3ce44SJohn Forte 						MDI_PATHINFO_STATE_STANDBY) {
1379*fcf3ce44SJohn Forte 						p_st = i;
1380*fcf3ce44SJohn Forte 					}
1381*fcf3ce44SJohn Forte 				}
1382*fcf3ce44SJohn Forte 			}
1383*fcf3ce44SJohn Forte 			if (strstr(pathlist.path_info[p_pw].path_addr,
1384*fcf3ce44SJohn Forte 				argv[0]) != NULL) {
1385*fcf3ce44SJohn Forte 				/* matching input pwwn */
1386*fcf3ce44SJohn Forte 				(void) strcpy(bus_path,
1387*fcf3ce44SJohn Forte 					pathlist.path_info[p_pw].path_hba);
1388*fcf3ce44SJohn Forte 			} else if (pathlist.path_info[p_on].path_state ==
1389*fcf3ce44SJohn Forte 				MDI_PATHINFO_STATE_ONLINE) {
1390*fcf3ce44SJohn Forte 				/* on_line path */
1391*fcf3ce44SJohn Forte 				(void) strcpy(bus_path,
1392*fcf3ce44SJohn Forte 					pathlist.path_info[p_on].path_hba);
1393*fcf3ce44SJohn Forte 			} else {
1394*fcf3ce44SJohn Forte 				/* standby or path0 */
1395*fcf3ce44SJohn Forte 				(void) strcpy(bus_path,
1396*fcf3ce44SJohn Forte 					pathlist.path_info[p_st].path_hba);
1397*fcf3ce44SJohn Forte 			}
1398*fcf3ce44SJohn Forte 			free(pathlist.path_info);
1399*fcf3ce44SJohn Forte 		} else {
1400*fcf3ce44SJohn Forte 
1401*fcf3ce44SJohn Forte 			(void) strcpy(bus_path, path_phys);
1402*fcf3ce44SJohn Forte 			ptr = strrchr(bus_path, '/');
1403*fcf3ce44SJohn Forte 			if (ptr) {
1404*fcf3ce44SJohn Forte 				*ptr = '\0';
1405*fcf3ce44SJohn Forte 			} else {
1406*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1407*fcf3ce44SJohn Forte 				MSGSTR(112, "Error: Invalid pathname (%s)"),
1408*fcf3ce44SJohn Forte 					path_phys);
1409*fcf3ce44SJohn Forte 				(void) fprintf(stderr, "\n");
1410*fcf3ce44SJohn Forte 				return (1);
1411*fcf3ce44SJohn Forte 			}
1412*fcf3ce44SJohn Forte 		}
1413*fcf3ce44SJohn Forte 
1414*fcf3ce44SJohn Forte 		if ((dcp = devctl_bus_acquire(bus_path,
1415*fcf3ce44SJohn Forte 			force_flag ? 0 : DC_EXCL)) == NULL) {
1416*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1417*fcf3ce44SJohn Forte 					MSGSTR(5521,
1418*fcf3ce44SJohn Forte 				" Error: can't acquire bus node from"
1419*fcf3ce44SJohn Forte 					" the path \"%s\": %s\n"),
1420*fcf3ce44SJohn Forte 					bus_path, strerror(errno));
1421*fcf3ce44SJohn Forte 			return (1);
1422*fcf3ce44SJohn Forte 		}
1423*fcf3ce44SJohn Forte 
1424*fcf3ce44SJohn Forte 		switch (todo) {
1425*fcf3ce44SJohn Forte 		case BUS_QUIESCE:
1426*fcf3ce44SJohn Forte 			exit_code = devctl_bus_quiesce(dcp);
1427*fcf3ce44SJohn Forte 			break;
1428*fcf3ce44SJohn Forte 		case BUS_UNQUIESCE:
1429*fcf3ce44SJohn Forte 			exit_code = devctl_bus_unquiesce(dcp);
1430*fcf3ce44SJohn Forte 			break;
1431*fcf3ce44SJohn Forte 		case BUS_GETSTATE:
1432*fcf3ce44SJohn Forte 			if ((exit_code = devctl_bus_getstate(dcp,
1433*fcf3ce44SJohn Forte 				&devstate)) == 0) {
1434*fcf3ce44SJohn Forte 				print_bus_state(argv[0], devstate);
1435*fcf3ce44SJohn Forte 			}
1436*fcf3ce44SJohn Forte 			break;
1437*fcf3ce44SJohn Forte 		case BUS_RESET:
1438*fcf3ce44SJohn Forte 			exit_code = devctl_bus_reset(dcp);
1439*fcf3ce44SJohn Forte 			break;
1440*fcf3ce44SJohn Forte 		case BUS_RESETALL:
1441*fcf3ce44SJohn Forte 			exit_code = devctl_bus_resetall(dcp);
1442*fcf3ce44SJohn Forte 			break;
1443*fcf3ce44SJohn Forte 		}
1444*fcf3ce44SJohn Forte 
1445*fcf3ce44SJohn Forte 		if (exit_code != 0) {
1446*fcf3ce44SJohn Forte 			perror(MSGSTR(5522, "devctl"));
1447*fcf3ce44SJohn Forte 		}
1448*fcf3ce44SJohn Forte 
1449*fcf3ce44SJohn Forte 		/* all done now -- release device */
1450*fcf3ce44SJohn Forte 		devctl_release(dcp);
1451*fcf3ce44SJohn Forte 		break;
1452*fcf3ce44SJohn Forte 	}
1453*fcf3ce44SJohn Forte 
1454*fcf3ce44SJohn Forte 	return (exit_code);
1455*fcf3ce44SJohn Forte }
1456*fcf3ce44SJohn Forte 
1457*fcf3ce44SJohn Forte 
1458*fcf3ce44SJohn Forte 
1459*fcf3ce44SJohn Forte /*
1460*fcf3ce44SJohn Forte  * Prepares an individual FC_AL device
1461*fcf3ce44SJohn Forte  * to be removed from the specified
1462*fcf3ce44SJohn Forte  * slot.
1463*fcf3ce44SJohn Forte  *
1464*fcf3ce44SJohn Forte  * RETURNS:
1465*fcf3ce44SJohn Forte  *	0	 if OK
1466*fcf3ce44SJohn Forte  *	non-zero otherwise.
1467*fcf3ce44SJohn Forte  */
1468*fcf3ce44SJohn Forte static	int
1469*fcf3ce44SJohn Forte h_pre_remove_dev(Hotplug_Devlist *hotplug_disk, WWN_list *wwn_list,
1470*fcf3ce44SJohn Forte 			int verbose_flag, int force_flag)
1471*fcf3ce44SJohn Forte {
1472*fcf3ce44SJohn Forte char		*dev_path, device_name[MAXNAMELEN];
1473*fcf3ce44SJohn Forte int		err;
1474*fcf3ce44SJohn Forte 
1475*fcf3ce44SJohn Forte 	/* Initialize pointers */
1476*fcf3ce44SJohn Forte 	dev_path = NULL;
1477*fcf3ce44SJohn Forte 
1478*fcf3ce44SJohn Forte 	if (hotplug_disk->dlhead != NULL) {
1479*fcf3ce44SJohn Forte 		dev_path = hotplug_disk->dlhead->dev_path;
1480*fcf3ce44SJohn Forte 	(void) strcpy(device_name, (hotplug_disk->dlhead)->logical_path);
1481*fcf3ce44SJohn Forte 	}
1482*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
1483*fcf3ce44SJohn Forte 			MSGSTR(157,
1484*fcf3ce44SJohn Forte 			"stopping:  %s...."), device_name);
1485*fcf3ce44SJohn Forte 	if (!(strstr(dev_path, SLSH_DRV_NAME_ST))) {
1486*fcf3ce44SJohn Forte 		if ((err = g_dev_stop(dev_path, wwn_list, verbose_flag)) != 0)
1487*fcf3ce44SJohn Forte 			return (err);
1488*fcf3ce44SJohn Forte 	}
1489*fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1490*fcf3ce44SJohn Forte 
1491*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
1492*fcf3ce44SJohn Forte 			MSGSTR(158, "offlining: %s...."), device_name);
1493*fcf3ce44SJohn Forte 	if ((err = g_offline_drive(hotplug_disk->dlhead,
1494*fcf3ce44SJohn Forte 						force_flag)) != 0) {
1495*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
1496*fcf3ce44SJohn Forte 				MSGSTR(160,
1497*fcf3ce44SJohn Forte 				"\nonlining: %s\n"), device_name);
1498*fcf3ce44SJohn Forte 
1499*fcf3ce44SJohn Forte 		(void) g_online_drive(hotplug_disk->dlhead, force_flag);
1500*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
1501*fcf3ce44SJohn Forte 				MSGSTR(159, "starting:  %s...."),
1502*fcf3ce44SJohn Forte 				device_name);
1503*fcf3ce44SJohn Forte 		if ((err = g_dev_start(dev_path, 0)) != 0) {
1504*fcf3ce44SJohn Forte 			return (err);
1505*fcf3ce44SJohn Forte 		}
1506*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1507*fcf3ce44SJohn Forte 		return (err);
1508*fcf3ce44SJohn Forte 	}
1509*fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1510*fcf3ce44SJohn Forte 	return (0);
1511*fcf3ce44SJohn Forte }
1512*fcf3ce44SJohn Forte 
1513*fcf3ce44SJohn Forte 
1514*fcf3ce44SJohn Forte 
1515*fcf3ce44SJohn Forte /*
1516*fcf3ce44SJohn Forte  * Prepares a SENA enclosure or SENA FC_AL device
1517*fcf3ce44SJohn Forte  * to be inserted/removed from a specified slot.
1518*fcf3ce44SJohn Forte  *
1519*fcf3ce44SJohn Forte  * RETURNS:
1520*fcf3ce44SJohn Forte  *	0	 if OK
1521*fcf3ce44SJohn Forte  *	non-zero otherwise.
1522*fcf3ce44SJohn Forte  */
1523*fcf3ce44SJohn Forte static	int
1524*fcf3ce44SJohn Forte h_pre_hotplug_sena(Hotplug_Devlist *hotplug_dev,
1525*fcf3ce44SJohn Forte 			WWN_list *wwn_list, int todo,
1526*fcf3ce44SJohn Forte 			int verbose_flag, int force_flag)
1527*fcf3ce44SJohn Forte {
1528*fcf3ce44SJohn Forte int			slot, f_r, i, found_null_wwn = 0, err;
1529*fcf3ce44SJohn Forte char			*ses_path, *dev_path, code;
1530*fcf3ce44SJohn Forte char			node_wwn_s[WWN_SIZE], device_name[MAXNAMELEN];
1531*fcf3ce44SJohn Forte struct l_state_struct	l_state;
1532*fcf3ce44SJohn Forte struct dlist		*dl;
1533*fcf3ce44SJohn Forte 
1534*fcf3ce44SJohn Forte 
1535*fcf3ce44SJohn Forte 	if (hotplug_dev->dev_type == DTYPE_ESI) {
1536*fcf3ce44SJohn Forte 		/* entire photon is being removed */
1537*fcf3ce44SJohn Forte 		if ((err = l_offline_photon(hotplug_dev, wwn_list,
1538*fcf3ce44SJohn Forte 				force_flag, verbose_flag)) != 0) {
1539*fcf3ce44SJohn Forte 			return (err);
1540*fcf3ce44SJohn Forte 		}
1541*fcf3ce44SJohn Forte 		return (0);
1542*fcf3ce44SJohn Forte 	}
1543*fcf3ce44SJohn Forte 
1544*fcf3ce44SJohn Forte 	/* if device is an individual sena disk */
1545*fcf3ce44SJohn Forte 	dl = hotplug_dev->seslist;
1546*fcf3ce44SJohn Forte 	while (dl) {
1547*fcf3ce44SJohn Forte 		ses_path = dl->dev_path;
1548*fcf3ce44SJohn Forte 		if ((err = l_get_status(ses_path, &l_state,
1549*fcf3ce44SJohn Forte 				verbose_flag)) == 0)
1550*fcf3ce44SJohn Forte 			break;
1551*fcf3ce44SJohn Forte 		dl = dl->next;
1552*fcf3ce44SJohn Forte 	}
1553*fcf3ce44SJohn Forte 	if (dl == NULL) {
1554*fcf3ce44SJohn Forte 		return (L_GET_STATUS_FAILED);
1555*fcf3ce44SJohn Forte 	}
1556*fcf3ce44SJohn Forte 
1557*fcf3ce44SJohn Forte 	f_r = hotplug_dev->f_flag;
1558*fcf3ce44SJohn Forte 	slot = hotplug_dev->slot;
1559*fcf3ce44SJohn Forte 	(void) l_get_drive_name(device_name, slot, f_r, hotplug_dev->box_name);
1560*fcf3ce44SJohn Forte 
1561*fcf3ce44SJohn Forte 	/* check if disk has null wwn */
1562*fcf3ce44SJohn Forte 	if (f_r) {
1563*fcf3ce44SJohn Forte 		(void) strncpy(node_wwn_s,
1564*fcf3ce44SJohn Forte 		l_state.drv_front[slot].g_disk_state.node_wwn_s, WWN_SIZE);
1565*fcf3ce44SJohn Forte 	} else {
1566*fcf3ce44SJohn Forte 		(void) strncpy(node_wwn_s,
1567*fcf3ce44SJohn Forte 		l_state.drv_rear[slot].g_disk_state.node_wwn_s, WWN_SIZE);
1568*fcf3ce44SJohn Forte 	}
1569*fcf3ce44SJohn Forte 	for (i = 0; i < WWN_SIZE; i++) {
1570*fcf3ce44SJohn Forte 		if (node_wwn_s[i] != '0')
1571*fcf3ce44SJohn Forte 			break;
1572*fcf3ce44SJohn Forte 		found_null_wwn = 1;
1573*fcf3ce44SJohn Forte 	}
1574*fcf3ce44SJohn Forte 
1575*fcf3ce44SJohn Forte 	switch (todo) {
1576*fcf3ce44SJohn Forte 		case INSERT_DEVICE:
1577*fcf3ce44SJohn Forte 			if (hotplug_dev->f_flag) {
1578*fcf3ce44SJohn Forte 				code =
1579*fcf3ce44SJohn Forte 				l_state.drv_front[slot].ib_status.code;
1580*fcf3ce44SJohn Forte 			} else {
1581*fcf3ce44SJohn Forte 				code =
1582*fcf3ce44SJohn Forte 				l_state.drv_rear[slot].ib_status.code;
1583*fcf3ce44SJohn Forte 			}
1584*fcf3ce44SJohn Forte 			if (code & S_NOT_INSTALLED) {
1585*fcf3ce44SJohn Forte 				/*
1586*fcf3ce44SJohn Forte 				 * At this point we know that the drive is not
1587*fcf3ce44SJohn Forte 				 * there. Turn on the RQST INSERT bit to make
1588*fcf3ce44SJohn Forte 				 * the LED blink
1589*fcf3ce44SJohn Forte 				 */
1590*fcf3ce44SJohn Forte 				if ((err = l_encl_status_page_funcs
1591*fcf3ce44SJohn Forte 					(SET_RQST_INSRT, 0, todo,
1592*fcf3ce44SJohn Forte 					ses_path, &l_state, f_r, slot,
1593*fcf3ce44SJohn Forte 					verbose_flag)) != 0) {
1594*fcf3ce44SJohn Forte 					(void) print_errString(err,
1595*fcf3ce44SJohn Forte 								device_name);
1596*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1597*fcf3ce44SJohn Forte 						MSGSTR(5530,
1598*fcf3ce44SJohn Forte 						" %s: could not turn "
1599*fcf3ce44SJohn Forte 						"on LED\n"),
1600*fcf3ce44SJohn Forte 						device_name);
1601*fcf3ce44SJohn Forte 				}
1602*fcf3ce44SJohn Forte 			} else {
1603*fcf3ce44SJohn Forte 				/*
1604*fcf3ce44SJohn Forte 				 * Drive is there so start it.
1605*fcf3ce44SJohn Forte 				 */
1606*fcf3ce44SJohn Forte 				if ((err = l_encl_status_page_funcs
1607*fcf3ce44SJohn Forte 					(SET_DRV_ON, 0, todo,
1608*fcf3ce44SJohn Forte 					ses_path, &l_state, f_r, slot,
1609*fcf3ce44SJohn Forte 					verbose_flag)) != 0) {
1610*fcf3ce44SJohn Forte 					(void) print_errString(err,
1611*fcf3ce44SJohn Forte 								device_name);
1612*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1613*fcf3ce44SJohn Forte 						MSGSTR(5531,
1614*fcf3ce44SJohn Forte 						" could not enable"
1615*fcf3ce44SJohn Forte 						" %s\n"),
1616*fcf3ce44SJohn Forte 						device_name);
1617*fcf3ce44SJohn Forte 				}
1618*fcf3ce44SJohn Forte 			}
1619*fcf3ce44SJohn Forte 			break;
1620*fcf3ce44SJohn Forte 
1621*fcf3ce44SJohn Forte 		case REMOVE_DEVICE:
1622*fcf3ce44SJohn Forte 			/*
1623*fcf3ce44SJohn Forte 			 * if disk has null wwn, then
1624*fcf3ce44SJohn Forte 			 * there is no need to check the
1625*fcf3ce44SJohn Forte 			 * disk/loop status.
1626*fcf3ce44SJohn Forte 			 */
1627*fcf3ce44SJohn Forte 			if (found_null_wwn == 1) {
1628*fcf3ce44SJohn Forte 				if (getenv("_LUX_W_DEBUG") != NULL) {
1629*fcf3ce44SJohn Forte 					(void) fprintf(stdout,
1630*fcf3ce44SJohn Forte 						"Device %s has "
1631*fcf3ce44SJohn Forte 						"null WWN.\n",
1632*fcf3ce44SJohn Forte 						device_name);
1633*fcf3ce44SJohn Forte 				}
1634*fcf3ce44SJohn Forte 				goto rmv;
1635*fcf3ce44SJohn Forte 			}
1636*fcf3ce44SJohn Forte 			if (hotplug_dev->f_flag) {
1637*fcf3ce44SJohn Forte 				if (
1638*fcf3ce44SJohn Forte 			l_state.drv_front[slot].ib_status.code
1639*fcf3ce44SJohn Forte 					== S_NOT_INSTALLED) {
1640*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1641*fcf3ce44SJohn Forte 						MSGSTR(86,
1642*fcf3ce44SJohn Forte 					" Notice: %s may already"
1643*fcf3ce44SJohn Forte 					" be removed.\n"),
1644*fcf3ce44SJohn Forte 					device_name);
1645*fcf3ce44SJohn Forte 				return (0);
1646*fcf3ce44SJohn Forte 				}
1647*fcf3ce44SJohn Forte 			} else if (
1648*fcf3ce44SJohn Forte 			l_state.drv_rear[slot].ib_status.code
1649*fcf3ce44SJohn Forte 					== S_NOT_INSTALLED) {
1650*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1651*fcf3ce44SJohn Forte 					MSGSTR(86,
1652*fcf3ce44SJohn Forte 					" Notice: %s may already"
1653*fcf3ce44SJohn Forte 					" be removed.\n"),
1654*fcf3ce44SJohn Forte 					device_name);
1655*fcf3ce44SJohn Forte 				return (0);
1656*fcf3ce44SJohn Forte 			}
1657*fcf3ce44SJohn Forte 
1658*fcf3ce44SJohn Forte rmv:
1659*fcf3ce44SJohn Forte 		if (hotplug_dev->dlhead == NULL) {
1660*fcf3ce44SJohn Forte 			dev_path = NULL;
1661*fcf3ce44SJohn Forte 		} else {
1662*fcf3ce44SJohn Forte 			dev_path = hotplug_dev->dlhead->dev_path;
1663*fcf3ce44SJohn Forte 		}
1664*fcf3ce44SJohn Forte 
1665*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
1666*fcf3ce44SJohn Forte 				MSGSTR(157,
1667*fcf3ce44SJohn Forte 				"stopping:  %s...."), device_name);
1668*fcf3ce44SJohn Forte 		if ((err = g_dev_stop(dev_path, wwn_list, 0)) != 0) {
1669*fcf3ce44SJohn Forte 			return (err);
1670*fcf3ce44SJohn Forte 		}
1671*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1672*fcf3ce44SJohn Forte 
1673*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
1674*fcf3ce44SJohn Forte 				MSGSTR(158, "offlining: %s...."),
1675*fcf3ce44SJohn Forte 				device_name);
1676*fcf3ce44SJohn Forte 		if ((err = g_offline_drive(hotplug_dev->dlhead,
1677*fcf3ce44SJohn Forte 						force_flag)) != 0) {
1678*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1679*fcf3ce44SJohn Forte 					MSGSTR(160,
1680*fcf3ce44SJohn Forte 				"\nonlining: %s\n"), device_name);
1681*fcf3ce44SJohn Forte 			(void) g_online_drive(hotplug_dev->dlhead, force_flag);
1682*fcf3ce44SJohn Forte 
1683*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1684*fcf3ce44SJohn Forte 					MSGSTR(159, "starting:  %s...."),
1685*fcf3ce44SJohn Forte 					device_name);
1686*fcf3ce44SJohn Forte 			(void) g_dev_start(dev_path, 0);
1687*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1688*fcf3ce44SJohn Forte 			return (err);
1689*fcf3ce44SJohn Forte 		}
1690*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(156, "Done\n"));
1691*fcf3ce44SJohn Forte 
1692*fcf3ce44SJohn Forte 		/*
1693*fcf3ce44SJohn Forte 		 * Take the drive off the loop
1694*fcf3ce44SJohn Forte 		 * and blink the LED.
1695*fcf3ce44SJohn Forte 		 */
1696*fcf3ce44SJohn Forte 		if (hotplug_dev->dev_location == SENA) {
1697*fcf3ce44SJohn Forte 			if ((err = l_encl_status_page_funcs(SET_RQST_RMV, 0,
1698*fcf3ce44SJohn Forte 				todo, ses_path, &l_state, f_r,
1699*fcf3ce44SJohn Forte 				slot, verbose_flag)) != 0) {
1700*fcf3ce44SJohn Forte 				(void) print_errString(err, device_name);
1701*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1702*fcf3ce44SJohn Forte 					MSGSTR(5539,
1703*fcf3ce44SJohn Forte 					" %s: could not blink"
1704*fcf3ce44SJohn Forte 					" the yellow LED\n"),
1705*fcf3ce44SJohn Forte 					device_name);
1706*fcf3ce44SJohn Forte 			}
1707*fcf3ce44SJohn Forte 		}
1708*fcf3ce44SJohn Forte 		break;
1709*fcf3ce44SJohn Forte 	}
1710*fcf3ce44SJohn Forte 	return (0);
1711*fcf3ce44SJohn Forte }
1712*fcf3ce44SJohn Forte 
1713*fcf3ce44SJohn Forte 
1714*fcf3ce44SJohn Forte 
1715*fcf3ce44SJohn Forte /*
1716*fcf3ce44SJohn Forte  * Performs the post removal operations for
1717*fcf3ce44SJohn Forte  * a SENA enclosure or a SENA FC_AL disk.
1718*fcf3ce44SJohn Forte  *
1719*fcf3ce44SJohn Forte  * RETURNS:
1720*fcf3ce44SJohn Forte  *	0	 if OK
1721*fcf3ce44SJohn Forte  *	non-zero otherwise
1722*fcf3ce44SJohn Forte  */
1723*fcf3ce44SJohn Forte static	int
1724*fcf3ce44SJohn Forte h_post_hotplug_sena(Hotplug_Devlist *hotplug_dev,
1725*fcf3ce44SJohn Forte 			WWN_list *wwn_list, int todo,
1726*fcf3ce44SJohn Forte 			int verbose_flag, int force_flag, int enc_type)
1727*fcf3ce44SJohn Forte {
1728*fcf3ce44SJohn Forte char			*ses_path, *dev_path = NULL, device_name[MAXNAMELEN];
1729*fcf3ce44SJohn Forte int			tid, slot, f_r, al_pa, timeout = 0;
1730*fcf3ce44SJohn Forte uchar_t			port_wwn[WWN_SIZE], node_wwn[WWN_SIZE];
1731*fcf3ce44SJohn Forte char			code;
1732*fcf3ce44SJohn Forte int			wait_spinup_flag = 0, wait_map_flag = 0;
1733*fcf3ce44SJohn Forte int			wait_node_flag = 0, err = 0, nArg;
1734*fcf3ce44SJohn Forte gfc_map_t		map;
1735*fcf3ce44SJohn Forte WWN_list		*newWwn_list = NULL;
1736*fcf3ce44SJohn Forte struct dlist		*dl, *dl1;
1737*fcf3ce44SJohn Forte struct l_state_struct	l_state;
1738*fcf3ce44SJohn Forte 
1739*fcf3ce44SJohn Forte 
1740*fcf3ce44SJohn Forte 	dl = hotplug_dev->seslist;
1741*fcf3ce44SJohn Forte 	slot = hotplug_dev->slot;
1742*fcf3ce44SJohn Forte 	f_r = hotplug_dev->f_flag;
1743*fcf3ce44SJohn Forte 	tid = hotplug_dev->tid;
1744*fcf3ce44SJohn Forte 
1745*fcf3ce44SJohn Forte 	if (hotplug_dev->dev_type == DTYPE_ESI) {
1746*fcf3ce44SJohn Forte 		/*
1747*fcf3ce44SJohn Forte 		 * See if photon has really been removed. If not,
1748*fcf3ce44SJohn Forte 		 * try onlining the devices if applicable
1749*fcf3ce44SJohn Forte 		 */
1750*fcf3ce44SJohn Forte 		H_DPRINTF("  post_hotplug_sena: Seeing if enclosure "
1751*fcf3ce44SJohn Forte 			"has really been removed:\n"
1752*fcf3ce44SJohn Forte 			"  tid=0x%x, ses_path %s\n",
1753*fcf3ce44SJohn Forte 			tid, dl->dev_path);
1754*fcf3ce44SJohn Forte 
1755*fcf3ce44SJohn Forte 		while (dl) {
1756*fcf3ce44SJohn Forte 			ses_path = dl->dev_path;
1757*fcf3ce44SJohn Forte 			if ((err = g_get_dev_map(ses_path, &map, 0)) == 0) {
1758*fcf3ce44SJohn Forte 				if ((map.hba_addr.port_topology ==
1759*fcf3ce44SJohn Forte 					FC_TOP_PUBLIC_LOOP) ||
1760*fcf3ce44SJohn Forte 					(map.hba_addr.port_topology ==
1761*fcf3ce44SJohn Forte 					FC_TOP_FABRIC)) {
1762*fcf3ce44SJohn Forte 					/* public or fabric loop device */
1763*fcf3ce44SJohn Forte 					free((void *)map.dev_addr);
1764*fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(5540,
1765*fcf3ce44SJohn Forte 					"This operation is not "
1766*fcf3ce44SJohn Forte 					"supported in this topology.\n"));
1767*fcf3ce44SJohn Forte 					return (0);
1768*fcf3ce44SJohn Forte 				}
1769*fcf3ce44SJohn Forte 				if ((err = g_get_wwn(ses_path, port_wwn,
1770*fcf3ce44SJohn Forte 					node_wwn, &al_pa, verbose_flag)) == 0) {
1771*fcf3ce44SJohn Forte 					tid = g_sf_alpa_to_switch[al_pa];
1772*fcf3ce44SJohn Forte 					if (g_device_in_map(&map, tid)) {
1773*fcf3ce44SJohn Forte 						free((void *)map.dev_addr);
1774*fcf3ce44SJohn Forte 						break;
1775*fcf3ce44SJohn Forte 					}
1776*fcf3ce44SJohn Forte 				}
1777*fcf3ce44SJohn Forte 				FREE_DEV_ADDR(map.dev_addr);
1778*fcf3ce44SJohn Forte 			}
1779*fcf3ce44SJohn Forte 
1780*fcf3ce44SJohn Forte 			dl = dl->next;
1781*fcf3ce44SJohn Forte 		}
1782*fcf3ce44SJohn Forte 		FREE_DEV_ADDR(map.dev_addr);
1783*fcf3ce44SJohn Forte 		if (dl) {
1784*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5640,
1785*fcf3ce44SJohn Forte 				"Photon \"%s\" not removed."
1786*fcf3ce44SJohn Forte 				" Onlining Drives in enclosure.\n"),
1787*fcf3ce44SJohn Forte 				hotplug_dev->box_name);
1788*fcf3ce44SJohn Forte 			for (dl = hotplug_dev->dlhead; dl; ) {
1789*fcf3ce44SJohn Forte 				(void) g_online_drive(dl->multipath,
1790*fcf3ce44SJohn Forte 						force_flag);
1791*fcf3ce44SJohn Forte 				(void) g_free_multipath(dl->multipath);
1792*fcf3ce44SJohn Forte 				dl1 = dl;
1793*fcf3ce44SJohn Forte 				dl = dl->next;
1794*fcf3ce44SJohn Forte 				(void) free(dl1);
1795*fcf3ce44SJohn Forte 			}
1796*fcf3ce44SJohn Forte 			hotplug_dev->dlhead = NULL;
1797*fcf3ce44SJohn Forte 			return (0);
1798*fcf3ce44SJohn Forte 		}
1799*fcf3ce44SJohn Forte 		/*
1800*fcf3ce44SJohn Forte 		 * Remove logical nodes for this
1801*fcf3ce44SJohn Forte 		 * photon, this includes ses and
1802*fcf3ce44SJohn Forte 		 * /dev/dsk entries.
1803*fcf3ce44SJohn Forte 		 * In Solaris7, disks with -C option
1804*fcf3ce44SJohn Forte 		 * removes the /dev/dsk entries.
1805*fcf3ce44SJohn Forte 		 * The -C option is available
1806*fcf3ce44SJohn Forte 		 * only for Solaris7. From Solaris8
1807*fcf3ce44SJohn Forte 		 * or higher releases, the "disks"
1808*fcf3ce44SJohn Forte 		 * program will be replaced by the
1809*fcf3ce44SJohn Forte 		 * devfsadm program.
1810*fcf3ce44SJohn Forte 		 */
1811*fcf3ce44SJohn Forte 		/* pass "disks -C" as cmdStrg. */
1812*fcf3ce44SJohn Forte 		nArg = 2;
1813*fcf3ce44SJohn Forte 		if (h_execCmnd(cmdStrg[0], nArg) != 0) {
1814*fcf3ce44SJohn Forte 			for (dl = hotplug_dev->dlhead;
1815*fcf3ce44SJohn Forte 				dl != NULL; dl = dl->next) {
1816*fcf3ce44SJohn Forte 				if ((err = h_remove_nodes(dl->multipath))
1817*fcf3ce44SJohn Forte 								!= 0) {
1818*fcf3ce44SJohn Forte 					return (err);
1819*fcf3ce44SJohn Forte 				}
1820*fcf3ce44SJohn Forte 			}
1821*fcf3ce44SJohn Forte 		} else {
1822*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1823*fcf3ce44SJohn Forte 					MSGSTR(5541,
1824*fcf3ce44SJohn Forte 				"  Logical Nodes being removed"
1825*fcf3ce44SJohn Forte 				" under /dev/dsk/ and /dev/rdsk:\n"));
1826*fcf3ce44SJohn Forte 			for (dl = hotplug_dev->dlhead;
1827*fcf3ce44SJohn Forte 					dl != NULL; dl = dl->next) {
1828*fcf3ce44SJohn Forte 				(void) h_print_logical_nodes(dl->multipath);
1829*fcf3ce44SJohn Forte 			}
1830*fcf3ce44SJohn Forte 		}
1831*fcf3ce44SJohn Forte 
1832*fcf3ce44SJohn Forte 		for (dl = hotplug_dev->dlhead; dl != NULL; ) {
1833*fcf3ce44SJohn Forte 			(void) g_free_multipath(dl->multipath);
1834*fcf3ce44SJohn Forte 			dl1 = dl;
1835*fcf3ce44SJohn Forte 			dl = dl->next;
1836*fcf3ce44SJohn Forte 			(void) free(dl1);
1837*fcf3ce44SJohn Forte 		}
1838*fcf3ce44SJohn Forte 		hotplug_dev->dlhead = NULL;
1839*fcf3ce44SJohn Forte 		if ((err =  h_remove_ses_nodes(hotplug_dev->seslist)) != 0) {
1840*fcf3ce44SJohn Forte 			return (err);
1841*fcf3ce44SJohn Forte 		}
1842*fcf3ce44SJohn Forte 		return (0);
1843*fcf3ce44SJohn Forte 	}
1844*fcf3ce44SJohn Forte 
1845*fcf3ce44SJohn Forte 	/* post hotplug operations for a SENA disk. */
1846*fcf3ce44SJohn Forte 	if (enc_type == DAK_ENC_TYPE) {
1847*fcf3ce44SJohn Forte 		(void) sprintf(device_name, MSGSTR(5664,
1848*fcf3ce44SJohn Forte 		    "  Drive in Box Name \"%s\" slot %d"),
1849*fcf3ce44SJohn Forte 		    hotplug_dev->box_name,
1850*fcf3ce44SJohn Forte 		    f_r ? slot : slot + (MAX_DRIVES_DAK/2));
1851*fcf3ce44SJohn Forte 	} else {
1852*fcf3ce44SJohn Forte 		if (tid & 0x10) {
1853*fcf3ce44SJohn Forte 			(void) sprintf(device_name, MSGSTR(5542,
1854*fcf3ce44SJohn Forte 			    "  Drive in Box Name \"%s\" rear slot %d"),
1855*fcf3ce44SJohn Forte 			    hotplug_dev->box_name, slot);
1856*fcf3ce44SJohn Forte 		} else {
1857*fcf3ce44SJohn Forte 			(void) sprintf(device_name, MSGSTR(5543,
1858*fcf3ce44SJohn Forte 			    "  Drive in Box Name \"%s\" front slot %d"),
1859*fcf3ce44SJohn Forte 			    hotplug_dev->box_name, slot);
1860*fcf3ce44SJohn Forte 		}
1861*fcf3ce44SJohn Forte 	}
1862*fcf3ce44SJohn Forte 	(void) fprintf(stdout, "%s\n", device_name);
1863*fcf3ce44SJohn Forte 
1864*fcf3ce44SJohn Forte 	dl = hotplug_dev->seslist;
1865*fcf3ce44SJohn Forte 	while (dl) {
1866*fcf3ce44SJohn Forte 		ses_path = dl->dev_path;
1867*fcf3ce44SJohn Forte 		if ((err = l_get_status(ses_path, &l_state,
1868*fcf3ce44SJohn Forte 					verbose_flag)) == 0)
1869*fcf3ce44SJohn Forte 			break;
1870*fcf3ce44SJohn Forte 		dl = dl->next;
1871*fcf3ce44SJohn Forte 	}
1872*fcf3ce44SJohn Forte 	if (dl == NULL) {
1873*fcf3ce44SJohn Forte 		print_errString(err, ses_path);
1874*fcf3ce44SJohn Forte 		return (L_GET_STATUS_FAILED);
1875*fcf3ce44SJohn Forte 	}
1876*fcf3ce44SJohn Forte 
1877*fcf3ce44SJohn Forte 	code = 0;
1878*fcf3ce44SJohn Forte 	while (((err = l_encl_status_page_funcs(OVERALL_STATUS,
1879*fcf3ce44SJohn Forte 			&code, todo, ses_path, &l_state, f_r, slot,
1880*fcf3ce44SJohn Forte 			verbose_flag)) != 0) || (code != 0)) {
1881*fcf3ce44SJohn Forte 		if (err) {
1882*fcf3ce44SJohn Forte 			(void) print_errString(err, ses_path);
1883*fcf3ce44SJohn Forte 		} else if (todo == REMOVE_DEVICE) {
1884*fcf3ce44SJohn Forte 			if (code == S_OK) {
1885*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1886*fcf3ce44SJohn Forte 						MSGSTR(5544,
1887*fcf3ce44SJohn Forte 					"\n  Warning: Device has not been"
1888*fcf3ce44SJohn Forte 					" removed from the enclosure\n"
1889*fcf3ce44SJohn Forte 					"  and is still on the loop."));
1890*fcf3ce44SJohn Forte 				return (0);
1891*fcf3ce44SJohn Forte 			} else {
1892*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1893*fcf3ce44SJohn Forte 						MSGSTR(5545,
1894*fcf3ce44SJohn Forte 					"  Notice: Device has not been"
1895*fcf3ce44SJohn Forte 					" removed from the enclosure.\n"
1896*fcf3ce44SJohn Forte 					"  It has been removed from the"
1897*fcf3ce44SJohn Forte 					" loop and is ready to be\n"
1898*fcf3ce44SJohn Forte 					"  removed"
1899*fcf3ce44SJohn Forte 					" from the enclosure, and"
1900*fcf3ce44SJohn Forte 					" the LED is blinking.\n\n"));
1901*fcf3ce44SJohn Forte 			}
1902*fcf3ce44SJohn Forte 			goto loop2;
1903*fcf3ce44SJohn Forte 		} else if ((todo == INSERT_DEVICE) &&
1904*fcf3ce44SJohn Forte 				((code != S_NOT_AVAILABLE) ||
1905*fcf3ce44SJohn Forte 				(timeout >
1906*fcf3ce44SJohn Forte 					PHOTON_SPINUP_TIMEOUT) ||
1907*fcf3ce44SJohn Forte 				err)) {
1908*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1909*fcf3ce44SJohn Forte 						MSGSTR(5546,
1910*fcf3ce44SJohn Forte 						"\n Warning: Disk status is"
1911*fcf3ce44SJohn Forte 						" Not OK!\n\n"));
1912*fcf3ce44SJohn Forte 				return (0);
1913*fcf3ce44SJohn Forte 		}
1914*fcf3ce44SJohn Forte 		(void) sleep(PHOTON_SPINUP_DELAY);
1915*fcf3ce44SJohn Forte 		if (wait_spinup_flag++ == 0) {
1916*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5547,
1917*fcf3ce44SJohn Forte 				" Waiting for the disk to spin up:"));
1918*fcf3ce44SJohn Forte 		} else {
1919*fcf3ce44SJohn Forte 			(void) fprintf(stdout, ".");
1920*fcf3ce44SJohn Forte 		}
1921*fcf3ce44SJohn Forte 		timeout++;
1922*fcf3ce44SJohn Forte 	}
1923*fcf3ce44SJohn Forte 	if (wait_spinup_flag) {
1924*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
1925*fcf3ce44SJohn Forte 	}
1926*fcf3ce44SJohn Forte loop2:
1927*fcf3ce44SJohn Forte 	switch (todo) {
1928*fcf3ce44SJohn Forte 		case INSERT_DEVICE:
1929*fcf3ce44SJohn Forte 			/* check loop map that drive is present */
1930*fcf3ce44SJohn Forte 			for (;;) {
1931*fcf3ce44SJohn Forte 				dl = hotplug_dev->seslist;
1932*fcf3ce44SJohn Forte 				map.dev_addr = (gfc_port_dev_info_t *)NULL;
1933*fcf3ce44SJohn Forte 				while (dl) {
1934*fcf3ce44SJohn Forte 					ses_path = dl->dev_path;
1935*fcf3ce44SJohn Forte 					if ((err = g_get_dev_map(ses_path,
1936*fcf3ce44SJohn Forte 						&map, verbose_flag)) != 0) {
1937*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1938*fcf3ce44SJohn Forte 							MSGSTR(5548,
1939*fcf3ce44SJohn Forte 						" Error: Could not get"
1940*fcf3ce44SJohn Forte 						" map for %s.\n"),
1941*fcf3ce44SJohn Forte 							ses_path);
1942*fcf3ce44SJohn Forte 						return (err);
1943*fcf3ce44SJohn Forte 					}
1944*fcf3ce44SJohn Forte 				if (g_device_in_map(&map, tid)) {
1945*fcf3ce44SJohn Forte 						goto loop3;
1946*fcf3ce44SJohn Forte 					}
1947*fcf3ce44SJohn Forte 					FREE_DEV_ADDR(map.dev_addr);
1948*fcf3ce44SJohn Forte 					dl = dl->next;
1949*fcf3ce44SJohn Forte 				}
1950*fcf3ce44SJohn Forte 				if (timeout > PHOTON_SPINUP_TIMEOUT) {
1951*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1952*fcf3ce44SJohn Forte 						MSGSTR(5549,
1953*fcf3ce44SJohn Forte 						" Warning: Device not in"
1954*fcf3ce44SJohn Forte 						" loop map.\n"));
1955*fcf3ce44SJohn Forte 					FREE_DEV_ADDR(map.dev_addr);
1956*fcf3ce44SJohn Forte 					return (0);
1957*fcf3ce44SJohn Forte 				}
1958*fcf3ce44SJohn Forte 				if (wait_map_flag++ == 0) {
1959*fcf3ce44SJohn Forte 					(void) fprintf(stdout,
1960*fcf3ce44SJohn Forte 						MSGSTR(5550,
1961*fcf3ce44SJohn Forte 					"  Waiting for the device "
1962*fcf3ce44SJohn Forte 					"to appear in the loop map:"));
1963*fcf3ce44SJohn Forte 				} else {
1964*fcf3ce44SJohn Forte 					(void) fprintf(stdout, ".");
1965*fcf3ce44SJohn Forte 				}
1966*fcf3ce44SJohn Forte 				timeout++;
1967*fcf3ce44SJohn Forte 				(void) sleep(PHOTON_SPINUP_DELAY);
1968*fcf3ce44SJohn Forte 			}
1969*fcf3ce44SJohn Forte loop3:
1970*fcf3ce44SJohn Forte 			if (wait_map_flag) {
1971*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "\n");
1972*fcf3ce44SJohn Forte 			}
1973*fcf3ce44SJohn Forte 
1974*fcf3ce44SJohn Forte 			/*
1975*fcf3ce44SJohn Forte 			 * Run drvconfig and disks to create
1976*fcf3ce44SJohn Forte 			 * logical nodes
1977*fcf3ce44SJohn Forte 			 */
1978*fcf3ce44SJohn Forte 			for (;;) {
1979*fcf3ce44SJohn Forte 				/* pass "disks" as cmdStrg */
1980*fcf3ce44SJohn Forte 				nArg = 3;
1981*fcf3ce44SJohn Forte 				if (h_execCmnd(cmdStrg[2], nArg) != 0) {
1982*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1983*fcf3ce44SJohn Forte 							MSGSTR(5551,
1984*fcf3ce44SJohn Forte 							" Could not "
1985*fcf3ce44SJohn Forte 						"run drvconfig.\n"));
1986*fcf3ce44SJohn Forte 					FREE_DEV_ADDR(map.dev_addr);
1987*fcf3ce44SJohn Forte 					return (L_DRVCONFIG_ERROR);
1988*fcf3ce44SJohn Forte 				}
1989*fcf3ce44SJohn Forte 
1990*fcf3ce44SJohn Forte 				if (l_device_present(ses_path, tid, &map,
1991*fcf3ce44SJohn Forte 					verbose_flag, &dev_path) == 1)
1992*fcf3ce44SJohn Forte 					break;
1993*fcf3ce44SJohn Forte 				if (timeout > PHOTON_SPINUP_TIMEOUT) {
1994*fcf3ce44SJohn Forte 					(void) fprintf(stderr,
1995*fcf3ce44SJohn Forte 							MSGSTR(5552,
1996*fcf3ce44SJohn Forte 						" Warning: Could not find "
1997*fcf3ce44SJohn Forte 						"any node for inserted "
1998*fcf3ce44SJohn Forte 						"device\n"));
1999*fcf3ce44SJohn Forte 					FREE_DEV_ADDR(map.dev_addr);
2000*fcf3ce44SJohn Forte 					return (0);
2001*fcf3ce44SJohn Forte 				}
2002*fcf3ce44SJohn Forte 				if (wait_node_flag++ == 0) {
2003*fcf3ce44SJohn Forte 					(void) fprintf(stdout,
2004*fcf3ce44SJohn Forte 						MSGSTR(5553,
2005*fcf3ce44SJohn Forte 					"  Waiting for the logical "
2006*fcf3ce44SJohn Forte 					"node to be created:"));
2007*fcf3ce44SJohn Forte 				} else {
2008*fcf3ce44SJohn Forte 					(void) fprintf(stdout, ".");
2009*fcf3ce44SJohn Forte 				}
2010*fcf3ce44SJohn Forte 				timeout++;
2011*fcf3ce44SJohn Forte 				(void) sleep(PHOTON_SPINUP_DELAY);
2012*fcf3ce44SJohn Forte 			}
2013*fcf3ce44SJohn Forte 			FREE_DEV_ADDR(map.dev_addr);
2014*fcf3ce44SJohn Forte 			if (wait_node_flag) {
2015*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "\n");
2016*fcf3ce44SJohn Forte 			}
2017*fcf3ce44SJohn Forte 			/*
2018*fcf3ce44SJohn Forte 			 * In Solaris7, disks with -C
2019*fcf3ce44SJohn Forte 			 * option creates the new links
2020*fcf3ce44SJohn Forte 			 * and removes any stale links.
2021*fcf3ce44SJohn Forte 			 * In pre-Solaris7 releases, just
2022*fcf3ce44SJohn Forte 			 * disks should do it all.
2023*fcf3ce44SJohn Forte 			 */
2024*fcf3ce44SJohn Forte 			/* pass "disks -C" as cmdStrg */
2025*fcf3ce44SJohn Forte 			nArg = 2;
2026*fcf3ce44SJohn Forte 			if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2027*fcf3ce44SJohn Forte 				return (L_DISKS_ERROR);
2028*fcf3ce44SJohn Forte 			}
2029*fcf3ce44SJohn Forte 			/*
2030*fcf3ce44SJohn Forte 			 * Get a new wwn list here in order to
2031*fcf3ce44SJohn Forte 			 * get the multiple paths to a newly added
2032*fcf3ce44SJohn Forte 			 * device.
2033*fcf3ce44SJohn Forte 			 */
2034*fcf3ce44SJohn Forte 			if ((err = g_get_wwn_list(&newWwn_list,
2035*fcf3ce44SJohn Forte 						verbose_flag)) != 0) {
2036*fcf3ce44SJohn Forte 				return (err);
2037*fcf3ce44SJohn Forte 			}
2038*fcf3ce44SJohn Forte 			if ((err = g_get_multipath(dev_path, &dl,
2039*fcf3ce44SJohn Forte 					newWwn_list, 0)) != 0) {
2040*fcf3ce44SJohn Forte 				return (err);
2041*fcf3ce44SJohn Forte 			}
2042*fcf3ce44SJohn Forte 			if ((err = h_display_logical_nodes(dl)) != 0) {
2043*fcf3ce44SJohn Forte 				return (err);
2044*fcf3ce44SJohn Forte 			}
2045*fcf3ce44SJohn Forte 			break;
2046*fcf3ce44SJohn Forte 
2047*fcf3ce44SJohn Forte 		case REMOVE_DEVICE:
2048*fcf3ce44SJohn Forte /*
2049*fcf3ce44SJohn Forte  * TBD
2050*fcf3ce44SJohn Forte  * Need to check all loops.
2051*fcf3ce44SJohn Forte  */
2052*fcf3ce44SJohn Forte 			/* check whether device is still in loop map */
2053*fcf3ce44SJohn Forte 			if ((err = g_get_dev_map(ses_path, &map,
2054*fcf3ce44SJohn Forte 					verbose_flag)) != 0) {
2055*fcf3ce44SJohn Forte 				return (err);
2056*fcf3ce44SJohn Forte 			}
2057*fcf3ce44SJohn Forte 
2058*fcf3ce44SJohn Forte 			if ((map.hba_addr.port_topology ==
2059*fcf3ce44SJohn Forte 				FC_TOP_PUBLIC_LOOP) ||
2060*fcf3ce44SJohn Forte 				(map.hba_addr.port_topology ==
2061*fcf3ce44SJohn Forte 				FC_TOP_FABRIC)) {
2062*fcf3ce44SJohn Forte 				/* public or fabric loop device */
2063*fcf3ce44SJohn Forte 				free((void *)map.dev_addr);
2064*fcf3ce44SJohn Forte 				(void) fprintf(stderr, MSGSTR(5540,
2065*fcf3ce44SJohn Forte 				"This operation is not "
2066*fcf3ce44SJohn Forte 				"supported in this topology.\n"));
2067*fcf3ce44SJohn Forte 				/*
2068*fcf3ce44SJohn Forte 				 * calling routine expects a 0 return code
2069*fcf3ce44SJohn Forte 				 * or a pre-defined luxadm error code.
2070*fcf3ce44SJohn Forte 				 * Here we do not have a pre-defined error
2071*fcf3ce44SJohn Forte 				 * code, a 0 is returned.
2072*fcf3ce44SJohn Forte 				 */
2073*fcf3ce44SJohn Forte 				return (0);
2074*fcf3ce44SJohn Forte 			}
2075*fcf3ce44SJohn Forte 
2076*fcf3ce44SJohn Forte 			if (g_device_in_map(&map, tid)) {
2077*fcf3ce44SJohn Forte 				(void) fprintf(stderr, MSGSTR(5554,
2078*fcf3ce44SJohn Forte 				" Warning: Device still in the loop map.\n"));
2079*fcf3ce44SJohn Forte 				FREE_DEV_ADDR(map.dev_addr);
2080*fcf3ce44SJohn Forte 				return (0);
2081*fcf3ce44SJohn Forte 			}
2082*fcf3ce44SJohn Forte 			FREE_DEV_ADDR(map.dev_addr);
2083*fcf3ce44SJohn Forte 			/*
2084*fcf3ce44SJohn Forte 			 * In Solaris7, "disks -C" program
2085*fcf3ce44SJohn Forte 			 * removes the /dev/{r}dsk entries.
2086*fcf3ce44SJohn Forte 			 * The -C option is available only
2087*fcf3ce44SJohn Forte 			 * for Solaris7. From Solaris8 or
2088*fcf3ce44SJohn Forte 			 * higher releases, the "disks" program
2089*fcf3ce44SJohn Forte 			 * will be replaced by devfsadm.
2090*fcf3ce44SJohn Forte 			 */
2091*fcf3ce44SJohn Forte 			/* pass "disks -C" as cmdStrg */
2092*fcf3ce44SJohn Forte 			nArg = 2;
2093*fcf3ce44SJohn Forte 			if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2094*fcf3ce44SJohn Forte 				return (L_DISKS_ERROR);
2095*fcf3ce44SJohn Forte 			}
2096*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
2097*fcf3ce44SJohn Forte 					MSGSTR(5555,
2098*fcf3ce44SJohn Forte 			"  Logical Nodes being removed"
2099*fcf3ce44SJohn Forte 			" under /dev/dsk/ and /dev/rdsk:\n"));
2100*fcf3ce44SJohn Forte 			(void) h_print_logical_nodes(
2101*fcf3ce44SJohn Forte 					hotplug_dev->dlhead);
2102*fcf3ce44SJohn Forte 			break;
2103*fcf3ce44SJohn Forte 	}
2104*fcf3ce44SJohn Forte 	return (0);
2105*fcf3ce44SJohn Forte }
2106*fcf3ce44SJohn Forte 
2107*fcf3ce44SJohn Forte 
2108*fcf3ce44SJohn Forte 
2109*fcf3ce44SJohn Forte 
2110*fcf3ce44SJohn Forte /*
2111*fcf3ce44SJohn Forte  * Creates new ses entries under /dev/es
2112*fcf3ce44SJohn Forte  * directory for the newly added
2113*fcf3ce44SJohn Forte  * enclosures.
2114*fcf3ce44SJohn Forte  *
2115*fcf3ce44SJohn Forte  * RETURNS:
2116*fcf3ce44SJohn Forte  *	0	 if OK
2117*fcf3ce44SJohn Forte  *	non-zero otherwise
2118*fcf3ce44SJohn Forte  */
2119*fcf3ce44SJohn Forte static	int
2120*fcf3ce44SJohn Forte h_post_insert_encl(timestruc_t ses_lastmtim)
2121*fcf3ce44SJohn Forte {
2122*fcf3ce44SJohn Forte struct stat		ses_stat;
2123*fcf3ce44SJohn Forte char			lname[MAXPATHLEN];
2124*fcf3ce44SJohn Forte int			err, found_newlink = 0;
2125*fcf3ce44SJohn Forte DIR			*dir;
2126*fcf3ce44SJohn Forte struct dirent		*dirent;
2127*fcf3ce44SJohn Forte Box_list		*bl1, *box_list = NULL;
2128*fcf3ce44SJohn Forte 
2129*fcf3ce44SJohn Forte 
2130*fcf3ce44SJohn Forte 	if ((dir = opendir(SES_DIR)) == NULL) {
2131*fcf3ce44SJohn Forte 		return (L_OPEN_ES_DIR_FAILED);
2132*fcf3ce44SJohn Forte 	}
2133*fcf3ce44SJohn Forte 	if ((err = l_get_box_list(&box_list, 0)) != 0) {
2134*fcf3ce44SJohn Forte 		closedir(dir);
2135*fcf3ce44SJohn Forte 		return (err);
2136*fcf3ce44SJohn Forte 	}
2137*fcf3ce44SJohn Forte 
2138*fcf3ce44SJohn Forte 	/*
2139*fcf3ce44SJohn Forte 	 * The mod time of /dev/es was newer than the mod time prior to
2140*fcf3ce44SJohn Forte 	 * insert so dir entry is checked at this time.
2141*fcf3ce44SJohn Forte 	 */
2142*fcf3ce44SJohn Forte 	while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2143*fcf3ce44SJohn Forte 		if (strcmp(dirent->d_name, ".") == 0 ||
2144*fcf3ce44SJohn Forte 			strcmp(dirent->d_name, "..") == 0)
2145*fcf3ce44SJohn Forte 			continue;
2146*fcf3ce44SJohn Forte 
2147*fcf3ce44SJohn Forte 		(void) sprintf(lname, SES_DIR"/%s", dirent->d_name);
2148*fcf3ce44SJohn Forte 		if (lstat(lname, &ses_stat) < 0) {
2149*fcf3ce44SJohn Forte 			(void) print_errString(L_LSTAT_ES_DIR_ERROR,
2150*fcf3ce44SJohn Forte 							lname);
2151*fcf3ce44SJohn Forte 			continue;
2152*fcf3ce44SJohn Forte 		}
2153*fcf3ce44SJohn Forte 
2154*fcf3ce44SJohn Forte 		for (bl1 = box_list; bl1; bl1 = bl1->box_next) {
2155*fcf3ce44SJohn Forte 			if (strstr(lname, bl1->b_physical_path))
2156*fcf3ce44SJohn Forte 				break;
2157*fcf3ce44SJohn Forte 		}
2158*fcf3ce44SJohn Forte 
2159*fcf3ce44SJohn Forte 		if (box_list && bl1)
2160*fcf3ce44SJohn Forte 			continue;
2161*fcf3ce44SJohn Forte 
2162*fcf3ce44SJohn Forte 		if (NEWER(ses_stat.st_ctim, ses_lastmtim)) {
2163*fcf3ce44SJohn Forte 			/* New enclosure was detected. */
2164*fcf3ce44SJohn Forte 			found_newlink++;
2165*fcf3ce44SJohn Forte 			if (found_newlink == 1) {
2166*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5556,
2167*fcf3ce44SJohn Forte 				"  New Logical Nodes under /dev/es:\n"));
2168*fcf3ce44SJohn Forte 			}
2169*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\t%s\n",
2170*fcf3ce44SJohn Forte 				dirent->d_name);
2171*fcf3ce44SJohn Forte 		}
2172*fcf3ce44SJohn Forte 	}
2173*fcf3ce44SJohn Forte 	if (!found_newlink) {
2174*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5662,
2175*fcf3ce44SJohn Forte 			" No new enclosure(s) were added!!\n\n"));
2176*fcf3ce44SJohn Forte 	}
2177*fcf3ce44SJohn Forte 
2178*fcf3ce44SJohn Forte 	closedir(dir);
2179*fcf3ce44SJohn Forte 
2180*fcf3ce44SJohn Forte 	(void) l_free_box_list(&box_list);
2181*fcf3ce44SJohn Forte 	return (0);
2182*fcf3ce44SJohn Forte }
2183*fcf3ce44SJohn Forte 
2184*fcf3ce44SJohn Forte 
2185*fcf3ce44SJohn Forte 
2186*fcf3ce44SJohn Forte /*
2187*fcf3ce44SJohn Forte  * performs the post removal of individual
2188*fcf3ce44SJohn Forte  * FC_AL disks.
2189*fcf3ce44SJohn Forte  *
2190*fcf3ce44SJohn Forte  * RETURNS:
2191*fcf3ce44SJohn Forte  *	0	 if OK
2192*fcf3ce44SJohn Forte  *	non-zero otherwise
2193*fcf3ce44SJohn Forte  */
2194*fcf3ce44SJohn Forte static	int
2195*fcf3ce44SJohn Forte h_post_remove_dev(Hotplug_Devlist *hotplug_disk,
2196*fcf3ce44SJohn Forte 				int todo, int verbose_flag)
2197*fcf3ce44SJohn Forte {
2198*fcf3ce44SJohn Forte char   		device_name[MAXNAMELEN], *dev_path = NULL;
2199*fcf3ce44SJohn Forte int		tid, err;
2200*fcf3ce44SJohn Forte gfc_map_t	map;
2201*fcf3ce44SJohn Forte int		nArg;
2202*fcf3ce44SJohn Forte 
2203*fcf3ce44SJohn Forte 
2204*fcf3ce44SJohn Forte 	tid = hotplug_disk->tid;
2205*fcf3ce44SJohn Forte 	(void) sprintf(device_name,
2206*fcf3ce44SJohn Forte 			MSGSTR(5557,
2207*fcf3ce44SJohn Forte 			"\n  Device: %s"),
2208*fcf3ce44SJohn Forte 			(hotplug_disk->dlhead)->logical_path);
2209*fcf3ce44SJohn Forte 
2210*fcf3ce44SJohn Forte 	(void) fprintf(stdout, "%s\n", device_name);
2211*fcf3ce44SJohn Forte 
2212*fcf3ce44SJohn Forte 	dev_path = (hotplug_disk->dlhead)->dev_path;
2213*fcf3ce44SJohn Forte 
2214*fcf3ce44SJohn Forte 	/*
2215*fcf3ce44SJohn Forte 	 * On qlc, after a forcelip on a FC combo box, it sometimes takes 17
2216*fcf3ce44SJohn Forte 	 * seconds for the loop to come back online.  During this 17 seconds,
2217*fcf3ce44SJohn Forte 	 * g_get_dev_map * will return L_NO_DEVICES_FOUND.  This delay
2218*fcf3ce44SJohn Forte 	 * has been added to assure that the L_NO_DEVICES_FOUND returned from
2219*fcf3ce44SJohn Forte 	 * g_get_dev_map is not the result of the 17 second delay on FC combo.
2220*fcf3ce44SJohn Forte 	 * This only affects qlc.
2221*fcf3ce44SJohn Forte 	 */
2222*fcf3ce44SJohn Forte 	if ((err = g_get_dev_map(dev_path, &map, verbose_flag)) != 0) {
2223*fcf3ce44SJohn Forte 		if ((err == L_NO_DEVICES_FOUND) &&
2224*fcf3ce44SJohn Forte 		    (strstr(dev_path, "SUNW,qlc@") != NULL)) {
2225*fcf3ce44SJohn Forte 			sleep(QLC_LIP_DELAY);
2226*fcf3ce44SJohn Forte 			if ((err = g_get_dev_map(dev_path, &map, verbose_flag))
2227*fcf3ce44SJohn Forte 			    != 0) {
2228*fcf3ce44SJohn Forte 				if (err != L_NO_DEVICES_FOUND)
2229*fcf3ce44SJohn Forte 					return (err);
2230*fcf3ce44SJohn Forte 			}
2231*fcf3ce44SJohn Forte 		} else if (err != L_NO_DEVICES_FOUND)
2232*fcf3ce44SJohn Forte 			return (err);
2233*fcf3ce44SJohn Forte 	}
2234*fcf3ce44SJohn Forte 
2235*fcf3ce44SJohn Forte 	/*
2236*fcf3ce44SJohn Forte 	 * if g_get_dev_map returns L_NO_DEVICES_FOUND, then there are not
2237*fcf3ce44SJohn Forte 	 * devices attached to the HBA and there is no sense in calling
2238*fcf3ce44SJohn Forte 	 * g_device_in_map().
2239*fcf3ce44SJohn Forte 	 */
2240*fcf3ce44SJohn Forte 	if (err != L_NO_DEVICES_FOUND) {
2241*fcf3ce44SJohn Forte 		if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
2242*fcf3ce44SJohn Forte 			(map.hba_addr.port_topology == FC_TOP_FABRIC)) {
2243*fcf3ce44SJohn Forte 			/* public or fabric loop device */
2244*fcf3ce44SJohn Forte 			free((void *)map.dev_addr);
2245*fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(5540,
2246*fcf3ce44SJohn Forte 				"This operation is not "
2247*fcf3ce44SJohn Forte 				"supported in this topology.\n"));
2248*fcf3ce44SJohn Forte 			return (0);
2249*fcf3ce44SJohn Forte 		}
2250*fcf3ce44SJohn Forte 
2251*fcf3ce44SJohn Forte 		if (g_device_in_map(&map, tid) != 0) {
2252*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2253*fcf3ce44SJohn Forte 				MSGSTR(5558,
2254*fcf3ce44SJohn Forte 				" Warning: Device has"
2255*fcf3ce44SJohn Forte 				" not been removed from\n"
2256*fcf3ce44SJohn Forte 				"  the slot and is still"
2257*fcf3ce44SJohn Forte 				" in the loop map.\n\n"));
2258*fcf3ce44SJohn Forte 			free((void *)map.dev_addr);
2259*fcf3ce44SJohn Forte 			return (0);
2260*fcf3ce44SJohn Forte 		}
2261*fcf3ce44SJohn Forte 		free((void *)map.dev_addr);
2262*fcf3ce44SJohn Forte 	}
2263*fcf3ce44SJohn Forte 	/*
2264*fcf3ce44SJohn Forte 	 * In Solaris7, "disks -C" program
2265*fcf3ce44SJohn Forte 	 * removes the /dev/{r}dsk entries.
2266*fcf3ce44SJohn Forte 	 * The -C option is available only
2267*fcf3ce44SJohn Forte 	 * for Solaris7. From Solaris8 or
2268*fcf3ce44SJohn Forte 	 * higher releases, the "disks" program
2269*fcf3ce44SJohn Forte 	 * will be replaced by devfsadm.
2270*fcf3ce44SJohn Forte 	 */
2271*fcf3ce44SJohn Forte 	/* pass "disks -C" as cmdStrg. */
2272*fcf3ce44SJohn Forte 	nArg = 2;
2273*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2274*fcf3ce44SJohn Forte 		return (L_DISKS_ERROR);
2275*fcf3ce44SJohn Forte 	}
2276*fcf3ce44SJohn Forte 	/* pass "tapes -C as cmdStrg. */
2277*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[5], nArg) != 0) {
2278*fcf3ce44SJohn Forte 		return (L_TAPES_ERROR);
2279*fcf3ce44SJohn Forte 	}
2280*fcf3ce44SJohn Forte 	(void) h_print_logical_nodes(hotplug_disk->dlhead);
2281*fcf3ce44SJohn Forte 
2282*fcf3ce44SJohn Forte 	return (0);
2283*fcf3ce44SJohn Forte }
2284*fcf3ce44SJohn Forte 
2285*fcf3ce44SJohn Forte 
2286*fcf3ce44SJohn Forte 
2287*fcf3ce44SJohn Forte /*
2288*fcf3ce44SJohn Forte  * Gets the last modification time for
2289*fcf3ce44SJohn Forte  * /dev/es/ and /dev/rdsk directories
2290*fcf3ce44SJohn Forte  * and passes these values to the caller.
2291*fcf3ce44SJohn Forte  *
2292*fcf3ce44SJohn Forte  * RETURNS:
2293*fcf3ce44SJohn Forte  *	0	 if OK
2294*fcf3ce44SJohn Forte  *	non-zero in case of error
2295*fcf3ce44SJohn Forte  */
2296*fcf3ce44SJohn Forte static	int
2297*fcf3ce44SJohn Forte h_pre_insert_encl_dev(timestruc_t *ses_time, timestruc_t *dsk_time,
2298*fcf3ce44SJohn Forte 						timestruc_t *rmt_time)
2299*fcf3ce44SJohn Forte {
2300*fcf3ce44SJohn Forte struct stat	ses_stat, dsk_stat, rmt_stat;
2301*fcf3ce44SJohn Forte 
2302*fcf3ce44SJohn Forte 	if (stat(SES_DIR, &ses_stat) < 0) {
2303*fcf3ce44SJohn Forte 		/*
2304*fcf3ce44SJohn Forte 		 * Even if there exists no /dev/es don't fail it.
2305*fcf3ce44SJohn Forte 		 * The host doesn't have to have any enclosure device
2306*fcf3ce44SJohn Forte 		 * configured.
2307*fcf3ce44SJohn Forte 		 */
2308*fcf3ce44SJohn Forte 		if (errno == ENOENT) {
2309*fcf3ce44SJohn Forte 			ses_time = (timestruc_t *)NULL;
2310*fcf3ce44SJohn Forte 		} else {
2311*fcf3ce44SJohn Forte 			return (L_LSTAT_ES_DIR_ERROR);
2312*fcf3ce44SJohn Forte 		}
2313*fcf3ce44SJohn Forte 	} else {
2314*fcf3ce44SJohn Forte 		*ses_time = ses_stat.st_mtim;
2315*fcf3ce44SJohn Forte 	}
2316*fcf3ce44SJohn Forte 
2317*fcf3ce44SJohn Forte 	if (stat(DEV_DSK_DIR, &dsk_stat) < 0) {
2318*fcf3ce44SJohn Forte 		return (L_STAT_DEV_DIR_ERROR);
2319*fcf3ce44SJohn Forte 	} else {
2320*fcf3ce44SJohn Forte 		*dsk_time = dsk_stat.st_mtim;
2321*fcf3ce44SJohn Forte 	}
2322*fcf3ce44SJohn Forte 	if (stat(DEV_TAPE_DIR, &rmt_stat) < 0) {
2323*fcf3ce44SJohn Forte 		/*
2324*fcf3ce44SJohn Forte 		 * Even if there exists no /dev/rmt don't fail it.
2325*fcf3ce44SJohn Forte 		 * The host doesn't have to have any tape device
2326*fcf3ce44SJohn Forte 		 * configured.
2327*fcf3ce44SJohn Forte 		 */
2328*fcf3ce44SJohn Forte 		if (errno == ENOENT) {
2329*fcf3ce44SJohn Forte 			rmt_time = (timestruc_t *)NULL;
2330*fcf3ce44SJohn Forte 		} else {
2331*fcf3ce44SJohn Forte 			return (L_STAT_RMT_DIR_ERROR);
2332*fcf3ce44SJohn Forte 		}
2333*fcf3ce44SJohn Forte 	} else {
2334*fcf3ce44SJohn Forte 		*rmt_time = rmt_stat.st_mtim;
2335*fcf3ce44SJohn Forte 	}
2336*fcf3ce44SJohn Forte 
2337*fcf3ce44SJohn Forte 	return (0);
2338*fcf3ce44SJohn Forte }
2339*fcf3ce44SJohn Forte 
2340*fcf3ce44SJohn Forte 
2341*fcf3ce44SJohn Forte 
2342*fcf3ce44SJohn Forte /*
2343*fcf3ce44SJohn Forte  * Waits for loop intialization to complete
2344*fcf3ce44SJohn Forte  * and runs drvconfig, disks and devlinks to create device nodes
2345*fcf3ce44SJohn Forte  * for devices that are being added and prints the newly created
2346*fcf3ce44SJohn Forte  * /dev/rdsk entries.
2347*fcf3ce44SJohn Forte  *
2348*fcf3ce44SJohn Forte  * RETURNS:
2349*fcf3ce44SJohn Forte  *	0	 if OK
2350*fcf3ce44SJohn Forte  *	non-zero in case of error
2351*fcf3ce44SJohn Forte  */
2352*fcf3ce44SJohn Forte 
2353*fcf3ce44SJohn Forte static	int
2354*fcf3ce44SJohn Forte h_post_insert_dev(timestruc_t dsk_lastmtim, timestruc_t rmt_lastmtim)
2355*fcf3ce44SJohn Forte {
2356*fcf3ce44SJohn Forte int		found_newlink = 0, nArg;
2357*fcf3ce44SJohn Forte 
2358*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
2359*fcf3ce44SJohn Forte 		MSGSTR(5560,
2360*fcf3ce44SJohn Forte 		"\nWaiting for Loop Initialization to complete...\n"));
2361*fcf3ce44SJohn Forte 
2362*fcf3ce44SJohn Forte 	/*
2363*fcf3ce44SJohn Forte 	 * We sleep here to let the system create nodes. Not sleeping
2364*fcf3ce44SJohn Forte 	 * could cause the drvconfig below to run too soon.
2365*fcf3ce44SJohn Forte 	 */
2366*fcf3ce44SJohn Forte 
2367*fcf3ce44SJohn Forte 	(void) sleep(NODE_CREATION_TIME);
2368*fcf3ce44SJohn Forte 
2369*fcf3ce44SJohn Forte 	/*
2370*fcf3ce44SJohn Forte 	 * Run drvconfig and disks to create
2371*fcf3ce44SJohn Forte 	 * logical nodes
2372*fcf3ce44SJohn Forte 	 */
2373*fcf3ce44SJohn Forte 	/* pass "drvconfig" as cmdStrg */
2374*fcf3ce44SJohn Forte 	nArg = 1;
2375*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[3], nArg) != 0) {
2376*fcf3ce44SJohn Forte 		return (L_DRVCONFIG_ERROR);
2377*fcf3ce44SJohn Forte 	}
2378*fcf3ce44SJohn Forte 
2379*fcf3ce44SJohn Forte 	/*
2380*fcf3ce44SJohn Forte 	 * In 2.7, disks with the -C
2381*fcf3ce44SJohn Forte 	 * option should be used to
2382*fcf3ce44SJohn Forte 	 * create new links and remove
2383*fcf3ce44SJohn Forte 	 * any stale links.
2384*fcf3ce44SJohn Forte 	 * In pre-2.7 releases, just
2385*fcf3ce44SJohn Forte 	 * disks should do it all.
2386*fcf3ce44SJohn Forte 	 */
2387*fcf3ce44SJohn Forte 
2388*fcf3ce44SJohn Forte 	/* pass "disks -C" as cmdStrg */
2389*fcf3ce44SJohn Forte 	nArg = 2;
2390*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2391*fcf3ce44SJohn Forte 		return (L_DISKS_ERROR);
2392*fcf3ce44SJohn Forte 	}
2393*fcf3ce44SJohn Forte 	/* pass "tapes -C as cmdStrg */
2394*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[5], nArg) != 0) {
2395*fcf3ce44SJohn Forte 		return (L_TAPES_ERROR);
2396*fcf3ce44SJohn Forte 	}
2397*fcf3ce44SJohn Forte 
2398*fcf3ce44SJohn Forte 	/* pass "devlinks" as cmdStrg */
2399*fcf3ce44SJohn Forte 	nArg = 1;
2400*fcf3ce44SJohn Forte 	if (h_execCmnd(cmdStrg[4], nArg) != 0) {
2401*fcf3ce44SJohn Forte 		return (L_DEVLINKS_ERROR);
2402*fcf3ce44SJohn Forte 	}
2403*fcf3ce44SJohn Forte 
2404*fcf3ce44SJohn Forte 	/* check /dev/dsk  and /dev/rmt for new links */
2405*fcf3ce44SJohn Forte 	found_newlink = h_find_new_device_link(DEV_DSK_DIR, dsk_lastmtim) +
2406*fcf3ce44SJohn Forte 			h_find_new_device_link(DEV_TAPE_DIR, rmt_lastmtim);
2407*fcf3ce44SJohn Forte 
2408*fcf3ce44SJohn Forte 	if (!found_newlink) {
2409*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5562,
2410*fcf3ce44SJohn Forte 			" No new device(s) were added!!\n\n"));
2411*fcf3ce44SJohn Forte 	}
2412*fcf3ce44SJohn Forte 
2413*fcf3ce44SJohn Forte 	return (0);
2414*fcf3ce44SJohn Forte }
2415*fcf3ce44SJohn Forte 
2416*fcf3ce44SJohn Forte 
2417*fcf3ce44SJohn Forte 
2418*fcf3ce44SJohn Forte /*
2419*fcf3ce44SJohn Forte  * Performs the pre hotplug operations on SENA enclosure(s),
2420*fcf3ce44SJohn Forte  * SENA disk(s) and individual fcal disk(s).
2421*fcf3ce44SJohn Forte  * If the device is failed to remove, then it removes the device from the
2422*fcf3ce44SJohn Forte  * hotplug list and continues with the next device in the list.
2423*fcf3ce44SJohn Forte  *
2424*fcf3ce44SJohn Forte  * RETURNS:
2425*fcf3ce44SJohn Forte  *	0	 if OK
2426*fcf3ce44SJohn Forte  *	prints an error message to stderr and returns 0
2427*fcf3ce44SJohn Forte  */
2428*fcf3ce44SJohn Forte static int
2429*fcf3ce44SJohn Forte h_pre_hotplug(Hotplug_Devlist **disk_list_head_ptr,
2430*fcf3ce44SJohn Forte 			WWN_list *wwn_list, int todo,
2431*fcf3ce44SJohn Forte 			int verbose_flag, int force_flag)
2432*fcf3ce44SJohn Forte {
2433*fcf3ce44SJohn Forte Hotplug_Devlist	*list, *disk_list;
2434*fcf3ce44SJohn Forte int		err = 0;
2435*fcf3ce44SJohn Forte 
2436*fcf3ce44SJohn Forte 	disk_list = *disk_list_head_ptr;
2437*fcf3ce44SJohn Forte 	while (disk_list != NULL) {
2438*fcf3ce44SJohn Forte 		if ((disk_list->dev_type == DTYPE_ESI) ||
2439*fcf3ce44SJohn Forte 			(disk_list->dev_location == SENA)) {
2440*fcf3ce44SJohn Forte 			if ((err = h_pre_hotplug_sena(disk_list, wwn_list,
2441*fcf3ce44SJohn Forte 				    todo, verbose_flag, force_flag)) != 0) {
2442*fcf3ce44SJohn Forte 				(void) print_errString(err,
2443*fcf3ce44SJohn Forte 						disk_list->dev_name);
2444*fcf3ce44SJohn Forte 				goto delete;
2445*fcf3ce44SJohn Forte 			}
2446*fcf3ce44SJohn Forte 		} else if (disk_list->dev_location == NON_SENA) {
2447*fcf3ce44SJohn Forte 			if ((err = h_pre_remove_dev(disk_list, wwn_list,
2448*fcf3ce44SJohn Forte 					verbose_flag, force_flag)) != 0) {
2449*fcf3ce44SJohn Forte 				(void) print_errString(err,
2450*fcf3ce44SJohn Forte 						disk_list->dev_name);
2451*fcf3ce44SJohn Forte 				goto delete;
2452*fcf3ce44SJohn Forte 			}
2453*fcf3ce44SJohn Forte 		}
2454*fcf3ce44SJohn Forte 		disk_list = disk_list->next;
2455*fcf3ce44SJohn Forte 		continue;
2456*fcf3ce44SJohn Forte delete:
2457*fcf3ce44SJohn Forte 		list = disk_list->prev;
2458*fcf3ce44SJohn Forte 		if (list != NULL) {
2459*fcf3ce44SJohn Forte 			list->next = disk_list->next;
2460*fcf3ce44SJohn Forte 			if (list->next != NULL)
2461*fcf3ce44SJohn Forte 				list->next->prev = list;
2462*fcf3ce44SJohn Forte 		}
2463*fcf3ce44SJohn Forte 		list = disk_list;
2464*fcf3ce44SJohn Forte 		disk_list = disk_list->next;
2465*fcf3ce44SJohn Forte 		if (list == *disk_list_head_ptr)
2466*fcf3ce44SJohn Forte 			*disk_list_head_ptr = disk_list;
2467*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->seslist);
2468*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->dlhead);
2469*fcf3ce44SJohn Forte 		(void) free(list);
2470*fcf3ce44SJohn Forte 	}
2471*fcf3ce44SJohn Forte 	return (0);
2472*fcf3ce44SJohn Forte }
2473*fcf3ce44SJohn Forte 
2474*fcf3ce44SJohn Forte 
2475*fcf3ce44SJohn Forte 
2476*fcf3ce44SJohn Forte /*
2477*fcf3ce44SJohn Forte  * Performs the post removal of a list of SENA enclosure(s),
2478*fcf3ce44SJohn Forte  * SENA disk(s) and individual fcal disk(s).
2479*fcf3ce44SJohn Forte  *
2480*fcf3ce44SJohn Forte  * RETURNS:
2481*fcf3ce44SJohn Forte  *	0	 O.K.
2482*fcf3ce44SJohn Forte  *	non-zero otherwise
2483*fcf3ce44SJohn Forte  */
2484*fcf3ce44SJohn Forte static int
2485*fcf3ce44SJohn Forte h_post_hotplug(Hotplug_Devlist *hotplug_dlist,
2486*fcf3ce44SJohn Forte 			WWN_list *wwn_list, int todo,
2487*fcf3ce44SJohn Forte 			int verbose_flag, int force_flag, int enc_type)
2488*fcf3ce44SJohn Forte {
2489*fcf3ce44SJohn Forte Hotplug_Devlist	*list;
2490*fcf3ce44SJohn Forte int		err;
2491*fcf3ce44SJohn Forte 
2492*fcf3ce44SJohn Forte 	/* Do a lip on every loop so that we get the latest loop maps */
2493*fcf3ce44SJohn Forte 	if (todo != INSERT_DEVICE) {
2494*fcf3ce44SJohn Forte 		if ((err = g_forcelip_all(hotplug_dlist)) != 0) {
2495*fcf3ce44SJohn Forte 			return (err);
2496*fcf3ce44SJohn Forte 		}
2497*fcf3ce44SJohn Forte 	}
2498*fcf3ce44SJohn Forte 
2499*fcf3ce44SJohn Forte 	while (hotplug_dlist != NULL) {
2500*fcf3ce44SJohn Forte 		if ((hotplug_dlist->dev_location == SENA) ||
2501*fcf3ce44SJohn Forte 			(hotplug_dlist->dev_type == DTYPE_ESI)) {
2502*fcf3ce44SJohn Forte 		if ((err = h_post_hotplug_sena(hotplug_dlist, wwn_list, todo,
2503*fcf3ce44SJohn Forte 				verbose_flag, force_flag, enc_type)) != 0)
2504*fcf3ce44SJohn Forte 			(void) print_errString(err, hotplug_dlist->dev_name);
2505*fcf3ce44SJohn Forte 		} else if (hotplug_dlist->dev_location == NON_SENA) {
2506*fcf3ce44SJohn Forte 			if ((err = h_post_remove_dev(hotplug_dlist,
2507*fcf3ce44SJohn Forte 					todo, verbose_flag)) != 0)
2508*fcf3ce44SJohn Forte 				(void) print_errString(err,
2509*fcf3ce44SJohn Forte 						hotplug_dlist->dev_name);
2510*fcf3ce44SJohn Forte 		}
2511*fcf3ce44SJohn Forte 		list = hotplug_dlist;
2512*fcf3ce44SJohn Forte 		hotplug_dlist = hotplug_dlist->next;
2513*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->seslist);
2514*fcf3ce44SJohn Forte 		(void) g_free_multipath(list->dlhead);
2515*fcf3ce44SJohn Forte 		(void) free(list);
2516*fcf3ce44SJohn Forte 	}
2517*fcf3ce44SJohn Forte 	return (0);
2518*fcf3ce44SJohn Forte }
2519*fcf3ce44SJohn Forte 
2520*fcf3ce44SJohn Forte 
2521*fcf3ce44SJohn Forte /*
2522*fcf3ce44SJohn Forte  * removes the device's logical paths.
2523*fcf3ce44SJohn Forte  *
2524*fcf3ce44SJohn Forte  * RETURNS:
2525*fcf3ce44SJohn Forte  *	0	 if OK
2526*fcf3ce44SJohn Forte  *	non-zero otherwise
2527*fcf3ce44SJohn Forte  */
2528*fcf3ce44SJohn Forte static	int
2529*fcf3ce44SJohn Forte h_remove_nodes(struct dlist *dl)
2530*fcf3ce44SJohn Forte {
2531*fcf3ce44SJohn Forte char		link[MAXPATHLEN], path[MAXPATHLEN];
2532*fcf3ce44SJohn Forte char		lname[MAXPATHLEN], *ptr;
2533*fcf3ce44SJohn Forte DIR		*dir;
2534*fcf3ce44SJohn Forte struct	dirent	*dirent;
2535*fcf3ce44SJohn Forte struct	dlist	*dlist;
2536*fcf3ce44SJohn Forte 
2537*fcf3ce44SJohn Forte 	if ((dir = opendir(DEV_DSK_DIR)) == NULL) {
2538*fcf3ce44SJohn Forte 		return (L_READ_DEV_DIR_ERROR);
2539*fcf3ce44SJohn Forte 	}
2540*fcf3ce44SJohn Forte 	if (dl == NULL) {
2541*fcf3ce44SJohn Forte 		/* pass "disks" as cmdStrg */
2542*fcf3ce44SJohn Forte 		if (h_execCmnd(cmdStrg[1], 1) != 0) {
2543*fcf3ce44SJohn Forte 			return (L_DISKS_ERROR);
2544*fcf3ce44SJohn Forte 		}
2545*fcf3ce44SJohn Forte 	}
2546*fcf3ce44SJohn Forte 
2547*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
2548*fcf3ce44SJohn Forte 			MSGSTR(5563,
2549*fcf3ce44SJohn Forte 			"    Removing Logical Nodes: \n"));
2550*fcf3ce44SJohn Forte 
2551*fcf3ce44SJohn Forte 	while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2552*fcf3ce44SJohn Forte 		if (strcmp(dirent->d_name, ".") == 0 ||
2553*fcf3ce44SJohn Forte 				strcmp(dirent->d_name, "..") == 0) {
2554*fcf3ce44SJohn Forte 			continue;
2555*fcf3ce44SJohn Forte 		}
2556*fcf3ce44SJohn Forte 		(void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name);
2557*fcf3ce44SJohn Forte 		if (readlink((const char *)lname, (char *)link,
2558*fcf3ce44SJohn Forte 					(size_t)MAXPATHLEN) <= 0) {
2559*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2560*fcf3ce44SJohn Forte 					MSGSTR(5564,
2561*fcf3ce44SJohn Forte 					" Error: Could not read %s\n"),
2562*fcf3ce44SJohn Forte 					lname);
2563*fcf3ce44SJohn Forte 				continue;
2564*fcf3ce44SJohn Forte 		}
2565*fcf3ce44SJohn Forte 		for (dlist = dl; dlist != NULL; dlist = dlist->next) {
2566*fcf3ce44SJohn Forte 			(void) strcpy(path, dlist->dev_path);
2567*fcf3ce44SJohn Forte 			ptr = strrchr(path, ':');
2568*fcf3ce44SJohn Forte 			if (ptr)
2569*fcf3ce44SJohn Forte 				*ptr = '\0';
2570*fcf3ce44SJohn Forte 			if (strstr(link, path)) {
2571*fcf3ce44SJohn Forte 				(void) unlink(lname);
2572*fcf3ce44SJohn Forte 				(void) sprintf(lname, "/dev/rdsk/%s",
2573*fcf3ce44SJohn Forte 							dirent->d_name);
2574*fcf3ce44SJohn Forte 				(void) fprintf(stdout,
2575*fcf3ce44SJohn Forte 						MSGSTR(5565,
2576*fcf3ce44SJohn Forte 						"\tRemoving %s\n"),
2577*fcf3ce44SJohn Forte 						dirent->d_name);
2578*fcf3ce44SJohn Forte 				(void) unlink(lname);
2579*fcf3ce44SJohn Forte 			}
2580*fcf3ce44SJohn Forte 		}
2581*fcf3ce44SJohn Forte 	}
2582*fcf3ce44SJohn Forte 	closedir(dir);
2583*fcf3ce44SJohn Forte 	return (0);
2584*fcf3ce44SJohn Forte }
2585*fcf3ce44SJohn Forte 
2586*fcf3ce44SJohn Forte 
2587*fcf3ce44SJohn Forte 
2588*fcf3ce44SJohn Forte /*
2589*fcf3ce44SJohn Forte  * removes the SENA's ses paths.
2590*fcf3ce44SJohn Forte  *
2591*fcf3ce44SJohn Forte  * RETURNS:
2592*fcf3ce44SJohn Forte  *	0	 if OK
2593*fcf3ce44SJohn Forte  *	non-zero otherwise
2594*fcf3ce44SJohn Forte  */
2595*fcf3ce44SJohn Forte static int
2596*fcf3ce44SJohn Forte h_remove_ses_nodes(struct dlist *dlist)
2597*fcf3ce44SJohn Forte {
2598*fcf3ce44SJohn Forte char		link[MAXPATHLEN], lname[MAXPATHLEN];
2599*fcf3ce44SJohn Forte DIR		*dir;
2600*fcf3ce44SJohn Forte struct dirent	*dirent;
2601*fcf3ce44SJohn Forte struct	dlist	*dl;
2602*fcf3ce44SJohn Forte 
2603*fcf3ce44SJohn Forte 
2604*fcf3ce44SJohn Forte 	if ((dir = opendir(SES_DIR)) == NULL) {
2605*fcf3ce44SJohn Forte 		return (L_READ_DEV_DIR_ERROR);
2606*fcf3ce44SJohn Forte 	}
2607*fcf3ce44SJohn Forte 
2608*fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(5566, "  Removing Ses Nodes:\n"));
2609*fcf3ce44SJohn Forte 
2610*fcf3ce44SJohn Forte 	/*
2611*fcf3ce44SJohn Forte 	 * Remove the ses entries
2612*fcf3ce44SJohn Forte 	 * of the form ses<#>
2613*fcf3ce44SJohn Forte 	 * from the /dev/es directory.
2614*fcf3ce44SJohn Forte 	 */
2615*fcf3ce44SJohn Forte 
2616*fcf3ce44SJohn Forte 	while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2617*fcf3ce44SJohn Forte 		if (strcmp(dirent->d_name, ".") == 0 ||
2618*fcf3ce44SJohn Forte 			strcmp(dirent->d_name, "..") == 0)
2619*fcf3ce44SJohn Forte 			continue;
2620*fcf3ce44SJohn Forte 
2621*fcf3ce44SJohn Forte 		(void) sprintf(lname, SES_DIR"/%s", dirent->d_name);
2622*fcf3ce44SJohn Forte 		if (readlink((const char *)lname, (char *)link,
2623*fcf3ce44SJohn Forte 			(size_t)MAXPATHLEN) <= 0) {
2624*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2625*fcf3ce44SJohn Forte 					MSGSTR(5564,
2626*fcf3ce44SJohn Forte 					" Error: Could not read %s\n"),
2627*fcf3ce44SJohn Forte 					lname);
2628*fcf3ce44SJohn Forte 			continue;
2629*fcf3ce44SJohn Forte 		}
2630*fcf3ce44SJohn Forte 		for (dl = dlist; dl != NULL; dl = dl->next) {
2631*fcf3ce44SJohn Forte 			if (strstr(link, dl->dev_path)) {
2632*fcf3ce44SJohn Forte 				(void) fprintf(stdout,
2633*fcf3ce44SJohn Forte 						MSGSTR(5568,
2634*fcf3ce44SJohn Forte 						"\tRemoving %s\n"),
2635*fcf3ce44SJohn Forte 						lname);
2636*fcf3ce44SJohn Forte 				(void) unlink(lname);
2637*fcf3ce44SJohn Forte 			}
2638*fcf3ce44SJohn Forte 		}
2639*fcf3ce44SJohn Forte 	}
2640*fcf3ce44SJohn Forte 	closedir(dir);
2641*fcf3ce44SJohn Forte 	(void) g_free_multipath(dlist);
2642*fcf3ce44SJohn Forte 	return (0);
2643*fcf3ce44SJohn Forte }
2644*fcf3ce44SJohn Forte 
2645*fcf3ce44SJohn Forte 
2646*fcf3ce44SJohn Forte /*
2647*fcf3ce44SJohn Forte  * prints the device's logical
2648*fcf3ce44SJohn Forte  * paths for disks to stdout.
2649*fcf3ce44SJohn Forte  *
2650*fcf3ce44SJohn Forte  * RETURNS:
2651*fcf3ce44SJohn Forte  *	0	 if OK
2652*fcf3ce44SJohn Forte  *	non-zero otherwise
2653*fcf3ce44SJohn Forte  */
2654*fcf3ce44SJohn Forte static	void
2655*fcf3ce44SJohn Forte h_print_logical_nodes(struct dlist *disk_list)
2656*fcf3ce44SJohn Forte {
2657*fcf3ce44SJohn Forte char		*lpath, *ptr, *buf_ptr, buf[MAXNAMELEN], dev[MAXNAMELEN];
2658*fcf3ce44SJohn Forte struct dlist	*dlist;
2659*fcf3ce44SJohn Forte int		i, found_dev = 0;
2660*fcf3ce44SJohn Forte char		*tape_entries[] = { "", "b", "bn", "c", "cb", "cbn", "cn",
2661*fcf3ce44SJohn Forte 				"h", "hb", "hbn", "hn", "l", "lb",
2662*fcf3ce44SJohn Forte 				"lbn", "ln", "m", "mb", "mbn", "mn",
2663*fcf3ce44SJohn Forte 				"n", "u", "ub", "ubn", "un", NULL};
2664*fcf3ce44SJohn Forte 
2665*fcf3ce44SJohn Forte 	for (dlist = disk_list; dlist != NULL; dlist = dlist->next) {
2666*fcf3ce44SJohn Forte 		lpath = dlist->logical_path;
2667*fcf3ce44SJohn Forte 		if ((ptr = strrchr(lpath, 'c')) == NULL)
2668*fcf3ce44SJohn Forte 			continue;
2669*fcf3ce44SJohn Forte 		(void) strcpy(buf, ptr);
2670*fcf3ce44SJohn Forte 		if ((ptr = strrchr(buf, 's')) == NULL)
2671*fcf3ce44SJohn Forte 			continue;
2672*fcf3ce44SJohn Forte 		*(++ptr) = NULL;
2673*fcf3ce44SJohn Forte 		found_dev++;
2674*fcf3ce44SJohn Forte 		if (found_dev == 1)
2675*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
2676*fcf3ce44SJohn Forte 					MSGSTR(5559, "  Logical Nodes being "
2677*fcf3ce44SJohn Forte 					"removed under /dev/dsk/ and "
2678*fcf3ce44SJohn Forte 					"/dev/rdsk:\n"));
2679*fcf3ce44SJohn Forte 		for (i = 0; i <= 7; i++) {
2680*fcf3ce44SJohn Forte 			(void) sprintf(dev, "%s%d", buf, i);
2681*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\t%s\n", dev);
2682*fcf3ce44SJohn Forte 		}
2683*fcf3ce44SJohn Forte 	}
2684*fcf3ce44SJohn Forte 	found_dev = 0;
2685*fcf3ce44SJohn Forte 	for (dlist = disk_list; dlist != NULL; dlist = dlist->next) {
2686*fcf3ce44SJohn Forte 		lpath = dlist->logical_path;
2687*fcf3ce44SJohn Forte 		if (strstr(lpath, DEV_TAPE_DIR)) {
2688*fcf3ce44SJohn Forte 			if ((ptr = strrchr(lpath, '/')) == NULL)
2689*fcf3ce44SJohn Forte 				continue;
2690*fcf3ce44SJohn Forte 			found_dev++;
2691*fcf3ce44SJohn Forte 			if (found_dev == 1)
2692*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "Logical Nodes being "
2693*fcf3ce44SJohn Forte 						"removed under /dev/rmt:\n");
2694*fcf3ce44SJohn Forte 			ptr++;
2695*fcf3ce44SJohn Forte 			buf_ptr = ptr;
2696*fcf3ce44SJohn Forte 			while (*ptr >= '0' && *ptr <= '9')
2697*fcf3ce44SJohn Forte 				ptr++;
2698*fcf3ce44SJohn Forte 			*ptr = NULL;
2699*fcf3ce44SJohn Forte 			for (i = 0, ptr = tape_entries[0];
2700*fcf3ce44SJohn Forte 					ptr != NULL;
2701*fcf3ce44SJohn Forte 					i++, ptr = tape_entries[i]) {
2702*fcf3ce44SJohn Forte 				(void) sprintf(dev, "%s%s", buf_ptr, ptr);
2703*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "\t%s\n", dev);
2704*fcf3ce44SJohn Forte 			}
2705*fcf3ce44SJohn Forte 		}
2706*fcf3ce44SJohn Forte 	}
2707*fcf3ce44SJohn Forte }
2708*fcf3ce44SJohn Forte 
2709*fcf3ce44SJohn Forte /*
2710*fcf3ce44SJohn Forte  * displays logical paths to a
2711*fcf3ce44SJohn Forte  * device to stdout.
2712*fcf3ce44SJohn Forte  *
2713*fcf3ce44SJohn Forte  * RETURNS:
2714*fcf3ce44SJohn Forte  *	0	 if OK
2715*fcf3ce44SJohn Forte  *	non-zero otherwise
2716*fcf3ce44SJohn Forte  */
2717*fcf3ce44SJohn Forte static int
2718*fcf3ce44SJohn Forte h_display_logical_nodes(struct dlist *dlist)
2719*fcf3ce44SJohn Forte {
2720*fcf3ce44SJohn Forte char		link[MAXPATHLEN], path[MAXPATHLEN];
2721*fcf3ce44SJohn Forte char		lname[MAXPATHLEN], *d1;
2722*fcf3ce44SJohn Forte DIR		*dir;
2723*fcf3ce44SJohn Forte struct	dirent	*dirent;
2724*fcf3ce44SJohn Forte struct	dlist	*dl;
2725*fcf3ce44SJohn Forte 
2726*fcf3ce44SJohn Forte 
2727*fcf3ce44SJohn Forte 	if ((dir = opendir(DEV_DSK_DIR)) == NULL) {
2728*fcf3ce44SJohn Forte 		return (L_READ_DEV_DIR_ERROR);
2729*fcf3ce44SJohn Forte 	}
2730*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
2731*fcf3ce44SJohn Forte 			MSGSTR(5569,
2732*fcf3ce44SJohn Forte 			"  Logical Nodes under /dev/dsk and /dev/rdsk :\n"));
2733*fcf3ce44SJohn Forte 
2734*fcf3ce44SJohn Forte 	while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2735*fcf3ce44SJohn Forte 		if (strcmp(dirent->d_name, ".") == 0 ||
2736*fcf3ce44SJohn Forte 			strcmp(dirent->d_name, "..") == 0) {
2737*fcf3ce44SJohn Forte 				continue;
2738*fcf3ce44SJohn Forte 		}
2739*fcf3ce44SJohn Forte 		(void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name);
2740*fcf3ce44SJohn Forte 		if (readlink((const char *)lname, (char *)link,
2741*fcf3ce44SJohn Forte 			(size_t)MAXPATHLEN) <= 0) {
2742*fcf3ce44SJohn Forte 			(void) print_errString(L_SYMLINK_ERROR, lname);
2743*fcf3ce44SJohn Forte 			continue;
2744*fcf3ce44SJohn Forte 		}
2745*fcf3ce44SJohn Forte 		for (dl = dlist; dl; dl = dl->next) {
2746*fcf3ce44SJohn Forte 			(void) strcpy(path, dl->dev_path);
2747*fcf3ce44SJohn Forte 			d1 = strrchr(path, ':');
2748*fcf3ce44SJohn Forte 			if (d1)
2749*fcf3ce44SJohn Forte 				*d1 = '\0';
2750*fcf3ce44SJohn Forte 			if (strstr(link, path)) {
2751*fcf3ce44SJohn Forte 				(void) fprintf(stdout,
2752*fcf3ce44SJohn Forte 						"\t%s\n",
2753*fcf3ce44SJohn Forte 						dirent->d_name);
2754*fcf3ce44SJohn Forte 			}
2755*fcf3ce44SJohn Forte 		}
2756*fcf3ce44SJohn Forte 	}
2757*fcf3ce44SJohn Forte 
2758*fcf3ce44SJohn Forte 	closedir(dir);
2759*fcf3ce44SJohn Forte 	return (0);
2760*fcf3ce44SJohn Forte }
2761*fcf3ce44SJohn Forte 
2762*fcf3ce44SJohn Forte 
2763*fcf3ce44SJohn Forte 
2764*fcf3ce44SJohn Forte /*
2765*fcf3ce44SJohn Forte  * prints a list of devices which
2766*fcf3ce44SJohn Forte  * will be inserted or removed
2767*fcf3ce44SJohn Forte  * to the stdout and asks for
2768*fcf3ce44SJohn Forte  * the user's confirmation.
2769*fcf3ce44SJohn Forte  *
2770*fcf3ce44SJohn Forte  * RETURNS:
2771*fcf3ce44SJohn Forte  *	0	 if OK
2772*fcf3ce44SJohn Forte  *	non-zero otherwise
2773*fcf3ce44SJohn Forte  */
2774*fcf3ce44SJohn Forte static int
2775*fcf3ce44SJohn Forte h_print_list_warn(Hotplug_Devlist *disk_list_head, int todo, int enc_type)
2776*fcf3ce44SJohn Forte {
2777*fcf3ce44SJohn Forte int			i;
2778*fcf3ce44SJohn Forte char			choice[2];
2779*fcf3ce44SJohn Forte struct dlist		*dl_ses, *dl_multi;
2780*fcf3ce44SJohn Forte Hotplug_Devlist		*disk_list = disk_list_head;
2781*fcf3ce44SJohn Forte 
2782*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
2783*fcf3ce44SJohn Forte 		MSGSTR(5570, "The list of devices which will be "));
2784*fcf3ce44SJohn Forte 	switch (todo) {
2785*fcf3ce44SJohn Forte 		case INSERT_DEVICE:
2786*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
2787*fcf3ce44SJohn Forte 			MSGSTR(5571, "inserted is:\n"));
2788*fcf3ce44SJohn Forte 			break;
2789*fcf3ce44SJohn Forte 		case REMOVE_DEVICE:
2790*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
2791*fcf3ce44SJohn Forte 			MSGSTR(5572, "removed is:\n"));
2792*fcf3ce44SJohn Forte 			break;
2793*fcf3ce44SJohn Forte 	}
2794*fcf3ce44SJohn Forte 
2795*fcf3ce44SJohn Forte 	for (i = 1; disk_list; i++, disk_list = disk_list->next) {
2796*fcf3ce44SJohn Forte 		if ((disk_list->dev_type == DTYPE_DIRECT) &&
2797*fcf3ce44SJohn Forte 			(disk_list->dev_location == SENA)) {
2798*fcf3ce44SJohn Forte 		    if (disk_list->f_flag != NULL) {
2799*fcf3ce44SJohn Forte 			if (enc_type == DAK_ENC_TYPE) {
2800*fcf3ce44SJohn Forte 			    (void) fprintf(stdout, MSGSTR(5665,
2801*fcf3ce44SJohn Forte 				"  %d: Box Name:    \"%s\" slot %d\n"),
2802*fcf3ce44SJohn Forte 				i, disk_list->box_name, disk_list->slot);
2803*fcf3ce44SJohn Forte 			} else {
2804*fcf3ce44SJohn Forte 			    (void) fprintf(stdout, MSGSTR(137,
2805*fcf3ce44SJohn Forte 				"  %d: Box Name:    \"%s\" front slot %d\n"),
2806*fcf3ce44SJohn Forte 				i, disk_list->box_name, disk_list->slot);
2807*fcf3ce44SJohn Forte 			}
2808*fcf3ce44SJohn Forte 		    } else {
2809*fcf3ce44SJohn Forte 			if (enc_type == DAK_ENC_TYPE) {
2810*fcf3ce44SJohn Forte 			    (void) fprintf(stdout, MSGSTR(5665,
2811*fcf3ce44SJohn Forte 				"  %d: Box Name:    \"%s\" slot %d\n"),
2812*fcf3ce44SJohn Forte 				i, disk_list->box_name,
2813*fcf3ce44SJohn Forte 				disk_list->slot + (MAX_DRIVES_DAK/2));
2814*fcf3ce44SJohn Forte 			} else {
2815*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(136,
2816*fcf3ce44SJohn Forte 				    "  %d: Box Name:    \"%s\" rear slot %d\n"),
2817*fcf3ce44SJohn Forte 				    i, disk_list->box_name, disk_list->slot);
2818*fcf3ce44SJohn Forte 			}
2819*fcf3ce44SJohn Forte 		    }
2820*fcf3ce44SJohn Forte 		} else if (((disk_list->dev_type == DTYPE_DIRECT) ||
2821*fcf3ce44SJohn Forte 				(disk_list->dev_type == DTYPE_SEQUENTIAL)) &&
2822*fcf3ce44SJohn Forte 				(disk_list->dev_location == NON_SENA)) {
2823*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5573,
2824*fcf3ce44SJohn Forte 					"  %d: Device name: %s\n"),
2825*fcf3ce44SJohn Forte 					i, disk_list->dev_name);
2826*fcf3ce44SJohn Forte 		} else if (disk_list->dev_type == DTYPE_ESI) {
2827*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(5574,
2828*fcf3ce44SJohn Forte 				"  %d: Box name:    %s\n"),
2829*fcf3ce44SJohn Forte 				i, disk_list->box_name);
2830*fcf3ce44SJohn Forte 		}
2831*fcf3ce44SJohn Forte 		if (getenv("_LUX_H_DEBUG") != NULL) {
2832*fcf3ce44SJohn Forte 			if (disk_list->dev_location == SENA) {
2833*fcf3ce44SJohn Forte 				(void) fprintf(stdout,
2834*fcf3ce44SJohn Forte 				"      Select ID:\t0x%x\n",
2835*fcf3ce44SJohn Forte 					disk_list->tid);
2836*fcf3ce44SJohn Forte 				if (disk_list->dev_type != DTYPE_ESI) {
2837*fcf3ce44SJohn Forte 					if (enc_type == DAK_ENC_TYPE) {
2838*fcf3ce44SJohn Forte 						(void) fprintf(stdout,
2839*fcf3ce44SJohn Forte 					    "      Location:   \tSlot %d \n",
2840*fcf3ce44SJohn Forte 					    disk_list->f_flag
2841*fcf3ce44SJohn Forte 					    ? disk_list->slot
2842*fcf3ce44SJohn Forte 					    : disk_list->slot
2843*fcf3ce44SJohn Forte 							+MAX_DRIVES_DAK/2);
2844*fcf3ce44SJohn Forte 					} else {
2845*fcf3ce44SJohn Forte 						(void) fprintf(stdout,
2846*fcf3ce44SJohn Forte 					    "      Location:   \tSlot %d %s \n",
2847*fcf3ce44SJohn Forte 					    disk_list->slot, disk_list->f_flag
2848*fcf3ce44SJohn Forte 					    ? "front" : "rear");
2849*fcf3ce44SJohn Forte 					}
2850*fcf3ce44SJohn Forte 				}
2851*fcf3ce44SJohn Forte 			}
2852*fcf3ce44SJohn Forte 		}
2853*fcf3ce44SJohn Forte 		if (todo == REMOVE_DEVICE) {
2854*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "     ");
2855*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(90, "Node WWN:"));
2856*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "    %s\n",
2857*fcf3ce44SJohn Forte 				disk_list->node_wwn_s);
2858*fcf3ce44SJohn Forte 
2859*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "     ");
2860*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(35, "Device Type:"));
2861*fcf3ce44SJohn Forte 			if (disk_list->dev_type == DTYPE_ESI) {
2862*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5581,
2863*fcf3ce44SJohn Forte 					" SENA (%s)\n"),
2864*fcf3ce44SJohn Forte 					dtype[disk_list->dev_type]);
2865*fcf3ce44SJohn Forte 			} else {
2866*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "%s\n",
2867*fcf3ce44SJohn Forte 					dtype[disk_list->dev_type]);
2868*fcf3ce44SJohn Forte 			}
2869*fcf3ce44SJohn Forte 
2870*fcf3ce44SJohn Forte 			if (disk_list->dev_type == DTYPE_ESI) {
2871*fcf3ce44SJohn Forte 				dl_ses = disk_list->seslist;
2872*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5575,
2873*fcf3ce44SJohn Forte 						"     SES Paths:\n"));
2874*fcf3ce44SJohn Forte 				while (dl_ses) {
2875*fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(5576,
2876*fcf3ce44SJohn Forte 					"      %s\n"), dl_ses->dev_path);
2877*fcf3ce44SJohn Forte 					dl_ses = dl_ses->next;
2878*fcf3ce44SJohn Forte 				}
2879*fcf3ce44SJohn Forte 			} else {
2880*fcf3ce44SJohn Forte 				dl_multi = disk_list->dlhead;
2881*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(5577,
2882*fcf3ce44SJohn Forte 						"     Device Paths:\n"));
2883*fcf3ce44SJohn Forte 				while (dl_multi) {
2884*fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(5578,
2885*fcf3ce44SJohn Forte 						"      %s\n"),
2886*fcf3ce44SJohn Forte 						dl_multi->logical_path);
2887*fcf3ce44SJohn Forte 					dl_multi = dl_multi->next;
2888*fcf3ce44SJohn Forte 				}
2889*fcf3ce44SJohn Forte 			}
2890*fcf3ce44SJohn Forte 		}
2891*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
2892*fcf3ce44SJohn Forte 	}
2893*fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(5579,
2894*fcf3ce44SJohn Forte 			"\nPlease verify the above list of devices"
2895*fcf3ce44SJohn Forte 			" and\nthen enter 'c' or <CR> to Continue"
2896*fcf3ce44SJohn Forte 			" or 'q' to Quit. [Default: c]: "));
2897*fcf3ce44SJohn Forte 
2898*fcf3ce44SJohn Forte 	/* Get the user input and continue accordingly. */
2899*fcf3ce44SJohn Forte 	for (;;) {
2900*fcf3ce44SJohn Forte 		(void) gets(choice);
2901*fcf3ce44SJohn Forte 		if (choice[0] == 'c' || choice[0] == 'C' ||
2902*fcf3ce44SJohn Forte 				choice[0] == 'q' || choice[0] == 'Q' ||
2903*fcf3ce44SJohn Forte 				choice[0] == '\0') {
2904*fcf3ce44SJohn Forte 			break;
2905*fcf3ce44SJohn Forte 		}
2906*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(5580,
2907*fcf3ce44SJohn Forte 			" Enter an appropriate option [c,<CR>,q]: "));
2908*fcf3ce44SJohn Forte 	}
2909*fcf3ce44SJohn Forte 
2910*fcf3ce44SJohn Forte 	if (choice[0] == 'q' || choice[0] == 'Q') {
2911*fcf3ce44SJohn Forte 		return (-1);
2912*fcf3ce44SJohn Forte 	}
2913*fcf3ce44SJohn Forte 	return (0);
2914*fcf3ce44SJohn Forte }
2915*fcf3ce44SJohn Forte 
2916*fcf3ce44SJohn Forte 
2917*fcf3ce44SJohn Forte static int
2918*fcf3ce44SJohn Forte h_find_new_device_link(char *device_dir, timestruc_t lastmtim)
2919*fcf3ce44SJohn Forte {
2920*fcf3ce44SJohn Forte struct stat	dsk_stat;
2921*fcf3ce44SJohn Forte char		lname[MAXPATHLEN], link[MAXPATHLEN];
2922*fcf3ce44SJohn Forte char		*link_ptr;
2923*fcf3ce44SJohn Forte DIR		*dir;
2924*fcf3ce44SJohn Forte struct dirent	*dirent;
2925*fcf3ce44SJohn Forte int		found_newlink = 0;
2926*fcf3ce44SJohn Forte 
2927*fcf3ce44SJohn Forte 
2928*fcf3ce44SJohn Forte 	if ((dir = opendir(device_dir)) == NULL) {
2929*fcf3ce44SJohn Forte 		if (errno == ENOENT) {
2930*fcf3ce44SJohn Forte 			return (0);
2931*fcf3ce44SJohn Forte 		} else {
2932*fcf3ce44SJohn Forte 			return (L_READ_DEV_DIR_ERROR);
2933*fcf3ce44SJohn Forte 		}
2934*fcf3ce44SJohn Forte 	}
2935*fcf3ce44SJohn Forte 
2936*fcf3ce44SJohn Forte 	while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2937*fcf3ce44SJohn Forte 		if (strcmp(dirent->d_name, ".") == 0 ||
2938*fcf3ce44SJohn Forte 			strcmp(dirent->d_name, "..") == 0) {
2939*fcf3ce44SJohn Forte 			continue;
2940*fcf3ce44SJohn Forte 		}
2941*fcf3ce44SJohn Forte 		(void) sprintf(lname, "%s/%s", device_dir, dirent->d_name);
2942*fcf3ce44SJohn Forte 		if (lstat(lname, &dsk_stat) < 0) {
2943*fcf3ce44SJohn Forte 			(void) print_errString(L_LSTAT_ES_DIR_ERROR,
2944*fcf3ce44SJohn Forte 									lname);
2945*fcf3ce44SJohn Forte 			continue;
2946*fcf3ce44SJohn Forte 		}
2947*fcf3ce44SJohn Forte 		if (readlink((const char *)lname, (char *)link,
2948*fcf3ce44SJohn Forte 				(size_t)MAXPATHLEN) <= 0) {
2949*fcf3ce44SJohn Forte 			(void) print_errString(L_SYMLINK_ERROR, lname);
2950*fcf3ce44SJohn Forte 			continue;
2951*fcf3ce44SJohn Forte 		}
2952*fcf3ce44SJohn Forte 
2953*fcf3ce44SJohn Forte 		/*
2954*fcf3ce44SJohn Forte 		 * "link" can be a relative pathname. But, since
2955*fcf3ce44SJohn Forte 		 * g_get_path_type() only accepts absolute paths, we
2956*fcf3ce44SJohn Forte 		 * will skip to the part where "/devices/" begins and pass a
2957*fcf3ce44SJohn Forte 		 * pointer from there. Since "link" is got from readlink(),
2958*fcf3ce44SJohn Forte 		 * it is unlikely that it will not have /devices string, but
2959*fcf3ce44SJohn Forte 		 * we will check for it anyways.
2960*fcf3ce44SJohn Forte 		 */
2961*fcf3ce44SJohn Forte 		if (!(link_ptr = strstr(link, "/devices/")))
2962*fcf3ce44SJohn Forte 			continue;
2963*fcf3ce44SJohn Forte 		if (!g_get_path_type(link_ptr)) {
2964*fcf3ce44SJohn Forte 			continue;
2965*fcf3ce44SJohn Forte 		}
2966*fcf3ce44SJohn Forte 		if (NEWER(dsk_stat.st_ctim, lastmtim)) {
2967*fcf3ce44SJohn Forte 			found_newlink++;
2968*fcf3ce44SJohn Forte 			if (found_newlink == 1) {
2969*fcf3ce44SJohn Forte 				if (! (strcmp(device_dir, DEV_DSK_DIR))) {
2970*fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(5561,
2971*fcf3ce44SJohn Forte 						"  New Logical Nodes under "
2972*fcf3ce44SJohn Forte 						"/dev/dsk and /dev/rdsk :\n"));
2973*fcf3ce44SJohn Forte 				} else {	/* device_dir is /dev/rmt */
2974*fcf3ce44SJohn Forte 					(void) fprintf(stdout, "New Logical "
2975*fcf3ce44SJohn Forte 						"Node under /dev/rmt:\n");
2976*fcf3ce44SJohn Forte 				}
2977*fcf3ce44SJohn Forte 			}
2978*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\t%s\n", dirent->d_name);
2979*fcf3ce44SJohn Forte 		}
2980*fcf3ce44SJohn Forte 	}
2981*fcf3ce44SJohn Forte 	closedir(dir);
2982*fcf3ce44SJohn Forte 	return (found_newlink);
2983*fcf3ce44SJohn Forte }
2984*fcf3ce44SJohn Forte 
2985*fcf3ce44SJohn Forte 
2986*fcf3ce44SJohn Forte /*
2987*fcf3ce44SJohn Forte  * prints the device state.
2988*fcf3ce44SJohn Forte  *
2989*fcf3ce44SJohn Forte  * RETURNS:
2990*fcf3ce44SJohn Forte  *	None.
2991*fcf3ce44SJohn Forte  */
2992*fcf3ce44SJohn Forte void
2993*fcf3ce44SJohn Forte print_dev_state(char *devname, int state)
2994*fcf3ce44SJohn Forte {
2995*fcf3ce44SJohn Forte 	(void) printf("\t%s: ", devname);
2996*fcf3ce44SJohn Forte 	if (state & DEVICE_ONLINE) {
2997*fcf3ce44SJohn Forte 		(void) printf(MSGSTR(3000, "Online"));
2998*fcf3ce44SJohn Forte 		if (state & DEVICE_BUSY) {
2999*fcf3ce44SJohn Forte 			(void) printf(" ");
3000*fcf3ce44SJohn Forte 			(void) printf(MSGSTR(37, "Busy"));
3001*fcf3ce44SJohn Forte 		}
3002*fcf3ce44SJohn Forte 		if (state & DEVICE_DOWN) {
3003*fcf3ce44SJohn Forte 			(void) printf(" ");
3004*fcf3ce44SJohn Forte 			(void) printf(MSGSTR(118, "Down"));
3005*fcf3ce44SJohn Forte 		}
3006*fcf3ce44SJohn Forte 	} else {
3007*fcf3ce44SJohn Forte 		if (state & DEVICE_OFFLINE) {
3008*fcf3ce44SJohn Forte 			(void) printf(MSGSTR(3001, "Offline"));
3009*fcf3ce44SJohn Forte 			if (state & DEVICE_DOWN) {
3010*fcf3ce44SJohn Forte 				(void) printf(" ");
3011*fcf3ce44SJohn Forte 				(void) printf(MSGSTR(118, "Down"));
3012*fcf3ce44SJohn Forte 			}
3013*fcf3ce44SJohn Forte 		}
3014*fcf3ce44SJohn Forte 	}
3015*fcf3ce44SJohn Forte 	(void) printf("\n");
3016*fcf3ce44SJohn Forte }
3017*fcf3ce44SJohn Forte 
3018*fcf3ce44SJohn Forte 
3019*fcf3ce44SJohn Forte /*
3020*fcf3ce44SJohn Forte  * prints the bus state.
3021*fcf3ce44SJohn Forte  *
3022*fcf3ce44SJohn Forte  * RETURNS:
3023*fcf3ce44SJohn Forte  *	None.
3024*fcf3ce44SJohn Forte  */
3025*fcf3ce44SJohn Forte void
3026*fcf3ce44SJohn Forte print_bus_state(char *devname, int state)
3027*fcf3ce44SJohn Forte {
3028*fcf3ce44SJohn Forte 	(void) printf("\t%s: ", devname);
3029*fcf3ce44SJohn Forte 	if (state == BUS_QUIESCED) {
3030*fcf3ce44SJohn Forte 		(void) printf(MSGSTR(3002, "Quiesced"));
3031*fcf3ce44SJohn Forte 	} else if (state == BUS_ACTIVE) {
3032*fcf3ce44SJohn Forte 		(void) printf(MSGSTR(39, "Active"));
3033*fcf3ce44SJohn Forte 	} else if (state == BUS_SHUTDOWN) {
3034*fcf3ce44SJohn Forte 		(void) printf(MSGSTR(3003, "Shutdown"));
3035*fcf3ce44SJohn Forte 	}
3036*fcf3ce44SJohn Forte 	(void) printf("\n");
3037*fcf3ce44SJohn Forte }
3038