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