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 /* 28*fcf3ce44SJohn Forte * I18N message number ranges 29*fcf3ce44SJohn Forte * This file: 4500 - 4999 30*fcf3ce44SJohn Forte * Shared common messages: 1 - 1999 31*fcf3ce44SJohn Forte */ 32*fcf3ce44SJohn Forte 33*fcf3ce44SJohn Forte #include <fcntl.h> 34*fcf3ce44SJohn Forte #include <limits.h> 35*fcf3ce44SJohn Forte #include <setjmp.h> 36*fcf3ce44SJohn Forte #include <signal.h> 37*fcf3ce44SJohn Forte #include <siginfo.h> 38*fcf3ce44SJohn Forte #include <stdio.h> 39*fcf3ce44SJohn Forte #include <stdlib.h> 40*fcf3ce44SJohn Forte #include <string.h> 41*fcf3ce44SJohn Forte #include <strings.h> 42*fcf3ce44SJohn Forte #include <unistd.h> 43*fcf3ce44SJohn Forte #include <ctype.h> 44*fcf3ce44SJohn Forte #include <dirent.h> 45*fcf3ce44SJohn Forte #include <sys/exec.h> 46*fcf3ce44SJohn Forte #include <sys/exechdr.h> 47*fcf3ce44SJohn Forte #include <sys/mman.h> 48*fcf3ce44SJohn Forte #include <sys/stat.h> 49*fcf3ce44SJohn Forte #include <sys/types.h> 50*fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h> 51*fcf3ce44SJohn Forte #include <sys/socalreg.h> 52*fcf3ce44SJohn Forte /* 53*fcf3ce44SJohn Forte * The following define is not to 54*fcf3ce44SJohn Forte * include sys/fc4/fcal_linkapp.h 55*fcf3ce44SJohn Forte * file from sys/socalio.h, since it 56*fcf3ce44SJohn Forte * has same structure defines as in 57*fcf3ce44SJohn Forte * sys/fibre-channel/fcio.h. 58*fcf3ce44SJohn Forte */ 59*fcf3ce44SJohn Forte #define _SYS_FC4_FCAL_LINKAPP_H 60*fcf3ce44SJohn Forte #include <sys/socalio.h> 61*fcf3ce44SJohn Forte #include <sys/time.h> 62*fcf3ce44SJohn Forte #include <nl_types.h> 63*fcf3ce44SJohn Forte #include <errno.h> 64*fcf3ce44SJohn Forte #include <stgcom.h> 65*fcf3ce44SJohn Forte #include <gfc.h> 66*fcf3ce44SJohn Forte #include <l_common.h> 67*fcf3ce44SJohn Forte #include "luxadm.h" 68*fcf3ce44SJohn Forte 69*fcf3ce44SJohn Forte /* Defines */ 70*fcf3ce44SJohn Forte #define FEPROM_SIZE 256*1024 71*fcf3ce44SJohn Forte #define FEPROM_MAX_PROGRAM 25 72*fcf3ce44SJohn Forte #define FEPROM_MAX_ERASE 1000 73*fcf3ce44SJohn Forte #define FEPROM_READ_MEMORY 0x00 74*fcf3ce44SJohn Forte #define FEPROM_ERASE 0x20 75*fcf3ce44SJohn Forte #define FEPROM_ERASE_VERIFY 0xa0 76*fcf3ce44SJohn Forte #define FEPROM_PROGRAM 0x40 77*fcf3ce44SJohn Forte #define FEPROM_PROGRAM_VERIFY 0xc0 78*fcf3ce44SJohn Forte #define FEPROM_RESET 0xff 79*fcf3ce44SJohn Forte #define HBA_MAX 128 80*fcf3ce44SJohn Forte 81*fcf3ce44SJohn Forte #define FOUND 0 82*fcf3ce44SJohn Forte #define NOT_FOUND 1 83*fcf3ce44SJohn Forte #define PROM_SIZ 0x20010 84*fcf3ce44SJohn Forte 85*fcf3ce44SJohn Forte #define MAX_RETRIES 3 86*fcf3ce44SJohn Forte #define MAX_WAIT_TIME 30 87*fcf3ce44SJohn Forte 88*fcf3ce44SJohn Forte /* 89*fcf3ce44SJohn Forte * The next define is to work around a problem with sbusmem driver not 90*fcf3ce44SJohn Forte * able to round up mmap() requests that are not around page boundaries. 91*fcf3ce44SJohn Forte */ 92*fcf3ce44SJohn Forte #define PROM_SIZ_ROUNDED 0x22000 93*fcf3ce44SJohn Forte #define SAMPLE_SIZ 0x100 94*fcf3ce44SJohn Forte 95*fcf3ce44SJohn Forte #define REG_OFFSET 0x20000 96*fcf3ce44SJohn Forte 97*fcf3ce44SJohn Forte #define FEPROM_WWN_OFFSET 0x3fe00 98*fcf3ce44SJohn Forte 99*fcf3ce44SJohn Forte #define FEPROM_SUN_WWN 0x50200200 100*fcf3ce44SJohn Forte 101*fcf3ce44SJohn Forte /* 102*fcf3ce44SJohn Forte * We'll leave this on leadville, as the onboard 103*fcf3ce44SJohn Forte * isn't allowed to be zapped by luxadm 104*fcf3ce44SJohn Forte */ 105*fcf3ce44SJohn Forte 106*fcf3ce44SJohn Forte #define ONBOARD_SOCAL "SUNW,socal@d" 107*fcf3ce44SJohn Forte 108*fcf3ce44SJohn Forte #define SOCAL_STR "SUNW,socal" 109*fcf3ce44SJohn Forte #define SOCAL_STR_LEN 10 110*fcf3ce44SJohn Forte 111*fcf3ce44SJohn Forte 112*fcf3ce44SJohn Forte static uchar_t buffer[FEPROM_SIZE]; 113*fcf3ce44SJohn Forte 114*fcf3ce44SJohn Forte static char sbus_list[HBA_MAX][PATH_MAX]; 115*fcf3ce44SJohn Forte static char sbussoc_list[HBA_MAX][PATH_MAX]; 116*fcf3ce44SJohn Forte static char bootpath[PATH_MAX]; 117*fcf3ce44SJohn Forte static char version[MAXNAMELEN]; 118*fcf3ce44SJohn Forte 119*fcf3ce44SJohn Forte static uint_t getsbuslist(void); 120*fcf3ce44SJohn Forte static int load_file(char *, caddr_t, volatile socal_reg_t *); 121*fcf3ce44SJohn Forte static void usec_delay(int); 122*fcf3ce44SJohn Forte static void getbootdev(unsigned int); 123*fcf3ce44SJohn Forte static void getsocpath(char *, int *); 124*fcf3ce44SJohn Forte static int loadsocpath(const char *, int *); 125*fcf3ce44SJohn Forte static int warn(void); 126*fcf3ce44SJohn Forte static int findversion(int, uchar_t *); 127*fcf3ce44SJohn Forte static int write_feprom(uchar_t *, uchar_t *, volatile socal_reg_t *); 128*fcf3ce44SJohn Forte static int feprom_erase(volatile uchar_t *, volatile socal_reg_t *); 129*fcf3ce44SJohn Forte 130*fcf3ce44SJohn Forte static struct exec exec; 131*fcf3ce44SJohn Forte 132*fcf3ce44SJohn Forte int 133*fcf3ce44SJohn Forte fcal_update(unsigned int verbose, char *file) 134*fcf3ce44SJohn Forte /*ARGSUSED*/ 135*fcf3ce44SJohn Forte { 136*fcf3ce44SJohn Forte int fd, strfound = 0, retval = 0; 137*fcf3ce44SJohn Forte int fbuf_idx, fd1, bytes_read; 138*fcf3ce44SJohn Forte caddr_t addr; 139*fcf3ce44SJohn Forte uint_t i; 140*fcf3ce44SJohn Forte uint_t fflag = 0; 141*fcf3ce44SJohn Forte uint_t vflag = 0; 142*fcf3ce44SJohn Forte uint_t numslots; 143*fcf3ce44SJohn Forte volatile socal_reg_t *regs; 144*fcf3ce44SJohn Forte char *slotname, socal[MAXNAMELEN]; 145*fcf3ce44SJohn Forte char fbuf[BUFSIZ]; 146*fcf3ce44SJohn Forte 147*fcf3ce44SJohn Forte if (!file) 148*fcf3ce44SJohn Forte vflag++; 149*fcf3ce44SJohn Forte else { 150*fcf3ce44SJohn Forte fflag++; 151*fcf3ce44SJohn Forte if ((fd1 = open(file, O_RDONLY)) == -1) { 152*fcf3ce44SJohn Forte (void) fprintf(stderr, 153*fcf3ce44SJohn Forte MSGSTR(4500, 154*fcf3ce44SJohn Forte "Error: open() failed on file " 155*fcf3ce44SJohn Forte "%s\n"), file); 156*fcf3ce44SJohn Forte return (1); 157*fcf3ce44SJohn Forte } 158*fcf3ce44SJohn Forte /* 159*fcf3ce44SJohn Forte * We will just make a check to see if it the file 160*fcf3ce44SJohn Forte * has the "SUNW,socal" strings in it 161*fcf3ce44SJohn Forte * We cannot use strstr() here because we are operating on 162*fcf3ce44SJohn Forte * binary data and so is very likely to have embedded NULLs 163*fcf3ce44SJohn Forte */ 164*fcf3ce44SJohn Forte while (!strfound && ((bytes_read = read(fd1, 165*fcf3ce44SJohn Forte fbuf, BUFSIZ)) > 0)) { 166*fcf3ce44SJohn Forte for (fbuf_idx = 0; fbuf_idx < bytes_read; 167*fcf3ce44SJohn Forte fbuf_idx++) { 168*fcf3ce44SJohn Forte /* First check for the SUNW,socal string */ 169*fcf3ce44SJohn Forte if (strncmp((fbuf + fbuf_idx), SOCAL_STR, 170*fcf3ce44SJohn Forte SOCAL_STR_LEN) == 0) { 171*fcf3ce44SJohn Forte strfound = 1; 172*fcf3ce44SJohn Forte break; 173*fcf3ce44SJohn Forte } 174*fcf3ce44SJohn Forte 175*fcf3ce44SJohn Forte } 176*fcf3ce44SJohn Forte } 177*fcf3ce44SJohn Forte (void) close(fd1); 178*fcf3ce44SJohn Forte 179*fcf3ce44SJohn Forte if (!strfound) { 180*fcf3ce44SJohn Forte (void) fprintf(stderr, 181*fcf3ce44SJohn Forte MSGSTR(4501, 182*fcf3ce44SJohn Forte "Error: %s is not a " 183*fcf3ce44SJohn Forte "FC100/S Fcode file\n"), file); 184*fcf3ce44SJohn Forte return (1); 185*fcf3ce44SJohn Forte } 186*fcf3ce44SJohn Forte } 187*fcf3ce44SJohn Forte 188*fcf3ce44SJohn Forte /* 189*fcf3ce44SJohn Forte * Get count of, and names of SBus slots using the SBus memory 190*fcf3ce44SJohn Forte * interface. 191*fcf3ce44SJohn Forte */ 192*fcf3ce44SJohn Forte (void) getbootdev(verbose); 193*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 194*fcf3ce44SJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath); 195*fcf3ce44SJohn Forte } 196*fcf3ce44SJohn Forte 197*fcf3ce44SJohn Forte numslots = getsbuslist(); 198*fcf3ce44SJohn Forte (void) fprintf(stdout, 199*fcf3ce44SJohn Forte MSGSTR(4503, "\n Found Path to %d FC100/S Cards\n"), numslots); 200*fcf3ce44SJohn Forte 201*fcf3ce44SJohn Forte for (i = 0; i < numslots; i++) { 202*fcf3ce44SJohn Forte 203*fcf3ce44SJohn Forte /* 204*fcf3ce44SJohn Forte * Open SBus memory for this slot. 205*fcf3ce44SJohn Forte */ 206*fcf3ce44SJohn Forte slotname = &sbus_list[i][0]; 207*fcf3ce44SJohn Forte if (fflag && (strcmp(slotname, bootpath) == 0)) { 208*fcf3ce44SJohn Forte (void) fprintf(stderr, 209*fcf3ce44SJohn Forte MSGSTR(4504, " Ignoring %s (bootpath)\n"), slotname); 210*fcf3ce44SJohn Forte continue; 211*fcf3ce44SJohn Forte } 212*fcf3ce44SJohn Forte 213*fcf3ce44SJohn Forte (void) sprintf(socal, "%s:0", &sbussoc_list[i][0]); 214*fcf3ce44SJohn Forte 215*fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) { 216*fcf3ce44SJohn Forte (void) sprintf(socal, "%s:1", &sbussoc_list[i][0]); 217*fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) { 218*fcf3ce44SJohn Forte (void) fprintf(stderr, 219*fcf3ce44SJohn Forte MSGSTR(4505, "Could not open %s\n"), 220*fcf3ce44SJohn Forte &sbussoc_list[i][0]); 221*fcf3ce44SJohn Forte (void) fprintf(stderr, 222*fcf3ce44SJohn Forte MSGSTR(4506, "Ignoring %s\n"), 223*fcf3ce44SJohn Forte &sbussoc_list[i][0]); 224*fcf3ce44SJohn Forte retval++; 225*fcf3ce44SJohn Forte continue; 226*fcf3ce44SJohn Forte } 227*fcf3ce44SJohn Forte } 228*fcf3ce44SJohn Forte 229*fcf3ce44SJohn Forte (void) close(fd); 230*fcf3ce44SJohn Forte 231*fcf3ce44SJohn Forte if (verbose) { 232*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n "); 233*fcf3ce44SJohn Forte (void) fprintf(stdout, 234*fcf3ce44SJohn Forte MSGSTR(85, "Opening %s\n"), slotname); 235*fcf3ce44SJohn Forte } 236*fcf3ce44SJohn Forte 237*fcf3ce44SJohn Forte fd = open(slotname, O_RDWR); 238*fcf3ce44SJohn Forte 239*fcf3ce44SJohn Forte if (fd < 0) { 240*fcf3ce44SJohn Forte perror(MSGSTR(4507, "open of slotname")); 241*fcf3ce44SJohn Forte retval++; 242*fcf3ce44SJohn Forte continue; 243*fcf3ce44SJohn Forte } 244*fcf3ce44SJohn Forte 245*fcf3ce44SJohn Forte /* 246*fcf3ce44SJohn Forte * Mmap that SBus memory into my memory space. 247*fcf3ce44SJohn Forte */ 248*fcf3ce44SJohn Forte addr = mmap((caddr_t)0, PROM_SIZ_ROUNDED, PROT_READ|PROT_WRITE, 249*fcf3ce44SJohn Forte MAP_SHARED, fd, 0); 250*fcf3ce44SJohn Forte 251*fcf3ce44SJohn Forte if (addr == MAP_FAILED) { 252*fcf3ce44SJohn Forte perror(MSGSTR(46, "mmap")); 253*fcf3ce44SJohn Forte (void) close(fd); 254*fcf3ce44SJohn Forte retval++; 255*fcf3ce44SJohn Forte continue; 256*fcf3ce44SJohn Forte } 257*fcf3ce44SJohn Forte 258*fcf3ce44SJohn Forte if ((int)addr == -1) { 259*fcf3ce44SJohn Forte perror(MSGSTR(46, "mmap")); 260*fcf3ce44SJohn Forte (void) close(fd); 261*fcf3ce44SJohn Forte retval++; 262*fcf3ce44SJohn Forte continue; 263*fcf3ce44SJohn Forte } 264*fcf3ce44SJohn Forte 265*fcf3ce44SJohn Forte regs = (socal_reg_t *)((int)addr + REG_OFFSET); 266*fcf3ce44SJohn Forte 267*fcf3ce44SJohn Forte (void) fprintf(stdout, 268*fcf3ce44SJohn Forte MSGSTR(4508, "\n Device: %s\n"), 269*fcf3ce44SJohn Forte &sbussoc_list[i][0]); 270*fcf3ce44SJohn Forte /* 271*fcf3ce44SJohn Forte * Load the New FCode 272*fcf3ce44SJohn Forte */ 273*fcf3ce44SJohn Forte if (fflag) { 274*fcf3ce44SJohn Forte if (!warn()) 275*fcf3ce44SJohn Forte retval += load_file(file, addr, regs); 276*fcf3ce44SJohn Forte } else if (vflag) { 277*fcf3ce44SJohn Forte if (findversion(i, (uchar_t *)&version[0]) == FOUND) { 278*fcf3ce44SJohn Forte (void) fprintf(stdout, 279*fcf3ce44SJohn Forte MSGSTR(4509, 280*fcf3ce44SJohn Forte " Detected FC100/S Version: %s\n"), version); 281*fcf3ce44SJohn Forte } 282*fcf3ce44SJohn Forte } 283*fcf3ce44SJohn Forte 284*fcf3ce44SJohn Forte if (munmap(addr, PROM_SIZ) == -1) { 285*fcf3ce44SJohn Forte perror(MSGSTR(4510, "munmap")); 286*fcf3ce44SJohn Forte retval++; 287*fcf3ce44SJohn Forte } 288*fcf3ce44SJohn Forte 289*fcf3ce44SJohn Forte (void) close(fd); 290*fcf3ce44SJohn Forte 291*fcf3ce44SJohn Forte } 292*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 293*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n")); 294*fcf3ce44SJohn Forte return (retval); 295*fcf3ce44SJohn Forte } 296*fcf3ce44SJohn Forte 297*fcf3ce44SJohn Forte static int 298*fcf3ce44SJohn Forte findversion(int index, uchar_t *version) 299*fcf3ce44SJohn Forte /*ARGSUSED*/ 300*fcf3ce44SJohn Forte { 301*fcf3ce44SJohn Forte int fd, ntries; 302*fcf3ce44SJohn Forte struct socal_fm_version *buffer; 303*fcf3ce44SJohn Forte char socal[MAXNAMELEN]; 304*fcf3ce44SJohn Forte char fp[MAXNAMELEN]; 305*fcf3ce44SJohn Forte char prom_ver[100]; 306*fcf3ce44SJohn Forte char mcode_ver[100]; 307*fcf3ce44SJohn Forte uint_t dev_type; 308*fcf3ce44SJohn Forte fcio_t fcio; 309*fcf3ce44SJohn Forte char fw_rev[FC_FW_REV_SIZE + 1]; 310*fcf3ce44SJohn Forte 311*fcf3ce44SJohn Forte 312*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(&sbussoc_list[index][0])) == 0) { 313*fcf3ce44SJohn Forte return (L_INVALID_PATH); 314*fcf3ce44SJohn Forte } 315*fcf3ce44SJohn Forte 316*fcf3ce44SJohn Forte 317*fcf3ce44SJohn Forte if (dev_type & FC4_FCA_MASK) { 318*fcf3ce44SJohn Forte P_DPRINTF("findversion: found an FC4 path\n"); 319*fcf3ce44SJohn Forte (void) sprintf(socal, "%s:0", &sbussoc_list[index][0]); 320*fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) { 321*fcf3ce44SJohn Forte (void) sprintf(socal, "%s:1", &sbussoc_list[index][0]); 322*fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) { 323*fcf3ce44SJohn Forte (void) fprintf(stderr, 324*fcf3ce44SJohn Forte MSGSTR(4511, "Could not open %s\n"), 325*fcf3ce44SJohn Forte &sbussoc_list[index][0]); 326*fcf3ce44SJohn Forte (void) close(fd); 327*fcf3ce44SJohn Forte return (NOT_FOUND); 328*fcf3ce44SJohn Forte } 329*fcf3ce44SJohn Forte } 330*fcf3ce44SJohn Forte if ((buffer = (struct socal_fm_version *)malloc( 331*fcf3ce44SJohn Forte sizeof (struct socal_fm_version))) == NULL) { 332*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(10, 333*fcf3ce44SJohn Forte " Error: Unable to allocate memory.")); 334*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 335*fcf3ce44SJohn Forte (void) close(fd); 336*fcf3ce44SJohn Forte return (NOT_FOUND); 337*fcf3ce44SJohn Forte } 338*fcf3ce44SJohn Forte 339*fcf3ce44SJohn Forte buffer->fcode_ver = (char *)version; 340*fcf3ce44SJohn Forte buffer->mcode_ver = mcode_ver; 341*fcf3ce44SJohn Forte buffer->prom_ver = prom_ver; 342*fcf3ce44SJohn Forte buffer->fcode_ver_len = MAXNAMELEN - 1; 343*fcf3ce44SJohn Forte buffer->mcode_ver_len = 100; 344*fcf3ce44SJohn Forte buffer->prom_ver_len = 100; 345*fcf3ce44SJohn Forte 346*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, buffer) < 0) { 347*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4512, 348*fcf3ce44SJohn Forte "fcal_s_download: could not get" 349*fcf3ce44SJohn Forte " fcode version.\n")); 350*fcf3ce44SJohn Forte (void) close(fd); 351*fcf3ce44SJohn Forte (void) free(buffer); 352*fcf3ce44SJohn Forte return (NOT_FOUND); 353*fcf3ce44SJohn Forte } 354*fcf3ce44SJohn Forte version[buffer->fcode_ver_len] = '\0'; 355*fcf3ce44SJohn Forte free(buffer); 356*fcf3ce44SJohn Forte 357*fcf3ce44SJohn Forte } else if (dev_type & FC_FCA_MASK) { 358*fcf3ce44SJohn Forte /* 359*fcf3ce44SJohn Forte * Get the fcode and prom's fw version 360*fcf3ce44SJohn Forte * using new ioctls. Currently, we pass 361*fcf3ce44SJohn Forte * only the fcode version to the calling function 362*fcf3ce44SJohn Forte * and ignore the FW version (using the existing 363*fcf3ce44SJohn Forte * implementation). The function definition 364*fcf3ce44SJohn Forte * might be changed in future to pass both the 365*fcf3ce44SJohn Forte * fcode and FW revisions to the calling function, if 366*fcf3ce44SJohn Forte * needed by the calling function. 367*fcf3ce44SJohn Forte */ 368*fcf3ce44SJohn Forte P_DPRINTF("findversion: found an FC path\n"); 369*fcf3ce44SJohn Forte (void) sprintf(fp, "%s/fp@0,0:devctl", 370*fcf3ce44SJohn Forte &sbussoc_list[index][0]); 371*fcf3ce44SJohn Forte if ((fd = open(fp, O_RDWR)) < 0) { 372*fcf3ce44SJohn Forte (void) sprintf(fp, "%s/fp@1,0:devctl", 373*fcf3ce44SJohn Forte &sbussoc_list[index][0]); 374*fcf3ce44SJohn Forte if ((fd = open(fp, O_RDWR)) < 0) { 375*fcf3ce44SJohn Forte (void) fprintf(stderr, 376*fcf3ce44SJohn Forte MSGSTR(4511, "Could not open %s\n"), 377*fcf3ce44SJohn Forte &sbussoc_list[index][0]); 378*fcf3ce44SJohn Forte (void) close(fd); 379*fcf3ce44SJohn Forte return (NOT_FOUND); 380*fcf3ce44SJohn Forte } 381*fcf3ce44SJohn Forte } 382*fcf3ce44SJohn Forte /* Get the fcode version */ 383*fcf3ce44SJohn Forte bzero(version, sizeof (version)); 384*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_FCODE_REV; 385*fcf3ce44SJohn Forte /* Information read operation */ 386*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 387*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)version; 388*fcf3ce44SJohn Forte fcio.fcio_olen = MAXNAMELEN; 389*fcf3ce44SJohn Forte 390*fcf3ce44SJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) { 391*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 392*fcf3ce44SJohn Forte if ((errno == EAGAIN) && 393*fcf3ce44SJohn Forte (ntries+1 < MAX_RETRIES)) { 394*fcf3ce44SJohn Forte /* wait 30 secs */ 395*fcf3ce44SJohn Forte (void) sleep(MAX_WAIT_TIME); 396*fcf3ce44SJohn Forte continue; 397*fcf3ce44SJohn Forte } 398*fcf3ce44SJohn Forte I_DPRINTF("ioctl FCIO_GET_FCODE_REV failed.\n" 399*fcf3ce44SJohn Forte "Error: %s\n", strerror(errno)); 400*fcf3ce44SJohn Forte (void) close(fd); 401*fcf3ce44SJohn Forte return (L_FCIO_GET_FCODE_REV_FAIL); 402*fcf3ce44SJohn Forte } 403*fcf3ce44SJohn Forte break; 404*fcf3ce44SJohn Forte } 405*fcf3ce44SJohn Forte version[MAXNAMELEN-1] = '\0'; 406*fcf3ce44SJohn Forte 407*fcf3ce44SJohn Forte /* Get the FW revision */ 408*fcf3ce44SJohn Forte bzero(fw_rev, sizeof (fw_rev)); 409*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_FW_REV; 410*fcf3ce44SJohn Forte /* Information read operation */ 411*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 412*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)fw_rev; 413*fcf3ce44SJohn Forte fcio.fcio_olen = FC_FW_REV_SIZE; 414*fcf3ce44SJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) { 415*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 416*fcf3ce44SJohn Forte if ((errno == EAGAIN) && 417*fcf3ce44SJohn Forte (ntries+1 < MAX_RETRIES)) { 418*fcf3ce44SJohn Forte /* wait 30 secs */ 419*fcf3ce44SJohn Forte (void) sleep(MAX_WAIT_TIME); 420*fcf3ce44SJohn Forte continue; 421*fcf3ce44SJohn Forte } 422*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_FW_REV ioctl failed.\n" 423*fcf3ce44SJohn Forte " Error: %s\n", strerror(errno)); 424*fcf3ce44SJohn Forte (void) close(fd); 425*fcf3ce44SJohn Forte return (L_FCIO_GET_FW_REV_FAIL); 426*fcf3ce44SJohn Forte } 427*fcf3ce44SJohn Forte break; 428*fcf3ce44SJohn Forte } 429*fcf3ce44SJohn Forte } 430*fcf3ce44SJohn Forte 431*fcf3ce44SJohn Forte (void) close(fd); 432*fcf3ce44SJohn Forte return (FOUND); 433*fcf3ce44SJohn Forte } 434*fcf3ce44SJohn Forte /* 435*fcf3ce44SJohn Forte * program an FEprom with data from 'source_address'. 436*fcf3ce44SJohn Forte * program the FEprom with zeroes, 437*fcf3ce44SJohn Forte * erase it, 438*fcf3ce44SJohn Forte * program it with the real data. 439*fcf3ce44SJohn Forte */ 440*fcf3ce44SJohn Forte static int 441*fcf3ce44SJohn Forte feprom_program(uchar_t *source_address, uchar_t *dest_address, 442*fcf3ce44SJohn Forte volatile socal_reg_t *regs) 443*fcf3ce44SJohn Forte { 444*fcf3ce44SJohn Forte int i; 445*fcf3ce44SJohn Forte 446*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4513, "Filling with zeroes...\n")); 447*fcf3ce44SJohn Forte if (!write_feprom((uchar_t *)0, dest_address, regs)) { 448*fcf3ce44SJohn Forte (void) fprintf(stderr, 449*fcf3ce44SJohn Forte MSGSTR(4514, "FEprom at 0x%x: zero fill failed\n"), 450*fcf3ce44SJohn Forte (int)dest_address); 451*fcf3ce44SJohn Forte return (0); 452*fcf3ce44SJohn Forte } 453*fcf3ce44SJohn Forte 454*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4515, "Erasing...\n")); 455*fcf3ce44SJohn Forte for (i = 0; i < FEPROM_MAX_ERASE; i++) { 456*fcf3ce44SJohn Forte if (feprom_erase(dest_address, regs)) 457*fcf3ce44SJohn Forte break; 458*fcf3ce44SJohn Forte } 459*fcf3ce44SJohn Forte 460*fcf3ce44SJohn Forte if (i >= FEPROM_MAX_ERASE) { 461*fcf3ce44SJohn Forte (void) fprintf(stderr, 462*fcf3ce44SJohn Forte MSGSTR(4516, "FEprom at 0x%x: failed to erase\n"), 463*fcf3ce44SJohn Forte (int)dest_address); 464*fcf3ce44SJohn Forte return (0); 465*fcf3ce44SJohn Forte } else if (i > 0) { 466*fcf3ce44SJohn Forte if (i == 1) { 467*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4517, 468*fcf3ce44SJohn Forte "FEprom erased after %d attempt\n"), i); 469*fcf3ce44SJohn Forte } else { 470*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4518, 471*fcf3ce44SJohn Forte "FEprom erased after %d attempts\n"), i); 472*fcf3ce44SJohn Forte } 473*fcf3ce44SJohn Forte } 474*fcf3ce44SJohn Forte 475*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4519, "Programming...\n")); 476*fcf3ce44SJohn Forte if (!(write_feprom(source_address, dest_address, regs))) { 477*fcf3ce44SJohn Forte (void) fprintf(stderr, 478*fcf3ce44SJohn Forte MSGSTR(4520, "FEprom at 0x%x: write failed\n"), 479*fcf3ce44SJohn Forte (int)dest_address); 480*fcf3ce44SJohn Forte return (0); 481*fcf3ce44SJohn Forte } 482*fcf3ce44SJohn Forte 483*fcf3ce44SJohn Forte /* select the zeroth bank at end so we can read it */ 484*fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000); 485*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4521, "Programming done\n")); 486*fcf3ce44SJohn Forte return (1); 487*fcf3ce44SJohn Forte } 488*fcf3ce44SJohn Forte 489*fcf3ce44SJohn Forte /* 490*fcf3ce44SJohn Forte * program an FEprom one byte at a time using hot electron injection. 491*fcf3ce44SJohn Forte */ 492*fcf3ce44SJohn Forte static int 493*fcf3ce44SJohn Forte write_feprom(uchar_t *source_address, uchar_t *dest_address, 494*fcf3ce44SJohn Forte volatile socal_reg_t *regs) 495*fcf3ce44SJohn Forte { 496*fcf3ce44SJohn Forte int pulse, i; 497*fcf3ce44SJohn Forte uchar_t *s = source_address; 498*fcf3ce44SJohn Forte volatile uchar_t *d; 499*fcf3ce44SJohn Forte 500*fcf3ce44SJohn Forte for (i = 0; i < FEPROM_SIZE; i++, s++) { 501*fcf3ce44SJohn Forte 502*fcf3ce44SJohn Forte if ((i & 0xffff) == 0) { 503*fcf3ce44SJohn Forte (void) fprintf(stdout, 504*fcf3ce44SJohn Forte MSGSTR(4522, "selecting bank %d\n"), i>>16); 505*fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000); 506*fcf3ce44SJohn Forte regs->socal_cr.w |= i & 0x30000; 507*fcf3ce44SJohn Forte } 508*fcf3ce44SJohn Forte 509*fcf3ce44SJohn Forte d = dest_address + (i & 0xffff); 510*fcf3ce44SJohn Forte 511*fcf3ce44SJohn Forte for (pulse = 0; pulse < FEPROM_MAX_PROGRAM; pulse++) { 512*fcf3ce44SJohn Forte *d = FEPROM_PROGRAM; 513*fcf3ce44SJohn Forte *d = source_address ? *s : 0; 514*fcf3ce44SJohn Forte usec_delay(50); 515*fcf3ce44SJohn Forte *d = FEPROM_PROGRAM_VERIFY; 516*fcf3ce44SJohn Forte usec_delay(30); 517*fcf3ce44SJohn Forte if (*d == (source_address ? *s : 0)) 518*fcf3ce44SJohn Forte break; 519*fcf3ce44SJohn Forte } 520*fcf3ce44SJohn Forte 521*fcf3ce44SJohn Forte if (pulse >= FEPROM_MAX_PROGRAM) { 522*fcf3ce44SJohn Forte *dest_address = FEPROM_RESET; 523*fcf3ce44SJohn Forte return (0); 524*fcf3ce44SJohn Forte } 525*fcf3ce44SJohn Forte } 526*fcf3ce44SJohn Forte 527*fcf3ce44SJohn Forte *dest_address = FEPROM_RESET; 528*fcf3ce44SJohn Forte return (1); 529*fcf3ce44SJohn Forte } 530*fcf3ce44SJohn Forte 531*fcf3ce44SJohn Forte /* 532*fcf3ce44SJohn Forte * erase an FEprom using Fowler-Nordheim tunneling. 533*fcf3ce44SJohn Forte */ 534*fcf3ce44SJohn Forte static int 535*fcf3ce44SJohn Forte feprom_erase(volatile uchar_t *dest_address, volatile socal_reg_t *regs) 536*fcf3ce44SJohn Forte { 537*fcf3ce44SJohn Forte int i; 538*fcf3ce44SJohn Forte volatile uchar_t *d = dest_address; 539*fcf3ce44SJohn Forte 540*fcf3ce44SJohn Forte *d = FEPROM_ERASE; 541*fcf3ce44SJohn Forte usec_delay(50); 542*fcf3ce44SJohn Forte *d = FEPROM_ERASE; 543*fcf3ce44SJohn Forte 544*fcf3ce44SJohn Forte usec_delay(10000); /* wait 10ms while FEprom erases */ 545*fcf3ce44SJohn Forte 546*fcf3ce44SJohn Forte for (i = 0; i < FEPROM_SIZE; i++) { 547*fcf3ce44SJohn Forte 548*fcf3ce44SJohn Forte if ((i & 0xffff) == 0) { 549*fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000); 550*fcf3ce44SJohn Forte regs->socal_cr.w |= i & 0x30000; 551*fcf3ce44SJohn Forte } 552*fcf3ce44SJohn Forte 553*fcf3ce44SJohn Forte d = dest_address + (i & 0xffff); 554*fcf3ce44SJohn Forte 555*fcf3ce44SJohn Forte *d = FEPROM_ERASE_VERIFY; 556*fcf3ce44SJohn Forte usec_delay(50); 557*fcf3ce44SJohn Forte if (*d != 0xff) { 558*fcf3ce44SJohn Forte *dest_address = FEPROM_RESET; 559*fcf3ce44SJohn Forte return (0); 560*fcf3ce44SJohn Forte } 561*fcf3ce44SJohn Forte } 562*fcf3ce44SJohn Forte *dest_address = FEPROM_RESET; 563*fcf3ce44SJohn Forte return (1); 564*fcf3ce44SJohn Forte } 565*fcf3ce44SJohn Forte 566*fcf3ce44SJohn Forte static void 567*fcf3ce44SJohn Forte usec_delay(int s) 568*fcf3ce44SJohn Forte { 569*fcf3ce44SJohn Forte hrtime_t now, then; 570*fcf3ce44SJohn Forte 571*fcf3ce44SJohn Forte now = gethrtime(); 572*fcf3ce44SJohn Forte then = now + s*1000; 573*fcf3ce44SJohn Forte do { 574*fcf3ce44SJohn Forte now = gethrtime(); 575*fcf3ce44SJohn Forte } while (now < then); 576*fcf3ce44SJohn Forte } 577*fcf3ce44SJohn Forte 578*fcf3ce44SJohn Forte static uint_t 579*fcf3ce44SJohn Forte getsbuslist(void) 580*fcf3ce44SJohn Forte { 581*fcf3ce44SJohn Forte int devcnt = 0; 582*fcf3ce44SJohn Forte char devpath[PATH_MAX]; 583*fcf3ce44SJohn Forte 584*fcf3ce44SJohn Forte /* We're searching the /devices directory, so... */ 585*fcf3ce44SJohn Forte (void) strcpy(devpath, "/devices"); 586*fcf3ce44SJohn Forte 587*fcf3ce44SJohn Forte /* get the directory entries under /devices for socal sbusmem */ 588*fcf3ce44SJohn Forte (void) getsocpath(devpath, (int *)&devcnt); 589*fcf3ce44SJohn Forte 590*fcf3ce44SJohn Forte return (devcnt); 591*fcf3ce44SJohn Forte } 592*fcf3ce44SJohn Forte 593*fcf3ce44SJohn Forte static void 594*fcf3ce44SJohn Forte getbootdev(unsigned int verbose) 595*fcf3ce44SJohn Forte { 596*fcf3ce44SJohn Forte char *df = "df /"; 597*fcf3ce44SJohn Forte FILE *ptr; 598*fcf3ce44SJohn Forte char *p, *p1; 599*fcf3ce44SJohn Forte char bootdev[PATH_MAX]; 600*fcf3ce44SJohn Forte char buf[BUFSIZ]; 601*fcf3ce44SJohn Forte int foundroot = 0; 602*fcf3ce44SJohn Forte 603*fcf3ce44SJohn Forte 604*fcf3ce44SJohn Forte if ((ptr = popen(df, "r")) != NULL) { 605*fcf3ce44SJohn Forte while (fgets(buf, BUFSIZ, ptr) != NULL) { 606*fcf3ce44SJohn Forte if (p = strstr(buf, "/dev/dsk/")) { 607*fcf3ce44SJohn Forte (void) memset((char *)&bootdev[0], 0, 608*fcf3ce44SJohn Forte PATH_MAX); 609*fcf3ce44SJohn Forte p1 = p; 610*fcf3ce44SJohn Forte while (*p1 != '\0') { 611*fcf3ce44SJohn Forte if (!isalnum(*p1) && (*p1 != '/')) 612*fcf3ce44SJohn Forte *p1 = ' '; 613*fcf3ce44SJohn Forte p1++; 614*fcf3ce44SJohn Forte } 615*fcf3ce44SJohn Forte (void) sscanf(p, "%s", bootdev); 616*fcf3ce44SJohn Forte foundroot = 1; 617*fcf3ce44SJohn Forte } 618*fcf3ce44SJohn Forte } 619*fcf3ce44SJohn Forte if (!foundroot) { 620*fcf3ce44SJohn Forte if (verbose) 621*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(44, 622*fcf3ce44SJohn Forte "root is not on a local disk!\n")); 623*fcf3ce44SJohn Forte (void) memset((char *)&bootpath[0], 0, PATH_MAX); 624*fcf3ce44SJohn Forte return; 625*fcf3ce44SJohn Forte } 626*fcf3ce44SJohn Forte (void) pclose(ptr); 627*fcf3ce44SJohn Forte if (bootdev[0]) { 628*fcf3ce44SJohn Forte char *ls; 629*fcf3ce44SJohn Forte char *p1; 630*fcf3ce44SJohn Forte char *p2 = NULL; 631*fcf3ce44SJohn Forte char *sbusmem = "/sbusmem@"; 632*fcf3ce44SJohn Forte char *slot = ",0:slot"; 633*fcf3ce44SJohn Forte 634*fcf3ce44SJohn Forte ls = (char *)malloc(PATH_MAX); 635*fcf3ce44SJohn Forte (void) memset((char *)ls, NULL, PATH_MAX); 636*fcf3ce44SJohn Forte (void) strcpy(ls, "ls -l "); 637*fcf3ce44SJohn Forte (void) strcat(ls, bootdev); 638*fcf3ce44SJohn Forte if ((ptr = popen(ls, "r")) != NULL) { 639*fcf3ce44SJohn Forte while (fgets(buf, BUFSIZ, ptr) != NULL) { 640*fcf3ce44SJohn Forte if (p = strstr(buf, "/devices")) { 641*fcf3ce44SJohn Forte if (p1 = strstr(buf, "sbus")) { 642*fcf3ce44SJohn Forte while (*p1 != '/') 643*fcf3ce44SJohn Forte p1++; 644*fcf3ce44SJohn Forte p2 = strstr(p1, "@"); 645*fcf3ce44SJohn Forte ++p2; 646*fcf3ce44SJohn Forte *p1 = '\0'; 647*fcf3ce44SJohn Forte } else { 648*fcf3ce44SJohn Forte if (p1 = strstr(buf, 649*fcf3ce44SJohn Forte SOCAL_STR)) { 650*fcf3ce44SJohn Forte p2 = strstr(p1, "@"); 651*fcf3ce44SJohn Forte ++p2; 652*fcf3ce44SJohn Forte --p1; 653*fcf3ce44SJohn Forte *p1 = '\0'; 654*fcf3ce44SJohn Forte } 655*fcf3ce44SJohn Forte } 656*fcf3ce44SJohn Forte } 657*fcf3ce44SJohn Forte } 658*fcf3ce44SJohn Forte (void) pclose(ptr); 659*fcf3ce44SJohn Forte } 660*fcf3ce44SJohn Forte (void) memset((char *)&bootdev[0], 0, PATH_MAX); 661*fcf3ce44SJohn Forte (void) sscanf(p, "%s", bootdev); 662*fcf3ce44SJohn Forte (void) memset((char *)&bootpath[0], 0, PATH_MAX); 663*fcf3ce44SJohn Forte (void) strcat(bootpath, bootdev); 664*fcf3ce44SJohn Forte (void) strcat(bootpath, sbusmem); 665*fcf3ce44SJohn Forte if (p2) { 666*fcf3ce44SJohn Forte (void) strncat(bootpath, p2, 1); 667*fcf3ce44SJohn Forte (void) strcat(bootpath, slot); 668*fcf3ce44SJohn Forte (void) strncat(bootpath, p2, 1); 669*fcf3ce44SJohn Forte } 670*fcf3ce44SJohn Forte } 671*fcf3ce44SJohn Forte } 672*fcf3ce44SJohn Forte } 673*fcf3ce44SJohn Forte 674*fcf3ce44SJohn Forte /* 675*fcf3ce44SJohn Forte * This function reads "size" bytes from the FC100/S PROM. 676*fcf3ce44SJohn Forte * source_address: PROM address 677*fcf3ce44SJohn Forte * dest_address: local memeory 678*fcf3ce44SJohn Forte * offset: Location in PROM to start reading from. 679*fcf3ce44SJohn Forte */ 680*fcf3ce44SJohn Forte static void 681*fcf3ce44SJohn Forte feprom_read(uchar_t *source_address, uchar_t *dest_address, 682*fcf3ce44SJohn Forte int offset, int size, volatile socal_reg_t *regs) 683*fcf3ce44SJohn Forte { 684*fcf3ce44SJohn Forte uchar_t *s = source_address; 685*fcf3ce44SJohn Forte uchar_t *d = dest_address; 686*fcf3ce44SJohn Forte int i = offset; 687*fcf3ce44SJohn Forte 688*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 689*fcf3ce44SJohn Forte (void) fprintf(stdout, 690*fcf3ce44SJohn Forte " feprom_read: selecting bank %d\n", 691*fcf3ce44SJohn Forte (i&0xf0000)>>16); 692*fcf3ce44SJohn Forte if (size <= 8) { 693*fcf3ce44SJohn Forte (void) fprintf(stdout, " Data read: "); 694*fcf3ce44SJohn Forte } 695*fcf3ce44SJohn Forte } 696*fcf3ce44SJohn Forte regs->socal_cr.w = i & 0xf0000; 697*fcf3ce44SJohn Forte s = source_address + (i & 0xffff); 698*fcf3ce44SJohn Forte *s = FEPROM_READ_MEMORY; 699*fcf3ce44SJohn Forte usec_delay(6); 700*fcf3ce44SJohn Forte for (; s < source_address + (i & 0xffff) + size; d++, s++) { 701*fcf3ce44SJohn Forte *d = *s; 702*fcf3ce44SJohn Forte if ((getenv("_LUX_D_DEBUG") != NULL) && 703*fcf3ce44SJohn Forte (size <= 8)) { 704*fcf3ce44SJohn Forte (void) fprintf(stdout, "0x%x ", *d); 705*fcf3ce44SJohn Forte } 706*fcf3ce44SJohn Forte } 707*fcf3ce44SJohn Forte if ((getenv("_LUX_D_DEBUG") != NULL) && 708*fcf3ce44SJohn Forte (size <= 8)) { 709*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n From offset: 0x%x\n", 710*fcf3ce44SJohn Forte offset); 711*fcf3ce44SJohn Forte } 712*fcf3ce44SJohn Forte } 713*fcf3ce44SJohn Forte 714*fcf3ce44SJohn Forte 715*fcf3ce44SJohn Forte static int 716*fcf3ce44SJohn Forte load_file(char *file, caddr_t prom, volatile socal_reg_t *regs) 717*fcf3ce44SJohn Forte { 718*fcf3ce44SJohn Forte uint_t wwn_d8, wwn_lo; 719*fcf3ce44SJohn Forte uint_t wwn_hi; 720*fcf3ce44SJohn Forte int ffd = open(file, 0); 721*fcf3ce44SJohn Forte 722*fcf3ce44SJohn Forte wwn_hi = FEPROM_SUN_WWN; 723*fcf3ce44SJohn Forte 724*fcf3ce44SJohn Forte if (ffd < 0) { 725*fcf3ce44SJohn Forte perror(MSGSTR(4524, "open of file")); 726*fcf3ce44SJohn Forte exit(1); 727*fcf3ce44SJohn Forte } 728*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4525, "Loading FCode: %s\n"), file); 729*fcf3ce44SJohn Forte 730*fcf3ce44SJohn Forte if (read(ffd, &exec, sizeof (exec)) != sizeof (exec)) { 731*fcf3ce44SJohn Forte perror(MSGSTR(4526, "read exec")); 732*fcf3ce44SJohn Forte exit(1); 733*fcf3ce44SJohn Forte } 734*fcf3ce44SJohn Forte 735*fcf3ce44SJohn Forte if (exec.a_trsize || exec.a_drsize) { 736*fcf3ce44SJohn Forte (void) fprintf(stderr, 737*fcf3ce44SJohn Forte MSGSTR(4527, "%s: is relocatable\n"), file); 738*fcf3ce44SJohn Forte exit(1); 739*fcf3ce44SJohn Forte } 740*fcf3ce44SJohn Forte 741*fcf3ce44SJohn Forte if (exec.a_data || exec.a_bss) { 742*fcf3ce44SJohn Forte (void) fprintf(stderr, 743*fcf3ce44SJohn Forte MSGSTR(4528, "%s: has data or bss\n"), file); 744*fcf3ce44SJohn Forte exit(1); 745*fcf3ce44SJohn Forte } 746*fcf3ce44SJohn Forte 747*fcf3ce44SJohn Forte if (exec.a_machtype != M_SPARC) { 748*fcf3ce44SJohn Forte (void) fprintf(stderr, 749*fcf3ce44SJohn Forte MSGSTR(4529, "%s: not for SPARC\n"), file); 750*fcf3ce44SJohn Forte exit(1); 751*fcf3ce44SJohn Forte } 752*fcf3ce44SJohn Forte 753*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4530, 754*fcf3ce44SJohn Forte "Loading 0x%x bytes from %s at offset 0x%x\n"), 755*fcf3ce44SJohn Forte (int)exec.a_text, file, 0); 756*fcf3ce44SJohn Forte 757*fcf3ce44SJohn Forte if (read(ffd, &buffer, exec.a_text) != exec.a_text) { 758*fcf3ce44SJohn Forte perror(MSGSTR(4531, "read")); 759*fcf3ce44SJohn Forte exit(1); 760*fcf3ce44SJohn Forte } 761*fcf3ce44SJohn Forte 762*fcf3ce44SJohn Forte (void) close(ffd); 763*fcf3ce44SJohn Forte 764*fcf3ce44SJohn Forte feprom_read((uchar_t *)prom, (uchar_t *)&wwn_d8, 765*fcf3ce44SJohn Forte FEPROM_WWN_OFFSET, 4, regs); 766*fcf3ce44SJohn Forte feprom_read((uchar_t *)prom, (uchar_t *)&wwn_lo, 767*fcf3ce44SJohn Forte FEPROM_WWN_OFFSET + 4, 4, regs); 768*fcf3ce44SJohn Forte wwn_hi |= wwn_d8 & 0x0f; /* only last digit is interesting */ 769*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 770*fcf3ce44SJohn Forte (void) fprintf(stdout, 771*fcf3ce44SJohn Forte " load_file: Writing WWN hi:0x%x lo:0x%x " 772*fcf3ce44SJohn Forte "to the FC100/S PROM\n", wwn_hi, wwn_lo); 773*fcf3ce44SJohn Forte } 774*fcf3ce44SJohn Forte /* put wwn into buffer location */ 775*fcf3ce44SJohn Forte bcopy((const void *)&wwn_hi, 776*fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET], 777*fcf3ce44SJohn Forte sizeof (wwn_hi)); 778*fcf3ce44SJohn Forte bcopy((const void *)&wwn_lo, 779*fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 4], 780*fcf3ce44SJohn Forte sizeof (wwn_lo)); 781*fcf3ce44SJohn Forte bcopy((const void *)&wwn_hi, 782*fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 8], 783*fcf3ce44SJohn Forte sizeof (wwn_hi)); 784*fcf3ce44SJohn Forte bcopy((const void *)&wwn_lo, 785*fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 0xc], 786*fcf3ce44SJohn Forte sizeof (wwn_lo)); 787*fcf3ce44SJohn Forte 788*fcf3ce44SJohn Forte if (feprom_program((uchar_t *)buffer, (uchar_t *)prom, regs) == 0) { 789*fcf3ce44SJohn Forte /* here 0 means failure */ 790*fcf3ce44SJohn Forte return (1); 791*fcf3ce44SJohn Forte } 792*fcf3ce44SJohn Forte 793*fcf3ce44SJohn Forte return (0); 794*fcf3ce44SJohn Forte } 795*fcf3ce44SJohn Forte 796*fcf3ce44SJohn Forte static int 797*fcf3ce44SJohn Forte warn(void) 798*fcf3ce44SJohn Forte { 799*fcf3ce44SJohn Forte char input[1024]; 800*fcf3ce44SJohn Forte 801*fcf3ce44SJohn Forte input[0] = '\0'; 802*fcf3ce44SJohn Forte 803*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4532, 804*fcf3ce44SJohn Forte "\nWARNING!! This program will update the FCode in this FC100/S Sbus Card.\n")); 805*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4533, 806*fcf3ce44SJohn Forte "This may take a few (5) minutes. Please be patient.\n")); 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte loop1: 809*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4534, 810*fcf3ce44SJohn Forte "Do you wish to continue ? (y/n) ")); 811*fcf3ce44SJohn Forte 812*fcf3ce44SJohn Forte (void) gets(input); 813*fcf3ce44SJohn Forte 814*fcf3ce44SJohn Forte if ((strcmp(input, MSGSTR(4535, "y")) == 0) || 815*fcf3ce44SJohn Forte (strcmp(input, MSGSTR(40, "yes")) == 0)) { 816*fcf3ce44SJohn Forte return (FOUND); 817*fcf3ce44SJohn Forte } else if ((strcmp(input, MSGSTR(4536, "n")) == 0) || 818*fcf3ce44SJohn Forte (strcmp(input, MSGSTR(45, "no")) == 0)) { 819*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4537, "Not Downloading FCode\n")); 820*fcf3ce44SJohn Forte return (NOT_FOUND); 821*fcf3ce44SJohn Forte } else { 822*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4538, "Invalid input\n")); 823*fcf3ce44SJohn Forte goto loop1; 824*fcf3ce44SJohn Forte } 825*fcf3ce44SJohn Forte } 826*fcf3ce44SJohn Forte 827*fcf3ce44SJohn Forte 828*fcf3ce44SJohn Forte /* 829*fcf3ce44SJohn Forte * getsocpath(): 830*fcf3ce44SJohn Forte * Searches the /devices directory recursively returning all soc_name 831*fcf3ce44SJohn Forte * entries in sbussoc_list (global). This excludes port entries and 832*fcf3ce44SJohn Forte * onboard socal (which leaves only directory entries with 833*fcf3ce44SJohn Forte * soc_name included). devcnt is updated to reflect number of soc_name 834*fcf3ce44SJohn Forte * devices found. 835*fcf3ce44SJohn Forte */ 836*fcf3ce44SJohn Forte 837*fcf3ce44SJohn Forte static void 838*fcf3ce44SJohn Forte getsocpath(char *devpath, int *devcnt) 839*fcf3ce44SJohn Forte { 840*fcf3ce44SJohn Forte struct stat statbuf; 841*fcf3ce44SJohn Forte struct dirent *dirp; 842*fcf3ce44SJohn Forte DIR *dp; 843*fcf3ce44SJohn Forte char *ptr; 844*fcf3ce44SJohn Forte 845*fcf3ce44SJohn Forte if (lstat(devpath, &statbuf) < 0) { 846*fcf3ce44SJohn Forte (void) fprintf(stderr, 847*fcf3ce44SJohn Forte MSGSTR(4539, "Error: %s lstat() error\n"), devpath); 848*fcf3ce44SJohn Forte exit(1); 849*fcf3ce44SJohn Forte } 850*fcf3ce44SJohn Forte 851*fcf3ce44SJohn Forte if (S_ISDIR(statbuf.st_mode) == 0) 852*fcf3ce44SJohn Forte /* 853*fcf3ce44SJohn Forte * not a directory so 854*fcf3ce44SJohn Forte * we don't care about it - return 855*fcf3ce44SJohn Forte */ 856*fcf3ce44SJohn Forte return; 857*fcf3ce44SJohn Forte 858*fcf3ce44SJohn Forte else { 859*fcf3ce44SJohn Forte if (strstr(devpath, ONBOARD_SOCAL)) 860*fcf3ce44SJohn Forte return; 861*fcf3ce44SJohn Forte 862*fcf3ce44SJohn Forte if (strstr(devpath, SOCAL_STR)) { 863*fcf3ce44SJohn Forte /* It's a keeper - call the load function */ 864*fcf3ce44SJohn Forte if ((loadsocpath(devpath, devcnt)) < 0) { 865*fcf3ce44SJohn Forte (void) fprintf(stderr, 866*fcf3ce44SJohn Forte MSGSTR(4540, "Error: Cannot set device list\n"), 867*fcf3ce44SJohn Forte devpath); 868*fcf3ce44SJohn Forte exit(1); 869*fcf3ce44SJohn Forte } 870*fcf3ce44SJohn Forte /* 871*fcf3ce44SJohn Forte * if socal directory - return, 872*fcf3ce44SJohn Forte * nothing else to see here 873*fcf3ce44SJohn Forte */ 874*fcf3ce44SJohn Forte return; 875*fcf3ce44SJohn Forte } 876*fcf3ce44SJohn Forte } 877*fcf3ce44SJohn Forte 878*fcf3ce44SJohn Forte /* 879*fcf3ce44SJohn Forte * It's a directory. Call ourself to 880*fcf3ce44SJohn Forte * traverse the path(s) 881*fcf3ce44SJohn Forte */ 882*fcf3ce44SJohn Forte 883*fcf3ce44SJohn Forte ptr = devpath + strlen(devpath); 884*fcf3ce44SJohn Forte *ptr++ = '/'; 885*fcf3ce44SJohn Forte *ptr = 0; 886*fcf3ce44SJohn Forte 887*fcf3ce44SJohn Forte /* Forget the /devices/pseudo/ directory */ 888*fcf3ce44SJohn Forte if (strcmp(devpath, "/devices/pseudo/") == 0) 889*fcf3ce44SJohn Forte return; 890*fcf3ce44SJohn Forte 891*fcf3ce44SJohn Forte if ((dp = opendir(devpath)) == NULL) { 892*fcf3ce44SJohn Forte (void) fprintf(stderr, 893*fcf3ce44SJohn Forte MSGSTR(4541, "Error: %s Can't read directory\n"), devpath); 894*fcf3ce44SJohn Forte exit(1); 895*fcf3ce44SJohn Forte } 896*fcf3ce44SJohn Forte 897*fcf3ce44SJohn Forte while ((dirp = readdir(dp)) != NULL) { 898*fcf3ce44SJohn Forte 899*fcf3ce44SJohn Forte if (strcmp(dirp->d_name, ".") == 0 || 900*fcf3ce44SJohn Forte strcmp(dirp->d_name, "..") == 0) 901*fcf3ce44SJohn Forte continue; 902*fcf3ce44SJohn Forte 903*fcf3ce44SJohn Forte (void) strcpy(ptr, dirp->d_name); /* append name */ 904*fcf3ce44SJohn Forte getsocpath(devpath, devcnt); 905*fcf3ce44SJohn Forte } 906*fcf3ce44SJohn Forte 907*fcf3ce44SJohn Forte if (closedir(dp) < 0) { 908*fcf3ce44SJohn Forte (void) fprintf(stderr, 909*fcf3ce44SJohn Forte MSGSTR(4542, "Error: %s Can't close directory\n"), devpath); 910*fcf3ce44SJohn Forte exit(1); 911*fcf3ce44SJohn Forte } 912*fcf3ce44SJohn Forte } 913*fcf3ce44SJohn Forte 914*fcf3ce44SJohn Forte static int 915*fcf3ce44SJohn Forte loadsocpath(const char *pathname, int *devcnt) 916*fcf3ce44SJohn Forte { 917*fcf3ce44SJohn Forte int ret = 0; 918*fcf3ce44SJohn Forte int len; 919*fcf3ce44SJohn Forte int len_tmp; 920*fcf3ce44SJohn Forte char *sp; 921*fcf3ce44SJohn Forte char *sp_tmp; 922*fcf3ce44SJohn Forte char buffer[PATH_MAX]; 923*fcf3ce44SJohn Forte 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte /* 926*fcf3ce44SJohn Forte * Okay we found a device, now let's load it in to sbussoc_list 927*fcf3ce44SJohn Forte * and load the sbusmem file into sbus_list 928*fcf3ce44SJohn Forte */ 929*fcf3ce44SJohn Forte 930*fcf3ce44SJohn Forte if (pathname != NULL && *devcnt < HBA_MAX) { 931*fcf3ce44SJohn Forte (void) strcpy(sbussoc_list[*devcnt], pathname); 932*fcf3ce44SJohn Forte if (sp_tmp = strstr(sbussoc_list[*devcnt], SOCAL_STR)) { 933*fcf3ce44SJohn Forte sp = sp_tmp; 934*fcf3ce44SJohn Forte /* len_tmp will be len of "SUNW,socal@" */ 935*fcf3ce44SJohn Forte len_tmp = SOCAL_STR_LEN + 1; 936*fcf3ce44SJohn Forte } 937*fcf3ce44SJohn Forte len = strlen(sbussoc_list[*devcnt]) - strlen(sp); 938*fcf3ce44SJohn Forte (void) strncpy(buffer, sbussoc_list[*devcnt], len); 939*fcf3ce44SJohn Forte buffer[len] = '\0'; 940*fcf3ce44SJohn Forte sp += len_tmp; 941*fcf3ce44SJohn Forte (void) sprintf(sbus_list[*devcnt], "%ssbusmem@%c,0:slot%c", 942*fcf3ce44SJohn Forte buffer, sp[0], sp[0]); 943*fcf3ce44SJohn Forte *devcnt += 1; 944*fcf3ce44SJohn Forte } 945*fcf3ce44SJohn Forte else 946*fcf3ce44SJohn Forte ret = -1; 947*fcf3ce44SJohn Forte return (ret); 948*fcf3ce44SJohn Forte } 949