19517SBill.Taylor@Sun.COM /*
29517SBill.Taylor@Sun.COM * CDDL HEADER START
39517SBill.Taylor@Sun.COM *
49517SBill.Taylor@Sun.COM * The contents of this file are subject to the terms of the
59517SBill.Taylor@Sun.COM * Common Development and Distribution License (the "License").
69517SBill.Taylor@Sun.COM * You may not use this file except in compliance with the License.
79517SBill.Taylor@Sun.COM *
89517SBill.Taylor@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99517SBill.Taylor@Sun.COM * or http://www.opensolaris.org/os/licensing.
109517SBill.Taylor@Sun.COM * See the License for the specific language governing permissions
119517SBill.Taylor@Sun.COM * and limitations under the License.
129517SBill.Taylor@Sun.COM *
139517SBill.Taylor@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149517SBill.Taylor@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159517SBill.Taylor@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169517SBill.Taylor@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179517SBill.Taylor@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189517SBill.Taylor@Sun.COM *
199517SBill.Taylor@Sun.COM * CDDL HEADER END
209517SBill.Taylor@Sun.COM */
219517SBill.Taylor@Sun.COM
229517SBill.Taylor@Sun.COM /*
23*12472SShantkumar.Hiremath@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
249517SBill.Taylor@Sun.COM */
259517SBill.Taylor@Sun.COM
269517SBill.Taylor@Sun.COM /*
279517SBill.Taylor@Sun.COM * IB (InfiniBand) specific functions.
289517SBill.Taylor@Sun.COM */
299517SBill.Taylor@Sun.COM
309517SBill.Taylor@Sun.COM /*
319517SBill.Taylor@Sun.COM * The reference for the functions in this file is the
329517SBill.Taylor@Sun.COM *
339517SBill.Taylor@Sun.COM * Mellanox HCA Flash Programming Application Note
349517SBill.Taylor@Sun.COM * (Mellanox document number 2205AN)
359517SBill.Taylor@Sun.COM * rev 1.44, 2007. Chapter 4 in particular.
369517SBill.Taylor@Sun.COM *
379517SBill.Taylor@Sun.COM * NOTE: this Mellanox document is labelled Confidential
389517SBill.Taylor@Sun.COM * so DO NOT move this file out of usr/closed without
399517SBill.Taylor@Sun.COM * explicit approval from Sun Legal.
409517SBill.Taylor@Sun.COM */
419517SBill.Taylor@Sun.COM
429517SBill.Taylor@Sun.COM /*
439517SBill.Taylor@Sun.COM * IMPORTANT NOTE:
449517SBill.Taylor@Sun.COM * 1. flash read is done in 32 bit quantities, and the driver returns
459517SBill.Taylor@Sun.COM * data in host byteorder form.
469517SBill.Taylor@Sun.COM * 2. flash write is done in 8 bit quantities by the driver.
479517SBill.Taylor@Sun.COM * 3. data in the flash should be in network byteorder (bigendian).
489517SBill.Taylor@Sun.COM * 4. data in image files is in network byteorder form.
499517SBill.Taylor@Sun.COM * 5. data in image structures in memory is kept in network byteorder.
509517SBill.Taylor@Sun.COM * 6. the functions in this file deal with data in host byteorder form.
519517SBill.Taylor@Sun.COM */
529517SBill.Taylor@Sun.COM
539517SBill.Taylor@Sun.COM
549517SBill.Taylor@Sun.COM #include <stdio.h>
559517SBill.Taylor@Sun.COM #include <stdlib.h>
569517SBill.Taylor@Sun.COM #include <unistd.h>
579517SBill.Taylor@Sun.COM #include <sys/types.h>
589517SBill.Taylor@Sun.COM #include <sys/stat.h>
599517SBill.Taylor@Sun.COM #include <sys/sysmacros.h>
609517SBill.Taylor@Sun.COM #include <sys/queue.h>
619517SBill.Taylor@Sun.COM #include <fcntl.h>
629517SBill.Taylor@Sun.COM #include <ctype.h>
639517SBill.Taylor@Sun.COM #include <string.h>
649517SBill.Taylor@Sun.COM #include <strings.h>
659517SBill.Taylor@Sun.COM
669517SBill.Taylor@Sun.COM #include <sys/byteorder.h>
679517SBill.Taylor@Sun.COM
689517SBill.Taylor@Sun.COM #include <libintl.h> /* for gettext(3c) */
699517SBill.Taylor@Sun.COM
709517SBill.Taylor@Sun.COM #include <fwflash/fwflash.h>
719517SBill.Taylor@Sun.COM #include "../../hdrs/MELLANOX.h"
729517SBill.Taylor@Sun.COM #include "../../hdrs/tavor_ib.h"
739517SBill.Taylor@Sun.COM
749517SBill.Taylor@Sun.COM
759517SBill.Taylor@Sun.COM
769517SBill.Taylor@Sun.COM char *devprefix = "/devices";
779517SBill.Taylor@Sun.COM char drivername[] = "tavor\0";
789517SBill.Taylor@Sun.COM char *devsuffix = ":devctl";
799517SBill.Taylor@Sun.COM
809517SBill.Taylor@Sun.COM
819517SBill.Taylor@Sun.COM extern di_node_t rootnode;
829517SBill.Taylor@Sun.COM extern int errno;
839517SBill.Taylor@Sun.COM extern struct fw_plugin *self;
849517SBill.Taylor@Sun.COM extern struct vrfyplugin *verifier;
859517SBill.Taylor@Sun.COM extern int fwflash_debug;
869517SBill.Taylor@Sun.COM
879517SBill.Taylor@Sun.COM
889517SBill.Taylor@Sun.COM /* required functions for this plugin */
899517SBill.Taylor@Sun.COM int fw_readfw(struct devicelist *device, char *filename);
909517SBill.Taylor@Sun.COM int fw_writefw(struct devicelist *device);
919517SBill.Taylor@Sun.COM int fw_identify(int start);
929517SBill.Taylor@Sun.COM int fw_devinfo();
939517SBill.Taylor@Sun.COM
949517SBill.Taylor@Sun.COM
959517SBill.Taylor@Sun.COM /* helper functions */
969517SBill.Taylor@Sun.COM
979517SBill.Taylor@Sun.COM static int tavor_identify(struct devicelist *thisdev);
989517SBill.Taylor@Sun.COM static int tavor_get_guids(struct ib_encap_ident *handle);
999517SBill.Taylor@Sun.COM static int tavor_close(struct devicelist *flashdev);
1009517SBill.Taylor@Sun.COM static void tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps);
1019517SBill.Taylor@Sun.COM static uint16_t crc16(uint8_t *image, uint32_t size);
1029517SBill.Taylor@Sun.COM static int tavor_write_sector(int fd, int sectnum, int32_t *data);
1039517SBill.Taylor@Sun.COM static int tavor_zero_sig_crc(int fd, uint32_t start);
1049517SBill.Taylor@Sun.COM static int tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start);
1059517SBill.Taylor@Sun.COM static int tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc);
1069517SBill.Taylor@Sun.COM static int tavor_blast_image(int fd, int prisec, uint32_t hcafia,
1079517SBill.Taylor@Sun.COM uint32_t sectsz, struct mlx_xps *newxps);
1089517SBill.Taylor@Sun.COM static int tavor_readback(int infd, int whichsect, int sectsz);
1099517SBill.Taylor@Sun.COM
1109517SBill.Taylor@Sun.COM
1119517SBill.Taylor@Sun.COM
1129517SBill.Taylor@Sun.COM int
fw_readfw(struct devicelist * flashdev,char * filename)1139517SBill.Taylor@Sun.COM fw_readfw(struct devicelist *flashdev, char *filename)
1149517SBill.Taylor@Sun.COM {
1159517SBill.Taylor@Sun.COM
1169517SBill.Taylor@Sun.COM int rv = FWFLASH_SUCCESS;
1179517SBill.Taylor@Sun.COM int fd;
1189517SBill.Taylor@Sun.COM mode_t mode = S_IRUSR | S_IWUSR;
1199517SBill.Taylor@Sun.COM uint8_t pchunks;
1209517SBill.Taylor@Sun.COM uint8_t *raw_pfi;
1219517SBill.Taylor@Sun.COM uint8_t *raw_sfi;
1229517SBill.Taylor@Sun.COM uint32_t j, offset;
1239517SBill.Taylor@Sun.COM uint32_t pfia, sfia, psz, ssz;
1249517SBill.Taylor@Sun.COM tavor_flash_ioctl_t tfi_data;
1259517SBill.Taylor@Sun.COM struct ib_encap_ident *manuf;
1269517SBill.Taylor@Sun.COM struct mlx_xps *lpps;
1279517SBill.Taylor@Sun.COM struct mlx_xps *lsps;
1289517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
1299517SBill.Taylor@Sun.COM uint32_t *ptr;
1309517SBill.Taylor@Sun.COM #endif
1319517SBill.Taylor@Sun.COM
1329517SBill.Taylor@Sun.COM errno = 0;
1339517SBill.Taylor@Sun.COM if ((fd = open(filename, O_RDWR|O_CREAT|O_DSYNC, mode)) < 0) {
1349517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
1359517SBill.Taylor@Sun.COM gettext("tavor: Unable to open specified file "
1369517SBill.Taylor@Sun.COM "(%s) for writing: %s\n"), filename, strerror(errno));
1379517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
1389517SBill.Taylor@Sun.COM }
1399517SBill.Taylor@Sun.COM
1409517SBill.Taylor@Sun.COM manuf =
1419517SBill.Taylor@Sun.COM (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident;
1429517SBill.Taylor@Sun.COM lpps = (struct mlx_xps *)(uintptr_t)manuf->pps;
1439517SBill.Taylor@Sun.COM lsps = (struct mlx_xps *)(uintptr_t)manuf->sps;
1449517SBill.Taylor@Sun.COM
1459517SBill.Taylor@Sun.COM /*
1469517SBill.Taylor@Sun.COM * Now that we've got an open, init'd fd, we can read the
1479517SBill.Taylor@Sun.COM * xFI from the device itself. We've already got the IS
1489517SBill.Taylor@Sun.COM * and xPS stored in manuf.
1499517SBill.Taylor@Sun.COM */
1509517SBill.Taylor@Sun.COM
1519517SBill.Taylor@Sun.COM /* stash some values for later */
1529517SBill.Taylor@Sun.COM pfia = MLXSWAPBITS32(lpps->fia);
1539517SBill.Taylor@Sun.COM sfia = MLXSWAPBITS32(lsps->fia);
1549517SBill.Taylor@Sun.COM psz = MLXSWAPBITS32(lpps->fis);
1559517SBill.Taylor@Sun.COM ssz = MLXSWAPBITS32(lsps->fis);
1569517SBill.Taylor@Sun.COM
1579517SBill.Taylor@Sun.COM /* Invariant Sector comes first */
1589517SBill.Taylor@Sun.COM if ((j = write(fd, manuf->inv, manuf->sector_sz)) !=
1599517SBill.Taylor@Sun.COM manuf->sector_sz) {
1609517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
1619517SBill.Taylor@Sun.COM gettext("tavor: Unable to write HCA Invariant Sector "
1629517SBill.Taylor@Sun.COM "(%d of %d bytes)\n"),
1639517SBill.Taylor@Sun.COM j, manuf->sector_sz);
1649517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
1659517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
1669517SBill.Taylor@Sun.COM } else {
1679517SBill.Taylor@Sun.COM fprintf(stdout, gettext("Writing ."));
1689517SBill.Taylor@Sun.COM }
1699517SBill.Taylor@Sun.COM
1709517SBill.Taylor@Sun.COM /* followed by Primary Pointer Sector */
1719517SBill.Taylor@Sun.COM if ((j = write(fd, manuf->pps, manuf->sector_sz)) !=
1729517SBill.Taylor@Sun.COM manuf->sector_sz) {
1739517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
1749517SBill.Taylor@Sun.COM gettext("tavor: Unable to write HCA Primary Pointer "
1759517SBill.Taylor@Sun.COM "Sector (%d of %d bytes)\n)"),
1769517SBill.Taylor@Sun.COM j, manuf->sector_sz);
1779517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
1789517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
1799517SBill.Taylor@Sun.COM } else {
1809517SBill.Taylor@Sun.COM fprintf(stdout, " .");
1819517SBill.Taylor@Sun.COM }
1829517SBill.Taylor@Sun.COM
1839517SBill.Taylor@Sun.COM /* followed by Secondary Pointer Sector */
1849517SBill.Taylor@Sun.COM if ((j = write(fd, manuf->sps, manuf->sector_sz)) !=
1859517SBill.Taylor@Sun.COM manuf->sector_sz) {
1869517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
1879517SBill.Taylor@Sun.COM gettext("tavor: Unable to write HCA Secondary Pointer "
1889517SBill.Taylor@Sun.COM "Sector (%d of %d bytes)\n"),
1899517SBill.Taylor@Sun.COM j, manuf->sector_sz);
1909517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
1919517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
1929517SBill.Taylor@Sun.COM } else {
1939517SBill.Taylor@Sun.COM fprintf(stdout, " .");
1949517SBill.Taylor@Sun.COM }
1959517SBill.Taylor@Sun.COM
1969517SBill.Taylor@Sun.COM /* Now for the xFI sectors */
1979517SBill.Taylor@Sun.COM pchunks = psz / manuf->sector_sz;
1989517SBill.Taylor@Sun.COM
1999517SBill.Taylor@Sun.COM if ((psz % manuf->sector_sz) != 0)
2009517SBill.Taylor@Sun.COM pchunks++;
2019517SBill.Taylor@Sun.COM
2029517SBill.Taylor@Sun.COM /* Get the PFI, then the SFI */
2039517SBill.Taylor@Sun.COM if ((raw_pfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) {
2049517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
2059517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for "
2069517SBill.Taylor@Sun.COM "device's Primary Firmware Image\n"));
2079517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
2089517SBill.Taylor@Sun.COM }
2099517SBill.Taylor@Sun.COM bzero(&tfi_data, sizeof (tavor_flash_ioctl_t));
2109517SBill.Taylor@Sun.COM tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR;
2119517SBill.Taylor@Sun.COM j = pfia / manuf->sector_sz;
2129517SBill.Taylor@Sun.COM
2139517SBill.Taylor@Sun.COM for (offset = 0; offset < psz; offset += manuf->sector_sz) {
2149517SBill.Taylor@Sun.COM tfi_data.tf_sector_num = j;
2159517SBill.Taylor@Sun.COM tfi_data.tf_sector = (caddr_t)&raw_pfi[offset];
2169517SBill.Taylor@Sun.COM rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &tfi_data);
2179517SBill.Taylor@Sun.COM if (rv < 0) {
2189517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
2199517SBill.Taylor@Sun.COM gettext("tavor: Unable to read sector %d of "
2209517SBill.Taylor@Sun.COM "HCA Primary Firmware Image\n"), j);
2219517SBill.Taylor@Sun.COM free(raw_pfi);
2229517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
2239517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
2249517SBill.Taylor@Sun.COM }
2259517SBill.Taylor@Sun.COM ++j;
2269517SBill.Taylor@Sun.COM }
2279517SBill.Taylor@Sun.COM
2289517SBill.Taylor@Sun.COM /*
2299517SBill.Taylor@Sun.COM * It appears that the tavor driver is returning a signed
2309517SBill.Taylor@Sun.COM * -1 (0xffff) in unassigned quadlets if we read a sector
2319517SBill.Taylor@Sun.COM * that isn't full, so for backwards compatibility with
2329517SBill.Taylor@Sun.COM * earlier fwflash versions, we need to zero out what
2339517SBill.Taylor@Sun.COM * remains in the sector.
2349517SBill.Taylor@Sun.COM */
2359517SBill.Taylor@Sun.COM bzero(&raw_pfi[psz], (pchunks * manuf->sector_sz) - psz);
2369517SBill.Taylor@Sun.COM
2379517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
2389517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)raw_pfi;
2399517SBill.Taylor@Sun.COM for (j = 0; j < (pchunks * manuf->sector_sz / 4); j++) {
2409517SBill.Taylor@Sun.COM ptr[j] = htonl(ptr[j]);
2419517SBill.Taylor@Sun.COM if (j > psz)
2429517SBill.Taylor@Sun.COM break;
2439517SBill.Taylor@Sun.COM }
2449517SBill.Taylor@Sun.COM #endif
2459517SBill.Taylor@Sun.COM
2469517SBill.Taylor@Sun.COM if ((j = write(fd, raw_pfi, pchunks * manuf->sector_sz))
2479517SBill.Taylor@Sun.COM != pchunks * manuf->sector_sz) {
2489517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
2499517SBill.Taylor@Sun.COM gettext("tavor: Unable to write HCA Primary Firmware "
2509517SBill.Taylor@Sun.COM "Image data (%d of %d bytes)\n"),
2519517SBill.Taylor@Sun.COM j, pchunks * manuf->sector_sz);
2529517SBill.Taylor@Sun.COM free(raw_pfi);
2539517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
2549517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
2559517SBill.Taylor@Sun.COM } else {
2569517SBill.Taylor@Sun.COM fprintf(stdout, " .");
2579517SBill.Taylor@Sun.COM }
2589517SBill.Taylor@Sun.COM
2599517SBill.Taylor@Sun.COM pchunks = ssz / manuf->sector_sz;
2609517SBill.Taylor@Sun.COM
2619517SBill.Taylor@Sun.COM if ((ssz % manuf->sector_sz) != 0)
2629517SBill.Taylor@Sun.COM pchunks++;
2639517SBill.Taylor@Sun.COM
2649517SBill.Taylor@Sun.COM /*
2659517SBill.Taylor@Sun.COM * We allocate wholenum sectors, but only write out what we
2669517SBill.Taylor@Sun.COM * really need (ssz bytes)
2679517SBill.Taylor@Sun.COM */
2689517SBill.Taylor@Sun.COM if ((raw_sfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) {
2699517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
2709517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for "
2719517SBill.Taylor@Sun.COM "device's Secondary Firmware Image\n"));
2729517SBill.Taylor@Sun.COM free(raw_pfi);
2739517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
2749517SBill.Taylor@Sun.COM }
2759517SBill.Taylor@Sun.COM bzero(&tfi_data, sizeof (tavor_flash_ioctl_t));
2769517SBill.Taylor@Sun.COM tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR;
2779517SBill.Taylor@Sun.COM
2789517SBill.Taylor@Sun.COM /* get our starting sector number */
2799517SBill.Taylor@Sun.COM j = sfia / manuf->sector_sz;
2809517SBill.Taylor@Sun.COM
2819517SBill.Taylor@Sun.COM for (offset = 0; offset < ssz; offset += manuf->sector_sz) {
2829517SBill.Taylor@Sun.COM tfi_data.tf_sector_num = j;
2839517SBill.Taylor@Sun.COM tfi_data.tf_sector = (caddr_t)&raw_sfi[offset];
2849517SBill.Taylor@Sun.COM if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ,
2859517SBill.Taylor@Sun.COM &tfi_data)) < 0) {
2869517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
2879517SBill.Taylor@Sun.COM gettext("tavor: Unable to read sector %d of "
2889517SBill.Taylor@Sun.COM "HCA Secondary Firmware Image\n"), j);
2899517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
2909517SBill.Taylor@Sun.COM free(raw_pfi);
2919517SBill.Taylor@Sun.COM free(raw_sfi);
2929517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
2939517SBill.Taylor@Sun.COM }
2949517SBill.Taylor@Sun.COM ++j;
2959517SBill.Taylor@Sun.COM }
2969517SBill.Taylor@Sun.COM
2979517SBill.Taylor@Sun.COM /*
2989517SBill.Taylor@Sun.COM * It appears that the tavor driver is returning a signed
2999517SBill.Taylor@Sun.COM * -1 (0xffff) in unassigned quadlets if we read a sector
3009517SBill.Taylor@Sun.COM * that isn't full, so for backwards compatibility with
3019517SBill.Taylor@Sun.COM * earlier fwflash versions, we need to zero out what
3029517SBill.Taylor@Sun.COM * remains in the sector.
3039517SBill.Taylor@Sun.COM */
3049517SBill.Taylor@Sun.COM bzero(&raw_sfi[ssz], (pchunks * manuf->sector_sz) - ssz);
3059517SBill.Taylor@Sun.COM
3069517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
3079517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)raw_sfi;
3089517SBill.Taylor@Sun.COM for (j = 0; j < ssz / 4; j++) {
3099517SBill.Taylor@Sun.COM ptr[j] = htonl(ptr[j]);
3109517SBill.Taylor@Sun.COM }
3119517SBill.Taylor@Sun.COM #endif
3129517SBill.Taylor@Sun.COM
3139517SBill.Taylor@Sun.COM /* only write out ssz bytes */
3149517SBill.Taylor@Sun.COM if ((j = write(fd, raw_sfi, ssz)) != ssz) {
3159517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
3169517SBill.Taylor@Sun.COM gettext("tavor: Unable to write HCA Secondary Firmware "
3179517SBill.Taylor@Sun.COM "Image data (%d of %d bytes)\n"),
3189517SBill.Taylor@Sun.COM j, ssz);
3199517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
3209517SBill.Taylor@Sun.COM free(raw_pfi);
3219517SBill.Taylor@Sun.COM free(raw_sfi);
3229517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
3239517SBill.Taylor@Sun.COM } else {
3249517SBill.Taylor@Sun.COM fprintf(stdout, " .\n");
3259517SBill.Taylor@Sun.COM }
3269517SBill.Taylor@Sun.COM
3279517SBill.Taylor@Sun.COM fprintf(stdout,
3289517SBill.Taylor@Sun.COM gettext("Done.\n"));
3299517SBill.Taylor@Sun.COM
3309517SBill.Taylor@Sun.COM free(raw_pfi);
3319517SBill.Taylor@Sun.COM free(raw_sfi);
3329517SBill.Taylor@Sun.COM /*
3339517SBill.Taylor@Sun.COM * this should succeed, but we don't just blindly ignore
3349517SBill.Taylor@Sun.COM * the return code cos that would be obnoxious.
3359517SBill.Taylor@Sun.COM */
3369517SBill.Taylor@Sun.COM return (tavor_close(flashdev));
3379517SBill.Taylor@Sun.COM }
3389517SBill.Taylor@Sun.COM
3399517SBill.Taylor@Sun.COM
3409517SBill.Taylor@Sun.COM /*
3419517SBill.Taylor@Sun.COM * If we're invoking fw_writefw, then flashdev is a valid,
3429517SBill.Taylor@Sun.COM * flashable device as determined by fw_identify().
3439517SBill.Taylor@Sun.COM *
3449517SBill.Taylor@Sun.COM * If verifier is null, then we haven't been called following a firmware
3459517SBill.Taylor@Sun.COM * image verification load operation.
3469517SBill.Taylor@Sun.COM */
3479517SBill.Taylor@Sun.COM int
fw_writefw(struct devicelist * flashdev)3489517SBill.Taylor@Sun.COM fw_writefw(struct devicelist *flashdev)
3499517SBill.Taylor@Sun.COM {
3509517SBill.Taylor@Sun.COM
3519517SBill.Taylor@Sun.COM int rv;
3529517SBill.Taylor@Sun.COM uint32_t j, sectsz, hpfia, hsfia;
3539517SBill.Taylor@Sun.COM uint32_t ipfia, isfia, ipfis, isfis;
3549517SBill.Taylor@Sun.COM struct ib_encap_ident *manuf;
3559517SBill.Taylor@Sun.COM struct mlx_is *iinv;
3569517SBill.Taylor@Sun.COM struct mlx_xps *ipps, *lpps;
3579517SBill.Taylor@Sun.COM struct mlx_xps *isps, *lsps;
3589517SBill.Taylor@Sun.COM struct mlx_xfi *ipfi, *isfi;
3599517SBill.Taylor@Sun.COM
3609517SBill.Taylor@Sun.COM /*
3619517SBill.Taylor@Sun.COM * linv, lpps/lsps are from the HCA whereas
3629517SBill.Taylor@Sun.COM * iinv/ipps/isps are in the on-disk firmware image that
3639517SBill.Taylor@Sun.COM * we've read in to the verifier->fwimage field, and are
3649517SBill.Taylor@Sun.COM * about to do some hand-waving with.
3659517SBill.Taylor@Sun.COM */
3669517SBill.Taylor@Sun.COM
3679517SBill.Taylor@Sun.COM /*
3689517SBill.Taylor@Sun.COM * From the Mellanox HCA Flash programming app note,
3699517SBill.Taylor@Sun.COM * start of ch4, page36:
3709517SBill.Taylor@Sun.COM * ===========================================================
3719517SBill.Taylor@Sun.COM * Failsafe firmware programming ensures that an HCA device
3729517SBill.Taylor@Sun.COM * can boot up in a functional mode even if the burn process
3739517SBill.Taylor@Sun.COM * was interrupted (because of a power failure, reboot, user
3749517SBill.Taylor@Sun.COM * interrupt, etc.). This can be implemented by burning the
3759517SBill.Taylor@Sun.COM * new image to a vacant region on the Flash, and erasing the
3769517SBill.Taylor@Sun.COM * old image only after the new image is successfully burnt.
3779517SBill.Taylor@Sun.COM * This method ensures that there is at least one valid firmware
3789517SBill.Taylor@Sun.COM * image on the Flash at all times. Thus, in case a firmware
3799517SBill.Taylor@Sun.COM * image programming process is aborted for any reason, the HCA
3809517SBill.Taylor@Sun.COM * will still be able to boot up properly using the valid image
3819517SBill.Taylor@Sun.COM * on the Flash.
3829517SBill.Taylor@Sun.COM * ...
3839517SBill.Taylor@Sun.COM *
3849517SBill.Taylor@Sun.COM * 4.1 Notes on Image Programming of HCA Flashes
3859517SBill.Taylor@Sun.COM * Following are some general notes regarding the Flash memory
3869517SBill.Taylor@Sun.COM * in the context of Mellanox HCA devices:
3879517SBill.Taylor@Sun.COM * > The Flash memory is divided into sectors, and each sector
3889517SBill.Taylor@Sun.COM * must be erased prior to its programming.
3899517SBill.Taylor@Sun.COM * > The image to be burnt is byte packed and should be programmed
3909517SBill.Taylor@Sun.COM * into the Flash byte by byte, preserving the byte order, starting
3919517SBill.Taylor@Sun.COM * at offset zero. No amendments are needed for endianess.
3929517SBill.Taylor@Sun.COM * > It is recommended to program the Flash while the device is idle.
3939517SBill.Taylor@Sun.COM * ===========================================================
3949517SBill.Taylor@Sun.COM *
3959517SBill.Taylor@Sun.COM * The comment about endianness is particularly important for us
3969517SBill.Taylor@Sun.COM * since we operate on both big- and litte-endian hosts - it means
3979517SBill.Taylor@Sun.COM * we have to do some byte-swapping gymnastics
3989517SBill.Taylor@Sun.COM */
3999517SBill.Taylor@Sun.COM
4009517SBill.Taylor@Sun.COM /*
4019517SBill.Taylor@Sun.COM * From the Mellanox HCA Flash programming app note,
4029517SBill.Taylor@Sun.COM * section 4.2.5 on page 41/42:
4039517SBill.Taylor@Sun.COM * ===========================================================
4049517SBill.Taylor@Sun.COM * 4.2.5 Failsafe Programming Example
4059517SBill.Taylor@Sun.COM * This section provides an example of a programming utility
4069517SBill.Taylor@Sun.COM * that performs a Failsafe firmware image update. The flow
4079517SBill.Taylor@Sun.COM * ensures that there is at least one valid firmware image on
4089517SBill.Taylor@Sun.COM * the Flash at all times. Thus, in case a firmware image pro-
4099517SBill.Taylor@Sun.COM * gramming process is aborted for any reason, the HCA will
4109517SBill.Taylor@Sun.COM * still be able to boot up properly using the valid image on
4119517SBill.Taylor@Sun.COM * the Flash. Any other flow that ensures the above is also
4129517SBill.Taylor@Sun.COM * considered a Failsafe firmware update.
4139517SBill.Taylor@Sun.COM *
4149517SBill.Taylor@Sun.COM * Update Flow:
4159517SBill.Taylor@Sun.COM * * Check the validity of the PPS and SPS:
4169517SBill.Taylor@Sun.COM * > If both PSs are valid, arbitrarily invalidate one of them
4179517SBill.Taylor@Sun.COM * > If both PSs are invalid, the image on flash is corrupted
4189517SBill.Taylor@Sun.COM * and cannot be updated in a Failsafe way. The user must
4199517SBill.Taylor@Sun.COM * burn a full image in a non-failsafe way.
4209517SBill.Taylor@Sun.COM *
4219517SBill.Taylor@Sun.COM * > If only the PPS is valid:
4229517SBill.Taylor@Sun.COM * i.Burn the secondary image (erase each sector first)
4239517SBill.Taylor@Sun.COM * ii.Burn the SPS with the correct image address (FIA field)
4249517SBill.Taylor@Sun.COM * iii.Invalidate the PPS
4259517SBill.Taylor@Sun.COM *
4269517SBill.Taylor@Sun.COM * > If only the SPS is valid:
4279517SBill.Taylor@Sun.COM * i.Burn the primary image (erase each sector first)
4289517SBill.Taylor@Sun.COM * ii.Burn the PPS with the correct image address (FIA field)
4299517SBill.Taylor@Sun.COM * iii.Invalidate the SPS
4309517SBill.Taylor@Sun.COM * ===========================================================
4319517SBill.Taylor@Sun.COM */
4329517SBill.Taylor@Sun.COM
4339517SBill.Taylor@Sun.COM /*
4349517SBill.Taylor@Sun.COM * Other required tasks called from this function:
4359517SBill.Taylor@Sun.COM *
4369517SBill.Taylor@Sun.COM * * check for CISCO boot extensions in the current xPS, and
4379517SBill.Taylor@Sun.COM * if found, set them in the new xPS
4389517SBill.Taylor@Sun.COM *
4399517SBill.Taylor@Sun.COM * * update the xPS CRC field
4409517SBill.Taylor@Sun.COM *
4419517SBill.Taylor@Sun.COM * _then_ you can setup the outbound transfer to the HCA flash.
4429517SBill.Taylor@Sun.COM */
4439517SBill.Taylor@Sun.COM
4449517SBill.Taylor@Sun.COM /*
4459517SBill.Taylor@Sun.COM * VERY IMPORTANT NOTE:
4469517SBill.Taylor@Sun.COM * The above text from the app note programming guide v1.44 does
4479517SBill.Taylor@Sun.COM * NOT match reality. If you try to do exactly what the above
4489517SBill.Taylor@Sun.COM * text specifies then you'll wind up with a warm, brick-like
4499517SBill.Taylor@Sun.COM * HCA that if you're really lucky has booted up in maintenance
4509517SBill.Taylor@Sun.COM * mode for you to re-flash.
4519517SBill.Taylor@Sun.COM *
4529517SBill.Taylor@Sun.COM * What you need to do is follow the example of the previous
4539517SBill.Taylor@Sun.COM * (v1.2 etc) version from the ON gate - which is what happens
4549517SBill.Taylor@Sun.COM * in this file. Basically - don't erase prior to writing a new
4559517SBill.Taylor@Sun.COM * sector, and _read back_ each sector after writing it. Especially
4569517SBill.Taylor@Sun.COM * the pointer sectors. Otherwise you'll get a warm brick.
4579517SBill.Taylor@Sun.COM */
4589517SBill.Taylor@Sun.COM
4599517SBill.Taylor@Sun.COM manuf =
4609517SBill.Taylor@Sun.COM (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident;
4619517SBill.Taylor@Sun.COM lpps = (struct mlx_xps *)(uintptr_t)manuf->pps;
4629517SBill.Taylor@Sun.COM lsps = (struct mlx_xps *)(uintptr_t)manuf->sps;
4639517SBill.Taylor@Sun.COM iinv = (struct mlx_is *)&verifier->fwimage[0];
4649517SBill.Taylor@Sun.COM sectsz = 1 << MLXSWAPBITS16(iinv->log2sectsz + iinv->log2sectszp);
4659517SBill.Taylor@Sun.COM ipps = (struct mlx_xps *)&verifier->fwimage[sectsz/4];
4669517SBill.Taylor@Sun.COM isps = (struct mlx_xps *)&verifier->fwimage[sectsz/2];
4679517SBill.Taylor@Sun.COM
4689517SBill.Taylor@Sun.COM /*
4699517SBill.Taylor@Sun.COM * If we get here, then the verifier has _already_ checked that
4709517SBill.Taylor@Sun.COM * the part number in the firmware image matches that in the HCA,
4719517SBill.Taylor@Sun.COM * so we only need this check if there's no hardware info available
4729517SBill.Taylor@Sun.COM * already after running through fw_identify().
4739517SBill.Taylor@Sun.COM */
4749517SBill.Taylor@Sun.COM if (manuf->pn_len == 0) {
4759517SBill.Taylor@Sun.COM int resp;
4769517SBill.Taylor@Sun.COM
4779517SBill.Taylor@Sun.COM (void) printf("\nUnable to completely verify that this "
4789517SBill.Taylor@Sun.COM "firmware image\n\t(%s)\nis compatible with your "
4799517SBill.Taylor@Sun.COM "HCA\n\t%s\n",
4809517SBill.Taylor@Sun.COM verifier->imgfile, flashdev->access_devname);
4819517SBill.Taylor@Sun.COM (void) printf("\n\tDo you really want to continue? (Y/N): ");
4829517SBill.Taylor@Sun.COM
4839517SBill.Taylor@Sun.COM (void) fflush(stdin);
4849517SBill.Taylor@Sun.COM resp = getchar();
4859517SBill.Taylor@Sun.COM if (resp != 'Y' && resp != 'y') {
4869517SBill.Taylor@Sun.COM (void) printf("\nNot proceeding with flash "
4879517SBill.Taylor@Sun.COM "operation of %s on %s\n",
4889517SBill.Taylor@Sun.COM verifier->imgfile, flashdev->access_devname);
4899517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
4909517SBill.Taylor@Sun.COM }
4919517SBill.Taylor@Sun.COM }
4929517SBill.Taylor@Sun.COM
4939517SBill.Taylor@Sun.COM /* stash these for later */
4949517SBill.Taylor@Sun.COM hpfia = MLXSWAPBITS32(lpps->fia);
4959517SBill.Taylor@Sun.COM hsfia = MLXSWAPBITS32(lsps->fia);
4969517SBill.Taylor@Sun.COM
4979517SBill.Taylor@Sun.COM /* where does the on-disk image think everything is at? */
4989517SBill.Taylor@Sun.COM ipfia = MLXSWAPBITS32(ipps->fia);
4999517SBill.Taylor@Sun.COM isfia = MLXSWAPBITS32(isps->fia);
5009517SBill.Taylor@Sun.COM ipfis = MLXSWAPBITS32(ipps->fis);
5019517SBill.Taylor@Sun.COM isfis = MLXSWAPBITS32(isps->fis);
5029517SBill.Taylor@Sun.COM
5039517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: hpfia 0x%0x hsfia 0x%0x "
5049517SBill.Taylor@Sun.COM "ipfia 0x%0x isfia 0x%0x ipfis 0x%0x isfis 0x%0x\n",
5059517SBill.Taylor@Sun.COM hpfia, hsfia, ipfia, isfia, ipfis, isfis);
5069517SBill.Taylor@Sun.COM
5079517SBill.Taylor@Sun.COM if ((ipfis + isfis) > manuf->device_sz) {
5089517SBill.Taylor@Sun.COM /*
5099517SBill.Taylor@Sun.COM * This is bad - don't flash an image which is larger
5109517SBill.Taylor@Sun.COM * than the size of the HCA's flash
5119517SBill.Taylor@Sun.COM */
5129517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
5139517SBill.Taylor@Sun.COM gettext("tavor: on-disk firmware image size (0x%lx bytes) "
5149517SBill.Taylor@Sun.COM "exceeds HCA's flash memory size (0x%lx bytes)!\n"),
5159517SBill.Taylor@Sun.COM ipfis + isfis, manuf->device_sz);
5169517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
5179517SBill.Taylor@Sun.COM gettext("tavor: not flashing this image (%s)\n"),
5189517SBill.Taylor@Sun.COM verifier->imgfile);
5199517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
5209517SBill.Taylor@Sun.COM }
5219517SBill.Taylor@Sun.COM
5229517SBill.Taylor@Sun.COM /*
5239517SBill.Taylor@Sun.COM * The Mellanox HCA Flash app programming note does _not_
5249517SBill.Taylor@Sun.COM * specify that you have to insert the HCA's guid section
5259517SBill.Taylor@Sun.COM * into the flash image before burning it.
5269517SBill.Taylor@Sun.COM *
5279517SBill.Taylor@Sun.COM * HOWEVER it was determined during testing that this is
5289517SBill.Taylor@Sun.COM * actually required (otherwise your HCA's GUIDs revert to
5299517SBill.Taylor@Sun.COM * the manufacturer's defaults, ugh!), so we'll do it too.
5309517SBill.Taylor@Sun.COM */
5319517SBill.Taylor@Sun.COM
5329517SBill.Taylor@Sun.COM ipfi = (struct mlx_xfi *)&verifier->fwimage[ipfia/4];
5339517SBill.Taylor@Sun.COM isfi = (struct mlx_xfi *)&verifier->fwimage[isfia/4];
5349517SBill.Taylor@Sun.COM
5359517SBill.Taylor@Sun.COM /*
5369517SBill.Taylor@Sun.COM * Here we check against our stored, properly-bitwise-munged copy
5379517SBill.Taylor@Sun.COM * of the HCA's GUIDS. If they're not set to default AND the OUI
5389517SBill.Taylor@Sun.COM * is MLX_OUI, then they're ok so we copy the HCA's version into
5399517SBill.Taylor@Sun.COM * our in-memory copy and blat it. If the GUIDs don't match this
5409517SBill.Taylor@Sun.COM * condition, then we use the default GUIDs which are in the on-disk
5419517SBill.Taylor@Sun.COM * firmware image instead.
5429517SBill.Taylor@Sun.COM */
5439517SBill.Taylor@Sun.COM if (((manuf->ibguids[0] != MLX_DEFAULT_NODE_GUID) &&
5449517SBill.Taylor@Sun.COM (manuf->ibguids[1] != MLX_DEFAULT_P1_GUID) &&
5459517SBill.Taylor@Sun.COM (manuf->ibguids[2] != MLX_DEFAULT_P2_GUID) &&
5469517SBill.Taylor@Sun.COM (manuf->ibguids[3] != MLX_DEFAULT_SYSIMG_GUID)) &&
5479517SBill.Taylor@Sun.COM ((((manuf->ibguids[0] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5489517SBill.Taylor@Sun.COM (((manuf->ibguids[1] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5499517SBill.Taylor@Sun.COM (((manuf->ibguids[2] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5509517SBill.Taylor@Sun.COM (((manuf->ibguids[3] & HIGHBITS64) >> OUISHIFT) == MLX_OUI))) {
5519517SBill.Taylor@Sun.COM /* The GUIDs are ok, blat them into the in-memory image */
5529517SBill.Taylor@Sun.COM j = ((ipfia + MLXSWAPBITS32(ipfi->nguidptr)) / 4) - 4;
5539517SBill.Taylor@Sun.COM bcopy(manuf->pri_guid_section, &verifier->fwimage[j],
5549517SBill.Taylor@Sun.COM sizeof (struct mlx_guid_sect));
5559517SBill.Taylor@Sun.COM j = ((isfia + MLXSWAPBITS32(isfi->nguidptr)) / 4) - 4;
5569517SBill.Taylor@Sun.COM bcopy(manuf->sec_guid_section, &verifier->fwimage[j],
5579517SBill.Taylor@Sun.COM sizeof (struct mlx_guid_sect));
5589517SBill.Taylor@Sun.COM } else {
5599517SBill.Taylor@Sun.COM /*
5609517SBill.Taylor@Sun.COM * The GUIDs are hosed, we'll have to use
5619517SBill.Taylor@Sun.COM * the vendor defaults in the image instead
5629517SBill.Taylor@Sun.COM */
5639517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
5649517SBill.Taylor@Sun.COM gettext("tavor: HCA's GUID section is set to defaults or "
5659517SBill.Taylor@Sun.COM " is invalid, using firmware image manufacturer's "
5669517SBill.Taylor@Sun.COM "default GUID section instead\n"));
5679517SBill.Taylor@Sun.COM }
5689517SBill.Taylor@Sun.COM
5699517SBill.Taylor@Sun.COM /* Just in case somebody is booting from this card... */
5709517SBill.Taylor@Sun.COM tavor_cisco_extensions(lpps, ipps);
5719517SBill.Taylor@Sun.COM tavor_cisco_extensions(lsps, isps);
5729517SBill.Taylor@Sun.COM
5739517SBill.Taylor@Sun.COM /* first we write the secondary image and SPS, then the primary */
5749517SBill.Taylor@Sun.COM rv = tavor_blast_image(manuf->fd, 2, hsfia, manuf->sector_sz, isps);
5759517SBill.Taylor@Sun.COM if (rv != FWFLASH_SUCCESS) {
5769517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
5779517SBill.Taylor@Sun.COM "tavor: failed to update #2 firmware image\n");
5789517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
5799517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
5809517SBill.Taylor@Sun.COM }
5819517SBill.Taylor@Sun.COM
5829517SBill.Taylor@Sun.COM rv = tavor_blast_image(manuf->fd, 1, hpfia, manuf->sector_sz, ipps);
5839517SBill.Taylor@Sun.COM if (rv != FWFLASH_SUCCESS) {
5849517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
5859517SBill.Taylor@Sun.COM "tavor: failed to update #1 firmware image\n");
5869517SBill.Taylor@Sun.COM (void) tavor_close(flashdev);
5879517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
5889517SBill.Taylor@Sun.COM }
5899517SBill.Taylor@Sun.COM
5909517SBill.Taylor@Sun.COM /* final update marker to the user */
5919517SBill.Taylor@Sun.COM (void) printf(" +\n");
5929517SBill.Taylor@Sun.COM return (tavor_close(flashdev));
5939517SBill.Taylor@Sun.COM }
5949517SBill.Taylor@Sun.COM
5959517SBill.Taylor@Sun.COM
5969517SBill.Taylor@Sun.COM /*
5979517SBill.Taylor@Sun.COM * The fw_identify() function walks the device
5989517SBill.Taylor@Sun.COM * tree trying to find devices which this plugin
5999517SBill.Taylor@Sun.COM * can work with.
6009517SBill.Taylor@Sun.COM *
6019517SBill.Taylor@Sun.COM * The parameter "start" gives us the starting index number
6029517SBill.Taylor@Sun.COM * to give the device when we add it to the fw_devices list.
6039517SBill.Taylor@Sun.COM *
6049517SBill.Taylor@Sun.COM * firstdev is allocated by us and we add space as necessary
6059517SBill.Taylor@Sun.COM *
6069517SBill.Taylor@Sun.COM */
6079517SBill.Taylor@Sun.COM int
fw_identify(int start)6089517SBill.Taylor@Sun.COM fw_identify(int start)
6099517SBill.Taylor@Sun.COM {
6109517SBill.Taylor@Sun.COM int rv = FWFLASH_FAILURE;
6119517SBill.Taylor@Sun.COM di_node_t thisnode;
6129517SBill.Taylor@Sun.COM struct devicelist *newdev;
6139517SBill.Taylor@Sun.COM char *devpath;
6149517SBill.Taylor@Sun.COM int idx = start;
6159517SBill.Taylor@Sun.COM int devlength = 0;
6169517SBill.Taylor@Sun.COM
6179517SBill.Taylor@Sun.COM thisnode = di_drv_first_node(drivername, rootnode);
6189517SBill.Taylor@Sun.COM
6199517SBill.Taylor@Sun.COM if (thisnode == DI_NODE_NIL) {
6209517SBill.Taylor@Sun.COM logmsg(MSG_INFO, gettext("No %s nodes in this system\n"),
6219517SBill.Taylor@Sun.COM drivername);
6229517SBill.Taylor@Sun.COM return (rv);
6239517SBill.Taylor@Sun.COM }
6249517SBill.Taylor@Sun.COM
6259517SBill.Taylor@Sun.COM /* we've found one, at least */
6269517SBill.Taylor@Sun.COM for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
6279517SBill.Taylor@Sun.COM
6289517SBill.Taylor@Sun.COM devpath = di_devfs_path(thisnode);
6299517SBill.Taylor@Sun.COM
6309517SBill.Taylor@Sun.COM if ((newdev = calloc(1, sizeof (struct devicelist)))
6319517SBill.Taylor@Sun.COM == NULL) {
6329517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
63310618SShantkumar.Hiremath@Sun.COM gettext("tavor identification function: unable "
6349517SBill.Taylor@Sun.COM "to allocate space for device entry\n"));
6359517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6369517SBill.Taylor@Sun.COM return (rv);
6379517SBill.Taylor@Sun.COM }
6389517SBill.Taylor@Sun.COM
6399517SBill.Taylor@Sun.COM /* calloc enough for /devices + devpath + ":devctl" + '\0' */
6409517SBill.Taylor@Sun.COM devlength = strlen(devpath) + strlen(devprefix) +
6419517SBill.Taylor@Sun.COM strlen(devsuffix) + 2;
6429517SBill.Taylor@Sun.COM
6439517SBill.Taylor@Sun.COM if ((newdev->access_devname = calloc(1, devlength)) == NULL) {
6449517SBill.Taylor@Sun.COM logmsg(MSG_ERROR, gettext("Unable to calloc space "
6459517SBill.Taylor@Sun.COM "for a devfs name\n"));
6469517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6479517SBill.Taylor@Sun.COM (void) free(newdev);
6489517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
6499517SBill.Taylor@Sun.COM }
6509517SBill.Taylor@Sun.COM snprintf(newdev->access_devname, devlength,
6519517SBill.Taylor@Sun.COM "%s%s%s", devprefix, devpath, devsuffix);
6529517SBill.Taylor@Sun.COM
6539517SBill.Taylor@Sun.COM /* CHECK VARIOUS IB THINGS HERE */
6549517SBill.Taylor@Sun.COM
6559517SBill.Taylor@Sun.COM if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
6569517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
6579517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for a "
6589517SBill.Taylor@Sun.COM "device identification record\n"));
6599517SBill.Taylor@Sun.COM (void) free(newdev->access_devname);
6609517SBill.Taylor@Sun.COM (void) free(newdev);
6619517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6629517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
6639517SBill.Taylor@Sun.COM }
6649517SBill.Taylor@Sun.COM
6659517SBill.Taylor@Sun.COM rv = tavor_identify(newdev);
6669517SBill.Taylor@Sun.COM if (rv == FWFLASH_FAILURE) {
6679517SBill.Taylor@Sun.COM (void) free(newdev->ident);
6689517SBill.Taylor@Sun.COM (void) free(newdev->access_devname);
6699517SBill.Taylor@Sun.COM (void) free(newdev);
6709517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6719517SBill.Taylor@Sun.COM continue;
6729517SBill.Taylor@Sun.COM }
6739517SBill.Taylor@Sun.COM
6749517SBill.Taylor@Sun.COM if ((newdev->drvname = calloc(1, strlen(drivername) + 1))
6759517SBill.Taylor@Sun.COM == NULL) {
6769517SBill.Taylor@Sun.COM logmsg(MSG_ERROR, gettext("Unable to allocate space "
6779517SBill.Taylor@Sun.COM "for a driver name\n"));
6789517SBill.Taylor@Sun.COM (void) free(newdev->ident);
6799517SBill.Taylor@Sun.COM (void) free(newdev->access_devname);
6809517SBill.Taylor@Sun.COM (void) free(newdev);
6819517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6829517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
6839517SBill.Taylor@Sun.COM }
6849517SBill.Taylor@Sun.COM
6859517SBill.Taylor@Sun.COM (void) strlcpy(newdev->drvname, drivername,
6869517SBill.Taylor@Sun.COM strlen(drivername) + 1);
6879517SBill.Taylor@Sun.COM
6889517SBill.Taylor@Sun.COM /* this next bit is backwards compatibility - "IB\0" */
6899517SBill.Taylor@Sun.COM if ((newdev->classname = calloc(1, 3)) == NULL) {
6909517SBill.Taylor@Sun.COM logmsg(MSG_ERROR, gettext("Unable to allocate space "
6919517SBill.Taylor@Sun.COM "for a class name\n"));
6929517SBill.Taylor@Sun.COM (void) free(newdev->drvname);
6939517SBill.Taylor@Sun.COM (void) free(newdev->ident);
6949517SBill.Taylor@Sun.COM (void) free(newdev->access_devname);
6959517SBill.Taylor@Sun.COM (void) free(newdev);
6969517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
6979517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
6989517SBill.Taylor@Sun.COM }
6999517SBill.Taylor@Sun.COM (void) strlcpy(newdev->classname, "IB", 3);
7009517SBill.Taylor@Sun.COM
7019517SBill.Taylor@Sun.COM newdev->index = idx;
7029517SBill.Taylor@Sun.COM ++idx;
7039517SBill.Taylor@Sun.COM newdev->plugin = self;
7049517SBill.Taylor@Sun.COM
7059517SBill.Taylor@Sun.COM di_devfs_path_free(devpath);
7069517SBill.Taylor@Sun.COM TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
7079517SBill.Taylor@Sun.COM }
7089517SBill.Taylor@Sun.COM
7099517SBill.Taylor@Sun.COM if (fwflash_debug != 0) {
7109517SBill.Taylor@Sun.COM struct devicelist *tempdev;
7119517SBill.Taylor@Sun.COM
7129517SBill.Taylor@Sun.COM TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
713*12472SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "fw_identify:\n");
7149517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n"
7159517SBill.Taylor@Sun.COM "\t\taccess_devname: %s\n"
7169517SBill.Taylor@Sun.COM "\t\tdrvname: %s\tclassname: %s\n"
7179517SBill.Taylor@Sun.COM "\t\tident->vid: %s\n"
7189517SBill.Taylor@Sun.COM "\t\tident->pid: %s\n"
7199517SBill.Taylor@Sun.COM "\t\tident->revid: %s\n"
7209517SBill.Taylor@Sun.COM "\t\tindex: %d\n"
7219517SBill.Taylor@Sun.COM "\t\tguid0: %s\n"
7229517SBill.Taylor@Sun.COM "\t\tguid1: %s\n"
7239517SBill.Taylor@Sun.COM "\t\tguid2: %s\n"
7249517SBill.Taylor@Sun.COM "\t\tguid3: %s\n"
7259517SBill.Taylor@Sun.COM "\t\tplugin @ 0x%lx\n\n",
7269517SBill.Taylor@Sun.COM &tempdev,
7279517SBill.Taylor@Sun.COM tempdev->access_devname,
7289517SBill.Taylor@Sun.COM tempdev->drvname, newdev->classname,
7299517SBill.Taylor@Sun.COM tempdev->ident->vid,
7309517SBill.Taylor@Sun.COM tempdev->ident->pid,
7319517SBill.Taylor@Sun.COM tempdev->ident->revid,
7329517SBill.Taylor@Sun.COM tempdev->index,
733*12472SShantkumar.Hiremath@Sun.COM (tempdev->addresses[0] ? tempdev->addresses[0] :
734*12472SShantkumar.Hiremath@Sun.COM "(not supported)"),
735*12472SShantkumar.Hiremath@Sun.COM (tempdev->addresses[1] ? tempdev->addresses[1] :
736*12472SShantkumar.Hiremath@Sun.COM "(not supported)"),
737*12472SShantkumar.Hiremath@Sun.COM (tempdev->addresses[2] ? tempdev->addresses[2] :
738*12472SShantkumar.Hiremath@Sun.COM "(not supported)"),
739*12472SShantkumar.Hiremath@Sun.COM (tempdev->addresses[3] ? tempdev->addresses[3] :
740*12472SShantkumar.Hiremath@Sun.COM "(not supported)"),
7419517SBill.Taylor@Sun.COM tempdev->plugin);
7429517SBill.Taylor@Sun.COM }
7439517SBill.Taylor@Sun.COM }
7449517SBill.Taylor@Sun.COM
7459517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
7469517SBill.Taylor@Sun.COM }
7479517SBill.Taylor@Sun.COM
7489517SBill.Taylor@Sun.COM
7499517SBill.Taylor@Sun.COM
7509517SBill.Taylor@Sun.COM int
fw_devinfo(struct devicelist * thisdev)7519517SBill.Taylor@Sun.COM fw_devinfo(struct devicelist *thisdev)
7529517SBill.Taylor@Sun.COM {
7539517SBill.Taylor@Sun.COM
7549517SBill.Taylor@Sun.COM struct ib_encap_ident *encap;
7559517SBill.Taylor@Sun.COM
7569517SBill.Taylor@Sun.COM
7579517SBill.Taylor@Sun.COM encap = (struct ib_encap_ident *)thisdev->ident->encap_ident;
7589517SBill.Taylor@Sun.COM
7599517SBill.Taylor@Sun.COM fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"),
7609517SBill.Taylor@Sun.COM thisdev->index, thisdev->access_devname, thisdev->classname);
7619517SBill.Taylor@Sun.COM
7629517SBill.Taylor@Sun.COM fprintf(stdout, "\t");
7639517SBill.Taylor@Sun.COM
7649517SBill.Taylor@Sun.COM /* Mellanox HCA Flash app note, p40, #4.2.3 table 9 */
7659517SBill.Taylor@Sun.COM fprintf(stdout,
7669517SBill.Taylor@Sun.COM gettext("GUID: System Image - %s\n"),
7679517SBill.Taylor@Sun.COM thisdev->addresses[3]);
7689517SBill.Taylor@Sun.COM fprintf(stdout,
7699517SBill.Taylor@Sun.COM gettext("\t\tNode Image - %s\n"),
7709517SBill.Taylor@Sun.COM thisdev->addresses[0]);
7719517SBill.Taylor@Sun.COM fprintf(stdout,
7729517SBill.Taylor@Sun.COM gettext("\t\tPort 1\t - %s\n"),
7739517SBill.Taylor@Sun.COM thisdev->addresses[1]);
7749517SBill.Taylor@Sun.COM fprintf(stdout,
7759517SBill.Taylor@Sun.COM gettext("\t\tPort 2\t - %s\n"),
7769517SBill.Taylor@Sun.COM thisdev->addresses[2]);
7779517SBill.Taylor@Sun.COM
7789517SBill.Taylor@Sun.COM if (encap->pn_len != 0) {
7799517SBill.Taylor@Sun.COM fprintf(stdout,
7809517SBill.Taylor@Sun.COM gettext("\tFirmware revision : %s\n"
781*12472SShantkumar.Hiremath@Sun.COM "\tProduct\t\t: %s %X\n"
7829517SBill.Taylor@Sun.COM "\tPSID\t\t: %s\n"),
7839517SBill.Taylor@Sun.COM thisdev->ident->revid,
7849517SBill.Taylor@Sun.COM encap->info.mlx_pn,
785*12472SShantkumar.Hiremath@Sun.COM encap->hwrev,
7869517SBill.Taylor@Sun.COM encap->info.mlx_psid);
787*12472SShantkumar.Hiremath@Sun.COM } else {
7889517SBill.Taylor@Sun.COM fprintf(stdout,
7899517SBill.Taylor@Sun.COM gettext("\tFirmware revision : %s\n"
7909517SBill.Taylor@Sun.COM "\tNo hardware information available for this "
7919517SBill.Taylor@Sun.COM "device\n"), thisdev->ident->revid);
7929517SBill.Taylor@Sun.COM }
7939517SBill.Taylor@Sun.COM fprintf(stdout, "\n\n");
7949517SBill.Taylor@Sun.COM
7959517SBill.Taylor@Sun.COM return (tavor_close(thisdev));
7969517SBill.Taylor@Sun.COM }
7979517SBill.Taylor@Sun.COM
7989517SBill.Taylor@Sun.COM
7999517SBill.Taylor@Sun.COM /*
8009517SBill.Taylor@Sun.COM * Helper functions lurk beneath this point
8019517SBill.Taylor@Sun.COM */
8029517SBill.Taylor@Sun.COM
8039517SBill.Taylor@Sun.COM
8049517SBill.Taylor@Sun.COM /*
8059517SBill.Taylor@Sun.COM * tavor_identify performs the following actions:
8069517SBill.Taylor@Sun.COM *
8079517SBill.Taylor@Sun.COM * allocates and assigns thisdev->vpr
8089517SBill.Taylor@Sun.COM *
8099517SBill.Taylor@Sun.COM * allocates space for the 4 GUIDs which each IB device must have
8109517SBill.Taylor@Sun.COM * queries the tavor driver for this device's GUIDs
8119517SBill.Taylor@Sun.COM *
8129517SBill.Taylor@Sun.COM * determines the hardware vendor, so that thisdev->vpr->vid
8139517SBill.Taylor@Sun.COM * can be set correctly
8149517SBill.Taylor@Sun.COM */
8159517SBill.Taylor@Sun.COM static int
tavor_identify(struct devicelist * thisdev)8169517SBill.Taylor@Sun.COM tavor_identify(struct devicelist *thisdev)
8179517SBill.Taylor@Sun.COM {
8189517SBill.Taylor@Sun.COM int rv = FWFLASH_SUCCESS;
8199517SBill.Taylor@Sun.COM int fd, ret, i;
8209517SBill.Taylor@Sun.COM
8219517SBill.Taylor@Sun.COM tavor_flash_init_ioctl_t init_ioctl;
8229517SBill.Taylor@Sun.COM tavor_flash_ioctl_t info;
8239517SBill.Taylor@Sun.COM struct ib_encap_ident *manuf;
8249517SBill.Taylor@Sun.COM cfi_t cfi;
8259517SBill.Taylor@Sun.COM char temppsid[17];
8269517SBill.Taylor@Sun.COM char rawpsid[16];
8279517SBill.Taylor@Sun.COM
8289517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
8299517SBill.Taylor@Sun.COM uint32_t *ptr;
8309517SBill.Taylor@Sun.COM #endif
8319517SBill.Taylor@Sun.COM
8329517SBill.Taylor@Sun.COM /* open the device */
8339517SBill.Taylor@Sun.COM /* hook thisdev->ident->encap_ident to ib_encap_ident */
8349517SBill.Taylor@Sun.COM /* check that all the bits are sane */
8359517SBill.Taylor@Sun.COM /* return success, if warranted */
8369517SBill.Taylor@Sun.COM
8379517SBill.Taylor@Sun.COM errno = 0;
8389517SBill.Taylor@Sun.COM if ((fd = open(thisdev->access_devname, O_RDONLY)) < 0) {
8399517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
8409517SBill.Taylor@Sun.COM gettext("tavor: Unable to open a %s-attached "
8419517SBill.Taylor@Sun.COM "device node: %s: %s\n"), drivername,
8429517SBill.Taylor@Sun.COM thisdev->access_devname, strerror(errno));
8439517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
8449517SBill.Taylor@Sun.COM }
8459517SBill.Taylor@Sun.COM
8469517SBill.Taylor@Sun.COM if ((manuf = calloc(1, sizeof (ib_encap_ident_t))) == NULL) {
8479517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
8489517SBill.Taylor@Sun.COM gettext("tavor: Unable to calloc space for a "
8499517SBill.Taylor@Sun.COM "%s-attached handle structure\n"),
8509517SBill.Taylor@Sun.COM drivername);
8519517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
8529517SBill.Taylor@Sun.COM }
8539517SBill.Taylor@Sun.COM manuf->magic = FWFLASH_IB_MAGIC_NUMBER;
8549517SBill.Taylor@Sun.COM manuf->state = FWFLASH_IB_STATE_NONE;
8559517SBill.Taylor@Sun.COM manuf->fd = fd;
8569517SBill.Taylor@Sun.COM
8579517SBill.Taylor@Sun.COM thisdev->ident->encap_ident = manuf;
8589517SBill.Taylor@Sun.COM
85910618SShantkumar.Hiremath@Sun.COM bzero(&init_ioctl, sizeof (tavor_flash_init_ioctl_t));
86010618SShantkumar.Hiremath@Sun.COM bzero(&cfi, sizeof (cfi_t));
8619517SBill.Taylor@Sun.COM /*
8629517SBill.Taylor@Sun.COM * Inform driver that this command supports the Intel Extended
8639517SBill.Taylor@Sun.COM * CFI command set.
8649517SBill.Taylor@Sun.COM */
8659517SBill.Taylor@Sun.COM cfi.cfi_char[0x10] = 'M';
8669517SBill.Taylor@Sun.COM cfi.cfi_char[0x11] = 'X';
8679517SBill.Taylor@Sun.COM cfi.cfi_char[0x12] = '2';
8689517SBill.Taylor@Sun.COM init_ioctl.tf_cfi_info[0x4] = MLXSWAPBITS32(cfi.cfi_int[0x4]);
8699517SBill.Taylor@Sun.COM
8709517SBill.Taylor@Sun.COM errno = 0;
8719517SBill.Taylor@Sun.COM ret = ioctl(fd, TAVOR_IOCTL_FLASH_INIT, &init_ioctl);
8729517SBill.Taylor@Sun.COM if (ret < 0) {
8739517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
8749517SBill.Taylor@Sun.COM gettext("ib: TAVOR_IOCTL_FLASH_INIT failed: %s\n"),
8759517SBill.Taylor@Sun.COM strerror(errno));
8769517SBill.Taylor@Sun.COM free(manuf);
8779517SBill.Taylor@Sun.COM close(fd);
8789517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
8799517SBill.Taylor@Sun.COM }
8809517SBill.Taylor@Sun.COM
8819517SBill.Taylor@Sun.COM manuf->hwrev = init_ioctl.tf_hwrev;
8829517SBill.Taylor@Sun.COM
883*12472SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "tavor_identify: init_ioctl: hwrev: %X, "
884*12472SShantkumar.Hiremath@Sun.COM "fwver: %d.%d.%04d\n", init_ioctl.tf_hwrev,
885*12472SShantkumar.Hiremath@Sun.COM init_ioctl.tf_fwrev.tfi_maj, init_ioctl.tf_fwrev.tfi_min,
886*12472SShantkumar.Hiremath@Sun.COM init_ioctl.tf_fwrev.tfi_sub);
887*12472SShantkumar.Hiremath@Sun.COM
8889517SBill.Taylor@Sun.COM /*
8899517SBill.Taylor@Sun.COM * Determine whether the attached driver supports the Intel or
8909517SBill.Taylor@Sun.COM * AMD Extended CFI command sets. If it doesn't support either,
8919517SBill.Taylor@Sun.COM * then we're hosed, so error out.
8929517SBill.Taylor@Sun.COM */
8939517SBill.Taylor@Sun.COM for (i = 0; i < TAVOR_FLASH_CFI_SIZE_QUADLET; i++) {
8949517SBill.Taylor@Sun.COM cfi.cfi_int[i] = MLXSWAPBITS32(init_ioctl.tf_cfi_info[i]);
8959517SBill.Taylor@Sun.COM }
8969517SBill.Taylor@Sun.COM manuf->cmd_set = cfi.cfi_char[0x13];
8979517SBill.Taylor@Sun.COM
8989517SBill.Taylor@Sun.COM if (cfi.cfi_char[0x10] == 'Q' &&
8999517SBill.Taylor@Sun.COM cfi.cfi_char[0x11] == 'R' &&
9009517SBill.Taylor@Sun.COM cfi.cfi_char[0x12] == 'Y') {
9019517SBill.Taylor@Sun.COM /* make sure the cmd set is AMD */
9029517SBill.Taylor@Sun.COM if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET) {
9039517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
9049517SBill.Taylor@Sun.COM gettext("tavor: Unsupported flash device "
9059517SBill.Taylor@Sun.COM "command set\n"));
9069517SBill.Taylor@Sun.COM free(manuf);
9079517SBill.Taylor@Sun.COM close(fd);
9089517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
9099517SBill.Taylor@Sun.COM }
9109517SBill.Taylor@Sun.COM /* set some defaults */
91110618SShantkumar.Hiremath@Sun.COM manuf->sector_sz = TAVOR_FLASH_SECTOR_SZ_DEFAULT;
9129517SBill.Taylor@Sun.COM manuf->device_sz = TAVOR_FLASH_DEVICE_SZ_DEFAULT;
91310618SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "tavor_identify: CMDSET is AMD, SectorSz "
91410618SShantkumar.Hiremath@Sun.COM "are default \n");
9159517SBill.Taylor@Sun.COM } else {
9169517SBill.Taylor@Sun.COM if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET &&
9179517SBill.Taylor@Sun.COM manuf->cmd_set != TAVOR_FLASH_INTEL_CMDSET) {
9189517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
9199517SBill.Taylor@Sun.COM gettext("ib: Unknown flash device command set\n"));
9209517SBill.Taylor@Sun.COM free(manuf);
9219517SBill.Taylor@Sun.COM close(fd);
9229517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
9239517SBill.Taylor@Sun.COM }
9249517SBill.Taylor@Sun.COM /* read from the CFI data */
9259517SBill.Taylor@Sun.COM manuf->sector_sz = ((cfi.cfi_char[0x30] << 8) |
9269517SBill.Taylor@Sun.COM cfi.cfi_char[0x2F]) << 8;
9279517SBill.Taylor@Sun.COM manuf->device_sz = 0x1 << cfi.cfi_char[0x27];
92810618SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "tavor_identify: SectorSz is from CFI Data\n");
9299517SBill.Taylor@Sun.COM }
9309517SBill.Taylor@Sun.COM
93110618SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "tavor_identify: sector_sz: 0x%08x dev_sz: 0x%08x\n",
9329517SBill.Taylor@Sun.COM manuf->sector_sz, manuf->device_sz);
9339517SBill.Taylor@Sun.COM
9349517SBill.Taylor@Sun.COM manuf->state |= FWFLASH_IB_STATE_MMAP;
9359517SBill.Taylor@Sun.COM
9369517SBill.Taylor@Sun.COM /* set firmware revision */
9379517SBill.Taylor@Sun.COM manuf->fw_rev.major = init_ioctl.tf_fwrev.tfi_maj;
9389517SBill.Taylor@Sun.COM manuf->fw_rev.minor = init_ioctl.tf_fwrev.tfi_min;
9399517SBill.Taylor@Sun.COM manuf->fw_rev.subminor = init_ioctl.tf_fwrev.tfi_sub;
9409517SBill.Taylor@Sun.COM
94110618SShantkumar.Hiremath@Sun.COM logmsg(MSG_INFO, "tavor_identify: pn_len %d hwpn %s \n",
94210618SShantkumar.Hiremath@Sun.COM init_ioctl.tf_pn_len,
94310618SShantkumar.Hiremath@Sun.COM (init_ioctl.tf_pn_len != 0) ? init_ioctl.tf_hwpn : "(null)");
94410618SShantkumar.Hiremath@Sun.COM
9459517SBill.Taylor@Sun.COM if (((thisdev->ident->vid = calloc(1, MLX_VPR_VIDLEN + 1)) == NULL) ||
9469517SBill.Taylor@Sun.COM ((thisdev->ident->revid = calloc(1, MLX_VPR_REVLEN + 1)) == NULL)) {
9479517SBill.Taylor@Sun.COM
9489517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
9499517SBill.Taylor@Sun.COM gettext("ib: Unable to allocate space for a VPR "
9509517SBill.Taylor@Sun.COM "record.\n"));
9519517SBill.Taylor@Sun.COM free(thisdev->ident);
9529517SBill.Taylor@Sun.COM free(manuf->info.mlx_pn);
9539517SBill.Taylor@Sun.COM free(manuf->info.mlx_psid);
9549517SBill.Taylor@Sun.COM free(manuf->info.mlx_id);
9559517SBill.Taylor@Sun.COM free(manuf);
9569517SBill.Taylor@Sun.COM close(fd);
9579517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
9589517SBill.Taylor@Sun.COM }
9599517SBill.Taylor@Sun.COM (void) strlcpy(thisdev->ident->vid, "MELLANOX", MLX_VPR_VIDLEN);
9609517SBill.Taylor@Sun.COM /*
9619517SBill.Taylor@Sun.COM * We actually want the hwrev field from the ioctl above.
9629517SBill.Taylor@Sun.COM * Until we find out otherwise, add it onto the end of the
9639517SBill.Taylor@Sun.COM * firmware version details.
9649517SBill.Taylor@Sun.COM */
9659517SBill.Taylor@Sun.COM
96610618SShantkumar.Hiremath@Sun.COM snprintf(thisdev->ident->revid, MLX_VPR_REVLEN, "%d.%d.%03d",
9679517SBill.Taylor@Sun.COM manuf->fw_rev.major, manuf->fw_rev.minor,
9689517SBill.Taylor@Sun.COM manuf->fw_rev.subminor);
9699517SBill.Taylor@Sun.COM
9709517SBill.Taylor@Sun.COM bzero(manuf->ibguids, sizeof (manuf->ibguids));
9719517SBill.Taylor@Sun.COM
9729517SBill.Taylor@Sun.COM /*
9739517SBill.Taylor@Sun.COM * For convenience we read in the Invariant Sector as
9749517SBill.Taylor@Sun.COM * well as both the Primary and Secondary Pointer Sectors
9759517SBill.Taylor@Sun.COM */
9769517SBill.Taylor@Sun.COM
9779517SBill.Taylor@Sun.COM if ((manuf->inv = calloc(1, manuf->sector_sz)) == NULL) {
9789517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
9799517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for storing "
9809517SBill.Taylor@Sun.COM "the HCA's Invariant Sector\n"));
9819517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
9829517SBill.Taylor@Sun.COM }
9839517SBill.Taylor@Sun.COM bzero(&info, sizeof (tavor_flash_ioctl_t));
9849517SBill.Taylor@Sun.COM
9859517SBill.Taylor@Sun.COM info.tf_type = TAVOR_FLASH_READ_SECTOR;
9869517SBill.Taylor@Sun.COM info.tf_sector = (caddr_t)manuf->inv;
9879517SBill.Taylor@Sun.COM info.tf_sector_num = 0;
9889517SBill.Taylor@Sun.COM
9899517SBill.Taylor@Sun.COM errno = 0;
9909517SBill.Taylor@Sun.COM
9919517SBill.Taylor@Sun.COM if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
9929517SBill.Taylor@Sun.COM < 0) {
9939517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
9949517SBill.Taylor@Sun.COM gettext("tavor: Unable to read HCA Invariant Sector\n"));
9959517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
9969517SBill.Taylor@Sun.COM }
9979517SBill.Taylor@Sun.COM
9989517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
9999517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)manuf->inv;
10009517SBill.Taylor@Sun.COM for (i = 0; i < (manuf->sector_sz / 4); i++) {
10019517SBill.Taylor@Sun.COM ptr[i] = htonl(ptr[i]);
10029517SBill.Taylor@Sun.COM }
10039517SBill.Taylor@Sun.COM #endif
10049517SBill.Taylor@Sun.COM
10059517SBill.Taylor@Sun.COM if ((manuf->pps = calloc(1, manuf->sector_sz)) == NULL) {
10069517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
10079517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for storing "
10089517SBill.Taylor@Sun.COM "the HCA's Primary Pointer Sector\n"));
10099517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
10109517SBill.Taylor@Sun.COM }
10119517SBill.Taylor@Sun.COM bzero(&info, sizeof (tavor_flash_ioctl_t));
10129517SBill.Taylor@Sun.COM
10139517SBill.Taylor@Sun.COM info.tf_type = TAVOR_FLASH_READ_SECTOR;
10149517SBill.Taylor@Sun.COM info.tf_sector = (caddr_t)manuf->pps;
10159517SBill.Taylor@Sun.COM info.tf_sector_num = 1;
10169517SBill.Taylor@Sun.COM
10179517SBill.Taylor@Sun.COM errno = 0;
10189517SBill.Taylor@Sun.COM
10199517SBill.Taylor@Sun.COM if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
10209517SBill.Taylor@Sun.COM < 0) {
10219517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
10229517SBill.Taylor@Sun.COM gettext("tavor: Unable to read HCA Primary "
10239517SBill.Taylor@Sun.COM "Pointer Sector\n"));
10249517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
10259517SBill.Taylor@Sun.COM }
10269517SBill.Taylor@Sun.COM
10279517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
10289517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)manuf->pps;
10299517SBill.Taylor@Sun.COM for (i = 0; i < (manuf->sector_sz / 4); i++) {
10309517SBill.Taylor@Sun.COM ptr[i] = htonl(ptr[i]);
10319517SBill.Taylor@Sun.COM }
10329517SBill.Taylor@Sun.COM #endif
10339517SBill.Taylor@Sun.COM
10349517SBill.Taylor@Sun.COM if ((manuf->sps = calloc(1, manuf->sector_sz)) == NULL) {
10359517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
10369517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for storing "
10379517SBill.Taylor@Sun.COM "the HCA's Secondary Pointer Sector\n"));
10389517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
10399517SBill.Taylor@Sun.COM }
10409517SBill.Taylor@Sun.COM bzero(&info, sizeof (tavor_flash_ioctl_t));
10419517SBill.Taylor@Sun.COM
10429517SBill.Taylor@Sun.COM info.tf_type = TAVOR_FLASH_READ_SECTOR;
10439517SBill.Taylor@Sun.COM info.tf_sector = (caddr_t)manuf->sps;
10449517SBill.Taylor@Sun.COM info.tf_sector_num = 2;
10459517SBill.Taylor@Sun.COM
10469517SBill.Taylor@Sun.COM errno = 0;
10479517SBill.Taylor@Sun.COM
10489517SBill.Taylor@Sun.COM if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
10499517SBill.Taylor@Sun.COM < 0) {
10509517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
10519517SBill.Taylor@Sun.COM gettext("tavor: Unable to read HCA Secondary "
10529517SBill.Taylor@Sun.COM "Pointer Sector\n"));
10539517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
10549517SBill.Taylor@Sun.COM }
10559517SBill.Taylor@Sun.COM
10569517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
10579517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)manuf->sps;
10589517SBill.Taylor@Sun.COM for (i = 0; i < (manuf->sector_sz / 4); i++) {
10599517SBill.Taylor@Sun.COM ptr[i] = htonl(ptr[i]);
10609517SBill.Taylor@Sun.COM }
10619517SBill.Taylor@Sun.COM #endif
10629517SBill.Taylor@Sun.COM
10639517SBill.Taylor@Sun.COM if ((ret = tavor_get_guids(manuf)) != FWFLASH_SUCCESS) {
10649517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
10659517SBill.Taylor@Sun.COM gettext("ib: No guids found for device %s!\n"),
10669517SBill.Taylor@Sun.COM thisdev->access_devname);
10679517SBill.Taylor@Sun.COM }
10689517SBill.Taylor@Sun.COM
10699517SBill.Taylor@Sun.COM /* set hw part number, psid, and name in handle */
10709517SBill.Taylor@Sun.COM bzero(temppsid, 17);
10719517SBill.Taylor@Sun.COM bcopy(manuf->pps+FLASH_PS_PSID_OFFSET, &rawpsid, 16);
10729517SBill.Taylor@Sun.COM
10739517SBill.Taylor@Sun.COM for (i = 0; i < 16; i += 4) {
10749517SBill.Taylor@Sun.COM temppsid[i] = rawpsid[i+3];
10759517SBill.Taylor@Sun.COM temppsid[i+1] = rawpsid[i+2];
10769517SBill.Taylor@Sun.COM temppsid[i+2] = rawpsid[i+1];
10779517SBill.Taylor@Sun.COM temppsid[i+3] = rawpsid[i];
10789517SBill.Taylor@Sun.COM }
10799517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
10809517SBill.Taylor@Sun.COM "tavor: have raw '%s', want munged '%s'\n",
10819517SBill.Taylor@Sun.COM rawpsid, temppsid);
10829517SBill.Taylor@Sun.COM
10839517SBill.Taylor@Sun.COM /* now walk the magic decoder ring table */
10849517SBill.Taylor@Sun.COM manuf->info.mlx_pn = NULL;
10859517SBill.Taylor@Sun.COM manuf->info.mlx_psid = NULL;
10869517SBill.Taylor@Sun.COM manuf->info.mlx_id = NULL;
10879517SBill.Taylor@Sun.COM manuf->pn_len = 0;
10889517SBill.Taylor@Sun.COM
10899517SBill.Taylor@Sun.COM for (i = 0; i < MLX_MAX_ID; i++) {
10909517SBill.Taylor@Sun.COM if ((strncmp(temppsid, mlx_mdr[i].mlx_psid,
10919517SBill.Taylor@Sun.COM MLX_PSID_SZ)) == 0) {
10929517SBill.Taylor@Sun.COM /* matched */
10939517SBill.Taylor@Sun.COM if ((manuf->info.mlx_pn = calloc(1,
10949517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_pn) + 1)) == NULL) {
10959517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
10969517SBill.Taylor@Sun.COM "tavor: no space available for the "
10979517SBill.Taylor@Sun.COM "HCA PSID record (1)\n");
10989517SBill.Taylor@Sun.COM } else {
10999517SBill.Taylor@Sun.COM (void) strlcpy(manuf->info.mlx_pn,
11009517SBill.Taylor@Sun.COM mlx_mdr[i].mlx_pn,
11019517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_pn) + 1);
11029517SBill.Taylor@Sun.COM manuf->pn_len = strlen(mlx_mdr[i].mlx_pn);
11039517SBill.Taylor@Sun.COM }
11049517SBill.Taylor@Sun.COM
11059517SBill.Taylor@Sun.COM if ((manuf->info.mlx_psid = calloc(1,
11069517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_psid) + 1)) == NULL) {
11079517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
11089517SBill.Taylor@Sun.COM "tavor: no space available for the "
11099517SBill.Taylor@Sun.COM "HCA PSID record (2)\n");
11109517SBill.Taylor@Sun.COM } else {
11119517SBill.Taylor@Sun.COM (void) strlcpy(manuf->info.mlx_psid,
11129517SBill.Taylor@Sun.COM mlx_mdr[i].mlx_psid,
11139517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_psid) + 1);
11149517SBill.Taylor@Sun.COM }
11159517SBill.Taylor@Sun.COM if ((manuf->info.mlx_id = calloc(1,
11169517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_id) + 1)) == NULL) {
11179517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
11189517SBill.Taylor@Sun.COM "tavor: no space available for the "
11199517SBill.Taylor@Sun.COM "HCA PSID record (3)\n");
11209517SBill.Taylor@Sun.COM } else {
11219517SBill.Taylor@Sun.COM (void) strlcpy(manuf->info.mlx_id,
11229517SBill.Taylor@Sun.COM mlx_mdr[i].mlx_id,
11239517SBill.Taylor@Sun.COM strlen(mlx_mdr[i].mlx_id) + 1);
11249517SBill.Taylor@Sun.COM }
11259517SBill.Taylor@Sun.COM }
11269517SBill.Taylor@Sun.COM }
11279517SBill.Taylor@Sun.COM if ((manuf->pn_len == 0) || (i == MLX_MAX_ID)) {
11289517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
11299517SBill.Taylor@Sun.COM "tavor: No hardware part number information available "
11309517SBill.Taylor@Sun.COM "for this HCA\n");
11319517SBill.Taylor@Sun.COM /* Until we deliver the arbel driver, it's all Mellanox */
11329517SBill.Taylor@Sun.COM i = strlen("No hardware information available for this device");
11339517SBill.Taylor@Sun.COM
11349517SBill.Taylor@Sun.COM thisdev->ident->pid = calloc(1, i + 2);
11359517SBill.Taylor@Sun.COM sprintf(thisdev->ident->pid, "No hardware information "
11369517SBill.Taylor@Sun.COM "available for this device");
11379517SBill.Taylor@Sun.COM } else {
11389517SBill.Taylor@Sun.COM if ((thisdev->ident->pid = calloc(1,
11399517SBill.Taylor@Sun.COM strlen(manuf->info.mlx_psid) + 1)) != NULL) {
11409517SBill.Taylor@Sun.COM (void) strlcpy(thisdev->ident->pid,
11419517SBill.Taylor@Sun.COM manuf->info.mlx_psid,
11429517SBill.Taylor@Sun.COM strlen(manuf->info.mlx_psid) + 1);
11439517SBill.Taylor@Sun.COM } else {
11449517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
11459517SBill.Taylor@Sun.COM gettext("ib: Unable to allocate space for a "
11469517SBill.Taylor@Sun.COM "hardware identifier\n"));
11479517SBill.Taylor@Sun.COM free(thisdev->ident);
11489517SBill.Taylor@Sun.COM free(manuf->info.mlx_pn);
11499517SBill.Taylor@Sun.COM free(manuf->info.mlx_psid);
11509517SBill.Taylor@Sun.COM free(manuf->info.mlx_id);
11519517SBill.Taylor@Sun.COM free(manuf);
11529517SBill.Taylor@Sun.COM close(fd);
11539517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
11549517SBill.Taylor@Sun.COM }
11559517SBill.Taylor@Sun.COM }
11569517SBill.Taylor@Sun.COM
11579517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
11589517SBill.Taylor@Sun.COM if ((thisdev->addresses[i] = calloc(1,
11599517SBill.Taylor@Sun.COM (2 * sizeof (uint64_t)) + 1)) == NULL) {
11609517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
11619517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for a "
11629517SBill.Taylor@Sun.COM "human-readable HCA guid\n"));
11639517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
11649517SBill.Taylor@Sun.COM }
11659517SBill.Taylor@Sun.COM (void) sprintf(thisdev->addresses[i], "%016llx",
11669517SBill.Taylor@Sun.COM manuf->ibguids[i]);
11679517SBill.Taylor@Sun.COM }
11689517SBill.Taylor@Sun.COM
11699517SBill.Taylor@Sun.COM /*
11709517SBill.Taylor@Sun.COM * We do NOT close the fd here, since we can close it
11719517SBill.Taylor@Sun.COM * at the end of the fw_readfw() or fw_writefw() functions
11729517SBill.Taylor@Sun.COM * instead and not get the poor dear confused about whether
11739517SBill.Taylor@Sun.COM * it's been inited already.
11749517SBill.Taylor@Sun.COM */
11759517SBill.Taylor@Sun.COM
11769517SBill.Taylor@Sun.COM return (rv);
11779517SBill.Taylor@Sun.COM }
11789517SBill.Taylor@Sun.COM
11799517SBill.Taylor@Sun.COM /*ARGSUSED*/
11809517SBill.Taylor@Sun.COM static int
tavor_get_guids(struct ib_encap_ident * handle)11819517SBill.Taylor@Sun.COM tavor_get_guids(struct ib_encap_ident *handle)
11829517SBill.Taylor@Sun.COM {
11839517SBill.Taylor@Sun.COM int rv, j;
11849517SBill.Taylor@Sun.COM uint32_t i = 0x00;
11859517SBill.Taylor@Sun.COM tavor_flash_ioctl_t info;
11869517SBill.Taylor@Sun.COM struct mlx_guid_sect *p, *s;
11879517SBill.Taylor@Sun.COM
11889517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
11899517SBill.Taylor@Sun.COM uint32_t *ptr, tmp;
11909517SBill.Taylor@Sun.COM #endif
11919517SBill.Taylor@Sun.COM
11929517SBill.Taylor@Sun.COM /*
11939517SBill.Taylor@Sun.COM * The reference for this function is the
11949517SBill.Taylor@Sun.COM * Mellanox HCA Flash Programming Application Note
11959517SBill.Taylor@Sun.COM * rev 1.44, 2007. Chapter 4 in particular.
11969517SBill.Taylor@Sun.COM *
11979517SBill.Taylor@Sun.COM * NOTE: this Mellanox document is labelled Confidential
11989517SBill.Taylor@Sun.COM * so DO NOT move this file out of usr/closed without
11999517SBill.Taylor@Sun.COM * explicit approval from Sun Legal.
12009517SBill.Taylor@Sun.COM */
12019517SBill.Taylor@Sun.COM
12029517SBill.Taylor@Sun.COM /*
12039517SBill.Taylor@Sun.COM * We need to check for both the Primary and Secondary
12049517SBill.Taylor@Sun.COM * Image GUIDs. handle->pps and handle->sps should be
12059517SBill.Taylor@Sun.COM * non-NULL by the time we're called, since we depend
12069517SBill.Taylor@Sun.COM * on them being stashed in handle. Saves on an ioctl().
12079517SBill.Taylor@Sun.COM */
12089517SBill.Taylor@Sun.COM
12099517SBill.Taylor@Sun.COM /* make sure we've got our fallback position organised */
12109517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
12119517SBill.Taylor@Sun.COM handle->ibguids[i] = 0x00000000;
12129517SBill.Taylor@Sun.COM }
12139517SBill.Taylor@Sun.COM
12149517SBill.Taylor@Sun.COM /* convenience .... */
12159517SBill.Taylor@Sun.COM
12169517SBill.Taylor@Sun.COM if ((p = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) {
12179517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
12189517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for "
12199517SBill.Taylor@Sun.COM "HCA guid record (1)\n"));
12209517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
12219517SBill.Taylor@Sun.COM }
12229517SBill.Taylor@Sun.COM if ((s = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) {
12239517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
12249517SBill.Taylor@Sun.COM gettext("tavor: Unable to allocate space for "
12259517SBill.Taylor@Sun.COM "HCA guid record (2)\n"));
12269517SBill.Taylor@Sun.COM free(p);
12279517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
12289517SBill.Taylor@Sun.COM }
12299517SBill.Taylor@Sun.COM
12309517SBill.Taylor@Sun.COM bcopy(&handle->pps[0], &i, 4);
12319517SBill.Taylor@Sun.COM handle->pfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR;
12329517SBill.Taylor@Sun.COM bcopy(&handle->sps[0], &i, 4);
12339517SBill.Taylor@Sun.COM handle->sfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR;
12349517SBill.Taylor@Sun.COM
12359517SBill.Taylor@Sun.COM bzero(&info, sizeof (tavor_flash_ioctl_t));
12369517SBill.Taylor@Sun.COM info.tf_type = TAVOR_FLASH_READ_QUADLET;
12379517SBill.Taylor@Sun.COM info.tf_addr = handle->pfi_guid_addr;
12389517SBill.Taylor@Sun.COM
12399517SBill.Taylor@Sun.COM errno = 0;
12409517SBill.Taylor@Sun.COM
12419517SBill.Taylor@Sun.COM rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, &info);
12429517SBill.Taylor@Sun.COM if (rv < 0) {
12439517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
12449517SBill.Taylor@Sun.COM gettext("tavor: Unable to read Primary Image "
12459517SBill.Taylor@Sun.COM "guid offset\n"));
12469517SBill.Taylor@Sun.COM free(p);
12479517SBill.Taylor@Sun.COM free(s);
12489517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
12499517SBill.Taylor@Sun.COM }
12509517SBill.Taylor@Sun.COM
12519517SBill.Taylor@Sun.COM /*
12529517SBill.Taylor@Sun.COM * This is because we want the whole of the section
12539517SBill.Taylor@Sun.COM * including the 16 reserved bytes at the front so
12549517SBill.Taylor@Sun.COM * that if we recalculate the CRC we've got the correct
12559517SBill.Taylor@Sun.COM * data to do it with
12569517SBill.Taylor@Sun.COM */
12579517SBill.Taylor@Sun.COM info.tf_addr = handle->pfi_guid_addr + info.tf_quadlet
12589517SBill.Taylor@Sun.COM - FLASH_GUID_PTR - 16;
12599517SBill.Taylor@Sun.COM
12609517SBill.Taylor@Sun.COM bzero(handle->pri_guid_section, sizeof (mlx_guid_sect_t));
12619517SBill.Taylor@Sun.COM
12629517SBill.Taylor@Sun.COM for (j = 0; j < 13; j++) {
12639517SBill.Taylor@Sun.COM errno = 0;
12649517SBill.Taylor@Sun.COM if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
12659517SBill.Taylor@Sun.COM &info)) < 0) {
12669517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
12679517SBill.Taylor@Sun.COM gettext("tavor: Unable to read Primary Image "
12689517SBill.Taylor@Sun.COM "guid chunk %d\n"), j);
12699517SBill.Taylor@Sun.COM }
12709517SBill.Taylor@Sun.COM handle->pri_guid_section[j] = info.tf_quadlet;
12719517SBill.Taylor@Sun.COM info.tf_addr += 4;
12729517SBill.Taylor@Sun.COM }
12739517SBill.Taylor@Sun.COM bcopy(&handle->pri_guid_section, p, sizeof (struct mlx_guid_sect));
12749517SBill.Taylor@Sun.COM
12759517SBill.Taylor@Sun.COM /* now grab the secondary guid set */
12769517SBill.Taylor@Sun.COM bzero(&info, sizeof (tavor_flash_ioctl_t));
12779517SBill.Taylor@Sun.COM info.tf_type = TAVOR_FLASH_READ_QUADLET;
12789517SBill.Taylor@Sun.COM info.tf_addr = handle->sfi_guid_addr;
12799517SBill.Taylor@Sun.COM
12809517SBill.Taylor@Sun.COM errno = 0;
12819517SBill.Taylor@Sun.COM
12829517SBill.Taylor@Sun.COM if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
12839517SBill.Taylor@Sun.COM &info)) < 0) {
12849517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
12859517SBill.Taylor@Sun.COM gettext("tavor: Unable to read Secondary Image "
12869517SBill.Taylor@Sun.COM "guid offset (%s)\n"), strerror(errno));
12879517SBill.Taylor@Sun.COM free(p);
12889517SBill.Taylor@Sun.COM free(s);
12899517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
12909517SBill.Taylor@Sun.COM }
12919517SBill.Taylor@Sun.COM
12929517SBill.Taylor@Sun.COM info.tf_addr = handle->sfi_guid_addr + info.tf_quadlet
12939517SBill.Taylor@Sun.COM - FLASH_GUID_PTR - 16;
12949517SBill.Taylor@Sun.COM
12959517SBill.Taylor@Sun.COM bzero(handle->sec_guid_section, sizeof (mlx_guid_sect_t));
12969517SBill.Taylor@Sun.COM
12979517SBill.Taylor@Sun.COM for (j = 0; j < 13; j++) {
12989517SBill.Taylor@Sun.COM errno = 0;
12999517SBill.Taylor@Sun.COM if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
13009517SBill.Taylor@Sun.COM &info)) < 0) {
13019517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
13029517SBill.Taylor@Sun.COM gettext("tavor: Unable to read Secondary Image "
13039517SBill.Taylor@Sun.COM "guid chunk %d (%s)\n"), j, strerror(errno));
13049517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
13059517SBill.Taylor@Sun.COM }
13069517SBill.Taylor@Sun.COM handle->sec_guid_section[j] = info.tf_quadlet;
13079517SBill.Taylor@Sun.COM info.tf_addr += 4;
13089517SBill.Taylor@Sun.COM }
13099517SBill.Taylor@Sun.COM
13109517SBill.Taylor@Sun.COM bcopy(&handle->sec_guid_section, s, sizeof (struct mlx_guid_sect));
13119517SBill.Taylor@Sun.COM
13129517SBill.Taylor@Sun.COM #if defined(_LITTLE_ENDIAN)
13139517SBill.Taylor@Sun.COM
13149517SBill.Taylor@Sun.COM /*
13159517SBill.Taylor@Sun.COM * We don't actually care about p or s later on if we
13169517SBill.Taylor@Sun.COM * write to the HCA - we've already stored the binary
13179517SBill.Taylor@Sun.COM * form in handle->pri_guid_section and handle->sec_guid_section.
13189517SBill.Taylor@Sun.COM * What we're doing here is creating human-readable forms.
13199517SBill.Taylor@Sun.COM */
13209517SBill.Taylor@Sun.COM
13219517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)p;
13229517SBill.Taylor@Sun.COM for (j = 0; j < 14; j += 2) {
13239517SBill.Taylor@Sun.COM tmp = ptr[j];
13249517SBill.Taylor@Sun.COM ptr[j] = ptr[j+1];
13259517SBill.Taylor@Sun.COM ptr[j+1] = tmp;
13269517SBill.Taylor@Sun.COM }
13279517SBill.Taylor@Sun.COM
13289517SBill.Taylor@Sun.COM ptr = (uint32_t *)(uintptr_t)s;
13299517SBill.Taylor@Sun.COM for (j = 0; j < 14; j += 2) {
13309517SBill.Taylor@Sun.COM tmp = ptr[j];
13319517SBill.Taylor@Sun.COM ptr[j] = ptr[j+1];
13329517SBill.Taylor@Sun.COM ptr[j+1] = tmp;
13339517SBill.Taylor@Sun.COM }
13349517SBill.Taylor@Sun.COM #endif
13359517SBill.Taylor@Sun.COM
13369517SBill.Taylor@Sun.COM /*
13379517SBill.Taylor@Sun.COM * We don't check and munge the GUIDs to the manufacturer's
13389517SBill.Taylor@Sun.COM * defaults, because if the GUIDs are actually set incorrectly
13399517SBill.Taylor@Sun.COM * at identify time, we really need to know that.
13409517SBill.Taylor@Sun.COM *
13419517SBill.Taylor@Sun.COM * If the GUIDs are bogus, then we'll fix that in fw_writefw()
13429517SBill.Taylor@Sun.COM * by blatting the manufacturer's defaults from the firmware
13439517SBill.Taylor@Sun.COM * image file instead.
13449517SBill.Taylor@Sun.COM */
13459517SBill.Taylor@Sun.COM if ((p->nodeguid == s->nodeguid) &&
13469517SBill.Taylor@Sun.COM (p->port1guid == s->port1guid) &&
13479517SBill.Taylor@Sun.COM (p->port2guid == s->port2guid) &&
13489517SBill.Taylor@Sun.COM (p->sysimguid == s->sysimguid)) {
13499517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
13509517SBill.Taylor@Sun.COM "tavor: primary and secondary guids are the same\n");
13519517SBill.Taylor@Sun.COM handle->ibguids[0] = p->nodeguid;
13529517SBill.Taylor@Sun.COM handle->ibguids[1] = p->port1guid;
13539517SBill.Taylor@Sun.COM handle->ibguids[2] = p->port2guid;
13549517SBill.Taylor@Sun.COM handle->ibguids[3] = p->sysimguid;
13559517SBill.Taylor@Sun.COM } else {
13569517SBill.Taylor@Sun.COM /*
13579517SBill.Taylor@Sun.COM * We're going to assume that the guids which are numerically
13589517SBill.Taylor@Sun.COM * larger than the others are correct and copy them to
13599517SBill.Taylor@Sun.COM * handle->ibguids.
13609517SBill.Taylor@Sun.COM *
13619517SBill.Taylor@Sun.COM * For those in the know wrt InfiniBand, if this assumption
13629517SBill.Taylor@Sun.COM * is incorrect, _please_ bug this and fix it, adding a
13639517SBill.Taylor@Sun.COM * comment or two to indicate why
13649517SBill.Taylor@Sun.COM */
13659517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
13669517SBill.Taylor@Sun.COM "tavor: primary and secondary guids don't all match\n");
13679517SBill.Taylor@Sun.COM
13689517SBill.Taylor@Sun.COM if (s->nodeguid > p->nodeguid) {
13699517SBill.Taylor@Sun.COM handle->ibguids[0] = s->nodeguid;
13709517SBill.Taylor@Sun.COM handle->ibguids[1] = s->port1guid;
13719517SBill.Taylor@Sun.COM handle->ibguids[2] = s->port2guid;
13729517SBill.Taylor@Sun.COM handle->ibguids[3] = s->sysimguid;
13739517SBill.Taylor@Sun.COM bzero(p, sizeof (struct mlx_guid_sect));
13749517SBill.Taylor@Sun.COM } else {
13759517SBill.Taylor@Sun.COM handle->ibguids[0] = p->nodeguid;
13769517SBill.Taylor@Sun.COM handle->ibguids[1] = p->port1guid;
13779517SBill.Taylor@Sun.COM handle->ibguids[2] = p->port2guid;
13789517SBill.Taylor@Sun.COM handle->ibguids[3] = p->sysimguid;
13799517SBill.Taylor@Sun.COM bzero(s, sizeof (struct mlx_guid_sect));
13809517SBill.Taylor@Sun.COM }
13819517SBill.Taylor@Sun.COM }
13829517SBill.Taylor@Sun.COM
13839517SBill.Taylor@Sun.COM free(p);
13849517SBill.Taylor@Sun.COM free(s);
13859517SBill.Taylor@Sun.COM
13869517SBill.Taylor@Sun.COM if (fwflash_debug) {
13879517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
13889517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "ibguids[%d] %0llx\n", i,
13899517SBill.Taylor@Sun.COM handle->ibguids[i]);
13909517SBill.Taylor@Sun.COM }
13919517SBill.Taylor@Sun.COM }
13929517SBill.Taylor@Sun.COM
13939517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
13949517SBill.Taylor@Sun.COM }
13959517SBill.Taylor@Sun.COM
13969517SBill.Taylor@Sun.COM
13979517SBill.Taylor@Sun.COM int
tavor_close(struct devicelist * flashdev)13989517SBill.Taylor@Sun.COM tavor_close(struct devicelist *flashdev)
13999517SBill.Taylor@Sun.COM {
14009517SBill.Taylor@Sun.COM
14019517SBill.Taylor@Sun.COM struct ib_encap_ident *handle;
14029517SBill.Taylor@Sun.COM
14039517SBill.Taylor@Sun.COM handle = (struct ib_encap_ident *)flashdev->ident->encap_ident;
14049517SBill.Taylor@Sun.COM if (handle->fd > 0) {
14059517SBill.Taylor@Sun.COM (void) ioctl(handle->fd, TAVOR_IOCTL_FLASH_FINI);
14069517SBill.Taylor@Sun.COM errno = 0;
14079517SBill.Taylor@Sun.COM if (close(handle->fd) != 0) {
14089517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
14099517SBill.Taylor@Sun.COM gettext("tavor: Unable to properly close "
14109517SBill.Taylor@Sun.COM "device %s! (%s)\n"),
14119517SBill.Taylor@Sun.COM flashdev->access_devname,
14129517SBill.Taylor@Sun.COM strerror(errno));
14139517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
14149517SBill.Taylor@Sun.COM }
14159517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
14169517SBill.Taylor@Sun.COM } else
14179517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
14189517SBill.Taylor@Sun.COM }
14199517SBill.Taylor@Sun.COM
14209517SBill.Taylor@Sun.COM
14219517SBill.Taylor@Sun.COM /*
14229517SBill.Taylor@Sun.COM * We would not need this if it were not for Cisco's image using the
14239517SBill.Taylor@Sun.COM * VSD to store boot options and flags for their PXE boot extension,
14249517SBill.Taylor@Sun.COM * but not setting the proper default values for the extension in
14259517SBill.Taylor@Sun.COM * their image. As it turns out, some of the data for the extension
14269517SBill.Taylor@Sun.COM * is stored in the VSD in the firmware file, and the rest is set by
14279517SBill.Taylor@Sun.COM * their firmware utility. That's not very nice for us, since it could
14289517SBill.Taylor@Sun.COM * change at any time without our knowledge. Well, for the time being,
14299517SBill.Taylor@Sun.COM * we can use this to examine and fix up anything in the VSD that we might
14309517SBill.Taylor@Sun.COM * need to handle, for any vendor specific settings.
14319517SBill.Taylor@Sun.COM */
14329517SBill.Taylor@Sun.COM static void
tavor_cisco_extensions(mlx_xps_t * hcaxps,mlx_xps_t * diskxps)14339517SBill.Taylor@Sun.COM tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps)
14349517SBill.Taylor@Sun.COM {
14359517SBill.Taylor@Sun.COM uint16_t sig1, sig2;
14369517SBill.Taylor@Sun.COM uint32_t i;
14379517SBill.Taylor@Sun.COM
14389517SBill.Taylor@Sun.COM
14399517SBill.Taylor@Sun.COM bcopy(hcaxps->vsdpsid, &i, 4);
14409517SBill.Taylor@Sun.COM sig1 = htonl(i);
14419517SBill.Taylor@Sun.COM bcopy(&hcaxps->vsdpsid[223], &i, 4);
14429517SBill.Taylor@Sun.COM sig2 = htonl(i);
14439517SBill.Taylor@Sun.COM
14449517SBill.Taylor@Sun.COM
14459517SBill.Taylor@Sun.COM if (sig1 == FLASH_VSD_CISCO_SIGNATURE &&
14469517SBill.Taylor@Sun.COM sig2 == FLASH_VSD_CISCO_SIGNATURE) {
14479517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
14489517SBill.Taylor@Sun.COM "tavor: CISCO signature found in HCA's VSD, copying to "
14499517SBill.Taylor@Sun.COM "new image's VSD\n");
14509517SBill.Taylor@Sun.COM
14519517SBill.Taylor@Sun.COM i = htonl(FLASH_VSD_CISCO_SIGNATURE);
14529517SBill.Taylor@Sun.COM bcopy(&i, diskxps->vsdpsid, 2);
14539517SBill.Taylor@Sun.COM
14549517SBill.Taylor@Sun.COM /*
14559517SBill.Taylor@Sun.COM * Set the boot_version field to '2'. This value is
14569517SBill.Taylor@Sun.COM * located in the 2nd byte of the last uint32_t.
14579517SBill.Taylor@Sun.COM * Per the previous version of fwflash, we just or
14589517SBill.Taylor@Sun.COM * the bit in and get on with it.
14599517SBill.Taylor@Sun.COM */
14609517SBill.Taylor@Sun.COM
14619517SBill.Taylor@Sun.COM i = (diskxps->vsdpsid[222] | FLASH_VSD_CISCO_BOOT_VERSION);
14629517SBill.Taylor@Sun.COM bcopy(&i, &diskxps->vsdpsid[222], 2);
14639517SBill.Taylor@Sun.COM /*
14649517SBill.Taylor@Sun.COM * Now set some defaults for the SRP boot extension,
14659517SBill.Taylor@Sun.COM * currently the only extension we support. These flags
14669517SBill.Taylor@Sun.COM * are located in the second uint32_t of the VSD.
14679517SBill.Taylor@Sun.COM */
14689517SBill.Taylor@Sun.COM
14699517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: CISCO boot flags currently set "
14709517SBill.Taylor@Sun.COM "to 0x%08x\n",
14719517SBill.Taylor@Sun.COM diskxps->vsdpsid[1]);
14729517SBill.Taylor@Sun.COM
14739517SBill.Taylor@Sun.COM diskxps->vsdpsid[1] =
14749517SBill.Taylor@Sun.COM htonl(diskxps->vsdpsid[1] |
14759517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_AUTOUPGRADE |
14769517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_BOOT_OPTIONS |
14779517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_1 |
14789517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_2 |
14799517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_SCAN |
14809517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_BOOT_TYPE_WELL_KNOWN |
14819517SBill.Taylor@Sun.COM FLASH_VSD_CISCO_FLAG_BOOT_TRY_FOREVER);
14829517SBill.Taylor@Sun.COM
14839517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: CISCO boot flags now set "
14849517SBill.Taylor@Sun.COM "to 0x%08x\n",
14859517SBill.Taylor@Sun.COM diskxps->vsdpsid[1]);
14869517SBill.Taylor@Sun.COM } else
14879517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
14889517SBill.Taylor@Sun.COM "tavor: CISCO signature not found in HCA's VSD\n");
14899517SBill.Taylor@Sun.COM }
14909517SBill.Taylor@Sun.COM
14919517SBill.Taylor@Sun.COM
14929517SBill.Taylor@Sun.COM static int
tavor_write_sector(int fd,int sectnum,int32_t * data)14939517SBill.Taylor@Sun.COM tavor_write_sector(int fd, int sectnum, int32_t *data)
14949517SBill.Taylor@Sun.COM {
14959517SBill.Taylor@Sun.COM int rv, i;
14969517SBill.Taylor@Sun.COM tavor_flash_ioctl_t cmd;
14979517SBill.Taylor@Sun.COM
14989517SBill.Taylor@Sun.COM
14999517SBill.Taylor@Sun.COM bzero(&cmd, sizeof (tavor_flash_ioctl_t));
15009517SBill.Taylor@Sun.COM
15019517SBill.Taylor@Sun.COM cmd.tf_type = TAVOR_FLASH_WRITE_SECTOR;
15029517SBill.Taylor@Sun.COM cmd.tf_sector_num = sectnum;
15039517SBill.Taylor@Sun.COM cmd.tf_sector = (caddr_t)data;
15049517SBill.Taylor@Sun.COM
15059517SBill.Taylor@Sun.COM errno = 0;
15069517SBill.Taylor@Sun.COM
15079517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15089517SBill.Taylor@Sun.COM "tavor: tavor_write_sector(fd %d, sectnum 0x%x, data 0x%lx)\n",
15099517SBill.Taylor@Sun.COM fd, sectnum, data);
15109517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15119517SBill.Taylor@Sun.COM "tavor:\n"
15129517SBill.Taylor@Sun.COM "\tcmd.tf_type %d\n"
15139517SBill.Taylor@Sun.COM "\tcmd.tf_sector 0x%lx\n"
15149517SBill.Taylor@Sun.COM "\tcmd.tf_sector_num %d\n",
15159517SBill.Taylor@Sun.COM cmd.tf_type, data, cmd.tf_sector_num);
15169517SBill.Taylor@Sun.COM
15179517SBill.Taylor@Sun.COM /*
15189517SBill.Taylor@Sun.COM * If we're debugging, dump the first 64 uint32_t that we've
15199517SBill.Taylor@Sun.COM * been passed
15209517SBill.Taylor@Sun.COM */
15219517SBill.Taylor@Sun.COM if (fwflash_debug > 0) {
15229517SBill.Taylor@Sun.COM i = 0;
15239517SBill.Taylor@Sun.COM while (i < 64) {
15249517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15259517SBill.Taylor@Sun.COM "%02x: %08x %08x %08x %08x\n",
15269517SBill.Taylor@Sun.COM i, data[i], data[i+1],
15279517SBill.Taylor@Sun.COM data[i+2], data[i+3]);
15289517SBill.Taylor@Sun.COM i += 4;
15299517SBill.Taylor@Sun.COM }
15309517SBill.Taylor@Sun.COM }
15319517SBill.Taylor@Sun.COM
15329517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15339517SBill.Taylor@Sun.COM if (rv < 0) {
15349517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
15359517SBill.Taylor@Sun.COM gettext("tavor: WRITE SECTOR failed for sector "
15369517SBill.Taylor@Sun.COM "%d: %s\n"),
15379517SBill.Taylor@Sun.COM sectnum, strerror(errno));
15389517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
15399517SBill.Taylor@Sun.COM } else
15409517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
15419517SBill.Taylor@Sun.COM }
15429517SBill.Taylor@Sun.COM
15439517SBill.Taylor@Sun.COM /*
15449517SBill.Taylor@Sun.COM * Write zeros to the on-HCA signature and CRC16 fields of sector.
15459517SBill.Taylor@Sun.COM *
15469517SBill.Taylor@Sun.COM * NOTE we do _not_ divide start by 4 because we're talking to the
15479517SBill.Taylor@Sun.COM * HCA, and not finding an offset into verifier->fwimage.
15489517SBill.Taylor@Sun.COM */
15499517SBill.Taylor@Sun.COM
15509517SBill.Taylor@Sun.COM static int
tavor_zero_sig_crc(int fd,uint32_t start)15519517SBill.Taylor@Sun.COM tavor_zero_sig_crc(int fd, uint32_t start)
15529517SBill.Taylor@Sun.COM {
15539517SBill.Taylor@Sun.COM int i, rv;
15549517SBill.Taylor@Sun.COM tavor_flash_ioctl_t cmd;
15559517SBill.Taylor@Sun.COM
15569517SBill.Taylor@Sun.COM /* signature first, then CRC16 */
15579517SBill.Taylor@Sun.COM bzero(&cmd, sizeof (tavor_flash_ioctl_t));
15589517SBill.Taylor@Sun.COM cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
15599517SBill.Taylor@Sun.COM cmd.tf_byte = 0x00;
15609517SBill.Taylor@Sun.COM
15619517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15629517SBill.Taylor@Sun.COM "tavor: tavor_zero_sig_crc(fd %d, start 0x%04x)\n",
15639517SBill.Taylor@Sun.COM fd, start);
15649517SBill.Taylor@Sun.COM
15659517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
15669517SBill.Taylor@Sun.COM cmd.tf_addr = start + FLASH_PS_SIGNATURE_OFFSET + i;
15679517SBill.Taylor@Sun.COM
15689517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15699517SBill.Taylor@Sun.COM "tavor: invalidating xPS sig (offset from IS 0x%04x) "
15709517SBill.Taylor@Sun.COM "byte %d\n",
15719517SBill.Taylor@Sun.COM cmd.tf_addr, i);
15729517SBill.Taylor@Sun.COM errno = 0;
15739517SBill.Taylor@Sun.COM
15749517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15759517SBill.Taylor@Sun.COM if (rv < 0) {
15769517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15779517SBill.Taylor@Sun.COM gettext("tavor: Unable to write 0x00 to "
15789517SBill.Taylor@Sun.COM "offset 0x%04x from IS (sig byte %d): %s\n"),
15799517SBill.Taylor@Sun.COM cmd.tf_addr, i, strerror(errno));
15809517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
15819517SBill.Taylor@Sun.COM }
15829517SBill.Taylor@Sun.COM }
15839517SBill.Taylor@Sun.COM
15849517SBill.Taylor@Sun.COM cmd.tf_byte = 0x00;
15859517SBill.Taylor@Sun.COM for (i = 0; i < 2; i++) {
15869517SBill.Taylor@Sun.COM cmd.tf_addr = start + FLASH_PS_CRC16_OFFSET + i;
15879517SBill.Taylor@Sun.COM
15889517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15899517SBill.Taylor@Sun.COM "tavor: invalidating xPS CRC16 (offset from IS 0x%04x) "
15909517SBill.Taylor@Sun.COM "byte %d\n",
15919517SBill.Taylor@Sun.COM cmd.tf_addr, i);
15929517SBill.Taylor@Sun.COM errno = 0;
15939517SBill.Taylor@Sun.COM
15949517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15959517SBill.Taylor@Sun.COM if (rv < 0) {
15969517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
15979517SBill.Taylor@Sun.COM gettext("tavor: Unable to write 0x00 to "
15989517SBill.Taylor@Sun.COM "offset 0x%04x from IS (CRC16 byte %d): %s\n"),
15999517SBill.Taylor@Sun.COM cmd.tf_addr, i, strerror(errno));
16009517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
16019517SBill.Taylor@Sun.COM }
16029517SBill.Taylor@Sun.COM }
16039517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
16049517SBill.Taylor@Sun.COM }
16059517SBill.Taylor@Sun.COM
16069517SBill.Taylor@Sun.COM
16079517SBill.Taylor@Sun.COM /*
16089517SBill.Taylor@Sun.COM * Write a new FIA for the given xPS. The _caller_ handles
16099517SBill.Taylor@Sun.COM * any required byte-swapping for us.
16109517SBill.Taylor@Sun.COM *
16119517SBill.Taylor@Sun.COM * NOTE we do _not_ divide start by 4 because we're talking to the
16129517SBill.Taylor@Sun.COM * HCA, and not finding an offset into verifier->fwimage.
16139517SBill.Taylor@Sun.COM */
16149517SBill.Taylor@Sun.COM static int
tavor_write_xps_fia(int fd,uint32_t offset,uint32_t start)16159517SBill.Taylor@Sun.COM tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start)
16169517SBill.Taylor@Sun.COM {
16179517SBill.Taylor@Sun.COM int i, rv;
16189517SBill.Taylor@Sun.COM uint8_t *addrbytep;
16199517SBill.Taylor@Sun.COM tavor_flash_ioctl_t cmd;
16209517SBill.Taylor@Sun.COM
16219517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16229517SBill.Taylor@Sun.COM "tavor: tavor_write_xps_fia(fd %d, offset 0x%04x, "
16239517SBill.Taylor@Sun.COM "start 0x%04x)\n",
16249517SBill.Taylor@Sun.COM fd, offset, start);
16259517SBill.Taylor@Sun.COM
16269517SBill.Taylor@Sun.COM addrbytep = (uint8_t *)&start;
16279517SBill.Taylor@Sun.COM
16289517SBill.Taylor@Sun.COM bzero(&cmd, sizeof (tavor_flash_ioctl_t));
16299517SBill.Taylor@Sun.COM cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
16309517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
16319517SBill.Taylor@Sun.COM cmd.tf_byte = addrbytep[i];
16329517SBill.Taylor@Sun.COM cmd.tf_addr = offset + FLASH_PS_FI_ADDR_OFFSET + i;
16339517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16349517SBill.Taylor@Sun.COM "tavor: writing xPS' new FIA, byte %d (0x%0x) at "
16359517SBill.Taylor@Sun.COM "offset from IS 0x%04x\n",
16369517SBill.Taylor@Sun.COM i, cmd.tf_byte, cmd.tf_addr);
16379517SBill.Taylor@Sun.COM errno = 0;
16389517SBill.Taylor@Sun.COM
16399517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
16409517SBill.Taylor@Sun.COM if (rv < 0) {
16419517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16429517SBill.Taylor@Sun.COM gettext("tavor: Unable to write byte %d "
16439517SBill.Taylor@Sun.COM "of xPS new FIA (0x%0x, offset from IS "
16449517SBill.Taylor@Sun.COM "0x%04x): %s\n"),
16459517SBill.Taylor@Sun.COM i, cmd.tf_byte, cmd.tf_addr, strerror(errno));
16469517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
16479517SBill.Taylor@Sun.COM }
16489517SBill.Taylor@Sun.COM }
16499517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
16509517SBill.Taylor@Sun.COM }
16519517SBill.Taylor@Sun.COM
16529517SBill.Taylor@Sun.COM
16539517SBill.Taylor@Sun.COM /*
16549517SBill.Taylor@Sun.COM * Write the new CRC16 and Signature to the given xPS. The caller
16559517SBill.Taylor@Sun.COM * has already byte-swapped newcrc if that's necessary.
16569517SBill.Taylor@Sun.COM *
16579517SBill.Taylor@Sun.COM * NOTE we do _not_ divide start by 4 because we're talking to the
16589517SBill.Taylor@Sun.COM * HCA, and not finding an offset into verifier->fwimage.
16599517SBill.Taylor@Sun.COM */
16609517SBill.Taylor@Sun.COM static int
tavor_write_xps_crc_sig(int fd,uint32_t offset,uint16_t newcrc)16619517SBill.Taylor@Sun.COM tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc)
16629517SBill.Taylor@Sun.COM {
16639517SBill.Taylor@Sun.COM int i, rv;
16649517SBill.Taylor@Sun.COM uint8_t *bytep;
16659517SBill.Taylor@Sun.COM uint32_t tempsig;
16669517SBill.Taylor@Sun.COM tavor_flash_ioctl_t cmd;
16679517SBill.Taylor@Sun.COM
16689517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16699517SBill.Taylor@Sun.COM "tavor: tavor_write_xps_crc_sig(fd %d, offset 0x%04x, "
16709517SBill.Taylor@Sun.COM "newcrc 0x%04x)\n",
16719517SBill.Taylor@Sun.COM fd, offset, newcrc);
16729517SBill.Taylor@Sun.COM
16739517SBill.Taylor@Sun.COM bytep = (uint8_t *)&newcrc;
16749517SBill.Taylor@Sun.COM
16759517SBill.Taylor@Sun.COM bzero(&cmd, sizeof (tavor_flash_ioctl_t));
16769517SBill.Taylor@Sun.COM cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
16779517SBill.Taylor@Sun.COM for (i = 0; i < 2; i++) {
16789517SBill.Taylor@Sun.COM cmd.tf_byte = bytep[i];
16799517SBill.Taylor@Sun.COM cmd.tf_addr = offset + FLASH_PS_CRC16_OFFSET + i;
16809517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16819517SBill.Taylor@Sun.COM "tavor: writing new XPS CRC16, byte %d (0x%0x) at "
16829517SBill.Taylor@Sun.COM "offset from IS 0x%04x\n",
16839517SBill.Taylor@Sun.COM i, bytep[i], cmd.tf_addr);
16849517SBill.Taylor@Sun.COM errno = 0;
16859517SBill.Taylor@Sun.COM
16869517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
16879517SBill.Taylor@Sun.COM if (rv < 0) {
16889517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
16899517SBill.Taylor@Sun.COM gettext("tavor: Unable to write byte %d "
16909517SBill.Taylor@Sun.COM "(0x%0x) of xPS' new CRC16 to offset "
16919517SBill.Taylor@Sun.COM "from IS 0x%04x: %s\n"),
16929517SBill.Taylor@Sun.COM i, bytep[i], cmd.tf_addr, strerror(errno));
16939517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
16949517SBill.Taylor@Sun.COM }
16959517SBill.Taylor@Sun.COM }
16969517SBill.Taylor@Sun.COM
16979517SBill.Taylor@Sun.COM tempsig = htonl(FLASH_PS_SIGNATURE);
16989517SBill.Taylor@Sun.COM bytep = (uint8_t *)&tempsig;
16999517SBill.Taylor@Sun.COM
17009517SBill.Taylor@Sun.COM for (i = 0; i < 4; i++) {
17019517SBill.Taylor@Sun.COM cmd.tf_byte = bytep[i];
17029517SBill.Taylor@Sun.COM cmd.tf_addr = offset + FLASH_PS_SIGNATURE_OFFSET + i;
17039517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
17049517SBill.Taylor@Sun.COM "tavor: writing new xPS Signature, byte %d (0x%0x) at "
17059517SBill.Taylor@Sun.COM "offset from IS 0x%04x\n",
17069517SBill.Taylor@Sun.COM i, bytep[i], cmd.tf_addr);
17079517SBill.Taylor@Sun.COM errno = 0;
17089517SBill.Taylor@Sun.COM
17099517SBill.Taylor@Sun.COM rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
17109517SBill.Taylor@Sun.COM if (rv < 0) {
17119517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
17129517SBill.Taylor@Sun.COM gettext("tavor: Unable to write byte %d (0x%0x) "
17139517SBill.Taylor@Sun.COM "of xPS' signature at offset from IS 0x%04x: %s\n"),
17149517SBill.Taylor@Sun.COM i, bytep[i], cmd.tf_addr, strerror(errno));
17159517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
17169517SBill.Taylor@Sun.COM }
17179517SBill.Taylor@Sun.COM }
17189517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
17199517SBill.Taylor@Sun.COM }
17209517SBill.Taylor@Sun.COM
17219517SBill.Taylor@Sun.COM
17229517SBill.Taylor@Sun.COM
17239517SBill.Taylor@Sun.COM /*
17249517SBill.Taylor@Sun.COM * This function contains "Begin/End documentation departure point"
17259517SBill.Taylor@Sun.COM * because the reality of what actually _works_ is quite, quite
17269517SBill.Taylor@Sun.COM * different to what is written in the Mellanox HCA Flash Application
17279517SBill.Taylor@Sun.COM * Programming Guide.
17289517SBill.Taylor@Sun.COM */
17299517SBill.Taylor@Sun.COM static int
tavor_blast_image(int fd,int prisec,uint32_t hcafia,uint32_t sectsz,struct mlx_xps * newxps)17309517SBill.Taylor@Sun.COM tavor_blast_image(int fd, int prisec, uint32_t hcafia, uint32_t sectsz,
17319517SBill.Taylor@Sun.COM struct mlx_xps *newxps)
17329517SBill.Taylor@Sun.COM {
17339517SBill.Taylor@Sun.COM uint32_t i, j, rv;
17349517SBill.Taylor@Sun.COM uint32_t startsectimg, startsecthca, numsect;
17359517SBill.Taylor@Sun.COM
17369517SBill.Taylor@Sun.COM if ((prisec != 1) && (prisec != 2)) {
17379517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
173810618SShantkumar.Hiremath@Sun.COM gettext("tavor: invalid image number requested (%d)\n"),
173910618SShantkumar.Hiremath@Sun.COM prisec);
17409517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
17419517SBill.Taylor@Sun.COM }
17429517SBill.Taylor@Sun.COM
17439517SBill.Taylor@Sun.COM /* Begin documentation departure point */
17449517SBill.Taylor@Sun.COM
17459517SBill.Taylor@Sun.COM /* zero the HCA's PPS signature and CRC */
17469517SBill.Taylor@Sun.COM if (tavor_zero_sig_crc(fd, (prisec * sectsz))
17479517SBill.Taylor@Sun.COM != FWFLASH_SUCCESS) {
17489517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
17499517SBill.Taylor@Sun.COM "tavor: Unable zero HCA's %s signature "
17509517SBill.Taylor@Sun.COM "and CRC16 fields\n",
17519517SBill.Taylor@Sun.COM ((prisec == 1) ? "PPS" : "SPS"));
17529517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
17539517SBill.Taylor@Sun.COM }
17549517SBill.Taylor@Sun.COM
17559517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: zeroing HCA's %s sig and crc\n",
17569517SBill.Taylor@Sun.COM (prisec == 1) ? "pps" : "sps");
17579517SBill.Taylor@Sun.COM
17589517SBill.Taylor@Sun.COM /* End documentation departure point */
17599517SBill.Taylor@Sun.COM
17609517SBill.Taylor@Sun.COM /* make sure we don't inadvertently overwrite bits */
17619517SBill.Taylor@Sun.COM
17629517SBill.Taylor@Sun.COM startsectimg = MLXSWAPBITS32(newxps->fia) / sectsz;
17639517SBill.Taylor@Sun.COM startsecthca = hcafia / sectsz;
17649517SBill.Taylor@Sun.COM
17659517SBill.Taylor@Sun.COM numsect = (MLXSWAPBITS32(newxps->fis) / sectsz) +
17669517SBill.Taylor@Sun.COM ((MLXSWAPBITS32(newxps->fis) % sectsz) ? 1 : 0);
17679517SBill.Taylor@Sun.COM
17689517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: %s imgsize 0x%0x startsecthca %d, "
17699517SBill.Taylor@Sun.COM "startsectimg %d, num sectors %d\n",
17709517SBill.Taylor@Sun.COM (prisec == 1) ? "PFI" : "SFI", MLXSWAPBITS32(newxps->fis),
17719517SBill.Taylor@Sun.COM startsecthca, startsectimg, numsect);
17729517SBill.Taylor@Sun.COM
17739517SBill.Taylor@Sun.COM for (i = 0; i < numsect; i++) {
17749517SBill.Taylor@Sun.COM
17759517SBill.Taylor@Sun.COM j = (MLXSWAPBITS32(newxps->fia) + (i * sectsz)) / 4;
17769517SBill.Taylor@Sun.COM
17779517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: image offset 0x%0x\n", j);
17789517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: writing HCA sector %d\n",
17799517SBill.Taylor@Sun.COM i + startsecthca);
17809517SBill.Taylor@Sun.COM
17819517SBill.Taylor@Sun.COM if (tavor_write_sector(fd, i + startsecthca,
17829517SBill.Taylor@Sun.COM &verifier->fwimage[j])
17839517SBill.Taylor@Sun.COM != FWFLASH_SUCCESS) {
17849517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
17859517SBill.Taylor@Sun.COM gettext("tavor: Unable to write "
17869517SBill.Taylor@Sun.COM "sector %d to HCA\n"),
17879517SBill.Taylor@Sun.COM i + startsecthca);
17889517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
17899517SBill.Taylor@Sun.COM }
17909517SBill.Taylor@Sun.COM (void) printf(" .");
17919517SBill.Taylor@Sun.COM
17929517SBill.Taylor@Sun.COM rv = tavor_readback(fd, i + startsecthca, sectsz);
17939517SBill.Taylor@Sun.COM if (rv != FWFLASH_SUCCESS) {
17949517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
17959517SBill.Taylor@Sun.COM gettext("tavor: Unable to read sector %d "
17969517SBill.Taylor@Sun.COM "back from HCA\n"), i + startsecthca);
17979517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
17989517SBill.Taylor@Sun.COM }
17999517SBill.Taylor@Sun.COM (void) printf(" | ");
18009517SBill.Taylor@Sun.COM }
18019517SBill.Taylor@Sun.COM
18029517SBill.Taylor@Sun.COM /* Begin documentation departure point */
18039517SBill.Taylor@Sun.COM
18049517SBill.Taylor@Sun.COM /* invalidate the xps signature and fia fields */
18059517SBill.Taylor@Sun.COM newxps->signature = 0xffffffff;
18069517SBill.Taylor@Sun.COM newxps->crc16 = 0xffff;
18079517SBill.Taylor@Sun.COM /* we put the fia back to imgfia later */
18089517SBill.Taylor@Sun.COM newxps->fia = 0xffffffff;
18099517SBill.Taylor@Sun.COM /* End documentation departure point */
18109517SBill.Taylor@Sun.COM
18119517SBill.Taylor@Sun.COM /* success so far, now burn the new xPS */
18129517SBill.Taylor@Sun.COM if (tavor_write_sector(fd, prisec, (int *)newxps)
18139517SBill.Taylor@Sun.COM != FWFLASH_SUCCESS) {
18149517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
18159517SBill.Taylor@Sun.COM gettext("tavor: Unable to write new %s "
18169517SBill.Taylor@Sun.COM "pointer sector to HCA\n"),
18179517SBill.Taylor@Sun.COM (prisec == 1) ? "primary" : "secondary");
18189517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
18199517SBill.Taylor@Sun.COM }
18209517SBill.Taylor@Sun.COM (void) printf(" .");
18219517SBill.Taylor@Sun.COM
18229517SBill.Taylor@Sun.COM /* Begin documentation departure point */
18239517SBill.Taylor@Sun.COM
18249517SBill.Taylor@Sun.COM /* write new fia to the HCA's pps */
18259517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: writing new fia (0x%0x) to HCA\n",
18269517SBill.Taylor@Sun.COM MLXSWAPBITS32(newxps->fia));
18279517SBill.Taylor@Sun.COM
18289517SBill.Taylor@Sun.COM if (tavor_write_xps_fia(fd, (prisec * sectsz),
18299517SBill.Taylor@Sun.COM MLXSWAPBITS32(hcafia)) != FWFLASH_SUCCESS) {
18309517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
18319517SBill.Taylor@Sun.COM gettext("tavor: Unable to update HCA's %s "
18329517SBill.Taylor@Sun.COM "pointer sector FIA record\n"),
18339517SBill.Taylor@Sun.COM (prisec == 1) ? "primary" : "secondary");
18349517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
18359517SBill.Taylor@Sun.COM }
18369517SBill.Taylor@Sun.COM
18379517SBill.Taylor@Sun.COM /* don't forget the byte-swapping */
18389517SBill.Taylor@Sun.COM newxps->fia = MLXSWAPBITS32(hcafia);
18399517SBill.Taylor@Sun.COM newxps->signature =
18409517SBill.Taylor@Sun.COM (uint32_t)MLXSWAPBITS32(FLASH_PS_SIGNATURE);
18419517SBill.Taylor@Sun.COM newxps->crc16 =
18429517SBill.Taylor@Sun.COM MLXSWAPBITS16(crc16((uint8_t *)newxps, FLASH_PS_CRC16_SIZE));
18439517SBill.Taylor@Sun.COM
18449517SBill.Taylor@Sun.COM logmsg(MSG_INFO, "tavor: writing new fia 0x%0x, "
18459517SBill.Taylor@Sun.COM "sig 0x%0x and new crc16 0x%0x\n",
18469517SBill.Taylor@Sun.COM newxps->fia, MLXSWAPBITS32(newxps->signature),
18479517SBill.Taylor@Sun.COM newxps->crc16);
18489517SBill.Taylor@Sun.COM
18499517SBill.Taylor@Sun.COM if (tavor_write_xps_crc_sig(fd, (prisec * sectsz),
18509517SBill.Taylor@Sun.COM newxps->crc16) != FWFLASH_SUCCESS) {
18519517SBill.Taylor@Sun.COM /*
18529517SBill.Taylor@Sun.COM * Now we're REALLY hosed. If the card comes up at all,
18539517SBill.Taylor@Sun.COM * expect it to be in "Maintenance Mode".
18549517SBill.Taylor@Sun.COM */
18559517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
18569517SBill.Taylor@Sun.COM gettext("tavor: Unable to update HCA's %s CRC "
18579517SBill.Taylor@Sun.COM "and Firmware Image signature fields\n"),
18589517SBill.Taylor@Sun.COM (prisec == 1) ? "PPS" : "SPS");
18599517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
18609517SBill.Taylor@Sun.COM }
18619517SBill.Taylor@Sun.COM
18629517SBill.Taylor@Sun.COM rv = tavor_readback(fd, prisec, sectsz);
18639517SBill.Taylor@Sun.COM if (rv != FWFLASH_SUCCESS) {
18649517SBill.Taylor@Sun.COM logmsg(MSG_ERROR,
18659517SBill.Taylor@Sun.COM gettext("tavor: Unable to read %s pointer sector "
18669517SBill.Taylor@Sun.COM "from HCA\n"),
18679517SBill.Taylor@Sun.COM (prisec == 1) ? "Primary" : "Secondary");
18689517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
18699517SBill.Taylor@Sun.COM }
18709517SBill.Taylor@Sun.COM (void) printf(" |");
18719517SBill.Taylor@Sun.COM /* End documentation departure point */
18729517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
18739517SBill.Taylor@Sun.COM }
18749517SBill.Taylor@Sun.COM
18759517SBill.Taylor@Sun.COM
18769517SBill.Taylor@Sun.COM static int
tavor_readback(int infd,int whichsect,int sectsz)18779517SBill.Taylor@Sun.COM tavor_readback(int infd, int whichsect, int sectsz)
18789517SBill.Taylor@Sun.COM {
18799517SBill.Taylor@Sun.COM uint32_t *data;
18809517SBill.Taylor@Sun.COM tavor_flash_ioctl_t cmd;
18819517SBill.Taylor@Sun.COM int rv;
18829517SBill.Taylor@Sun.COM
18839517SBill.Taylor@Sun.COM bzero(&cmd, sizeof (tavor_flash_ioctl_t));
18849517SBill.Taylor@Sun.COM data = calloc(1, sectsz); /* assumption! */
18859517SBill.Taylor@Sun.COM
18869517SBill.Taylor@Sun.COM cmd.tf_type = TAVOR_FLASH_READ_SECTOR;
18879517SBill.Taylor@Sun.COM cmd.tf_sector_num = whichsect;
18889517SBill.Taylor@Sun.COM cmd.tf_sector = (caddr_t)data;
18899517SBill.Taylor@Sun.COM rv = ioctl(infd, TAVOR_IOCTL_FLASH_READ, &cmd);
18909517SBill.Taylor@Sun.COM if (rv < 0) {
18919517SBill.Taylor@Sun.COM logmsg(MSG_INFO,
18929517SBill.Taylor@Sun.COM "tavor: UNABLE TO READ BACK SECTOR %d from HCA\n",
18939517SBill.Taylor@Sun.COM whichsect);
18949517SBill.Taylor@Sun.COM return (FWFLASH_FAILURE);
18959517SBill.Taylor@Sun.COM }
18969517SBill.Taylor@Sun.COM free(data);
18979517SBill.Taylor@Sun.COM return (FWFLASH_SUCCESS);
18989517SBill.Taylor@Sun.COM }
18999517SBill.Taylor@Sun.COM
19009517SBill.Taylor@Sun.COM
19019517SBill.Taylor@Sun.COM /*
19029517SBill.Taylor@Sun.COM * crc16 - computes 16 bit crc of supplied buffer.
19039517SBill.Taylor@Sun.COM * image should be in network byteorder
19049517SBill.Taylor@Sun.COM * result is returned in host byteorder form
19059517SBill.Taylor@Sun.COM */
19069517SBill.Taylor@Sun.COM static uint16_t
crc16(uint8_t * image,uint32_t size)19079517SBill.Taylor@Sun.COM crc16(uint8_t *image, uint32_t size)
19089517SBill.Taylor@Sun.COM {
19099517SBill.Taylor@Sun.COM const uint16_t poly = 0x100b;
19109517SBill.Taylor@Sun.COM uint32_t crc = 0xFFFF;
19119517SBill.Taylor@Sun.COM uint32_t word;
19129517SBill.Taylor@Sun.COM uint32_t i, j;
19139517SBill.Taylor@Sun.COM
19149517SBill.Taylor@Sun.COM for (i = 0; i < size / 4; i++) {
19159517SBill.Taylor@Sun.COM word = (image[4 * i] << 24) |
19169517SBill.Taylor@Sun.COM (image[4 * i + 1] << 16) |
19179517SBill.Taylor@Sun.COM (image[4 * i + 2] << 8) |
19189517SBill.Taylor@Sun.COM (image[4 * i + 3]);
19199517SBill.Taylor@Sun.COM
19209517SBill.Taylor@Sun.COM for (j = 0; j < 32; j++) {
19219517SBill.Taylor@Sun.COM if (crc & 0x8000) {
19229517SBill.Taylor@Sun.COM crc = (((crc << 1) |
19239517SBill.Taylor@Sun.COM (word >> 31)) ^ poly) & 0xFFFF;
19249517SBill.Taylor@Sun.COM } else {
19259517SBill.Taylor@Sun.COM crc = ((crc << 1) | (word >> 31)) & 0xFFFF;
19269517SBill.Taylor@Sun.COM }
19279517SBill.Taylor@Sun.COM word = (word << 1) & 0xFFFFFFFF;
19289517SBill.Taylor@Sun.COM }
19299517SBill.Taylor@Sun.COM }
19309517SBill.Taylor@Sun.COM
19319517SBill.Taylor@Sun.COM for (i = 0; i < 16; i++) {
19329517SBill.Taylor@Sun.COM if (crc & 0x8000) {
19339517SBill.Taylor@Sun.COM crc = ((crc << 1) ^ poly) & 0xFFFF;
19349517SBill.Taylor@Sun.COM } else {
19359517SBill.Taylor@Sun.COM crc = (crc << 1) & 0xFFFF;
19369517SBill.Taylor@Sun.COM }
19379517SBill.Taylor@Sun.COM }
19389517SBill.Taylor@Sun.COM
19399517SBill.Taylor@Sun.COM crc = crc ^ 0xFFFF;
19409517SBill.Taylor@Sun.COM return (crc & 0xFFFF);
19419517SBill.Taylor@Sun.COM }
1942