1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte #include <stdio.h> 29*fcf3ce44SJohn Forte #include <unistd.h> 30*fcf3ce44SJohn Forte #include <stdlib.h> 31*fcf3ce44SJohn Forte #include <sys/param.h> 32*fcf3ce44SJohn Forte #include <sys/types.h> 33*fcf3ce44SJohn Forte #include <fcntl.h> 34*fcf3ce44SJohn Forte #include <sys/stat.h> 35*fcf3ce44SJohn Forte #include <string.h> 36*fcf3ce44SJohn Forte #include <strings.h> 37*fcf3ce44SJohn Forte #include <ctype.h> 38*fcf3ce44SJohn Forte #include <errno.h> 39*fcf3ce44SJohn Forte #include <assert.h> 40*fcf3ce44SJohn Forte #include <sys/scsi/impl/uscsi.h> 41*fcf3ce44SJohn Forte #include <sys/scsi/generic/commands.h> 42*fcf3ce44SJohn Forte #include <sys/scsi/impl/commands.h> 43*fcf3ce44SJohn Forte #include <sys/scsi/generic/sense.h> 44*fcf3ce44SJohn Forte #include <sys/scsi/generic/mode.h> 45*fcf3ce44SJohn Forte #include <sys/scsi/generic/status.h> 46*fcf3ce44SJohn Forte #include <sys/scsi/generic/inquiry.h> 47*fcf3ce44SJohn Forte #include <sys/scsi/adapters/scsi_vhci.h> 48*fcf3ce44SJohn Forte #include <sys/byteorder.h> 49*fcf3ce44SJohn Forte #include "common.h" 50*fcf3ce44SJohn Forte #include "errorcodes.h" 51*fcf3ce44SJohn Forte 52*fcf3ce44SJohn Forte #define MAX_MODE_SENSE_LEN 0xffff 53*fcf3ce44SJohn Forte #define MAXLEN 1000 54*fcf3ce44SJohn Forte 55*fcf3ce44SJohn Forte #define RETRY_PATHLIST 1 56*fcf3ce44SJohn Forte #define BYTES_PER_LINE 16 57*fcf3ce44SJohn Forte #define SCMD_UNKNOWN 0xff 58*fcf3ce44SJohn Forte 59*fcf3ce44SJohn Forte #define SCSI_VHCI "/devices/scsi_vhci/" 60*fcf3ce44SJohn Forte #define SLASH "/" 61*fcf3ce44SJohn Forte #define DEV_PREFIX "/devices/" 62*fcf3ce44SJohn Forte #define DEV_PREFIX_STRLEN strlen(DEV_PREFIX) 63*fcf3ce44SJohn Forte #define DEVICES_DIR "/devices" 64*fcf3ce44SJohn Forte 65*fcf3ce44SJohn Forte extern char *dtype[]; /* from adm.c */ 66*fcf3ce44SJohn Forte extern int rand_r(unsigned int *); 67*fcf3ce44SJohn Forte 68*fcf3ce44SJohn Forte static int cleanup_dotdot_path(char *path); 69*fcf3ce44SJohn Forte static int wait_random_time(void); 70*fcf3ce44SJohn Forte static char *scsi_find_command_name(int cmd); 71*fcf3ce44SJohn Forte static void scsi_printerr(struct uscsi_cmd *ucmd, 72*fcf3ce44SJohn Forte struct scsi_extended_sense *rq, int rqlen, 73*fcf3ce44SJohn Forte char msg_string[], char *err_string); 74*fcf3ce44SJohn Forte static void string_dump(char *hdr, uchar_t *src, int nbytes, int format, 75*fcf3ce44SJohn Forte char msg_string[]); 76*fcf3ce44SJohn Forte static int issue_uscsi_cmd(int file, struct uscsi_cmd *command, int flag); 77*fcf3ce44SJohn Forte 78*fcf3ce44SJohn Forte 79*fcf3ce44SJohn Forte static int 80*fcf3ce44SJohn Forte wait_random_time(void) 81*fcf3ce44SJohn Forte { 82*fcf3ce44SJohn Forte time_t timeval; 83*fcf3ce44SJohn Forte struct tm *tmbuf = NULL; 84*fcf3ce44SJohn Forte struct timeval tval; 85*fcf3ce44SJohn Forte unsigned int seed; 86*fcf3ce44SJohn Forte int random; 87*fcf3ce44SJohn Forte pid_t pid; 88*fcf3ce44SJohn Forte 89*fcf3ce44SJohn Forte 90*fcf3ce44SJohn Forte /* 91*fcf3ce44SJohn Forte * Get the system time and use "system seconds" 92*fcf3ce44SJohn Forte * as 'seed' to generate a random number. Then, 93*fcf3ce44SJohn Forte * wait between 1/10 - 1/2 seconds before retry. 94*fcf3ce44SJohn Forte * Get the current process id and ex-or it with 95*fcf3ce44SJohn Forte * the seed so that the random number is always 96*fcf3ce44SJohn Forte * different even in case of multiple processes 97*fcf3ce44SJohn Forte * generate a random number at the same time. 98*fcf3ce44SJohn Forte */ 99*fcf3ce44SJohn Forte if ((timeval = time(NULL)) == -1) { 100*fcf3ce44SJohn Forte return (errno); 101*fcf3ce44SJohn Forte } 102*fcf3ce44SJohn Forte if ((tmbuf = localtime(&timeval)) == NULL) { 103*fcf3ce44SJohn Forte return (-1); /* L_LOCALTIME_ERROR */ 104*fcf3ce44SJohn Forte } 105*fcf3ce44SJohn Forte 106*fcf3ce44SJohn Forte pid = getpid(); 107*fcf3ce44SJohn Forte 108*fcf3ce44SJohn Forte /* get a random number. */ 109*fcf3ce44SJohn Forte seed = (unsigned int) tmbuf->tm_sec; 110*fcf3ce44SJohn Forte seed ^= pid; 111*fcf3ce44SJohn Forte random = rand_r(&seed); 112*fcf3ce44SJohn Forte 113*fcf3ce44SJohn Forte 114*fcf3ce44SJohn Forte random = ((random % 500) + 100) * MILLISEC; 115*fcf3ce44SJohn Forte tval.tv_sec = random / MICROSEC; 116*fcf3ce44SJohn Forte tval.tv_usec = random % MICROSEC; 117*fcf3ce44SJohn Forte 118*fcf3ce44SJohn Forte if (select(0, NULL, NULL, NULL, &tval) == -1) { 119*fcf3ce44SJohn Forte return (-1); /* L_SELECT_ERROR */ 120*fcf3ce44SJohn Forte } 121*fcf3ce44SJohn Forte return (0); 122*fcf3ce44SJohn Forte } 123*fcf3ce44SJohn Forte 124*fcf3ce44SJohn Forte /* 125*fcf3ce44SJohn Forte * Special string dump for error message 126*fcf3ce44SJohn Forte */ 127*fcf3ce44SJohn Forte static void 128*fcf3ce44SJohn Forte string_dump(char *hdr, uchar_t *src, int nbytes, int format, char msg_string[]) 129*fcf3ce44SJohn Forte { 130*fcf3ce44SJohn Forte int i; 131*fcf3ce44SJohn Forte int n; 132*fcf3ce44SJohn Forte char *p; 133*fcf3ce44SJohn Forte char s[256]; 134*fcf3ce44SJohn Forte 135*fcf3ce44SJohn Forte assert(format == HEX_ONLY || format == HEX_ASCII); 136*fcf3ce44SJohn Forte 137*fcf3ce44SJohn Forte (void) strcpy(s, hdr); 138*fcf3ce44SJohn Forte for (p = s; *p; p++) { 139*fcf3ce44SJohn Forte *p = ' '; 140*fcf3ce44SJohn Forte } 141*fcf3ce44SJohn Forte 142*fcf3ce44SJohn Forte p = hdr; 143*fcf3ce44SJohn Forte while (nbytes > 0) { 144*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 145*fcf3ce44SJohn Forte "%s", p); 146*fcf3ce44SJohn Forte p = s; 147*fcf3ce44SJohn Forte n = MIN(nbytes, BYTES_PER_LINE); 148*fcf3ce44SJohn Forte for (i = 0; i < n; i++) { 149*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 150*fcf3ce44SJohn Forte "%02x ", 151*fcf3ce44SJohn Forte src[i] & 0xff); 152*fcf3ce44SJohn Forte } 153*fcf3ce44SJohn Forte if (format == HEX_ASCII) { 154*fcf3ce44SJohn Forte for (i = BYTES_PER_LINE-n; i > 0; i--) { 155*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 156*fcf3ce44SJohn Forte " "); 157*fcf3ce44SJohn Forte } 158*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 159*fcf3ce44SJohn Forte " "); 160*fcf3ce44SJohn Forte for (i = 0; i < n; i++) { 161*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 162*fcf3ce44SJohn Forte "%c", 163*fcf3ce44SJohn Forte isprint(src[i]) ? src[i] : '.'); 164*fcf3ce44SJohn Forte } 165*fcf3ce44SJohn Forte } 166*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], "\n"); 167*fcf3ce44SJohn Forte nbytes -= n; 168*fcf3ce44SJohn Forte src += n; 169*fcf3ce44SJohn Forte } 170*fcf3ce44SJohn Forte } 171*fcf3ce44SJohn Forte /* 172*fcf3ce44SJohn Forte * Return a pointer to a string telling us the name of the command. 173*fcf3ce44SJohn Forte */ 174*fcf3ce44SJohn Forte static char * 175*fcf3ce44SJohn Forte scsi_find_command_name(int cmd) 176*fcf3ce44SJohn Forte { 177*fcf3ce44SJohn Forte /* 178*fcf3ce44SJohn Forte * Names of commands. Must have SCMD_UNKNOWN at end of list. 179*fcf3ce44SJohn Forte */ 180*fcf3ce44SJohn Forte struct scsi_command_name { 181*fcf3ce44SJohn Forte int command; 182*fcf3ce44SJohn Forte char *name; 183*fcf3ce44SJohn Forte } scsi_command_names[29]; 184*fcf3ce44SJohn Forte 185*fcf3ce44SJohn Forte register struct scsi_command_name *c; 186*fcf3ce44SJohn Forte 187*fcf3ce44SJohn Forte scsi_command_names[0].command = SCMD_TEST_UNIT_READY; 188*fcf3ce44SJohn Forte scsi_command_names[0].name = MSGSTR(61, "Test Unit Ready"); 189*fcf3ce44SJohn Forte 190*fcf3ce44SJohn Forte scsi_command_names[1].command = SCMD_FORMAT; 191*fcf3ce44SJohn Forte scsi_command_names[1].name = MSGSTR(110, "Format"); 192*fcf3ce44SJohn Forte 193*fcf3ce44SJohn Forte scsi_command_names[2].command = SCMD_REASSIGN_BLOCK; 194*fcf3ce44SJohn Forte scsi_command_names[2].name = MSGSTR(77, "Reassign Block"); 195*fcf3ce44SJohn Forte 196*fcf3ce44SJohn Forte scsi_command_names[3].command = SCMD_READ; 197*fcf3ce44SJohn Forte scsi_command_names[3].name = MSGSTR(27, "Read"); 198*fcf3ce44SJohn Forte 199*fcf3ce44SJohn Forte scsi_command_names[4].command = SCMD_WRITE; 200*fcf3ce44SJohn Forte scsi_command_names[4].name = MSGSTR(54, "Write"); 201*fcf3ce44SJohn Forte 202*fcf3ce44SJohn Forte scsi_command_names[5].command = SCMD_READ_G1; 203*fcf3ce44SJohn Forte scsi_command_names[5].name = MSGSTR(79, "Read(10 Byte)"); 204*fcf3ce44SJohn Forte 205*fcf3ce44SJohn Forte scsi_command_names[6].command = SCMD_WRITE_G1; 206*fcf3ce44SJohn Forte scsi_command_names[6].name = MSGSTR(51, "Write(10 Byte)"); 207*fcf3ce44SJohn Forte 208*fcf3ce44SJohn Forte scsi_command_names[7].command = SCMD_MODE_SELECT; 209*fcf3ce44SJohn Forte scsi_command_names[7].name = MSGSTR(97, "Mode Select"); 210*fcf3ce44SJohn Forte 211*fcf3ce44SJohn Forte scsi_command_names[8].command = SCMD_MODE_SENSE; 212*fcf3ce44SJohn Forte scsi_command_names[8].name = MSGSTR(95, "Mode Sense"); 213*fcf3ce44SJohn Forte 214*fcf3ce44SJohn Forte scsi_command_names[9].command = SCMD_REASSIGN_BLOCK; 215*fcf3ce44SJohn Forte scsi_command_names[9].name = MSGSTR(77, "Reassign Block"); 216*fcf3ce44SJohn Forte 217*fcf3ce44SJohn Forte scsi_command_names[10].command = SCMD_REQUEST_SENSE; 218*fcf3ce44SJohn Forte scsi_command_names[10].name = MSGSTR(74, "Request Sense"); 219*fcf3ce44SJohn Forte 220*fcf3ce44SJohn Forte scsi_command_names[11].command = SCMD_READ_DEFECT_LIST; 221*fcf3ce44SJohn Forte scsi_command_names[11].name = MSGSTR(80, "Read Defect List"); 222*fcf3ce44SJohn Forte 223*fcf3ce44SJohn Forte scsi_command_names[12].command = SCMD_INQUIRY; 224*fcf3ce44SJohn Forte scsi_command_names[12].name = MSGSTR(102, "Inquiry"); 225*fcf3ce44SJohn Forte 226*fcf3ce44SJohn Forte scsi_command_names[13].command = SCMD_WRITE_BUFFER; 227*fcf3ce44SJohn Forte scsi_command_names[13].name = MSGSTR(53, "Write Buffer"); 228*fcf3ce44SJohn Forte 229*fcf3ce44SJohn Forte scsi_command_names[14].command = SCMD_READ_BUFFER; 230*fcf3ce44SJohn Forte scsi_command_names[14].name = MSGSTR(82, "Read Buffer"); 231*fcf3ce44SJohn Forte 232*fcf3ce44SJohn Forte scsi_command_names[15].command = SCMD_START_STOP; 233*fcf3ce44SJohn Forte scsi_command_names[15].name = MSGSTR(67, "Start/Stop"); 234*fcf3ce44SJohn Forte 235*fcf3ce44SJohn Forte scsi_command_names[16].command = SCMD_RESERVE; 236*fcf3ce44SJohn Forte scsi_command_names[16].name = MSGSTR(72, "Reserve"); 237*fcf3ce44SJohn Forte 238*fcf3ce44SJohn Forte scsi_command_names[17].command = SCMD_RELEASE; 239*fcf3ce44SJohn Forte scsi_command_names[17].name = MSGSTR(75, "Release"); 240*fcf3ce44SJohn Forte 241*fcf3ce44SJohn Forte scsi_command_names[18].command = SCMD_MODE_SENSE_G1; 242*fcf3ce44SJohn Forte scsi_command_names[18].name = MSGSTR(94, "Mode Sense(10 Byte)"); 243*fcf3ce44SJohn Forte 244*fcf3ce44SJohn Forte scsi_command_names[19].command = SCMD_MODE_SELECT_G1; 245*fcf3ce44SJohn Forte scsi_command_names[19].name = MSGSTR(96, "Mode Select(10 Byte)"); 246*fcf3ce44SJohn Forte 247*fcf3ce44SJohn Forte scsi_command_names[20].command = SCMD_READ_CAPACITY; 248*fcf3ce44SJohn Forte scsi_command_names[20].name = MSGSTR(81, "Read Capacity"); 249*fcf3ce44SJohn Forte 250*fcf3ce44SJohn Forte scsi_command_names[21].command = SCMD_SYNC_CACHE; 251*fcf3ce44SJohn Forte scsi_command_names[21].name = MSGSTR(64, "Synchronize Cache"); 252*fcf3ce44SJohn Forte 253*fcf3ce44SJohn Forte scsi_command_names[22].command = SCMD_READ_DEFECT_LIST; 254*fcf3ce44SJohn Forte scsi_command_names[22].name = MSGSTR(80, "Read Defect List"); 255*fcf3ce44SJohn Forte 256*fcf3ce44SJohn Forte scsi_command_names[23].command = SCMD_GDIAG; 257*fcf3ce44SJohn Forte scsi_command_names[23].name = MSGSTR(108, "Get Diagnostic"); 258*fcf3ce44SJohn Forte 259*fcf3ce44SJohn Forte scsi_command_names[24].command = SCMD_SDIAG; 260*fcf3ce44SJohn Forte scsi_command_names[24].name = MSGSTR(69, "Set Diagnostic"); 261*fcf3ce44SJohn Forte 262*fcf3ce44SJohn Forte scsi_command_names[25].command = SCMD_PERS_RESERV_IN; 263*fcf3ce44SJohn Forte scsi_command_names[25].name = MSGSTR(10500, "Persistent Reserve In"); 264*fcf3ce44SJohn Forte 265*fcf3ce44SJohn Forte scsi_command_names[26].command = SCMD_PERS_RESERV_OUT; 266*fcf3ce44SJohn Forte scsi_command_names[26].name = MSGSTR(10501, "Persistent Reserve out"); 267*fcf3ce44SJohn Forte 268*fcf3ce44SJohn Forte scsi_command_names[27].command = SCMD_LOG_SENSE; 269*fcf3ce44SJohn Forte scsi_command_names[27].name = MSGSTR(10502, "Log Sense"); 270*fcf3ce44SJohn Forte 271*fcf3ce44SJohn Forte scsi_command_names[28].command = SCMD_UNKNOWN; 272*fcf3ce44SJohn Forte scsi_command_names[28].name = MSGSTR(25, "Unknown"); 273*fcf3ce44SJohn Forte 274*fcf3ce44SJohn Forte 275*fcf3ce44SJohn Forte for (c = scsi_command_names; c->command != SCMD_UNKNOWN; c++) 276*fcf3ce44SJohn Forte if (c->command == cmd) 277*fcf3ce44SJohn Forte break; 278*fcf3ce44SJohn Forte return (c->name); 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte 282*fcf3ce44SJohn Forte /* 283*fcf3ce44SJohn Forte * Function to create error message containing 284*fcf3ce44SJohn Forte * scsi request sense information 285*fcf3ce44SJohn Forte */ 286*fcf3ce44SJohn Forte 287*fcf3ce44SJohn Forte static void 288*fcf3ce44SJohn Forte scsi_printerr(struct uscsi_cmd *ucmd, struct scsi_extended_sense *rq, 289*fcf3ce44SJohn Forte int rqlen, char msg_string[], char *err_string) 290*fcf3ce44SJohn Forte { 291*fcf3ce44SJohn Forte int blkno; 292*fcf3ce44SJohn Forte 293*fcf3ce44SJohn Forte switch (rq->es_key) { 294*fcf3ce44SJohn Forte case KEY_NO_SENSE: 295*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(91, "No sense error")); 296*fcf3ce44SJohn Forte break; 297*fcf3ce44SJohn Forte case KEY_RECOVERABLE_ERROR: 298*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(76, "Recoverable error")); 299*fcf3ce44SJohn Forte break; 300*fcf3ce44SJohn Forte case KEY_NOT_READY: 301*fcf3ce44SJohn Forte (void) sprintf(msg_string, 302*fcf3ce44SJohn Forte MSGSTR(10503, 303*fcf3ce44SJohn Forte "Device Not ready." 304*fcf3ce44SJohn Forte " Error: Random Retry Failed: %s\n."), 305*fcf3ce44SJohn Forte err_string); 306*fcf3ce44SJohn Forte break; 307*fcf3ce44SJohn Forte case KEY_MEDIUM_ERROR: 308*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(99, "Medium error")); 309*fcf3ce44SJohn Forte break; 310*fcf3ce44SJohn Forte case KEY_HARDWARE_ERROR: 311*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(106, "Hardware error")); 312*fcf3ce44SJohn Forte break; 313*fcf3ce44SJohn Forte case KEY_ILLEGAL_REQUEST: 314*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(103, "Illegal request")); 315*fcf3ce44SJohn Forte break; 316*fcf3ce44SJohn Forte case KEY_UNIT_ATTENTION: 317*fcf3ce44SJohn Forte (void) sprintf(msg_string, 318*fcf3ce44SJohn Forte MSGSTR(10504, 319*fcf3ce44SJohn Forte "Unit attention." 320*fcf3ce44SJohn Forte "Error: Random Retry Failed.\n")); 321*fcf3ce44SJohn Forte break; 322*fcf3ce44SJohn Forte case KEY_WRITE_PROTECT: 323*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(52, "Write protect error")); 324*fcf3ce44SJohn Forte break; 325*fcf3ce44SJohn Forte case KEY_BLANK_CHECK: 326*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(131, "Blank check error")); 327*fcf3ce44SJohn Forte break; 328*fcf3ce44SJohn Forte case KEY_VENDOR_UNIQUE: 329*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(58, "Vendor unique error")); 330*fcf3ce44SJohn Forte break; 331*fcf3ce44SJohn Forte case KEY_COPY_ABORTED: 332*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(123, "Copy aborted error")); 333*fcf3ce44SJohn Forte break; 334*fcf3ce44SJohn Forte case KEY_ABORTED_COMMAND: 335*fcf3ce44SJohn Forte (void) sprintf(msg_string, 336*fcf3ce44SJohn Forte MSGSTR(10505, 337*fcf3ce44SJohn Forte "Aborted command." 338*fcf3ce44SJohn Forte " Error: Random Retry Failed.\n")); 339*fcf3ce44SJohn Forte break; 340*fcf3ce44SJohn Forte case KEY_EQUAL: 341*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(117, "Equal error")); 342*fcf3ce44SJohn Forte break; 343*fcf3ce44SJohn Forte case KEY_VOLUME_OVERFLOW: 344*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(57, "Volume overflow")); 345*fcf3ce44SJohn Forte break; 346*fcf3ce44SJohn Forte case KEY_MISCOMPARE: 347*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(98, "Miscompare error")); 348*fcf3ce44SJohn Forte break; 349*fcf3ce44SJohn Forte case KEY_RESERVED: 350*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(10506, 351*fcf3ce44SJohn Forte "Reserved value found")); 352*fcf3ce44SJohn Forte break; 353*fcf3ce44SJohn Forte default: 354*fcf3ce44SJohn Forte (void) sprintf(msg_string, MSGSTR(59, "Unknown error")); 355*fcf3ce44SJohn Forte break; 356*fcf3ce44SJohn Forte } 357*fcf3ce44SJohn Forte 358*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 359*fcf3ce44SJohn Forte MSGSTR(10507, " during: %s"), 360*fcf3ce44SJohn Forte scsi_find_command_name(ucmd->uscsi_cdb[0])); 361*fcf3ce44SJohn Forte 362*fcf3ce44SJohn Forte if (rq->es_valid) { 363*fcf3ce44SJohn Forte blkno = (rq->es_info_1 << 24) | (rq->es_info_2 << 16) | 364*fcf3ce44SJohn Forte (rq->es_info_3 << 8) | rq->es_info_4; 365*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 366*fcf3ce44SJohn Forte MSGSTR(49, ": block %d (0x%x)"), blkno, blkno); 367*fcf3ce44SJohn Forte } 368*fcf3ce44SJohn Forte 369*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], "\n"); 370*fcf3ce44SJohn Forte 371*fcf3ce44SJohn Forte if (rq->es_add_len >= 6) { 372*fcf3ce44SJohn Forte (void) sprintf(&msg_string[strlen(msg_string)], 373*fcf3ce44SJohn Forte MSGSTR(132, " Additional sense: 0x%x ASC Qualifier: 0x%x\n"), 374*fcf3ce44SJohn Forte rq->es_add_code, rq->es_qual_code); 375*fcf3ce44SJohn Forte /* 376*fcf3ce44SJohn Forte * rq->es_add_info[ADD_SENSE_CODE], 377*fcf3ce44SJohn Forte * rq->es_add_info[ADD_SENSE_QUAL_CODE]); 378*fcf3ce44SJohn Forte */ 379*fcf3ce44SJohn Forte } 380*fcf3ce44SJohn Forte if (rq->es_key == KEY_ILLEGAL_REQUEST) { 381*fcf3ce44SJohn Forte string_dump(MSGSTR(47, " cmd: "), (uchar_t *)ucmd, 382*fcf3ce44SJohn Forte sizeof (struct uscsi_cmd), HEX_ONLY, msg_string); 383*fcf3ce44SJohn Forte string_dump(MSGSTR(48, " cdb: "), 384*fcf3ce44SJohn Forte (uchar_t *)ucmd->uscsi_cdb, 385*fcf3ce44SJohn Forte ucmd->uscsi_cdblen, HEX_ONLY, msg_string); 386*fcf3ce44SJohn Forte } 387*fcf3ce44SJohn Forte string_dump(MSGSTR(43, " sense: "), 388*fcf3ce44SJohn Forte (uchar_t *)rq, 8 + rq->es_add_len, HEX_ONLY, 389*fcf3ce44SJohn Forte msg_string); 390*fcf3ce44SJohn Forte rqlen = rqlen; /* not used */ 391*fcf3ce44SJohn Forte } 392*fcf3ce44SJohn Forte 393*fcf3ce44SJohn Forte 394*fcf3ce44SJohn Forte /* 395*fcf3ce44SJohn Forte * Execute a command and determine the result. 396*fcf3ce44SJohn Forte */ 397*fcf3ce44SJohn Forte static int 398*fcf3ce44SJohn Forte issue_uscsi_cmd(int file, struct uscsi_cmd *command, int flag) 399*fcf3ce44SJohn Forte { 400*fcf3ce44SJohn Forte struct scsi_extended_sense *rqbuf; 401*fcf3ce44SJohn Forte int status, i, retry_cnt = 0, err; 402*fcf3ce44SJohn Forte char errorMsg[MAXLEN]; 403*fcf3ce44SJohn Forte 404*fcf3ce44SJohn Forte /* 405*fcf3ce44SJohn Forte * Set function flags for driver. 406*fcf3ce44SJohn Forte * 407*fcf3ce44SJohn Forte * Set Automatic request sense enable 408*fcf3ce44SJohn Forte * 409*fcf3ce44SJohn Forte */ 410*fcf3ce44SJohn Forte command->uscsi_flags = USCSI_RQENABLE; 411*fcf3ce44SJohn Forte command->uscsi_flags |= flag; 412*fcf3ce44SJohn Forte 413*fcf3ce44SJohn Forte /* intialize error message array */ 414*fcf3ce44SJohn Forte errorMsg[0] = '\0'; 415*fcf3ce44SJohn Forte 416*fcf3ce44SJohn Forte /* print command for debug */ 417*fcf3ce44SJohn Forte if (getenv("_LUX_S_DEBUG") != NULL) { 418*fcf3ce44SJohn Forte if ((command->uscsi_cdb == NULL) || 419*fcf3ce44SJohn Forte (flag & USCSI_RESET) || 420*fcf3ce44SJohn Forte (flag & USCSI_RESET_ALL)) { 421*fcf3ce44SJohn Forte if (flag & USCSI_RESET) { 422*fcf3ce44SJohn Forte (void) printf(" Issuing a SCSI Reset.\n"); 423*fcf3ce44SJohn Forte } 424*fcf3ce44SJohn Forte if (flag & USCSI_RESET_ALL) { 425*fcf3ce44SJohn Forte (void) printf(" Issuing a SCSI Reset All.\n"); 426*fcf3ce44SJohn Forte } 427*fcf3ce44SJohn Forte 428*fcf3ce44SJohn Forte } else { 429*fcf3ce44SJohn Forte (void) printf(" Issuing the following " 430*fcf3ce44SJohn Forte "SCSI command: %s\n", 431*fcf3ce44SJohn Forte scsi_find_command_name(command->uscsi_cdb[0])); 432*fcf3ce44SJohn Forte (void) printf(" fd=0x%x cdb=", file); 433*fcf3ce44SJohn Forte for (i = 0; i < (int)command->uscsi_cdblen; i++) { 434*fcf3ce44SJohn Forte (void) printf("%x ", *(command->uscsi_cdb + i)); 435*fcf3ce44SJohn Forte } 436*fcf3ce44SJohn Forte (void) printf("\n\tlen=0x%x bufaddr=0x%x buflen=0x%x" 437*fcf3ce44SJohn Forte " flags=0x%x\n", 438*fcf3ce44SJohn Forte command->uscsi_cdblen, 439*fcf3ce44SJohn Forte command->uscsi_bufaddr, 440*fcf3ce44SJohn Forte command->uscsi_buflen, command->uscsi_flags); 441*fcf3ce44SJohn Forte 442*fcf3ce44SJohn Forte if ((command->uscsi_buflen > 0) && 443*fcf3ce44SJohn Forte ((flag & USCSI_READ) == 0)) { 444*fcf3ce44SJohn Forte (void) dump_hex_data(" Buffer data: ", 445*fcf3ce44SJohn Forte (uchar_t *)command->uscsi_bufaddr, 446*fcf3ce44SJohn Forte MIN(command->uscsi_buflen, 512), HEX_ASCII); 447*fcf3ce44SJohn Forte } 448*fcf3ce44SJohn Forte } 449*fcf3ce44SJohn Forte (void) fflush(stdout); 450*fcf3ce44SJohn Forte } 451*fcf3ce44SJohn Forte 452*fcf3ce44SJohn Forte 453*fcf3ce44SJohn Forte /* 454*fcf3ce44SJohn Forte * Default command timeout in case command left it 0 455*fcf3ce44SJohn Forte */ 456*fcf3ce44SJohn Forte if (command->uscsi_timeout == 0) { 457*fcf3ce44SJohn Forte command->uscsi_timeout = 60; 458*fcf3ce44SJohn Forte } 459*fcf3ce44SJohn Forte /* Issue command - finally */ 460*fcf3ce44SJohn Forte 461*fcf3ce44SJohn Forte retry: 462*fcf3ce44SJohn Forte status = ioctl(file, USCSICMD, command); 463*fcf3ce44SJohn Forte if (status == 0 && command->uscsi_status == 0) { 464*fcf3ce44SJohn Forte if (getenv("_LUX_S_DEBUG") != NULL) { 465*fcf3ce44SJohn Forte if ((command->uscsi_buflen > 0) && 466*fcf3ce44SJohn Forte (flag & USCSI_READ)) { 467*fcf3ce44SJohn Forte (void) dump_hex_data("\tData read:", 468*fcf3ce44SJohn Forte (uchar_t *)command->uscsi_bufaddr, 469*fcf3ce44SJohn Forte MIN(command->uscsi_buflen, 512), HEX_ASCII); 470*fcf3ce44SJohn Forte } 471*fcf3ce44SJohn Forte } 472*fcf3ce44SJohn Forte return (status); 473*fcf3ce44SJohn Forte } 474*fcf3ce44SJohn Forte if ((status != 0) && (command->uscsi_status == 0)) { 475*fcf3ce44SJohn Forte if ((getenv("_LUX_S_DEBUG") != NULL) || 476*fcf3ce44SJohn Forte (getenv("_LUX_ER_DEBUG") != NULL)) { 477*fcf3ce44SJohn Forte (void) printf("Unexpected USCSICMD ioctl error: %s\n", 478*fcf3ce44SJohn Forte strerror(errno)); 479*fcf3ce44SJohn Forte } 480*fcf3ce44SJohn Forte return (status); 481*fcf3ce44SJohn Forte } 482*fcf3ce44SJohn Forte 483*fcf3ce44SJohn Forte /* 484*fcf3ce44SJohn Forte * Just a SCSI error, create error message 485*fcf3ce44SJohn Forte * Retry once for Unit Attention, 486*fcf3ce44SJohn Forte * Not Ready, and Aborted Command 487*fcf3ce44SJohn Forte */ 488*fcf3ce44SJohn Forte if ((command->uscsi_rqbuf != NULL) && 489*fcf3ce44SJohn Forte (((char)command->uscsi_rqlen - (char)command->uscsi_rqresid) > 0)) { 490*fcf3ce44SJohn Forte 491*fcf3ce44SJohn Forte rqbuf = (struct scsi_extended_sense *)command->uscsi_rqbuf; 492*fcf3ce44SJohn Forte 493*fcf3ce44SJohn Forte switch (rqbuf->es_key) { 494*fcf3ce44SJohn Forte case KEY_NOT_READY: 495*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 496*fcf3ce44SJohn Forte ER_DPRINTF("Note: Device Not Ready." 497*fcf3ce44SJohn Forte " Retrying...\n"); 498*fcf3ce44SJohn Forte 499*fcf3ce44SJohn Forte if ((err = wait_random_time()) == 0) { 500*fcf3ce44SJohn Forte goto retry; 501*fcf3ce44SJohn Forte } else { 502*fcf3ce44SJohn Forte return (err); 503*fcf3ce44SJohn Forte } 504*fcf3ce44SJohn Forte } 505*fcf3ce44SJohn Forte break; 506*fcf3ce44SJohn Forte 507*fcf3ce44SJohn Forte case KEY_UNIT_ATTENTION: 508*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 509*fcf3ce44SJohn Forte ER_DPRINTF(" cmd():" 510*fcf3ce44SJohn Forte " UNIT_ATTENTION: Retrying...\n"); 511*fcf3ce44SJohn Forte 512*fcf3ce44SJohn Forte goto retry; 513*fcf3ce44SJohn Forte } 514*fcf3ce44SJohn Forte break; 515*fcf3ce44SJohn Forte 516*fcf3ce44SJohn Forte case KEY_ABORTED_COMMAND: 517*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 518*fcf3ce44SJohn Forte ER_DPRINTF("Note: Command is aborted." 519*fcf3ce44SJohn Forte " Retrying...\n"); 520*fcf3ce44SJohn Forte 521*fcf3ce44SJohn Forte goto retry; 522*fcf3ce44SJohn Forte } 523*fcf3ce44SJohn Forte break; 524*fcf3ce44SJohn Forte } 525*fcf3ce44SJohn Forte if ((getenv("_LUX_S_DEBUG") != NULL) || 526*fcf3ce44SJohn Forte (getenv("_LUX_ER_DEBUG") != NULL)) { 527*fcf3ce44SJohn Forte scsi_printerr(command, 528*fcf3ce44SJohn Forte (struct scsi_extended_sense *)command->uscsi_rqbuf, 529*fcf3ce44SJohn Forte (command->uscsi_rqlen - command->uscsi_rqresid), 530*fcf3ce44SJohn Forte errorMsg, strerror(errno)); 531*fcf3ce44SJohn Forte } 532*fcf3ce44SJohn Forte 533*fcf3ce44SJohn Forte } else { 534*fcf3ce44SJohn Forte 535*fcf3ce44SJohn Forte /* 536*fcf3ce44SJohn Forte * Retry 5 times in case of BUSY, and only 537*fcf3ce44SJohn Forte * once for Reservation-conflict, Command 538*fcf3ce44SJohn Forte * Termination and Queue Full. Wait for 539*fcf3ce44SJohn Forte * random amount of time (between 1/10 - 1/2 secs.) 540*fcf3ce44SJohn Forte * between each retry. This random wait is to avoid 541*fcf3ce44SJohn Forte * the multiple threads being executed at the same time 542*fcf3ce44SJohn Forte * and also the constraint in Photon IB, where the 543*fcf3ce44SJohn Forte * command queue has a depth of one command. 544*fcf3ce44SJohn Forte */ 545*fcf3ce44SJohn Forte switch ((uchar_t)command->uscsi_status & STATUS_MASK) { 546*fcf3ce44SJohn Forte case STATUS_BUSY: 547*fcf3ce44SJohn Forte if (retry_cnt++ < 5) { 548*fcf3ce44SJohn Forte if ((err = wait_random_time()) == 0) { 549*fcf3ce44SJohn Forte R_DPRINTF(" cmd(): No. of retries %d." 550*fcf3ce44SJohn Forte " STATUS_BUSY: Retrying...\n", 551*fcf3ce44SJohn Forte retry_cnt); 552*fcf3ce44SJohn Forte goto retry; 553*fcf3ce44SJohn Forte 554*fcf3ce44SJohn Forte } else { 555*fcf3ce44SJohn Forte return (err); 556*fcf3ce44SJohn Forte } 557*fcf3ce44SJohn Forte } 558*fcf3ce44SJohn Forte break; 559*fcf3ce44SJohn Forte 560*fcf3ce44SJohn Forte case STATUS_RESERVATION_CONFLICT: 561*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 562*fcf3ce44SJohn Forte if ((err = wait_random_time()) == 0) { 563*fcf3ce44SJohn Forte R_DPRINTF(" cmd():" 564*fcf3ce44SJohn Forte " RESERVATION_CONFLICT:" 565*fcf3ce44SJohn Forte " Retrying...\n"); 566*fcf3ce44SJohn Forte goto retry; 567*fcf3ce44SJohn Forte 568*fcf3ce44SJohn Forte } else { 569*fcf3ce44SJohn Forte return (err); 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte } 572*fcf3ce44SJohn Forte break; 573*fcf3ce44SJohn Forte 574*fcf3ce44SJohn Forte case STATUS_TERMINATED: 575*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 576*fcf3ce44SJohn Forte R_DPRINTF("Note: Command Terminated." 577*fcf3ce44SJohn Forte " Retrying...\n"); 578*fcf3ce44SJohn Forte 579*fcf3ce44SJohn Forte if ((err = wait_random_time()) == 0) { 580*fcf3ce44SJohn Forte goto retry; 581*fcf3ce44SJohn Forte } else { 582*fcf3ce44SJohn Forte return (err); 583*fcf3ce44SJohn Forte } 584*fcf3ce44SJohn Forte } 585*fcf3ce44SJohn Forte break; 586*fcf3ce44SJohn Forte 587*fcf3ce44SJohn Forte case STATUS_QFULL: 588*fcf3ce44SJohn Forte if (retry_cnt++ < 1) { 589*fcf3ce44SJohn Forte R_DPRINTF("Note: Command Queue is full." 590*fcf3ce44SJohn Forte " Retrying...\n"); 591*fcf3ce44SJohn Forte 592*fcf3ce44SJohn Forte if ((err = wait_random_time()) == 0) { 593*fcf3ce44SJohn Forte goto retry; 594*fcf3ce44SJohn Forte } else { 595*fcf3ce44SJohn Forte return (err); 596*fcf3ce44SJohn Forte } 597*fcf3ce44SJohn Forte } 598*fcf3ce44SJohn Forte break; 599*fcf3ce44SJohn Forte } 600*fcf3ce44SJohn Forte 601*fcf3ce44SJohn Forte } 602*fcf3ce44SJohn Forte if (((getenv("_LUX_S_DEBUG") != NULL) || 603*fcf3ce44SJohn Forte (getenv("_LUX_ER_DEBUG") != NULL)) && 604*fcf3ce44SJohn Forte (errorMsg[0] != '\0')) { 605*fcf3ce44SJohn Forte (void) fprintf(stdout, " %s\n", errorMsg); 606*fcf3ce44SJohn Forte } 607*fcf3ce44SJohn Forte return (L_SCSI_ERROR | command->uscsi_status); 608*fcf3ce44SJohn Forte } 609*fcf3ce44SJohn Forte 610*fcf3ce44SJohn Forte /* 611*fcf3ce44SJohn Forte * MODE SENSE USCSI command 612*fcf3ce44SJohn Forte * 613*fcf3ce44SJohn Forte * 614*fcf3ce44SJohn Forte * pc = page control field 615*fcf3ce44SJohn Forte * page_code = Pages to return 616*fcf3ce44SJohn Forte */ 617*fcf3ce44SJohn Forte int 618*fcf3ce44SJohn Forte scsi_mode_sense_cmd(int fd, 619*fcf3ce44SJohn Forte uchar_t *buf_ptr, 620*fcf3ce44SJohn Forte int buf_len, 621*fcf3ce44SJohn Forte uchar_t pc, 622*fcf3ce44SJohn Forte uchar_t page_code) 623*fcf3ce44SJohn Forte { 624*fcf3ce44SJohn Forte struct uscsi_cmd ucmd; 625*fcf3ce44SJohn Forte /* 10 byte Mode Select cmd */ 626*fcf3ce44SJohn Forte union scsi_cdb cdb = {SCMD_MODE_SENSE_G1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 627*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 628*fcf3ce44SJohn Forte int status; 629*fcf3ce44SJohn Forte static int uscsi_count; 630*fcf3ce44SJohn Forte 631*fcf3ce44SJohn Forte if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) { 632*fcf3ce44SJohn Forte return (-1); /* L_INVALID_ARG */ 633*fcf3ce44SJohn Forte } 634*fcf3ce44SJohn Forte 635*fcf3ce44SJohn Forte (void) memset(buf_ptr, 0, buf_len); 636*fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd)); 637*fcf3ce44SJohn Forte /* Just for me - a sanity check */ 638*fcf3ce44SJohn Forte if ((page_code > MODEPAGE_ALLPAGES) || (pc > 3) || 639*fcf3ce44SJohn Forte (buf_len > MAX_MODE_SENSE_LEN)) { 640*fcf3ce44SJohn Forte return (-1); /* L_ILLEGAL_MODE_SENSE_PAGE */ 641*fcf3ce44SJohn Forte } 642*fcf3ce44SJohn Forte cdb.g1_addr3 = (pc << 6) + page_code; 643*fcf3ce44SJohn Forte cdb.g1_count1 = buf_len>>8; 644*fcf3ce44SJohn Forte cdb.g1_count0 = buf_len & 0xff; 645*fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb; 646*fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP1; 647*fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = (caddr_t)buf_ptr; 648*fcf3ce44SJohn Forte ucmd.uscsi_buflen = buf_len; 649*fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense; 650*fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense); 651*fcf3ce44SJohn Forte ucmd.uscsi_timeout = 120; 652*fcf3ce44SJohn Forte 653*fcf3ce44SJohn Forte status = issue_uscsi_cmd(fd, &ucmd, USCSI_READ); 654*fcf3ce44SJohn Forte /* Bytes actually transfered */ 655*fcf3ce44SJohn Forte if (status == 0) { 656*fcf3ce44SJohn Forte uscsi_count = buf_len - ucmd.uscsi_resid; 657*fcf3ce44SJohn Forte S_DPRINTF(" Number of bytes read on " 658*fcf3ce44SJohn Forte "Mode Sense 0x%x\n", uscsi_count); 659*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 660*fcf3ce44SJohn Forte (void) dump_hex_data(" Mode Sense data: ", buf_ptr, 661*fcf3ce44SJohn Forte uscsi_count, HEX_ASCII); 662*fcf3ce44SJohn Forte } 663*fcf3ce44SJohn Forte } 664*fcf3ce44SJohn Forte return (status); 665*fcf3ce44SJohn Forte } 666*fcf3ce44SJohn Forte 667*fcf3ce44SJohn Forte int 668*fcf3ce44SJohn Forte scsi_release(char *path) 669*fcf3ce44SJohn Forte { 670*fcf3ce44SJohn Forte struct uscsi_cmd ucmd; 671*fcf3ce44SJohn Forte union scsi_cdb cdb = {SCMD_RELEASE, 0, 0, 0, 0, 0}; 672*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 673*fcf3ce44SJohn Forte int fd, status; 674*fcf3ce44SJohn Forte 675*fcf3ce44SJohn Forte P_DPRINTF(" scsi_release: Release: Path %s\n", path); 676*fcf3ce44SJohn Forte if ((fd = open(path, O_NDELAY | O_RDONLY)) == -1) 677*fcf3ce44SJohn Forte return (1); 678*fcf3ce44SJohn Forte 679*fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd)); 680*fcf3ce44SJohn Forte 681*fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb; 682*fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0; 683*fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = NULL; 684*fcf3ce44SJohn Forte ucmd.uscsi_buflen = 0; 685*fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense; 686*fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense); 687*fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60; 688*fcf3ce44SJohn Forte status = (issue_uscsi_cmd(fd, &ucmd, 0)); 689*fcf3ce44SJohn Forte 690*fcf3ce44SJohn Forte (void) close(fd); 691*fcf3ce44SJohn Forte return (status); 692*fcf3ce44SJohn Forte } 693*fcf3ce44SJohn Forte 694*fcf3ce44SJohn Forte int 695*fcf3ce44SJohn Forte scsi_reserve(char *path) 696*fcf3ce44SJohn Forte { 697*fcf3ce44SJohn Forte struct uscsi_cmd ucmd; 698*fcf3ce44SJohn Forte union scsi_cdb cdb = {SCMD_RESERVE, 0, 0, 0, 0, 0}; 699*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 700*fcf3ce44SJohn Forte int fd, status; 701*fcf3ce44SJohn Forte 702*fcf3ce44SJohn Forte P_DPRINTF(" scsi_reserve: Reserve: Path %s\n", path); 703*fcf3ce44SJohn Forte if ((fd = open(path, O_NDELAY | O_RDONLY)) == -1) 704*fcf3ce44SJohn Forte return (1); 705*fcf3ce44SJohn Forte 706*fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd)); 707*fcf3ce44SJohn Forte 708*fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb; 709*fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0; 710*fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = NULL; 711*fcf3ce44SJohn Forte ucmd.uscsi_buflen = 0; 712*fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense; 713*fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense); 714*fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60; 715*fcf3ce44SJohn Forte status = (issue_uscsi_cmd(fd, &ucmd, 0)); 716*fcf3ce44SJohn Forte 717*fcf3ce44SJohn Forte (void) close(fd); 718*fcf3ce44SJohn Forte return (status); 719*fcf3ce44SJohn Forte } 720*fcf3ce44SJohn Forte 721*fcf3ce44SJohn Forte /* 722*fcf3ce44SJohn Forte * Print out fabric dev dtype 723*fcf3ce44SJohn Forte */ 724*fcf3ce44SJohn Forte void 725*fcf3ce44SJohn Forte print_fabric_dtype_prop(uchar_t *hba_port_wwn, uchar_t *port_wwn, 726*fcf3ce44SJohn Forte uchar_t dtype_prop) 727*fcf3ce44SJohn Forte { 728*fcf3ce44SJohn Forte if ((dtype_prop & DTYPE_MASK) < 0x10) { 729*fcf3ce44SJohn Forte (void) fprintf(stdout, " 0x%-2x (%s)\n", 730*fcf3ce44SJohn Forte (dtype_prop & DTYPE_MASK), dtype[(dtype_prop & DTYPE_MASK)]); 731*fcf3ce44SJohn Forte } else if ((dtype_prop & DTYPE_MASK) < 0x1f) { 732*fcf3ce44SJohn Forte (void) fprintf(stdout, 733*fcf3ce44SJohn Forte MSGSTR(2096, " 0x%-2x (Reserved)\n"), 734*fcf3ce44SJohn Forte (dtype_prop & DTYPE_MASK)); 735*fcf3ce44SJohn Forte } else { 736*fcf3ce44SJohn Forte /* Check to see if this is the HBA */ 737*fcf3ce44SJohn Forte if (wwnConversion(hba_port_wwn) != wwnConversion(port_wwn)) { 738*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2097, 739*fcf3ce44SJohn Forte " 0x%-2x (Unknown Type)\n"), (dtype_prop & DTYPE_MASK)); 740*fcf3ce44SJohn Forte } else { 741*fcf3ce44SJohn Forte /* MATCH */ 742*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2241, 743*fcf3ce44SJohn Forte " 0x%-2x (Unknown Type,Host Bus Adapter)\n"), 744*fcf3ce44SJohn Forte (dtype_prop & DTYPE_MASK)); 745*fcf3ce44SJohn Forte } 746*fcf3ce44SJohn Forte } 747*fcf3ce44SJohn Forte } 748*fcf3ce44SJohn Forte 749*fcf3ce44SJohn Forte 750*fcf3ce44SJohn Forte void 751*fcf3ce44SJohn Forte print_inq_data(char *arg_path, char *path, L_inquiry inq, uchar_t *serial, 752*fcf3ce44SJohn Forte size_t serial_len) 753*fcf3ce44SJohn Forte { 754*fcf3ce44SJohn Forte char **p; 755*fcf3ce44SJohn Forte uchar_t *v_parm; 756*fcf3ce44SJohn Forte int scsi_3, length; 757*fcf3ce44SJohn Forte char byte_number[MAXNAMELEN]; 758*fcf3ce44SJohn Forte static char *scsi_inquiry_labels_2[21]; 759*fcf3ce44SJohn Forte static char *scsi_inquiry_labels_3[22]; 760*fcf3ce44SJohn Forte static char *ansi_version[4]; 761*fcf3ce44SJohn Forte /* 762*fcf3ce44SJohn Forte * Intialize scsi_inquiry_labels_2 with i18n strings 763*fcf3ce44SJohn Forte */ 764*fcf3ce44SJohn Forte scsi_inquiry_labels_2[0] = MSGSTR(138, "Vendor: "); 765*fcf3ce44SJohn Forte scsi_inquiry_labels_2[1] = MSGSTR(149, "Product: "); 766*fcf3ce44SJohn Forte scsi_inquiry_labels_2[2] = MSGSTR(139, "Revision: "); 767*fcf3ce44SJohn Forte scsi_inquiry_labels_2[3] = MSGSTR(143, "Firmware Revision "); 768*fcf3ce44SJohn Forte scsi_inquiry_labels_2[4] = MSGSTR(144, "Serial Number "); 769*fcf3ce44SJohn Forte scsi_inquiry_labels_2[5] = MSGSTR(140, "Device type: "); 770*fcf3ce44SJohn Forte scsi_inquiry_labels_2[6] = MSGSTR(145, "Removable media: "); 771*fcf3ce44SJohn Forte scsi_inquiry_labels_2[7] = MSGSTR(146, "ISO version: "); 772*fcf3ce44SJohn Forte scsi_inquiry_labels_2[8] = MSGSTR(147, "ECMA version: "); 773*fcf3ce44SJohn Forte scsi_inquiry_labels_2[9] = MSGSTR(148, "ANSI version: "); 774*fcf3ce44SJohn Forte scsi_inquiry_labels_2[10] = 775*fcf3ce44SJohn Forte MSGSTR(2168, "Async event notification: "); 776*fcf3ce44SJohn Forte scsi_inquiry_labels_2[11] = 777*fcf3ce44SJohn Forte MSGSTR(2169, "Terminate i/o process msg: "); 778*fcf3ce44SJohn Forte scsi_inquiry_labels_2[12] = MSGSTR(150, "Response data format: "); 779*fcf3ce44SJohn Forte scsi_inquiry_labels_2[13] = MSGSTR(151, "Additional length: "); 780*fcf3ce44SJohn Forte scsi_inquiry_labels_2[14] = MSGSTR(152, "Relative addressing: "); 781*fcf3ce44SJohn Forte scsi_inquiry_labels_2[15] = 782*fcf3ce44SJohn Forte MSGSTR(2170, "32 bit transfers: "); 783*fcf3ce44SJohn Forte scsi_inquiry_labels_2[16] = 784*fcf3ce44SJohn Forte MSGSTR(2171, "16 bit transfers: "); 785*fcf3ce44SJohn Forte scsi_inquiry_labels_2[17] = 786*fcf3ce44SJohn Forte MSGSTR(2172, "Synchronous transfers: "); 787*fcf3ce44SJohn Forte scsi_inquiry_labels_2[18] = MSGSTR(153, "Linked commands: "); 788*fcf3ce44SJohn Forte scsi_inquiry_labels_2[19] = MSGSTR(154, "Command queueing: "); 789*fcf3ce44SJohn Forte scsi_inquiry_labels_2[20] = 790*fcf3ce44SJohn Forte MSGSTR(2173, "Soft reset option: "); 791*fcf3ce44SJohn Forte 792*fcf3ce44SJohn Forte /* 793*fcf3ce44SJohn Forte * Intialize scsi_inquiry_labels_3 with i18n strings 794*fcf3ce44SJohn Forte */ 795*fcf3ce44SJohn Forte scsi_inquiry_labels_3[0] = MSGSTR(138, "Vendor: "); 796*fcf3ce44SJohn Forte scsi_inquiry_labels_3[1] = MSGSTR(149, "Product: "); 797*fcf3ce44SJohn Forte scsi_inquiry_labels_3[2] = MSGSTR(139, "Revision: "); 798*fcf3ce44SJohn Forte scsi_inquiry_labels_3[3] = MSGSTR(143, "Firmware Revision "); 799*fcf3ce44SJohn Forte scsi_inquiry_labels_3[4] = MSGSTR(144, "Serial Number "); 800*fcf3ce44SJohn Forte scsi_inquiry_labels_3[5] = MSGSTR(140, "Device type: "); 801*fcf3ce44SJohn Forte scsi_inquiry_labels_3[6] = MSGSTR(145, "Removable media: "); 802*fcf3ce44SJohn Forte scsi_inquiry_labels_3[7] = MSGSTR(2174, "Medium Changer Element: "); 803*fcf3ce44SJohn Forte scsi_inquiry_labels_3[8] = MSGSTR(146, "ISO version: "); 804*fcf3ce44SJohn Forte scsi_inquiry_labels_3[9] = MSGSTR(147, "ECMA version: "); 805*fcf3ce44SJohn Forte scsi_inquiry_labels_3[10] = MSGSTR(148, "ANSI version: "); 806*fcf3ce44SJohn Forte scsi_inquiry_labels_3[11] = 807*fcf3ce44SJohn Forte MSGSTR(2175, "Async event reporting: "); 808*fcf3ce44SJohn Forte scsi_inquiry_labels_3[12] = 809*fcf3ce44SJohn Forte MSGSTR(2176, "Terminate task: "); 810*fcf3ce44SJohn Forte scsi_inquiry_labels_3[13] = 811*fcf3ce44SJohn Forte MSGSTR(2177, "Normal ACA Supported: "); 812*fcf3ce44SJohn Forte scsi_inquiry_labels_3[14] = MSGSTR(150, "Response data format: "); 813*fcf3ce44SJohn Forte scsi_inquiry_labels_3[15] = MSGSTR(151, "Additional length: "); 814*fcf3ce44SJohn Forte scsi_inquiry_labels_3[16] = 815*fcf3ce44SJohn Forte MSGSTR(2178, "Cmd received on port: "); 816*fcf3ce44SJohn Forte scsi_inquiry_labels_3[17] = 817*fcf3ce44SJohn Forte MSGSTR(2179, "SIP Bits: "); 818*fcf3ce44SJohn Forte scsi_inquiry_labels_3[18] = MSGSTR(152, "Relative addressing: "); 819*fcf3ce44SJohn Forte scsi_inquiry_labels_3[19] = MSGSTR(153, "Linked commands: "); 820*fcf3ce44SJohn Forte scsi_inquiry_labels_3[20] = 821*fcf3ce44SJohn Forte MSGSTR(2180, "Transfer Disable: "); 822*fcf3ce44SJohn Forte scsi_inquiry_labels_3[21] = MSGSTR(154, "Command queueing: "); 823*fcf3ce44SJohn Forte 824*fcf3ce44SJohn Forte /* 825*fcf3ce44SJohn Forte * Intialize scsi_inquiry_labels_3 with i18n strings 826*fcf3ce44SJohn Forte */ 827*fcf3ce44SJohn Forte ansi_version[0] = MSGSTR(2181, 828*fcf3ce44SJohn Forte " (Device might or might not comply to an ANSI version)"); 829*fcf3ce44SJohn Forte ansi_version[1] = MSGSTR(2182, 830*fcf3ce44SJohn Forte " (This code is reserved for historical uses)"); 831*fcf3ce44SJohn Forte ansi_version[2] = MSGSTR(2183, 832*fcf3ce44SJohn Forte " (Device complies to ANSI X3.131-1994 (SCSI-2))"); 833*fcf3ce44SJohn Forte ansi_version[3] = MSGSTR(2184, 834*fcf3ce44SJohn Forte " (Device complies to SCSI-3)"); 835*fcf3ce44SJohn Forte 836*fcf3ce44SJohn Forte /* print inquiry information */ 837*fcf3ce44SJohn Forte 838*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2185, "\nINQUIRY:\n")); 839*fcf3ce44SJohn Forte /* 840*fcf3ce44SJohn Forte * arg_path is the path sent to luxadm by the user. if arg_path 841*fcf3ce44SJohn Forte * is a /devices path, then we do not need to print out physical 842*fcf3ce44SJohn Forte * path info 843*fcf3ce44SJohn Forte */ 844*fcf3ce44SJohn Forte if (strcmp(arg_path, path) != 0 && 845*fcf3ce44SJohn Forte strstr(arg_path, "/devices/") == NULL) { 846*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 847*fcf3ce44SJohn Forte (void) fprintf(stdout, 848*fcf3ce44SJohn Forte MSGSTR(5, "Physical Path:")); 849*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n %s\n", path); 850*fcf3ce44SJohn Forte } 851*fcf3ce44SJohn Forte if (inq.inq_ansi < 3) { 852*fcf3ce44SJohn Forte p = scsi_inquiry_labels_2; 853*fcf3ce44SJohn Forte scsi_3 = 0; 854*fcf3ce44SJohn Forte } else { 855*fcf3ce44SJohn Forte p = scsi_inquiry_labels_3; 856*fcf3ce44SJohn Forte scsi_3 = 1; 857*fcf3ce44SJohn Forte } 858*fcf3ce44SJohn Forte if (inq.inq_len < 11) { 859*fcf3ce44SJohn Forte p += 1; 860*fcf3ce44SJohn Forte } else { 861*fcf3ce44SJohn Forte /* */ 862*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 863*fcf3ce44SJohn Forte print_chars(inq.inq_vid, sizeof (inq.inq_vid), 0); 864*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 865*fcf3ce44SJohn Forte } 866*fcf3ce44SJohn Forte if (inq.inq_len < 27) { 867*fcf3ce44SJohn Forte p += 1; 868*fcf3ce44SJohn Forte } else { 869*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 870*fcf3ce44SJohn Forte print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0); 871*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 872*fcf3ce44SJohn Forte } 873*fcf3ce44SJohn Forte if (inq.inq_len < 31) { 874*fcf3ce44SJohn Forte p += 1; 875*fcf3ce44SJohn Forte } else { 876*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 877*fcf3ce44SJohn Forte print_chars(inq.inq_revision, sizeof (inq.inq_revision), 0); 878*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 879*fcf3ce44SJohn Forte } 880*fcf3ce44SJohn Forte if (inq.inq_len < 39) { 881*fcf3ce44SJohn Forte p += 2; 882*fcf3ce44SJohn Forte } else { 883*fcf3ce44SJohn Forte /* 884*fcf3ce44SJohn Forte * If Pluto then print 885*fcf3ce44SJohn Forte * firmware rev & serial #. 886*fcf3ce44SJohn Forte */ 887*fcf3ce44SJohn Forte if (strstr((char *)inq.inq_pid, "SSA") != 0) { 888*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 889*fcf3ce44SJohn Forte print_chars(inq.inq_firmware_rev, 890*fcf3ce44SJohn Forte sizeof (inq.inq_firmware_rev), 0); 891*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 892*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 893*fcf3ce44SJohn Forte print_chars(serial, serial_len, 0); 894*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 895*fcf3ce44SJohn Forte } else if ((inq.inq_dtype & DTYPE_MASK) != DTYPE_ESI) { 896*fcf3ce44SJohn Forte p++; 897*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 898*fcf3ce44SJohn Forte print_chars(serial, serial_len, 0); 899*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 900*fcf3ce44SJohn Forte } else { 901*fcf3ce44SJohn Forte /* if we miss both the above if's */ 902*fcf3ce44SJohn Forte p += 2; 903*fcf3ce44SJohn Forte } 904*fcf3ce44SJohn Forte } 905*fcf3ce44SJohn Forte 906*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s0x%x (", 907*fcf3ce44SJohn Forte *p++, (inq.inq_dtype & DTYPE_MASK)); 908*fcf3ce44SJohn Forte if ((inq.inq_dtype & DTYPE_MASK) < 0x10) { 909*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", dtype[inq.inq_dtype & DTYPE_MASK]); 910*fcf3ce44SJohn Forte } else if ((inq.inq_dtype & DTYPE_MASK) < 0x1f) { 911*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(71, "Reserved")); 912*fcf3ce44SJohn Forte } else { 913*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2186, "Unknown device")); 914*fcf3ce44SJohn Forte } 915*fcf3ce44SJohn Forte (void) fprintf(stdout, ")\n"); 916*fcf3ce44SJohn Forte 917*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 918*fcf3ce44SJohn Forte if (inq.inq_rmb != NULL) { 919*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 920*fcf3ce44SJohn Forte } else { 921*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(45, "no")); 922*fcf3ce44SJohn Forte } 923*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte if (scsi_3) { 926*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 927*fcf3ce44SJohn Forte if (inq.inq_mchngr != NULL) { 928*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 929*fcf3ce44SJohn Forte } else { 930*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(45, "no")); 931*fcf3ce44SJohn Forte } 932*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 933*fcf3ce44SJohn Forte } 934*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_iso); 935*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_ecma); 936*fcf3ce44SJohn Forte 937*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s%d", *p++, inq.inq_ansi); 938*fcf3ce44SJohn Forte if (inq.inq_ansi < 0x4) { 939*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", ansi_version[inq.inq_ansi]); 940*fcf3ce44SJohn Forte } else 941*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(71, "Reserved")); 942*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 943*fcf3ce44SJohn Forte 944*fcf3ce44SJohn Forte if (inq.inq_aenc) { 945*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 946*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 947*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 948*fcf3ce44SJohn Forte } else { 949*fcf3ce44SJohn Forte p++; 950*fcf3ce44SJohn Forte } 951*fcf3ce44SJohn Forte if (scsi_3) { 952*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 953*fcf3ce44SJohn Forte if (inq.inq_normaca != NULL) { 954*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 955*fcf3ce44SJohn Forte } else { 956*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(45, "no")); 957*fcf3ce44SJohn Forte } 958*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 959*fcf3ce44SJohn Forte } 960*fcf3ce44SJohn Forte if (inq.inq_trmiop) { 961*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 962*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 963*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 964*fcf3ce44SJohn Forte } else { 965*fcf3ce44SJohn Forte p++; 966*fcf3ce44SJohn Forte } 967*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s%d\n", *p++, inq.inq_rdf); 968*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s0x%x\n", *p++, inq.inq_len); 969*fcf3ce44SJohn Forte if (scsi_3) { 970*fcf3ce44SJohn Forte if (inq.inq_dual_p) { 971*fcf3ce44SJohn Forte if (inq.inq_port != NULL) { 972*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2187, 973*fcf3ce44SJohn Forte "%sa\n"), *p++); 974*fcf3ce44SJohn Forte } else { 975*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2188, 976*fcf3ce44SJohn Forte "%sb\n"), *p++); 977*fcf3ce44SJohn Forte } 978*fcf3ce44SJohn Forte } else { 979*fcf3ce44SJohn Forte p++; 980*fcf3ce44SJohn Forte } 981*fcf3ce44SJohn Forte } 982*fcf3ce44SJohn Forte if (scsi_3) { 983*fcf3ce44SJohn Forte if (inq.inq_SIP_1 || inq.ui.inq_3.inq_SIP_2 || 984*fcf3ce44SJohn Forte inq.ui.inq_3.inq_SIP_3) { 985*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s%d, %d, %d\n", *p, 986*fcf3ce44SJohn Forte inq.inq_SIP_1, inq.ui.inq_3.inq_SIP_2, 987*fcf3ce44SJohn Forte inq.ui.inq_3.inq_SIP_3); 988*fcf3ce44SJohn Forte } 989*fcf3ce44SJohn Forte p++; 990*fcf3ce44SJohn Forte 991*fcf3ce44SJohn Forte } 992*fcf3ce44SJohn Forte 993*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_2_reladdr) { 994*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 995*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 996*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 997*fcf3ce44SJohn Forte } 998*fcf3ce44SJohn Forte p++; 999*fcf3ce44SJohn Forte 1000*fcf3ce44SJohn Forte if (!scsi_3) { 1001*fcf3ce44SJohn Forte 1002*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_wbus32) { 1003*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1004*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1005*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1006*fcf3ce44SJohn Forte } 1007*fcf3ce44SJohn Forte p++; 1008*fcf3ce44SJohn Forte 1009*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_wbus16) { 1010*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1011*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1012*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1013*fcf3ce44SJohn Forte } 1014*fcf3ce44SJohn Forte p++; 1015*fcf3ce44SJohn Forte 1016*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_sync) { 1017*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1018*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1019*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1020*fcf3ce44SJohn Forte } 1021*fcf3ce44SJohn Forte p++; 1022*fcf3ce44SJohn Forte 1023*fcf3ce44SJohn Forte } 1024*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_linked) { 1025*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1026*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1027*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1028*fcf3ce44SJohn Forte } 1029*fcf3ce44SJohn Forte p++; 1030*fcf3ce44SJohn Forte 1031*fcf3ce44SJohn Forte if (scsi_3) { 1032*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p++); 1033*fcf3ce44SJohn Forte if (inq.ui.inq_3.inq_trandis != NULL) { 1034*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1035*fcf3ce44SJohn Forte } else { 1036*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(45, "no")); 1037*fcf3ce44SJohn Forte } 1038*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1039*fcf3ce44SJohn Forte } 1040*fcf3ce44SJohn Forte 1041*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_cmdque) { 1042*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1043*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1044*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1045*fcf3ce44SJohn Forte } 1046*fcf3ce44SJohn Forte p++; 1047*fcf3ce44SJohn Forte 1048*fcf3ce44SJohn Forte if (!scsi_3) { 1049*fcf3ce44SJohn Forte if (inq.ui.inq_2.inq_sftre) { 1050*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", *p); 1051*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(40, "yes")); 1052*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1053*fcf3ce44SJohn Forte } 1054*fcf3ce44SJohn Forte p++; 1055*fcf3ce44SJohn Forte 1056*fcf3ce44SJohn Forte } 1057*fcf3ce44SJohn Forte 1058*fcf3ce44SJohn Forte /* 1059*fcf3ce44SJohn Forte * Now print the vendor-specific data. 1060*fcf3ce44SJohn Forte */ 1061*fcf3ce44SJohn Forte v_parm = inq.inq_ven_specific_1; 1062*fcf3ce44SJohn Forte if (inq.inq_len >= 32) { 1063*fcf3ce44SJohn Forte length = inq.inq_len - 31; 1064*fcf3ce44SJohn Forte if (strstr((char *)inq.inq_pid, "SSA") != 0) { 1065*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(2189, 1066*fcf3ce44SJohn Forte "Number of Ports, Targets: %d,%d\n"), 1067*fcf3ce44SJohn Forte inq.inq_ssa_ports, inq.inq_ssa_tgts); 1068*fcf3ce44SJohn Forte v_parm += 20; 1069*fcf3ce44SJohn Forte length -= 20; 1070*fcf3ce44SJohn Forte } else if ((strstr((char *)inq.inq_pid, "SUN") != 0) || 1071*fcf3ce44SJohn Forte (strncmp((char *)inq.inq_vid, "SUN ", 1072*fcf3ce44SJohn Forte sizeof (inq.inq_vid)) == 0)) { 1073*fcf3ce44SJohn Forte v_parm += 16; 1074*fcf3ce44SJohn Forte length -= 16; 1075*fcf3ce44SJohn Forte } 1076*fcf3ce44SJohn Forte /* 1077*fcf3ce44SJohn Forte * Do hex Dump of rest of the data. 1078*fcf3ce44SJohn Forte */ 1079*fcf3ce44SJohn Forte if (length > 0) { 1080*fcf3ce44SJohn Forte (void) fprintf(stdout, 1081*fcf3ce44SJohn Forte MSGSTR(2190, 1082*fcf3ce44SJohn Forte " VENDOR-SPECIFIC PARAMETERS\n")); 1083*fcf3ce44SJohn Forte (void) fprintf(stdout, 1084*fcf3ce44SJohn Forte MSGSTR(2191, 1085*fcf3ce44SJohn Forte "Byte# Hex Value " 1086*fcf3ce44SJohn Forte " ASCII\n")); 1087*fcf3ce44SJohn Forte (void) sprintf(byte_number, 1088*fcf3ce44SJohn Forte "%d ", inq.inq_len - length + 5); 1089*fcf3ce44SJohn Forte dump_hex_data(byte_number, v_parm, 1090*fcf3ce44SJohn Forte MIN(length, inq.inq_res3 - v_parm), HEX_ASCII); 1091*fcf3ce44SJohn Forte } 1092*fcf3ce44SJohn Forte /* 1093*fcf3ce44SJohn Forte * Skip reserved bytes 56-95. 1094*fcf3ce44SJohn Forte */ 1095*fcf3ce44SJohn Forte length -= (inq.inq_box_name - v_parm); 1096*fcf3ce44SJohn Forte if (length > 0) { 1097*fcf3ce44SJohn Forte (void) sprintf(byte_number, "%d ", 1098*fcf3ce44SJohn Forte inq.inq_len - length + 5); 1099*fcf3ce44SJohn Forte dump_hex_data(byte_number, inq.inq_box_name, 1100*fcf3ce44SJohn Forte MIN(length, sizeof (inq.inq_box_name) + 1101*fcf3ce44SJohn Forte sizeof (inq.inq_avu)), HEX_ASCII); 1102*fcf3ce44SJohn Forte } 1103*fcf3ce44SJohn Forte } 1104*fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) { 1105*fcf3ce44SJohn Forte dump_hex_data("\nComplete Inquiry: ", 1106*fcf3ce44SJohn Forte (uchar_t *)&inq, 1107*fcf3ce44SJohn Forte MIN(inq.inq_len + 5, sizeof (inq)), HEX_ASCII); 1108*fcf3ce44SJohn Forte } 1109*fcf3ce44SJohn Forte } 1110*fcf3ce44SJohn Forte 1111*fcf3ce44SJohn Forte /* 1112*fcf3ce44SJohn Forte * Internal routine to clean up ../'s in paths. 1113*fcf3ce44SJohn Forte * returns 0 if no "../" are left. 1114*fcf3ce44SJohn Forte * 1115*fcf3ce44SJohn Forte * Wouldn't it be nice if there was a standard system library 1116*fcf3ce44SJohn Forte * routine to do this...? 1117*fcf3ce44SJohn Forte */ 1118*fcf3ce44SJohn Forte static int 1119*fcf3ce44SJohn Forte cleanup_dotdot_path(char *path) 1120*fcf3ce44SJohn Forte { 1121*fcf3ce44SJohn Forte char holder[MAXPATHLEN]; 1122*fcf3ce44SJohn Forte char *dotdot; 1123*fcf3ce44SJohn Forte char *previous_slash; 1124*fcf3ce44SJohn Forte 1125*fcf3ce44SJohn Forte /* Find the first "/../" in the string */ 1126*fcf3ce44SJohn Forte dotdot = strstr(path, "/../"); 1127*fcf3ce44SJohn Forte if (dotdot == NULL) { 1128*fcf3ce44SJohn Forte return (0); 1129*fcf3ce44SJohn Forte } 1130*fcf3ce44SJohn Forte 1131*fcf3ce44SJohn Forte 1132*fcf3ce44SJohn Forte /* 1133*fcf3ce44SJohn Forte * If the [0] character is '/' and "../" immediatly 1134*fcf3ce44SJohn Forte * follows it, then we can strip the ../ 1135*fcf3ce44SJohn Forte * 1136*fcf3ce44SJohn Forte * /../../foo/bar == /foo/bar 1137*fcf3ce44SJohn Forte * 1138*fcf3ce44SJohn Forte */ 1139*fcf3ce44SJohn Forte if (dotdot == path) { 1140*fcf3ce44SJohn Forte strcpy(holder, &path[3]); /* strip "/.." */ 1141*fcf3ce44SJohn Forte strcpy(path, holder); 1142*fcf3ce44SJohn Forte return (1); 1143*fcf3ce44SJohn Forte } 1144*fcf3ce44SJohn Forte 1145*fcf3ce44SJohn Forte /* 1146*fcf3ce44SJohn Forte * Now look for the LAST "/" before the "/../" 1147*fcf3ce44SJohn Forte * as this is the parent dir we can get rid of. 1148*fcf3ce44SJohn Forte * We do this by temporarily truncating the string 1149*fcf3ce44SJohn Forte * at the '/' just before "../" using the dotdot pointer. 1150*fcf3ce44SJohn Forte */ 1151*fcf3ce44SJohn Forte *dotdot = '\0'; 1152*fcf3ce44SJohn Forte previous_slash = strrchr(path, '/'); 1153*fcf3ce44SJohn Forte if (previous_slash == NULL) { 1154*fcf3ce44SJohn Forte /* 1155*fcf3ce44SJohn Forte * hmm, somethings wrong. path looks something 1156*fcf3ce44SJohn Forte * like "foo/../bar/" so we can't really deal with it. 1157*fcf3ce44SJohn Forte */ 1158*fcf3ce44SJohn Forte return (0); 1159*fcf3ce44SJohn Forte } 1160*fcf3ce44SJohn Forte /* 1161*fcf3ce44SJohn Forte * Now truncate the path just after the previous '/' 1162*fcf3ce44SJohn Forte * and slam everything after the "../" back on 1163*fcf3ce44SJohn Forte */ 1164*fcf3ce44SJohn Forte *(previous_slash+1) = '\0'; 1165*fcf3ce44SJohn Forte (void) strcat(path, dotdot+4); 1166*fcf3ce44SJohn Forte return (1); /* We may have more "../"s */ 1167*fcf3ce44SJohn Forte } 1168*fcf3ce44SJohn Forte 1169*fcf3ce44SJohn Forte /* 1170*fcf3ce44SJohn Forte * Follow symbolic links from the logical device name to 1171*fcf3ce44SJohn Forte * the /devfs physical device name. To be complete, we 1172*fcf3ce44SJohn Forte * handle the case of multiple links. This function 1173*fcf3ce44SJohn Forte * either returns NULL (no links, or some other error), 1174*fcf3ce44SJohn Forte * or the physical device name, alloc'ed on the heap. 1175*fcf3ce44SJohn Forte * 1176*fcf3ce44SJohn Forte * NOTE: If the path is relative, it will be forced into 1177*fcf3ce44SJohn Forte * an absolute path by pre-pending the pwd to it. 1178*fcf3ce44SJohn Forte */ 1179*fcf3ce44SJohn Forte char * 1180*fcf3ce44SJohn Forte get_slash_devices_from_osDevName(char *osDevName, int flag) 1181*fcf3ce44SJohn Forte { 1182*fcf3ce44SJohn Forte struct stat stbuf; 1183*fcf3ce44SJohn Forte char source[MAXPATHLEN]; 1184*fcf3ce44SJohn Forte char scratch[MAXPATHLEN]; 1185*fcf3ce44SJohn Forte char pwd[MAXPATHLEN]; 1186*fcf3ce44SJohn Forte char *tmp, *phys_path; 1187*fcf3ce44SJohn Forte int cnt; 1188*fcf3ce44SJohn Forte boolean_t is_lstat_failed = B_TRUE; 1189*fcf3ce44SJohn Forte 1190*fcf3ce44SJohn Forte /* return NULL if path is NULL */ 1191*fcf3ce44SJohn Forte if (osDevName == NULL) { 1192*fcf3ce44SJohn Forte return (NULL); 1193*fcf3ce44SJohn Forte } 1194*fcf3ce44SJohn Forte 1195*fcf3ce44SJohn Forte strcpy(source, osDevName); 1196*fcf3ce44SJohn Forte for (;;) { 1197*fcf3ce44SJohn Forte 1198*fcf3ce44SJohn Forte /* 1199*fcf3ce44SJohn Forte * First make sure the path is absolute. If not, make it. 1200*fcf3ce44SJohn Forte * If it's already an absolute path, we have no need 1201*fcf3ce44SJohn Forte * to determine the cwd, so the program should still 1202*fcf3ce44SJohn Forte * function within security-by-obscurity directories. 1203*fcf3ce44SJohn Forte */ 1204*fcf3ce44SJohn Forte if (source[0] != '/') { 1205*fcf3ce44SJohn Forte tmp = getcwd(pwd, MAXPATHLEN); 1206*fcf3ce44SJohn Forte if (tmp == NULL) { 1207*fcf3ce44SJohn Forte return (NULL); 1208*fcf3ce44SJohn Forte } 1209*fcf3ce44SJohn Forte /* 1210*fcf3ce44SJohn Forte * Handle special case of "./foo/bar" 1211*fcf3ce44SJohn Forte */ 1212*fcf3ce44SJohn Forte if (source[0] == '.' && source[1] == '/') { 1213*fcf3ce44SJohn Forte strcpy(scratch, source+2); 1214*fcf3ce44SJohn Forte } else { /* no "./" so just take everything */ 1215*fcf3ce44SJohn Forte strcpy(scratch, source); 1216*fcf3ce44SJohn Forte } 1217*fcf3ce44SJohn Forte strcpy(source, pwd); 1218*fcf3ce44SJohn Forte (void) strcat(source, "/"); 1219*fcf3ce44SJohn Forte (void) strcat(source, scratch); 1220*fcf3ce44SJohn Forte } 1221*fcf3ce44SJohn Forte 1222*fcf3ce44SJohn Forte /* 1223*fcf3ce44SJohn Forte * Clean up any "../"s that are in the path 1224*fcf3ce44SJohn Forte */ 1225*fcf3ce44SJohn Forte while (cleanup_dotdot_path(source)); 1226*fcf3ce44SJohn Forte 1227*fcf3ce44SJohn Forte /* 1228*fcf3ce44SJohn Forte * source is now an absolute path to the link we're 1229*fcf3ce44SJohn Forte * concerned with 1230*fcf3ce44SJohn Forte */ 1231*fcf3ce44SJohn Forte if (flag == NOT_IGNORE_DANGLING_LINK) { 1232*fcf3ce44SJohn Forte /* 1233*fcf3ce44SJohn Forte * In order not to ingore dangling links, check 1234*fcf3ce44SJohn Forte * the lstat. If lstat succeeds, return the path 1235*fcf3ce44SJohn Forte * from readlink. 1236*fcf3ce44SJohn Forte * Note: osDevName input with /devices path from 1237*fcf3ce44SJohn Forte * a dangling /dev link doesn't pass lstat so 1238*fcf3ce44SJohn Forte * NULL is returned. 1239*fcf3ce44SJohn Forte */ 1240*fcf3ce44SJohn Forte if (stat(source, &stbuf) == -1) { 1241*fcf3ce44SJohn Forte if (!is_lstat_failed && 1242*fcf3ce44SJohn Forte strstr(source, "/devices")) { 1243*fcf3ce44SJohn Forte /* 1244*fcf3ce44SJohn Forte * lstat succeeded previously and source 1245*fcf3ce44SJohn Forte * contains "/devices" then it is dangling node. 1246*fcf3ce44SJohn Forte */ 1247*fcf3ce44SJohn Forte phys_path = (char *)calloc(1, strlen(source) + 1); 1248*fcf3ce44SJohn Forte if (phys_path != NULL) { 1249*fcf3ce44SJohn Forte (void) strncpy(phys_path, source, 1250*fcf3ce44SJohn Forte strlen(source) + 1); 1251*fcf3ce44SJohn Forte } 1252*fcf3ce44SJohn Forte return (phys_path); 1253*fcf3ce44SJohn Forte } else if (is_lstat_failed) { 1254*fcf3ce44SJohn Forte /* check lstat result. */ 1255*fcf3ce44SJohn Forte if (lstat(source, &stbuf) == -1) { 1256*fcf3ce44SJohn Forte return (NULL); 1257*fcf3ce44SJohn Forte } else { 1258*fcf3ce44SJohn Forte is_lstat_failed = B_FALSE; /* and coninue */ 1259*fcf3ce44SJohn Forte } 1260*fcf3ce44SJohn Forte } else { 1261*fcf3ce44SJohn Forte /* 1262*fcf3ce44SJohn Forte * With algorithm that resolves a link and 1263*fcf3ce44SJohn Forte * then issues readlink(), should not be 1264*fcf3ce44SJohn Forte * reached here. 1265*fcf3ce44SJohn Forte */ 1266*fcf3ce44SJohn Forte return (NULL); 1267*fcf3ce44SJohn Forte } 1268*fcf3ce44SJohn Forte } else { 1269*fcf3ce44SJohn Forte if (lstat(source, &stbuf) == -1) { 1270*fcf3ce44SJohn Forte /* 1271*fcf3ce44SJohn Forte * when stat succeeds it is not a dangling node 1272*fcf3ce44SJohn Forte * so it is not a special case. 1273*fcf3ce44SJohn Forte */ 1274*fcf3ce44SJohn Forte return (NULL); 1275*fcf3ce44SJohn Forte } 1276*fcf3ce44SJohn Forte } 1277*fcf3ce44SJohn Forte } else if (flag == STANDARD_DEVNAME_HANDLING) { 1278*fcf3ce44SJohn Forte /* 1279*fcf3ce44SJohn Forte * See if there's a real file out there. If not, 1280*fcf3ce44SJohn Forte * we have a dangling link and we ignore it. 1281*fcf3ce44SJohn Forte */ 1282*fcf3ce44SJohn Forte if (stat(source, &stbuf) == -1) { 1283*fcf3ce44SJohn Forte return (NULL); 1284*fcf3ce44SJohn Forte } 1285*fcf3ce44SJohn Forte if (lstat(source, &stbuf) == -1) { 1286*fcf3ce44SJohn Forte return (NULL); 1287*fcf3ce44SJohn Forte } 1288*fcf3ce44SJohn Forte } else { 1289*fcf3ce44SJohn Forte /* invalid flag */ 1290*fcf3ce44SJohn Forte return (NULL); 1291*fcf3ce44SJohn Forte } 1292*fcf3ce44SJohn Forte 1293*fcf3ce44SJohn Forte /* 1294*fcf3ce44SJohn Forte * If the file is not a link, we're done one 1295*fcf3ce44SJohn Forte * way or the other. If there were links, 1296*fcf3ce44SJohn Forte * return the full pathname of the resulting 1297*fcf3ce44SJohn Forte * file. 1298*fcf3ce44SJohn Forte * 1299*fcf3ce44SJohn Forte * Note: All of our temp's are on the stack, 1300*fcf3ce44SJohn Forte * so we have to copy the final result to the heap. 1301*fcf3ce44SJohn Forte */ 1302*fcf3ce44SJohn Forte if (!S_ISLNK(stbuf.st_mode)) { 1303*fcf3ce44SJohn Forte phys_path = (char *)calloc(1, strlen(source) + 1); 1304*fcf3ce44SJohn Forte if (phys_path != NULL) { 1305*fcf3ce44SJohn Forte (void) strncpy(phys_path, source, 1306*fcf3ce44SJohn Forte strlen(source) + 1); 1307*fcf3ce44SJohn Forte } 1308*fcf3ce44SJohn Forte return (phys_path); 1309*fcf3ce44SJohn Forte } 1310*fcf3ce44SJohn Forte cnt = readlink(source, scratch, sizeof (scratch)); 1311*fcf3ce44SJohn Forte if (cnt < 0) { 1312*fcf3ce44SJohn Forte return (NULL); 1313*fcf3ce44SJohn Forte } 1314*fcf3ce44SJohn Forte /* 1315*fcf3ce44SJohn Forte * scratch is on the heap, and for some reason readlink 1316*fcf3ce44SJohn Forte * doesn't always terminate things properly so we have 1317*fcf3ce44SJohn Forte * to make certain we're properly terminated 1318*fcf3ce44SJohn Forte */ 1319*fcf3ce44SJohn Forte scratch[cnt] = '\0'; 1320*fcf3ce44SJohn Forte 1321*fcf3ce44SJohn Forte /* 1322*fcf3ce44SJohn Forte * Now check to see if the link is relative. If so, 1323*fcf3ce44SJohn Forte * then we have to append it to the directory 1324*fcf3ce44SJohn Forte * which the source was in. (This is non trivial) 1325*fcf3ce44SJohn Forte */ 1326*fcf3ce44SJohn Forte if (scratch[0] != '/') { 1327*fcf3ce44SJohn Forte tmp = strrchr(source, '/'); 1328*fcf3ce44SJohn Forte if (tmp == NULL) { /* Whoa! Something's hosed! */ 1329*fcf3ce44SJohn Forte O_DPRINTF("Internal error... corrupt path.\n"); 1330*fcf3ce44SJohn Forte return (NULL); 1331*fcf3ce44SJohn Forte } 1332*fcf3ce44SJohn Forte /* Now strip off just the directory path */ 1333*fcf3ce44SJohn Forte *(tmp+1) = '\0'; /* Keeping the last '/' */ 1334*fcf3ce44SJohn Forte /* and append the new link */ 1335*fcf3ce44SJohn Forte (void) strcat(source, scratch); 1336*fcf3ce44SJohn Forte /* 1337*fcf3ce44SJohn Forte * Note: At this point, source should have "../"s 1338*fcf3ce44SJohn Forte * but we'll clean it up in the next pass through 1339*fcf3ce44SJohn Forte * the loop. 1340*fcf3ce44SJohn Forte */ 1341*fcf3ce44SJohn Forte } else { 1342*fcf3ce44SJohn Forte /* It's an absolute link so no worries */ 1343*fcf3ce44SJohn Forte strcpy(source, scratch); 1344*fcf3ce44SJohn Forte } 1345*fcf3ce44SJohn Forte } 1346*fcf3ce44SJohn Forte /* Never reach here */ 1347*fcf3ce44SJohn Forte } 1348*fcf3ce44SJohn Forte 1349*fcf3ce44SJohn Forte /* 1350*fcf3ce44SJohn Forte * Input - Space for client_path, phci_path and paddr fields of ioc structure 1351*fcf3ce44SJohn Forte * need to be allocated by the caller of this routine. 1352*fcf3ce44SJohn Forte */ 1353*fcf3ce44SJohn Forte int 1354*fcf3ce44SJohn Forte get_scsi_vhci_pathinfo(char *dev_path, sv_iocdata_t *ioc, int *path_count) 1355*fcf3ce44SJohn Forte { 1356*fcf3ce44SJohn Forte char *physical_path, *physical_path_s; 1357*fcf3ce44SJohn Forte int retval; 1358*fcf3ce44SJohn Forte int fd; 1359*fcf3ce44SJohn Forte int initial_path_count; 1360*fcf3ce44SJohn Forte int current_path_count; 1361*fcf3ce44SJohn Forte int i; 1362*fcf3ce44SJohn Forte char *delimiter; 1363*fcf3ce44SJohn Forte int malloc_error = 0; 1364*fcf3ce44SJohn Forte int prop_buf_size; 1365*fcf3ce44SJohn Forte int pathlist_retry_count = 0; 1366*fcf3ce44SJohn Forte 1367*fcf3ce44SJohn Forte if (strncmp(dev_path, SCSI_VHCI, 1368*fcf3ce44SJohn Forte strlen(SCSI_VHCI)) != NULL) { 1369*fcf3ce44SJohn Forte if ((physical_path = get_slash_devices_from_osDevName( 1370*fcf3ce44SJohn Forte dev_path, STANDARD_DEVNAME_HANDLING)) == NULL) { 1371*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1372*fcf3ce44SJohn Forte } 1373*fcf3ce44SJohn Forte if (strncmp(physical_path, SCSI_VHCI, 1374*fcf3ce44SJohn Forte strlen(SCSI_VHCI)) != NULL) { 1375*fcf3ce44SJohn Forte free(physical_path); 1376*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1377*fcf3ce44SJohn Forte } 1378*fcf3ce44SJohn Forte } else { 1379*fcf3ce44SJohn Forte if ((physical_path = calloc(1, MAXPATHLEN)) == NULL) { 1380*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1381*fcf3ce44SJohn Forte } 1382*fcf3ce44SJohn Forte (void) strcpy(physical_path, dev_path); 1383*fcf3ce44SJohn Forte } 1384*fcf3ce44SJohn Forte physical_path_s = physical_path; 1385*fcf3ce44SJohn Forte 1386*fcf3ce44SJohn Forte /* move beyond "/devices" prefix */ 1387*fcf3ce44SJohn Forte physical_path += DEV_PREFIX_STRLEN-1; 1388*fcf3ce44SJohn Forte /* remove :c,raw suffix */ 1389*fcf3ce44SJohn Forte delimiter = strrchr(physical_path, ':'); 1390*fcf3ce44SJohn Forte /* if we didn't find the ':' fine, else truncate */ 1391*fcf3ce44SJohn Forte if (delimiter != NULL) { 1392*fcf3ce44SJohn Forte *delimiter = NULL; 1393*fcf3ce44SJohn Forte } 1394*fcf3ce44SJohn Forte 1395*fcf3ce44SJohn Forte /* 1396*fcf3ce44SJohn Forte * We'll call ioctl SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO 1397*fcf3ce44SJohn Forte * at least twice. The first time will get the path count 1398*fcf3ce44SJohn Forte * and the size of the ioctl propoerty buffer. The second 1399*fcf3ce44SJohn Forte * time will get the path_info for each path. 1400*fcf3ce44SJohn Forte * 1401*fcf3ce44SJohn Forte * It's possible that additional paths are added while this 1402*fcf3ce44SJohn Forte * code is running. If the path count increases between the 1403*fcf3ce44SJohn Forte * 2 ioctl's above, then we'll retry (and assume all is well). 1404*fcf3ce44SJohn Forte */ 1405*fcf3ce44SJohn Forte (void) strcpy(ioc->client, physical_path); 1406*fcf3ce44SJohn Forte ioc->buf_elem = 1; 1407*fcf3ce44SJohn Forte ioc->ret_elem = (uint_t *)&(initial_path_count); 1408*fcf3ce44SJohn Forte ioc->ret_buf = NULL; 1409*fcf3ce44SJohn Forte 1410*fcf3ce44SJohn Forte /* free physical path */ 1411*fcf3ce44SJohn Forte free(physical_path_s); 1412*fcf3ce44SJohn Forte 1413*fcf3ce44SJohn Forte /* 0 buf_size asks driver to return actual size needed */ 1414*fcf3ce44SJohn Forte /* open the ioctl file descriptor */ 1415*fcf3ce44SJohn Forte if ((fd = open("/devices/scsi_vhci:devctl", O_RDWR)) < 0) { 1416*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1417*fcf3ce44SJohn Forte } 1418*fcf3ce44SJohn Forte 1419*fcf3ce44SJohn Forte retval = ioctl(fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, ioc); 1420*fcf3ce44SJohn Forte if (retval != 0) { 1421*fcf3ce44SJohn Forte close(fd); 1422*fcf3ce44SJohn Forte return (L_SCSI_VHCI_ERROR); 1423*fcf3ce44SJohn Forte } 1424*fcf3ce44SJohn Forte prop_buf_size = SV_PROP_MAX_BUF_SIZE; 1425*fcf3ce44SJohn Forte 1426*fcf3ce44SJohn Forte 1427*fcf3ce44SJohn Forte while (pathlist_retry_count <= RETRY_PATHLIST) { 1428*fcf3ce44SJohn Forte ioc->buf_elem = initial_path_count; 1429*fcf3ce44SJohn Forte /* Make driver put actual # paths in variable */ 1430*fcf3ce44SJohn Forte ioc->ret_elem = (uint_t *)&(current_path_count); 1431*fcf3ce44SJohn Forte 1432*fcf3ce44SJohn Forte /* 1433*fcf3ce44SJohn Forte * Allocate space for array of path_info structures. 1434*fcf3ce44SJohn Forte * Allocate enough space for # paths from get_pathcount 1435*fcf3ce44SJohn Forte */ 1436*fcf3ce44SJohn Forte ioc->ret_buf = (sv_path_info_t *) 1437*fcf3ce44SJohn Forte calloc(initial_path_count, 1438*fcf3ce44SJohn Forte sizeof (sv_path_info_t)); 1439*fcf3ce44SJohn Forte if (ioc->ret_buf == NULL) { 1440*fcf3ce44SJohn Forte close(fd); 1441*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1442*fcf3ce44SJohn Forte } 1443*fcf3ce44SJohn Forte 1444*fcf3ce44SJohn Forte /* 1445*fcf3ce44SJohn Forte * Allocate space for path properties returned by driver 1446*fcf3ce44SJohn Forte */ 1447*fcf3ce44SJohn Forte malloc_error = 0; 1448*fcf3ce44SJohn Forte for (i = 0; i < initial_path_count; i++) { 1449*fcf3ce44SJohn Forte ioc->ret_buf[i].ret_prop.buf_size = prop_buf_size; 1450*fcf3ce44SJohn Forte if ((ioc->ret_buf[i].ret_prop.buf = 1451*fcf3ce44SJohn Forte (caddr_t)malloc(prop_buf_size)) == NULL) { 1452*fcf3ce44SJohn Forte malloc_error = 1; 1453*fcf3ce44SJohn Forte break; 1454*fcf3ce44SJohn Forte } 1455*fcf3ce44SJohn Forte if ((ioc->ret_buf[i].ret_prop.ret_buf_size = 1456*fcf3ce44SJohn Forte (uint_t *)malloc(sizeof (uint_t))) == NULL) { 1457*fcf3ce44SJohn Forte malloc_error = 1; 1458*fcf3ce44SJohn Forte break; 1459*fcf3ce44SJohn Forte } 1460*fcf3ce44SJohn Forte } 1461*fcf3ce44SJohn Forte if (malloc_error == 1) { 1462*fcf3ce44SJohn Forte for (i = 0; i < initial_path_count; i++) { 1463*fcf3ce44SJohn Forte free(ioc->ret_buf[i].ret_prop.buf); 1464*fcf3ce44SJohn Forte free(ioc->ret_buf[i].ret_prop.ret_buf_size); 1465*fcf3ce44SJohn Forte } 1466*fcf3ce44SJohn Forte free(ioc->ret_buf); 1467*fcf3ce44SJohn Forte close(fd); 1468*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1469*fcf3ce44SJohn Forte } 1470*fcf3ce44SJohn Forte 1471*fcf3ce44SJohn Forte retval = ioctl(fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, ioc); 1472*fcf3ce44SJohn Forte if (retval != 0) { 1473*fcf3ce44SJohn Forte for (i = 0; i < initial_path_count; i++) { 1474*fcf3ce44SJohn Forte free(ioc->ret_buf[i].ret_prop.buf); 1475*fcf3ce44SJohn Forte free(ioc->ret_buf[i].ret_prop.ret_buf_size); 1476*fcf3ce44SJohn Forte } 1477*fcf3ce44SJohn Forte free(ioc->ret_buf); 1478*fcf3ce44SJohn Forte close(fd); 1479*fcf3ce44SJohn Forte return (L_SCSI_VHCI_ERROR); 1480*fcf3ce44SJohn Forte } 1481*fcf3ce44SJohn Forte if (initial_path_count < current_path_count) { 1482*fcf3ce44SJohn Forte /* then a new path was added */ 1483*fcf3ce44SJohn Forte pathlist_retry_count++; 1484*fcf3ce44SJohn Forte initial_path_count = current_path_count; 1485*fcf3ce44SJohn Forte } else { 1486*fcf3ce44SJohn Forte break; 1487*fcf3ce44SJohn Forte } 1488*fcf3ce44SJohn Forte } 1489*fcf3ce44SJohn Forte /* we are done with ioctl's, lose the fd */ 1490*fcf3ce44SJohn Forte close(fd); 1491*fcf3ce44SJohn Forte 1492*fcf3ce44SJohn Forte /* 1493*fcf3ce44SJohn Forte * Compare the length num elements from the ioctl response 1494*fcf3ce44SJohn Forte * and the caller's request - use smaller value. 1495*fcf3ce44SJohn Forte * 1496*fcf3ce44SJohn Forte * pathlist_p->path_count now has count returned from ioctl. 1497*fcf3ce44SJohn Forte * ioc.buf_elem has the value the caller provided. 1498*fcf3ce44SJohn Forte */ 1499*fcf3ce44SJohn Forte if (initial_path_count < current_path_count) { 1500*fcf3ce44SJohn Forte /* More paths exist than we allocated space for */ 1501*fcf3ce44SJohn Forte *path_count = initial_path_count; 1502*fcf3ce44SJohn Forte } else { 1503*fcf3ce44SJohn Forte *path_count = current_path_count; 1504*fcf3ce44SJohn Forte } 1505*fcf3ce44SJohn Forte 1506*fcf3ce44SJohn Forte return (0); 1507*fcf3ce44SJohn Forte } 1508*fcf3ce44SJohn Forte 1509*fcf3ce44SJohn Forte int 1510*fcf3ce44SJohn Forte get_mode_page(char *path, uchar_t **pg_buf) 1511*fcf3ce44SJohn Forte { 1512*fcf3ce44SJohn Forte struct mode_header_g1 *mode_header_ptr; 1513*fcf3ce44SJohn Forte int status, size, fd; 1514*fcf3ce44SJohn Forte 1515*fcf3ce44SJohn Forte /* open controller */ 1516*fcf3ce44SJohn Forte if ((fd = open(path, O_NDELAY | O_RDWR)) == -1) 1517*fcf3ce44SJohn Forte return (-1); /* L_OPEN_PATH_FAIL */ 1518*fcf3ce44SJohn Forte 1519*fcf3ce44SJohn Forte /* 1520*fcf3ce44SJohn Forte * Read the first part of the page to get the page size 1521*fcf3ce44SJohn Forte */ 1522*fcf3ce44SJohn Forte size = 20; 1523*fcf3ce44SJohn Forte if ((*pg_buf = (uchar_t *)calloc(1, size)) == NULL) { 1524*fcf3ce44SJohn Forte (void) close(fd); 1525*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1526*fcf3ce44SJohn Forte } 1527*fcf3ce44SJohn Forte /* read page */ 1528*fcf3ce44SJohn Forte if (status = scsi_mode_sense_cmd(fd, *pg_buf, size, 1529*fcf3ce44SJohn Forte 0, MODEPAGE_ALLPAGES)) { 1530*fcf3ce44SJohn Forte (void) close(fd); 1531*fcf3ce44SJohn Forte (void) free(*pg_buf); 1532*fcf3ce44SJohn Forte return (status); 1533*fcf3ce44SJohn Forte } 1534*fcf3ce44SJohn Forte /* Now get the size for all pages */ 1535*fcf3ce44SJohn Forte mode_header_ptr = (struct mode_header_g1 *)(void *)*pg_buf; 1536*fcf3ce44SJohn Forte size = ntohs(mode_header_ptr->length) + 1537*fcf3ce44SJohn Forte sizeof (mode_header_ptr->length); 1538*fcf3ce44SJohn Forte (void) free(*pg_buf); 1539*fcf3ce44SJohn Forte if ((*pg_buf = (uchar_t *)calloc(1, size)) == NULL) { 1540*fcf3ce44SJohn Forte (void) close(fd); 1541*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1542*fcf3ce44SJohn Forte } 1543*fcf3ce44SJohn Forte /* read all pages */ 1544*fcf3ce44SJohn Forte if (status = scsi_mode_sense_cmd(fd, *pg_buf, size, 1545*fcf3ce44SJohn Forte 0, MODEPAGE_ALLPAGES)) { 1546*fcf3ce44SJohn Forte (void) close(fd); 1547*fcf3ce44SJohn Forte (void) free(*pg_buf); 1548*fcf3ce44SJohn Forte return (status); 1549*fcf3ce44SJohn Forte } 1550*fcf3ce44SJohn Forte (void) close(fd); 1551*fcf3ce44SJohn Forte return (0); 1552*fcf3ce44SJohn Forte } 1553*fcf3ce44SJohn Forte 1554*fcf3ce44SJohn Forte /* 1555*fcf3ce44SJohn Forte * Dump a structure in hexadecimal. 1556*fcf3ce44SJohn Forte */ 1557*fcf3ce44SJohn Forte void 1558*fcf3ce44SJohn Forte dump_hex_data(char *hdr, uchar_t *src, int nbytes, int format) 1559*fcf3ce44SJohn Forte { 1560*fcf3ce44SJohn Forte int i; 1561*fcf3ce44SJohn Forte int n; 1562*fcf3ce44SJohn Forte char *p; 1563*fcf3ce44SJohn Forte char s[256]; 1564*fcf3ce44SJohn Forte 1565*fcf3ce44SJohn Forte assert(format == HEX_ONLY || format == HEX_ASCII); 1566*fcf3ce44SJohn Forte 1567*fcf3ce44SJohn Forte (void) strcpy(s, hdr); 1568*fcf3ce44SJohn Forte for (p = s; *p; p++) { 1569*fcf3ce44SJohn Forte *p = ' '; 1570*fcf3ce44SJohn Forte } 1571*fcf3ce44SJohn Forte 1572*fcf3ce44SJohn Forte p = hdr; 1573*fcf3ce44SJohn Forte while (nbytes > 0) { 1574*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s", p); 1575*fcf3ce44SJohn Forte p = s; 1576*fcf3ce44SJohn Forte n = MIN(nbytes, BYTES_PER_LINE); 1577*fcf3ce44SJohn Forte for (i = 0; i < n; i++) { 1578*fcf3ce44SJohn Forte (void) fprintf(stdout, "%02x ", src[i] & 0xff); 1579*fcf3ce44SJohn Forte } 1580*fcf3ce44SJohn Forte if (format == HEX_ASCII) { 1581*fcf3ce44SJohn Forte for (i = BYTES_PER_LINE-n; i > 0; i--) { 1582*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 1583*fcf3ce44SJohn Forte } 1584*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 1585*fcf3ce44SJohn Forte for (i = 0; i < n; i++) { 1586*fcf3ce44SJohn Forte (void) fprintf(stdout, "%c", 1587*fcf3ce44SJohn Forte isprint(src[i]) ? src[i] : '.'); 1588*fcf3ce44SJohn Forte } 1589*fcf3ce44SJohn Forte } 1590*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1591*fcf3ce44SJohn Forte nbytes -= n; 1592*fcf3ce44SJohn Forte src += n; 1593*fcf3ce44SJohn Forte } 1594*fcf3ce44SJohn Forte } 1595