diff options
Diffstat (limited to 'usr/src/cmd/luxadm/adm.c')
-rw-r--r-- | usr/src/cmd/luxadm/adm.c | 1104 |
1 files changed, 1104 insertions, 0 deletions
diff --git a/usr/src/cmd/luxadm/adm.c b/usr/src/cmd/luxadm/adm.c new file mode 100644 index 0000000000..cb2ad51b43 --- /dev/null +++ b/usr/src/cmd/luxadm/adm.c @@ -0,0 +1,1104 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + + + +/*LINTLIBRARY*/ + + +/* + * Administration program for SENA + * subsystems and individual FC_AL devices. + */ + +/* + * I18N message number ranges + * This file: 2000 - 2999 + * Shared common messages: 1 - 1999 + */ + +/* #define _POSIX_SOURCE 1 */ + +/* + * These defines are used to map instance number from sf minor node. + * They are copied from SF_INST_SHIFT4MINOR and SF_MINOR2INST in sfvar.h. + * sfvar.h is not clean for userland use. + * When it is cleaned up, these defines will be removed and sfvar.h + * will be included in luxadm.h header file. + */ +#define LUX_SF_INST_SHIFT4MINOR 6 +#define LUX_SF_MINOR2INST(x) (x >> LUX_SF_INST_SHIFT4MINOR) + +/* Includes */ +#include <stdlib.h> +#include <stdio.h> +#include <sys/file.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <strings.h> +#include <sys/stat.h> +#include <dirent.h> +#include <limits.h> +#include <stdarg.h> +#include <termio.h> /* For password */ +#include <sys/scsi/scsi.h> + +#include "common.h" +#include "luxadm.h" + + +/* Global variables */ +char *dtype[16]; /* setting a global for later use. */ +char *whoami; +int Options; +const int OPTION_A = 0x00000001; +const int OPTION_B = 0x00000002; +const int OPTION_C = 0x00000004; +const int OPTION_D = 0x00000008; +const int OPTION_E = 0x00000010; +const int OPTION_F = 0x00000020; +const int OPTION_L = 0x00000040; +const int OPTION_P = 0x00000080; +const int OPTION_R = 0x00000100; +const int OPTION_T = 0x00000200; +const int OPTION_V = 0x00000400; +const int OPTION_Z = 0x00001000; +const int OPTION_Y = 0x00002000; +const int OPTION_CAPF = 0x00004000; +const int PVERBOSE = 0x00008000; +const int SAVE = 0x00010000; +const int EXPERT = 0x00020000; + +/* + * Given a pointer to a character array, print the character array. + * the character array will not necesarily be NULL terminated. + * + * Inputs: + * size - the max number of characters to print + * fill_flag - flag when set fills all NULL characters with spaces + * Returns: + * N/A + */ +void +print_chars(uchar_t *buffer, int size, int fill_flag) +{ + +int i; + + for (i = 0; i < size; i++) { + if (buffer[i]) + (void) fprintf(stdout, "%c", buffer[i]); + else if (fill_flag) + (void) fprintf(stdout, " "); + else + return; + } +} + +/* + * Name : memstrstr + * Input : pointer to buf1, pointer to buf2, size of buf1, size of buf2 + * Returns : + * Pointer to start of contents-of-buf2 in buf1 if it is found + * NULL if buf1 does not contain contents of buf2 + * Synopsis: + * This function works similar to strstr(). The difference is that null + * characters in the buffer are treated like any other character. So, buf1 + * and buf2 can have embedded null characters in them. + */ +static char * +memstrstr(char *s1, char *s2, int size1, int size2) +{ + int count1, count2; + char *s1_ptr, *s2_ptr; + + count1 = size1; count2 = size2; + s1_ptr = s1; s2_ptr = s2; + + if (size2 == 0) + return (s1); + + while (count1--) { + if (*s1_ptr++ == *s2_ptr++) { + if (--count2 == 0) + return (s1_ptr - size2); + continue; + } + count2 = size2; + s2_ptr = s2; + } + + return (NULL); +} + + +/* + * Download host bus adapter FCode to all supported cards. + * + * Specify a directory that holds the FCode files, or + * it will use the default dir. Each file is dealt to + * the appropriate function. + * + * -p prints current versions only, -d specifies a directory to load + */ +static int +adm_fcode(int verbose, char *dir) +{ + struct stat statbuf; + struct dirent *dirp; + DIR *dp; + int fp; + char fbuf[BUFSIZ]; + char file[MAXPATHLEN]; + int retval = 0, strfound = 0; + char manf[BUFSIZ]; + + /* Find all adapters and print the current FCode version */ + if (Options & OPTION_P) { + +/* SOCAL (SBus) adapters are not supported on x86 */ +#ifndef __x86 + if (verbose) { + (void) fprintf(stdout, + MSGSTR(2215, "\n Searching for FC100/S cards:\n")); + } + retval += fcal_update(Options & PVERBOSE, NULL); +#endif + + if (verbose) { + (void) fprintf(stdout, + MSGSTR(2216, "\n Searching for FC100/P, FC100/2P cards:\n")); + } + retval += q_qlgc_update(Options & PVERBOSE, NULL); + if (verbose) { + (void) fprintf(stdout, + MSGSTR(2503, "\n Searching for Emulex cards:\n")); + } + retval += emulex_update(NULL); + + /* Send files to the correct function for loading to the HBA */ + } else { + + if (!dir) { + (void) fprintf(stdout, MSGSTR(2251, + " Location of Fcode not specified.\n")); + return (1); + + } else if (verbose) { + (void) fprintf(stdout, MSGSTR(2217, + " Using directory %s"), dir); + } + if (lstat(dir, &statbuf) < 0) { + (void) fprintf(stderr, MSGSTR(134, + "%s: lstat() failed - %s\n"), + dir, strerror(errno)); + return (1); + } + if (S_ISDIR(statbuf.st_mode) == 0) { + (void) fprintf(stderr, + MSGSTR(2218, "Error: %s is not a directory.\n"), dir); + return (1); + } + if ((dp = opendir(dir)) == NULL) { + (void) fprintf(stderr, MSGSTR(2219, + " Error Cannot open directory %s\n"), dir); + return (1); + } + + while ((dirp = readdir(dp)) != NULL) { + if (strcmp(dirp->d_name, ".") == 0 || + strcmp(dirp->d_name, "..") == 0) { + continue; + } + sprintf(file, "%s/%s", dir, dirp->d_name); + + if ((fp = open(file, O_RDONLY)) < 0) { + (void) fprintf(stderr, + MSGSTR(2220, + "Error: open() failed to open file " + "%s\n"), file); + /* + * We should just issue an error message and + * make an attempt on the next file, + * and the open error is still an error + * so the retval should be incremented + */ + retval++; + continue; + } + while ((read(fp, fbuf, BUFSIZ)) > 0) { + if (memstrstr(fbuf, "SUNW,socal", + BUFSIZ, strlen("SUNW,socal")) + != NULL) { + (void) fprintf(stdout, MSGSTR(2221, + "\n Using file: %s\n"), file); + retval += fcal_update( + Options & PVERBOSE, file); + strfound++; + break; + } else if ((memstrstr(fbuf, "SUNW,ifp", + BUFSIZ, strlen("SUNW,ifp")) + != NULL) || + (memstrstr(fbuf, "SUNW,qlc", + BUFSIZ, strlen("SUNW,qlc")) + != NULL)) { + (void) fprintf(stdout, MSGSTR(2221, + "\n Using file: %s\n"), file); + retval += q_qlgc_update( + Options & PVERBOSE, file); + strfound++; + break; + } + } + if (!strfound) { + /* check to see if this is an emulex fcode */ + memset(manf, 0, sizeof (manf)); + if ((emulex_fcode_reader(fp, "manufacturer", + manf, + sizeof (manf)) == 0) && + (strncmp(manf, "Emulex", sizeof (manf)) + == 0)) { + retval += emulex_update(file); + strfound = 0; + } else { + (void) fprintf(stderr, MSGSTR(2222, + "\nError: %s is not a valid Fcode " + "file.\n"), file); + retval++; + } + } else { + strfound = 0; + } + close(fp); + } + closedir(dp); + } + return (retval); +} + +/* + * Definition of getaction() routine which does keyword parsing + * + * Operation: A character string containing the ascii cmd to be + * parsed is passed in along with an array of structures. + * The 1st struct element is a recognizable cmd string, the second + * is the minimum number of characters from the start of this string + * to succeed on a match. For example, { "offline", 3, ONLINE } + * will match "off", "offli", "offline", but not "of" nor "offlinebarf" + * The third element is the {usually but not necessarily unique} + * integer to return on a successful match. Note: compares are cAsE insensitive. + * + * To change, extend or use this utility, just add or remove appropriate + * lines in the structure initializer below and in the #define s for the + * return values. + * + * N O T E + * Do not change the minimum number of characters to produce + * a match as someone may be building scripts that use this + * feature. + */ +struct keyword { + char *match; /* Character String to match against */ + int num_match; /* Minimum chars to produce a match */ + int ret_code; /* Value to return on a match */ +}; + +static struct keyword Keywords[] = { + {"display", 2, DISPLAY}, + {"download", 3, DOWNLOAD}, + {"enclosure_names", 2, ENCLOSURE_NAMES}, + {"failover", 3, FAILOVER}, + {"fcal_s_download", 4, FCAL_UPDATE}, + {"fcode_download", 4, FCODE_UPDATE}, + {"inquiry", 2, INQUIRY}, + {"insert_device", 3, INSERT_DEVICE}, + {"led", 3, LED}, + {"led_on", 5, LED_ON}, + {"led_off", 5, LED_OFF}, + {"led_blink", 5, LED_BLINK}, + {"password", 2, PASSWORD}, + {"power_on", 8, POWER_ON}, + {"power_off", 9, POWER_OFF}, + {"probe", 2, PROBE}, + {"qlgc_s_download", 4, QLGC_UPDATE}, + {"remove_device", 3, REMOVE_DEVICE}, + {"reserve", 5, RESERVE}, + {"release", 3, RELEASE}, + {"set_boot_dev", 5, SET_BOOT_DEV}, + {"start", 3, START}, + {"stop", 3, STOP}, + {"rdls", 2, RDLS}, + {"bypass", 3, BYPASS}, + {"enable", 3, ENABLE}, + {"p_offline", 4, LUX_P_OFFLINE}, + {"p_online", 4, LUX_P_ONLINE}, + {"forcelip", 2, FORCELIP}, + {"dump", 2, DUMP}, + {"check_file", 2, CHECK_FILE}, + {"dump_map", 2, DUMP_MAP}, + {"sysdump", 5, SYSDUMP}, + {"port", 4, PORT}, + {"external_loopback", 12, EXT_LOOPBACK}, + {"internal_loopback", 12, INT_LOOPBACK}, + {"no_loopback", 11, NO_LOOPBACK}, + {"version", 2, VERSION}, + {"create_fabric_device", 2, CREATE_FAB}, + /* hotplugging device operations */ + {"online", 2, DEV_ONLINE}, + {"offline", 2, DEV_OFFLINE}, + {"dev_getstate", 5, DEV_GETSTATE}, + {"dev_reset", 5, DEV_RESET}, + /* hotplugging bus operations */ + {"bus_quiesce", 5, BUS_QUIESCE}, + {"bus_unquiesce", 5, BUS_UNQUIESCE}, + {"bus_getstate", 5, BUS_GETSTATE}, + {"bus_reset", 9, BUS_RESET}, + {"bus_resetall", 12, BUS_RESETALL}, + /* hotplugging "helper" subcommands */ + { NULL, 0, 0} +}; + +#ifndef EOK +static const int EOK = 0; /* errno.h type success return code */ +#endif + + +/* + * function getaction() takes a character string, cmd, and + * tries to match it against a passed structure of known cmd + * character strings. If a match is found, corresponding code + * is returned in retval. Status returns as follows: + * EOK = Match found, look for cmd's code in retval + * EFAULT = One of passed parameters was bad + * EINVAL = cmd did not match any in list + */ +static int +getaction(char *cmd, struct keyword *matches, int *retval) +{ +int actlen; + + /* Idiot checking of pointers */ + if (! cmd || ! matches || ! retval || + ! (actlen = strlen(cmd))) /* Is there an cmd ? */ + return (EFAULT); + + /* Keep looping until NULL match string (end of list) */ + while (matches->match) { + /* + * Precedence: Make sure target is no longer than + * current match string + * and target is at least as long as + * minimum # match chars, + * then do case insensitive match + * based on actual target size + */ + if ((((int)strlen(matches->match)) >= actlen) && + (actlen >= matches->num_match) && + /* can't get strncasecmp to work on SCR4 */ + /* (strncasecmp(matches->match, cmd, actlen) == 0) */ + (strncmp(matches->match, cmd, actlen) == 0)) { + *retval = matches->ret_code; /* Found our match */ + return (EOK); + } else { + matches++; /* Next match string/struct */ + } + } /* End of matches loop */ + return (EINVAL); + +} /* End of getaction() */ + +/* main functions. */ +int +main(int argc, char **argv) +{ +register int c; +/* getopt varbs */ +extern char *optarg; +char *optstring = NULL; +int path_index, err = 0; +int cmd = 0; /* Cmd verb from cmd line */ +int exit_code = 0; /* exit code for program */ +int temp_fd; /* For -f option */ +char *file_name = NULL; +int option_t_input; +char *path_phys = NULL; +int USE_FCHBA = 0; + + whoami = argv[0]; + + + /* + * Enable locale announcement + */ + i18n_catopen(); + + while ((c = getopt(argc, argv, "ve")) + != EOF) { + switch (c) { + case 'v': + Options |= PVERBOSE; + break; + case 'e': + Options |= EXPERT; + break; + default: + /* Note: getopt prints an error if invalid option */ + USEAGE() + exit(-1); + } /* End of switch(c) */ + } + setbuf(stdout, NULL); /* set stdout unbuffered. */ + + /* + * Build any i18n global variables + */ + dtype[0] = MSGSTR(2192, "Disk device"); + dtype[1] = MSGSTR(2193, "Tape device"); + dtype[2] = MSGSTR(2194, "Printer device"); + dtype[3] = MSGSTR(2195, "Processor device"); + dtype[4] = MSGSTR(2196, "WORM device"); + dtype[5] = MSGSTR(2197, "CD-ROM device"); + dtype[6] = MSGSTR(2198, "Scanner device"); + dtype[7] = MSGSTR(2199, "Optical memory device"); + dtype[8] = MSGSTR(2200, "Medium changer device"); + dtype[9] = MSGSTR(2201, "Communications device"); + dtype[10] = MSGSTR(107, "Graphic arts device"); + dtype[11] = MSGSTR(107, "Graphic arts device"); + dtype[12] = MSGSTR(2202, "Array controller device"); + dtype[13] = MSGSTR(2203, "SES device"); + dtype[14] = MSGSTR(71, "Reserved"); + dtype[15] = MSGSTR(71, "Reserved"); + + + + /* + * Get subcommand. + */ + if ((getaction(argv[optind], Keywords, &cmd)) == EOK) { + optind++; + if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && + (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && + (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && (cmd != AU) && + (cmd != PORT) && (cmd != CREATE_FAB) && (optind >= argc)) { + (void) fprintf(stderr, + MSGSTR(2204, + "Error: enclosure or pathname not specified.\n")); + USEAGE(); + exit(-1); + } + } else { + (void) fprintf(stderr, + MSGSTR(2205, "%s: subcommand not specified.\n"), + whoami); + USEAGE(); + exit(-1); + } + + /* Extract & Save subcommand options */ + if ((cmd == ENABLE) || (cmd == BYPASS)) { + optstring = "Ffrab"; + } else if (cmd == FCODE_UPDATE) { + optstring = "pd:"; + } else if (cmd == REMOVE_DEVICE) { + optstring = "F"; + } else if (cmd == CREATE_FAB) { + optstring = "f:"; + } else { + optstring = "Fryszabepcdlvt:f:w:"; + } + while ((c = getopt(argc, argv, optstring)) != EOF) { + switch (c) { + case 'a': + Options |= OPTION_A; + break; + case 'b': + Options |= OPTION_B; + break; + case 'c': + Options |= OPTION_C; + break; + case 'd': + Options |= OPTION_D; + if (cmd == FCODE_UPDATE) { + file_name = optarg; + } + break; + case 'e': + Options |= OPTION_E; + break; + case 'f': + Options |= OPTION_F; + if (!((cmd == ENABLE) || (cmd == BYPASS))) { + file_name = optarg; + } + break; + case 'F': + Options |= OPTION_CAPF; + break; + case 'l': + Options |= OPTION_L; + break; + case 'p': + Options |= OPTION_P; + break; + case 'r': + Options |= OPTION_R; + break; + case 's': + Options |= SAVE; + break; + case 't': + Options |= OPTION_T; + option_t_input = atoi(optarg); + break; + case 'v': + Options |= OPTION_V; + break; + case 'z': + Options |= OPTION_Z; + break; + case 'y': + Options |= OPTION_Y; + break; + default: + /* Note: getopt prints an error if invalid option */ + USEAGE() + exit(-1); + } /* End of switch(c) */ + } + if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && + (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && + (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && + (cmd != AU) && (cmd != PORT) && + (cmd != CREATE_FAB) && (optind >= argc)) { + (void) fprintf(stderr, + MSGSTR(2206, + "Error: enclosure or pathname not specified.\n")); + USEAGE(); + exit(-1); + } + path_index = optind; + + /* + * Check if the file supplied with the -f option is valid + * Some sub commands (bypass for example) use the -f option + * for other reasons. In such cases, "file_name" should be + * NULL. + */ + if ((file_name != NULL) && (Options & OPTION_F)) { + if ((temp_fd = open(file_name, O_RDONLY)) == -1) { + perror(file_name); + exit(-1); + } else { + close(temp_fd); + } + } + + /* Determine which mode to operate in (FC-HBA or original) */ + USE_FCHBA = use_fchba(); + + switch (cmd) { + case DISPLAY: + if (Options & + ~(PVERBOSE | OPTION_A | OPTION_Z | OPTION_R | + OPTION_P | OPTION_V | OPTION_L | OPTION_E | OPTION_T)) { + USEAGE(); + exit(-1); + } + /* Display object(s) */ + if (USE_FCHBA) { + exit_code = fchba_display_config(&argv[path_index], + option_t_input, argc - path_index); + } else { + exit_code = adm_display_config(&argv[path_index]); + } + break; + + case DOWNLOAD: + if (Options & + ~(PVERBOSE | OPTION_F | SAVE)) { + USEAGE(); + exit(-1); + } + adm_download(&argv[path_index], file_name); + break; + + case ENCLOSURE_NAMES: + if (Options & ~PVERBOSE) { + USEAGE(); + exit(-1); + } + up_encl_name(&argv[path_index], argc); + break; + + case FAILOVER: + if (Options & ~PVERBOSE) { + USEAGE(); + exit(-1); + } + adm_failover(&argv[path_index]); + break; + + case INQUIRY: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + if (USE_FCHBA) { + exit_code = fchba_inquiry(&argv[path_index]); + } else { + exit_code = adm_inquiry(&argv[path_index]); + } + break; + + case PROBE: + if (Options & ~(PVERBOSE | OPTION_P)) { + USEAGE(); + exit(-1); + } + /* + * A special check just in case someone entered + * any characters after the -p or the probe. + * + * (I know, a nit.) + */ + if (((Options & PVERBOSE) && (Options & OPTION_P) && + (argc != 4)) || + (!(Options & PVERBOSE) && (Options & OPTION_P) && + (argc != 3)) || + ((Options & PVERBOSE) && (!(Options & OPTION_P)) && + (argc != 3)) || + (!(Options & PVERBOSE) && (!(Options & OPTION_P)) && + (argc != 2))) { + (void) fprintf(stderr, + MSGSTR(114, "Error: Incorrect number of arguments.\n")); + (void) fprintf(stderr, MSGSTR(2208, + "Usage: %s [-v] subcommand [option]\n"), whoami); + exit(-1); + } + if (USE_FCHBA) { + exit_code = fchba_non_encl_probe(); + } else { + pho_probe(); + non_encl_probe(); + } + break; + + case FCODE_UPDATE: /* Update Fcode in all cards */ + if ((Options & ~(PVERBOSE)) & + ~(OPTION_P | OPTION_D) || argv[path_index]) { + USEAGE(); + exit(-1); + } + if (!((Options & (OPTION_P | OPTION_D)) && + !((Options & OPTION_P) && (Options & OPTION_D)))) { + USEAGE(); + exit(-1); + } + if (adm_fcode(Options & PVERBOSE, file_name) != 0) { + exit(-1); + } + break; + + case QLGC_UPDATE: /* Update Fcode in PCI HBA card(s) */ + if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || + argv[path_index]) { + USEAGE(); + exit(-1); + } + if (q_qlgc_update(Options & PVERBOSE, file_name) != 0) { + exit(-1); + } + break; + + case FCAL_UPDATE: /* Update Fcode in Sbus soc+ card */ + if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || + argv[path_index]) { + USEAGE(); + exit(-1); + } + exit_code = fcal_update(Options & PVERBOSE, file_name); + break; + + case SET_BOOT_DEV: /* Set boot-device variable in nvram */ + exit_code = setboot(Options & OPTION_Y, + Options & PVERBOSE, argv[path_index]); + break; + + case LED: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + adm_led(&argv[path_index], L_LED_STATUS); + break; + case LED_ON: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + adm_led(&argv[path_index], L_LED_ON); + break; + case LED_OFF: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + adm_led(&argv[path_index], L_LED_OFF); + break; + case LED_BLINK: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + adm_led(&argv[path_index], L_LED_RQST_IDENTIFY); + break; + case PASSWORD: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + up_password(&argv[path_index]); + break; + + case RESERVE: + + if (Options & (~PVERBOSE)) { + USEAGE(); + exit(-1); + } + VERBPRINT(MSGSTR(2209, + " Reserving: \n %s\n"), argv[path_index]); + if (USE_FCHBA) { + struct stat sbuf; + /* Just stat the argument and make sure it exists */ + if (stat(argv[path_index], &sbuf) < 0) { + (void) fprintf(stderr, "%s: ", whoami); + (void) fprintf(stderr, + MSGSTR(112, "Error: Invalid pathname (%s)"), + argv[path_index]); + (void) fprintf(stderr, "\n"); + exit(-1); + } + path_phys = argv[path_index]; + if (err = scsi_reserve(path_phys)) { + (void) print_errString(err, argv[path_index]); + exit(-1); + } + } else { + exit_code = adm_reserve(argv[path_index]); + } + break; + + case RELEASE: + if (Options & (~PVERBOSE)) { + USEAGE(); + exit(-1); + } + VERBPRINT(MSGSTR(2210, " Canceling Reservation for:\n %s\n"), + argv[path_index]); + if (USE_FCHBA) { + struct stat sbuf; + /* Just stat the argument and make sure it exists */ + if (stat(argv[path_index], &sbuf) < 0) { + (void) fprintf(stderr, "%s: ", whoami); + (void) fprintf(stderr, + MSGSTR(112, "Error: Invalid pathname (%s)"), + argv[path_index]); + (void) fprintf(stderr, "\n"); + exit(-1); + } + path_phys = argv[path_index]; + if (err = scsi_release(path_phys)) { + (void) print_errString(err, argv[path_index]); + exit(-1); + } + } else { + exit_code = adm_release(argv[path_index]); + } + break; + + case START: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + exit_code = adm_start(&argv[path_index]); + break; + + case STOP: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + exit_code = adm_stop(&argv[path_index]); + break; + + case POWER_OFF: + if (Options & ~(PVERBOSE | OPTION_CAPF)) { + USEAGE(); + exit(-1); + } + exit_code = adm_power_off(&argv[path_index], 1); + break; + + case POWER_ON: + if (Options & (~PVERBOSE)) { + USEAGE(); + exit(-1); + } + exit_code = adm_power_off(&argv[path_index], 0); + break; + + /* + * EXPERT commands. + */ + + case FORCELIP: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + E_USEAGE(); + exit(-1); + } + exit_code = adm_forcelip(&argv[path_index]); + break; + + case BYPASS: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | + OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | + OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || + ((Options & OPTION_A) && (Options & OPTION_B))) { + E_USEAGE(); + exit(-1); + } + adm_bypass_enable(&argv[path_index], 1); + break; + + case ENABLE: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | + OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | + OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || + ((Options & OPTION_A) && (Options & OPTION_B))) { + E_USEAGE(); + exit(-1); + } + adm_bypass_enable(&argv[path_index], 0); + break; + case LUX_P_OFFLINE: /* Offline a port */ + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + E_USEAGE(); + exit(-1); + } + exit_code = adm_port_offline_online(&argv[path_index], + LUX_P_OFFLINE); + break; + + case LUX_P_ONLINE: /* Online a port */ + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + E_USEAGE(); + exit(-1); + } + exit_code = adm_port_offline_online(&argv[path_index], + LUX_P_ONLINE); + break; + + case RDLS: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + E_USEAGE(); + exit(-1); + } + if (USE_FCHBA) { + exit_code = fchba_display_link_status(&argv[path_index]); + } else { + display_link_status(&argv[path_index]); + } + break; + + case CREATE_FAB: + if (!(Options & (EXPERT | OPTION_F)) || + (Options & ~(PVERBOSE | EXPERT | OPTION_F))) { + E_USEAGE(); + exit(-1); + } + if (read_repos_file(file_name) != 0) { + exit(-1); + } + break; + + /* + * Undocumented commands. + */ + + case CHECK_FILE: /* Undocumented Cmd */ + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + exit_code = adm_check_file(&argv[path_index], + (Options & PVERBOSE)); + break; + + case DUMP: /* Undocumented Cmd */ + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + dump(&argv[path_index]); + break; + + case DUMP_MAP: /* Undocumented Cmd */ + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + if (USE_FCHBA) { + exit_code = fchba_dump_map(&argv[path_index]); + } else { + dump_map(&argv[path_index]); + } + break; + + case SYSDUMP: + if (Options & ~(PVERBOSE)) { + USEAGE(); + exit(-1); + } + if (err = sysdump(Options & PVERBOSE)) { + (void) print_errString(err, NULL); + exit(-1); + } + break; + + case PORT: /* Undocumented command */ + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + if (USE_FCHBA) { + exit_code = fchba_display_port(Options & PVERBOSE); + } else { + exit_code = adm_display_port(Options & PVERBOSE); + } + break; + + case EXT_LOOPBACK: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + if (adm_port_loopback(argv[path_index], EXT_LOOPBACK) < 0) { + exit(-1); + } + break; + + case INT_LOOPBACK: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + if (adm_port_loopback(argv[path_index], INT_LOOPBACK) < 0) { + exit(-1); + } + break; + + case NO_LOOPBACK: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + USEAGE(); + exit(-1); + } + if (adm_port_loopback(argv[path_index], NO_LOOPBACK) < 0) { + exit(-1); + } + break; + + case VERSION: + break; + + + case INSERT_DEVICE: + if (argv[path_index] == NULL) { + if ((err = h_insertSena_fcdev()) != 0) { + (void) print_errString(err, NULL); + exit(-1); + } + } else if ((err = hotplug(INSERT_DEVICE, + &argv[path_index], + Options & PVERBOSE, + Options & OPTION_CAPF)) != 0) { + (void) print_errString(err, argv[path_index]); + exit(-1); + } + break; + case REMOVE_DEVICE: + if (err = hotplug(REMOVE_DEVICE, &argv[path_index], + Options & PVERBOSE, Options & OPTION_CAPF)) { + (void) print_errString(err, argv[path_index]); + exit(-1); + } + break; + + /* for hotplug device operations */ + case DEV_ONLINE: + case DEV_OFFLINE: + case DEV_GETSTATE: + case DEV_RESET: + case BUS_QUIESCE: + case BUS_UNQUIESCE: + case BUS_GETSTATE: + case BUS_RESET: + case BUS_RESETALL: + if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { + E_USEAGE(); + exit(-1); + } + if (USE_FCHBA) { + if (fchba_hotplug_e(cmd, &argv[path_index], + Options & PVERBOSE, Options & OPTION_CAPF) != 0) { + exit(-1); + } + } else { + if (hotplug_e(cmd, &argv[path_index], + Options & PVERBOSE, Options & OPTION_CAPF) != 0) { + exit(-1); + } + } + break; + + default: + (void) fprintf(stderr, + MSGSTR(2213, "%s: subcommand decode failed.\n"), + whoami); + USEAGE(); + exit(-1); + } + return (exit_code); +} |