xref: /titanic_53/usr/src/cmd/luxadm/lux_util.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 #include	<stdio.h>
29*fcf3ce44SJohn Forte #include	<unistd.h>
30*fcf3ce44SJohn Forte #include	<stdlib.h>
31*fcf3ce44SJohn Forte #include	<sys/param.h>
32*fcf3ce44SJohn Forte #include	<sys/types.h>
33*fcf3ce44SJohn Forte #include	<fcntl.h>
34*fcf3ce44SJohn Forte #include	<sys/stat.h>
35*fcf3ce44SJohn Forte #include	<string.h>
36*fcf3ce44SJohn Forte #include	<strings.h>
37*fcf3ce44SJohn Forte #include	<ctype.h>
38*fcf3ce44SJohn Forte #include	<errno.h>
39*fcf3ce44SJohn Forte #include	<assert.h>
40*fcf3ce44SJohn Forte #include	<sys/scsi/impl/uscsi.h>
41*fcf3ce44SJohn Forte #include	<sys/scsi/generic/commands.h>
42*fcf3ce44SJohn Forte #include	<sys/scsi/impl/commands.h>
43*fcf3ce44SJohn Forte #include	<sys/scsi/generic/sense.h>
44*fcf3ce44SJohn Forte #include	<sys/scsi/generic/mode.h>
45*fcf3ce44SJohn Forte #include	<sys/scsi/generic/status.h>
46*fcf3ce44SJohn Forte #include	<sys/scsi/generic/inquiry.h>
47*fcf3ce44SJohn Forte #include	<sys/scsi/adapters/scsi_vhci.h>
48*fcf3ce44SJohn Forte #include	<sys/byteorder.h>
49*fcf3ce44SJohn Forte #include	"common.h"
50*fcf3ce44SJohn Forte #include	"errorcodes.h"
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte #define	MAX_MODE_SENSE_LEN		0xffff
53*fcf3ce44SJohn Forte #define	MAXLEN		1000
54*fcf3ce44SJohn Forte 
55*fcf3ce44SJohn Forte #define	RETRY_PATHLIST	1
56*fcf3ce44SJohn Forte #define	BYTES_PER_LINE	16
57*fcf3ce44SJohn Forte #define	SCMD_UNKNOWN	0xff
58*fcf3ce44SJohn Forte 
59*fcf3ce44SJohn Forte #define	SCSI_VHCI	"/devices/scsi_vhci/"
60*fcf3ce44SJohn Forte #define	SLASH		"/"
61*fcf3ce44SJohn Forte #define	DEV_PREFIX	"/devices/"
62*fcf3ce44SJohn Forte #define	DEV_PREFIX_STRLEN	strlen(DEV_PREFIX)
63*fcf3ce44SJohn Forte #define	DEVICES_DIR	"/devices"
64*fcf3ce44SJohn Forte 
65*fcf3ce44SJohn Forte extern	char	*dtype[]; /* from adm.c */
66*fcf3ce44SJohn Forte extern	int	rand_r(unsigned int *);
67*fcf3ce44SJohn Forte 
68*fcf3ce44SJohn Forte static int cleanup_dotdot_path(char *path);
69*fcf3ce44SJohn Forte static int wait_random_time(void);
70*fcf3ce44SJohn Forte static char *scsi_find_command_name(int cmd);
71*fcf3ce44SJohn Forte static void scsi_printerr(struct uscsi_cmd *ucmd,
72*fcf3ce44SJohn Forte 	    struct scsi_extended_sense *rq, int rqlen,
73*fcf3ce44SJohn Forte 	    char msg_string[], char *err_string);
74*fcf3ce44SJohn Forte static void string_dump(char *hdr, uchar_t *src, int nbytes, int format,
75*fcf3ce44SJohn Forte 	    char msg_string[]);
76*fcf3ce44SJohn Forte static int issue_uscsi_cmd(int file, struct uscsi_cmd *command, int flag);
77*fcf3ce44SJohn Forte 
78*fcf3ce44SJohn Forte 
79*fcf3ce44SJohn Forte static int
80*fcf3ce44SJohn Forte wait_random_time(void)
81*fcf3ce44SJohn Forte {
82*fcf3ce44SJohn Forte time_t		timeval;
83*fcf3ce44SJohn Forte struct tm	*tmbuf = NULL;
84*fcf3ce44SJohn Forte struct timeval	tval;
85*fcf3ce44SJohn Forte unsigned int	seed;
86*fcf3ce44SJohn Forte int		random;
87*fcf3ce44SJohn Forte pid_t		pid;
88*fcf3ce44SJohn Forte 
89*fcf3ce44SJohn Forte 
90*fcf3ce44SJohn Forte 	/*
91*fcf3ce44SJohn Forte 	 * Get the system time and use "system seconds"
92*fcf3ce44SJohn Forte 	 * as 'seed' to generate a random number. Then,
93*fcf3ce44SJohn Forte 	 * wait between 1/10 - 1/2 seconds before retry.
94*fcf3ce44SJohn Forte 	 * Get the current process id and ex-or it with
95*fcf3ce44SJohn Forte 	 * the seed so that the random number is always
96*fcf3ce44SJohn Forte 	 * different even in case of multiple processes
97*fcf3ce44SJohn Forte 	 * generate a random number at the same time.
98*fcf3ce44SJohn Forte 	 */
99*fcf3ce44SJohn Forte 	if ((timeval = time(NULL)) == -1) {
100*fcf3ce44SJohn Forte 		return (errno);
101*fcf3ce44SJohn Forte 	}
102*fcf3ce44SJohn Forte 	if ((tmbuf = localtime(&timeval)) == NULL) {
103*fcf3ce44SJohn Forte 		return (-1); /* L_LOCALTIME_ERROR */
104*fcf3ce44SJohn Forte 	}
105*fcf3ce44SJohn Forte 
106*fcf3ce44SJohn Forte 	pid = getpid();
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte 	/* get a random number. */
109*fcf3ce44SJohn Forte 	seed = (unsigned int) tmbuf->tm_sec;
110*fcf3ce44SJohn Forte 	seed ^= pid;
111*fcf3ce44SJohn Forte 	random = rand_r(&seed);
112*fcf3ce44SJohn Forte 
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte 	random = ((random % 500) + 100) * MILLISEC;
115*fcf3ce44SJohn Forte 	tval.tv_sec = random / MICROSEC;
116*fcf3ce44SJohn Forte 	tval.tv_usec = random % MICROSEC;
117*fcf3ce44SJohn Forte 
118*fcf3ce44SJohn Forte 	if (select(0, NULL, NULL, NULL, &tval) == -1) {
119*fcf3ce44SJohn Forte 		return (-1); /* L_SELECT_ERROR */
120*fcf3ce44SJohn Forte 	}
121*fcf3ce44SJohn Forte 	return (0);
122*fcf3ce44SJohn Forte }
123*fcf3ce44SJohn Forte 
124*fcf3ce44SJohn Forte /*
125*fcf3ce44SJohn Forte  *		Special string dump for error message
126*fcf3ce44SJohn Forte  */
127*fcf3ce44SJohn Forte static	void
128*fcf3ce44SJohn Forte string_dump(char *hdr, uchar_t *src, int nbytes, int format, char msg_string[])
129*fcf3ce44SJohn Forte {
130*fcf3ce44SJohn Forte 	int i;
131*fcf3ce44SJohn Forte 	int n;
132*fcf3ce44SJohn Forte 	char	*p;
133*fcf3ce44SJohn Forte 	char	s[256];
134*fcf3ce44SJohn Forte 
135*fcf3ce44SJohn Forte 	assert(format == HEX_ONLY || format == HEX_ASCII);
136*fcf3ce44SJohn Forte 
137*fcf3ce44SJohn Forte 	(void) strcpy(s, hdr);
138*fcf3ce44SJohn Forte 	for (p = s; *p; p++) {
139*fcf3ce44SJohn Forte 		*p = ' ';
140*fcf3ce44SJohn Forte 	}
141*fcf3ce44SJohn Forte 
142*fcf3ce44SJohn Forte 	p = hdr;
143*fcf3ce44SJohn Forte 	while (nbytes > 0) {
144*fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
145*fcf3ce44SJohn Forte 			"%s", p);
146*fcf3ce44SJohn Forte 		p = s;
147*fcf3ce44SJohn Forte 		n = MIN(nbytes, BYTES_PER_LINE);
148*fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
149*fcf3ce44SJohn Forte 			(void) sprintf(&msg_string[strlen(msg_string)],
150*fcf3ce44SJohn Forte 				"%02x ",
151*fcf3ce44SJohn Forte 				src[i] & 0xff);
152*fcf3ce44SJohn Forte 		}
153*fcf3ce44SJohn Forte 		if (format == HEX_ASCII) {
154*fcf3ce44SJohn Forte 			for (i = BYTES_PER_LINE-n; i > 0; i--) {
155*fcf3ce44SJohn Forte 				(void) sprintf(&msg_string[strlen(msg_string)],
156*fcf3ce44SJohn Forte 					"   ");
157*fcf3ce44SJohn Forte 			}
158*fcf3ce44SJohn Forte 			(void) sprintf(&msg_string[strlen(msg_string)],
159*fcf3ce44SJohn Forte 				"    ");
160*fcf3ce44SJohn Forte 			for (i = 0; i < n; i++) {
161*fcf3ce44SJohn Forte 				(void) sprintf(&msg_string[strlen(msg_string)],
162*fcf3ce44SJohn Forte 					"%c",
163*fcf3ce44SJohn Forte 					isprint(src[i]) ? src[i] : '.');
164*fcf3ce44SJohn Forte 			}
165*fcf3ce44SJohn Forte 		}
166*fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)], "\n");
167*fcf3ce44SJohn Forte 		nbytes -= n;
168*fcf3ce44SJohn Forte 		src += n;
169*fcf3ce44SJohn Forte 	}
170*fcf3ce44SJohn Forte }
171*fcf3ce44SJohn Forte /*
172*fcf3ce44SJohn Forte  * Return a pointer to a string telling us the name of the command.
173*fcf3ce44SJohn Forte  */
174*fcf3ce44SJohn Forte static char *
175*fcf3ce44SJohn Forte scsi_find_command_name(int cmd)
176*fcf3ce44SJohn Forte {
177*fcf3ce44SJohn Forte /*
178*fcf3ce44SJohn Forte  * Names of commands.  Must have SCMD_UNKNOWN at end of list.
179*fcf3ce44SJohn Forte  */
180*fcf3ce44SJohn Forte struct scsi_command_name {
181*fcf3ce44SJohn Forte 	int command;
182*fcf3ce44SJohn Forte 	char	*name;
183*fcf3ce44SJohn Forte } scsi_command_names[29];
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte register struct scsi_command_name *c;
186*fcf3ce44SJohn Forte 
187*fcf3ce44SJohn Forte 	scsi_command_names[0].command = SCMD_TEST_UNIT_READY;
188*fcf3ce44SJohn Forte 	scsi_command_names[0].name = MSGSTR(61, "Test Unit Ready");
189*fcf3ce44SJohn Forte 
190*fcf3ce44SJohn Forte 	scsi_command_names[1].command = SCMD_FORMAT;
191*fcf3ce44SJohn Forte 	scsi_command_names[1].name = MSGSTR(110, "Format");
192*fcf3ce44SJohn Forte 
193*fcf3ce44SJohn Forte 	scsi_command_names[2].command = SCMD_REASSIGN_BLOCK;
194*fcf3ce44SJohn Forte 	scsi_command_names[2].name = MSGSTR(77, "Reassign Block");
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte 	scsi_command_names[3].command = SCMD_READ;
197*fcf3ce44SJohn Forte 	scsi_command_names[3].name = MSGSTR(27, "Read");
198*fcf3ce44SJohn Forte 
199*fcf3ce44SJohn Forte 	scsi_command_names[4].command = SCMD_WRITE;
200*fcf3ce44SJohn Forte 	scsi_command_names[4].name = MSGSTR(54, "Write");
201*fcf3ce44SJohn Forte 
202*fcf3ce44SJohn Forte 	scsi_command_names[5].command = SCMD_READ_G1;
203*fcf3ce44SJohn Forte 	scsi_command_names[5].name = MSGSTR(79, "Read(10 Byte)");
204*fcf3ce44SJohn Forte 
205*fcf3ce44SJohn Forte 	scsi_command_names[6].command = SCMD_WRITE_G1;
206*fcf3ce44SJohn Forte 	scsi_command_names[6].name = MSGSTR(51, "Write(10 Byte)");
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte 	scsi_command_names[7].command = SCMD_MODE_SELECT;
209*fcf3ce44SJohn Forte 	scsi_command_names[7].name = MSGSTR(97, "Mode Select");
210*fcf3ce44SJohn Forte 
211*fcf3ce44SJohn Forte 	scsi_command_names[8].command = SCMD_MODE_SENSE;
212*fcf3ce44SJohn Forte 	scsi_command_names[8].name = MSGSTR(95, "Mode Sense");
213*fcf3ce44SJohn Forte 
214*fcf3ce44SJohn Forte 	scsi_command_names[9].command = SCMD_REASSIGN_BLOCK;
215*fcf3ce44SJohn Forte 	scsi_command_names[9].name = MSGSTR(77, "Reassign Block");
216*fcf3ce44SJohn Forte 
217*fcf3ce44SJohn Forte 	scsi_command_names[10].command = SCMD_REQUEST_SENSE;
218*fcf3ce44SJohn Forte 	scsi_command_names[10].name = MSGSTR(74, "Request Sense");
219*fcf3ce44SJohn Forte 
220*fcf3ce44SJohn Forte 	scsi_command_names[11].command = SCMD_READ_DEFECT_LIST;
221*fcf3ce44SJohn Forte 	scsi_command_names[11].name = MSGSTR(80, "Read Defect List");
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 	scsi_command_names[12].command = SCMD_INQUIRY;
224*fcf3ce44SJohn Forte 	scsi_command_names[12].name = MSGSTR(102, "Inquiry");
225*fcf3ce44SJohn Forte 
226*fcf3ce44SJohn Forte 	scsi_command_names[13].command = SCMD_WRITE_BUFFER;
227*fcf3ce44SJohn Forte 	scsi_command_names[13].name = MSGSTR(53, "Write Buffer");
228*fcf3ce44SJohn Forte 
229*fcf3ce44SJohn Forte 	scsi_command_names[14].command = SCMD_READ_BUFFER;
230*fcf3ce44SJohn Forte 	scsi_command_names[14].name = MSGSTR(82, "Read Buffer");
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte 	scsi_command_names[15].command = SCMD_START_STOP;
233*fcf3ce44SJohn Forte 	scsi_command_names[15].name = MSGSTR(67, "Start/Stop");
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 	scsi_command_names[16].command = SCMD_RESERVE;
236*fcf3ce44SJohn Forte 	scsi_command_names[16].name = MSGSTR(72, "Reserve");
237*fcf3ce44SJohn Forte 
238*fcf3ce44SJohn Forte 	scsi_command_names[17].command = SCMD_RELEASE;
239*fcf3ce44SJohn Forte 	scsi_command_names[17].name = MSGSTR(75, "Release");
240*fcf3ce44SJohn Forte 
241*fcf3ce44SJohn Forte 	scsi_command_names[18].command = SCMD_MODE_SENSE_G1;
242*fcf3ce44SJohn Forte 	scsi_command_names[18].name = MSGSTR(94, "Mode Sense(10 Byte)");
243*fcf3ce44SJohn Forte 
244*fcf3ce44SJohn Forte 	scsi_command_names[19].command = SCMD_MODE_SELECT_G1;
245*fcf3ce44SJohn Forte 	scsi_command_names[19].name = MSGSTR(96, "Mode Select(10 Byte)");
246*fcf3ce44SJohn Forte 
247*fcf3ce44SJohn Forte 	scsi_command_names[20].command = SCMD_READ_CAPACITY;
248*fcf3ce44SJohn Forte 	scsi_command_names[20].name = MSGSTR(81, "Read Capacity");
249*fcf3ce44SJohn Forte 
250*fcf3ce44SJohn Forte 	scsi_command_names[21].command = SCMD_SYNC_CACHE;
251*fcf3ce44SJohn Forte 	scsi_command_names[21].name = MSGSTR(64, "Synchronize Cache");
252*fcf3ce44SJohn Forte 
253*fcf3ce44SJohn Forte 	scsi_command_names[22].command = SCMD_READ_DEFECT_LIST;
254*fcf3ce44SJohn Forte 	scsi_command_names[22].name = MSGSTR(80, "Read Defect List");
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte 	scsi_command_names[23].command = SCMD_GDIAG;
257*fcf3ce44SJohn Forte 	scsi_command_names[23].name = MSGSTR(108, "Get Diagnostic");
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte 	scsi_command_names[24].command = SCMD_SDIAG;
260*fcf3ce44SJohn Forte 	scsi_command_names[24].name = MSGSTR(69, "Set Diagnostic");
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte 	scsi_command_names[25].command = SCMD_PERS_RESERV_IN;
263*fcf3ce44SJohn Forte 	scsi_command_names[25].name = MSGSTR(10500, "Persistent Reserve In");
264*fcf3ce44SJohn Forte 
265*fcf3ce44SJohn Forte 	scsi_command_names[26].command = SCMD_PERS_RESERV_OUT;
266*fcf3ce44SJohn Forte 	scsi_command_names[26].name = MSGSTR(10501, "Persistent Reserve out");
267*fcf3ce44SJohn Forte 
268*fcf3ce44SJohn Forte 	scsi_command_names[27].command = SCMD_LOG_SENSE;
269*fcf3ce44SJohn Forte 	scsi_command_names[27].name = MSGSTR(10502, "Log Sense");
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte 	scsi_command_names[28].command = SCMD_UNKNOWN;
272*fcf3ce44SJohn Forte 	scsi_command_names[28].name = MSGSTR(25, "Unknown");
273*fcf3ce44SJohn Forte 
274*fcf3ce44SJohn Forte 
275*fcf3ce44SJohn Forte 	for (c = scsi_command_names; c->command != SCMD_UNKNOWN; c++)
276*fcf3ce44SJohn Forte 		if (c->command == cmd)
277*fcf3ce44SJohn Forte 			break;
278*fcf3ce44SJohn Forte 	return (c->name);
279*fcf3ce44SJohn Forte }
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 
282*fcf3ce44SJohn Forte /*
283*fcf3ce44SJohn Forte  *	Function to create error message containing
284*fcf3ce44SJohn Forte  *	scsi request sense information
285*fcf3ce44SJohn Forte  */
286*fcf3ce44SJohn Forte 
287*fcf3ce44SJohn Forte static void
288*fcf3ce44SJohn Forte scsi_printerr(struct uscsi_cmd *ucmd, struct scsi_extended_sense *rq,
289*fcf3ce44SJohn Forte 		int rqlen, char msg_string[], char *err_string)
290*fcf3ce44SJohn Forte {
291*fcf3ce44SJohn Forte 	int		blkno;
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte 	switch (rq->es_key) {
294*fcf3ce44SJohn Forte 	case KEY_NO_SENSE:
295*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(91, "No sense error"));
296*fcf3ce44SJohn Forte 		break;
297*fcf3ce44SJohn Forte 	case KEY_RECOVERABLE_ERROR:
298*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(76, "Recoverable error"));
299*fcf3ce44SJohn Forte 		break;
300*fcf3ce44SJohn Forte 	case KEY_NOT_READY:
301*fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
302*fcf3ce44SJohn Forte 			MSGSTR(10503,
303*fcf3ce44SJohn Forte 			"Device Not ready."
304*fcf3ce44SJohn Forte 			" Error: Random Retry Failed: %s\n."),
305*fcf3ce44SJohn Forte 			err_string);
306*fcf3ce44SJohn Forte 		break;
307*fcf3ce44SJohn Forte 	case KEY_MEDIUM_ERROR:
308*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(99, "Medium error"));
309*fcf3ce44SJohn Forte 		break;
310*fcf3ce44SJohn Forte 	case KEY_HARDWARE_ERROR:
311*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(106, "Hardware error"));
312*fcf3ce44SJohn Forte 		break;
313*fcf3ce44SJohn Forte 	case KEY_ILLEGAL_REQUEST:
314*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(103, "Illegal request"));
315*fcf3ce44SJohn Forte 		break;
316*fcf3ce44SJohn Forte 	case KEY_UNIT_ATTENTION:
317*fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
318*fcf3ce44SJohn Forte 			MSGSTR(10504,
319*fcf3ce44SJohn Forte 			"Unit attention."
320*fcf3ce44SJohn Forte 			"Error: Random Retry Failed.\n"));
321*fcf3ce44SJohn Forte 		break;
322*fcf3ce44SJohn Forte 	case KEY_WRITE_PROTECT:
323*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(52, "Write protect error"));
324*fcf3ce44SJohn Forte 		break;
325*fcf3ce44SJohn Forte 	case KEY_BLANK_CHECK:
326*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(131, "Blank check error"));
327*fcf3ce44SJohn Forte 		break;
328*fcf3ce44SJohn Forte 	case KEY_VENDOR_UNIQUE:
329*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(58, "Vendor unique error"));
330*fcf3ce44SJohn Forte 		break;
331*fcf3ce44SJohn Forte 	case KEY_COPY_ABORTED:
332*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(123, "Copy aborted error"));
333*fcf3ce44SJohn Forte 		break;
334*fcf3ce44SJohn Forte 	case KEY_ABORTED_COMMAND:
335*fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
336*fcf3ce44SJohn Forte 			MSGSTR(10505,
337*fcf3ce44SJohn Forte 			"Aborted command."
338*fcf3ce44SJohn Forte 			" Error: Random Retry Failed.\n"));
339*fcf3ce44SJohn Forte 		break;
340*fcf3ce44SJohn Forte 	case KEY_EQUAL:
341*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(117, "Equal error"));
342*fcf3ce44SJohn Forte 		break;
343*fcf3ce44SJohn Forte 	case KEY_VOLUME_OVERFLOW:
344*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(57, "Volume overflow"));
345*fcf3ce44SJohn Forte 		break;
346*fcf3ce44SJohn Forte 	case KEY_MISCOMPARE:
347*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(98, "Miscompare error"));
348*fcf3ce44SJohn Forte 		break;
349*fcf3ce44SJohn Forte 	case KEY_RESERVED:
350*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(10506,
351*fcf3ce44SJohn Forte 			"Reserved value found"));
352*fcf3ce44SJohn Forte 		break;
353*fcf3ce44SJohn Forte 	default:
354*fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(59, "Unknown error"));
355*fcf3ce44SJohn Forte 		break;
356*fcf3ce44SJohn Forte 	}
357*fcf3ce44SJohn Forte 
358*fcf3ce44SJohn Forte 	(void) sprintf(&msg_string[strlen(msg_string)],
359*fcf3ce44SJohn Forte 		MSGSTR(10507, " during: %s"),
360*fcf3ce44SJohn Forte 		scsi_find_command_name(ucmd->uscsi_cdb[0]));
361*fcf3ce44SJohn Forte 
362*fcf3ce44SJohn Forte 	if (rq->es_valid) {
363*fcf3ce44SJohn Forte 		blkno = (rq->es_info_1 << 24) | (rq->es_info_2 << 16) |
364*fcf3ce44SJohn Forte 			(rq->es_info_3 << 8) | rq->es_info_4;
365*fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
366*fcf3ce44SJohn Forte 			MSGSTR(49, ": block %d (0x%x)"), blkno, blkno);
367*fcf3ce44SJohn Forte 	}
368*fcf3ce44SJohn Forte 
369*fcf3ce44SJohn Forte 	(void) sprintf(&msg_string[strlen(msg_string)], "\n");
370*fcf3ce44SJohn Forte 
371*fcf3ce44SJohn Forte 	if (rq->es_add_len >= 6) {
372*fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
373*fcf3ce44SJohn Forte 		MSGSTR(132, "  Additional sense: 0x%x   ASC Qualifier: 0x%x\n"),
374*fcf3ce44SJohn Forte 			rq->es_add_code, rq->es_qual_code);
375*fcf3ce44SJohn Forte 			/*
376*fcf3ce44SJohn Forte 			 * rq->es_add_info[ADD_SENSE_CODE],
377*fcf3ce44SJohn Forte 			 * rq->es_add_info[ADD_SENSE_QUAL_CODE]);
378*fcf3ce44SJohn Forte 			 */
379*fcf3ce44SJohn Forte 	}
380*fcf3ce44SJohn Forte 	if (rq->es_key == KEY_ILLEGAL_REQUEST) {
381*fcf3ce44SJohn Forte 		string_dump(MSGSTR(47, " cmd:   "), (uchar_t *)ucmd,
382*fcf3ce44SJohn Forte 			sizeof (struct uscsi_cmd), HEX_ONLY, msg_string);
383*fcf3ce44SJohn Forte 		string_dump(MSGSTR(48, " cdb:   "),
384*fcf3ce44SJohn Forte 			(uchar_t *)ucmd->uscsi_cdb,
385*fcf3ce44SJohn Forte 			ucmd->uscsi_cdblen, HEX_ONLY, msg_string);
386*fcf3ce44SJohn Forte 	}
387*fcf3ce44SJohn Forte 	string_dump(MSGSTR(43, " sense:  "),
388*fcf3ce44SJohn Forte 		(uchar_t *)rq, 8 + rq->es_add_len, HEX_ONLY,
389*fcf3ce44SJohn Forte 		msg_string);
390*fcf3ce44SJohn Forte 	rqlen = rqlen;	/* not used */
391*fcf3ce44SJohn Forte }
392*fcf3ce44SJohn Forte 
393*fcf3ce44SJohn Forte 
394*fcf3ce44SJohn Forte /*
395*fcf3ce44SJohn Forte  * Execute a command and determine the result.
396*fcf3ce44SJohn Forte  */
397*fcf3ce44SJohn Forte static int
398*fcf3ce44SJohn Forte issue_uscsi_cmd(int file, struct uscsi_cmd *command, int flag)
399*fcf3ce44SJohn Forte {
400*fcf3ce44SJohn Forte struct scsi_extended_sense	*rqbuf;
401*fcf3ce44SJohn Forte int				status, i, retry_cnt = 0, err;
402*fcf3ce44SJohn Forte char				errorMsg[MAXLEN];
403*fcf3ce44SJohn Forte 
404*fcf3ce44SJohn Forte 	/*
405*fcf3ce44SJohn Forte 	 * Set function flags for driver.
406*fcf3ce44SJohn Forte 	 *
407*fcf3ce44SJohn Forte 	 * Set Automatic request sense enable
408*fcf3ce44SJohn Forte 	 *
409*fcf3ce44SJohn Forte 	 */
410*fcf3ce44SJohn Forte 	command->uscsi_flags = USCSI_RQENABLE;
411*fcf3ce44SJohn Forte 	command->uscsi_flags |= flag;
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	/* intialize error message array */
414*fcf3ce44SJohn Forte 	errorMsg[0] = '\0';
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	/* print command for debug */
417*fcf3ce44SJohn Forte 	if (getenv("_LUX_S_DEBUG") != NULL) {
418*fcf3ce44SJohn Forte 		if ((command->uscsi_cdb == NULL) ||
419*fcf3ce44SJohn Forte 			(flag & USCSI_RESET) ||
420*fcf3ce44SJohn Forte 			(flag & USCSI_RESET_ALL)) {
421*fcf3ce44SJohn Forte 			if (flag & USCSI_RESET) {
422*fcf3ce44SJohn Forte 				(void) printf("  Issuing a SCSI Reset.\n");
423*fcf3ce44SJohn Forte 			}
424*fcf3ce44SJohn Forte 			if (flag & USCSI_RESET_ALL) {
425*fcf3ce44SJohn Forte 				(void) printf("  Issuing a SCSI Reset All.\n");
426*fcf3ce44SJohn Forte 			}
427*fcf3ce44SJohn Forte 
428*fcf3ce44SJohn Forte 		} else {
429*fcf3ce44SJohn Forte 			(void) printf("  Issuing the following "
430*fcf3ce44SJohn Forte 				"SCSI command: %s\n",
431*fcf3ce44SJohn Forte 			scsi_find_command_name(command->uscsi_cdb[0]));
432*fcf3ce44SJohn Forte 			(void) printf("	fd=0x%x cdb=", file);
433*fcf3ce44SJohn Forte 			for (i = 0; i < (int)command->uscsi_cdblen; i++) {
434*fcf3ce44SJohn Forte 				(void) printf("%x ", *(command->uscsi_cdb + i));
435*fcf3ce44SJohn Forte 			}
436*fcf3ce44SJohn Forte 			(void) printf("\n\tlen=0x%x bufaddr=0x%x buflen=0x%x"
437*fcf3ce44SJohn Forte 				" flags=0x%x\n",
438*fcf3ce44SJohn Forte 			command->uscsi_cdblen,
439*fcf3ce44SJohn Forte 			command->uscsi_bufaddr,
440*fcf3ce44SJohn Forte 			command->uscsi_buflen, command->uscsi_flags);
441*fcf3ce44SJohn Forte 
442*fcf3ce44SJohn Forte 			if ((command->uscsi_buflen > 0) &&
443*fcf3ce44SJohn Forte 				((flag & USCSI_READ) == 0)) {
444*fcf3ce44SJohn Forte 				(void) dump_hex_data("  Buffer data: ",
445*fcf3ce44SJohn Forte 				(uchar_t *)command->uscsi_bufaddr,
446*fcf3ce44SJohn Forte 				MIN(command->uscsi_buflen, 512), HEX_ASCII);
447*fcf3ce44SJohn Forte 			}
448*fcf3ce44SJohn Forte 		}
449*fcf3ce44SJohn Forte 		(void) fflush(stdout);
450*fcf3ce44SJohn Forte 	}
451*fcf3ce44SJohn Forte 
452*fcf3ce44SJohn Forte 
453*fcf3ce44SJohn Forte 	/*
454*fcf3ce44SJohn Forte 	 * Default command timeout in case command left it 0
455*fcf3ce44SJohn Forte 	 */
456*fcf3ce44SJohn Forte 	if (command->uscsi_timeout == 0) {
457*fcf3ce44SJohn Forte 		command->uscsi_timeout = 60;
458*fcf3ce44SJohn Forte 	}
459*fcf3ce44SJohn Forte 	/*	Issue command - finally */
460*fcf3ce44SJohn Forte 
461*fcf3ce44SJohn Forte retry:
462*fcf3ce44SJohn Forte 	status = ioctl(file, USCSICMD, command);
463*fcf3ce44SJohn Forte 	if (status == 0 && command->uscsi_status == 0) {
464*fcf3ce44SJohn Forte 		if (getenv("_LUX_S_DEBUG") != NULL) {
465*fcf3ce44SJohn Forte 			if ((command->uscsi_buflen > 0) &&
466*fcf3ce44SJohn Forte 				(flag & USCSI_READ)) {
467*fcf3ce44SJohn Forte 				(void) dump_hex_data("\tData read:",
468*fcf3ce44SJohn Forte 				(uchar_t *)command->uscsi_bufaddr,
469*fcf3ce44SJohn Forte 				MIN(command->uscsi_buflen, 512), HEX_ASCII);
470*fcf3ce44SJohn Forte 			}
471*fcf3ce44SJohn Forte 		}
472*fcf3ce44SJohn Forte 		return (status);
473*fcf3ce44SJohn Forte 	}
474*fcf3ce44SJohn Forte 	if ((status != 0) && (command->uscsi_status == 0)) {
475*fcf3ce44SJohn Forte 		if ((getenv("_LUX_S_DEBUG") != NULL) ||
476*fcf3ce44SJohn Forte 			(getenv("_LUX_ER_DEBUG") != NULL)) {
477*fcf3ce44SJohn Forte 			(void) printf("Unexpected USCSICMD ioctl error: %s\n",
478*fcf3ce44SJohn Forte 				strerror(errno));
479*fcf3ce44SJohn Forte 		}
480*fcf3ce44SJohn Forte 		return (status);
481*fcf3ce44SJohn Forte 	}
482*fcf3ce44SJohn Forte 
483*fcf3ce44SJohn Forte 	/*
484*fcf3ce44SJohn Forte 	 * Just a SCSI error, create error message
485*fcf3ce44SJohn Forte 	 * Retry once for Unit Attention,
486*fcf3ce44SJohn Forte 	 * Not Ready, and Aborted Command
487*fcf3ce44SJohn Forte 	 */
488*fcf3ce44SJohn Forte 	if ((command->uscsi_rqbuf != NULL) &&
489*fcf3ce44SJohn Forte 	    (((char)command->uscsi_rqlen - (char)command->uscsi_rqresid) > 0)) {
490*fcf3ce44SJohn Forte 
491*fcf3ce44SJohn Forte 		rqbuf = (struct scsi_extended_sense *)command->uscsi_rqbuf;
492*fcf3ce44SJohn Forte 
493*fcf3ce44SJohn Forte 		switch (rqbuf->es_key) {
494*fcf3ce44SJohn Forte 		case KEY_NOT_READY:
495*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
496*fcf3ce44SJohn Forte 				ER_DPRINTF("Note: Device Not Ready."
497*fcf3ce44SJohn Forte 						" Retrying...\n");
498*fcf3ce44SJohn Forte 
499*fcf3ce44SJohn Forte 				if ((err = wait_random_time()) == 0) {
500*fcf3ce44SJohn Forte 					goto retry;
501*fcf3ce44SJohn Forte 				} else {
502*fcf3ce44SJohn Forte 					return (err);
503*fcf3ce44SJohn Forte 				}
504*fcf3ce44SJohn Forte 			}
505*fcf3ce44SJohn Forte 			break;
506*fcf3ce44SJohn Forte 
507*fcf3ce44SJohn Forte 		case KEY_UNIT_ATTENTION:
508*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
509*fcf3ce44SJohn Forte 				ER_DPRINTF("  cmd():"
510*fcf3ce44SJohn Forte 				" UNIT_ATTENTION: Retrying...\n");
511*fcf3ce44SJohn Forte 
512*fcf3ce44SJohn Forte 				goto retry;
513*fcf3ce44SJohn Forte 			}
514*fcf3ce44SJohn Forte 			break;
515*fcf3ce44SJohn Forte 
516*fcf3ce44SJohn Forte 		case KEY_ABORTED_COMMAND:
517*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
518*fcf3ce44SJohn Forte 				ER_DPRINTF("Note: Command is aborted."
519*fcf3ce44SJohn Forte 				" Retrying...\n");
520*fcf3ce44SJohn Forte 
521*fcf3ce44SJohn Forte 				goto retry;
522*fcf3ce44SJohn Forte 			}
523*fcf3ce44SJohn Forte 			break;
524*fcf3ce44SJohn Forte 		}
525*fcf3ce44SJohn Forte 		if ((getenv("_LUX_S_DEBUG") != NULL) ||
526*fcf3ce44SJohn Forte 			(getenv("_LUX_ER_DEBUG") != NULL)) {
527*fcf3ce44SJohn Forte 			scsi_printerr(command,
528*fcf3ce44SJohn Forte 			(struct scsi_extended_sense *)command->uscsi_rqbuf,
529*fcf3ce44SJohn Forte 			(command->uscsi_rqlen - command->uscsi_rqresid),
530*fcf3ce44SJohn Forte 				errorMsg, strerror(errno));
531*fcf3ce44SJohn Forte 		}
532*fcf3ce44SJohn Forte 
533*fcf3ce44SJohn Forte 	} else {
534*fcf3ce44SJohn Forte 
535*fcf3ce44SJohn Forte 		/*
536*fcf3ce44SJohn Forte 		 * Retry 5 times in case of BUSY, and only
537*fcf3ce44SJohn Forte 		 * once for Reservation-conflict, Command
538*fcf3ce44SJohn Forte 		 * Termination and Queue Full. Wait for
539*fcf3ce44SJohn Forte 		 * random amount of time (between 1/10 - 1/2 secs.)
540*fcf3ce44SJohn Forte 		 * between each retry. This random wait is to avoid
541*fcf3ce44SJohn Forte 		 * the multiple threads being executed at the same time
542*fcf3ce44SJohn Forte 		 * and also the constraint in Photon IB, where the
543*fcf3ce44SJohn Forte 		 * command queue has a depth of one command.
544*fcf3ce44SJohn Forte 		 */
545*fcf3ce44SJohn Forte 		switch ((uchar_t)command->uscsi_status & STATUS_MASK) {
546*fcf3ce44SJohn Forte 		case STATUS_BUSY:
547*fcf3ce44SJohn Forte 			if (retry_cnt++ < 5) {
548*fcf3ce44SJohn Forte 				if ((err = wait_random_time()) == 0) {
549*fcf3ce44SJohn Forte 					R_DPRINTF("  cmd(): No. of retries %d."
550*fcf3ce44SJohn Forte 					" STATUS_BUSY: Retrying...\n",
551*fcf3ce44SJohn Forte 					retry_cnt);
552*fcf3ce44SJohn Forte 					goto retry;
553*fcf3ce44SJohn Forte 
554*fcf3ce44SJohn Forte 				} else {
555*fcf3ce44SJohn Forte 					return (err);
556*fcf3ce44SJohn Forte 				}
557*fcf3ce44SJohn Forte 			}
558*fcf3ce44SJohn Forte 			break;
559*fcf3ce44SJohn Forte 
560*fcf3ce44SJohn Forte 		case STATUS_RESERVATION_CONFLICT:
561*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
562*fcf3ce44SJohn Forte 				if ((err = wait_random_time()) == 0) {
563*fcf3ce44SJohn Forte 					R_DPRINTF("  cmd():"
564*fcf3ce44SJohn Forte 					" RESERVATION_CONFLICT:"
565*fcf3ce44SJohn Forte 					" Retrying...\n");
566*fcf3ce44SJohn Forte 					goto retry;
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 				} else {
569*fcf3ce44SJohn Forte 					return (err);
570*fcf3ce44SJohn Forte 				}
571*fcf3ce44SJohn Forte 			}
572*fcf3ce44SJohn Forte 			break;
573*fcf3ce44SJohn Forte 
574*fcf3ce44SJohn Forte 		case STATUS_TERMINATED:
575*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
576*fcf3ce44SJohn Forte 				R_DPRINTF("Note: Command Terminated."
577*fcf3ce44SJohn Forte 					" Retrying...\n");
578*fcf3ce44SJohn Forte 
579*fcf3ce44SJohn Forte 				if ((err = wait_random_time()) == 0) {
580*fcf3ce44SJohn Forte 					goto retry;
581*fcf3ce44SJohn Forte 				} else {
582*fcf3ce44SJohn Forte 					return (err);
583*fcf3ce44SJohn Forte 				}
584*fcf3ce44SJohn Forte 			}
585*fcf3ce44SJohn Forte 			break;
586*fcf3ce44SJohn Forte 
587*fcf3ce44SJohn Forte 		case STATUS_QFULL:
588*fcf3ce44SJohn Forte 			if (retry_cnt++ < 1) {
589*fcf3ce44SJohn Forte 				R_DPRINTF("Note: Command Queue is full."
590*fcf3ce44SJohn Forte 				" Retrying...\n");
591*fcf3ce44SJohn Forte 
592*fcf3ce44SJohn Forte 				if ((err = wait_random_time()) == 0) {
593*fcf3ce44SJohn Forte 					goto retry;
594*fcf3ce44SJohn Forte 				} else {
595*fcf3ce44SJohn Forte 					return (err);
596*fcf3ce44SJohn Forte 				}
597*fcf3ce44SJohn Forte 			}
598*fcf3ce44SJohn Forte 			break;
599*fcf3ce44SJohn Forte 		}
600*fcf3ce44SJohn Forte 
601*fcf3ce44SJohn Forte 	}
602*fcf3ce44SJohn Forte 	if (((getenv("_LUX_S_DEBUG") != NULL) ||
603*fcf3ce44SJohn Forte 		(getenv("_LUX_ER_DEBUG") != NULL)) &&
604*fcf3ce44SJohn Forte 		(errorMsg[0] != '\0')) {
605*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "  %s\n", errorMsg);
606*fcf3ce44SJohn Forte 	}
607*fcf3ce44SJohn Forte 	return (L_SCSI_ERROR | command->uscsi_status);
608*fcf3ce44SJohn Forte }
609*fcf3ce44SJohn Forte 
610*fcf3ce44SJohn Forte /*
611*fcf3ce44SJohn Forte  *		MODE SENSE USCSI command
612*fcf3ce44SJohn Forte  *
613*fcf3ce44SJohn Forte  *
614*fcf3ce44SJohn Forte  *		pc = page control field
615*fcf3ce44SJohn Forte  *		page_code = Pages to return
616*fcf3ce44SJohn Forte  */
617*fcf3ce44SJohn Forte int
618*fcf3ce44SJohn Forte scsi_mode_sense_cmd(int fd,
619*fcf3ce44SJohn Forte 	uchar_t *buf_ptr,
620*fcf3ce44SJohn Forte 	int buf_len,
621*fcf3ce44SJohn Forte 	uchar_t pc,
622*fcf3ce44SJohn Forte 	uchar_t page_code)
623*fcf3ce44SJohn Forte {
624*fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
625*fcf3ce44SJohn Forte /* 10 byte Mode Select cmd */
626*fcf3ce44SJohn Forte union scsi_cdb	cdb =  {SCMD_MODE_SENSE_G1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
627*fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
628*fcf3ce44SJohn Forte int		status;
629*fcf3ce44SJohn Forte static	int	uscsi_count;
630*fcf3ce44SJohn Forte 
631*fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
632*fcf3ce44SJohn Forte 		return (-1); /* L_INVALID_ARG */
633*fcf3ce44SJohn Forte 	}
634*fcf3ce44SJohn Forte 
635*fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
636*fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
637*fcf3ce44SJohn Forte 	/* Just for me  - a sanity check */
638*fcf3ce44SJohn Forte 	if ((page_code > MODEPAGE_ALLPAGES) || (pc > 3) ||
639*fcf3ce44SJohn Forte 		(buf_len > MAX_MODE_SENSE_LEN)) {
640*fcf3ce44SJohn Forte 		return (-1); /* L_ILLEGAL_MODE_SENSE_PAGE */
641*fcf3ce44SJohn Forte 	}
642*fcf3ce44SJohn Forte 	cdb.g1_addr3 = (pc << 6) + page_code;
643*fcf3ce44SJohn Forte 	cdb.g1_count1 = buf_len>>8;
644*fcf3ce44SJohn Forte 	cdb.g1_count0 = buf_len & 0xff;
645*fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
646*fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
647*fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
648*fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
649*fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
650*fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
651*fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
652*fcf3ce44SJohn Forte 
653*fcf3ce44SJohn Forte 	status = issue_uscsi_cmd(fd, &ucmd, USCSI_READ);
654*fcf3ce44SJohn Forte 	/* Bytes actually transfered */
655*fcf3ce44SJohn Forte 	if (status == 0) {
656*fcf3ce44SJohn Forte 		uscsi_count = buf_len - ucmd.uscsi_resid;
657*fcf3ce44SJohn Forte 		S_DPRINTF("  Number of bytes read on "
658*fcf3ce44SJohn Forte 		"Mode Sense 0x%x\n", uscsi_count);
659*fcf3ce44SJohn Forte 		if (getenv("_LUX_D_DEBUG") != NULL) {
660*fcf3ce44SJohn Forte 		    (void) dump_hex_data("  Mode Sense data: ", buf_ptr,
661*fcf3ce44SJohn Forte 		    uscsi_count, HEX_ASCII);
662*fcf3ce44SJohn Forte 		}
663*fcf3ce44SJohn Forte 	}
664*fcf3ce44SJohn Forte 	return (status);
665*fcf3ce44SJohn Forte }
666*fcf3ce44SJohn Forte 
667*fcf3ce44SJohn Forte int
668*fcf3ce44SJohn Forte scsi_release(char *path)
669*fcf3ce44SJohn Forte {
670*fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
671*fcf3ce44SJohn Forte union scsi_cdb		cdb = {SCMD_RELEASE, 0, 0, 0, 0, 0};
672*fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
673*fcf3ce44SJohn Forte int	fd, status;
674*fcf3ce44SJohn Forte 
675*fcf3ce44SJohn Forte 	P_DPRINTF("  scsi_release: Release: Path %s\n", path);
676*fcf3ce44SJohn Forte 	if ((fd = open(path, O_NDELAY | O_RDONLY)) == -1)
677*fcf3ce44SJohn Forte 	    return (1);
678*fcf3ce44SJohn Forte 
679*fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
680*fcf3ce44SJohn Forte 
681*fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
682*fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
683*fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
684*fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
685*fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
686*fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
687*fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
688*fcf3ce44SJohn Forte 	status = (issue_uscsi_cmd(fd, &ucmd, 0));
689*fcf3ce44SJohn Forte 
690*fcf3ce44SJohn Forte 	(void) close(fd);
691*fcf3ce44SJohn Forte 	return (status);
692*fcf3ce44SJohn Forte }
693*fcf3ce44SJohn Forte 
694*fcf3ce44SJohn Forte int
695*fcf3ce44SJohn Forte scsi_reserve(char *path)
696*fcf3ce44SJohn Forte {
697*fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
698*fcf3ce44SJohn Forte union scsi_cdb	cdb = {SCMD_RESERVE, 0, 0, 0, 0, 0};
699*fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
700*fcf3ce44SJohn Forte int	fd, status;
701*fcf3ce44SJohn Forte 
702*fcf3ce44SJohn Forte 	P_DPRINTF("  scsi_reserve: Reserve: Path %s\n", path);
703*fcf3ce44SJohn Forte 	if ((fd = open(path, O_NDELAY | O_RDONLY)) == -1)
704*fcf3ce44SJohn Forte 	    return (1);
705*fcf3ce44SJohn Forte 
706*fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
707*fcf3ce44SJohn Forte 
708*fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
709*fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
710*fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
711*fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
712*fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
713*fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
714*fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
715*fcf3ce44SJohn Forte 	status = (issue_uscsi_cmd(fd, &ucmd, 0));
716*fcf3ce44SJohn Forte 
717*fcf3ce44SJohn Forte 	(void) close(fd);
718*fcf3ce44SJohn Forte 	return (status);
719*fcf3ce44SJohn Forte }
720*fcf3ce44SJohn Forte 
721*fcf3ce44SJohn Forte /*
722*fcf3ce44SJohn Forte  * Print out fabric dev dtype
723*fcf3ce44SJohn Forte  */
724*fcf3ce44SJohn Forte void
725*fcf3ce44SJohn Forte print_fabric_dtype_prop(uchar_t *hba_port_wwn, uchar_t *port_wwn,
726*fcf3ce44SJohn Forte 	uchar_t dtype_prop)
727*fcf3ce44SJohn Forte {
728*fcf3ce44SJohn Forte 	if ((dtype_prop & DTYPE_MASK) < 0x10) {
729*fcf3ce44SJohn Forte 		(void) fprintf(stdout, " 0x%-2x (%s)\n",
730*fcf3ce44SJohn Forte 		(dtype_prop & DTYPE_MASK), dtype[(dtype_prop & DTYPE_MASK)]);
731*fcf3ce44SJohn Forte 	} else if ((dtype_prop & DTYPE_MASK) < 0x1f) {
732*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
733*fcf3ce44SJohn Forte 		MSGSTR(2096, " 0x%-2x (Reserved)\n"),
734*fcf3ce44SJohn Forte 		(dtype_prop & DTYPE_MASK));
735*fcf3ce44SJohn Forte 	} else {
736*fcf3ce44SJohn Forte 		/* Check to see if this is the HBA */
737*fcf3ce44SJohn Forte 		if (wwnConversion(hba_port_wwn) != wwnConversion(port_wwn)) {
738*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(2097,
739*fcf3ce44SJohn Forte 			" 0x%-2x (Unknown Type)\n"), (dtype_prop & DTYPE_MASK));
740*fcf3ce44SJohn Forte 		} else {
741*fcf3ce44SJohn Forte 			/* MATCH */
742*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(2241,
743*fcf3ce44SJohn Forte 			" 0x%-2x (Unknown Type,Host Bus Adapter)\n"),
744*fcf3ce44SJohn Forte 			(dtype_prop & DTYPE_MASK));
745*fcf3ce44SJohn Forte 		}
746*fcf3ce44SJohn Forte 	}
747*fcf3ce44SJohn Forte }
748*fcf3ce44SJohn Forte 
749*fcf3ce44SJohn Forte 
750*fcf3ce44SJohn Forte void
751*fcf3ce44SJohn Forte print_inq_data(char *arg_path, char *path, L_inquiry inq, uchar_t *serial,
752*fcf3ce44SJohn Forte     size_t serial_len)
753*fcf3ce44SJohn Forte {
754*fcf3ce44SJohn Forte char	**p;
755*fcf3ce44SJohn Forte uchar_t	*v_parm;
756*fcf3ce44SJohn Forte int	scsi_3, length;
757*fcf3ce44SJohn Forte char	byte_number[MAXNAMELEN];
758*fcf3ce44SJohn Forte static	char *scsi_inquiry_labels_2[21];
759*fcf3ce44SJohn Forte static	char *scsi_inquiry_labels_3[22];
760*fcf3ce44SJohn Forte static	char	*ansi_version[4];
761*fcf3ce44SJohn Forte 	/*
762*fcf3ce44SJohn Forte 	 * Intialize scsi_inquiry_labels_2 with i18n strings
763*fcf3ce44SJohn Forte 	 */
764*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[0] = MSGSTR(138, "Vendor:                     ");
765*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[1] = MSGSTR(149, "Product:                    ");
766*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[2] = MSGSTR(139, "Revision:                   ");
767*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[3] = MSGSTR(143, "Firmware Revision           ");
768*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[4] = MSGSTR(144, "Serial Number               ");
769*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[5] = MSGSTR(140, "Device type:                ");
770*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[6] = MSGSTR(145, "Removable media:            ");
771*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[7] = MSGSTR(146, "ISO version:                ");
772*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[8] = MSGSTR(147, "ECMA version:               ");
773*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[9] = MSGSTR(148, "ANSI version:               ");
774*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[10] =
775*fcf3ce44SJohn Forte 		MSGSTR(2168, "Async event notification:   ");
776*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[11] =
777*fcf3ce44SJohn Forte 		MSGSTR(2169, "Terminate i/o process msg:  ");
778*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[12] = MSGSTR(150, "Response data format:       ");
779*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[13] = MSGSTR(151, "Additional length:          ");
780*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[14] = MSGSTR(152, "Relative addressing:        ");
781*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[15] =
782*fcf3ce44SJohn Forte 		MSGSTR(2170, "32 bit transfers:           ");
783*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[16] =
784*fcf3ce44SJohn Forte 		MSGSTR(2171, "16 bit transfers:           ");
785*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[17] =
786*fcf3ce44SJohn Forte 		MSGSTR(2172, "Synchronous transfers:      ");
787*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[18] = MSGSTR(153, "Linked commands:            ");
788*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[19] = MSGSTR(154, "Command queueing:           ");
789*fcf3ce44SJohn Forte 	scsi_inquiry_labels_2[20] =
790*fcf3ce44SJohn Forte 		MSGSTR(2173, "Soft reset option:          ");
791*fcf3ce44SJohn Forte 
792*fcf3ce44SJohn Forte 	/*
793*fcf3ce44SJohn Forte 	 * Intialize scsi_inquiry_labels_3 with i18n strings
794*fcf3ce44SJohn Forte 	 */
795*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[0] = MSGSTR(138, "Vendor:                     ");
796*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[1] = MSGSTR(149, "Product:                    ");
797*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[2] = MSGSTR(139, "Revision:                   ");
798*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[3] = MSGSTR(143, "Firmware Revision           ");
799*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[4] = MSGSTR(144, "Serial Number               ");
800*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[5] = MSGSTR(140, "Device type:                ");
801*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[6] = MSGSTR(145, "Removable media:            ");
802*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[7] = MSGSTR(2174, "Medium Changer Element:     ");
803*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[8] = MSGSTR(146, "ISO version:                ");
804*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[9] = MSGSTR(147, "ECMA version:               ");
805*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[10] = MSGSTR(148, "ANSI version:               ");
806*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[11] =
807*fcf3ce44SJohn Forte 		MSGSTR(2175, "Async event reporting:      ");
808*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[12] =
809*fcf3ce44SJohn Forte 		MSGSTR(2176, "Terminate task:             ");
810*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[13] =
811*fcf3ce44SJohn Forte 		MSGSTR(2177, "Normal ACA Supported:       ");
812*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[14] = MSGSTR(150, "Response data format:       ");
813*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[15] = MSGSTR(151, "Additional length:          ");
814*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[16] =
815*fcf3ce44SJohn Forte 		MSGSTR(2178, "Cmd received on port:       ");
816*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[17] =
817*fcf3ce44SJohn Forte 		MSGSTR(2179, "SIP Bits:                   ");
818*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[18] = MSGSTR(152, "Relative addressing:        ");
819*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[19] = MSGSTR(153, "Linked commands:            ");
820*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[20] =
821*fcf3ce44SJohn Forte 		MSGSTR(2180, "Transfer Disable:           ");
822*fcf3ce44SJohn Forte 	scsi_inquiry_labels_3[21] = MSGSTR(154, "Command queueing:           ");
823*fcf3ce44SJohn Forte 
824*fcf3ce44SJohn Forte 	/*
825*fcf3ce44SJohn Forte 	 * Intialize scsi_inquiry_labels_3 with i18n strings
826*fcf3ce44SJohn Forte 	 */
827*fcf3ce44SJohn Forte 	ansi_version[0] = MSGSTR(2181,
828*fcf3ce44SJohn Forte 		" (Device might or might not comply to an ANSI version)");
829*fcf3ce44SJohn Forte 	ansi_version[1] = MSGSTR(2182,
830*fcf3ce44SJohn Forte 		" (This code is reserved for historical uses)");
831*fcf3ce44SJohn Forte 	ansi_version[2] = MSGSTR(2183,
832*fcf3ce44SJohn Forte 		" (Device complies to ANSI X3.131-1994 (SCSI-2))");
833*fcf3ce44SJohn Forte 	ansi_version[3] = MSGSTR(2184,
834*fcf3ce44SJohn Forte 		" (Device complies to SCSI-3)");
835*fcf3ce44SJohn Forte 
836*fcf3ce44SJohn Forte 	    /* print inquiry information */
837*fcf3ce44SJohn Forte 
838*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, MSGSTR(2185, "\nINQUIRY:\n"));
839*fcf3ce44SJohn Forte 		/*
840*fcf3ce44SJohn Forte 		 * arg_path is the path sent to luxadm by the user.  if arg_path
841*fcf3ce44SJohn Forte 		 * is a /devices path, then we do not need to print out physical
842*fcf3ce44SJohn Forte 		 * path info
843*fcf3ce44SJohn Forte 		 */
844*fcf3ce44SJohn Forte 	    if (strcmp(arg_path, path) != 0 &&
845*fcf3ce44SJohn Forte 		strstr(arg_path, "/devices/") == NULL) {
846*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "  ");
847*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
848*fcf3ce44SJohn Forte 		MSGSTR(5, "Physical Path:"));
849*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n  %s\n", path);
850*fcf3ce44SJohn Forte 	    }
851*fcf3ce44SJohn Forte 	    if (inq.inq_ansi < 3) {
852*fcf3ce44SJohn Forte 		p = scsi_inquiry_labels_2;
853*fcf3ce44SJohn Forte 		scsi_3 = 0;
854*fcf3ce44SJohn Forte 	    } else {
855*fcf3ce44SJohn Forte 		p = scsi_inquiry_labels_3;
856*fcf3ce44SJohn Forte 		scsi_3 = 1;
857*fcf3ce44SJohn Forte 	    }
858*fcf3ce44SJohn Forte 	    if (inq.inq_len < 11) {
859*fcf3ce44SJohn Forte 		p += 1;
860*fcf3ce44SJohn Forte 	    } else {
861*fcf3ce44SJohn Forte 		/* */
862*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
863*fcf3ce44SJohn Forte 		print_chars(inq.inq_vid, sizeof (inq.inq_vid), 0);
864*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
865*fcf3ce44SJohn Forte 	    }
866*fcf3ce44SJohn Forte 	    if (inq.inq_len < 27) {
867*fcf3ce44SJohn Forte 		p += 1;
868*fcf3ce44SJohn Forte 	    } else {
869*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
870*fcf3ce44SJohn Forte 		print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0);
871*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
872*fcf3ce44SJohn Forte 	    }
873*fcf3ce44SJohn Forte 	    if (inq.inq_len < 31) {
874*fcf3ce44SJohn Forte 		p += 1;
875*fcf3ce44SJohn Forte 	    } else {
876*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
877*fcf3ce44SJohn Forte 		print_chars(inq.inq_revision, sizeof (inq.inq_revision), 0);
878*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
879*fcf3ce44SJohn Forte 	    }
880*fcf3ce44SJohn Forte 	    if (inq.inq_len < 39) {
881*fcf3ce44SJohn Forte 		p += 2;
882*fcf3ce44SJohn Forte 	    } else {
883*fcf3ce44SJohn Forte 		/*
884*fcf3ce44SJohn Forte 		 * If Pluto then print
885*fcf3ce44SJohn Forte 		 * firmware rev & serial #.
886*fcf3ce44SJohn Forte 		 */
887*fcf3ce44SJohn Forte 		if (strstr((char *)inq.inq_pid, "SSA") != 0) {
888*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p++);
889*fcf3ce44SJohn Forte 			print_chars(inq.inq_firmware_rev,
890*fcf3ce44SJohn Forte 				sizeof (inq.inq_firmware_rev), 0);
891*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
892*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p++);
893*fcf3ce44SJohn Forte 			print_chars(serial, serial_len, 0);
894*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
895*fcf3ce44SJohn Forte 		} else if ((inq.inq_dtype & DTYPE_MASK) != DTYPE_ESI) {
896*fcf3ce44SJohn Forte 			p++;
897*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p++);
898*fcf3ce44SJohn Forte 			print_chars(serial, serial_len, 0);
899*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
900*fcf3ce44SJohn Forte 		} else {
901*fcf3ce44SJohn Forte 			/* if we miss both the above if's */
902*fcf3ce44SJohn Forte 			p += 2;
903*fcf3ce44SJohn Forte 		}
904*fcf3ce44SJohn Forte 	    }
905*fcf3ce44SJohn Forte 
906*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s0x%x (",
907*fcf3ce44SJohn Forte 			*p++, (inq.inq_dtype & DTYPE_MASK));
908*fcf3ce44SJohn Forte 	    if ((inq.inq_dtype & DTYPE_MASK) < 0x10) {
909*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", dtype[inq.inq_dtype & DTYPE_MASK]);
910*fcf3ce44SJohn Forte 	    } else if ((inq.inq_dtype & DTYPE_MASK) < 0x1f) {
911*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(71, "Reserved"));
912*fcf3ce44SJohn Forte 	    } else {
913*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(2186, "Unknown device"));
914*fcf3ce44SJohn Forte 	    }
915*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, ")\n");
916*fcf3ce44SJohn Forte 
917*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s", *p++);
918*fcf3ce44SJohn Forte 	    if (inq.inq_rmb != NULL) {
919*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
920*fcf3ce44SJohn Forte 	    } else {
921*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(45, "no"));
922*fcf3ce44SJohn Forte 	    }
923*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "\n");
924*fcf3ce44SJohn Forte 
925*fcf3ce44SJohn Forte 	    if (scsi_3) {
926*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
927*fcf3ce44SJohn Forte 		if (inq.inq_mchngr != NULL) {
928*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
929*fcf3ce44SJohn Forte 		} else {
930*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(45, "no"));
931*fcf3ce44SJohn Forte 		}
932*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
933*fcf3ce44SJohn Forte 	    }
934*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_iso);
935*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_ecma);
936*fcf3ce44SJohn Forte 
937*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s%d", *p++, inq.inq_ansi);
938*fcf3ce44SJohn Forte 	    if (inq.inq_ansi < 0x4) {
939*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", ansi_version[inq.inq_ansi]);
940*fcf3ce44SJohn Forte 	    } else
941*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(71, "Reserved"));
942*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "\n");
943*fcf3ce44SJohn Forte 
944*fcf3ce44SJohn Forte 	    if (inq.inq_aenc) {
945*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
946*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
947*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
948*fcf3ce44SJohn Forte 	    } else {
949*fcf3ce44SJohn Forte 		p++;
950*fcf3ce44SJohn Forte 	    }
951*fcf3ce44SJohn Forte 	    if (scsi_3) {
952*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
953*fcf3ce44SJohn Forte 		if (inq.inq_normaca != NULL) {
954*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
955*fcf3ce44SJohn Forte 		} else {
956*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(45, "no"));
957*fcf3ce44SJohn Forte 		}
958*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
959*fcf3ce44SJohn Forte 	    }
960*fcf3ce44SJohn Forte 	    if (inq.inq_trmiop) {
961*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
962*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
963*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
964*fcf3ce44SJohn Forte 	    } else {
965*fcf3ce44SJohn Forte 		p++;
966*fcf3ce44SJohn Forte 	    }
967*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_rdf);
968*fcf3ce44SJohn Forte 	    (void) fprintf(stdout, "%s0x%x\n", *p++, inq.inq_len);
969*fcf3ce44SJohn Forte 	    if (scsi_3) {
970*fcf3ce44SJohn Forte 		if (inq.inq_dual_p) {
971*fcf3ce44SJohn Forte 			if (inq.inq_port != NULL) {
972*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(2187,
973*fcf3ce44SJohn Forte 					"%sa\n"), *p++);
974*fcf3ce44SJohn Forte 			} else {
975*fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(2188,
976*fcf3ce44SJohn Forte 					"%sb\n"), *p++);
977*fcf3ce44SJohn Forte 			}
978*fcf3ce44SJohn Forte 		} else {
979*fcf3ce44SJohn Forte 		    p++;
980*fcf3ce44SJohn Forte 		}
981*fcf3ce44SJohn Forte 	    }
982*fcf3ce44SJohn Forte 	    if (scsi_3) {
983*fcf3ce44SJohn Forte 		if (inq.inq_SIP_1 || inq.ui.inq_3.inq_SIP_2 ||
984*fcf3ce44SJohn Forte 			inq.ui.inq_3.inq_SIP_3) {
985*fcf3ce44SJohn Forte 		    (void) fprintf(stdout, "%s%d, %d, %d\n", *p,
986*fcf3ce44SJohn Forte 			inq.inq_SIP_1, inq.ui.inq_3.inq_SIP_2,
987*fcf3ce44SJohn Forte 			inq.ui.inq_3.inq_SIP_3);
988*fcf3ce44SJohn Forte 		}
989*fcf3ce44SJohn Forte 		p++;
990*fcf3ce44SJohn Forte 
991*fcf3ce44SJohn Forte 	    }
992*fcf3ce44SJohn Forte 
993*fcf3ce44SJohn Forte 	    if (inq.ui.inq_2.inq_2_reladdr) {
994*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p);
995*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
996*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
997*fcf3ce44SJohn Forte 	    }
998*fcf3ce44SJohn Forte 	    p++;
999*fcf3ce44SJohn Forte 
1000*fcf3ce44SJohn Forte 	    if (!scsi_3) {
1001*fcf3ce44SJohn Forte 
1002*fcf3ce44SJohn Forte 		    if (inq.ui.inq_2.inq_wbus32) {
1003*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p);
1004*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
1005*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
1006*fcf3ce44SJohn Forte 		    }
1007*fcf3ce44SJohn Forte 		    p++;
1008*fcf3ce44SJohn Forte 
1009*fcf3ce44SJohn Forte 		    if (inq.ui.inq_2.inq_wbus16) {
1010*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p);
1011*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
1012*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
1013*fcf3ce44SJohn Forte 		    }
1014*fcf3ce44SJohn Forte 		    p++;
1015*fcf3ce44SJohn Forte 
1016*fcf3ce44SJohn Forte 		    if (inq.ui.inq_2.inq_sync) {
1017*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p);
1018*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
1019*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
1020*fcf3ce44SJohn Forte 		    }
1021*fcf3ce44SJohn Forte 		    p++;
1022*fcf3ce44SJohn Forte 
1023*fcf3ce44SJohn Forte 	    }
1024*fcf3ce44SJohn Forte 	    if (inq.ui.inq_2.inq_linked) {
1025*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p);
1026*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
1027*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
1028*fcf3ce44SJohn Forte 	    }
1029*fcf3ce44SJohn Forte 	    p++;
1030*fcf3ce44SJohn Forte 
1031*fcf3ce44SJohn Forte 	    if (scsi_3) {
1032*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p++);
1033*fcf3ce44SJohn Forte 		if (inq.ui.inq_3.inq_trandis != NULL) {
1034*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
1035*fcf3ce44SJohn Forte 		} else {
1036*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(45, "no"));
1037*fcf3ce44SJohn Forte 		}
1038*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
1039*fcf3ce44SJohn Forte 	    }
1040*fcf3ce44SJohn Forte 
1041*fcf3ce44SJohn Forte 	    if (inq.ui.inq_2.inq_cmdque) {
1042*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", *p);
1043*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(40, "yes"));
1044*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
1045*fcf3ce44SJohn Forte 	    }
1046*fcf3ce44SJohn Forte 	    p++;
1047*fcf3ce44SJohn Forte 
1048*fcf3ce44SJohn Forte 	    if (!scsi_3) {
1049*fcf3ce44SJohn Forte 		    if (inq.ui.inq_2.inq_sftre) {
1050*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%s", *p);
1051*fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(40, "yes"));
1052*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "\n");
1053*fcf3ce44SJohn Forte 		    }
1054*fcf3ce44SJohn Forte 		    p++;
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 	    }
1057*fcf3ce44SJohn Forte 
1058*fcf3ce44SJohn Forte 		/*
1059*fcf3ce44SJohn Forte 		 * Now print the vendor-specific data.
1060*fcf3ce44SJohn Forte 		 */
1061*fcf3ce44SJohn Forte 	    v_parm = inq.inq_ven_specific_1;
1062*fcf3ce44SJohn Forte 	    if (inq.inq_len >= 32) {
1063*fcf3ce44SJohn Forte 		length = inq.inq_len - 31;
1064*fcf3ce44SJohn Forte 		if (strstr((char *)inq.inq_pid, "SSA") != 0) {
1065*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(2189,
1066*fcf3ce44SJohn Forte 					"Number of Ports, Targets:   %d,%d\n"),
1067*fcf3ce44SJohn Forte 			inq.inq_ssa_ports, inq.inq_ssa_tgts);
1068*fcf3ce44SJohn Forte 			v_parm += 20;
1069*fcf3ce44SJohn Forte 			length -= 20;
1070*fcf3ce44SJohn Forte 		} else if ((strstr((char *)inq.inq_pid, "SUN") != 0) ||
1071*fcf3ce44SJohn Forte 			(strncmp((char *)inq.inq_vid, "SUN     ",
1072*fcf3ce44SJohn Forte 			sizeof (inq.inq_vid)) == 0)) {
1073*fcf3ce44SJohn Forte 			v_parm += 16;
1074*fcf3ce44SJohn Forte 			length -= 16;
1075*fcf3ce44SJohn Forte 		}
1076*fcf3ce44SJohn Forte 		/*
1077*fcf3ce44SJohn Forte 		 * Do hex Dump of rest of the data.
1078*fcf3ce44SJohn Forte 		 */
1079*fcf3ce44SJohn Forte 		if (length > 0) {
1080*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1081*fcf3ce44SJohn Forte 				MSGSTR(2190,
1082*fcf3ce44SJohn Forte 			"              VENDOR-SPECIFIC PARAMETERS\n"));
1083*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
1084*fcf3ce44SJohn Forte 				MSGSTR(2191,
1085*fcf3ce44SJohn Forte 				"Byte#                  Hex Value            "
1086*fcf3ce44SJohn Forte 				"                 ASCII\n"));
1087*fcf3ce44SJohn Forte 			(void) sprintf(byte_number,
1088*fcf3ce44SJohn Forte 			"%d    ", inq.inq_len - length + 5);
1089*fcf3ce44SJohn Forte 			dump_hex_data(byte_number, v_parm,
1090*fcf3ce44SJohn Forte 				MIN(length, inq.inq_res3 - v_parm), HEX_ASCII);
1091*fcf3ce44SJohn Forte 		}
1092*fcf3ce44SJohn Forte 		/*
1093*fcf3ce44SJohn Forte 		 * Skip reserved bytes 56-95.
1094*fcf3ce44SJohn Forte 		 */
1095*fcf3ce44SJohn Forte 		length -= (inq.inq_box_name - v_parm);
1096*fcf3ce44SJohn Forte 		if (length > 0) {
1097*fcf3ce44SJohn Forte 			(void) sprintf(byte_number, "%d    ",
1098*fcf3ce44SJohn Forte 				inq.inq_len - length + 5);
1099*fcf3ce44SJohn Forte 			dump_hex_data(byte_number, inq.inq_box_name,
1100*fcf3ce44SJohn Forte 				MIN(length, sizeof (inq.inq_box_name) +
1101*fcf3ce44SJohn Forte 				sizeof (inq.inq_avu)), HEX_ASCII);
1102*fcf3ce44SJohn Forte 		}
1103*fcf3ce44SJohn Forte 	    }
1104*fcf3ce44SJohn Forte 	    if (getenv("_LUX_D_DEBUG") != NULL) {
1105*fcf3ce44SJohn Forte 		dump_hex_data("\nComplete Inquiry: ",
1106*fcf3ce44SJohn Forte 			(uchar_t *)&inq,
1107*fcf3ce44SJohn Forte 			MIN(inq.inq_len + 5, sizeof (inq)), HEX_ASCII);
1108*fcf3ce44SJohn Forte 	    }
1109*fcf3ce44SJohn Forte }
1110*fcf3ce44SJohn Forte 
1111*fcf3ce44SJohn Forte /*
1112*fcf3ce44SJohn Forte  * Internal routine to clean up ../'s in paths.
1113*fcf3ce44SJohn Forte  * returns 0 if no "../" are left.
1114*fcf3ce44SJohn Forte  *
1115*fcf3ce44SJohn Forte  * Wouldn't it be nice if there was a standard system library
1116*fcf3ce44SJohn Forte  * routine to do this...?
1117*fcf3ce44SJohn Forte  */
1118*fcf3ce44SJohn Forte static int
1119*fcf3ce44SJohn Forte cleanup_dotdot_path(char *path)
1120*fcf3ce44SJohn Forte {
1121*fcf3ce44SJohn Forte 	char holder[MAXPATHLEN];
1122*fcf3ce44SJohn Forte 	char *dotdot;
1123*fcf3ce44SJohn Forte 	char *previous_slash;
1124*fcf3ce44SJohn Forte 
1125*fcf3ce44SJohn Forte 	/* Find the first "/../" in the string */
1126*fcf3ce44SJohn Forte 	dotdot = strstr(path, "/../");
1127*fcf3ce44SJohn Forte 	if (dotdot == NULL) {
1128*fcf3ce44SJohn Forte 		return (0);
1129*fcf3ce44SJohn Forte 	}
1130*fcf3ce44SJohn Forte 
1131*fcf3ce44SJohn Forte 
1132*fcf3ce44SJohn Forte 	/*
1133*fcf3ce44SJohn Forte 	 * If the [0] character is '/' and "../" immediatly
1134*fcf3ce44SJohn Forte 	 * follows it, then we can strip the ../
1135*fcf3ce44SJohn Forte 	 *
1136*fcf3ce44SJohn Forte 	 *	/../../foo/bar == /foo/bar
1137*fcf3ce44SJohn Forte 	 *
1138*fcf3ce44SJohn Forte 	 */
1139*fcf3ce44SJohn Forte 	if (dotdot == path) {
1140*fcf3ce44SJohn Forte 		strcpy(holder, &path[3]); /* strip "/.." */
1141*fcf3ce44SJohn Forte 		strcpy(path, holder);
1142*fcf3ce44SJohn Forte 		return (1);
1143*fcf3ce44SJohn Forte 	}
1144*fcf3ce44SJohn Forte 
1145*fcf3ce44SJohn Forte 	/*
1146*fcf3ce44SJohn Forte 	 * Now look for the LAST "/" before the "/../"
1147*fcf3ce44SJohn Forte 	 * as this is the parent dir we can get rid of.
1148*fcf3ce44SJohn Forte 	 * We do this by temporarily truncating the string
1149*fcf3ce44SJohn Forte 	 * at the '/' just before "../" using the dotdot pointer.
1150*fcf3ce44SJohn Forte 	 */
1151*fcf3ce44SJohn Forte 	*dotdot = '\0';
1152*fcf3ce44SJohn Forte 	previous_slash = strrchr(path, '/');
1153*fcf3ce44SJohn Forte 	if (previous_slash == NULL) {
1154*fcf3ce44SJohn Forte 		/*
1155*fcf3ce44SJohn Forte 		 * hmm, somethings wrong.  path looks something
1156*fcf3ce44SJohn Forte 		 * like "foo/../bar/" so we can't really deal with it.
1157*fcf3ce44SJohn Forte 		 */
1158*fcf3ce44SJohn Forte 		return (0);
1159*fcf3ce44SJohn Forte 	}
1160*fcf3ce44SJohn Forte 	/*
1161*fcf3ce44SJohn Forte 	 * Now truncate the path just after the previous '/'
1162*fcf3ce44SJohn Forte 	 * and slam everything after the "../" back on
1163*fcf3ce44SJohn Forte 	 */
1164*fcf3ce44SJohn Forte 	*(previous_slash+1) = '\0';
1165*fcf3ce44SJohn Forte 	(void) strcat(path, dotdot+4);
1166*fcf3ce44SJohn Forte 	return (1); /* We may have more "../"s */
1167*fcf3ce44SJohn Forte }
1168*fcf3ce44SJohn Forte 
1169*fcf3ce44SJohn Forte /*
1170*fcf3ce44SJohn Forte  * Follow symbolic links from the logical device name to
1171*fcf3ce44SJohn Forte  * the /devfs physical device name.  To be complete, we
1172*fcf3ce44SJohn Forte  * handle the case of multiple links.  This function
1173*fcf3ce44SJohn Forte  * either returns NULL (no links, or some other error),
1174*fcf3ce44SJohn Forte  * or the physical device name, alloc'ed on the heap.
1175*fcf3ce44SJohn Forte  *
1176*fcf3ce44SJohn Forte  * NOTE: If the path is relative, it will be forced into
1177*fcf3ce44SJohn Forte  * an absolute path by pre-pending the pwd to it.
1178*fcf3ce44SJohn Forte  */
1179*fcf3ce44SJohn Forte char *
1180*fcf3ce44SJohn Forte get_slash_devices_from_osDevName(char *osDevName, int flag)
1181*fcf3ce44SJohn Forte {
1182*fcf3ce44SJohn Forte 	struct stat	stbuf;
1183*fcf3ce44SJohn Forte 	char		source[MAXPATHLEN];
1184*fcf3ce44SJohn Forte 	char		scratch[MAXPATHLEN];
1185*fcf3ce44SJohn Forte 	char		pwd[MAXPATHLEN];
1186*fcf3ce44SJohn Forte 	char		*tmp, *phys_path;
1187*fcf3ce44SJohn Forte 	int		cnt;
1188*fcf3ce44SJohn Forte 	boolean_t	is_lstat_failed = B_TRUE;
1189*fcf3ce44SJohn Forte 
1190*fcf3ce44SJohn Forte 	/* return NULL if path is NULL */
1191*fcf3ce44SJohn Forte 	if (osDevName == NULL) {
1192*fcf3ce44SJohn Forte 		return (NULL);
1193*fcf3ce44SJohn Forte 	}
1194*fcf3ce44SJohn Forte 
1195*fcf3ce44SJohn Forte 	strcpy(source, osDevName);
1196*fcf3ce44SJohn Forte 	for (;;) {
1197*fcf3ce44SJohn Forte 
1198*fcf3ce44SJohn Forte 		/*
1199*fcf3ce44SJohn Forte 		 * First make sure the path is absolute.  If not, make it.
1200*fcf3ce44SJohn Forte 		 * If it's already an absolute path, we have no need
1201*fcf3ce44SJohn Forte 		 * to determine the cwd, so the program should still
1202*fcf3ce44SJohn Forte 		 * function within security-by-obscurity directories.
1203*fcf3ce44SJohn Forte 		 */
1204*fcf3ce44SJohn Forte 		if (source[0] != '/') {
1205*fcf3ce44SJohn Forte 			tmp = getcwd(pwd, MAXPATHLEN);
1206*fcf3ce44SJohn Forte 			if (tmp == NULL) {
1207*fcf3ce44SJohn Forte 				return (NULL);
1208*fcf3ce44SJohn Forte 			}
1209*fcf3ce44SJohn Forte 			/*
1210*fcf3ce44SJohn Forte 			 * Handle special case of "./foo/bar"
1211*fcf3ce44SJohn Forte 			 */
1212*fcf3ce44SJohn Forte 			if (source[0] == '.' && source[1] == '/') {
1213*fcf3ce44SJohn Forte 				strcpy(scratch, source+2);
1214*fcf3ce44SJohn Forte 			} else { /* no "./" so just take everything */
1215*fcf3ce44SJohn Forte 				strcpy(scratch, source);
1216*fcf3ce44SJohn Forte 			}
1217*fcf3ce44SJohn Forte 			strcpy(source, pwd);
1218*fcf3ce44SJohn Forte 			(void) strcat(source, "/");
1219*fcf3ce44SJohn Forte 			(void) strcat(source, scratch);
1220*fcf3ce44SJohn Forte 		}
1221*fcf3ce44SJohn Forte 
1222*fcf3ce44SJohn Forte 		/*
1223*fcf3ce44SJohn Forte 		 * Clean up any "../"s that are in the path
1224*fcf3ce44SJohn Forte 		 */
1225*fcf3ce44SJohn Forte 		while (cleanup_dotdot_path(source));
1226*fcf3ce44SJohn Forte 
1227*fcf3ce44SJohn Forte 		/*
1228*fcf3ce44SJohn Forte 		 * source is now an absolute path to the link we're
1229*fcf3ce44SJohn Forte 		 * concerned with
1230*fcf3ce44SJohn Forte 		 */
1231*fcf3ce44SJohn Forte 		if (flag == NOT_IGNORE_DANGLING_LINK) {
1232*fcf3ce44SJohn Forte 			/*
1233*fcf3ce44SJohn Forte 			 * In order not to ingore dangling links, check
1234*fcf3ce44SJohn Forte 			 * the lstat. If lstat succeeds, return the path
1235*fcf3ce44SJohn Forte 			 * from readlink.
1236*fcf3ce44SJohn Forte 			 * Note: osDevName input with /devices path from
1237*fcf3ce44SJohn Forte 			 * a dangling /dev link doesn't pass lstat so
1238*fcf3ce44SJohn Forte 			 * NULL is returned.
1239*fcf3ce44SJohn Forte 			 */
1240*fcf3ce44SJohn Forte 		    if (stat(source, &stbuf) == -1) {
1241*fcf3ce44SJohn Forte 			if (!is_lstat_failed &&
1242*fcf3ce44SJohn Forte 			    strstr(source, "/devices")) {
1243*fcf3ce44SJohn Forte 				/*
1244*fcf3ce44SJohn Forte 				 * lstat succeeded previously and source
1245*fcf3ce44SJohn Forte 				 * contains "/devices" then it is dangling node.
1246*fcf3ce44SJohn Forte 				 */
1247*fcf3ce44SJohn Forte 			    phys_path = (char *)calloc(1, strlen(source) + 1);
1248*fcf3ce44SJohn Forte 			    if (phys_path != NULL) {
1249*fcf3ce44SJohn Forte 				(void) strncpy(phys_path, source,
1250*fcf3ce44SJohn Forte 				strlen(source) + 1);
1251*fcf3ce44SJohn Forte 			    }
1252*fcf3ce44SJohn Forte 			    return (phys_path);
1253*fcf3ce44SJohn Forte 			} else if (is_lstat_failed) {
1254*fcf3ce44SJohn Forte 			    /* check lstat result. */
1255*fcf3ce44SJohn Forte 			    if (lstat(source, &stbuf) == -1) {
1256*fcf3ce44SJohn Forte 				return (NULL);
1257*fcf3ce44SJohn Forte 			    } else {
1258*fcf3ce44SJohn Forte 				is_lstat_failed = B_FALSE; /* and coninue */
1259*fcf3ce44SJohn Forte 			    }
1260*fcf3ce44SJohn Forte 			} else {
1261*fcf3ce44SJohn Forte 				/*
1262*fcf3ce44SJohn Forte 				 * With algorithm that resolves a link and
1263*fcf3ce44SJohn Forte 				 * then issues readlink(), should not be
1264*fcf3ce44SJohn Forte 				 * reached here.
1265*fcf3ce44SJohn Forte 				 */
1266*fcf3ce44SJohn Forte 			    return (NULL);
1267*fcf3ce44SJohn Forte 			}
1268*fcf3ce44SJohn Forte 		    } else {
1269*fcf3ce44SJohn Forte 			if (lstat(source, &stbuf) == -1) {
1270*fcf3ce44SJohn Forte 			/*
1271*fcf3ce44SJohn Forte 			 * when stat succeeds it is not a dangling node
1272*fcf3ce44SJohn Forte 			 * so it is not a special case.
1273*fcf3ce44SJohn Forte 			 */
1274*fcf3ce44SJohn Forte 			    return (NULL);
1275*fcf3ce44SJohn Forte 			}
1276*fcf3ce44SJohn Forte 		    }
1277*fcf3ce44SJohn Forte 		} else if (flag == STANDARD_DEVNAME_HANDLING) {
1278*fcf3ce44SJohn Forte 			/*
1279*fcf3ce44SJohn Forte 			 * See if there's a real file out there.  If not,
1280*fcf3ce44SJohn Forte 			 * we have a dangling link and we ignore it.
1281*fcf3ce44SJohn Forte 			 */
1282*fcf3ce44SJohn Forte 		    if (stat(source, &stbuf) == -1) {
1283*fcf3ce44SJohn Forte 			return (NULL);
1284*fcf3ce44SJohn Forte 		    }
1285*fcf3ce44SJohn Forte 		    if (lstat(source, &stbuf) == -1) {
1286*fcf3ce44SJohn Forte 			return (NULL);
1287*fcf3ce44SJohn Forte 		    }
1288*fcf3ce44SJohn Forte 		} else {
1289*fcf3ce44SJohn Forte 		    /* invalid flag */
1290*fcf3ce44SJohn Forte 		    return (NULL);
1291*fcf3ce44SJohn Forte 		}
1292*fcf3ce44SJohn Forte 
1293*fcf3ce44SJohn Forte 		/*
1294*fcf3ce44SJohn Forte 		 * If the file is not a link, we're done one
1295*fcf3ce44SJohn Forte 		 * way or the other.  If there were links,
1296*fcf3ce44SJohn Forte 		 * return the full pathname of the resulting
1297*fcf3ce44SJohn Forte 		 * file.
1298*fcf3ce44SJohn Forte 		 *
1299*fcf3ce44SJohn Forte 		 * Note:  All of our temp's are on the stack,
1300*fcf3ce44SJohn Forte 		 * so we have to copy the final result to the heap.
1301*fcf3ce44SJohn Forte 		 */
1302*fcf3ce44SJohn Forte 		if (!S_ISLNK(stbuf.st_mode)) {
1303*fcf3ce44SJohn Forte 			phys_path = (char *)calloc(1, strlen(source) + 1);
1304*fcf3ce44SJohn Forte 			if (phys_path != NULL) {
1305*fcf3ce44SJohn Forte 			    (void) strncpy(phys_path, source,
1306*fcf3ce44SJohn Forte 			    strlen(source) + 1);
1307*fcf3ce44SJohn Forte 			}
1308*fcf3ce44SJohn Forte 			return (phys_path);
1309*fcf3ce44SJohn Forte 		}
1310*fcf3ce44SJohn Forte 		cnt = readlink(source, scratch, sizeof (scratch));
1311*fcf3ce44SJohn Forte 		if (cnt < 0) {
1312*fcf3ce44SJohn Forte 			return (NULL);
1313*fcf3ce44SJohn Forte 		}
1314*fcf3ce44SJohn Forte 		/*
1315*fcf3ce44SJohn Forte 		 * scratch is on the heap, and for some reason readlink
1316*fcf3ce44SJohn Forte 		 * doesn't always terminate things properly so we have
1317*fcf3ce44SJohn Forte 		 * to make certain we're properly terminated
1318*fcf3ce44SJohn Forte 		 */
1319*fcf3ce44SJohn Forte 		scratch[cnt] = '\0';
1320*fcf3ce44SJohn Forte 
1321*fcf3ce44SJohn Forte 		/*
1322*fcf3ce44SJohn Forte 		 * Now check to see if the link is relative.  If so,
1323*fcf3ce44SJohn Forte 		 * then we have to append it to the directory
1324*fcf3ce44SJohn Forte 		 * which the source was in. (This is non trivial)
1325*fcf3ce44SJohn Forte 		 */
1326*fcf3ce44SJohn Forte 		if (scratch[0] != '/') {
1327*fcf3ce44SJohn Forte 			tmp = strrchr(source, '/');
1328*fcf3ce44SJohn Forte 			if (tmp == NULL) { /* Whoa!  Something's hosed! */
1329*fcf3ce44SJohn Forte 				O_DPRINTF("Internal error... corrupt path.\n");
1330*fcf3ce44SJohn Forte 				return (NULL);
1331*fcf3ce44SJohn Forte 			}
1332*fcf3ce44SJohn Forte 			/* Now strip off just the directory path */
1333*fcf3ce44SJohn Forte 			*(tmp+1) = '\0'; /* Keeping the last '/' */
1334*fcf3ce44SJohn Forte 			/* and append the new link */
1335*fcf3ce44SJohn Forte 			(void) strcat(source, scratch);
1336*fcf3ce44SJohn Forte 			/*
1337*fcf3ce44SJohn Forte 			 * Note:  At this point, source should have "../"s
1338*fcf3ce44SJohn Forte 			 * but we'll clean it up in the next pass through
1339*fcf3ce44SJohn Forte 			 * the loop.
1340*fcf3ce44SJohn Forte 			 */
1341*fcf3ce44SJohn Forte 		} else {
1342*fcf3ce44SJohn Forte 			/* It's an absolute link so no worries */
1343*fcf3ce44SJohn Forte 			strcpy(source, scratch);
1344*fcf3ce44SJohn Forte 		}
1345*fcf3ce44SJohn Forte 	}
1346*fcf3ce44SJohn Forte 	/* Never reach here */
1347*fcf3ce44SJohn Forte }
1348*fcf3ce44SJohn Forte 
1349*fcf3ce44SJohn Forte /*
1350*fcf3ce44SJohn Forte  * Input - Space for client_path, phci_path and paddr fields of ioc structure
1351*fcf3ce44SJohn Forte  * need to be allocated by the caller of this routine.
1352*fcf3ce44SJohn Forte  */
1353*fcf3ce44SJohn Forte int
1354*fcf3ce44SJohn Forte get_scsi_vhci_pathinfo(char *dev_path, sv_iocdata_t *ioc, int *path_count)
1355*fcf3ce44SJohn Forte {
1356*fcf3ce44SJohn Forte 	char	*physical_path, *physical_path_s;
1357*fcf3ce44SJohn Forte 	int	retval;
1358*fcf3ce44SJohn Forte 	int	fd;
1359*fcf3ce44SJohn Forte 	int	initial_path_count;
1360*fcf3ce44SJohn Forte 	int	current_path_count;
1361*fcf3ce44SJohn Forte 	int 	i;
1362*fcf3ce44SJohn Forte 	char	*delimiter;
1363*fcf3ce44SJohn Forte 	int	malloc_error = 0;
1364*fcf3ce44SJohn Forte 	int 	prop_buf_size;
1365*fcf3ce44SJohn Forte 	int	pathlist_retry_count = 0;
1366*fcf3ce44SJohn Forte 
1367*fcf3ce44SJohn Forte 	if (strncmp(dev_path, SCSI_VHCI,
1368*fcf3ce44SJohn Forte 			strlen(SCSI_VHCI)) != NULL) {
1369*fcf3ce44SJohn Forte 		if ((physical_path = get_slash_devices_from_osDevName(
1370*fcf3ce44SJohn Forte 			dev_path, STANDARD_DEVNAME_HANDLING)) == NULL) {
1371*fcf3ce44SJohn Forte 			return (L_INVALID_PATH);
1372*fcf3ce44SJohn Forte 		}
1373*fcf3ce44SJohn Forte 		if (strncmp(physical_path, SCSI_VHCI,
1374*fcf3ce44SJohn Forte 				strlen(SCSI_VHCI)) != NULL) {
1375*fcf3ce44SJohn Forte 			free(physical_path);
1376*fcf3ce44SJohn Forte 			return (L_INVALID_PATH);
1377*fcf3ce44SJohn Forte 		}
1378*fcf3ce44SJohn Forte 	} else {
1379*fcf3ce44SJohn Forte 		if ((physical_path = calloc(1, MAXPATHLEN)) == NULL) {
1380*fcf3ce44SJohn Forte 			return (L_MALLOC_FAILED);
1381*fcf3ce44SJohn Forte 		}
1382*fcf3ce44SJohn Forte 		(void) strcpy(physical_path, dev_path);
1383*fcf3ce44SJohn Forte 	}
1384*fcf3ce44SJohn Forte 	physical_path_s = physical_path;
1385*fcf3ce44SJohn Forte 
1386*fcf3ce44SJohn Forte 	/* move beyond "/devices" prefix */
1387*fcf3ce44SJohn Forte 	physical_path += DEV_PREFIX_STRLEN-1;
1388*fcf3ce44SJohn Forte 	/* remove  :c,raw suffix */
1389*fcf3ce44SJohn Forte 	delimiter = strrchr(physical_path, ':');
1390*fcf3ce44SJohn Forte 	/* if we didn't find the ':' fine, else truncate */
1391*fcf3ce44SJohn Forte 	if (delimiter != NULL) {
1392*fcf3ce44SJohn Forte 		*delimiter = NULL;
1393*fcf3ce44SJohn Forte 	}
1394*fcf3ce44SJohn Forte 
1395*fcf3ce44SJohn Forte 	/*
1396*fcf3ce44SJohn Forte 	 * We'll call ioctl SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO
1397*fcf3ce44SJohn Forte 	 * at least twice.  The first time will get the path count
1398*fcf3ce44SJohn Forte 	 * and the size of the ioctl propoerty buffer.  The second
1399*fcf3ce44SJohn Forte 	 * time will get the path_info for each path.
1400*fcf3ce44SJohn Forte 	 *
1401*fcf3ce44SJohn Forte 	 * It's possible that additional paths are added while this
1402*fcf3ce44SJohn Forte 	 * code is running.  If the path count increases between the
1403*fcf3ce44SJohn Forte 	 * 2 ioctl's above, then we'll retry (and assume all is well).
1404*fcf3ce44SJohn Forte 	 */
1405*fcf3ce44SJohn Forte 	(void) strcpy(ioc->client, physical_path);
1406*fcf3ce44SJohn Forte 	ioc->buf_elem = 1;
1407*fcf3ce44SJohn Forte 	ioc->ret_elem = (uint_t *)&(initial_path_count);
1408*fcf3ce44SJohn Forte 	ioc->ret_buf = NULL;
1409*fcf3ce44SJohn Forte 
1410*fcf3ce44SJohn Forte 	/* free physical path */
1411*fcf3ce44SJohn Forte 	free(physical_path_s);
1412*fcf3ce44SJohn Forte 
1413*fcf3ce44SJohn Forte 	/* 0 buf_size asks driver to return actual size needed */
1414*fcf3ce44SJohn Forte 	/* open the ioctl file descriptor */
1415*fcf3ce44SJohn Forte 	if ((fd = open("/devices/scsi_vhci:devctl", O_RDWR)) < 0) {
1416*fcf3ce44SJohn Forte 		return (L_OPEN_PATH_FAIL);
1417*fcf3ce44SJohn Forte 	}
1418*fcf3ce44SJohn Forte 
1419*fcf3ce44SJohn Forte 	retval = ioctl(fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, ioc);
1420*fcf3ce44SJohn Forte 	if (retval != 0) {
1421*fcf3ce44SJohn Forte 		close(fd);
1422*fcf3ce44SJohn Forte 	    return (L_SCSI_VHCI_ERROR);
1423*fcf3ce44SJohn Forte 	}
1424*fcf3ce44SJohn Forte 	prop_buf_size = SV_PROP_MAX_BUF_SIZE;
1425*fcf3ce44SJohn Forte 
1426*fcf3ce44SJohn Forte 
1427*fcf3ce44SJohn Forte 	while (pathlist_retry_count <= RETRY_PATHLIST) {
1428*fcf3ce44SJohn Forte 		ioc->buf_elem = initial_path_count;
1429*fcf3ce44SJohn Forte 		/* Make driver put actual # paths in variable */
1430*fcf3ce44SJohn Forte 		ioc->ret_elem = (uint_t *)&(current_path_count);
1431*fcf3ce44SJohn Forte 
1432*fcf3ce44SJohn Forte 		/*
1433*fcf3ce44SJohn Forte 		 * Allocate space for array of path_info structures.
1434*fcf3ce44SJohn Forte 		 * Allocate enough space for # paths from get_pathcount
1435*fcf3ce44SJohn Forte 		 */
1436*fcf3ce44SJohn Forte 		ioc->ret_buf = (sv_path_info_t *)
1437*fcf3ce44SJohn Forte 				calloc(initial_path_count,
1438*fcf3ce44SJohn Forte 					sizeof (sv_path_info_t));
1439*fcf3ce44SJohn Forte 		if (ioc->ret_buf == NULL) {
1440*fcf3ce44SJohn Forte 			close(fd);
1441*fcf3ce44SJohn Forte 			return (L_MALLOC_FAILED);
1442*fcf3ce44SJohn Forte 		}
1443*fcf3ce44SJohn Forte 
1444*fcf3ce44SJohn Forte 		/*
1445*fcf3ce44SJohn Forte 		 * Allocate space for path properties returned by driver
1446*fcf3ce44SJohn Forte 		 */
1447*fcf3ce44SJohn Forte 		malloc_error = 0;
1448*fcf3ce44SJohn Forte 		for (i = 0; i < initial_path_count; i++) {
1449*fcf3ce44SJohn Forte 			ioc->ret_buf[i].ret_prop.buf_size = prop_buf_size;
1450*fcf3ce44SJohn Forte 			if ((ioc->ret_buf[i].ret_prop.buf =
1451*fcf3ce44SJohn Forte 			    (caddr_t)malloc(prop_buf_size)) == NULL) {
1452*fcf3ce44SJohn Forte 				malloc_error = 1;
1453*fcf3ce44SJohn Forte 				break;
1454*fcf3ce44SJohn Forte 			}
1455*fcf3ce44SJohn Forte 			if ((ioc->ret_buf[i].ret_prop.ret_buf_size =
1456*fcf3ce44SJohn Forte 				(uint_t *)malloc(sizeof (uint_t))) == NULL) {
1457*fcf3ce44SJohn Forte 				malloc_error = 1;
1458*fcf3ce44SJohn Forte 				break;
1459*fcf3ce44SJohn Forte 			}
1460*fcf3ce44SJohn Forte 		}
1461*fcf3ce44SJohn Forte 		if (malloc_error == 1) {
1462*fcf3ce44SJohn Forte 			for (i = 0; i < initial_path_count; i++) {
1463*fcf3ce44SJohn Forte 				free(ioc->ret_buf[i].ret_prop.buf);
1464*fcf3ce44SJohn Forte 				free(ioc->ret_buf[i].ret_prop.ret_buf_size);
1465*fcf3ce44SJohn Forte 			}
1466*fcf3ce44SJohn Forte 			free(ioc->ret_buf);
1467*fcf3ce44SJohn Forte 			close(fd);
1468*fcf3ce44SJohn Forte 			return (L_MALLOC_FAILED);
1469*fcf3ce44SJohn Forte 		}
1470*fcf3ce44SJohn Forte 
1471*fcf3ce44SJohn Forte 		retval = ioctl(fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, ioc);
1472*fcf3ce44SJohn Forte 		if (retval != 0) {
1473*fcf3ce44SJohn Forte 			for (i = 0; i < initial_path_count; i++) {
1474*fcf3ce44SJohn Forte 				free(ioc->ret_buf[i].ret_prop.buf);
1475*fcf3ce44SJohn Forte 				free(ioc->ret_buf[i].ret_prop.ret_buf_size);
1476*fcf3ce44SJohn Forte 			}
1477*fcf3ce44SJohn Forte 			free(ioc->ret_buf);
1478*fcf3ce44SJohn Forte 			close(fd);
1479*fcf3ce44SJohn Forte 			return (L_SCSI_VHCI_ERROR);
1480*fcf3ce44SJohn Forte 		}
1481*fcf3ce44SJohn Forte 		if (initial_path_count < current_path_count) {
1482*fcf3ce44SJohn Forte 			/* then a new path was added */
1483*fcf3ce44SJohn Forte 			pathlist_retry_count++;
1484*fcf3ce44SJohn Forte 			initial_path_count = current_path_count;
1485*fcf3ce44SJohn Forte 		} else {
1486*fcf3ce44SJohn Forte 			break;
1487*fcf3ce44SJohn Forte 		}
1488*fcf3ce44SJohn Forte 	}
1489*fcf3ce44SJohn Forte 	/* we are done with ioctl's, lose the fd */
1490*fcf3ce44SJohn Forte 	close(fd);
1491*fcf3ce44SJohn Forte 
1492*fcf3ce44SJohn Forte 	/*
1493*fcf3ce44SJohn Forte 	 * Compare the length num elements from the ioctl response
1494*fcf3ce44SJohn Forte 	 *   and the caller's request - use smaller value.
1495*fcf3ce44SJohn Forte 	 *
1496*fcf3ce44SJohn Forte 	 * pathlist_p->path_count now has count returned from ioctl.
1497*fcf3ce44SJohn Forte 	 * ioc.buf_elem has the value the caller provided.
1498*fcf3ce44SJohn Forte 	 */
1499*fcf3ce44SJohn Forte 	if (initial_path_count < current_path_count) {
1500*fcf3ce44SJohn Forte 		/* More paths exist than we allocated space for */
1501*fcf3ce44SJohn Forte 		*path_count = initial_path_count;
1502*fcf3ce44SJohn Forte 	} else {
1503*fcf3ce44SJohn Forte 		*path_count = current_path_count;
1504*fcf3ce44SJohn Forte 	}
1505*fcf3ce44SJohn Forte 
1506*fcf3ce44SJohn Forte 	return (0);
1507*fcf3ce44SJohn Forte }
1508*fcf3ce44SJohn Forte 
1509*fcf3ce44SJohn Forte int
1510*fcf3ce44SJohn Forte get_mode_page(char *path, uchar_t **pg_buf)
1511*fcf3ce44SJohn Forte {
1512*fcf3ce44SJohn Forte struct mode_header_g1	*mode_header_ptr;
1513*fcf3ce44SJohn Forte int		status, size, fd;
1514*fcf3ce44SJohn Forte 
1515*fcf3ce44SJohn Forte 	/* open controller */
1516*fcf3ce44SJohn Forte 	if ((fd = open(path, O_NDELAY | O_RDWR)) == -1)
1517*fcf3ce44SJohn Forte 		return (-1); /* L_OPEN_PATH_FAIL */
1518*fcf3ce44SJohn Forte 
1519*fcf3ce44SJohn Forte 	/*
1520*fcf3ce44SJohn Forte 	 * Read the first part of the page to get the page size
1521*fcf3ce44SJohn Forte 	 */
1522*fcf3ce44SJohn Forte 	size = 20;
1523*fcf3ce44SJohn Forte 	if ((*pg_buf = (uchar_t *)calloc(1, size)) == NULL) {
1524*fcf3ce44SJohn Forte 	    (void) close(fd);
1525*fcf3ce44SJohn Forte 	    return (L_MALLOC_FAILED);
1526*fcf3ce44SJohn Forte 	}
1527*fcf3ce44SJohn Forte 	/* read page */
1528*fcf3ce44SJohn Forte 	if (status = scsi_mode_sense_cmd(fd, *pg_buf, size,
1529*fcf3ce44SJohn Forte 	    0, MODEPAGE_ALLPAGES)) {
1530*fcf3ce44SJohn Forte 	    (void) close(fd);
1531*fcf3ce44SJohn Forte 	    (void) free(*pg_buf);
1532*fcf3ce44SJohn Forte 	    return (status);
1533*fcf3ce44SJohn Forte 	}
1534*fcf3ce44SJohn Forte 	/* Now get the size for all pages */
1535*fcf3ce44SJohn Forte 	mode_header_ptr = (struct mode_header_g1 *)(void *)*pg_buf;
1536*fcf3ce44SJohn Forte 	size = ntohs(mode_header_ptr->length) +
1537*fcf3ce44SJohn Forte 		sizeof (mode_header_ptr->length);
1538*fcf3ce44SJohn Forte 	(void) free(*pg_buf);
1539*fcf3ce44SJohn Forte 	if ((*pg_buf = (uchar_t *)calloc(1, size)) == NULL) {
1540*fcf3ce44SJohn Forte 	    (void) close(fd);
1541*fcf3ce44SJohn Forte 	    return (L_MALLOC_FAILED);
1542*fcf3ce44SJohn Forte 	}
1543*fcf3ce44SJohn Forte 	/* read all pages */
1544*fcf3ce44SJohn Forte 	if (status = scsi_mode_sense_cmd(fd, *pg_buf, size,
1545*fcf3ce44SJohn Forte 					0, MODEPAGE_ALLPAGES)) {
1546*fcf3ce44SJohn Forte 	    (void) close(fd);
1547*fcf3ce44SJohn Forte 	    (void) free(*pg_buf);
1548*fcf3ce44SJohn Forte 	    return (status);
1549*fcf3ce44SJohn Forte 	}
1550*fcf3ce44SJohn Forte 	(void) close(fd);
1551*fcf3ce44SJohn Forte 	return (0);
1552*fcf3ce44SJohn Forte }
1553*fcf3ce44SJohn Forte 
1554*fcf3ce44SJohn Forte /*
1555*fcf3ce44SJohn Forte  * Dump a structure in hexadecimal.
1556*fcf3ce44SJohn Forte  */
1557*fcf3ce44SJohn Forte void
1558*fcf3ce44SJohn Forte dump_hex_data(char *hdr, uchar_t *src, int nbytes, int format)
1559*fcf3ce44SJohn Forte {
1560*fcf3ce44SJohn Forte 	int i;
1561*fcf3ce44SJohn Forte 	int n;
1562*fcf3ce44SJohn Forte 	char	*p;
1563*fcf3ce44SJohn Forte 	char	s[256];
1564*fcf3ce44SJohn Forte 
1565*fcf3ce44SJohn Forte 	assert(format == HEX_ONLY || format == HEX_ASCII);
1566*fcf3ce44SJohn Forte 
1567*fcf3ce44SJohn Forte 	(void) strcpy(s, hdr);
1568*fcf3ce44SJohn Forte 	for (p = s; *p; p++) {
1569*fcf3ce44SJohn Forte 		*p = ' ';
1570*fcf3ce44SJohn Forte 	}
1571*fcf3ce44SJohn Forte 
1572*fcf3ce44SJohn Forte 	p = hdr;
1573*fcf3ce44SJohn Forte 	while (nbytes > 0) {
1574*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", p);
1575*fcf3ce44SJohn Forte 		p = s;
1576*fcf3ce44SJohn Forte 		n = MIN(nbytes, BYTES_PER_LINE);
1577*fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
1578*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%02x ", src[i] & 0xff);
1579*fcf3ce44SJohn Forte 		}
1580*fcf3ce44SJohn Forte 		if (format == HEX_ASCII) {
1581*fcf3ce44SJohn Forte 			for (i = BYTES_PER_LINE-n; i > 0; i--) {
1582*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "   ");
1583*fcf3ce44SJohn Forte 			}
1584*fcf3ce44SJohn Forte 			(void) fprintf(stdout, "    ");
1585*fcf3ce44SJohn Forte 			for (i = 0; i < n; i++) {
1586*fcf3ce44SJohn Forte 				(void) fprintf(stdout, "%c",
1587*fcf3ce44SJohn Forte 					isprint(src[i]) ? src[i] : '.');
1588*fcf3ce44SJohn Forte 			}
1589*fcf3ce44SJohn Forte 		}
1590*fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
1591*fcf3ce44SJohn Forte 		nbytes -= n;
1592*fcf3ce44SJohn Forte 		src += n;
1593*fcf3ce44SJohn Forte 	}
1594*fcf3ce44SJohn Forte }
1595