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