1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27
28 #define LUX_SF_INST_SHIFT4MINOR 6
29 #define LUX_SF_MINOR2INST(x) (x >> LUX_SF_INST_SHIFT4MINOR)
30
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"
60
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;
81
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);
127
128 /*
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.
133 *
134 * RETURNS:
135 * 0 O.K.
136 * non-zero otherwise
137 */
138 int
print_devState(char * devname,char * ppath,int fr_flag,int slot,int verbose_flag)139 print_devState(char *devname, char *ppath, int fr_flag, int slot,
140 int verbose_flag)
141 {
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;
147
148
149 if ((err = l_get_status(ppath, &l_state, verbose_flag)) != 0) {
150 (void) print_errString(err, ppath);
151 return (err);
152 }
153
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;
158 }
159 elem_index += l_state.ib_tbl.config.type_hdr[i].num;
160 }
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));
167
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;
178 }
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);
217 }
218 return (-1);
219 }
220
221 /*
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.
229 *
230 * RETURNS: N/A
231 *
232 */
233 void
print_errString(int errnum,char * devpath)234 print_errString(int errnum, char *devpath)
235 {
236
237 char *errStr;
238
239 errStr = g_get_errString(errnum);
240
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);
247 }
248
249 /* free the allocated memory for error string */
250 if (errStr != NULL)
251 (void) free(errStr);
252 }
253
254 /*
255 * adm_inquiry() Display the inquiry information for
256 * a SENA enclosure(s) or disk(s).
257 *
258 * RETURNS:
259 * none.
260 */
261 int
adm_inquiry(char ** argv)262 adm_inquiry(char **argv)
263 {
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];
274
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;
287 }
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]);
303 }
304 path_index++;
305 retval++;
306 continue;
307 }
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;
314 }
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");
324 }
325 }
326 path_index++;
327 retval++;
328 continue;
329 }
330
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;
339 }
340
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;
350 }
351 print_inq_data(argv[path_index], path_phys, inq,
352 inq80.inq_serial, serial_len);
353 path_index++;
354 continue;
355 }
356 if ((err = g_get_wwn_list(&wwn_list, 0)) != 0) {
357 return (err);
358 }
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;
375 }
376 }
377
378 if (!(argpwwn || argnwwn)) {
379 /*
380 * if the wwn list is null or the arg device not found
381 * from the wwn list, still go ahead to issue inquiry.
382 */
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;
390 }
391
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;
401 }
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;
407 }
408
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;
415 }
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;
422 }
423 if (strstr(wwn_list_ptr->logical_path,
424 last_logical_path) != NULL) {
425 continue;
426 }
427 (void) strcpy(path_phys,
428 wwn_list_ptr->physical_path);
429 (void) strcpy(last_logical_path,
430 wwn_list_ptr->logical_path);
431 }
432
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;
439 }
440
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;
449 }
450 print_inq_data(argv[path_index], path_phys, inq,
451 inq80.inq_serial, serial_len);
452
453 }
454
455 (void) g_free_wwn_list(&wwn_list);
456 path_index++;
457 }
458 return (retval);
459 }
460
461 /*
462 * FORCELIP expert function
463 */
464 int
adm_forcelip(char ** argv)465 adm_forcelip(char **argv)
466 {
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];
471
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;
481 }
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]);
500 }
501 path_index++;
502 retval++;
503 continue;
504 }
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;
511 }
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");
518 }
519 path_index++;
520 retval++;
521 continue;
522 }
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;
528 }
529 path_index++;
530 if (path_struct != NULL) {
531 (void) free(path_struct);
532 }
533 }
534 return (retval);
535 }
536
537
538 /*
539 * DISPLAY function
540 *
541 * RETURNS:
542 * 0 O.K.
543 */
544 int
adm_display_config(char ** argv)545 adm_display_config(char **argv)
546 {
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];
554
555
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) {
563
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'))) {
568
569 if (err != -1) {
570 (void) print_errString(err,
571 argv[path_index]);
572 path_index++;
573 retval++;
574 continue;
575 }
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) {
582
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]);
592 }
593 path_index++;
594 retval++;
595 continue;
596 }
597
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;
604 }
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");
616 }
617 }
618
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");
630 }
631 }
632
633 path_index++;
634 retval++;
635 continue;
636 }
637
638 /*
639 * See what kind of device we are talking to.
640 */
641 if ((opnerr = g_get_inquiry(path_phys, &inq)) != 0) {
642 if (opnerr == L_OPEN_PATH_FAIL) {
643 /*
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().
649 *
650 */
651 (void) print_errString(errno, argv[path_index]);
652 path_index++;
653 retval++;
654 continue;
655 }
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);
662 }
663 } else if (strstr((char *)inq.inq_pid, ENCLOSURE_PROD_ID) != NULL) {
664 /*
665 * Display SENA enclosure.
666 */
667 (void) fprintf(stdout, "\n\t\t\t\t ");
668 print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0);
669
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);
676 }
677 } else if ((((inq.inq_dtype & DTYPE_MASK) == DTYPE_ESI)) &&
678 (l_get_enc_type(inq) == DAK_ENC_TYPE)) {
679 /*
680 * Display for the Daktari/DPM
681 */
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]);
685 }
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);
692 }
693 /*
694 * if device is in SENA enclosure
695 *
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
702 */
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);
718 }
719
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);
726 }
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);
738 }
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++;
755 }
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;
765 }
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");
774 }
775 path_index++;
776 if (map.dev_addr != NULL) {
777 free((void *)map.dev_addr);
778 }
779 (void) free(path_struct);
780 }
781 return (retval);
782 }
783
784
785 /*
786 * Powers off a list of SENA enclosure(s)
787 * and disk(s) which is provided by the user.
788 *
789 * RETURNS:
790 * none.
791 */
792 int
adm_power_off(char ** argv,int off_flag)793 adm_power_off(char **argv, int off_flag)
794 {
795 int path_index = 0, err = 0, retval = 0;
796 L_inquiry inq;
797 char *path_phys = NULL;
798 Path_struct *path_struct;
799
800 while (argv[path_index] != NULL) {
801 if ((err = l_convert_name(argv[path_index], &path_phys,
802 &path_struct, Options & PVERBOSE)) != 0) {
803 /*
804 * In case we did not find the device
805 * in the /devices directory.
806 *
807 * Only valid for pathnames like box,f1
808 */
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]);
821 }
822 path_index++;
823 retval++;
824 continue;
825 }
826 }
827 if (path_struct->ib_path_flag) {
828 /*
829 * We are addressing a disk using a path
830 * format type box,f1.
831 */
832 if (err = l_dev_pwr_up_down(path_phys,
833 path_struct, off_flag, Options & PVERBOSE,
834 Options & OPTION_CAPF)) {
835 /*
836 * Is it Bypassed... try to give more
837 * informtaion.
838 */
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++;
844 }
845 path_index++;
846 continue;
847 }
848
849 if (err = g_get_inquiry(path_phys, &inq)) {
850 (void) print_errString(err, argv[path_index]);
851 path_index++;
852 retval++;
853 continue;
854 }
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))) {
859
860 if (get_enclStatus(path_phys, argv[path_index],
861 off_flag) != 0) {
862 path_index++;
863 retval++;
864 continue;
865 }
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++;
872 }
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++;
879 }
880 } else {
881 /*
882 * SSA section:
883 */
884 (void) print_errString(L_INVALID_PATH,
885 argv[path_index]);
886 }
887 path_index++;
888 }
889 return (retval);
890 }
891
892
893
894 void
adm_bypass_enable(char ** argv,int bypass_flag)895 adm_bypass_enable(char **argv, int bypass_flag)
896 {
897 int path_index = 0, err = 0;
898 L_inquiry inq;
899 char *path_phys = NULL;
900 Path_struct *path_struct;
901
902 if ((err = l_convert_name(argv[path_index], &path_phys,
903 &path_struct, Options & PVERBOSE)) != 0) {
904 /*
905 * In case we did not find the device
906 * in the /devices directory.
907 *
908 * Only valid for pathnames like box,f1
909 */
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]);
921 }
922 exit(-1);
923 }
924 }
925 if (path_struct->ib_path_flag) {
926 if (Options & OPTION_F) {
927 E_USEAGE();
928 exit(-1);
929 }
930 /*
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.
936 */
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);
943 }
944 return;
945 }
946
947 if (err = g_get_inquiry(path_phys, &inq)) {
948 (void) print_errString(err, argv[path_index]);
949 exit(-1);
950 }
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);
961 }
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);
969 }
970 } else if ((inq.inq_dtype & DTYPE_MASK) == DTYPE_DIRECT) {
971 if (Options & OPTION_F) {
972 E_USEAGE();
973 exit(-1);
974 }
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);
981 }
982 }
983 }
984
985 /*
986 * adm_download() Download subsystem microcode.
987 * Path must point to a LUX IB.
988 *
989 * RETURNS:
990 * None.
991 */
992 void
adm_download(char ** argv,char * file_name)993 adm_download(char **argv, char *file_name)
994 {
995 int path_index = 0, err = 0;
996 char *path_phys = NULL;
997 L_inquiry inq;
998 Path_struct *path_struct;
999
1000 while (argv[path_index] != NULL) {
1001 /*
1002 * See what kind of device we are talking to.
1003 */
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]);
1014 }
1015 exit(-1);
1016 }
1017 if (err = g_get_inquiry(path_phys, &inq)) {
1018 (void) print_errString(err, argv[path_index]);
1019 exit(-1);
1020 }
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);
1032 }
1033 } else {
1034 (void) fprintf(stderr,
1035 MSGSTR(112, "Error: Invalid pathname (%s)"),
1036 argv[path_index]);
1037 }
1038 path_index++;
1039 }
1040 }
1041
1042 /*
1043 * display_link_status() Reads and displays the link status.
1044 *
1045 * RETURNS:
1046 * none.
1047 */
1048 void
display_link_status(char ** argv)1049 display_link_status(char **argv)
1050 {
1051 AL_rls *rls = NULL, *n;
1052 int path_index = 0, err = 0;
1053 char *path_phys = NULL;
1054 Path_struct *path_struct;
1055
1056
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]);
1068 }
1069 exit(-1);
1070 }
1071 if (err = g_rdls(path_phys, &rls, Options & PVERBOSE)) {
1072 (void) print_errString(err, argv[path_index]);
1073 exit(-1);
1074 }
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"));
1084 }
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);
1111 }
1112 n = n->next;
1113 }
1114
1115 path_index++;
1116 }
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"));
1122 }
1123
1124
1125 /*
1126 * ib_present_chk() Check to see if IB 0 or 1 is present in the box.
1127 *
1128 * RETURN:
1129 * 1 if ib present
1130 * 0 otherwise
1131 */
1132 int
ib_present_chk(struct l_state_struct * l_state,int which_one)1133 ib_present_chk(struct l_state_struct *l_state, int which_one)
1134 {
1135 Ctlr_elem_st ctlr;
1136 int i;
1137 int elem_index = 0;
1138 int result = 1;
1139
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;
1148 }
1149 break;
1150 }
1151 elem_index += l_state->ib_tbl.config.type_hdr[i].num;
1152 }
1153 return (result);
1154 }
1155
1156 /*
1157 * print_individual_state() Print individual disk status.
1158 *
1159 * RETURNS:
1160 * none.
1161 */
1162 void
print_individual_state(int status,int port)1163 print_individual_state(int status, int port)
1164 {
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)"));
1203 }
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, ") ");
1209 }
1210 }
1211
1212
1213 /*
1214 * display_disk_msg() Displays status for
1215 * an individual SENA device.
1216 *
1217 * RETURNS:
1218 * none.
1219 */
1220 void
display_disk_msg(struct l_disk_state_struct * dsk_ptr,struct l_state_struct * l_state,Bp_elem_st * bp,int front_flag)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)
1223 {
1224 int loop_flag = 0;
1225 int a_and_b = 0;
1226 int state_a = 0, state_b = 0;
1227
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 " ");
1248 }
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 " ");
1279 }
1280 } else {
1281 (void) fprintf(stdout, MSGSTR(2020, "On"));
1282
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) {
1296 /*
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.
1300 */
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;
1333
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 ") ");
1367 }
1368 }
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, " ");
1376 }
1377 }
1378 if (front_flag) {
1379 (void) fprintf(stdout, " ");
1380 }
1381 }
1382
1383
1384
1385 /*
1386 * pho_display_config() Displays device status
1387 * information for a SENA enclosure.
1388 *
1389 * RETURNS:
1390 * none.
1391 */
1392 void
pho_display_config(char * path_phys)1393 pho_display_config(char *path_phys)
1394 {
1395 L_state l_state;
1396 Bp_elem_st bpf, bpr;
1397 int i, j, elem_index = 0, err = 0;
1398
1399
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);
1405 }
1406
1407 /*
1408 * Look for abnormal status.
1409 */
1410 if (l_state.ib_tbl.p2_s.ui.ab_cond) {
1411 abnormal_condition_display(&l_state);
1412 }
1413
1414 (void) fprintf(stdout,
1415 MSGSTR(2032, " DISK STATUS \n"
1416 "SLOT FRONT DISKS (Node WWN) "
1417 " REAR DISKS (Node WWN)\n"));
1418 /*
1419 * Print the status for each disk
1420 */
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;
1426 }
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));
1433
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");
1439 }
1440
1441
1442
1443 /*
1444 * Display the subsystem status.
1445 */
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]);
1458 }
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);
1464 }
1465
1466 /*
1467 *
1468 */
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:
1487 /*
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.
1492 */
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]);
1496 }
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;
1504
1505 }
1506 /*
1507 * Calculate the index to each element.
1508 */
1509 elem_index += l_state.ib_tbl.config.type_hdr[i].num;
1510 }
1511 (void) fprintf(stdout, "\n");
1512 }
1513
1514
1515
1516
1517 /*
1518 * dpm_display_config() Displays device status
1519 * information for a DAKTARI enclosure.
1520 *
1521 * RETURNS:
1522 * none.
1523 */
1524 void
dpm_display_config(char * path_phys)1525 dpm_display_config(char *path_phys)
1526 {
1527 L_state l_state;
1528 Bp_elem_st bpf, bpr;
1529 int i, j, elem_index = 0, err = 0, count;
1530
1531
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);
1537 }
1538
1539 /*
1540 * Look for abnormal status.
1541 */
1542 if (l_state.ib_tbl.p2_s.ui.ab_cond) {
1543 abnormal_condition_display(&l_state);
1544 }
1545
1546 (void) fprintf(stdout,
1547 MSGSTR(2247, " DISK STATUS \n"
1548 "SLOT DISKS (Node WWN) \n"));
1549 /*
1550 * Print the status for each disk
1551 */
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;
1557 }
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));
1564
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");
1571 }
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");
1576 }
1577
1578
1579 /*
1580 * Display the subsystem status.
1581 */
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]);
1588 }
1589 (void) fprintf(stdout, MSGSTR(2034, " Box ID:%d"),
1590 l_state.ib_tbl.box_id);
1591 (void) fprintf(stdout, "\n ");
1592
1593 (void) fprintf(stdout, MSGSTR(90, "Node WWN:"));
1594
1595 for (i = 0; i < 8; i++) {
1596 (void) fprintf(stdout, "%1.2x",
1597 l_state.ib_tbl.config.enc_node_wwn[i]);
1598 }
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);
1604 }
1605
1606 /*
1607 *
1608 */
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:
1627 /*
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.
1632 */
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]);
1636 }
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;
1647
1648 }
1649 /*
1650 * Calculate the index to each element.
1651 */
1652 elem_index += l_state.ib_tbl.config.type_hdr[i].num;
1653 }
1654 (void) fprintf(stdout, "\n");
1655 }
1656
1657
1658
1659
1660
1661
1662 /*
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.
1666 *
1667 */
1668 void
intfix(void)1669 intfix(void)
1670 {
1671 if (termio_fd) {
1672 termios.c_lflag |= ECHO;
1673 ioctl(termio_fd, TCSETS, &termios);
1674 }
1675 exit(SIGINT);
1676 }
1677
1678
1679 /*
1680 * up_password() Changes the password for SENA enclosure.
1681 *
1682 * RETURNS:
1683 * none.
1684 */
1685 void
up_password(char ** argv)1686 up_password(char **argv)
1687 {
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;
1696
1697
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);
1702 }
1703 ioctl(termio_fd, TCGETS, &termios);
1704 sig = sigset(SIGINT, (void (*)())intfix);
1705 /*
1706 * Make sure path valid and is to a PHO
1707 * before bothering operator.
1708 */
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]);
1719 }
1720 exit(-1);
1721 }
1722 if (err = g_get_inquiry(path_phys, &inq)) {
1723 (void) print_errString(err, argv[path_index]);
1724 exit(-1);
1725 }
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)))) {
1730 /*
1731 * Again this is like the ssaadm code in that the name
1732 * is still not defined before this code must be released.
1733 */
1734 (void) fprintf(stderr,
1735 MSGSTR(2037, "Error: Enclosure is not a %s\n"),
1736 ENCLOSURE_PROD_ID);
1737 exit(-1);
1738 }
1739 (void) fprintf(stdout,
1740 MSGSTR(2038,
1741 "Changing FPM password for subsystem %s\n"),
1742 argv[path_index]);
1743
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: "));
1750
1751 termios.c_lflag &= ~ECHO;
1752 ioctl(termio_fd, TCSETS, &termios);
1753
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);
1767 }
1768 }
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);
1775 }
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);
1783 }
1784 }
1785 if (i != j) {
1786 matched = -1;
1787 } else for (i = matched = 0; password[i]; i++) {
1788 if (password[i] == input[i]) {
1789 matched++;
1790 }
1791 }
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"));
1798 }
1799 }
1800 (void) fprintf(stdout, "\n");
1801 sscanf(input, "%s", password);
1802 (void) signal(SIGINT, sig); /* restore signal handler */
1803
1804 /* Send new password to IB */
1805 if (l_new_password(path_phys, input)) {
1806 (void) print_errString(err, path_phys);
1807 exit(-1);
1808 }
1809 }
1810
1811 /*
1812 * Call g_failover to process failover command
1813 */
1814 void
adm_failover(char ** argv)1815 adm_failover(char **argv)
1816 {
1817 int path_index = 0, err = 0;
1818 char pathclass[20];
1819 char *path_phys = NULL;
1820
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);
1828 }
1829
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);
1837 }
1838
1839 if (err = g_failover(path_phys, pathclass)) {
1840 (void) print_errString(err, NULL);
1841 exit(-1);
1842 }
1843 }
1844 }
1845
1846
1847
1848 /*
1849 * up_encl_name() Update the enclosures logical name.
1850 *
1851 * RETURNS:
1852 * none.
1853 */
1854 void
up_encl_name(char ** argv,int argc)1855 up_encl_name(char **argv, int argc)
1856 {
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;
1863
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);
1880 }
1881 }
1882
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);
1892 }
1893
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]);
1904 }
1905 exit(-1);
1906 }
1907 /*
1908 * Make sure we are talking to an IB.
1909 */
1910 if (err = g_get_inquiry(path_phys, &inq)) {
1911 (void) print_errString(err, argv[path_index]);
1912 exit(-1);
1913 }
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)))) {
1918 /*
1919 * Again this is like the ssaadm code in that the name
1920 * is still not defined before this code must be released.
1921 */
1922 (void) fprintf(stderr,
1923 MSGSTR(2048, "Error: Pathname does not point to a %s"
1924 " enclosure\n"), ENCLOSURE_PROD_NAME);
1925 exit(-1);
1926 }
1927
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);
1932 }
1933
1934 for (i = 0; i < WWN_SIZE; i++) {
1935 (void) sprintf(&wwn1[i << 1], "%02x", node_wwn[i]);
1936 }
1937 if ((err = l_get_box_list(&b_list, Options & PVERBOSE)) != 0) {
1938 (void) print_errString(err, argv[path_index]);
1939 exit(-1);
1940 }
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);
1957 }
1958 (void) l_free_box_list(&b_list);
1959
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);
1964 }
1965 if (Options & PVERBOSE) {
1966 (void) fprintf(stdout,
1967 MSGSTR(2050, "The enclosure has been renamed to %s\n"),
1968 name);
1969 }
1970 }
1971
1972
1973 static int
get_enclStatus(char * phys_path,char * encl_name,int off_flag)1974 get_enclStatus(char *phys_path, char *encl_name, int off_flag)
1975 {
1976 int found_pwrOnDrv = 0, slot;
1977 int found_pwrOffDrv = 0, err = 0;
1978 L_state l_state;
1979
1980 if ((err = l_get_status(phys_path,
1981 &l_state, Options & PVERBOSE)) != 0) {
1982 (void) print_errString(err, encl_name);
1983 return (err);
1984 }
1985
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;
1997 }
1998 }
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);
2007 }
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;
2019 }
2020 }
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);
2029 }
2030 }
2031 return (0);
2032 }
2033
2034
2035
2036
2037
2038 /*
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.
2043 *
2044 * RETURNS:
2045 * none.
2046 */
2047 void
adm_led(char ** argv,int led_action)2048 adm_led(char **argv, int led_action)
2049 {
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;
2059
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]);
2076 }
2077 exit(-1);
2078 }
2079 }
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);
2084 }
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);
2091 }
2092 }
2093 /*
2094 * See if we are in fact talking to a loop or not.
2095 */
2096 if (err = g_get_dev_map(path_phys, &map,
2097 (Options & PVERBOSE))) {
2098 (void) print_errString(err, argv[path_index]);
2099
2100 }
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);
2106 }
2107 if (err = l_led(path_struct, led_action, &status,
2108 (Options & PVERBOSE))) {
2109 (void) print_errString(err, argv[path_index]);
2110 exit(-1);
2111 }
2112
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);
2118 }
2119 }
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));
2140 }
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);
2149 }
2150 }
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));
2169 }
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);
2178 }
2179 }
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);
2197 }
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);
2206 }
2207 }
2208 }
2209 break;
2210 }
2211 free((void *)map.dev_addr);
2212 path_index++;
2213 }
2214 }
2215
2216
2217
2218
2219
2220 /*
2221 * dump() Dump information
2222 *
2223 * RETURNS:
2224 * none.
2225 */
2226 void
dump(char ** argv)2227 dump(char **argv)
2228 {
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;
2236
2237 /*
2238 * get big buffer
2239 */
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);
2244 }
2245 buf = (uchar_t *)hdr;
2246
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]);
2258 }
2259 exit(-1);
2260 }
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);
2266 }
2267
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);
2273 }
2274 (void) fprintf(stdout,
2275 MSGSTR(2066, "\t\tEnvironmental Sense Information\n"));
2276
2277 /*
2278 * Dump all pages.
2279 */
2280 hdr_ptr = hdr;
2281
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));
2289 }
2290 path_index++;
2291 }
2292 (void) free(buf);
2293 }
2294
2295
2296
2297 /*
2298 * display_socal_stats() Display socal driver kstat information.
2299 *
2300 * RETURNS:
2301 * none.
2302 */
2303 void
display_socal_stats(int port,char * socal_path,struct socal_stats * fc_stats)2304 display_socal_stats(int port, char *socal_path, struct socal_stats *fc_stats)
2305 {
2306 int i;
2307 int header_flag = 0;
2308 char status_msg_buf[MAXNAMELEN];
2309 int num_status_entries;
2310
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]);
2327 }
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);
2332 }
2333 if (fc_stats->parity_chk_enabled != 0) {
2334 (void) fprintf(stdout, MSGSTR(2069,
2335 " This Host Adapter checks S-Bus parity.\n"));
2336 }
2337 }
2338
2339 (void) fprintf(stdout, MSGSTR(2070,
2340 " Version Resets Req_Q_Intrpts Qfulls"
2341 " Unsol_Resps Lips\n"));
2342
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);
2350
2351 (void) fprintf(stdout, MSGSTR(2071,
2352 " Els_rcvd Abts"
2353 " Abts_ok Offlines Loop_onlines Onlines\n"));
2354
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);
2362
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;
2368 }
2369
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"));
2377 }
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);
2382 }
2383 }
2384 }
2385
2386
2387
2388 /*
2389 * display_sf_stats() Display sf driver kstat information.
2390 *
2391 * This routine is called by private loop device only
2392 *
2393 * RETURNS:
2394 * none.
2395 */
2396 void
display_sf_stats(char * path_phys,int dtype,struct sf_stats * sf_stats)2397 display_sf_stats(char *path_phys, int dtype, struct sf_stats *sf_stats)
2398 {
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;
2404
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"));
2414 }
2415
2416 (void) fprintf(stdout, MSGSTR(2074,
2417 " Version Lip_count Lip_fail"
2418 " Alloc_fail #_cmds "
2419 "Throttle_limit Pool_size\n"));
2420
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);
2429
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"));
2436
2437 if (err = g_get_dev_map(path_phys, &map, (Options & PVERBOSE))) {
2438 (void) print_errString(err, path_phys);
2439 exit(-1);
2440 }
2441
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);
2447 }
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;
2466 }
2467 }
2468 if (i >= map.count) {
2469 (void) print_errString(L_INVALID_LOOP_MAP, path_phys);
2470 exit(-1);
2471 }
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);
2485 }
2486 }
2487 free((void *)map.dev_addr);
2488 }
2489
2490
2491
2492 /*
2493 * adm_display_err() Displays enclosure specific
2494 * error information.
2495 *
2496 * RETURNS:
2497 * none.
2498 */
2499 static void
adm_display_err(char * path_phys,int dtype)2500 adm_display_err(char *path_phys, int dtype)
2501 {
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;
2518
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);
2523 }
2524
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);
2530 }
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;
2542 }
2543 }
2544 }
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);
2554 }
2555 free(pathlist.path_info);
2556 } else {
2557
2558 (void) strcpy(drvr_path, path_phys);
2559
2560 if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
2561 (void) print_errString(L_INVLD_PATH_NO_SLASH_FND,
2562 path_phys);
2563 exit(-1);
2564 }
2565 *char_ptr = '\0'; /* Make into nexus or HBA driver path. */
2566 }
2567 /*
2568 * Each HBA and driver stack has its own structures
2569 * for this, so we have to handle each one individually.
2570 */
2571 path_type = g_get_path_type(drvr_path);
2572
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);
2577 }
2578 (void) strcpy(socal_path, char_ptr);
2579
2580 }
2581
2582 /* attach :devctl to get node stat instead of dir stat. */
2583 (void) strcat(drvr_path, FC_CTLR);
2584
2585 if (stat(drvr_path, &sbuf) < 0) {
2586 (void) print_errString(L_LSTAT_ERROR, path_phys);
2587 exit(-1);
2588 }
2589
2590 drvr_inst = minor(sbuf.st_rdev);
2591
2592
2593 /*
2594 * first take care of ifp card.
2595 */
2596 if (path_type & FC4_PCI_FCA) {
2597 if ((ifp_ks = kstat_lookup(kc, "ifp",
2598 drvr_inst, "statistics")) != NULL) {
2599
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);
2605 }
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);
2623 }
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);
2628 }
2629 if (ifp_stats.parity_chk_enabled != 0) {
2630 (void) fprintf(stdout, MSGSTR(2084,
2631 " This Host Adapter checks "
2632 "PCI-Bus parity.\n"));
2633 }
2634 }
2635
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"));
2651 }
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);
2657 }
2658 }
2659
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"));
2665
2666 if (err = g_get_dev_map(path_phys, &map,
2667 (Options & PVERBOSE))) {
2668 (void) print_errString(err, path_phys);
2669 exit(-1);
2670 }
2671
2672
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);
2680 }
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;
2700 }
2701 }
2702 if (i >= map.count) {
2703
2704 (void) print_errString(
2705 L_INVALID_LOOP_MAP, path_phys);
2706 exit(-1);
2707 }
2708
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);
2721 }
2722 }
2723
2724 free((void *)map.dev_addr);
2725 }
2726 } else if (path_type & FC4_SF_XPORT) {
2727 /*
2728 * process cards with sf xport nodes.
2729 */
2730 if (stat(socal_path, &sbuf) < 0) {
2731 (void) print_errString(L_LSTAT_ERROR, path_phys);
2732 exit(-1);
2733 }
2734 socal_inst = minor(sbuf.st_rdev)/2;
2735 port = socal_inst%2;
2736
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);
2745 }
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);
2753 }
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);
2760 }
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);
2767 }
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);
2778 }
2779 (void) kstat_close(kc);
2780
2781 }
2782
2783
2784
2785 /*ARGSUSED*/
2786 /*
2787 * adm_display_verbose_disk() Gets the mode page information
2788 * for a SENA disk and prints that information.
2789 *
2790 * RETURNS:
2791 * none.
2792 */
2793 void
adm_display_verbose_disk(char * path,int verbose)2794 adm_display_verbose_disk(char *path, int verbose)
2795 {
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;
2802
2803 if ((err = l_get_mode_pg(path, &pg_buf, verbose)) == 0) {
2804
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"));
2823 }
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"));
2846 }
2847 if (pg4_buf->rpm) {
2848 (void) fprintf(stdout,
2849 MSGSTR(2092,
2850 " Medium rotation rate:\t"
2851 "%d RPM\n"), pg4_buf->rpm);
2852 }
2853 break;
2854 }
2855 offset += pg_hdr->length + sizeof (struct mode_page);
2856 pg_hdr = ((struct mode_page *)((int)pg_buf +
2857 (uchar_t)offset));
2858 }
2859
2860
2861
2862
2863
2864 } else if (getenv("_LUX_P_DEBUG") != NULL) {
2865 (void) print_errString(err, path);
2866 }
2867 }
2868
2869 /*
2870 * Print out the port_wwn or node_wwn
2871 */
2872 void
print_wwn(FILE * fd,uchar_t * pn_wwn)2873 print_wwn(FILE *fd, uchar_t *pn_wwn)
2874 {
2875
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]);
2880 }
2881
2882 /*
2883 * Print out the fabric dev port_id, hard_addr, port_wwn and node_wwn
2884 */
2885 void
print_fabric_prop(int pos,uchar_t * port_wwn,uchar_t * node_wwn,int port_addr,int hard_addr)2886 print_fabric_prop(int pos, uchar_t *port_wwn, uchar_t *node_wwn, int port_addr,
2887 int hard_addr)
2888 {
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);
2893 }
2894
2895 /*
2896 * Print out the private loop dev port_id, hard_addr, port_wwn and node_wwn
2897 */
2898 void
print_private_loop_prop(int pos,uchar_t * port_wwn,uchar_t * node_wwn,int port_addr,int hard_addr)2899 print_private_loop_prop(int pos, uchar_t *port_wwn, uchar_t *node_wwn,
2900 int port_addr, int hard_addr)
2901 {
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);
2906 }
2907
2908 /*
2909 * Get the device map from
2910 * fc nexus driver and prints the map.
2911 *
2912 * RETURNS:
2913 * none.
2914 */
2915 void
dump_map(char ** argv)2916 dump_map(char **argv)
2917 {
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;
2931
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]);
2943 }
2944 exit(-1);
2945 }
2946
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);
2953 }
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;
2964 }
2965 if (pathlist.path_info[i].path_state ==
2966 MDI_PATHINFO_STATE_ONLINE) {
2967 p_on = i;
2968 }
2969 if (pathlist.path_info[i].path_state ==
2970 MDI_PATHINFO_STATE_STANDBY) {
2971 p_st = i;
2972 }
2973 }
2974 }
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);
2989 }
2990 free(pathlist.path_info);
2991 (void) strcat(temp2path, FC_CTLR);
2992 } else {
2993 (void) strcpy(temp2path, path_phys);
2994 }
2995
2996 if ((dev_type = g_get_path_type(temp2path)) == 0) {
2997 (void) print_errString(L_INVALID_PATH,
2998 argv[path_index]);
2999 exit(-1);
3000 }
3001
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 {
3008 /*
3009 * This did not work so try the FCIO_GETMAP
3010 * type ioctl.
3011 */
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);
3017 }
3018 limited_map_flag++;
3019 }
3020
3021 }
3022
3023 if (limited_map_flag) {
3024 (void) fprintf(stdout,
3025 MSGSTR(2093,
3026 "Host Adapter AL_PA: %x\n"),
3027 limited_map.lilp_myalpa);
3028
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]);
3035 }
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);
3042 }
3043 if ((err = g_get_map_topology(
3044 map_root, &map_topo)) != 0) {
3045 (void) print_errString(err, argv[path_index]);
3046 exit(-1);
3047 }
3048
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);
3060 }
3061 }
3062
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);
3076 }
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);
3082 }
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);
3088 }
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);
3094 }
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);
3104 }
3105
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);
3112 }
3113 }
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"));
3120
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);
3127 }
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);
3133 }
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);
3139 }
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);
3145 }
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);
3155 }
3156
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);
3163 }
3164 }
3165 break;
3166 default:
3167 (void) print_errString(L_UNEXPECTED_FC_TOPOLOGY,
3168 argv[path_index]);
3169 exit(-1);
3170 }
3171 g_dev_map_fini(map_root);
3172 }
3173 limited_map_flag = 0;
3174 path_index++;
3175 }
3176 }
3177
3178 /*
3179 * Gets a list of non-SENA fcal devices
3180 * found on the system.
3181 *
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.
3189 */
3190 int
n_get_non_encl_list(WWN_list ** wwn_list_ptr,int verbose)3191 n_get_non_encl_list(WWN_list **wwn_list_ptr, int verbose)
3192 {
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;
3201
3202
3203 /*
3204 * Only interested in devices that are not part of
3205 * a Photon enclosure.
3206 */
3207 if ((err = l_get_box_list(&b_list, verbose)) != 0) {
3208 return (err); /* Failure */
3209 }
3210
3211 if (err = g_get_wwn_list(&wwn_list, verbose)) {
3212 (void) l_free_box_list(&b_list);
3213 return (err);
3214 }
3215
3216 while (b_list != NULL) {
3217
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);
3224 }
3225 pathcnt = pathlist.path_count;
3226 }
3227
3228 for (k = 0; k < pathcnt; k++) {
3229
3230 if ((k > 0) && (strstr(oldphci_path,
3231 pathlist.path_info[k].path_hba))) {
3232 continue;
3233 }
3234
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);
3241 }
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;
3249 }
3250 if (pathcnt == 1) {
3251 free(pathlist.path_info);
3252 }
3253 }
3254
3255
3256 switch (map.hba_addr.port_topology) {
3257 case FC_TOP_FABRIC:
3258 case FC_TOP_PUBLIC_LOOP:
3259
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;
3268 }
3269 }
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);
3275 }
3276 }
3277 break;
3278
3279 case FC_TOP_PRIVATE_LOOP:
3280
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;
3289 }
3290 }
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;
3305 }
3306 }
3307 }
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);
3315 }
3316 free((void *)map.dev_addr);
3317
3318 }
3319 if (pathcnt > 1) {
3320 free(pathlist.path_info);
3321 }
3322
3323 b_list = b_list->box_next;
3324 }
3325 /* Return the list */
3326 *wwn_list_ptr = wwn_list;
3327 (void) l_free_box_list(&b_list);
3328 return (0);
3329 }
3330
3331
3332
3333 /*
3334 * n_rem_list_entry() We found an IB so remove disks that
3335 * are in the Photon from the individual device list.
3336 *
3337 * OUTPUT:
3338 * wwn_list - removes the fcal disks that are in SENA enclosure
3339 *
3340 * RETURNS:
3341 * none
3342 */
3343 void
n_rem_list_entry(uchar_t box_id,struct gfc_map * map,struct wwn_list_struct ** wwn_list)3344 n_rem_list_entry(uchar_t box_id, struct gfc_map *map,
3345 struct wwn_list_struct **wwn_list)
3346 {
3347 int k;
3348 gfc_port_dev_info_t *dev_addr_list;
3349
3350 N_DPRINTF(" n_rem_list_entry: Removing devices"
3351 " with box_id=0x%x from device list.\n", box_id);
3352
3353
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);
3361 }
3362 }
3363
3364 }
3365
3366
3367
3368 /*
3369 * n_rem_list_entry_fabric() We found an IB so remove disks that
3370 * are in the Photon from the individual device list.
3371 *
3372 * OUTPUT:
3373 * wwn_list - removes the fcal disks that are in SENA enclosure
3374 *
3375 * RETURNS:
3376 * none
3377 */
3378 void
n_rem_list_entry_fabric(int pa,struct gfc_map * map,struct wwn_list_struct ** wwn_list)3379 n_rem_list_entry_fabric(int pa, struct gfc_map *map,
3380 struct wwn_list_struct **wwn_list)
3381 {
3382 int k;
3383 gfc_port_dev_info_t *dev_addr_ptr;
3384
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++) {
3390
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);
3398 }
3399 }
3400 }
3401
3402
3403 /*
3404 * n_rem_wwn_entry() removes input wwn from wwn_list.
3405 *
3406 * OUTPUT:
3407 * wwn_list - removes the input wwn from wwn_list if found.
3408 *
3409 * RETURNS:
3410 * none
3411 */
3412 void
n_rem_wwn_entry(uchar_t node_wwn[],struct wwn_list_struct ** wwn_list)3413 n_rem_wwn_entry(uchar_t node_wwn[], struct wwn_list_struct **wwn_list)
3414 {
3415 int l, found_dev;
3416 WWN_list *inner, *l1;
3417
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;
3423 }
3424 }
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;
3432 }
3433 if (inner->wwn_next != NULL) {
3434 inner->wwn_next->wwn_prev =
3435 inner->wwn_prev;
3436 }
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,
3443 l1,
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;
3458 }
3459 (void) free(l1->physical_path);
3460 (void) free(l1->logical_path);
3461 (void) free(l1);
3462 } else {
3463 inner = inner->wwn_next;
3464 }
3465 }
3466 }
3467
3468
3469 /*
3470 * non_encl_probe() Finds and displays a list of
3471 * non-SENA fcal devices which is found on the
3472 * system.
3473 *
3474 * RETURNS:
3475 * none.
3476 */
3477 void
non_encl_probe()3478 non_encl_probe()
3479 {
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;
3488
3489 if (err = n_get_non_encl_list(&wwn_list, (Options & PVERBOSE))) {
3490 (void) print_errString(err, NULL);
3491 exit(-1);
3492 }
3493
3494 g_sort_wwn_list(&wwn_list);
3495
3496 wwn_listh = wwn_list;
3497
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"));
3505 }
3506 } else {
3507 return;
3508 }
3509
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);
3520 }
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);
3529 }
3530 }
3531 (void) fprintf(stdout, " ");
3532 (void) fprintf(stdout, MSGSTR(90, "Node WWN:"));
3533 (void) fprintf(stdout, "%s ", wwn_list->node_wwn_s);
3534
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"));
3545 }
3546 (void) fprintf(stdout, "\n ");
3547 (void) fprintf(stdout, MSGSTR(31, "Logical Path:%s"),
3548 wwn_list->logical_path);
3549 (void) fprintf(stdout, "\n");
3550
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);
3556 }
3557 inner = wwn_list->wwn_next;
3558
3559 while (inner != NULL) {
3560 if (strcmp(inner->node_wwn_s, wwn_list->node_wwn_s) == 0) {
3561
3562 if (tempptra != NULL) {
3563 if (strstr(inner->physical_path,
3564 SCSI_VHCI) != NULL) {
3565 (void) strcpy(temppath,
3566 inner->physical_path);
3567
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);
3575 }
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);
3584 }
3585 }
3586 }
3587
3588 if (((tempptra == NULL) || (strcmp(lun_a, lun_b)) == 0)) {
3589
3590 /*
3591 * Have we retrieved a snapshot yet?
3592 */
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);
3600 }
3601 }
3602
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);
3610 }
3611 /*
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.
3615 */
3616 retr_outer = 1;
3617 }
3618 /*
3619 * Apply devid to block devices only.
3620 * Get devid of inner path and compare
3621 * with outer path's devid.
3622 */
3623 if ((strstr(inner->physical_path,
3624 SLSH_DRV_NAME_SSD) != NULL) &&
3625 devid1 != NULL) {
3626
3627 if ((err = g_devid_get(inner->physical_path,
3628 &devid2, root, SSD_DRVR_NAME)) != 0) {
3629
3630 (void) print_errString(err,
3631 inner->physical_path);
3632 compare_result = 0;
3633 } else {
3634 compare_result = devid_compare(devid1, devid2);
3635 }
3636 } else {
3637 /* devid isn't applied */
3638 compare_result = 0;
3639 }
3640
3641 if (compare_result == 0) {
3642
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");
3650
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);
3657 }
3658 }
3659
3660 /* Remove this entry from the list */
3661 if (inner->wwn_prev != NULL) {
3662 inner->wwn_prev->wwn_next =
3663 inner->wwn_next;
3664 }
3665
3666 if (inner->wwn_next != NULL) {
3667 inner->wwn_next->wwn_prev =
3668 inner->wwn_prev;
3669 }
3670 free(inner->physical_path);
3671 free(inner->logical_path);
3672 l1 = inner;
3673 inner = inner->wwn_next;
3674 (void) free(l1);
3675
3676 } else {
3677 inner = inner->wwn_next;
3678 } /* End if (compare_result == 0) */
3679
3680 } else {
3681 inner = inner->wwn_next;
3682 }
3683 } else {
3684 inner = inner->wwn_next;
3685 }
3686 devid2 = NULL;
3687 }
3688 wwn_list = wwn_list->wwn_next;
3689 retr_outer = 0;
3690 devid1 = NULL;
3691 } /* End while (wwn_list != NULL) */
3692
3693 (void) g_free_wwn_list(&wwn_listh);
3694 (void) di_fini(root);
3695 }
3696
3697 void
pho_probe()3698 pho_probe()
3699 {
3700
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;
3704
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);
3709 }
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"));
3721 }
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;
3732 }
3733 c_list = c_list->box_next;
3734 }
3735 if (multi_print_flag) {
3736 b_list = b_list->box_next;
3737 continue;
3738 }
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);
3743 /*
3744 * Print logical path on same line if not multipathed.
3745 */
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;
3753 }
3754 c_list = c_list->box_next;
3755 }
3756 if (multi_path_flag) {
3757 (void) fprintf(stdout, "\n ");
3758 }
3759 (void) fprintf(stdout,
3760 MSGSTR(31, "Logical Path:%s"),
3761 b_list->logical_path);
3762
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);
3769 }
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);
3785 }
3786 }
3787 c_list = c_list->box_next;
3788 }
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++;
3795 }
3796 b_list = b_list->box_next;
3797 }
3798 }
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"));
3807 }
3808 (void) l_free_box_list(&b_list);
3809 }
3810
3811 /*
3812 * display_port_status() Prints the device's
3813 * port status.
3814 *
3815 * RETURNS:
3816 * none.
3817 */
3818 void
display_port_status(int d_state_flag)3819 display_port_status(int d_state_flag)
3820 {
3821
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."));
3838 }
3839 (void) fprintf(stdout, "\n");
3840 }
3841
3842 /*
3843 * Displays individual SENA
3844 * FC disk information.
3845 *
3846 * Caller to this routine should free the storage due to
3847 * the use of g_get_dev_map
3848 *
3849 * RETURNS:
3850 * none.
3851 */
3852 void
display_fc_disk(struct path_struct * path_struct,char * ses_path,gfc_map_t * map,L_inquiry inq,int verbose)3853 display_fc_disk(struct path_struct *path_struct, char *ses_path,
3854 gfc_map_t *map, L_inquiry inq, int verbose)
3855 {
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;
3870
3871 /*
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.
3875 */
3876 if (strcmp(path_phys, path_struct->p_physical_path) == 0)
3877 same_path_phys = B_TRUE;
3878
3879 (void) strcpy(path_phys, path_struct->p_physical_path);
3880 (void) memset((char *)logical_path, 0, sizeof (logical_path));
3881
3882 /*
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
3886 */
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);
3892 }
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);
3897 }
3898 }
3899
3900 /*
3901 * Get the WWN for our disk if we already haven't or if there was an
3902 * error earlier
3903 */
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);
3909 }
3910
3911 if (err = g_get_inquiry(ses_path, &local_inq)) {
3912 (void) print_errString(err, ses_path);
3913 exit(-1);
3914 }
3915 }
3916
3917 /*
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
3921 */
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);
3926 }
3927
3928 /*
3929 * Get path to all the FC disk and tape devices.
3930 * if we haven't already done so in a previous pass
3931 */
3932 if ((wwn_list == NULL) && (err = g_get_wwn_list(&wwn_list, verbose))) {
3933 (void) print_errString(err, ses_path);
3934 exit(-1); /* Failure */
3935 }
3936
3937 /*
3938 * Get the disk status if it is a different path_phys from
3939 * last time.
3940 */
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);
3948 }
3949 }
3950
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"));
3958
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);
3963 }
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);
3969 }
3970 no_path_flag++;
3971 }
3972
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]);
3978 }
3979
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;
3994 }
3995 offset += pg_hdr->length + sizeof (struct mode_page);
3996 pg_hdr = ((struct mode_page *)((int)pg_buf +
3997 (uchar_t)offset));
3998 }
3999 }
4000
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;
4014 }
4015
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"));
4029 }
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"));
4036 }
4037 }
4038 }
4039
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"));
4052 }
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"));
4059 }
4060 }
4061 }
4062
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):"));
4069 }
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"));
4077 }
4078
4079 (void) display_disk_info(inq, l_disk_state, path_struct, pg_hdr,
4080 mode_data_avail, (char *)local_inq.inq_box_name, verbose);
4081 }
4082
4083
4084
4085
4086
4087 /*
4088 * non_encl_fc_disk_display() Prints the device specific
4089 * information for an individual fcal device.
4090 *
4091 * RETURNS:
4092 * none.
4093 */
4094 static int
non_encl_fc_disk_display(Path_struct * path_struct,L_inquiry inq_struct,int verbose)4095 non_encl_fc_disk_display(Path_struct *path_struct,
4096 L_inquiry inq_struct, int verbose)
4097 {
4098
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;
4112
4113 (void) strcpy(phys_path, path_struct->p_physical_path);
4114
4115 /* Get path to all the FC disk and tape devices. */
4116 if (err = g_get_wwn_list(&wwn_list, verbose)) {
4117 return (err);
4118 }
4119
4120 g_sort_wwn_list(&wwn_list);
4121
4122 list_start = wwn_list;
4123 (void) strcpy(last_logical_path, phys_path);
4124
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;
4137 }
4138 }
4139
4140 for (wwn_list_ptr = list_start; wwn_list_ptr != NULL;
4141 wwn_list_ptr = wwn_list_ptr->wwn_next) {
4142
4143
4144 if (argpwwn) {
4145 if (strcasecmp(wwn_list_ptr->port_wwn_s,
4146 path_struct->argv) != 0) {
4147 continue;
4148 }
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;
4157 }
4158 if (strcasecmp(wwn_list_ptr->node_wwn_s,
4159 path_struct->argv) != 0) {
4160 continue;
4161 }
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;
4168 }
4169
4170 (void) memset(&l_disk_state, 0, sizeof (struct l_disk_state_struct));
4171
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);
4176 }
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);
4184 }
4185
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;
4200 }
4201 offset += pg_hdr->length + sizeof (struct mode_page);
4202 pg_hdr = ((struct mode_page *)((int)pg_buf +
4203 (uchar_t)offset));
4204 }
4205 }
4206
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;
4220 }
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);
4232 }
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);
4240 }
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]);
4246 }
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);
4254 }
4255
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;
4262 }
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]);
4269 }
4270
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);
4279 }
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)) {
4289
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;
4296 }
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)) {
4303
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;
4310 }
4311 if ((path_a_found) && (path_b_found)) {
4312 break;
4313 }
4314 }
4315 }
4316 free(pathlist.path_info);
4317 }
4318
4319 mlist = mlist->next;
4320 }
4321
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]);
4327 }
4328
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]);
4334 }
4335
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);
4339
4340 if (!(argpwwn || argnwwn)) {
4341 break;
4342 }
4343
4344 }
4345 (void) g_free_wwn_list(&wwn_list);
4346 return (0);
4347 }
4348
4349
4350
4351 /*
4352 * display_disk_info() Prints the device specific information
4353 * for any FC_AL disk device.
4354 *
4355 * RETURNS:
4356 * none.
4357 */
4358 void
display_disk_info(L_inquiry inq,L_disk_state l_disk_state,Path_struct * path_struct,struct mode_page * pg_hdr,int mode_data_avail,char * name_buf,int options)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)
4362 {
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;
4374
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);
4383 }
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);
4388
4389 (void) fprintf(stdout, MSGSTR(2115, "\n Product ID:\t\t"));
4390 print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0);
4391
4392 (void) fprintf(stdout, MSGSTR(2116, "\n WWN(Node):\t\t%s"),
4393 l_disk_state.g_disk_state.node_wwn_s);
4394
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);
4398 }
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);
4402 }
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);
4407
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);
4419 }
4420 (void) fprintf(stdout, "\n");
4421
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");
4429 }
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"));
4436 }
4437 (void) fprintf(stdout, "\n");
4438 }
4439
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"));
4447 }
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);
4461 }
4462 }
4463
4464 /*
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.
4469 */
4470
4471 if (name_buf != NULL) {
4472 fprintf(stdout, MSGSTR(2125, " Location:\t\t"));
4473 if (path_struct->slot_valid) {
4474 /*
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.
4478 */
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);
4483 }
4484 }
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);
4498 }
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);
4506 }
4507 } else {
4508 (void) fprintf(stdout, MSGSTR(2228,
4509 "In the enclosure named: %s\n"),
4510 name_buf);
4511 }
4512 }
4513
4514 (void) fprintf(stdout, " %s\t\t%s\n",
4515 MSGSTR(35, "Device Type:"),
4516 dtype[inq.inq_dtype & DTYPE_MASK]);
4517
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;
4529 }
4530 }
4531
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;
4539 }
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);
4547 }
4548 (void) fprintf(stdout, "\n");
4549
4550 }
4551
4552
4553
4554 /*
4555 * temp_decode() Display temperature bytes 1-3 state.
4556 *
4557 * RETURNS:
4558 * none.
4559 */
4560 void
temp_decode(Temp_elem_st * temp)4561 temp_decode(Temp_elem_st *temp)
4562 {
4563 if (temp->ot_fail) {
4564 (void) fprintf(stdout, MSGSTR(2129,
4565 ": FAILURE - Over Temperature"));
4566 }
4567 if (temp->ut_fail) {
4568 (void) fprintf(stdout, MSGSTR(2130,
4569 ": FAILURE - Under Temperature"));
4570 }
4571 if (temp->ot_warn) {
4572 (void) fprintf(stdout, MSGSTR(2131,
4573 ": WARNING - Over Temperature"));
4574 }
4575 if (temp->ut_warn) {
4576 (void) fprintf(stdout, MSGSTR(2132,
4577 ": WARNING - Under Temperature"));
4578 }
4579 }
4580
4581
4582
4583 /*
4584 * disp_degree() Display temperature in Degrees Celsius.
4585 *
4586 * RETURNS:
4587 * none.
4588 */
4589 void
disp_degree(Temp_elem_st * temp)4590 disp_degree(Temp_elem_st *temp)
4591 {
4592 int t;
4593
4594 t = temp->degrees;
4595 t -= 20; /* re-adjust */
4596 /*
4597 * NL_Comment
4598 * The %c is the degree symbol.
4599 */
4600 (void) fprintf(stdout, ":%1.2d%cC ", t, 186);
4601 }
4602
4603
4604
4605 /*
4606 * trans_decode() Display tranceivers state.
4607 *
4608 * RETURNS:
4609 * none.
4610 */
4611 void
trans_decode(Trans_elem_st * trans)4612 trans_decode(Trans_elem_st *trans)
4613 {
4614 if (trans->disabled) {
4615 (void) fprintf(stdout, ": ");
4616 (void) fprintf(stdout, MSGSTR(34,
4617 "Disabled"));
4618 }
4619 if (trans->lol) {
4620 (void) fprintf(stdout, MSGSTR(2133,
4621 ": Not receiving a signal"));
4622 }
4623 if (trans->lsr_fail) {
4624 (void) fprintf(stdout, MSGSTR(2134,
4625 ": Laser failed"));
4626 }
4627 }
4628
4629
4630
4631 /*
4632 * trans_messages() Display tranceiver status.
4633 *
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.
4638 *
4639 * RETURNS:
4640 * none.
4641 */
4642 void
trans_messages(struct l_state_struct * l_state,int ib_a_flag)4643 trans_messages(struct l_state_struct *l_state, int ib_a_flag)
4644 {
4645 Trans_elem_st trans;
4646 int i, j, k;
4647 int count = 0;
4648 int elem_index = 0;
4649
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) {
4654
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]);
4658 }
4659 count = k = 0;
4660
4661 for (j = 0; j <
4662 (int)l_state->ib_tbl.config.type_hdr[i].num; j++) {
4663 /*
4664 * Only display the status for the selected IB.
4665 */
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));
4671
4672 if (k == 0) {
4673 (void) fprintf(stdout, "\t\t%d ", k);
4674 } else {
4675 (void) fprintf(stdout, "\n\t\t%d ", k);
4676 }
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"));
4697 }
4698 k++;
4699 }
4700 count++;
4701 }
4702 }
4703 /*
4704 * Calculate the index to each element.
4705 */
4706 elem_index += l_state->ib_tbl.config.type_hdr[i].num;
4707 }
4708 (void) fprintf(stdout, "\n");
4709 }
4710
4711
4712
4713 /*
4714 * temperature_messages() Display temperature status.
4715 *
4716 * RETURNS:
4717 * none.
4718 */
4719 void
temperature_messages(struct l_state_struct * l_state,int rear_flag)4720 temperature_messages(struct l_state_struct *l_state, int rear_flag)
4721 {
4722 Temp_elem_st temp;
4723 int i, j, last_ok = 0;
4724 int all_ok = 1;
4725 int elem_index = 0;
4726
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]);
4736 }
4737
4738 /*
4739 * Check global status and if not all O.K.
4740 * then print individually.
4741 */
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));
4749
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);
4761 }
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++;
4771 }
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;
4797 }
4798 }
4799 if (all_ok) {
4800 (void) fprintf(stdout,
4801 MSGSTR(2136, " (All temperatures are "
4802 "NORMAL.)"));
4803 }
4804 all_ok = 1;
4805 (void) fprintf(stdout, "\n");
4806 } else {
4807 rear_flag = 0;
4808 }
4809 }
4810 elem_index += l_state->ib_tbl.config.type_hdr[i].num;
4811 }
4812 }
4813
4814
4815
4816 /*
4817 * ib_decode() Display IB byte 3 state.
4818 *
4819 * RETURNS:
4820 * none.
4821 */
4822 void
ib_decode(Ctlr_elem_st * ctlr)4823 ib_decode(Ctlr_elem_st *ctlr)
4824 {
4825 if (ctlr->overtemp_alart) {
4826 (void) fprintf(stdout, MSGSTR(2137,
4827 " - IB Over Temperature Alert "));
4828 }
4829 if (ctlr->ib_loop_1_fail) {
4830 (void) fprintf(stdout, MSGSTR(2138,
4831 " - IB Loop 1 has failed "));
4832 }
4833 if (ctlr->ib_loop_0_fail) {
4834 (void) fprintf(stdout, MSGSTR(2139,
4835 " - IB Loop 0 has failed "));
4836 }
4837 }
4838
4839
4840
4841 /*
4842 * mb_messages() Display motherboard
4843 * (interconnect assembly) messages.
4844 *
4845 * RETURNS:
4846 * none.
4847 */
4848 void
mb_messages(struct l_state_struct * l_state,int index,int elem_index)4849 mb_messages(struct l_state_struct *l_state, int index, int elem_index)
4850 {
4851 int j;
4852 Interconnect_st interconnect;
4853
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]);
4857 }
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");
4864
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"));
4879 }
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"));
4888 }
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"));
4897 }
4898 (void) fprintf(stdout, "\n");
4899 }
4900
4901
4902 }
4903
4904
4905
4906 /*
4907 * back_plane_messages() Display back_plane messages
4908 * including the temperature's.
4909 *
4910 * RETURNS:
4911 * none.
4912 */
4913 void
back_plane_messages(struct l_state_struct * l_state,int index,int elem_index)4914 back_plane_messages(struct l_state_struct *l_state, int index, int elem_index)
4915 {
4916 Bp_elem_st bp;
4917 int j;
4918 char status_string[MAXPATHLEN];
4919
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]);
4923 }
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: "));
4935 }
4936
4937 (void) l_element_msg_string(bp.code, status_string);
4938 (void) fprintf(stdout, "%s", status_string);
4939
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)"));
4958 }
4959 (void) fprintf(stdout, "\n");
4960 temperature_messages(l_state, j);
4961 } else {
4962 (void) fprintf(stdout, "\n");
4963 }
4964 }
4965 }
4966
4967
4968 /*
4969 * dpm_SSC100_messages() Display SSC100 messages
4970 * including the temperature's.
4971 *
4972 * RETURNS:
4973 * none.
4974 */
4975 void
dpm_SSC100_messages(struct l_state_struct * l_state,int index,int elem_index)4976 dpm_SSC100_messages(struct l_state_struct *l_state, int index, int elem_index)
4977 {
4978 Bp_elem_st bp;
4979 int j;
4980 char status_string[MAXPATHLEN];
4981
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]);
4985 }
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);
4992
4993 (void) l_element_msg_string(bp.code, status_string);
4994 (void) fprintf(stdout, "%s", status_string);
4995
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)"));
5014 }
5015 (void) fprintf(stdout, "\n");
5016 } else {
5017 (void) fprintf(stdout, "\n");
5018 }
5019 }
5020 temperature_messages(l_state, 0);
5021 }
5022
5023
5024
5025
5026 /*
5027 * loop_messages() Display loop messages.
5028 *
5029 * RETURNS:
5030 * none.
5031 */
5032 void
loop_messages(struct l_state_struct * l_state,int index,int elem_index)5033 loop_messages(struct l_state_struct *l_state, int index, int elem_index)
5034 {
5035 Loop_elem_st loop;
5036 int j;
5037
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]);
5041 }
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));
5047
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."));
5060 }
5061 }
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."));
5073 }
5074 }
5075 }
5076 (void) fprintf(stdout, "\n");
5077 }
5078 }
5079
5080
5081
5082 /*
5083 * ctlr_messages() Display ESI Controller status.
5084 *
5085 * RETURNS:
5086 * none.
5087 */
5088 void
ctlr_messages(struct l_state_struct * l_state,int index,int elem_index)5089 ctlr_messages(struct l_state_struct *l_state, int index, int elem_index)
5090 {
5091 Ctlr_elem_st ctlr;
5092 int j;
5093 int ib_a_flag = 1;
5094
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]);
5098 }
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;
5109 }
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);
5116 /*
5117 * Display the tranciver module state for this
5118 * IB.
5119 */
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");
5143 }
5144 }
5145 }
5146
5147
5148
5149 /*
5150 * fan_decode() Display Fans bytes 1-3 state.
5151 *
5152 * RETURNS:
5153 * none.
5154 */
5155 void
fan_decode(Fan_elem_st * fan)5156 fan_decode(Fan_elem_st *fan)
5157 {
5158 if (fan->fail) {
5159 (void) fprintf(stdout, MSGSTR(2155,
5160 ":Yellow LED is on"));
5161 }
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"));
5171 }
5172 }
5173
5174 /*
5175 * fan_messages() Display Fan status.
5176 *
5177 * RETURNS:
5178 * none.
5179 */
5180 void
fan_messages(struct l_state_struct * l_state,int hdr_index,int elem_index)5181 fan_messages(struct l_state_struct *l_state, int hdr_index, int elem_index)
5182 {
5183 Fan_elem_st fan;
5184 int j;
5185
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]);
5190 }
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"));
5220 }
5221 }
5222 (void) fprintf(stdout, "\n");
5223 }
5224
5225
5226
5227 /*
5228 * ps_decode() Display Power Supply bytes 1-3 state.
5229 *
5230 * RETURNS:
5231 * none.
5232 */
5233 void
ps_decode(Ps_elem_st * ps)5234 ps_decode(Ps_elem_st *ps)
5235 {
5236 if (ps->dc_over) {
5237 (void) fprintf(stdout, MSGSTR(2159,
5238 ": DC Voltage too high"));
5239 }
5240 if (ps->dc_under) {
5241 (void) fprintf(stdout, MSGSTR(2160,
5242 ": DC Voltage too low"));
5243 }
5244 if (ps->dc_over_i) {
5245 (void) fprintf(stdout, MSGSTR(2161,
5246 ": DC Current too high"));
5247 }
5248 if (ps->ovrtmp_fail || ps->temp_warn) {
5249 (void) fprintf(stdout, MSGSTR(2162,
5250 ": Temperature too high"));
5251 }
5252 if (ps->ac_fail) {
5253 (void) fprintf(stdout, MSGSTR(2163,
5254 ": AC Failed"));
5255 }
5256 if (ps->dc_fail) {
5257 (void) fprintf(stdout, MSGSTR(2164,
5258 ": DC Failed"));
5259 }
5260 }
5261
5262
5263
5264 /*
5265 * revision_msg() Print the revision message from page 7.
5266 *
5267 * RETURNS:
5268 * none.
5269 */
5270 void
revision_msg(struct l_state_struct * l_state,int index)5271 revision_msg(struct l_state_struct *l_state, int index)
5272 {
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);
5277 }
5278 }
5279
5280
5281
5282 /*
5283 * ps_messages() Display Power Supply status.
5284 *
5285 * RETURNS:
5286 * none.
5287 */
5288 void
ps_messages(struct l_state_struct * l_state,int index,int elem_index)5289 ps_messages(struct l_state_struct *l_state, int index, int elem_index)
5290 {
5291 Ps_elem_st ps;
5292 int j;
5293
5294 /* Get and print Power Supply messages */
5295
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]);
5299 }
5300
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"));
5330 }
5331
5332 }
5333 (void) fprintf(stdout, "\n");
5334 }
5335
5336
5337
5338 /*
5339 * abnormal_condition() Display any abnormal condition messages.
5340 *
5341 * RETURNS:
5342 * none.
5343 */
5344 void
abnormal_condition_display(struct l_state_struct * l_state)5345 abnormal_condition_display(struct l_state_struct *l_state)
5346 {
5347
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"));
5353 }
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"));
5358 }
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"));
5368 }
5369 (void) fprintf(stdout, "\n");
5370 }
5371
5372
5373
5374
5375
5376 /*
5377 * adm_start() Spin up the given list
5378 * of SENA devices.
5379 *
5380 * RETURNS:
5381 * none.
5382 */
5383 int
adm_start(char ** argv)5384 adm_start(char **argv)
5385 {
5386 char *path_phys = NULL;
5387 Path_struct *path_struct;
5388 int err = 0, retval = 0;
5389
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);
5400 }
5401 (argv)++;
5402 retval++;
5403 continue;
5404 }
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;
5411 }
5412 (argv)++;
5413 }
5414 return (retval);
5415 }
5416
5417
5418
5419 /*
5420 * adm_stop() Spin down a
5421 * given list of SENA devices.
5422 *
5423 * RETURNS:
5424 * none.
5425 */
5426 int
adm_stop(char ** argv)5427 adm_stop(char **argv)
5428 {
5429 char *path_phys = NULL;
5430 Path_struct *path_struct;
5431 int err = 0, retval = 0;
5432
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);
5444 }
5445 (argv)++;
5446 retval++;
5447 continue;
5448 }
5449
5450 /*
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).
5457 */
5458 if (strstr(path_phys, SLSH_DRV_NAME_ST)) {
5459 errno = ENOTSUP;
5460 (void) print_errString(0, path_phys);
5461 (argv)++;
5462 continue;
5463 }
5464
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;
5471 }
5472 (argv)++;
5473 }
5474 return (retval);
5475 }
5476
5477
5478 /*
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.
5483 *
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
5493 */
5494 int
adm_port_offline_online(char * argv[],int flag)5495 adm_port_offline_online(char *argv[], int flag)
5496 {
5497 int err, retval = 0;
5498 char *path_phys = NULL;
5499 char *nexus_path_ptr = NULL;
5500 Path_struct *path_struct = NULL;
5501
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);
5513 }
5514 argv++;
5515 retval++;
5516 continue;
5517 }
5518
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;
5524 }
5525
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;
5531 }
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;
5540 }
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++;
5551 }
5552 cleanup_and_go:
5553 free(path_phys);
5554 free(path_struct);
5555 free(nexus_path_ptr);
5556 argv++;
5557 }
5558 return (retval);
5559 }
5560
5561 /*
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.
5566 *
5567 * Sample output for ifp:
5568 *
5569 * /devices/pci@1f,4000/SUNW,ifp@2:devctl CONNECTED
5570 * /devices/pci@1f,2000/SUNW,ifp@1:devctl NOT CONNECTED
5571 *
5572 * Sample output for socal:
5573 *
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
5578 *
5579 * Note: for socal the path returned is not a devctl path as there is no
5580 * devctl path for socal.
5581 *
5582 * Sample output for fp:
5583 *
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
5586 */
5587 int
adm_display_port(int verbose)5588 adm_display_port(int verbose)
5589 {
5590 /*
5591 * If another port driver needs to be searched, add it here
5592 */
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;
5600
5601 portlist.hbacnt = 0;
5602
5603 /*
5604 * Look for all HBA ports as listed in portdrvr_list[]
5605 */
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++;
5612 }
5613 }
5614 x++;
5615 }
5616
5617
5618 /*
5619 * For each port path found get the connection state.
5620 * If there are devices attached the state is considered connected.
5621 */
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"));
5637 }
5638 }
5639 }
5640 g_free_portlist(&portlist);
5641 return (retval);
5642 }
5643
5644 /*
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
5655 *
5656 * RETURN: 0 on success
5657 * non-zero on failure
5658 */
5659 int
adm_port_loopback(char * portpath,int flag)5660 adm_port_loopback(char *portpath, int flag)
5661 {
5662 int err;
5663 char *path_phys = NULL;
5664 Path_struct *path_struct = NULL;
5665 int cmd;
5666
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);
5677 }
5678 return (-1);
5679 }
5680
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);
5700 }
5701
5702
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;
5735 }
5736 }
5737 free(path_phys);
5738 free(path_struct);
5739 return (0);
5740 }
5741
5742
5743
5744 /*
5745 * To print the pathlist and mpxio path attributes
5746 */
5747 void
adm_print_pathlist(char * dev_path)5748 adm_print_pathlist(char *dev_path)
5749 {
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];
5759
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");
5765
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);
5771 }
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);
5777
5778 (void) fprintf(stdout,
5779 MSGSTR(2304, " Device Address\t\t%s\n"),
5780 pathlist.path_info[i].path_addr);
5781
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);
5789 }
5790 }
5791
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);
5797 }
5798
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]);
5806 }
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]);
5821 }
5822 }
5823 }
5824 /* Free memory for per path info properties */
5825 free(pathlist.path_info);
5826 }
5827
5828 /*
5829 * compare_multipath
5830 * compares path with all paths in pathlist
5831 * If there is a match, 0 is returned, otherwise 1 is returned
5832 */
5833 int
compare_multipath(char * path,struct mplist_struct * pathlist)5834 compare_multipath(char *path, struct mplist_struct *pathlist)
5835 {
5836
5837 while (pathlist != NULL) {
5838 if (strncmp(path, pathlist->devpath, MAXPATHLEN) == 0) {
5839 return (0);
5840 }
5841 pathlist = pathlist->next;
5842 }
5843 return (1);
5844 }
5845
5846 /*
5847 * lun_display() Prints the
5848 * information for an individual lun.
5849 *
5850 * RETURNS:
5851 * none.
5852 */
5853 static int
lun_display(Path_struct * path_struct,L_inquiry inq_struct,int verbose)5854 lun_display(Path_struct *path_struct, L_inquiry inq_struct, int verbose)
5855 {
5856
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;
5870
5871
5872
5873 strcpy(phys_path, path_struct->p_physical_path);
5874 strcpy(last_logical_path, phys_path);
5875
5876 mplistp = mpl = mpln = (struct mplist_struct *)NULL;
5877 /*
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.
5881 */
5882 if (strstr(path_struct->argv, "/") != NULL) {
5883 if ((err = g_devices_get_all(&wwn_list)) != 0) {
5884 return (err);
5885 }
5886 } else {
5887 if ((err = g_get_wwn_list(&wwn_list, verbose)) != 0) {
5888 return (err);
5889 }
5890 }
5891
5892 g_sort_wwn_list(&wwn_list);
5893
5894 list_start = wwn_list;
5895
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;
5908 }
5909 }
5910
5911 for (wwn_list_ptr = list_start; wwn_list_ptr != NULL;
5912 wwn_list_ptr = wwn_list_ptr->wwn_next) {
5913
5914
5915 if (argpwwn) {
5916 if (strcasecmp(wwn_list_ptr->port_wwn_s,
5917 path_struct->argv) != 0) {
5918 continue;
5919 }
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;
5925 }
5926 if (strcasecmp(wwn_list_ptr->node_wwn_s,
5927 path_struct->argv) != 0) {
5928 continue;
5929 }
5930 (void) strcpy(phys_path, wwn_list_ptr->physical_path);
5931 (void) strcpy(last_logical_path,
5932 wwn_list_ptr->logical_path);
5933 }
5934
5935 if (argnwwn || argpwwn) {
5936 if (compare_multipath(wwn_list_ptr->logical_path,
5937 mplistp) == 0) {
5938 continue;
5939 }
5940 }
5941
5942 mode_data_avail = 0;
5943
5944 (void) memset(&l_disk_state, 0, sizeof (struct l_disk_state_struct));
5945
5946 /*
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
5949 */
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);
5955 }
5956
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);
5964 }
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;
5974 }
5975 }
5976
5977 if (!found) {
5978 return (L_NO_VALID_PATH);
5979 } else {
5980 found = 0;
5981 }
5982
5983 if ((dlist = (struct dlist *)
5984 calloc(1, sizeof (struct dlist))) == NULL) {
5985 return (L_MALLOC_FAILED);
5986 }
5987 if ((dlist->logical_path = (char *)calloc(1,
5988 strlen(wwn_list_find->logical_path) + 1)) == NULL) {
5989 return (L_MALLOC_FAILED);
5990 }
5991 if ((dlist->dev_path = (char *)calloc(1,
5992 strlen(phys_path) + 1)) == NULL) {
5993 return (L_MALLOC_FAILED);
5994 }
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;
5999 }
6000
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);
6010 }
6011
6012 mpl->devpath = (char *)calloc(1, MAXPATHLEN+1);
6013 if (mpl->devpath == NULL) {
6014 adm_mplist_free(mplistp);
6015 return (L_MALLOC_FAILED);
6016 }
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;
6024 }
6025 }
6026 }
6027
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];
6035
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;
6042 }
6043 offset += pg_hdr->length + sizeof (struct mode_page);
6044 pg_hdr = (struct mode_page *)&pg_buf[offset];
6045 }
6046 }
6047
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;
6061 }
6062
6063 (void) display_lun_info(l_disk_state, path_struct, pg_hdr,
6064 mode_data_avail, wwn_list, phys_path);
6065
6066 (void) g_free_multipath(l_disk_state.g_disk_state.multipath_list);
6067
6068 if (!(argpwwn || argnwwn)) {
6069 break;
6070 }
6071
6072 } /* End for wwn_list_ptr = list_start... */
6073
6074 (void) g_free_wwn_list(&wwn_list);
6075 adm_mplist_free(mplistp);
6076 return (0);
6077 }
6078
6079 /*
6080 * display_lun_info() Prints the device specific information
6081 * for a lun.
6082 *
6083 * RETURNS:
6084 * none.
6085 */
6086 void
display_lun_info(L_disk_state l_disk_state,Path_struct * path_struct,struct mode_page * pg_hdr,int mode_data_avail,WWN_list * wwn_list,char * phys_path)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)
6090 {
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);
6102
6103 if ((envdb = getenv("_LUX_T_DEBUG")) != NULL) {
6104 start_time = gethrtime();
6105 }
6106
6107 memset(&cap_data, 0, sizeof (cap_data));
6108
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);
6114 }
6115
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);
6122 }
6123 /*
6124 * check to see if the peripheral qualifier is zero
6125 * if it is non-zero, we will return with an error.
6126 */
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);
6132 }
6133
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);
6140
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);
6145
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);
6150
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);
6155 }
6156
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);
6164 }
6165 }
6166
6167 fprintf(stdout, "\n");
6168
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"));
6174 }
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);
6182 }
6183 }
6184
6185 fprintf(stdout, " %s\t\t%s\n", MSGSTR(35, "Device Type:"),
6186 dtype[inq.inq_dtype & DTYPE_MASK]);
6187
6188
6189 fprintf(stdout, MSGSTR(2128, " Path(s):\n"));
6190 fprintf(stdout, "\n");
6191
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);
6196 }
6197
6198
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 {
6204 /*
6205 * first display user's requested path
6206 * This will avoid duplicate inquiries as well
6207 */
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;
6215 }
6216 }
6217
6218 /*
6219 * Now display rest of paths
6220 * skipping one already displayed
6221 */
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;
6227 }
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);
6233 }
6234 display_path_info(mlist->dev_path, mlist->logical_path,
6235 wwn_list);
6236 }
6237 }
6238 fprintf(stdout, "\n");
6239
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);
6245 }
6246 }
6247
6248 /*
6249 * display_path_info() Prints the path specific information
6250 * for a lun.
6251 * Note: Only applies to ssd nodes currently
6252 *
6253 * RETURNS:
6254 * none.
6255 */
6256 static void
display_path_info(char * devpath,char * logicalpath,WWN_list * wwn_list)6257 display_path_info(char *devpath, char *logicalpath, WWN_list *wwn_list)
6258 {
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;
6266
6267 fprintf(stdout, " %s\n", logicalpath);
6268 fprintf(stdout, " %s\n", devpath);
6269 fprintf(stdout, " %s\t\t", MSGSTR(2321, "LUN path port WWN:"));
6270
6271 /*
6272 * Walk the wwn list passed in and print the
6273 * port wwn matching the device path
6274 */
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;
6280 }
6281 }
6282 /*
6283 * newline here in case port wwn not found
6284 */
6285 fprintf(stdout, "\n");
6286
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);
6296 }
6297 *cptr = '\0';
6298
6299 if ((err = get_host_controller_pwwn(drvr_path,
6300 (uchar_t *)&wwn_data)) != 0) {
6301 print_errString(err, drvr_path);
6302 exit(1);
6303 }
6304
6305 copy_wwn_data_to_str(wwns, wwn_data);
6306 fprintf(stdout, " %s\t%s\n",
6307 MSGSTR(2322, "Host controller port WWN:"), wwns);
6308
6309 /*
6310 * Determine path status
6311 */
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);
6318 }
6319 }
6320
6321 /*
6322 * Retrieves the lun capacity
6323 */
6324 static int
get_lun_capacity(char * devpath,struct scsi_capacity_16 * cap_data)6325 get_lun_capacity(char *devpath, struct scsi_capacity_16 *cap_data)
6326 {
6327 int fd;
6328
6329 if (devpath == NULL || cap_data == NULL) {
6330 return (L_INVALID_PATH);
6331 }
6332
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);
6339 }
6340 return (0);
6341 }
6342
6343 /*
6344 * Retrieves the reservation status
6345 */
6346 static int
get_path_status(char * devpath,int * status)6347 get_path_status(char *devpath, int *status)
6348 {
6349 int fd, mystatus = 0;
6350
6351
6352 if (devpath == NULL || status == NULL) {
6353 return (L_INVALID_PATH);
6354 }
6355
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;
6370 }
6371 }
6372 }
6373 close(fd);
6374 return (0);
6375 }
6376
6377 /*
6378 * Description:
6379 * Retrieves the port wwn associated with the hba node
6380 *
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
6383 */
6384 static int
get_host_controller_pwwn(char * hba_path,uchar_t * pwwn)6385 get_host_controller_pwwn(char *hba_path, uchar_t *pwwn)
6386 {
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;
6399
6400 if (hba_path == NULL || pwwn == NULL) {
6401 return (L_INVALID_PATH);
6402 }
6403
6404 if ((path_type = g_get_path_type(hba_path)) == 0) {
6405 return (L_INVALID_PATH);
6406 }
6407
6408 /*
6409 * ifp nodes do not have a port-wwn prom property
6410 * so handle them via FC4 device map
6411 */
6412 if (path_type & FC4_XPORT_MASK) {
6413 if ((err = get_FC4_host_controller_pwwn(hba_path, pwwn)) != 0) {
6414 return (err);
6415 } else {
6416 return (0);
6417 }
6418 /* For Leadville path get the port wwn through g_get_host param. */
6419 } else if ((path_type & FC_GEN_XPORT) &&
6420 ((path_type & FC_FCA_MASK) == FC_FCA_MASK)) {
6421 /*
6422 * For Leadville path, get the port wwn through
6423 * g_get_host param. This is a general solution
6424 * to support 3rd party vendor Leadville FCA.
6425 */
6426 my_hba_path[0] = '\0';
6427 (void) strlcat(my_hba_path, hba_path, sizeof (my_hba_path));
6428 (void) snprintf(my_hba_path, sizeof (my_hba_path), "%s%s",
6429 hba_path, FC_CTLR);
6430 if ((err = g_get_host_params(
6431 my_hba_path, &hba_port, 0)) != 0) {
6432 return (err);
6433 } else {
6434 (void) memcpy(pwwn, &hba_port.dev_pwwn.raw_wwn[0],
6435 WWN_SIZE);
6436 return (0);
6437 }
6438 } else if ((path_type & FC_FCA_MASK) == FC_PCI_FCA) {
6439 /*
6440 * Get port WWN through prom property
6441 */
6442 my_hba_path[0] = '\0';
6443 (void) strlcat(my_hba_path, hba_path, sizeof (my_hba_path));
6444 /*
6445 * sanity check for /devices mount point
6446 */
6447 if (strlen(my_hba_path) > (devlen = strlen("/devices"))) {
6448 cptr = &my_hba_path[devlen];
6449 } else {
6450 return (L_INVALID_PATH);
6451 }
6452
6453 /*
6454 * Now strip off the trailing "/fp@"
6455 */
6456 if ((portptr = strstr(cptr, "/fp@")) != NULL) {
6457 *portptr = '\0';
6458 }
6459
6460 if ((node = di_init(cptr, DINFOCPYALL)) == DI_NODE_NIL) {
6461 return (L_DEV_SNAPSHOT_FAILED);
6462 }
6463
6464 if (di_nodeid(node) == DI_SID_NODEID) {
6465 di_ret = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
6466 "port-wwn", &port_wwn_data);
6467 if (di_ret == -1 || port_wwn_data == NULL) {
6468 di_fini(node);
6469 return (L_NO_WWN_PROP_FOUND);
6470 } else {
6471 (void) memcpy(pwwn, port_wwn_data, WWN_SIZE);
6472 found++;
6473 }
6474 } else if (di_nodeid(node) == DI_PROM_NODEID) {
6475 if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) {
6476 di_fini(node);
6477 return (L_PROM_INIT_FAILED);
6478 }
6479
6480 for (promprop = di_prom_prop_next(ph, node,
6481 DI_PROM_PROP_NIL);
6482 promprop != DI_PROM_PROP_NIL;
6483 promprop = di_prom_prop_next(ph, node, promprop)) {
6484 if (((promname = di_prom_prop_name(
6485 promprop)) != NULL) &&
6486 (strcmp(promname, "port-wwn") == 0) &&
6487 (di_prom_prop_data(promprop,
6488 &promdata) == WWN_SIZE)) {
6489 /* Found port-wwn */
6490 (void) memcpy(pwwn, promdata, WWN_SIZE);
6491 found++;
6492 break;
6493 }
6494 }
6495 di_prom_fini(ph);
6496 }
6497
6498 di_fini(node);
6499 if (found) {
6500 return (0);
6501 } else {
6502 return (L_INVALID_PATH);
6503 }
6504 } else {
6505 return (L_INVALID_PATH_TYPE);
6506 }
6507 }
6508
6509
6510 /*
6511 * Description:
6512 * Retrieve pwwn via SFIOCGMAP
6513 */
6514 static int
get_FC4_host_controller_pwwn(char * hba_path,uchar_t * pwwn)6515 get_FC4_host_controller_pwwn(char *hba_path, uchar_t *pwwn)
6516 {
6517 sf_al_map_t sf_map;
6518 char my_hba_path[MAXPATHLEN];
6519 int fd;
6520
6521 if (hba_path == NULL || pwwn == NULL) {
6522 return (L_INVALID_PATH);
6523 }
6524
6525 (void) snprintf(my_hba_path, sizeof (my_hba_path), "%s%s",
6526 hba_path, FC_CTLR);
6527
6528 if ((fd = g_object_open(my_hba_path, O_NDELAY | O_RDONLY)) == -1) {
6529 return (errno);
6530 }
6531
6532 memset(&sf_map, 0, sizeof (sf_al_map_t));
6533
6534 if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
6535 close(fd);
6536 return (L_SFIOCGMAP_IOCTL_FAIL);
6537 }
6538
6539 close(fd);
6540
6541 if (sf_map.sf_count == 0) {
6542 close(fd);
6543 return (L_SFIOCGMAP_IOCTL_FAIL);
6544 }
6545
6546 (void) memcpy(pwwn, &sf_map.sf_hba_addr.sf_port_wwn[0], WWN_SIZE);
6547
6548 return (0);
6549 }
6550
6551 /*
6552 * from_ptr: ptr to uchar_t array of size WWN_SIZE
6553 * to_ptr: char ptr to string of size WWN_SIZE*2+1
6554 */
6555 void
copy_wwn_data_to_str(char * to_ptr,const uchar_t * from_ptr)6556 copy_wwn_data_to_str(char *to_ptr, const uchar_t *from_ptr)
6557 {
6558 if ((to_ptr == NULL) || (from_ptr == NULL))
6559 return;
6560
6561 sprintf(to_ptr, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
6562 from_ptr[0], from_ptr[1], from_ptr[2], from_ptr[3],
6563 from_ptr[4], from_ptr[5], from_ptr[6], from_ptr[7]);
6564 }
6565
6566 /*
6567 * Frees a previously allocated mplist_struct
6568 */
6569 void
adm_mplist_free(struct mplist_struct * mplistp)6570 adm_mplist_free(struct mplist_struct *mplistp)
6571 {
6572 struct mplist_struct *mplistn;
6573
6574 while (mplistp != NULL) {
6575 mplistn = mplistp->next;
6576 if (mplistp->devpath != NULL) {
6577 free(mplistp->devpath);
6578 mplistp->devpath = NULL;
6579 }
6580 free(mplistp);
6581 mplistp = mplistn;
6582 }
6583 }
6584
6585 int
adm_reserve(char * path)6586 adm_reserve(char *path)
6587 {
6588 char *path_phys = NULL;
6589 int err;
6590 if ((path_phys =
6591 g_get_physical_name(path)) == NULL) {
6592
6593 (void) fprintf(stderr, "%s: ", whoami);
6594 (void) fprintf(stderr,
6595 MSGSTR(112, "Error: Invalid pathname (%s)"),
6596 path);
6597 (void) fprintf(stderr, "\n");
6598 return (1);
6599 }
6600
6601 if ((err = g_reserve(path_phys)) != 0) {
6602 (void) print_errString(err, path);
6603 return (1);
6604 }
6605 return (0);
6606 }
6607
6608 int
adm_release(char * path)6609 adm_release(char *path)
6610 {
6611 char *path_phys = NULL;
6612 int err;
6613 if ((path_phys =
6614 g_get_physical_name(path)) == NULL) {
6615
6616 (void) fprintf(stderr, "%s: ", whoami);
6617 (void) fprintf(stderr,
6618 MSGSTR(112, "Error: Invalid pathname (%s)"),
6619 path);
6620 (void) fprintf(stderr, "\n");
6621 return (1);
6622 }
6623
6624 if ((err = g_release(path_phys)) != 0) {
6625 (void) print_errString(err, path);
6626 return (1);
6627 }
6628 return (0);
6629 }
6630
6631 void
i18n_catopen()6632 i18n_catopen() {
6633 (void) g_i18n_catopen();
6634 }
6635
adm_check_file(char ** path,int flag)6636 int adm_check_file(char **path, int flag) {
6637 int err;
6638 if (err = l_check_file(*path, flag)) {
6639 (void) print_errString(err, *path);
6640 return (-1);
6641 }
6642
6643 (void) fprintf(stdout, MSGSTR(2212, "Download file O.K. \n\n"));
6644 return (0);
6645 }
6646
6647 /*
6648 * Print out private loop dev dtype
6649 */
6650 void
print_private_loop_dtype_prop(uchar_t * hba_port_wwn,uchar_t * port_wwn,uchar_t dtype_prop)6651 print_private_loop_dtype_prop(uchar_t *hba_port_wwn, uchar_t *port_wwn,
6652 uchar_t dtype_prop)
6653 {
6654 if ((dtype_prop & DTYPE_MASK) < 0x10) {
6655 (void) fprintf(stdout, " 0x%-2x (%s",
6656 (dtype_prop & DTYPE_MASK), dtype[(dtype_prop & DTYPE_MASK)]);
6657 } else if ((dtype_prop & DTYPE_MASK) < 0x1f) {
6658 (void) fprintf(stdout,
6659 MSGSTR(2243, " 0x%-2x (Reserved"),
6660 (dtype_prop & DTYPE_MASK));
6661 } else {
6662 (void) fprintf(stdout, MSGSTR(2245,
6663 " 0x%-2x (Unknown Type"), (dtype_prop & DTYPE_MASK));
6664 }
6665 /* Check to see if this is the HBA */
6666 if (wwnConversion(hba_port_wwn) == wwnConversion(port_wwn)) {
6667 /* MATCH */
6668 (void) fprintf(stdout, MSGSTR(2244,
6669 ",Host Bus Adapter)\n"));
6670 } else {
6671 (void) fprintf(stdout, ")\n");
6672 }
6673 }
6674