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 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 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 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 = '\0'; 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 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 = '\0'; 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 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 = '\0'; 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 != '\0') && 2321 (*fc_stats->port_wwn[port] != '\0')) { 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 != '\0') { 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 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 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 != '\0') && 2617 (*ifp_stats.port_wwn != '\0')) { 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 != 0) { 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 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 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 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 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 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 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 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 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 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 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 = NULL, *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 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 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 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 = NULL; 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 != 0) { 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 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 = NULL; 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 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 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 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 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 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 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 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 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 != 0) { 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 != 0) { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 = NULL; 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 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 = 0, 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 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 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 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 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 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 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 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 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 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 6632 i18n_catopen() { 6633 (void) g_i18n_catopen(); 6634 } 6635 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 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