ses.c revision d65b419ea7828ceaecc8f2ed7188237add6b14dc
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * See the License for the specific language governing permissions
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * and limitations under the License.
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 * CDDL HEADER END
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * Use is subject to license terms.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * ses (SCSI Generic Device) specific functions.
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* useful defines */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_statdesc {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp const char *us_desc;
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_INPROGRESS, "in progress", B_TRUE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_COMPLETE_NOW, "completed (available)", B_FALSE,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "completed (need reset or power on)", B_FALSE, B_FALSE },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp { SES2_DLUCODE_S_COMPLETE_AT_POWERON, "completed (need power on)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "internal error (NEED NEW IMAGE BEFORE RESET)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "internal error (reset to revert to backup)",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (sizeof (ucode_statdesc_table) / sizeof (ucode_statdesc_table[0]))
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_status {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcptypedef struct ucode_wait {
c4800545504378963d9f2eeb253f06899664f9f6jmcptypedef struct sam4_statdesc {
c4800545504378963d9f2eeb253f06899664f9f6jmcp { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
c4800545504378963d9f2eeb253f06899664f9f6jmcp { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
c4800545504378963d9f2eeb253f06899664f9f6jmcp { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
c4800545504378963d9f2eeb253f06899664f9f6jmcp "Status: TASK SET FULL (insufficient resources in command queue" },
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* required functions for this plugin */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpint fw_readfw(struct devicelist *device, char *filename);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/* helper functions */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int print_updated_status(ses_node_t *np, void *arg);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcpstatic int get_status(nvlist_t *props, ucode_status_t *sp);
c4800545504378963d9f2eeb253f06899664f9f6jmcp * We don't currently support reading firmware from a SAS
c4800545504378963d9f2eeb253f06899664f9f6jmcp * expander. If we do eventually support it, we would use
c4800545504378963d9f2eeb253f06899664f9f6jmcp * the scsi READ BUFFER command to do so.
c4800545504378963d9f2eeb253f06899664f9f6jmcp "%s: not writing firmware for device %s to file %s\n",
c4800545504378963d9f2eeb253f06899664f9f6jmcp flashdev->drvname, flashdev->access_devname, filename);
c4800545504378963d9f2eeb253f06899664f9f6jmcp gettext("\n\nReading of firmware images from %s-attached "
c4800545504378963d9f2eeb253f06899664f9f6jmcp "devices is not supported\n\n"),
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 * If verifier is null, then we haven't been called following a firmware
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * image verification load operation.
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.
c4800545504378963d9f2eeb253f06899664f9f6jmcp /* should _not_ happen */
c4800545504378963d9f2eeb253f06899664f9f6jmcp "been verified.\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp "space for device prop list\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout, "\n"); /* get a fresh line for progress updates */
c4800545504378963d9f2eeb253f06899664f9f6jmcp "property, hence unable to flash device\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_add_byte_array(nvl, SES_CTL_PROP_UCODE_DATA,
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (uint8_t *)verifier->fwimage, verifier->imgsize) != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "%s: Out of memory for property addition\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp ses_open(LIBSES_VERSION, flashdev->access_devname)) == NULL) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp if ((targetnode = ses_snap_primary_enclosure(snapshot)) == NULL) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp "device %s\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp "after the system is rebooted.\n\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp "%s: unable to flash image %s to device %s\n\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * The fw_identify() function walks the device
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * tree trying to find devices which this plugin
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp * can work with.
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 * firstdev is allocated by us and we add space as needed
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp logmsg(MSG_INFO, gettext("No %s nodes in this system\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp "for a device node\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /* we've found one, at least */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp "to allocate space for device entry\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp /* calloc enough for /devices + devpath + devsuffix + '\0' */
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if ((newdev->access_devname = calloc(1, devlength)) == NULL) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp "space for a devfs name\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp "space to store a driver name\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp if ((newdev->classname = calloc(1, strlen(driver) + 1))
c4800545504378963d9f2eeb253f06899664f9f6jmcp "space for a class name\n"),
c4800545504378963d9f2eeb253f06899664f9f6jmcp * Only alloc as much as we truly need, and DON'T forget
c4800545504378963d9f2eeb253f06899664f9f6jmcp * that libnvpair manages the memory for property lookups!
c4800545504378963d9f2eeb253f06899664f9f6jmcp * The same goes for libdevinfo properties.
c4800545504378963d9f2eeb253f06899664f9f6jmcp * Also note that we're allocating here before we try to
c4800545504378963d9f2eeb253f06899664f9f6jmcp * ses_open() the target, because if we can't allocate
c4800545504378963d9f2eeb253f06899664f9f6jmcp * sufficient space then we might as well go home.
c4800545504378963d9f2eeb253f06899664f9f6jmcp newdev->ident = calloc(1, VIDLEN + PIDLEN + REVLEN + 3);
c4800545504378963d9f2eeb253f06899664f9f6jmcp * If the node has no properties, or the INQUIRY properties
c4800545504378963d9f2eeb253f06899664f9f6jmcp * don't exist, this device does not comply with SES2 so we
c4800545504378963d9f2eeb253f06899664f9f6jmcp * won't touch it.
c4800545504378963d9f2eeb253f06899664f9f6jmcp "\nvid: %s\npid: %s\nrevid: %s\n",
c4800545504378963d9f2eeb253f06899664f9f6jmcp "Chassis Serial Number: %s\n",
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "%s: no chassis-serial-number property "
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "for device %s\n",
f1c2346531c82ed357422b37e6c09f7b692e0c45James C. McPherson rv = di_prop_lookup_strings(DDI_DEV_T_ANY,
f1c2346531c82ed357422b37e6c09f7b692e0c45James C. McPherson thisnode, "target-port", &newdev->addresses[1]);
c4800545504378963d9f2eeb253f06899664f9f6jmcp "%s: no target-port property "
c4800545504378963d9f2eeb253f06899664f9f6jmcp "for device %s\n",
c4800545504378963d9f2eeb253f06899664f9f6jmcp "target-port property: %s\n",
c4800545504378963d9f2eeb253f06899664f9f6jmcp "\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",
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang (tempdev->addresses[0] ? tempdev->addresses[0] :
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "(not supported)"),
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang (tempdev->addresses[1] ? tempdev->addresses[1] :
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "(not supported)"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"),
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp thisdev->index, thisdev->access_devname, thisdev->classname);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tProduct : %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tFirmware revision : %s\n"
c4800545504378963d9f2eeb253f06899664f9f6jmcp "\tChassis Serial Number : %s\n"
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "\tTarget-port identifier : %s\n"),
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang (thisdev->addresses[0] ? thisdev->addresses[0] :
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "(not supported)"),
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang (thisdev->addresses[1] ? thisdev->addresses[1] :
0f59e5a798136b49e7c0666181494da06bd8051epeihong huang "(not supported)"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*ARGSUSED*/
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp if (nvlist_lookup_uint64(props, SES_EN_PROP_UCODE, &status) != 0) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp "not supported");
c4800545504378963d9f2eeb253f06899664f9f6jmcp gettext("\nError: Unable to retrieve current status\n"));
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp for (i = 0; i < NUCODE_STATUS; i++) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp /* LINTED */
c4800545504378963d9f2eeb253f06899664f9f6jmcp "libses: status.us_iserr: 0x%0x\n",
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp/*ARGSUSED*/
c4800545504378963d9f2eeb253f06899664f9f6jmcp /* If we've been called without data, eject */
c4800545504378963d9f2eeb253f06899664f9f6jmcp if (nvlist_lookup_byte_array(arg, SES_CTL_PROP_UCODE_DATA,
c4800545504378963d9f2eeb253f06899664f9f6jmcp (nvlist_lookup_string(props, SES_EN_PROP_VID, &vendor) != 0) ||
c4800545504378963d9f2eeb253f06899664f9f6jmcp (nvlist_lookup_string(props, SES_EN_PROP_PID, &product) != 0) ||
c4800545504378963d9f2eeb253f06899664f9f6jmcp (nvlist_lookup_string(props, SES_EN_PROP_REV, &revision) != 0) ||
c4800545504378963d9f2eeb253f06899664f9f6jmcp (nvlist_lookup_string(props, LIBSES_EN_PROP_CSN, &csn) != 0)) {
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) printf("%30s: %s\n", "current status", statdesc.us_desc);
5a7763bf3e9db4cfe6cb523b096cb74af71e3793jmcp (void) snprintf(buf, sizeof (buf), "downloading %u bytes", len);
c4800545504378963d9f2eeb253f06899664f9f6jmcp * If the bufferid isn't 2, then the verifier has already
87d06e46cdea545c3c673120b7211158dcfd35ccpeihong huang * OK'd the image that the user has provided.
c4800545504378963d9f2eeb253f06899664f9f6jmcp * At present the non-"standard" images need to be flashed
c4800545504378963d9f2eeb253f06899664f9f6jmcp * using the scsi WRITE BUFFER command
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (ses_node_ctl(np, SES_CTL_OP_DL_UCODE, arg) != FWFLASH_SUCCESS) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp "failed to update SES snapshot: %s",
c4800545504378963d9f2eeb253f06899664f9f6jmcp print_updated_status(ses_snap_primary_enclosure(newsnap),
d73e86db323b2684ada2db7e3b2fe57e542703b0suha int i = 0;
c4800545504378963d9f2eeb253f06899664f9f6jmcp action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
c4800545504378963d9f2eeb253f06899664f9f6jmcp wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
c4800545504378963d9f2eeb253f06899664f9f6jmcp "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((ret != FWFLASH_SUCCESS) || samstatus != SAM4_STATUS_GOOD) {
c4800545504378963d9f2eeb253f06899664f9f6jmcp for (i = 0; i < NSAM4_STATUS; i++) {