/*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <kstat.h>
#include <locale.h>
#include <nl_types.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <dirent.h>
#include <limits.h>
#include <stdarg.h>
#include <termio.h> /* For password */
#include <signal.h>
#include <l_common.h>
#include <l_error.h>
#include <stgcom.h>
#include <a_state.h>
#include <devid.h>
#include <g_state.h>
#include "common.h"
extern char *dtype[];
extern char *whoami;
extern int Options;
extern const int OPTION_A;
extern const int OPTION_B;
extern const int OPTION_C;
extern const int OPTION_D;
extern const int OPTION_E;
extern const int OPTION_F;
extern const int OPTION_L;
extern const int OPTION_P;
extern const int OPTION_R;
extern const int OPTION_T;
extern const int OPTION_V;
extern const int OPTION_Z;
extern const int OPTION_Y;
extern const int OPTION_CAPF;
extern const int PVERBOSE;
extern const int SAVE;
extern const int EXPERT;
static int termio_fd;
static void pho_display_config(char *);
static void dpm_display_config(char *);
WWN_list **);
static void n_rem_list_entry_fabric(int, struct gfc_map *,
WWN_list **);
Path_struct *, struct mode_page *, int, char *, int);
L_inquiry, int);
static void adm_display_err(char *, int);
static void temperature_messages(struct l_state_struct *, int);
static void ctlr_messages(struct l_state_struct *, int, int);
static void fan_messages(struct l_state_struct *, int, int);
static void ps_messages(struct l_state_struct *, int, int);
static void abnormal_condition_display(struct l_state_struct *);
static void loop_messages(struct l_state_struct *, int, int);
static void revision_msg(struct l_state_struct *, int);
static void mb_messages(struct l_state_struct *, int, int);
static void back_plane_messages(struct l_state_struct *, int, int);
static void dpm_SSC100_messages(struct l_state_struct *, int, int);
static void mb_messages(struct l_state_struct *, int, int);
static void back_plane_messages(struct l_state_struct *, int, int);
static void dpm_SSC100_messages(struct l_state_struct *, int, int);
static void trans_messages(struct l_state_struct *, int);
static void adm_print_pathlist(char *);
static void display_path_info(char *, char *, WWN_list *);
static void copy_wwn_data_to_str(char *, const uchar_t *);
static void adm_mplist_free(struct mplist_struct *);
int verbose);
static int get_lun_capacity(char *devpath,
struct scsi_capacity_16 *cap_data);
/*
* Gets the device's state from the SENA IB and
* checks whether device is offlined, bypassed
* or if the slot is empty and prints it to the
* stdout.
*
* RETURNS:
* 0 O.K.
* non-zero otherwise
*/
int
int verbose_flag)
{
int err;
int i, elem_index = 0;
return (err);
}
elem_index++;
break;
}
}
(void) bcopy((const void *)
(void) bcopy((const void *)
if (fr_flag) {
} else {
}
if (device_off) {
MSGSTR(2000,
"%s is offlined and bypassed.\n"
" Could not get device specific"
" information.\n\n"),
devname);
} else if (bypass_a_en && bypass_b_en) {
MSGSTR(2001,
"%s is bypassed (Port:AB).\n"
" Could not get device specific"
" information.\n\n"),
devname);
} else if (ib_status_code == S_NOT_INSTALLED) {
MSGSTR(2002,
"Slot %s is empty.\n\n"),
devname);
MSGSTR(2003,
"Backplane(Port:AB) is bypassed.\n"
" Could not get device specific"
" information for"
" %s.\n\n"), devname);
} else {
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
devname);
}
return (-1);
}
/*
* Given an error number, this functions
* calls the get_errString() to print a
* corresponding error message to the stderr.
* get_errString() always returns an error
* message, even in case of undefined error number.
* So, there is no need to check for a NULL pointer
* while printing the error message to the stdout.
*
* RETURNS: N/A
*
*/
void
{
char *errStr;
"%s \n\n", errStr);
} else {
}
/* free the allocated memory for error string */
}
/*
* adm_inquiry() Display the inquiry information for
* a SENA enclosure(s) or disk(s).
*
* RETURNS:
* none.
*/
int
{
if (err != -1) {
path_index++;
retval++;
continue;
}
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
}
path_index++;
retval++;
continue;
}
path_index++;
retval++;
continue;
}
} else {
if (err != -1) {
} else {
argv[path_index]);
}
}
path_index++;
retval++;
continue;
}
path_index++;
retval++;
continue;
}
&serial_len)) {
path_index++;
retval++;
continue;
}
path_index++;
continue;
}
return (err);
}
0) {
argpwwn = 1;
break;
path_struct->argv) == 0) {
argnwwn = 1;
break;
}
}
/*
* if the wwn list is null or the arg device not found
* from the wwn list, still go ahead to issue inquiry.
*/
path_index++;
retval++;
continue;
}
&serial_len)) {
path_index++;
retval++;
continue;
}
(void) g_free_wwn_list(&wwn_list);
path_index++;
continue;
}
if (argpwwn) {
path_struct->argv) != 0) {
continue;
}
} else if (argnwwn) {
path_struct->argv) != 0) {
continue;
}
last_logical_path) != NULL) {
continue;
}
(void) strcpy(last_logical_path,
}
retval++;
break;
}
&serial_len)) {
retval++;
break;
}
}
(void) g_free_wwn_list(&wwn_list);
path_index++;
}
return (retval);
}
/*
* FORCELIP expert function
*/
int
{
if (err != -1) {
path_index++;
retval++;
continue;
}
&path_phys, &path_struct,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
}
path_index++;
retval++;
continue;
}
path_index++;
retval++;
continue;
}
} else {
"Error: Invalid pathname (%s)"),
argv[path_index]);
}
path_index++;
retval++;
continue;
}
path_index++;
retval++;
continue;
}
path_index++;
if (path_struct != NULL) {
(void) free(path_struct);
}
}
return (retval);
}
/*
* DISPLAY function
*
* RETURNS:
* 0 O.K.
*/
int
{
int retval = 0;
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
path_index++;
retval++;
continue;
}
!= 0) {
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
}
path_index++;
retval++;
continue;
}
path_index++;
retval++;
continue;
}
} else {
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
} else {
MSGSTR(112,
"Error: Invalid pathname (%s)"),
argv[path_index]);
}
}
} else {
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
} else {
MSGSTR(112,
"Error: Invalid pathname (%s)"),
argv[path_index]);
}
}
path_index++;
retval++;
continue;
}
/*
* See what kind of device we are talking to.
*/
if (opnerr == L_OPEN_PATH_FAIL) {
/*
* We check only for L_OPEN_PATH_FAIL because
* that is the only error code returned by
* g_get_inquiry() which is not got from the ioctl
* call itself. So, we are dependent, in a way, on the
* implementation of g_get_inquiry().
*
*/
path_index++;
retval++;
continue;
}
exit(1);
}
/*
* Display SENA enclosure.
*/
} else {
}
/*
*/
}
} else {
}
/*
* if device is in SENA enclosure
*
* if the slot is valid, then I know this is a SENA enclosure
* and can continue
* otherwise:
* I first get the ses_path, if this doesn't fail
* I retrieve the inquiry data from the ses node
* and check teh PID to make sure this is a SENA
*/
!= NULL))))) {
} else {
}
}
sizeof (inq.inq_revision), 0);
}
/* if device is not in SENA or SSA enclosures. */
case DTYPE_DIRECT:
case DTYPE_SEQUENTIAL: /* Tape */
} else if (non_encl_fc_disk_display(path_struct,
MSGSTR(2111,
"Error: getting the device"
" information.\n"));
retval++;
}
break;
/* case 0x01: same as default */
default:
"Device Type:"));
break;
}
} else {
}
path_index++;
}
(void) free(path_struct);
}
return (retval);
}
/*
* Powers off a list of SENA enclosure(s)
* and disk(s) which is provided by the user.
*
* RETURNS:
* none.
*/
int
{
/*
* In case we did not find the device
* in the /devices directory.
*
* Only valid for pathnames like box,f1
*/
if (path_struct->ib_path_flag) {
} else {
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
}
path_index++;
retval++;
continue;
}
}
if (path_struct->ib_path_flag) {
/*
* We are addressing a disk using a path
* format type box,f1.
*/
Options & OPTION_CAPF)) {
/*
* Is it Bypassed... try to give more
* informtaion.
*/
retval++;
}
path_index++;
continue;
}
path_index++;
retval++;
continue;
}
off_flag) != 0) {
path_index++;
retval++;
continue;
}
/* power off SENA enclosure. */
Options & OPTION_CAPF)) {
retval++;
}
Options & OPTION_CAPF)) {
retval++;
}
} else {
/*
* SSA section:
*/
(void) print_errString(L_INVALID_PATH,
argv[path_index]);
}
path_index++;
}
return (retval);
}
void
{
/*
* In case we did not find the device
* in the /devices directory.
*
* Only valid for pathnames like box,f1
*/
if (path_struct->ib_path_flag) {
} else {
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
}
if (path_struct->ib_path_flag) {
E_USEAGE();
exit(-1);
}
/*
* We are addressing a disk using a path
* format type box,f1 and no disk
* path was found.
* check is performed.
*/
exit(-1);
}
return;
}
exit(-1);
}
E_USEAGE();
exit(-1);
}
exit(-1);
}
E_USEAGE();
exit(-1);
}
exit(-1);
}
}
}
/*
* adm_download() Download subsystem microcode.
* Path must point to a LUX IB.
*
* RETURNS:
* None.
*/
void
{
/*
* See what kind of device we are talking to.
*/
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
exit(-1);
}
(void) print_errString(err,
(err == L_OPEN_PATH_FAIL) ?
exit(-1);
}
} else {
argv[path_index]);
}
path_index++;
}
}
/*
* display_link_status() Reads and displays the link status.
*
* RETURNS:
* none.
*/
void
{
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
exit(-1);
}
n = rls;
if (n != NULL) {
"information for loop:%s\n"),
n->driver_path);
" sync loss signal loss sequence err"
" invalid word CRC\n"));
}
while (n) {
"%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n",
n->al_ha,
n->payload.rls_linkfail,
n->payload.rls_syncfail,
n->payload.rls_sigfail,
n->payload.rls_invalidcrc);
} else {
"%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n",
n->al_ha,
n->payload.rls_linkfail,
n->payload.rls_syncfail,
n->payload.rls_sigfail,
n->payload.rls_invalidcrc);
}
n = n->next;
}
path_index++;
}
" cleared by a reset, only power cycles.\n"
"These counts must be compared"
" to previously read counts.\n"));
}
/*
* ib_present_chk() Check to see if IB 0 or 1 is present in the box.
*
* RETURN:
* 1 if ib present
* 0 otherwise
*/
int
{
int i;
int elem_index = 0;
elem_index++; /* skip global */
(void) bcopy((const void *)
result = 0;
}
break;
}
}
return (result);
}
/*
* print_individual_state() Print individual disk status.
*
* RETURNS:
* none.
*/
void
{
if (status & L_OPEN_FAIL) {
} else if (status & L_NOT_READY) {
} else if (status & L_NOT_READABLE) {
} else if (status & L_SPUN_DWN_D) {
} else if (status & L_SCSI_ERR) {
} else if (status & L_RESERVED) {
MSGSTR(2010,
" (Rsrv cnflt:A) "));
MSGSTR(2011,
" (Rsrv cnflt:B) "));
} else {
MSGSTR(2012,
" (Reserve cnflt)"));
}
} else if (status & L_NO_LABEL) {
}
}
/*
* display_disk_msg() Displays status for
* an individual SENA device.
*
* RETURNS:
* none.
*/
void
{
int loop_flag = 0;
int a_and_b = 0;
") ");
MSGSTR(2014,
"(LED Blinking) "));
} else {
" ");
}
") ");
MSGSTR(2017,
"(Bypassed:AB)"));
" ");
MSGSTR(2018,
"(Bypassed: A)"));
" ");
MSGSTR(2019,
"(Bypassed: B)"));
" ");
} else {
" ");
}
} else {
} else if (ib_present_chk(l_state, 0) &&
/*
* Before printing that the port is bypassed
* verify that there is an IB for this port.
* If not then don't print.
*/
MSGSTR(2025,
" (Bypassed BP: A)"));
MSGSTR(2026,
"(Bypassed BP: B)"));
MSGSTR(2027,
"(Bypassed BP:AB)"));
} else {
MSGSTR(2028,
" (Loop not accessible)"));
loop_flag = 1;
MSGSTR(2029,
" (Invalid WWN) "));
MSGSTR(2030,
" (Login failed) "));
MSGSTR(2031,
" (No path found)"));
} else if (a_and_b) {
/* NOTE: Double state - should do 2 lines. */
PORT_A_B);
} else {
") ");
}
}
if (loop_flag) {
} else {
}
}
if (front_flag) {
}
}
/*
* pho_display_config() Displays device status
* information for a SENA enclosure.
*
* RETURNS:
* none.
*/
void
{
/* Get global status */
exit(-1);
}
/*
* Look for abnormal status.
*/
}
"SLOT FRONT DISKS (Node WWN) "
" REAR DISKS (Node WWN)\n"));
/*
* Print the status for each disk
*/
elem_index++;
break;
}
(void) bcopy((const void *)
(void) bcopy((const void *)
}
/*
* Display the subsystem status.
*/
MSGSTR(2242,
" SUBSYSTEM STATUS\nFW Revision:"));
for (i = 0; i < 8; i++) {
}
/* Make sure NULL terminated although it is supposed to be */
}
/*
*
*/
elem_index = 0;
/* Get and print CONTROLLER messages */
elem_index++; /* skip global */
case ELM_TYP_PS:
break;
case ELM_TYP_FT:
break;
case ELM_TYP_BP:
break;
case ELM_TYP_IB:
break;
case ELM_TYP_LN:
/*
* NOTE: I just use the Photon's message
* string here and don't look at the
* language code. The string includes
* the language name.
*/
}
break;
case ELM_TYP_LO: /* Loop configuration */
break;
case ELM_TYP_MB: /* Loop configuration */
break;
}
/*
* Calculate the index to each element.
*/
}
}
/*
* dpm_display_config() Displays device status
* information for a DAKTARI enclosure.
*
* RETURNS:
* none.
*/
void
{
/* Get global status */
exit(-1);
}
/*
* Look for abnormal status.
*/
}
"SLOT DISKS (Node WWN) \n"));
/*
* Print the status for each disk
*/
elem_index++;
break;
}
(void) bcopy((const void *)
(void) bcopy((const void *)
for (i = 0, count = 0;
i++, count++) {
}
}
/*
* Display the subsystem status.
*/
MSGSTR(2033,
"\t\tSUBSYSTEM STATUS\nFW Revision:"));
}
for (i = 0; i < 8; i++) {
}
/* Make sure NULL terminated although it is supposed to be */
}
/*
*
*/
elem_index = 0;
/* Get and print CONTROLLER messages */
elem_index++; /* skip global */
case ELM_TYP_PS:
break;
case ELM_TYP_FT:
break;
case ELM_TYP_BP:
break;
case ELM_TYP_IB:
break;
case ELM_TYP_LN:
/*
* NOTE: I just use the Photon's message
* string here and don't look at the
* language code. The string includes
* the language name.
*/
}
break;
case ELM_TYP_LO: /* Loop configuration */
break;
case ELM_TYP_MB: /* Loop configuration */
break;
case ELM_TYP_FL:
break;
}
/*
* Calculate the index to each element.
*/
}
}
/*
* Change the FPM (Front Panel Module) password of the
* subsystem associated with the IB addressed by the
* enclosure or pathname to name.
*
*/
void
intfix(void)
{
if (termio_fd) {
}
}
/*
* up_password() Changes the password for SENA enclosure.
*
* RETURNS:
* none.
*/
void
{
void (*sig)();
exit(-1);
}
/*
* Make sure path valid and is to a PHO
* before bothering operator.
*/
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
exit(-1);
}
/*
* Again this is like the ssaadm code in that the name
* is still not defined before this code must be released.
*/
exit(-1);
}
MSGSTR(2038,
"Changing FPM password for subsystem %s\n"),
argv[path_index]);
equal = 0;
while (!equal) {
for (i = 0; input[i]; i++) {
" The password"
" must be 4 decimal-digit characters.\n"));
exit(-1);
}
}
if (i && (i != 4)) {
" The password"
" must be 4 decimal-digit characters.\n"));
exit(-1);
}
for (j = 0; password[j]; j++) {
" The password"
" must be 4 decimal-digit characters.\n"));
exit(-1);
}
}
if (i != j) {
matched = -1;
matched++;
}
}
equal = 1;
} else {
" try again.\n"));
}
}
/* Send new password to IB */
exit(-1);
}
}
/*
* Call g_failover to process failover command
*/
void
{
exit(-1);
}
exit(-1);
}
exit(-1);
}
}
}
/*
* up_encl_name() Update the enclosures logical name.
*
* RETURNS:
* none.
*/
void
{
for (i = 0; name[i]; i++) {
((name[i] != '#') &&
(name[i] != '-') &&
(name[i] != '_') &&
"Usage: %s [-v] subcommand {a name consisting of"
" 1-16 alphanumeric characters}"
" {enclosure... | pathname...}\n"), whoami);
exit(-1);
}
}
"Usage: %s [-v] subcommand {a name consisting of"
" 1-16 alphanumeric characters}"
" {enclosure... | pathname...}\n"), whoami);
exit(-1);
}
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
/*
* Make sure we are talking to an IB.
*/
exit(-1);
}
/*
* Again this is like the ssaadm code in that the name
* is still not defined before this code must be released.
*/
" enclosure\n"), ENCLOSURE_PROD_NAME);
exit(-1);
}
exit(-1);
}
for (i = 0; i < WWN_SIZE; i++) {
}
exit(-1);
}
"in /dev/es\n"), ENCLOSURE_PROD_NAME);
exit(-1);
" is already being used.\n"
"Please choose a unique name.\n"
"You can use the \"probe\" subcommand to"
" see all of the enclosure names.\n"),
name);
(void) l_free_box_list(&b_list);
exit(-1);
}
(void) l_free_box_list(&b_list);
/* Send new name to IB */
exit(-1);
}
name);
}
}
static int
{
return (err);
}
if (off_flag) {
slot++) {
S_NOT_INSTALLED) &&
S_NOT_INSTALLED) &&
break;
}
}
if (!found_pwrOnDrv) {
MSGSTR(2051,
"Notice: Drives in enclosure"
" \"%s\" have already been"
" powered off.\n\n"),
return (-1);
}
} else {
slot++) {
S_NOT_INSTALLED) &&
S_NOT_INSTALLED) &&
break;
}
}
if (!found_pwrOffDrv) {
MSGSTR(2052,
"Notice: Drives in enclosure"
" \"%s\" have already been"
" powered on.\n\n"),
return (-1);
}
}
return (0);
}
/*
* adm_led() The led_request subcommand requests the subsystem
* to display the current state or turn off, on, or blink
* the yellow LED associated with the disk specified by the
* enclosure or pathname.
*
* RETURNS:
* none.
*/
void
{
/* Make sure we have a device path. */
if (path_struct->ib_path_flag) {
} else {
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
(void) print_errString(err,
argv[path_index]);
}
exit(-1);
}
}
if (!path_struct->ib_path_flag) {
exit(-1);
}
MSGSTR(2053,
"Error: pathname must be to a disk device.\n"
exit(-1);
}
}
/*
* See if we are in fact talking to a loop or not.
*/
}
if (led_action == L_LED_ON) {
"The led_on functionality is not applicable "
"to this subsystem.\n"));
exit(-1);
}
exit(-1);
}
/* Check to see if we have a daktari */
}
}
switch (led_action) {
case L_LED_STATUS:
if (!path_struct->slot_valid) {
"device:\n %s\n"), path_phys);
} else {
if (enc_t == DAK_ENC_TYPE) {
if (path_struct->f_flag) {
"device in location: slot %d\n"),
path_struct->slot);
} else {
"device in location: slot %d\n"),
path_struct->slot +
(MAX_DRIVES_DAK/2));
}
} else {
(path_struct->f_flag) ?
"device in location: front,slot %d\n")
"device in location: rear,slot %d\n"),
path_struct->slot);
}
}
if (!path_struct->slot_valid) {
"LED state is BLINKING for "
"device:\n %s\n"), path_phys);
} else {
if (enc_t == DAK_ENC_TYPE) {
if (path_struct->f_flag) {
"LED state is BLINKING for "
"device in location: slot %d\n"),
path_struct->slot);
} else {
"LED state is BLINKING for "
"device in location: slot %d\n"),
}
} else {
(path_struct->f_flag) ?
"device in location: front,slot %d\n")
"device in location: rear,slot %d\n"),
path_struct->slot);
}
}
} else {
if (!path_struct->slot_valid) {
"device:\n %s\n"), path_phys);
} else {
if (enc_t == DAK_ENC_TYPE) {
if (path_struct->f_flag) {
"LED state is OFF for "
"device in location: slot %d\n"),
path_struct->slot);
} else {
"LED state is OFF for "
"device in location: slot %d\n"),
}
} else {
(path_struct->f_flag) ?
"device in location: front,slot %d\n")
"device in location: rear,slot %d\n"),
path_struct->slot);
}
}
}
break;
}
path_index++;
}
}
/*
* dump() Dump information
*
* RETURNS:
* none.
*/
void
{
/*
* get big buffer
*/
NULL) {
exit(-1);
}
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
} else {
}
exit(-1);
}
/*
* Dump all pages.
*/
sizeof (struct rec_diag_hdr));
}
path_index++;
}
}
/*
* display_socal_stats() Display socal driver kstat information.
*
* RETURNS:
* none.
*/
void
{
int i;
int header_flag = 0;
int num_status_entries;
"\tInformation for FC Loop on port %d of"
" FC100/S Host Adapter\n\tat path: %s\n"),
port, socal_path);
" Host Adapter WWN's: Node:%s"
" Port:%s\n"),
}
" Host Adapter Firmware Revision: %s\n"),
}
if (fc_stats->parity_chk_enabled != 0) {
" This Host Adapter checks S-Bus parity.\n"));
}
}
" Version Resets Req_Q_Intrpts Qfulls"
" Unsol_Resps Lips\n"));
" Els_rcvd Abts"
" Abts_ok Offlines Loop_onlines Onlines\n"));
/* If any status conditions exist then display */
} else {
num_status_entries = 64;
}
for (i = 0; i < num_status_entries; i++) {
if (header_flag++ == 0) {
" Fibre Channel Transport status:\n "
"Status Value"
" Count\n"));
}
(void) l_format_fc_status_msg(status_msg_buf,
}
}
}
/*
* display_sf_stats() Display sf driver kstat information.
*
* This routine is called by private loop device only
*
* RETURNS:
* none.
*/
void
{
"Information from %s"),
} else {
}
" Version Lip_count Lip_fail"
" Alloc_fail #_cmds "
"Throttle_limit Pool_size\n"));
"\n\t\tTARGET ERROR INFORMATION:\n"));
"AL_PA Els_fail Timouts Abts_fail"
" Tsk_m_fail "
" Data_ro_mis Dl_len_mis Logouts\n"));
exit(-1);
}
if (dtype == DTYPE_DIRECT) {
exit(-1);
}
/* for san toleration, only need to modify the code */
/* such that the current sf_al_map structure replaced */
/* by the new gfc_map structure for private loop device */
i++, dev_addr_list++) {
== al_pa) {
"%3x%10d%8d%10d%11d%13d%11d%9d\n",
break;
}
}
exit(-1);
}
} else {
i++, dev_addr_list++) {
"%3x%10d%8d%10d%11d%13d%11d%9d\n",
}
}
}
/*
* adm_display_err() Displays enclosure specific
* error information.
*
* RETURNS:
* none.
*/
static void
{
exit(-1);
}
exit(-1);
}
for (i = 0; i < pathcnt; i++) {
p_on = i;
break;
p_st = i;
}
}
}
/* on_line path */
} else {
/* standby or path0 */
}
} else {
exit(-1);
}
}
/*
* Each HBA and driver stack has its own structures
* for this, so we have to handle each one individually.
*/
if (path_type) { /* Quick sanity check for valid path */
exit(-1);
}
}
/* attach :devctl to get node stat instead of dir stat. */
exit(-1);
}
/*
* first take care of ifp card.
*/
if (path_type & FC4_PCI_FCA) {
MSGSTR(2082,
"Error: could not read ifp%d\n"), drvr_inst);
exit(-1);
}
"\tInformation for FC Loop of"
" FC100/P Host Adapter\n\tat path: %s\n"),
"Information from %s"),
" Host Adapter WWN's: Node:%s"
" Port:%s\n"),
}
" Host Adapter Firmware Revision: %s\n"),
}
if (ifp_stats.parity_chk_enabled != 0) {
" This Host Adapter checks "
"PCI-Bus parity.\n"));
}
}
" Version Lips\n"));
/* If any status conditions exist then display */
for (i = 0; i < FC_STATUS_ENTRIES; i++) {
if (ifp_stats.resp_status[i] != 0) {
if (header_flag++ == 0) {
" Fibre Channel Transport "
"status:\n "
"Status "
" Value"
" Count\n"));
}
(void) l_format_ifp_status_msg(
ifp_stats.resp_status[i], i);
}
}
"\n\t\tTARGET ERROR INFORMATION:\n"));
"AL_PA logouts_recvd task_mgmt_failures"
" data_ro_mismatches data_len_mismatch\n"));
exit(-1);
}
if (dtype == DTYPE_DIRECT) {
(void) print_errString(err,
exit(-1);
}
dev_addr_list++) {
if (dev_addr_list->gfc_port_dev.
== al_pa) {
(void) fprintf
(stdout,
"%3x%14d%18d%20d%20d\n",
break;
}
}
(void) print_errString(
exit(-1);
}
} else {
dev_addr_list++) {
"%3x%14d%18d%20d%20d\n",
}
}
}
} else if (path_type & FC4_SF_XPORT) {
/*
* process cards with sf xport nodes.
*/
exit(-1);
}
"statistics"))) {
MSGSTR(2078,
" Error: could not lookup driver stats for sf%d\n"),
sf_inst);
exit(-1);
}
"statistics"))) {
MSGSTR(2079,
" Error: could not lookup driver stats for socal%d\n"),
exit(-1);
}
MSGSTR(2080,
" Error: could not read driver stats for sf%d\n"),
sf_inst);
exit(-1);
}
MSGSTR(2081,
" Error: could not read driver stats for socal%d\n"),
exit(-1);
}
"\n WARNING!! display -r on qlc is"
" currently not supported.\n"));
} else {
"\n WARNING!! display -r is not supported on path\n"
" %s\n"), drvr_path);
}
(void) kstat_close(kc);
}
/*ARGSUSED*/
/*
* adm_display_verbose_disk() Gets the mode page information
* for a SENA disk and prints that information.
*
* RETURNS:
* none.
*/
void
{
(uchar_t)sizeof (struct mode_header_10_struct) +
offset = sizeof (struct mode_header_10_struct) +
sizeof (mode_header_ptr->length))) {
case 0x01:
pg1_buf = (struct mode_page_01_struct *)
(int)pg_hdr;
P_DPRINTF(" adm_display_verbose_disk:"
"Mode Sense page 1 found.\n");
if (hdr_printed++ == 0) {
MSGSTR(2089,
" Mode Sense data:\n"));
}
MSGSTR(2090,
" AWRE:\t\t\t%d\n"
" ARRE:\t\t\t%d\n"
" Read Retry Count:\t\t"
"%d\n"
" Write Retry Count:\t\t"
"%d\n"),
break;
case MODEPAGE_GEOMETRY:
pg4_buf = (struct mode_page_04_struct *)
(int)pg_hdr;
P_DPRINTF(" adm_display_verbose_disk:"
"Mode Sense page 4 found.\n");
if (hdr_printed++ == 0) {
MSGSTR(2091,
" Mode Sense data:\n"));
}
MSGSTR(2092,
" Medium rotation rate:\t"
}
break;
}
}
}
}
/*
* Print out the port_wwn or node_wwn
*/
void
{
" %1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
}
/*
* Print out the fabric dev port_id, hard_addr, port_wwn and node_wwn
*/
void
int hard_addr)
{
}
/*
* Print out the private loop dev port_id, hard_addr, port_wwn and node_wwn
*/
void
{
}
/*
* Get the device map from
* fc nexus driver and prints the map.
*
* RETURNS:
* none.
*/
void
{
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
argv[path_index]);
if (err != -1) {
}
exit(-1);
}
/* obtain phci */
exit(-1);
}
for (i = 0; i < pathcnt; i++) {
MAXPATHSTATE) {
p_pw = i;
break;
}
p_on = i;
}
p_st = i;
}
}
}
/* matching input pwwn */
/* on_line path */
} else {
/* standby or path0 */
}
} else {
}
(void) print_errString(L_INVALID_PATH,
argv[path_index]);
exit(-1);
}
MAP_FORMAT_LILP)) == NULL) {
if (dev_type & FC_FCA_MASK) {
exit(-1);
} else {
/*
* This did not work so try the FCIO_GETMAP
* type ioctl.
*/
(void) print_errString(err,
argv[path_index]);
exit(-1);
}
}
}
if (limited_map_flag) {
MSGSTR(2093,
"Host Adapter AL_PA: %x\n"),
MSGSTR(2094,
"Pos AL_PA\n"));
i, limited_map.lilp_list[i]);
}
} else {
exit(-1);
}
if ((err = g_get_map_topology(
exit(-1);
}
if (err == L_NO_SUCH_DEV_FOUND) {
argv[path_index]);
exit(-1);
} else {
exit(-1);
}
}
switch (map_topo) {
case FC_TOP_FABRIC:
case FC_TOP_PUBLIC_LOOP:
case FC_TOP_PT_PT:
" Node WWN Type\n"));
while (map_dev) {
if ((err = g_dev_prop_lookup_ints(
exit(-1);
}
exit(-1);
}
exit(-1);
}
if ((err = g_dev_prop_lookup_ints(
exit(-1);
}
} else {
*dtype_prop);
}
if (((map_dev = g_get_next_dev(
(err != L_NO_SUCH_DEV_FOUND)) {
exit(-1);
}
}
break;
case FC_TOP_PRIVATE_LOOP:
MSGSTR(2295,
"Pos AL_PA ID Hard_Addr "
"Port WWN Node WWN Type\n"));
while (map_dev) {
if ((err = g_dev_prop_lookup_ints(
exit(-1);
}
exit(-1);
}
exit(-1);
}
if ((err = g_dev_prop_lookup_ints(
exit(-1);
}
} else {
port_wwn, *dtype_prop);
}
if (((map_dev = g_get_next_dev(
(err != L_NO_SUCH_DEV_FOUND)) {
exit(-1);
}
}
break;
default:
argv[path_index]);
exit(-1);
}
}
limited_map_flag = 0;
path_index++;
}
}
/*
* Gets a list of non-SENA fcal devices
* found on the system.
*
* OUTPUT:
* wwn_list pointer
* NULL: No non-enclosure devices found.
* !NULL: Devices found
* wwn_list points to a linked list of wwn's.
* RETURNS:
* 0 O.K.
*/
int
{
/*
* Only interested in devices that are not part of
* a Photon enclosure.
*/
return (err); /* Failure */
}
(void) l_free_box_list(&b_list);
return (err);
}
pathcnt = 1;
exit(-1);
}
}
for (k = 0; k < pathcnt; k++) {
if ((k > 0) && (strstr(oldphci_path,
continue;
}
(void) g_free_wwn_list(&wwn_list);
(void) l_free_box_list(&b_list);
return (err);
}
} else {
continue;
}
if (pathcnt == 1) {
}
}
case FC_TOP_FABRIC:
case FC_TOP_PUBLIC_LOOP:
j++) {
if (b_list->b_node_wwn[j] !=
found_ib = 0;
}
}
if (found_ib) {
(void) n_rem_list_entry_fabric(
&wwn_list);
}
}
break;
case FC_TOP_PRIVATE_LOOP:
j++) {
if (b_list->b_node_wwn[j] !=
priv_port.sf_node_wwn[j]) {
found_ib = 0;
}
}
if (found_ib) {
/* This function has been added */
/* here only to keep from having */
/* to tab over farther */
&wwn_list);
/* Return the list */
*wwn_list_ptr = NULL;
break;
}
}
}
break;
case FC_TOP_PT_PT:
return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
default:
return (L_UNEXPECTED_FC_TOPOLOGY);
}
}
if (pathcnt > 1) {
}
}
/* Return the list */
*wwn_list_ptr = wwn_list;
(void) l_free_box_list(&b_list);
return (0);
}
/*
* n_rem_list_entry() We found an IB so remove disks that
* are in the Photon from the individual device list.
*
* OUTPUT:
* wwn_list - removes the fcal disks that are in SENA enclosure
*
* RETURNS:
* none
*/
void
struct wwn_list_struct **wwn_list)
{
int k;
N_DPRINTF(" n_rem_list_entry: Removing devices"
" with box_id=0x%x from device list.\n", box_id);
k++, dev_addr_list++) {
== box_id) {
}
}
}
/*
* n_rem_list_entry_fabric() We found an IB so remove disks that
* are in the Photon from the individual device list.
*
* OUTPUT:
* wwn_list - removes the fcal disks that are in SENA enclosure
*
* RETURNS:
* none
*/
void
struct wwn_list_struct **wwn_list)
{
int k;
N_DPRINTF(" n_rem_list_entry: Removing devices"
" with the same domain and area ID as"
" 0x%x PA from device list.\n", pa);
k++, dev_addr_ptr++) {
/* matching the domain and area id with input alpa, */
/* ignoring last 8 bits. */
wwn_list);
}
}
}
/*
* n_rem_wwn_entry() removes input wwn from wwn_list.
*
* OUTPUT:
* wwn_list - removes the input wwn from wwn_list if found.
*
* RETURNS:
* none
*/
void
{
int l, found_dev;
found_dev = 0;
}
}
if (found_dev) {
/* Remove this entry from the list */
} else {
}
}
N_DPRINTF(" n_rem_wwn_entry: "
"Removing Logical=%s "
"Current=0x%x, "
"Prev=0x%x, Next=0x%x\n",
l1,
N_DPRINTF(" n_rem_list_entry: "
"No non-Photon "
"devices left"
" in the list.\n");
return;
}
} else {
}
}
}
/*
* non_encl_probe() Finds and displays a list of
* non-SENA fcal devices which is found on the
* system.
*
* RETURNS:
* none.
*/
void
{
int err = 0;
exit(-1);
}
} else {
}
} else {
return;
}
if ((!g_get_pathlist(temppath,
&pathlist)) &&
tempptra++;
}
} else {
SLSH_DRV_NAME_ST)) != NULL) ||
SLSH_DRV_NAME_SSD)) != NULL)) &&
tempptra++;
}
}
"Type:Reserved"));
} else {
"Type:Unknown"));
}
}
NULL) {
tempptrb++;
}
} else {
SLSH_DRV_NAME_ST)) != NULL) ||
SLSH_DRV_NAME_SSD)) != NULL)) &&
tempptrb++;
}
}
}
/*
* Have we retrieved a snapshot yet?
*/
if (root == DI_NODE_NIL) {
DI_NODE_NIL) {
MSGSTR(2319,
"\nFailed to get device tree snapshot:\n"));
exit(1);
}
}
/* Apply devid to ssd devices only */
SLSH_DRV_NAME_SSD) != NULL) {
(void) print_errString(err,
}
/*
* Try retrieve of devid only once. If it fails
* don't try it again but print error,
* There should be a devid prop.
*/
retr_outer = 1;
}
/*
* Apply devid to block devices only.
* Get devid of inner path and compare
* with outer path's devid.
*/
SLSH_DRV_NAME_SSD) != NULL) &&
(void) print_errString(err,
compare_result = 0;
} else {
}
} else {
/* devid isn't applied */
compare_result = 0;
}
if (compare_result == 0) {
inner->logical_path)) {
"Physical Path:"));
}
}
/* Remove this entry from the list */
}
}
} else {
} /* End if (compare_result == 0) */
} else {
}
} else {
}
}
retr_outer = 0;
} /* End while (wwn_list != NULL) */
(void) g_free_wwn_list(&wwn_listh);
}
void
{
exit(-1);
}
"in /dev/es\n"), ENCLOSURE_PROD_NAME);
} else {
"Found Enclosure(s)"));
} else {
}
/* Don't re-print multiple paths */
multi_print_flag = 0;
b_list->b_node_wwn_s) == 0) {
multi_print_flag = 1;
break;
}
}
if (multi_print_flag) {
continue;
}
/*
* Print logical path on same line if not multipathed.
*/
multi_path_flag = 0;
b_list->b_node_wwn_s) == 0)) {
multi_path_flag = 1;
}
}
if (multi_path_flag) {
}
}
b_list->b_node_wwn_s) == 0)) {
}
}
}
/* Check for duplicate names */
}
}
}
if (duplicate_names_found) {
"the same names.\n"
"You can not use the \"enclosure\""
" name to specify these subsystems.\n"
"Please use the \"enclosure_name\""
" subcommand to select unique names.\n\n"));
}
(void) l_free_box_list(&b_list);
}
/*
* display_port_status() Prints the device's
* port status.
*
* RETURNS:
* none.
*/
void
{
if (d_state_flag & L_OPEN_FAIL) {
} else if (d_state_flag & L_NOT_READY) {
} else if (d_state_flag & L_NOT_READABLE) {
} else if (d_state_flag & L_SPUN_DWN_D) {
} else if (d_state_flag & L_SCSI_ERR) {
} else if (d_state_flag & L_RESERVED) {
} else if (d_state_flag & L_NO_LABEL) {
} else {
}
}
/*
* Displays individual SENA
* FC disk information.
*
* Caller to this routine should free the storage due to
* the use of g_get_dev_map
*
* RETURNS:
* none.
*/
void
{
/*
* Do a quick check to see if its the same path as in last call.
* path_phys is a static array and so dont worry about its
* initialization.
*/
/*
* slot_valid is 1 when argument is of the form 'enclosure,[f|r]<n>'.
* If slot_valid != 1, g_get_dev_map and l_get_ses_path would
* already have been called
*/
/* Get the location information. */
exit(-1);
}
exit(-1);
}
}
/*
* Get the WWN for our disk if we already haven't or if there was an
* error earlier
*/
if (same_path_phys == B_FALSE) {
exit(-1);
}
exit(-1);
}
}
/*
* We are interested only a couple of ib_tbl fields and
* those get filled using l_get_ib_status.
* Note that NOT ALL of ib_tbl fields get filled here
*/
exit(-1);
}
/*
* Get path to all the FC disk and tape devices.
* if we haven't already done so in a previous pass
*/
}
/*
* Get the disk status if it is a different path_phys from
* last time.
*/
if (same_path_phys == B_FALSE) {
(void) memset(&l_disk_state, 0,
sizeof (struct l_disk_state_struct));
exit(-1);
}
}
"\nWARNING: No path found "
" (It may be necessary to run the \"disks\" "
"program.)\n\n"));
/* Just call to get the status directly. */
exit(-1);
}
exit(-1);
}
no_path_flag++;
}
"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
}
/* get mode page information for FC device */
(uchar_t)sizeof (struct mode_header_10_struct) +
offset = sizeof (struct mode_header_10_struct) +
sizeof (mode_header_ptr->length)) &&
!mode_data_avail) {
break;
}
}
}
case DTYPE_DIRECT:
path_struct->argv);
break;
case DTYPE_SEQUENTIAL: /* Tape */
path_struct->argv);
break;
default:
path_struct->argv);
break;
}
} else {
if (path_struct->f_flag) {
MSGSTR(66,
" Status(Port A):\tBYPASSED\n"));
}
} else {
MSGSTR(66,
" Status(Port A):\tBYPASSED\n"));
}
}
}
} else {
if (path_struct->f_flag) {
MSGSTR(65,
" Status(Port B):\tBYPASSED\n"));
}
} else {
MSGSTR(65,
" Status(Port B):\tBYPASSED\n"));
}
}
}
if (no_path_flag) {
if (port_a_flag != NULL) {
} else {
}
"No state available.\n"));
}
}
/*
* non_encl_fc_disk_display() Prints the device specific
* information for an individual fcal device.
*
* RETURNS:
* none.
*/
static int
{
/* Get path to all the FC disk and tape devices. */
return (err);
}
path_struct->argv) == 0) {
argpwwn = 1;
break;
path_struct->argv) == 0) {
argnwwn = 1;
break;
}
}
if (argpwwn) {
path_struct->argv) != 0) {
continue;
}
path_a_found = 0;
path_b_found = 0;
mode_data_avail = 0;
} else if (argnwwn) {
last_logical_path) != NULL) {
continue;
}
path_struct->argv) != 0) {
continue;
}
(void) strcpy(last_logical_path,
path_a_found = 0;
path_b_found = 0;
mode_data_avail = 0;
}
return (err);
}
N_DPRINTF(" non_encl_fc_disk_display: Error finding"
" multiple paths to the disk.\n");
(void) g_free_wwn_list(&wwn_list);
return (-1);
}
/* get mode page information for FC device */
(uchar_t)sizeof (struct mode_header_10_struct) +
offset = sizeof (struct mode_header_10_struct) +
sizeof (mode_header_ptr->length)) &&
!mode_data_avail) {
break;
}
}
}
case DTYPE_DIRECT:
path_struct->argv);
break;
case DTYPE_SEQUENTIAL: /* Tape */
path_struct->argv);
break;
default:
path_struct->argv);
break;
}
MSGSTR(2114,
"non_encl_fc_disk_display: Inquiry failed\n"));
(void) g_free_multipath(
(void) g_free_wwn_list(&wwn_list);
return (-1);
}
(void) g_free_multipath(
(void) g_free_wwn_list(&wwn_list);
return (-1);
}
"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
}
verbose)) != 0) {
(void) g_free_multipath(
exit(-1);
}
"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
}
"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
}
verbose))) {
exit(-1);
}
if (pathcnt > 1) {
for (i = 0; i < pathcnt; i++) {
if ((!path_a_found) &&
(path_b_found) &&
port_b_wwn_s) == NULL)) {
(void) strncpy(l_disk_state.
path_addr, 16);
}
if ((path_a_found) &&
(!path_b_found) &&
port_a_wwn_s) == NULL)) {
(void) strncpy(l_disk_state.
path_addr, 16);
}
if ((path_a_found) && (path_b_found)) {
break;
}
}
}
}
}
}
}
break;
}
}
(void) g_free_wwn_list(&wwn_list);
return (0);
}
/*
* display_disk_info() Prints the device specific information
* for any FC_AL disk device.
*
* RETURNS:
* none.
*/
void
{
float num_blks;
char *enc_phys_path;
int enc_type = 0;
int err;
if (err) {
exit(1);
}
}
}
if (num_blks) {
MSGSTR(60,
"Unformatted capacity:\t%6.3f MBytes"), num_blks);
}
}
} else {
}
}
MSGSTR(2122,
" Write Cache:\t\t"
"Enabled\n"));
}
MSGSTR(2123,
" Read Cache:\t\t"
"Enabled\n"));
MSGSTR(2320,
" Minimum prefetch:"
"\t0x%x\n"
" Maximum prefetch:"
"\t0x%x\n"),
}
}
/*
* for display command the initial library version didn't
* display Location information. The change is made
* to display the same Location info as the non-library version.
*/
if (path_struct->slot_valid) {
/*
* We have to do another inquiry on the enclosure (name_buf)
* to determine if this device is within a daktari, or
* a two sided device.
*/
&enc_path_struct, 0)) {
}
}
/* If either of the above fail, we just assume the default */
if (enc_type == DAK_ENC_TYPE) {
if (path_struct->f_flag) {
"In slot %d in the enclosure named: %s\n"),
} else {
"In slot %d in the enclosure named: %s\n"),
name_buf);
}
} else { /* Default enclosure type */
MSGSTR(2126,
"In slot %d in the Front of the enclosure named: %s\n")
: MSGSTR(2127,
"In slot %d in the Rear of the enclosure named: %s\n"),
}
} else {
"In the enclosure named: %s\n"),
name_buf);
}
}
} else {
while (mlist) {
}
}
if (path_struct->slot_valid) {
} else {
}
/* Only bother if the state is O.K. */
}
}
/*
* temp_decode() Display temperature bytes 1-3 state.
*
* RETURNS:
* none.
*/
void
{
": FAILURE - Over Temperature"));
}
": FAILURE - Under Temperature"));
}
": WARNING - Over Temperature"));
}
": WARNING - Under Temperature"));
}
}
/*
* disp_degree() Display temperature in Degrees Celsius.
*
* RETURNS:
* none.
*/
void
{
int t;
t -= 20; /* re-adjust */
/*
* NL_Comment
* The %c is the degree symbol.
*/
}
/*
* trans_decode() Display tranceivers state.
*
* RETURNS:
* none.
*/
void
{
"Disabled"));
}
": Not receiving a signal"));
}
": Laser failed"));
}
}
/*
* trans_messages() Display tranceiver status.
*
* NOTE: The decoding of the status assumes that the elements
* are in order with the first two elements are for the
* "A" IB. It also assumes the tranceivers are numbered
* 0 and 1.
*
* RETURNS:
* none.
*/
void
{
int i, j, k;
int count = 0;
int elem_index = 0;
/* Get and print messages */
elem_index++;
}
count = k = 0;
for (j = 0; j <
/*
* Only display the status for the selected IB.
*/
(void) bcopy((const void *)
if (k == 0) {
} else {
}
} else {
}
k++;
}
count++;
}
}
/*
* Calculate the index to each element.
*/
}
}
/*
* temperature_messages() Display temperature status.
*
* RETURNS:
* none.
*/
void
{
int i, j, last_ok = 0;
int elem_index = 0;
/* Get and print messages */
elem_index++; /* skip global */
if (!rear_flag) {
}
/*
* Check global status and if not all O.K.
* then print individually.
*/
for (j = 0; j <
(void) bcopy((const void *)
all_ok) {
} else {
}
disp_degree(&temp);
temp_decode(&temp);
all_ok = 0;
last_ok = 0;
} else {
last_ok++;
}
last_ok = 0;
all_ok = 0;
last_ok = 0;
all_ok = 0;
last_ok = 0;
all_ok = 0;
last_ok = 0;
all_ok = 0;
} else {
last_ok = 0;
all_ok = 0;
}
}
if (all_ok) {
"NORMAL.)"));
}
all_ok = 1;
} else {
rear_flag = 0;
}
}
}
}
/*
* ib_decode() Display IB byte 3 state.
*
* RETURNS:
* none.
*/
void
{
if (ctlr->overtemp_alart) {
" - IB Over Temperature Alert "));
}
if (ctlr->ib_loop_1_fail) {
" - IB Loop 1 has failed "));
}
if (ctlr->ib_loop_0_fail) {
" - IB Loop 0 has failed "));
}
}
/*
* mb_messages() Display motherboard
* (interconnect assembly) messages.
*
* RETURNS:
* none.
*/
void
{
int j;
}
j++) {
(void) bcopy((const void *)
(void *)&interconnect, sizeof (interconnect));
"Critical Failure: EEPROM failure"));
} else {
"Critical Failure: Unknown failure"));
}
"Non-Critical Failure: EEPROM failure"));
} else {
"Non-Critical Failure: Unknown failure"));
}
} else {
}
}
}
/*
* back_plane_messages() Display back_plane messages
* including the temperature's.
*
* RETURNS:
* none.
*/
void
{
int j;
}
j++) {
(void) bcopy((const void *)
if (j == 0) {
} else {
}
/* This case covers where a and b are bypassed */
}
} else {
}
}
}
/*
* dpm_SSC100_messages() Display SSC100 messages
* including the temperature's.
*
* RETURNS:
* none.
*/
void
{
int j;
}
j++) {
(void) bcopy((const void *)
/* This case covers where a and b are bypassed */
}
} else {
}
}
}
/*
* loop_messages() Display loop messages.
*
* RETURNS:
* none.
*/
void
{
int j;
}
j++) {
(void) bcopy((const void *)
if (j == 0) {
} else {
"Loop A is configured as two separate loops."));
} else {
"Loop A is configured as a single loop."));
}
}
} else {
} else {
"Loop B is configured as two separate loops."));
} else {
"Loop B is configured as a single loop."));
}
}
}
}
}
/*
* ctlr_messages() Display ESI Controller status.
*
* RETURNS:
* none.
*/
void
{
int j;
}
j++) {
(void) bcopy((const void *)
if (j == 0) {
} else {
ib_a_flag = 0;
}
/* If any byte 3 bits set display */
/* Display Version message */
/*
* Display the tranciver module state for this
* IB.
*/
} else {
}
}
}
/*
* fan_decode() Display Fans bytes 1-3 state.
*
* RETURNS:
* none.
*/
void
{
":Yellow LED is on"));
}
":Fan stopped"));
":Fan speed Low"));
} else {
":Fan speed Hi"));
}
}
/*
* fan_messages() Display Fan status.
*
* RETURNS:
* none.
*/
void
{
int j;
/* Get and print messages */
}
j++) {
(void) bcopy((const void *)
fan_decode(&fan);
fan_decode(&fan);
} else {
}
}
}
/*
* ps_decode() Display Power Supply bytes 1-3 state.
*
* RETURNS:
* none.
*/
void
{
": DC Voltage too high"));
}
": DC Voltage too low"));
}
": DC Current too high"));
}
": Temperature too high"));
}
": AC Failed"));
}
": DC Failed"));
}
}
/*
* revision_msg() Print the revision message from page 7.
*
* RETURNS:
* none.
*/
void
{
if (strlen((const char *)
}
}
/*
* ps_messages() Display Power Supply status.
*
* RETURNS:
* none.
*/
void
{
int j;
/* Get and print Power Supply messages */
}
j++) {
(void) bcopy((const void *)
} else {
}
}
}
/*
* abnormal_condition() Display any abnormal condition messages.
*
* RETURNS:
* none.
*/
void
{
"CRITICAL CONDITION DETECTED\n"));
}
"WARNING: NON-CRITICAL CONDITION DETECTED\n"));
}
"WARNING: Invalid Operation bit set.\n"
"\tThis means an Enclosure Control page"
" or an Array Control page with an invalid\n"
"\tformat has previously been transmitted to the"
" Enclosure Services card by a\n\tSend Diagnostic"
" SCSI command.\n"));
}
}
/*
* adm_start() Spin up the given list
* of SENA devices.
*
* RETURNS:
* none.
*/
int
{
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
*argv);
if (err != -1) {
}
(argv)++;
retval++;
continue;
}
(argv)++;
retval++;
continue;
}
(argv)++;
}
return (retval);
}
/*
* adm_stop() Spin down a
* given list of SENA devices.
*
* RETURNS:
* none.
*/
int
{
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
*argv);
if (err != -1) {
}
(argv)++;
retval++;
continue;
}
/*
* scsi stop is not supported for tape drives.
* The scsi unload op code for tape is the same as a
* scsi stop for disk so this command will eject the tape.
* If an eject is the desired behavior then remove the
* following if block. ('mt offline' will give you
* the same eject functionality).
*/
(void) print_errString(0, path_phys);
(argv)++;
continue;
}
(argv)++;
retval++;
continue;
}
(argv)++;
}
return (retval);
}
/*
* On a SOC+ chip, the port is either put into (offline) or pulled out
* of (online) a loopback mode since the laser cannot be turned on or off.
* As of this writing, this feature is yet to be supported by the ifp
* driver on a QLogic card.
*
* INPUT :
* Command line args and flag - LUX_P_ONLINE or LUX_P_OFFLINE
* The path that is passed has to be the physical path to the port.
* For example :
* RETURNS :
* Nothing
*/
int
{
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
*argv);
if (err != -1) {
}
argv++;
retval++;
continue;
}
/* Get the nexus path - need this to print messages */
retval++;
goto cleanup_and_go;
}
if (flag == LUX_P_OFFLINE) {
retval++;
goto cleanup_and_go;
}
} else if (flag == LUX_P_ONLINE) {
retval++;
goto cleanup_and_go;
}
} else {
MSGSTR(2225,
"Unknown action requested "
"on port - %d\nIgnoring."),
flag);
retval++;
}
argv++;
}
return (retval);
}
/*
* Expert level subcommand 'luxadm -e port'
* which displays all FC ports on a host and state information for
* connectivity (CONNECTED or NOT CONNECTED) indicating whether there
* are devices attached to the port.
*
* Sample output for ifp:
*
*
* Sample output for socal:
*
*
* Note: for socal the path returned is not a devctl path as there is no
* devctl path for socal.
*
* Sample output for fp:
*
*/
int
{
/*
* If another port driver needs to be searched, add it here
*/
"fp",
"ifp",
NULL};
int port_state;
/*
* Look for all HBA ports as listed in portdrvr_list[]
*/
while (portdrvr_list[x]) {
if (err != L_PORT_DRIVER_NOT_FOUND &&
err != L_PHYS_PATH_NOT_FOUND) {
retval++;
}
}
x++;
}
/*
* For each port path found get the connection state.
* If there are devices attached the state is considered connected.
*/
&port_state, verbose)) {
retval++;
} else {
if (port_state == PORT_CONNECTED) {
MSGSTR(2233,
"CONNECTED\n"));
} else {
MSGSTR(2234,
"NOT CONNECTED\n"));
}
}
}
return (retval);
}
/*
* Expert level subcommand 'luxadm -e external_loopback <portpath>
* internal_loopback
* no_loopback
* Does just what you would think. Sets port in designated loopback
* mode.
* INPUT: portpath - path to device on which to set loopback mode
* flag - loopback mode to set. Values are:
* EXT_LOOPBACK
* INT_LOOPBACK
* NO_LOOPBACK
*
* RETURN: 0 on success
* non-zero on failure
*/
int
{
int err;
int cmd;
MSGSTR(33,
" Error: converting"
" %s to physical path.\n"
" Invalid pathname.\n"),
portpath);
if (err != -1) {
}
return (-1);
}
switch (flag) {
case EXT_LOOPBACK:
cmd = EXT_LPBACK;
break;
case INT_LOOPBACK:
cmd = INT_LPBACK;
break;
case NO_LOOPBACK:
break;
default:
MSGSTR(2225,
"Unknown action requested "
"on port - %d\nIgnoring."),
flag);
return (-1);
}
return (-1);
} else {
switch (flag) {
case EXT_LOOPBACK:
MSGSTR(2230,
"External loopback mode set "
"on:\n%s\n"),
portpath);
break;
case INT_LOOPBACK:
MSGSTR(2231,
"Internal loopback mode set "
"on:\n%s\n"),
portpath);
break;
case NO_LOOPBACK:
MSGSTR(2232,
"Loopback mode unset "
"on:\n%s\n"),
portpath);
break;
default:
break;
}
}
return (0);
}
/*
* To print the pathlist and mpxio path attributes
*/
void
{
int retval = 0;
int err;
if (retval != 0) {
exit(-1);
}
for (i = 0; i < pathcnt; i++) {
if ((err = get_host_controller_pwwn(
(void) print_errString(err,
exit(1);
}
}
if (!err) {
wwns);
}
}
&ext_state)) != 0) {
(void) print_errString(err,
exit(1);
} else {
ext_state = 0;
MSGSTR(2327,
}
}
}
/* Free memory for per path info properties */
}
/*
* compare_multipath
* compares path with all paths in pathlist
* If there is a match, 0 is returned, otherwise 1 is returned
*/
int
{
return (0);
}
}
return (1);
}
/*
* lun_display() Prints the
* information for an individual lun.
*
* RETURNS:
* none.
*/
static int
{
int found = 0;
/*
* Get path to all the FC disk and tape devices.
* If there is no slash in the argument in this routine, we assume
* it is a wwn argument.
*/
return (err);
}
} else {
return (err);
}
}
path_struct->argv) == 0) {
argpwwn = 1;
break;
path_struct->argv) == 0) {
argnwwn = 1;
break;
}
}
if (argpwwn) {
path_struct->argv) != 0) {
continue;
}
} else if (argnwwn) {
last_logical_path) != NULL) {
continue;
}
path_struct->argv) != 0) {
continue;
}
(void) strcpy(last_logical_path,
}
mplistp) == 0) {
continue;
}
}
mode_data_avail = 0;
/*
* Don't call g_get_multipath if this is a SCSI_VHCI device
* dlist gets alloc'ed here to retain the free at the end
*/
return (err);
}
N_DPRINTF(" lun_display: Error finding"
" multiple paths to the disk.\n");
(void) g_free_wwn_list(&wwn_list);
return (L_NO_VALID_PATH);
}
} else {
/* Search for match on physical path name */
== 0) {
found++;
break;
}
}
if (!found) {
return (L_NO_VALID_PATH);
} else {
found = 0;
}
return (L_MALLOC_FAILED);
}
return (L_MALLOC_FAILED);
}
return (L_MALLOC_FAILED);
}
}
/* add the path to the list for compare */
if ((mpl = (struct mplist_struct *)
== NULL) {
return (L_MALLOC_FAILED);
}
return (L_MALLOC_FAILED);
}
} else {
}
}
}
/* get mode page information for FC device */
mode_header_ptr = (struct mode_header_10_struct *)
(void *)pg_buf;
offset = sizeof (struct mode_header_10_struct) +
sizeof (mode_header_ptr->length)) &&
!mode_data_avail) {
break;
}
}
}
case DTYPE_DIRECT:
path_struct->argv);
break;
case DTYPE_SEQUENTIAL: /* Tape */
path_struct->argv);
break;
default:
path_struct->argv);
break;
}
break;
}
} /* End for wwn_list_ptr = list_start... */
(void) g_free_wwn_list(&wwn_list);
return (0);
}
/*
* display_lun_info() Prints the device specific information
* for a lun.
*
* RETURNS:
* none.
*/
void
{
float lunMbytes;
int err;
int peripheral_qual;
start_time = gethrtime();
}
exit(1);
}
&serial_len)) {
exit(1);
}
/*
* check to see if the peripheral qualifier is zero
* if it is non-zero, we will return with an error.
*/
if (peripheral_qual != DPQ_POSSIBLE) {
"(%s) is not available.\n"), phys_path);
exit(1);
}
exit(1);
}
"Unformatted capacity:\t%6.3f MBytes"), lunMbytes);
}
}
"Enabled\n"));
}
"Enabled\n"));
"\t0x%x\n Maximum prefetch:\t0x%x\n"),
}
}
path_struct->argv);
exit(1);
}
} else {
/*
* first display user's requested path
* This will avoid duplicate inquiries as well
*/
== 0) {
wwn_list);
break;
}
}
/*
* Now display rest of paths
* skipping one already displayed
*/
== 0) {
continue;
}
exit(1);
}
wwn_list);
}
}
"\t\tTime = %lld millisec\n",
}
}
/*
* display_path_info() Prints the path specific information
* for a lun.
* Note: Only applies to ssd nodes currently
*
* RETURNS:
* none.
*/
static void
{
int err;
char *cptr;
int status;
/*
* Walk the wwn list passed in and print the
* port wwn matching the device path
*/
break;
}
}
/*
* newline here in case port wwn not found
*/
drvr_path[0] = '\0';
*cptr = '\0';
} else {
exit(1);
}
*cptr = '\0';
exit(1);
}
/*
* Determine path status
*/
exit(1);
} else {
}
}
/*
* Retrieves the lun capacity
*/
static int
{
int fd;
return (L_INVALID_PATH);
}
return (L_OPEN_PATH_FAIL);
} else {
sizeof (struct scsi_capacity_16));
}
return (0);
}
/*
* Retrieves the reservation status
*/
static int
{
return (L_INVALID_PATH);
}
*status = 0;
return (L_OPEN_PATH_FAIL);
} else {
if ((mystatus & L_SCSI_ERROR) &&
*status = L_NOT_READY;
} else if ((mystatus & L_SCSI_ERROR) &&
((mystatus & ~L_SCSI_ERROR) ==
*status = L_RESERVED;
} else {
*status = L_SCSI_ERR;
}
}
}
return (0);
}
/*
* Description:
* Retrieves the port wwn associated with the hba node
*
* pwwn: ptr to a uchar_t array of size WWN_SIZE
*/
static int
{
int di_ret;
char *promname;
return (L_INVALID_PATH);
}
return (L_INVALID_PATH);
}
/*
* ifp nodes do not have a port-wwn prom property
* so handle them via FC4 device map
*/
if (path_type & FC4_XPORT_MASK) {
return (err);
} else {
return (0);
}
/* For Leadville path get the port wwn through g_get_host param. */
} else if ((path_type & FC_GEN_XPORT) &&
/*
* For Leadville path, get the port wwn through
* g_get_host param. This is a general solution
* to support 3rd party vendor Leadville FCA.
*/
my_hba_path[0] = '\0';
if ((err = g_get_host_params(
my_hba_path, &hba_port, 0)) != 0) {
return (err);
} else {
WWN_SIZE);
return (0);
}
/*
* Get port WWN through prom property
*/
my_hba_path[0] = '\0';
/*
* sanity check for /devices mount point
*/
} else {
return (L_INVALID_PATH);
}
/*
* Now strip off the trailing "/fp@"
*/
*portptr = '\0';
}
return (L_DEV_SNAPSHOT_FAILED);
}
"port-wwn", &port_wwn_data);
return (L_NO_WWN_PROP_FOUND);
} else {
found++;
}
return (L_PROM_INIT_FAILED);
}
if (((promname = di_prom_prop_name(
/* Found port-wwn */
found++;
break;
}
}
}
if (found) {
return (0);
} else {
return (L_INVALID_PATH);
}
} else {
return (L_INVALID_PATH_TYPE);
}
}
/*
* Description:
* Retrieve pwwn via SFIOCGMAP
*/
static int
{
int fd;
return (L_INVALID_PATH);
}
return (errno);
}
return (L_SFIOCGMAP_IOCTL_FAIL);
}
return (L_SFIOCGMAP_IOCTL_FAIL);
}
return (0);
}
/*
* from_ptr: ptr to uchar_t array of size WWN_SIZE
* to_ptr: char ptr to string of size WWN_SIZE*2+1
*/
void
{
return;
}
/*
* Frees a previously allocated mplist_struct
*/
void
{
}
}
}
int
{
int err;
if ((path_phys =
path);
return (1);
}
return (1);
}
return (0);
}
int
{
int err;
if ((path_phys =
path);
return (1);
}
return (1);
}
return (0);
}
void
i18n_catopen() {
(void) g_i18n_catopen();
}
int err;
return (-1);
}
return (0);
}
/*
* Print out private loop dev dtype
*/
void
{
(dtype_prop & DTYPE_MASK));
} else {
}
/* Check to see if this is the HBA */
/* MATCH */
",Host Bus Adapter)\n"));
} else {
}
}