4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER START
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The contents of this file are subject to the terms of the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Common Development and Distribution License (the "License").
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You may not use this file except in compliance with the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or http://www.opensolaris.org/os/licensing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See the License for the specific language governing permissions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and limitations under the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * When distributing Covered Code, include this CDDL HEADER in each
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If applicable, add the following below this CDDL HEADER, with the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * fields enclosed by brackets "[]" replaced with your own identifying
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * information: Portions Copyright [yyyy] [name of copyright owner]
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER END
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister/*
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This file contains various support routines.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#include <sys/scsi/adapters/pmcs/pmcs.h>
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SAS Topology Configuration
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_flash_chunk(pmcs_hw_t *, uint8_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check current firmware version for correctness
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and try to flash the correct firmware if what is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * running isn't correct.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Must be called after setup and MPI setup and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * interrupts are enabled.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_firmware_update(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_modhandle_t modhp;
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister char buf[64], *bufp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int errno;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *cstart, *cend; /* Firmware image file */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *istart, *iend; /* ila */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *sstart, *send; /* SPCBoot */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *fwvp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int defret = 0;
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler int first_pass = 1;
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister long fw_version, ila_version;
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister uint8_t *fw_verp, *ila_verp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If updating is disabled, we're done.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fw_disable_update) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Firmware update disabled by conf file");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're already running the right firmware, we're done.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fw == PMCS_FIRMWARE_VERSION) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fw_force_update == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Firmware version matches, but still forcing update");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh modhp = ddi_modopen(PMCS_FIRMWARE_FILENAME, KRTLD_MODE_FIRST, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Firmware module not available; will not upgrade",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwvp = ddi_modsym(modhp, PMCS_FIRMWARE_VERSION_NAME, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_FIRMWARE_VERSION_NAME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the firmware version from the module isn't what we expect,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and force updating is disabled, return the default (for this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * mode of operation) value.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (*fwvp != PMCS_FIRMWARE_VERSION) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fw_force_update == 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: firmware module version wrong (0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, *fwvp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: firmware module version wrong (0x%x) - update forced",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, *fwvp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_CODE_NAME PMCS_FIRMWARE_START_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cstart = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_CODE_NAME PMCS_FIRMWARE_END_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cend = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_ILA_NAME PMCS_FIRMWARE_START_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh istart = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_ILA_NAME PMCS_FIRMWARE_END_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iend = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_SPCBOOT_NAME PMCS_FIRMWARE_START_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sstart = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FIRMWARE_SPCBOOT_NAME PMCS_FIRMWARE_END_SUF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh send = ddi_modsym(modhp, buf, &errno);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (errno) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: unable to find symbol '%s'", __func__, buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (defret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister /*
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister * Get the ILA and firmware versions from the modules themselves
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister */
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister ila_verp = iend - PMCS_ILA_VER_OFFSET;
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister (void) ddi_strtol((const char *)ila_verp, &bufp, 16, &ila_version);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister fw_verp = cend - PMCS_FW_VER_OFFSET;
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister (void) ddi_strtol((const char *)fw_verp, &bufp, 16, &fw_version);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister /*
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister * If force update is not set, verify that what we're loading is
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister * what we expect.
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister */
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister if (pwp->fw_force_update == 0) {
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister if (fw_version != PMCS_FIRMWARE_VERSION) {
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister "Expected fw version 0x%x, not 0x%lx: not "
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister "updating", PMCS_FIRMWARE_VERSION, fw_version);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister (void) ddi_modclose(modhp);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister return (defret);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister }
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister }
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister "Upgrading firmware on card from 0x%x to 0x%lx (ILA version 0x%lx)",
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister pwp->fw, fw_version, ila_version);
2ac4abe882db38ef90020f7c5ca28586e3d57258David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The SPCBoot image must be updated first, and this is written to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SEEPROM, not flash.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_set_nvmd(pwp, PMCS_NVMD_SPCBOOT, sstart,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (size_t)((size_t)send - (size_t)sstart)) == B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: unable to flash '%s' segment",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_FIRMWARE_SPCBOOT_NAME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butlerrepeat:
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler "%s: Beginning firmware update of %s image.",
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler __func__, (first_pass ? "first" : "second"));
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_fw_flash(pwp, (void *)istart,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (uint32_t)((size_t)iend - (size_t)istart))) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: unable to flash '%s' segment",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_FIRMWARE_ILA_NAME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_fw_flash(pwp, (void *)cstart,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (uint32_t)((size_t)cend - (size_t)cstart))) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: unable to flash '%s' segment",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_FIRMWARE_CODE_NAME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_soft_reset(pwp, B_FALSE)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: soft reset after flash update failed", __func__);
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler "%s: %s image successfully upgraded.",
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler __func__, (first_pass ? "First" : "Second"));
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_FW_UPGRADE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler if (first_pass) {
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler first_pass = 0;
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler goto repeat;
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler }
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler "%s: Firmware successfully upgraded", __func__);
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler
83778f4415cf351d3daec8ab6c5c567a0da4b414Jesse Butler (void) ddi_modclose(modhp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Flash firmware support
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called unlocked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fw_flash(pmcs_hw_t *pwp, pmcs_fw_hdr_t *hdr, uint32_t length)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fw_hdr_t *hp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *wrk, *base;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 1- Validate firmware chunks within passed pointer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp = hdr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wrk = (uint8_t *)hdr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh base = wrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (;;) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: partition 0x%x, Length 0x%x", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp->destination_partition, ntohl(hp->firmware_length));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ntohl(hp->firmware_length) == 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: bad firmware length 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ntohl(hp->firmware_length));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EINVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wrk += (sizeof (pmcs_fw_hdr_t) + ntohl(hp->firmware_length));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wrk == base + length) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wrk > base + length) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: out of bounds firmware length", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EINVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp = (void *)wrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 2- acquire scratch
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_acquire_scratch(pwp, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 3- loop through firmware chunks and send each one
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * down to be flashed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp = hdr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wrk = (uint8_t *)hdr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh base = wrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (;;) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_flash_chunk(pwp, wrk)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wrk += (sizeof (pmcs_fw_hdr_t) + ntohl(hp->firmware_length));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wrk == base + length) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp = (void *) wrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_flash_chunk(pmcs_hw_t *pwp, uint8_t *chunk)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fw_hdr_t *hp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t len, seg, off, result, amt, msg[PMCS_MSG_SIZE], *ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hp = (void *)chunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh len = sizeof (pmcs_fw_hdr_t) + ntohl(hp->firmware_length);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh seg = off = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (off < len) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = PMCS_SCRATCH_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (off + amt > len) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = len - off;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d offset %u length %u",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, seg, off, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pwp->scratch, &chunk[off], amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_OQ_EVENTS, PMCIN_FW_FLASH_UPDATE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (off == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = LE_32(len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[5] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[6] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[7] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[8] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[9] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[10] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[11] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = LE_32(amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memset(msg, 0xaf, sizeof (msg));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister WAIT_FOR(pwrk, PMCS_FLASH_WAIT_TIME, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (LE_32(msg[2])) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d complete pending reboot",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_IN_PROGRESS:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d downloaded", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_HDR_ERR:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d header error", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_OFFSET_ERR:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d offset error", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_UPDATE_CRC_ERR:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d update crc error", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_LENGTH_ERR:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d length error", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_HW_ERR:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d hw error", __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_DNLD_NOT_SUPPORTED:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d download not supported error",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLASH_UPDATE_DISABLED:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d update disabled error",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, seg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: segment %d unknown error %x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, seg, msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off += amt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh seg++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_validate_vpd
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Input: softstate pointer and pointer to vpd data buffer
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Returns: B_TRUE if VPD data looks OK, B_FALSE otherwise
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_validate_vpd(pmcs_hw_t *pwp, uint8_t *data)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_vpd_header_t *vpd_header;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *bufp, kv_len, *chksump, chksum = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char tbuf[80];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char prop[24];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int idx, str_len;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t strid_length, chksum_len;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_vpd_kv_t *vkvp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh vpd_header = (pmcs_vpd_header_t *)data;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make sure we understand the format of this data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala /*
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala * Only VPD version 1 is VALID for Thebe-INT cards and
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala * Only VPD version 2 is valid for Thebe-EXT cards
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala */
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala if ((vpd_header->eeprom_version == PMCS_EEPROM_INT_VERSION &&
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->subsys_pid[0] == PMCS_EEPROM_INT_SSID_BYTE1 &&
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->subsys_pid[1] == PMCS_EEPROM_INT_SSID_BYTE2) ||
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala (vpd_header->eeprom_version == PMCS_EEPROM_EXT_VERSION &&
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->subsys_pid[0] == PMCS_EEPROM_EXT_SSID_BYTE1 &&
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->subsys_pid[1] == PMCS_EEPROM_EXT_SSID_BYTE2)) {
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala goto valid_version;
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala } else {
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala "%s: Detected Thebe card with SSID(%02x%02x)", __func__,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->subsys_pid[0], vpd_header->subsys_pid[1]);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala "%s: EEPROM(%d) unsupported; requires %d for INT(%02x%02x) "
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala " and %d for EXT(%02x%02x) cards.", __func__,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala vpd_header->eeprom_version,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala PMCS_EEPROM_INT_VERSION, PMCS_EEPROM_INT_SSID_BYTE1,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala PMCS_EEPROM_INT_SSID_BYTE2, PMCS_EEPROM_EXT_VERSION,
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhala PMCS_EEPROM_EXT_SSID_BYTE1, PMCS_EEPROM_EXT_SSID_BYTE2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
688a63ed70eca66e1dc82c8f096cb66f8bd94013Srikanth Suravajhalavalid_version:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do we have a valid SAS WWID?
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (((vpd_header->hba_sas_wwid[0] & 0xf0) >> 4) != NAA_IEEE_REG) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SAS WWN has invalid NAA (%d)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((vpd_header->hba_sas_wwid[0] & 0xf0) >> 4));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwid = pmcs_barray2wwn(vpd_header->hba_sas_wwid);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (idx = 0; idx < PMCS_MAX_PORTS; idx++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->sas_wwns[idx] = wwid + idx;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (vpd_header->vpd_start_byte != PMCS_VPD_START) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Didn't see VPD start byte", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We only checksum the VPD data between (and including) VPD Start byte
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and the checksum value byte. The length of this data for CRC is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 15 less than the length indicated in vpd_length field of the header.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 8 (SAS WWN) + 2 (subsystem ID) + 2 (subsystem vendor ID) +
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 1 (end tag) + 2 (hex byte CRC, different from this one) = 15 bytes
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * VPD length (little endian format) is represented as byte-array field
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * & read the following way to avoid alignment issues (in SPARC)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh chksum_len = ((vpd_header->vpd_length[1] << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (vpd_header->vpd_length[0])) - 15;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Validate VPD data checksum */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh chksump = (uint8_t *)&vpd_header->vpd_start_byte;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT (*chksump == PMCS_VPD_START);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (idx = 0; idx < chksum_len; idx++, chksump++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh chksum += *chksump;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT (*chksump == PMCS_VPD_END);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (chksum) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "%s: VPD checksum failure", __func__);
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get length of string ID tag and read it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bufp = (uint8_t *)&vpd_header->vpd_start_byte;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bufp += 3; /* Skip the start byte and length */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * String ID tag length (little endian format) is represented as
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * byte-array & read the following way to avoid alignment issues
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (in SPARC)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strid_length = (vpd_header->strid_length[1] << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (vpd_header->strid_length[0]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (strid_length > 79) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strid_length = 79;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(bufp, tbuf, strid_length);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbuf[strid_length] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Product Name: '%s'", __func__, tbuf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_MODEL_NAME, tbuf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Skip VPD-R tag and length of read-only tag, then start reading
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * keyword/value pairs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bufp += strid_length; /* Skip to VPD-R tag */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bufp += 3; /* Skip VPD-R tag and length of VPD-R data */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh vkvp = (pmcs_vpd_kv_t *)bufp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (vkvp->keyword[0] != PMCS_VPD_END) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbuf[0] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh str_len = snprintf(tbuf, 80, "VPD: %c%c = <",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh vkvp->keyword[0], vkvp->keyword[1]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kv_len = vkvp->value_length;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (idx = 0; idx < kv_len; idx++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbuf[str_len + idx] = vkvp->value[idx];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prop[idx] = vkvp->value[idx];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prop[idx] = '\0';
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh str_len += kv_len;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbuf[str_len] = '>';
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbuf[str_len + 1] = 0;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "%s (Len: 0x%x)",
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh tbuf, kv_len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Keyword is Manufacturer */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((vkvp->keyword[0] == 'M') && (vkvp->keyword[1] == 'N')) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MANUFACTURER, prop);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Keyword is Serial Number */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((vkvp->keyword[0] == 'S') && (vkvp->keyword[1] == 'N')) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_SERIAL_NUMBER, prop);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh vkvp = (pmcs_vpd_kv_t *)(bufp + 3 + kv_len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bufp += kv_len + 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_get_nvmd
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function will read the requested data from the non-volatile
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * storage on the card. This could mean SEEPROM, VPD, or other areas
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as defined by the PM8001 programmer's manual.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * nvmd_type: The data type being requested
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * nvmd: NVM device to access (IOP/AAP1)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * offset: Must be 4K alignment
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * buf: Pointer to memory region for retrieved data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * size_left: Total available bytes left in buf
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Returns: non-negative on success, -1 on failure
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*ARGSUSED*/
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t nvmd,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t offset, char *buf, uint32_t size_left)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_get_nvmd_cmd_t iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *workp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *chunkp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *ptr, ibq, *iombp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t dlen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t tdas_nvmd, ip, tda, tbn_tdps;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t doa[3];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int32_t result = -1, i = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (nvmd_type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_NVMD_VPD:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tdas_nvmd = PMCIN_NVMD_TDPS_1 | PMCIN_NVMD_TWI;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tda = PMCIN_TDA_PAGE(2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbn_tdps = PMCIN_NVMD_TBN(0) | PMCIN_NVMD_TDPS_8;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ip = PMCIN_NVMD_INDIRECT_PLD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dlen = LE_32(PMCS_SEEPROM_PAGE_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[0] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[1] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[2] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_NVMD_REG_DUMP:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tdas_nvmd = nvmd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tda = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbn_tdps = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ip = PMCIN_NVMD_INDIRECT_PLD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dlen = LE_32(PMCS_REGISTER_DUMP_BLOCK_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[0] = offset & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[1] = (offset >> 8) & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[2] = (offset >> 16) & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_NVMD_EVENT_LOG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tdas_nvmd = nvmd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tda = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tbn_tdps = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ip = PMCIN_NVMD_INDIRECT_PLD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dlen = LE_32(PMCS_REGISTER_DUMP_BLOCK_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offset = offset + PMCS_NVMD_EVENT_LOG_OFFSET;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[0] = offset & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[1] = (offset >> 8) & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh doa[2] = (offset >> 16) & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Invalid nvmd type: %d", __func__, nvmd_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (workp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to get work struct", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = &iomb.header;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ptr, sizeof (pmcs_get_nvmd_cmd_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *ptr = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_GENERAL, PMCIN_GET_NVMD_DATA));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp->arg = (void *)&iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.htag = LE_32(workp->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ip = ip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.tbn_tdps = tbn_tdps;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.tda = tda;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.tdas_nvmd = tdas_nvmd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipbal = LE_32(DWORD0(pwp->flash_chunk_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipbah = LE_32(DWORD1(pwp->flash_chunk_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipdl = dlen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.doa[0] = doa[0];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.doa[1] = doa[1];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.doa[2] = doa[2];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ptr will now point to the inbound queue message
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh GET_IO_IQ_ENTRY(pwp, ptr, 0, ibq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "!%s: Unable to get IQ entry", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ptr, PMCS_MSG_SIZE << 2); /* PMCS_MSG_SIZE is in dwords */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iombp = (uint32_t *)&iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, iombp, sizeof (pmcs_get_nvmd_cmd_t) >> 2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, ibq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(workp, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = workp->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, workp->htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(*(ptr + 3)) & 0xffff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCS_NVMD_STAT_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Error, status = 0x%04x", __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh chunkp = (uint8_t *)pwp->flash_chunkp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (nvmd) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCIN_NVMD_VPD:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_validate_vpd(pwp, chunkp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCIN_NVMD_AAP1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCIN_NVMD_IOP:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(buf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (nvmd_type == PMCS_NVMD_REG_DUMP) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((i < PMCS_FLASH_CHUNK_SIZE) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (chunkp[i] != 0xff) && (chunkp[i] != '\0')) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(&buf[i], (size_left - i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%c", chunkp[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (nvmd_type == PMCS_NVMD_EVENT_LOG) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i = pmcs_dump_binary(pwp, pwp->flash_chunkp, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_FLASH_CHUNK_SIZE >> 2), buf, size_left);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "UNKNOWN NVMD DEVICE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_set_nvmd
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function will write the requested data to non-volatile storage
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on the HBA. This could mean SEEPROM, VPD, or other areas as defined by
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the PM8001 programmer's manual.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * nvmd_type: The data type to be written
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * buf: Pointer to memory region for data to write
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * len: Length of the data buffer
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Returns: B_TRUE on success, B_FALSE on failure
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t *buf,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t len)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_set_nvmd_cmd_t iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *workp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *ptr, ibq, *iombp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t dlen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t tdas_nvmd, ip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (nvmd_type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_NVMD_SPCBOOT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tdas_nvmd = PMCIN_NVMD_SEEPROM;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ip = PMCIN_NVMD_INDIRECT_PLD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((len >= PMCS_SPCBOOT_MIN_SIZE) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (len <= PMCS_SPCBOOT_MAX_SIZE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dlen = LE_32(len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Invalid nvmd type: %d", __func__, nvmd_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEVEL, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Request for nvmd type: %d", __func__, nvmd_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (workp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to get work struct", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = &iomb.header;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ptr, sizeof (pmcs_set_nvmd_cmd_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *ptr = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_GENERAL, PMCIN_SET_NVMD_DATA));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp->arg = (void *)&iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.htag = LE_32(workp->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ip = ip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.tdas_nvmd = tdas_nvmd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.signature = LE_32(PMCS_SEEPROM_SIGNATURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipbal = LE_32(DWORD0(pwp->flash_chunk_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipbah = LE_32(DWORD1(pwp->flash_chunk_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb.ipdl = dlen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG_DEVEL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "PMCIN_SET_NVMD_DATA iomb", (void *)&iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(buf, pwp->flash_chunkp, len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ptr will now point to the inbound queue message
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh GET_IO_IQ_ENTRY(pwp, ptr, 0, ibq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "!%s: Unable to get IQ entry", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ptr, PMCS_MSG_SIZE << 2); /* PMCS_MSG_SIZE is in dwords */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iombp = (uint32_t *)&iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, iombp, sizeof (pmcs_set_nvmd_cmd_t) >> 2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh workp->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, ibq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(workp, 2000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, workp->htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, workp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(*(ptr + 3)) & 0xffff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCS_NVMD_STAT_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Error, status = 0x%04x", __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}