17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
22*10264SZhong.Wang@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237836SJohn.Forte@Sun.COM * Use is subject to license terms.
247836SJohn.Forte@Sun.COM */
257836SJohn.Forte@Sun.COM
267836SJohn.Forte@Sun.COM
277836SJohn.Forte@Sun.COM
287836SJohn.Forte@Sun.COM
297836SJohn.Forte@Sun.COM /*LINTLIBRARY*/
307836SJohn.Forte@Sun.COM
317836SJohn.Forte@Sun.COM /*
327836SJohn.Forte@Sun.COM * This module is part of the Fibre Channel Interface library.
337836SJohn.Forte@Sun.COM *
347836SJohn.Forte@Sun.COM */
357836SJohn.Forte@Sun.COM
367836SJohn.Forte@Sun.COM /*
377836SJohn.Forte@Sun.COM * I18N message number ranges
387836SJohn.Forte@Sun.COM * This file: 10500 - 10999
397836SJohn.Forte@Sun.COM * Shared common messages: 1 - 1999
407836SJohn.Forte@Sun.COM */
417836SJohn.Forte@Sun.COM
427836SJohn.Forte@Sun.COM /* Includes */
437836SJohn.Forte@Sun.COM #include <stdlib.h>
447836SJohn.Forte@Sun.COM #include <stdio.h>
457836SJohn.Forte@Sun.COM #include <sys/file.h>
467836SJohn.Forte@Sun.COM #include <sys/types.h>
477836SJohn.Forte@Sun.COM #include <sys/stat.h>
487836SJohn.Forte@Sun.COM #include <sys/param.h>
497836SJohn.Forte@Sun.COM #include <fcntl.h>
507836SJohn.Forte@Sun.COM #include <string.h>
517836SJohn.Forte@Sun.COM #include <errno.h>
527836SJohn.Forte@Sun.COM #include <assert.h>
537836SJohn.Forte@Sun.COM #include <unistd.h>
547836SJohn.Forte@Sun.COM #include <sys/types.h>
557836SJohn.Forte@Sun.COM #include <sys/param.h>
567836SJohn.Forte@Sun.COM #include <sys/dklabel.h>
577836SJohn.Forte@Sun.COM #include <sys/autoconf.h>
587836SJohn.Forte@Sun.COM #include <sys/utsname.h>
597836SJohn.Forte@Sun.COM #include <sys/ddi.h> /* for min */
607836SJohn.Forte@Sun.COM #include <ctype.h> /* for isprint */
617836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
627836SJohn.Forte@Sun.COM #include <dirent.h> /* for DIR */
637836SJohn.Forte@Sun.COM #include <nl_types.h>
647836SJohn.Forte@Sun.COM #include <locale.h>
657836SJohn.Forte@Sun.COM #include <thread.h>
667836SJohn.Forte@Sun.COM #include <synch.h>
677836SJohn.Forte@Sun.COM #include <l_common.h>
687836SJohn.Forte@Sun.COM #include <stgcom.h>
697836SJohn.Forte@Sun.COM #include <l_error.h>
707836SJohn.Forte@Sun.COM #include <g_state.h>
717836SJohn.Forte@Sun.COM #include <libdevinfo.h>
727836SJohn.Forte@Sun.COM
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM /* Defines */
757836SJohn.Forte@Sun.COM #define BYTES_PER_LINE 16 /* # of bytes to dump per line */
767836SJohn.Forte@Sun.COM #define SCMD_UNKNOWN 0xff
777836SJohn.Forte@Sun.COM
787836SJohn.Forte@Sun.COM /* Bus strings - for internal use by g_get_path_type() only */
797836SJohn.Forte@Sun.COM #define PCI_BUS 1
807836SJohn.Forte@Sun.COM #define SBUS 2
81*10264SZhong.Wang@Sun.COM #define FCOE 3
827836SJohn.Forte@Sun.COM
837836SJohn.Forte@Sun.COM struct str_type {
847836SJohn.Forte@Sun.COM char *string;
857836SJohn.Forte@Sun.COM uint_t type;
867836SJohn.Forte@Sun.COM };
877836SJohn.Forte@Sun.COM
887836SJohn.Forte@Sun.COM static struct str_type ValidBusStrings[] = {
897836SJohn.Forte@Sun.COM {"pci@", PCI_BUS},
907836SJohn.Forte@Sun.COM {"sbus@", SBUS},
91*10264SZhong.Wang@Sun.COM {"fcoe", FCOE},
927836SJohn.Forte@Sun.COM {NULL, 0}
937836SJohn.Forte@Sun.COM };
947836SJohn.Forte@Sun.COM
957836SJohn.Forte@Sun.COM
967836SJohn.Forte@Sun.COM /*
977836SJohn.Forte@Sun.COM * Strings below were used before cougar driver(qlc) was proposed.
987836SJohn.Forte@Sun.COM * {"scsi/", FC_PCI_FCA},
997836SJohn.Forte@Sun.COM * {"fibre-channel/", FC_PCI_FCA},
1007836SJohn.Forte@Sun.COM */
1017836SJohn.Forte@Sun.COM static struct str_type ValidFCAstrings[] = {
1027836SJohn.Forte@Sun.COM {"SUNW,ifp@", FC4_PCI_FCA | FC4_IFP_XPORT},
1037836SJohn.Forte@Sun.COM {"SUNW,socal@", FC4_SOCAL_FCA},
1047836SJohn.Forte@Sun.COM {NULL, 0}
1057836SJohn.Forte@Sun.COM };
1067836SJohn.Forte@Sun.COM
1077836SJohn.Forte@Sun.COM static struct str_type ValidXportStrings[] = {
1087836SJohn.Forte@Sun.COM {"/sf@", FC4_SF_XPORT},
1097836SJohn.Forte@Sun.COM {"/fp@", FC_GEN_XPORT},
1107836SJohn.Forte@Sun.COM {NULL, 0}
1117836SJohn.Forte@Sun.COM };
1127836SJohn.Forte@Sun.COM
1137836SJohn.Forte@Sun.COM struct _enclDisk {
1147836SJohn.Forte@Sun.COM char *vid;
1157836SJohn.Forte@Sun.COM char *pid;
1167836SJohn.Forte@Sun.COM };
1177836SJohn.Forte@Sun.COM
1187836SJohn.Forte@Sun.COM /*
1197836SJohn.Forte@Sun.COM * SENA/SUNWGS type enclosure disk table. This table contains vendor IDs and
1207836SJohn.Forte@Sun.COM * the non-unique portion of the product identifier sufficient for
1217836SJohn.Forte@Sun.COM * comparison. This table needs to be updated as new drives are supported
1227836SJohn.Forte@Sun.COM * in the SENA/SUNWGS type enclosures that do not have a corresponding match
1237836SJohn.Forte@Sun.COM * in this table. Currently, the v880 and v890 are the only shipping products
1247836SJohn.Forte@Sun.COM * that utilize the SUNWGS type enclosure. SENA is EOL'd. The risk of new
1257836SJohn.Forte@Sun.COM * devices being added that do not match an entry in this table is small but it
1267836SJohn.Forte@Sun.COM * does exist.
1277836SJohn.Forte@Sun.COM */
1287836SJohn.Forte@Sun.COM static struct _enclDisk enclDiskTbl[] = {
1297836SJohn.Forte@Sun.COM {"SUN", "SENA"},
1307836SJohn.Forte@Sun.COM {"SUN", "SUNWGS"},
1317836SJohn.Forte@Sun.COM {"FUJITSU", "MA"},
1327836SJohn.Forte@Sun.COM {"HITACHI", "DK"},
1337836SJohn.Forte@Sun.COM {"HITACHI", "HU"},
1347836SJohn.Forte@Sun.COM {"SEAGATE", "ST"},
1357836SJohn.Forte@Sun.COM {NULL, NULL}
1367836SJohn.Forte@Sun.COM };
1377836SJohn.Forte@Sun.COM
1387836SJohn.Forte@Sun.COM
1397836SJohn.Forte@Sun.COM /* i18n */
1407836SJohn.Forte@Sun.COM nl_catd l_catd;
1417836SJohn.Forte@Sun.COM
1427836SJohn.Forte@Sun.COM
1437836SJohn.Forte@Sun.COM /* Internal Functions */
1447836SJohn.Forte@Sun.COM static void string_dump(char *, uchar_t *, int, int, char msg_string[]);
1457836SJohn.Forte@Sun.COM
1467836SJohn.Forte@Sun.COM /*
1477836SJohn.Forte@Sun.COM * Allocate space for and return a pointer to a string
1487836SJohn.Forte@Sun.COM * on the stack. If the string is null, create
1497836SJohn.Forte@Sun.COM * an empty string.
1507836SJohn.Forte@Sun.COM * Use g_destroy_data() to free when no longer used.
1517836SJohn.Forte@Sun.COM */
1527836SJohn.Forte@Sun.COM char *
g_alloc_string(char * s)1537836SJohn.Forte@Sun.COM g_alloc_string(char *s)
1547836SJohn.Forte@Sun.COM {
1557836SJohn.Forte@Sun.COM char *ns;
1567836SJohn.Forte@Sun.COM
1577836SJohn.Forte@Sun.COM if (s == (char *)NULL) {
1587836SJohn.Forte@Sun.COM ns = (char *)g_zalloc(1);
1597836SJohn.Forte@Sun.COM } else {
1607836SJohn.Forte@Sun.COM ns = (char *)g_zalloc(strlen(s) + 1);
1617836SJohn.Forte@Sun.COM if (ns != NULL) {
1627836SJohn.Forte@Sun.COM (void) strncpy(ns, s, (strlen(s) + 1));
1637836SJohn.Forte@Sun.COM }
1647836SJohn.Forte@Sun.COM }
1657836SJohn.Forte@Sun.COM return (ns);
1667836SJohn.Forte@Sun.COM }
1677836SJohn.Forte@Sun.COM
1687836SJohn.Forte@Sun.COM
1697836SJohn.Forte@Sun.COM /*
1707836SJohn.Forte@Sun.COM * This routine is a wrapper for free.
1717836SJohn.Forte@Sun.COM */
1727836SJohn.Forte@Sun.COM void
g_destroy_data(void * data)1737836SJohn.Forte@Sun.COM g_destroy_data(void *data)
1747836SJohn.Forte@Sun.COM {
1757836SJohn.Forte@Sun.COM A_DPRINTF(" g_destroy_data: Free\'ed buffer at 0x%x\n",
1767836SJohn.Forte@Sun.COM data);
1777836SJohn.Forte@Sun.COM free((void *)data);
1787836SJohn.Forte@Sun.COM }
1797836SJohn.Forte@Sun.COM
1807836SJohn.Forte@Sun.COM
1817836SJohn.Forte@Sun.COM /*
1827836SJohn.Forte@Sun.COM * Dump a structure in hexadecimal.
1837836SJohn.Forte@Sun.COM */
1847836SJohn.Forte@Sun.COM void
g_dump(char * hdr,uchar_t * src,int nbytes,int format)1857836SJohn.Forte@Sun.COM g_dump(char *hdr, uchar_t *src, int nbytes, int format)
1867836SJohn.Forte@Sun.COM {
1877836SJohn.Forte@Sun.COM int i;
1887836SJohn.Forte@Sun.COM int n;
1897836SJohn.Forte@Sun.COM char *p;
1907836SJohn.Forte@Sun.COM char s[256];
1917836SJohn.Forte@Sun.COM
1927836SJohn.Forte@Sun.COM assert(format == HEX_ONLY || format == HEX_ASCII);
1937836SJohn.Forte@Sun.COM
1947836SJohn.Forte@Sun.COM (void) strcpy(s, hdr);
1957836SJohn.Forte@Sun.COM for (p = s; *p; p++) {
1967836SJohn.Forte@Sun.COM *p = ' ';
1977836SJohn.Forte@Sun.COM }
1987836SJohn.Forte@Sun.COM
1997836SJohn.Forte@Sun.COM p = hdr;
2007836SJohn.Forte@Sun.COM while (nbytes > 0) {
2017836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%s", p);
2027836SJohn.Forte@Sun.COM p = s;
2037836SJohn.Forte@Sun.COM n = min(nbytes, BYTES_PER_LINE);
2047836SJohn.Forte@Sun.COM for (i = 0; i < n; i++) {
2057836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%02x ", src[i] & 0xff);
2067836SJohn.Forte@Sun.COM }
2077836SJohn.Forte@Sun.COM if (format == HEX_ASCII) {
2087836SJohn.Forte@Sun.COM for (i = BYTES_PER_LINE-n; i > 0; i--) {
2097836SJohn.Forte@Sun.COM (void) fprintf(stdout, " ");
2107836SJohn.Forte@Sun.COM }
2117836SJohn.Forte@Sun.COM (void) fprintf(stdout, " ");
2127836SJohn.Forte@Sun.COM for (i = 0; i < n; i++) {
2137836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%c",
2147836SJohn.Forte@Sun.COM isprint(src[i]) ? src[i] : '.');
2157836SJohn.Forte@Sun.COM }
2167836SJohn.Forte@Sun.COM }
2177836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
2187836SJohn.Forte@Sun.COM nbytes -= n;
2197836SJohn.Forte@Sun.COM src += n;
2207836SJohn.Forte@Sun.COM }
2217836SJohn.Forte@Sun.COM }
2227836SJohn.Forte@Sun.COM
2237836SJohn.Forte@Sun.COM /*
2247836SJohn.Forte@Sun.COM * Internal routine to clean up ../'s in paths.
2257836SJohn.Forte@Sun.COM * returns 0 if no "../" are left.
2267836SJohn.Forte@Sun.COM *
2277836SJohn.Forte@Sun.COM * Wouldn't it be nice if there was a standard system library
2287836SJohn.Forte@Sun.COM * routine to do this...?
2297836SJohn.Forte@Sun.COM */
2307836SJohn.Forte@Sun.COM static int
cleanup_dotdot_path(char * path)2317836SJohn.Forte@Sun.COM cleanup_dotdot_path(char *path)
2327836SJohn.Forte@Sun.COM {
2337836SJohn.Forte@Sun.COM char holder[MAXPATHLEN];
2347836SJohn.Forte@Sun.COM char *dotdot;
2357836SJohn.Forte@Sun.COM char *previous_slash;
2367836SJohn.Forte@Sun.COM
2377836SJohn.Forte@Sun.COM /* Find the first "/../" in the string */
2387836SJohn.Forte@Sun.COM dotdot = strstr(path, "/../");
2397836SJohn.Forte@Sun.COM if (dotdot == NULL) {
2407836SJohn.Forte@Sun.COM return (0);
2417836SJohn.Forte@Sun.COM }
2427836SJohn.Forte@Sun.COM
2437836SJohn.Forte@Sun.COM
2447836SJohn.Forte@Sun.COM /*
2457836SJohn.Forte@Sun.COM * If the [0] character is '/' and "../" immediatly
2467836SJohn.Forte@Sun.COM * follows it, then we can strip the ../
2477836SJohn.Forte@Sun.COM *
2487836SJohn.Forte@Sun.COM * /../../foo/bar == /foo/bar
2497836SJohn.Forte@Sun.COM *
2507836SJohn.Forte@Sun.COM */
2517836SJohn.Forte@Sun.COM if (dotdot == path) {
2527836SJohn.Forte@Sun.COM strcpy(holder, &path[3]); /* strip "/.." */
2537836SJohn.Forte@Sun.COM strcpy(path, holder);
2547836SJohn.Forte@Sun.COM return (1);
2557836SJohn.Forte@Sun.COM }
2567836SJohn.Forte@Sun.COM
2577836SJohn.Forte@Sun.COM /*
2587836SJohn.Forte@Sun.COM * Now look for the LAST "/" before the "/../"
2597836SJohn.Forte@Sun.COM * as this is the parent dir we can get rid of.
2607836SJohn.Forte@Sun.COM * We do this by temporarily truncating the string
2617836SJohn.Forte@Sun.COM * at the '/' just before "../" using the dotdot pointer.
2627836SJohn.Forte@Sun.COM */
2637836SJohn.Forte@Sun.COM *dotdot = '\0';
2647836SJohn.Forte@Sun.COM previous_slash = strrchr(path, '/');
2657836SJohn.Forte@Sun.COM if (previous_slash == NULL) {
2667836SJohn.Forte@Sun.COM /*
2677836SJohn.Forte@Sun.COM * hmm, somethings wrong. path looks something
2687836SJohn.Forte@Sun.COM * like "foo/../bar/" so we can't really deal with it.
2697836SJohn.Forte@Sun.COM */
2707836SJohn.Forte@Sun.COM return (0);
2717836SJohn.Forte@Sun.COM }
2727836SJohn.Forte@Sun.COM /*
2737836SJohn.Forte@Sun.COM * Now truncate the path just after the previous '/'
2747836SJohn.Forte@Sun.COM * and slam everything after the "../" back on
2757836SJohn.Forte@Sun.COM */
2767836SJohn.Forte@Sun.COM *(previous_slash+1) = '\0';
2777836SJohn.Forte@Sun.COM strcat(path, dotdot+4);
2787836SJohn.Forte@Sun.COM return (1); /* We may have more "../"s */
2797836SJohn.Forte@Sun.COM }
2807836SJohn.Forte@Sun.COM
2817836SJohn.Forte@Sun.COM
2827836SJohn.Forte@Sun.COM /*
2837836SJohn.Forte@Sun.COM * Follow symbolic links from the logical device name to
2847836SJohn.Forte@Sun.COM * the /devfs physical device name. To be complete, we
2857836SJohn.Forte@Sun.COM * handle the case of multiple links. This function
2867836SJohn.Forte@Sun.COM * either returns NULL (no links, or some other error),
2877836SJohn.Forte@Sun.COM * or the physical device name, alloc'ed on the heap.
2887836SJohn.Forte@Sun.COM *
2897836SJohn.Forte@Sun.COM * NOTE: If the path is relative, it will be forced into
2907836SJohn.Forte@Sun.COM * an absolute path by pre-pending the pwd to it.
2917836SJohn.Forte@Sun.COM */
2927836SJohn.Forte@Sun.COM char *
g_get_physical_name_from_link(char * path)2937836SJohn.Forte@Sun.COM g_get_physical_name_from_link(char *path)
2947836SJohn.Forte@Sun.COM {
2957836SJohn.Forte@Sun.COM struct stat stbuf;
2967836SJohn.Forte@Sun.COM char source[MAXPATHLEN];
2977836SJohn.Forte@Sun.COM char scratch[MAXPATHLEN];
2987836SJohn.Forte@Sun.COM char pwd[MAXPATHLEN];
2997836SJohn.Forte@Sun.COM char *tmp;
3007836SJohn.Forte@Sun.COM int cnt;
3017836SJohn.Forte@Sun.COM
3027836SJohn.Forte@Sun.COM /* return NULL if path is NULL */
3037836SJohn.Forte@Sun.COM if (path == NULL) {
3047836SJohn.Forte@Sun.COM return (NULL);
3057836SJohn.Forte@Sun.COM }
3067836SJohn.Forte@Sun.COM
3077836SJohn.Forte@Sun.COM strcpy(source, path);
3087836SJohn.Forte@Sun.COM for (;;) {
3097836SJohn.Forte@Sun.COM
3107836SJohn.Forte@Sun.COM /*
3117836SJohn.Forte@Sun.COM * First make sure the path is absolute. If not, make it.
3127836SJohn.Forte@Sun.COM * If it's already an absolute path, we have no need
3137836SJohn.Forte@Sun.COM * to determine the cwd, so the program should still
3147836SJohn.Forte@Sun.COM * function within security-by-obscurity directories.
3157836SJohn.Forte@Sun.COM */
3167836SJohn.Forte@Sun.COM if (source[0] != '/') {
3177836SJohn.Forte@Sun.COM tmp = getcwd(pwd, MAXPATHLEN);
3187836SJohn.Forte@Sun.COM if (tmp == NULL) {
3197836SJohn.Forte@Sun.COM O_DPRINTF("getcwd() failed - %s\n",
3207836SJohn.Forte@Sun.COM strerror(errno));
3217836SJohn.Forte@Sun.COM return (NULL);
3227836SJohn.Forte@Sun.COM }
3237836SJohn.Forte@Sun.COM /*
3247836SJohn.Forte@Sun.COM * Handle special case of "./foo/bar"
3257836SJohn.Forte@Sun.COM */
3267836SJohn.Forte@Sun.COM if (source[0] == '.' && source[1] == '/') {
3277836SJohn.Forte@Sun.COM strcpy(scratch, source+2);
3287836SJohn.Forte@Sun.COM } else { /* no "./" so just take everything */
3297836SJohn.Forte@Sun.COM strcpy(scratch, source);
3307836SJohn.Forte@Sun.COM }
3317836SJohn.Forte@Sun.COM strcpy(source, pwd);
3327836SJohn.Forte@Sun.COM strcat(source, "/");
3337836SJohn.Forte@Sun.COM strcat(source, scratch);
3347836SJohn.Forte@Sun.COM }
3357836SJohn.Forte@Sun.COM
3367836SJohn.Forte@Sun.COM /*
3377836SJohn.Forte@Sun.COM * Clean up any "../"s that are in the path
3387836SJohn.Forte@Sun.COM */
3397836SJohn.Forte@Sun.COM while (cleanup_dotdot_path(source));
3407836SJohn.Forte@Sun.COM
3417836SJohn.Forte@Sun.COM /*
3427836SJohn.Forte@Sun.COM * source is now an absolute path to the link we're
3437836SJohn.Forte@Sun.COM * concerned with
3447836SJohn.Forte@Sun.COM *
3457836SJohn.Forte@Sun.COM * See if there's a real file out there. If not,
3467836SJohn.Forte@Sun.COM * we have a dangling link and we ignore it.
3477836SJohn.Forte@Sun.COM */
3487836SJohn.Forte@Sun.COM
3497836SJohn.Forte@Sun.COM if (stat(source, &stbuf) == -1) {
3507836SJohn.Forte@Sun.COM O_DPRINTF("stat() failed for %s- %s\n",
3517836SJohn.Forte@Sun.COM source, strerror(errno));
3527836SJohn.Forte@Sun.COM return (NULL);
3537836SJohn.Forte@Sun.COM }
3547836SJohn.Forte@Sun.COM if (lstat(source, &stbuf) == -1) {
3557836SJohn.Forte@Sun.COM O_DPRINTF("lstat() failed for - %s\n",
3567836SJohn.Forte@Sun.COM source, strerror(errno));
3577836SJohn.Forte@Sun.COM return (NULL);
3587836SJohn.Forte@Sun.COM }
3597836SJohn.Forte@Sun.COM /*
3607836SJohn.Forte@Sun.COM * If the file is not a link, we're done one
3617836SJohn.Forte@Sun.COM * way or the other. If there were links,
3627836SJohn.Forte@Sun.COM * return the full pathname of the resulting
3637836SJohn.Forte@Sun.COM * file.
3647836SJohn.Forte@Sun.COM *
3657836SJohn.Forte@Sun.COM * Note: All of our temp's are on the stack,
3667836SJohn.Forte@Sun.COM * so we have to copy the final result to the heap.
3677836SJohn.Forte@Sun.COM */
3687836SJohn.Forte@Sun.COM if (!S_ISLNK(stbuf.st_mode)) {
3697836SJohn.Forte@Sun.COM return (g_alloc_string(source));
3707836SJohn.Forte@Sun.COM }
3717836SJohn.Forte@Sun.COM cnt = readlink(source, scratch, sizeof (scratch));
3727836SJohn.Forte@Sun.COM if (cnt < 0) {
3737836SJohn.Forte@Sun.COM O_DPRINTF("readlink() failed - %s\n",
3747836SJohn.Forte@Sun.COM strerror(errno));
3757836SJohn.Forte@Sun.COM return (NULL);
3767836SJohn.Forte@Sun.COM }
3777836SJohn.Forte@Sun.COM /*
3787836SJohn.Forte@Sun.COM * scratch is on the heap, and for some reason readlink
3797836SJohn.Forte@Sun.COM * doesn't always terminate things properly so we have
3807836SJohn.Forte@Sun.COM * to make certain we're properly terminated
3817836SJohn.Forte@Sun.COM */
3827836SJohn.Forte@Sun.COM scratch[cnt] = '\0';
3837836SJohn.Forte@Sun.COM
3847836SJohn.Forte@Sun.COM /*
3857836SJohn.Forte@Sun.COM * Now check to see if the link is relative. If so,
3867836SJohn.Forte@Sun.COM * then we have to append it to the directory
3877836SJohn.Forte@Sun.COM * which the source was in. (This is non trivial)
3887836SJohn.Forte@Sun.COM */
3897836SJohn.Forte@Sun.COM if (scratch[0] != '/') {
3907836SJohn.Forte@Sun.COM tmp = strrchr(source, '/');
3917836SJohn.Forte@Sun.COM if (tmp == NULL) { /* Whoa! Something's hosed! */
3927836SJohn.Forte@Sun.COM O_DPRINTF("Internal error... corrupt path.\n");
3937836SJohn.Forte@Sun.COM return (NULL);
3947836SJohn.Forte@Sun.COM }
3957836SJohn.Forte@Sun.COM /* Now strip off just the directory path */
3967836SJohn.Forte@Sun.COM *(tmp+1) = '\0'; /* Keeping the last '/' */
3977836SJohn.Forte@Sun.COM /* and append the new link */
3987836SJohn.Forte@Sun.COM strcat(source, scratch);
3997836SJohn.Forte@Sun.COM /*
4007836SJohn.Forte@Sun.COM * Note: At this point, source should have "../"s
4017836SJohn.Forte@Sun.COM * but we'll clean it up in the next pass through
4027836SJohn.Forte@Sun.COM * the loop.
4037836SJohn.Forte@Sun.COM */
4047836SJohn.Forte@Sun.COM } else {
4057836SJohn.Forte@Sun.COM /* It's an absolute link so no worries */
4067836SJohn.Forte@Sun.COM strcpy(source, scratch);
4077836SJohn.Forte@Sun.COM }
4087836SJohn.Forte@Sun.COM }
4097836SJohn.Forte@Sun.COM /* Never reach here */
4107836SJohn.Forte@Sun.COM }
4117836SJohn.Forte@Sun.COM
4127836SJohn.Forte@Sun.COM /*
4137836SJohn.Forte@Sun.COM * Function for getting physical pathnames
4147836SJohn.Forte@Sun.COM *
4157836SJohn.Forte@Sun.COM * This function can handle 3 different inputs.
4167836SJohn.Forte@Sun.COM *
4177836SJohn.Forte@Sun.COM * 1) Inputs of the form cN
4187836SJohn.Forte@Sun.COM * This requires the program to search the /dev/rdsk
4197836SJohn.Forte@Sun.COM * directory for a device that is conected to the
4207836SJohn.Forte@Sun.COM * controller with number 'N' and then getting
4217836SJohn.Forte@Sun.COM * the physical pathname of the controller.
4227836SJohn.Forte@Sun.COM * The format of the controller pathname is
4237836SJohn.Forte@Sun.COM * /devices/.../.../SUNW,soc@x,x/SUNW,pln@xxxx,xxxxxxxx:ctlr
4247836SJohn.Forte@Sun.COM * The physical pathname is returned.
4257836SJohn.Forte@Sun.COM *
4267836SJohn.Forte@Sun.COM * 2) Inputs of the form /dev/rdsk/cNtNdNsN
4277836SJohn.Forte@Sun.COM * These are identified by being a link
4287836SJohn.Forte@Sun.COM * The physical path they are linked to is returned.
4297836SJohn.Forte@Sun.COM *
4307836SJohn.Forte@Sun.COM * 3) Inputs of the form /devices/...
4317836SJohn.Forte@Sun.COM * These are actual physical names.
4327836SJohn.Forte@Sun.COM * They are not converted.
4337836SJohn.Forte@Sun.COM */
4347836SJohn.Forte@Sun.COM char *
g_get_physical_name(char * path)4357836SJohn.Forte@Sun.COM g_get_physical_name(char *path)
4367836SJohn.Forte@Sun.COM {
4377836SJohn.Forte@Sun.COM struct stat stbuf;
4387836SJohn.Forte@Sun.COM char s[MAXPATHLEN];
4397836SJohn.Forte@Sun.COM char namebuf[MAXPATHLEN];
4407836SJohn.Forte@Sun.COM char savedir[MAXPATHLEN];
4417836SJohn.Forte@Sun.COM char *result = NULL;
4427836SJohn.Forte@Sun.COM DIR *dirp;
4437836SJohn.Forte@Sun.COM struct dirent *entp;
4447836SJohn.Forte@Sun.COM char *dev_name, *char_ptr;
4457836SJohn.Forte@Sun.COM struct stat sb;
4467836SJohn.Forte@Sun.COM int found_flag = 0;
4477836SJohn.Forte@Sun.COM int status = 0;
4487836SJohn.Forte@Sun.COM int i;
4497836SJohn.Forte@Sun.COM
4507836SJohn.Forte@Sun.COM /* return invalid path if path NULL */
4517836SJohn.Forte@Sun.COM if (path == NULL) {
4527836SJohn.Forte@Sun.COM return (NULL);
4537836SJohn.Forte@Sun.COM }
4547836SJohn.Forte@Sun.COM
4557836SJohn.Forte@Sun.COM (void) strcpy(s, path);
4567836SJohn.Forte@Sun.COM /*
4577836SJohn.Forte@Sun.COM * See if the form is cN
4587836SJohn.Forte@Sun.COM * Must handle scenaro where there is a file cN in this directory
4597836SJohn.Forte@Sun.COM * Bug ID: 1184633
4607836SJohn.Forte@Sun.COM *
4617836SJohn.Forte@Sun.COM * We could be in the /dev/rdsk directory and the file could be of
4627836SJohn.Forte@Sun.COM * the form cNdNsN (See man disks).
4637836SJohn.Forte@Sun.COM */
4647836SJohn.Forte@Sun.COM status = stat(s, &stbuf);
4657836SJohn.Forte@Sun.COM if (((status == -1) && (errno == ENOENT)) ||
4667836SJohn.Forte@Sun.COM ((s[0] == 'c') && ((int)strlen(s) > 1) && ((int)strlen(s) < 5))) {
4677836SJohn.Forte@Sun.COM /*
4687836SJohn.Forte@Sun.COM * Further qualify cN entry
4697836SJohn.Forte@Sun.COM */
4707836SJohn.Forte@Sun.COM if ((s[0] != 'c') || ((int)strlen(s) <= 1) ||
4717836SJohn.Forte@Sun.COM ((int)strlen(s) >= 5)) {
4727836SJohn.Forte@Sun.COM goto exit;
4737836SJohn.Forte@Sun.COM }
4747836SJohn.Forte@Sun.COM for (i = 1; i < (int)strlen(s); i++) {
4757836SJohn.Forte@Sun.COM if ((s[i] < '0') || (s[i] > '9')) {
4767836SJohn.Forte@Sun.COM goto exit;
4777836SJohn.Forte@Sun.COM }
4787836SJohn.Forte@Sun.COM }
4797836SJohn.Forte@Sun.COM /*
4807836SJohn.Forte@Sun.COM * path does not point to a file or file is of form cN
4817836SJohn.Forte@Sun.COM */
4827836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_physical_name: "
4837836SJohn.Forte@Sun.COM "Found entry of the form cN n=%s len=%d\n",
4847836SJohn.Forte@Sun.COM &s[1], strlen(s));
4857836SJohn.Forte@Sun.COM
4867836SJohn.Forte@Sun.COM dev_name = g_zalloc(sizeof ("/dev/rdsk"));
4877836SJohn.Forte@Sun.COM sprintf((char *)dev_name, "/dev/rdsk");
4887836SJohn.Forte@Sun.COM
4897836SJohn.Forte@Sun.COM if ((dirp = opendir(dev_name)) == NULL) {
4907836SJohn.Forte@Sun.COM g_destroy_data(dev_name);
4917836SJohn.Forte@Sun.COM goto exit;
4927836SJohn.Forte@Sun.COM }
4937836SJohn.Forte@Sun.COM
4947836SJohn.Forte@Sun.COM while ((entp = readdir(dirp)) != NULL) {
4957836SJohn.Forte@Sun.COM if (strcmp(entp->d_name, ".") == 0 ||
4967836SJohn.Forte@Sun.COM strcmp(entp->d_name, "..") == 0)
4977836SJohn.Forte@Sun.COM continue;
4987836SJohn.Forte@Sun.COM
4997836SJohn.Forte@Sun.COM if (entp->d_name[0] != 'c')
5007836SJohn.Forte@Sun.COM /*
5017836SJohn.Forte@Sun.COM * Silently Ignore for now any names
5027836SJohn.Forte@Sun.COM * not stating with c
5037836SJohn.Forte@Sun.COM */
5047836SJohn.Forte@Sun.COM continue;
5057836SJohn.Forte@Sun.COM
5067836SJohn.Forte@Sun.COM sprintf(namebuf, "%s/%s", dev_name, entp->d_name);
5077836SJohn.Forte@Sun.COM
5087836SJohn.Forte@Sun.COM if ((lstat(namebuf, &sb)) < 0) {
5097836SJohn.Forte@Sun.COM L_WARNINGS(MSGSTR(55,
5107836SJohn.Forte@Sun.COM "Warning: Cannot stat %s\n"),
5117836SJohn.Forte@Sun.COM namebuf);
5127836SJohn.Forte@Sun.COM continue;
5137836SJohn.Forte@Sun.COM }
5147836SJohn.Forte@Sun.COM
5157836SJohn.Forte@Sun.COM if (!S_ISLNK(sb.st_mode)) {
5167836SJohn.Forte@Sun.COM L_WARNINGS(MSGSTR(56,
5177836SJohn.Forte@Sun.COM "Warning: %s is not a symbolic link\n"),
5187836SJohn.Forte@Sun.COM namebuf);
5197836SJohn.Forte@Sun.COM continue;
5207836SJohn.Forte@Sun.COM }
5217836SJohn.Forte@Sun.COM
5227836SJohn.Forte@Sun.COM if (strstr(entp->d_name, s) != NULL) {
5237836SJohn.Forte@Sun.COM /*
5247836SJohn.Forte@Sun.COM * found link to device in /devices
5257836SJohn.Forte@Sun.COM *
5267836SJohn.Forte@Sun.COM * Further qualify to be sure I have
5277836SJohn.Forte@Sun.COM * not found entry of the form c10
5287836SJohn.Forte@Sun.COM * when I am searching for c1
5297836SJohn.Forte@Sun.COM */
5307836SJohn.Forte@Sun.COM if (atoi(&s[1]) == atoi(&entp->d_name[1])) {
5317836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_physical_name: "
5327836SJohn.Forte@Sun.COM "Found entry in /dev/rdsk matching %s: %s\n",
5337836SJohn.Forte@Sun.COM s, entp->d_name);
5347836SJohn.Forte@Sun.COM found_flag = 1;
5357836SJohn.Forte@Sun.COM break;
5367836SJohn.Forte@Sun.COM }
5377836SJohn.Forte@Sun.COM }
5387836SJohn.Forte@Sun.COM }
5397836SJohn.Forte@Sun.COM closedir(dirp);
5407836SJohn.Forte@Sun.COM g_destroy_data(dev_name);
5417836SJohn.Forte@Sun.COM
5427836SJohn.Forte@Sun.COM if (found_flag) {
5437836SJohn.Forte@Sun.COM result = g_get_physical_name_from_link(namebuf);
5447836SJohn.Forte@Sun.COM if (result == NULL) {
5457836SJohn.Forte@Sun.COM goto exit;
5467836SJohn.Forte@Sun.COM }
5477836SJohn.Forte@Sun.COM /*
5487836SJohn.Forte@Sun.COM * Convert from device name to controller name
5497836SJohn.Forte@Sun.COM */
5507836SJohn.Forte@Sun.COM char_ptr = strrchr(result, '/');
5517836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate sting */
5527836SJohn.Forte@Sun.COM (void) strcat(result, CTLR_POSTFIX);
5537836SJohn.Forte@Sun.COM }
5547836SJohn.Forte@Sun.COM goto exit;
5557836SJohn.Forte@Sun.COM }
5567836SJohn.Forte@Sun.COM if (status == -1)
5577836SJohn.Forte@Sun.COM goto exit;
5587836SJohn.Forte@Sun.COM
5597836SJohn.Forte@Sun.COM if (lstat(s, &stbuf) == -1) {
5607836SJohn.Forte@Sun.COM L_WARNINGS(MSGSTR(134,
5617836SJohn.Forte@Sun.COM "%s: lstat() failed - %s\n"),
5627836SJohn.Forte@Sun.COM s, strerror(errno));
5637836SJohn.Forte@Sun.COM goto exit;
5647836SJohn.Forte@Sun.COM }
5657836SJohn.Forte@Sun.COM /*
5667836SJohn.Forte@Sun.COM */
5677836SJohn.Forte@Sun.COM if (!S_ISLNK(stbuf.st_mode)) {
5687836SJohn.Forte@Sun.COM /*
5697836SJohn.Forte@Sun.COM * Path is not a linked file so must be
5707836SJohn.Forte@Sun.COM * a physical path
5717836SJohn.Forte@Sun.COM */
5727836SJohn.Forte@Sun.COM if (S_ISCHR(stbuf.st_mode) || S_ISDIR(stbuf.st_mode)) {
5737836SJohn.Forte@Sun.COM /* Make sure a full path as that is required. */
5747836SJohn.Forte@Sun.COM if (strstr(s, "/devices")) {
5757836SJohn.Forte@Sun.COM result = g_alloc_string(s);
5767836SJohn.Forte@Sun.COM } else {
5777836SJohn.Forte@Sun.COM if (getcwd(savedir,
5787836SJohn.Forte@Sun.COM sizeof (savedir)) == NULL) {
5797836SJohn.Forte@Sun.COM return (NULL);
5807836SJohn.Forte@Sun.COM }
5817836SJohn.Forte@Sun.COM /*
5827836SJohn.Forte@Sun.COM * Check for this format:
5837836SJohn.Forte@Sun.COM * ./ssd@0,1:g,raw
5847836SJohn.Forte@Sun.COM */
5857836SJohn.Forte@Sun.COM if (s[0] == '.') {
5867836SJohn.Forte@Sun.COM strcat(savedir, &s[1]);
5877836SJohn.Forte@Sun.COM } else {
5887836SJohn.Forte@Sun.COM strcat(savedir, "/");
5897836SJohn.Forte@Sun.COM strcat(savedir, s);
5907836SJohn.Forte@Sun.COM }
5917836SJohn.Forte@Sun.COM result = g_alloc_string(savedir);
5927836SJohn.Forte@Sun.COM }
5937836SJohn.Forte@Sun.COM }
5947836SJohn.Forte@Sun.COM } else {
5957836SJohn.Forte@Sun.COM /*
5967836SJohn.Forte@Sun.COM * Entry is linked file
5977836SJohn.Forte@Sun.COM * so follow link to physical name
5987836SJohn.Forte@Sun.COM */
5997836SJohn.Forte@Sun.COM result = g_get_physical_name_from_link(path);
6007836SJohn.Forte@Sun.COM }
6017836SJohn.Forte@Sun.COM
6027836SJohn.Forte@Sun.COM exit:
6037836SJohn.Forte@Sun.COM return (result);
6047836SJohn.Forte@Sun.COM }
6057836SJohn.Forte@Sun.COM
6067836SJohn.Forte@Sun.COM /*
6077836SJohn.Forte@Sun.COM * Function to open a device
6087836SJohn.Forte@Sun.COM */
6097836SJohn.Forte@Sun.COM int
g_object_open(char * path,int flag)6107836SJohn.Forte@Sun.COM g_object_open(char *path, int flag)
6117836SJohn.Forte@Sun.COM {
6127836SJohn.Forte@Sun.COM int fd = -1, retry = 0;
6137836SJohn.Forte@Sun.COM if (getenv("_LUX_O_DEBUG") != NULL) {
6147836SJohn.Forte@Sun.COM (void) printf(" Object_open:%s ", path);
6157836SJohn.Forte@Sun.COM if (flag & O_WRONLY) {
6167836SJohn.Forte@Sun.COM (void) printf("O_WRONLY,");
6177836SJohn.Forte@Sun.COM } else if (flag & O_RDWR) {
6187836SJohn.Forte@Sun.COM (void) printf("O_RDWR,");
6197836SJohn.Forte@Sun.COM } else {
6207836SJohn.Forte@Sun.COM (void) printf("O_RDONLY,");
6217836SJohn.Forte@Sun.COM }
6227836SJohn.Forte@Sun.COM if (flag & O_NDELAY) {
6237836SJohn.Forte@Sun.COM (void) printf("O_NDELAY,");
6247836SJohn.Forte@Sun.COM }
6257836SJohn.Forte@Sun.COM if (flag & O_APPEND) {
6267836SJohn.Forte@Sun.COM (void) printf("O_APPEND,");
6277836SJohn.Forte@Sun.COM }
6287836SJohn.Forte@Sun.COM if (flag & O_DSYNC) {
6297836SJohn.Forte@Sun.COM (void) printf("O_DSYNC,");
6307836SJohn.Forte@Sun.COM }
6317836SJohn.Forte@Sun.COM if (flag & O_RSYNC) {
6327836SJohn.Forte@Sun.COM (void) printf("O_RSYNC,");
6337836SJohn.Forte@Sun.COM }
6347836SJohn.Forte@Sun.COM if (flag & O_SYNC) {
6357836SJohn.Forte@Sun.COM (void) printf("O_SYNC,");
6367836SJohn.Forte@Sun.COM }
6377836SJohn.Forte@Sun.COM if (flag & O_NOCTTY) {
6387836SJohn.Forte@Sun.COM (void) printf("O_NOCTTY,");
6397836SJohn.Forte@Sun.COM }
6407836SJohn.Forte@Sun.COM if (flag & O_CREAT) {
6417836SJohn.Forte@Sun.COM (void) printf("O_CREAT,");
6427836SJohn.Forte@Sun.COM }
6437836SJohn.Forte@Sun.COM if (flag & O_EXCL) {
6447836SJohn.Forte@Sun.COM (void) printf("O_EXCL,");
6457836SJohn.Forte@Sun.COM }
6467836SJohn.Forte@Sun.COM if (flag & O_TRUNC) {
6477836SJohn.Forte@Sun.COM (void) printf("O_TRUNC,");
6487836SJohn.Forte@Sun.COM }
6497836SJohn.Forte@Sun.COM (void) printf("\n");
6507836SJohn.Forte@Sun.COM }
6517836SJohn.Forte@Sun.COM
6527836SJohn.Forte@Sun.COM /* Open retries introduced due to bugid 4473337 */
6537836SJohn.Forte@Sun.COM errno = 0;
6547836SJohn.Forte@Sun.COM fd = open(path, flag);
6557836SJohn.Forte@Sun.COM while (fd < 0 && retry++ < RETRY_OBJECT_OPEN && (
6567836SJohn.Forte@Sun.COM errno == EBUSY || errno == EAGAIN)) {
6577836SJohn.Forte@Sun.COM O_DPRINTF(" Object_open: Retried:%d %d %s\n",
6587836SJohn.Forte@Sun.COM retry, errno, path);
6597836SJohn.Forte@Sun.COM (void) usleep(WAIT_OBJECT_OPEN);
6607836SJohn.Forte@Sun.COM fd = open(path, flag);
6617836SJohn.Forte@Sun.COM }
6627836SJohn.Forte@Sun.COM if (fd < 0) {
6637836SJohn.Forte@Sun.COM O_DPRINTF(" Object_open: Open failed:%s\n", path);
6647836SJohn.Forte@Sun.COM }
6657836SJohn.Forte@Sun.COM return (fd);
6667836SJohn.Forte@Sun.COM }
6677836SJohn.Forte@Sun.COM
6687836SJohn.Forte@Sun.COM
6697836SJohn.Forte@Sun.COM /*
6707836SJohn.Forte@Sun.COM * Return a pointer to a string telling us the name of the command.
6717836SJohn.Forte@Sun.COM */
6727836SJohn.Forte@Sun.COM char *
g_scsi_find_command_name(int cmd)6737836SJohn.Forte@Sun.COM g_scsi_find_command_name(int cmd)
6747836SJohn.Forte@Sun.COM {
6757836SJohn.Forte@Sun.COM /*
6767836SJohn.Forte@Sun.COM * Names of commands. Must have SCMD_UNKNOWN at end of list.
6777836SJohn.Forte@Sun.COM */
6787836SJohn.Forte@Sun.COM struct scsi_command_name {
6797836SJohn.Forte@Sun.COM int command;
6807836SJohn.Forte@Sun.COM char *name;
6817836SJohn.Forte@Sun.COM } scsi_command_names[29];
6827836SJohn.Forte@Sun.COM
6837836SJohn.Forte@Sun.COM register struct scsi_command_name *c;
6847836SJohn.Forte@Sun.COM
6857836SJohn.Forte@Sun.COM scsi_command_names[0].command = SCMD_TEST_UNIT_READY;
6867836SJohn.Forte@Sun.COM scsi_command_names[0].name = MSGSTR(61, "Test Unit Ready");
6877836SJohn.Forte@Sun.COM
6887836SJohn.Forte@Sun.COM scsi_command_names[1].command = SCMD_FORMAT;
6897836SJohn.Forte@Sun.COM scsi_command_names[1].name = MSGSTR(110, "Format");
6907836SJohn.Forte@Sun.COM
6917836SJohn.Forte@Sun.COM scsi_command_names[2].command = SCMD_REASSIGN_BLOCK;
6927836SJohn.Forte@Sun.COM scsi_command_names[2].name = MSGSTR(77, "Reassign Block");
6937836SJohn.Forte@Sun.COM
6947836SJohn.Forte@Sun.COM scsi_command_names[3].command = SCMD_READ;
6957836SJohn.Forte@Sun.COM scsi_command_names[3].name = MSGSTR(27, "Read");
6967836SJohn.Forte@Sun.COM
6977836SJohn.Forte@Sun.COM scsi_command_names[4].command = SCMD_WRITE;
6987836SJohn.Forte@Sun.COM scsi_command_names[4].name = MSGSTR(54, "Write");
6997836SJohn.Forte@Sun.COM
7007836SJohn.Forte@Sun.COM scsi_command_names[5].command = SCMD_READ_G1;
7017836SJohn.Forte@Sun.COM scsi_command_names[5].name = MSGSTR(79, "Read(10 Byte)");
7027836SJohn.Forte@Sun.COM
7037836SJohn.Forte@Sun.COM scsi_command_names[6].command = SCMD_WRITE_G1;
7047836SJohn.Forte@Sun.COM scsi_command_names[6].name = MSGSTR(51, "Write(10 Byte)");
7057836SJohn.Forte@Sun.COM
7067836SJohn.Forte@Sun.COM scsi_command_names[7].command = SCMD_MODE_SELECT;
7077836SJohn.Forte@Sun.COM scsi_command_names[7].name = MSGSTR(97, "Mode Select");
7087836SJohn.Forte@Sun.COM
7097836SJohn.Forte@Sun.COM scsi_command_names[8].command = SCMD_MODE_SENSE;
7107836SJohn.Forte@Sun.COM scsi_command_names[8].name = MSGSTR(95, "Mode Sense");
7117836SJohn.Forte@Sun.COM
7127836SJohn.Forte@Sun.COM scsi_command_names[9].command = SCMD_REASSIGN_BLOCK;
7137836SJohn.Forte@Sun.COM scsi_command_names[9].name = MSGSTR(77, "Reassign Block");
7147836SJohn.Forte@Sun.COM
7157836SJohn.Forte@Sun.COM scsi_command_names[10].command = SCMD_REQUEST_SENSE;
7167836SJohn.Forte@Sun.COM scsi_command_names[10].name = MSGSTR(74, "Request Sense");
7177836SJohn.Forte@Sun.COM
7187836SJohn.Forte@Sun.COM scsi_command_names[11].command = SCMD_READ_DEFECT_LIST;
7197836SJohn.Forte@Sun.COM scsi_command_names[11].name = MSGSTR(80, "Read Defect List");
7207836SJohn.Forte@Sun.COM
7217836SJohn.Forte@Sun.COM scsi_command_names[12].command = SCMD_INQUIRY;
7227836SJohn.Forte@Sun.COM scsi_command_names[12].name = MSGSTR(102, "Inquiry");
7237836SJohn.Forte@Sun.COM
7247836SJohn.Forte@Sun.COM scsi_command_names[13].command = SCMD_WRITE_BUFFER;
7257836SJohn.Forte@Sun.COM scsi_command_names[13].name = MSGSTR(53, "Write Buffer");
7267836SJohn.Forte@Sun.COM
7277836SJohn.Forte@Sun.COM scsi_command_names[14].command = SCMD_READ_BUFFER;
7287836SJohn.Forte@Sun.COM scsi_command_names[14].name = MSGSTR(82, "Read Buffer");
7297836SJohn.Forte@Sun.COM
7307836SJohn.Forte@Sun.COM scsi_command_names[15].command = SCMD_START_STOP;
7317836SJohn.Forte@Sun.COM scsi_command_names[15].name = MSGSTR(67, "Start/Stop");
7327836SJohn.Forte@Sun.COM
7337836SJohn.Forte@Sun.COM scsi_command_names[16].command = SCMD_RESERVE;
7347836SJohn.Forte@Sun.COM scsi_command_names[16].name = MSGSTR(72, "Reserve");
7357836SJohn.Forte@Sun.COM
7367836SJohn.Forte@Sun.COM scsi_command_names[17].command = SCMD_RELEASE;
7377836SJohn.Forte@Sun.COM scsi_command_names[17].name = MSGSTR(75, "Release");
7387836SJohn.Forte@Sun.COM
7397836SJohn.Forte@Sun.COM scsi_command_names[18].command = SCMD_MODE_SENSE_G1;
7407836SJohn.Forte@Sun.COM scsi_command_names[18].name = MSGSTR(94, "Mode Sense(10 Byte)");
7417836SJohn.Forte@Sun.COM
7427836SJohn.Forte@Sun.COM scsi_command_names[19].command = SCMD_MODE_SELECT_G1;
7437836SJohn.Forte@Sun.COM scsi_command_names[19].name = MSGSTR(96, "Mode Select(10 Byte)");
7447836SJohn.Forte@Sun.COM
7457836SJohn.Forte@Sun.COM scsi_command_names[20].command = SCMD_READ_CAPACITY;
7467836SJohn.Forte@Sun.COM scsi_command_names[20].name = MSGSTR(81, "Read Capacity");
7477836SJohn.Forte@Sun.COM
7487836SJohn.Forte@Sun.COM scsi_command_names[21].command = SCMD_SYNC_CACHE;
7497836SJohn.Forte@Sun.COM scsi_command_names[21].name = MSGSTR(64, "Synchronize Cache");
7507836SJohn.Forte@Sun.COM
7517836SJohn.Forte@Sun.COM scsi_command_names[22].command = SCMD_READ_DEFECT_LIST;
7527836SJohn.Forte@Sun.COM scsi_command_names[22].name = MSGSTR(80, "Read Defect List");
7537836SJohn.Forte@Sun.COM
7547836SJohn.Forte@Sun.COM scsi_command_names[23].command = SCMD_GDIAG;
7557836SJohn.Forte@Sun.COM scsi_command_names[23].name = MSGSTR(108, "Get Diagnostic");
7567836SJohn.Forte@Sun.COM
7577836SJohn.Forte@Sun.COM scsi_command_names[24].command = SCMD_SDIAG;
7587836SJohn.Forte@Sun.COM scsi_command_names[24].name = MSGSTR(69, "Set Diagnostic");
7597836SJohn.Forte@Sun.COM
7607836SJohn.Forte@Sun.COM scsi_command_names[25].command = SCMD_PERS_RESERV_IN;
7617836SJohn.Forte@Sun.COM scsi_command_names[25].name = MSGSTR(10500, "Persistent Reserve In");
7627836SJohn.Forte@Sun.COM
7637836SJohn.Forte@Sun.COM scsi_command_names[26].command = SCMD_PERS_RESERV_OUT;
7647836SJohn.Forte@Sun.COM scsi_command_names[26].name = MSGSTR(10501, "Persistent Reserve out");
7657836SJohn.Forte@Sun.COM
7667836SJohn.Forte@Sun.COM scsi_command_names[27].command = SCMD_LOG_SENSE;
7677836SJohn.Forte@Sun.COM scsi_command_names[27].name = MSGSTR(10502, "Log Sense");
7687836SJohn.Forte@Sun.COM
7697836SJohn.Forte@Sun.COM scsi_command_names[28].command = SCMD_UNKNOWN;
7707836SJohn.Forte@Sun.COM scsi_command_names[28].name = MSGSTR(25, "Unknown");
7717836SJohn.Forte@Sun.COM
7727836SJohn.Forte@Sun.COM
7737836SJohn.Forte@Sun.COM for (c = scsi_command_names; c->command != SCMD_UNKNOWN; c++)
7747836SJohn.Forte@Sun.COM if (c->command == cmd)
7757836SJohn.Forte@Sun.COM break;
7767836SJohn.Forte@Sun.COM return (c->name);
7777836SJohn.Forte@Sun.COM }
7787836SJohn.Forte@Sun.COM
7797836SJohn.Forte@Sun.COM
7807836SJohn.Forte@Sun.COM /*
7817836SJohn.Forte@Sun.COM * Function to create error message containing
7827836SJohn.Forte@Sun.COM * scsi request sense information
7837836SJohn.Forte@Sun.COM */
7847836SJohn.Forte@Sun.COM
7857836SJohn.Forte@Sun.COM void
g_scsi_printerr(struct uscsi_cmd * ucmd,struct scsi_extended_sense * rq,int rqlen,char msg_string[],char * err_string)7867836SJohn.Forte@Sun.COM g_scsi_printerr(struct uscsi_cmd *ucmd, struct scsi_extended_sense *rq,
7877836SJohn.Forte@Sun.COM int rqlen, char msg_string[], char *err_string)
7887836SJohn.Forte@Sun.COM {
7897836SJohn.Forte@Sun.COM int blkno;
7907836SJohn.Forte@Sun.COM
7917836SJohn.Forte@Sun.COM switch (rq->es_key) {
7927836SJohn.Forte@Sun.COM case KEY_NO_SENSE:
7937836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(91, "No sense error"));
7947836SJohn.Forte@Sun.COM break;
7957836SJohn.Forte@Sun.COM case KEY_RECOVERABLE_ERROR:
7967836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(76, "Recoverable error"));
7977836SJohn.Forte@Sun.COM break;
7987836SJohn.Forte@Sun.COM case KEY_NOT_READY:
7997836SJohn.Forte@Sun.COM (void) sprintf(msg_string,
8007836SJohn.Forte@Sun.COM MSGSTR(10503,
8017836SJohn.Forte@Sun.COM "Device Not ready."
8027836SJohn.Forte@Sun.COM " Error: Random Retry Failed: %s\n."),
8037836SJohn.Forte@Sun.COM err_string);
8047836SJohn.Forte@Sun.COM break;
8057836SJohn.Forte@Sun.COM case KEY_MEDIUM_ERROR:
8067836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(99, "Medium error"));
8077836SJohn.Forte@Sun.COM break;
8087836SJohn.Forte@Sun.COM case KEY_HARDWARE_ERROR:
8097836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(106, "Hardware error"));
8107836SJohn.Forte@Sun.COM break;
8117836SJohn.Forte@Sun.COM case KEY_ILLEGAL_REQUEST:
8127836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(103, "Illegal request"));
8137836SJohn.Forte@Sun.COM break;
8147836SJohn.Forte@Sun.COM case KEY_UNIT_ATTENTION:
8157836SJohn.Forte@Sun.COM (void) sprintf(msg_string,
8167836SJohn.Forte@Sun.COM MSGSTR(10504,
8177836SJohn.Forte@Sun.COM "Unit attention."
8187836SJohn.Forte@Sun.COM "Error: Random Retry Failed.\n"));
8197836SJohn.Forte@Sun.COM break;
8207836SJohn.Forte@Sun.COM case KEY_WRITE_PROTECT:
8217836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(52, "Write protect error"));
8227836SJohn.Forte@Sun.COM break;
8237836SJohn.Forte@Sun.COM case KEY_BLANK_CHECK:
8247836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(131, "Blank check error"));
8257836SJohn.Forte@Sun.COM break;
8267836SJohn.Forte@Sun.COM case KEY_VENDOR_UNIQUE:
8277836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(58, "Vendor unique error"));
8287836SJohn.Forte@Sun.COM break;
8297836SJohn.Forte@Sun.COM case KEY_COPY_ABORTED:
8307836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(123, "Copy aborted error"));
8317836SJohn.Forte@Sun.COM break;
8327836SJohn.Forte@Sun.COM case KEY_ABORTED_COMMAND:
8337836SJohn.Forte@Sun.COM (void) sprintf(msg_string,
8347836SJohn.Forte@Sun.COM MSGSTR(10505,
8357836SJohn.Forte@Sun.COM "Aborted command."
8367836SJohn.Forte@Sun.COM " Error: Random Retry Failed.\n"));
8377836SJohn.Forte@Sun.COM break;
8387836SJohn.Forte@Sun.COM case KEY_EQUAL:
8397836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(117, "Equal error"));
8407836SJohn.Forte@Sun.COM break;
8417836SJohn.Forte@Sun.COM case KEY_VOLUME_OVERFLOW:
8427836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(57, "Volume overflow"));
8437836SJohn.Forte@Sun.COM break;
8447836SJohn.Forte@Sun.COM case KEY_MISCOMPARE:
8457836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(98, "Miscompare error"));
8467836SJohn.Forte@Sun.COM break;
8477836SJohn.Forte@Sun.COM case KEY_RESERVED:
8487836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(10506,
8497836SJohn.Forte@Sun.COM "Reserved value found"));
8507836SJohn.Forte@Sun.COM break;
8517836SJohn.Forte@Sun.COM default:
8527836SJohn.Forte@Sun.COM (void) sprintf(msg_string, MSGSTR(59, "Unknown error"));
8537836SJohn.Forte@Sun.COM break;
8547836SJohn.Forte@Sun.COM }
8557836SJohn.Forte@Sun.COM
8567836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
8577836SJohn.Forte@Sun.COM MSGSTR(10507, " during: %s"),
8587836SJohn.Forte@Sun.COM g_scsi_find_command_name(ucmd->uscsi_cdb[0]));
8597836SJohn.Forte@Sun.COM
8607836SJohn.Forte@Sun.COM if (rq->es_valid) {
8617836SJohn.Forte@Sun.COM blkno = (rq->es_info_1 << 24) | (rq->es_info_2 << 16) |
8627836SJohn.Forte@Sun.COM (rq->es_info_3 << 8) | rq->es_info_4;
8637836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
8647836SJohn.Forte@Sun.COM MSGSTR(49, ": block %d (0x%x)"), blkno, blkno);
8657836SJohn.Forte@Sun.COM }
8667836SJohn.Forte@Sun.COM
8677836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)], "\n");
8687836SJohn.Forte@Sun.COM
8697836SJohn.Forte@Sun.COM if (rq->es_add_len >= 6) {
8707836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
8717836SJohn.Forte@Sun.COM MSGSTR(132, " Additional sense: 0x%x ASC Qualifier: 0x%x\n"),
8727836SJohn.Forte@Sun.COM rq->es_add_code, rq->es_qual_code);
8737836SJohn.Forte@Sun.COM /*
8747836SJohn.Forte@Sun.COM * rq->es_add_info[ADD_SENSE_CODE],
8757836SJohn.Forte@Sun.COM * rq->es_add_info[ADD_SENSE_QUAL_CODE]);
8767836SJohn.Forte@Sun.COM */
8777836SJohn.Forte@Sun.COM }
8787836SJohn.Forte@Sun.COM if (rq->es_key == KEY_ILLEGAL_REQUEST) {
8797836SJohn.Forte@Sun.COM string_dump(MSGSTR(47, " cmd: "), (uchar_t *)ucmd,
8807836SJohn.Forte@Sun.COM sizeof (struct uscsi_cmd), HEX_ONLY, msg_string);
8817836SJohn.Forte@Sun.COM string_dump(MSGSTR(48, " cdb: "),
8827836SJohn.Forte@Sun.COM (uchar_t *)ucmd->uscsi_cdb,
8837836SJohn.Forte@Sun.COM ucmd->uscsi_cdblen, HEX_ONLY, msg_string);
8847836SJohn.Forte@Sun.COM }
8857836SJohn.Forte@Sun.COM string_dump(MSGSTR(43, " sense: "),
8867836SJohn.Forte@Sun.COM (uchar_t *)rq, 8 + rq->es_add_len, HEX_ONLY,
8877836SJohn.Forte@Sun.COM msg_string);
8887836SJohn.Forte@Sun.COM rqlen = rqlen; /* not used */
8897836SJohn.Forte@Sun.COM }
8907836SJohn.Forte@Sun.COM
8917836SJohn.Forte@Sun.COM
8927836SJohn.Forte@Sun.COM /*
8937836SJohn.Forte@Sun.COM * Special string dump for error message
8947836SJohn.Forte@Sun.COM */
8957836SJohn.Forte@Sun.COM static void
string_dump(char * hdr,uchar_t * src,int nbytes,int format,char msg_string[])8967836SJohn.Forte@Sun.COM string_dump(char *hdr, uchar_t *src, int nbytes, int format, char msg_string[])
8977836SJohn.Forte@Sun.COM {
8987836SJohn.Forte@Sun.COM int i;
8997836SJohn.Forte@Sun.COM int n;
9007836SJohn.Forte@Sun.COM char *p;
9017836SJohn.Forte@Sun.COM char s[256];
9027836SJohn.Forte@Sun.COM
9037836SJohn.Forte@Sun.COM assert(format == HEX_ONLY || format == HEX_ASCII);
9047836SJohn.Forte@Sun.COM
9057836SJohn.Forte@Sun.COM (void) strcpy(s, hdr);
9067836SJohn.Forte@Sun.COM for (p = s; *p; p++) {
9077836SJohn.Forte@Sun.COM *p = ' ';
9087836SJohn.Forte@Sun.COM }
9097836SJohn.Forte@Sun.COM
9107836SJohn.Forte@Sun.COM p = hdr;
9117836SJohn.Forte@Sun.COM while (nbytes > 0) {
9127836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
9137836SJohn.Forte@Sun.COM "%s", p);
9147836SJohn.Forte@Sun.COM p = s;
9157836SJohn.Forte@Sun.COM n = min(nbytes, BYTES_PER_LINE);
9167836SJohn.Forte@Sun.COM for (i = 0; i < n; i++) {
9177836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
9187836SJohn.Forte@Sun.COM "%02x ",
9197836SJohn.Forte@Sun.COM src[i] & 0xff);
9207836SJohn.Forte@Sun.COM }
9217836SJohn.Forte@Sun.COM if (format == HEX_ASCII) {
9227836SJohn.Forte@Sun.COM for (i = BYTES_PER_LINE-n; i > 0; i--) {
9237836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
9247836SJohn.Forte@Sun.COM " ");
9257836SJohn.Forte@Sun.COM }
9267836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
9277836SJohn.Forte@Sun.COM " ");
9287836SJohn.Forte@Sun.COM for (i = 0; i < n; i++) {
9297836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)],
9307836SJohn.Forte@Sun.COM "%c",
9317836SJohn.Forte@Sun.COM isprint(src[i]) ? src[i] : '.');
9327836SJohn.Forte@Sun.COM }
9337836SJohn.Forte@Sun.COM }
9347836SJohn.Forte@Sun.COM (void) sprintf(&msg_string[strlen(msg_string)], "\n");
9357836SJohn.Forte@Sun.COM nbytes -= n;
9367836SJohn.Forte@Sun.COM src += n;
9377836SJohn.Forte@Sun.COM }
9387836SJohn.Forte@Sun.COM }
9397836SJohn.Forte@Sun.COM
9407836SJohn.Forte@Sun.COM
9417836SJohn.Forte@Sun.COM
9427836SJohn.Forte@Sun.COM /*
9437836SJohn.Forte@Sun.COM * This routine is a wrapper for malloc. It allocates pre-zeroed space,
9447836SJohn.Forte@Sun.COM * and checks the return value so the caller doesn't have to.
9457836SJohn.Forte@Sun.COM */
9467836SJohn.Forte@Sun.COM void *
g_zalloc(int count)9477836SJohn.Forte@Sun.COM g_zalloc(int count)
9487836SJohn.Forte@Sun.COM {
9497836SJohn.Forte@Sun.COM void *ptr;
9507836SJohn.Forte@Sun.COM
9517836SJohn.Forte@Sun.COM ptr = (void *) calloc(1, (unsigned)count);
9527836SJohn.Forte@Sun.COM A_DPRINTF(" g_zalloc: Allocated 0x%x bytes "
9537836SJohn.Forte@Sun.COM "at 0x%x\n", count, ptr);
9547836SJohn.Forte@Sun.COM
9557836SJohn.Forte@Sun.COM return (ptr);
9567836SJohn.Forte@Sun.COM }
9577836SJohn.Forte@Sun.COM
9587836SJohn.Forte@Sun.COM /*
9597836SJohn.Forte@Sun.COM * Open up the i18n catalog.
9607836SJohn.Forte@Sun.COM * Returns:
9617836SJohn.Forte@Sun.COM * 0 = O.K.
9627836SJohn.Forte@Sun.COM * -1 = Failed (Will revert to default strings)
9637836SJohn.Forte@Sun.COM */
9647836SJohn.Forte@Sun.COM int
g_i18n_catopen(void)9657836SJohn.Forte@Sun.COM g_i18n_catopen(void)
9667836SJohn.Forte@Sun.COM {
9677836SJohn.Forte@Sun.COM static int fileopen = 0;
9687836SJohn.Forte@Sun.COM static mutex_t mp;
9697836SJohn.Forte@Sun.COM
9707836SJohn.Forte@Sun.COM if (setlocale(LC_ALL, "") == NULL) {
9717836SJohn.Forte@Sun.COM (void) fprintf(stderr,
9727836SJohn.Forte@Sun.COM "Cannot operate in the locale requested. "
9737836SJohn.Forte@Sun.COM "Continuing in the default C locale\n");
9747836SJohn.Forte@Sun.COM }
9757836SJohn.Forte@Sun.COM if (mutex_lock(&mp) != 0) {
9767836SJohn.Forte@Sun.COM return (-1);
9777836SJohn.Forte@Sun.COM }
9787836SJohn.Forte@Sun.COM if (!fileopen) {
9797836SJohn.Forte@Sun.COM l_catd = catopen("a5k_g_fc_i18n_cat", NL_CAT_LOCALE);
9807836SJohn.Forte@Sun.COM if (l_catd == (nl_catd)-1) {
9817836SJohn.Forte@Sun.COM (void) mutex_unlock(&mp);
9827836SJohn.Forte@Sun.COM return (-1);
9837836SJohn.Forte@Sun.COM }
9847836SJohn.Forte@Sun.COM fileopen = 1;
9857836SJohn.Forte@Sun.COM }
9867836SJohn.Forte@Sun.COM (void) mutex_unlock(&mp);
9877836SJohn.Forte@Sun.COM return (0);
9887836SJohn.Forte@Sun.COM }
9897836SJohn.Forte@Sun.COM
9907836SJohn.Forte@Sun.COM /* Macro used by g_get_path_type() */
9917836SJohn.Forte@Sun.COM #define GetMatch(s_ptr) \
9927836SJohn.Forte@Sun.COM for (found = 0, search_arr_ptr = s_ptr; \
9937836SJohn.Forte@Sun.COM search_arr_ptr->string != NULL; \
9947836SJohn.Forte@Sun.COM search_arr_ptr++) {\
9957836SJohn.Forte@Sun.COM if (strstr(path_ptr, search_arr_ptr->string) != NULL) {\
9967836SJohn.Forte@Sun.COM found = 1;\
9977836SJohn.Forte@Sun.COM break;\
9987836SJohn.Forte@Sun.COM }\
9997836SJohn.Forte@Sun.COM }
10007836SJohn.Forte@Sun.COM
10017836SJohn.Forte@Sun.COM /*
10027836SJohn.Forte@Sun.COM * Input : A NULL terminated string
10037836SJohn.Forte@Sun.COM * This string is checked to be an absolute device path
10047836SJohn.Forte@Sun.COM * Output :
10057836SJohn.Forte@Sun.COM * The FCA type and Xport type if found in the path on success
10067836SJohn.Forte@Sun.COM * 0 on Failure
10077836SJohn.Forte@Sun.COM *
10087836SJohn.Forte@Sun.COM * Examples of valid device strings :
10097836SJohn.Forte@Sun.COM *
10107836SJohn.Forte@Sun.COM * Non Fabric FC driver :
10117836SJohn.Forte@Sun.COM * /devices/io-unit@f,e0200000/sbi@0,0/SUNW,socal@1,0/sf@1,0:ctlr
10127836SJohn.Forte@Sun.COM * /devices/io-unit@f,e2200000/sbi@0,0/SUNW,socal@3,0/sf@0,0/ssd@20,0:c,raw
10137836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@0,0/sf@0,0:devctl
10147836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@2,0/sf@1,0/ssd@w2200002037110cbf,0:b,raw
10157836SJohn.Forte@Sun.COM * /devices/pci@1f,4000/SUNW,ifp@4:devctl
10167836SJohn.Forte@Sun.COM * /devices/pci@1f,4000/SUNW,ifp@2/ssd@w2100002037049ba0,0:c,raw
10177836SJohn.Forte@Sun.COM * /devices/pci@6,4000/pci@2/SUNW,ifp@5/ssd@w210000203708b44f,0:c,raw
10187836SJohn.Forte@Sun.COM *
10197836SJohn.Forte@Sun.COM * Fabric FC driver (fp) :
10207836SJohn.Forte@Sun.COM * - offical device path for Qlogic 2202 with proper FCODE
10217836SJohn.Forte@Sun.COM * as of 12/99.
10227836SJohn.Forte@Sun.COM * /devices/pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0:devctl
10237836SJohn.Forte@Sun.COM * /devices/pci@e,2000/pci@2/SUNW,qlc@4/fp@0,0:devctl
10247836SJohn.Forte@Sun.COM *
10257836SJohn.Forte@Sun.COM */
10267836SJohn.Forte@Sun.COM uint_t
g_get_path_type(char * path)10277836SJohn.Forte@Sun.COM g_get_path_type(char *path)
10287836SJohn.Forte@Sun.COM {
10297836SJohn.Forte@Sun.COM uint_t path_type = 0;
10307836SJohn.Forte@Sun.COM int i = 0, pathcnt = 1;
10317836SJohn.Forte@Sun.COM char *path_ptr = path;
10327836SJohn.Forte@Sun.COM struct str_type *search_arr_ptr; /* updated by GetMatch macro */
10337836SJohn.Forte@Sun.COM char found; /* Updated by GetMatch marco */
10347836SJohn.Forte@Sun.COM char drvr_path1[MAXPATHLEN];
10357836SJohn.Forte@Sun.COM mp_pathlist_t pathlist;
10367836SJohn.Forte@Sun.COM int p_on = 0, p_st = 0;
10377836SJohn.Forte@Sun.COM
10387836SJohn.Forte@Sun.COM /* Path passed must be an absolute device path */
10397836SJohn.Forte@Sun.COM if (strncmp(path_ptr, DEV_PREFIX, DEV_PREFIX_LEN) ||
10407836SJohn.Forte@Sun.COM (strlen(path_ptr) == DEV_PREFIX_LEN)) {
10417836SJohn.Forte@Sun.COM return (0); /* Invalid path */
10427836SJohn.Forte@Sun.COM }
10437836SJohn.Forte@Sun.COM
10447836SJohn.Forte@Sun.COM /* if mpxio device, need to convert from vhci to phci */
10457836SJohn.Forte@Sun.COM if (strstr(path, SCSI_VHCI)) {
10467836SJohn.Forte@Sun.COM (void) strcpy(drvr_path1, path);
10477836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path1, &pathlist)) {
10487836SJohn.Forte@Sun.COM return (0);
10497836SJohn.Forte@Sun.COM }
10507836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
10517836SJohn.Forte@Sun.COM p_on = p_st = 0;
10527836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
10537836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
10547836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
10557836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
10567836SJohn.Forte@Sun.COM p_on = i;
10577836SJohn.Forte@Sun.COM break;
10587836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
10597836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
10607836SJohn.Forte@Sun.COM p_st = i;
10617836SJohn.Forte@Sun.COM }
10627836SJohn.Forte@Sun.COM }
10637836SJohn.Forte@Sun.COM }
10647836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
10657836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
10667836SJohn.Forte@Sun.COM /* on_line path */
10677836SJohn.Forte@Sun.COM (void) strcpy(drvr_path1,
10687836SJohn.Forte@Sun.COM pathlist.path_info[p_on].path_hba);
10697836SJohn.Forte@Sun.COM } else {
10707836SJohn.Forte@Sun.COM /* standby or path0 */
10717836SJohn.Forte@Sun.COM (void) strcpy(drvr_path1,
10727836SJohn.Forte@Sun.COM pathlist.path_info[p_st].path_hba);
10737836SJohn.Forte@Sun.COM }
10747836SJohn.Forte@Sun.COM free(pathlist.path_info);
10757836SJohn.Forte@Sun.COM path_ptr = drvr_path1;
10767836SJohn.Forte@Sun.COM }
10777836SJohn.Forte@Sun.COM
10787836SJohn.Forte@Sun.COM GetMatch(ValidBusStrings);
10797836SJohn.Forte@Sun.COM if (found == 0) {
10807836SJohn.Forte@Sun.COM /* No valid bus string - so not a valid path */
10817836SJohn.Forte@Sun.COM return (0);
10827836SJohn.Forte@Sun.COM }
10837836SJohn.Forte@Sun.COM
10847836SJohn.Forte@Sun.COM GetMatch(ValidFCAstrings); /* Check for a valid FCA string */
10857836SJohn.Forte@Sun.COM if (found != 0) {
10867836SJohn.Forte@Sun.COM path_type |= search_arr_ptr->type;
10877836SJohn.Forte@Sun.COM }
10887836SJohn.Forte@Sun.COM
10897836SJohn.Forte@Sun.COM /*
10907836SJohn.Forte@Sun.COM * continue to check xport even without valid FCA string.
10917836SJohn.Forte@Sun.COM * This is to support 3rd party FCA vendor on Leadville stack.
10927836SJohn.Forte@Sun.COM */
10937836SJohn.Forte@Sun.COM GetMatch(ValidXportStrings); /* Check for a valid transport str */
10947836SJohn.Forte@Sun.COM if (found == 0) {
10957836SJohn.Forte@Sun.COM return (path_type);
10967836SJohn.Forte@Sun.COM } else {
10977836SJohn.Forte@Sun.COM /*
10987836SJohn.Forte@Sun.COM * if leadville tranport is detected and fca is not set yet,
10997836SJohn.Forte@Sun.COM * set fca flag to generic FC_FCA_MASK.
11007836SJohn.Forte@Sun.COM */
11017836SJohn.Forte@Sun.COM if ((search_arr_ptr->type == FC_GEN_XPORT) &&
11027836SJohn.Forte@Sun.COM (!(path_type & FC_FCA_MASK))) {
11037836SJohn.Forte@Sun.COM path_type |= FC_FCA_MASK;
11047836SJohn.Forte@Sun.COM }
11057836SJohn.Forte@Sun.COM }
11067836SJohn.Forte@Sun.COM path_type |= search_arr_ptr->type;
11077836SJohn.Forte@Sun.COM
11087836SJohn.Forte@Sun.COM /*
11097836SJohn.Forte@Sun.COM * A quick sanity check to make sure that we dont have
11107836SJohn.Forte@Sun.COM * a combination that is not possible
11117836SJohn.Forte@Sun.COM */
11127836SJohn.Forte@Sun.COM if (((path_type & (FC4_FCA_MASK | FC_XPORT_MASK)) ==
11137836SJohn.Forte@Sun.COM path_type) ||
11147836SJohn.Forte@Sun.COM ((path_type & (FC_FCA_MASK | FC4_XPORT_MASK)) ==
11157836SJohn.Forte@Sun.COM path_type)) {
11167836SJohn.Forte@Sun.COM path_type = 0;
11177836SJohn.Forte@Sun.COM }
11187836SJohn.Forte@Sun.COM
11197836SJohn.Forte@Sun.COM return (path_type);
11207836SJohn.Forte@Sun.COM }
11217836SJohn.Forte@Sun.COM
11227836SJohn.Forte@Sun.COM
11237836SJohn.Forte@Sun.COM /*
11247836SJohn.Forte@Sun.COM * g_get_port_path(char *, portlist_t *)
11257836SJohn.Forte@Sun.COM * Purpose: Find all port nexus paths for a particular driver
11267836SJohn.Forte@Sun.COM * Input: portdrvr
11277836SJohn.Forte@Sun.COM * set to name of driver for which to find the paths
11287836SJohn.Forte@Sun.COM * Output: portlist
11297836SJohn.Forte@Sun.COM * allocated structure to hold paths found
11307836SJohn.Forte@Sun.COM * user must call g_free_portlist(portlist_t *) to
11317836SJohn.Forte@Sun.COM * free allocated memory
11327836SJohn.Forte@Sun.COM */
11337836SJohn.Forte@Sun.COM int
g_get_port_path(char * portdrvr,portlist_t * portlist)11347836SJohn.Forte@Sun.COM g_get_port_path(char *portdrvr, portlist_t *portlist)
11357836SJohn.Forte@Sun.COM {
11367836SJohn.Forte@Sun.COM di_node_t root;
11377836SJohn.Forte@Sun.COM di_node_t node;
11387836SJohn.Forte@Sun.COM di_minor_t minor_node;
11397836SJohn.Forte@Sun.COM char hbapathfound[MAXPATHLEN];
11407836SJohn.Forte@Sun.COM char *tmppath;
11417836SJohn.Forte@Sun.COM struct stat buf;
11427836SJohn.Forte@Sun.COM
11437836SJohn.Forte@Sun.COM /* return invalid argument if *portdrvr or *portlist is NULL */
11447836SJohn.Forte@Sun.COM if ((portdrvr == NULL) || (portlist == NULL)) {
11457836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
11467836SJohn.Forte@Sun.COM }
11477836SJohn.Forte@Sun.COM
11487836SJohn.Forte@Sun.COM /* Create a snapshot of the kernel device tree */
11497836SJohn.Forte@Sun.COM root = di_init("/", DINFOCPYALL);
11507836SJohn.Forte@Sun.COM if (root == DI_NODE_NIL) {
11517836SJohn.Forte@Sun.COM return (L_DEV_SNAPSHOT_FAILED);
11527836SJohn.Forte@Sun.COM }
11537836SJohn.Forte@Sun.COM
11547836SJohn.Forte@Sun.COM /* point to first node which matches portdrvr */
11557836SJohn.Forte@Sun.COM node = di_drv_first_node(portdrvr, root);
11567836SJohn.Forte@Sun.COM if (node == DI_NODE_NIL) {
11577836SJohn.Forte@Sun.COM /*
11587836SJohn.Forte@Sun.COM * Could not find driver node
11597836SJohn.Forte@Sun.COM */
11607836SJohn.Forte@Sun.COM (void) di_fini(root);
11617836SJohn.Forte@Sun.COM if (errno == EINVAL)
11627836SJohn.Forte@Sun.COM return (L_PORT_DRIVER_NOT_FOUND);
11637836SJohn.Forte@Sun.COM else
11647836SJohn.Forte@Sun.COM return (L_PHYS_PATH_NOT_FOUND);
11657836SJohn.Forte@Sun.COM }
11667836SJohn.Forte@Sun.COM
11677836SJohn.Forte@Sun.COM while (node) {
11687836SJohn.Forte@Sun.COM /* point to first minor node which matches node */
11697836SJohn.Forte@Sun.COM minor_node = di_minor_next(node, DI_MINOR_NIL);
11707836SJohn.Forte@Sun.COM
11717836SJohn.Forte@Sun.COM /* if we have a minor node use it */
11727836SJohn.Forte@Sun.COM while (minor_node) {
11737836SJohn.Forte@Sun.COM /*
11747836SJohn.Forte@Sun.COM * Is this a devctl or pseudo node?
11757836SJohn.Forte@Sun.COM * If not, skip it.
11767836SJohn.Forte@Sun.COM * Soc+ HBA port device paths such as:
11777836SJohn.Forte@Sun.COM * /devices/sbus@2,0/SUNW,socal@d,10000:0
11787836SJohn.Forte@Sun.COM * are pseudo nodes as of S9 so we need to
11797836SJohn.Forte@Sun.COM * include those as well.
11807836SJohn.Forte@Sun.COM */
11817836SJohn.Forte@Sun.COM if (di_minor_nodetype(minor_node) &&
11827836SJohn.Forte@Sun.COM (strcmp(di_minor_nodetype(minor_node),
11837836SJohn.Forte@Sun.COM DDI_NT_NEXUS) &&
11847836SJohn.Forte@Sun.COM strcmp(di_minor_nodetype(minor_node),
11857836SJohn.Forte@Sun.COM DDI_PSEUDO))) {
11867836SJohn.Forte@Sun.COM minor_node = di_minor_next(node, minor_node);
11877836SJohn.Forte@Sun.COM continue;
11887836SJohn.Forte@Sun.COM }
11897836SJohn.Forte@Sun.COM /*
11907836SJohn.Forte@Sun.COM * Prepend '/devices' to path
11917836SJohn.Forte@Sun.COM * Note: The path returned from di_devfs_path
11927836SJohn.Forte@Sun.COM * does NOT begin with '/devices'.
11937836SJohn.Forte@Sun.COM * '/devices' is considered a mount point
11947836SJohn.Forte@Sun.COM */
11957836SJohn.Forte@Sun.COM strcpy(hbapathfound, "/devices");
11967836SJohn.Forte@Sun.COM tmppath = di_devfs_path(node);
11977836SJohn.Forte@Sun.COM strcat(hbapathfound, tmppath);
11987836SJohn.Forte@Sun.COM (void) free(tmppath);
11997836SJohn.Forte@Sun.COM strcat(hbapathfound, ":");
12007836SJohn.Forte@Sun.COM strcat(hbapathfound, di_minor_name(minor_node));
12017836SJohn.Forte@Sun.COM /*
12027836SJohn.Forte@Sun.COM * Verify that the path is validly constructed
12037836SJohn.Forte@Sun.COM */
12047836SJohn.Forte@Sun.COM if ((stat(hbapathfound, (struct stat *)&buf)) < 0) {
12057836SJohn.Forte@Sun.COM (void) di_fini(root);
12067836SJohn.Forte@Sun.COM return (L_STAT_ERROR);
12077836SJohn.Forte@Sun.COM }
12087836SJohn.Forte@Sun.COM /* allocate memory and copy constructed path */
12097836SJohn.Forte@Sun.COM if ((portlist->hbacnt > MAX_HBA_PORT - 1) ||
12107836SJohn.Forte@Sun.COM ((portlist->physpath[portlist->hbacnt] =
12117836SJohn.Forte@Sun.COM (char *)malloc(MAXPATHLEN)) == NULL)) {
12127836SJohn.Forte@Sun.COM (void) di_fini(root);
12137836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
12147836SJohn.Forte@Sun.COM }
12157836SJohn.Forte@Sun.COM strcpy(portlist->physpath[portlist->hbacnt],
12167836SJohn.Forte@Sun.COM hbapathfound);
12177836SJohn.Forte@Sun.COM portlist->hbacnt++;
12187836SJohn.Forte@Sun.COM minor_node = di_minor_next(node, minor_node);
12197836SJohn.Forte@Sun.COM }
12207836SJohn.Forte@Sun.COM node = di_drv_next_node(node);
12217836SJohn.Forte@Sun.COM }
12227836SJohn.Forte@Sun.COM /*
12237836SJohn.Forte@Sun.COM * Destroy the snapshot and return
12247836SJohn.Forte@Sun.COM */
12257836SJohn.Forte@Sun.COM (void) di_fini(root);
12267836SJohn.Forte@Sun.COM return (0);
12277836SJohn.Forte@Sun.COM }
12287836SJohn.Forte@Sun.COM
12297836SJohn.Forte@Sun.COM /*
12307836SJohn.Forte@Sun.COM * Free the allocated portlist structure
12317836SJohn.Forte@Sun.COM */
12327836SJohn.Forte@Sun.COM void
g_free_portlist(portlist_t * portlist)12337836SJohn.Forte@Sun.COM g_free_portlist(portlist_t *portlist)
12347836SJohn.Forte@Sun.COM {
12357836SJohn.Forte@Sun.COM int x = 0;
12367836SJohn.Forte@Sun.COM
12377836SJohn.Forte@Sun.COM /* return if portlist is NULL */
12387836SJohn.Forte@Sun.COM if (portlist == NULL) {
12397836SJohn.Forte@Sun.COM return;
12407836SJohn.Forte@Sun.COM }
12417836SJohn.Forte@Sun.COM
12427836SJohn.Forte@Sun.COM for (x = 0; x < portlist->hbacnt; x++) {
12437836SJohn.Forte@Sun.COM if (portlist->physpath[x] != NULL) {
12447836SJohn.Forte@Sun.COM free(portlist->physpath[x]);
12457836SJohn.Forte@Sun.COM }
12467836SJohn.Forte@Sun.COM }
12477836SJohn.Forte@Sun.COM }
12487836SJohn.Forte@Sun.COM
12497836SJohn.Forte@Sun.COM /*
12507836SJohn.Forte@Sun.COM * Check VID/PID against enclosure disk table
12517836SJohn.Forte@Sun.COM */
12527836SJohn.Forte@Sun.COM boolean_t
g_enclDiskChk(char * vid,char * pid)12537836SJohn.Forte@Sun.COM g_enclDiskChk(char *vid, char *pid)
12547836SJohn.Forte@Sun.COM {
12557836SJohn.Forte@Sun.COM int i;
12567836SJohn.Forte@Sun.COM for (i = 0; enclDiskTbl[i].vid; i++) {
12577836SJohn.Forte@Sun.COM if ((strncmp(vid, enclDiskTbl[i].vid,
12587836SJohn.Forte@Sun.COM strlen(enclDiskTbl[i].vid)) == 0) &&
12597836SJohn.Forte@Sun.COM (strncmp(pid, enclDiskTbl[i].pid,
12607836SJohn.Forte@Sun.COM strlen(enclDiskTbl[i].pid)) == 0)) {
12617836SJohn.Forte@Sun.COM return (B_TRUE);
12627836SJohn.Forte@Sun.COM }
12637836SJohn.Forte@Sun.COM }
12647836SJohn.Forte@Sun.COM return (B_FALSE);
12657836SJohn.Forte@Sun.COM }
1266