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*7ff83669SZhong Wang  * 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 
29fcf3ce44SJohn Forte /*LINTLIBRARY*/
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte /*
32fcf3ce44SJohn Forte  *	This module is part of the Fibre Channel Interface library.
33fcf3ce44SJohn Forte  *
34fcf3ce44SJohn Forte  */
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte /*
37fcf3ce44SJohn Forte  * I18N message number ranges
38fcf3ce44SJohn Forte  *  This file: 10500 - 10999
39fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
40fcf3ce44SJohn Forte  */
41fcf3ce44SJohn Forte 
42fcf3ce44SJohn Forte /*	Includes	*/
43fcf3ce44SJohn Forte #include	<stdlib.h>
44fcf3ce44SJohn Forte #include 	<stdio.h>
45fcf3ce44SJohn Forte #include	<sys/file.h>
46fcf3ce44SJohn Forte #include	<sys/types.h>
47fcf3ce44SJohn Forte #include	<sys/stat.h>
48fcf3ce44SJohn Forte #include	<sys/param.h>
49fcf3ce44SJohn Forte #include	<fcntl.h>
50fcf3ce44SJohn Forte #include	<string.h>
51fcf3ce44SJohn Forte #include	<errno.h>
52fcf3ce44SJohn Forte #include	<assert.h>
53fcf3ce44SJohn Forte #include	<unistd.h>
54fcf3ce44SJohn Forte #include	<sys/types.h>
55fcf3ce44SJohn Forte #include	<sys/param.h>
56fcf3ce44SJohn Forte #include	<sys/dklabel.h>
57fcf3ce44SJohn Forte #include	<sys/autoconf.h>
58fcf3ce44SJohn Forte #include	<sys/utsname.h>
59fcf3ce44SJohn Forte #include 	<sys/ddi.h>		/* for min */
60fcf3ce44SJohn Forte #include	<ctype.h>		/* for isprint */
61fcf3ce44SJohn Forte #include	<sys/scsi/scsi.h>
62fcf3ce44SJohn Forte #include	<dirent.h>		/* for DIR */
63fcf3ce44SJohn Forte #include	<nl_types.h>
64fcf3ce44SJohn Forte #include	<locale.h>
65fcf3ce44SJohn Forte #include	<thread.h>
66fcf3ce44SJohn Forte #include	<synch.h>
67fcf3ce44SJohn Forte #include	<l_common.h>
68fcf3ce44SJohn Forte #include	<stgcom.h>
69fcf3ce44SJohn Forte #include	<l_error.h>
70fcf3ce44SJohn Forte #include	<g_state.h>
71fcf3ce44SJohn Forte #include	<libdevinfo.h>
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte /*	Defines		*/
75fcf3ce44SJohn Forte #define	BYTES_PER_LINE		16	/* # of bytes to dump per line */
76fcf3ce44SJohn Forte #define	SCMD_UNKNOWN		0xff
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte /* Bus strings - for internal use by g_get_path_type() only */
79fcf3ce44SJohn Forte #define	PCI_BUS			1
80fcf3ce44SJohn Forte #define	SBUS			2
81*7ff83669SZhong Wang #define	FCOE			3
82fcf3ce44SJohn Forte 
83fcf3ce44SJohn Forte struct str_type {
84fcf3ce44SJohn Forte 	char *string;
85fcf3ce44SJohn Forte 	uint_t type;
86fcf3ce44SJohn Forte };
87fcf3ce44SJohn Forte 
88fcf3ce44SJohn Forte static struct str_type ValidBusStrings[] = {
89fcf3ce44SJohn Forte 	{"pci@", PCI_BUS},
90fcf3ce44SJohn Forte 	{"sbus@", SBUS},
91*7ff83669SZhong Wang 	{"fcoe", FCOE},
92fcf3ce44SJohn Forte 	{NULL, 0}
93fcf3ce44SJohn Forte };
94fcf3ce44SJohn Forte 
95fcf3ce44SJohn Forte 
96fcf3ce44SJohn Forte /*
97fcf3ce44SJohn Forte  *	Strings below were used before cougar driver(qlc) was proposed.
98fcf3ce44SJohn Forte  *	{"scsi/", FC_PCI_FCA},
99fcf3ce44SJohn Forte  *	{"fibre-channel/", FC_PCI_FCA},
100fcf3ce44SJohn Forte  */
101fcf3ce44SJohn Forte static struct str_type ValidFCAstrings[] = {
102fcf3ce44SJohn Forte 	{"SUNW,ifp@", FC4_PCI_FCA | FC4_IFP_XPORT},
103fcf3ce44SJohn Forte 	{"SUNW,socal@", FC4_SOCAL_FCA},
104fcf3ce44SJohn Forte 	{NULL, 0}
105fcf3ce44SJohn Forte };
106fcf3ce44SJohn Forte 
107fcf3ce44SJohn Forte static struct str_type ValidXportStrings[] = {
108fcf3ce44SJohn Forte 	{"/sf@", FC4_SF_XPORT},
109fcf3ce44SJohn Forte 	{"/fp@", FC_GEN_XPORT},
110fcf3ce44SJohn Forte 	{NULL, 0}
111fcf3ce44SJohn Forte };
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte struct _enclDisk {
114fcf3ce44SJohn Forte 	char *vid;
115fcf3ce44SJohn Forte 	char *pid;
116fcf3ce44SJohn Forte };
117fcf3ce44SJohn Forte 
118fcf3ce44SJohn Forte /*
119fcf3ce44SJohn Forte  * SENA/SUNWGS type enclosure disk table. This table contains vendor IDs and
120fcf3ce44SJohn Forte  * the non-unique portion of the product identifier sufficient for
121fcf3ce44SJohn Forte  * comparison. This table needs to be updated as new drives are supported
122fcf3ce44SJohn Forte  * in the SENA/SUNWGS type enclosures that do not have a corresponding match
123fcf3ce44SJohn Forte  * in this table. Currently, the v880 and v890 are the only shipping products
124fcf3ce44SJohn Forte  * that utilize the SUNWGS type enclosure. SENA is EOL'd. The risk of new
125fcf3ce44SJohn Forte  * devices being added that do not match an entry in this table is small but it
126fcf3ce44SJohn Forte  * does exist.
127fcf3ce44SJohn Forte  */
128fcf3ce44SJohn Forte static struct _enclDisk enclDiskTbl[] = {
129fcf3ce44SJohn Forte 	{"SUN", "SENA"},
130fcf3ce44SJohn Forte 	{"SUN", "SUNWGS"},
131fcf3ce44SJohn Forte 	{"FUJITSU", "MA"},
132fcf3ce44SJohn Forte 	{"HITACHI", "DK"},
133fcf3ce44SJohn Forte 	{"HITACHI", "HU"},
134fcf3ce44SJohn Forte 	{"SEAGATE", "ST"},
135fcf3ce44SJohn Forte 	{NULL, NULL}
136fcf3ce44SJohn Forte };
137fcf3ce44SJohn Forte 
138fcf3ce44SJohn Forte 
139fcf3ce44SJohn Forte /* i18n */
140fcf3ce44SJohn Forte nl_catd		l_catd;
141fcf3ce44SJohn Forte 
142fcf3ce44SJohn Forte 
143fcf3ce44SJohn Forte /*	Internal Functions	*/
144fcf3ce44SJohn Forte static	void	string_dump(char *, uchar_t *, int, int, char msg_string[]);
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte /*
147fcf3ce44SJohn Forte  * Allocate space for and return a pointer to a string
148fcf3ce44SJohn Forte  * on the stack.  If the string is null, create
149fcf3ce44SJohn Forte  * an empty string.
150fcf3ce44SJohn Forte  * Use g_destroy_data() to free when no longer used.
151fcf3ce44SJohn Forte  */
152fcf3ce44SJohn Forte char *
g_alloc_string(char * s)153fcf3ce44SJohn Forte g_alloc_string(char *s)
154fcf3ce44SJohn Forte {
155fcf3ce44SJohn Forte 	char	*ns;
156fcf3ce44SJohn Forte 
157fcf3ce44SJohn Forte 	if (s == (char *)NULL) {
158fcf3ce44SJohn Forte 		ns = (char *)g_zalloc(1);
159fcf3ce44SJohn Forte 	} else {
160fcf3ce44SJohn Forte 		ns = (char *)g_zalloc(strlen(s) + 1);
161fcf3ce44SJohn Forte 		if (ns != NULL) {
162fcf3ce44SJohn Forte 			(void) strncpy(ns, s, (strlen(s) + 1));
163fcf3ce44SJohn Forte 		}
164fcf3ce44SJohn Forte 	}
165fcf3ce44SJohn Forte 	return (ns);
166fcf3ce44SJohn Forte }
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 
169fcf3ce44SJohn Forte /*
170fcf3ce44SJohn Forte  * This routine is a wrapper for free.
171fcf3ce44SJohn Forte  */
172fcf3ce44SJohn Forte void
g_destroy_data(void * data)173fcf3ce44SJohn Forte g_destroy_data(void *data)
174fcf3ce44SJohn Forte {
175fcf3ce44SJohn Forte 	A_DPRINTF("  g_destroy_data: Free\'ed buffer at 0x%x\n",
176fcf3ce44SJohn Forte 		data);
177fcf3ce44SJohn Forte 	free((void *)data);
178fcf3ce44SJohn Forte }
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 
181fcf3ce44SJohn Forte /*
182fcf3ce44SJohn Forte  * Dump a structure in hexadecimal.
183fcf3ce44SJohn Forte  */
184fcf3ce44SJohn Forte void
g_dump(char * hdr,uchar_t * src,int nbytes,int format)185fcf3ce44SJohn Forte g_dump(char *hdr, uchar_t *src, int nbytes, int format)
186fcf3ce44SJohn Forte {
187fcf3ce44SJohn Forte 	int i;
188fcf3ce44SJohn Forte 	int n;
189fcf3ce44SJohn Forte 	char	*p;
190fcf3ce44SJohn Forte 	char	s[256];
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 	assert(format == HEX_ONLY || format == HEX_ASCII);
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte 	(void) strcpy(s, hdr);
195fcf3ce44SJohn Forte 	for (p = s; *p; p++) {
196fcf3ce44SJohn Forte 		*p = ' ';
197fcf3ce44SJohn Forte 	}
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 	p = hdr;
200fcf3ce44SJohn Forte 	while (nbytes > 0) {
201fcf3ce44SJohn Forte 		(void) fprintf(stdout, "%s", p);
202fcf3ce44SJohn Forte 		p = s;
203fcf3ce44SJohn Forte 		n = min(nbytes, BYTES_PER_LINE);
204fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
205fcf3ce44SJohn Forte 			(void) fprintf(stdout, "%02x ", src[i] & 0xff);
206fcf3ce44SJohn Forte 		}
207fcf3ce44SJohn Forte 		if (format == HEX_ASCII) {
208fcf3ce44SJohn Forte 			for (i = BYTES_PER_LINE-n; i > 0; i--) {
209fcf3ce44SJohn Forte 				(void) fprintf(stdout, "   ");
210fcf3ce44SJohn Forte 			}
211fcf3ce44SJohn Forte 			(void) fprintf(stdout, "    ");
212fcf3ce44SJohn Forte 			for (i = 0; i < n; i++) {
213fcf3ce44SJohn Forte 				(void) fprintf(stdout, "%c",
214fcf3ce44SJohn Forte 					isprint(src[i]) ? src[i] : '.');
215fcf3ce44SJohn Forte 			}
216fcf3ce44SJohn Forte 		}
217fcf3ce44SJohn Forte 		(void) fprintf(stdout, "\n");
218fcf3ce44SJohn Forte 		nbytes -= n;
219fcf3ce44SJohn Forte 		src += n;
220fcf3ce44SJohn Forte 	}
221fcf3ce44SJohn Forte }
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte /*
224fcf3ce44SJohn Forte  * Internal routine to clean up ../'s in paths.
225fcf3ce44SJohn Forte  * returns 0 if no "../" are left.
226fcf3ce44SJohn Forte  *
227fcf3ce44SJohn Forte  * Wouldn't it be nice if there was a standard system library
228fcf3ce44SJohn Forte  * routine to do this...?
229fcf3ce44SJohn Forte  */
230fcf3ce44SJohn Forte static int
cleanup_dotdot_path(char * path)231fcf3ce44SJohn Forte cleanup_dotdot_path(char *path)
232fcf3ce44SJohn Forte {
233fcf3ce44SJohn Forte 	char holder[MAXPATHLEN];
234fcf3ce44SJohn Forte 	char *dotdot;
235fcf3ce44SJohn Forte 	char *previous_slash;
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 	/* Find the first "/../" in the string */
238fcf3ce44SJohn Forte 	dotdot = strstr(path, "/../");
239fcf3ce44SJohn Forte 	if (dotdot == NULL) {
240fcf3ce44SJohn Forte 		return (0);
241fcf3ce44SJohn Forte 	}
242fcf3ce44SJohn Forte 
243fcf3ce44SJohn Forte 
244fcf3ce44SJohn Forte 	/*
245fcf3ce44SJohn Forte 	 * If the [0] character is '/' and "../" immediatly
246fcf3ce44SJohn Forte 	 * follows it, then we can strip the ../
247fcf3ce44SJohn Forte 	 *
248fcf3ce44SJohn Forte 	 *	/../../foo/bar == /foo/bar
249fcf3ce44SJohn Forte 	 *
250fcf3ce44SJohn Forte 	 */
251fcf3ce44SJohn Forte 	if (dotdot == path) {
252fcf3ce44SJohn Forte 		strcpy(holder, &path[3]); /* strip "/.." */
253fcf3ce44SJohn Forte 		strcpy(path, holder);
254fcf3ce44SJohn Forte 		return (1);
255fcf3ce44SJohn Forte 	}
256fcf3ce44SJohn Forte 
257fcf3ce44SJohn Forte 	/*
258fcf3ce44SJohn Forte 	 * Now look for the LAST "/" before the "/../"
259fcf3ce44SJohn Forte 	 * as this is the parent dir we can get rid of.
260fcf3ce44SJohn Forte 	 * We do this by temporarily truncating the string
261fcf3ce44SJohn Forte 	 * at the '/' just before "../" using the dotdot pointer.
262fcf3ce44SJohn Forte 	 */
263fcf3ce44SJohn Forte 	*dotdot = '\0';
264fcf3ce44SJohn Forte 	previous_slash = strrchr(path, '/');
265fcf3ce44SJohn Forte 	if (previous_slash == NULL) {
266fcf3ce44SJohn Forte 		/*
267fcf3ce44SJohn Forte 		 * hmm, somethings wrong.  path looks something
268fcf3ce44SJohn Forte 		 * like "foo/../bar/" so we can't really deal with it.
269fcf3ce44SJohn Forte 		 */
270fcf3ce44SJohn Forte 		return (0);
271fcf3ce44SJohn Forte 	}
272fcf3ce44SJohn Forte 	/*
273fcf3ce44SJohn Forte 	 * Now truncate the path just after the previous '/'
274fcf3ce44SJohn Forte 	 * and slam everything after the "../" back on
275fcf3ce44SJohn Forte 	 */
276fcf3ce44SJohn Forte 	*(previous_slash+1) = '\0';
277fcf3ce44SJohn Forte 	strcat(path, dotdot+4);
278fcf3ce44SJohn Forte 	return (1); /* We may have more "../"s */
279fcf3ce44SJohn Forte }
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 
282fcf3ce44SJohn Forte /*
283fcf3ce44SJohn Forte  * Follow symbolic links from the logical device name to
284fcf3ce44SJohn Forte  * the /devfs physical device name.  To be complete, we
285fcf3ce44SJohn Forte  * handle the case of multiple links.  This function
286fcf3ce44SJohn Forte  * either returns NULL (no links, or some other error),
287fcf3ce44SJohn Forte  * or the physical device name, alloc'ed on the heap.
288fcf3ce44SJohn Forte  *
289fcf3ce44SJohn Forte  * NOTE: If the path is relative, it will be forced into
290fcf3ce44SJohn Forte  * an absolute path by pre-pending the pwd to it.
291fcf3ce44SJohn Forte  */
292fcf3ce44SJohn Forte char *
g_get_physical_name_from_link(char * path)293fcf3ce44SJohn Forte g_get_physical_name_from_link(char *path)
294fcf3ce44SJohn Forte {
295fcf3ce44SJohn Forte 	struct stat	stbuf;
296fcf3ce44SJohn Forte 	char		source[MAXPATHLEN];
297fcf3ce44SJohn Forte 	char		scratch[MAXPATHLEN];
298fcf3ce44SJohn Forte 	char		pwd[MAXPATHLEN];
299fcf3ce44SJohn Forte 	char		*tmp;
300fcf3ce44SJohn Forte 	int			cnt;
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 	/* return NULL if path is NULL */
303fcf3ce44SJohn Forte 	if (path == NULL) {
304fcf3ce44SJohn Forte 		return (NULL);
305fcf3ce44SJohn Forte 	}
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte 	strcpy(source, path);
308fcf3ce44SJohn Forte 	for (;;) {
309fcf3ce44SJohn Forte 
310fcf3ce44SJohn Forte 		/*
311fcf3ce44SJohn Forte 		 * First make sure the path is absolute.  If not, make it.
312fcf3ce44SJohn Forte 		 * If it's already an absolute path, we have no need
313fcf3ce44SJohn Forte 		 * to determine the cwd, so the program should still
314fcf3ce44SJohn Forte 		 * function within security-by-obscurity directories.
315fcf3ce44SJohn Forte 		 */
316fcf3ce44SJohn Forte 		if (source[0] != '/') {
317fcf3ce44SJohn Forte 			tmp = getcwd(pwd, MAXPATHLEN);
318fcf3ce44SJohn Forte 			if (tmp == NULL) {
319fcf3ce44SJohn Forte 				O_DPRINTF("getcwd() failed - %s\n",
320fcf3ce44SJohn Forte 					strerror(errno));
321fcf3ce44SJohn Forte 				return (NULL);
322fcf3ce44SJohn Forte 			}
323fcf3ce44SJohn Forte 			/*
324fcf3ce44SJohn Forte 			 * Handle special case of "./foo/bar"
325fcf3ce44SJohn Forte 			 */
326fcf3ce44SJohn Forte 			if (source[0] == '.' && source[1] == '/') {
327fcf3ce44SJohn Forte 				strcpy(scratch, source+2);
328fcf3ce44SJohn Forte 			} else { /* no "./" so just take everything */
329fcf3ce44SJohn Forte 				strcpy(scratch, source);
330fcf3ce44SJohn Forte 			}
331fcf3ce44SJohn Forte 			strcpy(source, pwd);
332fcf3ce44SJohn Forte 			strcat(source, "/");
333fcf3ce44SJohn Forte 			strcat(source, scratch);
334fcf3ce44SJohn Forte 		}
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte 		/*
337fcf3ce44SJohn Forte 		 * Clean up any "../"s that are in the path
338fcf3ce44SJohn Forte 		 */
339fcf3ce44SJohn Forte 		while (cleanup_dotdot_path(source));
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 		/*
342fcf3ce44SJohn Forte 		 * source is now an absolute path to the link we're
343fcf3ce44SJohn Forte 		 * concerned with
344fcf3ce44SJohn Forte 		 *
345fcf3ce44SJohn Forte 		 * See if there's a real file out there.  If not,
346fcf3ce44SJohn Forte 		 * we have a dangling link and we ignore it.
347fcf3ce44SJohn Forte 		 */
348fcf3ce44SJohn Forte 
349fcf3ce44SJohn Forte 		if (stat(source, &stbuf) == -1) {
350fcf3ce44SJohn Forte 			O_DPRINTF("stat() failed for %s- %s\n",
351fcf3ce44SJohn Forte 				source, strerror(errno));
352fcf3ce44SJohn Forte 			return (NULL);
353fcf3ce44SJohn Forte 		}
354fcf3ce44SJohn Forte 		if (lstat(source, &stbuf) == -1) {
355fcf3ce44SJohn Forte 			O_DPRINTF("lstat() failed for - %s\n",
356fcf3ce44SJohn Forte 				source, strerror(errno));
357fcf3ce44SJohn Forte 			return (NULL);
358fcf3ce44SJohn Forte 		}
359fcf3ce44SJohn Forte 		/*
360fcf3ce44SJohn Forte 		 * If the file is not a link, we're done one
361fcf3ce44SJohn Forte 		 * way or the other.  If there were links,
362fcf3ce44SJohn Forte 		 * return the full pathname of the resulting
363fcf3ce44SJohn Forte 		 * file.
364fcf3ce44SJohn Forte 		 *
365fcf3ce44SJohn Forte 		 * Note:  All of our temp's are on the stack,
366fcf3ce44SJohn Forte 		 * so we have to copy the final result to the heap.
367fcf3ce44SJohn Forte 		 */
368fcf3ce44SJohn Forte 		if (!S_ISLNK(stbuf.st_mode)) {
369fcf3ce44SJohn Forte 			return (g_alloc_string(source));
370fcf3ce44SJohn Forte 		}
371fcf3ce44SJohn Forte 		cnt = readlink(source, scratch, sizeof (scratch));
372fcf3ce44SJohn Forte 		if (cnt < 0) {
373fcf3ce44SJohn Forte 			O_DPRINTF("readlink() failed - %s\n",
374fcf3ce44SJohn Forte 				strerror(errno));
375fcf3ce44SJohn Forte 			return (NULL);
376fcf3ce44SJohn Forte 		}
377fcf3ce44SJohn Forte 		/*
378fcf3ce44SJohn Forte 		 * scratch is on the heap, and for some reason readlink
379fcf3ce44SJohn Forte 		 * doesn't always terminate things properly so we have
380fcf3ce44SJohn Forte 		 * to make certain we're properly terminated
381fcf3ce44SJohn Forte 		 */
382fcf3ce44SJohn Forte 		scratch[cnt] = '\0';
383fcf3ce44SJohn Forte 
384fcf3ce44SJohn Forte 		/*
385fcf3ce44SJohn Forte 		 * Now check to see if the link is relative.  If so,
386fcf3ce44SJohn Forte 		 * then we have to append it to the directory
387fcf3ce44SJohn Forte 		 * which the source was in. (This is non trivial)
388fcf3ce44SJohn Forte 		 */
389fcf3ce44SJohn Forte 		if (scratch[0] != '/') {
390fcf3ce44SJohn Forte 			tmp = strrchr(source, '/');
391fcf3ce44SJohn Forte 			if (tmp == NULL) { /* Whoa!  Something's hosed! */
392fcf3ce44SJohn Forte 				O_DPRINTF("Internal error... corrupt path.\n");
393fcf3ce44SJohn Forte 				return (NULL);
394fcf3ce44SJohn Forte 			}
395fcf3ce44SJohn Forte 			/* Now strip off just the directory path */
396fcf3ce44SJohn Forte 			*(tmp+1) = '\0'; /* Keeping the last '/' */
397fcf3ce44SJohn Forte 			/* and append the new link */
398fcf3ce44SJohn Forte 			strcat(source, scratch);
399fcf3ce44SJohn Forte 			/*
400fcf3ce44SJohn Forte 			 * Note:  At this point, source should have "../"s
401fcf3ce44SJohn Forte 			 * but we'll clean it up in the next pass through
402fcf3ce44SJohn Forte 			 * the loop.
403fcf3ce44SJohn Forte 			 */
404fcf3ce44SJohn Forte 		} else {
405fcf3ce44SJohn Forte 			/* It's an absolute link so no worries */
406fcf3ce44SJohn Forte 			strcpy(source, scratch);
407fcf3ce44SJohn Forte 		}
408fcf3ce44SJohn Forte 	}
409fcf3ce44SJohn Forte 	/* Never reach here */
410fcf3ce44SJohn Forte }
411fcf3ce44SJohn Forte 
412fcf3ce44SJohn Forte /*
413fcf3ce44SJohn Forte  * Function for getting physical pathnames
414fcf3ce44SJohn Forte  *
415fcf3ce44SJohn Forte  * This function can handle 3 different inputs.
416fcf3ce44SJohn Forte  *
417fcf3ce44SJohn Forte  * 1) Inputs of the form cN
418fcf3ce44SJohn Forte  *	This requires the program  to search the /dev/rdsk
419fcf3ce44SJohn Forte  *	directory for a device that is conected to the
420fcf3ce44SJohn Forte  *	controller with number 'N' and then getting
421fcf3ce44SJohn Forte  *	the physical pathname of the controller.
422fcf3ce44SJohn Forte  *	The format of the controller pathname is
423fcf3ce44SJohn Forte  *	/devices/.../.../SUNW,soc@x,x/SUNW,pln@xxxx,xxxxxxxx:ctlr
424fcf3ce44SJohn Forte  *	The physical pathname is returned.
425fcf3ce44SJohn Forte  *
426fcf3ce44SJohn Forte  * 2) Inputs of the form /dev/rdsk/cNtNdNsN
427fcf3ce44SJohn Forte  *	These are identified by being a link
428fcf3ce44SJohn Forte  *	The physical path they are linked to is returned.
429fcf3ce44SJohn Forte  *
430fcf3ce44SJohn Forte  * 3) Inputs of the form /devices/...
431fcf3ce44SJohn Forte  *	These are actual physical names.
432fcf3ce44SJohn Forte  *	They are not converted.
433fcf3ce44SJohn Forte  */
434fcf3ce44SJohn Forte char *
g_get_physical_name(char * path)435fcf3ce44SJohn Forte g_get_physical_name(char *path)
436fcf3ce44SJohn Forte {
437fcf3ce44SJohn Forte 	struct stat	stbuf;
438fcf3ce44SJohn Forte 	char		s[MAXPATHLEN];
439fcf3ce44SJohn Forte 	char		namebuf[MAXPATHLEN];
440fcf3ce44SJohn Forte 	char		savedir[MAXPATHLEN];
441fcf3ce44SJohn Forte 	char		*result = NULL;
442fcf3ce44SJohn Forte 	DIR		*dirp;
443fcf3ce44SJohn Forte 	struct dirent	*entp;
444fcf3ce44SJohn Forte 	char		*dev_name, *char_ptr;
445fcf3ce44SJohn Forte 	struct stat	sb;
446fcf3ce44SJohn Forte 	int		found_flag = 0;
447fcf3ce44SJohn Forte 	int		status = 0;
448fcf3ce44SJohn Forte 	int		i;
449fcf3ce44SJohn Forte 
450fcf3ce44SJohn Forte 	/* return invalid path if path NULL */
451fcf3ce44SJohn Forte 	if (path == NULL) {
452fcf3ce44SJohn Forte 		return (NULL);
453fcf3ce44SJohn Forte 	}
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	(void) strcpy(s, path);
456fcf3ce44SJohn Forte 	/*
457fcf3ce44SJohn Forte 	 * See if the form is cN
458fcf3ce44SJohn Forte 	 * Must handle scenaro where there is a file cN in this directory
459fcf3ce44SJohn Forte 	 * Bug ID: 1184633
460fcf3ce44SJohn Forte 	 *
461fcf3ce44SJohn Forte 	 * We could be in the /dev/rdsk directory and the file could be of
462fcf3ce44SJohn Forte 	 * the form cNdNsN (See man disks).
463fcf3ce44SJohn Forte 	 */
464fcf3ce44SJohn Forte 	status = stat(s, &stbuf);
465fcf3ce44SJohn Forte 	if (((status == -1) && (errno == ENOENT)) ||
466fcf3ce44SJohn Forte 	    ((s[0] == 'c') && ((int)strlen(s) > 1) && ((int)strlen(s) < 5))) {
467fcf3ce44SJohn Forte 		/*
468fcf3ce44SJohn Forte 		 * Further qualify cN entry
469fcf3ce44SJohn Forte 		 */
470fcf3ce44SJohn Forte 		if ((s[0] != 'c') || ((int)strlen(s) <= 1) ||
471fcf3ce44SJohn Forte 		((int)strlen(s) >= 5)) {
472fcf3ce44SJohn Forte 			goto exit;
473fcf3ce44SJohn Forte 		}
474fcf3ce44SJohn Forte 		for (i = 1; i < (int)strlen(s); i++) {
475fcf3ce44SJohn Forte 			if ((s[i] < '0') || (s[i] > '9')) {
476fcf3ce44SJohn Forte 				goto exit;
477fcf3ce44SJohn Forte 			}
478fcf3ce44SJohn Forte 		}
479fcf3ce44SJohn Forte 		/*
480fcf3ce44SJohn Forte 		 * path does not point to a file or file is of form cN
481fcf3ce44SJohn Forte 		 */
482fcf3ce44SJohn Forte 		P_DPRINTF("  g_get_physical_name: "
483fcf3ce44SJohn Forte 			"Found entry of the form cN n=%s len=%d\n",
484fcf3ce44SJohn Forte 			&s[1], strlen(s));
485fcf3ce44SJohn Forte 
486fcf3ce44SJohn Forte 		dev_name = g_zalloc(sizeof ("/dev/rdsk"));
487fcf3ce44SJohn Forte 		sprintf((char *)dev_name, "/dev/rdsk");
488fcf3ce44SJohn Forte 
489fcf3ce44SJohn Forte 		if ((dirp = opendir(dev_name)) == NULL) {
490fcf3ce44SJohn Forte 			g_destroy_data(dev_name);
491fcf3ce44SJohn Forte 			goto exit;
492fcf3ce44SJohn Forte 		}
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 		while ((entp = readdir(dirp)) != NULL) {
495fcf3ce44SJohn Forte 		    if (strcmp(entp->d_name, ".") == 0 ||
496fcf3ce44SJohn Forte 			strcmp(entp->d_name, "..") == 0)
497fcf3ce44SJohn Forte 			continue;
498fcf3ce44SJohn Forte 
499fcf3ce44SJohn Forte 		    if (entp->d_name[0] != 'c')
500fcf3ce44SJohn Forte 			/*
501fcf3ce44SJohn Forte 			 * Silently Ignore for now any names
502fcf3ce44SJohn Forte 			 * not stating with c
503fcf3ce44SJohn Forte 			 */
504fcf3ce44SJohn Forte 			continue;
505fcf3ce44SJohn Forte 
506fcf3ce44SJohn Forte 		    sprintf(namebuf, "%s/%s", dev_name, entp->d_name);
507fcf3ce44SJohn Forte 
508fcf3ce44SJohn Forte 		    if ((lstat(namebuf, &sb)) < 0) {
509fcf3ce44SJohn Forte 				L_WARNINGS(MSGSTR(55,
510fcf3ce44SJohn Forte 					"Warning: Cannot stat %s\n"),
511fcf3ce44SJohn Forte 					namebuf);
512fcf3ce44SJohn Forte 			continue;
513fcf3ce44SJohn Forte 		    }
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte 		    if (!S_ISLNK(sb.st_mode)) {
516fcf3ce44SJohn Forte 				L_WARNINGS(MSGSTR(56,
517fcf3ce44SJohn Forte 					"Warning: %s is not a symbolic link\n"),
518fcf3ce44SJohn Forte 					namebuf);
519fcf3ce44SJohn Forte 			continue;
520fcf3ce44SJohn Forte 		    }
521fcf3ce44SJohn Forte 
522fcf3ce44SJohn Forte 		    if (strstr(entp->d_name, s) != NULL) {
523fcf3ce44SJohn Forte 			/*
524fcf3ce44SJohn Forte 			 * found link to device in /devices
525fcf3ce44SJohn Forte 			 *
526fcf3ce44SJohn Forte 			 * Further qualify to be sure I have
527fcf3ce44SJohn Forte 			 * not found entry of the form c10
528fcf3ce44SJohn Forte 			 * when I am searching for c1
529fcf3ce44SJohn Forte 			 */
530fcf3ce44SJohn Forte 			if (atoi(&s[1]) == atoi(&entp->d_name[1])) {
531fcf3ce44SJohn Forte 			    P_DPRINTF("  g_get_physical_name: "
532fcf3ce44SJohn Forte 			    "Found entry in /dev/rdsk matching %s: %s\n",
533fcf3ce44SJohn Forte 				s, entp->d_name);
534fcf3ce44SJohn Forte 				found_flag = 1;
535fcf3ce44SJohn Forte 				break;
536fcf3ce44SJohn Forte 			}
537fcf3ce44SJohn Forte 		    }
538fcf3ce44SJohn Forte 		}
539fcf3ce44SJohn Forte 		closedir(dirp);
540fcf3ce44SJohn Forte 		g_destroy_data(dev_name);
541fcf3ce44SJohn Forte 
542fcf3ce44SJohn Forte 		if (found_flag) {
543fcf3ce44SJohn Forte 		    result = g_get_physical_name_from_link(namebuf);
544fcf3ce44SJohn Forte 		    if (result == NULL) {
545fcf3ce44SJohn Forte 			goto exit;
546fcf3ce44SJohn Forte 		    }
547fcf3ce44SJohn Forte 			/*
548fcf3ce44SJohn Forte 			 * Convert from device name to controller name
549fcf3ce44SJohn Forte 			 */
550fcf3ce44SJohn Forte 		    char_ptr = strrchr(result, '/');
551fcf3ce44SJohn Forte 		    *char_ptr = '\0';   /* Terminate sting  */
552fcf3ce44SJohn Forte 		    (void) strcat(result, CTLR_POSTFIX);
553fcf3ce44SJohn Forte 		}
554fcf3ce44SJohn Forte 		goto exit;
555fcf3ce44SJohn Forte 	}
556fcf3ce44SJohn Forte 	if (status == -1)
557fcf3ce44SJohn Forte 		goto exit;
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	if (lstat(s, &stbuf) == -1) {
560fcf3ce44SJohn Forte 			L_WARNINGS(MSGSTR(134,
561fcf3ce44SJohn Forte 				"%s: lstat() failed - %s\n"),
562fcf3ce44SJohn Forte 				s, strerror(errno));
563fcf3ce44SJohn Forte 		goto exit;
564fcf3ce44SJohn Forte 	}
565fcf3ce44SJohn Forte 	/*
566fcf3ce44SJohn Forte 	 */
567fcf3ce44SJohn Forte 	if (!S_ISLNK(stbuf.st_mode)) {
568fcf3ce44SJohn Forte 		/*
569fcf3ce44SJohn Forte 		 * Path is not a linked file so must be
570fcf3ce44SJohn Forte 		 * a physical path
571fcf3ce44SJohn Forte 		 */
572fcf3ce44SJohn Forte 		if (S_ISCHR(stbuf.st_mode) || S_ISDIR(stbuf.st_mode)) {
573fcf3ce44SJohn Forte 			/* Make sure a full path as that is required. */
574fcf3ce44SJohn Forte 			if (strstr(s, "/devices")) {
575fcf3ce44SJohn Forte 				result = g_alloc_string(s);
576fcf3ce44SJohn Forte 			} else {
577fcf3ce44SJohn Forte 				if (getcwd(savedir,
578fcf3ce44SJohn Forte 					sizeof (savedir)) == NULL) {
579fcf3ce44SJohn Forte 					return (NULL);
580fcf3ce44SJohn Forte 				}
581fcf3ce44SJohn Forte 				/*
582fcf3ce44SJohn Forte 				 * Check for this format:
583fcf3ce44SJohn Forte 				 * ./ssd@0,1:g,raw
584fcf3ce44SJohn Forte 				 */
585fcf3ce44SJohn Forte 				if (s[0] == '.') {
586fcf3ce44SJohn Forte 					strcat(savedir, &s[1]);
587fcf3ce44SJohn Forte 				} else {
588fcf3ce44SJohn Forte 					strcat(savedir, "/");
589fcf3ce44SJohn Forte 					strcat(savedir, s);
590fcf3ce44SJohn Forte 				}
591fcf3ce44SJohn Forte 				result = g_alloc_string(savedir);
592fcf3ce44SJohn Forte 			}
593fcf3ce44SJohn Forte 		}
594fcf3ce44SJohn Forte 	} else {
595fcf3ce44SJohn Forte 		/*
596fcf3ce44SJohn Forte 		 * Entry is linked file
597fcf3ce44SJohn Forte 		 * so follow link to physical name
598fcf3ce44SJohn Forte 		 */
599fcf3ce44SJohn Forte 		result = g_get_physical_name_from_link(path);
600fcf3ce44SJohn Forte 	}
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte exit:
603fcf3ce44SJohn Forte 	return (result);
604fcf3ce44SJohn Forte }
605fcf3ce44SJohn Forte 
606fcf3ce44SJohn Forte /*
607fcf3ce44SJohn Forte  *	Function to open a device
608fcf3ce44SJohn Forte  */
609fcf3ce44SJohn Forte int
g_object_open(char * path,int flag)610fcf3ce44SJohn Forte g_object_open(char *path, int flag)
611fcf3ce44SJohn Forte {
612fcf3ce44SJohn Forte int fd = -1, retry = 0;
613fcf3ce44SJohn Forte 	if (getenv("_LUX_O_DEBUG") != NULL) {
614fcf3ce44SJohn Forte 		(void) printf("  Object_open:%s ", path);
615fcf3ce44SJohn Forte 		if (flag & O_WRONLY) {
616fcf3ce44SJohn Forte 			(void) printf("O_WRONLY,");
617fcf3ce44SJohn Forte 		} else if (flag & O_RDWR) {
618fcf3ce44SJohn Forte 			(void) printf("O_RDWR,");
619fcf3ce44SJohn Forte 		} else {
620fcf3ce44SJohn Forte 			(void) printf("O_RDONLY,");
621fcf3ce44SJohn Forte 		}
622fcf3ce44SJohn Forte 		if (flag & O_NDELAY) {
623fcf3ce44SJohn Forte 			(void) printf("O_NDELAY,");
624fcf3ce44SJohn Forte 		}
625fcf3ce44SJohn Forte 		if (flag & O_APPEND) {
626fcf3ce44SJohn Forte 			(void) printf("O_APPEND,");
627fcf3ce44SJohn Forte 		}
628fcf3ce44SJohn Forte 		if (flag & O_DSYNC) {
629fcf3ce44SJohn Forte 			(void) printf("O_DSYNC,");
630fcf3ce44SJohn Forte 		}
631fcf3ce44SJohn Forte 		if (flag & O_RSYNC) {
632fcf3ce44SJohn Forte 			(void) printf("O_RSYNC,");
633fcf3ce44SJohn Forte 		}
634fcf3ce44SJohn Forte 		if (flag & O_SYNC) {
635fcf3ce44SJohn Forte 			(void) printf("O_SYNC,");
636fcf3ce44SJohn Forte 		}
637fcf3ce44SJohn Forte 		if (flag & O_NOCTTY) {
638fcf3ce44SJohn Forte 			(void) printf("O_NOCTTY,");
639fcf3ce44SJohn Forte 		}
640fcf3ce44SJohn Forte 		if (flag & O_CREAT) {
641fcf3ce44SJohn Forte 			(void) printf("O_CREAT,");
642fcf3ce44SJohn Forte 		}
643fcf3ce44SJohn Forte 		if (flag & O_EXCL) {
644fcf3ce44SJohn Forte 			(void) printf("O_EXCL,");
645fcf3ce44SJohn Forte 		}
646fcf3ce44SJohn Forte 		if (flag & O_TRUNC) {
647fcf3ce44SJohn Forte 			(void) printf("O_TRUNC,");
648fcf3ce44SJohn Forte 		}
649fcf3ce44SJohn Forte 		(void) printf("\n");
650fcf3ce44SJohn Forte 	}
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte 	/* Open retries introduced due to bugid 4473337	*/
653fcf3ce44SJohn Forte 	errno	= 0;
654fcf3ce44SJohn Forte 	fd	= open(path, flag);
655fcf3ce44SJohn Forte 	while (fd < 0 && retry++ < RETRY_OBJECT_OPEN && (
656fcf3ce44SJohn Forte 			errno == EBUSY || errno == EAGAIN)) {
657fcf3ce44SJohn Forte 		O_DPRINTF("  Object_open: Retried:%d %d %s\n",
658fcf3ce44SJohn Forte 			retry, errno, path);
659fcf3ce44SJohn Forte 		(void) usleep(WAIT_OBJECT_OPEN);
660fcf3ce44SJohn Forte 		fd = open(path, flag);
661fcf3ce44SJohn Forte 	}
662fcf3ce44SJohn Forte 	if (fd < 0) {
663fcf3ce44SJohn Forte 		O_DPRINTF("  Object_open: Open failed:%s\n", path);
664fcf3ce44SJohn Forte 	}
665fcf3ce44SJohn Forte 	return (fd);
666fcf3ce44SJohn Forte }
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte /*
670fcf3ce44SJohn Forte  * Return a pointer to a string telling us the name of the command.
671fcf3ce44SJohn Forte  */
672fcf3ce44SJohn Forte char *
g_scsi_find_command_name(int cmd)673fcf3ce44SJohn Forte g_scsi_find_command_name(int cmd)
674fcf3ce44SJohn Forte {
675fcf3ce44SJohn Forte /*
676fcf3ce44SJohn Forte  * Names of commands.  Must have SCMD_UNKNOWN at end of list.
677fcf3ce44SJohn Forte  */
678fcf3ce44SJohn Forte struct scsi_command_name {
679fcf3ce44SJohn Forte 	int command;
680fcf3ce44SJohn Forte 	char	*name;
681fcf3ce44SJohn Forte } scsi_command_names[29];
682fcf3ce44SJohn Forte 
683fcf3ce44SJohn Forte register struct scsi_command_name *c;
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte 	scsi_command_names[0].command = SCMD_TEST_UNIT_READY;
686fcf3ce44SJohn Forte 	scsi_command_names[0].name = MSGSTR(61, "Test Unit Ready");
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 	scsi_command_names[1].command = SCMD_FORMAT;
689fcf3ce44SJohn Forte 	scsi_command_names[1].name = MSGSTR(110, "Format");
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte 	scsi_command_names[2].command = SCMD_REASSIGN_BLOCK;
692fcf3ce44SJohn Forte 	scsi_command_names[2].name = MSGSTR(77, "Reassign Block");
693fcf3ce44SJohn Forte 
694fcf3ce44SJohn Forte 	scsi_command_names[3].command = SCMD_READ;
695fcf3ce44SJohn Forte 	scsi_command_names[3].name = MSGSTR(27, "Read");
696fcf3ce44SJohn Forte 
697fcf3ce44SJohn Forte 	scsi_command_names[4].command = SCMD_WRITE;
698fcf3ce44SJohn Forte 	scsi_command_names[4].name = MSGSTR(54, "Write");
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 	scsi_command_names[5].command = SCMD_READ_G1;
701fcf3ce44SJohn Forte 	scsi_command_names[5].name = MSGSTR(79, "Read(10 Byte)");
702fcf3ce44SJohn Forte 
703fcf3ce44SJohn Forte 	scsi_command_names[6].command = SCMD_WRITE_G1;
704fcf3ce44SJohn Forte 	scsi_command_names[6].name = MSGSTR(51, "Write(10 Byte)");
705fcf3ce44SJohn Forte 
706fcf3ce44SJohn Forte 	scsi_command_names[7].command = SCMD_MODE_SELECT;
707fcf3ce44SJohn Forte 	scsi_command_names[7].name = MSGSTR(97, "Mode Select");
708fcf3ce44SJohn Forte 
709fcf3ce44SJohn Forte 	scsi_command_names[8].command = SCMD_MODE_SENSE;
710fcf3ce44SJohn Forte 	scsi_command_names[8].name = MSGSTR(95, "Mode Sense");
711fcf3ce44SJohn Forte 
712fcf3ce44SJohn Forte 	scsi_command_names[9].command = SCMD_REASSIGN_BLOCK;
713fcf3ce44SJohn Forte 	scsi_command_names[9].name = MSGSTR(77, "Reassign Block");
714fcf3ce44SJohn Forte 
715fcf3ce44SJohn Forte 	scsi_command_names[10].command = SCMD_REQUEST_SENSE;
716fcf3ce44SJohn Forte 	scsi_command_names[10].name = MSGSTR(74, "Request Sense");
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	scsi_command_names[11].command = SCMD_READ_DEFECT_LIST;
719fcf3ce44SJohn Forte 	scsi_command_names[11].name = MSGSTR(80, "Read Defect List");
720fcf3ce44SJohn Forte 
721fcf3ce44SJohn Forte 	scsi_command_names[12].command = SCMD_INQUIRY;
722fcf3ce44SJohn Forte 	scsi_command_names[12].name = MSGSTR(102, "Inquiry");
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	scsi_command_names[13].command = SCMD_WRITE_BUFFER;
725fcf3ce44SJohn Forte 	scsi_command_names[13].name = MSGSTR(53, "Write Buffer");
726fcf3ce44SJohn Forte 
727fcf3ce44SJohn Forte 	scsi_command_names[14].command = SCMD_READ_BUFFER;
728fcf3ce44SJohn Forte 	scsi_command_names[14].name = MSGSTR(82, "Read Buffer");
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 	scsi_command_names[15].command = SCMD_START_STOP;
731fcf3ce44SJohn Forte 	scsi_command_names[15].name = MSGSTR(67, "Start/Stop");
732fcf3ce44SJohn Forte 
733fcf3ce44SJohn Forte 	scsi_command_names[16].command = SCMD_RESERVE;
734fcf3ce44SJohn Forte 	scsi_command_names[16].name = MSGSTR(72, "Reserve");
735fcf3ce44SJohn Forte 
736fcf3ce44SJohn Forte 	scsi_command_names[17].command = SCMD_RELEASE;
737fcf3ce44SJohn Forte 	scsi_command_names[17].name = MSGSTR(75, "Release");
738fcf3ce44SJohn Forte 
739fcf3ce44SJohn Forte 	scsi_command_names[18].command = SCMD_MODE_SENSE_G1;
740fcf3ce44SJohn Forte 	scsi_command_names[18].name = MSGSTR(94, "Mode Sense(10 Byte)");
741fcf3ce44SJohn Forte 
742fcf3ce44SJohn Forte 	scsi_command_names[19].command = SCMD_MODE_SELECT_G1;
743fcf3ce44SJohn Forte 	scsi_command_names[19].name = MSGSTR(96, "Mode Select(10 Byte)");
744fcf3ce44SJohn Forte 
745fcf3ce44SJohn Forte 	scsi_command_names[20].command = SCMD_READ_CAPACITY;
746fcf3ce44SJohn Forte 	scsi_command_names[20].name = MSGSTR(81, "Read Capacity");
747fcf3ce44SJohn Forte 
748fcf3ce44SJohn Forte 	scsi_command_names[21].command = SCMD_SYNC_CACHE;
749fcf3ce44SJohn Forte 	scsi_command_names[21].name = MSGSTR(64, "Synchronize Cache");
750fcf3ce44SJohn Forte 
751fcf3ce44SJohn Forte 	scsi_command_names[22].command = SCMD_READ_DEFECT_LIST;
752fcf3ce44SJohn Forte 	scsi_command_names[22].name = MSGSTR(80, "Read Defect List");
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	scsi_command_names[23].command = SCMD_GDIAG;
755fcf3ce44SJohn Forte 	scsi_command_names[23].name = MSGSTR(108, "Get Diagnostic");
756fcf3ce44SJohn Forte 
757fcf3ce44SJohn Forte 	scsi_command_names[24].command = SCMD_SDIAG;
758fcf3ce44SJohn Forte 	scsi_command_names[24].name = MSGSTR(69, "Set Diagnostic");
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 	scsi_command_names[25].command = SCMD_PERS_RESERV_IN;
761fcf3ce44SJohn Forte 	scsi_command_names[25].name = MSGSTR(10500, "Persistent Reserve In");
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte 	scsi_command_names[26].command = SCMD_PERS_RESERV_OUT;
764fcf3ce44SJohn Forte 	scsi_command_names[26].name = MSGSTR(10501, "Persistent Reserve out");
765fcf3ce44SJohn Forte 
766fcf3ce44SJohn Forte 	scsi_command_names[27].command = SCMD_LOG_SENSE;
767fcf3ce44SJohn Forte 	scsi_command_names[27].name = MSGSTR(10502, "Log Sense");
768fcf3ce44SJohn Forte 
769fcf3ce44SJohn Forte 	scsi_command_names[28].command = SCMD_UNKNOWN;
770fcf3ce44SJohn Forte 	scsi_command_names[28].name = MSGSTR(25, "Unknown");
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 
773fcf3ce44SJohn Forte 	for (c = scsi_command_names; c->command != SCMD_UNKNOWN; c++)
774fcf3ce44SJohn Forte 		if (c->command == cmd)
775fcf3ce44SJohn Forte 			break;
776fcf3ce44SJohn Forte 	return (c->name);
777fcf3ce44SJohn Forte }
778fcf3ce44SJohn Forte 
779fcf3ce44SJohn Forte 
780fcf3ce44SJohn Forte /*
781fcf3ce44SJohn Forte  *	Function to create error message containing
782fcf3ce44SJohn Forte  *	scsi request sense information
783fcf3ce44SJohn Forte  */
784fcf3ce44SJohn Forte 
785fcf3ce44SJohn Forte void
g_scsi_printerr(struct uscsi_cmd * ucmd,struct scsi_extended_sense * rq,int rqlen,char msg_string[],char * err_string)786fcf3ce44SJohn Forte g_scsi_printerr(struct uscsi_cmd *ucmd, struct scsi_extended_sense *rq,
787fcf3ce44SJohn Forte 		int rqlen, char msg_string[], char *err_string)
788fcf3ce44SJohn Forte {
789fcf3ce44SJohn Forte 	int		blkno;
790fcf3ce44SJohn Forte 
791fcf3ce44SJohn Forte 	switch (rq->es_key) {
792fcf3ce44SJohn Forte 	case KEY_NO_SENSE:
793fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(91, "No sense error"));
794fcf3ce44SJohn Forte 		break;
795fcf3ce44SJohn Forte 	case KEY_RECOVERABLE_ERROR:
796fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(76, "Recoverable error"));
797fcf3ce44SJohn Forte 		break;
798fcf3ce44SJohn Forte 	case KEY_NOT_READY:
799fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
800fcf3ce44SJohn Forte 			MSGSTR(10503,
801fcf3ce44SJohn Forte 			"Device Not ready."
802fcf3ce44SJohn Forte 			" Error: Random Retry Failed: %s\n."),
803fcf3ce44SJohn Forte 			err_string);
804fcf3ce44SJohn Forte 		break;
805fcf3ce44SJohn Forte 	case KEY_MEDIUM_ERROR:
806fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(99, "Medium error"));
807fcf3ce44SJohn Forte 		break;
808fcf3ce44SJohn Forte 	case KEY_HARDWARE_ERROR:
809fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(106, "Hardware error"));
810fcf3ce44SJohn Forte 		break;
811fcf3ce44SJohn Forte 	case KEY_ILLEGAL_REQUEST:
812fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(103, "Illegal request"));
813fcf3ce44SJohn Forte 		break;
814fcf3ce44SJohn Forte 	case KEY_UNIT_ATTENTION:
815fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
816fcf3ce44SJohn Forte 			MSGSTR(10504,
817fcf3ce44SJohn Forte 			"Unit attention."
818fcf3ce44SJohn Forte 			"Error: Random Retry Failed.\n"));
819fcf3ce44SJohn Forte 		break;
820fcf3ce44SJohn Forte 	case KEY_WRITE_PROTECT:
821fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(52, "Write protect error"));
822fcf3ce44SJohn Forte 		break;
823fcf3ce44SJohn Forte 	case KEY_BLANK_CHECK:
824fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(131, "Blank check error"));
825fcf3ce44SJohn Forte 		break;
826fcf3ce44SJohn Forte 	case KEY_VENDOR_UNIQUE:
827fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(58, "Vendor unique error"));
828fcf3ce44SJohn Forte 		break;
829fcf3ce44SJohn Forte 	case KEY_COPY_ABORTED:
830fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(123, "Copy aborted error"));
831fcf3ce44SJohn Forte 		break;
832fcf3ce44SJohn Forte 	case KEY_ABORTED_COMMAND:
833fcf3ce44SJohn Forte 		(void) sprintf(msg_string,
834fcf3ce44SJohn Forte 			MSGSTR(10505,
835fcf3ce44SJohn Forte 			"Aborted command."
836fcf3ce44SJohn Forte 			" Error: Random Retry Failed.\n"));
837fcf3ce44SJohn Forte 		break;
838fcf3ce44SJohn Forte 	case KEY_EQUAL:
839fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(117, "Equal error"));
840fcf3ce44SJohn Forte 		break;
841fcf3ce44SJohn Forte 	case KEY_VOLUME_OVERFLOW:
842fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(57, "Volume overflow"));
843fcf3ce44SJohn Forte 		break;
844fcf3ce44SJohn Forte 	case KEY_MISCOMPARE:
845fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(98, "Miscompare error"));
846fcf3ce44SJohn Forte 		break;
847fcf3ce44SJohn Forte 	case KEY_RESERVED:
848fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(10506,
849fcf3ce44SJohn Forte 			"Reserved value found"));
850fcf3ce44SJohn Forte 		break;
851fcf3ce44SJohn Forte 	default:
852fcf3ce44SJohn Forte 		(void) sprintf(msg_string, MSGSTR(59, "Unknown error"));
853fcf3ce44SJohn Forte 		break;
854fcf3ce44SJohn Forte 	}
855fcf3ce44SJohn Forte 
856fcf3ce44SJohn Forte 	(void) sprintf(&msg_string[strlen(msg_string)],
857fcf3ce44SJohn Forte 		MSGSTR(10507, " during: %s"),
858fcf3ce44SJohn Forte 		g_scsi_find_command_name(ucmd->uscsi_cdb[0]));
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 	if (rq->es_valid) {
861fcf3ce44SJohn Forte 		blkno = (rq->es_info_1 << 24) | (rq->es_info_2 << 16) |
862fcf3ce44SJohn Forte 			(rq->es_info_3 << 8) | rq->es_info_4;
863fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
864fcf3ce44SJohn Forte 			MSGSTR(49, ": block %d (0x%x)"), blkno, blkno);
865fcf3ce44SJohn Forte 	}
866fcf3ce44SJohn Forte 
867fcf3ce44SJohn Forte 	(void) sprintf(&msg_string[strlen(msg_string)], "\n");
868fcf3ce44SJohn Forte 
869fcf3ce44SJohn Forte 	if (rq->es_add_len >= 6) {
870fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
871fcf3ce44SJohn Forte 		MSGSTR(132, "  Additional sense: 0x%x   ASC Qualifier: 0x%x\n"),
872fcf3ce44SJohn Forte 			rq->es_add_code, rq->es_qual_code);
873fcf3ce44SJohn Forte 			/*
874fcf3ce44SJohn Forte 			 * rq->es_add_info[ADD_SENSE_CODE],
875fcf3ce44SJohn Forte 			 * rq->es_add_info[ADD_SENSE_QUAL_CODE]);
876fcf3ce44SJohn Forte 			 */
877fcf3ce44SJohn Forte 	}
878fcf3ce44SJohn Forte 	if (rq->es_key == KEY_ILLEGAL_REQUEST) {
879fcf3ce44SJohn Forte 		string_dump(MSGSTR(47, " cmd:   "), (uchar_t *)ucmd,
880fcf3ce44SJohn Forte 			sizeof (struct uscsi_cmd), HEX_ONLY, msg_string);
881fcf3ce44SJohn Forte 		string_dump(MSGSTR(48, " cdb:   "),
882fcf3ce44SJohn Forte 			(uchar_t *)ucmd->uscsi_cdb,
883fcf3ce44SJohn Forte 			ucmd->uscsi_cdblen, HEX_ONLY, msg_string);
884fcf3ce44SJohn Forte 	}
885fcf3ce44SJohn Forte 	string_dump(MSGSTR(43, " sense:  "),
886fcf3ce44SJohn Forte 		(uchar_t *)rq, 8 + rq->es_add_len, HEX_ONLY,
887fcf3ce44SJohn Forte 		msg_string);
888fcf3ce44SJohn Forte 	rqlen = rqlen;	/* not used */
889fcf3ce44SJohn Forte }
890fcf3ce44SJohn Forte 
891fcf3ce44SJohn Forte 
892fcf3ce44SJohn Forte /*
893fcf3ce44SJohn Forte  *		Special string dump for error message
894fcf3ce44SJohn Forte  */
895fcf3ce44SJohn Forte static	void
string_dump(char * hdr,uchar_t * src,int nbytes,int format,char msg_string[])896fcf3ce44SJohn Forte string_dump(char *hdr, uchar_t *src, int nbytes, int format, char msg_string[])
897fcf3ce44SJohn Forte {
898fcf3ce44SJohn Forte 	int i;
899fcf3ce44SJohn Forte 	int n;
900fcf3ce44SJohn Forte 	char	*p;
901fcf3ce44SJohn Forte 	char	s[256];
902fcf3ce44SJohn Forte 
903fcf3ce44SJohn Forte 	assert(format == HEX_ONLY || format == HEX_ASCII);
904fcf3ce44SJohn Forte 
905fcf3ce44SJohn Forte 	(void) strcpy(s, hdr);
906fcf3ce44SJohn Forte 	for (p = s; *p; p++) {
907fcf3ce44SJohn Forte 		*p = ' ';
908fcf3ce44SJohn Forte 	}
909fcf3ce44SJohn Forte 
910fcf3ce44SJohn Forte 	p = hdr;
911fcf3ce44SJohn Forte 	while (nbytes > 0) {
912fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)],
913fcf3ce44SJohn Forte 			"%s", p);
914fcf3ce44SJohn Forte 		p = s;
915fcf3ce44SJohn Forte 		n = min(nbytes, BYTES_PER_LINE);
916fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
917fcf3ce44SJohn Forte 			(void) sprintf(&msg_string[strlen(msg_string)],
918fcf3ce44SJohn Forte 				"%02x ",
919fcf3ce44SJohn Forte 				src[i] & 0xff);
920fcf3ce44SJohn Forte 		}
921fcf3ce44SJohn Forte 		if (format == HEX_ASCII) {
922fcf3ce44SJohn Forte 			for (i = BYTES_PER_LINE-n; i > 0; i--) {
923fcf3ce44SJohn Forte 				(void) sprintf(&msg_string[strlen(msg_string)],
924fcf3ce44SJohn Forte 					"   ");
925fcf3ce44SJohn Forte 			}
926fcf3ce44SJohn Forte 			(void) sprintf(&msg_string[strlen(msg_string)],
927fcf3ce44SJohn Forte 				"    ");
928fcf3ce44SJohn Forte 			for (i = 0; i < n; i++) {
929fcf3ce44SJohn Forte 				(void) sprintf(&msg_string[strlen(msg_string)],
930fcf3ce44SJohn Forte 					"%c",
931fcf3ce44SJohn Forte 					isprint(src[i]) ? src[i] : '.');
932fcf3ce44SJohn Forte 			}
933fcf3ce44SJohn Forte 		}
934fcf3ce44SJohn Forte 		(void) sprintf(&msg_string[strlen(msg_string)], "\n");
935fcf3ce44SJohn Forte 		nbytes -= n;
936fcf3ce44SJohn Forte 		src += n;
937fcf3ce44SJohn Forte 	}
938fcf3ce44SJohn Forte }
939fcf3ce44SJohn Forte 
940fcf3ce44SJohn Forte 
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte /*
943fcf3ce44SJohn Forte  * This routine is a wrapper for malloc.  It allocates pre-zeroed space,
944fcf3ce44SJohn Forte  * and checks the return value so the caller doesn't have to.
945fcf3ce44SJohn Forte  */
946fcf3ce44SJohn Forte void *
g_zalloc(int count)947fcf3ce44SJohn Forte g_zalloc(int count)
948fcf3ce44SJohn Forte {
949fcf3ce44SJohn Forte 	void	*ptr;
950fcf3ce44SJohn Forte 
951fcf3ce44SJohn Forte 	ptr = (void *) calloc(1, (unsigned)count);
952fcf3ce44SJohn Forte 	A_DPRINTF("  g_zalloc: Allocated 0x%x bytes "
953fcf3ce44SJohn Forte 			"at 0x%x\n", count, ptr);
954fcf3ce44SJohn Forte 
955fcf3ce44SJohn Forte 	return (ptr);
956fcf3ce44SJohn Forte }
957fcf3ce44SJohn Forte 
958fcf3ce44SJohn Forte /*
959fcf3ce44SJohn Forte  * Open up the i18n catalog.
960fcf3ce44SJohn Forte  * Returns:
961fcf3ce44SJohn Forte  *  0 = O.K.
962fcf3ce44SJohn Forte  * -1 = Failed (Will revert to default strings)
963fcf3ce44SJohn Forte  */
964fcf3ce44SJohn Forte int
g_i18n_catopen(void)965fcf3ce44SJohn Forte g_i18n_catopen(void)
966fcf3ce44SJohn Forte {
967fcf3ce44SJohn Forte 	static int fileopen = 0;
968fcf3ce44SJohn Forte 	static mutex_t mp;
969fcf3ce44SJohn Forte 
970fcf3ce44SJohn Forte 	if (setlocale(LC_ALL, "") == NULL) {
971fcf3ce44SJohn Forte 	    (void) fprintf(stderr,
972fcf3ce44SJohn Forte 		"Cannot operate in the locale requested. "
973fcf3ce44SJohn Forte 		"Continuing in the default C locale\n");
974fcf3ce44SJohn Forte 	}
975fcf3ce44SJohn Forte 	if (mutex_lock(&mp) != 0) {
976fcf3ce44SJohn Forte 		return (-1);
977fcf3ce44SJohn Forte 	}
978fcf3ce44SJohn Forte 	if (!fileopen) {
979fcf3ce44SJohn Forte 		l_catd = catopen("a5k_g_fc_i18n_cat", NL_CAT_LOCALE);
980fcf3ce44SJohn Forte 		if (l_catd == (nl_catd)-1) {
981fcf3ce44SJohn Forte 			(void) mutex_unlock(&mp);
982fcf3ce44SJohn Forte 			return (-1);
983fcf3ce44SJohn Forte 		}
984fcf3ce44SJohn Forte 		fileopen = 1;
985fcf3ce44SJohn Forte 	}
986fcf3ce44SJohn Forte 	(void) mutex_unlock(&mp);
987fcf3ce44SJohn Forte 	return (0);
988fcf3ce44SJohn Forte }
989fcf3ce44SJohn Forte 
990fcf3ce44SJohn Forte /* Macro used by g_get_path_type() */
991fcf3ce44SJohn Forte #define	GetMatch(s_ptr)	\
992fcf3ce44SJohn Forte 	for (found = 0, search_arr_ptr = s_ptr; \
993fcf3ce44SJohn Forte 		search_arr_ptr->string != NULL; \
994fcf3ce44SJohn Forte 			search_arr_ptr++) {\
995fcf3ce44SJohn Forte 		if (strstr(path_ptr, search_arr_ptr->string) != NULL) {\
996fcf3ce44SJohn Forte 			found = 1;\
997fcf3ce44SJohn Forte 			break;\
998fcf3ce44SJohn Forte 		}\
999fcf3ce44SJohn Forte 	}
1000fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte /*
1002fcf3ce44SJohn Forte  * Input  : A NULL terminated string
1003fcf3ce44SJohn Forte  *          This string is checked to be an absolute device path
1004fcf3ce44SJohn Forte  * Output :
1005fcf3ce44SJohn Forte  * 	The FCA type and Xport type if found in the path on success
1006fcf3ce44SJohn Forte  *	0 on Failure
1007fcf3ce44SJohn Forte  *
1008fcf3ce44SJohn Forte  * Examples of valid device strings :
1009fcf3ce44SJohn Forte  *
1010fcf3ce44SJohn Forte  * Non Fabric FC driver :
1011fcf3ce44SJohn Forte  * /devices/io-unit@f,e0200000/sbi@0,0/SUNW,socal@1,0/sf@1,0:ctlr
1012fcf3ce44SJohn Forte  * /devices/io-unit@f,e2200000/sbi@0,0/SUNW,socal@3,0/sf@0,0/ssd@20,0:c,raw
1013fcf3ce44SJohn Forte  * /devices/sbus@1f,0/SUNW,socal@0,0/sf@0,0:devctl
1014fcf3ce44SJohn Forte  * /devices/sbus@1f,0/SUNW,socal@2,0/sf@1,0/ssd@w2200002037110cbf,0:b,raw
1015fcf3ce44SJohn Forte  * /devices/pci@1f,4000/SUNW,ifp@4:devctl
1016fcf3ce44SJohn Forte  * /devices/pci@1f,4000/SUNW,ifp@2/ssd@w2100002037049ba0,0:c,raw
1017fcf3ce44SJohn Forte  * /devices/pci@6,4000/pci@2/SUNW,ifp@5/ssd@w210000203708b44f,0:c,raw
1018fcf3ce44SJohn Forte  *
1019fcf3ce44SJohn Forte  * Fabric FC driver (fp) :
1020fcf3ce44SJohn Forte  * 	- offical device path for Qlogic 2202 with proper FCODE
1021fcf3ce44SJohn Forte  *	  as of 12/99.
1022fcf3ce44SJohn Forte  * /devices/pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0:devctl
1023fcf3ce44SJohn Forte  * /devices/pci@e,2000/pci@2/SUNW,qlc@4/fp@0,0:devctl
1024fcf3ce44SJohn Forte  *
1025fcf3ce44SJohn Forte  */
1026fcf3ce44SJohn Forte uint_t
g_get_path_type(char * path)1027fcf3ce44SJohn Forte g_get_path_type(char *path)
1028fcf3ce44SJohn Forte {
1029fcf3ce44SJohn Forte 	uint_t path_type = 0;
1030fcf3ce44SJohn Forte 	int	i = 0, pathcnt = 1;
1031fcf3ce44SJohn Forte 	char *path_ptr = path;
1032fcf3ce44SJohn Forte 	struct str_type *search_arr_ptr; /* updated by GetMatch macro */
1033fcf3ce44SJohn Forte 	char found;			 /* Updated by GetMatch marco */
1034fcf3ce44SJohn Forte 	char		drvr_path1[MAXPATHLEN];
1035fcf3ce44SJohn Forte 	mp_pathlist_t	pathlist;
1036fcf3ce44SJohn Forte 	int		p_on = 0, p_st = 0;
1037fcf3ce44SJohn Forte 
1038fcf3ce44SJohn Forte 	/* Path passed must be an absolute device path */
1039fcf3ce44SJohn Forte 	if (strncmp(path_ptr, DEV_PREFIX, DEV_PREFIX_LEN) ||
1040fcf3ce44SJohn Forte 				(strlen(path_ptr) == DEV_PREFIX_LEN)) {
1041fcf3ce44SJohn Forte 		return (0);	/* Invalid path */
1042fcf3ce44SJohn Forte 	}
1043fcf3ce44SJohn Forte 
1044fcf3ce44SJohn Forte 	/* if mpxio device, need to convert from vhci to phci */
1045fcf3ce44SJohn Forte 	if (strstr(path, SCSI_VHCI)) {
1046fcf3ce44SJohn Forte 		(void) strcpy(drvr_path1, path);
1047fcf3ce44SJohn Forte 		if (g_get_pathlist(drvr_path1, &pathlist)) {
1048fcf3ce44SJohn Forte 			return (0);
1049fcf3ce44SJohn Forte 		}
1050fcf3ce44SJohn Forte 		pathcnt = pathlist.path_count;
1051fcf3ce44SJohn Forte 		p_on = p_st = 0;
1052fcf3ce44SJohn Forte 		for (i = 0; i < pathcnt; i++) {
1053fcf3ce44SJohn Forte 			if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
1054fcf3ce44SJohn Forte 				if (pathlist.path_info[i].path_state ==
1055fcf3ce44SJohn Forte 					MDI_PATHINFO_STATE_ONLINE) {
1056fcf3ce44SJohn Forte 					p_on = i;
1057fcf3ce44SJohn Forte 					break;
1058fcf3ce44SJohn Forte 				} else if (pathlist.path_info[i].path_state ==
1059fcf3ce44SJohn Forte 					MDI_PATHINFO_STATE_STANDBY) {
1060fcf3ce44SJohn Forte 					p_st = i;
1061fcf3ce44SJohn Forte 				}
1062fcf3ce44SJohn Forte 			}
1063fcf3ce44SJohn Forte 		}
1064fcf3ce44SJohn Forte 		if (pathlist.path_info[p_on].path_state ==
1065fcf3ce44SJohn Forte 		    MDI_PATHINFO_STATE_ONLINE) {
1066fcf3ce44SJohn Forte 			/* on_line path */
1067fcf3ce44SJohn Forte 			(void) strcpy(drvr_path1,
1068fcf3ce44SJohn Forte 				pathlist.path_info[p_on].path_hba);
1069fcf3ce44SJohn Forte 		} else {
1070fcf3ce44SJohn Forte 			/* standby or path0 */
1071fcf3ce44SJohn Forte 			(void) strcpy(drvr_path1,
1072fcf3ce44SJohn Forte 				pathlist.path_info[p_st].path_hba);
1073fcf3ce44SJohn Forte 		}
1074fcf3ce44SJohn Forte 		free(pathlist.path_info);
1075fcf3ce44SJohn Forte 		path_ptr = drvr_path1;
1076fcf3ce44SJohn Forte 	}
1077fcf3ce44SJohn Forte 
1078fcf3ce44SJohn Forte 	GetMatch(ValidBusStrings);
1079fcf3ce44SJohn Forte 	if (found == 0) {
1080fcf3ce44SJohn Forte 		/* No valid bus string - so not a valid path */
1081fcf3ce44SJohn Forte 		return (0);
1082fcf3ce44SJohn Forte 	}
1083fcf3ce44SJohn Forte 
1084fcf3ce44SJohn Forte 	GetMatch(ValidFCAstrings);	/* Check for a valid FCA string */
1085fcf3ce44SJohn Forte 	if (found != 0) {
1086fcf3ce44SJohn Forte 		path_type |= search_arr_ptr->type;
1087fcf3ce44SJohn Forte 	}
1088fcf3ce44SJohn Forte 
1089fcf3ce44SJohn Forte 	/*
1090fcf3ce44SJohn Forte 	 * continue to check xport even without valid FCA string.
1091fcf3ce44SJohn Forte 	 * This is to support 3rd party FCA vendor on Leadville stack.
1092fcf3ce44SJohn Forte 	 */
1093fcf3ce44SJohn Forte 	GetMatch(ValidXportStrings);	/* Check for a valid transport str */
1094fcf3ce44SJohn Forte 	if (found == 0) {
1095fcf3ce44SJohn Forte 		return (path_type);
1096fcf3ce44SJohn Forte 	} else {
1097fcf3ce44SJohn Forte 		/*
1098fcf3ce44SJohn Forte 		 * if leadville tranport is detected and fca is not set yet,
1099fcf3ce44SJohn Forte 		 * set fca flag to generic FC_FCA_MASK.
1100fcf3ce44SJohn Forte 		 */
1101fcf3ce44SJohn Forte 		if ((search_arr_ptr->type == FC_GEN_XPORT) &&
1102fcf3ce44SJohn Forte 			(!(path_type & FC_FCA_MASK))) {
1103fcf3ce44SJohn Forte 			path_type |= FC_FCA_MASK;
1104fcf3ce44SJohn Forte 		}
1105fcf3ce44SJohn Forte 	}
1106fcf3ce44SJohn Forte 	path_type |= search_arr_ptr->type;
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 	/*
1109fcf3ce44SJohn Forte 	 * A quick sanity check to make sure that we dont have
1110fcf3ce44SJohn Forte 	 * a combination that is not possible
1111fcf3ce44SJohn Forte 	 */
1112fcf3ce44SJohn Forte 	if (((path_type & (FC4_FCA_MASK | FC_XPORT_MASK)) ==
1113fcf3ce44SJohn Forte 			path_type) ||
1114fcf3ce44SJohn Forte 		((path_type & (FC_FCA_MASK | FC4_XPORT_MASK)) ==
1115fcf3ce44SJohn Forte 			path_type)) {
1116fcf3ce44SJohn Forte 		path_type = 0;
1117fcf3ce44SJohn Forte 	}
1118fcf3ce44SJohn Forte 
1119fcf3ce44SJohn Forte 	return (path_type);
1120fcf3ce44SJohn Forte }
1121fcf3ce44SJohn Forte 
1122fcf3ce44SJohn Forte 
1123fcf3ce44SJohn Forte /*
1124fcf3ce44SJohn Forte  * g_get_port_path(char *, portlist_t *)
1125fcf3ce44SJohn Forte  * Purpose: Find all port nexus paths for a particular driver
1126fcf3ce44SJohn Forte  * Input:   portdrvr
1127fcf3ce44SJohn Forte  *		set to name of driver for which to find the paths
1128fcf3ce44SJohn Forte  * Output:  portlist
1129fcf3ce44SJohn Forte  *		allocated structure to hold paths found
1130fcf3ce44SJohn Forte  *		user must call g_free_portlist(portlist_t *) to
1131fcf3ce44SJohn Forte  *		free allocated memory
1132fcf3ce44SJohn Forte  */
1133fcf3ce44SJohn Forte int
g_get_port_path(char * portdrvr,portlist_t * portlist)1134fcf3ce44SJohn Forte g_get_port_path(char *portdrvr, portlist_t *portlist)
1135fcf3ce44SJohn Forte {
1136fcf3ce44SJohn Forte 	di_node_t root;
1137fcf3ce44SJohn Forte 	di_node_t node;
1138fcf3ce44SJohn Forte 	di_minor_t minor_node;
1139fcf3ce44SJohn Forte 	char hbapathfound[MAXPATHLEN];
1140fcf3ce44SJohn Forte 	char *tmppath;
1141fcf3ce44SJohn Forte 	struct stat buf;
1142fcf3ce44SJohn Forte 
1143fcf3ce44SJohn Forte 	/* return invalid argument if *portdrvr or *portlist is NULL */
1144fcf3ce44SJohn Forte 	if ((portdrvr == NULL) || (portlist == NULL)) {
1145fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
1146fcf3ce44SJohn Forte 	}
1147fcf3ce44SJohn Forte 
1148fcf3ce44SJohn Forte 	/* Create a snapshot of the kernel device tree */
1149fcf3ce44SJohn Forte 	root = di_init("/", DINFOCPYALL);
1150fcf3ce44SJohn Forte 	if (root == DI_NODE_NIL) {
1151fcf3ce44SJohn Forte 		return (L_DEV_SNAPSHOT_FAILED);
1152fcf3ce44SJohn Forte 	}
1153fcf3ce44SJohn Forte 
1154fcf3ce44SJohn Forte 	/* point to first node which matches portdrvr */
1155fcf3ce44SJohn Forte 	node = di_drv_first_node(portdrvr, root);
1156fcf3ce44SJohn Forte