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