1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte #include <hbaapi.h> 29*fcf3ce44SJohn Forte #include <stdio.h> 30*fcf3ce44SJohn Forte #include <unistd.h> 31*fcf3ce44SJohn Forte #include <stdlib.h> 32*fcf3ce44SJohn Forte #include <sys/param.h> 33*fcf3ce44SJohn Forte #include <sys/types.h> 34*fcf3ce44SJohn Forte #include <sys/stat.h> 35*fcf3ce44SJohn Forte #include <string.h> 36*fcf3ce44SJohn Forte #include <strings.h> 37*fcf3ce44SJohn Forte #include <ctype.h> 38*fcf3ce44SJohn Forte #include <sys/scsi/generic/sense.h> 39*fcf3ce44SJohn Forte #include <sys/scsi/generic/mode.h> 40*fcf3ce44SJohn Forte #include <sys/scsi/generic/inquiry.h> 41*fcf3ce44SJohn Forte #include <errno.h> 42*fcf3ce44SJohn Forte #include <libdevice.h> 43*fcf3ce44SJohn Forte #include <config_admin.h> 44*fcf3ce44SJohn Forte #include <sys/byteorder.h> 45*fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h> 46*fcf3ce44SJohn Forte #include "common.h" 47*fcf3ce44SJohn Forte #include "sun_fc_version.h" 48*fcf3ce44SJohn Forte 49*fcf3ce44SJohn Forte #define DEFAULT_LUN_COUNT 1024 50*fcf3ce44SJohn Forte #define LUN_SIZE 8 51*fcf3ce44SJohn Forte #define LUN_HEADER_SIZE 8 52*fcf3ce44SJohn Forte #define DEFAULT_LUN_LENGTH DEFAULT_LUN_COUNT * \ 53*fcf3ce44SJohn Forte LUN_SIZE + \ 54*fcf3ce44SJohn Forte LUN_HEADER_SIZE 55*fcf3ce44SJohn Forte struct lun_val { 56*fcf3ce44SJohn Forte uchar_t val[8]; 57*fcf3ce44SJohn Forte }; 58*fcf3ce44SJohn Forte struct rep_luns_rsp { 59*fcf3ce44SJohn Forte uint32_t length; 60*fcf3ce44SJohn Forte uint32_t rsrvd; 61*fcf3ce44SJohn Forte struct lun_val lun[1]; 62*fcf3ce44SJohn Forte }; 63*fcf3ce44SJohn Forte 64*fcf3ce44SJohn Forte /* Extracted from the old scsi.h file */ 65*fcf3ce44SJohn Forte struct capacity_data_struct { 66*fcf3ce44SJohn Forte uint_t last_block_addr; 67*fcf3ce44SJohn Forte uint_t block_size; 68*fcf3ce44SJohn Forte }; 69*fcf3ce44SJohn Forte 70*fcf3ce44SJohn Forte 71*fcf3ce44SJohn Forte /* Structure to handle the inq. page 0x80 serial number */ 72*fcf3ce44SJohn Forte struct page80 { 73*fcf3ce44SJohn Forte uchar_t inq_dtype; 74*fcf3ce44SJohn Forte uchar_t inq_page_code; 75*fcf3ce44SJohn Forte uchar_t reserved; 76*fcf3ce44SJohn Forte uchar_t inq_page_len; 77*fcf3ce44SJohn Forte uchar_t inq_serial[251]; 78*fcf3ce44SJohn Forte }; 79*fcf3ce44SJohn Forte 80*fcf3ce44SJohn Forte extern char *dtype[]; 81*fcf3ce44SJohn Forte extern int Options; 82*fcf3ce44SJohn Forte extern const int OPTION_P; 83*fcf3ce44SJohn Forte 84*fcf3ce44SJohn Forte int skip_hba(int i); 85*fcf3ce44SJohn Forte int find_supported_inq_page(HBA_HANDLE handle, HBA_WWN hwwn, HBA_WWN pwwn, 86*fcf3ce44SJohn Forte uint64_t lun, int page_num); 87*fcf3ce44SJohn Forte /* 88*fcf3ce44SJohn Forte * The routines within this file operate against the T11 89*fcf3ce44SJohn Forte * HBA API interface. In some cases, proprietary Sun driver 90*fcf3ce44SJohn Forte * interface are also called to add additional information 91*fcf3ce44SJohn Forte * above what the standard library supports. 92*fcf3ce44SJohn Forte */ 93*fcf3ce44SJohn Forte 94*fcf3ce44SJohn Forte uint64_t 95*fcf3ce44SJohn Forte wwnConversion(uchar_t *wwn) { 96*fcf3ce44SJohn Forte uint64_t tmp; 97*fcf3ce44SJohn Forte (void) memcpy(&tmp, wwn, sizeof (uint64_t)); 98*fcf3ce44SJohn Forte return (ntohll(tmp)); 99*fcf3ce44SJohn Forte } 100*fcf3ce44SJohn Forte 101*fcf3ce44SJohn Forte void printStatus(HBA_STATUS status) { 102*fcf3ce44SJohn Forte switch (status) { 103*fcf3ce44SJohn Forte case HBA_STATUS_OK: 104*fcf3ce44SJohn Forte printf(MSGSTR(2410, "OK")); 105*fcf3ce44SJohn Forte return; 106*fcf3ce44SJohn Forte case HBA_STATUS_ERROR: 107*fcf3ce44SJohn Forte printf(MSGSTR(2411, "ERROR")); 108*fcf3ce44SJohn Forte return; 109*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_NOT_SUPPORTED: 110*fcf3ce44SJohn Forte printf(MSGSTR(2412, "NOT SUPPORTED")); 111*fcf3ce44SJohn Forte return; 112*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_INVALID_HANDLE: 113*fcf3ce44SJohn Forte printf(MSGSTR(2413, "INVALID HANDLE")); 114*fcf3ce44SJohn Forte return; 115*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_ARG: 116*fcf3ce44SJohn Forte printf(MSGSTR(2414, "ERROR ARG")); 117*fcf3ce44SJohn Forte return; 118*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_ILLEGAL_WWN: 119*fcf3ce44SJohn Forte printf(MSGSTR(2415, "ILLEGAL WWN")); 120*fcf3ce44SJohn Forte return; 121*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_ILLEGAL_INDEX: 122*fcf3ce44SJohn Forte printf(MSGSTR(2416, "ILLEGAL INDEX")); 123*fcf3ce44SJohn Forte return; 124*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_MORE_DATA: 125*fcf3ce44SJohn Forte printf(MSGSTR(2417, "MORE DATA")); 126*fcf3ce44SJohn Forte return; 127*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_STALE_DATA: 128*fcf3ce44SJohn Forte printf(MSGSTR(2418, "STALE DATA")); 129*fcf3ce44SJohn Forte return; 130*fcf3ce44SJohn Forte case HBA_STATUS_SCSI_CHECK_CONDITION: 131*fcf3ce44SJohn Forte printf(MSGSTR(2419, "SCSI CHECK CONDITION")); 132*fcf3ce44SJohn Forte return; 133*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_BUSY: 134*fcf3ce44SJohn Forte printf(MSGSTR(2420, "BUSY")); 135*fcf3ce44SJohn Forte return; 136*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_TRY_AGAIN: 137*fcf3ce44SJohn Forte printf(MSGSTR(2421, "TRY AGAIN")); 138*fcf3ce44SJohn Forte return; 139*fcf3ce44SJohn Forte case HBA_STATUS_ERROR_UNAVAILABLE: 140*fcf3ce44SJohn Forte printf(MSGSTR(2422, "UNAVAILABLE")); 141*fcf3ce44SJohn Forte return; 142*fcf3ce44SJohn Forte default: 143*fcf3ce44SJohn Forte printf(MSGSTR(2423, "UNKNOWN ERROR TYPE %d"), status); 144*fcf3ce44SJohn Forte return; 145*fcf3ce44SJohn Forte } 146*fcf3ce44SJohn Forte } 147*fcf3ce44SJohn Forte 148*fcf3ce44SJohn Forte uint32_t 149*fcf3ce44SJohn Forte getNumberOfAdapters() { 150*fcf3ce44SJohn Forte uint32_t count = HBA_GetNumberOfAdapters(); 151*fcf3ce44SJohn Forte if (count == 0) { 152*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2405, 153*fcf3ce44SJohn Forte "\nERROR: No Fibre Channel Adapters found.\n")); 154*fcf3ce44SJohn Forte } 155*fcf3ce44SJohn Forte return (count); 156*fcf3ce44SJohn Forte } 157*fcf3ce44SJohn Forte 158*fcf3ce44SJohn Forte #define MAX_RETRIES 10 159*fcf3ce44SJohn Forte 160*fcf3ce44SJohn Forte /* 161*fcf3ce44SJohn Forte * Returns non-zero on failure (aka, HBA_STATUS_ERROR_* 162*fcf3ce44SJohn Forte * Will handle retries if applicable. 163*fcf3ce44SJohn Forte */ 164*fcf3ce44SJohn Forte int 165*fcf3ce44SJohn Forte getAdapterAttrs(HBA_HANDLE handle, char *name, HBA_ADAPTERATTRIBUTES *attrs) { 166*fcf3ce44SJohn Forte int count = 0; 167*fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */ 168*fcf3ce44SJohn Forte 169*fcf3ce44SJohn Forte /* Loop as long as we have a retryable error */ 170*fcf3ce44SJohn Forte while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 171*fcf3ce44SJohn Forte status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) { 172*fcf3ce44SJohn Forte status = HBA_GetAdapterAttributes(handle, attrs); 173*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 174*fcf3ce44SJohn Forte break; 175*fcf3ce44SJohn Forte } 176*fcf3ce44SJohn Forte (void) sleep(1); 177*fcf3ce44SJohn Forte } 178*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 179*fcf3ce44SJohn Forte /* We encountered a non-retryable error */ 180*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2501, 181*fcf3ce44SJohn Forte "\nERROR: Unable to retrieve adapter port details (%s)"), 182*fcf3ce44SJohn Forte name); 183*fcf3ce44SJohn Forte printStatus(status); 184*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 185*fcf3ce44SJohn Forte } 186*fcf3ce44SJohn Forte return (status); 187*fcf3ce44SJohn Forte } 188*fcf3ce44SJohn Forte 189*fcf3ce44SJohn Forte /* 190*fcf3ce44SJohn Forte * Returns non-zero on failure (aka, HBA_STATUS_ERROR_* 191*fcf3ce44SJohn Forte * Will handle retries if applicable. 192*fcf3ce44SJohn Forte */ 193*fcf3ce44SJohn Forte int 194*fcf3ce44SJohn Forte getAdapterPortAttrs(HBA_HANDLE handle, char *name, int portIndex, 195*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES *attrs) { 196*fcf3ce44SJohn Forte int count = 0; 197*fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */ 198*fcf3ce44SJohn Forte 199*fcf3ce44SJohn Forte /* Loop as long as we have a retryable error */ 200*fcf3ce44SJohn Forte while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 201*fcf3ce44SJohn Forte status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) { 202*fcf3ce44SJohn Forte status = HBA_GetAdapterPortAttributes(handle, portIndex, attrs); 203*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 204*fcf3ce44SJohn Forte break; 205*fcf3ce44SJohn Forte } 206*fcf3ce44SJohn Forte 207*fcf3ce44SJohn Forte /* The odds of this occuring are very slim, but possible. */ 208*fcf3ce44SJohn Forte if (status == HBA_STATUS_ERROR_STALE_DATA) { 209*fcf3ce44SJohn Forte /* 210*fcf3ce44SJohn Forte * If we hit a stale data scenario, 211*fcf3ce44SJohn Forte * we'll just tell the user to try again. 212*fcf3ce44SJohn Forte */ 213*fcf3ce44SJohn Forte status = HBA_STATUS_ERROR_TRY_AGAIN; 214*fcf3ce44SJohn Forte break; 215*fcf3ce44SJohn Forte } 216*fcf3ce44SJohn Forte sleep(1); 217*fcf3ce44SJohn Forte } 218*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 219*fcf3ce44SJohn Forte /* We encountered a non-retryable error */ 220*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2501, 221*fcf3ce44SJohn Forte "\nERROR: Unable to retrieve adapter port details (%s)"), 222*fcf3ce44SJohn Forte name); 223*fcf3ce44SJohn Forte printStatus(status); 224*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 225*fcf3ce44SJohn Forte } 226*fcf3ce44SJohn Forte return (status); 227*fcf3ce44SJohn Forte } 228*fcf3ce44SJohn Forte 229*fcf3ce44SJohn Forte /* 230*fcf3ce44SJohn Forte * Returns non-zero on failure (aka, HBA_STATUS_ERROR_* 231*fcf3ce44SJohn Forte * Will handle retries if applicable. 232*fcf3ce44SJohn Forte */ 233*fcf3ce44SJohn Forte int 234*fcf3ce44SJohn Forte getDiscPortAttrs(HBA_HANDLE handle, char *name, int portIndex, int discIndex, 235*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES *attrs) { 236*fcf3ce44SJohn Forte int count = 0; 237*fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */ 238*fcf3ce44SJohn Forte 239*fcf3ce44SJohn Forte /* Loop as long as we have a retryable error */ 240*fcf3ce44SJohn Forte while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 241*fcf3ce44SJohn Forte status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) { 242*fcf3ce44SJohn Forte status = HBA_GetDiscoveredPortAttributes(handle, portIndex, 243*fcf3ce44SJohn Forte discIndex, attrs); 244*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 245*fcf3ce44SJohn Forte break; 246*fcf3ce44SJohn Forte } 247*fcf3ce44SJohn Forte 248*fcf3ce44SJohn Forte /* The odds of this occuring are very slim, but possible. */ 249*fcf3ce44SJohn Forte if (status == HBA_STATUS_ERROR_STALE_DATA) { 250*fcf3ce44SJohn Forte /* 251*fcf3ce44SJohn Forte * If we hit a stale data scenario, we'll just tell the 252*fcf3ce44SJohn Forte * user to try again. 253*fcf3ce44SJohn Forte */ 254*fcf3ce44SJohn Forte status = HBA_STATUS_ERROR_TRY_AGAIN; 255*fcf3ce44SJohn Forte break; 256*fcf3ce44SJohn Forte } 257*fcf3ce44SJohn Forte sleep(1); 258*fcf3ce44SJohn Forte } 259*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 260*fcf3ce44SJohn Forte /* We encountered a non-retryable error */ 261*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2504, 262*fcf3ce44SJohn Forte "\nERROR: Unable to retrieve target port details (%s)"), 263*fcf3ce44SJohn Forte name); 264*fcf3ce44SJohn Forte printStatus(status); 265*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 266*fcf3ce44SJohn Forte } 267*fcf3ce44SJohn Forte return (status); 268*fcf3ce44SJohn Forte } 269*fcf3ce44SJohn Forte 270*fcf3ce44SJohn Forte 271*fcf3ce44SJohn Forte /*ARGSUSED*/ 272*fcf3ce44SJohn Forte int 273*fcf3ce44SJohn Forte fchba_display_port(int verbose) 274*fcf3ce44SJohn Forte { 275*fcf3ce44SJohn Forte int retval = 0; 276*fcf3ce44SJohn Forte HBA_HANDLE handle; 277*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 278*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 279*fcf3ce44SJohn Forte HBA_STATUS status; 280*fcf3ce44SJohn Forte int count, adapterIndex, portIndex; 281*fcf3ce44SJohn Forte char name[256]; 282*fcf3ce44SJohn Forte char *physical = NULL; 283*fcf3ce44SJohn Forte char path[MAXPATHLEN]; 284*fcf3ce44SJohn Forte 285*fcf3ce44SJohn Forte if ((retval = loadLibrary())) { 286*fcf3ce44SJohn Forte return (retval); 287*fcf3ce44SJohn Forte } 288*fcf3ce44SJohn Forte 289*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 290*fcf3ce44SJohn Forte 291*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 292*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 293*fcf3ce44SJohn Forte continue; 294*fcf3ce44SJohn Forte } 295*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 296*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 297*fcf3ce44SJohn Forte /* Just skip it, maybe it was DR'd */ 298*fcf3ce44SJohn Forte continue; 299*fcf3ce44SJohn Forte } 300*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 301*fcf3ce44SJohn Forte if (handle == 0) { 302*fcf3ce44SJohn Forte /* Just skip it, maybe it was DR'd */ 303*fcf3ce44SJohn Forte continue; 304*fcf3ce44SJohn Forte } 305*fcf3ce44SJohn Forte 306*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 307*fcf3ce44SJohn Forte /* This should never happen, we'll just skip the adapter */ 308*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 309*fcf3ce44SJohn Forte continue; 310*fcf3ce44SJohn Forte } 311*fcf3ce44SJohn Forte 312*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 313*fcf3ce44SJohn Forte portIndex++) { 314*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 315*fcf3ce44SJohn Forte &portAttrs)) { 316*fcf3ce44SJohn Forte continue; 317*fcf3ce44SJohn Forte } 318*fcf3ce44SJohn Forte physical = get_slash_devices_from_osDevName( 319*fcf3ce44SJohn Forte portAttrs.OSDeviceName, 320*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 321*fcf3ce44SJohn Forte if (physical) { 322*fcf3ce44SJohn Forte char *tmp = strstr(physical, ":fc"); 323*fcf3ce44SJohn Forte if (tmp) { 324*fcf3ce44SJohn Forte *tmp = '\0'; 325*fcf3ce44SJohn Forte (void) snprintf(path, MAXPATHLEN, "%s:devctl", 326*fcf3ce44SJohn Forte physical); 327*fcf3ce44SJohn Forte } else { 328*fcf3ce44SJohn Forte (void) snprintf(path, MAXPATHLEN, "%s", 329*fcf3ce44SJohn Forte physical); 330*fcf3ce44SJohn Forte } 331*fcf3ce44SJohn Forte free(physical); 332*fcf3ce44SJohn Forte physical = NULL; 333*fcf3ce44SJohn Forte (void) printf("%-65s ", path); 334*fcf3ce44SJohn Forte } else { 335*fcf3ce44SJohn Forte (void) printf("%-65s ", portAttrs.OSDeviceName); 336*fcf3ce44SJohn Forte } 337*fcf3ce44SJohn Forte if (portAttrs.NumberofDiscoveredPorts > 0) { 338*fcf3ce44SJohn Forte printf(MSGSTR(2233, "CONNECTED\n")); 339*fcf3ce44SJohn Forte } else { 340*fcf3ce44SJohn Forte printf(MSGSTR(2234, "NOT CONNECTED\n")); 341*fcf3ce44SJohn Forte } 342*fcf3ce44SJohn Forte } 343*fcf3ce44SJohn Forte } 344*fcf3ce44SJohn Forte (void) HBA_FreeLibrary(); 345*fcf3ce44SJohn Forte return (retval); 346*fcf3ce44SJohn Forte } 347*fcf3ce44SJohn Forte 348*fcf3ce44SJohn Forte /* 349*fcf3ce44SJohn Forte * Internal routines/structure to deal with a path list 350*fcf3ce44SJohn Forte * so we can ensure uniqueness 351*fcf3ce44SJohn Forte */ 352*fcf3ce44SJohn Forte struct path_entry { 353*fcf3ce44SJohn Forte char path[MAXPATHLEN]; 354*fcf3ce44SJohn Forte HBA_UINT8 wwn[8]; 355*fcf3ce44SJohn Forte uchar_t dtype; 356*fcf3ce44SJohn Forte struct path_entry *next; 357*fcf3ce44SJohn Forte }; 358*fcf3ce44SJohn Forte void add_path(struct path_entry *head, struct path_entry *cur) { 359*fcf3ce44SJohn Forte struct path_entry *tmp; 360*fcf3ce44SJohn Forte for (tmp = head; tmp->next != NULL; tmp = tmp->next) { } 361*fcf3ce44SJohn Forte tmp->next = cur; 362*fcf3ce44SJohn Forte } 363*fcf3ce44SJohn Forte struct path_entry *is_duplicate_path(struct path_entry *head, char *path) { 364*fcf3ce44SJohn Forte struct path_entry *tmp; 365*fcf3ce44SJohn Forte for (tmp = head; tmp != NULL; tmp = tmp->next) { 366*fcf3ce44SJohn Forte if (strncmp(tmp->path, path, sizeof (tmp->path)) == 0) { 367*fcf3ce44SJohn Forte return (tmp); 368*fcf3ce44SJohn Forte } 369*fcf3ce44SJohn Forte } 370*fcf3ce44SJohn Forte return (NULL); 371*fcf3ce44SJohn Forte } 372*fcf3ce44SJohn Forte void free_path_list(struct path_entry *head) { 373*fcf3ce44SJohn Forte struct path_entry *tmp; 374*fcf3ce44SJohn Forte struct path_entry *tmp2; 375*fcf3ce44SJohn Forte for (tmp = head; tmp != NULL; ) { 376*fcf3ce44SJohn Forte tmp2 = tmp->next; 377*fcf3ce44SJohn Forte free(tmp); 378*fcf3ce44SJohn Forte tmp = tmp2; 379*fcf3ce44SJohn Forte } 380*fcf3ce44SJohn Forte } 381*fcf3ce44SJohn Forte 382*fcf3ce44SJohn Forte 383*fcf3ce44SJohn Forte int 384*fcf3ce44SJohn Forte is_wwn(char *arg) { 385*fcf3ce44SJohn Forte int i; 386*fcf3ce44SJohn Forte if (strlen(arg) == 16) { 387*fcf3ce44SJohn Forte for (i = 0; i < 16; i++) { 388*fcf3ce44SJohn Forte if (!isxdigit(arg[i])) { 389*fcf3ce44SJohn Forte return (0); 390*fcf3ce44SJohn Forte } 391*fcf3ce44SJohn Forte } 392*fcf3ce44SJohn Forte return (1); 393*fcf3ce44SJohn Forte } 394*fcf3ce44SJohn Forte return (0); 395*fcf3ce44SJohn Forte } 396*fcf3ce44SJohn Forte 397*fcf3ce44SJohn Forte int 398*fcf3ce44SJohn Forte is_path(char *arg) { 399*fcf3ce44SJohn Forte struct stat buf; 400*fcf3ce44SJohn Forte if (stat(arg, &buf)) { 401*fcf3ce44SJohn Forte return (0); 402*fcf3ce44SJohn Forte } 403*fcf3ce44SJohn Forte return (1); 404*fcf3ce44SJohn Forte } 405*fcf3ce44SJohn Forte 406*fcf3ce44SJohn Forte /* We take a wild guess for our first get target mappings call */ 407*fcf3ce44SJohn Forte #define MAP_GUESS 50 408*fcf3ce44SJohn Forte 409*fcf3ce44SJohn Forte HBA_STATUS 410*fcf3ce44SJohn Forte fetch_mappings(HBA_HANDLE handle, HBA_WWN pwwn, HBA_FCPTARGETMAPPINGV2 **map) { 411*fcf3ce44SJohn Forte int loop = 0; 412*fcf3ce44SJohn Forte int count = 0; 413*fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */ 414*fcf3ce44SJohn Forte *map = (HBA_FCPTARGETMAPPINGV2 *) calloc(1, 415*fcf3ce44SJohn Forte (sizeof (HBA_FCPSCSIENTRYV2)* (MAP_GUESS-1)) + 416*fcf3ce44SJohn Forte sizeof (HBA_FCPTARGETMAPPINGV2)); 417*fcf3ce44SJohn Forte 418*fcf3ce44SJohn Forte /* Loop as long as we have a retryable error */ 419*fcf3ce44SJohn Forte while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 420*fcf3ce44SJohn Forte status == HBA_STATUS_ERROR_BUSY || 421*fcf3ce44SJohn Forte status == HBA_STATUS_ERROR_MORE_DATA) && loop++ < MAX_RETRIES) { 422*fcf3ce44SJohn Forte status = HBA_GetFcpTargetMappingV2(handle, pwwn, *map); 423*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 424*fcf3ce44SJohn Forte break; 425*fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_MORE_DATA) { 426*fcf3ce44SJohn Forte count = (*map)->NumberOfEntries; 427*fcf3ce44SJohn Forte free(*map); 428*fcf3ce44SJohn Forte *map = (HBA_FCPTARGETMAPPINGV2 *) calloc(1, 429*fcf3ce44SJohn Forte (sizeof (HBA_FCPSCSIENTRYV2)* (count-1)) + 430*fcf3ce44SJohn Forte sizeof (HBA_FCPTARGETMAPPINGV2)); 431*fcf3ce44SJohn Forte (*map)->NumberOfEntries = count; 432*fcf3ce44SJohn Forte continue; 433*fcf3ce44SJohn Forte } 434*fcf3ce44SJohn Forte sleep(1); 435*fcf3ce44SJohn Forte } 436*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 437*fcf3ce44SJohn Forte /* We encountered a non-retryable error */ 438*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2502, 439*fcf3ce44SJohn Forte "\nERROR: Unable to retrieve SCSI device paths " 440*fcf3ce44SJohn Forte "(HBA Port WWN %016llx)"), 441*fcf3ce44SJohn Forte wwnConversion(pwwn.wwn)); 442*fcf3ce44SJohn Forte printStatus(status); 443*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 444*fcf3ce44SJohn Forte } 445*fcf3ce44SJohn Forte return (status); 446*fcf3ce44SJohn Forte } 447*fcf3ce44SJohn Forte 448*fcf3ce44SJohn Forte /* 449*fcf3ce44SJohn Forte * Returns the index of the first match, or -1 if no match 450*fcf3ce44SJohn Forte */ 451*fcf3ce44SJohn Forte int 452*fcf3ce44SJohn Forte match_mappings(char *compare, HBA_FCPTARGETMAPPINGV2 *map) { 453*fcf3ce44SJohn Forte int mapIndex; 454*fcf3ce44SJohn Forte char *physical = NULL; 455*fcf3ce44SJohn Forte char *tmp; 456*fcf3ce44SJohn Forte int wwnCompare = 0; 457*fcf3ce44SJohn Forte uint64_t wwn; 458*fcf3ce44SJohn Forte 459*fcf3ce44SJohn Forte if (map == NULL || compare == NULL) { 460*fcf3ce44SJohn Forte return (-1); 461*fcf3ce44SJohn Forte } 462*fcf3ce44SJohn Forte 463*fcf3ce44SJohn Forte if (is_wwn(compare)) { 464*fcf3ce44SJohn Forte wwnCompare = 1; 465*fcf3ce44SJohn Forte (void) sscanf(compare, "%016llx", &wwn); 466*fcf3ce44SJohn Forte } else { 467*fcf3ce44SJohn Forte /* Convert the paths to phsyical paths */ 468*fcf3ce44SJohn Forte physical = get_slash_devices_from_osDevName(compare, 469*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 470*fcf3ce44SJohn Forte } 471*fcf3ce44SJohn Forte 472*fcf3ce44SJohn Forte for (mapIndex = 0; mapIndex < map->NumberOfEntries; mapIndex ++) { 473*fcf3ce44SJohn Forte if (wwnCompare) { 474*fcf3ce44SJohn Forte if (wwn == wwnConversion( 475*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.NodeWWN.wwn) || 476*fcf3ce44SJohn Forte wwn == wwnConversion( 477*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN.wwn)) { 478*fcf3ce44SJohn Forte return (mapIndex); 479*fcf3ce44SJohn Forte } 480*fcf3ce44SJohn Forte } else { 481*fcf3ce44SJohn Forte if (physical != NULL) { 482*fcf3ce44SJohn Forte tmp = get_slash_devices_from_osDevName( 483*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 484*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 485*fcf3ce44SJohn Forte if ((tmp != NULL) && 486*fcf3ce44SJohn Forte strncmp(physical, tmp, MAXPATHLEN) == 0) { 487*fcf3ce44SJohn Forte free(physical); 488*fcf3ce44SJohn Forte return (mapIndex); 489*fcf3ce44SJohn Forte } 490*fcf3ce44SJohn Forte } 491*fcf3ce44SJohn Forte } 492*fcf3ce44SJohn Forte } 493*fcf3ce44SJohn Forte if (physical) { 494*fcf3ce44SJohn Forte free(physical); 495*fcf3ce44SJohn Forte } 496*fcf3ce44SJohn Forte return (-1); 497*fcf3ce44SJohn Forte } 498*fcf3ce44SJohn Forte 499*fcf3ce44SJohn Forte 500*fcf3ce44SJohn Forte /* 501*fcf3ce44SJohn Forte * returns non-zero on failure (aka HBA_STATUS_ERROR_* 502*fcf3ce44SJohn Forte */ 503*fcf3ce44SJohn Forte int 504*fcf3ce44SJohn Forte loadLibrary() { 505*fcf3ce44SJohn Forte int status = HBA_LoadLibrary(); 506*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 507*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2505, 508*fcf3ce44SJohn Forte "ERROR: Unable to load HBA API library: ")); 509*fcf3ce44SJohn Forte printStatus(status); 510*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 511*fcf3ce44SJohn Forte } 512*fcf3ce44SJohn Forte return (status); 513*fcf3ce44SJohn Forte } 514*fcf3ce44SJohn Forte 515*fcf3ce44SJohn Forte int 516*fcf3ce44SJohn Forte fchba_non_encl_probe() { 517*fcf3ce44SJohn Forte HBA_HANDLE handle; 518*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 519*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 520*fcf3ce44SJohn Forte HBA_FCPTARGETMAPPINGV2 *map; 521*fcf3ce44SJohn Forte HBA_STATUS status; 522*fcf3ce44SJohn Forte int count, adapterIndex, portIndex, mapIndex; 523*fcf3ce44SJohn Forte char name[256]; 524*fcf3ce44SJohn Forte struct path_entry *head = NULL; 525*fcf3ce44SJohn Forte uint64_t lun = 0; 526*fcf3ce44SJohn Forte L_inquiry inq; 527*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 528*fcf3ce44SJohn Forte HBA_UINT8 scsiStatus; 529*fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq), senseSize = sizeof (sense); 530*fcf3ce44SJohn Forte 531*fcf3ce44SJohn Forte if (loadLibrary()) { 532*fcf3ce44SJohn Forte return (-1); 533*fcf3ce44SJohn Forte } 534*fcf3ce44SJohn Forte 535*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 536*fcf3ce44SJohn Forte 537*fcf3ce44SJohn Forte /* Loop over all HBAs */ 538*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 539*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 540*fcf3ce44SJohn Forte continue; 541*fcf3ce44SJohn Forte } 542*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 543*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 544*fcf3ce44SJohn Forte /* May have been DR'd */ 545*fcf3ce44SJohn Forte continue; 546*fcf3ce44SJohn Forte } 547*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 548*fcf3ce44SJohn Forte if (handle == 0) { 549*fcf3ce44SJohn Forte /* May have been DR'd */ 550*fcf3ce44SJohn Forte continue; 551*fcf3ce44SJohn Forte } 552*fcf3ce44SJohn Forte 553*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 554*fcf3ce44SJohn Forte /* Should not happen, just skip it */ 555*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 556*fcf3ce44SJohn Forte continue; 557*fcf3ce44SJohn Forte } 558*fcf3ce44SJohn Forte 559*fcf3ce44SJohn Forte 560*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 561*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 562*fcf3ce44SJohn Forte portIndex++) { 563*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 564*fcf3ce44SJohn Forte &portAttrs)) { 565*fcf3ce44SJohn Forte continue; 566*fcf3ce44SJohn Forte } 567*fcf3ce44SJohn Forte 568*fcf3ce44SJohn Forte if (fetch_mappings(handle, portAttrs.PortWWN, &map)) { 569*fcf3ce44SJohn Forte continue; 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte 572*fcf3ce44SJohn Forte /* Loop over all target Mapping entries */ 573*fcf3ce44SJohn Forte for (mapIndex = 0; mapIndex < map->NumberOfEntries; 574*fcf3ce44SJohn Forte mapIndex ++) { 575*fcf3ce44SJohn Forte struct path_entry *tmpPath = NULL; 576*fcf3ce44SJohn Forte int doInquiry = 0; 577*fcf3ce44SJohn Forte if (!head) { 578*fcf3ce44SJohn Forte head = (struct path_entry *)calloc(1, 579*fcf3ce44SJohn Forte sizeof (struct path_entry)); 580*fcf3ce44SJohn Forte tmpPath = head; 581*fcf3ce44SJohn Forte strncpy(head->path, 582*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 583*fcf3ce44SJohn Forte sizeof (map->entry[mapIndex].ScsiId.OSDeviceName)); 584*fcf3ce44SJohn Forte (void) memcpy(tmpPath->wwn, 585*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.NodeWWN.wwn, 586*fcf3ce44SJohn Forte sizeof (HBA_UINT8) * 8); 587*fcf3ce44SJohn Forte doInquiry = 1; 588*fcf3ce44SJohn Forte } else if (tmpPath = is_duplicate_path(head, 589*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName)) { 590*fcf3ce44SJohn Forte if (tmpPath->dtype != 0x1f) { 591*fcf3ce44SJohn Forte doInquiry = 0; 592*fcf3ce44SJohn Forte } else { 593*fcf3ce44SJohn Forte doInquiry = 1; 594*fcf3ce44SJohn Forte } 595*fcf3ce44SJohn Forte } else { 596*fcf3ce44SJohn Forte tmpPath = (struct path_entry *) 597*fcf3ce44SJohn Forte calloc(1, sizeof (struct path_entry)); 598*fcf3ce44SJohn Forte strncpy(tmpPath->path, 599*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 600*fcf3ce44SJohn Forte sizeof (map->entry[mapIndex].ScsiId.OSDeviceName)); 601*fcf3ce44SJohn Forte (void) memcpy(tmpPath->wwn, 602*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.NodeWWN.wwn, 603*fcf3ce44SJohn Forte sizeof (HBA_UINT8) * 8); 604*fcf3ce44SJohn Forte add_path(head, tmpPath); 605*fcf3ce44SJohn Forte doInquiry = 1; 606*fcf3ce44SJohn Forte } 607*fcf3ce44SJohn Forte 608*fcf3ce44SJohn Forte if (doInquiry) { 609*fcf3ce44SJohn Forte lun = map->entry[mapIndex].FcpId.FcpLun; 610*fcf3ce44SJohn Forte memset(&inq, 0, sizeof (inq)); 611*fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense)); 612*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 613*fcf3ce44SJohn Forte portAttrs.PortWWN, 614*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN, 615*fcf3ce44SJohn Forte lun, 0, 0, 616*fcf3ce44SJohn Forte &inq, &inquirySize, 617*fcf3ce44SJohn Forte &scsiStatus, 618*fcf3ce44SJohn Forte &sense, &senseSize); 619*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 620*fcf3ce44SJohn Forte inq.inq_dtype = 0x1f; 621*fcf3ce44SJohn Forte } 622*fcf3ce44SJohn Forte tmpPath->dtype = inq.inq_dtype; 623*fcf3ce44SJohn Forte } 624*fcf3ce44SJohn Forte } 625*fcf3ce44SJohn Forte } 626*fcf3ce44SJohn Forte } 627*fcf3ce44SJohn Forte if (head) { 628*fcf3ce44SJohn Forte struct path_entry *tmp; 629*fcf3ce44SJohn Forte printf(MSGSTR(2098, "\nFound Fibre Channel device(s):\n")); 630*fcf3ce44SJohn Forte for (tmp = head; tmp != NULL; tmp = tmp->next) { 631*fcf3ce44SJohn Forte printf(" "); 632*fcf3ce44SJohn Forte printf(MSGSTR(90, "Node WWN:")); 633*fcf3ce44SJohn Forte printf("%016llx ", wwnConversion(tmp->wwn)); 634*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(35, "Device Type:")); 635*fcf3ce44SJohn Forte (void) fflush(stdout); 636*fcf3ce44SJohn Forte 637*fcf3ce44SJohn Forte if ((tmp->dtype & DTYPE_MASK) < 0x10) { 638*fcf3ce44SJohn Forte fprintf(stdout, "%s", 639*fcf3ce44SJohn Forte dtype[tmp->dtype & DTYPE_MASK]); 640*fcf3ce44SJohn Forte } else if ((tmp->dtype & DTYPE_MASK) < 0x1f) { 641*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2406, 642*fcf3ce44SJohn Forte "Reserved")); 643*fcf3ce44SJohn Forte } else { 644*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2407, 645*fcf3ce44SJohn Forte "Unknown")); 646*fcf3ce44SJohn Forte } 647*fcf3ce44SJohn Forte 648*fcf3ce44SJohn Forte printf("\n "); 649*fcf3ce44SJohn Forte printf(MSGSTR(31, "Logical Path:%s"), tmp->path); 650*fcf3ce44SJohn Forte printf("\n"); 651*fcf3ce44SJohn Forte 652*fcf3ce44SJohn Forte /* We probably shouldn't be using a g_fc interface here */ 653*fcf3ce44SJohn Forte if (Options & OPTION_P) { 654*fcf3ce44SJohn Forte char *phys_path = 655*fcf3ce44SJohn Forte get_slash_devices_from_osDevName( 656*fcf3ce44SJohn Forte tmp->path, 657*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 658*fcf3ce44SJohn Forte if (phys_path != NULL) { 659*fcf3ce44SJohn Forte fprintf(stdout, " "); 660*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(5, "Physical Path:")); 661*fcf3ce44SJohn Forte fprintf(stdout, "\n %s\n", phys_path); 662*fcf3ce44SJohn Forte free(phys_path); 663*fcf3ce44SJohn Forte } 664*fcf3ce44SJohn Forte } 665*fcf3ce44SJohn Forte } 666*fcf3ce44SJohn Forte free_path_list(head); 667*fcf3ce44SJohn Forte } 668*fcf3ce44SJohn Forte HBA_FreeLibrary(); 669*fcf3ce44SJohn Forte return (0); 670*fcf3ce44SJohn Forte } 671*fcf3ce44SJohn Forte 672*fcf3ce44SJohn Forte 673*fcf3ce44SJohn Forte int 674*fcf3ce44SJohn Forte fchba_inquiry(char **argv) 675*fcf3ce44SJohn Forte { 676*fcf3ce44SJohn Forte int path_index = 0, found = 0; 677*fcf3ce44SJohn Forte uint64_t wwn; 678*fcf3ce44SJohn Forte uint64_t lun = 0; 679*fcf3ce44SJohn Forte HBA_HANDLE handle; 680*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 681*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 682*fcf3ce44SJohn Forte HBA_FCPTARGETMAPPINGV2 *map; 683*fcf3ce44SJohn Forte HBA_STATUS status; 684*fcf3ce44SJohn Forte int count, adapterIndex, portIndex, mapIndex; 685*fcf3ce44SJohn Forte char name[256]; 686*fcf3ce44SJohn Forte L_inquiry inq; 687*fcf3ce44SJohn Forte struct page80 serial; 688*fcf3ce44SJohn Forte uint32_t serialSize = sizeof (serial); 689*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 690*fcf3ce44SJohn Forte HBA_UINT8 scsiStatus; 691*fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq), senseSize = sizeof (sense); 692*fcf3ce44SJohn Forte boolean_t goodPath = B_FALSE; 693*fcf3ce44SJohn Forte int matched = 0, wwnCompare = 0; 694*fcf3ce44SJohn Forte char *tmp, *physical = NULL; 695*fcf3ce44SJohn Forte int ret = 0; 696*fcf3ce44SJohn Forte 697*fcf3ce44SJohn Forte if (loadLibrary()) { 698*fcf3ce44SJohn Forte return (-1); 699*fcf3ce44SJohn Forte } 700*fcf3ce44SJohn Forte for (path_index = 0; argv[path_index] != NULL; path_index++) { 701*fcf3ce44SJohn Forte goodPath = B_FALSE; 702*fcf3ce44SJohn Forte found = 0; 703*fcf3ce44SJohn Forte 704*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 705*fcf3ce44SJohn Forte (void) sscanf(argv[path_index], "%016llx", &wwn); 706*fcf3ce44SJohn Forte wwnCompare = 1; 707*fcf3ce44SJohn Forte } else if (!is_path(argv[path_index])) { 708*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 709*fcf3ce44SJohn Forte argv[path_index]); 710*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 711*fcf3ce44SJohn Forte ret = -1; 712*fcf3ce44SJohn Forte continue; 713*fcf3ce44SJohn Forte } 714*fcf3ce44SJohn Forte if (!wwnCompare) { 715*fcf3ce44SJohn Forte /* Convert the paths to phsyical paths */ 716*fcf3ce44SJohn Forte physical = get_slash_devices_from_osDevName(argv[path_index], 717*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 718*fcf3ce44SJohn Forte if (!physical) { 719*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, 720*fcf3ce44SJohn Forte "Error: Invalid pathname (%s)"), 721*fcf3ce44SJohn Forte argv[path_index]); 722*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 723*fcf3ce44SJohn Forte ret = -1; 724*fcf3ce44SJohn Forte continue; 725*fcf3ce44SJohn Forte } 726*fcf3ce44SJohn Forte } 727*fcf3ce44SJohn Forte 728*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 729*fcf3ce44SJohn Forte 730*fcf3ce44SJohn Forte /* Loop over all HBAs */ 731*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 732*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 733*fcf3ce44SJohn Forte continue; 734*fcf3ce44SJohn Forte } 735*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 736*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 737*fcf3ce44SJohn Forte /* May have been DR'd */ 738*fcf3ce44SJohn Forte continue; 739*fcf3ce44SJohn Forte } 740*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 741*fcf3ce44SJohn Forte if (handle == 0) { 742*fcf3ce44SJohn Forte /* May have been DR'd */ 743*fcf3ce44SJohn Forte continue; 744*fcf3ce44SJohn Forte } 745*fcf3ce44SJohn Forte 746*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 747*fcf3ce44SJohn Forte /* Should never happen */ 748*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 749*fcf3ce44SJohn Forte continue; 750*fcf3ce44SJohn Forte } 751*fcf3ce44SJohn Forte 752*fcf3ce44SJohn Forte 753*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 754*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 755*fcf3ce44SJohn Forte portIndex++) { 756*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 757*fcf3ce44SJohn Forte &portAttrs)) { 758*fcf3ce44SJohn Forte continue; 759*fcf3ce44SJohn Forte } 760*fcf3ce44SJohn Forte 761*fcf3ce44SJohn Forte if (fetch_mappings(handle, portAttrs.PortWWN, &map)) { 762*fcf3ce44SJohn Forte continue; 763*fcf3ce44SJohn Forte } 764*fcf3ce44SJohn Forte 765*fcf3ce44SJohn Forte for (mapIndex = 0; mapIndex < map->NumberOfEntries; 766*fcf3ce44SJohn Forte mapIndex ++) { 767*fcf3ce44SJohn Forte matched = 0; 768*fcf3ce44SJohn Forte if (wwnCompare) { 769*fcf3ce44SJohn Forte if (wwn == wwnConversion( 770*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.NodeWWN.wwn) || 771*fcf3ce44SJohn Forte wwn == wwnConversion( 772*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN.wwn)) { 773*fcf3ce44SJohn Forte lun = map->entry[mapIndex].FcpId.FcpLun; 774*fcf3ce44SJohn Forte matched = 1; 775*fcf3ce44SJohn Forte } 776*fcf3ce44SJohn Forte } else { 777*fcf3ce44SJohn Forte tmp = get_slash_devices_from_osDevName( 778*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 779*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 780*fcf3ce44SJohn Forte if ((tmp != NULL) && (strncmp(physical, tmp, 781*fcf3ce44SJohn Forte MAXPATHLEN) == 0)) { 782*fcf3ce44SJohn Forte lun = map->entry[mapIndex].FcpId.FcpLun; 783*fcf3ce44SJohn Forte matched = 1; 784*fcf3ce44SJohn Forte free(tmp); 785*fcf3ce44SJohn Forte } 786*fcf3ce44SJohn Forte } 787*fcf3ce44SJohn Forte 788*fcf3ce44SJohn Forte if (matched) { 789*fcf3ce44SJohn Forte memset(&inq, 0, sizeof (inq)); 790*fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense)); 791*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 792*fcf3ce44SJohn Forte portAttrs.PortWWN, 793*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN, 794*fcf3ce44SJohn Forte lun, 0, 0, 795*fcf3ce44SJohn Forte &inq, &inquirySize, 796*fcf3ce44SJohn Forte &scsiStatus, 797*fcf3ce44SJohn Forte &sense, &senseSize); 798*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 799*fcf3ce44SJohn Forte goodPath = B_TRUE; 800*fcf3ce44SJohn Forte /* 801*fcf3ce44SJohn Forte * Call the inquiry cmd on page 0x80 only if 802*fcf3ce44SJohn Forte * the vendor supports page 0x80 803*fcf3ce44SJohn Forte */ 804*fcf3ce44SJohn Forte memset(&serial, 0, sizeof (serial)); 805*fcf3ce44SJohn Forte if ((find_supported_inq_page(handle, 806*fcf3ce44SJohn Forte portAttrs.PortWWN, 807*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN, 808*fcf3ce44SJohn Forte lun, 0x80))) { 809*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 810*fcf3ce44SJohn Forte portAttrs.PortWWN, 811*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN, 812*fcf3ce44SJohn Forte lun, 1, 0x80, 813*fcf3ce44SJohn Forte &serial, &serialSize, 814*fcf3ce44SJohn Forte &scsiStatus, 815*fcf3ce44SJohn Forte &sense, &senseSize); 816*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 817*fcf3ce44SJohn Forte strncpy( 818*fcf3ce44SJohn Forte (char *)serial.inq_serial, 819*fcf3ce44SJohn Forte "Unavailable", 820*fcf3ce44SJohn Forte sizeof (serial.inq_serial)); 821*fcf3ce44SJohn Forte } 822*fcf3ce44SJohn Forte } else { 823*fcf3ce44SJohn Forte strncpy((char *)serial.inq_serial, 824*fcf3ce44SJohn Forte "Unsupported", 825*fcf3ce44SJohn Forte sizeof (serial.inq_serial)); 826*fcf3ce44SJohn Forte } 827*fcf3ce44SJohn Forte /* 828*fcf3ce44SJohn Forte * we are adding serial number information 829*fcf3ce44SJohn Forte * from 0x80. If length is less than 39, 830*fcf3ce44SJohn Forte * then we want to increase length to 52 to 831*fcf3ce44SJohn Forte * reflect the fact that we have serial number 832*fcf3ce44SJohn Forte * information 833*fcf3ce44SJohn Forte */ 834*fcf3ce44SJohn Forte if (inq.inq_len < 39) { 835*fcf3ce44SJohn Forte inq.inq_len = 52; 836*fcf3ce44SJohn Forte } 837*fcf3ce44SJohn Forte print_inq_data(argv[path_index], 838*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 839*fcf3ce44SJohn Forte inq, serial.inq_serial, 840*fcf3ce44SJohn Forte sizeof (serial.inq_serial)); 841*fcf3ce44SJohn Forte if (! wwnCompare) { 842*fcf3ce44SJohn Forte found = 1; 843*fcf3ce44SJohn Forte break; 844*fcf3ce44SJohn Forte } 845*fcf3ce44SJohn Forte } else { 846*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2430, 847*fcf3ce44SJohn Forte "Error: I/O failure communicating with %s "), 848*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName); 849*fcf3ce44SJohn Forte printStatus(status); 850*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 851*fcf3ce44SJohn Forte } 852*fcf3ce44SJohn Forte } 853*fcf3ce44SJohn Forte } 854*fcf3ce44SJohn Forte if (found == 1) { 855*fcf3ce44SJohn Forte break; 856*fcf3ce44SJohn Forte } 857*fcf3ce44SJohn Forte } 858*fcf3ce44SJohn Forte if (found == 1) { 859*fcf3ce44SJohn Forte break; 860*fcf3ce44SJohn Forte } 861*fcf3ce44SJohn Forte } 862*fcf3ce44SJohn Forte 863*fcf3ce44SJohn Forte if (physical) { 864*fcf3ce44SJohn Forte free(physical); 865*fcf3ce44SJohn Forte } 866*fcf3ce44SJohn Forte 867*fcf3ce44SJohn Forte if (!goodPath) { 868*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 869*fcf3ce44SJohn Forte argv[path_index]); 870*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 871*fcf3ce44SJohn Forte ret = -1; 872*fcf3ce44SJohn Forte } 873*fcf3ce44SJohn Forte } 874*fcf3ce44SJohn Forte return (ret); 875*fcf3ce44SJohn Forte } 876*fcf3ce44SJohn Forte 877*fcf3ce44SJohn Forte 878*fcf3ce44SJohn Forte 879*fcf3ce44SJohn Forte int 880*fcf3ce44SJohn Forte fchba_dump_map(char **argv) 881*fcf3ce44SJohn Forte { 882*fcf3ce44SJohn Forte int path_index = 0; 883*fcf3ce44SJohn Forte uint64_t wwn; 884*fcf3ce44SJohn Forte uint64_t lun = 0; 885*fcf3ce44SJohn Forte HBA_HANDLE handle; 886*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 887*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 888*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES discPortAttrs; 889*fcf3ce44SJohn Forte HBA_FCPTARGETMAPPINGV2 *map; 890*fcf3ce44SJohn Forte HBA_STATUS status; 891*fcf3ce44SJohn Forte int count, adapterIndex, portIndex, mapIndex, discIndex; 892*fcf3ce44SJohn Forte char name[256], *physical, *comp_phys; 893*fcf3ce44SJohn Forte L_inquiry inq; 894*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 895*fcf3ce44SJohn Forte HBA_UINT8 scsiStatus; 896*fcf3ce44SJohn Forte int matched; 897*fcf3ce44SJohn Forte int done; 898*fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq), senseSize = sizeof (sense); 899*fcf3ce44SJohn Forte boolean_t goodPath = B_FALSE; 900*fcf3ce44SJohn Forte int ret = 0; 901*fcf3ce44SJohn Forte uint32_t responseSize = DEFAULT_LUN_LENGTH; 902*fcf3ce44SJohn Forte uchar_t raw_luns[DEFAULT_LUN_LENGTH]; 903*fcf3ce44SJohn Forte struct rep_luns_rsp *lun_resp; 904*fcf3ce44SJohn Forte 905*fcf3ce44SJohn Forte 906*fcf3ce44SJohn Forte if (loadLibrary()) { 907*fcf3ce44SJohn Forte return (-1); 908*fcf3ce44SJohn Forte } 909*fcf3ce44SJohn Forte for (path_index = 0; argv[path_index] != NULL; path_index++) { 910*fcf3ce44SJohn Forte goodPath = B_FALSE; 911*fcf3ce44SJohn Forte 912*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 913*fcf3ce44SJohn Forte (void) sscanf(argv[path_index], "%016llx", &wwn); 914*fcf3ce44SJohn Forte } else if (!is_path(argv[path_index])) { 915*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 916*fcf3ce44SJohn Forte argv[path_index]); 917*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 918*fcf3ce44SJohn Forte ret = -1; 919*fcf3ce44SJohn Forte continue; 920*fcf3ce44SJohn Forte } 921*fcf3ce44SJohn Forte 922*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 923*fcf3ce44SJohn Forte 924*fcf3ce44SJohn Forte done = 0; 925*fcf3ce44SJohn Forte /* Loop over all HBAs */ 926*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count && !done; 927*fcf3ce44SJohn Forte adapterIndex ++) { 928*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 929*fcf3ce44SJohn Forte continue; 930*fcf3ce44SJohn Forte } 931*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 932*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 933*fcf3ce44SJohn Forte /* May have been DR'd */ 934*fcf3ce44SJohn Forte continue; 935*fcf3ce44SJohn Forte } 936*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 937*fcf3ce44SJohn Forte if (handle == 0) { 938*fcf3ce44SJohn Forte /* May have been DR'd */ 939*fcf3ce44SJohn Forte continue; 940*fcf3ce44SJohn Forte } 941*fcf3ce44SJohn Forte 942*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 943*fcf3ce44SJohn Forte /* Should never happen */ 944*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 945*fcf3ce44SJohn Forte continue; 946*fcf3ce44SJohn Forte } 947*fcf3ce44SJohn Forte 948*fcf3ce44SJohn Forte 949*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 950*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts && !done; 951*fcf3ce44SJohn Forte portIndex++) { 952*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 953*fcf3ce44SJohn Forte &portAttrs)) { 954*fcf3ce44SJohn Forte continue; 955*fcf3ce44SJohn Forte } 956*fcf3ce44SJohn Forte 957*fcf3ce44SJohn Forte 958*fcf3ce44SJohn Forte matched = 0; 959*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 960*fcf3ce44SJohn Forte if (wwn == wwnConversion( 961*fcf3ce44SJohn Forte portAttrs.NodeWWN.wwn) || 962*fcf3ce44SJohn Forte wwn == wwnConversion( 963*fcf3ce44SJohn Forte portAttrs.PortWWN.wwn)) { 964*fcf3ce44SJohn Forte matched = 1; 965*fcf3ce44SJohn Forte } 966*fcf3ce44SJohn Forte } else { 967*fcf3ce44SJohn Forte if (is_path(argv[path_index]) && 968*fcf3ce44SJohn Forte ((physical = get_slash_devices_from_osDevName( 969*fcf3ce44SJohn Forte argv[path_index], 970*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING)) != NULL) && 971*fcf3ce44SJohn Forte ((comp_phys = get_slash_devices_from_osDevName( 972*fcf3ce44SJohn Forte portAttrs.OSDeviceName, 973*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING)) != NULL)) { 974*fcf3ce44SJohn Forte char *tmp = strstr(physical, ":devctl"); 975*fcf3ce44SJohn Forte if (tmp) { 976*fcf3ce44SJohn Forte *tmp = '\0'; 977*fcf3ce44SJohn Forte } else { 978*fcf3ce44SJohn Forte tmp = strstr(physical, ":fc"); 979*fcf3ce44SJohn Forte if (tmp) { 980*fcf3ce44SJohn Forte *tmp = '\0'; 981*fcf3ce44SJohn Forte } 982*fcf3ce44SJohn Forte } 983*fcf3ce44SJohn Forte if (strstr(comp_phys, physical)) { 984*fcf3ce44SJohn Forte matched = 1; 985*fcf3ce44SJohn Forte } 986*fcf3ce44SJohn Forte } 987*fcf3ce44SJohn Forte if (physical) { 988*fcf3ce44SJohn Forte free(physical); 989*fcf3ce44SJohn Forte physical = NULL; 990*fcf3ce44SJohn Forte } 991*fcf3ce44SJohn Forte if (comp_phys) { 992*fcf3ce44SJohn Forte free(comp_phys); 993*fcf3ce44SJohn Forte comp_phys = NULL; 994*fcf3ce44SJohn Forte } 995*fcf3ce44SJohn Forte } 996*fcf3ce44SJohn Forte 997*fcf3ce44SJohn Forte if (!fetch_mappings(handle, portAttrs.PortWWN, &map)) { 998*fcf3ce44SJohn Forte mapIndex = match_mappings(argv[path_index], map); 999*fcf3ce44SJohn Forte if (mapIndex >= 0) { 1000*fcf3ce44SJohn Forte matched = 1; 1001*fcf3ce44SJohn Forte } 1002*fcf3ce44SJohn Forte } else { 1003*fcf3ce44SJohn Forte continue; 1004*fcf3ce44SJohn Forte } 1005*fcf3ce44SJohn Forte 1006*fcf3ce44SJohn Forte if (matched) { 1007*fcf3ce44SJohn Forte goodPath = B_TRUE; 1008*fcf3ce44SJohn Forte printf(MSGSTR(2095, 1009*fcf3ce44SJohn Forte "Pos Port_ID Hard_Addr Port WWN" 1010*fcf3ce44SJohn Forte " Node WWN Type\n")); 1011*fcf3ce44SJohn Forte for (discIndex = 0; 1012*fcf3ce44SJohn Forte discIndex < portAttrs.NumberofDiscoveredPorts; 1013*fcf3ce44SJohn Forte discIndex++) { 1014*fcf3ce44SJohn Forte if (getDiscPortAttrs(handle, name, portIndex, 1015*fcf3ce44SJohn Forte discIndex, &discPortAttrs)) { 1016*fcf3ce44SJohn Forte /* Move on to the next target */ 1017*fcf3ce44SJohn Forte continue; 1018*fcf3ce44SJohn Forte } 1019*fcf3ce44SJohn Forte 1020*fcf3ce44SJohn Forte printf("%-4d %-6x %-6x %016llx %016llx", 1021*fcf3ce44SJohn Forte discIndex, 1022*fcf3ce44SJohn Forte discPortAttrs.PortFcId, 0, 1023*fcf3ce44SJohn Forte wwnConversion(discPortAttrs.PortWWN.wwn), 1024*fcf3ce44SJohn Forte wwnConversion(discPortAttrs.NodeWWN.wwn)); 1025*fcf3ce44SJohn Forte 1026*fcf3ce44SJohn Forte /* 1027*fcf3ce44SJohn Forte * devices are not all required to respond to 1028*fcf3ce44SJohn Forte * Scsi Inquiry calls sent to LUN 0. We must 1029*fcf3ce44SJohn Forte * fisrt issue a ReportLUN and then send the 1030*fcf3ce44SJohn Forte * SCSI Inquiry call to the first LUN Returned 1031*fcf3ce44SJohn Forte * from the ReportLUN call 1032*fcf3ce44SJohn Forte */ 1033*fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense)); 1034*fcf3ce44SJohn Forte status = HBA_ScsiReportLUNsV2(handle, 1035*fcf3ce44SJohn Forte portAttrs.PortWWN, 1036*fcf3ce44SJohn Forte discPortAttrs.PortWWN, 1037*fcf3ce44SJohn Forte (void *)raw_luns, &responseSize, &scsiStatus, 1038*fcf3ce44SJohn Forte (void *)&sense, &senseSize); 1039*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 1040*fcf3ce44SJohn Forte lun_resp = 1041*fcf3ce44SJohn Forte (struct rep_luns_rsp *) 1042*fcf3ce44SJohn Forte (unsigned long)raw_luns; 1043*fcf3ce44SJohn Forte lun = ntohll( 1044*fcf3ce44SJohn Forte wwnConversion(lun_resp->lun[0].val)); 1045*fcf3ce44SJohn Forte } else { 1046*fcf3ce44SJohn Forte /* 1047*fcf3ce44SJohn Forte * in case we are unable to retrieve report 1048*fcf3ce44SJohn Forte * LUN data, we will blindly try sending the 1049*fcf3ce44SJohn Forte * INQUIRY to lun 0. 1050*fcf3ce44SJohn Forte */ 1051*fcf3ce44SJohn Forte lun = 0; 1052*fcf3ce44SJohn Forte } 1053*fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense)); 1054*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 1055*fcf3ce44SJohn Forte portAttrs.PortWWN, 1056*fcf3ce44SJohn Forte discPortAttrs.PortWWN, 1057*fcf3ce44SJohn Forte lun, 0, 0, 1058*fcf3ce44SJohn Forte &inq, &inquirySize, 1059*fcf3ce44SJohn Forte &scsiStatus, 1060*fcf3ce44SJohn Forte &sense, &senseSize); 1061*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1062*fcf3ce44SJohn Forte inq.inq_dtype = 0x1f; 1063*fcf3ce44SJohn Forte } 1064*fcf3ce44SJohn Forte print_fabric_dtype_prop(portAttrs.PortWWN.wwn, 1065*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN.wwn, 1066*fcf3ce44SJohn Forte inq.inq_dtype); 1067*fcf3ce44SJohn Forte } 1068*fcf3ce44SJohn Forte /* Now dump this HBA's stats */ 1069*fcf3ce44SJohn Forte printf("%-4d %-6x %-6x %016llx %016llx", 1070*fcf3ce44SJohn Forte discIndex, 1071*fcf3ce44SJohn Forte portAttrs.PortFcId, 0, 1072*fcf3ce44SJohn Forte wwnConversion(portAttrs.PortWWN.wwn), 1073*fcf3ce44SJohn Forte wwnConversion(portAttrs.NodeWWN.wwn)); 1074*fcf3ce44SJohn Forte print_fabric_dtype_prop(portAttrs.PortWWN.wwn, 1075*fcf3ce44SJohn Forte portAttrs.PortWWN.wwn, 0x1f); 1076*fcf3ce44SJohn Forte done = 1; 1077*fcf3ce44SJohn Forte } 1078*fcf3ce44SJohn Forte } 1079*fcf3ce44SJohn Forte } 1080*fcf3ce44SJohn Forte if (!goodPath) { 1081*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 1082*fcf3ce44SJohn Forte argv[path_index]); 1083*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1084*fcf3ce44SJohn Forte ret = -1; 1085*fcf3ce44SJohn Forte } 1086*fcf3ce44SJohn Forte } 1087*fcf3ce44SJohn Forte return (ret); 1088*fcf3ce44SJohn Forte } 1089*fcf3ce44SJohn Forte 1090*fcf3ce44SJohn Forte int 1091*fcf3ce44SJohn Forte fchba_display_link_status(char **argv) 1092*fcf3ce44SJohn Forte { 1093*fcf3ce44SJohn Forte int path_index = 0; 1094*fcf3ce44SJohn Forte uint64_t wwn; 1095*fcf3ce44SJohn Forte HBA_HANDLE handle; 1096*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 1097*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 1098*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES discPortAttrs; 1099*fcf3ce44SJohn Forte HBA_FCPTARGETMAPPINGV2 *map; 1100*fcf3ce44SJohn Forte HBA_STATUS status; 1101*fcf3ce44SJohn Forte int count, adapterIndex, portIndex, discIndex; 1102*fcf3ce44SJohn Forte char name[256], *physical, *comp_phys; 1103*fcf3ce44SJohn Forte int matched; 1104*fcf3ce44SJohn Forte struct fc_rls_acc_params rls; 1105*fcf3ce44SJohn Forte uint32_t rls_size = sizeof (rls); 1106*fcf3ce44SJohn Forte boolean_t goodPath = B_FALSE; 1107*fcf3ce44SJohn Forte int ret = 0; 1108*fcf3ce44SJohn Forte 1109*fcf3ce44SJohn Forte if (loadLibrary()) { 1110*fcf3ce44SJohn Forte return (-1); 1111*fcf3ce44SJohn Forte } 1112*fcf3ce44SJohn Forte for (path_index = 0; argv[path_index] != NULL; path_index++) { 1113*fcf3ce44SJohn Forte goodPath = B_FALSE; 1114*fcf3ce44SJohn Forte 1115*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 1116*fcf3ce44SJohn Forte (void) sscanf(argv[path_index], "%016llx", &wwn); 1117*fcf3ce44SJohn Forte } else if (!is_path(argv[path_index])) { 1118*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 1119*fcf3ce44SJohn Forte argv[path_index]); 1120*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1121*fcf3ce44SJohn Forte ret = -1; 1122*fcf3ce44SJohn Forte continue; 1123*fcf3ce44SJohn Forte } 1124*fcf3ce44SJohn Forte 1125*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 1126*fcf3ce44SJohn Forte 1127*fcf3ce44SJohn Forte /* Loop over all HBAs */ 1128*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 1129*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 1130*fcf3ce44SJohn Forte continue; 1131*fcf3ce44SJohn Forte } 1132*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 1133*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1134*fcf3ce44SJohn Forte /* May have been DR'd */ 1135*fcf3ce44SJohn Forte continue; 1136*fcf3ce44SJohn Forte } 1137*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 1138*fcf3ce44SJohn Forte if (handle == 0) { 1139*fcf3ce44SJohn Forte /* May have been DR'd */ 1140*fcf3ce44SJohn Forte continue; 1141*fcf3ce44SJohn Forte } 1142*fcf3ce44SJohn Forte 1143*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 1144*fcf3ce44SJohn Forte /* Should never happen */ 1145*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1146*fcf3ce44SJohn Forte continue; 1147*fcf3ce44SJohn Forte } 1148*fcf3ce44SJohn Forte 1149*fcf3ce44SJohn Forte 1150*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 1151*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 1152*fcf3ce44SJohn Forte portIndex++) { 1153*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 1154*fcf3ce44SJohn Forte &portAttrs)) { 1155*fcf3ce44SJohn Forte continue; 1156*fcf3ce44SJohn Forte } 1157*fcf3ce44SJohn Forte 1158*fcf3ce44SJohn Forte matched = 0; 1159*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 1160*fcf3ce44SJohn Forte if (wwn == wwnConversion( 1161*fcf3ce44SJohn Forte portAttrs.NodeWWN.wwn) || 1162*fcf3ce44SJohn Forte wwn == wwnConversion( 1163*fcf3ce44SJohn Forte portAttrs.PortWWN.wwn)) { 1164*fcf3ce44SJohn Forte matched = 1; 1165*fcf3ce44SJohn Forte } 1166*fcf3ce44SJohn Forte } else { 1167*fcf3ce44SJohn Forte if (is_path(argv[path_index]) && 1168*fcf3ce44SJohn Forte ((physical = get_slash_devices_from_osDevName( 1169*fcf3ce44SJohn Forte argv[path_index], 1170*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING)) != NULL) && 1171*fcf3ce44SJohn Forte ((comp_phys = get_slash_devices_from_osDevName( 1172*fcf3ce44SJohn Forte portAttrs.OSDeviceName, 1173*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING)) != NULL)) { 1174*fcf3ce44SJohn Forte char *tmp = strstr(physical, ":devctl"); 1175*fcf3ce44SJohn Forte if (tmp) { 1176*fcf3ce44SJohn Forte *tmp = '\0'; 1177*fcf3ce44SJohn Forte } else { 1178*fcf3ce44SJohn Forte tmp = strstr(physical, ":fc"); 1179*fcf3ce44SJohn Forte if (tmp) { 1180*fcf3ce44SJohn Forte *tmp = '\0'; 1181*fcf3ce44SJohn Forte } 1182*fcf3ce44SJohn Forte } 1183*fcf3ce44SJohn Forte if (strstr(comp_phys, physical)) { 1184*fcf3ce44SJohn Forte matched = 1; 1185*fcf3ce44SJohn Forte } 1186*fcf3ce44SJohn Forte } 1187*fcf3ce44SJohn Forte if (physical) { 1188*fcf3ce44SJohn Forte free(physical); 1189*fcf3ce44SJohn Forte physical = NULL; 1190*fcf3ce44SJohn Forte } 1191*fcf3ce44SJohn Forte if (comp_phys) { 1192*fcf3ce44SJohn Forte free(comp_phys); 1193*fcf3ce44SJohn Forte comp_phys = NULL; 1194*fcf3ce44SJohn Forte } 1195*fcf3ce44SJohn Forte } 1196*fcf3ce44SJohn Forte 1197*fcf3ce44SJohn Forte if (!matched) { 1198*fcf3ce44SJohn Forte if (fetch_mappings(handle, portAttrs.PortWWN, &map)) { 1199*fcf3ce44SJohn Forte continue; 1200*fcf3ce44SJohn Forte } 1201*fcf3ce44SJohn Forte } 1202*fcf3ce44SJohn Forte 1203*fcf3ce44SJohn Forte if (matched || match_mappings(argv[path_index], map) >= 0) { 1204*fcf3ce44SJohn Forte goodPath = B_TRUE; 1205*fcf3ce44SJohn Forte fprintf(stdout, 1206*fcf3ce44SJohn Forte MSGSTR(2007, "\nLink Error Status " 1207*fcf3ce44SJohn Forte "information for loop:%s\n"), argv[path_index]); 1208*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2008, "al_pa lnk fail " 1209*fcf3ce44SJohn Forte " sync loss signal loss sequence err" 1210*fcf3ce44SJohn Forte " invalid word CRC\n")); 1211*fcf3ce44SJohn Forte 1212*fcf3ce44SJohn Forte for (discIndex = 0; 1213*fcf3ce44SJohn Forte discIndex < portAttrs.NumberofDiscoveredPorts; 1214*fcf3ce44SJohn Forte discIndex++) { 1215*fcf3ce44SJohn Forte 1216*fcf3ce44SJohn Forte 1217*fcf3ce44SJohn Forte if (getDiscPortAttrs(handle, name, portIndex, 1218*fcf3ce44SJohn Forte discIndex, &discPortAttrs)) { 1219*fcf3ce44SJohn Forte continue; 1220*fcf3ce44SJohn Forte } 1221*fcf3ce44SJohn Forte 1222*fcf3ce44SJohn Forte status = HBA_SendRLS(handle, portAttrs.PortWWN, 1223*fcf3ce44SJohn Forte discPortAttrs.PortWWN, 1224*fcf3ce44SJohn Forte &rls, &rls_size); 1225*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1226*fcf3ce44SJohn Forte memset(&rls, 0xff, sizeof (rls)); 1227*fcf3ce44SJohn Forte } 1228*fcf3ce44SJohn Forte 1229*fcf3ce44SJohn Forte if ((rls.rls_link_fail == 0xffffffff) && 1230*fcf3ce44SJohn Forte (rls.rls_sync_loss == 0xffffffff) && 1231*fcf3ce44SJohn Forte (rls.rls_sig_loss == 0xffffffff) && 1232*fcf3ce44SJohn Forte (rls.rls_prim_seq_err == 0xffffffff) && 1233*fcf3ce44SJohn Forte (rls.rls_invalid_word == 0xffffffff) && 1234*fcf3ce44SJohn Forte (rls.rls_invalid_crc == 0xffffffff)) { 1235*fcf3ce44SJohn Forte fprintf(stdout, 1236*fcf3ce44SJohn Forte "%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n", 1237*fcf3ce44SJohn Forte discPortAttrs.PortFcId, 1238*fcf3ce44SJohn Forte rls.rls_link_fail, 1239*fcf3ce44SJohn Forte rls.rls_sync_loss, 1240*fcf3ce44SJohn Forte rls.rls_sig_loss, 1241*fcf3ce44SJohn Forte rls.rls_prim_seq_err, 1242*fcf3ce44SJohn Forte rls.rls_invalid_word, 1243*fcf3ce44SJohn Forte rls.rls_invalid_crc); 1244*fcf3ce44SJohn Forte } else { 1245*fcf3ce44SJohn Forte fprintf(stdout, 1246*fcf3ce44SJohn Forte "%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n", 1247*fcf3ce44SJohn Forte discPortAttrs.PortFcId, 1248*fcf3ce44SJohn Forte rls.rls_link_fail, 1249*fcf3ce44SJohn Forte rls.rls_sync_loss, 1250*fcf3ce44SJohn Forte rls.rls_sig_loss, 1251*fcf3ce44SJohn Forte rls.rls_prim_seq_err, 1252*fcf3ce44SJohn Forte rls.rls_invalid_word, 1253*fcf3ce44SJohn Forte rls.rls_invalid_crc); 1254*fcf3ce44SJohn Forte } 1255*fcf3ce44SJohn Forte 1256*fcf3ce44SJohn Forte 1257*fcf3ce44SJohn Forte } 1258*fcf3ce44SJohn Forte /* Now dump this HBA's stats */ 1259*fcf3ce44SJohn Forte status = HBA_SendRLS(handle, portAttrs.PortWWN, 1260*fcf3ce44SJohn Forte portAttrs.PortWWN, 1261*fcf3ce44SJohn Forte &rls, &rls_size); 1262*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1263*fcf3ce44SJohn Forte memset(&rls, 0xff, sizeof (rls)); 1264*fcf3ce44SJohn Forte } 1265*fcf3ce44SJohn Forte 1266*fcf3ce44SJohn Forte if ((rls.rls_link_fail == 0xffffffff) && 1267*fcf3ce44SJohn Forte (rls.rls_sync_loss == 0xffffffff) && 1268*fcf3ce44SJohn Forte (rls.rls_sig_loss == 0xffffffff) && 1269*fcf3ce44SJohn Forte (rls.rls_prim_seq_err == 0xffffffff) && 1270*fcf3ce44SJohn Forte (rls.rls_invalid_word == 0xffffffff) && 1271*fcf3ce44SJohn Forte (rls.rls_invalid_crc == 0xffffffff)) { 1272*fcf3ce44SJohn Forte fprintf(stdout, 1273*fcf3ce44SJohn Forte "%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n", 1274*fcf3ce44SJohn Forte portAttrs.PortFcId, 1275*fcf3ce44SJohn Forte rls.rls_link_fail, 1276*fcf3ce44SJohn Forte rls.rls_sync_loss, 1277*fcf3ce44SJohn Forte rls.rls_sig_loss, 1278*fcf3ce44SJohn Forte rls.rls_prim_seq_err, 1279*fcf3ce44SJohn Forte rls.rls_invalid_word, 1280*fcf3ce44SJohn Forte rls.rls_invalid_crc); 1281*fcf3ce44SJohn Forte } else { 1282*fcf3ce44SJohn Forte fprintf(stdout, 1283*fcf3ce44SJohn Forte "%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n", 1284*fcf3ce44SJohn Forte portAttrs.PortFcId, 1285*fcf3ce44SJohn Forte rls.rls_link_fail, 1286*fcf3ce44SJohn Forte rls.rls_sync_loss, 1287*fcf3ce44SJohn Forte rls.rls_sig_loss, 1288*fcf3ce44SJohn Forte rls.rls_prim_seq_err, 1289*fcf3ce44SJohn Forte rls.rls_invalid_word, 1290*fcf3ce44SJohn Forte rls.rls_invalid_crc); 1291*fcf3ce44SJohn Forte } 1292*fcf3ce44SJohn Forte } 1293*fcf3ce44SJohn Forte } 1294*fcf3ce44SJohn Forte } 1295*fcf3ce44SJohn Forte if (!goodPath) { 1296*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 1297*fcf3ce44SJohn Forte argv[path_index]); 1298*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1299*fcf3ce44SJohn Forte ret = -1; 1300*fcf3ce44SJohn Forte } 1301*fcf3ce44SJohn Forte } 1302*fcf3ce44SJohn Forte (void) fprintf(stdout, 1303*fcf3ce44SJohn Forte MSGSTR(2009, "NOTE: These LESB counts are not" 1304*fcf3ce44SJohn Forte " cleared by a reset, only power cycles.\n" 1305*fcf3ce44SJohn Forte "These counts must be compared" 1306*fcf3ce44SJohn Forte " to previously read counts.\n")); 1307*fcf3ce44SJohn Forte return (ret); 1308*fcf3ce44SJohn Forte } 1309*fcf3ce44SJohn Forte 1310*fcf3ce44SJohn Forte typedef struct _PathInformation { 1311*fcf3ce44SJohn Forte char pathClass[MAXPATHLEN]; 1312*fcf3ce44SJohn Forte char pathState[MAXPATHLEN]; 1313*fcf3ce44SJohn Forte int32_t pathInfoState; 1314*fcf3ce44SJohn Forte int32_t pathInfoExternalState; 1315*fcf3ce44SJohn Forte } PathInformation; 1316*fcf3ce44SJohn Forte 1317*fcf3ce44SJohn Forte struct lun_tracking { 1318*fcf3ce44SJohn Forte HBA_FCPSCSIENTRYV2 map; 1319*fcf3ce44SJohn Forte HBA_WWN hba_pwwn; 1320*fcf3ce44SJohn Forte char hba_path[MAXPATHLEN]; 1321*fcf3ce44SJohn Forte PathInformation info; 1322*fcf3ce44SJohn Forte 1323*fcf3ce44SJohn Forte /* Points to another lun_tracking instance with the same map->LUID */ 1324*fcf3ce44SJohn Forte struct lun_tracking *next_path; 1325*fcf3ce44SJohn Forte 1326*fcf3ce44SJohn Forte /* Points to next lun_tracking with a different map->LUID */ 1327*fcf3ce44SJohn Forte struct lun_tracking *next_lun; 1328*fcf3ce44SJohn Forte }; 1329*fcf3ce44SJohn Forte 1330*fcf3ce44SJohn Forte 1331*fcf3ce44SJohn Forte static const char VHCI_COMPONENT[] = "scsi_vhci"; 1332*fcf3ce44SJohn Forte static void 1333*fcf3ce44SJohn Forte scsi_vhci_details(struct lun_tracking *lun) 1334*fcf3ce44SJohn Forte { 1335*fcf3ce44SJohn Forte HBA_FCPSCSIENTRYV2 entry = lun->map; 1336*fcf3ce44SJohn Forte int retval = 0; 1337*fcf3ce44SJohn Forte int pathcnt, i, count, found = 0; 1338*fcf3ce44SJohn Forte char temppath[MAXPATHLEN]; 1339*fcf3ce44SJohn Forte char buf[MAXPATHLEN]; 1340*fcf3ce44SJohn Forte char *path_state[5]; 1341*fcf3ce44SJohn Forte 1342*fcf3ce44SJohn Forte char *phys_path = get_slash_devices_from_osDevName( 1343*fcf3ce44SJohn Forte entry.ScsiId.OSDeviceName, 1344*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 1345*fcf3ce44SJohn Forte char *devPath = NULL; 1346*fcf3ce44SJohn Forte char *trailingCruft = NULL; 1347*fcf3ce44SJohn Forte char devaddr[MAXPATHLEN]; 1348*fcf3ce44SJohn Forte sv_iocdata_t ioc; 1349*fcf3ce44SJohn Forte int prop_buf_size = SV_PROP_MAX_BUF_SIZE; 1350*fcf3ce44SJohn Forte char *path_class_val = NULL; 1351*fcf3ce44SJohn Forte char client_path[MAXPATHLEN]; 1352*fcf3ce44SJohn Forte char phci_path[MAXPATHLEN]; 1353*fcf3ce44SJohn Forte 1354*fcf3ce44SJohn Forte /* Only proceed if we are an mpxio path */ 1355*fcf3ce44SJohn Forte if (phys_path == NULL || strstr(phys_path, VHCI_COMPONENT) == NULL) { 1356*fcf3ce44SJohn Forte return; 1357*fcf3ce44SJohn Forte } 1358*fcf3ce44SJohn Forte 1359*fcf3ce44SJohn Forte path_state[0] = MSGSTR(2400, "INIT"); 1360*fcf3ce44SJohn Forte path_state[1] = MSGSTR(2401, "ONLINE"); 1361*fcf3ce44SJohn Forte path_state[2] = MSGSTR(2402, "STANDBY"); 1362*fcf3ce44SJohn Forte path_state[3] = MSGSTR(2403, "FAULT"); 1363*fcf3ce44SJohn Forte path_state[4] = MSGSTR(2404, "OFFLINE"); 1364*fcf3ce44SJohn Forte 1365*fcf3ce44SJohn Forte sprintf(devaddr, "%016llx,%x", wwnConversion( 1366*fcf3ce44SJohn Forte entry.FcpId.PortWWN.wwn), 1367*fcf3ce44SJohn Forte entry.ScsiId.ScsiOSLun); 1368*fcf3ce44SJohn Forte 1369*fcf3ce44SJohn Forte /* First get the controller path */ 1370*fcf3ce44SJohn Forte sprintf(temppath, "/dev/cfg/c%d", entry.ScsiId.ScsiBusNumber); 1371*fcf3ce44SJohn Forte if ((count = readlink(temppath, buf, sizeof (buf)))) { 1372*fcf3ce44SJohn Forte buf[count] = '\0'; 1373*fcf3ce44SJohn Forte /* Now skip over the leading "../.." */ 1374*fcf3ce44SJohn Forte devPath = strstr(buf, "/devices/"); 1375*fcf3ce44SJohn Forte if (devPath == NULL) { 1376*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, "Unavailable"); 1377*fcf3ce44SJohn Forte strcpy(lun->info.pathState, "Unavailable"); 1378*fcf3ce44SJohn Forte free(phys_path); 1379*fcf3ce44SJohn Forte return; 1380*fcf3ce44SJohn Forte } 1381*fcf3ce44SJohn Forte 1382*fcf3ce44SJohn Forte /* Now chop off the trailing ":xxx" portion if present */ 1383*fcf3ce44SJohn Forte trailingCruft = strrchr(buf, ':'); 1384*fcf3ce44SJohn Forte if (trailingCruft) { 1385*fcf3ce44SJohn Forte trailingCruft[0] = '\0'; 1386*fcf3ce44SJohn Forte } 1387*fcf3ce44SJohn Forte } else { 1388*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, "Unavailable"); 1389*fcf3ce44SJohn Forte strcpy(lun->info.pathState, "Unavailable"); 1390*fcf3ce44SJohn Forte free(phys_path); 1391*fcf3ce44SJohn Forte return; 1392*fcf3ce44SJohn Forte } 1393*fcf3ce44SJohn Forte 1394*fcf3ce44SJohn Forte ioc.client = client_path; 1395*fcf3ce44SJohn Forte ioc.phci = phci_path; 1396*fcf3ce44SJohn Forte 1397*fcf3ce44SJohn Forte retval = get_scsi_vhci_pathinfo(phys_path, &ioc, &pathcnt); 1398*fcf3ce44SJohn Forte if (retval != 0) { 1399*fcf3ce44SJohn Forte print_errString(retval, NULL); 1400*fcf3ce44SJohn Forte exit(-1); 1401*fcf3ce44SJohn Forte } 1402*fcf3ce44SJohn Forte 1403*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 1404*fcf3ce44SJohn Forte nvlist_t *nvl; 1405*fcf3ce44SJohn Forte if (strstr(devPath, ioc.ret_buf[i].device.ret_phci)) { 1406*fcf3ce44SJohn Forte /* This could break someday if MPxIO changes devaddr */ 1407*fcf3ce44SJohn Forte if (strstr(ioc.ret_buf[i].ret_addr, devaddr)) { 1408*fcf3ce44SJohn Forte retval = nvlist_unpack(ioc.ret_buf[i].ret_prop.buf, 1409*fcf3ce44SJohn Forte prop_buf_size, &nvl, 0); 1410*fcf3ce44SJohn Forte if (retval != 0) { 1411*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, 1412*fcf3ce44SJohn Forte "UNKNOWN PROB"); 1413*fcf3ce44SJohn Forte } else { 1414*fcf3ce44SJohn Forte strcpy(lun->info.pathState, 1415*fcf3ce44SJohn Forte path_state[ioc.ret_buf[i].ret_state]); 1416*fcf3ce44SJohn Forte lun->info.pathInfoState = ioc.ret_buf[i].ret_state; 1417*fcf3ce44SJohn Forte lun->info.pathInfoExternalState = 1418*fcf3ce44SJohn Forte ioc.ret_buf[i].ret_ext_state; 1419*fcf3ce44SJohn Forte if (nvlist_lookup_string(nvl, "path-class", 1420*fcf3ce44SJohn Forte &path_class_val) == 0) { 1421*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, path_class_val); 1422*fcf3ce44SJohn Forte } else { 1423*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, "UNKNOWN"); 1424*fcf3ce44SJohn Forte } 1425*fcf3ce44SJohn Forte } 1426*fcf3ce44SJohn Forte nvlist_free(nvl); 1427*fcf3ce44SJohn Forte found++; 1428*fcf3ce44SJohn Forte break; 1429*fcf3ce44SJohn Forte } 1430*fcf3ce44SJohn Forte } 1431*fcf3ce44SJohn Forte 1432*fcf3ce44SJohn Forte } 1433*fcf3ce44SJohn Forte 1434*fcf3ce44SJohn Forte if (!found) { 1435*fcf3ce44SJohn Forte strcpy(lun->info.pathClass, "Unavailable"); 1436*fcf3ce44SJohn Forte strcpy(lun->info.pathState, "Unavailable"); 1437*fcf3ce44SJohn Forte } 1438*fcf3ce44SJohn Forte free(phys_path); 1439*fcf3ce44SJohn Forte 1440*fcf3ce44SJohn Forte /* free everything we alloced */ 1441*fcf3ce44SJohn Forte for (i = 0; i < ioc.buf_elem; i++) { 1442*fcf3ce44SJohn Forte free(ioc.ret_buf[i].ret_prop.buf); 1443*fcf3ce44SJohn Forte free(ioc.ret_buf[i].ret_prop.ret_buf_size); 1444*fcf3ce44SJohn Forte } 1445*fcf3ce44SJohn Forte free(ioc.ret_buf); 1446*fcf3ce44SJohn Forte 1447*fcf3ce44SJohn Forte } 1448*fcf3ce44SJohn Forte 1449*fcf3ce44SJohn Forte /* Utility routine to add new entries to the list (ignores dups) */ 1450*fcf3ce44SJohn Forte static void 1451*fcf3ce44SJohn Forte add_lun_path(struct lun_tracking *head, HBA_FCPSCSIENTRYV2 *map, 1452*fcf3ce44SJohn Forte HBA_WWN pwwn, char *path) 1453*fcf3ce44SJohn Forte { 1454*fcf3ce44SJohn Forte struct lun_tracking *tmp = NULL, *cmp = NULL; 1455*fcf3ce44SJohn Forte 1456*fcf3ce44SJohn Forte for (tmp = head; tmp != NULL; tmp = tmp->next_lun) { 1457*fcf3ce44SJohn Forte if (memcmp(&tmp->map.LUID, &map->LUID, 1458*fcf3ce44SJohn Forte sizeof (HBA_LUID)) == 0) { 1459*fcf3ce44SJohn Forte 1460*fcf3ce44SJohn Forte /* Ensure this isn't a duplicate */ 1461*fcf3ce44SJohn Forte for (cmp = tmp; cmp->next_path != NULL; 1462*fcf3ce44SJohn Forte cmp = cmp->next_path) { 1463*fcf3ce44SJohn Forte if (memcmp(&cmp->map, map, sizeof (cmp->map)) == 0) { 1464*fcf3ce44SJohn Forte return; 1465*fcf3ce44SJohn Forte } 1466*fcf3ce44SJohn Forte } 1467*fcf3ce44SJohn Forte if (memcmp(&cmp->map, map, sizeof (cmp->map)) == 0) { 1468*fcf3ce44SJohn Forte return; 1469*fcf3ce44SJohn Forte } 1470*fcf3ce44SJohn Forte 1471*fcf3ce44SJohn Forte /* We have a new entry to add */ 1472*fcf3ce44SJohn Forte cmp->next_path = (struct lun_tracking *)calloc(1, 1473*fcf3ce44SJohn Forte sizeof (struct lun_tracking)); 1474*fcf3ce44SJohn Forte cmp = cmp->next_path; 1475*fcf3ce44SJohn Forte (void) memcpy(&cmp->map, map, 1476*fcf3ce44SJohn Forte sizeof (cmp->map)); 1477*fcf3ce44SJohn Forte (void) memcpy(&cmp->hba_pwwn, &pwwn, 1478*fcf3ce44SJohn Forte sizeof (cmp->hba_pwwn)); 1479*fcf3ce44SJohn Forte (void) snprintf(cmp->hba_path, MAXPATHLEN, 1480*fcf3ce44SJohn Forte path); 1481*fcf3ce44SJohn Forte scsi_vhci_details(cmp); 1482*fcf3ce44SJohn Forte return; 1483*fcf3ce44SJohn Forte } 1484*fcf3ce44SJohn Forte } 1485*fcf3ce44SJohn Forte /* Append a new LUN at the end of the list */ 1486*fcf3ce44SJohn Forte for (tmp = head; tmp->next_lun != NULL; tmp = tmp->next_lun) {} 1487*fcf3ce44SJohn Forte tmp->next_lun = (struct lun_tracking *)calloc(1, 1488*fcf3ce44SJohn Forte sizeof (struct lun_tracking)); 1489*fcf3ce44SJohn Forte tmp = tmp->next_lun; 1490*fcf3ce44SJohn Forte (void) memcpy(&tmp->map, map, 1491*fcf3ce44SJohn Forte sizeof (tmp->map)); 1492*fcf3ce44SJohn Forte (void) memcpy(&tmp->hba_pwwn, &pwwn, 1493*fcf3ce44SJohn Forte sizeof (tmp->hba_pwwn)); 1494*fcf3ce44SJohn Forte (void) snprintf(tmp->hba_path, MAXPATHLEN, 1495*fcf3ce44SJohn Forte path); 1496*fcf3ce44SJohn Forte scsi_vhci_details(tmp); 1497*fcf3ce44SJohn Forte } 1498*fcf3ce44SJohn Forte 1499*fcf3ce44SJohn Forte /*ARGSUSED*/ 1500*fcf3ce44SJohn Forte int 1501*fcf3ce44SJohn Forte fchba_display_config(char **argv, int option_t_input, int argc) 1502*fcf3ce44SJohn Forte { 1503*fcf3ce44SJohn Forte int path_index = 0; 1504*fcf3ce44SJohn Forte uint64_t wwn; 1505*fcf3ce44SJohn Forte uint64_t lun = 0; 1506*fcf3ce44SJohn Forte HBA_HANDLE handle; 1507*fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES hbaAttrs; 1508*fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs; 1509*fcf3ce44SJohn Forte HBA_FCPTARGETMAPPINGV2 *map; 1510*fcf3ce44SJohn Forte HBA_STATUS status; 1511*fcf3ce44SJohn Forte int count, adapterIndex, portIndex; 1512*fcf3ce44SJohn Forte char name[256]; 1513*fcf3ce44SJohn Forte L_inquiry inq; 1514*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 1515*fcf3ce44SJohn Forte struct page80 serial; 1516*fcf3ce44SJohn Forte HBA_UINT8 scsiStatus; 1517*fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq), senseSize = sizeof (sense); 1518*fcf3ce44SJohn Forte uint32_t serialSize = sizeof (serial); 1519*fcf3ce44SJohn Forte struct mode_page *pg_hdr; 1520*fcf3ce44SJohn Forte uchar_t *pg_buf; 1521*fcf3ce44SJohn Forte float lunMbytes; 1522*fcf3ce44SJohn Forte struct capacity_data_struct cap_data; 1523*fcf3ce44SJohn Forte uint32_t cap_data_size = sizeof (cap_data); 1524*fcf3ce44SJohn Forte struct mode_header_g1 *mode_header_ptr; 1525*fcf3ce44SJohn Forte int offset; 1526*fcf3ce44SJohn Forte char *phys_path = NULL; 1527*fcf3ce44SJohn Forte int mpxio = 0; 1528*fcf3ce44SJohn Forte int wwnCompare = 0; 1529*fcf3ce44SJohn Forte char *physical = NULL; 1530*fcf3ce44SJohn Forte struct lun_tracking *head = NULL; 1531*fcf3ce44SJohn Forte boolean_t goodPath = B_FALSE; 1532*fcf3ce44SJohn Forte int ret = 0; 1533*fcf3ce44SJohn Forte 1534*fcf3ce44SJohn Forte 1535*fcf3ce44SJohn Forte 1536*fcf3ce44SJohn Forte if ((status = loadLibrary())) { 1537*fcf3ce44SJohn Forte return (-1); 1538*fcf3ce44SJohn Forte } 1539*fcf3ce44SJohn Forte for (path_index = 0; argv[path_index] != NULL; path_index++) { 1540*fcf3ce44SJohn Forte goodPath = B_FALSE; 1541*fcf3ce44SJohn Forte 1542*fcf3ce44SJohn Forte if (is_wwn(argv[path_index])) { 1543*fcf3ce44SJohn Forte (void) sscanf(argv[path_index], "%016llx", &wwn); 1544*fcf3ce44SJohn Forte wwnCompare = 1; 1545*fcf3ce44SJohn Forte } else if (!is_path(argv[path_index])) { 1546*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 1547*fcf3ce44SJohn Forte argv[path_index]); 1548*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1549*fcf3ce44SJohn Forte ret = -1; 1550*fcf3ce44SJohn Forte continue; 1551*fcf3ce44SJohn Forte } 1552*fcf3ce44SJohn Forte if (!wwnCompare) { 1553*fcf3ce44SJohn Forte /* Convert the paths to phsyical paths */ 1554*fcf3ce44SJohn Forte physical = get_slash_devices_from_osDevName(argv[path_index], 1555*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 1556*fcf3ce44SJohn Forte if (!physical) { 1557*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, 1558*fcf3ce44SJohn Forte "Error: Invalid pathname (%s)"), 1559*fcf3ce44SJohn Forte argv[path_index]); 1560*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1561*fcf3ce44SJohn Forte ret = -1; 1562*fcf3ce44SJohn Forte continue; 1563*fcf3ce44SJohn Forte } 1564*fcf3ce44SJohn Forte } 1565*fcf3ce44SJohn Forte 1566*fcf3ce44SJohn Forte count = getNumberOfAdapters(); 1567*fcf3ce44SJohn Forte 1568*fcf3ce44SJohn Forte 1569*fcf3ce44SJohn Forte /* 1570*fcf3ce44SJohn Forte * We have to loop twice to ensure we don't miss any 1571*fcf3ce44SJohn Forte * extra paths for other targets in a multi-target device 1572*fcf3ce44SJohn Forte */ 1573*fcf3ce44SJohn Forte 1574*fcf3ce44SJohn Forte /* First check WWN/path comparisons */ 1575*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 1576*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 1577*fcf3ce44SJohn Forte continue; 1578*fcf3ce44SJohn Forte } 1579*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 1580*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1581*fcf3ce44SJohn Forte /* May have been DR'd */ 1582*fcf3ce44SJohn Forte continue; 1583*fcf3ce44SJohn Forte } 1584*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 1585*fcf3ce44SJohn Forte if (handle == 0) { 1586*fcf3ce44SJohn Forte /* May have been DR'd */ 1587*fcf3ce44SJohn Forte continue; 1588*fcf3ce44SJohn Forte } 1589*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 1590*fcf3ce44SJohn Forte /* Should never happen */ 1591*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1592*fcf3ce44SJohn Forte continue; 1593*fcf3ce44SJohn Forte } 1594*fcf3ce44SJohn Forte 1595*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 1596*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 1597*fcf3ce44SJohn Forte portIndex++) { 1598*fcf3ce44SJohn Forte int matched = 0; 1599*fcf3ce44SJohn Forte int mapIndex; 1600*fcf3ce44SJohn Forte char *tmp; 1601*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 1602*fcf3ce44SJohn Forte &portAttrs)) { 1603*fcf3ce44SJohn Forte continue; 1604*fcf3ce44SJohn Forte } 1605*fcf3ce44SJohn Forte 1606*fcf3ce44SJohn Forte if (fetch_mappings(handle, portAttrs.PortWWN, &map)) { 1607*fcf3ce44SJohn Forte continue; 1608*fcf3ce44SJohn Forte } 1609*fcf3ce44SJohn Forte 1610*fcf3ce44SJohn Forte 1611*fcf3ce44SJohn Forte 1612*fcf3ce44SJohn Forte for (mapIndex = 0; mapIndex < map->NumberOfEntries; 1613*fcf3ce44SJohn Forte mapIndex ++) { 1614*fcf3ce44SJohn Forte matched = 0; 1615*fcf3ce44SJohn Forte if (wwnCompare) { 1616*fcf3ce44SJohn Forte if (wwn == wwnConversion( 1617*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.NodeWWN.wwn) || 1618*fcf3ce44SJohn Forte wwn == wwnConversion( 1619*fcf3ce44SJohn Forte map->entry[mapIndex].FcpId.PortWWN.wwn)) { 1620*fcf3ce44SJohn Forte matched = 1; 1621*fcf3ce44SJohn Forte } 1622*fcf3ce44SJohn Forte } else { 1623*fcf3ce44SJohn Forte tmp = get_slash_devices_from_osDevName( 1624*fcf3ce44SJohn Forte map->entry[mapIndex].ScsiId.OSDeviceName, 1625*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 1626*fcf3ce44SJohn Forte if ((tmp != NULL) && (strncmp(physical, tmp, 1627*fcf3ce44SJohn Forte MAXPATHLEN) == 0)) { 1628*fcf3ce44SJohn Forte matched = 1; 1629*fcf3ce44SJohn Forte free(tmp); 1630*fcf3ce44SJohn Forte } 1631*fcf3ce44SJohn Forte } 1632*fcf3ce44SJohn Forte if (matched && head == NULL) { 1633*fcf3ce44SJohn Forte goodPath = B_TRUE; 1634*fcf3ce44SJohn Forte head = (struct lun_tracking *)calloc(1, 1635*fcf3ce44SJohn Forte sizeof (struct lun_tracking)); 1636*fcf3ce44SJohn Forte (void) memcpy(&head->map, &map->entry[mapIndex], 1637*fcf3ce44SJohn Forte sizeof (head->map)); 1638*fcf3ce44SJohn Forte (void) memcpy(&head->hba_pwwn, &portAttrs.PortWWN, 1639*fcf3ce44SJohn Forte sizeof (head->hba_pwwn)); 1640*fcf3ce44SJohn Forte (void) snprintf(head->hba_path, MAXPATHLEN, 1641*fcf3ce44SJohn Forte portAttrs.OSDeviceName); 1642*fcf3ce44SJohn Forte scsi_vhci_details(head); 1643*fcf3ce44SJohn Forte } else if (matched) { 1644*fcf3ce44SJohn Forte goodPath = B_TRUE; 1645*fcf3ce44SJohn Forte add_lun_path(head, &map->entry[mapIndex], 1646*fcf3ce44SJohn Forte portAttrs.PortWWN, portAttrs.OSDeviceName); 1647*fcf3ce44SJohn Forte } 1648*fcf3ce44SJohn Forte } 1649*fcf3ce44SJohn Forte } 1650*fcf3ce44SJohn Forte } 1651*fcf3ce44SJohn Forte 1652*fcf3ce44SJohn Forte if (physical) { 1653*fcf3ce44SJohn Forte free(physical); 1654*fcf3ce44SJohn Forte } 1655*fcf3ce44SJohn Forte 1656*fcf3ce44SJohn Forte /* Now do it again and look for matching LUIDs (aka GUIDs) */ 1657*fcf3ce44SJohn Forte for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) { 1658*fcf3ce44SJohn Forte if (skip_hba(adapterIndex)) { 1659*fcf3ce44SJohn Forte continue; 1660*fcf3ce44SJohn Forte } 1661*fcf3ce44SJohn Forte status = HBA_GetAdapterName(adapterIndex, (char *)&name); 1662*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1663*fcf3ce44SJohn Forte /* May have been DR'd */ 1664*fcf3ce44SJohn Forte continue; 1665*fcf3ce44SJohn Forte } 1666*fcf3ce44SJohn Forte handle = HBA_OpenAdapter(name); 1667*fcf3ce44SJohn Forte if (handle == 0) { 1668*fcf3ce44SJohn Forte /* May have been DR'd */ 1669*fcf3ce44SJohn Forte continue; 1670*fcf3ce44SJohn Forte } 1671*fcf3ce44SJohn Forte 1672*fcf3ce44SJohn Forte if (getAdapterAttrs(handle, name, &hbaAttrs)) { 1673*fcf3ce44SJohn Forte /* Should never happen */ 1674*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1675*fcf3ce44SJohn Forte continue; 1676*fcf3ce44SJohn Forte } 1677*fcf3ce44SJohn Forte 1678*fcf3ce44SJohn Forte 1679*fcf3ce44SJohn Forte /* Loop over all HBA Ports */ 1680*fcf3ce44SJohn Forte for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts; 1681*fcf3ce44SJohn Forte portIndex++) { 1682*fcf3ce44SJohn Forte int matched = 0; 1683*fcf3ce44SJohn Forte int mapIndex; 1684*fcf3ce44SJohn Forte if (getAdapterPortAttrs(handle, name, portIndex, 1685*fcf3ce44SJohn Forte &portAttrs)) { 1686*fcf3ce44SJohn Forte continue; 1687*fcf3ce44SJohn Forte } 1688*fcf3ce44SJohn Forte 1689*fcf3ce44SJohn Forte if (fetch_mappings(handle, portAttrs.PortWWN, &map)) { 1690*fcf3ce44SJohn Forte continue; 1691*fcf3ce44SJohn Forte } 1692*fcf3ce44SJohn Forte 1693*fcf3ce44SJohn Forte 1694*fcf3ce44SJohn Forte for (mapIndex = 0; mapIndex < map->NumberOfEntries; 1695*fcf3ce44SJohn Forte mapIndex ++) { 1696*fcf3ce44SJohn Forte struct lun_tracking *outer; 1697*fcf3ce44SJohn Forte matched = 0; 1698*fcf3ce44SJohn Forte for (outer = head; outer != NULL; 1699*fcf3ce44SJohn Forte outer = outer->next_lun) { 1700*fcf3ce44SJohn Forte struct lun_tracking *inner; 1701*fcf3ce44SJohn Forte for (inner = outer; inner != NULL; 1702*fcf3ce44SJohn Forte inner = inner->next_path) { 1703*fcf3ce44SJohn Forte if (memcmp(&inner->map.LUID, 1704*fcf3ce44SJohn Forte &map->entry[mapIndex].LUID, 1705*fcf3ce44SJohn Forte sizeof (HBA_LUID)) == 0) { 1706*fcf3ce44SJohn Forte matched = 1; 1707*fcf3ce44SJohn Forte break; 1708*fcf3ce44SJohn Forte } 1709*fcf3ce44SJohn Forte } 1710*fcf3ce44SJohn Forte if (matched) { 1711*fcf3ce44SJohn Forte break; 1712*fcf3ce44SJohn Forte } 1713*fcf3ce44SJohn Forte } 1714*fcf3ce44SJohn Forte if (matched && head == NULL) { 1715*fcf3ce44SJohn Forte goodPath = B_TRUE; 1716*fcf3ce44SJohn Forte head = (struct lun_tracking *)calloc(1, 1717*fcf3ce44SJohn Forte sizeof (struct lun_tracking)); 1718*fcf3ce44SJohn Forte (void) memcpy(&head->map, &map->entry[mapIndex], 1719*fcf3ce44SJohn Forte sizeof (head->map)); 1720*fcf3ce44SJohn Forte (void) memcpy(&head->hba_pwwn, &portAttrs.PortWWN, 1721*fcf3ce44SJohn Forte sizeof (head->hba_pwwn)); 1722*fcf3ce44SJohn Forte (void) snprintf(head->hba_path, MAXPATHLEN, 1723*fcf3ce44SJohn Forte portAttrs.OSDeviceName); 1724*fcf3ce44SJohn Forte scsi_vhci_details(head); 1725*fcf3ce44SJohn Forte } else if (matched) { 1726*fcf3ce44SJohn Forte goodPath = B_TRUE; 1727*fcf3ce44SJohn Forte add_lun_path(head, &map->entry[mapIndex], 1728*fcf3ce44SJohn Forte portAttrs.PortWWN, portAttrs.OSDeviceName); 1729*fcf3ce44SJohn Forte } 1730*fcf3ce44SJohn Forte } 1731*fcf3ce44SJohn Forte } 1732*fcf3ce44SJohn Forte } 1733*fcf3ce44SJohn Forte if (!goodPath) { 1734*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"), 1735*fcf3ce44SJohn Forte argv[path_index]); 1736*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1737*fcf3ce44SJohn Forte ret = -1; 1738*fcf3ce44SJohn Forte /* Just bomb out instead of going on */ 1739*fcf3ce44SJohn Forte return (ret); 1740*fcf3ce44SJohn Forte } 1741*fcf3ce44SJohn Forte } 1742*fcf3ce44SJohn Forte 1743*fcf3ce44SJohn Forte /* Now display all the LUNs that we found that matched */ 1744*fcf3ce44SJohn Forte { 1745*fcf3ce44SJohn Forte struct lun_tracking *first_time; 1746*fcf3ce44SJohn Forte struct lun_tracking *tmp_path; 1747*fcf3ce44SJohn Forte for (first_time = head; first_time != NULL; 1748*fcf3ce44SJohn Forte first_time = first_time->next_lun) { 1749*fcf3ce44SJohn Forte struct lun_tracking *path; 1750*fcf3ce44SJohn Forte phys_path = get_slash_devices_from_osDevName( 1751*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName, 1752*fcf3ce44SJohn Forte STANDARD_DEVNAME_HANDLING); 1753*fcf3ce44SJohn Forte /* Change behavior if this is an MPxIO device */ 1754*fcf3ce44SJohn Forte if (phys_path != NULL) { 1755*fcf3ce44SJohn Forte if (strstr(phys_path, VHCI_COMPONENT) != NULL) { 1756*fcf3ce44SJohn Forte mpxio = 1; 1757*fcf3ce44SJohn Forte } 1758*fcf3ce44SJohn Forte } 1759*fcf3ce44SJohn Forte 1760*fcf3ce44SJohn Forte for (tmp_path = first_time; tmp_path != NULL; 1761*fcf3ce44SJohn Forte tmp_path = tmp_path->next_path) { 1762*fcf3ce44SJohn Forte if (mpxio && (strncmp(tmp_path->info.pathState, 1763*fcf3ce44SJohn Forte "ONLINE", strlen(tmp_path->info.pathState)))) { 1764*fcf3ce44SJohn Forte /* continue to next online path */ 1765*fcf3ce44SJohn Forte continue; 1766*fcf3ce44SJohn Forte } 1767*fcf3ce44SJohn Forte status = HBA_OpenAdapterByWWN(&handle, 1768*fcf3ce44SJohn Forte tmp_path->hba_pwwn); 1769*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1770*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2431, 1771*fcf3ce44SJohn Forte "Error: Failed to get handle for %s "), 1772*fcf3ce44SJohn Forte tmp_path->hba_path); 1773*fcf3ce44SJohn Forte printStatus(status); 1774*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1775*fcf3ce44SJohn Forte /* continue to next path */ 1776*fcf3ce44SJohn Forte continue; 1777*fcf3ce44SJohn Forte } 1778*fcf3ce44SJohn Forte 1779*fcf3ce44SJohn Forte lun = tmp_path->map.FcpId.FcpLun; 1780*fcf3ce44SJohn Forte memset(&inq, 0, sizeof (inq)); 1781*fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense)); 1782*fcf3ce44SJohn Forte 1783*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 1784*fcf3ce44SJohn Forte tmp_path->hba_pwwn, 1785*fcf3ce44SJohn Forte tmp_path->map.FcpId.PortWWN, 1786*fcf3ce44SJohn Forte lun, 0, 0, 1787*fcf3ce44SJohn Forte &inq, &inquirySize, 1788*fcf3ce44SJohn Forte &scsiStatus, 1789*fcf3ce44SJohn Forte &sense, &senseSize); 1790*fcf3ce44SJohn Forte 1791*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 1792*fcf3ce44SJohn Forte break; 1793*fcf3ce44SJohn Forte } 1794*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1795*fcf3ce44SJohn Forte } 1796*fcf3ce44SJohn Forte 1797*fcf3ce44SJohn Forte if (tmp_path == NULL) { 1798*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(2430, 1799*fcf3ce44SJohn Forte "Error: I/O failure communicating with %s "), 1800*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName); 1801*fcf3ce44SJohn Forte printStatus(status); 1802*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 1803*fcf3ce44SJohn Forte continue; 1804*fcf3ce44SJohn Forte } 1805*fcf3ce44SJohn Forte 1806*fcf3ce44SJohn Forte switch ((inq.inq_dtype & DTYPE_MASK)) { 1807*fcf3ce44SJohn Forte case DTYPE_DIRECT: 1808*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(121, 1809*fcf3ce44SJohn Forte "DEVICE PROPERTIES for disk: %s\n"), 1810*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName); 1811*fcf3ce44SJohn Forte break; 1812*fcf3ce44SJohn Forte case DTYPE_SEQUENTIAL: /* Tape */ 1813*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2249, 1814*fcf3ce44SJohn Forte "DEVICE PROPERTIES for tape: %s\n"), 1815*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName); 1816*fcf3ce44SJohn Forte break; 1817*fcf3ce44SJohn Forte default: 1818*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2250, 1819*fcf3ce44SJohn Forte "DEVICE PROPERTIES for: %s\n"), 1820*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName); 1821*fcf3ce44SJohn Forte break; 1822*fcf3ce44SJohn Forte } 1823*fcf3ce44SJohn Forte fprintf(stdout, " "); 1824*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(3, "Vendor:")); 1825*fcf3ce44SJohn Forte fprintf(stdout, "\t\t"); 1826*fcf3ce44SJohn Forte print_chars(inq.inq_vid, sizeof (inq.inq_vid), 0); 1827*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2115, "\n Product ID:\t\t")); 1828*fcf3ce44SJohn Forte print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0); 1829*fcf3ce44SJohn Forte 1830*fcf3ce44SJohn Forte fprintf(stdout, "\n "); 1831*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2119, "Revision:")); 1832*fcf3ce44SJohn Forte fprintf(stdout, "\t\t"); 1833*fcf3ce44SJohn Forte print_chars(inq.inq_revision, sizeof (inq.inq_revision), 0); 1834*fcf3ce44SJohn Forte 1835*fcf3ce44SJohn Forte fprintf(stdout, "\n "); 1836*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(17, "Serial Num:")); 1837*fcf3ce44SJohn Forte fprintf(stdout, "\t\t"); 1838*fcf3ce44SJohn Forte (void) fflush(stdout); 1839*fcf3ce44SJohn Forte /* 1840*fcf3ce44SJohn Forte * Call the inquiry cmd on page 0x80 only if the vendor 1841*fcf3ce44SJohn Forte * supports page 0x80. 1842*fcf3ce44SJohn Forte */ 1843*fcf3ce44SJohn Forte if ((find_supported_inq_page(handle, first_time->hba_pwwn, 1844*fcf3ce44SJohn Forte first_time->map.FcpId.PortWWN, lun, 0x80))) { 1845*fcf3ce44SJohn Forte memset(&serial, 0, sizeof (serial)); 1846*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, 1847*fcf3ce44SJohn Forte first_time->hba_pwwn, 1848*fcf3ce44SJohn Forte first_time->map.FcpId.PortWWN, 1849*fcf3ce44SJohn Forte lun, 1, 0x80, 1850*fcf3ce44SJohn Forte &serial, &serialSize, 1851*fcf3ce44SJohn Forte &scsiStatus, 1852*fcf3ce44SJohn Forte &sense, &senseSize); 1853*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 1854*fcf3ce44SJohn Forte print_chars(serial.inq_serial, 1855*fcf3ce44SJohn Forte sizeof (serial.inq_serial), 0); 1856*fcf3ce44SJohn Forte } else { 1857*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2506, "Unsupported")); 1858*fcf3ce44SJohn Forte } 1859*fcf3ce44SJohn Forte } else { 1860*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2506, "Unsupported")); 1861*fcf3ce44SJohn Forte } 1862*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1863*fcf3ce44SJohn Forte if ((inq.inq_dtype & DTYPE_MASK) == DTYPE_DIRECT) { 1864*fcf3ce44SJohn Forte /* Read capacity wont work on standby paths, so try till OK */ 1865*fcf3ce44SJohn Forte for (tmp_path = first_time; tmp_path != NULL; 1866*fcf3ce44SJohn Forte tmp_path = tmp_path->next_path) { 1867*fcf3ce44SJohn Forte if (mpxio && (strncmp(tmp_path->info.pathState, 1868*fcf3ce44SJohn Forte "ONLINE", strlen(tmp_path->info.pathState)))) { 1869*fcf3ce44SJohn Forte /* continue to next online path */ 1870*fcf3ce44SJohn Forte continue; 1871*fcf3ce44SJohn Forte } 1872*fcf3ce44SJohn Forte status = HBA_OpenAdapterByWWN(&handle, 1873*fcf3ce44SJohn Forte tmp_path->hba_pwwn); 1874*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1875*fcf3ce44SJohn Forte /* continue to next path */ 1876*fcf3ce44SJohn Forte continue; 1877*fcf3ce44SJohn Forte } 1878*fcf3ce44SJohn Forte 1879*fcf3ce44SJohn Forte status = HBA_ScsiReadCapacityV2(handle, 1880*fcf3ce44SJohn Forte tmp_path->hba_pwwn, 1881*fcf3ce44SJohn Forte tmp_path->map.FcpId.PortWWN, 1882*fcf3ce44SJohn Forte tmp_path->map.FcpId.FcpLun, 1883*fcf3ce44SJohn Forte &cap_data, &cap_data_size, 1884*fcf3ce44SJohn Forte &scsiStatus, 1885*fcf3ce44SJohn Forte &sense, &senseSize); 1886*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 1887*fcf3ce44SJohn Forte break; 1888*fcf3ce44SJohn Forte } else if (status == HBA_STATUS_SCSI_CHECK_CONDITION && 1889*fcf3ce44SJohn Forte sense.es_key == KEY_UNIT_ATTENTION) { 1890*fcf3ce44SJohn Forte /* 1891*fcf3ce44SJohn Forte * retry for check-condition state when unit attention 1892*fcf3ce44SJohn Forte * condition has been established 1893*fcf3ce44SJohn Forte */ 1894*fcf3ce44SJohn Forte status = HBA_ScsiReadCapacityV2(handle, 1895*fcf3ce44SJohn Forte tmp_path->hba_pwwn, 1896*fcf3ce44SJohn Forte tmp_path->map.FcpId.PortWWN, 1897*fcf3ce44SJohn Forte tmp_path->map.FcpId.FcpLun, 1898*fcf3ce44SJohn Forte &cap_data, &cap_data_size, 1899*fcf3ce44SJohn Forte &scsiStatus, 1900*fcf3ce44SJohn Forte &sense, &senseSize); 1901*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 1902*fcf3ce44SJohn Forte break; 1903*fcf3ce44SJohn Forte } 1904*fcf3ce44SJohn Forte } 1905*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1906*fcf3ce44SJohn Forte } 1907*fcf3ce44SJohn Forte } 1908*fcf3ce44SJohn Forte if (handle != HBA_HANDLE_INVALID) { 1909*fcf3ce44SJohn Forte HBA_CloseAdapter(handle); 1910*fcf3ce44SJohn Forte } 1911*fcf3ce44SJohn Forte if (status != HBA_STATUS_OK) { 1912*fcf3ce44SJohn Forte /* Make sure we don't display garbage */ 1913*fcf3ce44SJohn Forte cap_data.block_size = 0; 1914*fcf3ce44SJohn Forte cap_data.last_block_addr = 0; 1915*fcf3ce44SJohn Forte } 1916*fcf3ce44SJohn Forte 1917*fcf3ce44SJohn Forte if (cap_data.block_size > 0 && 1918*fcf3ce44SJohn Forte cap_data.last_block_addr > 0) { 1919*fcf3ce44SJohn Forte lunMbytes = ntohl(cap_data.last_block_addr) + 1; 1920*fcf3ce44SJohn Forte lunMbytes *= ntohl(cap_data.block_size); 1921*fcf3ce44SJohn Forte lunMbytes /= (float)(1024*1024); 1922*fcf3ce44SJohn Forte fprintf(stdout, "\n "); 1923*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(60, 1924*fcf3ce44SJohn Forte "Unformatted capacity:\t%6.3f MBytes"), lunMbytes); 1925*fcf3ce44SJohn Forte } 1926*fcf3ce44SJohn Forte fprintf(stdout, "\n"); 1927*fcf3ce44SJohn Forte 1928*fcf3ce44SJohn Forte /* 1929*fcf3ce44SJohn Forte * get mode page information for FC device. 1930*fcf3ce44SJohn Forte * do not do mode sense if this is a tape device. 1931*fcf3ce44SJohn Forte * mode sense will rewind the tape 1932*fcf3ce44SJohn Forte */ 1933*fcf3ce44SJohn Forte if ((inq.inq_dtype & DTYPE_MASK) != DTYPE_SEQUENTIAL) { 1934*fcf3ce44SJohn Forte if (get_mode_page(first_time->map.ScsiId.OSDeviceName, 1935*fcf3ce44SJohn Forte &pg_buf) == 0) { 1936*fcf3ce44SJohn Forte mode_header_ptr = (struct mode_header_g1 *) 1937*fcf3ce44SJohn Forte (void *)pg_buf; 1938*fcf3ce44SJohn Forte offset = sizeof (struct mode_header_g1) + 1939*fcf3ce44SJohn Forte ntohs(mode_header_ptr->bdesc_length); 1940*fcf3ce44SJohn Forte pg_hdr = (struct mode_page *)&pg_buf[offset]; 1941*fcf3ce44SJohn Forte 1942*fcf3ce44SJohn Forte while (offset < (ntohs(mode_header_ptr->length) + 1943*fcf3ce44SJohn Forte sizeof (mode_header_ptr->length))) { 1944*fcf3ce44SJohn Forte if (pg_hdr->code == MODEPAGE_CACHING) { 1945*fcf3ce44SJohn Forte struct mode_caching *pg8_buf; 1946*fcf3ce44SJohn Forte pg8_buf = (struct mode_caching *) 1947*fcf3ce44SJohn Forte (void *)pg_hdr; 1948*fcf3ce44SJohn Forte if (pg8_buf->wce) { 1949*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2122, 1950*fcf3ce44SJohn Forte " Write Cache:\t\t" 1951*fcf3ce44SJohn Forte "Enabled\n")); 1952*fcf3ce44SJohn Forte } 1953*fcf3ce44SJohn Forte if (pg8_buf->rcd == 0) { 1954*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2123, 1955*fcf3ce44SJohn Forte " Read Cache:\t\t" 1956*fcf3ce44SJohn Forte "Enabled\n")); 1957*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2509, 1958*fcf3ce44SJohn Forte " Minimum prefetch:\t0x%x\n" 1959*fcf3ce44SJohn Forte " Maximum prefetch:\t0x%x\n"), 1960*fcf3ce44SJohn Forte pg8_buf->min_prefetch, 1961*fcf3ce44SJohn Forte pg8_buf->max_prefetch); 1962*fcf3ce44SJohn Forte } 1963*fcf3ce44SJohn Forte break; 1964*fcf3ce44SJohn Forte } 1965*fcf3ce44SJohn Forte offset += pg_hdr->length + 1966*fcf3ce44SJohn Forte sizeof (struct mode_page); 1967*fcf3ce44SJohn Forte pg_hdr = (struct mode_page *)&pg_buf[offset]; 1968*fcf3ce44SJohn Forte } 1969*fcf3ce44SJohn Forte } 1970*fcf3ce44SJohn Forte } 1971*fcf3ce44SJohn Forte 1972*fcf3ce44SJohn Forte fprintf(stdout, " %s\t\t", MSGSTR(35, "Device Type:")); 1973*fcf3ce44SJohn Forte if ((inq.inq_dtype & DTYPE_MASK) < 0x10) { 1974*fcf3ce44SJohn Forte fprintf(stdout, "%s\n", 1975*fcf3ce44SJohn Forte dtype[inq.inq_dtype & DTYPE_MASK]); 1976*fcf3ce44SJohn Forte } else if ((inq.inq_dtype & DTYPE_MASK) < 0x1f) { 1977*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2432, "Reserved")); 1978*fcf3ce44SJohn Forte } else { 1979*fcf3ce44SJohn Forte /* dtype of 0x1f is returned */ 1980*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2433, "Unknown")); 1981*fcf3ce44SJohn Forte } 1982*fcf3ce44SJohn Forte 1983*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2128, " Path(s):\n")); 1984*fcf3ce44SJohn Forte fprintf(stdout, "\n"); 1985*fcf3ce44SJohn Forte fprintf(stdout, " %s\n", 1986*fcf3ce44SJohn Forte first_time->map.ScsiId.OSDeviceName); 1987*fcf3ce44SJohn Forte if (phys_path != NULL) { 1988*fcf3ce44SJohn Forte fprintf(stdout, " %s\n", phys_path); 1989*fcf3ce44SJohn Forte } 1990*fcf3ce44SJohn Forte 1991*fcf3ce44SJohn Forte /* Now display all paths to this LUN */ 1992*fcf3ce44SJohn Forte for (path = first_time; path != NULL; 1993*fcf3ce44SJohn Forte path = path->next_path) { 1994*fcf3ce44SJohn Forte /* Display the controller information */ 1995*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2303, " Controller \t%s\n"), 1996*fcf3ce44SJohn Forte path->hba_path); 1997*fcf3ce44SJohn Forte 1998*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2507, 1999*fcf3ce44SJohn Forte " Device Address\t\t%016llx,%x\n"), 2000*fcf3ce44SJohn Forte wwnConversion( 2001*fcf3ce44SJohn Forte path->map.FcpId.PortWWN.wwn), 2002*fcf3ce44SJohn Forte path->map.ScsiId.ScsiOSLun); 2003*fcf3ce44SJohn Forte 2004*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2508, 2005*fcf3ce44SJohn Forte " Host controller port WWN\t%016llx\n"), 2006*fcf3ce44SJohn Forte wwnConversion(path->hba_pwwn.wwn)); 2007*fcf3ce44SJohn Forte 2008*fcf3ce44SJohn Forte if (mpxio) { 2009*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2305, 2010*fcf3ce44SJohn Forte " Class\t\t\t%s\n"), path->info.pathClass); 2011*fcf3ce44SJohn Forte fprintf(stdout, MSGSTR(2306, 2012*fcf3ce44SJohn Forte " State\t\t\t%s\n"), path->info.pathState); 2013*fcf3ce44SJohn Forte } 2014*fcf3ce44SJohn Forte if (phys_path != NULL) { 2015*fcf3ce44SJohn Forte free(phys_path); 2016*fcf3ce44SJohn Forte phys_path = NULL; 2017*fcf3ce44SJohn Forte } 2018*fcf3ce44SJohn Forte } 2019*fcf3ce44SJohn Forte printf("\n"); 2020*fcf3ce44SJohn Forte } 2021*fcf3ce44SJohn Forte } 2022*fcf3ce44SJohn Forte return (ret); 2023*fcf3ce44SJohn Forte } 2024*fcf3ce44SJohn Forte 2025*fcf3ce44SJohn Forte /* 2026*fcf3ce44SJohn Forte * handle expert-mode hotplug commands 2027*fcf3ce44SJohn Forte * 2028*fcf3ce44SJohn Forte * return 0 iff all is okay 2029*fcf3ce44SJohn Forte */ 2030*fcf3ce44SJohn Forte int 2031*fcf3ce44SJohn Forte fchba_hotplug_e(int todo, char **argv, int verbose_flag, int force_flag) 2032*fcf3ce44SJohn Forte { 2033*fcf3ce44SJohn Forte char *path_phys = NULL; 2034*fcf3ce44SJohn Forte int exit_code; 2035*fcf3ce44SJohn Forte devctl_hdl_t dcp; 2036*fcf3ce44SJohn Forte 2037*fcf3ce44SJohn Forte if (todo != DEV_ONLINE && 2038*fcf3ce44SJohn Forte todo != DEV_OFFLINE) { 2039*fcf3ce44SJohn Forte fprintf(stderr, "%s\n", strerror(ENOTSUP)); 2040*fcf3ce44SJohn Forte return (-1); 2041*fcf3ce44SJohn Forte } 2042*fcf3ce44SJohn Forte 2043*fcf3ce44SJohn Forte /* Convert the paths to phsyical paths */ 2044*fcf3ce44SJohn Forte path_phys = get_slash_devices_from_osDevName(argv[0], 2045*fcf3ce44SJohn Forte NOT_IGNORE_DANGLING_LINK); 2046*fcf3ce44SJohn Forte if (!path_phys) { 2047*fcf3ce44SJohn Forte fprintf(stderr, MSGSTR(112, 2048*fcf3ce44SJohn Forte "Error: Invalid pathname (%s)"), 2049*fcf3ce44SJohn Forte argv[0]); 2050*fcf3ce44SJohn Forte fprintf(stderr, "\n"); 2051*fcf3ce44SJohn Forte return (-1); 2052*fcf3ce44SJohn Forte } 2053*fcf3ce44SJohn Forte if (verbose_flag) { 2054*fcf3ce44SJohn Forte (void) fprintf(stdout, 2055*fcf3ce44SJohn Forte MSGSTR(5516, 2056*fcf3ce44SJohn Forte "phys path = \"%s\"\n"), 2057*fcf3ce44SJohn Forte path_phys); 2058*fcf3ce44SJohn Forte } 2059*fcf3ce44SJohn Forte /* acquire rights to hack on device */ 2060*fcf3ce44SJohn Forte if ((dcp = devctl_device_acquire(path_phys, 2061*fcf3ce44SJohn Forte force_flag ? 0 : DC_EXCL)) == NULL) { 2062*fcf3ce44SJohn Forte 2063*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5517, 2064*fcf3ce44SJohn Forte "Error: can't acquire \"%s\": %s\n"), 2065*fcf3ce44SJohn Forte path_phys, strerror(errno)); 2066*fcf3ce44SJohn Forte return (1); 2067*fcf3ce44SJohn Forte } 2068*fcf3ce44SJohn Forte 2069*fcf3ce44SJohn Forte switch (todo) { 2070*fcf3ce44SJohn Forte case DEV_ONLINE: 2071*fcf3ce44SJohn Forte exit_code = devctl_device_online(dcp); 2072*fcf3ce44SJohn Forte break; 2073*fcf3ce44SJohn Forte case DEV_OFFLINE: 2074*fcf3ce44SJohn Forte exit_code = devctl_device_offline(dcp); 2075*fcf3ce44SJohn Forte break; 2076*fcf3ce44SJohn Forte } 2077*fcf3ce44SJohn Forte 2078*fcf3ce44SJohn Forte if (exit_code != 0) { 2079*fcf3ce44SJohn Forte perror(MSGSTR(5518, "devctl")); 2080*fcf3ce44SJohn Forte } 2081*fcf3ce44SJohn Forte 2082*fcf3ce44SJohn Forte /* all done now -- release device */ 2083*fcf3ce44SJohn Forte devctl_release(dcp); 2084*fcf3ce44SJohn Forte 2085*fcf3ce44SJohn Forte if (path_phys) { 2086*fcf3ce44SJohn Forte free(path_phys); 2087*fcf3ce44SJohn Forte } 2088*fcf3ce44SJohn Forte 2089*fcf3ce44SJohn Forte return (exit_code); 2090*fcf3ce44SJohn Forte } 2091*fcf3ce44SJohn Forte 2092*fcf3ce44SJohn Forte /* 2093*fcf3ce44SJohn Forte * Returns non zero if we should use FC-HBA. 2094*fcf3ce44SJohn Forte * For x86, luxadm uses FC-HBA. 2095*fcf3ce44SJohn Forte */ 2096*fcf3ce44SJohn Forte int 2097*fcf3ce44SJohn Forte use_fchba() 2098*fcf3ce44SJohn Forte { 2099*fcf3ce44SJohn Forte 2100*fcf3ce44SJohn Forte #ifdef __x86 2101*fcf3ce44SJohn Forte return (1); 2102*fcf3ce44SJohn Forte #else 2103*fcf3ce44SJohn Forte return (0); 2104*fcf3ce44SJohn Forte #endif 2105*fcf3ce44SJohn Forte 2106*fcf3ce44SJohn Forte } 2107*fcf3ce44SJohn Forte 2108*fcf3ce44SJohn Forte /* 2109*fcf3ce44SJohn Forte * Returns non-zero if we should skip the HBA at index "i" 2110*fcf3ce44SJohn Forte */ 2111*fcf3ce44SJohn Forte int 2112*fcf3ce44SJohn Forte skip_hba(int i) { 2113*fcf3ce44SJohn Forte HBA_LIBRARYATTRIBUTES lib_attrs; 2114*fcf3ce44SJohn Forte (void) HBA_GetVendorLibraryAttributes(i, &lib_attrs); 2115*fcf3ce44SJohn Forte if (strncmp(lib_attrs.VName, VSL_NAME, 2116*fcf3ce44SJohn Forte sizeof (lib_attrs.VName)) == 0) { 2117*fcf3ce44SJohn Forte return (0); 2118*fcf3ce44SJohn Forte } 2119*fcf3ce44SJohn Forte return (1); 2120*fcf3ce44SJohn Forte } 2121*fcf3ce44SJohn Forte 2122*fcf3ce44SJohn Forte /* 2123*fcf3ce44SJohn Forte * Function to determine if the given page is supported by vendor. 2124*fcf3ce44SJohn Forte */ 2125*fcf3ce44SJohn Forte int 2126*fcf3ce44SJohn Forte find_supported_inq_page(HBA_HANDLE handle, HBA_WWN hwwn, HBA_WWN pwwn, 2127*fcf3ce44SJohn Forte uint64_t lun, int page_num) 2128*fcf3ce44SJohn Forte { 2129*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 2130*fcf3ce44SJohn Forte L_inquiry00 inq00; 2131*fcf3ce44SJohn Forte uchar_t *data; 2132*fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_ERROR; 2133*fcf3ce44SJohn Forte int index; 2134*fcf3ce44SJohn Forte HBA_UINT8 scsiStatus; 2135*fcf3ce44SJohn Forte uint32_t inqSize = sizeof (inq00); 2136*fcf3ce44SJohn Forte uint32_t senseSize = sizeof (sense); 2137*fcf3ce44SJohn Forte 2138*fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, hwwn, pwwn, lun, 1, 0x00, 2139*fcf3ce44SJohn Forte &inq00, &inqSize, &scsiStatus, &sense, &senseSize); 2140*fcf3ce44SJohn Forte 2141*fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) { 2142*fcf3ce44SJohn Forte data = (uchar_t *)&inq00; 2143*fcf3ce44SJohn Forte for (index = 4; (index <= inq00.len+3)&& 2144*fcf3ce44SJohn Forte (data[index] <= page_num); index ++) { 2145*fcf3ce44SJohn Forte if (data[index] == page_num) { 2146*fcf3ce44SJohn Forte return (1); 2147*fcf3ce44SJohn Forte } 2148*fcf3ce44SJohn Forte } 2149*fcf3ce44SJohn Forte } 2150*fcf3ce44SJohn Forte return (0); 2151*fcf3ce44SJohn Forte } 2152