4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 #define LUX_SF_INST_SHIFT4MINOR 6
29 #define LUX_SF_MINOR2INST(x) (x >> LUX_SF_INST_SHIFT4MINOR)
34 #include <sys/errno.h>
35 #include <sys/types.h>
37 #include <sys/param.h>
39 #include <sys/mkdev.h>
49 #include <termio.h> /* For password */
51 #include <sys/scsi/scsi.h>
52 #include <sys/scsi/generic/commands.h>
64 extern const int OPTION_A
;
65 extern const int OPTION_B
;
66 extern const int OPTION_C
;
67 extern const int OPTION_D
;
68 extern const int OPTION_E
;
69 extern const int OPTION_F
;
70 extern const int OPTION_L
;
71 extern const int OPTION_P
;
72 extern const int OPTION_R
;
73 extern const int OPTION_T
;
74 extern const int OPTION_V
;
75 extern const int OPTION_Z
;
76 extern const int OPTION_Y
;
77 extern const int OPTION_CAPF
;
78 extern const int PVERBOSE
;
79 extern const int SAVE
;
80 extern const int EXPERT
;
82 static struct termios termios
;
84 static void pho_display_config(char *);
85 static void dpm_display_config(char *);
86 static void n_rem_list_entry(uchar_t
, struct gfc_map
*,
88 static void n_rem_list_entry_fabric(int, struct gfc_map
*,
90 static void n_rem_wwn_entry(uchar_t
*, WWN_list
**);
91 static void display_disk_info(L_inquiry
, L_disk_state
,
92 Path_struct
*, struct mode_page
*, int, char *, int);
93 static void display_lun_info(L_disk_state
, Path_struct
*,
94 struct mode_page
*, int, WWN_list
*, char *);
95 static void display_fc_disk(struct path_struct
*, char *, gfc_map_t
*,
97 static void adm_display_err(char *, int);
98 static void temperature_messages(struct l_state_struct
*, int);
99 static void ctlr_messages(struct l_state_struct
*, int, int);
100 static void fan_messages(struct l_state_struct
*, int, int);
101 static void ps_messages(struct l_state_struct
*, int, int);
102 static void abnormal_condition_display(struct l_state_struct
*);
103 static void loop_messages(struct l_state_struct
*, int, int);
104 static void revision_msg(struct l_state_struct
*, int);
105 static void mb_messages(struct l_state_struct
*, int, int);
106 static void back_plane_messages(struct l_state_struct
*, int, int);
107 static void dpm_SSC100_messages(struct l_state_struct
*, int, int);
108 static void mb_messages(struct l_state_struct
*, int, int);
109 static void back_plane_messages(struct l_state_struct
*, int, int);
110 static void dpm_SSC100_messages(struct l_state_struct
*, int, int);
111 static void trans_decode(Trans_elem_st
*trans
);
112 static void trans_messages(struct l_state_struct
*, int);
113 static void adm_print_pathlist(char *);
114 static void display_path_info(char *, char *, WWN_list
*);
115 static void copy_wwn_data_to_str(char *, const uchar_t
*);
116 static void adm_mplist_free(struct mplist_struct
*);
117 static int lun_display(Path_struct
*path_struct
, L_inquiry inq_struct
,
119 static int non_encl_fc_disk_display(Path_struct
*path_struct
,
120 L_inquiry inq_struct
, int verbose
);
121 static int get_enclStatus(char *phys_path
, char *encl_name
, int off_flag
);
122 static int get_host_controller_pwwn(char *hba_path
, uchar_t
*pwwn
);
123 static int get_lun_capacity(char *devpath
,
124 struct scsi_capacity_16
*cap_data
);
125 static int get_path_status(char *devpath
, int *status
);
126 static int get_FC4_host_controller_pwwn(char *hba_path
, uchar_t
*pwwn
);
129 * Gets the device's state from the SENA IB and
130 * checks whether device is offlined, bypassed
131 * or if the slot is empty and prints it to the
139 print_devState(char *devname
, char *ppath
, int fr_flag
, int slot
,
144 int i
, elem_index
= 0;
145 uchar_t device_off
, ib_status_code
, bypass_a_en
, bypass_b_en
;
149 if ((err
= l_get_status(ppath
, &l_state
, verbose_flag
)) != 0) {
150 (void) print_errString(err
, ppath
);
154 for (i
= 0; i
< (int)l_state
.ib_tbl
.config
.enc_num_elem
; i
++) {
156 if (l_state
.ib_tbl
.config
.type_hdr
[i
].type
== ELM_TYP_BP
) {
159 elem_index
+= l_state
.ib_tbl
.config
.type_hdr
[i
].num
;
161 (void) bcopy((const void *)
162 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
]),
163 (void *)&bpf
, sizeof (bpf
));
164 (void) bcopy((const void *)
165 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
+ 1]),
166 (void *)&bpr
, sizeof (bpr
));
169 device_off
= l_state
.drv_front
[slot
].ib_status
.dev_off
;
170 bypass_a_en
= l_state
.drv_front
[slot
].ib_status
.bypass_a_en
;
171 bypass_b_en
= l_state
.drv_front
[slot
].ib_status
.bypass_b_en
;
172 ib_status_code
= l_state
.drv_front
[slot
].ib_status
.code
;
174 device_off
= l_state
.drv_rear
[slot
].ib_status
.dev_off
;
175 bypass_a_en
= l_state
.drv_rear
[slot
].ib_status
.bypass_a_en
;
176 bypass_b_en
= l_state
.drv_rear
[slot
].ib_status
.bypass_b_en
;
177 ib_status_code
= l_state
.drv_rear
[slot
].ib_status
.code
;
180 (void) fprintf(stdout
,
182 "%s is offlined and bypassed.\n"
183 " Could not get device specific"
184 " information.\n\n"),
186 } else if (bypass_a_en
&& bypass_b_en
) {
187 (void) fprintf(stdout
,
189 "%s is bypassed (Port:AB).\n"
190 " Could not get device specific"
191 " information.\n\n"),
193 } else if (ib_status_code
== S_NOT_INSTALLED
) {
194 (void) fprintf(stdout
,
196 "Slot %s is empty.\n\n"),
198 } else if (((bpf
.code
!= S_NOT_INSTALLED
) &&
199 ((bpf
.byp_a_enabled
|| bpf
.en_bypass_a
) &&
200 (bpf
.byp_b_enabled
|| bpf
.en_bypass_b
))) ||
201 ((bpr
.code
!= S_NOT_INSTALLED
) &&
202 ((bpr
.byp_a_enabled
|| bpr
.en_bypass_a
) &&
203 (bpr
.byp_b_enabled
|| bpr
.en_bypass_b
)))) {
204 (void) fprintf(stdout
,
206 "Backplane(Port:AB) is bypassed.\n"
207 " Could not get device specific"
209 " %s.\n\n"), devname
);
211 (void) fprintf(stderr
,
214 " %s to physical path.\n"
215 " Invalid pathname.\n"),
222 * Given an error number, this functions
223 * calls the get_errString() to print a
224 * corresponding error message to the stderr.
225 * get_errString() always returns an error
226 * message, even in case of undefined error number.
227 * So, there is no need to check for a NULL pointer
228 * while printing the error message to the stdout.
234 print_errString(int errnum
, char *devpath
)
239 errStr
= g_get_errString(errnum
);
241 if (devpath
== NULL
) {
242 (void) fprintf(stderr
,
245 (void) fprintf(stderr
,
246 "%s - %s.\n\n", errStr
, devpath
);
249 /* free the allocated memory for error string */
255 * adm_inquiry() Display the inquiry information for
256 * a SENA enclosure(s) or disk(s).
262 adm_inquiry(char **argv
)
267 int path_index
= 0, retval
= 0;
268 int slot
, f_r
, err
= 0, argpwwn
, argnwwn
;
269 char inq_path
[MAXNAMELEN
];
270 char *path_phys
= NULL
, *ptr
;
271 Path_struct
*path_struct
;
272 WWN_list
*wwn_list
, *wwn_list_ptr
, *list_start
;
273 char last_logical_path
[MAXPATHLEN
];
275 while (argv
[path_index
] != NULL
) {
276 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
277 &path_struct
, Options
& PVERBOSE
)) != 0) {
278 (void) strcpy(inq_path
, argv
[path_index
]);
279 if (((ptr
= strstr(inq_path
, ",")) != NULL
) &&
280 ((*(ptr
+ 1) == 'f') || (*(ptr
+ 1) == 'r') ||
281 (*(ptr
+1) == 's'))) {
283 (void) print_errString(err
, argv
[path_index
]);
289 slot
= path_struct
->slot
;
290 f_r
= path_struct
->f_flag
;
292 if ((err
= l_convert_name(inq_path
, &path_phys
,
293 &path_struct
, Options
& PVERBOSE
)) != 0) {
294 (void) fprintf(stderr
,
297 " %s to physical path.\n"
298 " Invalid pathname.\n"),
301 (void) print_errString(err
,
308 if ((err
= print_devState(argv
[path_index
],
309 path_struct
->p_physical_path
,
310 f_r
, slot
, Options
& PVERBOSE
)) != 0) {
317 (void) print_errString(err
, argv
[path_index
]);
319 (void) fprintf(stderr
, "\n ");
320 (void) fprintf(stderr
,
321 MSGSTR(112, "Error: Invalid pathname (%s)"),
323 (void) fprintf(stderr
, "\n");
331 if (strstr(argv
[path_index
], "/") != NULL
) {
332 if (err
= g_get_inquiry(path_phys
, &inq
)) {
333 (void) fprintf(stderr
, "\n");
334 (void) print_errString(err
, argv
[path_index
]);
335 (void) fprintf(stderr
, "\n");
341 serial_len
= sizeof (inq80
.inq_serial
);
342 if (err
= g_get_serial_number(path_phys
, inq80
.inq_serial
,
344 (void) fprintf(stderr
, "\n");
345 (void) print_errString(err
, argv
[path_index
]);
346 (void) fprintf(stderr
, "\n");
351 print_inq_data(argv
[path_index
], path_phys
, inq
,
352 inq80
.inq_serial
, serial_len
);
356 if ((err
= g_get_wwn_list(&wwn_list
, 0)) != 0) {
359 g_sort_wwn_list(&wwn_list
);
360 list_start
= wwn_list
;
361 argpwwn
= argnwwn
= 0;
362 (void) strcpy(last_logical_path
, path_phys
);
363 for (wwn_list_ptr
= wwn_list
; wwn_list_ptr
!= NULL
;
364 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
365 if (strcasecmp(wwn_list_ptr
->port_wwn_s
, path_struct
->argv
) ==
367 list_start
= wwn_list_ptr
;
370 } else if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
371 path_struct
->argv
) == 0) {
372 list_start
= wwn_list_ptr
;
378 if (!(argpwwn
|| argnwwn
)) {
380 * if the wwn list is null or the arg device not found
381 * from the wwn list, still go ahead to issue inquiry.
383 if (err
= g_get_inquiry(path_phys
, &inq
)) {
384 (void) fprintf(stderr
, "\n");
385 (void) print_errString(err
, argv
[path_index
]);
386 (void) fprintf(stderr
, "\n");
392 serial_len
= sizeof (inq80
.inq_serial
);
393 if (err
= g_get_serial_number(path_phys
, inq80
.inq_serial
,
395 (void) fprintf(stderr
, "\n");
396 (void) print_errString(err
, argv
[path_index
]);
397 (void) fprintf(stderr
, "\n");
402 print_inq_data(argv
[path_index
], path_phys
, inq
,
403 inq80
.inq_serial
, serial_len
);
404 (void) g_free_wwn_list(&wwn_list
);
409 for (wwn_list_ptr
= list_start
; wwn_list_ptr
!= NULL
;
410 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
412 if (strcasecmp(wwn_list_ptr
->port_wwn_s
,
413 path_struct
->argv
) != 0) {
416 (void) strcpy(path_phys
,
417 wwn_list_ptr
->physical_path
);
418 } else if (argnwwn
) {
419 if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
420 path_struct
->argv
) != 0) {
423 if (strstr(wwn_list_ptr
->logical_path
,
424 last_logical_path
) != NULL
) {
427 (void) strcpy(path_phys
,
428 wwn_list_ptr
->physical_path
);
429 (void) strcpy(last_logical_path
,
430 wwn_list_ptr
->logical_path
);
433 if (err
= g_get_inquiry(path_phys
, &inq
)) {
434 (void) fprintf(stderr
, "\n");
435 (void) print_errString(err
, argv
[path_index
]);
436 (void) fprintf(stderr
, "\n");
441 serial_len
= sizeof (inq80
.inq_serial
);
442 if (err
= g_get_serial_number(path_phys
, inq80
.inq_serial
,
444 (void) fprintf(stderr
, "\n");
445 (void) print_errString(err
, argv
[path_index
]);
446 (void) fprintf(stderr
, "\n");
450 print_inq_data(argv
[path_index
], path_phys
, inq
,
451 inq80
.inq_serial
, serial_len
);
455 (void) g_free_wwn_list(&wwn_list
);
462 * FORCELIP expert function
465 adm_forcelip(char **argv
)
467 int slot
, f_r
, path_index
= 0, err
= 0, retval
= 0;
468 Path_struct
*path_struct
= NULL
;
469 char *path_phys
= NULL
, *ptr
;
470 char err_path
[MAXNAMELEN
];
472 while (argv
[path_index
] != NULL
) {
473 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
474 &path_struct
, Options
& PVERBOSE
)) != 0) {
475 (void) strcpy(err_path
, argv
[path_index
]);
477 (void) print_errString(err
, argv
[path_index
]);
482 if (((ptr
= strstr(err_path
, ", ")) != NULL
) &&
483 ((*(ptr
+ 1) == 'f') || (*(ptr
+ 1) == 'r') ||
484 (*(ptr
+1) == 's'))) {
486 slot
= path_struct
->slot
;
487 f_r
= path_struct
->f_flag
;
489 if ((err
= l_convert_name(err_path
,
490 &path_phys
, &path_struct
,
491 Options
& PVERBOSE
)) != 0) {
492 (void) fprintf(stderr
, MSGSTR(33,
494 " %s to physical path.\n"
495 " Invalid pathname.\n"),
498 (void) print_errString(err
,
505 if ((err
= print_devState(argv
[path_index
],
506 path_struct
->p_physical_path
,
507 f_r
, slot
, Options
& PVERBOSE
)) != 0) {
513 (void) fprintf(stderr
, "\n ");
514 (void) fprintf(stderr
, MSGSTR(112,
515 "Error: Invalid pathname (%s)"),
517 (void) fprintf(stderr
, "\n");
523 if (err
= g_force_lip(path_phys
, Options
& PVERBOSE
)) {
524 (void) print_errString(err
, argv
[path_index
]);
530 if (path_struct
!= NULL
) {
531 (void) free(path_struct
);
545 adm_display_config(char **argv
)
547 L_inquiry inq
, ses_inq
;
548 int i
, slot
, f_r
, path_index
= 0, err
= 0, opnerr
= 0;
551 Path_struct
*path_struct
;
552 char *path_phys
= NULL
, *ptr
;
553 char ses_path
[MAXPATHLEN
], inq_path
[MAXNAMELEN
];
556 while (argv
[path_index
] != NULL
) {
557 VERBPRINT(MSGSTR(2108, " Displaying information for: %s\n"),
559 map
.dev_addr
= (gfc_port_dev_info_t
*)NULL
;
560 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
561 &path_struct
, Options
& PVERBOSE
)) != 0) {
562 if (strstr(argv
[path_index
], SCSI_VHCI
) == NULL
) {
564 (void) strcpy(inq_path
, argv
[path_index
]);
565 if (((ptr
= strstr(inq_path
, ",")) != NULL
) &&
566 ((*(ptr
+ 1) == 'f') || (*(ptr
+ 1) == 'r') ||
567 (*(ptr
+1) == 's'))) {
570 (void) print_errString(err
,
577 slot
= path_struct
->slot
;
578 f_r
= path_struct
->f_flag
;
579 if ((err
= l_convert_name(inq_path
, &path_phys
,
580 &path_struct
, Options
& PVERBOSE
))
583 (void) fprintf(stderr
,
586 " %s to physical path.\n"
587 " Invalid pathname.\n"),
590 (void) print_errString(err
,
598 if ((err
= print_devState(argv
[path_index
],
599 path_struct
->p_physical_path
,
600 f_r
, slot
, Options
& PVERBOSE
)) != 0) {
607 (void) print_errString(err
,
610 (void) fprintf(stderr
, "\n ");
611 (void) fprintf(stderr
,
613 "Error: Invalid pathname (%s)"),
615 (void) fprintf(stderr
, "\n");
621 (void) print_errString(err
,
624 (void) fprintf(stderr
, "\n ");
625 (void) fprintf(stderr
,
627 "Error: Invalid pathname (%s)"),
629 (void) fprintf(stderr
, "\n");
639 * See what kind of device we are talking to.
641 if ((opnerr
= g_get_inquiry(path_phys
, &inq
)) != 0) {
642 if (opnerr
== L_OPEN_PATH_FAIL
) {
644 * We check only for L_OPEN_PATH_FAIL because
645 * that is the only error code returned by
646 * g_get_inquiry() which is not got from the ioctl
647 * call itself. So, we are dependent, in a way, on the
648 * implementation of g_get_inquiry().
651 (void) print_errString(errno
, argv
[path_index
]);
656 } else if (!g_enclDiskChk((char *)inq
.inq_vid
,
657 (char *)inq
.inq_pid
)) {
658 if ((err
= lun_display(path_struct
,
659 inq
, Options
& PVERBOSE
)) != 0) {
660 (void) print_errString(err
, path_phys
);
663 } else if (strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) != NULL
) {
665 * Display SENA enclosure.
667 (void) fprintf(stdout
, "\n\t\t\t\t ");
668 print_chars(inq
.inq_pid
, sizeof (inq
.inq_pid
), 0);
670 (void) fprintf(stdout
, "\n");
671 if (Options
& OPTION_R
) {
672 adm_display_err(path_phys
,
673 (inq
.inq_dtype
& DTYPE_MASK
));
675 pho_display_config(path_phys
);
677 } else if ((((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
)) &&
678 (l_get_enc_type(inq
) == DAK_ENC_TYPE
)) {
680 * Display for the Daktari/DPM
682 (void) fprintf(stdout
, "\n\t\t");
683 for (i
= 0; i
< sizeof (inq
.inq_pid
); i
++) {
684 (void) fprintf(stdout
, "%c", inq
.inq_pid
[i
]);
686 (void) fprintf(stdout
, "\n");
687 if (Options
& OPTION_R
) {
688 adm_display_err(path_phys
,
689 (inq
.inq_dtype
& DTYPE_MASK
));
691 dpm_display_config(path_phys
);
694 * if device is in SENA enclosure
696 * if the slot is valid, then I know this is a SENA enclosure
699 * I first get the ses_path, if this doesn't fail
700 * I retrieve the inquiry data from the ses node
701 * and check teh PID to make sure this is a SENA
703 } else if (((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_DIRECT
) &&
704 ((path_struct
->slot_valid
== 1) ||
705 ((g_get_dev_map(path_phys
, &map
,
706 (Options
& PVERBOSE
)) == 0) &&
707 (l_get_ses_path(path_phys
, ses_path
,
708 &map
, Options
& PVERBOSE
) == 0) &&
709 (g_get_inquiry(ses_path
, &ses_inq
) == 0) &&
710 ((strstr((char *)ses_inq
.inq_pid
, ENCLOSURE_PROD_ID
)
712 if (Options
& OPTION_R
) {
713 adm_display_err(path_phys
,
714 (inq
.inq_dtype
& DTYPE_MASK
));
716 display_fc_disk(path_struct
, ses_path
, &map
, inq
,
720 } else if (strstr((char *)inq
.inq_pid
, "SUN_SEN") != 0) {
721 if (strcmp(argv
[path_index
], path_phys
) != 0) {
722 (void) fprintf(stdout
, " ");
723 (void) fprintf(stdout
,
724 MSGSTR(5, "Physical Path:"));
725 (void) fprintf(stdout
, "\n %s\n", path_phys
);
727 (void) fprintf(stdout
, MSGSTR(2109, "DEVICE is a "));
728 print_chars(inq
.inq_vid
, sizeof (inq
.inq_vid
), 1);
729 (void) fprintf(stdout
, " ");
730 print_chars(inq
.inq_pid
, sizeof (inq
.inq_pid
), 1);
731 (void) fprintf(stdout
, MSGSTR(2110, " card."));
732 if (inq
.inq_len
> 31) {
733 (void) fprintf(stdout
, " ");
734 (void) fprintf(stdout
, MSGSTR(26, "Revision:"));
735 (void) fprintf(stdout
, " ");
736 print_chars(inq
.inq_revision
,
737 sizeof (inq
.inq_revision
), 0);
739 (void) fprintf(stdout
, "\n");
740 /* if device is not in SENA or SSA enclosures. */
741 } else if ((inq
.inq_dtype
& DTYPE_MASK
) < 0x10) {
742 switch ((inq
.inq_dtype
& DTYPE_MASK
)) {
744 case DTYPE_SEQUENTIAL
: /* Tape */
745 if (Options
& OPTION_R
) {
746 adm_display_err(path_phys
,
747 (inq
.inq_dtype
& DTYPE_MASK
));
748 } else if (non_encl_fc_disk_display(path_struct
,
749 inq
, Options
& PVERBOSE
) != 0) {
750 (void) fprintf(stderr
,
752 "Error: getting the device"
757 /* case 0x01: same as default */
759 (void) fprintf(stdout
, " ");
760 (void) fprintf(stdout
, MSGSTR(35,
762 (void) fprintf(stdout
, "%s\n",
763 dtype
[inq
.inq_dtype
& DTYPE_MASK
]);
766 } else if ((inq
.inq_dtype
& DTYPE_MASK
) < 0x1f) {
767 (void) fprintf(stdout
,
768 MSGSTR(2112, " Device type: Reserved"));
769 (void) fprintf(stdout
, "\n");
771 (void) fprintf(stdout
,
772 MSGSTR(2113, " Device type: Unknown device"));
773 (void) fprintf(stdout
, "\n");
776 if (map
.dev_addr
!= NULL
) {
777 free((void *)map
.dev_addr
);
779 (void) free(path_struct
);
786 * Powers off a list of SENA enclosure(s)
787 * and disk(s) which is provided by the user.
793 adm_power_off(char **argv
, int off_flag
)
795 int path_index
= 0, err
= 0, retval
= 0;
797 char *path_phys
= NULL
;
798 Path_struct
*path_struct
;
800 while (argv
[path_index
] != NULL
) {
801 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
802 &path_struct
, Options
& PVERBOSE
)) != 0) {
804 * In case we did not find the device
805 * in the /devices directory.
807 * Only valid for pathnames like box,f1
809 if (path_struct
->ib_path_flag
) {
810 path_phys
= path_struct
->p_physical_path
;
812 (void) fprintf(stderr
,
815 " %s to physical path.\n"
816 " Invalid pathname.\n"),
819 (void) print_errString(err
,
827 if (path_struct
->ib_path_flag
) {
829 * We are addressing a disk using a path
830 * format type box,f1.
832 if (err
= l_dev_pwr_up_down(path_phys
,
833 path_struct
, off_flag
, Options
& PVERBOSE
,
834 Options
& OPTION_CAPF
)) {
836 * Is it Bypassed... try to give more
839 print_devState(argv
[path_index
],
840 path_struct
->p_physical_path
,
841 path_struct
->f_flag
, path_struct
->slot
,
849 if (err
= g_get_inquiry(path_phys
, &inq
)) {
850 (void) print_errString(err
, argv
[path_index
]);
855 if ((strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) != 0) ||
856 (strncmp((char *)inq
.inq_vid
, "SUN ",
857 sizeof (inq
.inq_vid
)) &&
858 ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
))) {
860 if (get_enclStatus(path_phys
, argv
[path_index
],
866 /* power off SENA enclosure. */
867 if (err
= l_pho_pwr_up_down(argv
[path_index
], path_phys
,
868 off_flag
, Options
& PVERBOSE
,
869 Options
& OPTION_CAPF
)) {
870 (void) print_errString(err
, argv
[path_index
]);
873 } else if ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_DIRECT
) {
874 if (err
= l_dev_pwr_up_down(path_phys
,
875 path_struct
, off_flag
, Options
& PVERBOSE
,
876 Options
& OPTION_CAPF
)) {
877 (void) print_errString(err
, argv
[path_index
]);
884 (void) print_errString(L_INVALID_PATH
,
895 adm_bypass_enable(char **argv
, int bypass_flag
)
897 int path_index
= 0, err
= 0;
899 char *path_phys
= NULL
;
900 Path_struct
*path_struct
;
902 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
903 &path_struct
, Options
& PVERBOSE
)) != 0) {
905 * In case we did not find the device
906 * in the /devices directory.
908 * Only valid for pathnames like box,f1
910 if (path_struct
->ib_path_flag
) {
911 path_phys
= path_struct
->p_physical_path
;
913 (void) fprintf(stderr
,
916 " %s to physical path.\n"
917 " Invalid pathname.\n"),
920 (void) print_errString(err
, argv
[path_index
]);
925 if (path_struct
->ib_path_flag
) {
926 if (Options
& OPTION_F
) {
931 * We are addressing a disk using a path
932 * format type box,f1 and no disk
934 * So set the Force flag so no reserved/busy
935 * check is performed.
937 if (err
= l_dev_bypass_enable(path_struct
,
938 bypass_flag
, OPTION_CAPF
,
940 Options
& PVERBOSE
)) {
941 (void) print_errString(err
, argv
[path_index
]);
947 if (err
= g_get_inquiry(path_phys
, &inq
)) {
948 (void) print_errString(err
, argv
[path_index
]);
951 if ((strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) != 0) ||
952 (strncmp((char *)inq
.inq_vid
, "SUN ",
953 sizeof (inq
.inq_vid
)) &&
954 ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
))) {
955 if ((!((Options
& OPTION_F
) ||
956 (Options
& OPTION_R
))) ||
957 ((Options
& OPTION_R
) &&
958 (Options
& OPTION_F
))) {
962 if (err
= l_bp_bypass_enable(path_phys
, bypass_flag
,
965 Options
& OPTION_CAPF
,
966 Options
& PVERBOSE
)) {
967 (void) print_errString(err
, argv
[path_index
]);
970 } else if ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_DIRECT
) {
971 if (Options
& OPTION_F
) {
975 if (err
= l_dev_bypass_enable(path_struct
,
976 bypass_flag
, Options
& OPTION_CAPF
,
978 Options
& PVERBOSE
)) {
979 (void) print_errString(err
, argv
[path_index
]);
986 * adm_download() Download subsystem microcode.
987 * Path must point to a LUX IB.
993 adm_download(char **argv
, char *file_name
)
995 int path_index
= 0, err
= 0;
996 char *path_phys
= NULL
;
998 Path_struct
*path_struct
;
1000 while (argv
[path_index
] != NULL
) {
1002 * See what kind of device we are talking to.
1004 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
1005 &path_struct
, Options
& PVERBOSE
)) != 0) {
1006 (void) fprintf(stderr
,
1008 " Error: converting"
1009 " %s to physical path.\n"
1010 " Invalid pathname.\n"),
1013 (void) print_errString(err
, argv
[path_index
]);
1017 if (err
= g_get_inquiry(path_phys
, &inq
)) {
1018 (void) print_errString(err
, argv
[path_index
]);
1021 if ((strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) != 0) ||
1022 (strncmp((char *)inq
.inq_vid
, "SUN ",
1023 sizeof (inq
.inq_vid
)) &&
1024 ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
))) {
1025 if (err
= l_download(path_phys
,
1026 file_name
, (Options
& SAVE
),
1027 (Options
& PVERBOSE
))) {
1028 (void) print_errString(err
,
1029 (err
== L_OPEN_PATH_FAIL
) ?
1030 argv
[path_index
]: file_name
);
1034 (void) fprintf(stderr
,
1035 MSGSTR(112, "Error: Invalid pathname (%s)"),
1043 * display_link_status() Reads and displays the link status.
1049 display_link_status(char **argv
)
1051 AL_rls
*rls
= NULL
, *n
;
1052 int path_index
= 0, err
= 0;
1053 char *path_phys
= NULL
;
1054 Path_struct
*path_struct
;
1057 while (argv
[path_index
] != NULL
) {
1058 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
1059 &path_struct
, Options
& PVERBOSE
)) != 0) {
1060 (void) fprintf(stderr
,
1062 " Error: converting"
1063 " %s to physical path.\n"
1064 " Invalid pathname.\n"),
1067 (void) print_errString(err
, argv
[path_index
]);
1071 if (err
= g_rdls(path_phys
, &rls
, Options
& PVERBOSE
)) {
1072 (void) print_errString(err
, argv
[path_index
]);
1077 (void) fprintf(stdout
,
1078 MSGSTR(2007, "\nLink Error Status "
1079 "information for loop:%s\n"),
1081 (void) fprintf(stdout
, MSGSTR(2008, "al_pa lnk fail "
1082 " sync loss signal loss sequence err"
1083 " invalid word CRC\n"));
1086 if ((n
->payload
.rls_linkfail
== 0xffffffff) &&
1087 (n
->payload
.rls_syncfail
== 0xffffffff) &&
1088 (n
->payload
.rls_sigfail
== 0xffffffff) &&
1089 (n
->payload
.rls_primitiverr
== 0xffffffff) &&
1090 (n
->payload
.rls_invalidword
== 0xffffffff) &&
1091 (n
->payload
.rls_invalidcrc
== 0xffffffff)) {
1092 (void) fprintf(stdout
,
1093 "%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n",
1095 n
->payload
.rls_linkfail
,
1096 n
->payload
.rls_syncfail
,
1097 n
->payload
.rls_sigfail
,
1098 n
->payload
.rls_primitiverr
,
1099 n
->payload
.rls_invalidword
,
1100 n
->payload
.rls_invalidcrc
);
1102 (void) fprintf(stdout
,
1103 "%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n",
1105 n
->payload
.rls_linkfail
,
1106 n
->payload
.rls_syncfail
,
1107 n
->payload
.rls_sigfail
,
1108 n
->payload
.rls_primitiverr
,
1109 n
->payload
.rls_invalidword
,
1110 n
->payload
.rls_invalidcrc
);
1117 (void) fprintf(stdout
,
1118 MSGSTR(2009, "NOTE: These LESB counts are not"
1119 " cleared by a reset, only power cycles.\n"
1120 "These counts must be compared"
1121 " to previously read counts.\n"));
1126 * ib_present_chk() Check to see if IB 0 or 1 is present in the box.
1133 ib_present_chk(struct l_state_struct
*l_state
, int which_one
)
1140 for (i
= 0; i
< (int)l_state
->ib_tbl
.config
.enc_num_elem
; i
++) {
1141 elem_index
++; /* skip global */
1142 if (l_state
->ib_tbl
.config
.type_hdr
[i
].type
== ELM_TYP_IB
) {
1143 (void) bcopy((const void *)
1144 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ which_one
],
1145 (void *)&ctlr
, sizeof (ctlr
));
1146 if (ctlr
.code
== S_NOT_INSTALLED
) {
1151 elem_index
+= l_state
->ib_tbl
.config
.type_hdr
[i
].num
;
1157 * print_individual_state() Print individual disk status.
1163 print_individual_state(int status
, int port
)
1165 if (status
& L_OPEN_FAIL
) {
1166 (void) fprintf(stdout
, " (");
1167 (void) fprintf(stdout
,
1168 MSGSTR(28, "Open Failed"));
1169 (void) fprintf(stdout
, ") ");
1170 } else if (status
& L_NOT_READY
) {
1171 (void) fprintf(stdout
, " (");
1172 (void) fprintf(stdout
,
1173 MSGSTR(20, "Not Ready"));
1174 (void) fprintf(stdout
, ") ");
1175 } else if (status
& L_NOT_READABLE
) {
1176 (void) fprintf(stdout
, "(");
1177 (void) fprintf(stdout
,
1178 MSGSTR(88, "Not Readable"));
1179 (void) fprintf(stdout
, ") ");
1180 } else if (status
& L_SPUN_DWN_D
) {
1181 (void) fprintf(stdout
, " (");
1182 (void) fprintf(stdout
,
1183 MSGSTR(68, "Spun Down"));
1184 (void) fprintf(stdout
, ") ");
1185 } else if (status
& L_SCSI_ERR
) {
1186 (void) fprintf(stdout
, " (");
1187 (void) fprintf(stdout
,
1188 MSGSTR(70, "SCSI Error"));
1189 (void) fprintf(stdout
, ") ");
1190 } else if (status
& L_RESERVED
) {
1191 if (port
== PORT_A
) {
1192 (void) fprintf(stdout
,
1194 " (Rsrv cnflt:A) "));
1195 } else if (port
== PORT_B
) {
1196 (void) fprintf(stdout
,
1198 " (Rsrv cnflt:B) "));
1200 (void) fprintf(stdout
,
1202 " (Reserve cnflt)"));
1204 } else if (status
& L_NO_LABEL
) {
1205 (void) fprintf(stdout
, "(");
1206 (void) fprintf(stdout
,
1207 MSGSTR(92, "No UNIX Label"));
1208 (void) fprintf(stdout
, ") ");
1214 * display_disk_msg() Displays status for
1215 * an individual SENA device.
1221 display_disk_msg(struct l_disk_state_struct
*dsk_ptr
,
1222 struct l_state_struct
*l_state
, Bp_elem_st
*bp
, int front_flag
)
1226 int state_a
= 0, state_b
= 0;
1228 if (dsk_ptr
->ib_status
.code
== S_NOT_INSTALLED
) {
1229 (void) fprintf(stdout
,
1230 MSGSTR(30, "Not Installed"));
1231 (void) fprintf(stdout
, " ");
1232 if (dsk_ptr
->ib_status
.fault
||
1233 dsk_ptr
->ib_status
.fault_req
) {
1234 (void) fprintf(stdout
, "(");
1235 (void) fprintf(stdout
,
1236 MSGSTR(2013, "Faulted"));
1237 (void) fprintf(stdout
,
1239 } else if (dsk_ptr
->ib_status
.ident
||
1240 dsk_ptr
->ib_status
.rdy_to_ins
||
1241 dsk_ptr
->ib_status
.rmv
) {
1242 (void) fprintf(stdout
,
1244 "(LED Blinking) "));
1246 (void) fprintf(stdout
,
1249 } else if (dsk_ptr
->ib_status
.dev_off
) {
1250 (void) fprintf(stdout
, MSGSTR(2015, "Off"));
1251 if (dsk_ptr
->ib_status
.fault
|| dsk_ptr
->ib_status
.fault_req
) {
1252 (void) fprintf(stdout
, "(");
1253 (void) fprintf(stdout
,
1254 MSGSTR(2016, "Faulted"));
1255 (void) fprintf(stdout
,
1257 } else if (dsk_ptr
->ib_status
.bypass_a_en
&&
1258 dsk_ptr
->ib_status
.bypass_b_en
) {
1259 (void) fprintf(stdout
,
1262 (void) fprintf(stdout
,
1264 } else if (dsk_ptr
->ib_status
.bypass_a_en
) {
1265 (void) fprintf(stdout
,
1268 (void) fprintf(stdout
,
1270 } else if (dsk_ptr
->ib_status
.bypass_b_en
) {
1271 (void) fprintf(stdout
,
1274 (void) fprintf(stdout
,
1277 (void) fprintf(stdout
,
1281 (void) fprintf(stdout
, MSGSTR(2020, "On"));
1283 if (dsk_ptr
->ib_status
.fault
|| dsk_ptr
->ib_status
.fault_req
) {
1284 (void) fprintf(stdout
, " (");
1285 (void) fprintf(stdout
,
1286 MSGSTR(2021, "Faulted"));
1287 (void) fprintf(stdout
, ") ");
1288 } else if (dsk_ptr
->ib_status
.bypass_a_en
&&
1289 dsk_ptr
->ib_status
.bypass_b_en
) {
1290 (void) fprintf(stdout
, " ");
1291 (void) fprintf(stdout
,
1292 MSGSTR(2022, "(Bypassed:AB)"));
1293 (void) fprintf(stdout
, " ");
1294 } else if (ib_present_chk(l_state
, 0) &&
1295 dsk_ptr
->ib_status
.bypass_a_en
) {
1297 * Before printing that the port is bypassed
1298 * verify that there is an IB for this port.
1299 * If not then don't print.
1301 (void) fprintf(stdout
, " ");
1302 (void) fprintf(stdout
,
1303 MSGSTR(2023, "(Bypassed: A)"));
1304 (void) fprintf(stdout
, " ");
1305 } else if (ib_present_chk(l_state
, 1) &&
1306 dsk_ptr
->ib_status
.bypass_b_en
) {
1307 (void) fprintf(stdout
, " ");
1308 (void) fprintf(stdout
,
1309 MSGSTR(2024, "(Bypassed: B)"));
1310 (void) fprintf(stdout
, " ");
1311 } else if ((bp
->code
!= S_NOT_INSTALLED
) &&
1312 ((bp
->byp_a_enabled
|| bp
->en_bypass_a
) &&
1313 !(bp
->byp_b_enabled
|| bp
->en_bypass_b
))) {
1314 (void) fprintf(stdout
,
1316 " (Bypassed BP: A)"));
1317 } else if ((bp
->code
!= S_NOT_INSTALLED
) &&
1318 ((bp
->byp_b_enabled
|| bp
->en_bypass_b
) &&
1319 !(bp
->byp_a_enabled
|| bp
->en_bypass_a
))) {
1320 (void) fprintf(stdout
,
1322 "(Bypassed BP: B)"));
1323 } else if ((bp
->code
!= S_NOT_INSTALLED
) &&
1324 ((bp
->byp_a_enabled
|| bp
->en_bypass_a
) &&
1325 (bp
->byp_b_enabled
|| bp
->en_bypass_b
))) {
1326 (void) fprintf(stdout
,
1328 "(Bypassed BP:AB)"));
1330 state_a
= dsk_ptr
->g_disk_state
.d_state_flags
[PORT_A
];
1331 state_b
= dsk_ptr
->g_disk_state
.d_state_flags
[PORT_B
];
1332 a_and_b
= state_a
& state_b
;
1334 if (dsk_ptr
->l_state_flag
& L_NO_LOOP
) {
1335 (void) fprintf(stdout
,
1337 " (Loop not accessible)"));
1339 } else if (dsk_ptr
->l_state_flag
& L_INVALID_WWN
) {
1340 (void) fprintf(stdout
,
1342 " (Invalid WWN) "));
1343 } else if (dsk_ptr
->l_state_flag
& L_INVALID_MAP
) {
1344 (void) fprintf(stdout
,
1346 " (Login failed) "));
1347 } else if (dsk_ptr
->l_state_flag
& L_NO_PATH_FOUND
) {
1348 (void) fprintf(stdout
,
1350 " (No path found)"));
1351 } else if (a_and_b
) {
1352 print_individual_state(a_and_b
, PORT_A_B
);
1353 } else if (state_a
&& (!state_b
)) {
1354 print_individual_state(state_a
, PORT_A
);
1355 } else if ((!state_a
) && state_b
) {
1356 print_individual_state(state_b
, PORT_B
);
1357 } else if (state_a
|| state_b
) {
1358 /* NOTE: Double state - should do 2 lines. */
1359 print_individual_state(state_a
| state_b
,
1362 (void) fprintf(stdout
, " (");
1363 (void) fprintf(stdout
,
1364 MSGSTR(29, "O.K."));
1365 (void) fprintf(stdout
,
1370 (void) fprintf(stdout
, " ");
1371 } else if (strlen(dsk_ptr
->g_disk_state
.node_wwn_s
)) {
1372 (void) fprintf(stdout
, "%s",
1373 dsk_ptr
->g_disk_state
.node_wwn_s
);
1375 (void) fprintf(stdout
, " ");
1379 (void) fprintf(stdout
, " ");
1386 * pho_display_config() Displays device status
1387 * information for a SENA enclosure.
1393 pho_display_config(char *path_phys
)
1396 Bp_elem_st bpf
, bpr
;
1397 int i
, j
, elem_index
= 0, err
= 0;
1400 /* Get global status */
1401 if (err
= l_get_status(path_phys
, &l_state
,
1402 (Options
& PVERBOSE
))) {
1403 (void) print_errString(err
, path_phys
);
1408 * Look for abnormal status.
1410 if (l_state
.ib_tbl
.p2_s
.ui
.ab_cond
) {
1411 abnormal_condition_display(&l_state
);
1414 (void) fprintf(stdout
,
1415 MSGSTR(2032, " DISK STATUS \n"
1416 "SLOT FRONT DISKS (Node WWN) "
1417 " REAR DISKS (Node WWN)\n"));
1419 * Print the status for each disk
1421 for (j
= 0; j
< (int)l_state
.ib_tbl
.config
.enc_num_elem
; j
++) {
1423 if (l_state
.ib_tbl
.config
.type_hdr
[j
].type
== ELM_TYP_BP
)
1425 elem_index
+= l_state
.ib_tbl
.config
.type_hdr
[j
].num
;
1427 (void) bcopy((const void *)
1428 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
]),
1429 (void *)&bpf
, sizeof (bpf
));
1430 (void) bcopy((const void *)
1431 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
+ 1]),
1432 (void *)&bpr
, sizeof (bpr
));
1434 for (i
= 0; i
< (int)l_state
.total_num_drv
/2; i
++) {
1435 (void) fprintf(stdout
, "%-2d ", i
);
1436 display_disk_msg(&l_state
.drv_front
[i
], &l_state
, &bpf
, 1);
1437 display_disk_msg(&l_state
.drv_rear
[i
], &l_state
, &bpr
, 0);
1438 (void) fprintf(stdout
, "\n");
1444 * Display the subsystem status.
1446 (void) fprintf(stdout
,
1448 " SUBSYSTEM STATUS\nFW Revision:"));
1449 print_chars(l_state
.ib_tbl
.config
.prod_revision
,
1450 sizeof (l_state
.ib_tbl
.config
.prod_revision
), 1);
1451 (void) fprintf(stdout
, MSGSTR(2034, " Box ID:%d"),
1452 l_state
.ib_tbl
.box_id
);
1453 (void) fprintf(stdout
, " ");
1454 (void) fprintf(stdout
, MSGSTR(90, "Node WWN:"));
1455 for (i
= 0; i
< 8; i
++) {
1456 (void) fprintf(stdout
, "%1.2x",
1457 l_state
.ib_tbl
.config
.enc_node_wwn
[i
]);
1459 /* Make sure NULL terminated although it is supposed to be */
1460 if (strlen((const char *)l_state
.ib_tbl
.enclosure_name
) <=
1461 sizeof (l_state
.ib_tbl
.enclosure_name
)) {
1462 (void) fprintf(stdout
, MSGSTR(2035, " Enclosure Name:%s\n"),
1463 l_state
.ib_tbl
.enclosure_name
);
1470 /* Get and print CONTROLLER messages */
1471 for (i
= 0; i
< (int)l_state
.ib_tbl
.config
.enc_num_elem
; i
++) {
1472 elem_index
++; /* skip global */
1473 switch (l_state
.ib_tbl
.config
.type_hdr
[i
].type
) {
1475 ps_messages(&l_state
, i
, elem_index
);
1478 fan_messages(&l_state
, i
, elem_index
);
1481 back_plane_messages(&l_state
, i
, elem_index
);
1484 ctlr_messages(&l_state
, i
, elem_index
);
1488 * NOTE: I just use the Photon's message
1489 * string here and don't look at the
1490 * language code. The string includes
1491 * the language name.
1493 if (l_state
.ib_tbl
.config
.type_hdr
[i
].text_len
!= 0) {
1494 (void) fprintf(stdout
, "%s\t",
1495 l_state
.ib_tbl
.config
.text
[i
]);
1498 case ELM_TYP_LO
: /* Loop configuration */
1499 loop_messages(&l_state
, i
, elem_index
);
1501 case ELM_TYP_MB
: /* Loop configuration */
1502 mb_messages(&l_state
, i
, elem_index
);
1507 * Calculate the index to each element.
1509 elem_index
+= l_state
.ib_tbl
.config
.type_hdr
[i
].num
;
1511 (void) fprintf(stdout
, "\n");
1518 * dpm_display_config() Displays device status
1519 * information for a DAKTARI enclosure.
1525 dpm_display_config(char *path_phys
)
1528 Bp_elem_st bpf
, bpr
;
1529 int i
, j
, elem_index
= 0, err
= 0, count
;
1532 /* Get global status */
1533 if (err
= l_get_status(path_phys
, &l_state
,
1534 (Options
& PVERBOSE
))) {
1535 (void) print_errString(err
, path_phys
);
1540 * Look for abnormal status.
1542 if (l_state
.ib_tbl
.p2_s
.ui
.ab_cond
) {
1543 abnormal_condition_display(&l_state
);
1546 (void) fprintf(stdout
,
1547 MSGSTR(2247, " DISK STATUS \n"
1548 "SLOT DISKS (Node WWN) \n"));
1550 * Print the status for each disk
1552 for (j
= 0; j
< (int)l_state
.ib_tbl
.config
.enc_num_elem
; j
++) {
1554 if (l_state
.ib_tbl
.config
.type_hdr
[j
].type
== ELM_TYP_BP
)
1556 elem_index
+= l_state
.ib_tbl
.config
.type_hdr
[j
].num
;
1558 (void) bcopy((const void *)
1559 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
]),
1560 (void *)&bpf
, sizeof (bpf
));
1561 (void) bcopy((const void *)
1562 &(l_state
.ib_tbl
.p2_s
.element
[elem_index
+ 1]),
1563 (void *)&bpr
, sizeof (bpr
));
1565 for (i
= 0, count
= 0;
1566 i
< (int)l_state
.total_num_drv
/2;
1568 (void) fprintf(stdout
, "%-2d ", count
);
1569 display_disk_msg(&l_state
.drv_front
[i
], &l_state
, &bpf
, 1);
1570 (void) fprintf(stdout
, "\n");
1572 for (i
= 0; i
< (int)l_state
.total_num_drv
/2; i
++, count
++) {
1573 (void) fprintf(stdout
, "%-2d ", count
);
1574 display_disk_msg(&l_state
.drv_rear
[i
], &l_state
, &bpf
, 1);
1575 (void) fprintf(stdout
, "\n");
1580 * Display the subsystem status.
1582 (void) fprintf(stdout
,
1584 "\t\tSUBSYSTEM STATUS\nFW Revision:"));
1585 for (i
= 0; i
< sizeof (l_state
.ib_tbl
.config
.prod_revision
); i
++) {
1586 (void) fprintf(stdout
, "%c",
1587 l_state
.ib_tbl
.config
.prod_revision
[i
]);
1589 (void) fprintf(stdout
, MSGSTR(2034, " Box ID:%d"),
1590 l_state
.ib_tbl
.box_id
);
1591 (void) fprintf(stdout
, "\n ");
1593 (void) fprintf(stdout
, MSGSTR(90, "Node WWN:"));
1595 for (i
= 0; i
< 8; i
++) {
1596 (void) fprintf(stdout
, "%1.2x",
1597 l_state
.ib_tbl
.config
.enc_node_wwn
[i
]);
1599 /* Make sure NULL terminated although it is supposed to be */
1600 if (strlen((const char *)l_state
.ib_tbl
.enclosure_name
) <=
1601 sizeof (l_state
.ib_tbl
.enclosure_name
)) {
1602 (void) fprintf(stdout
, MSGSTR(2035, " Enclosure Name:%s\n"),
1603 l_state
.ib_tbl
.enclosure_name
);
1610 /* Get and print CONTROLLER messages */
1611 for (i
= 0; i
< (int)l_state
.ib_tbl
.config
.enc_num_elem
; i
++) {
1612 elem_index
++; /* skip global */
1613 switch (l_state
.ib_tbl
.config
.type_hdr
[i
].type
) {
1615 ps_messages(&l_state
, i
, elem_index
);
1618 fan_messages(&l_state
, i
, elem_index
);
1621 dpm_SSC100_messages(&l_state
, i
, elem_index
);
1624 ctlr_messages(&l_state
, i
, elem_index
);
1628 * NOTE: I just use the Photon's message
1629 * string here and don't look at the
1630 * language code. The string includes
1631 * the language name.
1633 if (l_state
.ib_tbl
.config
.type_hdr
[i
].text_len
!= 0) {
1634 (void) fprintf(stdout
, "%s\t",
1635 l_state
.ib_tbl
.config
.text
[i
]);
1638 case ELM_TYP_LO
: /* Loop configuration */
1639 loop_messages(&l_state
, i
, elem_index
);
1641 case ELM_TYP_MB
: /* Loop configuration */
1642 mb_messages(&l_state
, i
, elem_index
);
1645 trans_messages(&l_state
, 1);
1650 * Calculate the index to each element.
1652 elem_index
+= l_state
.ib_tbl
.config
.type_hdr
[i
].num
;
1654 (void) fprintf(stdout
, "\n");
1663 * Change the FPM (Front Panel Module) password of the
1664 * subsystem associated with the IB addressed by the
1665 * enclosure or pathname to name.
1672 termios
.c_lflag
|= ECHO
;
1673 ioctl(termio_fd
, TCSETS
, &termios
);
1680 * up_password() Changes the password for SENA enclosure.
1686 up_password(char **argv
)
1688 int path_index
= 0, err
= 0;
1689 char password
[1024];
1691 int i
, j
, matched
, equal
;
1694 char *path_phys
= NULL
;
1695 Path_struct
*path_struct
;
1698 if ((termio_fd
= open("/dev/tty", O_RDONLY
)) == -1) {
1699 (void) fprintf(stderr
,
1700 MSGSTR(2036, "Error: tty open failed.\n"));
1703 ioctl(termio_fd
, TCGETS
, &termios
);
1704 sig
= sigset(SIGINT
, (void (*)())intfix
);
1706 * Make sure path valid and is to a PHO
1707 * before bothering operator.
1709 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
1710 &path_struct
, Options
& PVERBOSE
)) != 0) {
1711 (void) fprintf(stderr
,
1713 " Error: converting"
1714 " %s to physical path.\n"
1715 " Invalid pathname.\n"),
1718 (void) print_errString(err
, argv
[path_index
]);
1722 if (err
= g_get_inquiry(path_phys
, &inq
)) {
1723 (void) print_errString(err
, argv
[path_index
]);
1726 if ((strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) == 0) &&
1727 (!(strncmp((char *)inq
.inq_vid
, "SUN ",
1728 sizeof (inq
.inq_vid
)) &&
1729 ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
)))) {
1731 * Again this is like the ssaadm code in that the name
1732 * is still not defined before this code must be released.
1734 (void) fprintf(stderr
,
1735 MSGSTR(2037, "Error: Enclosure is not a %s\n"),
1739 (void) fprintf(stdout
,
1741 "Changing FPM password for subsystem %s\n"),
1746 memset(input
, 0, sizeof (input
));
1747 memset(password
, 0, sizeof (password
));
1748 (void) fprintf(stdout
,
1749 MSGSTR(2039, "New password: "));
1751 termios
.c_lflag
&= ~ECHO
;
1752 ioctl(termio_fd
, TCSETS
, &termios
);
1755 (void) fprintf(stdout
,
1756 MSGSTR(2040, "\nRe-enter new password: "));
1757 (void) gets(password
);
1758 termios
.c_lflag
|= ECHO
;
1759 ioctl(termio_fd
, TCSETS
, &termios
);
1760 for (i
= 0; input
[i
]; i
++) {
1761 if (!isdigit(input
[i
])) {
1762 (void) fprintf(stderr
,
1763 MSGSTR(2041, "\nError: Invalid password."
1765 " must be 4 decimal-digit characters.\n"));
1769 if (i
&& (i
!= 4)) {
1770 (void) fprintf(stderr
,
1771 MSGSTR(2042, "\nError: Invalid password."
1773 " must be 4 decimal-digit characters.\n"));
1776 for (j
= 0; password
[j
]; j
++) {
1777 if (!isdigit(password
[j
])) {
1778 (void) fprintf(stderr
,
1779 MSGSTR(2043, "\nError: Invalid password."
1781 " must be 4 decimal-digit characters.\n"));
1787 } else for (i
= matched
= 0; password
[i
]; i
++) {
1788 if (password
[i
] == input
[i
]) {
1792 if ((matched
!= -1) && (matched
== i
)) {
1795 (void) fprintf(stdout
,
1796 MSGSTR(2044, "\npassword: They don't match;"
1800 (void) fprintf(stdout
, "\n");
1801 sscanf(input
, "%s", password
);
1802 (void) signal(SIGINT
, sig
); /* restore signal handler */
1804 /* Send new password to IB */
1805 if (l_new_password(path_phys
, input
)) {
1806 (void) print_errString(err
, path_phys
);
1812 * Call g_failover to process failover command
1815 adm_failover(char **argv
)
1817 int path_index
= 0, err
= 0;
1819 char *path_phys
= NULL
;
1821 (void) memset(pathclass
, 0, sizeof (pathclass
));
1822 (void) strcpy(pathclass
, argv
[path_index
++]);
1823 if ((strcmp(pathclass
, "primary") != 0) &&
1824 (strcmp(pathclass
, "secondary") != 0)) {
1825 (void) fprintf(stderr
,
1826 MSGSTR(2300, "Incorrect pathclass\n"));
1830 while (argv
[path_index
] != NULL
) {
1831 path_phys
= g_get_physical_name(argv
[path_index
++]);
1832 if ((path_phys
== NULL
) ||
1833 (strstr(path_phys
, SCSI_VHCI
) == NULL
)) {
1834 (void) fprintf(stderr
,
1835 MSGSTR(2301, "Incorrect pathname\n"));
1839 if (err
= g_failover(path_phys
, pathclass
)) {
1840 (void) print_errString(err
, NULL
);
1849 * up_encl_name() Update the enclosures logical name.
1855 up_encl_name(char **argv
, int argc
)
1857 int i
, rval
, al_pa
, path_index
= 0, err
= 0;
1859 Box_list
*b_list
= NULL
;
1860 uchar_t node_wwn
[WWN_SIZE
], port_wwn
[WWN_SIZE
];
1861 char wwn1
[(WWN_SIZE
*2)+1], name
[1024], *path_phys
= NULL
;
1862 Path_struct
*path_struct
;
1864 (void) memset(name
, 0, sizeof (name
));
1865 (void) memset(&inq
, 0, sizeof (inq
));
1866 (void) sscanf(argv
[path_index
++], "%s", name
);
1867 for (i
= 0; name
[i
]; i
++) {
1868 if ((!isalnum(name
[i
]) &&
1869 ((name
[i
] != '#') &&
1872 (name
[i
] != '.'))) || i
>= 16) {
1873 (void) fprintf(stderr
,
1874 MSGSTR(2045, "Error: Invalid enclosure name.\n"));
1875 (void) fprintf(stderr
, MSGSTR(2046,
1876 "Usage: %s [-v] subcommand {a name consisting of"
1877 " 1-16 alphanumeric characters}"
1878 " {enclosure... | pathname...}\n"), whoami
);
1883 if (((Options
& PVERBOSE
) && (argc
!= 5)) ||
1884 (!(Options
& PVERBOSE
) && (argc
!= 4))) {
1885 (void) fprintf(stderr
,
1886 MSGSTR(114, "Error: Incorrect number of arguments.\n"));
1887 (void) fprintf(stderr
, MSGSTR(2047,
1888 "Usage: %s [-v] subcommand {a name consisting of"
1889 " 1-16 alphanumeric characters}"
1890 " {enclosure... | pathname...}\n"), whoami
);
1894 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
1895 &path_struct
, Options
& PVERBOSE
)) != 0) {
1896 (void) fprintf(stderr
,
1898 " Error: converting"
1899 " %s to physical path.\n"
1900 " Invalid pathname.\n"),
1903 (void) print_errString(err
, argv
[path_index
]);
1908 * Make sure we are talking to an IB.
1910 if (err
= g_get_inquiry(path_phys
, &inq
)) {
1911 (void) print_errString(err
, argv
[path_index
]);
1914 if ((strstr((char *)inq
.inq_pid
, ENCLOSURE_PROD_ID
) == 0) &&
1915 (!(strncmp((char *)inq
.inq_vid
, "SUN ",
1916 sizeof (inq
.inq_vid
)) &&
1917 ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_ESI
)))) {
1919 * Again this is like the ssaadm code in that the name
1920 * is still not defined before this code must be released.
1922 (void) fprintf(stderr
,
1923 MSGSTR(2048, "Error: Pathname does not point to a %s"
1924 " enclosure\n"), ENCLOSURE_PROD_NAME
);
1928 if (err
= g_get_wwn(path_phys
, port_wwn
, node_wwn
, &al_pa
,
1929 Options
& PVERBOSE
)) {
1930 (void) print_errString(err
, argv
[path_index
]);
1934 for (i
= 0; i
< WWN_SIZE
; i
++) {
1935 (void) sprintf(&wwn1
[i
<< 1], "%02x", node_wwn
[i
]);
1937 if ((err
= l_get_box_list(&b_list
, Options
& PVERBOSE
)) != 0) {
1938 (void) print_errString(err
, argv
[path_index
]);
1941 if (b_list
== NULL
) {
1942 (void) fprintf(stdout
,
1943 MSGSTR(93, "No %s enclosures found "
1944 "in /dev/es\n"), ENCLOSURE_PROD_NAME
);
1946 } else if (l_duplicate_names(b_list
, wwn1
, name
,
1947 Options
& PVERBOSE
)) {
1948 (void) fprintf(stderr
,
1949 MSGSTR(2049, "Warning: The name you selected, %s,"
1950 " is already being used.\n"
1951 "Please choose a unique name.\n"
1952 "You can use the \"probe\" subcommand to"
1953 " see all of the enclosure names.\n"),
1955 (void) l_free_box_list(&b_list
);
1958 (void) l_free_box_list(&b_list
);
1960 /* Send new name to IB */
1961 if (rval
= l_new_name(path_phys
, name
)) {
1962 (void) print_errString(rval
, path_phys
);
1965 if (Options
& PVERBOSE
) {
1966 (void) fprintf(stdout
,
1967 MSGSTR(2050, "The enclosure has been renamed to %s\n"),
1974 get_enclStatus(char *phys_path
, char *encl_name
, int off_flag
)
1976 int found_pwrOnDrv
= 0, slot
;
1977 int found_pwrOffDrv
= 0, err
= 0;
1980 if ((err
= l_get_status(phys_path
,
1981 &l_state
, Options
& PVERBOSE
)) != 0) {
1982 (void) print_errString(err
, encl_name
);
1987 for (slot
= 0; slot
< l_state
.total_num_drv
/2;
1989 if (((l_state
.drv_front
[slot
].ib_status
.code
!=
1991 (!l_state
.drv_front
[slot
].ib_status
.dev_off
)) ||
1992 ((l_state
.drv_rear
[slot
].ib_status
.code
!=
1994 (!l_state
.drv_rear
[slot
].ib_status
.dev_off
))) {
1999 if (!found_pwrOnDrv
) {
2000 (void) fprintf(stdout
,
2002 "Notice: Drives in enclosure"
2003 " \"%s\" have already been"
2004 " powered off.\n\n"),
2009 for (slot
= 0; slot
< l_state
.total_num_drv
/2;
2011 if (((l_state
.drv_front
[slot
].ib_status
.code
!=
2013 (l_state
.drv_front
[slot
].ib_status
.dev_off
)) ||
2014 ((l_state
.drv_rear
[slot
].ib_status
.code
!=
2016 (l_state
.drv_rear
[slot
].ib_status
.dev_off
))) {
2021 if (!found_pwrOffDrv
) {
2022 (void) fprintf(stdout
,
2024 "Notice: Drives in enclosure"
2025 " \"%s\" have already been"
2026 " powered on.\n\n"),
2039 * adm_led() The led_request subcommand requests the subsystem
2040 * to display the current state or turn off, on, or blink
2041 * the yellow LED associated with the disk specified by the
2042 * enclosure or pathname.
2048 adm_led(char **argv
, int led_action
)
2050 int path_index
= 0, err
= 0;
2054 char *path_phys
= NULL
;
2055 Path_struct
*path_struct
;
2056 int enc_t
= 0; /* enclosure type */
2057 char ses_path
[MAXPATHLEN
];
2060 while (argv
[path_index
] != NULL
) {
2061 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
2062 &path_struct
, Options
& PVERBOSE
)) != 0) {
2063 /* Make sure we have a device path. */
2064 if (path_struct
->ib_path_flag
) {
2065 path_phys
= path_struct
->p_physical_path
;
2067 (void) fprintf(stderr
,
2069 " Error: converting"
2070 " %s to physical path.\n"
2071 " Invalid pathname.\n"),
2074 (void) print_errString(err
,
2080 if (!path_struct
->ib_path_flag
) {
2081 if (err
= g_get_inquiry(path_phys
, &inq
)) {
2082 (void) print_errString(err
, argv
[path_index
]);
2085 if ((inq
.inq_dtype
& DTYPE_MASK
) != DTYPE_DIRECT
) {
2086 (void) fprintf(stderr
,
2088 "Error: pathname must be to a disk device.\n"
2089 " %s\n"), argv
[path_index
]);
2094 * See if we are in fact talking to a loop or not.
2096 if (err
= g_get_dev_map(path_phys
, &map
,
2097 (Options
& PVERBOSE
))) {
2098 (void) print_errString(err
, argv
[path_index
]);
2101 if (led_action
== L_LED_ON
) {
2102 (void) fprintf(stderr
, MSGSTR(2054,
2103 "The led_on functionality is not applicable "
2104 "to this subsystem.\n"));
2107 if (err
= l_led(path_struct
, led_action
, &status
,
2108 (Options
& PVERBOSE
))) {
2109 (void) print_errString(err
, argv
[path_index
]);
2113 /* Check to see if we have a daktari */
2114 if (l_get_ses_path(path_phys
, ses_path
, &map
,
2115 (Options
& PVERBOSE
)) == 0) {
2116 if (g_get_inquiry(ses_path
, &ses_inq
) == 0) {
2117 enc_t
= l_get_enc_type(ses_inq
);
2120 switch (led_action
) {
2122 if (status
.fault
|| status
.fault_req
) {
2123 if (!path_struct
->slot_valid
) {
2124 (void) fprintf(stdout
,
2125 MSGSTR(2055, "LED state is ON for "
2126 "device:\n %s\n"), path_phys
);
2128 if (enc_t
== DAK_ENC_TYPE
) {
2129 if (path_struct
->f_flag
) {
2130 (void) fprintf(stdout
,
2131 MSGSTR(2236, "LED state is ON for "
2132 "device in location: slot %d\n"),
2135 (void) fprintf(stdout
,
2136 MSGSTR(2236, "LED state is ON for "
2137 "device in location: slot %d\n"),
2139 (MAX_DRIVES_DAK
/2));
2142 (void) fprintf(stdout
,
2143 (path_struct
->f_flag
) ?
2144 MSGSTR(2056, "LED state is ON for "
2145 "device in location: front,slot %d\n")
2146 : MSGSTR(2057, "LED state is ON for "
2147 "device in location: rear,slot %d\n"),
2151 } else if (status
.ident
|| status
.rdy_to_ins
||
2153 if (!path_struct
->slot_valid
) {
2154 (void) fprintf(stdout
, MSGSTR(2058,
2155 "LED state is BLINKING for "
2156 "device:\n %s\n"), path_phys
);
2158 if (enc_t
== DAK_ENC_TYPE
) {
2159 if (path_struct
->f_flag
) {
2160 (void) fprintf(stdout
, MSGSTR(2237,
2161 "LED state is BLINKING for "
2162 "device in location: slot %d\n"),
2165 (void) fprintf(stdout
, MSGSTR(2237,
2166 "LED state is BLINKING for "
2167 "device in location: slot %d\n"),
2168 path_struct
->slot
+ (MAX_DRIVES_DAK
/2));
2171 (void) fprintf(stdout
,
2172 (path_struct
->f_flag
) ?
2173 MSGSTR(2059, "LED state is BLINKING for "
2174 "device in location: front,slot %d\n")
2175 : MSGSTR(2060, "LED state is BLINKING for "
2176 "device in location: rear,slot %d\n"),
2181 if (!path_struct
->slot_valid
) {
2182 (void) fprintf(stdout
,
2183 MSGSTR(2061, "LED state is OFF for "
2184 "device:\n %s\n"), path_phys
);
2186 if (enc_t
== DAK_ENC_TYPE
) {
2187 if (path_struct
->f_flag
) {
2188 (void) fprintf(stdout
, MSGSTR(2238,
2189 "LED state is OFF for "
2190 "device in location: slot %d\n"),
2193 (void) fprintf(stdout
, MSGSTR(2238,
2194 "LED state is OFF for "
2195 "device in location: slot %d\n"),
2196 path_struct
->slot
+ MAX_DRIVES_DAK
/2);
2199 (void) fprintf(stdout
,
2200 (path_struct
->f_flag
) ?
2201 MSGSTR(2062, "LED state is OFF for "
2202 "device in location: front,slot %d\n")
2203 : MSGSTR(2063, "LED state is OFF for "
2204 "device in location: rear,slot %d\n"),
2211 free((void *)map
.dev_addr
);
2221 * dump() Dump information
2230 int path_index
= 0, err
= 0;
2232 char hdr_buf
[MAXNAMELEN
];
2233 Rec_diag_hdr
*hdr
, *hdr_ptr
;
2234 char *path_phys
= NULL
;
2235 Path_struct
*path_struct
;
2240 if ((hdr
= (struct rec_diag_hdr
*)calloc(1, MAX_REC_DIAG_LENGTH
)) ==
2242 (void) print_errString(L_MALLOC_FAILED
, NULL
);
2245 buf
= (uchar_t
*)hdr
;
2247 while (argv
[path_index
] != NULL
) {
2248 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
2249 &path_struct
, Options
& PVERBOSE
)) != 0) {
2250 (void) fprintf(stderr
,
2252 " Error: converting"
2253 " %s to physical path.\n"
2254 " Invalid pathname.\n"),
2257 (void) print_errString(err
, argv
[path_index
]);
2261 if (err
= g_get_inquiry(path_phys
, &inq
)) {
2262 (void) print_errString(err
, argv
[path_index
]);
2264 (void) g_dump(MSGSTR(2065, "INQUIRY data: "),
2265 (uchar_t
*)&inq
, 5 + inq
.inq_len
, HEX_ASCII
);
2268 (void) memset(buf
, 0, MAX_REC_DIAG_LENGTH
);
2269 if (err
= l_get_envsen(path_phys
, buf
, MAX_REC_DIAG_LENGTH
,
2270 (Options
& PVERBOSE
))) {
2271 (void) print_errString(err
, argv
[path_index
]);
2274 (void) fprintf(stdout
,
2275 MSGSTR(2066, "\t\tEnvironmental Sense Information\n"));
2282 while (hdr_ptr
->page_len
!= 0) {
2283 (void) sprintf(hdr_buf
, MSGSTR(2067, "Page %d: "),
2284 hdr_ptr
->page_code
);
2285 (void) g_dump(hdr_buf
, (uchar_t
*)hdr_ptr
,
2286 HEADER_LEN
+ hdr_ptr
->page_len
, HEX_ASCII
);
2287 hdr_ptr
+= ((HEADER_LEN
+ hdr_ptr
->page_len
) /
2288 sizeof (struct rec_diag_hdr
));
2298 * display_socal_stats() Display socal driver kstat information.
2304 display_socal_stats(int port
, char *socal_path
, struct socal_stats
*fc_stats
)
2307 int header_flag
= 0;
2308 char status_msg_buf
[MAXNAMELEN
];
2309 int num_status_entries
;
2311 (void) fprintf(stdout
, MSGSTR(2068,
2312 "\tInformation for FC Loop on port %d of"
2313 " FC100/S Host Adapter\n\tat path: %s\n"),
2315 if (fc_stats
->version
> 1) {
2316 (void) fprintf(stdout
, "\t");
2317 (void) fprintf(stdout
, MSGSTR(32,
2318 "Information from %s"), fc_stats
->drvr_name
);
2319 (void) fprintf(stdout
, "\n");
2320 if ((*fc_stats
->node_wwn
!= NULL
) &&
2321 (*fc_stats
->port_wwn
[port
] != NULL
)) {
2322 (void) fprintf(stdout
, MSGSTR(104,
2323 " Host Adapter WWN's: Node:%s"
2326 fc_stats
->port_wwn
[port
]);
2328 if (*fc_stats
->fw_revision
!= NULL
) {
2329 (void) fprintf(stdout
, MSGSTR(105,
2330 " Host Adapter Firmware Revision: %s\n"),
2331 fc_stats
->fw_revision
);
2333 if (fc_stats
->parity_chk_enabled
!= 0) {
2334 (void) fprintf(stdout
, MSGSTR(2069,
2335 " This Host Adapter checks S-Bus parity.\n"));
2339 (void) fprintf(stdout
, MSGSTR(2070,
2340 " Version Resets Req_Q_Intrpts Qfulls"
2341 " Unsol_Resps Lips\n"));
2343 (void) fprintf(stdout
, " %4d%8d%11d%13d%10d%7d\n",
2346 fc_stats
->reqq_intrs
,
2348 fc_stats
->pstats
[port
].unsol_resps
,
2349 fc_stats
->pstats
[port
].lips
);
2351 (void) fprintf(stdout
, MSGSTR(2071,
2353 " Abts_ok Offlines Loop_onlines Onlines\n"));
2355 (void) fprintf(stdout
, " %4d%9d%10d%9d%13d%10d\n",
2356 fc_stats
->pstats
[port
].els_rcvd
,
2357 fc_stats
->pstats
[port
].abts
,
2358 fc_stats
->pstats
[port
].abts_ok
,
2359 fc_stats
->pstats
[port
].offlines
,
2360 fc_stats
->pstats
[port
].online_loops
,
2361 fc_stats
->pstats
[port
].onlines
);
2363 /* If any status conditions exist then display */
2364 if (fc_stats
->version
> 1) {
2365 num_status_entries
= FC_STATUS_ENTRIES
;
2367 num_status_entries
= 64;
2370 for (i
= 0; i
< num_status_entries
; i
++) {
2371 if (fc_stats
->pstats
[port
].resp_status
[i
] != 0) {
2372 if (header_flag
++ == 0) {
2373 (void) fprintf(stdout
, MSGSTR(2072,
2374 " Fibre Channel Transport status:\n "
2378 (void) l_format_fc_status_msg(status_msg_buf
,
2379 fc_stats
->pstats
[port
].resp_status
[i
], i
);
2380 (void) fprintf(stdout
, " %s\n",
2389 * display_sf_stats() Display sf driver kstat information.
2391 * This routine is called by private loop device only
2397 display_sf_stats(char *path_phys
, int dtype
, struct sf_stats
*sf_stats
)
2399 int i
, al_pa
, err
= 0;
2401 uchar_t node_wwn
[WWN_SIZE
];
2402 uchar_t port_wwn
[WWN_SIZE
];
2403 gfc_port_dev_info_t
*dev_addr_list
;
2405 if (sf_stats
->version
> 1) {
2406 (void) fprintf(stdout
, "\n\t");
2407 (void) fprintf(stdout
, MSGSTR(32,
2408 "Information from %s"),
2409 sf_stats
->drvr_name
);
2410 (void) fprintf(stdout
, "\n");
2412 (void) fprintf(stdout
,
2413 MSGSTR(2073, "\n\t\tInformation from sf driver:\n"));
2416 (void) fprintf(stdout
, MSGSTR(2074,
2417 " Version Lip_count Lip_fail"
2418 " Alloc_fail #_cmds "
2419 "Throttle_limit Pool_size\n"));
2421 (void) fprintf(stdout
, " %4d%9d%12d%11d%10d%11d%12d\n",
2423 sf_stats
->lip_count
,
2424 sf_stats
->lip_failures
,
2425 sf_stats
->cralloc_failures
,
2427 sf_stats
->throttle_limit
,
2428 sf_stats
->cr_pool_size
);
2430 (void) fprintf(stdout
, MSGSTR(2075,
2431 "\n\t\tTARGET ERROR INFORMATION:\n"));
2432 (void) fprintf(stdout
, MSGSTR(2076,
2433 "AL_PA Els_fail Timouts Abts_fail"
2435 " Data_ro_mis Dl_len_mis Logouts\n"));
2437 if (err
= g_get_dev_map(path_phys
, &map
, (Options
& PVERBOSE
))) {
2438 (void) print_errString(err
, path_phys
);
2442 if (dtype
== DTYPE_DIRECT
) {
2443 if (err
= g_get_wwn(path_phys
, port_wwn
, node_wwn
, &al_pa
,
2444 Options
& PVERBOSE
)) {
2445 (void) print_errString(err
, path_phys
);
2448 /* for san toleration, only need to modify the code */
2449 /* such that the current sf_al_map structure replaced */
2450 /* by the new gfc_map structure for private loop device */
2451 for (i
= 0, dev_addr_list
= map
.dev_addr
; i
< map
.count
;
2452 i
++, dev_addr_list
++) {
2453 if (dev_addr_list
->gfc_port_dev
.priv_port
.sf_al_pa
2455 (void) fprintf(stdout
,
2456 "%3x%10d%8d%10d%11d%13d%11d%9d\n",
2458 sf_stats
->tstats
[i
].els_failures
,
2459 sf_stats
->tstats
[i
].timeouts
,
2460 sf_stats
->tstats
[i
].abts_failures
,
2461 sf_stats
->tstats
[i
].task_mgmt_failures
,
2462 sf_stats
->tstats
[i
].data_ro_mismatches
,
2463 sf_stats
->tstats
[i
].dl_len_mismatches
,
2464 sf_stats
->tstats
[i
].logouts_recvd
);
2468 if (i
>= map
.count
) {
2469 (void) print_errString(L_INVALID_LOOP_MAP
, path_phys
);
2473 for (i
= 0, dev_addr_list
= map
.dev_addr
; i
< map
.count
;
2474 i
++, dev_addr_list
++) {
2475 (void) fprintf(stdout
,
2476 "%3x%10d%8d%10d%11d%13d%11d%9d\n",
2477 dev_addr_list
->gfc_port_dev
.priv_port
.sf_al_pa
,
2478 sf_stats
->tstats
[i
].els_failures
,
2479 sf_stats
->tstats
[i
].timeouts
,
2480 sf_stats
->tstats
[i
].abts_failures
,
2481 sf_stats
->tstats
[i
].task_mgmt_failures
,
2482 sf_stats
->tstats
[i
].data_ro_mismatches
,
2483 sf_stats
->tstats
[i
].dl_len_mismatches
,
2484 sf_stats
->tstats
[i
].logouts_recvd
);
2487 free((void *)map
.dev_addr
);
2493 * adm_display_err() Displays enclosure specific
2494 * error information.
2500 adm_display_err(char *path_phys
, int dtype
)
2502 int i
, drvr_inst
, sf_inst
, socal_inst
, port
, al_pa
, err
= 0;
2503 char *char_ptr
, socal_path
[MAXPATHLEN
], drvr_path
[MAXPATHLEN
];
2506 kstat_t
*ifp_ks
, *sf_ks
, *fc_ks
;
2507 sf_stats_t sf_stats
;
2508 socal_stats_t fc_stats
;
2509 ifp_stats_t ifp_stats
;
2510 int header_flag
= 0, pathcnt
= 1;
2511 char status_msg_buf
[MAXNAMELEN
];
2513 uchar_t node_wwn
[WWN_SIZE
], port_wwn
[WWN_SIZE
];
2515 gfc_port_dev_info_t
*dev_addr_list
;
2516 mp_pathlist_t pathlist
;
2517 int p_on
= 0, p_st
= 0;
2519 if ((kc
= kstat_open()) == (kstat_ctl_t
*)NULL
) {
2520 (void) fprintf(stderr
,
2521 MSGSTR(2077, " Error: can't open kstat\n"));
2525 if (strstr(path_phys
, SCSI_VHCI
)) {
2526 (void) strcpy(drvr_path
, path_phys
);
2527 if (err
= g_get_pathlist(drvr_path
, &pathlist
)) {
2528 (void) print_errString(err
, NULL
);
2531 pathcnt
= pathlist
.path_count
;
2533 for (i
= 0; i
< pathcnt
; i
++) {
2534 if (pathlist
.path_info
[i
].path_state
< MAXPATHSTATE
) {
2535 if (pathlist
.path_info
[i
].path_state
==
2536 MDI_PATHINFO_STATE_ONLINE
) {
2539 } else if (pathlist
.path_info
[i
].path_state
==
2540 MDI_PATHINFO_STATE_STANDBY
) {
2545 if (pathlist
.path_info
[p_on
].path_state
==
2546 MDI_PATHINFO_STATE_ONLINE
) {
2548 (void) strcpy(drvr_path
,
2549 pathlist
.path_info
[p_on
].path_hba
);
2551 /* standby or path0 */
2552 (void) strcpy(drvr_path
,
2553 pathlist
.path_info
[p_st
].path_hba
);
2555 free(pathlist
.path_info
);
2558 (void) strcpy(drvr_path
, path_phys
);
2560 if ((char_ptr
= strrchr(drvr_path
, '/')) == NULL
) {
2561 (void) print_errString(L_INVLD_PATH_NO_SLASH_FND
,
2565 *char_ptr
= '\0'; /* Make into nexus or HBA driver path. */
2568 * Each HBA and driver stack has its own structures
2569 * for this, so we have to handle each one individually.
2571 path_type
= g_get_path_type(drvr_path
);
2573 if (path_type
) { /* Quick sanity check for valid path */
2574 if ((err
= g_get_nexus_path(drvr_path
, &char_ptr
)) != 0) {
2575 (void) print_errString(err
, path_phys
);
2578 (void) strcpy(socal_path
, char_ptr
);
2582 /* attach :devctl to get node stat instead of dir stat. */
2583 (void) strcat(drvr_path
, FC_CTLR
);
2585 if (stat(drvr_path
, &sbuf
) < 0) {
2586 (void) print_errString(L_LSTAT_ERROR
, path_phys
);
2590 drvr_inst
= minor(sbuf
.st_rdev
);
2594 * first take care of ifp card.
2596 if (path_type
& FC4_PCI_FCA
) {
2597 if ((ifp_ks
= kstat_lookup(kc
, "ifp",
2598 drvr_inst
, "statistics")) != NULL
) {
2600 if (kstat_read(kc
, ifp_ks
, &ifp_stats
) < 0) {
2601 (void) fprintf(stderr
,
2603 "Error: could not read ifp%d\n"), drvr_inst
);
2606 (void) fprintf(stdout
, MSGSTR(2083,
2607 "\tInformation for FC Loop of"
2608 " FC100/P Host Adapter\n\tat path: %s\n"),
2610 if (ifp_stats
.version
> 1) {
2611 (void) fprintf(stdout
, "\t");
2612 (void) fprintf(stdout
, MSGSTR(32,
2613 "Information from %s"),
2614 ifp_stats
.drvr_name
);
2615 (void) fprintf(stdout
, "\n");
2616 if ((*ifp_stats
.node_wwn
!= NULL
) &&
2617 (*ifp_stats
.port_wwn
!= NULL
)) {
2618 (void) fprintf(stdout
, MSGSTR(104,
2619 " Host Adapter WWN's: Node:%s"
2622 ifp_stats
.port_wwn
);
2624 if (*ifp_stats
.fw_revision
!= NULL
) {
2625 (void) fprintf(stdout
, MSGSTR(105,
2626 " Host Adapter Firmware Revision: %s\n"),
2627 ifp_stats
.fw_revision
);
2629 if (ifp_stats
.parity_chk_enabled
!= 0) {
2630 (void) fprintf(stdout
, MSGSTR(2084,
2631 " This Host Adapter checks "
2632 "PCI-Bus parity.\n"));
2636 (void) fprintf(stdout
, MSGSTR(2085,
2637 " Version Lips\n"));
2638 (void) fprintf(stdout
, " %10d%7d\n",
2640 ifp_stats
.lip_count
);
2641 /* If any status conditions exist then display */
2642 for (i
= 0; i
< FC_STATUS_ENTRIES
; i
++) {
2643 if (ifp_stats
.resp_status
[i
] != 0) {
2644 if (header_flag
++ == 0) {
2645 (void) fprintf(stdout
, MSGSTR(2086,
2646 " Fibre Channel Transport "
2652 (void) l_format_ifp_status_msg(
2654 ifp_stats
.resp_status
[i
], i
);
2655 (void) fprintf(stdout
, " %s\n",
2660 (void) fprintf(stdout
, MSGSTR(2087,
2661 "\n\t\tTARGET ERROR INFORMATION:\n"));
2662 (void) fprintf(stdout
, MSGSTR(2088,
2663 "AL_PA logouts_recvd task_mgmt_failures"
2664 " data_ro_mismatches data_len_mismatch\n"));
2666 if (err
= g_get_dev_map(path_phys
, &map
,
2667 (Options
& PVERBOSE
))) {
2668 (void) print_errString(err
, path_phys
);
2673 if (dtype
== DTYPE_DIRECT
) {
2674 if (err
= g_get_wwn(path_phys
, port_wwn
,
2676 Options
& PVERBOSE
)) {
2677 (void) print_errString(err
,
2681 for (i
= 0, dev_addr_list
= map
.dev_addr
;
2684 if (dev_addr_list
->gfc_port_dev
.
2689 "%3x%14d%18d%20d%20d\n",
2691 ifp_stats
.tstats
[i
].
2693 ifp_stats
.tstats
[i
].
2695 ifp_stats
.tstats
[i
].
2697 ifp_stats
.tstats
[i
].
2702 if (i
>= map
.count
) {
2704 (void) print_errString(
2705 L_INVALID_LOOP_MAP
, path_phys
);
2710 for (i
= 0, dev_addr_list
= map
.dev_addr
;
2713 (void) fprintf(stdout
,
2714 "%3x%14d%18d%20d%20d\n",
2715 dev_addr_list
->gfc_port_dev
.
2717 ifp_stats
.tstats
[i
].logouts_recvd
,
2718 ifp_stats
.tstats
[i
].task_mgmt_failures
,
2719 ifp_stats
.tstats
[i
].data_ro_mismatches
,
2720 ifp_stats
.tstats
[i
].dl_len_mismatches
);
2724 free((void *)map
.dev_addr
);
2726 } else if (path_type
& FC4_SF_XPORT
) {
2728 * process cards with sf xport nodes.
2730 if (stat(socal_path
, &sbuf
) < 0) {
2731 (void) print_errString(L_LSTAT_ERROR
, path_phys
);
2734 socal_inst
= minor(sbuf
.st_rdev
)/2;
2735 port
= socal_inst
%2;
2737 sf_inst
= LUX_SF_MINOR2INST(minor(sbuf
.st_rdev
));
2738 if (!(sf_ks
= kstat_lookup(kc
, "sf", sf_inst
,
2740 (void) fprintf(stderr
,
2742 " Error: could not lookup driver stats for sf%d\n"),
2746 if (!(fc_ks
= kstat_lookup(kc
, "socal", socal_inst
,
2748 (void) fprintf(stderr
,
2750 " Error: could not lookup driver stats for socal%d\n"),
2754 if (kstat_read(kc
, sf_ks
, &sf_stats
) < 0) {
2755 (void) fprintf(stderr
,
2757 " Error: could not read driver stats for sf%d\n"),
2761 if (kstat_read(kc
, fc_ks
, &fc_stats
) < 0) {
2762 (void) fprintf(stderr
,
2764 " Error: could not read driver stats for socal%d\n"),
2768 (void) display_socal_stats(port
, socal_path
, &fc_stats
);
2769 (void) display_sf_stats(path_phys
, dtype
, &sf_stats
);
2770 } else if ((path_type
& FC_FCA_MASK
) == FC_PCI_FCA
) {
2771 fprintf(stderr
, MSGSTR(2252,
2772 "\n WARNING!! display -r on qlc is"
2773 " currently not supported.\n"));
2775 fprintf(stderr
, MSGSTR(2253,
2776 "\n WARNING!! display -r is not supported on path\n"
2777 " %s\n"), drvr_path
);
2779 (void) kstat_close(kc
);
2787 * adm_display_verbose_disk() Gets the mode page information
2788 * for a SENA disk and prints that information.
2794 adm_display_verbose_disk(char *path
, int verbose
)
2797 Mode_header_10
*mode_header_ptr
;
2800 struct mode_page
*pg_hdr
;
2801 int offset
, hdr_printed
= 0, err
= 0;
2803 if ((err
= l_get_mode_pg(path
, &pg_buf
, verbose
)) == 0) {
2805 mode_header_ptr
= (struct mode_header_10_struct
*)(int)pg_buf
;
2806 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
2807 (uchar_t
)sizeof (struct mode_header_10_struct
) +
2808 (uchar_t
*)(uintptr_t)(mode_header_ptr
->bdesc_length
)));
2809 offset
= sizeof (struct mode_header_10_struct
) +
2810 mode_header_ptr
->bdesc_length
;
2811 while (offset
< (mode_header_ptr
->length
+
2812 sizeof (mode_header_ptr
->length
))) {
2813 switch (pg_hdr
->code
) {
2815 pg1_buf
= (struct mode_page_01_struct
*)
2817 P_DPRINTF(" adm_display_verbose_disk:"
2818 "Mode Sense page 1 found.\n");
2819 if (hdr_printed
++ == 0) {
2820 (void) fprintf(stdout
,
2822 " Mode Sense data:\n"));
2824 (void) fprintf(stdout
,
2828 " Read Retry Count:\t\t"
2830 " Write Retry Count:\t\t"
2834 pg1_buf
->read_retry_count
,
2835 pg1_buf
->write_retry_count
);
2837 case MODEPAGE_GEOMETRY
:
2838 pg4_buf
= (struct mode_page_04_struct
*)
2840 P_DPRINTF(" adm_display_verbose_disk:"
2841 "Mode Sense page 4 found.\n");
2842 if (hdr_printed
++ == 0) {
2843 (void) fprintf(stdout
,
2845 " Mode Sense data:\n"));
2848 (void) fprintf(stdout
,
2850 " Medium rotation rate:\t"
2851 "%d RPM\n"), pg4_buf
->rpm
);
2855 offset
+= pg_hdr
->length
+ sizeof (struct mode_page
);
2856 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
2864 } else if (getenv("_LUX_P_DEBUG") != NULL
) {
2865 (void) print_errString(err
, path
);
2870 * Print out the port_wwn or node_wwn
2873 print_wwn(FILE *fd
, uchar_t
*pn_wwn
)
2877 " %1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
2878 pn_wwn
[0], pn_wwn
[1], pn_wwn
[2], pn_wwn
[3],
2879 pn_wwn
[4], pn_wwn
[5], pn_wwn
[6], pn_wwn
[7]);
2883 * Print out the fabric dev port_id, hard_addr, port_wwn and node_wwn
2886 print_fabric_prop(int pos
, uchar_t
*port_wwn
, uchar_t
*node_wwn
, int port_addr
,
2889 (void) fprintf(stdout
, "%-4d %-6x %-6x ",
2890 pos
, port_addr
, hard_addr
);
2891 print_wwn(stdout
, port_wwn
);
2892 print_wwn(stdout
, node_wwn
);
2896 * Print out the private loop dev port_id, hard_addr, port_wwn and node_wwn
2899 print_private_loop_prop(int pos
, uchar_t
*port_wwn
, uchar_t
*node_wwn
,
2900 int port_addr
, int hard_addr
)
2902 (void) fprintf(stdout
, "%-3d %-2x %-2x %-2x ",
2903 pos
, port_addr
, g_sf_alpa_to_switch
[port_addr
], hard_addr
);
2904 print_wwn(stdout
, port_wwn
);
2905 print_wwn(stdout
, node_wwn
);
2909 * Get the device map from
2910 * fc nexus driver and prints the map.
2916 dump_map(char **argv
)
2918 int i
= 0, path_index
= 0, pathcnt
= 1;
2919 int limited_map_flag
= 0, err
= 0;
2920 char *path_phys
= NULL
;
2921 Path_struct
*path_struct
;
2922 struct lilpmap limited_map
;
2924 char temp2path
[MAXPATHLEN
];
2925 mp_pathlist_t pathlist
;
2926 int p_pw
= 0, p_on
= 0, p_st
= 0;
2927 gfc_dev_t map_root
, map_dev
;
2928 int *port_addr
, *hard_addr
, pos
= 0, count
;
2929 uchar_t
*hba_port_wwn
, *port_wwn
, *node_wwn
, *dtype_prop
;
2932 while (argv
[path_index
] != NULL
) {
2933 if ((err
= l_convert_name(argv
[path_index
], &path_phys
,
2934 &path_struct
, Options
& PVERBOSE
)) != 0) {
2935 (void) fprintf(stderr
,
2937 " Error: converting"
2938 " %s to physical path.\n"
2939 " Invalid pathname.\n"),
2942 (void) print_errString(err
, argv
[path_index
]);
2947 if (strstr(path_phys
, SCSI_VHCI
) != NULL
) {
2949 (void) strcpy(temp2path
, path_phys
);
2950 if (err
= g_get_pathlist(temp2path
, &pathlist
)) {
2951 (void) print_errString(err
, NULL
);
2954 pathcnt
= pathlist
.path_count
;
2955 p_pw
= p_on
= p_st
= 0;
2956 for (i
= 0; i
< pathcnt
; i
++) {
2957 if (pathlist
.path_info
[i
].path_state
<
2959 if (strstr(pathlist
.path_info
[i
].
2961 path_struct
->argv
) != NULL
) {
2965 if (pathlist
.path_info
[i
].path_state
==
2966 MDI_PATHINFO_STATE_ONLINE
) {
2969 if (pathlist
.path_info
[i
].path_state
==
2970 MDI_PATHINFO_STATE_STANDBY
) {
2975 if (strstr(pathlist
.path_info
[p_pw
].path_addr
,
2976 path_struct
->argv
) != NULL
) {
2977 /* matching input pwwn */
2978 (void) strcpy(temp2path
,
2979 pathlist
.path_info
[p_pw
].path_hba
);
2980 } else if (pathlist
.path_info
[p_on
].path_state
==
2981 MDI_PATHINFO_STATE_ONLINE
) {
2983 (void) strcpy(temp2path
,
2984 pathlist
.path_info
[p_on
].path_hba
);
2986 /* standby or path0 */
2987 (void) strcpy(temp2path
,
2988 pathlist
.path_info
[p_st
].path_hba
);
2990 free(pathlist
.path_info
);
2991 (void) strcat(temp2path
, FC_CTLR
);
2993 (void) strcpy(temp2path
, path_phys
);
2996 if ((dev_type
= g_get_path_type(temp2path
)) == 0) {
2997 (void) print_errString(L_INVALID_PATH
,
3002 if ((map_root
= g_dev_map_init(temp2path
, &err
,
3003 MAP_FORMAT_LILP
)) == NULL
) {
3004 if (dev_type
& FC_FCA_MASK
) {
3005 (void) print_errString(err
, argv
[path_index
]);
3009 * This did not work so try the FCIO_GETMAP
3012 if (err
= g_get_limited_map(path_phys
,
3013 &limited_map
, (Options
& PVERBOSE
))) {
3014 (void) print_errString(err
,
3023 if (limited_map_flag
) {
3024 (void) fprintf(stdout
,
3026 "Host Adapter AL_PA: %x\n"),
3027 limited_map
.lilp_myalpa
);
3029 (void) fprintf(stdout
,
3032 for (i
= 0; i
< (uint_t
)limited_map
.lilp_length
; i
++) {
3033 (void) fprintf(stdout
, "%-3d %-2x\n",
3034 i
, limited_map
.lilp_list
[i
]);
3037 if ((err
= g_dev_prop_lookup_bytes(map_root
,
3038 PORT_WWN_PROP
, &count
, &hba_port_wwn
)) != 0) {
3039 g_dev_map_fini(map_root
);
3040 (void) print_errString(err
, argv
[path_index
]);
3043 if ((err
= g_get_map_topology(
3044 map_root
, &map_topo
)) != 0) {
3045 (void) print_errString(err
, argv
[path_index
]);
3049 if ((map_dev
= g_get_first_dev(map_root
, &err
)) == NULL
) {
3050 if (err
== L_NO_SUCH_DEV_FOUND
) {
3051 g_dev_map_fini(map_root
);
3052 (void) fprintf(stderr
,
3053 MSGSTR(2308, " No devices are found on %s.\n"),
3057 g_dev_map_fini(map_root
);
3058 (void) print_errString(err
, argv
[path_index
]);
3065 case FC_TOP_PUBLIC_LOOP
:
3067 (void) fprintf(stdout
,
3068 MSGSTR(2095, "Pos Port_ID Hard_Addr Port WWN"
3069 " Node WWN Type\n"));
3071 if ((err
= g_dev_prop_lookup_ints(
3072 map_dev
, PORT_ADDR_PROP
, &port_addr
)) != 0) {
3073 g_dev_map_fini(map_root
);
3074 (void) print_errString(err
, argv
[path_index
]);
3077 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3078 PORT_WWN_PROP
, &count
, &port_wwn
)) != 0) {
3079 g_dev_map_fini(map_root
);
3080 (void) print_errString(err
, argv
[path_index
]);
3083 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3084 NODE_WWN_PROP
, &count
, &node_wwn
)) != 0) {
3085 g_dev_map_fini(map_root
);
3086 (void) print_errString(err
, argv
[path_index
]);
3089 if ((err
= g_dev_prop_lookup_ints(
3090 map_dev
, HARD_ADDR_PROP
, &hard_addr
)) != 0) {
3091 g_dev_map_fini(map_root
);
3092 (void) print_errString(err
, argv
[path_index
]);
3095 print_fabric_prop(pos
++, port_wwn
,
3096 node_wwn
, *port_addr
, *hard_addr
);
3097 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3098 INQ_DTYPE_PROP
, &count
, &dtype_prop
)) != 0) {
3099 (void) fprintf(stdout
,
3100 MSGSTR(2307, " Failed to get the type.\n"));
3102 print_fabric_dtype_prop(hba_port_wwn
, port_wwn
,
3106 if (((map_dev
= g_get_next_dev(
3107 map_dev
, &err
)) == NULL
) &&
3108 (err
!= L_NO_SUCH_DEV_FOUND
)) {
3109 g_dev_map_fini(map_root
);
3110 (void) print_errString(err
, argv
[path_index
]);
3115 case FC_TOP_PRIVATE_LOOP
:
3116 (void) fprintf(stdout
,
3118 "Pos AL_PA ID Hard_Addr "
3119 "Port WWN Node WWN Type\n"));
3122 if ((err
= g_dev_prop_lookup_ints(
3123 map_dev
, PORT_ADDR_PROP
, &port_addr
)) != 0) {
3124 g_dev_map_fini(map_root
);
3125 (void) print_errString(err
, argv
[path_index
]);
3128 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3129 PORT_WWN_PROP
, &count
, &port_wwn
)) != 0) {
3130 g_dev_map_fini(map_root
);
3131 (void) print_errString(err
, argv
[path_index
]);
3134 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3135 NODE_WWN_PROP
, &count
, &node_wwn
)) != 0) {
3136 g_dev_map_fini(map_root
);
3137 (void) print_errString(err
, argv
[path_index
]);
3140 if ((err
= g_dev_prop_lookup_ints(
3141 map_dev
, HARD_ADDR_PROP
, &hard_addr
)) != 0) {
3142 g_dev_map_fini(map_root
);
3143 (void) print_errString(err
, argv
[path_index
]);
3146 print_private_loop_prop(pos
++, port_wwn
,
3147 node_wwn
, *port_addr
, *hard_addr
);
3148 if ((err
= g_dev_prop_lookup_bytes(map_dev
,
3149 INQ_DTYPE_PROP
, &count
, &dtype_prop
)) != 0) {
3150 (void) fprintf(stdout
,
3151 MSGSTR(2307, " Failed to get the type.\n"));
3153 print_private_loop_dtype_prop(hba_port_wwn
,
3154 port_wwn
, *dtype_prop
);
3157 if (((map_dev
= g_get_next_dev(
3158 map_dev
, &err
)) == NULL
) &&
3159 (err
!= L_NO_SUCH_DEV_FOUND
)) {
3160 g_dev_map_fini(map_root
);
3161 (void) print_errString(err
, argv
[path_index
]);
3167 (void) print_errString(L_UNEXPECTED_FC_TOPOLOGY
,
3171 g_dev_map_fini(map_root
);
3173 limited_map_flag
= 0;
3179 * Gets a list of non-SENA fcal devices
3180 * found on the system.
3184 * NULL: No non-enclosure devices found.
3185 * !NULL: Devices found
3186 * wwn_list points to a linked list of wwn's.
3191 n_get_non_encl_list(WWN_list
**wwn_list_ptr
, int verbose
)
3193 int i
, j
, k
, err
, found_ib
= 0, pathcnt
= 1;
3195 Box_list
*b_list
= NULL
;
3198 gfc_port_dev_info_t
*dev_addr_list
;
3199 char phci_path
[MAXPATHLEN
], oldphci_path
[MAXPATHLEN
];
3200 mp_pathlist_t pathlist
;
3204 * Only interested in devices that are not part of
3205 * a Photon enclosure.
3207 if ((err
= l_get_box_list(&b_list
, verbose
)) != 0) {
3208 return (err
); /* Failure */
3211 if (err
= g_get_wwn_list(&wwn_list
, verbose
)) {
3212 (void) l_free_box_list(&b_list
);
3216 while (b_list
!= NULL
) {
3219 if (strstr(b_list
->b_physical_path
, SCSI_VHCI
) != NULL
) {
3220 (void) strcpy(phci_path
, b_list
->b_physical_path
);
3221 if (err
= g_get_pathlist(phci_path
, &pathlist
)) {
3222 (void) print_errString(err
, NULL
);
3225 pathcnt
= pathlist
.path_count
;
3228 for (k
= 0; k
< pathcnt
; k
++) {
3230 if ((k
> 0) && (strstr(oldphci_path
,
3231 pathlist
.path_info
[k
].path_hba
))) {
3235 if (strstr(b_list
->b_physical_path
, SCSI_VHCI
) == NULL
) {
3236 if ((err
= g_get_dev_map(b_list
->b_physical_path
,
3237 &map
, verbose
)) != 0) {
3238 (void) g_free_wwn_list(&wwn_list
);
3239 (void) l_free_box_list(&b_list
);
3243 (void) strcpy(phci_path
,
3244 pathlist
.path_info
[k
].path_hba
);
3245 (void) strcpy(oldphci_path
, phci_path
);
3246 (void) strcat(phci_path
, FC_CTLR
);
3247 if (g_get_dev_map(phci_path
, &map
, verbose
)) {
3251 free(pathlist
.path_info
);
3256 switch (map
.hba_addr
.port_topology
) {
3258 case FC_TOP_PUBLIC_LOOP
:
3260 for (i
= 0, dev_addr_list
= map
.dev_addr
;
3261 i
< map
.count
; i
++, dev_addr_list
++) {
3262 for (found_ib
= 1, j
= 0; j
< WWN_SIZE
;
3264 if (b_list
->b_node_wwn
[j
] !=
3265 dev_addr_list
->gfc_port_dev
.
3266 pub_port
.dev_nwwn
.raw_wwn
[j
]) {
3271 (void) n_rem_list_entry_fabric(
3272 dev_addr_list
->gfc_port_dev
.
3273 pub_port
.dev_did
.port_id
, &map
,
3279 case FC_TOP_PRIVATE_LOOP
:
3281 for (i
= 0, dev_addr_list
= map
.dev_addr
;
3282 i
< map
.count
; i
++, dev_addr_list
++) {
3283 for (found_ib
= 1, j
= 0; j
< WWN_SIZE
;
3285 if (b_list
->b_node_wwn
[j
] !=
3286 dev_addr_list
->gfc_port_dev
.
3287 priv_port
.sf_node_wwn
[j
]) {
3292 box_id
= g_sf_alpa_to_switch
3293 [dev_addr_list
->gfc_port_dev
.
3294 priv_port
.sf_al_pa
] &
3296 /* This function has been added */
3297 /* here only to keep from having */
3298 /* to tab over farther */
3299 (void) n_rem_list_entry(box_id
, &map
,
3301 if (wwn_list
== NULL
) {
3302 /* Return the list */
3303 *wwn_list_ptr
= NULL
;
3310 (void) free((void *)map
.dev_addr
);
3311 return (L_PT_PT_FC_TOP_NOT_SUPPORTED
);
3313 (void) free((void *)map
.dev_addr
);
3314 return (L_UNEXPECTED_FC_TOPOLOGY
);
3316 free((void *)map
.dev_addr
);
3320 free(pathlist
.path_info
);
3323 b_list
= b_list
->box_next
;
3325 /* Return the list */
3326 *wwn_list_ptr
= wwn_list
;
3327 (void) l_free_box_list(&b_list
);
3334 * n_rem_list_entry() We found an IB so remove disks that
3335 * are in the Photon from the individual device list.
3338 * wwn_list - removes the fcal disks that are in SENA enclosure
3344 n_rem_list_entry(uchar_t box_id
, struct gfc_map
*map
,
3345 struct wwn_list_struct
**wwn_list
)
3348 gfc_port_dev_info_t
*dev_addr_list
;
3350 N_DPRINTF(" n_rem_list_entry: Removing devices"
3351 " with box_id=0x%x from device list.\n", box_id
);
3354 for (k
= 0, dev_addr_list
= map
->dev_addr
; k
< map
->count
;
3355 k
++, dev_addr_list
++) {
3356 if ((g_sf_alpa_to_switch
[dev_addr_list
->gfc_port_dev
.
3357 priv_port
.sf_hard_address
] & BOX_ID_MASK
)
3359 n_rem_wwn_entry(dev_addr_list
->gfc_port_dev
.
3360 priv_port
.sf_node_wwn
, wwn_list
);
3369 * n_rem_list_entry_fabric() We found an IB so remove disks that
3370 * are in the Photon from the individual device list.
3373 * wwn_list - removes the fcal disks that are in SENA enclosure
3379 n_rem_list_entry_fabric(int pa
, struct gfc_map
*map
,
3380 struct wwn_list_struct
**wwn_list
)
3383 gfc_port_dev_info_t
*dev_addr_ptr
;
3385 N_DPRINTF(" n_rem_list_entry: Removing devices"
3386 " with the same domain and area ID as"
3387 " 0x%x PA from device list.\n", pa
);
3388 for (k
= 0, dev_addr_ptr
= map
->dev_addr
; k
< map
->count
;
3389 k
++, dev_addr_ptr
++) {
3391 /* matching the domain and area id with input alpa, */
3392 /* ignoring last 8 bits. */
3393 if ((dev_addr_ptr
->gfc_port_dev
.pub_port
.dev_did
.port_id
|
3394 0xff) == (pa
| 0xff)) {
3395 n_rem_wwn_entry(dev_addr_ptr
->
3396 gfc_port_dev
.pub_port
.dev_nwwn
.raw_wwn
,
3404 * n_rem_wwn_entry() removes input wwn from wwn_list.
3407 * wwn_list - removes the input wwn from wwn_list if found.
3413 n_rem_wwn_entry(uchar_t node_wwn
[], struct wwn_list_struct
**wwn_list
)
3416 WWN_list
*inner
, *l1
;
3419 while (inner
!= NULL
) {
3420 for (found_dev
= 1, l
= 0; l
< WWN_SIZE
; l
++) {
3421 if (inner
->w_node_wwn
[l
] != node_wwn
[l
]) {
3426 /* Remove this entry from the list */
3427 if (inner
->wwn_prev
!= NULL
) {
3428 inner
->wwn_prev
->wwn_next
=
3431 *wwn_list
= inner
->wwn_next
;
3433 if (inner
->wwn_next
!= NULL
) {
3434 inner
->wwn_next
->wwn_prev
=
3438 N_DPRINTF(" n_rem_wwn_entry: "
3439 "Removing Logical=%s "
3441 "Prev=0x%x, Next=0x%x\n",
3446 inner
= inner
->wwn_next
;
3447 if ((l1
->wwn_prev
== NULL
) &&
3448 (l1
->wwn_next
) == NULL
) {
3449 (void) free(l1
->physical_path
);
3450 (void) free(l1
->logical_path
);
3453 N_DPRINTF(" n_rem_list_entry: "
3459 (void) free(l1
->physical_path
);
3460 (void) free(l1
->logical_path
);
3463 inner
= inner
->wwn_next
;
3470 * non_encl_probe() Finds and displays a list of
3471 * non-SENA fcal devices which is found on the
3480 WWN_list
*wwn_list
, *wwn_listh
, *inner
, *l1
;
3482 char lun_a
[MAXPATHLEN
], lun_b
[MAXPATHLEN
], temppath
[MAXPATHLEN
];
3483 char *tempptra
, *tempptrb
, *tempptr
;
3484 mp_pathlist_t pathlist
;
3485 int compare_result
, retr_outer
= 0;
3486 ddi_devid_t devid1
= NULL
, devid2
= NULL
;
3487 di_node_t root
= DI_NODE_NIL
;
3489 if (err
= n_get_non_encl_list(&wwn_list
, (Options
& PVERBOSE
))) {
3490 (void) print_errString(err
, NULL
);
3494 g_sort_wwn_list(&wwn_list
);
3496 wwn_listh
= wwn_list
;
3498 if (wwn_list
!= NULL
) {
3499 if (wwn_list
->wwn_next
!= NULL
) {
3500 (void) fprintf(stdout
,
3501 MSGSTR(2098, "\nFound Fibre Channel device(s):\n"));
3503 (void) fprintf(stdout
,
3504 MSGSTR(2099, "\nFound Fibre Channel device:\n"));
3510 while (wwn_list
!= NULL
) {
3511 if (strstr(wwn_list
->physical_path
, SCSI_VHCI
) != NULL
) {
3512 (void) strcpy(temppath
, wwn_list
->physical_path
);
3513 if ((!g_get_pathlist(temppath
,
3515 ((tempptra
= strchr(pathlist
.path_info
[0].
3516 path_addr
, ','))) != NULL
) {
3518 (void) strcpy(lun_a
, tempptra
);
3519 free(pathlist
.path_info
);
3522 if ((((tempptr
= strstr(wwn_list
->physical_path
,
3523 SLSH_DRV_NAME_ST
)) != NULL
) ||
3524 ((tempptr
= strstr(wwn_list
->physical_path
,
3525 SLSH_DRV_NAME_SSD
)) != NULL
)) &&
3526 ((tempptra
= strchr(tempptr
, ',')) != NULL
)) {
3528 (void) strcpy(lun_a
, tempptra
);
3531 (void) fprintf(stdout
, " ");
3532 (void) fprintf(stdout
, MSGSTR(90, "Node WWN:"));
3533 (void) fprintf(stdout
, "%s ", wwn_list
->node_wwn_s
);
3535 if (wwn_list
->device_type
< 0x10) {
3536 (void) fprintf(stdout
, MSGSTR(35, "Device Type:"));
3537 (void) fprintf(stdout
, "%s",
3538 dtype
[wwn_list
->device_type
]);
3539 } else if (wwn_list
->device_type
< 0x1f) {
3540 (void) fprintf(stdout
, MSGSTR(2100,
3543 (void) fprintf(stdout
, MSGSTR(2101,
3546 (void) fprintf(stdout
, "\n ");
3547 (void) fprintf(stdout
, MSGSTR(31, "Logical Path:%s"),
3548 wwn_list
->logical_path
);
3549 (void) fprintf(stdout
, "\n");
3551 if (Options
& OPTION_P
) {
3552 (void) fprintf(stdout
, " ");
3553 (void) fprintf(stdout
,
3554 MSGSTR(5, "Physical Path:"));
3555 (void) fprintf(stdout
, "\n %s\n", wwn_list
->physical_path
);
3557 inner
= wwn_list
->wwn_next
;
3559 while (inner
!= NULL
) {
3560 if (strcmp(inner
->node_wwn_s
, wwn_list
->node_wwn_s
) == 0) {
3562 if (tempptra
!= NULL
) {
3563 if (strstr(inner
->physical_path
,
3564 SCSI_VHCI
) != NULL
) {
3565 (void) strcpy(temppath
,
3566 inner
->physical_path
);
3568 if ((!g_get_pathlist(temppath
, &pathlist
)) &&
3569 ((tempptrb
= strchr(
3570 pathlist
.path_info
[0].path_addr
, ','))) !=
3573 (void) strcpy(lun_b
, tempptrb
);
3574 free(pathlist
.path_info
);
3577 if ((((tempptr
= strstr(inner
->physical_path
,
3578 SLSH_DRV_NAME_ST
)) != NULL
) ||
3579 ((tempptr
= strstr(inner
->physical_path
,
3580 SLSH_DRV_NAME_SSD
)) != NULL
)) &&
3581 ((tempptrb
= strchr(tempptr
, ',')) != NULL
)) {
3583 (void) strcpy(lun_b
, tempptrb
);
3588 if (((tempptra
== NULL
) || (strcmp(lun_a
, lun_b
)) == 0)) {
3591 * Have we retrieved a snapshot yet?
3593 if (root
== DI_NODE_NIL
) {
3594 if ((root
= di_init("/", DINFOCPYALL
)) ==
3596 (void) fprintf(stdout
,
3598 "\nFailed to get device tree snapshot:\n"));
3603 /* Apply devid to ssd devices only */
3604 if (!retr_outer
&& strstr(wwn_list
->physical_path
,
3605 SLSH_DRV_NAME_SSD
) != NULL
) {
3606 if ((err
= g_devid_get(wwn_list
->physical_path
,
3607 &devid1
, root
, SSD_DRVR_NAME
)) != 0) {
3608 (void) print_errString(err
,
3609 wwn_list
->physical_path
);
3612 * Try retrieve of devid only once. If it fails
3613 * don't try it again but print error,
3614 * There should be a devid prop.
3619 * Apply devid to block devices only.
3620 * Get devid of inner path and compare
3621 * with outer path's devid.
3623 if ((strstr(inner
->physical_path
,
3624 SLSH_DRV_NAME_SSD
) != NULL
) &&
3627 if ((err
= g_devid_get(inner
->physical_path
,
3628 &devid2
, root
, SSD_DRVR_NAME
)) != 0) {
3630 (void) print_errString(err
,
3631 inner
->physical_path
);
3634 compare_result
= devid_compare(devid1
, devid2
);
3637 /* devid isn't applied */
3641 if (compare_result
== 0) {
3643 if (strcmp(wwn_list
->logical_path
,
3644 inner
->logical_path
)) {
3645 (void) fprintf(stdout
, " ");
3646 (void) fprintf(stdout
,
3647 MSGSTR(31, "Logical Path:%s"),
3648 inner
->logical_path
);
3649 (void) fprintf(stdout
, "\n");
3651 if (Options
& OPTION_P
) {
3652 (void) fprintf(stdout
, " ");
3653 (void) fprintf(stdout
, MSGSTR(5,
3655 (void) fprintf(stdout
, "\n %s\n",
3656 inner
->physical_path
);
3660 /* Remove this entry from the list */
3661 if (inner
->wwn_prev
!= NULL
) {
3662 inner
->wwn_prev
->wwn_next
=
3666 if (inner
->wwn_next
!= NULL
) {
3667 inner
->wwn_next
->wwn_prev
=
3670 free(inner
->physical_path
);
3671 free(inner
->logical_path
);
3673 inner
= inner
->wwn_next
;
3677 inner
= inner
->wwn_next
;
3678 } /* End if (compare_result == 0) */
3681 inner
= inner
->wwn_next
;
3684 inner
= inner
->wwn_next
;
3688 wwn_list
= wwn_list
->wwn_next
;
3691 } /* End while (wwn_list != NULL) */
3693 (void) g_free_wwn_list(&wwn_listh
);
3694 (void) di_fini(root
);
3701 Box_list
*b_list
, *o_list
, *c_list
;
3702 int multi_path_flag
, multi_print_flag
;
3703 int duplicate_names_found
= 0, err
= 0;
3705 b_list
= o_list
= c_list
= NULL
;
3706 if ((err
= l_get_box_list(&b_list
, Options
& PVERBOSE
)) != 0) {
3707 (void) print_errString(err
, NULL
);
3710 if (b_list
== NULL
) {
3711 (void) fprintf(stdout
,
3712 MSGSTR(93, "No %s enclosures found "
3713 "in /dev/es\n"), ENCLOSURE_PROD_NAME
);
3716 if (b_list
->box_next
!= NULL
) {
3717 (void) fprintf(stdout
, MSGSTR(2102,
3718 "Found Enclosure(s)"));
3720 (void) fprintf(stdout
, MSGSTR(2103, "Found Enclosure"));
3722 (void) fprintf(stdout
, ":\n");
3723 while (b_list
!= NULL
) {
3724 /* Don't re-print multiple paths */
3726 multi_print_flag
= 0;
3727 while (c_list
!= b_list
) {
3728 if (strcmp(c_list
->b_node_wwn_s
,
3729 b_list
->b_node_wwn_s
) == 0) {
3730 multi_print_flag
= 1;
3733 c_list
= c_list
->box_next
;
3735 if (multi_print_flag
) {
3736 b_list
= b_list
->box_next
;
3739 (void) fprintf(stdout
,
3740 MSGSTR(2104, "%s Name:%s Node WWN:%s "),
3741 b_list
->prod_id_s
, b_list
->b_name
,
3742 b_list
->b_node_wwn_s
);
3744 * Print logical path on same line if not multipathed.
3746 multi_path_flag
= 0;
3748 while (c_list
!= NULL
) {
3749 if ((c_list
!= b_list
) &&
3750 (strcmp(c_list
->b_node_wwn_s
,
3751 b_list
->b_node_wwn_s
) == 0)) {
3752 multi_path_flag
= 1;
3754 c_list
= c_list
->box_next
;
3756 if (multi_path_flag
) {
3757 (void) fprintf(stdout
, "\n ");
3759 (void) fprintf(stdout
,
3760 MSGSTR(31, "Logical Path:%s"),
3761 b_list
->logical_path
);
3763 if (Options
& OPTION_P
) {
3764 (void) fprintf(stdout
, "\n ");
3765 (void) fprintf(stdout
,
3766 MSGSTR(5, "Physical Path:"));
3767 (void) fprintf(stdout
, "%s",
3768 b_list
->b_physical_path
);
3771 while (c_list
!= NULL
) {
3772 if ((c_list
!= b_list
) &&
3773 (strcmp(c_list
->b_node_wwn_s
,
3774 b_list
->b_node_wwn_s
) == 0)) {
3775 (void) fprintf(stdout
, "\n ");
3776 (void) fprintf(stdout
,
3777 MSGSTR(31, "Logical Path:%s"),
3778 c_list
->logical_path
);
3779 if (Options
& OPTION_P
) {
3780 (void) fprintf(stdout
, "\n ");
3781 (void) fprintf(stdout
,
3782 MSGSTR(5, "Physical Path:"));
3783 (void) fprintf(stdout
, "%s",
3784 c_list
->b_physical_path
);
3787 c_list
= c_list
->box_next
;
3789 (void) fprintf(stdout
, "\n");
3790 /* Check for duplicate names */
3791 if (l_duplicate_names(o_list
, b_list
->b_node_wwn_s
,
3792 (char *)b_list
->b_name
,
3793 Options
& PVERBOSE
)) {
3794 duplicate_names_found
++;
3796 b_list
= b_list
->box_next
;
3799 if (duplicate_names_found
) {
3800 (void) fprintf(stdout
,
3801 MSGSTR(2105, "\nWARNING: There are enclosures with "
3803 "You can not use the \"enclosure\""
3804 " name to specify these subsystems.\n"
3805 "Please use the \"enclosure_name\""
3806 " subcommand to select unique names.\n\n"));
3808 (void) l_free_box_list(&b_list
);
3812 * display_port_status() Prints the device's
3819 display_port_status(int d_state_flag
)
3822 if (d_state_flag
& L_OPEN_FAIL
) {
3823 (void) fprintf(stdout
, MSGSTR(28, "Open Failed"));
3824 } else if (d_state_flag
& L_NOT_READY
) {
3825 (void) fprintf(stdout
, MSGSTR(20, "Not Ready"));
3826 } else if (d_state_flag
& L_NOT_READABLE
) {
3827 (void) fprintf(stdout
, MSGSTR(88, "Not Readable"));
3828 } else if (d_state_flag
& L_SPUN_DWN_D
) {
3829 (void) fprintf(stdout
, MSGSTR(68, "Spun Down"));
3830 } else if (d_state_flag
& L_SCSI_ERR
) {
3831 (void) fprintf(stdout
, MSGSTR(70, "SCSI Error"));
3832 } else if (d_state_flag
& L_RESERVED
) {
3833 (void) fprintf(stdout
, MSGSTR(73, "Reservation conflict"));
3834 } else if (d_state_flag
& L_NO_LABEL
) {
3835 (void) fprintf(stdout
, MSGSTR(92, "No UNIX Label"));
3837 (void) fprintf(stdout
, MSGSTR(29, "O.K."));
3839 (void) fprintf(stdout
, "\n");
3843 * Displays individual SENA
3844 * FC disk information.
3846 * Caller to this routine should free the storage due to
3847 * the use of g_get_dev_map
3853 display_fc_disk(struct path_struct
*path_struct
, char *ses_path
,
3854 gfc_map_t
*map
, L_inquiry inq
, int verbose
)
3856 static WWN_list
*wwn_list
= NULL
;
3857 static char path_phys
[MAXPATHLEN
];
3858 static L_disk_state l_disk_state
;
3859 static L_inquiry local_inq
;
3860 static uchar_t node_wwn
[WWN_SIZE
];
3861 char same_path_phys
= B_FALSE
; /* To chk for repeat args */
3862 uchar_t port_wwn
[WWN_SIZE
], *pg_buf
;
3863 char logical_path
[MAXPATHLEN
];
3864 int al_pa
, port_a_flag
= 0;
3865 int offset
, mode_data_avail
= 0;
3866 int no_path_flag
= 0, err
= 0;
3868 Mode_header_10
*mode_header_ptr
= NULL
;
3869 struct mode_page
*pg_hdr
;
3872 * Do a quick check to see if its the same path as in last call.
3873 * path_phys is a static array and so dont worry about its
3876 if (strcmp(path_phys
, path_struct
->p_physical_path
) == 0)
3877 same_path_phys
= B_TRUE
;
3879 (void) strcpy(path_phys
, path_struct
->p_physical_path
);
3880 (void) memset((char *)logical_path
, 0, sizeof (logical_path
));
3883 * slot_valid is 1 when argument is of the form 'enclosure,[f|r]<n>'.
3884 * If slot_valid != 1, g_get_dev_map and l_get_ses_path would
3885 * already have been called
3887 if (path_struct
->slot_valid
== 1) {
3888 /* Get the location information. */
3889 if (err
= g_get_dev_map(path_phys
, map
, (Options
& PVERBOSE
))) {
3890 (void) print_errString(err
, path_phys
);
3893 if (err
= l_get_ses_path(path_phys
, ses_path
, map
,
3894 (Options
& PVERBOSE
))) {
3895 (void) print_errString(err
, path_phys
);
3901 * Get the WWN for our disk if we already haven't or if there was an
3904 if (same_path_phys
== B_FALSE
) {
3905 if (err
= g_get_wwn(path_phys
, port_wwn
, node_wwn
,
3906 &al_pa
, (Options
& PVERBOSE
))) {
3907 (void) print_errString(err
, path_phys
);
3911 if (err
= g_get_inquiry(ses_path
, &local_inq
)) {
3912 (void) print_errString(err
, ses_path
);
3918 * We are interested only a couple of ib_tbl fields and
3919 * those get filled using l_get_ib_status.
3920 * Note that NOT ALL of ib_tbl fields get filled here
3922 if ((err
= l_get_ib_status(ses_path
, &l_state
,
3923 Options
& PVERBOSE
)) != 0) {
3924 (void) print_errString(err
, ses_path
);
3929 * Get path to all the FC disk and tape devices.
3930 * if we haven't already done so in a previous pass
3932 if ((wwn_list
== NULL
) && (err
= g_get_wwn_list(&wwn_list
, verbose
))) {
3933 (void) print_errString(err
, ses_path
);
3934 exit(-1); /* Failure */
3938 * Get the disk status if it is a different path_phys from
3941 if (same_path_phys
== B_FALSE
) {
3942 (void) memset(&l_disk_state
, 0,
3943 sizeof (struct l_disk_state_struct
));
3944 if (err
= l_get_disk_status(path_phys
, &l_disk_state
,
3945 wwn_list
, (Options
& PVERBOSE
))) {
3946 (void) print_errString(err
, path_phys
);
3951 if (l_disk_state
.l_state_flag
& L_NO_PATH_FOUND
) {
3952 (void) fprintf(stderr
, MSGSTR(2106,
3953 "\nWARNING: No path found "
3954 "in /dev/rdsk directory\n"
3955 " Please check the logical links in /dev/rdsk\n"
3956 " (It may be necessary to run the \"disks\" "
3959 /* Just call to get the status directly. */
3960 if (err
= l_get_port(ses_path
, &port_a_flag
, verbose
)) {
3961 (void) print_errString(err
, ses_path
);
3964 if (err
= l_get_disk_port_status(path_phys
,
3965 &l_disk_state
, port_a_flag
,
3966 (Options
& PVERBOSE
))) {
3967 (void) print_errString(err
, path_phys
);
3973 if (strlen(l_disk_state
.g_disk_state
.node_wwn_s
) == 0) {
3974 (void) sprintf(l_disk_state
.g_disk_state
.node_wwn_s
,
3975 "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
3976 node_wwn
[0], node_wwn
[1], node_wwn
[2], node_wwn
[3],
3977 node_wwn
[4], node_wwn
[5], node_wwn
[6], node_wwn
[7]);
3980 /* get mode page information for FC device */
3981 if (l_get_mode_pg(path_phys
, &pg_buf
, Options
& PVERBOSE
) == 0) {
3982 mode_header_ptr
= (struct mode_header_10_struct
*)(int)pg_buf
;
3983 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
3984 (uchar_t
)sizeof (struct mode_header_10_struct
) +
3985 (uchar_t
*)(uintptr_t)(mode_header_ptr
->bdesc_length
)));
3986 offset
= sizeof (struct mode_header_10_struct
) +
3987 mode_header_ptr
->bdesc_length
;
3988 while (offset
< (mode_header_ptr
->length
+
3989 sizeof (mode_header_ptr
->length
)) &&
3991 if (pg_hdr
->code
== MODEPAGE_CACHING
) {
3995 offset
+= pg_hdr
->length
+ sizeof (struct mode_page
);
3996 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
4001 switch ((inq
.inq_dtype
& DTYPE_MASK
)) {
4003 fprintf(stdout
, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
4006 case DTYPE_SEQUENTIAL
: /* Tape */
4007 fprintf(stdout
, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
4011 fprintf(stdout
, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
4016 if (l_disk_state
.g_disk_state
.port_a_valid
) {
4017 (void) fprintf(stdout
, " ");
4018 (void) fprintf(stdout
, MSGSTR(141, "Status(Port A):"));
4019 (void) fprintf(stdout
, "\t");
4020 display_port_status(
4021 l_disk_state
.g_disk_state
.d_state_flags
[PORT_A
]);
4023 if (path_struct
->f_flag
) {
4024 if ((ib_present_chk(&l_state
, 0) == 1) &&
4025 (l_state
.drv_front
[path_struct
->slot
].ib_status
.bypass_a_en
)) {
4026 (void) fprintf(stdout
,
4028 " Status(Port A):\tBYPASSED\n"));
4031 if ((ib_present_chk(&l_state
, 0) == 1) &&
4032 (l_state
.drv_rear
[path_struct
->slot
].ib_status
.bypass_a_en
)) {
4033 (void) fprintf(stdout
,
4035 " Status(Port A):\tBYPASSED\n"));
4040 if (l_disk_state
.g_disk_state
.port_b_valid
) {
4041 (void) fprintf(stdout
, " ");
4042 (void) fprintf(stdout
, MSGSTR(142, "Status(Port B):"));
4043 (void) fprintf(stdout
, "\t");
4044 display_port_status(l_disk_state
.g_disk_state
.d_state_flags
[PORT_B
]);
4046 if (path_struct
->f_flag
) {
4047 if ((ib_present_chk(&l_state
, 1) == 1) &&
4048 (l_state
.drv_front
[path_struct
->slot
].ib_status
.bypass_b_en
)) {
4049 (void) fprintf(stdout
,
4051 " Status(Port B):\tBYPASSED\n"));
4054 if ((ib_present_chk(&l_state
, 1) == 1) &&
4055 (l_state
.drv_rear
[path_struct
->slot
].ib_status
.bypass_b_en
)) {
4056 (void) fprintf(stdout
,
4058 " Status(Port B):\tBYPASSED\n"));
4064 (void) fprintf(stdout
, " ");
4065 if (port_a_flag
!= NULL
) {
4066 (void) fprintf(stdout
, MSGSTR(142, "Status(Port B):"));
4068 (void) fprintf(stdout
, MSGSTR(141, "Status(Port A):"));
4070 (void) fprintf(stdout
, "\t");
4071 display_port_status(
4072 l_disk_state
.g_disk_state
.d_state_flags
[port_a_flag
]);
4073 } else if ((!l_disk_state
.g_disk_state
.port_a_valid
) &&
4074 (!l_disk_state
.g_disk_state
.port_b_valid
)) {
4075 (void) fprintf(stdout
, MSGSTR(2107, " Status:\t\t"
4076 "No state available.\n"));
4079 (void) display_disk_info(inq
, l_disk_state
, path_struct
, pg_hdr
,
4080 mode_data_avail
, (char *)local_inq
.inq_box_name
, verbose
);
4088 * non_encl_fc_disk_display() Prints the device specific
4089 * information for an individual fcal device.
4095 non_encl_fc_disk_display(Path_struct
*path_struct
,
4096 L_inquiry inq_struct
, int verbose
)
4099 char phys_path
[MAXPATHLEN
];
4100 uchar_t node_wwn
[WWN_SIZE
], port_wwn
[WWN_SIZE
], *pg_buf
= NULL
;
4101 L_disk_state l_disk_state
;
4102 struct dlist
*mlist
;
4103 int i
= 0, al_pa
, offset
, mode_data_avail
= 0, err
= 0;
4104 int path_a_found
= 0, path_b_found
= 0, argpwwn
= 0,
4105 argnwwn
= 0, pathcnt
= 1;
4106 L_inquiry local_inq
;
4107 Mode_header_10
*mode_header_ptr
;
4108 struct mode_page
*pg_hdr
;
4109 WWN_list
*wwn_list
, *wwn_list_ptr
, *list_start
;
4110 char temppath
[MAXPATHLEN
], last_logical_path
[MAXPATHLEN
];
4111 mp_pathlist_t pathlist
;
4113 (void) strcpy(phys_path
, path_struct
->p_physical_path
);
4115 /* Get path to all the FC disk and tape devices. */
4116 if (err
= g_get_wwn_list(&wwn_list
, verbose
)) {
4120 g_sort_wwn_list(&wwn_list
);
4122 list_start
= wwn_list
;
4123 (void) strcpy(last_logical_path
, phys_path
);
4125 for (wwn_list_ptr
= wwn_list
; wwn_list_ptr
!= NULL
;
4126 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
4127 if (strcasecmp(wwn_list_ptr
->port_wwn_s
,
4128 path_struct
->argv
) == 0) {
4129 list_start
= wwn_list_ptr
;
4132 } else if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
4133 path_struct
->argv
) == 0) {
4134 list_start
= wwn_list_ptr
;
4140 for (wwn_list_ptr
= list_start
; wwn_list_ptr
!= NULL
;
4141 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
4145 if (strcasecmp(wwn_list_ptr
->port_wwn_s
,
4146 path_struct
->argv
) != 0) {
4149 (void) strcpy(phys_path
, wwn_list_ptr
->physical_path
);
4152 mode_data_avail
= 0;
4153 } else if (argnwwn
) {
4154 if (strstr(wwn_list_ptr
->logical_path
,
4155 last_logical_path
) != NULL
) {
4158 if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
4159 path_struct
->argv
) != 0) {
4162 (void) strcpy(phys_path
, wwn_list_ptr
->physical_path
);
4163 (void) strcpy(last_logical_path
,
4164 wwn_list_ptr
->logical_path
);
4167 mode_data_avail
= 0;
4170 (void) memset(&l_disk_state
, 0, sizeof (struct l_disk_state_struct
));
4172 if ((err
= g_get_multipath(phys_path
,
4173 &(l_disk_state
.g_disk_state
.multipath_list
),
4174 wwn_list
, verbose
)) != 0) {
4177 mlist
= l_disk_state
.g_disk_state
.multipath_list
;
4178 if (mlist
== NULL
) {
4179 l_disk_state
.l_state_flag
= L_NO_PATH_FOUND
;
4180 N_DPRINTF(" non_encl_fc_disk_display: Error finding"
4181 " multiple paths to the disk.\n");
4182 (void) g_free_wwn_list(&wwn_list
);
4186 /* get mode page information for FC device */
4187 if (l_get_mode_pg(phys_path
, &pg_buf
, verbose
) == 0) {
4188 mode_header_ptr
= (struct mode_header_10_struct
*)(int)pg_buf
;
4189 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
4190 (uchar_t
)sizeof (struct mode_header_10_struct
) +
4191 (uchar_t
*)(uintptr_t)(mode_header_ptr
->bdesc_length
)));
4192 offset
= sizeof (struct mode_header_10_struct
) +
4193 mode_header_ptr
->bdesc_length
;
4194 while (offset
< (mode_header_ptr
->length
+
4195 sizeof (mode_header_ptr
->length
)) &&
4197 if (pg_hdr
->code
== MODEPAGE_CACHING
) {
4201 offset
+= pg_hdr
->length
+ sizeof (struct mode_page
);
4202 pg_hdr
= ((struct mode_page
*)((int)pg_buf
+
4207 switch ((inq_struct
.inq_dtype
& DTYPE_MASK
)) {
4209 fprintf(stdout
, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
4212 case DTYPE_SEQUENTIAL
: /* Tape */
4213 fprintf(stdout
, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
4217 fprintf(stdout
, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
4221 while ((mlist
!= NULL
) && (!(path_a_found
&& path_b_found
))) {
4222 (void) strcpy(phys_path
, mlist
->dev_path
);
4223 if (err
= g_get_inquiry(phys_path
, &local_inq
)) {
4224 (void) fprintf(stderr
,
4226 "non_encl_fc_disk_display: Inquiry failed\n"));
4227 (void) print_errString(err
, phys_path
);
4228 (void) g_free_multipath(
4229 l_disk_state
.g_disk_state
.multipath_list
);
4230 (void) g_free_wwn_list(&wwn_list
);
4233 if ((err
= g_get_wwn(mlist
->dev_path
, port_wwn
, node_wwn
,
4234 &al_pa
, verbose
)) != 0) {
4235 (void) print_errString(err
, mlist
->dev_path
);
4236 (void) g_free_multipath(
4237 l_disk_state
.g_disk_state
.multipath_list
);
4238 (void) g_free_wwn_list(&wwn_list
);
4241 if (strlen(l_disk_state
.g_disk_state
.node_wwn_s
) == 0) {
4242 (void) sprintf(l_disk_state
.g_disk_state
.node_wwn_s
,
4243 "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
4244 node_wwn
[0], node_wwn
[1], node_wwn
[2], node_wwn
[3],
4245 node_wwn
[4], node_wwn
[5], node_wwn
[6], node_wwn
[7]);
4247 if ((err
= l_get_disk_port_status(phys_path
, &l_disk_state
,
4248 (local_inq
.inq_port
) ? FC_PORT_B
: FC_PORT_A
,
4250 (void) print_errString(err
, phys_path
);
4251 (void) g_free_multipath(
4252 l_disk_state
.g_disk_state
.multipath_list
);
4256 if ((!local_inq
.inq_port
) && (!path_a_found
)) {
4257 (void) sprintf(l_disk_state
.g_disk_state
.port_a_wwn_s
,
4258 "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
4259 port_wwn
[0], port_wwn
[1], port_wwn
[2], port_wwn
[3],
4260 port_wwn
[4], port_wwn
[5], port_wwn
[6], port_wwn
[7]);
4261 path_a_found
= l_disk_state
.g_disk_state
.port_a_valid
= 1;
4263 if ((local_inq
.inq_port
) && (!path_b_found
)) {
4264 path_b_found
= l_disk_state
.g_disk_state
.port_b_valid
= 1;
4265 (void) sprintf(l_disk_state
.g_disk_state
.port_b_wwn_s
,
4266 "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
4267 port_wwn
[0], port_wwn
[1], port_wwn
[2], port_wwn
[3],
4268 port_wwn
[4], port_wwn
[5], port_wwn
[6], port_wwn
[7]);
4271 if ((strstr(mlist
->dev_path
, SCSI_VHCI
) != NULL
) &&
4272 (!l_get_disk_port_status(phys_path
, &l_disk_state
,
4273 (!local_inq
.inq_port
) ? FC_PORT_B
: FC_PORT_A
,
4275 (void) strcpy(temppath
, mlist
->dev_path
);
4276 if (err
= g_get_pathlist(temppath
, &pathlist
)) {
4277 (void) print_errString(err
, NULL
);
4280 pathcnt
= pathlist
.path_count
;
4282 for (i
= 0; i
< pathcnt
; i
++) {
4283 if ((!path_a_found
) &&
4285 (strstr(pathlist
.path_info
[i
].
4287 l_disk_state
.g_disk_state
.
4288 port_b_wwn_s
) == NULL
)) {
4290 (void) strncpy(l_disk_state
.
4291 g_disk_state
.port_a_wwn_s
,
4292 pathlist
.path_info
[i
].
4294 path_a_found
= l_disk_state
.
4295 g_disk_state
.port_a_valid
= 1;
4297 if ((path_a_found
) &&
4299 (strstr(pathlist
.path_info
[i
].
4301 l_disk_state
.g_disk_state
.
4302 port_a_wwn_s
) == NULL
)) {
4304 (void) strncpy(l_disk_state
.
4305 g_disk_state
.port_b_wwn_s
,
4306 pathlist
.path_info
[i
].
4308 path_b_found
= l_disk_state
.
4309 g_disk_state
.port_b_valid
= 1;
4311 if ((path_a_found
) && (path_b_found
)) {
4316 free(pathlist
.path_info
);
4319 mlist
= mlist
->next
;
4322 if (l_disk_state
.g_disk_state
.port_a_valid
) {
4323 (void) fprintf(stdout
, " ");
4324 (void) fprintf(stdout
, MSGSTR(141, "Status(Port A):"));
4325 (void) fprintf(stdout
, "\t");
4326 display_port_status(l_disk_state
.g_disk_state
.d_state_flags
[FC_PORT_A
]);
4329 if (l_disk_state
.g_disk_state
.port_b_valid
) {
4330 (void) fprintf(stdout
, " ");
4331 (void) fprintf(stdout
, MSGSTR(142, "Status(Port B):"));
4332 (void) fprintf(stdout
, "\t");
4333 display_port_status(l_disk_state
.g_disk_state
.d_state_flags
[FC_PORT_B
]);
4336 (void) display_disk_info(local_inq
, l_disk_state
, path_struct
,
4337 pg_hdr
, mode_data_avail
, NULL
, verbose
);
4338 (void) g_free_multipath(l_disk_state
.g_disk_state
.multipath_list
);
4340 if (!(argpwwn
|| argnwwn
)) {
4345 (void) g_free_wwn_list(&wwn_list
);
4352 * display_disk_info() Prints the device specific information
4353 * for any FC_AL disk device.
4359 display_disk_info(L_inquiry inq
, L_disk_state l_disk_state
,
4360 Path_struct
*path_struct
, struct mode_page
*pg_hdr
,
4361 int mode_data_avail
, char *name_buf
, int options
)
4364 struct dlist
*mlist
;
4366 struct my_mode_caching
*pg8_buf
;
4368 char *enc_phys_path
;
4369 Path_struct
*enc_path_struct
;
4375 serial_len
= sizeof (inq80
.inq_serial
);
4376 err
= g_get_serial_number(path_struct
->p_physical_path
,
4377 inq80
.inq_serial
, &serial_len
);
4379 fprintf(stderr
, "\n");
4380 print_errString(err
, path_struct
->p_physical_path
);
4381 fprintf(stderr
, "\n");
4384 (void) fprintf(stdout
, " ");
4385 (void) fprintf(stdout
, MSGSTR(3, "Vendor:"));
4386 (void) fprintf(stdout
, "\t\t");
4387 print_chars(inq
.inq_vid
, sizeof (inq
.inq_vid
), 0);
4389 (void) fprintf(stdout
, MSGSTR(2115, "\n Product ID:\t\t"));
4390 print_chars(inq
.inq_pid
, sizeof (inq
.inq_pid
), 0);
4392 (void) fprintf(stdout
, MSGSTR(2116, "\n WWN(Node):\t\t%s"),
4393 l_disk_state
.g_disk_state
.node_wwn_s
);
4395 if (l_disk_state
.g_disk_state
.port_a_valid
) {
4396 (void) fprintf(stdout
, MSGSTR(2117, "\n WWN(Port A):\t\t%s"),
4397 l_disk_state
.g_disk_state
.port_a_wwn_s
);
4399 if (l_disk_state
.g_disk_state
.port_b_valid
) {
4400 (void) fprintf(stdout
, MSGSTR(2118, "\n WWN(Port B):\t\t%s"),
4401 l_disk_state
.g_disk_state
.port_b_wwn_s
);
4403 (void) fprintf(stdout
, "\n ");
4404 (void) fprintf(stdout
, MSGSTR(2119, "Revision:"));
4405 (void) fprintf(stdout
, "\t\t");
4406 print_chars(inq
.inq_revision
, sizeof (inq
.inq_revision
), 0);
4408 (void) fprintf(stdout
, "\n ");
4409 (void) fprintf(stdout
, MSGSTR(17, "Serial Num:"));
4410 (void) fprintf(stdout
, "\t\t");
4411 print_chars(inq80
.inq_serial
, serial_len
, 0);
4412 num_blks
= l_disk_state
.g_disk_state
.num_blocks
;
4414 num_blks
/= 2048; /* get Mbytes */
4415 (void) fprintf(stdout
, "\n ");
4416 (void) fprintf(stdout
,
4418 "Unformatted capacity:\t%6.3f MBytes"), num_blks
);
4420 (void) fprintf(stdout
, "\n");
4422 if (l_disk_state
.g_disk_state
.persistent_reserv_flag
) {
4423 (void) fprintf(stdout
,
4424 MSGSTR(2120, " Persistent Reserve:\t"));
4425 if (l_disk_state
.g_disk_state
.persistent_active
) {
4426 (void) fprintf(stdout
,
4427 MSGSTR(39, "Active"));
4428 (void) fprintf(stdout
, "\n");
4430 if (l_disk_state
.g_disk_state
.persistent_registered
) {
4431 (void) fprintf(stdout
,
4432 MSGSTR(2121, "Found Registered Keys"));
4434 (void) fprintf(stdout
,
4435 MSGSTR(87, "Not being used"));
4437 (void) fprintf(stdout
, "\n");
4440 if ((mode_data_avail
) && (pg_hdr
->code
== MODEPAGE_CACHING
)) {
4441 pg8_buf
= (struct my_mode_caching
*)(int)pg_hdr
;
4443 (void) fprintf(stdout
,
4448 if (pg8_buf
->rcd
== 0) {
4449 (void) fprintf(stdout
,
4453 (void) fprintf(stdout
,
4455 " Minimum prefetch:"
4457 " Maximum prefetch:"
4459 pg8_buf
->min_prefetch
,
4460 pg8_buf
->max_prefetch
);
4465 * When /dev/rdsk/cxtxdxsx form of input is specified
4466 * for display command the initial library version didn't
4467 * display Location information. The change is made
4468 * to display the same Location info as the non-library version.
4471 if (name_buf
!= NULL
) {
4472 fprintf(stdout
, MSGSTR(2125, " Location:\t\t"));
4473 if (path_struct
->slot_valid
) {
4475 * We have to do another inquiry on the enclosure (name_buf)
4476 * to determine if this device is within a daktari, or
4477 * a two sided device.
4479 if (!l_convert_name(name_buf
, &enc_phys_path
,
4480 &enc_path_struct
, 0)) {
4481 if (!g_get_inquiry(enc_phys_path
, &enc_inq
)) {
4482 enc_type
= l_get_enc_type(enc_inq
);
4485 /* If either of the above fail, we just assume the default */
4486 free(enc_phys_path
);
4487 free(enc_path_struct
);
4488 if (enc_type
== DAK_ENC_TYPE
) {
4489 if (path_struct
->f_flag
) {
4490 (void) fprintf(stdout
, MSGSTR(2239,
4491 "In slot %d in the enclosure named: %s\n"),
4492 path_struct
->slot
, name_buf
);
4494 (void) fprintf(stdout
, MSGSTR(2239,
4495 "In slot %d in the enclosure named: %s\n"),
4496 path_struct
->slot
+ (MAX_DRIVES_DAK
/2),
4499 } else { /* Default enclosure type */
4500 (void) fprintf(stdout
, path_struct
->f_flag
?
4502 "In slot %d in the Front of the enclosure named: %s\n")
4504 "In slot %d in the Rear of the enclosure named: %s\n"),
4505 path_struct
->slot
, name_buf
);
4508 (void) fprintf(stdout
, MSGSTR(2228,
4509 "In the enclosure named: %s\n"),
4514 (void) fprintf(stdout
, " %s\t\t%s\n",
4515 MSGSTR(35, "Device Type:"),
4516 dtype
[inq
.inq_dtype
& DTYPE_MASK
]);
4518 mlist
= l_disk_state
.g_disk_state
.multipath_list
;
4519 (void) fprintf(stdout
, MSGSTR(2128, " Path(s):\n"));
4520 if (strstr(mlist
->dev_path
, SCSI_VHCI
) != NULL
) {
4521 (void) fprintf(stdout
, " %s\n %s\n",
4522 mlist
->logical_path
, mlist
->dev_path
);
4523 (void) adm_print_pathlist(mlist
->dev_path
);
4526 (void) fprintf(stdout
, " %s\n %s\n",
4527 mlist
->logical_path
, mlist
->dev_path
);
4528 mlist
= mlist
->next
;
4532 if (Options
& OPTION_V
) {
4533 if (path_struct
->slot_valid
) {
4540 /* Only bother if the state is O.K. */
4541 if ((l_disk_state
.g_disk_state
.port_a_valid
) &&
4542 (l_disk_state
.g_disk_state
.d_state_flags
[port_a
] == 0))
4543 adm_display_verbose_disk(path_struct
->p_physical_path
, options
);
4544 else if ((l_disk_state
.g_disk_state
.port_b_valid
) &&
4545 (l_disk_state
.g_disk_state
.d_state_flags
[port_b
] == 0))
4546 adm_display_verbose_disk(path_struct
->p_physical_path
, options
);
4548 (void) fprintf(stdout
, "\n");
4555 * temp_decode() Display temperature bytes 1-3 state.
4561 temp_decode(Temp_elem_st
*temp
)
4563 if (temp
->ot_fail
) {
4564 (void) fprintf(stdout
, MSGSTR(2129,
4565 ": FAILURE - Over Temperature"));
4567 if (temp
->ut_fail
) {
4568 (void) fprintf(stdout
, MSGSTR(2130,
4569 ": FAILURE - Under Temperature"));
4571 if (temp
->ot_warn
) {
4572 (void) fprintf(stdout
, MSGSTR(2131,
4573 ": WARNING - Over Temperature"));
4575 if (temp
->ut_warn
) {
4576 (void) fprintf(stdout
, MSGSTR(2132,
4577 ": WARNING - Under Temperature"));
4584 * disp_degree() Display temperature in Degrees Celsius.
4590 disp_degree(Temp_elem_st
*temp
)
4595 t
-= 20; /* re-adjust */
4598 * The %c is the degree symbol.
4600 (void) fprintf(stdout
, ":%1.2d%cC ", t
, 186);
4606 * trans_decode() Display tranceivers state.
4612 trans_decode(Trans_elem_st
*trans
)
4614 if (trans
->disabled
) {
4615 (void) fprintf(stdout
, ": ");
4616 (void) fprintf(stdout
, MSGSTR(34,
4620 (void) fprintf(stdout
, MSGSTR(2133,
4621 ": Not receiving a signal"));
4623 if (trans
->lsr_fail
) {
4624 (void) fprintf(stdout
, MSGSTR(2134,
4632 * trans_messages() Display tranceiver status.
4634 * NOTE: The decoding of the status assumes that the elements
4635 * are in order with the first two elements are for the
4636 * "A" IB. It also assumes the tranceivers are numbered
4643 trans_messages(struct l_state_struct
*l_state
, int ib_a_flag
)
4645 Trans_elem_st trans
;
4650 /* Get and print messages */
4651 for (i
= 0; i
< (int)l_state
->ib_tbl
.config
.enc_num_elem
; i
++) {
4653 if (l_state
->ib_tbl
.config
.type_hdr
[i
].type
== ELM_TYP_FL
) {
4655 if (l_state
->ib_tbl
.config
.type_hdr
[i
].text_len
!= 0) {
4656 (void) fprintf(stdout
, "\n\t\t%s\n",
4657 l_state
->ib_tbl
.config
.text
[i
]);
4662 (int)l_state
->ib_tbl
.config
.type_hdr
[i
].num
; j
++) {
4664 * Only display the status for the selected IB.
4666 if ((count
< 2 && ib_a_flag
) ||
4667 (count
>= 2 && !ib_a_flag
)) {
4668 (void) bcopy((const void *)
4669 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
4670 (void *)&trans
, sizeof (trans
));
4673 (void) fprintf(stdout
, "\t\t%d ", k
);
4675 (void) fprintf(stdout
, "\n\t\t%d ", k
);
4677 if (trans
.code
== S_OK
) {
4678 (void) fprintf(stdout
,
4679 MSGSTR(29, "O.K."));
4680 revision_msg(l_state
, elem_index
+ j
);
4681 } else if ((trans
.code
== S_CRITICAL
) ||
4682 (trans
.code
== S_NONCRITICAL
)) {
4683 (void) fprintf(stdout
,
4684 MSGSTR(2135, "Failed"));
4685 revision_msg(l_state
, elem_index
+ j
);
4686 trans_decode(&trans
);
4687 } else if (trans
.code
== S_NOT_INSTALLED
) {
4688 (void) fprintf(stdout
,
4689 MSGSTR(30, "Not Installed"));
4690 } else if (trans
.code
== S_NOT_AVAILABLE
) {
4691 (void) fprintf(stdout
,
4692 MSGSTR(34, "Disabled"));
4693 revision_msg(l_state
, elem_index
+ j
);
4695 (void) fprintf(stdout
,
4696 MSGSTR(4, "Unknown status"));
4704 * Calculate the index to each element.
4706 elem_index
+= l_state
->ib_tbl
.config
.type_hdr
[i
].num
;
4708 (void) fprintf(stdout
, "\n");
4714 * temperature_messages() Display temperature status.
4720 temperature_messages(struct l_state_struct
*l_state
, int rear_flag
)
4723 int i
, j
, last_ok
= 0;
4727 /* Get and print messages */
4728 for (i
= 0; i
< (int)l_state
->ib_tbl
.config
.enc_num_elem
; i
++) {
4729 elem_index
++; /* skip global */
4730 if (l_state
->ib_tbl
.config
.type_hdr
[i
].type
== ELM_TYP_TS
) {
4732 rear_flag
= 1; /* only do front or rear backplane */
4733 if (l_state
->ib_tbl
.config
.type_hdr
[i
].text_len
!= 0) {
4734 (void) fprintf(stdout
, "\t %s",
4735 l_state
->ib_tbl
.config
.text
[i
]);
4739 * Check global status and if not all O.K.
4740 * then print individually.
4742 (void) bcopy((const void *)&l_state
->ib_tbl
.p2_s
.element
[i
],
4743 (void *)&temp
, sizeof (temp
));
4745 (int)l_state
->ib_tbl
.config
.type_hdr
[i
].num
; j
++) {
4746 (void) bcopy((const void *)
4747 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
4748 (void *)&temp
, sizeof (temp
));
4750 if ((j
== 0) && (temp
.code
== S_OK
) &&
4751 (!(temp
.ot_fail
|| temp
.ot_warn
||
4752 temp
.ut_fail
|| temp
.ut_warn
))) {
4753 (void) fprintf(stdout
, "\n\t %d", j
);
4754 } else if ((j
== 6) && (temp
.code
== S_OK
) &&
4756 (void) fprintf(stdout
, "\n\t %d", j
);
4757 } else if (last_ok
&& (temp
.code
== S_OK
)) {
4758 (void) fprintf(stdout
, "%d", j
);
4760 (void) fprintf(stdout
, "\n\t\t%d", j
);
4762 if (temp
.code
== S_OK
) {
4764 if (temp
.ot_fail
|| temp
.ot_warn
||
4765 temp
.ut_fail
|| temp
.ut_warn
) {
4772 } else if (temp
.code
== S_CRITICAL
) {
4773 (void) fprintf(stdout
,
4774 MSGSTR(122, "Critical failure"));
4777 } else if (temp
.code
== S_NONCRITICAL
) {
4778 (void) fprintf(stdout
,
4779 MSGSTR(89, "Non-Critical Failure"));
4782 } else if (temp
.code
== S_NOT_INSTALLED
) {
4783 (void) fprintf(stdout
,
4784 MSGSTR(30, "Not Installed"));
4787 } else if (temp
.code
== S_NOT_AVAILABLE
) {
4788 (void) fprintf(stdout
,
4789 MSGSTR(34, "Disabled"));
4793 (void) fprintf(stdout
,
4794 MSGSTR(4, "Unknown status"));
4800 (void) fprintf(stdout
,
4801 MSGSTR(2136, " (All temperatures are "
4805 (void) fprintf(stdout
, "\n");
4810 elem_index
+= l_state
->ib_tbl
.config
.type_hdr
[i
].num
;
4817 * ib_decode() Display IB byte 3 state.
4823 ib_decode(Ctlr_elem_st
*ctlr
)
4825 if (ctlr
->overtemp_alart
) {
4826 (void) fprintf(stdout
, MSGSTR(2137,
4827 " - IB Over Temperature Alert "));
4829 if (ctlr
->ib_loop_1_fail
) {
4830 (void) fprintf(stdout
, MSGSTR(2138,
4831 " - IB Loop 1 has failed "));
4833 if (ctlr
->ib_loop_0_fail
) {
4834 (void) fprintf(stdout
, MSGSTR(2139,
4835 " - IB Loop 0 has failed "));
4842 * mb_messages() Display motherboard
4843 * (interconnect assembly) messages.
4849 mb_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
4852 Interconnect_st interconnect
;
4854 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
4855 (void) fprintf(stdout
, "%s\n",
4856 l_state
->ib_tbl
.config
.text
[index
]);
4858 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
4860 (void) bcopy((const void *)
4861 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
4862 (void *)&interconnect
, sizeof (interconnect
));
4863 (void) fprintf(stdout
, "\t");
4865 if (interconnect
.code
== S_OK
) {
4866 (void) fprintf(stdout
,
4867 MSGSTR(29, "O.K."));
4868 revision_msg(l_state
, elem_index
+ j
);
4869 } else if (interconnect
.code
== S_NOT_INSTALLED
) {
4870 (void) fprintf(stdout
,
4871 MSGSTR(30, "Not Installed"));
4872 } else if (interconnect
.code
== S_CRITICAL
) {
4873 if (interconnect
.eprom_fail
!= NULL
) {
4874 (void) fprintf(stdout
, MSGSTR(2140,
4875 "Critical Failure: EEPROM failure"));
4877 (void) fprintf(stdout
, MSGSTR(2141,
4878 "Critical Failure: Unknown failure"));
4880 revision_msg(l_state
, elem_index
+ j
);
4881 } else if (interconnect
.code
== S_NONCRITICAL
) {
4882 if (interconnect
.eprom_fail
!= NULL
) {
4883 (void) fprintf(stdout
, MSGSTR(2142,
4884 "Non-Critical Failure: EEPROM failure"));
4886 (void) fprintf(stdout
, MSGSTR(2143,
4887 "Non-Critical Failure: Unknown failure"));
4889 revision_msg(l_state
, elem_index
+ j
);
4890 } else if (interconnect
.code
== S_NOT_AVAILABLE
) {
4891 (void) fprintf(stdout
,
4892 MSGSTR(34, "Disabled"));
4893 revision_msg(l_state
, elem_index
+ j
);
4895 (void) fprintf(stdout
,
4896 MSGSTR(4, "Unknown status"));
4898 (void) fprintf(stdout
, "\n");
4907 * back_plane_messages() Display back_plane messages
4908 * including the temperature's.
4914 back_plane_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
4918 char status_string
[MAXPATHLEN
];
4920 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
4921 (void) fprintf(stdout
, "%s\n",
4922 l_state
->ib_tbl
.config
.text
[index
]);
4924 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
4926 (void) bcopy((const void *)
4927 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
4928 (void *)&bp
, sizeof (bp
));
4930 (void) fprintf(stdout
,
4931 MSGSTR(2144, "\tFront Backplane: "));
4933 (void) fprintf(stdout
,
4934 MSGSTR(2145, "\tRear Backplane: "));
4937 (void) l_element_msg_string(bp
.code
, status_string
);
4938 (void) fprintf(stdout
, "%s", status_string
);
4940 if (bp
.code
!= S_NOT_INSTALLED
) {
4941 revision_msg(l_state
, elem_index
+ j
);
4942 if ((bp
.byp_a_enabled
|| bp
.en_bypass_a
) &&
4943 !(bp
.byp_b_enabled
|| bp
.en_bypass_b
)) {
4944 (void) fprintf(stdout
, " (");
4945 (void) fprintf(stdout
,
4946 MSGSTR(130, "Bypass A enabled"));
4947 (void) fprintf(stdout
, ")");
4948 } else if ((bp
.byp_b_enabled
|| bp
.en_bypass_b
) &&
4949 !(bp
.byp_a_enabled
|| bp
.en_bypass_a
)) {
4950 (void) fprintf(stdout
, " (");
4951 (void) fprintf(stdout
,
4952 MSGSTR(129, "Bypass B enabled"));
4953 (void) fprintf(stdout
, ")");
4954 /* This case covers where a and b are bypassed */
4955 } else if (bp
.byp_b_enabled
|| bp
.en_bypass_b
) {
4956 (void) fprintf(stdout
,
4957 MSGSTR(2146, " (Bypass's A & B enabled)"));
4959 (void) fprintf(stdout
, "\n");
4960 temperature_messages(l_state
, j
);
4962 (void) fprintf(stdout
, "\n");
4969 * dpm_SSC100_messages() Display SSC100 messages
4970 * including the temperature's.
4976 dpm_SSC100_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
4980 char status_string
[MAXPATHLEN
];
4982 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
4983 (void) fprintf(stdout
, "%s\n",
4984 l_state
->ib_tbl
.config
.text
[index
]);
4986 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
4988 (void) bcopy((const void *)
4989 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
4990 (void *)&bp
, sizeof (bp
));
4991 (void) fprintf(stdout
, MSGSTR(2246, " SSC100 #%d: "), j
);
4993 (void) l_element_msg_string(bp
.code
, status_string
);
4994 (void) fprintf(stdout
, "%s", status_string
);
4996 if (bp
.code
!= S_NOT_INSTALLED
) {
4997 revision_msg(l_state
, elem_index
+ j
);
4998 if ((bp
.byp_a_enabled
|| bp
.en_bypass_a
) &&
4999 !(bp
.byp_b_enabled
|| bp
.en_bypass_b
)) {
5000 (void) fprintf(stdout
, " (");
5001 (void) fprintf(stdout
,
5002 MSGSTR(130, "Bypass A enabled"));
5003 (void) fprintf(stdout
, ")");
5004 } else if ((bp
.byp_b_enabled
|| bp
.en_bypass_b
) &&
5005 !(bp
.byp_a_enabled
|| bp
.en_bypass_a
)) {
5006 (void) fprintf(stdout
, " (");
5007 (void) fprintf(stdout
,
5008 MSGSTR(129, "Bypass B enabled"));
5009 (void) fprintf(stdout
, ")");
5010 /* This case covers where a and b are bypassed */
5011 } else if (bp
.byp_b_enabled
|| bp
.en_bypass_b
) {
5012 (void) fprintf(stdout
,
5013 MSGSTR(2146, " (Bypass's A & B enabled)"));
5015 (void) fprintf(stdout
, "\n");
5017 (void) fprintf(stdout
, "\n");
5020 temperature_messages(l_state
, 0);
5027 * loop_messages() Display loop messages.
5033 loop_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
5038 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
5039 (void) fprintf(stdout
, "%s\n",
5040 l_state
->ib_tbl
.config
.text
[index
]);
5042 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
5044 (void) bcopy((const void *)
5045 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
5046 (void *)&loop
, sizeof (loop
));
5048 (void) fprintf(stdout
, "\t");
5050 if (loop
.code
== S_NOT_INSTALLED
) {
5051 (void) fprintf(stdout
,
5052 MSGSTR(2147, "Loop A is not installed"));
5055 (void) fprintf(stdout
, MSGSTR(2148,
5056 "Loop A is configured as two separate loops."));
5058 (void) fprintf(stdout
, MSGSTR(2149,
5059 "Loop A is configured as a single loop."));
5063 if (loop
.code
== S_NOT_INSTALLED
) {
5064 (void) fprintf(stdout
,
5065 MSGSTR(2150, "Loop B is not installed"));
5068 (void) fprintf(stdout
, MSGSTR(2151,
5069 "Loop B is configured as two separate loops."));
5071 (void) fprintf(stdout
, MSGSTR(2152,
5072 "Loop B is configured as a single loop."));
5076 (void) fprintf(stdout
, "\n");
5083 * ctlr_messages() Display ESI Controller status.
5089 ctlr_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
5095 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
5096 (void) fprintf(stdout
, "%s\n",
5097 l_state
->ib_tbl
.config
.text
[index
]);
5099 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
5101 (void) bcopy((const void *)
5102 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
5103 (void *)&ctlr
, sizeof (ctlr
));
5105 (void) fprintf(stdout
, MSGSTR(2153, "\tA: "));
5107 (void) fprintf(stdout
, MSGSTR(2154, "\tB: "));
5110 if (ctlr
.code
== S_OK
) {
5111 (void) fprintf(stdout
, MSGSTR(29, "O.K."));
5112 /* If any byte 3 bits set display */
5114 /* Display Version message */
5115 revision_msg(l_state
, elem_index
+ j
);
5117 * Display the tranciver module state for this
5120 trans_messages(l_state
, ib_a_flag
);
5121 } else if (ctlr
.code
== S_CRITICAL
) {
5122 (void) fprintf(stdout
,
5123 MSGSTR(122, "Critical failure"));
5125 (void) fprintf(stdout
, "\n");
5126 } else if (ctlr
.code
== S_NONCRITICAL
) {
5127 (void) fprintf(stdout
,
5128 MSGSTR(89, "Non-Critical Failure"));
5130 (void) fprintf(stdout
, "\n");
5131 } else if (ctlr
.code
== S_NOT_INSTALLED
) {
5132 (void) fprintf(stdout
,
5133 MSGSTR(30, "Not Installed"));
5134 (void) fprintf(stdout
, "\n");
5135 } else if (ctlr
.code
== S_NOT_AVAILABLE
) {
5136 (void) fprintf(stdout
,
5137 MSGSTR(34, "Disabled"));
5138 (void) fprintf(stdout
, "\n");
5140 (void) fprintf(stdout
,
5141 MSGSTR(4, "Unknown status"));
5142 (void) fprintf(stdout
, "\n");
5150 * fan_decode() Display Fans bytes 1-3 state.
5156 fan_decode(Fan_elem_st
*fan
)
5159 (void) fprintf(stdout
, MSGSTR(2155,
5160 ":Yellow LED is on"));
5162 if (fan
->speed
== 0) {
5163 (void) fprintf(stdout
, MSGSTR(2156,
5165 } else if (fan
->speed
< S_HI_SPEED
) {
5166 (void) fprintf(stdout
, MSGSTR(2157,
5169 (void) fprintf(stdout
, MSGSTR(2158,
5175 * fan_messages() Display Fan status.
5181 fan_messages(struct l_state_struct
*l_state
, int hdr_index
, int elem_index
)
5186 /* Get and print messages */
5187 if (l_state
->ib_tbl
.config
.type_hdr
[hdr_index
].text_len
!= 0) {
5188 (void) fprintf(stdout
, "%s\n",
5189 l_state
->ib_tbl
.config
.text
[hdr_index
]);
5191 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[hdr_index
].num
;
5193 (void) bcopy((const void *)
5194 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
5195 (void *)&fan
, sizeof (fan
));
5196 (void) fprintf(stdout
, "\t%d ", j
);
5197 if (fan
.code
== S_OK
) {
5198 (void) fprintf(stdout
, MSGSTR(29, "O.K."));
5199 revision_msg(l_state
, elem_index
+ j
);
5200 } else if (fan
.code
== S_CRITICAL
) {
5201 (void) fprintf(stdout
,
5202 MSGSTR(122, "Critical failure"));
5204 revision_msg(l_state
, elem_index
+ j
);
5205 } else if (fan
.code
== S_NONCRITICAL
) {
5206 (void) fprintf(stdout
,
5207 MSGSTR(89, "Non-Critical Failure"));
5209 revision_msg(l_state
, elem_index
+ j
);
5210 } else if (fan
.code
== S_NOT_INSTALLED
) {
5211 (void) fprintf(stdout
,
5212 MSGSTR(30, "Not Installed"));
5213 } else if (fan
.code
== S_NOT_AVAILABLE
) {
5214 (void) fprintf(stdout
,
5215 MSGSTR(34, "Disabled"));
5216 revision_msg(l_state
, elem_index
+ j
);
5218 (void) fprintf(stdout
,
5219 MSGSTR(4, "Unknown status"));
5222 (void) fprintf(stdout
, "\n");
5228 * ps_decode() Display Power Supply bytes 1-3 state.
5234 ps_decode(Ps_elem_st
*ps
)
5237 (void) fprintf(stdout
, MSGSTR(2159,
5238 ": DC Voltage too high"));
5241 (void) fprintf(stdout
, MSGSTR(2160,
5242 ": DC Voltage too low"));
5244 if (ps
->dc_over_i
) {
5245 (void) fprintf(stdout
, MSGSTR(2161,
5246 ": DC Current too high"));
5248 if (ps
->ovrtmp_fail
|| ps
->temp_warn
) {
5249 (void) fprintf(stdout
, MSGSTR(2162,
5250 ": Temperature too high"));
5253 (void) fprintf(stdout
, MSGSTR(2163,
5257 (void) fprintf(stdout
, MSGSTR(2164,
5265 * revision_msg() Print the revision message from page 7.
5271 revision_msg(struct l_state_struct
*l_state
, int index
)
5273 if (strlen((const char *)
5274 l_state
->ib_tbl
.p7_s
.element_desc
[index
].desc_string
)) {
5275 (void) fprintf(stdout
, "(%s)",
5276 l_state
->ib_tbl
.p7_s
.element_desc
[index
].desc_string
);
5283 * ps_messages() Display Power Supply status.
5289 ps_messages(struct l_state_struct
*l_state
, int index
, int elem_index
)
5294 /* Get and print Power Supply messages */
5296 if (l_state
->ib_tbl
.config
.type_hdr
[index
].text_len
!= 0) {
5297 (void) fprintf(stdout
, "%s\n",
5298 l_state
->ib_tbl
.config
.text
[index
]);
5301 for (j
= 0; j
< (int)l_state
->ib_tbl
.config
.type_hdr
[index
].num
;
5303 (void) bcopy((const void *)
5304 &l_state
->ib_tbl
.p2_s
.element
[elem_index
+ j
],
5305 (void *)&ps
, sizeof (ps
));
5306 (void) fprintf(stdout
, "\t%d ", j
);
5307 if (ps
.code
== S_OK
) {
5308 (void) fprintf(stdout
, MSGSTR(29, "O.K."));
5309 revision_msg(l_state
, elem_index
+ j
);
5310 } else if (ps
.code
== S_CRITICAL
) {
5311 (void) fprintf(stdout
,
5312 MSGSTR(122, "Critical failure"));
5314 revision_msg(l_state
, elem_index
+ j
);
5315 } else if (ps
.code
== S_NONCRITICAL
) {
5316 (void) fprintf(stdout
,
5317 MSGSTR(89, "Non-Critical Failure"));
5319 revision_msg(l_state
, elem_index
+ j
);
5320 } else if (ps
.code
== S_NOT_INSTALLED
) {
5321 (void) fprintf(stdout
,
5322 MSGSTR(30, "Not Installed"));
5323 } else if (ps
.code
== S_NOT_AVAILABLE
) {
5324 (void) fprintf(stdout
,
5325 MSGSTR(34, "Disabled"));
5326 revision_msg(l_state
, elem_index
+ j
);
5328 (void) fprintf(stdout
,
5329 MSGSTR(4, "Unknown status"));
5333 (void) fprintf(stdout
, "\n");
5339 * abnormal_condition() Display any abnormal condition messages.
5345 abnormal_condition_display(struct l_state_struct
*l_state
)
5348 (void) fprintf(stdout
, "\n");
5349 if (l_state
->ib_tbl
.p2_s
.ui
.crit
) {
5350 (void) fprintf(stdout
,
5352 "CRITICAL CONDITION DETECTED\n"));
5354 if (l_state
->ib_tbl
.p2_s
.ui
.non_crit
) {
5355 (void) fprintf(stdout
,
5357 "WARNING: NON-CRITICAL CONDITION DETECTED\n"));
5359 if (l_state
->ib_tbl
.p2_s
.ui
.invop
) {
5360 (void) fprintf(stdout
,
5362 "WARNING: Invalid Operation bit set.\n"
5363 "\tThis means an Enclosure Control page"
5364 " or an Array Control page with an invalid\n"
5365 "\tformat has previously been transmitted to the"
5366 " Enclosure Services card by a\n\tSend Diagnostic"
5367 " SCSI command.\n"));
5369 (void) fprintf(stdout
, "\n");
5377 * adm_start() Spin up the given list
5384 adm_start(char **argv
)
5386 char *path_phys
= NULL
;
5387 Path_struct
*path_struct
;
5388 int err
= 0, retval
= 0;
5390 while (*argv
!= NULL
) {
5391 if ((err
= l_convert_name(*argv
, &path_phys
,
5392 &path_struct
, Options
& PVERBOSE
)) != 0) {
5393 (void) fprintf(stderr
, MSGSTR(33,
5394 " Error: converting"
5395 " %s to physical path.\n"
5396 " Invalid pathname.\n"),
5399 (void) print_errString(err
, *argv
);
5405 VERBPRINT(MSGSTR(101, "Issuing start to:\n %s\n"), *argv
);
5406 if (err
= g_start(path_phys
)) {
5407 (void) print_errString(err
, *argv
);
5420 * adm_stop() Spin down a
5421 * given list of SENA devices.
5427 adm_stop(char **argv
)
5429 char *path_phys
= NULL
;
5430 Path_struct
*path_struct
;
5431 int err
= 0, retval
= 0;
5433 while (*argv
!= NULL
) {
5434 if ((err
= l_convert_name(*argv
, &path_phys
,
5435 &path_struct
, Options
& PVERBOSE
)) != 0) {
5436 (void) fprintf(stderr
,
5438 " Error: converting"
5439 " %s to physical path.\n"
5440 " Invalid pathname.\n"),
5443 (void) print_errString(err
, *argv
);
5451 * scsi stop is not supported for tape drives.
5452 * The scsi unload op code for tape is the same as a
5453 * scsi stop for disk so this command will eject the tape.
5454 * If an eject is the desired behavior then remove the
5455 * following if block. ('mt offline' will give you
5456 * the same eject functionality).
5458 if (strstr(path_phys
, SLSH_DRV_NAME_ST
)) {
5460 (void) print_errString(0, path_phys
);
5465 VERBPRINT(MSGSTR(100, "Issuing stop to:\n %s\n"), *argv
);
5466 if (err
= g_stop(path_phys
, 1)) {
5467 (void) print_errString(err
, *argv
);
5479 * On a SOC+ chip, the port is either put into (offline) or pulled out
5480 * of (online) a loopback mode since the laser cannot be turned on or off.
5481 * As of this writing, this feature is yet to be supported by the ifp
5482 * driver on a QLogic card.
5485 * Command line args and flag - LUX_P_ONLINE or LUX_P_OFFLINE
5486 * The path that is passed has to be the physical path to the port.
5488 * /devices/sbus@2,0/SUNW,socal@2,0:0
5489 * /devices/io-unit@f,e0200000/sbi@0,0/SUNW,socal@2,0:0
5490 * /devices/pci@1f,4000/SUNW,ifp@2:devctl
5495 adm_port_offline_online(char *argv
[], int flag
)
5497 int err
, retval
= 0;
5498 char *path_phys
= NULL
;
5499 char *nexus_path_ptr
= NULL
;
5500 Path_struct
*path_struct
= NULL
;
5502 while (*argv
!= NULL
) {
5503 if ((err
= l_convert_name(*argv
, &path_phys
,
5504 &path_struct
, Options
& PVERBOSE
)) != 0) {
5505 (void) fprintf(stderr
,
5507 " Error: converting"
5508 " %s to physical path.\n"
5509 " Invalid pathname.\n"),
5512 (void) print_errString(err
, *argv
);
5519 /* Get the nexus path - need this to print messages */
5520 if ((err
= g_get_nexus_path(path_phys
, &nexus_path_ptr
)) != 0) {
5521 (void) print_errString(err
, *argv
);
5523 goto cleanup_and_go
;
5526 if (flag
== LUX_P_OFFLINE
) {
5527 if ((err
= g_port_offline(nexus_path_ptr
))) {
5528 (void) print_errString(err
, nexus_path_ptr
);
5530 goto cleanup_and_go
;
5533 MSGSTR(2223, "Port %s has been disabled\n"),
5535 } else if (flag
== LUX_P_ONLINE
) {
5536 if ((err
= g_port_online(nexus_path_ptr
))) {
5537 (void) print_errString(err
, nexus_path_ptr
);
5539 goto cleanup_and_go
;
5542 MSGSTR(2224, "Port %s has been enabled\n"),
5545 (void) fprintf(stderr
,
5547 "Unknown action requested "
5548 "on port - %d\nIgnoring."),
5555 free(nexus_path_ptr
);
5562 * Expert level subcommand 'luxadm -e port'
5563 * which displays all FC ports on a host and state information for
5564 * connectivity (CONNECTED or NOT CONNECTED) indicating whether there
5565 * are devices attached to the port.
5567 * Sample output for ifp:
5569 * /devices/pci@1f,4000/SUNW,ifp@2:devctl CONNECTED
5570 * /devices/pci@1f,2000/SUNW,ifp@1:devctl NOT CONNECTED
5572 * Sample output for socal:
5574 * /devices/sbus@2,0/SUNW,socal@d,10000:0 CONNECTED
5575 * /devices/sbus@2,0/SUNW,socal@d,10000:1 NOT CONNECTED
5576 * /devices/sbus@2,0/SUNW,socal@2,0:0 NOT CONNECTED
5577 * /devices/sbus@2,0/SUNW,socal@2,0:1 CONNECTED
5579 * Note: for socal the path returned is not a devctl path as there is no
5580 * devctl path for socal.
5582 * Sample output for fp:
5584 * /devices/sbus@2,0/SUNW,qlc@5/fp@0,0:devctl CONNECTED
5585 * /devices/sbus@2,0/SUNW,qlc@4/fp@1,0:devctl CONNECTED
5588 adm_display_port(int verbose
)
5591 * If another port driver needs to be searched, add it here
5593 static char *portdrvr_list
[] = {"socal",
5597 portlist_t portlist
;
5598 int x
= 0, err
= 0, retval
= 0;
5601 portlist
.hbacnt
= 0;
5604 * Look for all HBA ports as listed in portdrvr_list[]
5606 while (portdrvr_list
[x
]) {
5607 if (err
= g_get_port_path(portdrvr_list
[x
], &portlist
)) {
5608 if (err
!= L_PORT_DRIVER_NOT_FOUND
&&
5609 err
!= L_PHYS_PATH_NOT_FOUND
) {
5610 (void) print_errString(err
, portdrvr_list
[x
]);
5619 * For each port path found get the connection state.
5620 * If there are devices attached the state is considered connected.
5622 for (x
= 0; x
< portlist
.hbacnt
; x
++) {
5623 if (err
= g_get_port_state(portlist
.physpath
[x
],
5624 &port_state
, verbose
)) {
5625 (void) print_errString(err
, portlist
.physpath
[x
]);
5628 fprintf(stdout
, "%-65s ", portlist
.physpath
[x
]);
5629 if (port_state
== PORT_CONNECTED
) {
5630 (void) fprintf(stdout
,
5634 (void) fprintf(stdout
,
5636 "NOT CONNECTED\n"));
5640 g_free_portlist(&portlist
);
5645 * Expert level subcommand 'luxadm -e external_loopback <portpath>
5648 * Does just what you would think. Sets port in designated loopback
5650 * INPUT: portpath - path to device on which to set loopback mode
5651 * flag - loopback mode to set. Values are:
5656 * RETURN: 0 on success
5657 * non-zero on failure
5660 adm_port_loopback(char *portpath
, int flag
)
5663 char *path_phys
= NULL
;
5664 Path_struct
*path_struct
= NULL
;
5667 if ((err
= l_convert_name(portpath
, &path_phys
,
5668 &path_struct
, Options
& PVERBOSE
)) != 0) {
5669 (void) fprintf(stderr
,
5671 " Error: converting"
5672 " %s to physical path.\n"
5673 " Invalid pathname.\n"),
5676 (void) print_errString(err
, portpath
);
5692 (void) fprintf(stderr
,
5694 "Unknown action requested "
5695 "on port - %d\nIgnoring."),
5703 if ((err
= g_loopback_mode(path_phys
, cmd
)) != 0) {
5704 (void) print_errString(err
, portpath
);
5711 (void) fprintf(stdout
,
5713 "External loopback mode set "
5718 (void) fprintf(stdout
,
5720 "Internal loopback mode set "
5725 (void) fprintf(stdout
,
5727 "Loopback mode unset "
5733 MSGSTR(2248, "Undefined command\n"));
5745 * To print the pathlist and mpxio path attributes
5748 adm_print_pathlist(char *dev_path
)
5751 mp_pathlist_t pathlist
;
5753 char temppath
[MAXPATHLEN
];
5754 char wwns
[(WWN_SIZE
*2) +1];
5755 uchar_t wwn_data
[WWN_SIZE
];
5757 int state
, ext_state
= 0;
5758 char *path_state
[5];
5760 path_state
[0] = MSGSTR(2400, "INIT");
5761 path_state
[1] = MSGSTR(2401, "ONLINE");
5762 path_state
[2] = MSGSTR(2402, "STANDBY");
5763 path_state
[3] = MSGSTR(2403, "FAULT");
5764 path_state
[4] = MSGSTR(2404, "OFFLINE");
5766 (void) strcpy(temppath
, dev_path
);
5767 retval
= g_get_pathlist(temppath
, &pathlist
);
5769 (void) print_errString(retval
, NULL
);
5772 pathcnt
= pathlist
.path_count
;
5773 for (i
= 0; i
< pathcnt
; i
++) {
5774 (void) fprintf(stdout
,
5775 MSGSTR(2303, " Controller \t%s\n"),
5776 pathlist
.path_info
[i
].path_hba
);
5778 (void) fprintf(stdout
,
5779 MSGSTR(2304, " Device Address\t\t%s\n"),
5780 pathlist
.path_info
[i
].path_addr
);
5782 if ((err
= get_host_controller_pwwn(
5783 pathlist
.path_info
[i
].path_hba
,
5784 (uchar_t
*)&wwn_data
)) != 0) {
5785 if (err
!= ENOTSUP
) {
5786 (void) print_errString(err
,
5787 pathlist
.path_info
[i
].path_hba
);
5793 copy_wwn_data_to_str(wwns
, wwn_data
);
5794 (void) fprintf(stdout
,
5795 MSGSTR(2326, " Host controller port WWN\t%s\n"),
5799 (void) fprintf(stdout
,
5800 MSGSTR(2305, " Class\t\t\t%s\n"),
5801 pathlist
.path_info
[i
].path_class
);
5802 if (pathlist
.path_info
[i
].path_state
< MAXPATHSTATE
) {
5803 (void) fprintf(stdout
,
5804 MSGSTR(2306, " State\t\t\t%s\n"),
5805 path_state
[pathlist
.path_info
[i
].path_state
]);
5807 if ((err
= g_stms_get_path_state(dev_path
,
5808 pathlist
.path_info
[i
].path_hba
, &state
,
5809 &ext_state
)) != 0) {
5810 (void) print_errString(err
,
5811 pathlist
.path_info
[i
].path_hba
);
5814 if ((ext_state
& MDI_PATHINFO_STATE_USER_DISABLE
)
5815 == MDI_PATHINFO_STATE_USER_DISABLE
) {
5819 " I/Os disabled on this %s path\n\n"),
5820 path_state
[pathlist
.path_info
[i
].path_state
]);
5824 /* Free memory for per path info properties */
5825 free(pathlist
.path_info
);
5830 * compares path with all paths in pathlist
5831 * If there is a match, 0 is returned, otherwise 1 is returned
5834 compare_multipath(char *path
, struct mplist_struct
*pathlist
)
5837 while (pathlist
!= NULL
) {
5838 if (strncmp(path
, pathlist
->devpath
, MAXPATHLEN
) == 0) {
5841 pathlist
= pathlist
->next
;
5847 * lun_display() Prints the
5848 * information for an individual lun.
5854 lun_display(Path_struct
*path_struct
, L_inquiry inq_struct
, int verbose
)
5857 char phys_path
[MAXPATHLEN
], last_logical_path
[MAXPATHLEN
];
5858 uchar_t
*pg_buf
= NULL
;
5859 L_disk_state l_disk_state
;
5860 struct dlist
*mlist
;
5861 int offset
, mode_data_avail
, err
= 0;
5862 Mode_header_10
*mode_header_ptr
;
5863 struct mode_page
*pg_hdr
;
5864 WWN_list
*wwn_list
, *list_start
, *wwn_list_ptr
;
5865 WWN_list
*wwn_list_find
;
5867 int argpwwn
= 0, argnwwn
= 0;
5868 struct mplist_struct
*mplistp
, *mpl
, *mpln
;
5869 struct dlist
*dlist
;
5873 strcpy(phys_path
, path_struct
->p_physical_path
);
5874 strcpy(last_logical_path
, phys_path
);
5876 mplistp
= mpl
= mpln
= NULL
;
5878 * Get path to all the FC disk and tape devices.
5879 * If there is no slash in the argument in this routine, we assume
5880 * it is a wwn argument.
5882 if (strstr(path_struct
->argv
, "/") != NULL
) {
5883 if ((err
= g_devices_get_all(&wwn_list
)) != 0) {
5887 if ((err
= g_get_wwn_list(&wwn_list
, verbose
)) != 0) {
5892 g_sort_wwn_list(&wwn_list
);
5894 list_start
= wwn_list
;
5896 for (wwn_list_ptr
= wwn_list
; wwn_list_ptr
!= NULL
;
5897 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
5898 if (strcasecmp(wwn_list_ptr
->port_wwn_s
,
5899 path_struct
->argv
) == 0) {
5900 list_start
= wwn_list_ptr
;
5903 } else if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
5904 path_struct
->argv
) == 0) {
5905 list_start
= wwn_list_ptr
;
5911 for (wwn_list_ptr
= list_start
; wwn_list_ptr
!= NULL
;
5912 wwn_list_ptr
= wwn_list_ptr
->wwn_next
) {
5916 if (strcasecmp(wwn_list_ptr
->port_wwn_s
,
5917 path_struct
->argv
) != 0) {
5920 (void) strcpy(phys_path
, wwn_list_ptr
->physical_path
);
5921 } else if (argnwwn
) {
5922 if (strstr(wwn_list_ptr
->logical_path
,
5923 last_logical_path
) != NULL
) {
5926 if (strcasecmp(wwn_list_ptr
->node_wwn_s
,
5927 path_struct
->argv
) != 0) {
5930 (void) strcpy(phys_path
, wwn_list_ptr
->physical_path
);
5931 (void) strcpy(last_logical_path
,
5932 wwn_list_ptr
->logical_path
);
5935 if (argnwwn
|| argpwwn
) {
5936 if (compare_multipath(wwn_list_ptr
->logical_path
,
5942 mode_data_avail
= 0;
5944 (void) memset(&l_disk_state
, 0, sizeof (struct l_disk_state_struct
));
5947 * Don't call g_get_multipath if this is a SCSI_VHCI device
5948 * dlist gets alloc'ed here to retain the free at the end
5950 if (strstr(phys_path
, SCSI_VHCI
) == NULL
) {
5951 if ((err
= g_get_multipath(phys_path
,
5952 &(l_disk_state
.g_disk_state
.multipath_list
),
5953 wwn_list
, verbose
)) != 0) {
5957 mlist
= l_disk_state
.g_disk_state
.multipath_list
;
5958 if (mlist
== NULL
) {
5959 l_disk_state
.l_state_flag
= L_NO_PATH_FOUND
;
5960 N_DPRINTF(" lun_display: Error finding"
5961 " multiple paths to the disk.\n");
5962 (void) g_free_wwn_list(&wwn_list
);
5963 return (L_NO_VALID_PATH
);
5966 /* Search for match on physical path name */
5967 for (wwn_list_find
= list_start
; wwn_list_find
!= NULL
;
5968 wwn_list_find
= wwn_list_find
->wwn_next
) {
5969 if (strncmp(wwn_list_find
->physical_path
, phys_path
,
5970 strlen(wwn_list_find
->physical_path
))
5978 return (L_NO_VALID_PATH
);
5983 if ((dlist
= (struct dlist
*)
5984 calloc(1, sizeof (struct dlist
))) == NULL
) {
5985 return (L_MALLOC_FAILED
);
5987 if ((dlist
->logical_path
= (char *)calloc(1,
5988 strlen(wwn_list_find
->logical_path
) + 1)) == NULL
) {
5989 return (L_MALLOC_FAILED
);
5991 if ((dlist
->dev_path
= (char *)calloc(1,
5992 strlen(phys_path
) + 1)) == NULL
) {
5993 return (L_MALLOC_FAILED
);
5995 strncpy(dlist
->logical_path
, wwn_list_find
->logical_path
,
5996 strlen(wwn_list_find
->logical_path
));
5997 strncpy(dlist
->dev_path
, phys_path
, strlen(phys_path
));
5998 l_disk_state
.g_disk_state
.multipath_list
= dlist
;
6001 if (argnwwn
|| argpwwn
) {
6002 for (mlist
= l_disk_state
.g_disk_state
.multipath_list
;
6003 mlist
!= NULL
; mlist
= mlist
->next
) {
6004 /* add the path to the list for compare */
6005 if ((mpl
= (struct mplist_struct
*)
6006 calloc(1, sizeof (struct mplist_struct
)))
6008 adm_mplist_free(mplistp
);
6009 return (L_MALLOC_FAILED
);
6012 mpl
->devpath
= (char *)calloc(1, MAXPATHLEN
+1);
6013 if (mpl
->devpath
== NULL
) {
6014 adm_mplist_free(mplistp
);
6015 return (L_MALLOC_FAILED
);
6017 strncpy(mpl
->devpath
, mlist
->logical_path
,
6018 strlen(mlist
->logical_path
));
6019 if (mplistp
== NULL
) {
6020 mplistp
= mpln
= mpl
;
6028 /* get mode page information for FC device */
6029 if (l_get_mode_pg(phys_path
, &pg_buf
, verbose
) == 0) {
6030 mode_header_ptr
= (struct mode_header_10_struct
*)
6032 offset
= sizeof (struct mode_header_10_struct
) +
6033 mode_header_ptr
->bdesc_length
;
6034 pg_hdr
= (struct mode_page
*)&pg_buf
[offset
];
6036 while (offset
< (mode_header_ptr
->length
+
6037 sizeof (mode_header_ptr
->length
)) &&
6039 if (pg_hdr
->code
== MODEPAGE_CACHING
) {
6043 offset
+= pg_hdr
->length
+ sizeof (struct mode_page
);
6044 pg_hdr
= (struct mode_page
*)&pg_buf
[offset
];
6048 switch ((inq_struct
.inq_dtype
& DTYPE_MASK
)) {
6050 fprintf(stdout
, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
6053 case DTYPE_SEQUENTIAL
: /* Tape */
6054 fprintf(stdout
, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
6058 fprintf(stdout
, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
6063 (void) display_lun_info(l_disk_state
, path_struct
, pg_hdr
,
6064 mode_data_avail
, wwn_list
, phys_path
);
6066 (void) g_free_multipath(l_disk_state
.g_disk_state
.multipath_list
);
6068 if (!(argpwwn
|| argnwwn
)) {
6072 } /* End for wwn_list_ptr = list_start... */
6074 (void) g_free_wwn_list(&wwn_list
);
6075 adm_mplist_free(mplistp
);
6080 * display_lun_info() Prints the device specific information
6087 display_lun_info(L_disk_state l_disk_state
, Path_struct
*path_struct
,
6088 struct mode_page
*pg_hdr
, int mode_data_avail
, WWN_list
6089 *wwn_list
, char *phys_path
)
6092 struct scsi_capacity_16 cap_data
;
6093 struct dlist
*mlist
;
6094 struct my_mode_caching
*pg8_buf
;
6097 hrtime_t start_time
, end_time
;
6099 int peripheral_qual
;
6101 size_t serial_len
= sizeof (inq80
.inq_serial
);
6103 if ((envdb
= getenv("_LUX_T_DEBUG")) != NULL
) {
6104 start_time
= gethrtime();
6107 memset(&cap_data
, 0, sizeof (cap_data
));
6109 if (err
= g_get_inquiry(phys_path
, &inq
)) {
6110 fprintf(stderr
, "\n");
6111 print_errString(err
, phys_path
);
6112 fprintf(stderr
, "\n");
6116 if (err
= g_get_serial_number(phys_path
, inq80
.inq_serial
,
6118 fprintf(stderr
, "\n");
6119 print_errString(err
, phys_path
);
6120 fprintf(stderr
, "\n");
6124 * check to see if the peripheral qualifier is zero
6125 * if it is non-zero, we will return with an error.
6127 peripheral_qual
= inq
.inq_dtype
& ~DTYPE_MASK
;
6128 if (peripheral_qual
!= DPQ_POSSIBLE
) {
6129 fprintf(stderr
, MSGSTR(2254, "\n Error: Logical Unit "
6130 "(%s) is not available.\n"), phys_path
);
6134 fprintf(stdout
, " ");
6135 fprintf(stdout
, MSGSTR(3, "Vendor:"));
6136 fprintf(stdout
, "\t\t");
6137 print_chars(inq
.inq_vid
, sizeof (inq
.inq_vid
), 0);
6138 fprintf(stdout
, MSGSTR(2115, "\n Product ID:\t\t"));
6139 print_chars(inq
.inq_pid
, sizeof (inq
.inq_pid
), 0);
6141 fprintf(stdout
, "\n ");
6142 fprintf(stdout
, MSGSTR(2119, "Revision:"));
6143 fprintf(stdout
, "\t\t");
6144 print_chars(inq
.inq_revision
, sizeof (inq
.inq_revision
), 0);
6146 fprintf(stdout
, "\n ");
6147 fprintf(stdout
, MSGSTR(17, "Serial Num:"));
6148 fprintf(stdout
, "\t\t");
6149 print_chars(inq80
.inq_serial
, serial_len
, 0);
6151 if ((inq
.inq_dtype
& DTYPE_MASK
) == DTYPE_DIRECT
) {
6152 if ((err
= get_lun_capacity(phys_path
, &cap_data
)) != 0) {
6153 print_errString(err
, phys_path
);
6157 if (cap_data
.sc_capacity
> 0 && cap_data
.sc_lbasize
> 0) {
6158 lunMbytes
= cap_data
.sc_capacity
+ 1;
6159 lunMbytes
*= cap_data
.sc_lbasize
;
6160 lunMbytes
/= (float)(1024*1024);
6161 fprintf(stdout
, "\n ");
6162 fprintf(stdout
, MSGSTR(60,
6163 "Unformatted capacity:\t%6.3f MBytes"), lunMbytes
);
6167 fprintf(stdout
, "\n");
6169 if ((mode_data_avail
) && (pg_hdr
->code
== MODEPAGE_CACHING
)) {
6170 pg8_buf
= (struct my_mode_caching
*)(void *)pg_hdr
;
6172 fprintf(stdout
, MSGSTR(2122, " Write Cache:\t\t"
6175 if (pg8_buf
->rcd
== 0) {
6176 fprintf(stdout
, MSGSTR(2123, " Read Cache:\t\t"
6178 fprintf(stdout
, MSGSTR(2124, " Minimum prefetch:"
6179 "\t0x%x\n Maximum prefetch:\t0x%x\n"),
6180 pg8_buf
->min_prefetch
,
6181 pg8_buf
->max_prefetch
);
6185 fprintf(stdout
, " %s\t\t%s\n", MSGSTR(35, "Device Type:"),
6186 dtype
[inq
.inq_dtype
& DTYPE_MASK
]);
6189 fprintf(stdout
, MSGSTR(2128, " Path(s):\n"));
6190 fprintf(stdout
, "\n");
6192 if ((mlist
= l_disk_state
.g_disk_state
.multipath_list
) == NULL
) {
6193 fprintf(stderr
, MSGSTR(2323, "Error: No paths found (%s)"),
6199 if (strstr(mlist
->dev_path
, SCSI_VHCI
) != NULL
) {
6200 fprintf(stdout
, " %s\n %s\n",
6201 mlist
->logical_path
, mlist
->dev_path
);
6202 adm_print_pathlist(mlist
->dev_path
);
6205 * first display user's requested path
6206 * This will avoid duplicate inquiries as well
6208 for (mlist
= l_disk_state
.g_disk_state
.multipath_list
;
6209 mlist
!= NULL
; mlist
= mlist
->next
) {
6210 if ((strcmp(mlist
->dev_path
, path_struct
->p_physical_path
))
6212 display_path_info(mlist
->dev_path
, mlist
->logical_path
,
6219 * Now display rest of paths
6220 * skipping one already displayed
6222 for (mlist
= l_disk_state
.g_disk_state
.multipath_list
;
6223 mlist
!= NULL
; mlist
= mlist
->next
) {
6224 if ((strcmp(mlist
->dev_path
, path_struct
->p_physical_path
))
6228 if (err
= g_get_inquiry(mlist
->dev_path
, &inq
)) {
6229 fprintf(stderr
, "\n");
6230 print_errString(err
, mlist
->dev_path
);
6231 fprintf(stderr
, "\n");
6234 display_path_info(mlist
->dev_path
, mlist
->logical_path
,
6238 fprintf(stdout
, "\n");
6240 if (envdb
!= NULL
) {
6241 end_time
= gethrtime();
6242 fprintf(stdout
, " display_lun_info: "
6243 "\t\tTime = %lld millisec\n",
6244 (end_time
- start_time
)/1000000);
6249 * display_path_info() Prints the path specific information
6251 * Note: Only applies to ssd nodes currently
6257 display_path_info(char *devpath
, char *logicalpath
, WWN_list
*wwn_list
)
6259 WWN_list
*wwn_list_walk
;
6261 uchar_t wwn_data
[WWN_SIZE
];
6262 char wwns
[(WWN_SIZE
*2) +1];
6263 char drvr_path
[MAXPATHLEN
];
6267 fprintf(stdout
, " %s\n", logicalpath
);
6268 fprintf(stdout
, " %s\n", devpath
);
6269 fprintf(stdout
, " %s\t\t", MSGSTR(2321, "LUN path port WWN:"));
6272 * Walk the wwn list passed in and print the
6273 * port wwn matching the device path
6275 for (wwn_list_walk
= wwn_list
; wwn_list_walk
!= NULL
;
6276 wwn_list_walk
= wwn_list_walk
->wwn_next
) {
6277 if (strcmp(wwn_list_walk
->physical_path
, devpath
) == 0) {
6278 fprintf(stdout
, "%s", wwn_list_walk
->port_wwn_s
);
6283 * newline here in case port wwn not found
6285 fprintf(stdout
, "\n");
6287 drvr_path
[0] = '\0';
6288 (void) strcat(drvr_path
, devpath
);
6289 if (((cptr
= strstr(drvr_path
, SLSH_DRV_NAME_SSD
)) != NULL
) ||
6290 ((cptr
= strstr(drvr_path
, SLSH_DRV_NAME_ST
)) != NULL
)) {;
6293 fprintf(stderr
, MSGSTR(2324, "Error: Incorrect path (%s)\n"),
6299 if ((err
= get_host_controller_pwwn(drvr_path
,
6300 (uchar_t
*)&wwn_data
)) != 0) {
6301 print_errString(err
, drvr_path
);
6305 copy_wwn_data_to_str(wwns
, wwn_data
);
6306 fprintf(stdout
, " %s\t%s\n",
6307 MSGSTR(2322, "Host controller port WWN:"), wwns
);
6310 * Determine path status
6312 if ((err
= get_path_status(devpath
, &status
)) != 0) {
6313 print_errString(err
, devpath
);
6316 fprintf(stdout
, " %s\t\t", MSGSTR(2329, "Path status:"));
6317 display_port_status(status
);
6322 * Retrieves the lun capacity
6325 get_lun_capacity(char *devpath
, struct scsi_capacity_16
*cap_data
)
6329 if (devpath
== NULL
|| cap_data
== NULL
) {
6330 return (L_INVALID_PATH
);
6333 if ((fd
= g_object_open(devpath
, O_RDONLY
| O_NDELAY
)) == -1) {
6334 return (L_OPEN_PATH_FAIL
);
6336 (void) g_scsi_read_capacity_1016_cmd(fd
, cap_data
,
6337 sizeof (struct scsi_capacity_16
));
6344 * Retrieves the reservation status
6347 get_path_status(char *devpath
, int *status
)
6349 int fd
, mystatus
= 0;
6352 if (devpath
== NULL
|| status
== NULL
) {
6353 return (L_INVALID_PATH
);
6357 if ((fd
= g_object_open(devpath
, O_RDONLY
| O_NDELAY
)) == -1) {
6358 return (L_OPEN_PATH_FAIL
);
6360 if ((mystatus
= g_scsi_tur(fd
)) != 0) {
6361 if ((mystatus
& L_SCSI_ERROR
) &&
6362 ((mystatus
& ~L_SCSI_ERROR
) == STATUS_CHECK
)) {
6363 *status
= L_NOT_READY
;
6364 } else if ((mystatus
& L_SCSI_ERROR
) &&
6365 ((mystatus
& ~L_SCSI_ERROR
) ==
6366 STATUS_RESERVATION_CONFLICT
)) {
6367 *status
= L_RESERVED
;
6369 *status
= L_SCSI_ERR
;
6379 * Retrieves the port wwn associated with the hba node
6381 * hba_path: /devices/pci@8,600000/SUNW,qlc@4/fp@0,0
6382 * pwwn: ptr to a uchar_t array of size WWN_SIZE
6385 get_host_controller_pwwn(char *hba_path
, uchar_t
*pwwn
)
6387 char *cptr
, *portptr
;
6388 int found
= 0, err
, devlen
;
6389 char my_hba_path
[MAXPATHLEN
];
6391 di_prom_prop_t promprop
;
6392 uchar_t
*port_wwn_data
= NULL
;
6394 di_prom_handle_t ph
;
6398 fc_port_dev_t hba_port
;
6400 if (hba_path
== NULL
|| pwwn
== NULL
) {
6401 return (L_INVALID_PATH
);
6404 if ((path_type
= g_get_path_type(hba_path
)) == 0) {
6405 return (L_INVALID_PATH
);
6409 * ifp nodes do not have a port-wwn prom property
6410 * so handle them via FC4 device map
6412 if (path_type
& FC4_XPORT_MASK
) {
6413 return (get_FC4_host_controller_pwwn(hba_path
, pwwn
));
6414 /* For Leadville path get the port wwn through g_get_host param. */
6415 } else if ((path_type
& FC_GEN_XPORT
) &&
6416 ((path_type
& FC_FCA_MASK
) == FC_FCA_MASK
)) {
6418 * For Leadville path, get the port wwn through
6419 * g_get_host param. This is a general solution
6420 * to support 3rd party vendor Leadville FCA.
6422 my_hba_path
[0] = '\0';
6423 (void) strlcat(my_hba_path
, hba_path
, sizeof (my_hba_path
));
6424 (void) snprintf(my_hba_path
, sizeof (my_hba_path
), "%s%s",
6426 if ((err
= g_get_host_params(
6427 my_hba_path
, &hba_port
, 0)) != 0) {
6430 (void) memcpy(pwwn
, &hba_port
.dev_pwwn
.raw_wwn
[0],
6434 } else if ((path_type
& FC_FCA_MASK
) == FC_PCI_FCA
) {
6436 * Get port WWN through prom property
6438 my_hba_path
[0] = '\0';
6439 (void) strlcat(my_hba_path
, hba_path
, sizeof (my_hba_path
));
6441 * sanity check for /devices mount point
6443 if (strlen(my_hba_path
) > (devlen
= strlen("/devices"))) {
6444 cptr
= &my_hba_path
[devlen
];
6446 return (L_INVALID_PATH
);
6450 * Now strip off the trailing "/fp@"
6452 if ((portptr
= strstr(cptr
, "/fp@")) != NULL
) {
6456 if ((node
= di_init(cptr
, DINFOCPYALL
)) == DI_NODE_NIL
) {
6457 return (L_DEV_SNAPSHOT_FAILED
);
6460 if (di_nodeid(node
) == DI_SID_NODEID
) {
6461 di_ret
= di_prop_lookup_bytes(DDI_DEV_T_ANY
, node
,
6462 "port-wwn", &port_wwn_data
);
6463 if (di_ret
== -1 || port_wwn_data
== NULL
) {
6465 return (L_NO_WWN_PROP_FOUND
);
6467 (void) memcpy(pwwn
, port_wwn_data
, WWN_SIZE
);
6470 } else if (di_nodeid(node
) == DI_PROM_NODEID
) {
6471 if ((ph
= di_prom_init()) == DI_PROM_HANDLE_NIL
) {
6473 return (L_PROM_INIT_FAILED
);
6476 for (promprop
= di_prom_prop_next(ph
, node
,
6478 promprop
!= DI_PROM_PROP_NIL
;
6479 promprop
= di_prom_prop_next(ph
, node
, promprop
)) {
6480 if (((promname
= di_prom_prop_name(
6481 promprop
)) != NULL
) &&
6482 (strcmp(promname
, "port-wwn") == 0) &&
6483 (di_prom_prop_data(promprop
,
6484 &promdata
) == WWN_SIZE
)) {
6485 /* Found port-wwn */
6486 (void) memcpy(pwwn
, promdata
, WWN_SIZE
);
6498 return (L_INVALID_PATH
);
6501 return (L_INVALID_PATH_TYPE
);
6508 * Retrieve pwwn via SFIOCGMAP
6511 get_FC4_host_controller_pwwn(char *hba_path
, uchar_t
*pwwn
)
6514 char my_hba_path
[MAXPATHLEN
];
6517 if (hba_path
== NULL
|| pwwn
== NULL
) {
6518 return (L_INVALID_PATH
);
6521 (void) snprintf(my_hba_path
, sizeof (my_hba_path
), "%s%s",
6524 if ((fd
= g_object_open(my_hba_path
, O_NDELAY
| O_RDONLY
)) == -1) {
6528 memset(&sf_map
, 0, sizeof (sf_al_map_t
));
6530 if (ioctl(fd
, SFIOCGMAP
, &sf_map
) != 0) {
6532 return (L_SFIOCGMAP_IOCTL_FAIL
);
6537 if (sf_map
.sf_count
== 0) {
6539 return (L_SFIOCGMAP_IOCTL_FAIL
);
6542 (void) memcpy(pwwn
, &sf_map
.sf_hba_addr
.sf_port_wwn
[0], WWN_SIZE
);
6548 * from_ptr: ptr to uchar_t array of size WWN_SIZE
6549 * to_ptr: char ptr to string of size WWN_SIZE*2+1
6552 copy_wwn_data_to_str(char *to_ptr
, const uchar_t
*from_ptr
)
6554 if ((to_ptr
== NULL
) || (from_ptr
== NULL
))
6557 sprintf(to_ptr
, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
6558 from_ptr
[0], from_ptr
[1], from_ptr
[2], from_ptr
[3],
6559 from_ptr
[4], from_ptr
[5], from_ptr
[6], from_ptr
[7]);
6563 * Frees a previously allocated mplist_struct
6566 adm_mplist_free(struct mplist_struct
*mplistp
)
6568 struct mplist_struct
*mplistn
;
6570 while (mplistp
!= NULL
) {
6571 mplistn
= mplistp
->next
;
6572 if (mplistp
->devpath
!= NULL
) {
6573 free(mplistp
->devpath
);
6574 mplistp
->devpath
= NULL
;
6582 adm_reserve(char *path
)
6584 char *path_phys
= NULL
;
6587 g_get_physical_name(path
)) == NULL
) {
6589 (void) fprintf(stderr
, "%s: ", whoami
);
6590 (void) fprintf(stderr
,
6591 MSGSTR(112, "Error: Invalid pathname (%s)"),
6593 (void) fprintf(stderr
, "\n");
6597 if ((err
= g_reserve(path_phys
)) != 0) {
6598 (void) print_errString(err
, path
);
6605 adm_release(char *path
)
6607 char *path_phys
= NULL
;
6610 g_get_physical_name(path
)) == NULL
) {
6612 (void) fprintf(stderr
, "%s: ", whoami
);
6613 (void) fprintf(stderr
,
6614 MSGSTR(112, "Error: Invalid pathname (%s)"),
6616 (void) fprintf(stderr
, "\n");
6620 if ((err
= g_release(path_phys
)) != 0) {
6621 (void) print_errString(err
, path
);
6629 (void) g_i18n_catopen();
6632 int adm_check_file(char **path
, int flag
) {
6634 if (err
= l_check_file(*path
, flag
)) {
6635 (void) print_errString(err
, *path
);
6639 (void) fprintf(stdout
, MSGSTR(2212, "Download file O.K. \n\n"));
6644 * Print out private loop dev dtype
6647 print_private_loop_dtype_prop(uchar_t
*hba_port_wwn
, uchar_t
*port_wwn
,
6650 if ((dtype_prop
& DTYPE_MASK
) < 0x10) {
6651 (void) fprintf(stdout
, " 0x%-2x (%s",
6652 (dtype_prop
& DTYPE_MASK
), dtype
[(dtype_prop
& DTYPE_MASK
)]);
6653 } else if ((dtype_prop
& DTYPE_MASK
) < 0x1f) {
6654 (void) fprintf(stdout
,
6655 MSGSTR(2243, " 0x%-2x (Reserved"),
6656 (dtype_prop
& DTYPE_MASK
));
6658 (void) fprintf(stdout
, MSGSTR(2245,
6659 " 0x%-2x (Unknown Type"), (dtype_prop
& DTYPE_MASK
));
6661 /* Check to see if this is the HBA */
6662 if (wwnConversion(hba_port_wwn
) == wwnConversion(port_wwn
)) {
6664 (void) fprintf(stdout
, MSGSTR(2244,
6665 ",Host Bus Adapter)\n"));
6667 (void) fprintf(stdout
, ")\n");