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