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