add UNLEASHED_OBJ to unleashed.mk
[unleashed/tickless.git] / usr / src / cmd / luxadm / g_adm.c
blobb0cecdc016a4a5bef3157627749867d94ccf79fe
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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)
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <sys/file.h>
34 #include <sys/errno.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/param.h>
38 #include <kstat.h>
39 #include <sys/mkdev.h>
40 #include <locale.h>
41 #include <nl_types.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <strings.h>
45 #include <ctype.h>
46 #include <dirent.h>
47 #include <limits.h>
48 #include <stdarg.h>
49 #include <termio.h> /* For password */
50 #include <signal.h>
51 #include <sys/scsi/scsi.h>
52 #include <sys/scsi/generic/commands.h>
53 #include <l_common.h>
54 #include <l_error.h>
55 #include <stgcom.h>
56 #include <a_state.h>
57 #include <devid.h>
58 #include <g_state.h>
59 #include "common.h"
61 extern char *dtype[];
62 extern char *whoami;
63 extern int Options;
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;
83 static int termio_fd;
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 *,
87 WWN_list **);
88 static void n_rem_list_entry_fabric(int, struct gfc_map *,
89 WWN_list **);
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 *,
96 L_inquiry, int);
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,
118 int verbose);
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
132 * stdout.
134 * RETURNS:
135 * 0 O.K.
136 * non-zero otherwise
139 print_devState(char *devname, char *ppath, int fr_flag, int slot,
140 int verbose_flag)
142 L_state l_state;
143 int err;
144 int i, elem_index = 0;
145 uchar_t device_off, ib_status_code, bypass_a_en, bypass_b_en;
146 Bp_elem_st bpf, bpr;
149 if ((err = l_get_status(ppath, &l_state, verbose_flag)) != 0) {
150 (void) print_errString(err, ppath);
151 return (err);
154 for (i = 0; i < (int)l_state.ib_tbl.config.enc_num_elem; i++) {
155 elem_index++;
156 if (l_state.ib_tbl.config.type_hdr[i].type == ELM_TYP_BP) {
157 break;
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));
168 if (fr_flag) {
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;
173 } else {
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;
179 if (device_off) {
180 (void) fprintf(stdout,
181 MSGSTR(2000,
182 "%s is offlined and bypassed.\n"
183 " Could not get device specific"
184 " information.\n\n"),
185 devname);
186 } else if (bypass_a_en && bypass_b_en) {
187 (void) fprintf(stdout,
188 MSGSTR(2001,
189 "%s is bypassed (Port:AB).\n"
190 " Could not get device specific"
191 " information.\n\n"),
192 devname);
193 } else if (ib_status_code == S_NOT_INSTALLED) {
194 (void) fprintf(stdout,
195 MSGSTR(2002,
196 "Slot %s is empty.\n\n"),
197 devname);
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,
205 MSGSTR(2003,
206 "Backplane(Port:AB) is bypassed.\n"
207 " Could not get device specific"
208 " information for"
209 " %s.\n\n"), devname);
210 } else {
211 (void) fprintf(stderr,
212 MSGSTR(33,
213 " Error: converting"
214 " %s to physical path.\n"
215 " Invalid pathname.\n"),
216 devname);
218 return (-1);
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.
230 * RETURNS: N/A
233 void
234 print_errString(int errnum, char *devpath)
237 char *errStr;
239 errStr = g_get_errString(errnum);
241 if (devpath == NULL) {
242 (void) fprintf(stderr,
243 "%s \n\n", errStr);
244 } else {
245 (void) fprintf(stderr,
246 "%s - %s.\n\n", errStr, devpath);
249 /* free the allocated memory for error string */
250 if (errStr != NULL)
251 (void) free(errStr);
255 * adm_inquiry() Display the inquiry information for
256 * a SENA enclosure(s) or disk(s).
258 * RETURNS:
259 * none.
262 adm_inquiry(char **argv)
264 L_inquiry inq;
265 L_inquiry80 inq80;
266 size_t serial_len;
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'))) {
282 if (err != -1) {
283 (void) print_errString(err, argv[path_index]);
284 path_index++;
285 retval++;
286 continue;
288 *ptr = NULL;
289 slot = path_struct->slot;
290 f_r = path_struct->f_flag;
291 path_phys = NULL;
292 if ((err = l_convert_name(inq_path, &path_phys,
293 &path_struct, Options & PVERBOSE)) != 0) {
294 (void) fprintf(stderr,
295 MSGSTR(33,
296 " Error: converting"
297 " %s to physical path.\n"
298 " Invalid pathname.\n"),
299 argv[path_index]);
300 if (err != -1) {
301 (void) print_errString(err,
302 argv[path_index]);
304 path_index++;
305 retval++;
306 continue;
308 if ((err = print_devState(argv[path_index],
309 path_struct->p_physical_path,
310 f_r, slot, Options & PVERBOSE)) != 0) {
311 path_index++;
312 retval++;
313 continue;
315 } else {
316 if (err != -1) {
317 (void) print_errString(err, argv[path_index]);
318 } else {
319 (void) fprintf(stderr, "\n ");
320 (void) fprintf(stderr,
321 MSGSTR(112, "Error: Invalid pathname (%s)"),
322 argv[path_index]);
323 (void) fprintf(stderr, "\n");
326 path_index++;
327 retval++;
328 continue;
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");
336 path_index++;
337 retval++;
338 continue;
341 serial_len = sizeof (inq80.inq_serial);
342 if (err = g_get_serial_number(path_phys, inq80.inq_serial,
343 &serial_len)) {
344 (void) fprintf(stderr, "\n");
345 (void) print_errString(err, argv[path_index]);
346 (void) fprintf(stderr, "\n");
347 path_index++;
348 retval++;
349 continue;
351 print_inq_data(argv[path_index], path_phys, inq,
352 inq80.inq_serial, serial_len);
353 path_index++;
354 continue;
356 if ((err = g_get_wwn_list(&wwn_list, 0)) != 0) {
357 return (err);
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) ==
366 0) {
367 list_start = wwn_list_ptr;
368 argpwwn = 1;
369 break;
370 } else if (strcasecmp(wwn_list_ptr->node_wwn_s,
371 path_struct->argv) == 0) {
372 list_start = wwn_list_ptr;
373 argnwwn = 1;
374 break;
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");
387 path_index++;
388 retval++;
389 continue;
392 serial_len = sizeof (inq80.inq_serial);
393 if (err = g_get_serial_number(path_phys, inq80.inq_serial,
394 &serial_len)) {
395 (void) fprintf(stderr, "\n");
396 (void) print_errString(err, argv[path_index]);
397 (void) fprintf(stderr, "\n");
398 path_index++;
399 retval++;
400 continue;
402 print_inq_data(argv[path_index], path_phys, inq,
403 inq80.inq_serial, serial_len);
404 (void) g_free_wwn_list(&wwn_list);
405 path_index++;
406 continue;
409 for (wwn_list_ptr = list_start; wwn_list_ptr != NULL;
410 wwn_list_ptr = wwn_list_ptr->wwn_next) {
411 if (argpwwn) {
412 if (strcasecmp(wwn_list_ptr->port_wwn_s,
413 path_struct->argv) != 0) {
414 continue;
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) {
421 continue;
423 if (strstr(wwn_list_ptr->logical_path,
424 last_logical_path) != NULL) {
425 continue;
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");
437 retval++;
438 break;
441 serial_len = sizeof (inq80.inq_serial);
442 if (err = g_get_serial_number(path_phys, inq80.inq_serial,
443 &serial_len)) {
444 (void) fprintf(stderr, "\n");
445 (void) print_errString(err, argv[path_index]);
446 (void) fprintf(stderr, "\n");
447 retval++;
448 break;
450 print_inq_data(argv[path_index], path_phys, inq,
451 inq80.inq_serial, serial_len);
455 (void) g_free_wwn_list(&wwn_list);
456 path_index++;
458 return (retval);
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]);
476 if (err != -1) {
477 (void) print_errString(err, argv[path_index]);
478 path_index++;
479 retval++;
480 continue;
482 if (((ptr = strstr(err_path, ", ")) != NULL) &&
483 ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') ||
484 (*(ptr +1) == 's'))) {
485 *ptr = NULL;
486 slot = path_struct->slot;
487 f_r = path_struct->f_flag;
488 path_phys = NULL;
489 if ((err = l_convert_name(err_path,
490 &path_phys, &path_struct,
491 Options & PVERBOSE)) != 0) {
492 (void) fprintf(stderr, MSGSTR(33,
493 " Error: converting"
494 " %s to physical path.\n"
495 " Invalid pathname.\n"),
496 argv[path_index]);
497 if (err != -1) {
498 (void) print_errString(err,
499 argv[path_index]);
501 path_index++;
502 retval++;
503 continue;
505 if ((err = print_devState(argv[path_index],
506 path_struct->p_physical_path,
507 f_r, slot, Options & PVERBOSE)) != 0) {
508 path_index++;
509 retval++;
510 continue;
512 } else {
513 (void) fprintf(stderr, "\n ");
514 (void) fprintf(stderr, MSGSTR(112,
515 "Error: Invalid pathname (%s)"),
516 argv[path_index]);
517 (void) fprintf(stderr, "\n");
519 path_index++;
520 retval++;
521 continue;
523 if (err = g_force_lip(path_phys, Options & PVERBOSE)) {
524 (void) print_errString(err, argv[path_index]);
525 path_index++;
526 retval++;
527 continue;
529 path_index++;
530 if (path_struct != NULL) {
531 (void) free(path_struct);
534 return (retval);
539 * DISPLAY function
541 * RETURNS:
542 * 0 O.K.
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;
549 int retval = 0;
550 gfc_map_t map;
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"),
558 argv[path_index]);
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'))) {
569 if (err != -1) {
570 (void) print_errString(err,
571 argv[path_index]);
572 path_index++;
573 retval++;
574 continue;
576 *ptr = NULL;
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))
581 != 0) {
583 (void) fprintf(stderr,
584 MSGSTR(33,
585 " Error: converting"
586 " %s to physical path.\n"
587 " Invalid pathname.\n"),
588 argv[path_index]);
589 if (err != -1) {
590 (void) print_errString(err,
591 argv[path_index]);
593 path_index++;
594 retval++;
595 continue;
598 if ((err = print_devState(argv[path_index],
599 path_struct->p_physical_path,
600 f_r, slot, Options & PVERBOSE)) != 0) {
601 path_index++;
602 retval++;
603 continue;
605 } else {
606 if (err != -1) {
607 (void) print_errString(err,
608 argv[path_index]);
609 } else {
610 (void) fprintf(stderr, "\n ");
611 (void) fprintf(stderr,
612 MSGSTR(112,
613 "Error: Invalid pathname (%s)"),
614 argv[path_index]);
615 (void) fprintf(stderr, "\n");
619 } else {
620 if (err != -1) {
621 (void) print_errString(err,
622 argv[path_index]);
623 } else {
624 (void) fprintf(stderr, "\n ");
625 (void) fprintf(stderr,
626 MSGSTR(112,
627 "Error: Invalid pathname (%s)"),
628 argv[path_index]);
629 (void) fprintf(stderr, "\n");
633 path_index++;
634 retval++;
635 continue;
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]);
652 path_index++;
653 retval++;
654 continue;
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);
661 exit(1);
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));
674 } else {
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));
690 } else {
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
697 * and can continue
698 * otherwise:
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)
711 != NULL))))) {
712 if (Options & OPTION_R) {
713 adm_display_err(path_phys,
714 (inq.inq_dtype & DTYPE_MASK));
715 } else {
716 display_fc_disk(path_struct, ses_path, &map, inq,
717 Options & PVERBOSE);
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)) {
743 case DTYPE_DIRECT:
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,
751 MSGSTR(2111,
752 "Error: getting the device"
753 " information.\n"));
754 retval++;
756 break;
757 /* case 0x01: same as default */
758 default:
759 (void) fprintf(stdout, " ");
760 (void) fprintf(stdout, MSGSTR(35,
761 "Device Type:"));
762 (void) fprintf(stdout, "%s\n",
763 dtype[inq.inq_dtype & DTYPE_MASK]);
764 break;
766 } else if ((inq.inq_dtype & DTYPE_MASK) < 0x1f) {
767 (void) fprintf(stdout,
768 MSGSTR(2112, " Device type: Reserved"));
769 (void) fprintf(stdout, "\n");
770 } else {
771 (void) fprintf(stdout,
772 MSGSTR(2113, " Device type: Unknown device"));
773 (void) fprintf(stdout, "\n");
775 path_index++;
776 if (map.dev_addr != NULL) {
777 free((void *)map.dev_addr);
779 (void) free(path_struct);
781 return (retval);
786 * Powers off a list of SENA enclosure(s)
787 * and disk(s) which is provided by the user.
789 * RETURNS:
790 * none.
793 adm_power_off(char **argv, int off_flag)
795 int path_index = 0, err = 0, retval = 0;
796 L_inquiry inq;
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;
811 } else {
812 (void) fprintf(stderr,
813 MSGSTR(33,
814 " Error: converting"
815 " %s to physical path.\n"
816 " Invalid pathname.\n"),
817 argv[path_index]);
818 if (err != -1) {
819 (void) print_errString(err,
820 argv[path_index]);
822 path_index++;
823 retval++;
824 continue;
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
837 * informtaion.
839 print_devState(argv[path_index],
840 path_struct->p_physical_path,
841 path_struct->f_flag, path_struct->slot,
842 Options & PVERBOSE);
843 retval++;
845 path_index++;
846 continue;
849 if (err = g_get_inquiry(path_phys, &inq)) {
850 (void) print_errString(err, argv[path_index]);
851 path_index++;
852 retval++;
853 continue;
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],
861 off_flag) != 0) {
862 path_index++;
863 retval++;
864 continue;
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]);
871 retval++;
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]);
878 retval++;
880 } else {
882 * SSA section:
884 (void) print_errString(L_INVALID_PATH,
885 argv[path_index]);
887 path_index++;
889 return (retval);
894 void
895 adm_bypass_enable(char **argv, int bypass_flag)
897 int path_index = 0, err = 0;
898 L_inquiry inq;
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;
912 } else {
913 (void) fprintf(stderr,
914 MSGSTR(33,
915 " Error: converting"
916 " %s to physical path.\n"
917 " Invalid pathname.\n"),
918 argv[path_index]);
919 if (err != -1) {
920 (void) print_errString(err, argv[path_index]);
922 exit(-1);
925 if (path_struct->ib_path_flag) {
926 if (Options & OPTION_F) {
927 E_USEAGE();
928 exit(-1);
931 * We are addressing a disk using a path
932 * format type box,f1 and no disk
933 * path was found.
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,
939 Options & OPTION_A,
940 Options & PVERBOSE)) {
941 (void) print_errString(err, argv[path_index]);
942 exit(-1);
944 return;
947 if (err = g_get_inquiry(path_phys, &inq)) {
948 (void) print_errString(err, argv[path_index]);
949 exit(-1);
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))) {
959 E_USEAGE();
960 exit(-1);
962 if (err = l_bp_bypass_enable(path_phys, bypass_flag,
963 Options & OPTION_A,
964 Options & OPTION_F,
965 Options & OPTION_CAPF,
966 Options & PVERBOSE)) {
967 (void) print_errString(err, argv[path_index]);
968 exit(-1);
970 } else if ((inq.inq_dtype & DTYPE_MASK) == DTYPE_DIRECT) {
971 if (Options & OPTION_F) {
972 E_USEAGE();
973 exit(-1);
975 if (err = l_dev_bypass_enable(path_struct,
976 bypass_flag, Options & OPTION_CAPF,
977 Options & OPTION_A,
978 Options & PVERBOSE)) {
979 (void) print_errString(err, argv[path_index]);
980 exit(-1);
986 * adm_download() Download subsystem microcode.
987 * Path must point to a LUX IB.
989 * RETURNS:
990 * None.
992 void
993 adm_download(char **argv, char *file_name)
995 int path_index = 0, err = 0;
996 char *path_phys = NULL;
997 L_inquiry inq;
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,
1007 MSGSTR(33,
1008 " Error: converting"
1009 " %s to physical path.\n"
1010 " Invalid pathname.\n"),
1011 argv[path_index]);
1012 if (err != -1) {
1013 (void) print_errString(err, argv[path_index]);
1015 exit(-1);
1017 if (err = g_get_inquiry(path_phys, &inq)) {
1018 (void) print_errString(err, argv[path_index]);
1019 exit(-1);
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);
1031 exit(-1);
1033 } else {
1034 (void) fprintf(stderr,
1035 MSGSTR(112, "Error: Invalid pathname (%s)"),
1036 argv[path_index]);
1038 path_index++;
1043 * display_link_status() Reads and displays the link status.
1045 * RETURNS:
1046 * none.
1048 void
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,
1061 MSGSTR(33,
1062 " Error: converting"
1063 " %s to physical path.\n"
1064 " Invalid pathname.\n"),
1065 argv[path_index]);
1066 if (err != -1) {
1067 (void) print_errString(err, argv[path_index]);
1069 exit(-1);
1071 if (err = g_rdls(path_phys, &rls, Options & PVERBOSE)) {
1072 (void) print_errString(err, argv[path_index]);
1073 exit(-1);
1075 n = rls;
1076 if (n != NULL) {
1077 (void) fprintf(stdout,
1078 MSGSTR(2007, "\nLink Error Status "
1079 "information for loop:%s\n"),
1080 n->driver_path);
1081 (void) fprintf(stdout, MSGSTR(2008, "al_pa lnk fail "
1082 " sync loss signal loss sequence err"
1083 " invalid word CRC\n"));
1085 while (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",
1094 n->al_ha,
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);
1101 } else {
1102 (void) fprintf(stdout,
1103 "%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n",
1104 n->al_ha,
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);
1112 n = n->next;
1115 path_index++;
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.
1128 * RETURN:
1129 * 1 if ib present
1130 * 0 otherwise
1133 ib_present_chk(struct l_state_struct *l_state, int which_one)
1135 Ctlr_elem_st ctlr;
1136 int i;
1137 int elem_index = 0;
1138 int result = 1;
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) {
1147 result = 0;
1149 break;
1151 elem_index += l_state->ib_tbl.config.type_hdr[i].num;
1153 return (result);
1157 * print_individual_state() Print individual disk status.
1159 * RETURNS:
1160 * none.
1162 void
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,
1193 MSGSTR(2010,
1194 " (Rsrv cnflt:A) "));
1195 } else if (port == PORT_B) {
1196 (void) fprintf(stdout,
1197 MSGSTR(2011,
1198 " (Rsrv cnflt:B) "));
1199 } else {
1200 (void) fprintf(stdout,
1201 MSGSTR(2012,
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.
1217 * RETURNS:
1218 * none.
1220 void
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)
1224 int loop_flag = 0;
1225 int a_and_b = 0;
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,
1238 ") ");
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,
1243 MSGSTR(2014,
1244 "(LED Blinking) "));
1245 } else {
1246 (void) fprintf(stdout,
1247 " ");
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,
1256 ") ");
1257 } else if (dsk_ptr->ib_status.bypass_a_en &&
1258 dsk_ptr->ib_status.bypass_b_en) {
1259 (void) fprintf(stdout,
1260 MSGSTR(2017,
1261 "(Bypassed:AB)"));
1262 (void) fprintf(stdout,
1263 " ");
1264 } else if (dsk_ptr->ib_status.bypass_a_en) {
1265 (void) fprintf(stdout,
1266 MSGSTR(2018,
1267 "(Bypassed: A)"));
1268 (void) fprintf(stdout,
1269 " ");
1270 } else if (dsk_ptr->ib_status.bypass_b_en) {
1271 (void) fprintf(stdout,
1272 MSGSTR(2019,
1273 "(Bypassed: B)"));
1274 (void) fprintf(stdout,
1275 " ");
1276 } else {
1277 (void) fprintf(stdout,
1278 " ");
1280 } else {
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,
1315 MSGSTR(2025,
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,
1321 MSGSTR(2026,
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,
1327 MSGSTR(2027,
1328 "(Bypassed BP:AB)"));
1329 } else {
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,
1336 MSGSTR(2028,
1337 " (Loop not accessible)"));
1338 loop_flag = 1;
1339 } else if (dsk_ptr->l_state_flag & L_INVALID_WWN) {
1340 (void) fprintf(stdout,
1341 MSGSTR(2029,
1342 " (Invalid WWN) "));
1343 } else if (dsk_ptr->l_state_flag & L_INVALID_MAP) {
1344 (void) fprintf(stdout,
1345 MSGSTR(2030,
1346 " (Login failed) "));
1347 } else if (dsk_ptr->l_state_flag & L_NO_PATH_FOUND) {
1348 (void) fprintf(stdout,
1349 MSGSTR(2031,
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,
1360 PORT_A_B);
1361 } else {
1362 (void) fprintf(stdout, " (");
1363 (void) fprintf(stdout,
1364 MSGSTR(29, "O.K."));
1365 (void) fprintf(stdout,
1366 ") ");
1369 if (loop_flag) {
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);
1374 } else {
1375 (void) fprintf(stdout, " ");
1378 if (front_flag) {
1379 (void) fprintf(stdout, " ");
1386 * pho_display_config() Displays device status
1387 * information for a SENA enclosure.
1389 * RETURNS:
1390 * none.
1392 void
1393 pho_display_config(char *path_phys)
1395 L_state l_state;
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);
1404 exit(-1);
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++) {
1422 elem_index++;
1423 if (l_state.ib_tbl.config.type_hdr[j].type == ELM_TYP_BP)
1424 break;
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,
1447 MSGSTR(2242,
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);
1469 elem_index = 0;
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) {
1474 case ELM_TYP_PS:
1475 ps_messages(&l_state, i, elem_index);
1476 break;
1477 case ELM_TYP_FT:
1478 fan_messages(&l_state, i, elem_index);
1479 break;
1480 case ELM_TYP_BP:
1481 back_plane_messages(&l_state, i, elem_index);
1482 break;
1483 case ELM_TYP_IB:
1484 ctlr_messages(&l_state, i, elem_index);
1485 break;
1486 case ELM_TYP_LN:
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]);
1497 break;
1498 case ELM_TYP_LO: /* Loop configuration */
1499 loop_messages(&l_state, i, elem_index);
1500 break;
1501 case ELM_TYP_MB: /* Loop configuration */
1502 mb_messages(&l_state, i, elem_index);
1503 break;
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.
1521 * RETURNS:
1522 * none.
1524 void
1525 dpm_display_config(char *path_phys)
1527 L_state l_state;
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);
1536 exit(-1);
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++) {
1553 elem_index++;
1554 if (l_state.ib_tbl.config.type_hdr[j].type == ELM_TYP_BP)
1555 break;
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;
1567 i++, count++) {
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,
1583 MSGSTR(2033,
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);
1609 elem_index = 0;
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) {
1614 case ELM_TYP_PS:
1615 ps_messages(&l_state, i, elem_index);
1616 break;
1617 case ELM_TYP_FT:
1618 fan_messages(&l_state, i, elem_index);
1619 break;
1620 case ELM_TYP_BP:
1621 dpm_SSC100_messages(&l_state, i, elem_index);
1622 break;
1623 case ELM_TYP_IB:
1624 ctlr_messages(&l_state, i, elem_index);
1625 break;
1626 case ELM_TYP_LN:
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]);
1637 break;
1638 case ELM_TYP_LO: /* Loop configuration */
1639 loop_messages(&l_state, i, elem_index);
1640 break;
1641 case ELM_TYP_MB: /* Loop configuration */
1642 mb_messages(&l_state, i, elem_index);
1643 break;
1644 case ELM_TYP_FL:
1645 trans_messages(&l_state, 1);
1646 break;
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.
1668 void
1669 intfix(void)
1671 if (termio_fd) {
1672 termios.c_lflag |= ECHO;
1673 ioctl(termio_fd, TCSETS, &termios);
1675 exit(SIGINT);
1680 * up_password() Changes the password for SENA enclosure.
1682 * RETURNS:
1683 * none.
1685 void
1686 up_password(char **argv)
1688 int path_index = 0, err = 0;
1689 char password[1024];
1690 char input[1024];
1691 int i, j, matched, equal;
1692 L_inquiry inq;
1693 void (*sig)();
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"));
1701 exit(-1);
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,
1712 MSGSTR(33,
1713 " Error: converting"
1714 " %s to physical path.\n"
1715 " Invalid pathname.\n"),
1716 argv[path_index]);
1717 if (err != -1) {
1718 (void) print_errString(err, argv[path_index]);
1720 exit(-1);
1722 if (err = g_get_inquiry(path_phys, &inq)) {
1723 (void) print_errString(err, argv[path_index]);
1724 exit(-1);
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"),
1736 ENCLOSURE_PROD_ID);
1737 exit(-1);
1739 (void) fprintf(stdout,
1740 MSGSTR(2038,
1741 "Changing FPM password for subsystem %s\n"),
1742 argv[path_index]);
1744 equal = 0;
1745 while (!equal) {
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);
1754 (void) gets(input);
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."
1764 " The password"
1765 " must be 4 decimal-digit characters.\n"));
1766 exit(-1);
1769 if (i && (i != 4)) {
1770 (void) fprintf(stderr,
1771 MSGSTR(2042, "\nError: Invalid password."
1772 " The password"
1773 " must be 4 decimal-digit characters.\n"));
1774 exit(-1);
1776 for (j = 0; password[j]; j++) {
1777 if (!isdigit(password[j])) {
1778 (void) fprintf(stderr,
1779 MSGSTR(2043, "\nError: Invalid password."
1780 " The password"
1781 " must be 4 decimal-digit characters.\n"));
1782 exit(-1);
1785 if (i != j) {
1786 matched = -1;
1787 } else for (i = matched = 0; password[i]; i++) {
1788 if (password[i] == input[i]) {
1789 matched++;
1792 if ((matched != -1) && (matched == i)) {
1793 equal = 1;
1794 } else {
1795 (void) fprintf(stdout,
1796 MSGSTR(2044, "\npassword: They don't match;"
1797 " try again.\n"));
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);
1807 exit(-1);
1812 * Call g_failover to process failover command
1814 void
1815 adm_failover(char **argv)
1817 int path_index = 0, err = 0;
1818 char pathclass[20];
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"));
1827 exit(-1);
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"));
1836 exit(-1);
1839 if (err = g_failover(path_phys, pathclass)) {
1840 (void) print_errString(err, NULL);
1841 exit(-1);
1849 * up_encl_name() Update the enclosures logical name.
1851 * RETURNS:
1852 * none.
1854 void
1855 up_encl_name(char **argv, int argc)
1857 int i, rval, al_pa, path_index = 0, err = 0;
1858 L_inquiry inq;
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] != '#') &&
1870 (name[i] != '-') &&
1871 (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);
1879 exit(-1);
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);
1891 exit(-1);
1894 if ((err = l_convert_name(argv[path_index], &path_phys,
1895 &path_struct, Options & PVERBOSE)) != 0) {
1896 (void) fprintf(stderr,
1897 MSGSTR(33,
1898 " Error: converting"
1899 " %s to physical path.\n"
1900 " Invalid pathname.\n"),
1901 argv[path_index]);
1902 if (err != -1) {
1903 (void) print_errString(err, argv[path_index]);
1905 exit(-1);
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]);
1912 exit(-1);
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);
1925 exit(-1);
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]);
1931 exit(-1);
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]);
1939 exit(-1);
1941 if (b_list == NULL) {
1942 (void) fprintf(stdout,
1943 MSGSTR(93, "No %s enclosures found "
1944 "in /dev/es\n"), ENCLOSURE_PROD_NAME);
1945 exit(-1);
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"),
1954 name);
1955 (void) l_free_box_list(&b_list);
1956 exit(-1);
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);
1963 exit(-1);
1965 if (Options & PVERBOSE) {
1966 (void) fprintf(stdout,
1967 MSGSTR(2050, "The enclosure has been renamed to %s\n"),
1968 name);
1973 static int
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;
1978 L_state l_state;
1980 if ((err = l_get_status(phys_path,
1981 &l_state, Options & PVERBOSE)) != 0) {
1982 (void) print_errString(err, encl_name);
1983 return (err);
1986 if (off_flag) {
1987 for (slot = 0; slot < l_state.total_num_drv/2;
1988 slot++) {
1989 if (((l_state.drv_front[slot].ib_status.code !=
1990 S_NOT_INSTALLED) &&
1991 (!l_state.drv_front[slot].ib_status.dev_off)) ||
1992 ((l_state.drv_rear[slot].ib_status.code !=
1993 S_NOT_INSTALLED) &&
1994 (!l_state.drv_rear[slot].ib_status.dev_off))) {
1995 found_pwrOnDrv++;
1996 break;
1999 if (!found_pwrOnDrv) {
2000 (void) fprintf(stdout,
2001 MSGSTR(2051,
2002 "Notice: Drives in enclosure"
2003 " \"%s\" have already been"
2004 " powered off.\n\n"),
2005 encl_name);
2006 return (-1);
2008 } else {
2009 for (slot = 0; slot < l_state.total_num_drv/2;
2010 slot++) {
2011 if (((l_state.drv_front[slot].ib_status.code !=
2012 S_NOT_INSTALLED) &&
2013 (l_state.drv_front[slot].ib_status.dev_off)) ||
2014 ((l_state.drv_rear[slot].ib_status.code !=
2015 S_NOT_INSTALLED) &&
2016 (l_state.drv_rear[slot].ib_status.dev_off))) {
2017 found_pwrOffDrv++;
2018 break;
2021 if (!found_pwrOffDrv) {
2022 (void) fprintf(stdout,
2023 MSGSTR(2052,
2024 "Notice: Drives in enclosure"
2025 " \"%s\" have already been"
2026 " powered on.\n\n"),
2027 encl_name);
2028 return (-1);
2031 return (0);
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.
2044 * RETURNS:
2045 * none.
2047 void
2048 adm_led(char **argv, int led_action)
2050 int path_index = 0, err = 0;
2051 gfc_map_t map;
2052 L_inquiry inq;
2053 Dev_elem_st status;
2054 char *path_phys = NULL;
2055 Path_struct *path_struct;
2056 int enc_t = 0; /* enclosure type */
2057 char ses_path[MAXPATHLEN];
2058 L_inquiry ses_inq;
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;
2066 } else {
2067 (void) fprintf(stderr,
2068 MSGSTR(33,
2069 " Error: converting"
2070 " %s to physical path.\n"
2071 " Invalid pathname.\n"),
2072 argv[path_index]);
2073 if (err != -1) {
2074 (void) print_errString(err,
2075 argv[path_index]);
2077 exit(-1);
2080 if (!path_struct->ib_path_flag) {
2081 if (err = g_get_inquiry(path_phys, &inq)) {
2082 (void) print_errString(err, argv[path_index]);
2083 exit(-1);
2085 if ((inq.inq_dtype & DTYPE_MASK) != DTYPE_DIRECT) {
2086 (void) fprintf(stderr,
2087 MSGSTR(2053,
2088 "Error: pathname must be to a disk device.\n"
2089 " %s\n"), argv[path_index]);
2090 exit(-1);
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"));
2105 exit(-1);
2107 if (err = l_led(path_struct, led_action, &status,
2108 (Options & PVERBOSE))) {
2109 (void) print_errString(err, argv[path_index]);
2110 exit(-1);
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) {
2121 case L_LED_STATUS:
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);
2127 } else {
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"),
2133 path_struct->slot);
2134 } else {
2135 (void) fprintf(stdout,
2136 MSGSTR(2236, "LED state is ON for "
2137 "device in location: slot %d\n"),
2138 path_struct->slot +
2139 (MAX_DRIVES_DAK/2));
2141 } else {
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"),
2148 path_struct->slot);
2151 } else if (status.ident || status.rdy_to_ins ||
2152 status.rmv) {
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);
2157 } else {
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"),
2163 path_struct->slot);
2164 } else {
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));
2170 } else {
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"),
2177 path_struct->slot);
2180 } else {
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);
2185 } else {
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"),
2191 path_struct->slot);
2192 } else {
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);
2198 } else {
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"),
2205 path_struct->slot);
2209 break;
2211 free((void *)map.dev_addr);
2212 path_index++;
2221 * dump() Dump information
2223 * RETURNS:
2224 * none.
2226 void
2227 dump(char **argv)
2229 uchar_t *buf;
2230 int path_index = 0, err = 0;
2231 L_inquiry inq;
2232 char hdr_buf[MAXNAMELEN];
2233 Rec_diag_hdr *hdr, *hdr_ptr;
2234 char *path_phys = NULL;
2235 Path_struct *path_struct;
2238 * get big buffer
2240 if ((hdr = (struct rec_diag_hdr *)calloc(1, MAX_REC_DIAG_LENGTH)) ==
2241 NULL) {
2242 (void) print_errString(L_MALLOC_FAILED, NULL);
2243 exit(-1);
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,
2251 MSGSTR(33,
2252 " Error: converting"
2253 " %s to physical path.\n"
2254 " Invalid pathname.\n"),
2255 argv[path_index]);
2256 if (err != -1) {
2257 (void) print_errString(err, argv[path_index]);
2259 exit(-1);
2261 if (err = g_get_inquiry(path_phys, &inq)) {
2262 (void) print_errString(err, argv[path_index]);
2263 } else {
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]);
2272 exit(-1);
2274 (void) fprintf(stdout,
2275 MSGSTR(2066, "\t\tEnvironmental Sense Information\n"));
2278 * Dump all pages.
2280 hdr_ptr = hdr;
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));
2290 path_index++;
2292 (void) free(buf);
2298 * display_socal_stats() Display socal driver kstat information.
2300 * RETURNS:
2301 * none.
2303 void
2304 display_socal_stats(int port, char *socal_path, struct socal_stats *fc_stats)
2306 int i;
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"),
2314 port, socal_path);
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"
2324 " Port:%s\n"),
2325 fc_stats->node_wwn,
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",
2344 fc_stats->version,
2345 fc_stats->resets,
2346 fc_stats->reqq_intrs,
2347 fc_stats->qfulls,
2348 fc_stats->pstats[port].unsol_resps,
2349 fc_stats->pstats[port].lips);
2351 (void) fprintf(stdout, MSGSTR(2071,
2352 " Els_rcvd Abts"
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;
2366 } else {
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 "
2375 "Status Value"
2376 " Count\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",
2381 status_msg_buf);
2389 * display_sf_stats() Display sf driver kstat information.
2391 * This routine is called by private loop device only
2393 * RETURNS:
2394 * none.
2396 void
2397 display_sf_stats(char *path_phys, int dtype, struct sf_stats *sf_stats)
2399 int i, al_pa, err = 0;
2400 gfc_map_t map;
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");
2411 } else {
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",
2422 sf_stats->version,
2423 sf_stats->lip_count,
2424 sf_stats->lip_failures,
2425 sf_stats->cralloc_failures,
2426 sf_stats->ncmds,
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"
2434 " Tsk_m_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);
2439 exit(-1);
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);
2446 exit(-1);
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
2454 == al_pa) {
2455 (void) fprintf(stdout,
2456 "%3x%10d%8d%10d%11d%13d%11d%9d\n",
2457 al_pa,
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);
2465 break;
2468 if (i >= map.count) {
2469 (void) print_errString(L_INVALID_LOOP_MAP, path_phys);
2470 exit(-1);
2472 } else {
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.
2496 * RETURNS:
2497 * none.
2499 static void
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];
2504 struct stat sbuf;
2505 kstat_ctl_t *kc;
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];
2512 gfc_map_t map;
2513 uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
2514 uint_t path_type;
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"));
2522 exit(-1);
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);
2529 exit(-1);
2531 pathcnt = pathlist.path_count;
2532 p_on = p_st = 0;
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) {
2537 p_on = i;
2538 break;
2539 } else if (pathlist.path_info[i].path_state ==
2540 MDI_PATHINFO_STATE_STANDBY) {
2541 p_st = i;
2545 if (pathlist.path_info[p_on].path_state ==
2546 MDI_PATHINFO_STATE_ONLINE) {
2547 /* on_line path */
2548 (void) strcpy(drvr_path,
2549 pathlist.path_info[p_on].path_hba);
2550 } else {
2551 /* standby or path0 */
2552 (void) strcpy(drvr_path,
2553 pathlist.path_info[p_st].path_hba);
2555 free(pathlist.path_info);
2556 } else {
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,
2562 path_phys);
2563 exit(-1);
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);
2576 exit(-1);
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);
2587 exit(-1);
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,
2602 MSGSTR(2082,
2603 "Error: could not read ifp%d\n"), drvr_inst);
2604 exit(-1);
2606 (void) fprintf(stdout, MSGSTR(2083,
2607 "\tInformation for FC Loop of"
2608 " FC100/P Host Adapter\n\tat path: %s\n"),
2609 drvr_path);
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"
2620 " Port:%s\n"),
2621 ifp_stats.node_wwn,
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",
2639 ifp_stats.version,
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 "
2647 "status:\n "
2648 "Status "
2649 " Value"
2650 " Count\n"));
2652 (void) l_format_ifp_status_msg(
2653 status_msg_buf,
2654 ifp_stats.resp_status[i], i);
2655 (void) fprintf(stdout, " %s\n",
2656 status_msg_buf);
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);
2669 exit(-1);
2673 if (dtype == DTYPE_DIRECT) {
2674 if (err = g_get_wwn(path_phys, port_wwn,
2675 node_wwn, &al_pa,
2676 Options & PVERBOSE)) {
2677 (void) print_errString(err,
2678 path_phys);
2679 exit(-1);
2681 for (i = 0, dev_addr_list = map.dev_addr;
2682 i < map.count; i++,
2683 dev_addr_list++) {
2684 if (dev_addr_list->gfc_port_dev.
2685 priv_port.sf_al_pa
2686 == al_pa) {
2687 (void) fprintf
2688 (stdout,
2689 "%3x%14d%18d%20d%20d\n",
2690 al_pa,
2691 ifp_stats.tstats[i].
2692 logouts_recvd,
2693 ifp_stats.tstats[i].
2694 task_mgmt_failures,
2695 ifp_stats.tstats[i].
2696 data_ro_mismatches,
2697 ifp_stats.tstats[i].
2698 dl_len_mismatches);
2699 break;
2702 if (i >= map.count) {
2704 (void) print_errString(
2705 L_INVALID_LOOP_MAP, path_phys);
2706 exit(-1);
2709 } else {
2710 for (i = 0, dev_addr_list = map.dev_addr;
2711 i < map.count; i++,
2712 dev_addr_list++) {
2713 (void) fprintf(stdout,
2714 "%3x%14d%18d%20d%20d\n",
2715 dev_addr_list->gfc_port_dev.
2716 priv_port.sf_al_pa,
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);
2732 exit(-1);
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,
2739 "statistics"))) {
2740 (void) fprintf(stderr,
2741 MSGSTR(2078,
2742 " Error: could not lookup driver stats for sf%d\n"),
2743 sf_inst);
2744 exit(-1);
2746 if (!(fc_ks = kstat_lookup(kc, "socal", socal_inst,
2747 "statistics"))) {
2748 (void) fprintf(stderr,
2749 MSGSTR(2079,
2750 " Error: could not lookup driver stats for socal%d\n"),
2751 socal_inst);
2752 exit(-1);
2754 if (kstat_read(kc, sf_ks, &sf_stats) < 0) {
2755 (void) fprintf(stderr,
2756 MSGSTR(2080,
2757 " Error: could not read driver stats for sf%d\n"),
2758 sf_inst);
2759 exit(-1);
2761 if (kstat_read(kc, fc_ks, &fc_stats) < 0) {
2762 (void) fprintf(stderr,
2763 MSGSTR(2081,
2764 " Error: could not read driver stats for socal%d\n"),
2765 socal_inst);
2766 exit(-1);
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"));
2774 } else {
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);
2785 /*ARGSUSED*/
2787 * adm_display_verbose_disk() Gets the mode page information
2788 * for a SENA disk and prints that information.
2790 * RETURNS:
2791 * none.
2793 void
2794 adm_display_verbose_disk(char *path, int verbose)
2796 uchar_t *pg_buf;
2797 Mode_header_10 *mode_header_ptr;
2798 Mp_01 *pg1_buf;
2799 Mp_04 *pg4_buf;
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) {
2814 case 0x01:
2815 pg1_buf = (struct mode_page_01_struct *)
2816 (int)pg_hdr;
2817 P_DPRINTF(" adm_display_verbose_disk:"
2818 "Mode Sense page 1 found.\n");
2819 if (hdr_printed++ == 0) {
2820 (void) fprintf(stdout,
2821 MSGSTR(2089,
2822 " Mode Sense data:\n"));
2824 (void) fprintf(stdout,
2825 MSGSTR(2090,
2826 " AWRE:\t\t\t%d\n"
2827 " ARRE:\t\t\t%d\n"
2828 " Read Retry Count:\t\t"
2829 "%d\n"
2830 " Write Retry Count:\t\t"
2831 "%d\n"),
2832 pg1_buf->awre,
2833 pg1_buf->arre,
2834 pg1_buf->read_retry_count,
2835 pg1_buf->write_retry_count);
2836 break;
2837 case MODEPAGE_GEOMETRY:
2838 pg4_buf = (struct mode_page_04_struct *)
2839 (int)pg_hdr;
2840 P_DPRINTF(" adm_display_verbose_disk:"
2841 "Mode Sense page 4 found.\n");
2842 if (hdr_printed++ == 0) {
2843 (void) fprintf(stdout,
2844 MSGSTR(2091,
2845 " Mode Sense data:\n"));
2847 if (pg4_buf->rpm) {
2848 (void) fprintf(stdout,
2849 MSGSTR(2092,
2850 " Medium rotation rate:\t"
2851 "%d RPM\n"), pg4_buf->rpm);
2853 break;
2855 offset += pg_hdr->length + sizeof (struct mode_page);
2856 pg_hdr = ((struct mode_page *)((int)pg_buf +
2857 (uchar_t)offset));
2864 } else if (getenv("_LUX_P_DEBUG") != NULL) {
2865 (void) print_errString(err, path);
2870 * Print out the port_wwn or node_wwn
2872 void
2873 print_wwn(FILE *fd, uchar_t *pn_wwn)
2876 (void) fprintf(fd,
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
2885 void
2886 print_fabric_prop(int pos, uchar_t *port_wwn, uchar_t *node_wwn, int port_addr,
2887 int hard_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
2898 void
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.
2912 * RETURNS:
2913 * none.
2915 void
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;
2923 uint_t dev_type;
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;
2930 uint_t map_topo;
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,
2936 MSGSTR(33,
2937 " Error: converting"
2938 " %s to physical path.\n"
2939 " Invalid pathname.\n"),
2940 argv[path_index]);
2941 if (err != -1) {
2942 (void) print_errString(err, argv[path_index]);
2944 exit(-1);
2947 if (strstr(path_phys, SCSI_VHCI) != NULL) {
2948 /* obtain phci */
2949 (void) strcpy(temp2path, path_phys);
2950 if (err = g_get_pathlist(temp2path, &pathlist)) {
2951 (void) print_errString(err, NULL);
2952 exit(-1);
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 <
2958 MAXPATHSTATE) {
2959 if (strstr(pathlist.path_info[i].
2960 path_addr,
2961 path_struct->argv) != NULL) {
2962 p_pw = i;
2963 break;
2965 if (pathlist.path_info[i].path_state ==
2966 MDI_PATHINFO_STATE_ONLINE) {
2967 p_on = i;
2969 if (pathlist.path_info[i].path_state ==
2970 MDI_PATHINFO_STATE_STANDBY) {
2971 p_st = i;
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) {
2982 /* on_line path */
2983 (void) strcpy(temp2path,
2984 pathlist.path_info[p_on].path_hba);
2985 } else {
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);
2992 } else {
2993 (void) strcpy(temp2path, path_phys);
2996 if ((dev_type = g_get_path_type(temp2path)) == 0) {
2997 (void) print_errString(L_INVALID_PATH,
2998 argv[path_index]);
2999 exit(-1);
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]);
3006 exit(-1);
3007 } else {
3009 * This did not work so try the FCIO_GETMAP
3010 * type ioctl.
3012 if (err = g_get_limited_map(path_phys,
3013 &limited_map, (Options & PVERBOSE))) {
3014 (void) print_errString(err,
3015 argv[path_index]);
3016 exit(-1);
3018 limited_map_flag++;
3023 if (limited_map_flag) {
3024 (void) fprintf(stdout,
3025 MSGSTR(2093,
3026 "Host Adapter AL_PA: %x\n"),
3027 limited_map.lilp_myalpa);
3029 (void) fprintf(stdout,
3030 MSGSTR(2094,
3031 "Pos AL_PA\n"));
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]);
3036 } else {
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]);
3041 exit(-1);
3043 if ((err = g_get_map_topology(
3044 map_root, &map_topo)) != 0) {
3045 (void) print_errString(err, argv[path_index]);
3046 exit(-1);
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"),
3054 argv[path_index]);
3055 exit(-1);
3056 } else {
3057 g_dev_map_fini(map_root);
3058 (void) print_errString(err, argv[path_index]);
3059 exit(-1);
3063 switch (map_topo) {
3064 case FC_TOP_FABRIC:
3065 case FC_TOP_PUBLIC_LOOP:
3066 case FC_TOP_PT_PT:
3067 (void) fprintf(stdout,
3068 MSGSTR(2095, "Pos Port_ID Hard_Addr Port WWN"
3069 " Node WWN Type\n"));
3070 while (map_dev) {
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]);
3075 exit(-1);
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]);
3081 exit(-1);
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]);
3087 exit(-1);
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]);
3093 exit(-1);
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"));
3101 } else {
3102 print_fabric_dtype_prop(hba_port_wwn, port_wwn,
3103 *dtype_prop);
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]);
3111 exit(-1);
3114 break;
3115 case FC_TOP_PRIVATE_LOOP:
3116 (void) fprintf(stdout,
3117 MSGSTR(2295,
3118 "Pos AL_PA ID Hard_Addr "
3119 "Port WWN Node WWN Type\n"));
3121 while (map_dev) {
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]);
3126 exit(-1);
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]);
3132 exit(-1);
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]);
3138 exit(-1);
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]);
3144 exit(-1);
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"));
3152 } else {
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]);
3162 exit(-1);
3165 break;
3166 default:
3167 (void) print_errString(L_UNEXPECTED_FC_TOPOLOGY,
3168 argv[path_index]);
3169 exit(-1);
3171 g_dev_map_fini(map_root);
3173 limited_map_flag = 0;
3174 path_index++;
3179 * Gets a list of non-SENA fcal devices
3180 * found on the system.
3182 * OUTPUT:
3183 * wwn_list pointer
3184 * NULL: No non-enclosure devices found.
3185 * !NULL: Devices found
3186 * wwn_list points to a linked list of wwn's.
3187 * RETURNS:
3188 * 0 O.K.
3191 n_get_non_encl_list(WWN_list **wwn_list_ptr, int verbose)
3193 int i, j, k, err, found_ib = 0, pathcnt = 1;
3194 WWN_list *wwn_list;
3195 Box_list *b_list = NULL;
3196 gfc_map_t map;
3197 uchar_t box_id;
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);
3213 return (err);
3216 while (b_list != NULL) {
3218 pathcnt = 1;
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);
3223 exit(-1);
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))) {
3232 continue;
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);
3240 return (err);
3242 } else {
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)) {
3248 continue;
3250 if (pathcnt == 1) {
3251 free(pathlist.path_info);
3256 switch (map.hba_addr.port_topology) {
3257 case FC_TOP_FABRIC:
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;
3263 j++) {
3264 if (b_list->b_node_wwn[j] !=
3265 dev_addr_list->gfc_port_dev.
3266 pub_port.dev_nwwn.raw_wwn[j]) {
3267 found_ib = 0;
3270 if (found_ib) {
3271 (void) n_rem_list_entry_fabric(
3272 dev_addr_list->gfc_port_dev.
3273 pub_port.dev_did.port_id, &map,
3274 &wwn_list);
3277 break;
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;
3284 j++) {
3285 if (b_list->b_node_wwn[j] !=
3286 dev_addr_list->gfc_port_dev.
3287 priv_port.sf_node_wwn[j]) {
3288 found_ib = 0;
3291 if (found_ib) {
3292 box_id = g_sf_alpa_to_switch
3293 [dev_addr_list->gfc_port_dev.
3294 priv_port.sf_al_pa] &
3295 BOX_ID_MASK;
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,
3300 &wwn_list);
3301 if (wwn_list == NULL) {
3302 /* Return the list */
3303 *wwn_list_ptr = NULL;
3304 break;
3308 break;
3309 case FC_TOP_PT_PT:
3310 (void) free((void *)map.dev_addr);
3311 return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
3312 default:
3313 (void) free((void *)map.dev_addr);
3314 return (L_UNEXPECTED_FC_TOPOLOGY);
3316 free((void *)map.dev_addr);
3319 if (pathcnt > 1) {
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);
3328 return (0);
3334 * n_rem_list_entry() We found an IB so remove disks that
3335 * are in the Photon from the individual device list.
3337 * OUTPUT:
3338 * wwn_list - removes the fcal disks that are in SENA enclosure
3340 * RETURNS:
3341 * none
3343 void
3344 n_rem_list_entry(uchar_t box_id, struct gfc_map *map,
3345 struct wwn_list_struct **wwn_list)
3347 int k;
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)
3358 == box_id) {
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.
3372 * OUTPUT:
3373 * wwn_list - removes the fcal disks that are in SENA enclosure
3375 * RETURNS:
3376 * none
3378 void
3379 n_rem_list_entry_fabric(int pa, struct gfc_map *map,
3380 struct wwn_list_struct **wwn_list)
3382 int k;
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,
3397 wwn_list);
3404 * n_rem_wwn_entry() removes input wwn from wwn_list.
3406 * OUTPUT:
3407 * wwn_list - removes the input wwn from wwn_list if found.
3409 * RETURNS:
3410 * none
3412 void
3413 n_rem_wwn_entry(uchar_t node_wwn[], struct wwn_list_struct **wwn_list)
3415 int l, found_dev;
3416 WWN_list *inner, *l1;
3418 inner = *wwn_list;
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]) {
3422 found_dev = 0;
3425 if (found_dev) {
3426 /* Remove this entry from the list */
3427 if (inner->wwn_prev != NULL) {
3428 inner->wwn_prev->wwn_next =
3429 inner->wwn_next;
3430 } else {
3431 *wwn_list = inner->wwn_next;
3433 if (inner->wwn_next != NULL) {
3434 inner->wwn_next->wwn_prev =
3435 inner->wwn_prev;
3437 l1 = inner;
3438 N_DPRINTF(" n_rem_wwn_entry: "
3439 "Removing Logical=%s "
3440 "Current=0x%x, "
3441 "Prev=0x%x, Next=0x%x\n",
3442 l1->logical_path,
3444 l1->wwn_prev,
3445 l1->wwn_next);
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);
3451 (void) free(l1);
3452 *wwn_list = NULL;
3453 N_DPRINTF(" n_rem_list_entry: "
3454 "No non-Photon "
3455 "devices left"
3456 " in the list.\n");
3457 return;
3459 (void) free(l1->physical_path);
3460 (void) free(l1->logical_path);
3461 (void) free(l1);
3462 } else {
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
3472 * system.
3474 * RETURNS:
3475 * none.
3477 void
3478 non_encl_probe()
3480 WWN_list *wwn_list, *wwn_listh, *inner, *l1;
3481 int err = 0;
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);
3491 exit(-1);
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"));
3502 } else {
3503 (void) fprintf(stdout,
3504 MSGSTR(2099, "\nFound Fibre Channel device:\n"));
3506 } else {
3507 return;
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,
3514 &pathlist)) &&
3515 ((tempptra = strchr(pathlist.path_info[0].
3516 path_addr, ','))) != NULL) {
3517 tempptra++;
3518 (void) strcpy(lun_a, tempptra);
3519 free(pathlist.path_info);
3521 } else {
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)) {
3527 tempptra++;
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,
3541 "Type:Reserved"));
3542 } else {
3543 (void) fprintf(stdout, MSGSTR(2101,
3544 "Type:Unknown"));
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, ','))) !=
3571 NULL) {
3572 tempptrb++;
3573 (void) strcpy(lun_b, tempptrb);
3574 free(pathlist.path_info);
3576 } else {
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)) {
3582 tempptrb++;
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)) ==
3595 DI_NODE_NIL) {
3596 (void) fprintf(stdout,
3597 MSGSTR(2319,
3598 "\nFailed to get device tree snapshot:\n"));
3599 exit(1);
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.
3616 retr_outer = 1;
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) &&
3625 devid1 != 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);
3632 compare_result = 0;
3633 } else {
3634 compare_result = devid_compare(devid1, devid2);
3636 } else {
3637 /* devid isn't applied */
3638 compare_result = 0;
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,
3654 "Physical Path:"));
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 =
3663 inner->wwn_next;
3666 if (inner->wwn_next != NULL) {
3667 inner->wwn_next->wwn_prev =
3668 inner->wwn_prev;
3670 free(inner->physical_path);
3671 free(inner->logical_path);
3672 l1 = inner;
3673 inner = inner->wwn_next;
3674 (void) free(l1);
3676 } else {
3677 inner = inner->wwn_next;
3678 } /* End if (compare_result == 0) */
3680 } else {
3681 inner = inner->wwn_next;
3683 } else {
3684 inner = inner->wwn_next;
3686 devid2 = NULL;
3688 wwn_list = wwn_list->wwn_next;
3689 retr_outer = 0;
3690 devid1 = NULL;
3691 } /* End while (wwn_list != NULL) */
3693 (void) g_free_wwn_list(&wwn_listh);
3694 (void) di_fini(root);
3697 void
3698 pho_probe()
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);
3708 exit(-1);
3710 if (b_list == NULL) {
3711 (void) fprintf(stdout,
3712 MSGSTR(93, "No %s enclosures found "
3713 "in /dev/es\n"), ENCLOSURE_PROD_NAME);
3714 } else {
3715 o_list = b_list;
3716 if (b_list->box_next != NULL) {
3717 (void) fprintf(stdout, MSGSTR(2102,
3718 "Found Enclosure(s)"));
3719 } else {
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 */
3725 c_list = o_list;
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;
3731 break;
3733 c_list = c_list->box_next;
3735 if (multi_print_flag) {
3736 b_list = b_list->box_next;
3737 continue;
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;
3747 c_list = o_list;
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);
3770 c_list = o_list;
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 "
3802 "the same names.\n"
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
3813 * port status.
3815 * RETURNS:
3816 * none.
3818 void
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"));
3836 } else {
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
3849 * RETURNS:
3850 * none.
3852 void
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;
3867 L_state l_state;
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
3874 * initialization.
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);
3891 exit(-1);
3893 if (err = l_get_ses_path(path_phys, ses_path, map,
3894 (Options & PVERBOSE))) {
3895 (void) print_errString(err, path_phys);
3896 exit(-1);
3901 * Get the WWN for our disk if we already haven't or if there was an
3902 * error earlier
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);
3908 exit(-1);
3911 if (err = g_get_inquiry(ses_path, &local_inq)) {
3912 (void) print_errString(err, ses_path);
3913 exit(-1);
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);
3925 exit(-1);
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
3939 * last time.
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);
3947 exit(-1);
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\" "
3957 "program.)\n\n"));
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);
3962 exit(-1);
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);
3968 exit(-1);
3970 no_path_flag++;
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)) &&
3990 !mode_data_avail) {
3991 if (pg_hdr->code == MODEPAGE_CACHING) {
3992 mode_data_avail++;
3993 break;
3995 offset += pg_hdr->length + sizeof (struct mode_page);
3996 pg_hdr = ((struct mode_page *)((int)pg_buf +
3997 (uchar_t)offset));
4001 switch ((inq.inq_dtype & DTYPE_MASK)) {
4002 case DTYPE_DIRECT:
4003 fprintf(stdout, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
4004 path_struct->argv);
4005 break;
4006 case DTYPE_SEQUENTIAL: /* Tape */
4007 fprintf(stdout, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
4008 path_struct->argv);
4009 break;
4010 default:
4011 fprintf(stdout, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
4012 path_struct->argv);
4013 break;
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]);
4022 } else {
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,
4027 MSGSTR(66,
4028 " Status(Port A):\tBYPASSED\n"));
4030 } else {
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,
4034 MSGSTR(66,
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]);
4045 } else {
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,
4050 MSGSTR(65,
4051 " Status(Port B):\tBYPASSED\n"));
4053 } else {
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,
4057 MSGSTR(65,
4058 " Status(Port B):\tBYPASSED\n"));
4063 if (no_path_flag) {
4064 (void) fprintf(stdout, " ");
4065 if (port_a_flag != NULL) {
4066 (void) fprintf(stdout, MSGSTR(142, "Status(Port B):"));
4067 } else {
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.
4091 * RETURNS:
4092 * none.
4094 static int
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)) {
4117 return (err);
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;
4130 argpwwn = 1;
4131 break;
4132 } else if (strcasecmp(wwn_list_ptr->node_wwn_s,
4133 path_struct->argv) == 0) {
4134 list_start = wwn_list_ptr;
4135 argnwwn = 1;
4136 break;
4140 for (wwn_list_ptr = list_start; wwn_list_ptr != NULL;
4141 wwn_list_ptr = wwn_list_ptr->wwn_next) {
4144 if (argpwwn) {
4145 if (strcasecmp(wwn_list_ptr->port_wwn_s,
4146 path_struct->argv) != 0) {
4147 continue;
4149 (void) strcpy(phys_path, wwn_list_ptr->physical_path);
4150 path_a_found = 0;
4151 path_b_found = 0;
4152 mode_data_avail = 0;
4153 } else if (argnwwn) {
4154 if (strstr(wwn_list_ptr->logical_path,
4155 last_logical_path) != NULL) {
4156 continue;
4158 if (strcasecmp(wwn_list_ptr->node_wwn_s,
4159 path_struct->argv) != 0) {
4160 continue;
4162 (void) strcpy(phys_path, wwn_list_ptr->physical_path);
4163 (void) strcpy(last_logical_path,
4164 wwn_list_ptr->logical_path);
4165 path_a_found = 0;
4166 path_b_found = 0;
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) {
4175 return (err);
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);
4183 return (-1);
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)) &&
4196 !mode_data_avail) {
4197 if (pg_hdr->code == MODEPAGE_CACHING) {
4198 mode_data_avail++;
4199 break;
4201 offset += pg_hdr->length + sizeof (struct mode_page);
4202 pg_hdr = ((struct mode_page *)((int)pg_buf +
4203 (uchar_t)offset));
4207 switch ((inq_struct.inq_dtype & DTYPE_MASK)) {
4208 case DTYPE_DIRECT:
4209 fprintf(stdout, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
4210 path_struct->argv);
4211 break;
4212 case DTYPE_SEQUENTIAL: /* Tape */
4213 fprintf(stdout, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
4214 path_struct->argv);
4215 break;
4216 default:
4217 fprintf(stdout, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
4218 path_struct->argv);
4219 break;
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,
4225 MSGSTR(2114,
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);
4231 return (-1);
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);
4239 return (-1);
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,
4249 verbose)) != 0) {
4250 (void) print_errString(err, phys_path);
4251 (void) g_free_multipath(
4252 l_disk_state.g_disk_state.multipath_list);
4253 exit(-1);
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,
4274 verbose))) {
4275 (void) strcpy(temppath, mlist->dev_path);
4276 if (err = g_get_pathlist(temppath, &pathlist)) {
4277 (void) print_errString(err, NULL);
4278 exit(-1);
4280 pathcnt = pathlist.path_count;
4281 if (pathcnt > 1) {
4282 for (i = 0; i < pathcnt; i++) {
4283 if ((!path_a_found) &&
4284 (path_b_found) &&
4285 (strstr(pathlist.path_info[i].
4286 path_addr,
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].
4293 path_addr, 16);
4294 path_a_found = l_disk_state.
4295 g_disk_state.port_a_valid = 1;
4297 if ((path_a_found) &&
4298 (!path_b_found) &&
4299 (strstr(pathlist.path_info[i].
4300 path_addr,
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].
4307 path_addr, 16);
4308 path_b_found = l_disk_state.
4309 g_disk_state.port_b_valid = 1;
4311 if ((path_a_found) && (path_b_found)) {
4312 break;
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)) {
4341 break;
4345 (void) g_free_wwn_list(&wwn_list);
4346 return (0);
4352 * display_disk_info() Prints the device specific information
4353 * for any FC_AL disk device.
4355 * RETURNS:
4356 * none.
4358 void
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)
4363 float num_blks;
4364 struct dlist *mlist;
4365 int port_a, port_b;
4366 struct my_mode_caching *pg8_buf;
4367 L_inquiry enc_inq;
4368 char *enc_phys_path;
4369 Path_struct *enc_path_struct;
4370 int enc_type = 0;
4371 L_inquiry80 inq80;
4372 size_t serial_len;
4373 int err;
4375 serial_len = sizeof (inq80.inq_serial);
4376 err = g_get_serial_number(path_struct->p_physical_path,
4377 inq80.inq_serial, &serial_len);
4378 if (err) {
4379 fprintf(stderr, "\n");
4380 print_errString(err, path_struct->p_physical_path);
4381 fprintf(stderr, "\n");
4382 exit(1);
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;
4413 if (num_blks) {
4414 num_blks /= 2048; /* get Mbytes */
4415 (void) fprintf(stdout, "\n ");
4416 (void) fprintf(stdout,
4417 MSGSTR(60,
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"));
4433 } else {
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;
4442 if (pg8_buf->wce) {
4443 (void) fprintf(stdout,
4444 MSGSTR(2122,
4445 " Write Cache:\t\t"
4446 "Enabled\n"));
4448 if (pg8_buf->rcd == 0) {
4449 (void) fprintf(stdout,
4450 MSGSTR(2123,
4451 " Read Cache:\t\t"
4452 "Enabled\n"));
4453 (void) fprintf(stdout,
4454 MSGSTR(2320,
4455 " Minimum prefetch:"
4456 "\t0x%x\n"
4457 " Maximum prefetch:"
4458 "\t0x%x\n"),
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);
4493 } else {
4494 (void) fprintf(stdout, MSGSTR(2239,
4495 "In slot %d in the enclosure named: %s\n"),
4496 path_struct->slot + (MAX_DRIVES_DAK/2),
4497 name_buf);
4499 } else { /* Default enclosure type */
4500 (void) fprintf(stdout, path_struct->f_flag ?
4501 MSGSTR(2126,
4502 "In slot %d in the Front of the enclosure named: %s\n")
4503 : MSGSTR(2127,
4504 "In slot %d in the Rear of the enclosure named: %s\n"),
4505 path_struct->slot, name_buf);
4507 } else {
4508 (void) fprintf(stdout, MSGSTR(2228,
4509 "In the enclosure named: %s\n"),
4510 name_buf);
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);
4524 } else {
4525 while (mlist) {
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) {
4534 port_a = PORT_A;
4535 port_b = PORT_B;
4536 } else {
4537 port_a = FC_PORT_A;
4538 port_b = FC_PORT_B;
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.
4557 * RETURNS:
4558 * none.
4560 void
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.
4586 * RETURNS:
4587 * none.
4589 void
4590 disp_degree(Temp_elem_st *temp)
4592 int t;
4594 t = temp->degrees;
4595 t -= 20; /* re-adjust */
4597 * NL_Comment
4598 * The %c is the degree symbol.
4600 (void) fprintf(stdout, ":%1.2d%cC ", t, 186);
4606 * trans_decode() Display tranceivers state.
4608 * RETURNS:
4609 * none.
4611 void
4612 trans_decode(Trans_elem_st *trans)
4614 if (trans->disabled) {
4615 (void) fprintf(stdout, ": ");
4616 (void) fprintf(stdout, MSGSTR(34,
4617 "Disabled"));
4619 if (trans->lol) {
4620 (void) fprintf(stdout, MSGSTR(2133,
4621 ": Not receiving a signal"));
4623 if (trans->lsr_fail) {
4624 (void) fprintf(stdout, MSGSTR(2134,
4625 ": Laser failed"));
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
4637 * 0 and 1.
4639 * RETURNS:
4640 * none.
4642 void
4643 trans_messages(struct l_state_struct *l_state, int ib_a_flag)
4645 Trans_elem_st trans;
4646 int i, j, k;
4647 int count = 0;
4648 int elem_index = 0;
4650 /* Get and print messages */
4651 for (i = 0; i < (int)l_state->ib_tbl.config.enc_num_elem; i++) {
4652 elem_index++;
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]);
4659 count = k = 0;
4661 for (j = 0; j <
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));
4672 if (k == 0) {
4673 (void) fprintf(stdout, "\t\t%d ", k);
4674 } else {
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);
4694 } else {
4695 (void) fprintf(stdout,
4696 MSGSTR(4, "Unknown status"));
4698 k++;
4700 count++;
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.
4716 * RETURNS:
4717 * none.
4719 void
4720 temperature_messages(struct l_state_struct *l_state, int rear_flag)
4722 Temp_elem_st temp;
4723 int i, j, last_ok = 0;
4724 int all_ok = 1;
4725 int elem_index = 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) {
4731 if (!rear_flag) {
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));
4744 for (j = 0; j <
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) &&
4755 all_ok) {
4756 (void) fprintf(stdout, "\n\t %d", j);
4757 } else if (last_ok && (temp.code == S_OK)) {
4758 (void) fprintf(stdout, "%d", j);
4759 } else {
4760 (void) fprintf(stdout, "\n\t\t%d", j);
4762 if (temp.code == S_OK) {
4763 disp_degree(&temp);
4764 if (temp.ot_fail || temp.ot_warn ||
4765 temp.ut_fail || temp.ut_warn) {
4766 temp_decode(&temp);
4767 all_ok = 0;
4768 last_ok = 0;
4769 } else {
4770 last_ok++;
4772 } else if (temp.code == S_CRITICAL) {
4773 (void) fprintf(stdout,
4774 MSGSTR(122, "Critical failure"));
4775 last_ok = 0;
4776 all_ok = 0;
4777 } else if (temp.code == S_NONCRITICAL) {
4778 (void) fprintf(stdout,
4779 MSGSTR(89, "Non-Critical Failure"));
4780 last_ok = 0;
4781 all_ok = 0;
4782 } else if (temp.code == S_NOT_INSTALLED) {
4783 (void) fprintf(stdout,
4784 MSGSTR(30, "Not Installed"));
4785 last_ok = 0;
4786 all_ok = 0;
4787 } else if (temp.code == S_NOT_AVAILABLE) {
4788 (void) fprintf(stdout,
4789 MSGSTR(34, "Disabled"));
4790 last_ok = 0;
4791 all_ok = 0;
4792 } else {
4793 (void) fprintf(stdout,
4794 MSGSTR(4, "Unknown status"));
4795 last_ok = 0;
4796 all_ok = 0;
4799 if (all_ok) {
4800 (void) fprintf(stdout,
4801 MSGSTR(2136, " (All temperatures are "
4802 "NORMAL.)"));
4804 all_ok = 1;
4805 (void) fprintf(stdout, "\n");
4806 } else {
4807 rear_flag = 0;
4810 elem_index += l_state->ib_tbl.config.type_hdr[i].num;
4817 * ib_decode() Display IB byte 3 state.
4819 * RETURNS:
4820 * none.
4822 void
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.
4845 * RETURNS:
4846 * none.
4848 void
4849 mb_messages(struct l_state_struct *l_state, int index, int elem_index)
4851 int j;
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;
4859 j++) {
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"));
4876 } else {
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"));
4885 } else {
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);
4894 } else {
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.
4910 * RETURNS:
4911 * none.
4913 void
4914 back_plane_messages(struct l_state_struct *l_state, int index, int elem_index)
4916 Bp_elem_st bp;
4917 int j;
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;
4925 j++) {
4926 (void) bcopy((const void *)
4927 &l_state->ib_tbl.p2_s.element[elem_index + j],
4928 (void *)&bp, sizeof (bp));
4929 if (j == 0) {
4930 (void) fprintf(stdout,
4931 MSGSTR(2144, "\tFront Backplane: "));
4932 } else {
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);
4961 } else {
4962 (void) fprintf(stdout, "\n");
4969 * dpm_SSC100_messages() Display SSC100 messages
4970 * including the temperature's.
4972 * RETURNS:
4973 * none.
4975 void
4976 dpm_SSC100_messages(struct l_state_struct *l_state, int index, int elem_index)
4978 Bp_elem_st bp;
4979 int j;
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;
4987 j++) {
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");
5016 } else {
5017 (void) fprintf(stdout, "\n");
5020 temperature_messages(l_state, 0);
5027 * loop_messages() Display loop messages.
5029 * RETURNS:
5030 * none.
5032 void
5033 loop_messages(struct l_state_struct *l_state, int index, int elem_index)
5035 Loop_elem_st loop;
5036 int j;
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;
5043 j++) {
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");
5049 if (j == 0) {
5050 if (loop.code == S_NOT_INSTALLED) {
5051 (void) fprintf(stdout,
5052 MSGSTR(2147, "Loop A is not installed"));
5053 } else {
5054 if (loop.split) {
5055 (void) fprintf(stdout, MSGSTR(2148,
5056 "Loop A is configured as two separate loops."));
5057 } else {
5058 (void) fprintf(stdout, MSGSTR(2149,
5059 "Loop A is configured as a single loop."));
5062 } else {
5063 if (loop.code == S_NOT_INSTALLED) {
5064 (void) fprintf(stdout,
5065 MSGSTR(2150, "Loop B is not installed"));
5066 } else {
5067 if (loop.split) {
5068 (void) fprintf(stdout, MSGSTR(2151,
5069 "Loop B is configured as two separate loops."));
5070 } else {
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.
5085 * RETURNS:
5086 * none.
5088 void
5089 ctlr_messages(struct l_state_struct *l_state, int index, int elem_index)
5091 Ctlr_elem_st ctlr;
5092 int j;
5093 int ib_a_flag = 1;
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;
5100 j++) {
5101 (void) bcopy((const void *)
5102 &l_state->ib_tbl.p2_s.element[elem_index + j],
5103 (void *)&ctlr, sizeof (ctlr));
5104 if (j == 0) {
5105 (void) fprintf(stdout, MSGSTR(2153, "\tA: "));
5106 } else {
5107 (void) fprintf(stdout, MSGSTR(2154, "\tB: "));
5108 ib_a_flag = 0;
5110 if (ctlr.code == S_OK) {
5111 (void) fprintf(stdout, MSGSTR(29, "O.K."));
5112 /* If any byte 3 bits set display */
5113 ib_decode(&ctlr);
5114 /* Display Version message */
5115 revision_msg(l_state, elem_index + j);
5117 * Display the tranciver module state for this
5118 * IB.
5120 trans_messages(l_state, ib_a_flag);
5121 } else if (ctlr.code == S_CRITICAL) {
5122 (void) fprintf(stdout,
5123 MSGSTR(122, "Critical failure"));
5124 ib_decode(&ctlr);
5125 (void) fprintf(stdout, "\n");
5126 } else if (ctlr.code == S_NONCRITICAL) {
5127 (void) fprintf(stdout,
5128 MSGSTR(89, "Non-Critical Failure"));
5129 ib_decode(&ctlr);
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");
5139 } else {
5140 (void) fprintf(stdout,
5141 MSGSTR(4, "Unknown status"));
5142 (void) fprintf(stdout, "\n");
5150 * fan_decode() Display Fans bytes 1-3 state.
5152 * RETURNS:
5153 * none.
5155 void
5156 fan_decode(Fan_elem_st *fan)
5158 if (fan->fail) {
5159 (void) fprintf(stdout, MSGSTR(2155,
5160 ":Yellow LED is on"));
5162 if (fan->speed == 0) {
5163 (void) fprintf(stdout, MSGSTR(2156,
5164 ":Fan stopped"));
5165 } else if (fan->speed < S_HI_SPEED) {
5166 (void) fprintf(stdout, MSGSTR(2157,
5167 ":Fan speed Low"));
5168 } else {
5169 (void) fprintf(stdout, MSGSTR(2158,
5170 ":Fan speed Hi"));
5175 * fan_messages() Display Fan status.
5177 * RETURNS:
5178 * none.
5180 void
5181 fan_messages(struct l_state_struct *l_state, int hdr_index, int elem_index)
5183 Fan_elem_st fan;
5184 int j;
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;
5192 j++) {
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"));
5203 fan_decode(&fan);
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"));
5208 fan_decode(&fan);
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);
5217 } else {
5218 (void) fprintf(stdout,
5219 MSGSTR(4, "Unknown status"));
5222 (void) fprintf(stdout, "\n");
5228 * ps_decode() Display Power Supply bytes 1-3 state.
5230 * RETURNS:
5231 * none.
5233 void
5234 ps_decode(Ps_elem_st *ps)
5236 if (ps->dc_over) {
5237 (void) fprintf(stdout, MSGSTR(2159,
5238 ": DC Voltage too high"));
5240 if (ps->dc_under) {
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"));
5252 if (ps->ac_fail) {
5253 (void) fprintf(stdout, MSGSTR(2163,
5254 ": AC Failed"));
5256 if (ps->dc_fail) {
5257 (void) fprintf(stdout, MSGSTR(2164,
5258 ": DC Failed"));
5265 * revision_msg() Print the revision message from page 7.
5267 * RETURNS:
5268 * none.
5270 void
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.
5285 * RETURNS:
5286 * none.
5288 void
5289 ps_messages(struct l_state_struct *l_state, int index, int elem_index)
5291 Ps_elem_st ps;
5292 int j;
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;
5302 j++) {
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"));
5313 ps_decode(&ps);
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"));
5318 ps_decode(&ps);
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);
5327 } else {
5328 (void) fprintf(stdout,
5329 MSGSTR(4, "Unknown status"));
5333 (void) fprintf(stdout, "\n");
5339 * abnormal_condition() Display any abnormal condition messages.
5341 * RETURNS:
5342 * none.
5344 void
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,
5351 MSGSTR(2165, " "
5352 "CRITICAL CONDITION DETECTED\n"));
5354 if (l_state->ib_tbl.p2_s.ui.non_crit) {
5355 (void) fprintf(stdout,
5356 MSGSTR(2166, " "
5357 "WARNING: NON-CRITICAL CONDITION DETECTED\n"));
5359 if (l_state->ib_tbl.p2_s.ui.invop) {
5360 (void) fprintf(stdout,
5361 MSGSTR(2167, " "
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
5378 * of SENA devices.
5380 * RETURNS:
5381 * none.
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"),
5397 *argv);
5398 if (err != -1) {
5399 (void) print_errString(err, *argv);
5401 (argv)++;
5402 retval++;
5403 continue;
5405 VERBPRINT(MSGSTR(101, "Issuing start to:\n %s\n"), *argv);
5406 if (err = g_start(path_phys)) {
5407 (void) print_errString(err, *argv);
5408 (argv)++;
5409 retval++;
5410 continue;
5412 (argv)++;
5414 return (retval);
5420 * adm_stop() Spin down a
5421 * given list of SENA devices.
5423 * RETURNS:
5424 * none.
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,
5437 MSGSTR(33,
5438 " Error: converting"
5439 " %s to physical path.\n"
5440 " Invalid pathname.\n"),
5441 *argv);
5442 if (err != -1) {
5443 (void) print_errString(err, *argv);
5445 (argv)++;
5446 retval++;
5447 continue;
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)) {
5459 errno = ENOTSUP;
5460 (void) print_errString(0, path_phys);
5461 (argv)++;
5462 continue;
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);
5468 (argv)++;
5469 retval++;
5470 continue;
5472 (argv)++;
5474 return (retval);
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.
5484 * INPUT :
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.
5487 * For example :
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
5491 * RETURNS :
5492 * Nothing
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,
5506 MSGSTR(33,
5507 " Error: converting"
5508 " %s to physical path.\n"
5509 " Invalid pathname.\n"),
5510 *argv);
5511 if (err != -1) {
5512 (void) print_errString(err, *argv);
5514 argv++;
5515 retval++;
5516 continue;
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);
5522 retval++;
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);
5529 retval++;
5530 goto cleanup_and_go;
5532 fprintf(stdout,
5533 MSGSTR(2223, "Port %s has been disabled\n"),
5534 nexus_path_ptr);
5535 } else if (flag == LUX_P_ONLINE) {
5536 if ((err = g_port_online(nexus_path_ptr))) {
5537 (void) print_errString(err, nexus_path_ptr);
5538 retval++;
5539 goto cleanup_and_go;
5541 fprintf(stdout,
5542 MSGSTR(2224, "Port %s has been enabled\n"),
5543 nexus_path_ptr);
5544 } else {
5545 (void) fprintf(stderr,
5546 MSGSTR(2225,
5547 "Unknown action requested "
5548 "on port - %d\nIgnoring."),
5549 flag);
5550 retval++;
5552 cleanup_and_go:
5553 free(path_phys);
5554 free(path_struct);
5555 free(nexus_path_ptr);
5556 argv++;
5558 return (retval);
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",
5594 "fp",
5595 "ifp",
5596 NULL};
5597 portlist_t portlist;
5598 int x = 0, err = 0, retval = 0;
5599 int port_state;
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]);
5611 retval++;
5614 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]);
5626 retval++;
5627 } else {
5628 fprintf(stdout, "%-65s ", portlist.physpath[x]);
5629 if (port_state == PORT_CONNECTED) {
5630 (void) fprintf(stdout,
5631 MSGSTR(2233,
5632 "CONNECTED\n"));
5633 } else {
5634 (void) fprintf(stdout,
5635 MSGSTR(2234,
5636 "NOT CONNECTED\n"));
5640 g_free_portlist(&portlist);
5641 return (retval);
5645 * Expert level subcommand 'luxadm -e external_loopback <portpath>
5646 * internal_loopback
5647 * no_loopback
5648 * Does just what you would think. Sets port in designated loopback
5649 * mode.
5650 * INPUT: portpath - path to device on which to set loopback mode
5651 * flag - loopback mode to set. Values are:
5652 * EXT_LOOPBACK
5653 * INT_LOOPBACK
5654 * NO_LOOPBACK
5656 * RETURN: 0 on success
5657 * non-zero on failure
5660 adm_port_loopback(char *portpath, int flag)
5662 int err;
5663 char *path_phys = NULL;
5664 Path_struct *path_struct = NULL;
5665 int cmd;
5667 if ((err = l_convert_name(portpath, &path_phys,
5668 &path_struct, Options & PVERBOSE)) != 0) {
5669 (void) fprintf(stderr,
5670 MSGSTR(33,
5671 " Error: converting"
5672 " %s to physical path.\n"
5673 " Invalid pathname.\n"),
5674 portpath);
5675 if (err != -1) {
5676 (void) print_errString(err, portpath);
5678 return (-1);
5681 switch (flag) {
5682 case EXT_LOOPBACK:
5683 cmd = EXT_LPBACK;
5684 break;
5685 case INT_LOOPBACK:
5686 cmd = INT_LPBACK;
5687 break;
5688 case NO_LOOPBACK:
5689 cmd = NO_LPBACK;
5690 break;
5691 default:
5692 (void) fprintf(stderr,
5693 MSGSTR(2225,
5694 "Unknown action requested "
5695 "on port - %d\nIgnoring."),
5696 flag);
5697 free(path_phys);
5698 free(path_struct);
5699 return (-1);
5703 if ((err = g_loopback_mode(path_phys, cmd)) != 0) {
5704 (void) print_errString(err, portpath);
5705 free(path_phys);
5706 free(path_struct);
5707 return (-1);
5708 } else {
5709 switch (flag) {
5710 case EXT_LOOPBACK:
5711 (void) fprintf(stdout,
5712 MSGSTR(2230,
5713 "External loopback mode set "
5714 "on:\n%s\n"),
5715 portpath);
5716 break;
5717 case INT_LOOPBACK:
5718 (void) fprintf(stdout,
5719 MSGSTR(2231,
5720 "Internal loopback mode set "
5721 "on:\n%s\n"),
5722 portpath);
5723 break;
5724 case NO_LOOPBACK:
5725 (void) fprintf(stdout,
5726 MSGSTR(2232,
5727 "Loopback mode unset "
5728 "on:\n%s\n"),
5729 portpath);
5730 break;
5731 default:
5732 fprintf(stderr,
5733 MSGSTR(2248, "Undefined command\n"));
5734 break;
5737 free(path_phys);
5738 free(path_struct);
5739 return (0);
5745 * To print the pathlist and mpxio path attributes
5747 void
5748 adm_print_pathlist(char *dev_path)
5750 int i, pathcnt = 1;
5751 mp_pathlist_t pathlist;
5752 int retval = 0;
5753 char temppath[MAXPATHLEN];
5754 char wwns[(WWN_SIZE *2) +1];
5755 uchar_t wwn_data[WWN_SIZE];
5756 int err;
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);
5768 if (retval != 0) {
5769 (void) print_errString(retval, NULL);
5770 exit(-1);
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);
5788 exit(1);
5792 if (!err) {
5793 copy_wwn_data_to_str(wwns, wwn_data);
5794 (void) fprintf(stdout,
5795 MSGSTR(2326, " Host controller port WWN\t%s\n"),
5796 wwns);
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);
5812 exit(1);
5813 } else {
5814 if ((ext_state & MDI_PATHINFO_STATE_USER_DISABLE)
5815 == MDI_PATHINFO_STATE_USER_DISABLE) {
5816 ext_state = 0;
5817 fprintf(stdout,
5818 MSGSTR(2327,
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);
5829 * compare_multipath
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) {
5839 return (0);
5841 pathlist = pathlist->next;
5843 return (1);
5847 * lun_display() Prints the
5848 * information for an individual lun.
5850 * RETURNS:
5851 * none.
5853 static int
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;
5866 int found = 0;
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) {
5884 return (err);
5886 } else {
5887 if ((err = g_get_wwn_list(&wwn_list, verbose)) != 0) {
5888 return (err);
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;
5901 argpwwn = 1;
5902 break;
5903 } else if (strcasecmp(wwn_list_ptr->node_wwn_s,
5904 path_struct->argv) == 0) {
5905 list_start = wwn_list_ptr;
5906 argnwwn = 1;
5907 break;
5911 for (wwn_list_ptr = list_start; wwn_list_ptr != NULL;
5912 wwn_list_ptr = wwn_list_ptr->wwn_next) {
5915 if (argpwwn) {
5916 if (strcasecmp(wwn_list_ptr->port_wwn_s,
5917 path_struct->argv) != 0) {
5918 continue;
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) {
5924 continue;
5926 if (strcasecmp(wwn_list_ptr->node_wwn_s,
5927 path_struct->argv) != 0) {
5928 continue;
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,
5937 mplistp) == 0) {
5938 continue;
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) {
5954 return (err);
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);
5965 } else {
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))
5971 == 0) {
5972 found++;
5973 break;
5977 if (!found) {
5978 return (L_NO_VALID_PATH);
5979 } else {
5980 found = 0;
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)))
6007 == NULL) {
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;
6021 } else {
6022 mpln->next = mpl;
6023 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 *)
6031 (void *)pg_buf;
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)) &&
6038 !mode_data_avail) {
6039 if (pg_hdr->code == MODEPAGE_CACHING) {
6040 mode_data_avail++;
6041 break;
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)) {
6049 case DTYPE_DIRECT:
6050 fprintf(stdout, MSGSTR(121, "DEVICE PROPERTIES for disk: %s\n"),
6051 path_struct->argv);
6052 break;
6053 case DTYPE_SEQUENTIAL: /* Tape */
6054 fprintf(stdout, MSGSTR(2249, "DEVICE PROPERTIES for tape: %s\n"),
6055 path_struct->argv);
6056 break;
6057 default:
6058 fprintf(stdout, MSGSTR(2250, "DEVICE PROPERTIES for: %s\n"),
6059 path_struct->argv);
6060 break;
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)) {
6069 break;
6072 } /* End for wwn_list_ptr = list_start... */
6074 (void) g_free_wwn_list(&wwn_list);
6075 adm_mplist_free(mplistp);
6076 return (0);
6080 * display_lun_info() Prints the device specific information
6081 * for a lun.
6083 * RETURNS:
6084 * none.
6086 void
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)
6091 float lunMbytes;
6092 struct scsi_capacity_16 cap_data;
6093 struct dlist *mlist;
6094 struct my_mode_caching *pg8_buf;
6095 int err;
6096 L_inquiry inq;
6097 hrtime_t start_time, end_time;
6098 char *envdb = NULL;
6099 int peripheral_qual;
6100 L_inquiry80 inq80;
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");
6113 exit(1);
6116 if (err = g_get_serial_number(phys_path, inq80.inq_serial,
6117 &serial_len)) {
6118 fprintf(stderr, "\n");
6119 print_errString(err, phys_path);
6120 fprintf(stderr, "\n");
6121 exit(1);
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);
6131 exit(1);
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);
6154 exit(1);
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;
6171 if (pg8_buf->wce) {
6172 fprintf(stdout, MSGSTR(2122, " Write Cache:\t\t"
6173 "Enabled\n"));
6175 if (pg8_buf->rcd == 0) {
6176 fprintf(stdout, MSGSTR(2123, " Read Cache:\t\t"
6177 "Enabled\n"));
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)"),
6194 path_struct->argv);
6195 exit(1);
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);
6203 } else {
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))
6211 == 0) {
6212 display_path_info(mlist->dev_path, mlist->logical_path,
6213 wwn_list);
6214 break;
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))
6225 == 0) {
6226 continue;
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");
6232 exit(1);
6234 display_path_info(mlist->dev_path, mlist->logical_path,
6235 wwn_list);
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
6250 * for a lun.
6251 * Note: Only applies to ssd nodes currently
6253 * RETURNS:
6254 * none.
6256 static void
6257 display_path_info(char *devpath, char *logicalpath, WWN_list *wwn_list)
6259 WWN_list *wwn_list_walk;
6260 int err;
6261 uchar_t wwn_data[WWN_SIZE];
6262 char wwns[(WWN_SIZE *2) +1];
6263 char drvr_path[MAXPATHLEN];
6264 char *cptr;
6265 int status;
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);
6279 break;
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)) {;
6291 *cptr = '\0';
6292 } else {
6293 fprintf(stderr, MSGSTR(2324, "Error: Incorrect path (%s)\n"),
6294 drvr_path);
6295 exit(1);
6297 *cptr = '\0';
6299 if ((err = get_host_controller_pwwn(drvr_path,
6300 (uchar_t *)&wwn_data)) != 0) {
6301 print_errString(err, drvr_path);
6302 exit(1);
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);
6314 exit(1);
6315 } else {
6316 fprintf(stdout, " %s\t\t", MSGSTR(2329, "Path status:"));
6317 display_port_status(status);
6322 * Retrieves the lun capacity
6324 static int
6325 get_lun_capacity(char *devpath, struct scsi_capacity_16 *cap_data)
6327 int fd;
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);
6335 } else {
6336 (void) g_scsi_read_capacity_1016_cmd(fd, cap_data,
6337 sizeof (struct scsi_capacity_16));
6338 close(fd);
6340 return (0);
6344 * Retrieves the reservation status
6346 static int
6347 get_path_status(char *devpath, int *status)
6349 int fd, mystatus = 0;
6352 if (devpath == NULL || status == NULL) {
6353 return (L_INVALID_PATH);
6356 *status = 0;
6357 if ((fd = g_object_open(devpath, O_RDONLY | O_NDELAY)) == -1) {
6358 return (L_OPEN_PATH_FAIL);
6359 } else {
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;
6368 } else {
6369 *status = L_SCSI_ERR;
6373 close(fd);
6374 return (0);
6378 * Description:
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
6384 static int
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];
6390 di_node_t node;
6391 di_prom_prop_t promprop;
6392 uchar_t *port_wwn_data = NULL;
6393 int di_ret;
6394 di_prom_handle_t ph;
6395 char *promname;
6396 uchar_t *promdata;
6397 uint_t path_type;
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",
6425 hba_path, FC_CTLR);
6426 if ((err = g_get_host_params(
6427 my_hba_path, &hba_port, 0)) != 0) {
6428 return (err);
6429 } else {
6430 (void) memcpy(pwwn, &hba_port.dev_pwwn.raw_wwn[0],
6431 WWN_SIZE);
6432 return (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];
6445 } else {
6446 return (L_INVALID_PATH);
6450 * Now strip off the trailing "/fp@"
6452 if ((portptr = strstr(cptr, "/fp@")) != NULL) {
6453 *portptr = '\0';
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) {
6464 di_fini(node);
6465 return (L_NO_WWN_PROP_FOUND);
6466 } else {
6467 (void) memcpy(pwwn, port_wwn_data, WWN_SIZE);
6468 found++;
6470 } else if (di_nodeid(node) == DI_PROM_NODEID) {
6471 if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) {
6472 di_fini(node);
6473 return (L_PROM_INIT_FAILED);
6476 for (promprop = di_prom_prop_next(ph, node,
6477 DI_PROM_PROP_NIL);
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);
6487 found++;
6488 break;
6491 di_prom_fini(ph);
6494 di_fini(node);
6495 if (found) {
6496 return (0);
6497 } else {
6498 return (L_INVALID_PATH);
6500 } else {
6501 return (L_INVALID_PATH_TYPE);
6507 * Description:
6508 * Retrieve pwwn via SFIOCGMAP
6510 static int
6511 get_FC4_host_controller_pwwn(char *hba_path, uchar_t *pwwn)
6513 sf_al_map_t sf_map;
6514 char my_hba_path[MAXPATHLEN];
6515 int fd;
6517 if (hba_path == NULL || pwwn == NULL) {
6518 return (L_INVALID_PATH);
6521 (void) snprintf(my_hba_path, sizeof (my_hba_path), "%s%s",
6522 hba_path, FC_CTLR);
6524 if ((fd = g_object_open(my_hba_path, O_NDELAY | O_RDONLY)) == -1) {
6525 return (errno);
6528 memset(&sf_map, 0, sizeof (sf_al_map_t));
6530 if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
6531 close(fd);
6532 return (L_SFIOCGMAP_IOCTL_FAIL);
6535 close(fd);
6537 if (sf_map.sf_count == 0) {
6538 close(fd);
6539 return (L_SFIOCGMAP_IOCTL_FAIL);
6542 (void) memcpy(pwwn, &sf_map.sf_hba_addr.sf_port_wwn[0], WWN_SIZE);
6544 return (0);
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
6551 void
6552 copy_wwn_data_to_str(char *to_ptr, const uchar_t *from_ptr)
6554 if ((to_ptr == NULL) || (from_ptr == NULL))
6555 return;
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
6565 void
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;
6576 free(mplistp);
6577 mplistp = mplistn;
6582 adm_reserve(char *path)
6584 char *path_phys = NULL;
6585 int err;
6586 if ((path_phys =
6587 g_get_physical_name(path)) == NULL) {
6589 (void) fprintf(stderr, "%s: ", whoami);
6590 (void) fprintf(stderr,
6591 MSGSTR(112, "Error: Invalid pathname (%s)"),
6592 path);
6593 (void) fprintf(stderr, "\n");
6594 return (1);
6597 if ((err = g_reserve(path_phys)) != 0) {
6598 (void) print_errString(err, path);
6599 return (1);
6601 return (0);
6605 adm_release(char *path)
6607 char *path_phys = NULL;
6608 int err;
6609 if ((path_phys =
6610 g_get_physical_name(path)) == NULL) {
6612 (void) fprintf(stderr, "%s: ", whoami);
6613 (void) fprintf(stderr,
6614 MSGSTR(112, "Error: Invalid pathname (%s)"),
6615 path);
6616 (void) fprintf(stderr, "\n");
6617 return (1);
6620 if ((err = g_release(path_phys)) != 0) {
6621 (void) print_errString(err, path);
6622 return (1);
6624 return (0);
6627 void
6628 i18n_catopen() {
6629 (void) g_i18n_catopen();
6632 int adm_check_file(char **path, int flag) {
6633 int err;
6634 if (err = l_check_file(*path, flag)) {
6635 (void) print_errString(err, *path);
6636 return (-1);
6639 (void) fprintf(stdout, MSGSTR(2212, "Download file O.K. \n\n"));
6640 return (0);
6644 * Print out private loop dev dtype
6646 void
6647 print_private_loop_dtype_prop(uchar_t *hba_port_wwn, uchar_t *port_wwn,
6648 uchar_t dtype_prop)
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));
6657 } else {
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)) {
6663 /* MATCH */
6664 (void) fprintf(stdout, MSGSTR(2244,
6665 ",Host Bus Adapter)\n"));
6666 } else {
6667 (void) fprintf(stdout, ")\n");