adm.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* 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
* 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 <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <strings.h>
#include <dirent.h>
#include <limits.h>
#include <stdarg.h>
#include <termio.h> /* For password */
#include "common.h"
#include "luxadm.h"
/* Global variables */
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
{
int i;
for (i = 0; i < size; i++) {
if (buffer[i])
else if (fill_flag)
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 *
{
if (size2 == 0)
return (s1);
while (count1--) {
if (--count2 == 0)
continue;
}
}
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
{
int fp;
char file[MAXPATHLEN];
/* Find all adapters and print the current FCode version */
/* SOCAL (SBus) adapters are not supported on x86 */
#ifndef __x86
if (verbose) {
}
#endif
if (verbose) {
}
if (verbose) {
}
/* Send files to the correct function for loading to the HBA */
} else {
if (!dir) {
" Location of Fcode not specified.\n"));
return (1);
} else if (verbose) {
" Using directory %s"), dir);
}
"%s: lstat() failed - %s\n"),
return (1);
}
return (1);
}
" Error Cannot open directory %s\n"), dir);
return (1);
}
continue;
}
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;
}
!= NULL) {
"\n Using file: %s\n"), file);
retval += fcal_update(
strfound++;
break;
!= NULL) ||
!= NULL)) {
"\n Using file: %s\n"), file);
retval += q_qlgc_update(
strfound++;
break;
}
}
if (!strfound) {
/* check to see if this is an emulex fcode */
manf,
sizeof (manf)) == 0) &&
== 0)) {
strfound = 0;
} else {
"\nError: %s is not a valid Fcode "
"file.\n"), file);
retval++;
}
} else {
strfound = 0;
}
}
}
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 */
};
/* hotplugging device operations */
/* hotplugging bus operations */
/* hotplugging "helper" subcommands */
{ NULL, 0, 0}
};
#ifndef EOK
#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
{
int actlen;
/* Idiot checking of pointers */
return (EFAULT);
/* Keep looping until NULL match string (end of list) */
/*
* 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
*/
/* can't get strncasecmp to work on SCR4 */
/* (strncasecmp(matches->match, cmd, actlen) == 0) */
return (EOK);
} else {
}
} /* End of matches loop */
return (EINVAL);
} /* End of getaction() */
/* main functions. */
int
{
register int c;
/* getopt varbs */
extern char *optarg;
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 */
int option_t_input;
int USE_FCHBA = 0;
/*
* Enable locale announcement
*/
i18n_catopen();
!= EOF) {
switch (c) {
case 'v':
break;
case 'e':
break;
default:
/* Note: getopt prints an error if invalid option */
USEAGE()
exit(-1);
} /* End of switch(c) */
}
/*
* Build any i18n global variables
*/
/*
* Get subcommand.
*/
optind++;
MSGSTR(2204,
"Error: enclosure or pathname not specified.\n"));
USEAGE();
exit(-1);
}
} else {
whoami);
USEAGE();
exit(-1);
}
/* Extract & Save subcommand options */
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:";
}
switch (c) {
case 'a':
break;
case 'b':
break;
case 'c':
break;
case 'd':
if (cmd == FCODE_UPDATE) {
}
break;
case 'e':
break;
case 'f':
}
break;
case 'F':
Options |= OPTION_CAPF;
break;
case 'l':
break;
case 'p':
break;
case 'r':
break;
case 's':
break;
case 't':
break;
case 'v':
break;
case 'z':
break;
case 'y':
break;
default:
/* Note: getopt prints an error if invalid option */
USEAGE()
exit(-1);
} /* End of switch(c) */
}
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.
*/
exit(-1);
} else {
}
}
/* Determine which mode to operate in (FC-HBA or original) */
switch (cmd) {
case DISPLAY:
if (Options &
USEAGE();
exit(-1);
}
/* Display object(s) */
if (USE_FCHBA) {
} else {
}
break;
case DOWNLOAD:
if (Options &
USEAGE();
exit(-1);
}
break;
case ENCLOSURE_NAMES:
USEAGE();
exit(-1);
}
break;
case FAILOVER:
USEAGE();
exit(-1);
}
break;
case INQUIRY:
USEAGE();
exit(-1);
}
if (USE_FCHBA) {
} else {
}
break;
case PROBE:
USEAGE();
exit(-1);
}
/*
* A special check just in case someone entered
* any characters after the -p or the probe.
*
* (I know, a nit.)
*/
(argc != 4)) ||
(argc != 3)) ||
(argc != 3)) ||
(argc != 2))) {
"Usage: %s [-v] subcommand [option]\n"), whoami);
exit(-1);
}
if (USE_FCHBA) {
} else {
pho_probe();
}
break;
case FCODE_UPDATE: /* Update Fcode in all cards */
USEAGE();
exit(-1);
}
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case QLGC_UPDATE: /* Update Fcode in PCI HBA card(s) */
argv[path_index]) {
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case FCAL_UPDATE: /* Update Fcode in Sbus soc+ card */
argv[path_index]) {
USEAGE();
exit(-1);
}
break;
case SET_BOOT_DEV: /* Set boot-device variable in nvram */
break;
case LED:
USEAGE();
exit(-1);
}
break;
case LED_ON:
USEAGE();
exit(-1);
}
break;
case LED_OFF:
USEAGE();
exit(-1);
}
break;
case LED_BLINK:
USEAGE();
exit(-1);
}
break;
case PASSWORD:
USEAGE();
exit(-1);
}
break;
case RESERVE:
USEAGE();
exit(-1);
}
if (USE_FCHBA) {
/* Just stat the argument and make sure it exists */
argv[path_index]);
exit(-1);
}
exit(-1);
}
} else {
}
break;
case RELEASE:
USEAGE();
exit(-1);
}
argv[path_index]);
if (USE_FCHBA) {
/* Just stat the argument and make sure it exists */
argv[path_index]);
exit(-1);
}
exit(-1);
}
} else {
}
break;
case START:
USEAGE();
exit(-1);
}
break;
case STOP:
USEAGE();
exit(-1);
}
break;
case POWER_OFF:
USEAGE();
exit(-1);
}
break;
case POWER_ON:
USEAGE();
exit(-1);
}
break;
/*
* EXPERT commands.
*/
case FORCELIP:
E_USEAGE();
exit(-1);
}
break;
case BYPASS:
E_USEAGE();
exit(-1);
}
break;
case ENABLE:
E_USEAGE();
exit(-1);
}
break;
case LUX_P_OFFLINE: /* Offline a port */
E_USEAGE();
exit(-1);
}
break;
case LUX_P_ONLINE: /* Online a port */
E_USEAGE();
exit(-1);
}
break;
case RDLS:
E_USEAGE();
exit(-1);
}
if (USE_FCHBA) {
} else {
}
break;
case CREATE_FAB:
E_USEAGE();
exit(-1);
}
if (read_repos_file(file_name) != 0) {
exit(-1);
}
break;
/*
* Undocumented commands.
*/
case CHECK_FILE: /* Undocumented Cmd */
USEAGE();
exit(-1);
}
break;
case DUMP: /* Undocumented Cmd */
USEAGE();
exit(-1);
}
break;
case DUMP_MAP: /* Undocumented Cmd */
USEAGE();
exit(-1);
}
if (USE_FCHBA) {
} else {
}
break;
case SYSDUMP:
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case PORT: /* Undocumented command */
USEAGE();
exit(-1);
}
if (USE_FCHBA) {
} else {
}
break;
case EXT_LOOPBACK:
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case INT_LOOPBACK:
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case NO_LOOPBACK:
USEAGE();
exit(-1);
}
exit(-1);
}
break;
case VERSION:
break;
case INSERT_DEVICE:
if ((err = h_insertSena_fcdev()) != 0) {
exit(-1);
}
&argv[path_index],
Options & OPTION_CAPF)) != 0) {
exit(-1);
}
break;
case REMOVE_DEVICE:
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:
E_USEAGE();
exit(-1);
}
if (USE_FCHBA) {
exit(-1);
}
} else {
exit(-1);
}
}
break;
default:
whoami);
USEAGE();
exit(-1);
}
return (exit_code);
}