d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * CDDL HEADER START
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The contents of this file are subject to the terms of the
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Common Development and Distribution License (the "License").
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * You may not use this file except in compliance with the License.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * See the License for the specific language governing permissions
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * and limitations under the License.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * When distributing Covered Code, include this CDDL HEADER in each
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * If applicable, add the following below this CDDL HEADER, with the
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * fields enclosed by brackets "[]" replaced with your own identifying
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * information: Portions Copyright [yyyy] [name of copyright owner]
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * CDDL HEADER END
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Use is subject to license terms.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * sd / ssd (SCSI Direct-attached Device) specific functions.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "Status: TASK SET FULL (insufficient resources in command queue" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/* required functions for this plugin */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint fw_readfw(struct devicelist *device, char *filename);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/* helper functions */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChenstatic char *find_link(di_node_t bnode, char *acc_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int sd_idtfy_custmz(struct devicelist *device, char *sp);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * We don't currently support reading firmware from a disk. If we do eventually
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * support it, we would use the scsi READ BUFFER command to do so.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_readfw(struct devicelist *flashdev, char *filename)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: not writing firmware for device %s to file %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname, flashdev->access_devname, filename);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("\n\nReading of firmware images from %s-attached "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "devices is not supported\n\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((verifier == NULL) || (verifier->imgsize == 0) ||
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* should _NOT_ happen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: Firmware image has not been verified\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((target = libscsi_open(handle, NULL, flashdev->access_devname))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void *)verifier->fwimage, (size_t)verifier->imgsize);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen 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);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen for (i = 0; i < NSAM4_STATUS; i++) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Note: For flash based disks "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(SSD, etc). You may need power off the system to wait a "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "few minutes for supercap to fully discharge, then power "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "on the system again to activate the new firmware\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The fw_identify() function walks the device
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * tree trying to find devices which this plugin
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * can work with.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The parameter "start" gives us the starting index number
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * to give the device when we add it to the fw_devices list.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * firstdev is allocated by us and we add space as needed
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * When we store the desired information, inquiry-serial-no
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * goes in thisdev->addresses[1], and client-guid goes in
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * thisdev->addresses[2].
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We need to inquiry information manually by sending probe command */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Just in case we've got an FC-attached device on sparc */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "No %s nodes in this system\n", driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: failed to initialize "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* we've found one, at least */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* Need to free by di_devfs_path_free */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * We check if this is removable device, in which case
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * we really aren't interested, so exit stage left
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: not interested in removable media device\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev = calloc(1, sizeof (struct devicelist)))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to allocate space for device entry\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->drvname = calloc(1, strlen(driver) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->classname = calloc(1, strlen(driver) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* Get the access name for current node */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* The slice number may be 2 or 0, we will try 2 first */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* try 0 for EFI label */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "%s: unable to open device %s\n",
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* and the /dev/rdsk/ name */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Only alloc as much as we truly need, and DON'T forget
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * that libdevinfo manages the memory!
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We don't use new->ident->encap_ident currently */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Retrive information by using libscsi */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Vendor ID */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We need to do customize the output for SATA disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get vendor id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "allocation failure\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Product ID */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen * There is no SPACE character in the PID field
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen * Customize strings for special SATA disks
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* The first string is vendor id */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get sata vendor id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* The second string is product id */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get sata product id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Revision ID */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable to get revision "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Finish using libscsi */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no inquiry-serial-no property for %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no client-guid property "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "for device %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* try fallback */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no guid property for device %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "client-guid property: %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Check if sd targets presented are all unflashable. */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\ttempdev @ 0x%lx\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taccess_devname: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tdrvname: %s\tclassname: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->vid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->pid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->revid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tindex: %d\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[0]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[1]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[2]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tplugin @ 0x%lx\n\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen " Class [%s]\t\t\t%s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tVendor\t\t\t: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tProduct\t\t\t: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tFirmware revision\t: %-s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tInquiry Serial Number : %-s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tGUID\t\t\t: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Function to clean up all the memory allocated
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * by this plugin, for thisdev.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Note that we DO NOT free addresses[1,2] because _IF_
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * these elements are valid, they are managed by libdevinfo
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * and we didn't allocate any space for them.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* what this points to is freed in common code */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Helper functions
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic char *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "di_node_t\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "link\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if (di_devlink_walk(hdl, linkname, acc_devname + strlen(devprefix),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("Unable to walk devlink snapshot for %s: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* vid customization */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Customize retail Seagate disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->vid = strdup("SEAGATE")) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Customize retail INTEL disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->vid = strdup("INTEL")) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* disks to do in the furture, fill 'ATA' first */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* pid customization */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Unable to allocate space for "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "product id\n"));