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 /*LINTLIBRARY*/ 28*fcf3ce44SJohn Forte 29*fcf3ce44SJohn Forte 30*fcf3ce44SJohn Forte /* 31*fcf3ce44SJohn Forte * This module is part of the photon library 32*fcf3ce44SJohn Forte */ 33*fcf3ce44SJohn Forte 34*fcf3ce44SJohn Forte /* 35*fcf3ce44SJohn Forte * I18N message number ranges 36*fcf3ce44SJohn Forte * This file: 8500 - 8999 37*fcf3ce44SJohn Forte * Shared common messages: 1 - 1999 38*fcf3ce44SJohn Forte */ 39*fcf3ce44SJohn Forte 40*fcf3ce44SJohn Forte /* #define _POSIX_SOURCE 1 */ 41*fcf3ce44SJohn Forte 42*fcf3ce44SJohn Forte /* Includes */ 43*fcf3ce44SJohn Forte #include <stdlib.h> 44*fcf3ce44SJohn Forte #include <stdio.h> 45*fcf3ce44SJohn Forte #include <sys/file.h> 46*fcf3ce44SJohn Forte #include <sys/types.h> 47*fcf3ce44SJohn Forte #include <sys/stat.h> 48*fcf3ce44SJohn Forte #include <sys/param.h> 49*fcf3ce44SJohn Forte #include <fcntl.h> 50*fcf3ce44SJohn Forte #include <unistd.h> 51*fcf3ce44SJohn Forte #include <errno.h> 52*fcf3ce44SJohn Forte #include <string.h> 53*fcf3ce44SJohn Forte #include <time.h> 54*fcf3ce44SJohn Forte #include <sys/scsi/scsi.h> 55*fcf3ce44SJohn Forte #include <sys/vtoc.h> 56*fcf3ce44SJohn Forte #include <nl_types.h> 57*fcf3ce44SJohn Forte #include <strings.h> 58*fcf3ce44SJohn Forte #include <sys/ddi.h> /* for max */ 59*fcf3ce44SJohn Forte #include <l_common.h> 60*fcf3ce44SJohn Forte #include <stgcom.h> 61*fcf3ce44SJohn Forte #include <l_error.h> 62*fcf3ce44SJohn Forte #include <rom.h> 63*fcf3ce44SJohn Forte #include <a_state.h> 64*fcf3ce44SJohn Forte #include <a5k.h> 65*fcf3ce44SJohn Forte 66*fcf3ce44SJohn Forte 67*fcf3ce44SJohn Forte /* Global variables */ 68*fcf3ce44SJohn Forte extern uchar_t g_switch_to_alpa[]; 69*fcf3ce44SJohn Forte extern uchar_t g_sf_alpa_to_switch[]; 70*fcf3ce44SJohn Forte 71*fcf3ce44SJohn Forte 72*fcf3ce44SJohn Forte /* 73*fcf3ce44SJohn Forte * This function checks if the passed char pointer has WWN_SIZE nulls (zeroes). 74*fcf3ce44SJohn Forte * 75*fcf3ce44SJohn Forte * This is only a convenience function. 76*fcf3ce44SJohn Forte * 77*fcf3ce44SJohn Forte * INPUT: 78*fcf3ce44SJohn Forte * wwn_ptr - pointer to a character string of length WWN_SIZE 79*fcf3ce44SJohn Forte * It is expected to be holding the WWN 80*fcf3ce44SJohn Forte * Ex: A WWN like 508002000000ddc1 is expected to be stored as 81*fcf3ce44SJohn Forte * the following 8 bytes - 82*fcf3ce44SJohn Forte * 0x50, 0x80, 0x00, 0x20, ... etc 83*fcf3ce44SJohn Forte * 84*fcf3ce44SJohn Forte * RETURNS: 85*fcf3ce44SJohn Forte * 0 - if there is atleast one of WWN_SIZE bytes is != '\0' 86*fcf3ce44SJohn Forte * non-zero - if all WWN_SIZE bytes are '\0' 87*fcf3ce44SJohn Forte */ 88*fcf3ce44SJohn Forte int 89*fcf3ce44SJohn Forte is_null_wwn(uchar_t *wwn_ptr) 90*fcf3ce44SJohn Forte { 91*fcf3ce44SJohn Forte int i; 92*fcf3ce44SJohn Forte 93*fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE; i++) { 94*fcf3ce44SJohn Forte if (wwn_ptr[i] != '\0' || wwn_ptr[i] != '0') 95*fcf3ce44SJohn Forte return (0); 96*fcf3ce44SJohn Forte } 97*fcf3ce44SJohn Forte return (1); 98*fcf3ce44SJohn Forte } 99*fcf3ce44SJohn Forte 100*fcf3ce44SJohn Forte 101*fcf3ce44SJohn Forte /* 102*fcf3ce44SJohn Forte * This functions constructs a device path of the device/enclosure with the 103*fcf3ce44SJohn Forte * given tid and, for public/fabric cases, on the same area and domain as 104*fcf3ce44SJohn Forte * the given ses_path. 105*fcf3ce44SJohn Forte * 106*fcf3ce44SJohn Forte * INPUT: 107*fcf3ce44SJohn Forte * ses_path - pointer to the ses_path 108*fcf3ce44SJohn Forte * tid - tid of the device/enclosure whose path is to be constructed 109*fcf3ce44SJohn Forte * map - pointer to the map 110*fcf3ce44SJohn Forte * dtype - dtype of the device whose path is to be constructed 111*fcf3ce44SJohn Forte * 112*fcf3ce44SJohn Forte * OUTPUT: 113*fcf3ce44SJohn Forte * dev_path - pointer to the device path of type dtype and with tid 114*fcf3ce44SJohn Forte * - Caller has to free this after use 115*fcf3ce44SJohn Forte * 116*fcf3ce44SJohn Forte * RETURNS: 117*fcf3ce44SJohn Forte * 0 - on success 118*fcf3ce44SJohn Forte * non-zero - otherwise 119*fcf3ce44SJohn Forte */ 120*fcf3ce44SJohn Forte int 121*fcf3ce44SJohn Forte l_make_node(char *ses_path, int tid, char *dev_path, 122*fcf3ce44SJohn Forte gfc_map_t *map, int dtype) 123*fcf3ce44SJohn Forte { 124*fcf3ce44SJohn Forte int len, i, err; 125*fcf3ce44SJohn Forte int this_pid, ses_pid; 126*fcf3ce44SJohn Forte char ssd[40], wwn[20]; 127*fcf3ce44SJohn Forte gfc_port_dev_info_t *dev_addr_ptr; 128*fcf3ce44SJohn Forte struct stat stat_buf; 129*fcf3ce44SJohn Forte WWN_list *wwnlp, *wwn_list; 130*fcf3ce44SJohn Forte int found = 0; 131*fcf3ce44SJohn Forte 132*fcf3ce44SJohn Forte if ((ses_path == NULL) || (dev_path == NULL) || (map == NULL)) { 133*fcf3ce44SJohn Forte return (L_INVALID_PATH_FORMAT); 134*fcf3ce44SJohn Forte } 135*fcf3ce44SJohn Forte 136*fcf3ce44SJohn Forte switch (map->hba_addr.port_topology) { 137*fcf3ce44SJohn Forte case FC_TOP_PRIVATE_LOOP: 138*fcf3ce44SJohn Forte for (i = 0, dev_addr_ptr = map->dev_addr; 139*fcf3ce44SJohn Forte i < map->count; i++, dev_addr_ptr++) { 140*fcf3ce44SJohn Forte if (dev_addr_ptr->gfc_port_dev.priv_port. 141*fcf3ce44SJohn Forte sf_al_pa == g_switch_to_alpa[tid]) 142*fcf3ce44SJohn Forte break; 143*fcf3ce44SJohn Forte } 144*fcf3ce44SJohn Forte if (i >= map->count) { 145*fcf3ce44SJohn Forte *dev_path = '\0'; 146*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 147*fcf3ce44SJohn Forte } 148*fcf3ce44SJohn Forte 149*fcf3ce44SJohn Forte /* Make sure that the port WWN is valid */ 150*fcf3ce44SJohn Forte if (is_null_wwn(dev_addr_ptr->gfc_port_dev. 151*fcf3ce44SJohn Forte priv_port.sf_port_wwn)) { 152*fcf3ce44SJohn Forte *dev_path = '\0'; 153*fcf3ce44SJohn Forte return (L_INVLD_WWN_FORMAT); 154*fcf3ce44SJohn Forte } 155*fcf3ce44SJohn Forte 156*fcf3ce44SJohn Forte (void) g_ll_to_str(dev_addr_ptr->gfc_port_dev. 157*fcf3ce44SJohn Forte priv_port.sf_port_wwn, wwn); 158*fcf3ce44SJohn Forte 159*fcf3ce44SJohn Forte if (strstr(ses_path, SCSI_VHCI) != NULL) { 160*fcf3ce44SJohn Forte if (err = g_get_wwn_list(&wwn_list, 0)) { 161*fcf3ce44SJohn Forte return (err); 162*fcf3ce44SJohn Forte } 163*fcf3ce44SJohn Forte for (wwnlp = wwn_list, found = 0; 164*fcf3ce44SJohn Forte wwnlp != NULL; 165*fcf3ce44SJohn Forte wwnlp = wwnlp->wwn_next) { 166*fcf3ce44SJohn Forte if (strcmp(wwnlp->port_wwn_s, 167*fcf3ce44SJohn Forte wwn) == 0) { 168*fcf3ce44SJohn Forte found = 1; 169*fcf3ce44SJohn Forte break; 170*fcf3ce44SJohn Forte } 171*fcf3ce44SJohn Forte } 172*fcf3ce44SJohn Forte if (found) { 173*fcf3ce44SJohn Forte (void) strcpy(dev_path, 174*fcf3ce44SJohn Forte wwnlp->physical_path); 175*fcf3ce44SJohn Forte } else { 176*fcf3ce44SJohn Forte return (L_INVALID_PATH); 177*fcf3ce44SJohn Forte } 178*fcf3ce44SJohn Forte } else { 179*fcf3ce44SJohn Forte 180*fcf3ce44SJohn Forte len = strlen(ses_path) - 181*fcf3ce44SJohn Forte strlen(strrchr(ses_path, '/')); 182*fcf3ce44SJohn Forte 183*fcf3ce44SJohn Forte if (dtype != DTYPE_ESI) { 184*fcf3ce44SJohn Forte (void) sprintf(ssd, 185*fcf3ce44SJohn Forte "/ssd@w%s,0:c", wwn); 186*fcf3ce44SJohn Forte } else { 187*fcf3ce44SJohn Forte (void) sprintf(ssd, 188*fcf3ce44SJohn Forte "/ses@w%s,0:c", wwn); 189*fcf3ce44SJohn Forte } 190*fcf3ce44SJohn Forte 191*fcf3ce44SJohn Forte /* TBD: Must find path, not just use :c */ 192*fcf3ce44SJohn Forte (void) strncpy(dev_path, ses_path, len); 193*fcf3ce44SJohn Forte dev_path[len] = '\0'; 194*fcf3ce44SJohn Forte (void) strcat(dev_path, ssd); 195*fcf3ce44SJohn Forte } 196*fcf3ce44SJohn Forte break; 197*fcf3ce44SJohn Forte case FC_TOP_FABRIC: 198*fcf3ce44SJohn Forte case FC_TOP_PUBLIC_LOOP: 199*fcf3ce44SJohn Forte /* First lets get the PA from the ses path passed in */ 200*fcf3ce44SJohn Forte if (err = l_get_pid_from_path(ses_path, map, &ses_pid)) { 201*fcf3ce44SJohn Forte return (err); 202*fcf3ce44SJohn Forte } 203*fcf3ce44SJohn Forte 204*fcf3ce44SJohn Forte /* 205*fcf3ce44SJohn Forte * Now we go through every entry in the map and match the 206*fcf3ce44SJohn Forte * area and domain ids with the PA of the passed ses path. 207*fcf3ce44SJohn Forte * If we find a match, we then match the low order byte 208*fcf3ce44SJohn Forte */ 209*fcf3ce44SJohn Forte for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count; 210*fcf3ce44SJohn Forte i++, dev_addr_ptr++) { 211*fcf3ce44SJohn Forte this_pid = dev_addr_ptr->gfc_port_dev.pub_port. 212*fcf3ce44SJohn Forte dev_did.port_id; 213*fcf3ce44SJohn Forte if ((this_pid & AREA_DOMAIN_ID) == 214*fcf3ce44SJohn Forte (ses_pid & AREA_DOMAIN_ID)) { 215*fcf3ce44SJohn Forte if ((uchar_t)(this_pid & 0xFF) == 216*fcf3ce44SJohn Forte g_switch_to_alpa[tid]) 217*fcf3ce44SJohn Forte break; 218*fcf3ce44SJohn Forte } 219*fcf3ce44SJohn Forte } 220*fcf3ce44SJohn Forte if (i >= map->count) { 221*fcf3ce44SJohn Forte *dev_path = '\0'; 222*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 223*fcf3ce44SJohn Forte } 224*fcf3ce44SJohn Forte /* Make sure that the port WWN is valid */ 225*fcf3ce44SJohn Forte if (is_null_wwn(dev_addr_ptr->gfc_port_dev.pub_port. 226*fcf3ce44SJohn Forte dev_pwwn.raw_wwn)) { 227*fcf3ce44SJohn Forte *dev_path = '\0'; 228*fcf3ce44SJohn Forte return (L_INVLD_WWN_FORMAT); 229*fcf3ce44SJohn Forte } 230*fcf3ce44SJohn Forte (void) g_ll_to_str(dev_addr_ptr->gfc_port_dev. 231*fcf3ce44SJohn Forte pub_port.dev_pwwn.raw_wwn, wwn); 232*fcf3ce44SJohn Forte 233*fcf3ce44SJohn Forte 234*fcf3ce44SJohn Forte 235*fcf3ce44SJohn Forte if (strstr(ses_path, SCSI_VHCI) != NULL) { 236*fcf3ce44SJohn Forte if (err = g_get_wwn_list(&wwn_list, 0)) { 237*fcf3ce44SJohn Forte return (err); 238*fcf3ce44SJohn Forte } 239*fcf3ce44SJohn Forte for (wwnlp = wwn_list, found = 0; wwnlp != NULL; 240*fcf3ce44SJohn Forte wwnlp = wwnlp->wwn_next) { 241*fcf3ce44SJohn Forte if (strcmp(wwnlp->port_wwn_s, 242*fcf3ce44SJohn Forte wwn) == 0) { 243*fcf3ce44SJohn Forte found = 1; 244*fcf3ce44SJohn Forte } 245*fcf3ce44SJohn Forte } 246*fcf3ce44SJohn Forte if (found) { 247*fcf3ce44SJohn Forte (void) strcpy(dev_path, 248*fcf3ce44SJohn Forte wwnlp->physical_path); 249*fcf3ce44SJohn Forte } else { 250*fcf3ce44SJohn Forte return (L_INVALID_PATH); 251*fcf3ce44SJohn Forte } 252*fcf3ce44SJohn Forte } else { 253*fcf3ce44SJohn Forte len = strlen(ses_path) - 254*fcf3ce44SJohn Forte strlen(strrchr(ses_path, '/')); 255*fcf3ce44SJohn Forte 256*fcf3ce44SJohn Forte if (dtype != DTYPE_ESI) { 257*fcf3ce44SJohn Forte (void) sprintf(ssd, "/ssd@w%s,0:c", wwn); 258*fcf3ce44SJohn Forte } else { 259*fcf3ce44SJohn Forte (void) sprintf(ssd, "/ses@w%s,0:c", wwn); 260*fcf3ce44SJohn Forte } 261*fcf3ce44SJohn Forte 262*fcf3ce44SJohn Forte /* TBD: Must find path, not just use :c */ 263*fcf3ce44SJohn Forte (void) strncpy(dev_path, ses_path, len); 264*fcf3ce44SJohn Forte dev_path[len] = '\0'; 265*fcf3ce44SJohn Forte (void) strcat(dev_path, ssd); 266*fcf3ce44SJohn Forte } 267*fcf3ce44SJohn Forte 268*fcf3ce44SJohn Forte if (stat(dev_path, &stat_buf) == -1) { 269*fcf3ce44SJohn Forte return (errno); 270*fcf3ce44SJohn Forte } 271*fcf3ce44SJohn Forte 272*fcf3ce44SJohn Forte break; 273*fcf3ce44SJohn Forte case FC_TOP_PT_PT: 274*fcf3ce44SJohn Forte return (L_PT_PT_FC_TOP_NOT_SUPPORTED); 275*fcf3ce44SJohn Forte default: 276*fcf3ce44SJohn Forte return (L_UNEXPECTED_FC_TOPOLOGY); 277*fcf3ce44SJohn Forte } /* End of switch on port_topology */ 278*fcf3ce44SJohn Forte return (0); 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte 282*fcf3ce44SJohn Forte 283*fcf3ce44SJohn Forte /* 284*fcf3ce44SJohn Forte * checks for null wwn to a disk. 285*fcf3ce44SJohn Forte * and returns -1 if found, 0 286*fcf3ce44SJohn Forte * otherwise. 287*fcf3ce44SJohn Forte * 288*fcf3ce44SJohn Forte * OUTPUT: 289*fcf3ce44SJohn Forte * char *ses_path 290*fcf3ce44SJohn Forte * 291*fcf3ce44SJohn Forte * RETURNS: 292*fcf3ce44SJohn Forte * 0 if OK 293*fcf3ce44SJohn Forte * non-zero otherwise 294*fcf3ce44SJohn Forte */ 295*fcf3ce44SJohn Forte int 296*fcf3ce44SJohn Forte l_chk_null_wwn(Path_struct *path_struct, char *ses_path, 297*fcf3ce44SJohn Forte L_state *l_state, int verbose) 298*fcf3ce44SJohn Forte { 299*fcf3ce44SJohn Forte char *ptr, boxname[MAXPATHLEN]; 300*fcf3ce44SJohn Forte char node_wwn_s[WWN_SIZE * 2 + 1]; 301*fcf3ce44SJohn Forte Box_list *boxlist; 302*fcf3ce44SJohn Forte 303*fcf3ce44SJohn Forte 304*fcf3ce44SJohn Forte if ((path_struct == NULL) || (ses_path == NULL) || 305*fcf3ce44SJohn Forte (l_state == NULL)) { 306*fcf3ce44SJohn Forte return (L_INVALID_PATH_FORMAT); 307*fcf3ce44SJohn Forte } 308*fcf3ce44SJohn Forte 309*fcf3ce44SJohn Forte /* 310*fcf3ce44SJohn Forte * verify and continue only if the argv 311*fcf3ce44SJohn Forte * has a format like box,{f/r}<slot #>. 312*fcf3ce44SJohn Forte * Otherwise, return to the caller. 313*fcf3ce44SJohn Forte * The only way to address null wwn disk 314*fcf3ce44SJohn Forte * is using the box,{f/r}<slot#> format. 315*fcf3ce44SJohn Forte */ 316*fcf3ce44SJohn Forte /* add support for new {f/r/s}<slot#> support for DPM */ 317*fcf3ce44SJohn Forte (void) strcpy(boxname, path_struct->argv); 318*fcf3ce44SJohn Forte if (((ptr = strstr(boxname, ",")) != NULL) && 319*fcf3ce44SJohn Forte ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') || 320*fcf3ce44SJohn Forte (*(ptr + 1) == 's'))) { 321*fcf3ce44SJohn Forte *ptr = NULL; 322*fcf3ce44SJohn Forte } else { 323*fcf3ce44SJohn Forte return (0); 324*fcf3ce44SJohn Forte } 325*fcf3ce44SJohn Forte 326*fcf3ce44SJohn Forte 327*fcf3ce44SJohn Forte /* 328*fcf3ce44SJohn Forte * Get the list of enclosures 329*fcf3ce44SJohn Forte * connected to the system. 330*fcf3ce44SJohn Forte */ 331*fcf3ce44SJohn Forte if (l_get_box_list(&boxlist, verbose) != 0) { 332*fcf3ce44SJohn Forte return (L_NO_ENCL_LIST_FOUND); 333*fcf3ce44SJohn Forte } 334*fcf3ce44SJohn Forte 335*fcf3ce44SJohn Forte *ses_path = NULL; 336*fcf3ce44SJohn Forte 337*fcf3ce44SJohn Forte /* 338*fcf3ce44SJohn Forte * The following method is safer to get an ses path 339*fcf3ce44SJohn Forte * to the enclosure than calling l_get_ses_path(), 340*fcf3ce44SJohn Forte * with physical path to null WWN disk. 341*fcf3ce44SJohn Forte * Because, l_get_ses_path uses the disk's 342*fcf3ce44SJohn Forte * al_pa to get the box id and then ses path 343*fcf3ce44SJohn Forte * to the box. When a disk has null wwn, it may 344*fcf3ce44SJohn Forte * not have a valid al_pa, and hard address. 345*fcf3ce44SJohn Forte * There is a possibility that l_get_ses_path() 346*fcf3ce44SJohn Forte * not returning ses path to the correct enclosure. 347*fcf3ce44SJohn Forte */ 348*fcf3ce44SJohn Forte while (boxlist != NULL) { 349*fcf3ce44SJohn Forte if ((strcmp(boxname, (char *)boxlist->b_name) == 0)) { 350*fcf3ce44SJohn Forte (void) strcpy(ses_path, boxlist->b_physical_path); 351*fcf3ce44SJohn Forte break; 352*fcf3ce44SJohn Forte } 353*fcf3ce44SJohn Forte boxlist = boxlist->box_next; 354*fcf3ce44SJohn Forte } 355*fcf3ce44SJohn Forte 356*fcf3ce44SJohn Forte /* free the box list */ 357*fcf3ce44SJohn Forte (void) l_free_box_list(&boxlist); 358*fcf3ce44SJohn Forte 359*fcf3ce44SJohn Forte if ((ses_path != NULL) && (strstr(ses_path, "ses") != NULL)) { 360*fcf3ce44SJohn Forte if (l_get_status(ses_path, l_state, 361*fcf3ce44SJohn Forte verbose) != 0) { 362*fcf3ce44SJohn Forte return (L_GET_STATUS_FAILED); 363*fcf3ce44SJohn Forte } 364*fcf3ce44SJohn Forte if (path_struct->f_flag) { 365*fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, 366*fcf3ce44SJohn Forte l_state->drv_front[path_struct->slot].g_disk_state.node_wwn_s); 367*fcf3ce44SJohn Forte } else { 368*fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, 369*fcf3ce44SJohn Forte l_state->drv_rear[path_struct->slot].g_disk_state.node_wwn_s); 370*fcf3ce44SJohn Forte } 371*fcf3ce44SJohn Forte 372*fcf3ce44SJohn Forte W_DPRINTF("Found ses path: %s\n" 373*fcf3ce44SJohn Forte "and Node WWN: %s\n", ses_path, node_wwn_s); 374*fcf3ce44SJohn Forte 375*fcf3ce44SJohn Forte /* check for null WWN */ 376*fcf3ce44SJohn Forte if (is_null_wwn((uchar_t *)node_wwn_s) == 0) { 377*fcf3ce44SJohn Forte return (0); /* Non-null wwn */ 378*fcf3ce44SJohn Forte } 379*fcf3ce44SJohn Forte W_DPRINTF("Found NULL WWN: %s\n", node_wwn_s); 380*fcf3ce44SJohn Forte return (1); 381*fcf3ce44SJohn Forte } 382*fcf3ce44SJohn Forte 383*fcf3ce44SJohn Forte return (0); 384*fcf3ce44SJohn Forte 385*fcf3ce44SJohn Forte } 386*fcf3ce44SJohn Forte 387*fcf3ce44SJohn Forte 388*fcf3ce44SJohn Forte 389*fcf3ce44SJohn Forte /* 390*fcf3ce44SJohn Forte * If OVERALL_STATUS is sent as the "func", 391*fcf3ce44SJohn Forte * the code pointer must be valid (non NULL). 392*fcf3ce44SJohn Forte * Otherwise NULL is a valid input for the code pointer. 393*fcf3ce44SJohn Forte * 394*fcf3ce44SJohn Forte * RETURNS: 395*fcf3ce44SJohn Forte * 0 if OK 396*fcf3ce44SJohn Forte * non-zero otherwise 397*fcf3ce44SJohn Forte */ 398*fcf3ce44SJohn Forte int 399*fcf3ce44SJohn Forte l_encl_status_page_funcs(int func, char *code, int todo, char *ses_path, 400*fcf3ce44SJohn Forte struct l_state_struct *l_state, 401*fcf3ce44SJohn Forte int f_flag, int slot, int verbose_flag) 402*fcf3ce44SJohn Forte { 403*fcf3ce44SJohn Forte uchar_t *page_buf; 404*fcf3ce44SJohn Forte int fd, front_index, rear_index, offset, err; 405*fcf3ce44SJohn Forte unsigned short page_len; 406*fcf3ce44SJohn Forte struct device_element *elem; 407*fcf3ce44SJohn Forte 408*fcf3ce44SJohn Forte if ((ses_path == NULL) || (l_state == NULL)) { 409*fcf3ce44SJohn Forte return (L_INVALID_PATH_FORMAT); 410*fcf3ce44SJohn Forte } 411*fcf3ce44SJohn Forte 412*fcf3ce44SJohn Forte if ((page_buf = (uchar_t *)g_zalloc(MAX_REC_DIAG_LENGTH)) == NULL) { 413*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 414*fcf3ce44SJohn Forte } 415*fcf3ce44SJohn Forte 416*fcf3ce44SJohn Forte if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) { 417*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 418*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 419*fcf3ce44SJohn Forte } 420*fcf3ce44SJohn Forte 421*fcf3ce44SJohn Forte if ((err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH, 422*fcf3ce44SJohn Forte L_PAGE_2, verbose_flag)) != 0) { 423*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 424*fcf3ce44SJohn Forte (void) close(fd); 425*fcf3ce44SJohn Forte return (err); 426*fcf3ce44SJohn Forte } 427*fcf3ce44SJohn Forte 428*fcf3ce44SJohn Forte page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN; 429*fcf3ce44SJohn Forte 430*fcf3ce44SJohn Forte if ((err = l_get_disk_element_index(l_state, &front_index, 431*fcf3ce44SJohn Forte &rear_index)) != 0) { 432*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 433*fcf3ce44SJohn Forte (void) close(fd); 434*fcf3ce44SJohn Forte return (err); 435*fcf3ce44SJohn Forte } 436*fcf3ce44SJohn Forte /* Skip global element */ 437*fcf3ce44SJohn Forte front_index++; 438*fcf3ce44SJohn Forte if ((strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_OFF_NAME, 439*fcf3ce44SJohn Forte strlen(DAK_OFF_NAME)) == 0) || 440*fcf3ce44SJohn Forte (strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_PROD_STR, 441*fcf3ce44SJohn Forte strlen(DAK_OFF_NAME)) == 0)) { 442*fcf3ce44SJohn Forte rear_index += l_state->total_num_drv/2 + 1; 443*fcf3ce44SJohn Forte } else 444*fcf3ce44SJohn Forte rear_index++; 445*fcf3ce44SJohn Forte 446*fcf3ce44SJohn Forte if (f_flag) { 447*fcf3ce44SJohn Forte offset = (8 + (front_index + slot)*4); 448*fcf3ce44SJohn Forte } else { 449*fcf3ce44SJohn Forte offset = (8 + (rear_index + slot)*4); 450*fcf3ce44SJohn Forte } 451*fcf3ce44SJohn Forte 452*fcf3ce44SJohn Forte elem = (struct device_element *)(page_buf + offset); 453*fcf3ce44SJohn Forte 454*fcf3ce44SJohn Forte switch (func) { 455*fcf3ce44SJohn Forte case OVERALL_STATUS: 456*fcf3ce44SJohn Forte if (code == NULL) { 457*fcf3ce44SJohn Forte return (L_INVALID_ARG); 458*fcf3ce44SJohn Forte } 459*fcf3ce44SJohn Forte switch (todo) { 460*fcf3ce44SJohn Forte case INSERT_DEVICE: 461*fcf3ce44SJohn Forte *code = (elem->code != S_OK) ? elem->code : 0; 462*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 463*fcf3ce44SJohn Forte (void) close(fd); 464*fcf3ce44SJohn Forte return (0); 465*fcf3ce44SJohn Forte case REMOVE_DEVICE: 466*fcf3ce44SJohn Forte *code = (elem->code != S_NOT_INSTALLED) ? 467*fcf3ce44SJohn Forte elem->code : 0; 468*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 469*fcf3ce44SJohn Forte (void) close(fd); 470*fcf3ce44SJohn Forte return (0); 471*fcf3ce44SJohn Forte } 472*fcf3ce44SJohn Forte /* NOTREACHED */ 473*fcf3ce44SJohn Forte case SET_RQST_INSRT: 474*fcf3ce44SJohn Forte bzero(elem, sizeof (struct device_element)); 475*fcf3ce44SJohn Forte elem->select = 1; 476*fcf3ce44SJohn Forte elem->rdy_to_ins = 1; 477*fcf3ce44SJohn Forte break; 478*fcf3ce44SJohn Forte case SET_RQST_RMV: 479*fcf3ce44SJohn Forte bzero(elem, sizeof (struct device_element)); 480*fcf3ce44SJohn Forte elem->select = 1; 481*fcf3ce44SJohn Forte elem->rmv = 1; 482*fcf3ce44SJohn Forte elem->dev_off = 1; 483*fcf3ce44SJohn Forte elem->en_bypass_a = 1; 484*fcf3ce44SJohn Forte elem->en_bypass_b = 1; 485*fcf3ce44SJohn Forte break; 486*fcf3ce44SJohn Forte case SET_FAULT: 487*fcf3ce44SJohn Forte bzero(elem, sizeof (struct device_element)); 488*fcf3ce44SJohn Forte elem->select = 1; 489*fcf3ce44SJohn Forte elem->fault_req = 1; 490*fcf3ce44SJohn Forte elem->dev_off = 1; 491*fcf3ce44SJohn Forte elem->en_bypass_a = 1; 492*fcf3ce44SJohn Forte elem->en_bypass_b = 1; 493*fcf3ce44SJohn Forte break; 494*fcf3ce44SJohn Forte case SET_DRV_ON: 495*fcf3ce44SJohn Forte bzero(elem, sizeof (struct device_element)); 496*fcf3ce44SJohn Forte elem->select = 1; 497*fcf3ce44SJohn Forte break; 498*fcf3ce44SJohn Forte } 499*fcf3ce44SJohn Forte 500*fcf3ce44SJohn Forte err = g_scsi_send_diag_cmd(fd, (uchar_t *)page_buf, page_len); 501*fcf3ce44SJohn Forte (void) g_destroy_data(page_buf); 502*fcf3ce44SJohn Forte (void) close(fd); 503*fcf3ce44SJohn Forte return (err); 504*fcf3ce44SJohn Forte } 505*fcf3ce44SJohn Forte 506*fcf3ce44SJohn Forte 507*fcf3ce44SJohn Forte 508*fcf3ce44SJohn Forte /* 509*fcf3ce44SJohn Forte * Finds whether device id (tid) exists in the 510*fcf3ce44SJohn Forte * Arbitrated loop map or not. 511*fcf3ce44SJohn Forte * 512*fcf3ce44SJohn Forte * INPUT: 513*fcf3ce44SJohn Forte * ses_path - pointer to a ses path 514*fcf3ce44SJohn Forte * tid - the target id of the device we want to check on 515*fcf3ce44SJohn Forte * - only the low order 8 bits has the tid 516*fcf3ce44SJohn Forte * map - pointer to a map of the system 517*fcf3ce44SJohn Forte * verbose_flag - self explanatory 518*fcf3ce44SJohn Forte * 519*fcf3ce44SJohn Forte * OUTPUT: 520*fcf3ce44SJohn Forte * dev_path - the device path of the device with "tid". 521*fcf3ce44SJohn Forte * Caller is responsible for freeing it 522*fcf3ce44SJohn Forte * 523*fcf3ce44SJohn Forte * RETURNS: 524*fcf3ce44SJohn Forte * 1 if device present 525*fcf3ce44SJohn Forte * 0 otherwise 526*fcf3ce44SJohn Forte */ 527*fcf3ce44SJohn Forte int 528*fcf3ce44SJohn Forte l_device_present(char *ses_path, int tid, gfc_map_t *map, 529*fcf3ce44SJohn Forte int verbose_flag, char **dev_path) 530*fcf3ce44SJohn Forte { 531*fcf3ce44SJohn Forte char sf_path[MAXPATHLEN]; 532*fcf3ce44SJohn Forte uchar_t wwn[40], c; 533*fcf3ce44SJohn Forte int len, i, j, k, fnib, snib, this_pid; 534*fcf3ce44SJohn Forte int fd, ses_pid, al_pa, err; 535*fcf3ce44SJohn Forte char ssd[30]; 536*fcf3ce44SJohn Forte gfc_port_dev_info_t *dev_addr_ptr; 537*fcf3ce44SJohn Forte WWN_list *wwnlp, *wwn_list; 538*fcf3ce44SJohn Forte 539*fcf3ce44SJohn Forte 540*fcf3ce44SJohn Forte if (dev_path == NULL) 541*fcf3ce44SJohn Forte return (0); 542*fcf3ce44SJohn Forte 543*fcf3ce44SJohn Forte if ((ses_path == NULL) || (map == NULL)) { 544*fcf3ce44SJohn Forte return (L_NO_SES_PATH); 545*fcf3ce44SJohn Forte } 546*fcf3ce44SJohn Forte 547*fcf3ce44SJohn Forte *dev_path = NULL; 548*fcf3ce44SJohn Forte 549*fcf3ce44SJohn Forte switch (map->hba_addr.port_topology) { 550*fcf3ce44SJohn Forte case FC_TOP_PRIVATE_LOOP: 551*fcf3ce44SJohn Forte for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count; 552*fcf3ce44SJohn Forte i++, dev_addr_ptr++) { 553*fcf3ce44SJohn Forte if (dev_addr_ptr->gfc_port_dev. 554*fcf3ce44SJohn Forte priv_port.sf_inq_dtype != DTYPE_ESI) { 555*fcf3ce44SJohn Forte al_pa = dev_addr_ptr->gfc_port_dev. 556*fcf3ce44SJohn Forte priv_port.sf_al_pa; 557*fcf3ce44SJohn Forte if (tid == g_sf_alpa_to_switch[al_pa]) { 558*fcf3ce44SJohn Forte break; 559*fcf3ce44SJohn Forte } 560*fcf3ce44SJohn Forte } 561*fcf3ce44SJohn Forte } 562*fcf3ce44SJohn Forte if (i >= map->count) 563*fcf3ce44SJohn Forte return (0); 564*fcf3ce44SJohn Forte /* 565*fcf3ce44SJohn Forte * Make sure that the port WWN is valid 566*fcf3ce44SJohn Forte */ 567*fcf3ce44SJohn Forte if (is_null_wwn(dev_addr_ptr->gfc_port_dev. 568*fcf3ce44SJohn Forte priv_port.sf_port_wwn)) { 569*fcf3ce44SJohn Forte return (0); 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte for (j = 0, k = 0; j < WWN_SIZE; j++) { 572*fcf3ce44SJohn Forte c = dev_addr_ptr->gfc_port_dev.priv_port.sf_port_wwn[j]; 573*fcf3ce44SJohn Forte fnib = (((int)(c & 0xf0)) >> 4); 574*fcf3ce44SJohn Forte snib = (c & 0x0f); 575*fcf3ce44SJohn Forte if (fnib >= 0 && fnib <= 9) 576*fcf3ce44SJohn Forte wwn[k++] = '0' + fnib; 577*fcf3ce44SJohn Forte else if (fnib >= 10 && fnib <= 15) 578*fcf3ce44SJohn Forte wwn[k++] = 'a' + fnib - 10; 579*fcf3ce44SJohn Forte if (snib >= 0 && snib <= 9) 580*fcf3ce44SJohn Forte wwn[k++] = '0' + snib; 581*fcf3ce44SJohn Forte else if (snib >= 10 && snib <= 15) 582*fcf3ce44SJohn Forte wwn[k++] = 'a' + snib - 10; 583*fcf3ce44SJohn Forte } 584*fcf3ce44SJohn Forte wwn[k] = '\0'; 585*fcf3ce44SJohn Forte break; 586*fcf3ce44SJohn Forte case FC_TOP_PUBLIC_LOOP: 587*fcf3ce44SJohn Forte case FC_TOP_FABRIC: 588*fcf3ce44SJohn Forte /* 589*fcf3ce44SJohn Forte * Get the phys address (port id) of this ses device 590*fcf3ce44SJohn Forte */ 591*fcf3ce44SJohn Forte if (err = l_get_pid_from_path(ses_path, map, &ses_pid)) 592*fcf3ce44SJohn Forte return (err); 593*fcf3ce44SJohn Forte 594*fcf3ce44SJohn Forte for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count; 595*fcf3ce44SJohn Forte i++, dev_addr_ptr++) { 596*fcf3ce44SJohn Forte if (dev_addr_ptr->gfc_port_dev.pub_port.dev_dtype != 597*fcf3ce44SJohn Forte DTYPE_ESI) { 598*fcf3ce44SJohn Forte /* 599*fcf3ce44SJohn Forte * We have a device. First match the area and 600*fcf3ce44SJohn Forte * domain ids and if they match, then see if 601*fcf3ce44SJohn Forte * the 8bit tid matches the last 8 bits of 602*fcf3ce44SJohn Forte * 'this_pid' 603*fcf3ce44SJohn Forte */ 604*fcf3ce44SJohn Forte this_pid = dev_addr_ptr->gfc_port_dev. 605*fcf3ce44SJohn Forte pub_port.dev_did.port_id; 606*fcf3ce44SJohn Forte if ((this_pid & AREA_DOMAIN_ID) == 607*fcf3ce44SJohn Forte (ses_pid & AREA_DOMAIN_ID)) { 608*fcf3ce44SJohn Forte if (tid == g_sf_alpa_to_switch[ 609*fcf3ce44SJohn Forte this_pid & 0xFF]) 610*fcf3ce44SJohn Forte break; 611*fcf3ce44SJohn Forte } 612*fcf3ce44SJohn Forte } 613*fcf3ce44SJohn Forte } 614*fcf3ce44SJohn Forte 615*fcf3ce44SJohn Forte if (i >= map->count) 616*fcf3ce44SJohn Forte return (0); 617*fcf3ce44SJohn Forte /* 618*fcf3ce44SJohn Forte * Make sure that the port WWN is valid 619*fcf3ce44SJohn Forte */ 620*fcf3ce44SJohn Forte if (is_null_wwn(dev_addr_ptr->gfc_port_dev. 621*fcf3ce44SJohn Forte pub_port.dev_pwwn.raw_wwn)) { 622*fcf3ce44SJohn Forte return (0); 623*fcf3ce44SJohn Forte } 624*fcf3ce44SJohn Forte for (j = 0, k = 0; j < WWN_SIZE; j++) { 625*fcf3ce44SJohn Forte c = dev_addr_ptr->gfc_port_dev.pub_port. 626*fcf3ce44SJohn Forte dev_pwwn.raw_wwn[j]; 627*fcf3ce44SJohn Forte fnib = (((int)(c & 0xf0)) >> 4); 628*fcf3ce44SJohn Forte snib = (c & 0x0f); 629*fcf3ce44SJohn Forte if (fnib >= 0 && fnib <= 9) 630*fcf3ce44SJohn Forte wwn[k++] = '0' + fnib; 631*fcf3ce44SJohn Forte else if (fnib >= 10 && fnib <= 15) 632*fcf3ce44SJohn Forte wwn[k++] = 'a' + fnib - 10; 633*fcf3ce44SJohn Forte if (snib >= 0 && snib <= 9) 634*fcf3ce44SJohn Forte wwn[k++] = '0' + snib; 635*fcf3ce44SJohn Forte else if (snib >= 10 && snib <= 15) 636*fcf3ce44SJohn Forte wwn[k++] = 'a' + snib - 10; 637*fcf3ce44SJohn Forte } 638*fcf3ce44SJohn Forte wwn[k] = '\0'; 639*fcf3ce44SJohn Forte break; 640*fcf3ce44SJohn Forte case FC_TOP_PT_PT: 641*fcf3ce44SJohn Forte return (L_PT_PT_FC_TOP_NOT_SUPPORTED); 642*fcf3ce44SJohn Forte default: 643*fcf3ce44SJohn Forte return (L_UNEXPECTED_FC_TOPOLOGY); 644*fcf3ce44SJohn Forte } /* End of switch on port_topology */ 645*fcf3ce44SJohn Forte 646*fcf3ce44SJohn Forte if (strstr(ses_path, SCSI_VHCI) != NULL) { 647*fcf3ce44SJohn Forte if (err = g_get_wwn_list(&wwn_list, 0)) { 648*fcf3ce44SJohn Forte return (err); 649*fcf3ce44SJohn Forte } 650*fcf3ce44SJohn Forte for (wwnlp = wwn_list; wwnlp != NULL; 651*fcf3ce44SJohn Forte wwnlp = wwnlp->wwn_next) { 652*fcf3ce44SJohn Forte if (memcmp(wwnlp->port_wwn_s, wwn, WWN_S_LEN) == 0) { 653*fcf3ce44SJohn Forte break; 654*fcf3ce44SJohn Forte } 655*fcf3ce44SJohn Forte } 656*fcf3ce44SJohn Forte if (wwnlp != NULL) { 657*fcf3ce44SJohn Forte if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) { 658*fcf3ce44SJohn Forte g_free_wwn_list(&wwn_list); 659*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 660*fcf3ce44SJohn Forte } 661*fcf3ce44SJohn Forte (void) strcpy(*dev_path, wwnlp->physical_path); 662*fcf3ce44SJohn Forte } else { 663*fcf3ce44SJohn Forte g_free_wwn_list(&wwn_list); 664*fcf3ce44SJohn Forte return (0); 665*fcf3ce44SJohn Forte } 666*fcf3ce44SJohn Forte } else { 667*fcf3ce44SJohn Forte 668*fcf3ce44SJohn Forte len = strlen(ses_path) - strlen(strrchr(ses_path, '/')); 669*fcf3ce44SJohn Forte 670*fcf3ce44SJohn Forte (void) sprintf(ssd, "ssd@w%s,0", wwn); 671*fcf3ce44SJohn Forte 672*fcf3ce44SJohn Forte (void) strncpy(sf_path, ses_path, len); 673*fcf3ce44SJohn Forte sf_path[len] = '\0'; 674*fcf3ce44SJohn Forte P_DPRINTF(" l_device_present: wwn=%s, sf_path=%s\n", 675*fcf3ce44SJohn Forte wwn, sf_path); 676*fcf3ce44SJohn Forte 677*fcf3ce44SJohn Forte if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) { 678*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 679*fcf3ce44SJohn Forte } 680*fcf3ce44SJohn Forte (void) sprintf(*dev_path, "%s/%s", sf_path, ssd); 681*fcf3ce44SJohn Forte P_DPRINTF(" l_device_present: dev_path=%s\n", *dev_path); 682*fcf3ce44SJohn Forte 683*fcf3ce44SJohn Forte (void) strcat(*dev_path, ":c"); 684*fcf3ce44SJohn Forte } 685*fcf3ce44SJohn Forte if ((fd = open(*dev_path, O_RDONLY)) == -1) { 686*fcf3ce44SJohn Forte free(*dev_path); 687*fcf3ce44SJohn Forte *dev_path = NULL; 688*fcf3ce44SJohn Forte return (0); 689*fcf3ce44SJohn Forte } 690*fcf3ce44SJohn Forte (void) close(fd); 691*fcf3ce44SJohn Forte return (1); 692*fcf3ce44SJohn Forte } 693*fcf3ce44SJohn Forte 694*fcf3ce44SJohn Forte 695*fcf3ce44SJohn Forte 696*fcf3ce44SJohn Forte /* 697*fcf3ce44SJohn Forte * onlines the given list of devices 698*fcf3ce44SJohn Forte * and free up the allocated memory. 699*fcf3ce44SJohn Forte * 700*fcf3ce44SJohn Forte * RETURNS: 701*fcf3ce44SJohn Forte * N/A 702*fcf3ce44SJohn Forte */ 703*fcf3ce44SJohn Forte static void 704*fcf3ce44SJohn Forte online_dev(struct dlist *dl_head, int force_flag) 705*fcf3ce44SJohn Forte { 706*fcf3ce44SJohn Forte struct dlist *dl, *dl1; 707*fcf3ce44SJohn Forte 708*fcf3ce44SJohn Forte for (dl = dl_head; dl != NULL; ) { 709*fcf3ce44SJohn Forte (void) g_online_drive(dl->multipath, force_flag); 710*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 711*fcf3ce44SJohn Forte dl1 = dl; 712*fcf3ce44SJohn Forte dl = dl->next; 713*fcf3ce44SJohn Forte (void) g_destroy_data(dl1); 714*fcf3ce44SJohn Forte } 715*fcf3ce44SJohn Forte } 716*fcf3ce44SJohn Forte 717*fcf3ce44SJohn Forte 718*fcf3ce44SJohn Forte 719*fcf3ce44SJohn Forte /* 720*fcf3ce44SJohn Forte * offlines all the disks in a 721*fcf3ce44SJohn Forte * SENA enclosure. 722*fcf3ce44SJohn Forte * 723*fcf3ce44SJohn Forte * RETURNS: 724*fcf3ce44SJohn Forte * 0 if O.K. 725*fcf3ce44SJohn Forte * non-zero otherwise 726*fcf3ce44SJohn Forte */ 727*fcf3ce44SJohn Forte int 728*fcf3ce44SJohn Forte l_offline_photon(struct hotplug_disk_list *hotplug_sena, 729*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list, 730*fcf3ce44SJohn Forte int force_flag, int verbose_flag) 731*fcf3ce44SJohn Forte { 732*fcf3ce44SJohn Forte int i, err; 733*fcf3ce44SJohn Forte struct dlist *dl_head, *dl_tail, *dl, *dl_ses; 734*fcf3ce44SJohn Forte char *dev_path, ses_path[MAXPATHLEN]; 735*fcf3ce44SJohn Forte L_state *l_state = NULL; 736*fcf3ce44SJohn Forte 737*fcf3ce44SJohn Forte if (hotplug_sena == NULL) { 738*fcf3ce44SJohn Forte return (L_INVALID_PATH_FORMAT); 739*fcf3ce44SJohn Forte } 740*fcf3ce44SJohn Forte 741*fcf3ce44SJohn Forte dl_head = dl_tail = NULL; 742*fcf3ce44SJohn Forte if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) { 743*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 744*fcf3ce44SJohn Forte } 745*fcf3ce44SJohn Forte 746*fcf3ce44SJohn Forte /* Get global status for this Photon */ 747*fcf3ce44SJohn Forte dl_ses = hotplug_sena->seslist; 748*fcf3ce44SJohn Forte while (dl_ses) { 749*fcf3ce44SJohn Forte (void) strcpy(ses_path, dl_ses->dev_path); 750*fcf3ce44SJohn Forte if (l_get_status(ses_path, l_state, verbose_flag) == 0) 751*fcf3ce44SJohn Forte break; 752*fcf3ce44SJohn Forte dl_ses = dl_ses->next; 753*fcf3ce44SJohn Forte } 754*fcf3ce44SJohn Forte 755*fcf3ce44SJohn Forte if (dl_ses == NULL) { 756*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 757*fcf3ce44SJohn Forte return (L_ENCL_INVALID_PATH); 758*fcf3ce44SJohn Forte } 759*fcf3ce44SJohn Forte 760*fcf3ce44SJohn Forte for (i = 0; i < l_state->total_num_drv/2; i++) { 761*fcf3ce44SJohn Forte if (*l_state->drv_front[i].g_disk_state.physical_path) { 762*fcf3ce44SJohn Forte if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) { 763*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 764*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 765*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 766*fcf3ce44SJohn Forte } 767*fcf3ce44SJohn Forte (void) strcpy(dev_path, 768*fcf3ce44SJohn Forte (char *)&l_state->drv_front[i].g_disk_state.physical_path); 769*fcf3ce44SJohn Forte if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) { 770*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 771*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 772*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 773*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 774*fcf3ce44SJohn Forte } 775*fcf3ce44SJohn Forte dl->dev_path = dev_path; 776*fcf3ce44SJohn Forte if ((err = g_get_multipath(dev_path, 777*fcf3ce44SJohn Forte &(dl->multipath), wwn_list, 0)) != 0) { 778*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 779*fcf3ce44SJohn Forte if (dl->multipath != NULL) { 780*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 781*fcf3ce44SJohn Forte } 782*fcf3ce44SJohn Forte (void) g_destroy_data(dl); 783*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 784*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 785*fcf3ce44SJohn Forte return (err); 786*fcf3ce44SJohn Forte } 787*fcf3ce44SJohn Forte if ((err = g_offline_drive(dl->multipath, 788*fcf3ce44SJohn Forte force_flag)) != 0) { 789*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 790*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 791*fcf3ce44SJohn Forte (void) g_destroy_data(dl); 792*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 793*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 794*fcf3ce44SJohn Forte return (err); 795*fcf3ce44SJohn Forte } 796*fcf3ce44SJohn Forte if (dl_head == NULL) { 797*fcf3ce44SJohn Forte dl_head = dl_tail = dl; 798*fcf3ce44SJohn Forte } else { 799*fcf3ce44SJohn Forte dl_tail->next = dl; 800*fcf3ce44SJohn Forte dl->prev = dl_tail; 801*fcf3ce44SJohn Forte dl_tail = dl; 802*fcf3ce44SJohn Forte } 803*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 804*fcf3ce44SJohn Forte } 805*fcf3ce44SJohn Forte if (*l_state->drv_rear[i].g_disk_state.physical_path) { 806*fcf3ce44SJohn Forte if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) { 807*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 808*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 809*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 810*fcf3ce44SJohn Forte } 811*fcf3ce44SJohn Forte (void) strcpy(dev_path, 812*fcf3ce44SJohn Forte (char *)&l_state->drv_rear[i].g_disk_state.physical_path); 813*fcf3ce44SJohn Forte if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) { 814*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 815*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 816*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 817*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 818*fcf3ce44SJohn Forte } 819*fcf3ce44SJohn Forte dl->dev_path = dev_path; 820*fcf3ce44SJohn Forte if ((err = g_get_multipath(dev_path, 821*fcf3ce44SJohn Forte &(dl->multipath), wwn_list, 0)) != 0) { 822*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 823*fcf3ce44SJohn Forte if (dl->multipath != NULL) { 824*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 825*fcf3ce44SJohn Forte } 826*fcf3ce44SJohn Forte (void) g_destroy_data(dl); 827*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 828*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 829*fcf3ce44SJohn Forte return (err); 830*fcf3ce44SJohn Forte } 831*fcf3ce44SJohn Forte if ((err = g_offline_drive(dl->multipath, 832*fcf3ce44SJohn Forte force_flag)) != 0) { 833*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 834*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 835*fcf3ce44SJohn Forte (void) g_destroy_data(dl); 836*fcf3ce44SJohn Forte (void) online_dev(dl_head, force_flag); 837*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 838*fcf3ce44SJohn Forte return (err); 839*fcf3ce44SJohn Forte } 840*fcf3ce44SJohn Forte if (dl_head == NULL) { 841*fcf3ce44SJohn Forte dl_head = dl_tail = dl; 842*fcf3ce44SJohn Forte } else { 843*fcf3ce44SJohn Forte dl_tail->next = dl; 844*fcf3ce44SJohn Forte dl->prev = dl_tail; 845*fcf3ce44SJohn Forte dl_tail = dl; 846*fcf3ce44SJohn Forte } 847*fcf3ce44SJohn Forte (void) g_destroy_data(dev_path); 848*fcf3ce44SJohn Forte } 849*fcf3ce44SJohn Forte } 850*fcf3ce44SJohn Forte hotplug_sena->dlhead = dl_head; 851*fcf3ce44SJohn Forte (void) l_free_lstate(&l_state); 852*fcf3ce44SJohn Forte return (0); 853*fcf3ce44SJohn Forte 854*fcf3ce44SJohn Forte } 855*fcf3ce44SJohn Forte 856*fcf3ce44SJohn Forte 857*fcf3ce44SJohn Forte 858*fcf3ce44SJohn Forte /* 859*fcf3ce44SJohn Forte * prepares a char string 860*fcf3ce44SJohn Forte * containing the name of the 861*fcf3ce44SJohn Forte * device which will be hotplugged. 862*fcf3ce44SJohn Forte * 863*fcf3ce44SJohn Forte * RETURNS: 864*fcf3ce44SJohn Forte * N/A 865*fcf3ce44SJohn Forte */ 866*fcf3ce44SJohn Forte void 867*fcf3ce44SJohn Forte l_get_drive_name(char *drive_name, int slot, int f_flag, char *box_name) 868*fcf3ce44SJohn Forte { 869*fcf3ce44SJohn Forte int enc_type = 0; 870*fcf3ce44SJohn Forte L_inquiry inq; 871*fcf3ce44SJohn Forte char *physpath; 872*fcf3ce44SJohn Forte Path_struct *p_pathstruct; 873*fcf3ce44SJohn Forte 874*fcf3ce44SJohn Forte if ((drive_name == NULL) || (box_name == NULL)) { 875*fcf3ce44SJohn Forte return; 876*fcf3ce44SJohn Forte } 877*fcf3ce44SJohn Forte 878*fcf3ce44SJohn Forte if (!l_convert_name(box_name, &physpath, &p_pathstruct, 0)) { 879*fcf3ce44SJohn Forte if (!g_get_inquiry(physpath, &inq)) { 880*fcf3ce44SJohn Forte enc_type = l_get_enc_type(inq); 881*fcf3ce44SJohn Forte } 882*fcf3ce44SJohn Forte } 883*fcf3ce44SJohn Forte /* If either of the above fail, we use the default value of 0 */ 884*fcf3ce44SJohn Forte free(physpath); 885*fcf3ce44SJohn Forte free(p_pathstruct); 886*fcf3ce44SJohn Forte switch (enc_type) { 887*fcf3ce44SJohn Forte case DAK_ENC_TYPE: 888*fcf3ce44SJohn Forte if (f_flag != NULL) { 889*fcf3ce44SJohn Forte (void) sprintf(drive_name, MSGSTR(8502, 890*fcf3ce44SJohn Forte "Drive in \"%s\" slot %d"), box_name, slot); 891*fcf3ce44SJohn Forte } else { 892*fcf3ce44SJohn Forte (void) sprintf(drive_name, MSGSTR(8502, 893*fcf3ce44SJohn Forte "Drive in \"%s\" slot %d"), box_name, 894*fcf3ce44SJohn Forte slot + (MAX_DRIVES_DAK/2)); 895*fcf3ce44SJohn Forte } 896*fcf3ce44SJohn Forte break; 897*fcf3ce44SJohn Forte default: 898*fcf3ce44SJohn Forte if (f_flag != NULL) { 899*fcf3ce44SJohn Forte (void) sprintf(drive_name, MSGSTR(8500, 900*fcf3ce44SJohn Forte "Drive in \"%s\" front slot %d"), box_name, slot); 901*fcf3ce44SJohn Forte } else { 902*fcf3ce44SJohn Forte (void) sprintf(drive_name, MSGSTR(8501, 903*fcf3ce44SJohn Forte "Drive in \"%s\" rear slot %d"), box_name, slot); 904*fcf3ce44SJohn Forte } 905*fcf3ce44SJohn Forte break; 906*fcf3ce44SJohn Forte } 907*fcf3ce44SJohn Forte } 908