19683SXin.Chen@Sun.COM /*
29683SXin.Chen@Sun.COM * CDDL HEADER START
39683SXin.Chen@Sun.COM *
49683SXin.Chen@Sun.COM * The contents of this file are subject to the terms of the
59683SXin.Chen@Sun.COM * Common Development and Distribution License (the "License").
69683SXin.Chen@Sun.COM * You may not use this file except in compliance with the License.
79683SXin.Chen@Sun.COM *
89683SXin.Chen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99683SXin.Chen@Sun.COM * or http://www.opensolaris.org/os/licensing.
109683SXin.Chen@Sun.COM * See the License for the specific language governing permissions
119683SXin.Chen@Sun.COM * and limitations under the License.
129683SXin.Chen@Sun.COM *
139683SXin.Chen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149683SXin.Chen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159683SXin.Chen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169683SXin.Chen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179683SXin.Chen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189683SXin.Chen@Sun.COM *
199683SXin.Chen@Sun.COM * CDDL HEADER END
209683SXin.Chen@Sun.COM */
219683SXin.Chen@Sun.COM /*
229683SXin.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
239683SXin.Chen@Sun.COM * Use is subject to license terms.
249683SXin.Chen@Sun.COM */
259683SXin.Chen@Sun.COM
269683SXin.Chen@Sun.COM /*
279683SXin.Chen@Sun.COM * sd / ssd (SCSI Direct-attached Device) specific functions.
289683SXin.Chen@Sun.COM */
299683SXin.Chen@Sun.COM #include <libnvpair.h>
309683SXin.Chen@Sun.COM #include <stdio.h>
319683SXin.Chen@Sun.COM #include <stdlib.h>
329683SXin.Chen@Sun.COM #include <unistd.h>
339683SXin.Chen@Sun.COM #include <sys/types.h>
349683SXin.Chen@Sun.COM #include <sys/sysmacros.h>
359683SXin.Chen@Sun.COM #include <sys/queue.h>
369683SXin.Chen@Sun.COM #include <fcntl.h>
379683SXin.Chen@Sun.COM #include <string.h>
389683SXin.Chen@Sun.COM #include <errno.h>
399683SXin.Chen@Sun.COM #include <scsi/libscsi.h>
409683SXin.Chen@Sun.COM #include <libintl.h> /* for gettext(3c) */
419683SXin.Chen@Sun.COM #include <fwflash/fwflash.h>
429683SXin.Chen@Sun.COM
439683SXin.Chen@Sun.COM typedef struct sam4_statdesc {
449683SXin.Chen@Sun.COM int status;
459683SXin.Chen@Sun.COM char *message;
469683SXin.Chen@Sun.COM } sam4_statdesc_t;
479683SXin.Chen@Sun.COM
489683SXin.Chen@Sun.COM static sam4_statdesc_t sam4_status[] = {
499683SXin.Chen@Sun.COM { SAM4_STATUS_GOOD, "Status: GOOD (success)" },
509683SXin.Chen@Sun.COM { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
519683SXin.Chen@Sun.COM { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
529683SXin.Chen@Sun.COM { SAM4_STATUS_BUSY, "Status: Device is BUSY" },
539683SXin.Chen@Sun.COM { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
549683SXin.Chen@Sun.COM { SAM4_STATUS_TASK_SET_FULL,
559683SXin.Chen@Sun.COM "Status: TASK SET FULL (insufficient resources in command queue" },
569683SXin.Chen@Sun.COM { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
579683SXin.Chen@Sun.COM { NULL, NULL }
589683SXin.Chen@Sun.COM };
599683SXin.Chen@Sun.COM
609683SXin.Chen@Sun.COM #define NSAM4_STATUS \
619683SXin.Chen@Sun.COM (sizeof (sam4_status) / sizeof (sam4_status[0]))
629683SXin.Chen@Sun.COM
639683SXin.Chen@Sun.COM #define FW_SD_FREE_DEVPATH(devpath) { \
649683SXin.Chen@Sun.COM di_devfs_path_free((devpath)); \
659683SXin.Chen@Sun.COM }
669683SXin.Chen@Sun.COM #define FW_SD_FREE_DEVICELIST(thisdev, devpath) { \
679683SXin.Chen@Sun.COM free((thisdev)); \
689683SXin.Chen@Sun.COM FW_SD_FREE_DEVPATH((devpath)) \
699683SXin.Chen@Sun.COM }
709683SXin.Chen@Sun.COM #define FW_SD_FREE_DRV_NAME(thisdev, devpath) { \
719683SXin.Chen@Sun.COM free((thisdev)->drvname); \
729974SXin.Chen@Sun.COM FW_SD_FREE_DEVICELIST((thisdev), (devpath)) \
739683SXin.Chen@Sun.COM }
749683SXin.Chen@Sun.COM #define FW_SD_FREE_CLS_NAME(thisdev, devpath) { \
759683SXin.Chen@Sun.COM free((thisdev)->classname); \
769683SXin.Chen@Sun.COM FW_SD_FREE_DRV_NAME((thisdev), (devpath)) \
779683SXin.Chen@Sun.COM }
789974SXin.Chen@Sun.COM #define FW_SD_FREE_ACC_NAME(thisdev, devpath) { \
799974SXin.Chen@Sun.COM free((thisdev)->access_devname); \
809974SXin.Chen@Sun.COM FW_SD_FREE_CLS_NAME(thisdev, devpath) \
819974SXin.Chen@Sun.COM }
829974SXin.Chen@Sun.COM #define FW_SD_FREE_ADDR(thisdev, devpath) { \
839974SXin.Chen@Sun.COM free((thisdev)->addresses[0]); \
849974SXin.Chen@Sun.COM FW_SD_FREE_ACC_NAME(thisdev, devpath) \
859974SXin.Chen@Sun.COM }
869683SXin.Chen@Sun.COM #define FW_SD_FREE_IDENT(thisdev, devpath) { \
879683SXin.Chen@Sun.COM free((thisdev)->ident); \
889974SXin.Chen@Sun.COM FW_SD_FREE_ADDR((thisdev), (devpath)) \
899683SXin.Chen@Sun.COM }
909683SXin.Chen@Sun.COM #define FW_SD_FREE_IDENT_VID(thisdev, devpath) { \
919683SXin.Chen@Sun.COM free((thisdev)->ident->vid); \
929683SXin.Chen@Sun.COM FW_SD_FREE_IDENT((thisdev), (devpath)) \
939683SXin.Chen@Sun.COM }
949683SXin.Chen@Sun.COM #define FW_SD_FREE_IDENT_PID(thisdev, devpath) { \
959683SXin.Chen@Sun.COM free((thisdev)->ident->pid); \
969683SXin.Chen@Sun.COM FW_SD_FREE_IDENT_VID((thisdev), (devpath)) \
979683SXin.Chen@Sun.COM }
989683SXin.Chen@Sun.COM #define FW_SD_FREE_IDENT_ALL(thisdev, devpath) { \
999683SXin.Chen@Sun.COM free((thisdev)->ident->revid); \
1009683SXin.Chen@Sun.COM FW_SD_FREE_IDENT_PID((thisdev), (devpath)) \
1019683SXin.Chen@Sun.COM }
1029683SXin.Chen@Sun.COM
1039683SXin.Chen@Sun.COM int errno;
1049683SXin.Chen@Sun.COM char drivername[] = "sd\0";
1059683SXin.Chen@Sun.COM int plugin_version = FWPLUGIN_VERSION_2;
1069683SXin.Chen@Sun.COM
1079683SXin.Chen@Sun.COM static char *devprefix = "/devices";
1089683SXin.Chen@Sun.COM extern di_node_t rootnode;
1099683SXin.Chen@Sun.COM extern struct fw_plugin *self;
1109683SXin.Chen@Sun.COM extern struct vrfyplugin *verifier;
1119683SXin.Chen@Sun.COM extern int fwflash_debug;
1129683SXin.Chen@Sun.COM
1139683SXin.Chen@Sun.COM /* required functions for this plugin */
1149683SXin.Chen@Sun.COM int fw_readfw(struct devicelist *device, char *filename);
1159683SXin.Chen@Sun.COM int fw_writefw(struct devicelist *device);
1169683SXin.Chen@Sun.COM int fw_identify(int start);
1179683SXin.Chen@Sun.COM int fw_devinfo(struct devicelist *thisdev);
1189683SXin.Chen@Sun.COM void fw_cleanup(struct devicelist *thisdev);
1199683SXin.Chen@Sun.COM
1209683SXin.Chen@Sun.COM /* helper functions */
1219974SXin.Chen@Sun.COM static char *find_link(di_node_t bnode, char *acc_devname);
1229683SXin.Chen@Sun.COM static int link_cb(di_devlink_t devlink, void *arg);
1239683SXin.Chen@Sun.COM static int sd_idtfy_custmz(struct devicelist *device, char *sp);
1249683SXin.Chen@Sun.COM
1259683SXin.Chen@Sun.COM /*
1269683SXin.Chen@Sun.COM * We don't currently support reading firmware from a disk. If we do eventually
1279683SXin.Chen@Sun.COM * support it, we would use the scsi READ BUFFER command to do so.
1289683SXin.Chen@Sun.COM */
1299683SXin.Chen@Sun.COM int
fw_readfw(struct devicelist * flashdev,char * filename)1309683SXin.Chen@Sun.COM fw_readfw(struct devicelist *flashdev, char *filename)
1319683SXin.Chen@Sun.COM {
1329683SXin.Chen@Sun.COM
1339683SXin.Chen@Sun.COM logmsg(MSG_INFO,
1349683SXin.Chen@Sun.COM "%s: not writing firmware for device %s to file %s\n",
1359683SXin.Chen@Sun.COM flashdev->drvname, flashdev->access_devname, filename);
1369683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
1379683SXin.Chen@Sun.COM gettext("\n\nReading of firmware images from %s-attached "
1389683SXin.Chen@Sun.COM "devices is not supported\n\n"),
1399683SXin.Chen@Sun.COM flashdev->drvname);
1409683SXin.Chen@Sun.COM
1419683SXin.Chen@Sun.COM return (FWFLASH_SUCCESS);
1429683SXin.Chen@Sun.COM }
1439683SXin.Chen@Sun.COM
1449683SXin.Chen@Sun.COM int
fw_writefw(struct devicelist * flashdev)1459683SXin.Chen@Sun.COM fw_writefw(struct devicelist *flashdev)
1469683SXin.Chen@Sun.COM {
1479683SXin.Chen@Sun.COM int rv;
1489683SXin.Chen@Sun.COM int i = 0;
1499683SXin.Chen@Sun.COM libscsi_hdl_t *handle;
1509683SXin.Chen@Sun.COM libscsi_target_t *target;
1519683SXin.Chen@Sun.COM libscsi_action_t *action;
1529683SXin.Chen@Sun.COM libscsi_errno_t serr;
1539683SXin.Chen@Sun.COM spc3_write_buffer_cdb_t *wb_cdb;
1549683SXin.Chen@Sun.COM sam4_status_t samstatus;
1559683SXin.Chen@Sun.COM
1569683SXin.Chen@Sun.COM if ((verifier == NULL) || (verifier->imgsize == 0) ||
1579683SXin.Chen@Sun.COM (verifier->fwimage == NULL)) {
1589683SXin.Chen@Sun.COM /* should _NOT_ happen */
1599683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
1609683SXin.Chen@Sun.COM gettext("%s: Firmware image has not been verified\n"),
1619683SXin.Chen@Sun.COM flashdev->drvname);
1629683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
1639683SXin.Chen@Sun.COM }
1649683SXin.Chen@Sun.COM
1659683SXin.Chen@Sun.COM if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
1669683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"),
1679683SXin.Chen@Sun.COM flashdev->drvname);
1689683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
1699683SXin.Chen@Sun.COM }
1709683SXin.Chen@Sun.COM
1719683SXin.Chen@Sun.COM if ((target = libscsi_open(handle, NULL, flashdev->access_devname))
1729683SXin.Chen@Sun.COM == NULL) {
1739683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
1749683SXin.Chen@Sun.COM gettext("%s: unable to open device %s\n"),
1759683SXin.Chen@Sun.COM flashdev->drvname, flashdev->access_devname);
1769683SXin.Chen@Sun.COM libscsi_fini(handle);
1779683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
1789683SXin.Chen@Sun.COM }
1799683SXin.Chen@Sun.COM
1809683SXin.Chen@Sun.COM action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
1819683SXin.Chen@Sun.COM LIBSCSI_AF_WRITE|LIBSCSI_AF_RQSENSE,
1829683SXin.Chen@Sun.COM (void *)verifier->fwimage, (size_t)verifier->imgsize);
1839683SXin.Chen@Sun.COM
1849683SXin.Chen@Sun.COM wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
1859683SXin.Chen@Sun.COM
1869683SXin.Chen@Sun.COM wb_cdb->wbc_mode = SPC3_WB_MODE_DL_UCODE_SAVE;
1879683SXin.Chen@Sun.COM wb_cdb->wbc_bufferid = verifier->flashbuf;
1889683SXin.Chen@Sun.COM
1899683SXin.Chen@Sun.COM wb_cdb->wbc_buffer_offset[0] = 0;
1909683SXin.Chen@Sun.COM wb_cdb->wbc_buffer_offset[1] = 0;
1919683SXin.Chen@Sun.COM wb_cdb->wbc_buffer_offset[2] = 0;
1929683SXin.Chen@Sun.COM
1939683SXin.Chen@Sun.COM wb_cdb->wbc_parameter_list_len[0] =
1949683SXin.Chen@Sun.COM (verifier->imgsize & 0xff0000) >> 16;
1959683SXin.Chen@Sun.COM wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
1969683SXin.Chen@Sun.COM wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
1979683SXin.Chen@Sun.COM
1989683SXin.Chen@Sun.COM rv = libscsi_exec(action, target);
1999683SXin.Chen@Sun.COM samstatus = libscsi_action_get_status(action);
2009683SXin.Chen@Sun.COM
2019683SXin.Chen@Sun.COM logmsg(MSG_INFO, "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
2029683SXin.Chen@Sun.COM rv, samstatus);
2039683SXin.Chen@Sun.COM
2049683SXin.Chen@Sun.COM libscsi_action_free(action);
2059683SXin.Chen@Sun.COM libscsi_close(handle, target);
2069683SXin.Chen@Sun.COM libscsi_fini(handle);
2079683SXin.Chen@Sun.COM
2089683SXin.Chen@Sun.COM if (rv != FWFLASH_SUCCESS)
2099683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
2109683SXin.Chen@Sun.COM
2119683SXin.Chen@Sun.COM for (i = 0; i < NSAM4_STATUS; i++) {
2129683SXin.Chen@Sun.COM if (sam4_status[i].status == samstatus) {
2139683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("RETURN STATUS: %s\n"),
2149683SXin.Chen@Sun.COM (sam4_status[i].message));
2159683SXin.Chen@Sun.COM break;
2169683SXin.Chen@Sun.COM }
2179683SXin.Chen@Sun.COM }
2189683SXin.Chen@Sun.COM if (i == NSAM4_STATUS)
2199683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("Status UNKNOWN\n"));
2209683SXin.Chen@Sun.COM
2219683SXin.Chen@Sun.COM if (samstatus == SAM4_STATUS_GOOD) {
2229683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("Note: For flash based disks "
2239683SXin.Chen@Sun.COM "(SSD, etc). You may need power off the system to wait a "
2249683SXin.Chen@Sun.COM "few minutes for supercap to fully discharge, then power "
2259683SXin.Chen@Sun.COM "on the system again to activate the new firmware\n"));
2269683SXin.Chen@Sun.COM return (FWFLASH_SUCCESS);
2279683SXin.Chen@Sun.COM }
2289683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
2299683SXin.Chen@Sun.COM }
2309683SXin.Chen@Sun.COM
2319683SXin.Chen@Sun.COM /*
2329683SXin.Chen@Sun.COM * The fw_identify() function walks the device
2339683SXin.Chen@Sun.COM * tree trying to find devices which this plugin
2349683SXin.Chen@Sun.COM * can work with.
2359683SXin.Chen@Sun.COM *
2369683SXin.Chen@Sun.COM * The parameter "start" gives us the starting index number
2379683SXin.Chen@Sun.COM * to give the device when we add it to the fw_devices list.
2389683SXin.Chen@Sun.COM *
2399683SXin.Chen@Sun.COM * firstdev is allocated by us and we add space as needed
2409683SXin.Chen@Sun.COM *
2419683SXin.Chen@Sun.COM * When we store the desired information, inquiry-serial-no
2429683SXin.Chen@Sun.COM * goes in thisdev->addresses[1], and client-guid goes in
2439683SXin.Chen@Sun.COM * thisdev->addresses[2].
2449683SXin.Chen@Sun.COM */
2459683SXin.Chen@Sun.COM int
fw_identify(int start)2469683SXin.Chen@Sun.COM fw_identify(int start)
2479683SXin.Chen@Sun.COM {
2489683SXin.Chen@Sun.COM int idx = start;
2499683SXin.Chen@Sun.COM int fw_sata_disk = 0;
2509683SXin.Chen@Sun.COM int *exists;
2519683SXin.Chen@Sun.COM di_node_t thisnode;
2529683SXin.Chen@Sun.COM struct devicelist *newdev = NULL;
2539683SXin.Chen@Sun.COM char *devpath = NULL;
2549683SXin.Chen@Sun.COM char *driver = NULL;
2559683SXin.Chen@Sun.COM char *sp_temp;
2569683SXin.Chen@Sun.COM char *sp_temp_cut;
2579683SXin.Chen@Sun.COM
2589683SXin.Chen@Sun.COM /* We need to inquiry information manually by sending probe command */
2599683SXin.Chen@Sun.COM libscsi_hdl_t *handle;
2609683SXin.Chen@Sun.COM libscsi_target_t *target;
2619683SXin.Chen@Sun.COM libscsi_errno_t serr;
2629683SXin.Chen@Sun.COM
2639683SXin.Chen@Sun.COM /* Just in case we've got an FC-attached device on sparc */
2649683SXin.Chen@Sun.COM if (strcmp(self->drvname, "ssd") == 0) {
2659683SXin.Chen@Sun.COM driver = self->drvname;
2669683SXin.Chen@Sun.COM } else
2679683SXin.Chen@Sun.COM driver = drivername;
2689683SXin.Chen@Sun.COM
2699683SXin.Chen@Sun.COM thisnode = di_drv_first_node(driver, rootnode);
2709683SXin.Chen@Sun.COM
2719683SXin.Chen@Sun.COM if (thisnode == DI_NODE_NIL) {
2729683SXin.Chen@Sun.COM logmsg(MSG_INFO, "No %s nodes in this system\n", driver);
2739683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
2749683SXin.Chen@Sun.COM }
2759683SXin.Chen@Sun.COM
2769683SXin.Chen@Sun.COM if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
2779683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: failed to initialize "
2789683SXin.Chen@Sun.COM "libscsi\n"), newdev->drvname);
2799683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
2809683SXin.Chen@Sun.COM }
2819683SXin.Chen@Sun.COM
2829683SXin.Chen@Sun.COM /* we've found one, at least */
2839683SXin.Chen@Sun.COM for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
2849974SXin.Chen@Sun.COM /* Need to free by di_devfs_path_free */
2859974SXin.Chen@Sun.COM if ((devpath = di_devfs_path(thisnode)) == NULL) {
2869974SXin.Chen@Sun.COM logmsg(MSG_INFO, "unable to get device path for "
2879974SXin.Chen@Sun.COM "current node with errno %d\n", errno);
2889974SXin.Chen@Sun.COM continue;
289*10869SXin.Chen@Sun.COM }
2909683SXin.Chen@Sun.COM /*
2919683SXin.Chen@Sun.COM * We check if this is removable device, in which case
2929683SXin.Chen@Sun.COM * we really aren't interested, so exit stage left
2939683SXin.Chen@Sun.COM */
2949683SXin.Chen@Sun.COM if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode,
2959683SXin.Chen@Sun.COM "removable-media", &exists) > -1) {
2969683SXin.Chen@Sun.COM logmsg(MSG_INFO,
2979683SXin.Chen@Sun.COM "%s: not interested in removable media device\n"
2989683SXin.Chen@Sun.COM "%s\n", driver, devpath);
2999974SXin.Chen@Sun.COM FW_SD_FREE_DEVPATH(devpath)
3009683SXin.Chen@Sun.COM continue;
3019683SXin.Chen@Sun.COM }
3029683SXin.Chen@Sun.COM
3039683SXin.Chen@Sun.COM if ((newdev = calloc(1, sizeof (struct devicelist)))
3049683SXin.Chen@Sun.COM == NULL) {
3059683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
3069683SXin.Chen@Sun.COM gettext("%s: identification function unable "
3079683SXin.Chen@Sun.COM "to allocate space for device entry\n"),
3089683SXin.Chen@Sun.COM driver);
3099683SXin.Chen@Sun.COM libscsi_fini(handle);
3109683SXin.Chen@Sun.COM FW_SD_FREE_DEVPATH(devpath)
3119683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3129683SXin.Chen@Sun.COM }
3139683SXin.Chen@Sun.COM
3149683SXin.Chen@Sun.COM if ((newdev->drvname = calloc(1, strlen(driver) + 1))
3159683SXin.Chen@Sun.COM == NULL) {
3169683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
3179683SXin.Chen@Sun.COM gettext("%s: Unable to allocate space to store a "
3189683SXin.Chen@Sun.COM "driver name\n"), driver);
3199683SXin.Chen@Sun.COM libscsi_fini(handle);
3209974SXin.Chen@Sun.COM FW_SD_FREE_DEVICELIST(newdev, devpath)
3219683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3229683SXin.Chen@Sun.COM }
3239683SXin.Chen@Sun.COM (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
3249683SXin.Chen@Sun.COM
3259683SXin.Chen@Sun.COM if ((newdev->classname = calloc(1, strlen(driver) + 1))
3269683SXin.Chen@Sun.COM == NULL) {
3279683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
3289683SXin.Chen@Sun.COM gettext("%s: Unable to allocate space for a class "
3299683SXin.Chen@Sun.COM "name\n"), drivername);
3309683SXin.Chen@Sun.COM libscsi_fini(handle);
3319683SXin.Chen@Sun.COM FW_SD_FREE_DRV_NAME(newdev, devpath)
3329683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3339683SXin.Chen@Sun.COM }
3349683SXin.Chen@Sun.COM (void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
3359683SXin.Chen@Sun.COM
3369974SXin.Chen@Sun.COM /* Get the access name for current node */
3379974SXin.Chen@Sun.COM if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
3389974SXin.Chen@Sun.COM logmsg(MSG_ERROR,
3399974SXin.Chen@Sun.COM gettext("%s: Unable to allocate space for a devfs "
3409974SXin.Chen@Sun.COM "name\n"), driver);
3419974SXin.Chen@Sun.COM libscsi_fini(handle);
3429974SXin.Chen@Sun.COM FW_SD_FREE_CLS_NAME(newdev, devpath)
3439974SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3449974SXin.Chen@Sun.COM }
3459974SXin.Chen@Sun.COM
3469974SXin.Chen@Sun.COM /* The slice number may be 2 or 0, we will try 2 first */
3479974SXin.Chen@Sun.COM (void) snprintf(newdev->access_devname, MAXPATHLEN,
3489974SXin.Chen@Sun.COM "%s%s:c,raw", devprefix, devpath);
3499974SXin.Chen@Sun.COM if ((target = libscsi_open(handle, NULL,
3509974SXin.Chen@Sun.COM newdev->access_devname)) == NULL) {
3519974SXin.Chen@Sun.COM /* try 0 for EFI label */
3529974SXin.Chen@Sun.COM (void) snprintf(newdev->access_devname, MAXPATHLEN,
3539974SXin.Chen@Sun.COM "%s%s:a,raw", devprefix, devpath);
3549974SXin.Chen@Sun.COM if ((target = libscsi_open(handle, NULL,
3559974SXin.Chen@Sun.COM newdev->access_devname)) == NULL) {
3569974SXin.Chen@Sun.COM logmsg(MSG_INFO,
3579974SXin.Chen@Sun.COM "%s: unable to open device %s\n",
3589974SXin.Chen@Sun.COM newdev->drvname, newdev->access_devname);
3599974SXin.Chen@Sun.COM FW_SD_FREE_ACC_NAME(newdev, devpath)
3609974SXin.Chen@Sun.COM continue;
3619974SXin.Chen@Sun.COM }
3629974SXin.Chen@Sun.COM }
3639974SXin.Chen@Sun.COM
3649974SXin.Chen@Sun.COM /* and the /dev/rdsk/ name */
3659974SXin.Chen@Sun.COM if ((newdev->addresses[0] = find_link(thisnode,
3669974SXin.Chen@Sun.COM newdev->access_devname)) == NULL) {
3679974SXin.Chen@Sun.COM libscsi_fini(handle);
3689974SXin.Chen@Sun.COM FW_SD_FREE_ACC_NAME(newdev, devpath)
3699974SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3709974SXin.Chen@Sun.COM }
3719974SXin.Chen@Sun.COM
3729683SXin.Chen@Sun.COM /*
3739683SXin.Chen@Sun.COM * Only alloc as much as we truly need, and DON'T forget
3749683SXin.Chen@Sun.COM * that libdevinfo manages the memory!
3759683SXin.Chen@Sun.COM */
3769683SXin.Chen@Sun.COM if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
3779683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
3789683SXin.Chen@Sun.COM gettext("%s: Unable to allocate space for SCSI "
3799683SXin.Chen@Sun.COM "INQUIRY data\n"), driver);
3809683SXin.Chen@Sun.COM libscsi_fini(handle);
3819974SXin.Chen@Sun.COM FW_SD_FREE_ADDR(newdev, devpath)
3829683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
3839683SXin.Chen@Sun.COM }
3849683SXin.Chen@Sun.COM
3859683SXin.Chen@Sun.COM /* We don't use new->ident->encap_ident currently */
3869683SXin.Chen@Sun.COM
3879683SXin.Chen@Sun.COM /* Retrive information by using libscsi */
3889683SXin.Chen@Sun.COM /* Vendor ID */
3899683SXin.Chen@Sun.COM sp_temp = (char *)libscsi_vendor(target);
3909683SXin.Chen@Sun.COM if (strncmp(sp_temp, "ATA", 3) == 0) {
3919683SXin.Chen@Sun.COM /* We need to do customize the output for SATA disks */
3929683SXin.Chen@Sun.COM fw_sata_disk = 1;
3939683SXin.Chen@Sun.COM } else {
3949683SXin.Chen@Sun.COM fw_sata_disk = 0;
3959683SXin.Chen@Sun.COM if ((newdev->ident->vid =
3969683SXin.Chen@Sun.COM calloc(1, strlen(sp_temp) + 1)) == NULL ||
3979683SXin.Chen@Sun.COM sp_temp == NULL) {
3989683SXin.Chen@Sun.COM if (!sp_temp) {
3999683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: unable "
4009683SXin.Chen@Sun.COM "to get vendor id of %s\n"),
4019683SXin.Chen@Sun.COM newdev->drvname,
4029683SXin.Chen@Sun.COM newdev->access_devname);
4039683SXin.Chen@Sun.COM } else {
4049683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("Memory "
4059683SXin.Chen@Sun.COM "allocation failure\n"));
4069683SXin.Chen@Sun.COM }
4079683SXin.Chen@Sun.COM
4089683SXin.Chen@Sun.COM libscsi_close(handle, target);
4099683SXin.Chen@Sun.COM libscsi_fini(handle);
4109683SXin.Chen@Sun.COM FW_SD_FREE_IDENT(newdev, devpath)
4119683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4129683SXin.Chen@Sun.COM }
4139683SXin.Chen@Sun.COM strlcpy(newdev->ident->vid, sp_temp,
4149683SXin.Chen@Sun.COM strlen(sp_temp) + 1);
4159683SXin.Chen@Sun.COM }
4169683SXin.Chen@Sun.COM
4179683SXin.Chen@Sun.COM /* Product ID */
4189683SXin.Chen@Sun.COM sp_temp = (char *)libscsi_product(target);
4199683SXin.Chen@Sun.COM if (fw_sata_disk) {
4209683SXin.Chen@Sun.COM sp_temp_cut = strchr(sp_temp, ' ');
4219683SXin.Chen@Sun.COM if (!sp_temp_cut) {
4229974SXin.Chen@Sun.COM /*
4239974SXin.Chen@Sun.COM * There is no SPACE character in the PID field
4249974SXin.Chen@Sun.COM * Customize strings for special SATA disks
4259974SXin.Chen@Sun.COM */
4269683SXin.Chen@Sun.COM if (sd_idtfy_custmz(newdev, sp_temp)
4279683SXin.Chen@Sun.COM != FWFLASH_SUCCESS) {
4289683SXin.Chen@Sun.COM libscsi_close(handle, target);
4299683SXin.Chen@Sun.COM libscsi_fini(handle);
4309683SXin.Chen@Sun.COM FW_SD_FREE_IDENT(newdev, devpath)
4319683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4329683SXin.Chen@Sun.COM }
4339683SXin.Chen@Sun.COM } else {
4349683SXin.Chen@Sun.COM /* The first string is vendor id */
4359683SXin.Chen@Sun.COM if ((newdev->ident->vid = calloc(1,
4369683SXin.Chen@Sun.COM (sp_temp_cut - sp_temp + 1))) == NULL) {
4379683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: unable "
4389683SXin.Chen@Sun.COM "to get sata vendor id of %s\n"),
4399683SXin.Chen@Sun.COM newdev->drvname,
4409683SXin.Chen@Sun.COM newdev->access_devname);
4419683SXin.Chen@Sun.COM
4429683SXin.Chen@Sun.COM libscsi_close(handle, target);
4439683SXin.Chen@Sun.COM libscsi_fini(handle);
4449683SXin.Chen@Sun.COM FW_SD_FREE_IDENT(newdev, devpath)
4459683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4469683SXin.Chen@Sun.COM }
4479683SXin.Chen@Sun.COM strlcpy(newdev->ident->vid, sp_temp,
4489683SXin.Chen@Sun.COM sp_temp_cut - sp_temp + 1);
4499683SXin.Chen@Sun.COM
4509683SXin.Chen@Sun.COM /* The second string is product id */
4519683SXin.Chen@Sun.COM if ((newdev->ident->pid =
4529683SXin.Chen@Sun.COM calloc(1, strlen(sp_temp) -
4539683SXin.Chen@Sun.COM strlen(newdev->ident->vid))) == NULL) {
4549683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: unable "
4559683SXin.Chen@Sun.COM "to get sata product id of %s\n"),
4569683SXin.Chen@Sun.COM newdev->drvname,
4579683SXin.Chen@Sun.COM newdev->access_devname);
4589683SXin.Chen@Sun.COM
4599683SXin.Chen@Sun.COM libscsi_close(handle, target);
4609683SXin.Chen@Sun.COM libscsi_fini(handle);
4619683SXin.Chen@Sun.COM FW_SD_FREE_IDENT_VID(newdev, devpath)
4629683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4639683SXin.Chen@Sun.COM }
4649683SXin.Chen@Sun.COM strlcpy(newdev->ident->pid, sp_temp_cut + 1,
4659683SXin.Chen@Sun.COM strlen(sp_temp) -
4669683SXin.Chen@Sun.COM strlen(newdev->ident->vid));
4679683SXin.Chen@Sun.COM }
4689683SXin.Chen@Sun.COM } else {
4699683SXin.Chen@Sun.COM if ((newdev->ident->pid =
4709683SXin.Chen@Sun.COM calloc(1, strlen(sp_temp) + 1)) == NULL ||
4719683SXin.Chen@Sun.COM sp_temp == NULL) {
4729683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: unable to get "
4739683SXin.Chen@Sun.COM "product id of %s\n"), newdev->drvname,
4749683SXin.Chen@Sun.COM newdev->access_devname);
4759683SXin.Chen@Sun.COM FW_SD_FREE_IDENT_VID(newdev, devpath)
4769683SXin.Chen@Sun.COM libscsi_close(handle, target);
4779683SXin.Chen@Sun.COM libscsi_fini(handle);
4789683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4799683SXin.Chen@Sun.COM }
4809683SXin.Chen@Sun.COM strlcpy(newdev->ident->pid, sp_temp,
4819683SXin.Chen@Sun.COM strlen(sp_temp) + 1);
4829683SXin.Chen@Sun.COM }
4839683SXin.Chen@Sun.COM
4849683SXin.Chen@Sun.COM /* Revision ID */
4859683SXin.Chen@Sun.COM sp_temp = (char *)libscsi_revision(target);
4869683SXin.Chen@Sun.COM if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1))
4879683SXin.Chen@Sun.COM == NULL || sp_temp == NULL) {
4889683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("%s: unable to get revision "
4899683SXin.Chen@Sun.COM "id of %s\n"), newdev->drvname,
4909683SXin.Chen@Sun.COM newdev->access_devname);
4919683SXin.Chen@Sun.COM libscsi_close(handle, target);
4929683SXin.Chen@Sun.COM libscsi_fini(handle);
4939683SXin.Chen@Sun.COM FW_SD_FREE_IDENT_PID(newdev, devpath)
4949683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
4959683SXin.Chen@Sun.COM }
4969683SXin.Chen@Sun.COM strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1);
4979683SXin.Chen@Sun.COM
4989683SXin.Chen@Sun.COM /* Finish using libscsi */
4999683SXin.Chen@Sun.COM libscsi_close(handle, target);
5009683SXin.Chen@Sun.COM
5019683SXin.Chen@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
5029683SXin.Chen@Sun.COM "inquiry-serial-no", &newdev->addresses[1]) < 0) {
5039683SXin.Chen@Sun.COM logmsg(MSG_INFO,
5049683SXin.Chen@Sun.COM "%s: no inquiry-serial-no property for %s\n",
5059683SXin.Chen@Sun.COM driver, newdev->access_devname);
5069683SXin.Chen@Sun.COM logmsg(MSG_INFO, "The errno is %d\n", errno);
5079683SXin.Chen@Sun.COM }
5089683SXin.Chen@Sun.COM
5099683SXin.Chen@Sun.COM if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
5109683SXin.Chen@Sun.COM "client-guid", &newdev->addresses[2])) < 0) {
5119683SXin.Chen@Sun.COM logmsg(MSG_INFO,
5129683SXin.Chen@Sun.COM "%s: no client-guid property "
5139683SXin.Chen@Sun.COM "for device %s\n",
5149683SXin.Chen@Sun.COM driver, newdev->access_devname);
5159683SXin.Chen@Sun.COM /* try fallback */
5169683SXin.Chen@Sun.COM if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
5179683SXin.Chen@Sun.COM "guid", &newdev->addresses[2])) < 0) {
5189683SXin.Chen@Sun.COM logmsg(MSG_INFO,
5199683SXin.Chen@Sun.COM "%s: no guid property for device %s\n",
5209683SXin.Chen@Sun.COM driver, newdev->access_devname);
5219683SXin.Chen@Sun.COM }
5229683SXin.Chen@Sun.COM } else {
5239683SXin.Chen@Sun.COM logmsg(MSG_INFO,
5249683SXin.Chen@Sun.COM "client-guid property: %s\n",
5259683SXin.Chen@Sun.COM newdev->addresses[2]);
5269683SXin.Chen@Sun.COM }
5279683SXin.Chen@Sun.COM
5289683SXin.Chen@Sun.COM newdev->index = idx;
5299683SXin.Chen@Sun.COM ++idx;
5309683SXin.Chen@Sun.COM newdev->plugin = self;
5319683SXin.Chen@Sun.COM
5329683SXin.Chen@Sun.COM TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
5339974SXin.Chen@Sun.COM FW_SD_FREE_DEVPATH(devpath)
5349683SXin.Chen@Sun.COM }
5359683SXin.Chen@Sun.COM libscsi_fini(handle);
5369683SXin.Chen@Sun.COM
5379683SXin.Chen@Sun.COM /* Check if sd targets presented are all unflashable. */
5389683SXin.Chen@Sun.COM if (idx == start)
5399683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
5409683SXin.Chen@Sun.COM
5419683SXin.Chen@Sun.COM if (fwflash_debug != 0) {
5429683SXin.Chen@Sun.COM struct devicelist *tempdev;
5439683SXin.Chen@Sun.COM
5449683SXin.Chen@Sun.COM TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
5459683SXin.Chen@Sun.COM logmsg(MSG_INFO, "%s:fw_identify:\n",
5469683SXin.Chen@Sun.COM driver);
5479683SXin.Chen@Sun.COM logmsg(MSG_INFO,
5489683SXin.Chen@Sun.COM "\ttempdev @ 0x%lx\n"
5499683SXin.Chen@Sun.COM "\t\taccess_devname: %s\n"
5509683SXin.Chen@Sun.COM "\t\tdrvname: %s\tclassname: %s\n"
5519683SXin.Chen@Sun.COM "\t\tident->vid: %s\n"
5529683SXin.Chen@Sun.COM "\t\tident->pid: %s\n"
5539683SXin.Chen@Sun.COM "\t\tident->revid: %s\n"
5549683SXin.Chen@Sun.COM "\t\tindex: %d\n"
5559683SXin.Chen@Sun.COM "\t\taddress[0]: %s\n"
5569683SXin.Chen@Sun.COM "\t\taddress[1]: %s\n"
5579683SXin.Chen@Sun.COM "\t\taddress[2]: %s\n"
5589683SXin.Chen@Sun.COM "\t\tplugin @ 0x%lx\n\n",
5599683SXin.Chen@Sun.COM &tempdev,
5609683SXin.Chen@Sun.COM tempdev->access_devname,
5619683SXin.Chen@Sun.COM tempdev->drvname, newdev->classname,
5629683SXin.Chen@Sun.COM tempdev->ident->vid,
5639683SXin.Chen@Sun.COM tempdev->ident->pid,
5649683SXin.Chen@Sun.COM tempdev->ident->revid,
5659683SXin.Chen@Sun.COM tempdev->index,
5669683SXin.Chen@Sun.COM tempdev->addresses[0],
5679683SXin.Chen@Sun.COM (tempdev->addresses[1] ? tempdev->addresses[1] :
5689683SXin.Chen@Sun.COM "(not supported)"),
5699683SXin.Chen@Sun.COM (tempdev->addresses[2] ? tempdev->addresses[2] :
5709683SXin.Chen@Sun.COM "(not supported)"),
5719683SXin.Chen@Sun.COM &tempdev->plugin);
5729683SXin.Chen@Sun.COM }
5739683SXin.Chen@Sun.COM }
5749683SXin.Chen@Sun.COM return (FWFLASH_SUCCESS);
5759683SXin.Chen@Sun.COM }
5769683SXin.Chen@Sun.COM
5779683SXin.Chen@Sun.COM int
fw_devinfo(struct devicelist * thisdev)5789683SXin.Chen@Sun.COM fw_devinfo(struct devicelist *thisdev)
5799683SXin.Chen@Sun.COM {
5809683SXin.Chen@Sun.COM fprintf(stdout, gettext("Device[%d]\t\t\t%s\n"
5819683SXin.Chen@Sun.COM " Class [%s]\t\t\t%s\n"),
5829683SXin.Chen@Sun.COM thisdev->index, thisdev->access_devname,
5839683SXin.Chen@Sun.COM thisdev->classname, thisdev->addresses[0]);
5849683SXin.Chen@Sun.COM
5859683SXin.Chen@Sun.COM fprintf(stdout,
5869683SXin.Chen@Sun.COM gettext(
5879683SXin.Chen@Sun.COM "\tVendor\t\t\t: %s\n"
5889683SXin.Chen@Sun.COM "\tProduct\t\t\t: %s\n"
5899683SXin.Chen@Sun.COM "\tFirmware revision\t: %-s\n"
5909683SXin.Chen@Sun.COM "\tInquiry Serial Number : %-s\n"
5919683SXin.Chen@Sun.COM "\tGUID\t\t\t: %s\n"),
5929683SXin.Chen@Sun.COM thisdev->ident->vid,
5939683SXin.Chen@Sun.COM thisdev->ident->pid,
5949683SXin.Chen@Sun.COM thisdev->ident->revid,
5959683SXin.Chen@Sun.COM (thisdev->addresses[1] ? thisdev->addresses[1] :
5969683SXin.Chen@Sun.COM "(not supported)"),
5979683SXin.Chen@Sun.COM (thisdev->addresses[2] ? thisdev->addresses[2] :
5989683SXin.Chen@Sun.COM "(not supported)"));
5999683SXin.Chen@Sun.COM
6009683SXin.Chen@Sun.COM fprintf(stdout, "\n\n");
6019683SXin.Chen@Sun.COM
6029683SXin.Chen@Sun.COM return (FWFLASH_SUCCESS);
6039683SXin.Chen@Sun.COM }
6049683SXin.Chen@Sun.COM
6059683SXin.Chen@Sun.COM void
fw_cleanup(struct devicelist * thisdev)6069683SXin.Chen@Sun.COM fw_cleanup(struct devicelist *thisdev)
6079683SXin.Chen@Sun.COM {
6089683SXin.Chen@Sun.COM /*
6099683SXin.Chen@Sun.COM * Function to clean up all the memory allocated
6109683SXin.Chen@Sun.COM * by this plugin, for thisdev.
6119683SXin.Chen@Sun.COM */
6129683SXin.Chen@Sun.COM free(thisdev->access_devname);
6139683SXin.Chen@Sun.COM free(thisdev->drvname);
6149683SXin.Chen@Sun.COM free(thisdev->classname);
6159683SXin.Chen@Sun.COM
6169683SXin.Chen@Sun.COM /*
6179683SXin.Chen@Sun.COM * Note that we DO NOT free addresses[1,2] because _IF_
6189683SXin.Chen@Sun.COM * these elements are valid, they are managed by libdevinfo
6199683SXin.Chen@Sun.COM * and we didn't allocate any space for them.
6209683SXin.Chen@Sun.COM */
6219683SXin.Chen@Sun.COM free(thisdev->addresses[0]);
6229683SXin.Chen@Sun.COM
6239683SXin.Chen@Sun.COM /* what this points to is freed in common code */
6249683SXin.Chen@Sun.COM thisdev->plugin = NULL;
6259683SXin.Chen@Sun.COM
6269683SXin.Chen@Sun.COM free(thisdev->ident->vid);
6279683SXin.Chen@Sun.COM free(thisdev->ident->pid);
6289683SXin.Chen@Sun.COM free(thisdev->ident->revid);
6299683SXin.Chen@Sun.COM
6309683SXin.Chen@Sun.COM thisdev->ident = NULL;
6319683SXin.Chen@Sun.COM }
6329683SXin.Chen@Sun.COM
6339683SXin.Chen@Sun.COM /*
6349683SXin.Chen@Sun.COM * Helper functions
6359683SXin.Chen@Sun.COM */
6369683SXin.Chen@Sun.COM static int
link_cb(di_devlink_t devlink,void * arg)6379683SXin.Chen@Sun.COM link_cb(di_devlink_t devlink, void *arg)
6389683SXin.Chen@Sun.COM {
6399683SXin.Chen@Sun.COM const char *result;
6409683SXin.Chen@Sun.COM
6419683SXin.Chen@Sun.COM result = di_devlink_path(devlink);
6429683SXin.Chen@Sun.COM if (result == NULL) {
6439683SXin.Chen@Sun.COM arg = (void *)"(null)";
6449683SXin.Chen@Sun.COM } else {
6459683SXin.Chen@Sun.COM (void) strlcpy(arg, result, strlen(result) + 1);
6469683SXin.Chen@Sun.COM }
6479683SXin.Chen@Sun.COM
6489683SXin.Chen@Sun.COM logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
6499683SXin.Chen@Sun.COM ((result != NULL) ? result : "(null)"));
6509683SXin.Chen@Sun.COM
6519683SXin.Chen@Sun.COM return (DI_WALK_CONTINUE);
6529683SXin.Chen@Sun.COM }
6539683SXin.Chen@Sun.COM
6549683SXin.Chen@Sun.COM static char *
find_link(di_node_t bnode,char * acc_devname)6559974SXin.Chen@Sun.COM find_link(di_node_t bnode, char *acc_devname)
6569683SXin.Chen@Sun.COM {
6579683SXin.Chen@Sun.COM di_minor_t devminor = DI_MINOR_NIL;
6589974SXin.Chen@Sun.COM di_devlink_handle_t hdl;
6599683SXin.Chen@Sun.COM char *cbresult = NULL;
6609683SXin.Chen@Sun.COM char linkname[] = "^rdsk/\0";
6619683SXin.Chen@Sun.COM
6629683SXin.Chen@Sun.COM if (bnode == DI_NODE_NIL) {
6639683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
6649683SXin.Chen@Sun.COM gettext("find_link must be called with non-null "
6659683SXin.Chen@Sun.COM "di_node_t\n"));
6669683SXin.Chen@Sun.COM return (NULL);
6679683SXin.Chen@Sun.COM }
6689683SXin.Chen@Sun.COM
6699974SXin.Chen@Sun.COM if ((cbresult = calloc(1, MAXPATHLEN)) == NULL) {
6709683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
6719683SXin.Chen@Sun.COM "link\n"));
6729683SXin.Chen@Sun.COM return (NULL);
6739683SXin.Chen@Sun.COM }
6749683SXin.Chen@Sun.COM
6759683SXin.Chen@Sun.COM devminor = di_minor_next(bnode, devminor);
6769683SXin.Chen@Sun.COM errno = 0;
6779683SXin.Chen@Sun.COM hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
6789683SXin.Chen@Sun.COM if (hdl == NULL) {
6799683SXin.Chen@Sun.COM if (errno == EPERM || errno == EACCES) {
6809683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
6819683SXin.Chen@Sun.COM gettext("%s: You must be super-user to use this "
6829683SXin.Chen@Sun.COM "plugin.\n"), drivername);
6839683SXin.Chen@Sun.COM } else {
6849683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
6859683SXin.Chen@Sun.COM gettext("unable to take devlink snapshot: %s\n"),
6869683SXin.Chen@Sun.COM strerror(errno));
6879683SXin.Chen@Sun.COM }
6889974SXin.Chen@Sun.COM free(cbresult);
6899683SXin.Chen@Sun.COM return (NULL);
6909683SXin.Chen@Sun.COM }
6919683SXin.Chen@Sun.COM
6929683SXin.Chen@Sun.COM errno = 0;
6939974SXin.Chen@Sun.COM if (di_devlink_walk(hdl, linkname, acc_devname + strlen(devprefix),
6949974SXin.Chen@Sun.COM DI_PRIMARY_LINK, (void *)cbresult, link_cb) < 0) {
6959683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
6969683SXin.Chen@Sun.COM gettext("Unable to walk devlink snapshot for %s: %s\n"),
6979974SXin.Chen@Sun.COM acc_devname, strerror(errno));
6989974SXin.Chen@Sun.COM free(cbresult);
6999683SXin.Chen@Sun.COM return (NULL);
7009683SXin.Chen@Sun.COM }
7019683SXin.Chen@Sun.COM
7029683SXin.Chen@Sun.COM if (di_devlink_fini(&hdl) < 0) {
7039683SXin.Chen@Sun.COM logmsg(MSG_ERROR,
7049683SXin.Chen@Sun.COM gettext("Unable to close devlink snapshot: %s\n"),
7059683SXin.Chen@Sun.COM strerror(errno));
7069683SXin.Chen@Sun.COM }
7079683SXin.Chen@Sun.COM
7089683SXin.Chen@Sun.COM logmsg(MSG_INFO, "cbresult: %s\n", cbresult);
7099683SXin.Chen@Sun.COM return (cbresult);
7109683SXin.Chen@Sun.COM }
7119683SXin.Chen@Sun.COM
7129683SXin.Chen@Sun.COM static int
sd_idtfy_custmz(struct devicelist * device,char * sp)7139683SXin.Chen@Sun.COM sd_idtfy_custmz(struct devicelist *device, char *sp)
7149683SXin.Chen@Sun.COM {
7159683SXin.Chen@Sun.COM /* vid customization */
7169683SXin.Chen@Sun.COM if (strncmp(sp, "ST", 2) == 0) {
7179683SXin.Chen@Sun.COM /* Customize retail Seagate disks */
7189683SXin.Chen@Sun.COM if ((device->ident->vid = strdup("SEAGATE")) == NULL) {
7199683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
7209683SXin.Chen@Sun.COM }
7219683SXin.Chen@Sun.COM } else if (strncmp(sp, "SSD", 3) == 0) {
7229683SXin.Chen@Sun.COM /* Customize retail INTEL disks */
7239683SXin.Chen@Sun.COM if ((device->ident->vid = strdup("INTEL")) == NULL) {
7249683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
7259683SXin.Chen@Sun.COM }
7269683SXin.Chen@Sun.COM } else {
7279683SXin.Chen@Sun.COM /* disks to do in the furture, fill 'ATA' first */
7289683SXin.Chen@Sun.COM if ((device->ident->vid = strdup("ATA")) == NULL) {
7299683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
7309683SXin.Chen@Sun.COM }
7319683SXin.Chen@Sun.COM }
7329683SXin.Chen@Sun.COM
7339683SXin.Chen@Sun.COM /* pid customization */
7349683SXin.Chen@Sun.COM if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) {
7359683SXin.Chen@Sun.COM logmsg(MSG_ERROR, gettext("Unable to allocate space for "
7369683SXin.Chen@Sun.COM "product id\n"));
7379683SXin.Chen@Sun.COM free(device->ident->vid);
7389683SXin.Chen@Sun.COM return (FWFLASH_FAILURE);
7399683SXin.Chen@Sun.COM }
7409683SXin.Chen@Sun.COM strlcpy(device->ident->pid, sp, strlen(sp) + 1);
7419683SXin.Chen@Sun.COM
7429683SXin.Chen@Sun.COM return (FWFLASH_SUCCESS);
7439683SXin.Chen@Sun.COM }
744