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 29 /*LINTLIBRARY*/ 30 31 32 /* 33 * Administration program for SENA 34 * subsystems and individual FC_AL devices. 35 */ 36 37 /* 38 * I18N message number ranges 39 * This file: 2000 - 2999 40 * Shared common messages: 1 - 1999 41 */ 42 43 /* #define _POSIX_SOURCE 1 */ 44 45 /* 46 * These defines are used to map instance number from sf minor node. 47 * They are copied from SF_INST_SHIFT4MINOR and SF_MINOR2INST in sfvar.h. 48 * sfvar.h is not clean for userland use. 49 * When it is cleaned up, these defines will be removed and sfvar.h 50 * will be included in luxadm.h header file. 51 */ 52 #define LUX_SF_INST_SHIFT4MINOR 6 53 #define LUX_SF_MINOR2INST(x) (x >> LUX_SF_INST_SHIFT4MINOR) 54 55 /* Includes */ 56 #include <stdlib.h> 57 #include <stdio.h> 58 #include <sys/file.h> 59 #include <sys/errno.h> 60 #include <sys/types.h> 61 #include <sys/stat.h> 62 #include <sys/param.h> 63 #include <fcntl.h> 64 #include <unistd.h> 65 #include <errno.h> 66 #include <string.h> 67 #include <ctype.h> 68 #include <strings.h> 69 #include <sys/stat.h> 70 #include <dirent.h> 71 #include <limits.h> 72 #include <stdarg.h> 73 #include <termio.h> /* For password */ 74 #include <sys/scsi/scsi.h> 75 76 #include "common.h" 77 #include "luxadm.h" 78 79 80 /* Global variables */ 81 char *dtype[16]; /* setting a global for later use. */ 82 char *whoami; 83 int Options; 84 const int OPTION_A = 0x00000001; 85 const int OPTION_B = 0x00000002; 86 const int OPTION_C = 0x00000004; 87 const int OPTION_D = 0x00000008; 88 const int OPTION_E = 0x00000010; 89 const int OPTION_F = 0x00000020; 90 const int OPTION_L = 0x00000040; 91 const int OPTION_P = 0x00000080; 92 const int OPTION_R = 0x00000100; 93 const int OPTION_T = 0x00000200; 94 const int OPTION_V = 0x00000400; 95 const int OPTION_Z = 0x00001000; 96 const int OPTION_Y = 0x00002000; 97 const int OPTION_CAPF = 0x00004000; 98 const int PVERBOSE = 0x00008000; 99 const int SAVE = 0x00010000; 100 const int EXPERT = 0x00020000; 101 102 /* 103 * Given a pointer to a character array, print the character array. 104 * the character array will not necesarily be NULL terminated. 105 * 106 * Inputs: 107 * size - the max number of characters to print 108 * fill_flag - flag when set fills all NULL characters with spaces 109 * Returns: 110 * N/A 111 */ 112 void 113 print_chars(uchar_t *buffer, int size, int fill_flag) 114 { 115 116 int i; 117 118 for (i = 0; i < size; i++) { 119 if (buffer[i]) 120 (void) fprintf(stdout, "%c", buffer[i]); 121 else if (fill_flag) 122 (void) fprintf(stdout, " "); 123 else 124 return; 125 } 126 } 127 128 /* 129 * Name : memstrstr 130 * Input : pointer to buf1, pointer to buf2, size of buf1, size of buf2 131 * Returns : 132 * Pointer to start of contents-of-buf2 in buf1 if it is found 133 * NULL if buf1 does not contain contents of buf2 134 * Synopsis: 135 * This function works similar to strstr(). The difference is that null 136 * characters in the buffer are treated like any other character. So, buf1 137 * and buf2 can have embedded null characters in them. 138 */ 139 static char * 140 memstrstr(char *s1, char *s2, int size1, int size2) 141 { 142 int count1, count2; 143 char *s1_ptr, *s2_ptr; 144 145 count1 = size1; count2 = size2; 146 s1_ptr = s1; s2_ptr = s2; 147 148 if (size2 == 0) 149 return (s1); 150 151 while (count1--) { 152 if (*s1_ptr++ == *s2_ptr++) { 153 if (--count2 == 0) 154 return (s1_ptr - size2); 155 continue; 156 } 157 count2 = size2; 158 s2_ptr = s2; 159 } 160 161 return (NULL); 162 } 163 164 165 /* 166 * Download host bus adapter FCode to all supported cards. 167 * 168 * Specify a directory that holds the FCode files, or 169 * it will use the default dir. Each file is dealt to 170 * the appropriate function. 171 * 172 * -p prints current versions only, -d specifies a directory to load 173 */ 174 static int 175 adm_fcode(int verbose, char *dir) 176 { 177 struct stat statbuf; 178 struct dirent *dirp; 179 DIR *dp; 180 int fp; 181 char fbuf[BUFSIZ]; 182 char file[MAXPATHLEN]; 183 int retval = 0, strfound = 0; 184 char manf[BUFSIZ]; 185 186 /* Find all adapters and print the current FCode version */ 187 if (Options & OPTION_P) { 188 189 /* SOCAL (SBus) adapters are not supported on x86 */ 190 #ifndef __x86 191 if (verbose) { 192 (void) fprintf(stdout, 193 MSGSTR(2215, "\n Searching for FC100/S cards:\n")); 194 } 195 retval += fcal_update(Options & PVERBOSE, NULL); 196 #endif 197 198 if (verbose) { 199 (void) fprintf(stdout, 200 MSGSTR(2216, "\n Searching for FC100/P, FC100/2P cards:\n")); 201 } 202 retval += q_qlgc_update(Options & PVERBOSE, NULL); 203 if (verbose) { 204 (void) fprintf(stdout, 205 MSGSTR(2503, "\n Searching for Emulex cards:\n")); 206 } 207 retval += emulex_update(NULL); 208 209 /* Send files to the correct function for loading to the HBA */ 210 } else { 211 212 if (!dir) { 213 (void) fprintf(stdout, MSGSTR(2251, 214 " Location of Fcode not specified.\n")); 215 return (1); 216 217 } else if (verbose) { 218 (void) fprintf(stdout, MSGSTR(2217, 219 " Using directory %s"), dir); 220 } 221 if (lstat(dir, &statbuf) < 0) { 222 (void) fprintf(stderr, MSGSTR(134, 223 "%s: lstat() failed - %s\n"), 224 dir, strerror(errno)); 225 return (1); 226 } 227 if (S_ISDIR(statbuf.st_mode) == 0) { 228 (void) fprintf(stderr, 229 MSGSTR(2218, "Error: %s is not a directory.\n"), dir); 230 return (1); 231 } 232 if ((dp = opendir(dir)) == NULL) { 233 (void) fprintf(stderr, MSGSTR(2219, 234 " Error Cannot open directory %s\n"), dir); 235 return (1); 236 } 237 238 while ((dirp = readdir(dp)) != NULL) { 239 if (strcmp(dirp->d_name, ".") == 0 || 240 strcmp(dirp->d_name, "..") == 0) { 241 continue; 242 } 243 sprintf(file, "%s/%s", dir, dirp->d_name); 244 245 if ((fp = open(file, O_RDONLY)) < 0) { 246 (void) fprintf(stderr, 247 MSGSTR(2220, 248 "Error: open() failed to open file " 249 "%s\n"), file); 250 /* 251 * We should just issue an error message and 252 * make an attempt on the next file, 253 * and the open error is still an error 254 * so the retval should be incremented 255 */ 256 retval++; 257 continue; 258 } 259 while ((read(fp, fbuf, BUFSIZ)) > 0) { 260 if (memstrstr(fbuf, "SUNW,socal", 261 BUFSIZ, strlen("SUNW,socal")) 262 != NULL) { 263 (void) fprintf(stdout, MSGSTR(2221, 264 "\n Using file: %s\n"), file); 265 retval += fcal_update( 266 Options & PVERBOSE, file); 267 strfound++; 268 break; 269 } else if ((memstrstr(fbuf, "SUNW,ifp", 270 BUFSIZ, strlen("SUNW,ifp")) 271 != NULL) || 272 (memstrstr(fbuf, "SUNW,qlc", 273 BUFSIZ, strlen("SUNW,qlc")) 274 != NULL)) { 275 (void) fprintf(stdout, MSGSTR(2221, 276 "\n Using file: %s\n"), file); 277 retval += q_qlgc_update( 278 Options & PVERBOSE, file); 279 strfound++; 280 break; 281 } 282 } 283 if (!strfound) { 284 /* check to see if this is an emulex fcode */ 285 memset(manf, 0, sizeof (manf)); 286 if ((emulex_fcode_reader(fp, "manufacturer", 287 manf, 288 sizeof (manf)) == 0) && 289 (strncmp(manf, "Emulex", sizeof (manf)) 290 == 0)) { 291 retval += emulex_update(file); 292 strfound = 0; 293 } else { 294 (void) fprintf(stderr, MSGSTR(2222, 295 "\nError: %s is not a valid Fcode " 296 "file.\n"), file); 297 retval++; 298 } 299 } else { 300 strfound = 0; 301 } 302 close(fp); 303 } 304 closedir(dp); 305 } 306 return (retval); 307 } 308 309 /* 310 * Definition of getaction() routine which does keyword parsing 311 * 312 * Operation: A character string containing the ascii cmd to be 313 * parsed is passed in along with an array of structures. 314 * The 1st struct element is a recognizable cmd string, the second 315 * is the minimum number of characters from the start of this string 316 * to succeed on a match. For example, { "offline", 3, ONLINE } 317 * will match "off", "offli", "offline", but not "of" nor "offlinebarf" 318 * The third element is the {usually but not necessarily unique} 319 * integer to return on a successful match. Note: compares are cAsE insensitive. 320 * 321 * To change, extend or use this utility, just add or remove appropriate 322 * lines in the structure initializer below and in the #define s for the 323 * return values. 324 * 325 * N O T E 326 * Do not change the minimum number of characters to produce 327 * a match as someone may be building scripts that use this 328 * feature. 329 */ 330 struct keyword { 331 char *match; /* Character String to match against */ 332 int num_match; /* Minimum chars to produce a match */ 333 int ret_code; /* Value to return on a match */ 334 }; 335 336 static struct keyword Keywords[] = { 337 {"display", 2, DISPLAY}, 338 {"download", 3, DOWNLOAD}, 339 {"enclosure_names", 2, ENCLOSURE_NAMES}, 340 {"failover", 3, FAILOVER}, 341 {"fcal_s_download", 4, FCAL_UPDATE}, 342 {"fcode_download", 4, FCODE_UPDATE}, 343 {"inquiry", 2, INQUIRY}, 344 {"insert_device", 3, INSERT_DEVICE}, 345 {"led", 3, LED}, 346 {"led_on", 5, LED_ON}, 347 {"led_off", 5, LED_OFF}, 348 {"led_blink", 5, LED_BLINK}, 349 {"password", 2, PASSWORD}, 350 {"power_on", 8, POWER_ON}, 351 {"power_off", 9, POWER_OFF}, 352 {"probe", 2, PROBE}, 353 {"qlgc_s_download", 4, QLGC_UPDATE}, 354 {"remove_device", 3, REMOVE_DEVICE}, 355 {"reserve", 5, RESERVE}, 356 {"release", 3, RELEASE}, 357 {"set_boot_dev", 5, SET_BOOT_DEV}, 358 {"start", 3, START}, 359 {"stop", 3, STOP}, 360 {"rdls", 2, RDLS}, 361 {"bypass", 3, BYPASS}, 362 {"enable", 3, ENABLE}, 363 {"p_offline", 4, LUX_P_OFFLINE}, 364 {"p_online", 4, LUX_P_ONLINE}, 365 {"forcelip", 2, FORCELIP}, 366 {"dump", 2, DUMP}, 367 {"check_file", 2, CHECK_FILE}, 368 {"dump_map", 2, DUMP_MAP}, 369 {"sysdump", 5, SYSDUMP}, 370 {"port", 4, PORT}, 371 {"external_loopback", 12, EXT_LOOPBACK}, 372 {"internal_loopback", 12, INT_LOOPBACK}, 373 {"no_loopback", 11, NO_LOOPBACK}, 374 {"version", 2, VERSION}, 375 {"create_fabric_device", 2, CREATE_FAB}, 376 /* hotplugging device operations */ 377 {"online", 2, DEV_ONLINE}, 378 {"offline", 2, DEV_OFFLINE}, 379 {"dev_getstate", 5, DEV_GETSTATE}, 380 {"dev_reset", 5, DEV_RESET}, 381 /* hotplugging bus operations */ 382 {"bus_quiesce", 5, BUS_QUIESCE}, 383 {"bus_unquiesce", 5, BUS_UNQUIESCE}, 384 {"bus_getstate", 5, BUS_GETSTATE}, 385 {"bus_reset", 9, BUS_RESET}, 386 {"bus_resetall", 12, BUS_RESETALL}, 387 /* hotplugging "helper" subcommands */ 388 { NULL, 0, 0} 389 }; 390 391 #ifndef EOK 392 static const int EOK = 0; /* errno.h type success return code */ 393 #endif 394 395 396 /* 397 * function getaction() takes a character string, cmd, and 398 * tries to match it against a passed structure of known cmd 399 * character strings. If a match is found, corresponding code 400 * is returned in retval. Status returns as follows: 401 * EOK = Match found, look for cmd's code in retval 402 * EFAULT = One of passed parameters was bad 403 * EINVAL = cmd did not match any in list 404 */ 405 static int 406 getaction(char *cmd, struct keyword *matches, int *retval) 407 { 408 int actlen; 409 410 /* Idiot checking of pointers */ 411 if (! cmd || ! matches || ! retval || 412 ! (actlen = strlen(cmd))) /* Is there an cmd ? */ 413 return (EFAULT); 414 415 /* Keep looping until NULL match string (end of list) */ 416 while (matches->match) { 417 /* 418 * Precedence: Make sure target is no longer than 419 * current match string 420 * and target is at least as long as 421 * minimum # match chars, 422 * then do case insensitive match 423 * based on actual target size 424 */ 425 if ((((int)strlen(matches->match)) >= actlen) && 426 (actlen >= matches->num_match) && 427 /* can't get strncasecmp to work on SCR4 */ 428 /* (strncasecmp(matches->match, cmd, actlen) == 0) */ 429 (strncmp(matches->match, cmd, actlen) == 0)) { 430 *retval = matches->ret_code; /* Found our match */ 431 return (EOK); 432 } else { 433 matches++; /* Next match string/struct */ 434 } 435 } /* End of matches loop */ 436 return (EINVAL); 437 438 } /* End of getaction() */ 439 440 /* main functions. */ 441 int 442 main(int argc, char **argv) 443 { 444 register int c; 445 /* getopt varbs */ 446 extern char *optarg; 447 char *optstring = NULL; 448 int path_index, err = 0; 449 int cmd = 0; /* Cmd verb from cmd line */ 450 int exit_code = 0; /* exit code for program */ 451 int temp_fd; /* For -f option */ 452 char *file_name = NULL; 453 int option_t_input; 454 char *path_phys = NULL; 455 int USE_FCHBA = 0; 456 457 whoami = argv[0]; 458 459 460 /* 461 * Enable locale announcement 462 */ 463 i18n_catopen(); 464 465 while ((c = getopt(argc, argv, "ve")) 466 != EOF) { 467 switch (c) { 468 case 'v': 469 Options |= PVERBOSE; 470 break; 471 case 'e': 472 Options |= EXPERT; 473 break; 474 default: 475 /* Note: getopt prints an error if invalid option */ 476 USEAGE() 477 exit(-1); 478 } /* End of switch(c) */ 479 } 480 setbuf(stdout, NULL); /* set stdout unbuffered. */ 481 482 /* 483 * Build any i18n global variables 484 */ 485 dtype[0] = MSGSTR(2192, "Disk device"); 486 dtype[1] = MSGSTR(2193, "Tape device"); 487 dtype[2] = MSGSTR(2194, "Printer device"); 488 dtype[3] = MSGSTR(2195, "Processor device"); 489 dtype[4] = MSGSTR(2196, "WORM device"); 490 dtype[5] = MSGSTR(2197, "CD-ROM device"); 491 dtype[6] = MSGSTR(2198, "Scanner device"); 492 dtype[7] = MSGSTR(2199, "Optical memory device"); 493 dtype[8] = MSGSTR(2200, "Medium changer device"); 494 dtype[9] = MSGSTR(2201, "Communications device"); 495 dtype[10] = MSGSTR(107, "Graphic arts device"); 496 dtype[11] = MSGSTR(107, "Graphic arts device"); 497 dtype[12] = MSGSTR(2202, "Array controller device"); 498 dtype[13] = MSGSTR(2203, "SES device"); 499 dtype[14] = MSGSTR(71, "Reserved"); 500 dtype[15] = MSGSTR(71, "Reserved"); 501 502 503 504 /* 505 * Get subcommand. 506 */ 507 if ((getaction(argv[optind], Keywords, &cmd)) == EOK) { 508 optind++; 509 if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && 510 (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && 511 (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && (cmd != AU) && 512 (cmd != PORT) && (cmd != CREATE_FAB) && (optind >= argc)) { 513 (void) fprintf(stderr, 514 MSGSTR(2204, 515 "Error: enclosure or pathname not specified.\n")); 516 USEAGE(); 517 exit(-1); 518 } 519 } else { 520 (void) fprintf(stderr, 521 MSGSTR(2205, "%s: subcommand not specified.\n"), 522 whoami); 523 USEAGE(); 524 exit(-1); 525 } 526 527 /* Extract & Save subcommand options */ 528 if ((cmd == ENABLE) || (cmd == BYPASS)) { 529 optstring = "Ffrab"; 530 } else if (cmd == FCODE_UPDATE) { 531 optstring = "pd:"; 532 } else if (cmd == REMOVE_DEVICE) { 533 optstring = "F"; 534 } else if (cmd == CREATE_FAB) { 535 optstring = "f:"; 536 } else { 537 optstring = "Fryszabepcdlvt:f:w:"; 538 } 539 while ((c = getopt(argc, argv, optstring)) != EOF) { 540 switch (c) { 541 case 'a': 542 Options |= OPTION_A; 543 break; 544 case 'b': 545 Options |= OPTION_B; 546 break; 547 case 'c': 548 Options |= OPTION_C; 549 break; 550 case 'd': 551 Options |= OPTION_D; 552 if (cmd == FCODE_UPDATE) { 553 file_name = optarg; 554 } 555 break; 556 case 'e': 557 Options |= OPTION_E; 558 break; 559 case 'f': 560 Options |= OPTION_F; 561 if (!((cmd == ENABLE) || (cmd == BYPASS))) { 562 file_name = optarg; 563 } 564 break; 565 case 'F': 566 Options |= OPTION_CAPF; 567 break; 568 case 'l': 569 Options |= OPTION_L; 570 break; 571 case 'p': 572 Options |= OPTION_P; 573 break; 574 case 'r': 575 Options |= OPTION_R; 576 break; 577 case 's': 578 Options |= SAVE; 579 break; 580 case 't': 581 Options |= OPTION_T; 582 option_t_input = atoi(optarg); 583 break; 584 case 'v': 585 Options |= OPTION_V; 586 break; 587 case 'z': 588 Options |= OPTION_Z; 589 break; 590 case 'y': 591 Options |= OPTION_Y; 592 break; 593 default: 594 /* Note: getopt prints an error if invalid option */ 595 USEAGE() 596 exit(-1); 597 } /* End of switch(c) */ 598 } 599 if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && 600 (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && 601 (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && 602 (cmd != AU) && (cmd != PORT) && 603 (cmd != CREATE_FAB) && (optind >= argc)) { 604 (void) fprintf(stderr, 605 MSGSTR(2206, 606 "Error: enclosure or pathname not specified.\n")); 607 USEAGE(); 608 exit(-1); 609 } 610 path_index = optind; 611 612 /* 613 * Check if the file supplied with the -f option is valid 614 * Some sub commands (bypass for example) use the -f option 615 * for other reasons. In such cases, "file_name" should be 616 * NULL. 617 */ 618 if ((file_name != NULL) && (Options & OPTION_F)) { 619 if ((temp_fd = open(file_name, O_RDONLY)) == -1) { 620 perror(file_name); 621 exit(-1); 622 } else { 623 close(temp_fd); 624 } 625 } 626 627 /* Determine which mode to operate in (FC-HBA or original) */ 628 USE_FCHBA = use_fchba(); 629 630 switch (cmd) { 631 case DISPLAY: 632 if (Options & 633 ~(PVERBOSE | OPTION_A | OPTION_Z | OPTION_R | 634 OPTION_P | OPTION_V | OPTION_L | OPTION_E | OPTION_T)) { 635 USEAGE(); 636 exit(-1); 637 } 638 /* Display object(s) */ 639 if (USE_FCHBA) { 640 exit_code = fchba_display_config(&argv[path_index], 641 option_t_input, argc - path_index); 642 } else { 643 exit_code = adm_display_config(&argv[path_index]); 644 } 645 break; 646 647 case DOWNLOAD: 648 if (Options & 649 ~(PVERBOSE | OPTION_F | SAVE)) { 650 USEAGE(); 651 exit(-1); 652 } 653 adm_download(&argv[path_index], file_name); 654 break; 655 656 case ENCLOSURE_NAMES: 657 if (Options & ~PVERBOSE) { 658 USEAGE(); 659 exit(-1); 660 } 661 up_encl_name(&argv[path_index], argc); 662 break; 663 664 case FAILOVER: 665 if (Options & ~PVERBOSE) { 666 USEAGE(); 667 exit(-1); 668 } 669 adm_failover(&argv[path_index]); 670 break; 671 672 case INQUIRY: 673 if (Options & ~(PVERBOSE)) { 674 USEAGE(); 675 exit(-1); 676 } 677 if (USE_FCHBA) { 678 exit_code = fchba_inquiry(&argv[path_index]); 679 } else { 680 exit_code = adm_inquiry(&argv[path_index]); 681 } 682 break; 683 684 case PROBE: 685 if (Options & ~(PVERBOSE | OPTION_P)) { 686 USEAGE(); 687 exit(-1); 688 } 689 /* 690 * A special check just in case someone entered 691 * any characters after the -p or the probe. 692 * 693 * (I know, a nit.) 694 */ 695 if (((Options & PVERBOSE) && (Options & OPTION_P) && 696 (argc != 4)) || 697 (!(Options & PVERBOSE) && (Options & OPTION_P) && 698 (argc != 3)) || 699 ((Options & PVERBOSE) && (!(Options & OPTION_P)) && 700 (argc != 3)) || 701 (!(Options & PVERBOSE) && (!(Options & OPTION_P)) && 702 (argc != 2))) { 703 (void) fprintf(stderr, 704 MSGSTR(114, "Error: Incorrect number of arguments.\n")); 705 (void) fprintf(stderr, MSGSTR(2208, 706 "Usage: %s [-v] subcommand [option]\n"), whoami); 707 exit(-1); 708 } 709 if (USE_FCHBA) { 710 exit_code = fchba_non_encl_probe(); 711 } else { 712 pho_probe(); 713 non_encl_probe(); 714 } 715 break; 716 717 case FCODE_UPDATE: /* Update Fcode in all cards */ 718 if ((Options & ~(PVERBOSE)) & 719 ~(OPTION_P | OPTION_D) || argv[path_index]) { 720 USEAGE(); 721 exit(-1); 722 } 723 if (!((Options & (OPTION_P | OPTION_D)) && 724 !((Options & OPTION_P) && (Options & OPTION_D)))) { 725 USEAGE(); 726 exit(-1); 727 } 728 if (adm_fcode(Options & PVERBOSE, file_name) != 0) { 729 exit(-1); 730 } 731 break; 732 733 case QLGC_UPDATE: /* Update Fcode in PCI HBA card(s) */ 734 if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || 735 argv[path_index]) { 736 USEAGE(); 737 exit(-1); 738 } 739 if (q_qlgc_update(Options & PVERBOSE, file_name) != 0) { 740 exit(-1); 741 } 742 break; 743 744 case FCAL_UPDATE: /* Update Fcode in Sbus soc+ card */ 745 if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || 746 argv[path_index]) { 747 USEAGE(); 748 exit(-1); 749 } 750 exit_code = fcal_update(Options & PVERBOSE, file_name); 751 break; 752 753 case SET_BOOT_DEV: /* Set boot-device variable in nvram */ 754 exit_code = setboot(Options & OPTION_Y, 755 Options & PVERBOSE, argv[path_index]); 756 break; 757 758 case LED: 759 if (Options & ~(PVERBOSE)) { 760 USEAGE(); 761 exit(-1); 762 } 763 adm_led(&argv[path_index], L_LED_STATUS); 764 break; 765 case LED_ON: 766 if (Options & ~(PVERBOSE)) { 767 USEAGE(); 768 exit(-1); 769 } 770 adm_led(&argv[path_index], L_LED_ON); 771 break; 772 case LED_OFF: 773 if (Options & ~(PVERBOSE)) { 774 USEAGE(); 775 exit(-1); 776 } 777 adm_led(&argv[path_index], L_LED_OFF); 778 break; 779 case LED_BLINK: 780 if (Options & ~(PVERBOSE)) { 781 USEAGE(); 782 exit(-1); 783 } 784 adm_led(&argv[path_index], L_LED_RQST_IDENTIFY); 785 break; 786 case PASSWORD: 787 if (Options & ~(PVERBOSE)) { 788 USEAGE(); 789 exit(-1); 790 } 791 up_password(&argv[path_index]); 792 break; 793 794 case RESERVE: 795 796 if (Options & (~PVERBOSE)) { 797 USEAGE(); 798 exit(-1); 799 } 800 VERBPRINT(MSGSTR(2209, 801 " Reserving: \n %s\n"), argv[path_index]); 802 if (USE_FCHBA) { 803 struct stat sbuf; 804 /* Just stat the argument and make sure it exists */ 805 if (stat(argv[path_index], &sbuf) < 0) { 806 (void) fprintf(stderr, "%s: ", whoami); 807 (void) fprintf(stderr, 808 MSGSTR(112, "Error: Invalid pathname (%s)"), 809 argv[path_index]); 810 (void) fprintf(stderr, "\n"); 811 exit(-1); 812 } 813 path_phys = argv[path_index]; 814 if (err = scsi_reserve(path_phys)) { 815 (void) print_errString(err, argv[path_index]); 816 exit(-1); 817 } 818 } else { 819 exit_code = adm_reserve(argv[path_index]); 820 } 821 break; 822 823 case RELEASE: 824 if (Options & (~PVERBOSE)) { 825 USEAGE(); 826 exit(-1); 827 } 828 VERBPRINT(MSGSTR(2210, " Canceling Reservation for:\n %s\n"), 829 argv[path_index]); 830 if (USE_FCHBA) { 831 struct stat sbuf; 832 /* Just stat the argument and make sure it exists */ 833 if (stat(argv[path_index], &sbuf) < 0) { 834 (void) fprintf(stderr, "%s: ", whoami); 835 (void) fprintf(stderr, 836 MSGSTR(112, "Error: Invalid pathname (%s)"), 837 argv[path_index]); 838 (void) fprintf(stderr, "\n"); 839 exit(-1); 840 } 841 path_phys = argv[path_index]; 842 if (err = scsi_release(path_phys)) { 843 (void) print_errString(err, argv[path_index]); 844 exit(-1); 845 } 846 } else { 847 exit_code = adm_release(argv[path_index]); 848 } 849 break; 850 851 case START: 852 if (Options & ~(PVERBOSE)) { 853 USEAGE(); 854 exit(-1); 855 } 856 exit_code = adm_start(&argv[path_index]); 857 break; 858 859 case STOP: 860 if (Options & ~(PVERBOSE)) { 861 USEAGE(); 862 exit(-1); 863 } 864 exit_code = adm_stop(&argv[path_index]); 865 break; 866 867 case POWER_OFF: 868 if (Options & ~(PVERBOSE | OPTION_CAPF)) { 869 USEAGE(); 870 exit(-1); 871 } 872 exit_code = adm_power_off(&argv[path_index], 1); 873 break; 874 875 case POWER_ON: 876 if (Options & (~PVERBOSE)) { 877 USEAGE(); 878 exit(-1); 879 } 880 exit_code = adm_power_off(&argv[path_index], 0); 881 break; 882 883 /* 884 * EXPERT commands. 885 */ 886 887 case FORCELIP: 888 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 889 E_USEAGE(); 890 exit(-1); 891 } 892 exit_code = adm_forcelip(&argv[path_index]); 893 break; 894 895 case BYPASS: 896 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | 897 OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | 898 OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || 899 ((Options & OPTION_A) && (Options & OPTION_B))) { 900 E_USEAGE(); 901 exit(-1); 902 } 903 adm_bypass_enable(&argv[path_index], 1); 904 break; 905 906 case ENABLE: 907 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | 908 OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | 909 OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || 910 ((Options & OPTION_A) && (Options & OPTION_B))) { 911 E_USEAGE(); 912 exit(-1); 913 } 914 adm_bypass_enable(&argv[path_index], 0); 915 break; 916 case LUX_P_OFFLINE: /* Offline a port */ 917 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 918 E_USEAGE(); 919 exit(-1); 920 } 921 exit_code = adm_port_offline_online(&argv[path_index], 922 LUX_P_OFFLINE); 923 break; 924 925 case LUX_P_ONLINE: /* Online a port */ 926 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 927 E_USEAGE(); 928 exit(-1); 929 } 930 exit_code = adm_port_offline_online(&argv[path_index], 931 LUX_P_ONLINE); 932 break; 933 934 case RDLS: 935 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 936 E_USEAGE(); 937 exit(-1); 938 } 939 if (USE_FCHBA) { 940 exit_code = fchba_display_link_status(&argv[path_index]); 941 } else { 942 display_link_status(&argv[path_index]); 943 } 944 break; 945 946 case CREATE_FAB: 947 if (!(Options & (EXPERT | OPTION_F)) || 948 (Options & ~(PVERBOSE | EXPERT | OPTION_F))) { 949 E_USEAGE(); 950 exit(-1); 951 } 952 if (read_repos_file(file_name) != 0) { 953 exit(-1); 954 } 955 break; 956 957 /* 958 * Undocumented commands. 959 */ 960 961 case CHECK_FILE: /* Undocumented Cmd */ 962 if (Options & ~(PVERBOSE)) { 963 USEAGE(); 964 exit(-1); 965 } 966 exit_code = adm_check_file(&argv[path_index], 967 (Options & PVERBOSE)); 968 break; 969 970 case DUMP: /* Undocumented Cmd */ 971 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 972 USEAGE(); 973 exit(-1); 974 } 975 dump(&argv[path_index]); 976 break; 977 978 case DUMP_MAP: /* Undocumented Cmd */ 979 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 980 USEAGE(); 981 exit(-1); 982 } 983 if (USE_FCHBA) { 984 exit_code = fchba_dump_map(&argv[path_index]); 985 } else { 986 dump_map(&argv[path_index]); 987 } 988 break; 989 990 case SYSDUMP: 991 if (Options & ~(PVERBOSE)) { 992 USEAGE(); 993 exit(-1); 994 } 995 if (err = sysdump(Options & PVERBOSE)) { 996 (void) print_errString(err, NULL); 997 exit(-1); 998 } 999 break; 1000 1001 case PORT: /* Undocumented command */ 1002 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 1003 USEAGE(); 1004 exit(-1); 1005 } 1006 if (USE_FCHBA) { 1007 exit_code = fchba_display_port(Options & PVERBOSE); 1008 } else { 1009 exit_code = adm_display_port(Options & PVERBOSE); 1010 } 1011 break; 1012 1013 case EXT_LOOPBACK: 1014 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 1015 USEAGE(); 1016 exit(-1); 1017 } 1018 if (adm_port_loopback(argv[path_index], EXT_LOOPBACK) < 0) { 1019 exit(-1); 1020 } 1021 break; 1022 1023 case INT_LOOPBACK: 1024 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 1025 USEAGE(); 1026 exit(-1); 1027 } 1028 if (adm_port_loopback(argv[path_index], INT_LOOPBACK) < 0) { 1029 exit(-1); 1030 } 1031 break; 1032 1033 case NO_LOOPBACK: 1034 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 1035 USEAGE(); 1036 exit(-1); 1037 } 1038 if (adm_port_loopback(argv[path_index], NO_LOOPBACK) < 0) { 1039 exit(-1); 1040 } 1041 break; 1042 1043 case VERSION: 1044 break; 1045 1046 1047 case INSERT_DEVICE: 1048 if (argv[path_index] == NULL) { 1049 if ((err = h_insertSena_fcdev()) != 0) { 1050 (void) print_errString(err, NULL); 1051 exit(-1); 1052 } 1053 } else if ((err = hotplug(INSERT_DEVICE, 1054 &argv[path_index], 1055 Options & PVERBOSE, 1056 Options & OPTION_CAPF)) != 0) { 1057 (void) print_errString(err, argv[path_index]); 1058 exit(-1); 1059 } 1060 break; 1061 case REMOVE_DEVICE: 1062 if (err = hotplug(REMOVE_DEVICE, &argv[path_index], 1063 Options & PVERBOSE, Options & OPTION_CAPF)) { 1064 (void) print_errString(err, argv[path_index]); 1065 exit(-1); 1066 } 1067 break; 1068 1069 /* for hotplug device operations */ 1070 case DEV_ONLINE: 1071 case DEV_OFFLINE: 1072 case DEV_GETSTATE: 1073 case DEV_RESET: 1074 case BUS_QUIESCE: 1075 case BUS_UNQUIESCE: 1076 case BUS_GETSTATE: 1077 case BUS_RESET: 1078 case BUS_RESETALL: 1079 if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { 1080 E_USEAGE(); 1081 exit(-1); 1082 } 1083 if (USE_FCHBA) { 1084 if (fchba_hotplug_e(cmd, &argv[path_index], 1085 Options & PVERBOSE, Options & OPTION_CAPF) != 0) { 1086 exit(-1); 1087 } 1088 } else { 1089 if (hotplug_e(cmd, &argv[path_index], 1090 Options & PVERBOSE, Options & OPTION_CAPF) != 0) { 1091 exit(-1); 1092 } 1093 } 1094 break; 1095 1096 default: 1097 (void) fprintf(stderr, 1098 MSGSTR(2213, "%s: subcommand decode failed.\n"), 1099 whoami); 1100 USEAGE(); 1101 exit(-1); 1102 } 1103 return (exit_code); 1104 } 1105