fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * I18N message number ranges
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This file: 21000 - 21499
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Shared common messages: 1 - 1999
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Functions to support the download of FCode to PCI HBAs
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Qlogic ISP21XX/22XX boards: FC100/P single port, ISP2200 dual port
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and Emulex cards
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Error codes - used by the fcode_load_file routine */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define FCODE_SUCCESS 0 /* successful completion */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define FCODE_LOAD_FAILURE 1 /* general failure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define FCODE_IOCTL_FAILURE 2 /* FCODE ioctl download failure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * EMULEX Fcode attributes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Emulex specific error codes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Diagnostic error codes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Download image contains bad data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Download image not compatible with current hardware */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define EMLX_IMAGE_INCOMPATIBLE (EMLX_ERRNO_START + 2)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Unable to take adapter offline */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Image download failed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define EMLX_OFFLINE_FAILED (EMLX_ERRNO_START + 4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is just a random value chosen to identify Sbus Fcodes. Sbus FCode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for Ivory is based on a 2200 chip but this value does not reflect that.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Global variables */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char fc_trans[] = "SUNW,ifp"; /* fibre channel transport */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char fp_trans[] = "SUNW,qlc"; /* fca layer driver */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char fp_trans_id[] = "fp@"; /* transport layer id */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char qlgc2100[] = "FC100/P"; /* product name for 2100 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char qlgc2200[] = "ISP2200"; /* product name for 2200 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char qlgc2300[] = "ISP2300"; /* product name for 2300 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char qlgc2312[] = "ISP2312"; /* product name for 2312 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The variable qlgc2200Sbus represents the string which is always the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * starting string of the version information in an ISP2200 Sbus Fcode.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char qlgc2200Sbus[] = "ISP2200 Sbus FC-AL Host Adapter Driver";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Internal functions */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int q_load_file(int, char *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int q_getdevctlpath(char *, int *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int q_warn(int);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int q_findversion(int, int, uchar_t *, uint16_t *);
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reedstatic int q_findfileversion(char *, uchar_t *, uint16_t *, int, int *);
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reedstatic int q_findSbusfile(int, int *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int memstrstr(char *, char *, int, int);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int fcode_load_file(int, char *, int *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Functions to support Fcode download for Emulex HBAs
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int emulex_fcodeversion(di_node_t, uchar_t *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void handle_emulex_error(int, char *);
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * Searches for and updates the cards. This is the "main" function
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and will give the output to the user by calling the subfunctions.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * args: FCode file; if NULL only the current FCode version is printed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fd, fcode_fd = -1, errnum = 0, devcnt = 0, retval = 0, isSbus = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static uchar_t version[MAXNAMELEN], version_file[MAXNAMELEN];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte void (*sigint)(); /* to store default SIGTERM setting */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static struct utmpx *utmpp = NULL; /* pointer for getutxent() */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The variables port1 and port2 are used to store the bus id
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * e.g. the bus id for this path:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * /devices/sbus@12,0/SUNW,qlc@2,30000/fp@0,0:devctl
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is "sbus@12". They are initialized to a random value and are
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * set such that they are not equal initially.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check for a valid file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), file);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (read(fcode_fd, fcode_buf, FCODE_HDR) != FCODE_HDR) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if it's SBUS FCode by calling q_findSbusfile
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if it is then isSbus will be 1, if not it will be 0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in case of an error, it will be -1
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FCode header check - make sure it's PCI FCode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Structure of FCode header (byte# refers to byte numbering
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in FCode spec, not the byte# of our fcode_buf buffer):
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * header byte 00 0x55 prom signature byte one
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * byte 01 0xaa prom signature byte two
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * data byte 00-03 P C I R
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * header byte 32 0x55
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * byte 33 0xaa
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * data byte 60-63 P C I R
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The second format with an offset of 32 is used for ifp prom
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: %s is not a valid FC100/P, "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "ISP2200, ISP23xx FCode file.\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check for single user mode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* get bootpath */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get count of, and names of PCI slots with ifp device control
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (devctl) nodes. Search /devices.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (q_getdevctlpath(devpath, (int *)&devcnt) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\n Found Path to %d FC100/P, ISP2200, ISP23xx Devices\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Could not get /devices path to FC100/P,"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "ISP2200, ISP23xx Cards.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < devcnt; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy((char *)phys_path, &pcibus_list[i][0],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21006, "\n Opening Device: %s\n"), &pcibus_list[i][0]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if the device is valid */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fd = open(&pcibus_list[i][0], O_RDWR)) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check FCode version present on the adapter (at last boot)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (q_findversion(verbose, i, (uchar_t *)&version[0],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Detected FCode Version:\tNo version available for this FCode\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For ISP2200, Sbus HBA, do just 1 download
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for both the ports (dual port HBA)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Here it is assumed that readdir() always
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * returns the paths in pcibus_list[] in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sorted order.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "/n New FCode has already been downloaded "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "to this ISP2200 SBus HBA Card.\n"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "It is sufficient to download to one "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "port of the ISP2200 SBus HBA Card. "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Moving on...\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check version of the supplied FCode file (once)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " New FCode Version:\t\t%s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Load the New FCode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Give warning if file doesn't appear to be correct
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Disable user-interrupt Control-C */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Load FCode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &pcibus_list[i][0]) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Successful FCode download: %s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: FCode download failed: %s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Restore SIGINT (user interrupt) setting */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrieve the version banner from the card
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * uses ioctl: FCIO_FCODE_MCODE_VERSION FCode revision
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteq_findversion(int verbose, int index, uchar_t *version, uint16_t *chip_id)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((version_buffer = (struct ifp_fm_version *)malloc(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, version_buffer) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Driver interface FCIO_FCODE_MCODE_VERSION failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Need a way to get card MCODE (firmware) to track certain HW bugs */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, " Device %i: QLGC chip_id %x\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, " FCode:%s\n MCODE:%s\n PROM:%s\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (strstr(&pcibus_list[index][0], fp_trans)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get the fcode and prom's fw version
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * using the fp ioctls. Currently, we pass
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * only the fcode version to the calling function
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and ignore the FW version (using the existing
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * implementation).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Get the fcode version */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Information read operation */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* wait 30 secs */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Get type of card from product name in FCode version banner */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrieve the version banner and file type (2100 or 2200) from the file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteq_findfileversion(char *dl_fcode, uchar_t *version_file, uint16_t *file_id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get file version from FCode for 2100 or 2202
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Ok, we're just checking for 2200 here. If it is we need
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to offset to find the banner.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this is an ISP2200 Sbus Fcode file, then search for the string
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * "ISP2200 FC-AL Host Adapter Driver" in the whole fcode file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Subtract 111 from the offset we add below for PCI Fcodes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Banner length varies; grab banner to end of date marker yr/mo/da */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (mark = (111 + qlc_offset); mark < (191 + qlc_offset); mark++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy(temp, (char *)&dl_fcode[mark], 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Find if the FCode file is a ISP2200 SBUS Fcode file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((sbus_info = (char *)malloc(file_size)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Search for the version string in the whole file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((*sbus_offset = memstrstr((char *)sbus_info, qlgc2200Sbus,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Build a list of all the devctl entries for all the 2100/2200 based adapters
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21016, "Error: %s lstat() error\n"), devpath);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (strstr(devpath, fp_trans_id) && strstr(devpath, fp_trans))) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Verify the path is valid */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * not a directory so
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we don't care about it - return
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * It's a directory. Call ourself to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * traverse the path(s)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Forget the /devices/pseudo/ directory */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21017, "Error: %s Can't read directory\n"), devpath);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strcpy(ptr, dirp->d_name); /* append name */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21018, "Error: Can't close directory %s\n"), devpath);
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * Get the boot device. Cannot load FCode to current boot device.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Boot devices under volume management will prompt a warning.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *p = NULL, *p1 = NULL; /* p = full device, p1 = chunk to rm */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), MNTTAB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Cannot get boot device, check %s.\n"), MNTTAB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If we can't get a link, we may be dealing with a volume mgr
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * so give a warning. If a colon is present, we likely have a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * non-local disk or cd-rom, so no warning is necessary.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * e.g. /devices/pci@1f,4000/scsi@3/sd@6,0:b (cdrom, no link) or
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * storage-e4:/blah/blah remote boot server
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\nWarning: Cannot read boot device link, check %s.\n"), MNTTAB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Do not upgrade FCode on adapters controlling the boot device.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copy boot device path to bootpath. First remove leading
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * path junk (../../..) then if it's an ifp device, chop off
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the disk and add the devctl to the end of the path.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Load FCode to card.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uses ioctl: IFPIO_FCODE_DOWNLOAD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (ifp_download_t) + fcode_size)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (read(fcode_fd, download_p->dl_fcode, fcode_size)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21000, "Error: Could not open %s\n"), device);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file_id |= (download_p->dl_fcode[0x43] << 8) & 0xff00;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ioctl(dev_fd, IFPIO_FCODE_DOWNLOAD, download_p) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Driver interface IFPIO_FCODE_DOWNLOAD failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Information read operation */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Issue warning strings and loop for Yes/No user interaction
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * err# 0 -- we're ok, warn for pending FCode load
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * 1 -- not in single user mode
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * 2 -- can't get chip_id
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * 3 -- card and file do not have same type (2100/2200)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\nWarning: System is not in single-user mode.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Loading FCode will reset the adapter and terminate I/O activity\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Warning: FCode is missing or existing FCode has"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " unrecognized version.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Warning: New FCode file version does not match this"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " board type. Skipping...\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\nWARNING!! This program will update the FCode in this"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " and Emulex devices.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "This may take a few (5) minutes. Please be patient.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Do you wish to continue ? (y/n) "));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((strcmp(input, MSGSTR(21033, "n")) == 0) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSGSTR(21035, "Invalid input\n"));
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * Name : memstrstr
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Input : pointer to buf1, pointer to buf2, size of buf1, size of buf2
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * Offset of the start of contents-of-buf2 in buf1 if it is found
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed * -1 if buf1 does not contain contents of buf2
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This function works similar to strstr(). The difference is that null
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * characters in the buffer are treated like any other character. So, buf1
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and buf2 can have embedded null characters in them.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortememstrstr(char *s1, char *s2, int size1, int size2)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (count1 = 0; count1 < (size1 - size2 + 1); count1++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (--count2 == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * generic fcode load file routine. given a file descriptor to a fcode file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * this routine will issue the FCIO_DOWNLOAD_FCODE ioctl to the given
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * device. Any ioctl errors will be returned in fcio_errno
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Arguments:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fcode_fd file descriptor to a fcode file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * device path to the device we will be downloading the fcode onto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fcio_errno pointer to an int that will be used to return any errors
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * back to the caller
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrurn Values:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 0 successful download
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * >0 otherwise
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefcode_load_file(int fcode_fd, char *device, int *fcio_errno)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21122, "Error: Could not open %s, failed "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Searches for and updates the fcode for Emulex HBA cards
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * args: FCode file; if NULL only the current FCode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * version is printed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static char ver_file[EMULEX_FCODE_VERSION_LENGTH];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* set the fcode download flag */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check for a valid file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21118, "Error: Could not open %s, failed "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check for single user mode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* get bootpath */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Download the Fcode to all the emulex cards found
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Create a snapshot of the kernel device tree */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Could not get /devices path to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Emulex Devices.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* point to first node which matches emulex driver */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Could not find any emulex cards
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\n Found Path to %d Emulex Devices.\n"), devcnt);
c1911bae1f52a21ee68eafb8e35680d3e2ef0401Reed /* Found an attached node */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "\n Found Path to %d Emulex Devices.\n"), devcnt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Traverse device tree to find all emulex cards
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Found an attached node */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Found a node with "port" property */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if the device is valid */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21121, "Error: Could not open %s, failed "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check FCode version present on the adapter
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (at last boot)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte memset(prom_ver_data, 0, sizeof (prom_ver_data));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (emulex_fcodeversion(node, (uchar_t *)&prom_ver_data[0])
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Detected FCode Version:\tNo version available for this FCode\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Detected FCode Version:\t%s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (emulex_fcode_reader(fcode_fd, "fcode-version",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " New FCode Version:\t\t%s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Load the New FCode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Give warning if file doesn't appear to be correct
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Disable user-interrupt Control-C */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Load FCode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " Successful FCode download: %s\n"),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Restore SIGINT (user interrupt) setting */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrieve the version from the card.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uses PROM properties
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteemulex_fcodeversion(di_node_t node, uchar_t *ver) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check to make sure ver is not NULL */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte promprop = di_prom_prop_next(ph, node, promprop)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrieves information from the Emulex fcode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Given a pattern, this routine will look for this pattern in the fcode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and if found will return the pattern value
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * possible patterns are manufacturer and fcode-version
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteemulex_fcode_reader(int fcode_fd, char *pattern, char *pattern_value,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check the arguments */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!fcode_fd || !pattern_value || pattern_value_size < 8) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((image = (uchar_t *)calloc(image_size, 1)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSGSTR(21013, "Error: Memory allocation failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Read the fcode image file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Initialize */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Default pattern_value string */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Search entire image for pattern string */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Read next two bytes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check second byte first due to endianness */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched then
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check first byte second due to endianness */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then exit loop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Not found. Try again with different endianess */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Initialize */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Search entire 32bit endian image for pattern string */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Read next four bytes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched then exit loop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched then exit loop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched then exit loop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Save byte in circular buffer */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check byte for pattern match */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If no match, then reset pattern */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If complete pattern has been matched then exit loop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Align buffer and eliminate non-printable characters */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (b == sizeof (buffer1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Zero any non-printable characters */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Scan backwards for first non-zero string. This will be the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * version string
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (buffer2[i] != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (; i >= 0; i--) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (buffer2[i] == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * error handling routine to handle emulex error conditions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortehandle_emulex_error(int fcio_errno, char *phys_path) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Fcode download failed. "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Bad fcode image.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (fcio_errno == EMLX_IMAGE_INCOMPATIBLE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Fcode download failed. Fcode is not "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "compatible with card.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Error: FCode download failed: %s\n"),