1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte /* 27*fcf3ce44SJohn Forte * I18N message number ranges 28*fcf3ce44SJohn Forte * This file: 21000 - 21499 29*fcf3ce44SJohn Forte * Shared common messages: 1 - 1999 30*fcf3ce44SJohn Forte */ 31*fcf3ce44SJohn Forte 32*fcf3ce44SJohn Forte 33*fcf3ce44SJohn Forte 34*fcf3ce44SJohn Forte /* 35*fcf3ce44SJohn Forte * Functions to support the download of FCode to PCI HBAs 36*fcf3ce44SJohn Forte * Qlogic ISP21XX/22XX boards: FC100/P single port, ISP2200 dual port 37*fcf3ce44SJohn Forte * and Emulex cards 38*fcf3ce44SJohn Forte */ 39*fcf3ce44SJohn Forte #include <errno.h> 40*fcf3ce44SJohn Forte #include <ctype.h> 41*fcf3ce44SJohn Forte #include <fcntl.h> 42*fcf3ce44SJohn Forte #include <stdio.h> 43*fcf3ce44SJohn Forte #include <string.h> 44*fcf3ce44SJohn Forte #include <strings.h> 45*fcf3ce44SJohn Forte #include <unistd.h> 46*fcf3ce44SJohn Forte #include <stdlib.h> 47*fcf3ce44SJohn Forte #include <sys/stat.h> 48*fcf3ce44SJohn Forte #include <limits.h> 49*fcf3ce44SJohn Forte #include <signal.h> 50*fcf3ce44SJohn Forte #include <dirent.h> 51*fcf3ce44SJohn Forte #include <nl_types.h> 52*fcf3ce44SJohn Forte #include <utmpx.h> 53*fcf3ce44SJohn Forte #include <sys/mnttab.h> 54*fcf3ce44SJohn Forte #include <sys/file.h> 55*fcf3ce44SJohn Forte #include <sys/mtio.h> 56*fcf3ce44SJohn Forte #include <sys/scsi/impl/uscsi.h> 57*fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h> 58*fcf3ce44SJohn Forte #include <stgcom.h> 59*fcf3ce44SJohn Forte #include <sys/scsi/adapters/ifpio.h> 60*fcf3ce44SJohn Forte #include <libdevinfo.h> 61*fcf3ce44SJohn Forte #include "luxadm.h" 62*fcf3ce44SJohn Forte 63*fcf3ce44SJohn Forte /* Error codes - used by the fcode_load_file routine */ 64*fcf3ce44SJohn Forte #define FCODE_SUCCESS 0 /* successful completion */ 65*fcf3ce44SJohn Forte #define FCODE_LOAD_FAILURE 1 /* general failure */ 66*fcf3ce44SJohn Forte #define FCODE_IOCTL_FAILURE 2 /* FCODE ioctl download failure */ 67*fcf3ce44SJohn Forte 68*fcf3ce44SJohn Forte #define HBA_MAX 128 69*fcf3ce44SJohn Forte #define FCODE_HDR 200 70*fcf3ce44SJohn Forte #define MAX_RETRIES 3 71*fcf3ce44SJohn Forte #define MAX_WAIT_TIME 30 72*fcf3ce44SJohn Forte 73*fcf3ce44SJohn Forte /* 74*fcf3ce44SJohn Forte * EMULEX Fcode attributes 75*fcf3ce44SJohn Forte */ 76*fcf3ce44SJohn Forte #define EMULEX_FCODE_VERSION_LENGTH 16 77*fcf3ce44SJohn Forte #define EMULEX_READ_BUFFER_SIZE 128 78*fcf3ce44SJohn Forte 79*fcf3ce44SJohn Forte /* Emulex specific error codes */ 80*fcf3ce44SJohn Forte #define EMLX_ERRNO_START 0x100 81*fcf3ce44SJohn Forte 82*fcf3ce44SJohn Forte /* Diagnostic error codes */ 83*fcf3ce44SJohn Forte #define EMLX_TEST_FAILED (EMLX_ERRNO_START + 0) 84*fcf3ce44SJohn Forte 85*fcf3ce44SJohn Forte /* Download image contains bad data */ 86*fcf3ce44SJohn Forte #define EMLX_IMAGE_BAD (EMLX_ERRNO_START + 1) 87*fcf3ce44SJohn Forte /* Download image not compatible with current hardware */ 88*fcf3ce44SJohn Forte #define EMLX_IMAGE_INCOMPATIBLE (EMLX_ERRNO_START + 2) 89*fcf3ce44SJohn Forte /* Unable to take adapter offline */ 90*fcf3ce44SJohn Forte #define EMLX_IMAGE_FAILED (EMLX_ERRNO_START + 3) 91*fcf3ce44SJohn Forte /* Image download failed */ 92*fcf3ce44SJohn Forte #define EMLX_OFFLINE_FAILED (EMLX_ERRNO_START + 4) 93*fcf3ce44SJohn Forte 94*fcf3ce44SJohn Forte 95*fcf3ce44SJohn Forte 96*fcf3ce44SJohn Forte 97*fcf3ce44SJohn Forte /* 98*fcf3ce44SJohn Forte * This is just a random value chosen to identify Sbus Fcodes. Sbus FCode 99*fcf3ce44SJohn Forte * for Ivory is based on a 2200 chip but this value does not reflect that. 100*fcf3ce44SJohn Forte */ 101*fcf3ce44SJohn Forte #define SBUS_CHIP_ID 0x1969 102*fcf3ce44SJohn Forte #define IVORY_BUS "/sbus@" 103*fcf3ce44SJohn Forte #define IVORY_DRVR "/SUNW,qlc@" 104*fcf3ce44SJohn Forte 105*fcf3ce44SJohn Forte /* Global variables */ 106*fcf3ce44SJohn Forte static char fc_trans[] = "SUNW,ifp"; /* fibre channel transport */ 107*fcf3ce44SJohn Forte static char fp_trans[] = "SUNW,qlc"; /* fca layer driver */ 108*fcf3ce44SJohn Forte static char fp_trans_id[] = "fp@"; /* transport layer id */ 109*fcf3ce44SJohn Forte static char qlgc2100[] = "FC100/P"; /* product name for 2100 */ 110*fcf3ce44SJohn Forte static char qlgc2200[] = "ISP2200"; /* product name for 2200 */ 111*fcf3ce44SJohn Forte static char qlgc2300[] = "ISP2300"; /* product name for 2300 */ 112*fcf3ce44SJohn Forte static char qlgc2312[] = "ISP2312"; /* product name for 2312 */ 113*fcf3ce44SJohn Forte /* 114*fcf3ce44SJohn Forte * The variable qlgc2200Sbus represents the string which is always the 115*fcf3ce44SJohn Forte * starting string of the version information in an ISP2200 Sbus Fcode. 116*fcf3ce44SJohn Forte */ 117*fcf3ce44SJohn Forte static char qlgc2200Sbus[] = "ISP2200 Sbus FC-AL Host Adapter Driver"; 118*fcf3ce44SJohn Forte static char pcibus_list[HBA_MAX][PATH_MAX]; 119*fcf3ce44SJohn Forte /* Internal functions */ 120*fcf3ce44SJohn Forte static int q_load_file(int, char *); 121*fcf3ce44SJohn Forte static int q_getbootdev(uchar_t *); 122*fcf3ce44SJohn Forte static int q_getdevctlpath(char *, int *); 123*fcf3ce44SJohn Forte static int q_warn(int); 124*fcf3ce44SJohn Forte static int q_findversion(int, int, uchar_t *, uint16_t *); 125*fcf3ce44SJohn Forte static int q_findfileversion(char *, uchar_t *, uint16_t *, int, int *); 126*fcf3ce44SJohn Forte static int q_findSbusfile(int, int *); 127*fcf3ce44SJohn Forte static int memstrstr(char *, char *, int, int); 128*fcf3ce44SJohn Forte static int fcode_load_file(int, char *, int *); 129*fcf3ce44SJohn Forte 130*fcf3ce44SJohn Forte /* 131*fcf3ce44SJohn Forte * Functions to support Fcode download for Emulex HBAs 132*fcf3ce44SJohn Forte */ 133*fcf3ce44SJohn Forte static int emulex_fcodeversion(di_node_t, uchar_t *); 134*fcf3ce44SJohn Forte static void handle_emulex_error(int, char *); 135*fcf3ce44SJohn Forte 136*fcf3ce44SJohn Forte /* 137*fcf3ce44SJohn Forte * Searches for and updates the cards. This is the "main" function 138*fcf3ce44SJohn Forte * and will give the output to the user by calling the subfunctions. 139*fcf3ce44SJohn Forte * args: FCode file; if NULL only the current FCode version is printed 140*fcf3ce44SJohn Forte */ 141*fcf3ce44SJohn Forte int 142*fcf3ce44SJohn Forte q_qlgc_update(unsigned int verbose, char *file) 143*fcf3ce44SJohn Forte /*ARGSUSED*/ 144*fcf3ce44SJohn Forte { 145*fcf3ce44SJohn Forte int fd, fcode_fd = -1, errnum = 0, devcnt = 0, retval = 0, isSbus = 0; 146*fcf3ce44SJohn Forte int sbus_off; 147*fcf3ce44SJohn Forte uint_t i, fflag = 0; 148*fcf3ce44SJohn Forte uint16_t chip_id = 0, file_id = 0; 149*fcf3ce44SJohn Forte uchar_t fcode_buf[FCODE_HDR]; 150*fcf3ce44SJohn Forte static uchar_t bootpath[PATH_MAX]; 151*fcf3ce44SJohn Forte static uchar_t version[MAXNAMELEN], version_file[MAXNAMELEN]; 152*fcf3ce44SJohn Forte char devpath[PATH_MAX], tmppath[PATH_MAX]; 153*fcf3ce44SJohn Forte void (*sigint)(); /* to store default SIGTERM setting */ 154*fcf3ce44SJohn Forte static struct utmpx *utmpp = NULL; /* pointer for getutxent() */ 155*fcf3ce44SJohn Forte char *ptr1, *ptr2; 156*fcf3ce44SJohn Forte char phys_path[PATH_MAX]; 157*fcf3ce44SJohn Forte /* 158*fcf3ce44SJohn Forte * The variables port1 and port2 are used to store the bus id 159*fcf3ce44SJohn Forte * e.g. the bus id for this path: 160*fcf3ce44SJohn Forte * /devices/sbus@12,0/SUNW,qlc@2,30000/fp@0,0:devctl 161*fcf3ce44SJohn Forte * is "sbus@12". They are initialized to a random value and are 162*fcf3ce44SJohn Forte * set such that they are not equal initially. 163*fcf3ce44SJohn Forte */ 164*fcf3ce44SJohn Forte static char port1[MAXNAMELEN] = {NULL}; 165*fcf3ce44SJohn Forte static char port2[MAXNAMELEN] = {NULL}; 166*fcf3ce44SJohn Forte 167*fcf3ce44SJohn Forte if (file) { 168*fcf3ce44SJohn Forte fflag++; 169*fcf3ce44SJohn Forte 170*fcf3ce44SJohn Forte /* check for a valid file */ 171*fcf3ce44SJohn Forte if ((fcode_fd = open(file, O_RDONLY)) < 0) { 172*fcf3ce44SJohn Forte (void) fprintf(stderr, 173*fcf3ce44SJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), file); 174*fcf3ce44SJohn Forte return (1); 175*fcf3ce44SJohn Forte } 176*fcf3ce44SJohn Forte if (read(fcode_fd, fcode_buf, FCODE_HDR) != FCODE_HDR) { 177*fcf3ce44SJohn Forte perror(MSGSTR(21001, "read")); 178*fcf3ce44SJohn Forte (void) close(fcode_fd); 179*fcf3ce44SJohn Forte return (1); 180*fcf3ce44SJohn Forte } 181*fcf3ce44SJohn Forte 182*fcf3ce44SJohn Forte /* 183*fcf3ce44SJohn Forte * Check if it's SBUS FCode by calling q_findSbusfile 184*fcf3ce44SJohn Forte * if it is then isSbus will be 1, if not it will be 0 185*fcf3ce44SJohn Forte * in case of an error, it will be -1 186*fcf3ce44SJohn Forte */ 187*fcf3ce44SJohn Forte isSbus = q_findSbusfile(fcode_fd, &sbus_off); 188*fcf3ce44SJohn Forte if (isSbus == -1) { 189*fcf3ce44SJohn Forte (void) close(fcode_fd); 190*fcf3ce44SJohn Forte return (1); 191*fcf3ce44SJohn Forte } 192*fcf3ce44SJohn Forte 193*fcf3ce44SJohn Forte /* 194*fcf3ce44SJohn Forte * FCode header check - make sure it's PCI FCode 195*fcf3ce44SJohn Forte * Structure of FCode header (byte# refers to byte numbering 196*fcf3ce44SJohn Forte * in FCode spec, not the byte# of our fcode_buf buffer): 197*fcf3ce44SJohn Forte * header byte 00 0x55 prom signature byte one 198*fcf3ce44SJohn Forte * byte 01 0xaa prom signature byte two 199*fcf3ce44SJohn Forte * data byte 00-03 P C I R 200*fcf3ce44SJohn Forte * OR 201*fcf3ce44SJohn Forte * header byte 32 0x55 202*fcf3ce44SJohn Forte * byte 33 0xaa 203*fcf3ce44SJohn Forte * data byte 60-63 P C I R 204*fcf3ce44SJohn Forte * The second format with an offset of 32 is used for ifp prom 205*fcf3ce44SJohn Forte */ 206*fcf3ce44SJohn Forte if (!(((fcode_buf[0x00] == 0x55) && 207*fcf3ce44SJohn Forte (fcode_buf[0x01] == 0xaa) && 208*fcf3ce44SJohn Forte (fcode_buf[0x1c] == 'P') && 209*fcf3ce44SJohn Forte (fcode_buf[0x1d] == 'C') && 210*fcf3ce44SJohn Forte (fcode_buf[0x1e] == 'I') && 211*fcf3ce44SJohn Forte (fcode_buf[0x1f] == 'R')) || 212*fcf3ce44SJohn Forte 213*fcf3ce44SJohn Forte ((fcode_buf[0x20] == 0x55) && 214*fcf3ce44SJohn Forte (fcode_buf[0x21] == 0xaa) && 215*fcf3ce44SJohn Forte (fcode_buf[0x3c] == 'P') && 216*fcf3ce44SJohn Forte (fcode_buf[0x3d] == 'C') && 217*fcf3ce44SJohn Forte (fcode_buf[0x3e] == 'I') && 218*fcf3ce44SJohn Forte (fcode_buf[0x3f] == 'R')) || 219*fcf3ce44SJohn Forte 220*fcf3ce44SJohn Forte (isSbus))) { 221*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21002, 222*fcf3ce44SJohn Forte "Error: %s is not a valid FC100/P, " 223*fcf3ce44SJohn Forte "ISP2200, ISP23xx FCode file.\n"), 224*fcf3ce44SJohn Forte file); 225*fcf3ce44SJohn Forte (void) close(fcode_fd); 226*fcf3ce44SJohn Forte return (1); 227*fcf3ce44SJohn Forte } 228*fcf3ce44SJohn Forte 229*fcf3ce44SJohn Forte /* check for single user mode */ 230*fcf3ce44SJohn Forte while ((utmpp = getutxent()) != NULL) { 231*fcf3ce44SJohn Forte if (strstr(utmpp->ut_line, "run-level") && 232*fcf3ce44SJohn Forte (strcmp(utmpp->ut_line, "run-level S") && 233*fcf3ce44SJohn Forte strcmp(utmpp->ut_line, "run-level 1"))) { 234*fcf3ce44SJohn Forte if (q_warn(1)) { 235*fcf3ce44SJohn Forte (void) endutxent(); 236*fcf3ce44SJohn Forte (void) close(fcode_fd); 237*fcf3ce44SJohn Forte return (1); 238*fcf3ce44SJohn Forte } 239*fcf3ce44SJohn Forte break; 240*fcf3ce44SJohn Forte } 241*fcf3ce44SJohn Forte } 242*fcf3ce44SJohn Forte (void) endutxent(); 243*fcf3ce44SJohn Forte 244*fcf3ce44SJohn Forte /* get bootpath */ 245*fcf3ce44SJohn Forte if (!q_getbootdev((uchar_t *)&bootpath[0]) && 246*fcf3ce44SJohn Forte getenv("_LUX_D_DEBUG") != NULL) { 247*fcf3ce44SJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath); 248*fcf3ce44SJohn Forte } 249*fcf3ce44SJohn Forte } 250*fcf3ce44SJohn Forte /* 251*fcf3ce44SJohn Forte * Get count of, and names of PCI slots with ifp device control 252*fcf3ce44SJohn Forte * (devctl) nodes. Search /devices. 253*fcf3ce44SJohn Forte */ 254*fcf3ce44SJohn Forte (void) strcpy(devpath, "/devices"); 255*fcf3ce44SJohn Forte if (q_getdevctlpath(devpath, (int *)&devcnt) == 0) { 256*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21003, 257*fcf3ce44SJohn Forte "\n Found Path to %d FC100/P, ISP2200, ISP23xx Devices\n"), 258*fcf3ce44SJohn Forte devcnt); 259*fcf3ce44SJohn Forte } else { 260*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21004, 261*fcf3ce44SJohn Forte "Error: Could not get /devices path to FC100/P," 262*fcf3ce44SJohn Forte "ISP2200, ISP23xx Cards.\n")); 263*fcf3ce44SJohn Forte retval++; 264*fcf3ce44SJohn Forte } 265*fcf3ce44SJohn Forte 266*fcf3ce44SJohn Forte for (i = 0; i < devcnt; i++) { 267*fcf3ce44SJohn Forte 268*fcf3ce44SJohn Forte (void) strncpy((char *)phys_path, &pcibus_list[i][0], 269*fcf3ce44SJohn Forte strlen(&pcibus_list[i][0])); 270*fcf3ce44SJohn Forte if (fflag && (strstr((char *)bootpath, 271*fcf3ce44SJohn Forte strtok((char *)phys_path, ":")) != NULL)) { 272*fcf3ce44SJohn Forte (void) fprintf(stderr, 273*fcf3ce44SJohn Forte MSGSTR(21005, "Ignoring %s (bootpath)\n"), 274*fcf3ce44SJohn Forte &pcibus_list[i][0]); 275*fcf3ce44SJohn Forte continue; 276*fcf3ce44SJohn Forte } 277*fcf3ce44SJohn Forte 278*fcf3ce44SJohn Forte (void) fprintf(stdout, 279*fcf3ce44SJohn Forte MSGSTR(21006, "\n Opening Device: %s\n"), &pcibus_list[i][0]); 280*fcf3ce44SJohn Forte /* Check if the device is valid */ 281*fcf3ce44SJohn Forte if ((fd = open(&pcibus_list[i][0], O_RDWR)) < 0) { 282*fcf3ce44SJohn Forte (void) fprintf(stderr, 283*fcf3ce44SJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), 284*fcf3ce44SJohn Forte &pcibus_list[i][0]); 285*fcf3ce44SJohn Forte retval++; 286*fcf3ce44SJohn Forte continue; 287*fcf3ce44SJohn Forte } 288*fcf3ce44SJohn Forte (void) close(fd); 289*fcf3ce44SJohn Forte /* 290*fcf3ce44SJohn Forte * Check FCode version present on the adapter (at last boot) 291*fcf3ce44SJohn Forte */ 292*fcf3ce44SJohn Forte if (q_findversion(verbose, i, (uchar_t *)&version[0], 293*fcf3ce44SJohn Forte &chip_id) == 0) { 294*fcf3ce44SJohn Forte if (strlen((char *)version) == 0) { 295*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21007, 296*fcf3ce44SJohn Forte " Detected FCode Version:\tNo version available for this FCode\n")); 297*fcf3ce44SJohn Forte } else { 298*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21008, 299*fcf3ce44SJohn Forte " Detected FCode Version:\t%s\n"), version); 300*fcf3ce44SJohn Forte } 301*fcf3ce44SJohn Forte } else { 302*fcf3ce44SJohn Forte chip_id = 0x0; 303*fcf3ce44SJohn Forte } 304*fcf3ce44SJohn Forte 305*fcf3ce44SJohn Forte if (fflag) { 306*fcf3ce44SJohn Forte /* 307*fcf3ce44SJohn Forte * For ISP2200, Sbus HBA, do just 1 download 308*fcf3ce44SJohn Forte * for both the ports (dual port HBA) 309*fcf3ce44SJohn Forte * Here it is assumed that readdir() always 310*fcf3ce44SJohn Forte * returns the paths in pcibus_list[] in the 311*fcf3ce44SJohn Forte * sorted order. 312*fcf3ce44SJohn Forte */ 313*fcf3ce44SJohn Forte (void) strcpy(tmppath, pcibus_list[i]); 314*fcf3ce44SJohn Forte if (ptr1 = strstr(tmppath, IVORY_BUS)) { 315*fcf3ce44SJohn Forte if (ptr2 = strstr(ptr1, IVORY_DRVR)) { 316*fcf3ce44SJohn Forte ptr2 = strchr(ptr2, ','); 317*fcf3ce44SJohn Forte if (ptr2 = strchr(++ptr2, ',')) { 318*fcf3ce44SJohn Forte *ptr2 = '\0'; 319*fcf3ce44SJohn Forte } 320*fcf3ce44SJohn Forte } 321*fcf3ce44SJohn Forte (void) strcpy(port2, ptr1); 322*fcf3ce44SJohn Forte if (strcmp(port1, port2) == 0) { 323*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21037, 324*fcf3ce44SJohn Forte "/n New FCode has already been downloaded " 325*fcf3ce44SJohn Forte "to this ISP2200 SBus HBA Card.\n" 326*fcf3ce44SJohn Forte "It is sufficient to download to one " 327*fcf3ce44SJohn Forte "port of the ISP2200 SBus HBA Card. " 328*fcf3ce44SJohn Forte "Moving on...\n")); 329*fcf3ce44SJohn Forte continue; 330*fcf3ce44SJohn Forte } 331*fcf3ce44SJohn Forte } 332*fcf3ce44SJohn Forte /* 333*fcf3ce44SJohn Forte * Check version of the supplied FCode file (once) 334*fcf3ce44SJohn Forte */ 335*fcf3ce44SJohn Forte if ((file_id != 0 && version_file != NULL) || 336*fcf3ce44SJohn Forte (q_findfileversion((char *) 337*fcf3ce44SJohn Forte &fcode_buf[0], (uchar_t *)&version_file[0], 338*fcf3ce44SJohn Forte &file_id, isSbus, &sbus_off) == 0)) { 339*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21009, 340*fcf3ce44SJohn Forte " New FCode Version:\t\t%s\n"), 341*fcf3ce44SJohn Forte version_file); 342*fcf3ce44SJohn Forte } else { 343*fcf3ce44SJohn Forte (void) close(fcode_fd); 344*fcf3ce44SJohn Forte return (1); 345*fcf3ce44SJohn Forte } 346*fcf3ce44SJohn Forte 347*fcf3ce44SJohn Forte /* 348*fcf3ce44SJohn Forte * Load the New FCode 349*fcf3ce44SJohn Forte * Give warning if file doesn't appear to be correct 350*fcf3ce44SJohn Forte * 351*fcf3ce44SJohn Forte */ 352*fcf3ce44SJohn Forte if (chip_id == 0) { 353*fcf3ce44SJohn Forte errnum = 2; /* can't get chip_id */ 354*fcf3ce44SJohn Forte retval++; 355*fcf3ce44SJohn Forte } else if (chip_id - file_id != 0) { 356*fcf3ce44SJohn Forte errnum = 3; /* file/card mismatch */ 357*fcf3ce44SJohn Forte retval++; 358*fcf3ce44SJohn Forte } else { 359*fcf3ce44SJohn Forte errnum = 0; /* everything is ok */ 360*fcf3ce44SJohn Forte } 361*fcf3ce44SJohn Forte 362*fcf3ce44SJohn Forte if (!q_warn(errnum)) { 363*fcf3ce44SJohn Forte /* Disable user-interrupt Control-C */ 364*fcf3ce44SJohn Forte sigint = 365*fcf3ce44SJohn Forte (void (*)(int)) signal(SIGINT, SIG_IGN); 366*fcf3ce44SJohn Forte 367*fcf3ce44SJohn Forte /* Load FCode */ 368*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21010, 369*fcf3ce44SJohn Forte " Loading FCode: %s\n"), file); 370*fcf3ce44SJohn Forte 371*fcf3ce44SJohn Forte if (q_load_file(fcode_fd, 372*fcf3ce44SJohn Forte &pcibus_list[i][0]) == 0) { 373*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21011, 374*fcf3ce44SJohn Forte " Successful FCode download: %s\n"), 375*fcf3ce44SJohn Forte &pcibus_list[i][0]); 376*fcf3ce44SJohn Forte (void) strcpy(port1, port2); 377*fcf3ce44SJohn Forte } else { 378*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21012, 379*fcf3ce44SJohn Forte "Error: FCode download failed: %s\n"), 380*fcf3ce44SJohn Forte &pcibus_list[i][0]); 381*fcf3ce44SJohn Forte retval++; 382*fcf3ce44SJohn Forte } 383*fcf3ce44SJohn Forte /* Restore SIGINT (user interrupt) setting */ 384*fcf3ce44SJohn Forte (void) signal(SIGINT, sigint); 385*fcf3ce44SJohn Forte } 386*fcf3ce44SJohn Forte } 387*fcf3ce44SJohn Forte } 388*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 389*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n")); 390*fcf3ce44SJohn Forte if (fcode_fd != -1) 391*fcf3ce44SJohn Forte (void) close(fcode_fd); 392*fcf3ce44SJohn Forte return (retval); 393*fcf3ce44SJohn Forte } 394*fcf3ce44SJohn Forte 395*fcf3ce44SJohn Forte 396*fcf3ce44SJohn Forte /* 397*fcf3ce44SJohn Forte * Retrieve the version banner from the card 398*fcf3ce44SJohn Forte * uses ioctl: FCIO_FCODE_MCODE_VERSION FCode revision 399*fcf3ce44SJohn Forte */ 400*fcf3ce44SJohn Forte static int 401*fcf3ce44SJohn Forte q_findversion(int verbose, int index, uchar_t *version, uint16_t *chip_id) 402*fcf3ce44SJohn Forte /*ARGSUSED*/ 403*fcf3ce44SJohn Forte { 404*fcf3ce44SJohn Forte int fd, ntries; 405*fcf3ce44SJohn Forte struct ifp_fm_version *version_buffer = NULL; 406*fcf3ce44SJohn Forte char prom_ver[100] = {NULL}; 407*fcf3ce44SJohn Forte char mcode_ver[100] = {NULL}; 408*fcf3ce44SJohn Forte fcio_t fcio; 409*fcf3ce44SJohn Forte 410*fcf3ce44SJohn Forte if (strstr(&pcibus_list[index][0], fc_trans)) { 411*fcf3ce44SJohn Forte 412*fcf3ce44SJohn Forte if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) { 413*fcf3ce44SJohn Forte (void) fprintf(stderr, 414*fcf3ce44SJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), 415*fcf3ce44SJohn Forte &pcibus_list[index][0]); 416*fcf3ce44SJohn Forte return (1); 417*fcf3ce44SJohn Forte } 418*fcf3ce44SJohn Forte 419*fcf3ce44SJohn Forte if ((version_buffer = (struct ifp_fm_version *)malloc( 420*fcf3ce44SJohn Forte sizeof (struct ifp_fm_version))) == NULL) { 421*fcf3ce44SJohn Forte (void) fprintf(stderr, 422*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 423*fcf3ce44SJohn Forte (void) close(fd); 424*fcf3ce44SJohn Forte return (1); 425*fcf3ce44SJohn Forte } 426*fcf3ce44SJohn Forte 427*fcf3ce44SJohn Forte version_buffer->fcode_ver = (char *)version; 428*fcf3ce44SJohn Forte version_buffer->mcode_ver = mcode_ver; 429*fcf3ce44SJohn Forte version_buffer->prom_ver = prom_ver; 430*fcf3ce44SJohn Forte version_buffer->fcode_ver_len = MAXNAMELEN - 1; 431*fcf3ce44SJohn Forte version_buffer->mcode_ver_len = 100; 432*fcf3ce44SJohn Forte version_buffer->prom_ver_len = 100; 433*fcf3ce44SJohn Forte 434*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, version_buffer) < 0) { 435*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21014, 436*fcf3ce44SJohn Forte "Error: Driver interface FCIO_FCODE_MCODE_VERSION failed\n")); 437*fcf3ce44SJohn Forte free(version_buffer); 438*fcf3ce44SJohn Forte (void) close(fd); 439*fcf3ce44SJohn Forte return (1); 440*fcf3ce44SJohn Forte } 441*fcf3ce44SJohn Forte version[version_buffer->fcode_ver_len] = '\0'; 442*fcf3ce44SJohn Forte 443*fcf3ce44SJohn Forte /* Need a way to get card MCODE (firmware) to track certain HW bugs */ 444*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 445*fcf3ce44SJohn Forte (void) fprintf(stdout, " Device %i: QLGC chip_id %x\n", 446*fcf3ce44SJohn Forte index+1, *chip_id); 447*fcf3ce44SJohn Forte (void) fprintf(stdout, " FCode:%s\n MCODE:%s\n PROM:%s\n", 448*fcf3ce44SJohn Forte (char *)version, mcode_ver, prom_ver); 449*fcf3ce44SJohn Forte } 450*fcf3ce44SJohn Forte free(version_buffer); 451*fcf3ce44SJohn Forte 452*fcf3ce44SJohn Forte } else if (strstr(&pcibus_list[index][0], fp_trans)) { 453*fcf3ce44SJohn Forte /* 454*fcf3ce44SJohn Forte * Get the fcode and prom's fw version 455*fcf3ce44SJohn Forte * using the fp ioctls. Currently, we pass 456*fcf3ce44SJohn Forte * only the fcode version to the calling function 457*fcf3ce44SJohn Forte * and ignore the FW version (using the existing 458*fcf3ce44SJohn Forte * implementation). 459*fcf3ce44SJohn Forte */ 460*fcf3ce44SJohn Forte 461*fcf3ce44SJohn Forte if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) { 462*fcf3ce44SJohn Forte (void) fprintf(stderr, 463*fcf3ce44SJohn Forte MSGSTR(4511, "Could not open %s\n"), 464*fcf3ce44SJohn Forte &pcibus_list[index][0]); 465*fcf3ce44SJohn Forte (void) close(fd); 466*fcf3ce44SJohn Forte return (1); 467*fcf3ce44SJohn Forte } 468*fcf3ce44SJohn Forte /* Get the fcode version */ 469*fcf3ce44SJohn Forte bzero(version, sizeof (version)); 470*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_FCODE_REV; 471*fcf3ce44SJohn Forte /* Information read operation */ 472*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 473*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)version; 474*fcf3ce44SJohn Forte fcio.fcio_olen = MAXNAMELEN; 475*fcf3ce44SJohn Forte 476*fcf3ce44SJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) { 477*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 478*fcf3ce44SJohn Forte if ((errno == EAGAIN) && 479*fcf3ce44SJohn Forte (ntries+1 < MAX_RETRIES)) { 480*fcf3ce44SJohn Forte /* wait 30 secs */ 481*fcf3ce44SJohn Forte (void) sleep(MAX_WAIT_TIME); 482*fcf3ce44SJohn Forte continue; 483*fcf3ce44SJohn Forte } 484*fcf3ce44SJohn Forte (void) close(fd); 485*fcf3ce44SJohn Forte return (L_FCIO_GET_FCODE_REV_FAIL); 486*fcf3ce44SJohn Forte } 487*fcf3ce44SJohn Forte break; 488*fcf3ce44SJohn Forte } 489*fcf3ce44SJohn Forte version[MAXNAMELEN-1] = '\0'; 490*fcf3ce44SJohn Forte } 491*fcf3ce44SJohn Forte 492*fcf3ce44SJohn Forte /* Get type of card from product name in FCode version banner */ 493*fcf3ce44SJohn Forte if (strstr((char *)version, qlgc2100)) { 494*fcf3ce44SJohn Forte *chip_id = 0x2100; 495*fcf3ce44SJohn Forte } else if (strstr((char *)version, qlgc2200)) { 496*fcf3ce44SJohn Forte *chip_id = 0x2200; 497*fcf3ce44SJohn Forte if (strstr((char *)version, "Sbus")) { 498*fcf3ce44SJohn Forte *chip_id = SBUS_CHIP_ID; 499*fcf3ce44SJohn Forte } 500*fcf3ce44SJohn Forte } else if (strstr((char *)version, qlgc2300)) { 501*fcf3ce44SJohn Forte *chip_id = 0x2300; 502*fcf3ce44SJohn Forte } else if (strstr((char *)version, qlgc2312)) { 503*fcf3ce44SJohn Forte *chip_id = 0x2312; 504*fcf3ce44SJohn Forte } else { 505*fcf3ce44SJohn Forte *chip_id = 0x0; 506*fcf3ce44SJohn Forte } 507*fcf3ce44SJohn Forte 508*fcf3ce44SJohn Forte (void) close(fd); 509*fcf3ce44SJohn Forte return (0); 510*fcf3ce44SJohn Forte } 511*fcf3ce44SJohn Forte 512*fcf3ce44SJohn Forte /* 513*fcf3ce44SJohn Forte * Retrieve the version banner and file type (2100 or 2200) from the file 514*fcf3ce44SJohn Forte */ 515*fcf3ce44SJohn Forte static int 516*fcf3ce44SJohn Forte q_findfileversion(char *dl_fcode, uchar_t *version_file, uint16_t *file_id, 517*fcf3ce44SJohn Forte int isSbus, int *sbus_offset) 518*fcf3ce44SJohn Forte { 519*fcf3ce44SJohn Forte int mark; 520*fcf3ce44SJohn Forte int qlc_offset = 0; 521*fcf3ce44SJohn Forte char temp[4] = {NULL}; 522*fcf3ce44SJohn Forte 523*fcf3ce44SJohn Forte 524*fcf3ce44SJohn Forte /* 525*fcf3ce44SJohn Forte * Get file version from FCode for 2100 or 2202 526*fcf3ce44SJohn Forte */ 527*fcf3ce44SJohn Forte if (isSbus) { 528*fcf3ce44SJohn Forte *file_id = SBUS_CHIP_ID; 529*fcf3ce44SJohn Forte } else { 530*fcf3ce44SJohn Forte if ((dl_fcode[0x23] == 0x22) || 531*fcf3ce44SJohn Forte (dl_fcode[0x23] == 0x23)) { 532*fcf3ce44SJohn Forte *file_id = dl_fcode[0x22] & 0xff; 533*fcf3ce44SJohn Forte *file_id |= (dl_fcode[0x23] << 8) & 0xff00; 534*fcf3ce44SJohn Forte } else { 535*fcf3ce44SJohn Forte *file_id = dl_fcode[0x42] & 0xff; 536*fcf3ce44SJohn Forte *file_id |= (dl_fcode[0x43] << 8) & 0xff00; 537*fcf3ce44SJohn Forte } 538*fcf3ce44SJohn Forte } 539*fcf3ce44SJohn Forte 540*fcf3ce44SJohn Forte /* 541*fcf3ce44SJohn Forte * Ok, we're just checking for 2200 here. If it is we need 542*fcf3ce44SJohn Forte * to offset to find the banner. 543*fcf3ce44SJohn Forte */ 544*fcf3ce44SJohn Forte if ((*file_id == 0x2200) || 545*fcf3ce44SJohn Forte (*file_id == 0x2300) || 546*fcf3ce44SJohn Forte (*file_id == 0x2312)) { 547*fcf3ce44SJohn Forte qlc_offset = -32; 548*fcf3ce44SJohn Forte } 549*fcf3ce44SJohn Forte 550*fcf3ce44SJohn Forte /* 551*fcf3ce44SJohn Forte * If this is an ISP2200 Sbus Fcode file, then search for the string 552*fcf3ce44SJohn Forte * "ISP2200 FC-AL Host Adapter Driver" in the whole fcode file 553*fcf3ce44SJohn Forte */ 554*fcf3ce44SJohn Forte if (isSbus) { 555*fcf3ce44SJohn Forte *file_id = SBUS_CHIP_ID; 556*fcf3ce44SJohn Forte qlc_offset = *sbus_offset; 557*fcf3ce44SJohn Forte /* Subtract 111 from the offset we add below for PCI Fcodes */ 558*fcf3ce44SJohn Forte qlc_offset -= 111; 559*fcf3ce44SJohn Forte } 560*fcf3ce44SJohn Forte 561*fcf3ce44SJohn Forte /* Banner length varies; grab banner to end of date marker yr/mo/da */ 562*fcf3ce44SJohn Forte version_file[0] = '\0'; 563*fcf3ce44SJohn Forte for (mark = (111 + qlc_offset); mark < (191 + qlc_offset); mark++) { 564*fcf3ce44SJohn Forte (void) strncpy(temp, (char *)&dl_fcode[mark], 4); 565*fcf3ce44SJohn Forte if ((strncmp(&temp[0], "/", 1) == 0) && 566*fcf3ce44SJohn Forte (strncmp(&temp[3], "/", 1) == 0)) { 567*fcf3ce44SJohn Forte (void) strncat((char *)version_file, 568*fcf3ce44SJohn Forte (char *)&dl_fcode[mark], 6); 569*fcf3ce44SJohn Forte break; 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte (void) strncat((char *)version_file, temp, 1); 572*fcf3ce44SJohn Forte } 573*fcf3ce44SJohn Forte return (0); 574*fcf3ce44SJohn Forte } 575*fcf3ce44SJohn Forte 576*fcf3ce44SJohn Forte /* 577*fcf3ce44SJohn Forte * Find if the FCode file is a ISP2200 SBUS Fcode file 578*fcf3ce44SJohn Forte */ 579*fcf3ce44SJohn Forte static int 580*fcf3ce44SJohn Forte q_findSbusfile(int fd, int *sbus_offset) 581*fcf3ce44SJohn Forte { 582*fcf3ce44SJohn Forte static int file_size; 583*fcf3ce44SJohn Forte char *sbus_info; 584*fcf3ce44SJohn Forte struct stat statinfo; 585*fcf3ce44SJohn Forte 586*fcf3ce44SJohn Forte if (lseek(fd, 0, SEEK_SET) == -1) { 587*fcf3ce44SJohn Forte perror(MSGSTR(21022, "seek")); 588*fcf3ce44SJohn Forte return (-1); 589*fcf3ce44SJohn Forte } 590*fcf3ce44SJohn Forte if (fstat(fd, &statinfo)) { 591*fcf3ce44SJohn Forte perror(MSGSTR(21023, "fstat")); 592*fcf3ce44SJohn Forte return (-1); 593*fcf3ce44SJohn Forte } 594*fcf3ce44SJohn Forte file_size = statinfo.st_size; 595*fcf3ce44SJohn Forte 596*fcf3ce44SJohn Forte if ((sbus_info = (char *)malloc(file_size)) == NULL) { 597*fcf3ce44SJohn Forte (void) fprintf(stderr, 598*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 599*fcf3ce44SJohn Forte return (-1); 600*fcf3ce44SJohn Forte } 601*fcf3ce44SJohn Forte 602*fcf3ce44SJohn Forte if (read(fd, sbus_info, file_size) < 0) { 603*fcf3ce44SJohn Forte perror(MSGSTR(21001, "read")); 604*fcf3ce44SJohn Forte free(sbus_info); 605*fcf3ce44SJohn Forte return (-1); 606*fcf3ce44SJohn Forte } 607*fcf3ce44SJohn Forte 608*fcf3ce44SJohn Forte /* 609*fcf3ce44SJohn Forte * Search for the version string in the whole file 610*fcf3ce44SJohn Forte */ 611*fcf3ce44SJohn Forte if ((*sbus_offset = memstrstr((char *)sbus_info, qlgc2200Sbus, 612*fcf3ce44SJohn Forte file_size, strlen(qlgc2200Sbus))) != -1) { 613*fcf3ce44SJohn Forte free(sbus_info); 614*fcf3ce44SJohn Forte return (1); 615*fcf3ce44SJohn Forte } else { 616*fcf3ce44SJohn Forte free(sbus_info); 617*fcf3ce44SJohn Forte return (0); 618*fcf3ce44SJohn Forte } 619*fcf3ce44SJohn Forte } 620*fcf3ce44SJohn Forte 621*fcf3ce44SJohn Forte 622*fcf3ce44SJohn Forte /* 623*fcf3ce44SJohn Forte * Build a list of all the devctl entries for all the 2100/2200 based adapters 624*fcf3ce44SJohn Forte */ 625*fcf3ce44SJohn Forte static int 626*fcf3ce44SJohn Forte q_getdevctlpath(char *devpath, int *devcnt) 627*fcf3ce44SJohn Forte { 628*fcf3ce44SJohn Forte struct stat statbuf; 629*fcf3ce44SJohn Forte struct dirent *dirp = NULL; 630*fcf3ce44SJohn Forte DIR *dp = NULL; 631*fcf3ce44SJohn Forte char *ptr = NULL; 632*fcf3ce44SJohn Forte int err; 633*fcf3ce44SJohn Forte int testopen; 634*fcf3ce44SJohn Forte 635*fcf3ce44SJohn Forte if (lstat(devpath, &statbuf) < 0) { 636*fcf3ce44SJohn Forte (void) fprintf(stderr, 637*fcf3ce44SJohn Forte MSGSTR(21016, "Error: %s lstat() error\n"), devpath); 638*fcf3ce44SJohn Forte return (1); 639*fcf3ce44SJohn Forte } 640*fcf3ce44SJohn Forte 641*fcf3ce44SJohn Forte if ((strstr(devpath, fc_trans) || 642*fcf3ce44SJohn Forte (strstr(devpath, fp_trans_id) && strstr(devpath, fp_trans))) && 643*fcf3ce44SJohn Forte strstr(devpath, "devctl")) { 644*fcf3ce44SJohn Forte /* Verify the path is valid */ 645*fcf3ce44SJohn Forte if ((testopen = open(devpath, O_RDONLY)) >= 0) { 646*fcf3ce44SJohn Forte (void) close(testopen); 647*fcf3ce44SJohn Forte (void) strcpy(pcibus_list[*devcnt], devpath); 648*fcf3ce44SJohn Forte *devcnt += 1; 649*fcf3ce44SJohn Forte return (0); 650*fcf3ce44SJohn Forte } 651*fcf3ce44SJohn Forte } 652*fcf3ce44SJohn Forte 653*fcf3ce44SJohn Forte if (S_ISDIR(statbuf.st_mode) == 0) { 654*fcf3ce44SJohn Forte /* 655*fcf3ce44SJohn Forte * not a directory so 656*fcf3ce44SJohn Forte * we don't care about it - return 657*fcf3ce44SJohn Forte */ 658*fcf3ce44SJohn Forte return (0); 659*fcf3ce44SJohn Forte } 660*fcf3ce44SJohn Forte 661*fcf3ce44SJohn Forte /* 662*fcf3ce44SJohn Forte * It's a directory. Call ourself to 663*fcf3ce44SJohn Forte * traverse the path(s) 664*fcf3ce44SJohn Forte */ 665*fcf3ce44SJohn Forte ptr = devpath + strlen(devpath); 666*fcf3ce44SJohn Forte *ptr++ = '/'; 667*fcf3ce44SJohn Forte *ptr = 0; 668*fcf3ce44SJohn Forte 669*fcf3ce44SJohn Forte /* Forget the /devices/pseudo/ directory */ 670*fcf3ce44SJohn Forte if (strcmp(devpath, "/devices/pseudo/") == 0) { 671*fcf3ce44SJohn Forte return (0); 672*fcf3ce44SJohn Forte } 673*fcf3ce44SJohn Forte 674*fcf3ce44SJohn Forte if ((dp = opendir(devpath)) == NULL) { 675*fcf3ce44SJohn Forte (void) fprintf(stderr, 676*fcf3ce44SJohn Forte MSGSTR(21017, "Error: %s Can't read directory\n"), devpath); 677*fcf3ce44SJohn Forte return (1); 678*fcf3ce44SJohn Forte } 679*fcf3ce44SJohn Forte 680*fcf3ce44SJohn Forte while ((dirp = readdir(dp)) != NULL) { 681*fcf3ce44SJohn Forte 682*fcf3ce44SJohn Forte if (strcmp(dirp->d_name, ".") == 0 || 683*fcf3ce44SJohn Forte strcmp(dirp->d_name, "..") == 0) { 684*fcf3ce44SJohn Forte continue; 685*fcf3ce44SJohn Forte } 686*fcf3ce44SJohn Forte (void) strcpy(ptr, dirp->d_name); /* append name */ 687*fcf3ce44SJohn Forte err = q_getdevctlpath(devpath, devcnt); 688*fcf3ce44SJohn Forte } 689*fcf3ce44SJohn Forte 690*fcf3ce44SJohn Forte if (closedir(dp) < 0) { 691*fcf3ce44SJohn Forte (void) fprintf(stderr, 692*fcf3ce44SJohn Forte MSGSTR(21018, "Error: Can't close directory %s\n"), devpath); 693*fcf3ce44SJohn Forte return (1); 694*fcf3ce44SJohn Forte } 695*fcf3ce44SJohn Forte return (err); 696*fcf3ce44SJohn Forte } 697*fcf3ce44SJohn Forte 698*fcf3ce44SJohn Forte /* 699*fcf3ce44SJohn Forte * Get the boot device. Cannot load FCode to current boot device. 700*fcf3ce44SJohn Forte * Boot devices under volume management will prompt a warning. 701*fcf3ce44SJohn Forte */ 702*fcf3ce44SJohn Forte static int 703*fcf3ce44SJohn Forte q_getbootdev(uchar_t *bootpath) 704*fcf3ce44SJohn Forte { 705*fcf3ce44SJohn Forte struct mnttab mp; 706*fcf3ce44SJohn Forte struct mnttab mpref; 707*fcf3ce44SJohn Forte FILE *fp = NULL; 708*fcf3ce44SJohn Forte static char buf[BUFSIZ]; 709*fcf3ce44SJohn Forte char *p = NULL, *p1 = NULL; /* p = full device, p1 = chunk to rm */ 710*fcf3ce44SJohn Forte char *slot = ":devctl"; 711*fcf3ce44SJohn Forte char *root = "/"; 712*fcf3ce44SJohn Forte 713*fcf3ce44SJohn Forte if ((fp = fopen(MNTTAB, "r")) == NULL) { 714*fcf3ce44SJohn Forte (void) fprintf(stderr, 715*fcf3ce44SJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), MNTTAB); 716*fcf3ce44SJohn Forte return (1); 717*fcf3ce44SJohn Forte } 718*fcf3ce44SJohn Forte 719*fcf3ce44SJohn Forte mntnull(&mpref); 720*fcf3ce44SJohn Forte mpref.mnt_mountp = (char *)root; 721*fcf3ce44SJohn Forte 722*fcf3ce44SJohn Forte if (getmntany(fp, &mp, &mpref) != 0 || 723*fcf3ce44SJohn Forte mpref.mnt_mountp == NULL) { 724*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21019, 725*fcf3ce44SJohn Forte "Error: Cannot get boot device, check %s.\n"), MNTTAB); 726*fcf3ce44SJohn Forte (void) fclose(fp); 727*fcf3ce44SJohn Forte return (1); 728*fcf3ce44SJohn Forte } 729*fcf3ce44SJohn Forte (void) fclose(fp); 730*fcf3ce44SJohn Forte 731*fcf3ce44SJohn Forte /* 732*fcf3ce44SJohn Forte * If we can't get a link, we may be dealing with a volume mgr 733*fcf3ce44SJohn Forte * so give a warning. If a colon is present, we likely have a 734*fcf3ce44SJohn Forte * non-local disk or cd-rom, so no warning is necessary. 735*fcf3ce44SJohn Forte * e.g. /devices/pci@1f,4000/scsi@3/sd@6,0:b (cdrom, no link) or 736*fcf3ce44SJohn Forte * storage-e4:/blah/blah remote boot server 737*fcf3ce44SJohn Forte */ 738*fcf3ce44SJohn Forte if (readlink(mp.mnt_special, buf, BUFSIZ) < 0) { 739*fcf3ce44SJohn Forte if (strstr(mp.mnt_special, ":") == NULL) { 740*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21020, 741*fcf3ce44SJohn Forte "\nWarning: Cannot read boot device link, check %s.\n"), MNTTAB); 742*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21021, 743*fcf3ce44SJohn Forte "Do not upgrade FCode on adapters controlling the boot device.\n")); 744*fcf3ce44SJohn Forte } 745*fcf3ce44SJohn Forte return (1); 746*fcf3ce44SJohn Forte } 747*fcf3ce44SJohn Forte /* 748*fcf3ce44SJohn Forte * Copy boot device path to bootpath. First remove leading 749*fcf3ce44SJohn Forte * path junk (../../..) then if it's an ifp device, chop off 750*fcf3ce44SJohn Forte * the disk and add the devctl to the end of the path. 751*fcf3ce44SJohn Forte */ 752*fcf3ce44SJohn Forte if (p = strstr(buf, "/devices")) { 753*fcf3ce44SJohn Forte if (strstr(buf, fc_trans) != NULL) { 754*fcf3ce44SJohn Forte p1 = strrchr(p, '/'); 755*fcf3ce44SJohn Forte *p1 = '\0'; 756*fcf3ce44SJohn Forte } 757*fcf3ce44SJohn Forte } 758*fcf3ce44SJohn Forte (void) strcpy((char *)bootpath, (char *)p); 759*fcf3ce44SJohn Forte if (p1) { 760*fcf3ce44SJohn Forte (void) strcat((char *)bootpath, slot); 761*fcf3ce44SJohn Forte } 762*fcf3ce44SJohn Forte return (0); 763*fcf3ce44SJohn Forte } 764*fcf3ce44SJohn Forte 765*fcf3ce44SJohn Forte /* 766*fcf3ce44SJohn Forte * Load FCode to card. 767*fcf3ce44SJohn Forte * uses ioctl: IFPIO_FCODE_DOWNLOAD 768*fcf3ce44SJohn Forte */ 769*fcf3ce44SJohn Forte static int 770*fcf3ce44SJohn Forte q_load_file(int fcode_fd, char *device) 771*fcf3ce44SJohn Forte { 772*fcf3ce44SJohn Forte static int dev_fd, fcode_size; 773*fcf3ce44SJohn Forte struct stat stat; 774*fcf3ce44SJohn Forte ifp_download_t *download_p = NULL; 775*fcf3ce44SJohn Forte fcio_t fcio; 776*fcf3ce44SJohn Forte uint16_t file_id = 0; 777*fcf3ce44SJohn Forte uchar_t *bin; 778*fcf3ce44SJohn Forte 779*fcf3ce44SJohn Forte if (lseek(fcode_fd, 0, SEEK_SET) == -1) { 780*fcf3ce44SJohn Forte perror(MSGSTR(21022, "seek")); 781*fcf3ce44SJohn Forte (void) close(fcode_fd); 782*fcf3ce44SJohn Forte return (1); 783*fcf3ce44SJohn Forte } 784*fcf3ce44SJohn Forte if (fstat(fcode_fd, &stat) == -1) { 785*fcf3ce44SJohn Forte perror(MSGSTR(21023, "fstat")); 786*fcf3ce44SJohn Forte (void) close(fcode_fd); 787*fcf3ce44SJohn Forte return (1); 788*fcf3ce44SJohn Forte } 789*fcf3ce44SJohn Forte 790*fcf3ce44SJohn Forte fcode_size = stat.st_size; 791*fcf3ce44SJohn Forte 792*fcf3ce44SJohn Forte if (strstr(device, fc_trans)) { 793*fcf3ce44SJohn Forte if ((download_p = (ifp_download_t *)malloc( 794*fcf3ce44SJohn Forte sizeof (ifp_download_t) + fcode_size)) == NULL) { 795*fcf3ce44SJohn Forte (void) fprintf(stderr, 796*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 797*fcf3ce44SJohn Forte (void) close(fcode_fd); 798*fcf3ce44SJohn Forte return (1); 799*fcf3ce44SJohn Forte } 800*fcf3ce44SJohn Forte } else { 801*fcf3ce44SJohn Forte if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) { 802*fcf3ce44SJohn Forte (void) fprintf(stderr, 803*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 804*fcf3ce44SJohn Forte (void) close(fcode_fd); 805*fcf3ce44SJohn Forte return (1); 806*fcf3ce44SJohn Forte } 807*fcf3ce44SJohn Forte } 808*fcf3ce44SJohn Forte 809*fcf3ce44SJohn Forte if (strstr(device, fc_trans)) { 810*fcf3ce44SJohn Forte if (read(fcode_fd, download_p->dl_fcode, fcode_size) 811*fcf3ce44SJohn Forte != fcode_size) { 812*fcf3ce44SJohn Forte perror(MSGSTR(21001, "read")); 813*fcf3ce44SJohn Forte free(download_p); 814*fcf3ce44SJohn Forte (void) close(fcode_fd); 815*fcf3ce44SJohn Forte return (1); 816*fcf3ce44SJohn Forte } 817*fcf3ce44SJohn Forte } else { 818*fcf3ce44SJohn Forte if (read(fcode_fd, bin, fcode_size) 819*fcf3ce44SJohn Forte != fcode_size) { 820*fcf3ce44SJohn Forte perror(MSGSTR(21001, "read")); 821*fcf3ce44SJohn Forte free(bin); 822*fcf3ce44SJohn Forte (void) close(fcode_fd); 823*fcf3ce44SJohn Forte return (1); 824*fcf3ce44SJohn Forte } 825*fcf3ce44SJohn Forte } 826*fcf3ce44SJohn Forte 827*fcf3ce44SJohn Forte 828*fcf3ce44SJohn Forte if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) { 829*fcf3ce44SJohn Forte (void) fprintf(stderr, 830*fcf3ce44SJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), device); 831*fcf3ce44SJohn Forte free(download_p); 832*fcf3ce44SJohn Forte return (1); 833*fcf3ce44SJohn Forte } 834*fcf3ce44SJohn Forte if (strstr(device, fc_trans)) { 835*fcf3ce44SJohn Forte download_p->dl_fcode_len = fcode_size; 836*fcf3ce44SJohn Forte file_id = download_p->dl_fcode[0x42] & 0xff; 837*fcf3ce44SJohn Forte file_id |= (download_p->dl_fcode[0x43] << 8) & 0xff00; 838*fcf3ce44SJohn Forte download_p->dl_chip_id = file_id; 839*fcf3ce44SJohn Forte if (ioctl(dev_fd, IFPIO_FCODE_DOWNLOAD, download_p) < 0) { 840*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21024, 841*fcf3ce44SJohn Forte "Error: Driver interface IFPIO_FCODE_DOWNLOAD failed\n")); 842*fcf3ce44SJohn Forte free(download_p); 843*fcf3ce44SJohn Forte (void) close(dev_fd); 844*fcf3ce44SJohn Forte return (1); 845*fcf3ce44SJohn Forte } 846*fcf3ce44SJohn Forte free(download_p); 847*fcf3ce44SJohn Forte } else if (strstr(device, fp_trans)) { 848*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE; 849*fcf3ce44SJohn Forte /* Information read operation */ 850*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 851*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)bin; 852*fcf3ce44SJohn Forte fcio.fcio_ilen = fcode_size; 853*fcf3ce44SJohn Forte 854*fcf3ce44SJohn Forte if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) { 855*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21036, 856*fcf3ce44SJohn Forte "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n")); 857*fcf3ce44SJohn Forte free(download_p); 858*fcf3ce44SJohn Forte (void) close(dev_fd); 859*fcf3ce44SJohn Forte return (1); 860*fcf3ce44SJohn Forte } 861*fcf3ce44SJohn Forte free(bin); 862*fcf3ce44SJohn Forte } 863*fcf3ce44SJohn Forte (void) close(dev_fd); 864*fcf3ce44SJohn Forte return (0); 865*fcf3ce44SJohn Forte } 866*fcf3ce44SJohn Forte 867*fcf3ce44SJohn Forte /* 868*fcf3ce44SJohn Forte * Issue warning strings and loop for Yes/No user interaction 869*fcf3ce44SJohn Forte * err# 0 -- we're ok, warn for pending FCode load 870*fcf3ce44SJohn Forte * 1 -- not in single user mode 871*fcf3ce44SJohn Forte * 2 -- can't get chip_id 872*fcf3ce44SJohn Forte * 3 -- card and file do not have same type (2100/2200) 873*fcf3ce44SJohn Forte */ 874*fcf3ce44SJohn Forte static int 875*fcf3ce44SJohn Forte q_warn(int errnum) 876*fcf3ce44SJohn Forte { 877*fcf3ce44SJohn Forte char input[1024]; 878*fcf3ce44SJohn Forte input[0] = '\0'; 879*fcf3ce44SJohn Forte 880*fcf3ce44SJohn Forte if (errnum == 1) { 881*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21025, 882*fcf3ce44SJohn Forte "\nWarning: System is not in single-user mode.\n")); 883*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21026, 884*fcf3ce44SJohn Forte "Loading FCode will reset the adapter and terminate I/O activity\n")); 885*fcf3ce44SJohn Forte } else { 886*fcf3ce44SJohn Forte if (errnum == 2) { 887*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21027, 888*fcf3ce44SJohn Forte " Warning: FCode is missing or existing FCode has" 889*fcf3ce44SJohn Forte " unrecognized version.\n")); 890*fcf3ce44SJohn Forte return (1); 891*fcf3ce44SJohn Forte } else if (errnum == 3) { 892*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21028, 893*fcf3ce44SJohn Forte " Warning: New FCode file version does not match this" 894*fcf3ce44SJohn Forte " board type. Skipping...\n")); 895*fcf3ce44SJohn Forte return (1); 896*fcf3ce44SJohn Forte } 897*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21029, 898*fcf3ce44SJohn Forte "\nWARNING!! This program will update the FCode in this" 899*fcf3ce44SJohn Forte " FC100/PCI, ISP2200/PCI, ISP23xx/PCI " 900*fcf3ce44SJohn Forte " and Emulex devices.\n")); 901*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21030, 902*fcf3ce44SJohn Forte "This may take a few (5) minutes. Please be patient.\n")); 903*fcf3ce44SJohn Forte } 904*fcf3ce44SJohn Forte 905*fcf3ce44SJohn Forte loop1: 906*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21031, 907*fcf3ce44SJohn Forte "Do you wish to continue ? (y/n) ")); 908*fcf3ce44SJohn Forte 909*fcf3ce44SJohn Forte (void) gets(input); 910*fcf3ce44SJohn Forte 911*fcf3ce44SJohn Forte if ((strcmp(input, MSGSTR(21032, "y")) == 0) || 912*fcf3ce44SJohn Forte (strcmp(input, MSGSTR(40, "yes")) == 0)) { 913*fcf3ce44SJohn Forte return (0); 914*fcf3ce44SJohn Forte } else if ((strcmp(input, MSGSTR(21033, "n")) == 0) || 915*fcf3ce44SJohn Forte (strcmp(input, MSGSTR(45, "no")) == 0)) { 916*fcf3ce44SJohn Forte (void) fprintf(stderr, 917*fcf3ce44SJohn Forte MSGSTR(21034, "Not Downloading FCode\n")); 918*fcf3ce44SJohn Forte return (1); 919*fcf3ce44SJohn Forte } else { 920*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21035, "Invalid input\n")); 921*fcf3ce44SJohn Forte goto loop1; 922*fcf3ce44SJohn Forte } 923*fcf3ce44SJohn Forte } 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte /* 926*fcf3ce44SJohn Forte * Name : memstrstr 927*fcf3ce44SJohn Forte * Input : pointer to buf1, pointer to buf2, size of buf1, size of buf2 928*fcf3ce44SJohn Forte * Returns : 929*fcf3ce44SJohn Forte * Offset of the start of contents-of-buf2 in buf1 if it is found 930*fcf3ce44SJohn Forte * -1 if buf1 does not contain contents of buf2 931*fcf3ce44SJohn Forte * Synopsis: 932*fcf3ce44SJohn Forte * This function works similar to strstr(). The difference is that null 933*fcf3ce44SJohn Forte * characters in the buffer are treated like any other character. So, buf1 934*fcf3ce44SJohn Forte * and buf2 can have embedded null characters in them. 935*fcf3ce44SJohn Forte */ 936*fcf3ce44SJohn Forte static int 937*fcf3ce44SJohn Forte memstrstr(char *s1, char *s2, int size1, int size2) 938*fcf3ce44SJohn Forte { 939*fcf3ce44SJohn Forte int count1, count2; 940*fcf3ce44SJohn Forte char *s1_ptr, *s2_ptr; 941*fcf3ce44SJohn Forte 942*fcf3ce44SJohn Forte count1 = size1; count2 = size2; 943*fcf3ce44SJohn Forte s1_ptr = s1; s2_ptr = s2; 944*fcf3ce44SJohn Forte 945*fcf3ce44SJohn Forte if ((size2 == 0)||(size1 == 0)) 946*fcf3ce44SJohn Forte return (-1); 947*fcf3ce44SJohn Forte 948*fcf3ce44SJohn Forte for (count1 = 0; count1 < (size1 - size2 + 1); count1++) { 949*fcf3ce44SJohn Forte if (*s1_ptr++ == *s2_ptr++) { 950*fcf3ce44SJohn Forte if (--count2 == 0) { 951*fcf3ce44SJohn Forte return (count1 - size2 + 1); 952*fcf3ce44SJohn Forte } 953*fcf3ce44SJohn Forte continue; 954*fcf3ce44SJohn Forte } 955*fcf3ce44SJohn Forte count2 = size2; 956*fcf3ce44SJohn Forte s2_ptr = s2; 957*fcf3ce44SJohn Forte } 958*fcf3ce44SJohn Forte 959*fcf3ce44SJohn Forte return (-1); 960*fcf3ce44SJohn Forte } 961*fcf3ce44SJohn Forte 962*fcf3ce44SJohn Forte /* 963*fcf3ce44SJohn Forte * generic fcode load file routine. given a file descriptor to a fcode file 964*fcf3ce44SJohn Forte * this routine will issue the FCIO_DOWNLOAD_FCODE ioctl to the given 965*fcf3ce44SJohn Forte * device. Any ioctl errors will be returned in fcio_errno 966*fcf3ce44SJohn Forte * 967*fcf3ce44SJohn Forte * Arguments: 968*fcf3ce44SJohn Forte * fcode_fd file descriptor to a fcode file 969*fcf3ce44SJohn Forte * device path to the device we will be downloading the fcode onto 970*fcf3ce44SJohn Forte * fcio_errno pointer to an int that will be used to return any errors 971*fcf3ce44SJohn Forte * back to the caller 972*fcf3ce44SJohn Forte * Retrurn Values: 973*fcf3ce44SJohn Forte * 0 successful download 974*fcf3ce44SJohn Forte * >0 otherwise 975*fcf3ce44SJohn Forte */ 976*fcf3ce44SJohn Forte static int 977*fcf3ce44SJohn Forte fcode_load_file(int fcode_fd, char *device, int *fcio_errno) 978*fcf3ce44SJohn Forte { 979*fcf3ce44SJohn Forte 980*fcf3ce44SJohn Forte fcio_t fcio; 981*fcf3ce44SJohn Forte static int dev_fd, fcode_size; 982*fcf3ce44SJohn Forte uchar_t *bin; 983*fcf3ce44SJohn Forte struct stat stat; 984*fcf3ce44SJohn Forte 985*fcf3ce44SJohn Forte if (device == NULL || fcio_errno == NULL) { 986*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 987*fcf3ce44SJohn Forte } 988*fcf3ce44SJohn Forte 989*fcf3ce44SJohn Forte *fcio_errno = 0; 990*fcf3ce44SJohn Forte if (lseek(fcode_fd, 0, SEEK_SET) == -1) { 991*fcf3ce44SJohn Forte perror(MSGSTR(21022, "seek")); 992*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 993*fcf3ce44SJohn Forte } 994*fcf3ce44SJohn Forte 995*fcf3ce44SJohn Forte if (fstat(fcode_fd, &stat) == -1) { 996*fcf3ce44SJohn Forte perror(MSGSTR(21023, "fstat")); 997*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 998*fcf3ce44SJohn Forte } 999*fcf3ce44SJohn Forte 1000*fcf3ce44SJohn Forte fcode_size = stat.st_size; 1001*fcf3ce44SJohn Forte 1002*fcf3ce44SJohn Forte if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) { 1003*fcf3ce44SJohn Forte (void) fprintf(stderr, 1004*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 1005*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 1006*fcf3ce44SJohn Forte } 1007*fcf3ce44SJohn Forte 1008*fcf3ce44SJohn Forte if (read(fcode_fd, bin, fcode_size) 1009*fcf3ce44SJohn Forte != fcode_size) { 1010*fcf3ce44SJohn Forte perror(MSGSTR(21001, "read")); 1011*fcf3ce44SJohn Forte free(bin); 1012*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 1013*fcf3ce44SJohn Forte } 1014*fcf3ce44SJohn Forte 1015*fcf3ce44SJohn Forte if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) { 1016*fcf3ce44SJohn Forte (void) fprintf(stderr, 1017*fcf3ce44SJohn Forte MSGSTR(21122, "Error: Could not open %s, failed " 1018*fcf3ce44SJohn Forte "with errno %d\n"), device, errno); 1019*fcf3ce44SJohn Forte free(bin); 1020*fcf3ce44SJohn Forte return (FCODE_LOAD_FAILURE); 1021*fcf3ce44SJohn Forte } 1022*fcf3ce44SJohn Forte 1023*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE; 1024*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 1025*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)bin; 1026*fcf3ce44SJohn Forte fcio.fcio_ilen = fcode_size; 1027*fcf3ce44SJohn Forte 1028*fcf3ce44SJohn Forte if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) { 1029*fcf3ce44SJohn Forte (void) close(dev_fd); 1030*fcf3ce44SJohn Forte *fcio_errno = fcio.fcio_errno; 1031*fcf3ce44SJohn Forte free(bin); 1032*fcf3ce44SJohn Forte return (FCODE_IOCTL_FAILURE); 1033*fcf3ce44SJohn Forte } 1034*fcf3ce44SJohn Forte 1035*fcf3ce44SJohn Forte free(bin); 1036*fcf3ce44SJohn Forte (void) close(dev_fd); 1037*fcf3ce44SJohn Forte return (FCODE_SUCCESS); 1038*fcf3ce44SJohn Forte } 1039*fcf3ce44SJohn Forte 1040*fcf3ce44SJohn Forte /* 1041*fcf3ce44SJohn Forte * Searches for and updates the fcode for Emulex HBA cards 1042*fcf3ce44SJohn Forte * args: FCode file; if NULL only the current FCode 1043*fcf3ce44SJohn Forte * version is printed 1044*fcf3ce44SJohn Forte */ 1045*fcf3ce44SJohn Forte 1046*fcf3ce44SJohn Forte int 1047*fcf3ce44SJohn Forte emulex_update(char *file) 1048*fcf3ce44SJohn Forte { 1049*fcf3ce44SJohn Forte 1050*fcf3ce44SJohn Forte int fd, retval = 0; 1051*fcf3ce44SJohn Forte int devcnt = 0; 1052*fcf3ce44SJohn Forte uint_t state = 0, fflag = 0; 1053*fcf3ce44SJohn Forte static uchar_t bootpath[PATH_MAX]; 1054*fcf3ce44SJohn Forte int fcode_fd = -1; 1055*fcf3ce44SJohn Forte static struct utmpx *utmpp = NULL; 1056*fcf3ce44SJohn Forte di_node_t root; 1057*fcf3ce44SJohn Forte di_node_t node, sib_node, count_node; 1058*fcf3ce44SJohn Forte di_minor_t minor_node; 1059*fcf3ce44SJohn Forte char phys_path[PATH_MAX], *path; 1060*fcf3ce44SJohn Forte int errnum = 0, fcio_errno = 0; 1061*fcf3ce44SJohn Forte static uchar_t prom_ver_data[MAXNAMELEN]; 1062*fcf3ce44SJohn Forte static char ver_file[EMULEX_FCODE_VERSION_LENGTH]; 1063*fcf3ce44SJohn Forte void (*sigint)(); 1064*fcf3ce44SJohn Forte int prop_entries = -1; 1065*fcf3ce44SJohn Forte int *port_data = NULL; 1066*fcf3ce44SJohn Forte 1067*fcf3ce44SJohn Forte if (file) { 1068*fcf3ce44SJohn Forte /* set the fcode download flag */ 1069*fcf3ce44SJohn Forte fflag++; 1070*fcf3ce44SJohn Forte 1071*fcf3ce44SJohn Forte /* check for a valid file */ 1072*fcf3ce44SJohn Forte if ((fcode_fd = open(file, O_RDONLY)) < 0) { 1073*fcf3ce44SJohn Forte (void) fprintf(stderr, 1074*fcf3ce44SJohn Forte MSGSTR(21118, "Error: Could not open %s, failed " 1075*fcf3ce44SJohn Forte "with errno %d\n"), file, errno); 1076*fcf3ce44SJohn Forte return (1); 1077*fcf3ce44SJohn Forte } 1078*fcf3ce44SJohn Forte 1079*fcf3ce44SJohn Forte /* check for single user mode */ 1080*fcf3ce44SJohn Forte while ((utmpp = getutxent()) != NULL) { 1081*fcf3ce44SJohn Forte if (strstr(utmpp->ut_line, "run-level") && 1082*fcf3ce44SJohn Forte (strcmp(utmpp->ut_line, "run-level S") && 1083*fcf3ce44SJohn Forte strcmp(utmpp->ut_line, "run-level 1"))) { 1084*fcf3ce44SJohn Forte if (q_warn(1)) { 1085*fcf3ce44SJohn Forte (void) endutxent(); 1086*fcf3ce44SJohn Forte (void) close(fcode_fd); 1087*fcf3ce44SJohn Forte return (1); 1088*fcf3ce44SJohn Forte } 1089*fcf3ce44SJohn Forte break; 1090*fcf3ce44SJohn Forte } 1091*fcf3ce44SJohn Forte } 1092*fcf3ce44SJohn Forte (void) endutxent(); 1093*fcf3ce44SJohn Forte 1094*fcf3ce44SJohn Forte /* get bootpath */ 1095*fcf3ce44SJohn Forte if (!q_getbootdev((uchar_t *)&bootpath[0]) && 1096*fcf3ce44SJohn Forte getenv("_LUX_D_DEBUG") != NULL) { 1097*fcf3ce44SJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath); 1098*fcf3ce44SJohn Forte } 1099*fcf3ce44SJohn Forte } 1100*fcf3ce44SJohn Forte 1101*fcf3ce44SJohn Forte /* 1102*fcf3ce44SJohn Forte * Download the Fcode to all the emulex cards found 1103*fcf3ce44SJohn Forte */ 1104*fcf3ce44SJohn Forte 1105*fcf3ce44SJohn Forte /* Create a snapshot of the kernel device tree */ 1106*fcf3ce44SJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 1107*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21114, 1108*fcf3ce44SJohn Forte "Error: Could not get /devices path to " 1109*fcf3ce44SJohn Forte "Emulex Devices.\n")); 1110*fcf3ce44SJohn Forte retval++; 1111*fcf3ce44SJohn Forte } 1112*fcf3ce44SJohn Forte 1113*fcf3ce44SJohn Forte /* point to first node which matches emulex driver */ 1114*fcf3ce44SJohn Forte node = di_drv_first_node("emlxs", root); 1115*fcf3ce44SJohn Forte 1116*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) { 1117*fcf3ce44SJohn Forte /* 1118*fcf3ce44SJohn Forte * Could not find any emulex cards 1119*fcf3ce44SJohn Forte */ 1120*fcf3ce44SJohn Forte (void) di_fini(root); 1121*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21115, 1122*fcf3ce44SJohn Forte "\n Found Path to %d Emulex Devices.\n"), devcnt); 1123*fcf3ce44SJohn Forte retval++; 1124*fcf3ce44SJohn Forte } else { 1125*fcf3ce44SJohn Forte 1126*fcf3ce44SJohn Forte count_node = node; 1127*fcf3ce44SJohn Forte while (count_node != DI_NODE_NIL) { 1128*fcf3ce44SJohn Forte state = di_state(count_node); 1129*fcf3ce44SJohn Forte if ((state & DI_DRIVER_DETACHED) 1130*fcf3ce44SJohn Forte != DI_DRIVER_DETACHED) { 1131*fcf3ce44SJohn Forte devcnt++; 1132*fcf3ce44SJohn Forte } 1133*fcf3ce44SJohn Forte count_node = di_drv_next_node(count_node); 1134*fcf3ce44SJohn Forte } 1135*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21116, 1136*fcf3ce44SJohn Forte "\n Found Path to %d Emulex Devices.\n"), devcnt); 1137*fcf3ce44SJohn Forte } 1138*fcf3ce44SJohn Forte 1139*fcf3ce44SJohn Forte 1140*fcf3ce44SJohn Forte /* 1141*fcf3ce44SJohn Forte * Traverse device tree to find all emulex cards 1142*fcf3ce44SJohn Forte */ 1143*fcf3ce44SJohn Forte while (node != DI_NODE_NIL) { 1144*fcf3ce44SJohn Forte 1145*fcf3ce44SJohn Forte state = di_state(node); 1146*fcf3ce44SJohn Forte if ((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) { 1147*fcf3ce44SJohn Forte node = di_drv_next_node(node); 1148*fcf3ce44SJohn Forte continue; 1149*fcf3ce44SJohn Forte } 1150*fcf3ce44SJohn Forte 1151*fcf3ce44SJohn Forte sib_node = di_child_node(node); 1152*fcf3ce44SJohn Forte while (sib_node != DI_NODE_NIL) { 1153*fcf3ce44SJohn Forte 1154*fcf3ce44SJohn Forte state = di_state(sib_node); 1155*fcf3ce44SJohn Forte if ((state & DI_DRIVER_DETACHED) != 1156*fcf3ce44SJohn Forte DI_DRIVER_DETACHED) { 1157*fcf3ce44SJohn Forte 1158*fcf3ce44SJohn Forte /* Found an attached node */ 1159*fcf3ce44SJohn Forte prop_entries = di_prop_lookup_ints( 1160*fcf3ce44SJohn Forte DDI_DEV_T_ANY, sib_node, 1161*fcf3ce44SJohn Forte "port", &port_data); 1162*fcf3ce44SJohn Forte if (prop_entries != -1) { 1163*fcf3ce44SJohn Forte 1164*fcf3ce44SJohn Forte /* Found a node with "port" property */ 1165*fcf3ce44SJohn Forte minor_node = di_minor_next(sib_node, 1166*fcf3ce44SJohn Forte DI_MINOR_NIL); 1167*fcf3ce44SJohn Forte break; 1168*fcf3ce44SJohn Forte } 1169*fcf3ce44SJohn Forte } 1170*fcf3ce44SJohn Forte sib_node = di_sibling_node(sib_node); 1171*fcf3ce44SJohn Forte } 1172*fcf3ce44SJohn Forte 1173*fcf3ce44SJohn Forte if (sib_node == DI_NODE_NIL) { 1174*fcf3ce44SJohn Forte return (1); 1175*fcf3ce44SJohn Forte } 1176*fcf3ce44SJohn Forte path = di_devfs_path(sib_node); 1177*fcf3ce44SJohn Forte (void) strcpy(phys_path, "/devices"); 1178*fcf3ce44SJohn Forte (void) strncat(phys_path, path, strlen(path)); 1179*fcf3ce44SJohn Forte di_devfs_path_free(path); 1180*fcf3ce44SJohn Forte 1181*fcf3ce44SJohn Forte if (fflag && (strstr((char *)bootpath, 1182*fcf3ce44SJohn Forte (char *)phys_path) != NULL)) { 1183*fcf3ce44SJohn Forte (void) fprintf(stderr, 1184*fcf3ce44SJohn Forte MSGSTR(21117, "Ignoring %s (bootpath)\n"), 1185*fcf3ce44SJohn Forte phys_path); 1186*fcf3ce44SJohn Forte node = di_drv_next_node(node); 1187*fcf3ce44SJohn Forte continue; 1188*fcf3ce44SJohn Forte } 1189*fcf3ce44SJohn Forte 1190*fcf3ce44SJohn Forte if (minor_node) { 1191*fcf3ce44SJohn Forte (void) strncat(phys_path, ":", 1); 1192*fcf3ce44SJohn Forte (void) strncat(phys_path, 1193*fcf3ce44SJohn Forte di_minor_name(minor_node), 1194*fcf3ce44SJohn Forte strlen(di_minor_name(minor_node))); 1195*fcf3ce44SJohn Forte } 1196*fcf3ce44SJohn Forte 1197*fcf3ce44SJohn Forte (void) fprintf(stdout, 1198*fcf3ce44SJohn Forte MSGSTR(21107, "\n Opening Device: %s\n"), 1199*fcf3ce44SJohn Forte phys_path); 1200*fcf3ce44SJohn Forte 1201*fcf3ce44SJohn Forte /* Check if the device is valid */ 1202*fcf3ce44SJohn Forte if ((fd = open(phys_path, O_RDWR)) < 0) { 1203*fcf3ce44SJohn Forte (void) fprintf(stderr, 1204*fcf3ce44SJohn Forte MSGSTR(21121, "Error: Could not open %s, failed " 1205*fcf3ce44SJohn Forte "with errno %d\n"), phys_path, errno); 1206*fcf3ce44SJohn Forte retval++; 1207*fcf3ce44SJohn Forte node = di_drv_next_node(node); 1208*fcf3ce44SJohn Forte continue; 1209*fcf3ce44SJohn Forte } 1210*fcf3ce44SJohn Forte 1211*fcf3ce44SJohn Forte (void) close(fd); 1212*fcf3ce44SJohn Forte 1213*fcf3ce44SJohn Forte /* 1214*fcf3ce44SJohn Forte * Check FCode version present on the adapter 1215*fcf3ce44SJohn Forte * (at last boot) 1216*fcf3ce44SJohn Forte */ 1217*fcf3ce44SJohn Forte memset(prom_ver_data, 0, sizeof (prom_ver_data)); 1218*fcf3ce44SJohn Forte if (emulex_fcodeversion(node, (uchar_t *)&prom_ver_data[0]) 1219*fcf3ce44SJohn Forte == 0) { 1220*fcf3ce44SJohn Forte errnum = 0; 1221*fcf3ce44SJohn Forte if (strlen((char *)prom_ver_data) == 0) { 1222*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21108, 1223*fcf3ce44SJohn Forte " Detected FCode Version:\tNo version available for this FCode\n")); 1224*fcf3ce44SJohn Forte } else { 1225*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21109, 1226*fcf3ce44SJohn Forte " Detected FCode Version:\t%s\n"), 1227*fcf3ce44SJohn Forte prom_ver_data); 1228*fcf3ce44SJohn Forte } 1229*fcf3ce44SJohn Forte } else { 1230*fcf3ce44SJohn Forte errnum = 2; /* can't get prom properties */ 1231*fcf3ce44SJohn Forte retval++; 1232*fcf3ce44SJohn Forte } 1233*fcf3ce44SJohn Forte 1234*fcf3ce44SJohn Forte if (fflag) { 1235*fcf3ce44SJohn Forte 1236*fcf3ce44SJohn Forte memset(ver_file, 0, sizeof (ver_file)); 1237*fcf3ce44SJohn Forte if (emulex_fcode_reader(fcode_fd, "fcode-version", 1238*fcf3ce44SJohn Forte ver_file, sizeof (ver_file)) == 0) { 1239*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21110, 1240*fcf3ce44SJohn Forte " New FCode Version:\t\t%s\n"), 1241*fcf3ce44SJohn Forte ver_file); 1242*fcf3ce44SJohn Forte } else { 1243*fcf3ce44SJohn Forte di_fini(root); 1244*fcf3ce44SJohn Forte (void) close(fcode_fd); 1245*fcf3ce44SJohn Forte return (1); 1246*fcf3ce44SJohn Forte } 1247*fcf3ce44SJohn Forte 1248*fcf3ce44SJohn Forte /* 1249*fcf3ce44SJohn Forte * Load the New FCode 1250*fcf3ce44SJohn Forte * Give warning if file doesn't appear to be correct 1251*fcf3ce44SJohn Forte */ 1252*fcf3ce44SJohn Forte if (!q_warn(errnum)) { 1253*fcf3ce44SJohn Forte /* Disable user-interrupt Control-C */ 1254*fcf3ce44SJohn Forte sigint = 1255*fcf3ce44SJohn Forte (void (*)(int)) signal(SIGINT, SIG_IGN); 1256*fcf3ce44SJohn Forte /* Load FCode */ 1257*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21111, 1258*fcf3ce44SJohn Forte " Loading FCode: %s\n"), file); 1259*fcf3ce44SJohn Forte if (fcode_load_file(fcode_fd, phys_path, 1260*fcf3ce44SJohn Forte &fcio_errno) == FCODE_SUCCESS) { 1261*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(21112, 1262*fcf3ce44SJohn Forte " Successful FCode download: %s\n"), 1263*fcf3ce44SJohn Forte phys_path); 1264*fcf3ce44SJohn Forte } else { 1265*fcf3ce44SJohn Forte handle_emulex_error(fcio_errno, 1266*fcf3ce44SJohn Forte phys_path); 1267*fcf3ce44SJohn Forte retval++; 1268*fcf3ce44SJohn Forte } 1269*fcf3ce44SJohn Forte 1270*fcf3ce44SJohn Forte /* Restore SIGINT (user interrupt) setting */ 1271*fcf3ce44SJohn Forte (void) signal(SIGINT, sigint); 1272*fcf3ce44SJohn Forte } 1273*fcf3ce44SJohn Forte } 1274*fcf3ce44SJohn Forte 1275*fcf3ce44SJohn Forte node = di_drv_next_node(node); 1276*fcf3ce44SJohn Forte } 1277*fcf3ce44SJohn Forte 1278*fcf3ce44SJohn Forte di_fini(root); 1279*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 1280*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n")); 1281*fcf3ce44SJohn Forte if (fcode_fd != -1) 1282*fcf3ce44SJohn Forte (void) close(fcode_fd); 1283*fcf3ce44SJohn Forte return (retval); 1284*fcf3ce44SJohn Forte 1285*fcf3ce44SJohn Forte } 1286*fcf3ce44SJohn Forte 1287*fcf3ce44SJohn Forte /* 1288*fcf3ce44SJohn Forte * Retrieve the version from the card. 1289*fcf3ce44SJohn Forte * uses PROM properties 1290*fcf3ce44SJohn Forte */ 1291*fcf3ce44SJohn Forte static int 1292*fcf3ce44SJohn Forte emulex_fcodeversion(di_node_t node, uchar_t *ver) { 1293*fcf3ce44SJohn Forte di_prom_prop_t promprop; 1294*fcf3ce44SJohn Forte di_prom_handle_t ph; 1295*fcf3ce44SJohn Forte char *promname; 1296*fcf3ce44SJohn Forte uchar_t *ver_data = NULL; 1297*fcf3ce44SJohn Forte int size, found = 0; 1298*fcf3ce44SJohn Forte 1299*fcf3ce44SJohn Forte /* check to make sure ver is not NULL */ 1300*fcf3ce44SJohn Forte if (ver == NULL) { 1301*fcf3ce44SJohn Forte return (1); 1302*fcf3ce44SJohn Forte } 1303*fcf3ce44SJohn Forte 1304*fcf3ce44SJohn Forte if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) { 1305*fcf3ce44SJohn Forte return (1); 1306*fcf3ce44SJohn Forte } 1307*fcf3ce44SJohn Forte 1308*fcf3ce44SJohn Forte for (promprop = di_prom_prop_next(ph, node, 1309*fcf3ce44SJohn Forte DI_PROM_PROP_NIL); 1310*fcf3ce44SJohn Forte promprop != DI_PROM_PROP_NIL; 1311*fcf3ce44SJohn Forte promprop = di_prom_prop_next(ph, node, promprop)) { 1312*fcf3ce44SJohn Forte if (((promname = di_prom_prop_name( 1313*fcf3ce44SJohn Forte promprop)) != NULL) && 1314*fcf3ce44SJohn Forte (strcmp(promname, "fcode-version") == 0)) { 1315*fcf3ce44SJohn Forte size = di_prom_prop_data(promprop, &ver_data); 1316*fcf3ce44SJohn Forte (void) memset(ver, NULL, size); 1317*fcf3ce44SJohn Forte (void) memcpy(ver, ver_data, size); 1318*fcf3ce44SJohn Forte found = 1; 1319*fcf3ce44SJohn Forte } 1320*fcf3ce44SJohn Forte } 1321*fcf3ce44SJohn Forte 1322*fcf3ce44SJohn Forte if (found) { 1323*fcf3ce44SJohn Forte return (0); 1324*fcf3ce44SJohn Forte } else { 1325*fcf3ce44SJohn Forte return (1); 1326*fcf3ce44SJohn Forte } 1327*fcf3ce44SJohn Forte } 1328*fcf3ce44SJohn Forte 1329*fcf3ce44SJohn Forte /* 1330*fcf3ce44SJohn Forte * Retrieves information from the Emulex fcode 1331*fcf3ce44SJohn Forte * 1332*fcf3ce44SJohn Forte * Given a pattern, this routine will look for this pattern in the fcode 1333*fcf3ce44SJohn Forte * file and if found will return the pattern value 1334*fcf3ce44SJohn Forte * 1335*fcf3ce44SJohn Forte * possible patterns are manufacturer and fcode-version 1336*fcf3ce44SJohn Forte */ 1337*fcf3ce44SJohn Forte int 1338*fcf3ce44SJohn Forte emulex_fcode_reader(int fcode_fd, char *pattern, char *pattern_value, 1339*fcf3ce44SJohn Forte uint32_t pattern_value_size) { 1340*fcf3ce44SJohn Forte int32_t i = 0; 1341*fcf3ce44SJohn Forte uint32_t n = 0; 1342*fcf3ce44SJohn Forte uint32_t b = 0; 1343*fcf3ce44SJohn Forte char byte1; 1344*fcf3ce44SJohn Forte char byte2; 1345*fcf3ce44SJohn Forte char byte3; 1346*fcf3ce44SJohn Forte char byte4; 1347*fcf3ce44SJohn Forte char buffer1[EMULEX_READ_BUFFER_SIZE]; 1348*fcf3ce44SJohn Forte char buffer2[EMULEX_READ_BUFFER_SIZE]; 1349*fcf3ce44SJohn Forte uint32_t plen, image_size; 1350*fcf3ce44SJohn Forte struct stat stat; 1351*fcf3ce44SJohn Forte uchar_t *image; 1352*fcf3ce44SJohn Forte 1353*fcf3ce44SJohn Forte /* Check the arguments */ 1354*fcf3ce44SJohn Forte if (!fcode_fd || !pattern_value || pattern_value_size < 8) { 1355*fcf3ce44SJohn Forte return (1); 1356*fcf3ce44SJohn Forte } 1357*fcf3ce44SJohn Forte 1358*fcf3ce44SJohn Forte if (fstat(fcode_fd, &stat) == -1) { 1359*fcf3ce44SJohn Forte perror(MSGSTR(21023, "fstat")); 1360*fcf3ce44SJohn Forte return (1); 1361*fcf3ce44SJohn Forte } 1362*fcf3ce44SJohn Forte image_size = stat.st_size; 1363*fcf3ce44SJohn Forte if (image_size < 2) { 1364*fcf3ce44SJohn Forte return (1); 1365*fcf3ce44SJohn Forte } 1366*fcf3ce44SJohn Forte if ((image = (uchar_t *)calloc(image_size, 1)) == NULL) { 1367*fcf3ce44SJohn Forte (void) fprintf(stderr, 1368*fcf3ce44SJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n")); 1369*fcf3ce44SJohn Forte return (1); 1370*fcf3ce44SJohn Forte } 1371*fcf3ce44SJohn Forte 1372*fcf3ce44SJohn Forte /* Read the fcode image file */ 1373*fcf3ce44SJohn Forte lseek(fcode_fd, 0, SEEK_SET); 1374*fcf3ce44SJohn Forte read(fcode_fd, image, image_size); 1375*fcf3ce44SJohn Forte 1376*fcf3ce44SJohn Forte /* Initialize */ 1377*fcf3ce44SJohn Forte bzero(buffer1, sizeof (buffer1)); 1378*fcf3ce44SJohn Forte bzero(buffer2, sizeof (buffer2)); 1379*fcf3ce44SJohn Forte /* Default pattern_value string */ 1380*fcf3ce44SJohn Forte strcpy((char *)pattern_value, "<unknown>"); 1381*fcf3ce44SJohn Forte plen = strlen(pattern); 1382*fcf3ce44SJohn Forte n = 0; 1383*fcf3ce44SJohn Forte b = 0; 1384*fcf3ce44SJohn Forte i = 0; 1385*fcf3ce44SJohn Forte 1386*fcf3ce44SJohn Forte /* Search entire image for pattern string */ 1387*fcf3ce44SJohn Forte while (i <= (image_size - 2)) { 1388*fcf3ce44SJohn Forte /* Read next two bytes */ 1389*fcf3ce44SJohn Forte byte1 = image[i++]; 1390*fcf3ce44SJohn Forte byte2 = image[i++]; 1391*fcf3ce44SJohn Forte 1392*fcf3ce44SJohn Forte /* Check second byte first due to endianness */ 1393*fcf3ce44SJohn Forte 1394*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1395*fcf3ce44SJohn Forte buffer1[b++] = byte2; 1396*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1397*fcf3ce44SJohn Forte b = 0; 1398*fcf3ce44SJohn Forte } 1399*fcf3ce44SJohn Forte 1400*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1401*fcf3ce44SJohn Forte if (pattern[n++] != byte2) { 1402*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1403*fcf3ce44SJohn Forte n = 0; 1404*fcf3ce44SJohn Forte } else { 1405*fcf3ce44SJohn Forte /* 1406*fcf3ce44SJohn Forte * If complete pattern has been matched then 1407*fcf3ce44SJohn Forte * exit loop 1408*fcf3ce44SJohn Forte */ 1409*fcf3ce44SJohn Forte if (n == plen) { 1410*fcf3ce44SJohn Forte goto found; 1411*fcf3ce44SJohn Forte } 1412*fcf3ce44SJohn Forte } 1413*fcf3ce44SJohn Forte 1414*fcf3ce44SJohn Forte 1415*fcf3ce44SJohn Forte /* Check first byte second due to endianness */ 1416*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1417*fcf3ce44SJohn Forte buffer1[b++] = byte1; 1418*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1419*fcf3ce44SJohn Forte b = 0; 1420*fcf3ce44SJohn Forte } 1421*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1422*fcf3ce44SJohn Forte if (pattern[n++] != byte1) { 1423*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1424*fcf3ce44SJohn Forte n = 0; 1425*fcf3ce44SJohn Forte } else { 1426*fcf3ce44SJohn Forte /* 1427*fcf3ce44SJohn Forte * If complete pattern has been matched 1428*fcf3ce44SJohn Forte * then exit loop 1429*fcf3ce44SJohn Forte */ 1430*fcf3ce44SJohn Forte if (n == plen) { 1431*fcf3ce44SJohn Forte goto found; 1432*fcf3ce44SJohn Forte } 1433*fcf3ce44SJohn Forte } 1434*fcf3ce44SJohn Forte } 1435*fcf3ce44SJohn Forte 1436*fcf3ce44SJohn Forte /* Not found. Try again with different endianess */ 1437*fcf3ce44SJohn Forte 1438*fcf3ce44SJohn Forte /* Initialize */ 1439*fcf3ce44SJohn Forte bzero(buffer1, sizeof (buffer1)); 1440*fcf3ce44SJohn Forte bzero(buffer2, sizeof (buffer2)); 1441*fcf3ce44SJohn Forte n = 0; 1442*fcf3ce44SJohn Forte b = 0; 1443*fcf3ce44SJohn Forte i = 0; 1444*fcf3ce44SJohn Forte 1445*fcf3ce44SJohn Forte /* Search entire 32bit endian image for pattern string */ 1446*fcf3ce44SJohn Forte while (i <= (image_size - 4)) { 1447*fcf3ce44SJohn Forte /* Read next four bytes */ 1448*fcf3ce44SJohn Forte byte1 = image[i++]; 1449*fcf3ce44SJohn Forte byte2 = image[i++]; 1450*fcf3ce44SJohn Forte byte3 = image[i++]; 1451*fcf3ce44SJohn Forte byte4 = image[i++]; 1452*fcf3ce44SJohn Forte 1453*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1454*fcf3ce44SJohn Forte buffer1[b++] = byte4; 1455*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1456*fcf3ce44SJohn Forte b = 0; 1457*fcf3ce44SJohn Forte } 1458*fcf3ce44SJohn Forte 1459*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1460*fcf3ce44SJohn Forte if (pattern[n++] != byte4) { 1461*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1462*fcf3ce44SJohn Forte n = 0; 1463*fcf3ce44SJohn Forte } else { 1464*fcf3ce44SJohn Forte /* 1465*fcf3ce44SJohn Forte * If complete pattern has been matched then exit loop 1466*fcf3ce44SJohn Forte */ 1467*fcf3ce44SJohn Forte if (n == plen) { 1468*fcf3ce44SJohn Forte goto found; 1469*fcf3ce44SJohn Forte } 1470*fcf3ce44SJohn Forte } 1471*fcf3ce44SJohn Forte 1472*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1473*fcf3ce44SJohn Forte buffer1[b++] = byte3; 1474*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1475*fcf3ce44SJohn Forte b = 0; 1476*fcf3ce44SJohn Forte } 1477*fcf3ce44SJohn Forte 1478*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1479*fcf3ce44SJohn Forte if (pattern[n++] != byte3) { 1480*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1481*fcf3ce44SJohn Forte n = 0; 1482*fcf3ce44SJohn Forte } else { 1483*fcf3ce44SJohn Forte /* 1484*fcf3ce44SJohn Forte * If complete pattern has been matched then exit loop 1485*fcf3ce44SJohn Forte */ 1486*fcf3ce44SJohn Forte if (n == plen) { 1487*fcf3ce44SJohn Forte goto found; 1488*fcf3ce44SJohn Forte } 1489*fcf3ce44SJohn Forte } 1490*fcf3ce44SJohn Forte 1491*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1492*fcf3ce44SJohn Forte buffer1[b++] = byte2; 1493*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1494*fcf3ce44SJohn Forte b = 0; 1495*fcf3ce44SJohn Forte } 1496*fcf3ce44SJohn Forte 1497*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1498*fcf3ce44SJohn Forte if (pattern[n++] != byte2) { 1499*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1500*fcf3ce44SJohn Forte n = 0; 1501*fcf3ce44SJohn Forte } else { 1502*fcf3ce44SJohn Forte /* 1503*fcf3ce44SJohn Forte * If complete pattern has been matched then exit loop 1504*fcf3ce44SJohn Forte */ 1505*fcf3ce44SJohn Forte if (n == plen) { 1506*fcf3ce44SJohn Forte goto found; 1507*fcf3ce44SJohn Forte } 1508*fcf3ce44SJohn Forte } 1509*fcf3ce44SJohn Forte 1510*fcf3ce44SJohn Forte /* Save byte in circular buffer */ 1511*fcf3ce44SJohn Forte buffer1[b++] = byte1; 1512*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1513*fcf3ce44SJohn Forte b = 0; 1514*fcf3ce44SJohn Forte } 1515*fcf3ce44SJohn Forte 1516*fcf3ce44SJohn Forte /* Check byte for pattern match */ 1517*fcf3ce44SJohn Forte if (pattern[n++] != byte1) { 1518*fcf3ce44SJohn Forte /* If no match, then reset pattern */ 1519*fcf3ce44SJohn Forte n = 0; 1520*fcf3ce44SJohn Forte } else { 1521*fcf3ce44SJohn Forte /* 1522*fcf3ce44SJohn Forte * If complete pattern has been matched then exit loop 1523*fcf3ce44SJohn Forte */ 1524*fcf3ce44SJohn Forte if (n == plen) { 1525*fcf3ce44SJohn Forte goto found; 1526*fcf3ce44SJohn Forte } 1527*fcf3ce44SJohn Forte } 1528*fcf3ce44SJohn Forte } 1529*fcf3ce44SJohn Forte 1530*fcf3ce44SJohn Forte free(image); 1531*fcf3ce44SJohn Forte return (1); 1532*fcf3ce44SJohn Forte 1533*fcf3ce44SJohn Forte found: 1534*fcf3ce44SJohn Forte free(image); 1535*fcf3ce44SJohn Forte 1536*fcf3ce44SJohn Forte /* Align buffer and eliminate non-printable characters */ 1537*fcf3ce44SJohn Forte for (i = 0; i < (sizeof (buffer1)-plen); i++) { 1538*fcf3ce44SJohn Forte byte1 = buffer1[b++]; 1539*fcf3ce44SJohn Forte if (b == sizeof (buffer1)) { 1540*fcf3ce44SJohn Forte b = 0; 1541*fcf3ce44SJohn Forte } 1542*fcf3ce44SJohn Forte /* Zero any non-printable characters */ 1543*fcf3ce44SJohn Forte if (byte1 >= 33 && byte1 <= 126) { 1544*fcf3ce44SJohn Forte buffer2[i] = byte1; 1545*fcf3ce44SJohn Forte } else { 1546*fcf3ce44SJohn Forte buffer2[i] = 0; 1547*fcf3ce44SJohn Forte } 1548*fcf3ce44SJohn Forte } 1549*fcf3ce44SJohn Forte 1550*fcf3ce44SJohn Forte /* 1551*fcf3ce44SJohn Forte * Scan backwards for first non-zero string. This will be the 1552*fcf3ce44SJohn Forte * version string 1553*fcf3ce44SJohn Forte */ 1554*fcf3ce44SJohn Forte for (i = sizeof (buffer1)-plen-1; i >= 0; i--) { 1555*fcf3ce44SJohn Forte if (buffer2[i] != 0) { 1556*fcf3ce44SJohn Forte for (; i >= 0; i--) { 1557*fcf3ce44SJohn Forte if (buffer2[i] == 0) { 1558*fcf3ce44SJohn Forte i++; 1559*fcf3ce44SJohn Forte strncpy((char *)pattern_value, 1560*fcf3ce44SJohn Forte &buffer2[i], pattern_value_size); 1561*fcf3ce44SJohn Forte break; 1562*fcf3ce44SJohn Forte } 1563*fcf3ce44SJohn Forte } 1564*fcf3ce44SJohn Forte break; 1565*fcf3ce44SJohn Forte } 1566*fcf3ce44SJohn Forte } 1567*fcf3ce44SJohn Forte return (0); 1568*fcf3ce44SJohn Forte } 1569*fcf3ce44SJohn Forte 1570*fcf3ce44SJohn Forte /* 1571*fcf3ce44SJohn Forte * error handling routine to handle emulex error conditions 1572*fcf3ce44SJohn Forte */ 1573*fcf3ce44SJohn Forte static void 1574*fcf3ce44SJohn Forte handle_emulex_error(int fcio_errno, char *phys_path) { 1575*fcf3ce44SJohn Forte if (fcio_errno == EMLX_IMAGE_BAD) { 1576*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(21119, 1577*fcf3ce44SJohn Forte "Error: Fcode download failed. " 1578*fcf3ce44SJohn Forte "Bad fcode image.\n")); 1579*fcf3ce44SJohn Forte } else if (fcio_errno == EMLX_IMAGE_INCOMPATIBLE) { 1580*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(21120, 1581*fcf3ce44SJohn Forte "Error: Fcode download failed. Fcode is not " 1582*fcf3ce44SJohn Forte "compatible with card.\n")); 1583*fcf3ce44SJohn Forte } else { 1584*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(21036, 1585*fcf3ce44SJohn Forte "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n")); 1586*fcf3ce44SJohn Forte (void) fprintf(stderr, 1587*fcf3ce44SJohn Forte MSGSTR(21113, 1588*fcf3ce44SJohn Forte "Error: FCode download failed: %s\n"), 1589*fcf3ce44SJohn Forte phys_path); 1590*fcf3ce44SJohn Forte } 1591*fcf3ce44SJohn Forte } 1592