/* * Decodes the SCSI sense byte to a string. * * RETURNS: * character string */ static char * decode_sense_byte(uchar_t status) { switch (status & STATUS_MASK) { case STATUS_GOOD: return (MSGSTR(10000, "Good status")); case STATUS_CHECK: return (MSGSTR(128, "Check condition")); case STATUS_MET: return (MSGSTR(124, "Condition met")); case STATUS_BUSY: return (MSGSTR(37, "Busy")); case STATUS_INTERMEDIATE: return (MSGSTR(10001, "Intermediate")); case STATUS_INTERMEDIATE_MET: return (MSGSTR(10002, "Intermediate - condition met")); case STATUS_RESERVATION_CONFLICT: return (MSGSTR(10003, "Reservation_conflict")); case STATUS_TERMINATED: return (MSGSTR(126, "Command terminated")); case STATUS_QFULL: return (MSGSTR(83, "Queue full")); default: return (MSGSTR(4, "Unknown status")); } }
printprof() { register nltype *np; nltype **sortednlp; int index, timecmp(); int i; actime = 0.0; printf( "\f\n" ); flatprofheader(); /* * Sort the symbol table in by time */ sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( sortednlp == (nltype **) 0 ) { fprintf(stderr, MSGSTR(MEMSORT, "[printprof] ran out of memory for time sorting\n")); } for ( index = 0 ; index < nname ; index += 1 ) { sortednlp[ index ] = &nl[ index ]; } qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); for ( index = 0 ; index < nname ; index += 1 ) { np = sortednlp[ index ]; /* Don't print routines excluded by default, e.g. _mcount */ for(i = 0; defaultEnl[i] && np != defaultEnl[i]; i++) ; if(np == defaultEnl[i]) continue; flatprofline( np ); } actime = 0.0; cfree( sortednlp ); }
/* * Read the mnttab and resolve the special device of the fs we are * interested in, into an absolute pathname */ static int getbootdevname(char *bootfs, char *bdev) { FILE *f; char *fname; char *devname; struct mnttab m; struct stat sbuf; int mountpt = 0; int found = 0; devname = bootfs; if (stat(bootfs, &sbuf) < 0) { perror(MSGSTR(6001, "stat")); return (0); } switch (sbuf.st_mode & S_IFMT) { case S_IFBLK: break; default: mountpt = 1; break; } if (mountpt) { fname = MNTTAB; f = fopen(fname, "r"); if (f == NULL) { perror(fname); return (0); } while (getmntent(f, &m) == 0) { if (strcmp(m.mnt_mountp, bootfs)) continue; else { found = 1; break; } } (void) fclose(f); if (!found) { return (0); } devname = m.mnt_special; } if (devfs_dev_to_prom_name(devname, bdev) != 0) { perror(devname); return (0); } return (1); }
/* * error handling routine to handle emulex error conditions */ static void handle_emulex_error(int fcio_errno, char *phys_path) { if (fcio_errno == EMLX_IMAGE_BAD) { fprintf(stderr, MSGSTR(21119, "Error: Fcode download failed. " "Bad fcode image.\n")); } else if (fcio_errno == EMLX_IMAGE_INCOMPATIBLE) { fprintf(stderr, MSGSTR(21120, "Error: Fcode download failed. Fcode is not " "compatible with card.\n")); } else { (void) fprintf(stderr, MSGSTR(21036, "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n")); (void) fprintf(stderr, MSGSTR(21113, "Error: FCode download failed: %s\n"), phys_path); } }
/* * Find if the FCode file is a ISP2200 SBUS Fcode file */ static int q_findSbusfile(int fd, int *sbus_offset) { static int file_size; char *sbus_info; struct stat statinfo; if (lseek(fd, 0, SEEK_SET) == -1) { perror(MSGSTR(21022, "seek")); return (-1); } if (fstat(fd, &statinfo)) { perror(MSGSTR(21023, "fstat")); return (-1); } file_size = statinfo.st_size; if ((sbus_info = (char *)malloc(file_size)) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); return (-1); } if (read(fd, sbus_info, file_size) < 0) { perror(MSGSTR(21001, "read")); free(sbus_info); return (-1); } /* * Search for the version string in the whole file */ if ((*sbus_offset = memstrstr((char *)sbus_info, qlgc2200Sbus, file_size, strlen(qlgc2200Sbus))) != -1) { free(sbus_info); return (1); } else { free(sbus_info); return (0); } }
/* * Call getbootdevname() to get the absolute pathname of boot device * and call setprom() to set the boot-device variable. */ int setboot(unsigned int yes, unsigned int verbose, char *fname) { char bdev[MAXPATHLEN]; if (!getbootdevname(fname, bdev)) { (void) fprintf(stderr, MSGSTR(6000, "Cannot determine device name for %s\n"), fname); return (errno); } return (setprom(yes, verbose, bdev)); }
/* * setprom() - use /dev/openprom to read the "boot_device" variable and set * it to the new value. */ static int setprom(unsigned yes, unsigned verbose, char *bdev) { struct openpromio *pio; int fd; char save_bootdev[MAXVALSIZE]; if ((fd = open("/dev/openprom", O_RDWR)) < 0) { perror(MSGSTR(6002, "Could not open openprom dev")); return (errno); } pio = (struct openpromio *)malloc(sizeof (struct openpromio) + MAXVALSIZE + MAXPROPSIZE); if (pio == (struct openpromio *)NULL) { perror(MSGSTR(6003, " Error: Unable to allocate memory.")); return (errno); } pio->oprom_size = MAXVALSIZE; (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); if (ioctl(fd, OPROMGETOPT, pio) < 0) { perror(MSGSTR(6004, "openprom getopt ioctl")); return (errno); } /* * save the existing boot-device, so we can use it if setting * to new value fails. */ (void) strcpy(save_bootdev, pio->oprom_array); if (verbose) { (void) fprintf(stdout, MSGSTR(6005, "Current boot-device = %s\n"), pio->oprom_array); (void) fprintf(stdout, MSGSTR(6006, "New boot-device = %s\n"), bdev); } if (!yes) { (void) fprintf(stdout, MSGSTR(6007, "Do you want to change boot-device " "to the new setting? (y/n) ")); switch (getchar()) { case 'Y': case 'y': break; default: return (0); } } /* set the new value for boot-device */ pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 + (int)strlen(bdev); (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); (void) strcpy(pio->oprom_array + (int)strlen(BOOTDEV_PROP_NAME) + 1, bdev); if (ioctl(fd, OPROMSETOPT, pio) < 0) { perror(MSGSTR(6008, "openprom setopt ioctl")); return (errno); } /* read back the value that was set */ pio->oprom_size = MAXVALSIZE; (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); if (ioctl(fd, OPROMGETOPT, pio) < 0) { perror(MSGSTR(6009, "openprom getopt ioctl")); return (errno); } if (strcmp(bdev, pio->oprom_array)) { /* could not set the new device name, set the old one back */ perror(MSGSTR(6010, "Could not set boot-device, reverting to old value")); pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 + (int)strlen(save_bootdev); (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); (void) strcpy(pio->oprom_array + (int)strlen(BOOTDEV_PROP_NAME) + 1, save_bootdev); if (ioctl(fd, OPROMSETOPT, pio) < 0) { perror(MSGSTR(6011, "openprom setopt ioctl")); return (errno); } } (void) close(fd); return (0); }
/* * generic fcode load file routine. given a file descriptor to a fcode file * this routine will issue the FCIO_DOWNLOAD_FCODE ioctl to the given * device. Any ioctl errors will be returned in fcio_errno * * Arguments: * fcode_fd file descriptor to a fcode file * device path to the device we will be downloading the fcode onto * fcio_errno pointer to an int that will be used to return any errors * back to the caller * Retrurn Values: * 0 successful download * >0 otherwise */ static int fcode_load_file(int fcode_fd, char *device, int *fcio_errno) { fcio_t fcio; static int dev_fd, fcode_size; uchar_t *bin; struct stat stat; if (device == NULL || fcio_errno == NULL) { return (FCODE_LOAD_FAILURE); } *fcio_errno = 0; if (lseek(fcode_fd, 0, SEEK_SET) == -1) { perror(MSGSTR(21022, "seek")); return (FCODE_LOAD_FAILURE); } if (fstat(fcode_fd, &stat) == -1) { perror(MSGSTR(21023, "fstat")); return (FCODE_LOAD_FAILURE); } fcode_size = stat.st_size; if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); return (FCODE_LOAD_FAILURE); } if (read(fcode_fd, bin, fcode_size) != fcode_size) { perror(MSGSTR(21001, "read")); free(bin); return (FCODE_LOAD_FAILURE); } if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) { (void) fprintf(stderr, MSGSTR(21122, "Error: Could not open %s, failed " "with errno %d\n"), device, errno); free(bin); return (FCODE_LOAD_FAILURE); } fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE; fcio.fcio_xfer = FCIO_XFER_WRITE; fcio.fcio_ibuf = (caddr_t)bin; fcio.fcio_ilen = fcode_size; if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) { (void) close(dev_fd); *fcio_errno = fcio.fcio_errno; free(bin); return (FCODE_IOCTL_FAILURE); } free(bin); (void) close(dev_fd); return (FCODE_SUCCESS); }
/* * Issue warning strings and loop for Yes/No user interaction * err# 0 -- we're ok, warn for pending FCode load * 1 -- not in single user mode * 2 -- can't get chip_id * 3 -- card and file do not have same type (2100/2200) */ static int q_warn(int errnum) { char input[1024]; input[0] = '\0'; if (errnum == 1) { (void) fprintf(stderr, MSGSTR(21025, "\nWarning: System is not in single-user mode.\n")); (void) fprintf(stderr, MSGSTR(21026, "Loading FCode will reset the adapter and terminate I/O activity\n")); } else { if (errnum == 2) { (void) fprintf(stderr, MSGSTR(21027, " Warning: FCode is missing or existing FCode has" " unrecognized version.\n")); return (1); } else if (errnum == 3) { (void) fprintf(stderr, MSGSTR(21028, " Warning: New FCode file version does not match this" " board type. Skipping...\n")); return (1); } (void) fprintf(stderr, MSGSTR(21029, "\nWARNING!! This program will update the FCode in this" " FC100/PCI, ISP2200/PCI, ISP23xx/PCI " " and Emulex devices.\n")); (void) fprintf(stderr, MSGSTR(21030, "This may take a few (5) minutes. Please be patient.\n")); } loop1: (void) fprintf(stderr, MSGSTR(21031, "Do you wish to continue ? (y/n) ")); (void) gets(input); if ((strcmp(input, MSGSTR(21032, "y")) == 0) || (strcmp(input, MSGSTR(40, "yes")) == 0)) { return (0); } else if ((strcmp(input, MSGSTR(21033, "n")) == 0) || (strcmp(input, MSGSTR(45, "no")) == 0)) { (void) fprintf(stderr, MSGSTR(21034, "Not Downloading FCode\n")); return (1); } else { (void) fprintf(stderr, MSGSTR(21035, "Invalid input\n")); goto loop1; } }
/* * Load FCode to card. * uses ioctl: IFPIO_FCODE_DOWNLOAD */ static int q_load_file(int fcode_fd, char *device) { static int dev_fd, fcode_size; struct stat stat; ifp_download_t *download_p = NULL; fcio_t fcio; uint16_t file_id = 0; uchar_t *bin; if (lseek(fcode_fd, 0, SEEK_SET) == -1) { perror(MSGSTR(21022, "seek")); (void) close(fcode_fd); return (1); } if (fstat(fcode_fd, &stat) == -1) { perror(MSGSTR(21023, "fstat")); (void) close(fcode_fd); return (1); } fcode_size = stat.st_size; if (strstr(device, fc_trans)) { if ((download_p = (ifp_download_t *)malloc( sizeof (ifp_download_t) + fcode_size)) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); (void) close(fcode_fd); return (1); } } else { if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); (void) close(fcode_fd); return (1); } } if (strstr(device, fc_trans)) { if (read(fcode_fd, download_p->dl_fcode, fcode_size) != fcode_size) { perror(MSGSTR(21001, "read")); free(download_p); (void) close(fcode_fd); return (1); } } else { if (read(fcode_fd, bin, fcode_size) != fcode_size) { perror(MSGSTR(21001, "read")); free(bin); (void) close(fcode_fd); return (1); } } if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) { (void) fprintf(stderr, MSGSTR(21000, "Error: Could not open %s\n"), device); free(download_p); return (1); } if (strstr(device, fc_trans)) { download_p->dl_fcode_len = fcode_size; file_id = download_p->dl_fcode[0x42] & 0xff; file_id |= (download_p->dl_fcode[0x43] << 8) & 0xff00; download_p->dl_chip_id = file_id; if (ioctl(dev_fd, IFPIO_FCODE_DOWNLOAD, download_p) < 0) { (void) fprintf(stderr, MSGSTR(21024, "Error: Driver interface IFPIO_FCODE_DOWNLOAD failed\n")); free(download_p); (void) close(dev_fd); return (1); } free(download_p); } else if (strstr(device, fp_trans)) { fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE; /* Information read operation */ fcio.fcio_xfer = FCIO_XFER_WRITE; fcio.fcio_ibuf = (caddr_t)bin; fcio.fcio_ilen = fcode_size; if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) { (void) fprintf(stderr, MSGSTR(21036, "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n")); free(download_p); (void) close(dev_fd); return (1); } free(bin); } (void) close(dev_fd); return (0); }
/* * Get the boot device. Cannot load FCode to current boot device. * Boot devices under volume management will prompt a warning. */ static int q_getbootdev(uchar_t *bootpath) { struct mnttab mp; struct mnttab mpref; FILE *fp = NULL; static char buf[BUFSIZ]; char *p = NULL, *p1 = NULL; /* p = full device, p1 = chunk to rm */ char *slot = ":devctl"; char *root = "/"; if ((fp = fopen(MNTTAB, "r")) == NULL) { (void) fprintf(stderr, MSGSTR(21000, "Error: Could not open %s\n"), MNTTAB); return (1); } mntnull(&mpref); mpref.mnt_mountp = (char *)root; if (getmntany(fp, &mp, &mpref) != 0 || mpref.mnt_mountp == NULL) { (void) fprintf(stderr, MSGSTR(21019, "Error: Cannot get boot device, check %s.\n"), MNTTAB); (void) fclose(fp); return (1); } (void) fclose(fp); /* * If we can't get a link, we may be dealing with a volume mgr * so give a warning. If a colon is present, we likely have a * non-local disk or cd-rom, so no warning is necessary. * e.g. /devices/pci@1f,4000/scsi@3/sd@6,0:b (cdrom, no link) or * storage-e4:/blah/blah remote boot server */ if (readlink(mp.mnt_special, buf, BUFSIZ) < 0) { if (strstr(mp.mnt_special, ":") == NULL) { (void) fprintf(stderr, MSGSTR(21020, "\nWarning: Cannot read boot device link, check %s.\n"), MNTTAB); (void) fprintf(stderr, MSGSTR(21021, "Do not upgrade FCode on adapters controlling the boot device.\n")); } return (1); } /* * Copy boot device path to bootpath. First remove leading * path junk (../../..) then if it's an ifp device, chop off * the disk and add the devctl to the end of the path. */ if (p = strstr(buf, "/devices")) { if (strstr(buf, fc_trans) != NULL) { p1 = strrchr(p, '/'); *p1 = '\0'; } } (void) strcpy((char *)bootpath, (char *)p); if (p1) { (void) strcat((char *)bootpath, slot); } return (0); }
/* * Build a list of all the devctl entries for all the 2100/2200 based adapters */ static int q_getdevctlpath(char *devpath, int *devcnt) { struct stat statbuf; struct dirent *dirp = NULL; DIR *dp = NULL; char *ptr = NULL; int err = 0; int testopen; if (lstat(devpath, &statbuf) < 0) { (void) fprintf(stderr, MSGSTR(21016, "Error: %s lstat() error\n"), devpath); return (1); } if ((strstr(devpath, fc_trans) || (strstr(devpath, fp_trans_id) && strstr(devpath, fp_trans))) && strstr(devpath, "devctl")) { /* Verify the path is valid */ if ((testopen = open(devpath, O_RDONLY)) >= 0) { (void) close(testopen); (void) strcpy(pcibus_list[*devcnt], devpath); *devcnt += 1; return (0); } } if (S_ISDIR(statbuf.st_mode) == 0) { /* * not a directory so * we don't care about it - return */ return (0); } /* * It's a directory. Call ourself to * traverse the path(s) */ ptr = devpath + strlen(devpath); *ptr++ = '/'; *ptr = 0; /* Forget the /devices/pseudo/ directory */ if (strcmp(devpath, "/devices/pseudo/") == 0) { return (0); } if ((dp = opendir(devpath)) == NULL) { (void) fprintf(stderr, MSGSTR(21017, "Error: %s Can't read directory\n"), devpath); return (1); } while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } (void) strcpy(ptr, dirp->d_name); /* append name */ err = q_getdevctlpath(devpath, devcnt); } if (closedir(dp) < 0) { (void) fprintf(stderr, MSGSTR(21018, "Error: Can't close directory %s\n"), devpath); return (1); } return (err); }
/* main functions. */ int main(int argc, char **argv) { register int c; /* getopt varbs */ extern char *optarg; char *optstring = NULL; int path_index, err = 0; int cmd = 0; /* Cmd verb from cmd line */ int exit_code = 0; /* exit code for program */ int temp_fd; /* For -f option */ char *file_name = NULL; int option_t_input; char *path_phys = NULL; int USE_FCHBA = 0; whoami = argv[0]; /* * Enable locale announcement */ i18n_catopen(); while ((c = getopt(argc, argv, "ve")) != EOF) { switch (c) { case 'v': Options |= PVERBOSE; break; case 'e': Options |= EXPERT; break; default: /* Note: getopt prints an error if invalid option */ USEAGE() exit(-1); } /* End of switch(c) */ } setbuf(stdout, NULL); /* set stdout unbuffered. */ /* * Build any i18n global variables */ dtype[0] = MSGSTR(2192, "Disk device"); dtype[1] = MSGSTR(2193, "Tape device"); dtype[2] = MSGSTR(2194, "Printer device"); dtype[3] = MSGSTR(2195, "Processor device"); dtype[4] = MSGSTR(2196, "WORM device"); dtype[5] = MSGSTR(2197, "CD-ROM device"); dtype[6] = MSGSTR(2198, "Scanner device"); dtype[7] = MSGSTR(2199, "Optical memory device"); dtype[8] = MSGSTR(2200, "Medium changer device"); dtype[9] = MSGSTR(2201, "Communications device"); dtype[10] = MSGSTR(107, "Graphic arts device"); dtype[11] = MSGSTR(107, "Graphic arts device"); dtype[12] = MSGSTR(2202, "Array controller device"); dtype[13] = MSGSTR(2203, "SES device"); dtype[14] = MSGSTR(71, "Reserved"); dtype[15] = MSGSTR(71, "Reserved"); /* * Get subcommand. */ if ((getaction(argv[optind], Keywords, &cmd)) == EOK) { optind++; if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && (cmd != AU) && (cmd != PORT) && (cmd != CREATE_FAB) && (optind >= argc)) { (void) fprintf(stderr, MSGSTR(2204, "Error: enclosure or pathname not specified.\n")); USEAGE(); exit(-1); } } else { (void) fprintf(stderr, MSGSTR(2205, "%s: subcommand not specified.\n"), whoami); USEAGE(); exit(-1); } /* Extract & Save subcommand options */ if ((cmd == ENABLE) || (cmd == BYPASS)) { optstring = "Ffrab"; } else if (cmd == FCODE_UPDATE) { optstring = "pd:"; } else if (cmd == REMOVE_DEVICE) { optstring = "F"; } else if (cmd == CREATE_FAB) { optstring = "f:"; } else { optstring = "Fryszabepcdlvt:f:w:"; } while ((c = getopt(argc, argv, optstring)) != EOF) { switch (c) { case 'a': Options |= OPTION_A; break; case 'b': Options |= OPTION_B; break; case 'c': Options |= OPTION_C; break; case 'd': Options |= OPTION_D; if (cmd == FCODE_UPDATE) { file_name = optarg; } break; case 'e': Options |= OPTION_E; break; case 'f': Options |= OPTION_F; if (!((cmd == ENABLE) || (cmd == BYPASS))) { file_name = optarg; } break; case 'F': Options |= OPTION_CAPF; break; case 'l': Options |= OPTION_L; break; case 'p': Options |= OPTION_P; break; case 'r': Options |= OPTION_R; break; case 's': Options |= SAVE; break; case 't': Options |= OPTION_T; option_t_input = atoi(optarg); break; case 'v': Options |= OPTION_V; break; case 'z': Options |= OPTION_Z; break; case 'y': Options |= OPTION_Y; break; default: /* Note: getopt prints an error if invalid option */ USEAGE() exit(-1); } /* End of switch(c) */ } if ((cmd != PROBE) && (cmd != FCAL_UPDATE) && (cmd != QLGC_UPDATE) && (cmd != FCODE_UPDATE) && (cmd != INSERT_DEVICE) && (cmd != SYSDUMP) && (cmd != AU) && (cmd != PORT) && (cmd != CREATE_FAB) && (optind >= argc)) { (void) fprintf(stderr, MSGSTR(2206, "Error: enclosure or pathname not specified.\n")); USEAGE(); exit(-1); } path_index = optind; /* * Check if the file supplied with the -f option is valid * Some sub commands (bypass for example) use the -f option * for other reasons. In such cases, "file_name" should be * NULL. */ if ((file_name != NULL) && (Options & OPTION_F)) { if ((temp_fd = open(file_name, O_RDONLY)) == -1) { perror(file_name); exit(-1); } else { close(temp_fd); } } /* Determine which mode to operate in (FC-HBA or original) */ USE_FCHBA = use_fchba(); switch (cmd) { case DISPLAY: if (Options & ~(PVERBOSE | OPTION_A | OPTION_Z | OPTION_R | OPTION_P | OPTION_V | OPTION_L | OPTION_E | OPTION_T)) { USEAGE(); exit(-1); } /* Display object(s) */ if (USE_FCHBA) { exit_code = fchba_display_config(&argv[path_index], option_t_input, argc - path_index); } else { exit_code = adm_display_config(&argv[path_index]); } break; case DOWNLOAD: if (Options & ~(PVERBOSE | OPTION_F | SAVE)) { USEAGE(); exit(-1); } adm_download(&argv[path_index], file_name); break; case ENCLOSURE_NAMES: if (Options & ~PVERBOSE) { USEAGE(); exit(-1); } up_encl_name(&argv[path_index], argc); break; case FAILOVER: if (Options & ~PVERBOSE) { USEAGE(); exit(-1); } adm_failover(&argv[path_index]); break; case INQUIRY: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } if (USE_FCHBA) { exit_code = fchba_inquiry(&argv[path_index]); } else { exit_code = adm_inquiry(&argv[path_index]); } break; case PROBE: if (Options & ~(PVERBOSE | OPTION_P)) { USEAGE(); exit(-1); } /* * A special check just in case someone entered * any characters after the -p or the probe. * * (I know, a nit.) */ if (((Options & PVERBOSE) && (Options & OPTION_P) && (argc != 4)) || (!(Options & PVERBOSE) && (Options & OPTION_P) && (argc != 3)) || ((Options & PVERBOSE) && (!(Options & OPTION_P)) && (argc != 3)) || (!(Options & PVERBOSE) && (!(Options & OPTION_P)) && (argc != 2))) { (void) fprintf(stderr, MSGSTR(114, "Error: Incorrect number of arguments.\n")); (void) fprintf(stderr, MSGSTR(2208, "Usage: %s [-v] subcommand [option]\n"), whoami); exit(-1); } if (USE_FCHBA) { exit_code = fchba_non_encl_probe(); } else { pho_probe(); non_encl_probe(); } break; case FCODE_UPDATE: /* Update Fcode in all cards */ if ((Options & ~(PVERBOSE)) & ~(OPTION_P | OPTION_D) || argv[path_index]) { USEAGE(); exit(-1); } if (!((Options & (OPTION_P | OPTION_D)) && !((Options & OPTION_P) && (Options & OPTION_D)))) { USEAGE(); exit(-1); } if (adm_fcode(Options & PVERBOSE, file_name) != 0) { exit(-1); } break; case QLGC_UPDATE: /* Update Fcode in PCI HBA card(s) */ if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || argv[path_index]) { USEAGE(); exit(-1); } if (q_qlgc_update(Options & PVERBOSE, file_name) != 0) { exit(-1); } break; case FCAL_UPDATE: /* Update Fcode in Sbus soc+ card */ if ((Options & ~(PVERBOSE)) & ~(OPTION_F) || argv[path_index]) { USEAGE(); exit(-1); } exit_code = fcal_update(Options & PVERBOSE, file_name); break; case SET_BOOT_DEV: /* Set boot-device variable in nvram */ exit_code = setboot(Options & OPTION_Y, Options & PVERBOSE, argv[path_index]); break; case LED: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } adm_led(&argv[path_index], L_LED_STATUS); break; case LED_ON: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } adm_led(&argv[path_index], L_LED_ON); break; case LED_OFF: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } adm_led(&argv[path_index], L_LED_OFF); break; case LED_BLINK: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } adm_led(&argv[path_index], L_LED_RQST_IDENTIFY); break; case PASSWORD: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } up_password(&argv[path_index]); break; case RESERVE: if (Options & (~PVERBOSE)) { USEAGE(); exit(-1); } VERBPRINT(MSGSTR(2209, " Reserving: \n %s\n"), argv[path_index]); if (USE_FCHBA) { struct stat sbuf; /* Just stat the argument and make sure it exists */ if (stat(argv[path_index], &sbuf) < 0) { (void) fprintf(stderr, "%s: ", whoami); (void) fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), argv[path_index]); (void) fprintf(stderr, "\n"); exit(-1); } path_phys = argv[path_index]; if (err = scsi_reserve(path_phys)) { (void) print_errString(err, argv[path_index]); exit(-1); } } else { exit_code = adm_reserve(argv[path_index]); } break; case RELEASE: if (Options & (~PVERBOSE)) { USEAGE(); exit(-1); } VERBPRINT(MSGSTR(2210, " Canceling Reservation for:\n %s\n"), argv[path_index]); if (USE_FCHBA) { struct stat sbuf; /* Just stat the argument and make sure it exists */ if (stat(argv[path_index], &sbuf) < 0) { (void) fprintf(stderr, "%s: ", whoami); (void) fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), argv[path_index]); (void) fprintf(stderr, "\n"); exit(-1); } path_phys = argv[path_index]; if (err = scsi_release(path_phys)) { (void) print_errString(err, argv[path_index]); exit(-1); } } else { exit_code = adm_release(argv[path_index]); } break; case START: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } exit_code = adm_start(&argv[path_index]); break; case STOP: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } exit_code = adm_stop(&argv[path_index]); break; case POWER_OFF: if (Options & ~(PVERBOSE | OPTION_CAPF)) { USEAGE(); exit(-1); } exit_code = adm_power_off(&argv[path_index], 1); break; case POWER_ON: if (Options & (~PVERBOSE)) { USEAGE(); exit(-1); } exit_code = adm_power_off(&argv[path_index], 0); break; /* * EXPERT commands. */ case FORCELIP: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { E_USEAGE(); exit(-1); } exit_code = adm_forcelip(&argv[path_index]); break; case BYPASS: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || ((Options & OPTION_A) && (Options & OPTION_B))) { E_USEAGE(); exit(-1); } adm_bypass_enable(&argv[path_index], 1); break; case ENABLE: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT | OPTION_CAPF | OPTION_A | OPTION_B | OPTION_F | OPTION_R)) || !(Options & (OPTION_A | OPTION_B)) || ((Options & OPTION_A) && (Options & OPTION_B))) { E_USEAGE(); exit(-1); } adm_bypass_enable(&argv[path_index], 0); break; case LUX_P_OFFLINE: /* Offline a port */ if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { E_USEAGE(); exit(-1); } exit_code = adm_port_offline_online(&argv[path_index], LUX_P_OFFLINE); break; case LUX_P_ONLINE: /* Online a port */ if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { E_USEAGE(); exit(-1); } exit_code = adm_port_offline_online(&argv[path_index], LUX_P_ONLINE); break; case RDLS: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { E_USEAGE(); exit(-1); } if (USE_FCHBA) { exit_code = fchba_display_link_status(&argv[path_index]); } else { display_link_status(&argv[path_index]); } break; case CREATE_FAB: if (!(Options & (EXPERT | OPTION_F)) || (Options & ~(PVERBOSE | EXPERT | OPTION_F))) { E_USEAGE(); exit(-1); } if (read_repos_file(file_name) != 0) { exit(-1); } break; /* * Undocumented commands. */ case CHECK_FILE: /* Undocumented Cmd */ if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } exit_code = adm_check_file(&argv[path_index], (Options & PVERBOSE)); break; case DUMP: /* Undocumented Cmd */ if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } dump(&argv[path_index]); break; case DUMP_MAP: /* Undocumented Cmd */ if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } if (USE_FCHBA) { exit_code = fchba_dump_map(&argv[path_index]); } else { dump_map(&argv[path_index]); } break; case SYSDUMP: if (Options & ~(PVERBOSE)) { USEAGE(); exit(-1); } if (err = sysdump(Options & PVERBOSE)) { (void) print_errString(err, NULL); exit(-1); } break; case PORT: /* Undocumented command */ if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } if (USE_FCHBA) { exit_code = fchba_display_port(Options & PVERBOSE); } else { exit_code = adm_display_port(Options & PVERBOSE); } break; case EXT_LOOPBACK: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } if (adm_port_loopback(argv[path_index], EXT_LOOPBACK) < 0) { exit(-1); } break; case INT_LOOPBACK: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } if (adm_port_loopback(argv[path_index], INT_LOOPBACK) < 0) { exit(-1); } break; case NO_LOOPBACK: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { USEAGE(); exit(-1); } if (adm_port_loopback(argv[path_index], NO_LOOPBACK) < 0) { exit(-1); } break; case VERSION: break; case INSERT_DEVICE: if (argv[path_index] == NULL) { if ((err = h_insertSena_fcdev()) != 0) { (void) print_errString(err, NULL); exit(-1); } } else if ((err = hotplug(INSERT_DEVICE, &argv[path_index], Options & PVERBOSE, Options & OPTION_CAPF)) != 0) { (void) print_errString(err, argv[path_index]); exit(-1); } break; case REMOVE_DEVICE: if (err = hotplug(REMOVE_DEVICE, &argv[path_index], Options & PVERBOSE, Options & OPTION_CAPF)) { (void) print_errString(err, argv[path_index]); exit(-1); } break; /* for hotplug device operations */ case DEV_ONLINE: case DEV_OFFLINE: case DEV_GETSTATE: case DEV_RESET: case BUS_QUIESCE: case BUS_UNQUIESCE: case BUS_GETSTATE: case BUS_RESET: case BUS_RESETALL: if (!(Options & EXPERT) || (Options & ~(PVERBOSE | EXPERT))) { E_USEAGE(); exit(-1); } if (USE_FCHBA) { if (fchba_hotplug_e(cmd, &argv[path_index], Options & PVERBOSE, Options & OPTION_CAPF) != 0) { exit(-1); } } else { if (hotplug_e(cmd, &argv[path_index], Options & PVERBOSE, Options & OPTION_CAPF) != 0) { exit(-1); } } break; default: (void) fprintf(stderr, MSGSTR(2213, "%s: subcommand decode failed.\n"), whoami); USEAGE(); exit(-1); } return (exit_code); }
/* * Searches for and updates the cards. This is the "main" function * and will give the output to the user by calling the subfunctions. * args: FCode file; if NULL only the current FCode version is printed */ int q_qlgc_update(unsigned int verbose, char *file) /*ARGSUSED*/ { int fd, fcode_fd = -1, errnum = 0, devcnt = 0, retval = 0, isSbus = 0; int sbus_off; uint_t i, fflag = 0; uint16_t chip_id = 0, file_id = 0; uchar_t fcode_buf[FCODE_HDR]; static uchar_t bootpath[PATH_MAX]; static uchar_t version[MAXNAMELEN], version_file[MAXNAMELEN]; char devpath[PATH_MAX], tmppath[PATH_MAX]; void (*sigint)(); /* to store default SIGTERM setting */ static struct utmpx *utmpp = NULL; /* pointer for getutxent() */ char *ptr1, *ptr2; char phys_path[PATH_MAX]; /* * The variables port1 and port2 are used to store the bus id * e.g. the bus id for this path: * /devices/sbus@12,0/SUNW,qlc@2,30000/fp@0,0:devctl * is "sbus@12". They are initialized to a random value and are * set such that they are not equal initially. */ static char port1[MAXNAMELEN] = {NULL}; static char port2[MAXNAMELEN] = {NULL}; if (file) { fflag++; /* check for a valid file */ if ((fcode_fd = open(file, O_RDONLY)) < 0) { (void) fprintf(stderr, MSGSTR(21000, "Error: Could not open %s\n"), file); return (1); } if (read(fcode_fd, fcode_buf, FCODE_HDR) != FCODE_HDR) { perror(MSGSTR(21001, "read")); (void) close(fcode_fd); return (1); } /* * Check if it's SBUS FCode by calling q_findSbusfile * if it is then isSbus will be 1, if not it will be 0 * in case of an error, it will be -1 */ isSbus = q_findSbusfile(fcode_fd, &sbus_off); if (isSbus == -1) { (void) close(fcode_fd); return (1); } /* * FCode header check - make sure it's PCI FCode * Structure of FCode header (byte# refers to byte numbering * in FCode spec, not the byte# of our fcode_buf buffer): * header byte 00 0x55 prom signature byte one * byte 01 0xaa prom signature byte two * data byte 00-03 P C I R * OR * header byte 32 0x55 * byte 33 0xaa * data byte 60-63 P C I R * The second format with an offset of 32 is used for ifp prom */ if (!(((fcode_buf[0x00] == 0x55) && (fcode_buf[0x01] == 0xaa) && (fcode_buf[0x1c] == 'P') && (fcode_buf[0x1d] == 'C') && (fcode_buf[0x1e] == 'I') && (fcode_buf[0x1f] == 'R')) || ((fcode_buf[0x20] == 0x55) && (fcode_buf[0x21] == 0xaa) && (fcode_buf[0x3c] == 'P') && (fcode_buf[0x3d] == 'C') && (fcode_buf[0x3e] == 'I') && (fcode_buf[0x3f] == 'R')) || (isSbus))) { (void) fprintf(stderr, MSGSTR(21002, "Error: %s is not a valid FC100/P, " "ISP2200, ISP23xx FCode file.\n"), file); (void) close(fcode_fd); return (1); } /* check for single user mode */ while ((utmpp = getutxent()) != NULL) { if (strstr(utmpp->ut_line, "run-level") && (strcmp(utmpp->ut_line, "run-level S") && strcmp(utmpp->ut_line, "run-level 1"))) { if (q_warn(1)) { (void) endutxent(); (void) close(fcode_fd); return (1); } break; } } (void) endutxent(); /* get bootpath */ if (!q_getbootdev((uchar_t *)&bootpath[0]) && getenv("_LUX_D_DEBUG") != NULL) { (void) fprintf(stdout, " Bootpath: %s\n", bootpath); } } /* * Get count of, and names of PCI slots with ifp device control * (devctl) nodes. Search /devices. */ (void) strcpy(devpath, "/devices"); if (q_getdevctlpath(devpath, (int *)&devcnt) == 0) { (void) fprintf(stdout, MSGSTR(21003, "\n Found Path to %d FC100/P, ISP2200, ISP23xx Devices\n"), devcnt); } else { (void) fprintf(stderr, MSGSTR(21004, "Error: Could not get /devices path to FC100/P," "ISP2200, ISP23xx Cards.\n")); retval++; } for (i = 0; i < devcnt; i++) { (void) strncpy((char *)phys_path, &pcibus_list[i][0], strlen(&pcibus_list[i][0])); if (fflag && (strstr((char *)bootpath, strtok((char *)phys_path, ":")) != NULL)) { (void) fprintf(stderr, MSGSTR(21005, "Ignoring %s (bootpath)\n"), &pcibus_list[i][0]); continue; } (void) fprintf(stdout, MSGSTR(21006, "\n Opening Device: %s\n"), &pcibus_list[i][0]); /* Check if the device is valid */ if ((fd = open(&pcibus_list[i][0], O_RDWR)) < 0) { (void) fprintf(stderr, MSGSTR(21000, "Error: Could not open %s\n"), &pcibus_list[i][0]); retval++; continue; } (void) close(fd); /* * Check FCode version present on the adapter (at last boot) */ if (q_findversion(verbose, i, (uchar_t *)&version[0], &chip_id) == 0) { if (strlen((char *)version) == 0) { (void) fprintf(stdout, MSGSTR(21007, " Detected FCode Version:\tNo version available for this FCode\n")); } else { (void) fprintf(stdout, MSGSTR(21008, " Detected FCode Version:\t%s\n"), version); } } else { chip_id = 0x0; } if (fflag) { /* * For ISP2200, Sbus HBA, do just 1 download * for both the ports (dual port HBA) * Here it is assumed that readdir() always * returns the paths in pcibus_list[] in the * sorted order. */ (void) strcpy(tmppath, pcibus_list[i]); if (ptr1 = strstr(tmppath, IVORY_BUS)) { if (ptr2 = strstr(ptr1, IVORY_DRVR)) { ptr2 = strchr(ptr2, ','); if (ptr2 = strchr(++ptr2, ',')) { *ptr2 = '\0'; } } (void) strcpy(port2, ptr1); if (strcmp(port1, port2) == 0) { (void) fprintf(stdout, MSGSTR(21037, "/n New FCode has already been downloaded " "to this ISP2200 SBus HBA Card.\n" "It is sufficient to download to one " "port of the ISP2200 SBus HBA Card. " "Moving on...\n")); continue; } } /* * Check version of the supplied FCode file (once) */ if ((file_id != 0 && version_file != NULL) || (q_findfileversion((char *) &fcode_buf[0], (uchar_t *)&version_file[0], &file_id, isSbus, &sbus_off) == 0)) { (void) fprintf(stdout, MSGSTR(21009, " New FCode Version:\t\t%s\n"), version_file); } else { (void) close(fcode_fd); return (1); } /* * Load the New FCode * Give warning if file doesn't appear to be correct * */ if (chip_id == 0) { errnum = 2; /* can't get chip_id */ retval++; } else if (chip_id - file_id != 0) { errnum = 3; /* file/card mismatch */ retval++; } else { errnum = 0; /* everything is ok */ } if (!q_warn(errnum)) { /* Disable user-interrupt Control-C */ sigint = (void (*)(int)) signal(SIGINT, SIG_IGN); /* Load FCode */ (void) fprintf(stdout, MSGSTR(21010, " Loading FCode: %s\n"), file); if (q_load_file(fcode_fd, &pcibus_list[i][0]) == 0) { (void) fprintf(stdout, MSGSTR(21011, " Successful FCode download: %s\n"), &pcibus_list[i][0]); (void) strcpy(port1, port2); } else { (void) fprintf(stderr, MSGSTR(21012, "Error: FCode download failed: %s\n"), &pcibus_list[i][0]); retval++; } /* Restore SIGINT (user interrupt) setting */ (void) signal(SIGINT, sigint); } } } (void) fprintf(stdout, " "); (void) fprintf(stdout, MSGSTR(125, "Complete\n")); if (fcode_fd != -1) (void) close(fcode_fd); return (retval); }
/* * Retrieves information from the Emulex fcode * * Given a pattern, this routine will look for this pattern in the fcode * file and if found will return the pattern value * * possible patterns are manufacturer and fcode-version */ int emulex_fcode_reader(int fcode_fd, char *pattern, char *pattern_value, uint32_t pattern_value_size) { int32_t i = 0; uint32_t n = 0; uint32_t b = 0; char byte1; char byte2; char byte3; char byte4; char buffer1[EMULEX_READ_BUFFER_SIZE]; char buffer2[EMULEX_READ_BUFFER_SIZE]; uint32_t plen, image_size; struct stat stat; uchar_t *image; /* Check the arguments */ if (!fcode_fd || !pattern_value || pattern_value_size < 8) { return (1); } if (fstat(fcode_fd, &stat) == -1) { perror(MSGSTR(21023, "fstat")); return (1); } image_size = stat.st_size; if (image_size < 2) { return (1); } if ((image = (uchar_t *)calloc(image_size, 1)) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); return (1); } /* Read the fcode image file */ lseek(fcode_fd, 0, SEEK_SET); read(fcode_fd, image, image_size); /* Initialize */ bzero(buffer1, sizeof (buffer1)); bzero(buffer2, sizeof (buffer2)); /* Default pattern_value string */ strcpy((char *)pattern_value, "<unknown>"); plen = strlen(pattern); n = 0; b = 0; i = 0; /* Search entire image for pattern string */ while (i <= (image_size - 2)) { /* Read next two bytes */ byte1 = image[i++]; byte2 = image[i++]; /* Check second byte first due to endianness */ /* Save byte in circular buffer */ buffer1[b++] = byte2; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte2) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched then * exit loop */ if (n == plen) { goto found; } } /* Check first byte second due to endianness */ /* Save byte in circular buffer */ buffer1[b++] = byte1; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte1) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched * then exit loop */ if (n == plen) { goto found; } } } /* Not found. Try again with different endianess */ /* Initialize */ bzero(buffer1, sizeof (buffer1)); bzero(buffer2, sizeof (buffer2)); n = 0; b = 0; i = 0; /* Search entire 32bit endian image for pattern string */ while (i <= (image_size - 4)) { /* Read next four bytes */ byte1 = image[i++]; byte2 = image[i++]; byte3 = image[i++]; byte4 = image[i++]; /* Save byte in circular buffer */ buffer1[b++] = byte4; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte4) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched then exit loop */ if (n == plen) { goto found; } } /* Save byte in circular buffer */ buffer1[b++] = byte3; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte3) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched then exit loop */ if (n == plen) { goto found; } } /* Save byte in circular buffer */ buffer1[b++] = byte2; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte2) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched then exit loop */ if (n == plen) { goto found; } } /* Save byte in circular buffer */ buffer1[b++] = byte1; if (b == sizeof (buffer1)) { b = 0; } /* Check byte for pattern match */ if (pattern[n++] != byte1) { /* If no match, then reset pattern */ n = 0; } else { /* * If complete pattern has been matched then exit loop */ if (n == plen) { goto found; } } } free(image); return (1); found: free(image); /* Align buffer and eliminate non-printable characters */ for (i = 0; i < (sizeof (buffer1)-plen); i++) { byte1 = buffer1[b++]; if (b == sizeof (buffer1)) { b = 0; } /* Zero any non-printable characters */ if (byte1 >= 33 && byte1 <= 126) { buffer2[i] = byte1; } else { buffer2[i] = 0; } } /* * Scan backwards for first non-zero string. This will be the * version string */ for (i = sizeof (buffer1)-plen-1; i >= 0; i--) { if (buffer2[i] != 0) { for (; i >= 0; i--) { if (buffer2[i] == 0) { i++; strncpy((char *)pattern_value, &buffer2[i], pattern_value_size); break; } } break; } } return (0); }
int emulex_update(char *file) { int fd, retval = 0; int devcnt = 0; uint_t state = 0, fflag = 0; static uchar_t bootpath[PATH_MAX]; int fcode_fd = -1; static struct utmpx *utmpp = NULL; di_node_t root; di_node_t node, sib_node, count_node; di_minor_t minor_node; char phys_path[PATH_MAX], *path; int errnum = 0, fcio_errno = 0; static uchar_t prom_ver_data[MAXNAMELEN]; static char ver_file[EMULEX_FCODE_VERSION_LENGTH]; void (*sigint)(); int prop_entries = -1; int *port_data = NULL; if (file) { /* set the fcode download flag */ fflag++; /* check for a valid file */ if ((fcode_fd = open(file, O_RDONLY)) < 0) { (void) fprintf(stderr, MSGSTR(21118, "Error: Could not open %s, failed " "with errno %d\n"), file, errno); return (1); } /* check for single user mode */ while ((utmpp = getutxent()) != NULL) { if (strstr(utmpp->ut_line, "run-level") && (strcmp(utmpp->ut_line, "run-level S") && strcmp(utmpp->ut_line, "run-level 1"))) { if (q_warn(1)) { (void) endutxent(); (void) close(fcode_fd); return (1); } break; } } (void) endutxent(); /* get bootpath */ if (!q_getbootdev((uchar_t *)&bootpath[0]) && getenv("_LUX_D_DEBUG") != NULL) { (void) fprintf(stdout, " Bootpath: %s\n", bootpath); } } /* * Download the Fcode to all the emulex cards found */ /* Create a snapshot of the kernel device tree */ if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { (void) fprintf(stderr, MSGSTR(21114, "Error: Could not get /devices path to " "Emulex Devices.\n")); retval++; } /* point to first node which matches emulex driver */ node = di_drv_first_node("emlxs", root); if (node == DI_NODE_NIL) { /* * Could not find any emulex cards */ (void) di_fini(root); (void) fprintf(stderr, MSGSTR(21115, "\n Found Path to %d Emulex Devices.\n"), devcnt); retval++; } else { count_node = node; while (count_node != DI_NODE_NIL) { state = di_state(count_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { sib_node = di_child_node(count_node); while (sib_node != DI_NODE_NIL) { state = di_state(sib_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { /* Found an attached node */ prop_entries = di_prop_lookup_ints( DDI_DEV_T_ANY, sib_node, "port", &port_data); if (prop_entries != -1) { devcnt++; break; } } sib_node = di_sibling_node(sib_node); } } count_node = di_drv_next_node(count_node); } (void) fprintf(stdout, MSGSTR(21116, "\n Found Path to %d Emulex Devices.\n"), devcnt); } /* * Traverse device tree to find all emulex cards */ while (node != DI_NODE_NIL) { state = di_state(node); if ((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) { node = di_drv_next_node(node); continue; } sib_node = di_child_node(node); while (sib_node != DI_NODE_NIL) { state = di_state(sib_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { /* Found an attached node */ prop_entries = di_prop_lookup_ints( DDI_DEV_T_ANY, sib_node, "port", &port_data); if (prop_entries != -1) { /* Found a node with "port" property */ minor_node = di_minor_next(sib_node, DI_MINOR_NIL); break; } } sib_node = di_sibling_node(sib_node); } if (sib_node == DI_NODE_NIL) { goto try_next; } path = di_devfs_path(sib_node); (void) strcpy(phys_path, "/devices"); (void) strncat(phys_path, path, strlen(path)); di_devfs_path_free(path); if (fflag && (strstr((char *)bootpath, (char *)phys_path) != NULL)) { (void) fprintf(stderr, MSGSTR(21117, "Ignoring %s (bootpath)\n"), phys_path); node = di_drv_next_node(node); continue; } if (minor_node) { (void) strncat(phys_path, ":", 1); (void) strncat(phys_path, di_minor_name(minor_node), strlen(di_minor_name(minor_node))); } (void) fprintf(stdout, MSGSTR(21107, "\n Opening Device: %s\n"), phys_path); /* Check if the device is valid */ if ((fd = open(phys_path, O_RDWR)) < 0) { (void) fprintf(stderr, MSGSTR(21121, "Error: Could not open %s, failed " "with errno %d\n"), phys_path, errno); retval++; node = di_drv_next_node(node); continue; } (void) close(fd); /* * Check FCode version present on the adapter * (at last boot) */ memset(prom_ver_data, 0, sizeof (prom_ver_data)); if (emulex_fcodeversion(node, (uchar_t *)&prom_ver_data[0]) == 0) { errnum = 0; if (strlen((char *)prom_ver_data) == 0) { (void) fprintf(stdout, MSGSTR(21108, " Detected FCode Version:\tNo version available for this FCode\n")); } else { (void) fprintf(stdout, MSGSTR(21109, " Detected FCode Version:\t%s\n"), prom_ver_data); } } else { errnum = 2; /* can't get prom properties */ retval++; } if (fflag) { memset(ver_file, 0, sizeof (ver_file)); if (emulex_fcode_reader(fcode_fd, "fcode-version", ver_file, sizeof (ver_file)) == 0) { (void) fprintf(stdout, MSGSTR(21110, " New FCode Version:\t\t%s\n"), ver_file); } else { di_fini(root); (void) close(fcode_fd); return (1); } /* * Load the New FCode * Give warning if file doesn't appear to be correct */ if (!q_warn(errnum)) { /* Disable user-interrupt Control-C */ sigint = (void (*)(int)) signal(SIGINT, SIG_IGN); /* Load FCode */ (void) fprintf(stdout, MSGSTR(21111, " Loading FCode: %s\n"), file); if (fcode_load_file(fcode_fd, phys_path, &fcio_errno) == FCODE_SUCCESS) { (void) fprintf(stdout, MSGSTR(21112, " Successful FCode download: %s\n"), phys_path); } else { handle_emulex_error(fcio_errno, phys_path); retval++; } /* Restore SIGINT (user interrupt) setting */ (void) signal(SIGINT, sigint); } } try_next: node = di_drv_next_node(node); } di_fini(root); (void) fprintf(stdout, " "); (void) fprintf(stdout, MSGSTR(125, "Complete\n")); if (fcode_fd != -1) (void) close(fcode_fd); return (retval); }
/* * This function finds a predefined error string to a given * error number (errornum), allocates memory for the string * and returns the corresponding error message to the caller. * * RETURNS * error string if O.K. * NULL otherwise */ char *get_errString(int errornum) { char err_msg[MAXLEN], *errStrg; err_msg[0] = '\0'; /* Just in case */ if (errornum < L_BASE) { /* Some sort of random system error most likely */ errStrg = strerror(errno); if (errStrg != NULL) { (void) strcpy(err_msg, errStrg); } else { /* Something's _really_ messed up */ (void) sprintf(err_msg, MSGSTR(10081, " Error: could not decode the" " error message.\n" " The given error message is not" " defined in the library.\n" " Message number: %d.\n"), errornum); } /* Make sure ALL CASES set err_msg to something */ } else switch (errornum) { case L_SCSI_ERROR: (void) sprintf(err_msg, MSGSTR(10096, " Error: SCSI failure.")); break; case L_PR_INVLD_TRNSFR_LEN: (void) sprintf(err_msg, MSGSTR(10005, " Error: Persistant Reserve command" " transfer length not word aligned.")); break; case L_RD_NO_DISK_ELEM: (void) sprintf(err_msg, MSGSTR(10006, " Error: Could not find the disk elements" " in the Receive Diagnostic pages.")); break; case L_RD_INVLD_TRNSFR_LEN: (void) sprintf(err_msg, MSGSTR(10007, " Error: Receive Diagnostic command" " transfer length not word aligned.")); break; case L_ILLEGAL_MODE_SENSE_PAGE: (void) sprintf(err_msg, MSGSTR(10008, " Error: Programming error - " "illegal Mode Sense parameter.")); break; case L_INVALID_NO_OF_ENVSEN_PAGES: (void) sprintf(err_msg, MSGSTR(10009, " Error: Invalid no. of sense pages.\n" " Could not get valid sense page" " information from the device.")); break; case L_INVALID_BUF_LEN: (void) sprintf(err_msg, MSGSTR(10010, " Error: Invalid buffer length.\n" " Could not get diagnostic " " information from the device.")); break; case L_INVALID_PATH: (void) sprintf(err_msg, MSGSTR(113, " Error: Invalid pathname")); break; case L_NO_PHYS_PATH: (void) sprintf(err_msg, MSGSTR(10011, " Error: Could not get" " physical path to the device.")); break; case L_NO_SES_PATH: (void) sprintf(err_msg, MSGSTR(10098, " Error: No SES found" " for the device path.")); break; case L_INVLD_PATH_NO_SLASH_FND: (void) sprintf(err_msg, MSGSTR(10012, "Error in the device physical path.")); break; case L_INVLD_PATH_NO_ATSIGN_FND: (void) sprintf(err_msg, MSGSTR(10013, " Error in the device physical path:" " no @ found.")); break; case L_INVALID_SLOT: (void) sprintf(err_msg, MSGSTR(10014, " Error: Invalid path format." " Invalid slot.")); break; case L_INVALID_LED_RQST: (void) sprintf(err_msg, MSGSTR(10015, " Error: Invalid LED request.")); break; case L_INVALID_PATH_FORMAT: (void) sprintf(err_msg, MSGSTR(10016, " Error: Invalid path format.")); break; case L_OPEN_PATH_FAIL: (void) sprintf(err_msg, MSGSTR(10017, " Error opening the path.")); break; case L_INVALID_PASSWORD_LEN: (void) sprintf(err_msg, MSGSTR(10018, "Error: Invalid password length.")); break; case L_INVLD_PHYS_PATH_TO_DISK: (void) sprintf(err_msg, MSGSTR(10019, " Error: Physical path not of a disk.")); break; case L_INVLD_ID_FOUND: (void) sprintf(err_msg, MSGSTR(10020, " Error in the device physical path:" " Invalid ID found in the path.")); break; case L_INVLD_WWN_FORMAT: (void) sprintf(err_msg, MSGSTR(10021, " Error in the device physical path:" " Invalid wwn format.")); break; case L_NO_VALID_PATH: (void) sprintf(err_msg, MSGSTR(10022, " Error: Could not find valid path to" " the device.")); break; case L_NO_WWN_FOUND_IN_PATH: (void) sprintf(err_msg, MSGSTR(10023, " Error in the device physical path:" " No WWN found.")); break; case L_NO_NODE_WWN_IN_WWNLIST: (void) sprintf(err_msg, MSGSTR(10024, " Error: Device's Node WWN is not" " found in the WWN list.\n")); break; case L_NO_NODE_WWN_IN_BOXLIST: (void) sprintf(err_msg, MSGSTR(10025, " Error: Device's Node WWN is not" " found in the Box list.\n")); break; case L_NULL_WWN_LIST: (void) sprintf(err_msg, MSGSTR(10026, " Error: Null WWN list found.")); break; case L_NO_LOOP_ADDRS_FOUND: (void) sprintf(err_msg, MSGSTR(10027, " Error: Could not find the loop address for " " the device at physical path.")); break; case L_INVLD_PORT_IN_PATH: (void) sprintf(err_msg, MSGSTR(10028, "Error in the device physical path:" " Invalid port number found." " (Should be 0 or 1).")); break; case L_INVALID_LOOP_MAP: (void) sprintf(err_msg, MSGSTR(10029, "Error: Invalid loop map found.")); break; case L_SFIOCGMAP_IOCTL_FAIL: (void) sprintf(err_msg, MSGSTR(10030, " Error: SFIOCGMAP ioctl failed." " Cannot read loop map.")); break; case L_FCIO_GETMAP_IOCTL_FAIL: (void) sprintf(err_msg, MSGSTR(10031, " Error: FCIO_GETMAP ioctl failed." " Cannot read loop map.")); break; case L_FCIO_LINKSTATUS_FAILED: (void) sprintf(err_msg, MSGSTR(10032, " Error: FCIO_LINKSTATUS ioctl failed." " Cannot read loop map.")); break; case L_FCIOGETMAP_INVLD_LEN: (void) sprintf(err_msg, MSGSTR(10033, " Error: FCIO_GETMAP ioctl returned" " an invalid parameter:" " # entries to large.")); break; case L_FCIO_FORCE_LIP_FAIL: (void) sprintf(err_msg, MSGSTR(10034, " Error: FCIO_FORCE_LIP ioctl failed.")); break; case L_FCIO_FORCE_LIP_PARTIAL_FAIL: (void) sprintf(err_msg, MSGSTR(10115, " Error: FCIO_FORCE_LIP ioctl failed on one" " or more (but not all) of the paths.")); break; case L_DWNLD_CHKSUM_FAILED: (void) sprintf(err_msg, MSGSTR(10035, "Error: Download file checksum failed.")); break; case L_DWNLD_READ_HEADER_FAIL: (void) sprintf(err_msg, MSGSTR(10036, " Error: Reading download file exec" " header failed.")); break; case L_DWNLD_READ_INCORRECT_BYTES: (void) sprintf(err_msg, MSGSTR(10037, " Error: Incorrect number of bytes read.")); break; case L_DWNLD_INVALID_TEXT_SIZE: (void) sprintf(err_msg, MSGSTR(10038, " Error: Reading text segment: " " Found wrong size.")); break; case L_DWNLD_READ_ERROR: (void) sprintf(err_msg, MSGSTR(10039, " Error: Failed to read download file.")); break; case L_DWNLD_BAD_FRMWARE: (void) sprintf(err_msg, MSGSTR(10040, " Error: Bad Firmware MAGIC.")); break; case L_DWNLD_TIMED_OUT: (void) sprintf(err_msg, MSGSTR(10041, " Error: Timed out in 5 minutes" " waiting for the" " IB to become available.")); break; case L_REC_DIAG_PG1: (void) sprintf(err_msg, MSGSTR(10042, " Error parsing the Receive" " diagnostic page.")); break; case L_TRANSFER_LEN: (void) sprintf(err_msg, MSGSTR(10043, " ")); break; case L_REQUIRE_FILE: (void) sprintf(err_msg, MSGSTR(10109, " Error: No default file. You must specify" " the filename path.")); break; case L_MALLOC_FAILED: (void) sprintf(err_msg, MSGSTR(10, " Error: Unable to allocate memory.")); break; case L_LOCALTIME_ERROR: (void) sprintf(err_msg, MSGSTR(10044, " Error: Could not convert time" " to broken-down time: Hrs/Mins/Secs.")); break; case L_SELECT_ERROR: (void) sprintf(err_msg, MSGSTR(10045, " select() error during retry:" " Could not wait for" " specified time.")); break; case L_NO_DISK_DEV_FOUND: (void) sprintf(err_msg, MSGSTR(10046, " Error: No disk devices found" " in the /dev/rdsk" " directory.")); break; case L_NO_TAPE_DEV_FOUND: (void) sprintf(err_msg, MSGSTR(10047, " Error: No tape devices found" " in the /dev/rmt" " directory.")); break; case L_LSTAT_ERROR: (void) sprintf(err_msg, MSGSTR(10048, " lstat() error: Cannot obtain status" " for the device.")); break; case L_SYMLINK_ERROR: (void) sprintf(err_msg, MSGSTR(10049, " Error: Could not read the symbolic link.")); break; case L_UNAME_FAILED: (void) sprintf(err_msg, MSGSTR(10050, " uname() error: Could not obtain the" " architeture of the host machine.")); break; case L_DRVCONFIG_ERROR: (void) sprintf(err_msg, MSGSTR(10051, " Error: Could not run drvconfig.")); break; case L_DISKS_ERROR: (void) sprintf(err_msg, MSGSTR(10052, " Error: Could not run disks.")); break; case L_DEVLINKS_ERROR: (void) sprintf(err_msg, MSGSTR(10053, " Error: Could not run devlinks.")); break; case L_READ_DEV_DIR_ERROR: (void) sprintf(err_msg, MSGSTR(10054, " Error: Could not read /dev/rdsk" " directory.")); break; case L_OPEN_ES_DIR_FAILED: (void) sprintf(err_msg, MSGSTR(10055, " Error: Could not open /dev/es" " directory.")); break; case L_LSTAT_ES_DIR_ERROR: (void) sprintf(err_msg, MSGSTR(10056, " lstat() error: Could not get status" " for /dev/es directory.")); break; case L_DEV_BUSY: (void) sprintf(err_msg, MSGSTR(10057, " Error: Could not offline the device\n" " May be Busy.")); break; case L_EXCL_OPEN_FAILED: (void) sprintf(err_msg, MSGSTR(10058, " Error: Could not open device in" " exclusive mode." " May already be open.")); break; case L_DEVICE_RESERVED: (void) sprintf(err_msg, MSGSTR(10059, " Error: Disk is reserved.")); break; case L_DISKS_RESERVED: (void) sprintf(err_msg, MSGSTR(10060, " Error: One or more disks in" " SENA are reserved.")); break; case L_SLOT_EMPTY: (void) sprintf(err_msg, MSGSTR(10061, " Error: Slot is empty.")); break; case L_ACQUIRE_FAIL: (void) sprintf(err_msg, MSGSTR(10062, " Error: Could not acquire" " the device.")); break; case L_POWER_OFF_FAIL_BUSY: (void) sprintf(err_msg, MSGSTR(10063, " Error: Could not power off the device.\n" " May be Busy.")); break; case L_ENCL_NAME_CHANGE_FAIL: (void) sprintf(err_msg, MSGSTR(10064, " Error: The Enclosure name change failed.")); break; case L_DUPLICATE_ENCLOSURES: (void) sprintf(err_msg, MSGSTR(10065, " Error: There are two or more enclosures" " with the same name." " Please use a logical or physical" " pathname.")); break; case L_INVALID_NUM_DISKS_ENCL: (void) sprintf(err_msg, MSGSTR(10066, " Error: The number of disks in the" " front & rear of the enclosure are" " different." " This is not a supported configuration.")); break; case L_ENCL_INVALID_PATH: (void) sprintf(err_msg, MSGSTR(10067, " Error: Invalid path." " Device is not a SENA subsystem.")); break; case L_NO_ENCL_LIST_FOUND: (void) sprintf(err_msg, MSGSTR(10068, " Error: Cannot get the Box list.")); break; case L_IB_NO_ELEM_FOUND: (void) sprintf(err_msg, MSGSTR(10069, " Error: No elements returned from" " enclosure (IB).")); break; case L_GET_STATUS_FAILED: (void) sprintf(err_msg, MSGSTR(10070, " Error: Get status failed.")); break; case L_RD_PG_MIN_BUFF: (void) sprintf(err_msg, MSGSTR(10071, " Error: Reading page from IB.\n" " Buffer size too small.")); break; case L_RD_PG_INVLD_CODE: (void) sprintf(err_msg, MSGSTR(10072, " Error: Reading page from IB\n" " Invalid page code or page len found.")); break; case L_BP_BUSY_RESERVED: (void) sprintf(err_msg, MSGSTR(10073, " Error: There is a busy or reserved disk" " attached to this backplane.\n" " You must close the disk,\n" " or release the disk,\n" " or resubmit the command using" " the Force option.")); break; case L_BP_BUSY: (void) sprintf(err_msg, MSGSTR(10074, " Error: There is a busy disk" " attached to this backplane.\n" " You must close the disk,\n" " or resubmit the command using" " the Force option.")); break; case L_BP_RESERVED: (void) sprintf(err_msg, MSGSTR(10075, " Error: There is a reserved disk" " attached to this backplane.\n" " You must release the disk,\n" " or resubmit the subcommand using" " the Force option.")); break; case L_NO_BP_ELEM_FOUND: (void) sprintf(err_msg, MSGSTR(10076, " Error: No Back plane elements found" " in the enclosure.")); break; case L_SSA_CONFLICT: (void) sprintf(err_msg, MSGSTR(10077, " There is a conflict between the " "enclosure name and an SSA name of " "same form, cN.\n" " Please use a logical or physical " "pathname.")); break; case L_WARNING: (void) sprintf(err_msg, MSGSTR(10078, " Warning:")); break; case L_TH_JOIN: (void) sprintf(err_msg, MSGSTR(10079, " Error: Thread join failed.")); break; case L_FCIO_RESET_LINK_FAIL: (void) sprintf(err_msg, MSGSTR(10082, " Error: FCIO_RESET_LINK ioctl failed.\n" " Could not reset the loop.")); break; case L_FCIO_GET_FCODE_REV_FAIL: (void) sprintf(err_msg, MSGSTR(10083, " Error: FCIO_GET_FCODE_REV ioctl failed.\n" " Could not get the fcode version.")); break; case L_FCIO_GET_FW_REV_FAIL: (void) sprintf(err_msg, MSGSTR(10084, " Error: FCIO_GET_FW_REV ioctl failed.\n" " Could not get the firmware revision.")); break; case L_NO_DEVICES_FOUND: (void) sprintf(err_msg, MSGSTR(10085, " No FC devices found.")); break; case L_INVALID_DEVICE_COUNT: (void) sprintf(err_msg, MSGSTR(10086, " Error: FCIO_GET_DEV_LIST ioctl returned" " an invalid device count.")); break; case L_FCIO_GET_NUM_DEVS_FAIL: (void) sprintf(err_msg, MSGSTR(10087, " Error: FCIO_GET_NUM_DEVS ioctl failed.\n" " Could not get the number of devices.")); break; case L_FCIO_GET_DEV_LIST_FAIL: (void) sprintf(err_msg, MSGSTR(10088, " Error: FCIO_GET_DEV_LIST ioctl failed.\n" " Could not get the device list.")); break; case L_FCIO_GET_LINK_STATUS_FAIL: (void) sprintf(err_msg, MSGSTR(10089, " Error: FCIO_GET_LINK_STATUS ioctl failed.\n" " Could not get the link status.")); break; case L_PORT_OFFLINE_FAIL: (void) sprintf(err_msg, MSGSTR(10090, " Error: ioctl to offline the port failed.")); break; case L_PORT_OFFLINE_UNSUPPORTED: (void) sprintf(err_msg, MSGSTR(10091, " Error: The driver does not support ioctl to" " disable the FCA port.")); break; case L_PORT_ONLINE_FAIL: (void) sprintf(err_msg, MSGSTR(10092, " Error: ioctl to online the port failed.")); break; case L_PORT_ONLINE_UNSUPPORTED: (void) sprintf(err_msg, MSGSTR(10093, " Error: The driver does not support ioctl to" " enable the FCA port.")); break; case L_FCP_TGT_INQUIRY_FAIL: (void) sprintf(err_msg, MSGSTR(10094, " Error: FCP_TGT_INQUIRY ioctl failed.\n" " Could not get the target inquiry data" " from FCP.")); break; case L_FSTAT_ERROR: (void) sprintf(err_msg, MSGSTR(10095, " fstat() error: Cannot obtain status" " for the device.")); break; case L_FCIO_GET_HOST_PARAMS_FAIL: (void) sprintf(err_msg, MSGSTR(10097, " Error: FCIO_GET_HOST_PARAMS ioctl failed.\n" " Could not get the host parameters.")); break; case L_STAT_ERROR: (void) sprintf(err_msg, MSGSTR(10099, " stat() error: Cannot obtain status" " for the device.")); break; case L_DEV_SNAPSHOT_FAILED: (void) sprintf(err_msg, MSGSTR(10100, " Error: Could not retrieve device tree" " snapshot.")); break; case L_LOOPBACK_UNSUPPORTED: (void) sprintf(err_msg, MSGSTR(10101, " Error: Loopback mode is unsupported for this" " device.")); break; case L_LOOPBACK_FAILED: (void) sprintf(err_msg, MSGSTR(10102, " Error: Error occurred during loopback mode" " set.")); break; case L_FCIO_GET_TOPOLOGY_FAIL: (void) sprintf(err_msg, MSGSTR(10103, " Error: FCIO_GET_TOPOLOGY ioctl failed.\n" " Could not get the fca port topology.")); break; case L_UNEXPECTED_FC_TOPOLOGY: (void) sprintf(err_msg, MSGSTR(10104, " Error: Unexpected Fibre Channel topology" " found.")); break; case L_INVALID_PRIVATE_LOOP_ADDRESS: (void) sprintf(err_msg, MSGSTR(10105, " Error: AL_PA is not a valid private loop" " address.")); break; case L_NO_FABRIC_ADDR_FOUND: (void) sprintf(err_msg, MSGSTR(10106, " Error: Could not find the fabric address" " for the device at physical path.")); break; case L_INVALID_FABRIC_ADDRESS: (void) sprintf(err_msg, MSGSTR(10107, " Error: Device port address on the Fabric" " topology is not valid.")); break; case L_PT_PT_FC_TOP_NOT_SUPPORTED: (void) sprintf(err_msg, MSGSTR(10108, " Error: Point to Point Fibre Channel " "topology is currently not supported.")); break; case L_FCIO_DEV_LOGIN_FAIL: (void) sprintf(err_msg, MSGSTR(10310, " Error: FCIO_DEV_LOGIN ioctl failed.")); break; case L_FCIO_DEV_LOGOUT_FAIL: (void) sprintf(err_msg, MSGSTR(10311, " Error: FCIO_DEV_LOGOUT ioctl failed.")); break; case L_OPNOSUPP_ON_TOPOLOGY: (void) sprintf(err_msg, MSGSTR(10312, " Error: operation not supported " "on connected topology.")); break; case L_INVALID_PATH_TYPE: (void) sprintf(err_msg, MSGSTR(10313, " Error: operation not supported " "on the path.")); break; case L_FCIO_GET_STATE_FAIL: (void) sprintf(err_msg, MSGSTR(10314, " Error: FCIO_GET_STATE ioctl failed.")); break; case L_WWN_NOT_FOUND_IN_DEV_LIST: (void) sprintf(err_msg, MSGSTR(10315, " Error: device WWN not found in " "device list.")); break; case L_STAT_RMT_DIR_ERROR: (void) sprintf(err_msg, MSGSTR(10110, " stat() error: Could not get status" " for /dev/rmt directory.")); break; case L_STAT_DEV_DIR_ERROR: (void) sprintf(err_msg, MSGSTR(10111, " stat() error: Could not get status" " for /dev/dsk directory.")); break; case L_PROM_INIT_FAILED: (void) sprintf(err_msg, MSGSTR(10234, " Error: di_prom_init failure")); break; case L_PORT_DRIVER_NOT_FOUND: (void) sprintf(err_msg, MSGSTR(10113, " Error: requested port driver" " does not exist")); break; case L_PHYS_PATH_NOT_FOUND: (void) sprintf(err_msg, MSGSTR(10114, " Error: requested phys path does not exist")); break; case L_GET_DEV_LIST_ULP_FAILURE: (void) sprintf(err_msg, MSGSTR(10150, " Error: g_get_dev_list failed on ULP " "processing of target device(s)")); break; case L_SCSI_VHCI_ERROR: (void) sprintf(err_msg, MSGSTR(10230, " Error: Unable to perform failover")); break; case L_SCSI_VHCI_ALREADY_ACTIVE: (void) sprintf(err_msg, MSGSTR(10231, " Error: Pathclass already active")); break; case L_NO_DEVID: (void) sprintf(err_msg, MSGSTR(10232, " Error: No device identifier found")); break; case L_DRIVER_NOTSUPP: (void) sprintf(err_msg, MSGSTR(10233, " Error: Driver not supported")); break; case L_PROC_WWN_ARG_ERROR: (void) sprintf(err_msg, MSGSTR(10235, " Error: process WWN argument")); break; case L_NO_WWN_PROP_FOUND: (void) sprintf(err_msg, MSGSTR(10236, " Error: WWN prop not found")); break; case L_NO_DRIVER_NODES_FOUND: (void) sprintf(err_msg, MSGSTR(10237, " Error: Requested driver nodes not found")); break; case L_INVALID_MAP_DEV_ADDR: (void) sprintf(err_msg, MSGSTR(10330, " Error: Invalid map device handle found")); break; case L_INVALID_MAP_DEV_PROP_TYPE: (void) sprintf(err_msg, MSGSTR(10331, " Error: Invalid device property type found")); break; case L_INVALID_MAP_DEV_PROP_NAME: (void) sprintf(err_msg, MSGSTR(10332, " Error: Invalid device property name found")); break; case L_INVALID_MAP_DEV_PROP: (void) sprintf(err_msg, MSGSTR(10333, " Error: Invalid device property handle " "found")); break; case L_SCSI_VHCI_NO_STANDBY: (void) sprintf(err_msg, MSGSTR(10334, " Error: Unable to perform failover, " "standby path unavailable")); break; case L_SCSI_VHCI_FAILOVER_NOTSUP: (void) sprintf(err_msg, MSGSTR(10335, " Error: Device does not support failover")); break; case L_SCSI_VHCI_FAILOVER_BUSY: (void) sprintf(err_msg, MSGSTR(10336, " Error: Failover currently in progress")); break; case L_NO_SUCH_DEV_FOUND: (void) sprintf(err_msg, MSGSTR(10337, " Error: No such device found")); break; case L_NO_SUCH_PROP_FOUND: (void) sprintf(err_msg, MSGSTR(10338, " Error: No such property found")); break; case L_INVALID_ARG: (void) sprintf(err_msg, MSGSTR(10339, " Error: Invalid argument found")); break; default: if (((L_SCSI_ERROR ^ errornum) == STATUS_GOOD) || ((L_SCSI_ERROR ^ errornum) == STATUS_BUSY) || ((L_SCSI_ERROR ^ errornum) == STATUS_CHECK) || ((L_SCSI_ERROR ^ errornum) == STATUS_MET) || ((L_SCSI_ERROR ^ errornum) == STATUS_INTERMEDIATE) || ((L_SCSI_ERROR ^ errornum) == STATUS_INTERMEDIATE_MET) || ((L_SCSI_ERROR ^ errornum) == STATUS_RESERVATION_CONFLICT) || ((L_SCSI_ERROR ^ errornum) == STATUS_TERMINATED) || ((L_SCSI_ERROR ^ errornum) == STATUS_QFULL)) { (void) sprintf(err_msg, MSGSTR(10080, " SCSI Error - Sense Byte:(0x%x) %s \n" " Error: Retry failed."), (L_SCSI_ERROR ^ errornum) & STATUS_MASK, decode_sense_byte((uchar_t)L_SCSI_ERROR ^ errornum)); } else { (void) sprintf(err_msg, MSGSTR(10081, " Error: could not decode the" " error message.\n" " The given error message is not" " defined in the library.\n" " Message number: %d.\n"), errornum); } } /* end of switch */ errStrg = alloc_string(err_msg); return (errStrg); }
/* * Retrieve the version banner from the card * uses ioctl: FCIO_FCODE_MCODE_VERSION FCode revision */ static int q_findversion(int verbose, int index, uchar_t *version, uint16_t *chip_id) /*ARGSUSED*/ { int fd, ntries; struct ifp_fm_version *version_buffer = NULL; char prom_ver[100] = {NULL}; char mcode_ver[100] = {NULL}; fcio_t fcio; if (strstr(&pcibus_list[index][0], fc_trans)) { if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) { (void) fprintf(stderr, MSGSTR(21000, "Error: Could not open %s\n"), &pcibus_list[index][0]); return (1); } if ((version_buffer = (struct ifp_fm_version *)malloc( sizeof (struct ifp_fm_version))) == NULL) { (void) fprintf(stderr, MSGSTR(21013, "Error: Memory allocation failed\n")); (void) close(fd); return (1); } version_buffer->fcode_ver = (char *)version; version_buffer->mcode_ver = mcode_ver; version_buffer->prom_ver = prom_ver; version_buffer->fcode_ver_len = MAXNAMELEN - 1; version_buffer->mcode_ver_len = 100; version_buffer->prom_ver_len = 100; if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, version_buffer) < 0) { (void) fprintf(stderr, MSGSTR(21014, "Error: Driver interface FCIO_FCODE_MCODE_VERSION failed\n")); free(version_buffer); (void) close(fd); return (1); } version[version_buffer->fcode_ver_len] = '\0'; /* Need a way to get card MCODE (firmware) to track certain HW bugs */ if (getenv("_LUX_D_DEBUG") != NULL) { (void) fprintf(stdout, " Device %i: QLGC chip_id %x\n", index+1, *chip_id); (void) fprintf(stdout, " FCode:%s\n MCODE:%s\n PROM:%s\n", (char *)version, mcode_ver, prom_ver); } free(version_buffer); } else if (strstr(&pcibus_list[index][0], fp_trans)) { /* * Get the fcode and prom's fw version * using the fp ioctls. Currently, we pass * only the fcode version to the calling function * and ignore the FW version (using the existing * implementation). */ if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) { (void) fprintf(stderr, MSGSTR(4511, "Could not open %s\n"), &pcibus_list[index][0]); (void) close(fd); return (1); } /* Get the fcode version */ bzero(version, sizeof (version)); fcio.fcio_cmd = FCIO_GET_FCODE_REV; /* Information read operation */ fcio.fcio_xfer = FCIO_XFER_READ; fcio.fcio_obuf = (caddr_t)version; fcio.fcio_olen = MAXNAMELEN; for (ntries = 0; ntries < MAX_RETRIES; ntries++) { if (ioctl(fd, FCIO_CMD, &fcio) != 0) { if ((errno == EAGAIN) && (ntries+1 < MAX_RETRIES)) { /* wait 30 secs */ (void) sleep(MAX_WAIT_TIME); continue; } (void) close(fd); return (L_FCIO_GET_FCODE_REV_FAIL); } break; } version[MAXNAMELEN-1] = '\0'; } /* Get type of card from product name in FCode version banner */ if (strstr((char *)version, qlgc2100)) { *chip_id = 0x2100; } else if (strstr((char *)version, qlgc2200)) { *chip_id = 0x2200; if (strstr((char *)version, "Sbus")) { *chip_id = SBUS_CHIP_ID; } } else if (strstr((char *)version, qlgc2300)) { *chip_id = 0x2300; } else if (strstr((char *)version, qlgc2312)) { *chip_id = 0x2312; } else { *chip_id = 0x0; } (void) close(fd); return (0); }
/* * Download host bus adapter FCode to all supported cards. * * Specify a directory that holds the FCode files, or * it will use the default dir. Each file is dealt to * the appropriate function. * * -p prints current versions only, -d specifies a directory to load */ static int adm_fcode(int verbose, char *dir) { struct stat statbuf; struct dirent *dirp; DIR *dp; int fp; char fbuf[BUFSIZ]; char file[MAXPATHLEN]; int retval = 0, strfound = 0; char manf[BUFSIZ]; /* Find all adapters and print the current FCode version */ if (Options & OPTION_P) { /* SOCAL (SBus) adapters are not supported on x86 */ #ifndef __x86 if (verbose) { (void) fprintf(stdout, MSGSTR(2215, "\n Searching for FC100/S cards:\n")); } retval += fcal_update(Options & PVERBOSE, NULL); #endif if (verbose) { (void) fprintf(stdout, MSGSTR(2216, "\n Searching for FC100/P, FC100/2P cards:\n")); } retval += q_qlgc_update(Options & PVERBOSE, NULL); if (verbose) { (void) fprintf(stdout, MSGSTR(2503, "\n Searching for Emulex cards:\n")); } retval += emulex_update(NULL); /* Send files to the correct function for loading to the HBA */ } else { if (!dir) { (void) fprintf(stdout, MSGSTR(2251, " Location of Fcode not specified.\n")); return (1); } else if (verbose) { (void) fprintf(stdout, MSGSTR(2217, " Using directory %s"), dir); } if (lstat(dir, &statbuf) < 0) { (void) fprintf(stderr, MSGSTR(134, "%s: lstat() failed - %s\n"), dir, strerror(errno)); return (1); } if (S_ISDIR(statbuf.st_mode) == 0) { (void) fprintf(stderr, MSGSTR(2218, "Error: %s is not a directory.\n"), dir); return (1); } if ((dp = opendir(dir)) == NULL) { (void) fprintf(stderr, MSGSTR(2219, " Error Cannot open directory %s\n"), dir); return (1); } while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } sprintf(file, "%s/%s", dir, dirp->d_name); if ((fp = open(file, O_RDONLY)) < 0) { (void) fprintf(stderr, MSGSTR(2220, "Error: open() failed to open file " "%s\n"), file); /* * We should just issue an error message and * make an attempt on the next file, * and the open error is still an error * so the retval should be incremented */ retval++; continue; } while ((read(fp, fbuf, BUFSIZ)) > 0) { if (memstrstr(fbuf, "SUNW,socal", BUFSIZ, strlen("SUNW,socal")) != NULL) { (void) fprintf(stdout, MSGSTR(2221, "\n Using file: %s\n"), file); retval += fcal_update( Options & PVERBOSE, file); strfound++; break; } else if ((memstrstr(fbuf, "SUNW,ifp", BUFSIZ, strlen("SUNW,ifp")) != NULL) || (memstrstr(fbuf, "SUNW,qlc", BUFSIZ, strlen("SUNW,qlc")) != NULL)) { (void) fprintf(stdout, MSGSTR(2221, "\n Using file: %s\n"), file); retval += q_qlgc_update( Options & PVERBOSE, file); strfound++; break; } } if (!strfound) { /* check to see if this is an emulex fcode */ memset(manf, 0, sizeof (manf)); if ((emulex_fcode_reader(fp, "manufacturer", manf, sizeof (manf)) == 0) && (strncmp(manf, "Emulex", sizeof (manf)) == 0)) { retval += emulex_update(file); strfound = 0; } else { (void) fprintf(stderr, MSGSTR(2222, "\nError: %s is not a valid Fcode " "file.\n"), file); retval++; } } else { strfound = 0; } close(fp); } closedir(dp); } return (retval); }