ses.c revision d73e86db323b2684ada2db7e3b2fe57e542703b0
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * CDDL HEADER START
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * The contents of this file are subject to the terms of the
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * Common Development and Distribution License (the "License").
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * You may not use this file except in compliance with the License.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * or http://www.opensolaris.org/os/licensing.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * See the License for the specific language governing permissions
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * and limitations under the License.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * When distributing Covered Code, include this CDDL HEADER in each
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * If applicable, add the following below this CDDL HEADER, with the
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * fields enclosed by brackets "[]" replaced with your own identifying
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * information: Portions Copyright [yyyy] [name of copyright owner]
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * CDDL HEADER END
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * Use is subject to license terms.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#pragma ident "%Z%%M% %I% %E% SMI"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * ses (SCSI Generic Device) specific functions.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <assert.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <libnvpair.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <stdio.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <stdlib.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <unistd.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/types.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/stat.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/sysmacros.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/queue.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <fcntl.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <string.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <strings.h>
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <scsi/libses.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/scsi/generic/commands.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <sys/scsi/impl/uscsi.h>
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <libintl.h> /* for gettext(3c) */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#include <fwflash/fwflash.h>
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#ifdef NDEBUG
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define verify(EX) ((void)(EX))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#else
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define verify(EX) assert(EX)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#endif
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define VIDLEN 0x08
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define PIDLEN 0x10
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define REVLEN 0x04
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define SASADDRLEN 0x10
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define PCBUFLEN 0x40
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define RQBUFLEN 0xfe
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define STATBUFLEN 0xfe
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define INQBUFLEN 0x80
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* useful defines */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define UCODE_CHECK_STATUS 0
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define UCODE_CHECK_SUPPORTED 1
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_statdesc {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint64_t us_value;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp const char *us_desc;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp boolean_t us_pending;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp boolean_t us_iserr;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp} ucode_statdesc_t;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic ucode_statdesc_t ucode_statdesc_table[] = {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_NOP, "none", B_FALSE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_INPROGRESS, "in progress", B_TRUE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_SAVING, "saved", B_TRUE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_COMPLETE_NOW, "completed (available)", B_FALSE,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_COMPLETE_AT_RESET,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "completed (need reset or power on)", B_FALSE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_COMPLETE_AT_POWERON, "completed (need power on)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_PAGE_ERR, "page error (offset %d)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_TRUE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_IMAGE_ERR, "invalid image",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_TRUE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_TIMEOUT, "download timeout",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_TRUE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_INTERNAL_NEEDIMAGE,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "internal error (NEED NEW IMAGE BEFORE RESET)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_TRUE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_INTERNAL_SAFE,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "internal error (reset to revert to backup)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp B_FALSE, B_TRUE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp};
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp#define NUCODE_STATUS \
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (sizeof (ucode_statdesc_table) / sizeof (ucode_statdesc_table[0]))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_status {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint64_t us_status;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp boolean_t us_iserr;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp boolean_t us_pending;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp char us_desc[128];
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp} ucode_status_t;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_wait {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint64_t uw_prevstatus;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp boolean_t uw_pending;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_node_t *uw_oldnp;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp} ucode_wait_t;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpchar drivername[] = "ses\0";
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic char *devprefix = "/devices";
d73e86db323b2684ada2db7e3b2fe57e542703b0suhastatic char *devsuffix = ":0";
72b4c2cd5756cbce91ec4b298168685490456787jmcpstatic ses_target_t *ses_target;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpextern di_node_t rootnode;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpextern int errno;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpextern struct fw_plugin *self;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpextern struct vrfyplugin *verifier;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpextern int fwflash_debug;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* required functions for this plugin */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint fw_readfw(struct devicelist *device, char *filename);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint fw_writefw(struct devicelist *device);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint fw_identify(int start);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint fw_devinfo(struct devicelist *thisdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* helper functions */
d73e86db323b2684ada2db7e3b2fe57e542703b0suhastatic struct vpr *inquiry(char *path);
d73e86db323b2684ada2db7e3b2fe57e542703b0suhastatic int ses_dl_ucode_check(struct devicelist *flashdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic ses_walk_action_t print_updated_status(ses_node_t *np, void *arg);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic int get_status(nvlist_t *props, ucode_status_t *sp);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic ses_walk_action_t sendimg(ses_node_t *np, void *data);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * SES2 does not actually allow us to read a firmware
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * image from an SES device, so we just return success
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * if this is requested, after printing a message.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpfw_readfw(struct devicelist *flashdev, char *filename)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int rv = FWFLASH_SUCCESS;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: not writing firmware for device %s to file %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha flashdev->access_devname, filename);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("\n\nSES2 does not support retrieval "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "of firmware images\n\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (rv);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * If we're invoking fw_writefw, then flashdev is a valid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * flashable device supporting the SES2 Download Microcode Diagnostic
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * Control page (0x0e).
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * If verifier is null, then we haven't been called following a firmware
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * image verification load operation.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * *THIS* function uses scsi SEND DIAGNOSTIC/download microcode to
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * achieve the task... if you chase down to the bottom of libses you
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * can see that too.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpfw_writefw(struct devicelist *flashdev)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_t *nvl;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_snap_t *snapshot;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_add_uint64(nvl, SES_CTL_PROP_UCODE_MODE,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp SES_DLUCODE_M_WITH_OFFS) != 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to allocate "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "space for device prop list\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_FAILURE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((verifier == NULL) || (verifier->imgsize == 0) ||
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (verifier->fwimage == NULL)) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /* should _not_ happen */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Firmware image has not "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "been verified.\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_FAILURE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout, "\n"); /* get a fresh line for progress updates */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_add_uint64(nvl, SES_CTL_PROP_UCODE_BUFID,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verifier->flashbuf) != 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to add buffer id "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "property\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp goto cancel;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_add_byte_array(nvl, SES_CTL_PROP_UCODE_DATA,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (uint8_t *)verifier->fwimage, verifier->imgsize) != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_ERROR,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "%s: Out of memory for property addition\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha drivername);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp goto cancel;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((ses_target =
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_open(LIBSES_VERSION, flashdev->access_devname)) == NULL) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to open flashable device\n%s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha flashdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp goto cancel;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp snapshot = ses_snap_hold(ses_target);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * We flash via a walker callback function, because it's easier
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * to do it this way when using libses.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) ses_walk(snapshot, sendimg, nvl);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Done. New image will be active "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "after the system is rebooted.\n"));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha fprintf(stdout, "\n");
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_snap_rele(snapshot);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_close(ses_target);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpcancel:
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_free(nvl);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (FWFLASH_SUCCESS);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * The fw_identify() function walks the device
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * tree trying to find devices which this plugin
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * can work with.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * The parameter "start" gives us the starting index number
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * to give the device when we add it to the fw_devices list.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp *
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * firstdev is allocated by us and we add space as needed
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpfw_identify(int start)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp int rv = FWFLASH_FAILURE;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp di_node_t thisnode;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp struct devicelist *newdev;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp char *devpath;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp int idx = start;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp int devlength = 0;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha thisnode = di_drv_first_node(drivername, rootnode);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (thisnode == DI_NODE_NIL) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_INFO, gettext("No %s nodes in this system\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha drivername);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (rv);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((devpath = calloc(1, MAXPATHLEN + 1)) == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to malloc space "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "for a %s-attached device node\n"), drivername);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (rv);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(devpath, MAXPATHLEN);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /* we've found one, at least */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp devpath = di_devfs_path(thisnode);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((newdev = calloc(1, sizeof (struct devicelist)))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp == NULL) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: identification function unable "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "to allocate space for device entry\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (rv);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha /* malloc enough for /devices + devpath + ":0" + '\0' */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp devlength = strlen(devpath) + strlen(devprefix) +
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp strlen(devsuffix) + 2;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((newdev->access_devname = calloc(1, devlength)) == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to malloc "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "space for a devfs name\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(devpath);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_FAILURE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp snprintf(newdev->access_devname, devlength,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "%s%s%s", devprefix, devpath, devsuffix);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((newdev->drvname = calloc(1, strlen(drivername) + 1))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to malloc "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "space for a driver name\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_FAILURE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) strlcpy(newdev->drvname, drivername,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha strlen(drivername) + 1);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((newdev->classname = calloc(1, strlen(drivername) + 1))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR, gettext("ses: Unable to malloc "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "space for a class name\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->drvname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_FAILURE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) strlcpy(newdev->classname, drivername,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha strlen(drivername) + 1);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /*
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * Check for friendly vendor names, and whether this device
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * supports the Download Microcode Control page.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha newdev->ident = inquiry(newdev->access_devname);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha rv = ses_dl_ucode_check(newdev);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((rv == FWFLASH_FAILURE) || (newdev->ident == NULL))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha continue;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (newdev->ident == NULL) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: unable to inquire on potentially "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "flashable device\n%s\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp newdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->drvname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->classname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp continue;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /*
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * Look for the target-port property. We use addresses[1]
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * because addresses[0] is already assigned by the inquiry
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * function
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((newdev->addresses[1] = calloc(1, SASADDRLEN + 1))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Out of memory for target-port\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->access_devname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->drvname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev->classname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp free(newdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp continue;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp } else {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "target-port", &newdev->addresses[1]) < 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: no target-port property for "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "device %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha newdev->access_devname);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha strlcpy(newdev->addresses[1],
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "0000000000000000", 17);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp newdev->index = idx;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ++idx;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp newdev->plugin = self;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (fwflash_debug != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp struct devicelist *tempdev;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO, "ses:fw_writefw:\n");
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\taccess_devname: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tdrvname: %s\tclassname: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tident->vid: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tident->pid: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tident->revid: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tindex: %d\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\taddress[0]: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\taddress[1]: %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\t\tplugin @ 0x%lx\n\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp &tempdev,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->access_devname,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->drvname, newdev->classname,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->ident->vid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->ident->pid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->ident->revid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp tempdev->index,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (tempdev->addresses[0] != NULL) ?
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (char *)tempdev->addresses[0] : "NULL",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (tempdev->addresses[1] != NULL) ?
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (char *)tempdev->addresses[1] : "NULL",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha tempdev->plugin);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_SUCCESS);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpfw_devinfo(struct devicelist *thisdev)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->index, thisdev->access_devname, thisdev->classname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (thisdev->addresses[0] != NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha fprintf(stdout,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("\tChassis Serial Number : %s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha thisdev->addresses[0]);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp gettext("\tVendor : %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tProduct : %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tFirmware revision : %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tTarget-port identifier : %s\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->ident->vid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->ident->pid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->ident->revid,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->addresses[1]);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout, "\n\n");
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (FWFLASH_SUCCESS);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*ARGSUSED*/
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic int
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpget_status(nvlist_t *props, ucode_status_t *sp)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp int i;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint64_t status, astatus;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_lookup_uint64(props, SES_EN_PROP_UCODE, &status) != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp sp->us_status = -1ULL;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) snprintf(sp->us_desc, sizeof (sp->us_desc),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "not supported");
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (-1);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha verify(nvlist_lookup_uint64(props, SES_EN_PROP_UCODE_A, &astatus) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp for (i = 0; i < NUCODE_STATUS; i++) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (ucode_statdesc_table[i].us_value == status)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp break;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp sp->us_status = status;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (i == NUCODE_STATUS) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) snprintf(sp->us_desc, sizeof (sp->us_desc),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "unknown (0x%02x)", (int)status);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp sp->us_iserr = sp->us_pending = B_FALSE;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp } else {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /* LINTED */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) snprintf(sp->us_desc, sizeof (sp->us_desc),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ucode_statdesc_table[i].us_desc, (int)astatus);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp sp->us_iserr = ucode_statdesc_table[i].us_iserr;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp sp->us_pending = ucode_statdesc_table[i].us_pending;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic ses_walk_action_t
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpprint_updated_status(ses_node_t *np, void *arg)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ucode_wait_t *uwp = arg;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_node_t *oldnp = uwp->uw_oldnp;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_t *props, *oldprops;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint64_t id, oldid;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ucode_status_t status;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (ses_node_type(np) != SES_NODE_ENCLOSURE)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify((props = ses_node_props(np)) != NULL);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify((oldprops = ses_node_props(oldnp)) != NULL);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_uint64(props, SES_EN_PROP_EID, &id) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_uint64(oldprops, SES_EN_PROP_EID, &oldid) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (oldid != id)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) get_status(props, &status);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (status.us_status != uwp->uw_prevstatus)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "status", status.us_desc);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uwp->uw_prevstatus = status.us_status;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uwp->uw_pending = status.us_pending;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (status.us_iserr)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: status.us_iserr: 0x%0x\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp status.us_iserr);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*ARGSUSED*/
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic ses_walk_action_t
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpsendimg(ses_node_t *np, void *data)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_t *props;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp nvlist_t *arg = data;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp char *vendor, *product, *revision, *csn;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp char buf[128];
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_snap_t *newsnap;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp int ret;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ucode_status_t statdesc;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ucode_wait_t wait;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp uint8_t *imagedata;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha size_t len;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (ses_node_type(np) != SES_NODE_ENCLOSURE)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify((props = ses_node_props(np)) != NULL);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_string(props, SES_EN_PROP_VID, &vendor) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_string(props, SES_EN_PROP_PID, &product) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_string(props, SES_EN_PROP_REV, &revision) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_string(props, LIBSES_EN_PROP_CSN, &csn) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "vendor", vendor);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "product", product);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "revision", revision);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "serial", csn);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ret = get_status(props, &statdesc);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "current status", statdesc.us_desc);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (ret != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (arg != NULL)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_TERMINATE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp else
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp verify(nvlist_lookup_byte_array(arg, SES_CTL_PROP_UCODE_DATA,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp &imagedata, &len) == 0);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) snprintf(buf, sizeof (buf), "downloading %u bytes", len);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("\n%30s: ", buf);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (ses_node_ctl(np, SES_CTL_OP_DL_UCODE, arg) != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("failed!\n");
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%s\n", ses_errmsg());
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp } else {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("ok\n");
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp }
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp wait.uw_prevstatus = -1ULL;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp wait.uw_oldnp = np;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp do {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((newsnap = ses_snap_new(ses_target)) == NULL)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_ERROR,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "failed to update SES snapshot: %s",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_errmsg());
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) ses_walk(newsnap, print_updated_status,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp &wait);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_snap_rele(newsnap);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp } while (wait.uw_pending);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp return (SES_WALK_ACTION_CONTINUE);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp
d73e86db323b2684ada2db7e3b2fe57e542703b0suha/*
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * Simple function to sent a standard SCSI INQUIRY(6) cdb out
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * to thisnode and blat the response back into a struct vpr*
d73e86db323b2684ada2db7e3b2fe57e542703b0suha */
d73e86db323b2684ada2db7e3b2fe57e542703b0suhastatic struct vpr *
d73e86db323b2684ada2db7e3b2fe57e542703b0suhainquiry(char *path) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha struct uscsi_cmd *inqcmd;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha uchar_t inqbuf[INQBUFLEN]; /* inquiry response */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha uchar_t rqbuf[RQBUFLEN]; /* request sense data */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha struct vpr *inqvpr;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int fd, rval;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqvpr = NULL;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((inqcmd = calloc(1, sizeof (struct uscsi_cmd))) == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to malloc %d bytes "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "for a SCSI INQUIRY(6) command\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha sizeof (struct uscsi_cmd));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((inqvpr = calloc(1, sizeof (struct vpr))) == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to malloc %d bytes "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "for SCSI INQUIRY(6) response\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha sizeof (struct vpr));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((inqcmd->uscsi_cdb = calloc(1, CDB_GROUP0 * sizeof (caddr_t)))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to malloc %d bytes "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "for SCSI INQUIRY(6)\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha CDB_GROUP0 * sizeof (caddr_t));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO, "ses:inquiry:opening device %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha path);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((fd = open(path, O_RDONLY|O_SYNC)) < 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: Unable to open device %s: %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha path, strerror(errno));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd->uscsi_cdb);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (((inqvpr->vid = calloc(1, VIDLEN + 1))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL) ||
d73e86db323b2684ada2db7e3b2fe57e542703b0suha ((inqvpr->pid = calloc(1, PIDLEN + 1))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL) ||
d73e86db323b2684ada2db7e3b2fe57e542703b0suha ((inqvpr->revid = calloc(1, REVLEN + 1))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL)) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to malloc %d bytes "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "for %s identification function.\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha VIDLEN+PIDLEN+REVLEN, drivername);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd->uscsi_cdb);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->vid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->pid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->revid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha /* just make sure these buffers are clean */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(inqbuf, INQBUFLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(rqbuf, RQBUFLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(inqcmd->uscsi_cdb, CDB_GROUP0);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_flags = USCSI_READ;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_timeout = 0;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_bufaddr = (caddr_t)inqbuf;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_buflen = INQBUFLEN;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdblen = CDB_GROUP0; /* a GROUP 0 command */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[0] = SCMD_INQUIRY;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[1] = 0x00; /* EVPD = Enable Vital Product Data */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[2] = 0x00; /* which pagecode to query? */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[3] = 0x00; /* allocation length, msb */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[4] = INQBUFLEN; /* allocation length, lsb */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_cdb[5] = 0x0; /* control byte */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_rqbuf = (caddr_t)&rqbuf;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqcmd->uscsi_rqlen = RQBUFLEN;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha rval = ioctl(fd, USCSICMD, inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (rval < 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha /* ioctl failed */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to retrieve SCSI INQUIRY(6) data "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "from device %s: %s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha path, strerror(errno));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd->uscsi_cdb);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->vid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->pid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->revid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bcopy(&inqbuf[8], inqvpr->vid, VIDLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bcopy(&inqbuf[16], inqvpr->pid, PIDLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bcopy(&inqbuf[32], inqvpr->revid, REVLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) close(fd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses inquiry: vid %s ; pid %s ; revid %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqvpr->vid, inqvpr->pid, inqvpr->revid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((strncmp(inqvpr->vid, "SUN", 3) != 0) &&
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (strncmp(inqvpr->vid, "LSI", 3) != 0) &&
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (strncmp(inqvpr->vid, "Quanta", 6) != 0) &&
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (strncmp(inqvpr->vid, "QUANTA", 6) != 0)) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->vid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->pid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqvpr->revid);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqvpr->vid = NULL;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqvpr->pid = NULL;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha inqvpr->revid = NULL;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses inquiry: unrecognised device\n");
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (NULL);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd->uscsi_cdb);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(inqcmd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (inqvpr);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha}
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha/*
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * ses_dl_ucode_check() lets us check whether SES2's Download
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * Microcode Control diagnostic and status pages are supported
d73e86db323b2684ada2db7e3b2fe57e542703b0suha * by flashdev.
d73e86db323b2684ada2db7e3b2fe57e542703b0suha */
d73e86db323b2684ada2db7e3b2fe57e542703b0suhaint
d73e86db323b2684ada2db7e3b2fe57e542703b0suhases_dl_ucode_check(struct devicelist *flashdev)
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp{
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int rv;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int limit;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int i = 0;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int fd;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha struct uscsi_cmd *usc;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha uchar_t sensebuf[RQBUFLEN]; /* for the request sense data */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha uchar_t pagesup[PCBUFLEN]; /* should be less than 64 pages */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((fd = open(flashdev->access_devname,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha O_RDONLY|O_NDELAY)) < 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses:ses_dl_ucode_check: Unable to open %s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha flashdev->access_devname);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (FWFLASH_FAILURE);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((usc = calloc(1, sizeof (struct uscsi_cmd))) == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to alloc %d bytes for "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "microcode download query: %s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha sizeof (struct uscsi_cmd), strerror(errno));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) close(fd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (FWFLASH_FAILURE);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if ((usc->uscsi_cdb = calloc(1, CDB_GROUP0 * sizeof (caddr_t)))
d73e86db323b2684ada2db7e3b2fe57e542703b0suha == NULL) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_ERROR,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha gettext("ses: Unable to alloc %d bytes for "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "microcode download query: %s\n"),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha CDB_GROUP0 * sizeof (caddr_t), strerror(errno));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) close(fd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(usc);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (FWFLASH_FAILURE);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(sensebuf, RQBUFLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_flags = USCSI_READ | USCSI_RQENABLE;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_timeout = 0;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdblen = CDB_GROUP0;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_rqbuf = (caddr_t)&sensebuf;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_rqlen = RQBUFLEN;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha bzero(pagesup, PCBUFLEN);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_bufaddr = (caddr_t)&pagesup;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_buflen = PCBUFLEN;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[0] = SCMD_GDIAG; /* "Get" or receive */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[1] = 1; /* PCV = Page Code Valid */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[2] = 0x00; /* list all Supported diag pages */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[3] = 0x00;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[4] = PCBUFLEN;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha usc->uscsi_cdb[5] = 0; /* control byte, reserved */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha rv = ioctl(fd, USCSICMD, usc);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (rv < 0) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO,
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "ses: DL uCode checker ioctl error (%d): %s\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha errno, strerror(errno));
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (FWFLASH_FAILURE);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha rv = FWFLASH_FAILURE;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha /* in SPC4, this is an "n-3" field */
d73e86db323b2684ada2db7e3b2fe57e542703b0suha limit = (pagesup[2] << 8) + pagesup[3] + 4;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha while (i < limit) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha if (pagesup[4 + i] == 0x0E) {
d73e86db323b2684ada2db7e3b2fe57e542703b0suha i = limit;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha logmsg(MSG_INFO, "ses: device %s "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "supports the Download Microcode "
d73e86db323b2684ada2db7e3b2fe57e542703b0suha "diagnostic control page\n",
d73e86db323b2684ada2db7e3b2fe57e542703b0suha flashdev->access_devname);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha rv = FWFLASH_SUCCESS;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha ++i;
d73e86db323b2684ada2db7e3b2fe57e542703b0suha }
d73e86db323b2684ada2db7e3b2fe57e542703b0suha (void) close(fd);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(usc->uscsi_cdb);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha free(usc);
d73e86db323b2684ada2db7e3b2fe57e542703b0suha
d73e86db323b2684ada2db7e3b2fe57e542703b0suha return (rv);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp}