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 * I18N message number ranges 31*fcf3ce44SJohn Forte * This file: 12000 - 12499 32*fcf3ce44SJohn Forte * Shared common messages: 1 - 1999 33*fcf3ce44SJohn Forte */ 34*fcf3ce44SJohn Forte 35*fcf3ce44SJohn Forte /* 36*fcf3ce44SJohn Forte * This module is part of the Fibre Channel Interface library. 37*fcf3ce44SJohn Forte */ 38*fcf3ce44SJohn Forte 39*fcf3ce44SJohn Forte /* #define _POSIX_SOURCE 1 */ 40*fcf3ce44SJohn Forte 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/mkdev.h> 49*fcf3ce44SJohn Forte #include <sys/param.h> 50*fcf3ce44SJohn Forte #include <fcntl.h> 51*fcf3ce44SJohn Forte #include <unistd.h> 52*fcf3ce44SJohn Forte #include <string.h> 53*fcf3ce44SJohn Forte #include <sys/scsi/scsi.h> 54*fcf3ce44SJohn Forte #include <dirent.h> /* for DIR */ 55*fcf3ce44SJohn Forte #include <sys/vtoc.h> 56*fcf3ce44SJohn Forte #include <nl_types.h> 57*fcf3ce44SJohn Forte #include <strings.h> 58*fcf3ce44SJohn Forte #include <errno.h> 59*fcf3ce44SJohn Forte #include <sys/ddi.h> /* for max */ 60*fcf3ce44SJohn Forte #include <fnmatch.h> 61*fcf3ce44SJohn Forte #include <l_common.h> 62*fcf3ce44SJohn Forte #include <stgcom.h> 63*fcf3ce44SJohn Forte #include <l_error.h> 64*fcf3ce44SJohn Forte #include <g_state.h> 65*fcf3ce44SJohn Forte #include <g_scsi.h> 66*fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcp_util.h> 67*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h> 68*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fcph.h> 69*fcf3ce44SJohn Forte #include <sys/socalio.h> 70*fcf3ce44SJohn Forte #include <libdevinfo.h> 71*fcf3ce44SJohn Forte #include <ctype.h> 72*fcf3ce44SJohn Forte #include <devid.h> 73*fcf3ce44SJohn Forte 74*fcf3ce44SJohn Forte /* Some forward declarations of static functions */ 75*fcf3ce44SJohn Forte /* 76*fcf3ce44SJohn Forte * becomes extern interface for Tapestry. 77*fcf3ce44SJohn Forte * static int g_get_inq_dtype(char *, la_wwn_t, uchar_t *); 78*fcf3ce44SJohn Forte * static int g_get_dev_list(char *, fc_port_dev_t **, int *, int); 79*fcf3ce44SJohn Forte */ 80*fcf3ce44SJohn Forte static int g_issue_fcp_ioctl(int, struct fcp_ioctl *, int); 81*fcf3ce44SJohn Forte static int g_set_port_state(char *, int); 82*fcf3ce44SJohn Forte static int g_dev_log_in_out(char *, la_wwn_t, uint16_t); 83*fcf3ce44SJohn Forte static int g_get_dev_port_state(char *, la_wwn_t, uint32_t *); 84*fcf3ce44SJohn Forte static void g_free_rls(AL_rls *); 85*fcf3ce44SJohn Forte static int g_scsi_inquiry_cmd80(int, uchar_t *, int); 86*fcf3ce44SJohn Forte static int get_fca_inq_dtype(char *, la_wwn_t, uchar_t *); 87*fcf3ce44SJohn Forte static int g_find_supported_inq_page(int, int); 88*fcf3ce44SJohn Forte static int wwn_list_name_compare(const void *, const void *); 89*fcf3ce44SJohn Forte static int devid_get_all(ddi_devid_t, di_node_t, char *, 90*fcf3ce44SJohn Forte struct mplist_struct **); 91*fcf3ce44SJohn Forte static int get_multipath(char *, struct dlist **, 92*fcf3ce44SJohn Forte struct wwn_list_struct *); 93*fcf3ce44SJohn Forte static int get_multipath_disk(char *, struct dlist **, 94*fcf3ce44SJohn Forte struct wwn_list_struct *); 95*fcf3ce44SJohn Forte static void mplist_free(struct mplist_struct *); 96*fcf3ce44SJohn Forte static int get_wwn_data(di_node_t, uchar_t **, uchar_t **); 97*fcf3ce44SJohn Forte static int get_dev_path(struct wwn_list_struct **, char *, char *); 98*fcf3ce44SJohn Forte static int insert_missing_pwwn(char *, struct wwn_list_struct **); 99*fcf3ce44SJohn Forte static int get_scsi_vhci_port_wwn(char *, uchar_t *); 100*fcf3ce44SJohn Forte static int search_wwn_entry(struct wwn_list_found_struct *, uchar_t *, 101*fcf3ce44SJohn Forte uchar_t *); 102*fcf3ce44SJohn Forte static int add_wwn_entry(struct wwn_list_found_struct **, uchar_t *, 103*fcf3ce44SJohn Forte uchar_t *); 104*fcf3ce44SJohn Forte static int string_to_wwn(uchar_t *, uchar_t *); 105*fcf3ce44SJohn Forte static int get_wwns(char *, uchar_t *, uchar_t *, int *, 106*fcf3ce44SJohn Forte struct wwn_list_found_struct **); 107*fcf3ce44SJohn Forte 108*fcf3ce44SJohn Forte /* type for g_dev_map_init related routines */ 109*fcf3ce44SJohn Forte 110*fcf3ce44SJohn Forte #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0) 111*fcf3ce44SJohn Forte 112*fcf3ce44SJohn Forte typedef struct impl_map_dev_prop { 113*fcf3ce44SJohn Forte char prop_name[MAXNAMELEN]; 114*fcf3ce44SJohn Forte int prop_type; 115*fcf3ce44SJohn Forte int prop_size; 116*fcf3ce44SJohn Forte void *prop_data; 117*fcf3ce44SJohn Forte int prop_error; 118*fcf3ce44SJohn Forte struct impl_map_dev_prop *next; 119*fcf3ce44SJohn Forte } impl_map_dev_prop_t; 120*fcf3ce44SJohn Forte 121*fcf3ce44SJohn Forte typedef struct impl_map_dev { 122*fcf3ce44SJohn Forte int flag; 123*fcf3ce44SJohn Forte uint_t topo; 124*fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_list; 125*fcf3ce44SJohn Forte struct impl_map_dev *parent; 126*fcf3ce44SJohn Forte struct impl_map_dev *child; 127*fcf3ce44SJohn Forte struct impl_map_dev *next; 128*fcf3ce44SJohn Forte } impl_map_dev_t; 129*fcf3ce44SJohn Forte 130*fcf3ce44SJohn Forte /* Defines */ 131*fcf3ce44SJohn Forte #define VERBPRINT if (verbose) (void) printf 132*fcf3ce44SJohn Forte 133*fcf3ce44SJohn Forte #define DIR_MATCH_ST "*[0-9+]n" 134*fcf3ce44SJohn Forte #define DIR_MATCH_SSD "*s2" 135*fcf3ce44SJohn Forte 136*fcf3ce44SJohn Forte #define PROP_NOEXIST 0 137*fcf3ce44SJohn Forte #define PROP_EXIST 1 138*fcf3ce44SJohn Forte 139*fcf3ce44SJohn Forte /* Prototypes */ 140*fcf3ce44SJohn Forte static int create_map(char *, gfc_map_t *, int, int); 141*fcf3ce44SJohn Forte static char ctoi(char); 142*fcf3ce44SJohn Forte static int lilp_map_cmp(const void*, const void*); 143*fcf3ce44SJohn Forte static int devices_get_all(di_node_t, char *, char *, 144*fcf3ce44SJohn Forte struct wwn_list_struct **); 145*fcf3ce44SJohn Forte static char *my_devfs_path(di_node_t); 146*fcf3ce44SJohn Forte static void my_devfs_path_free(char *path); 147*fcf3ce44SJohn Forte static void copy_wwn_data_to_str(char *, const uchar_t *); 148*fcf3ce44SJohn Forte static void init_drv(char *, char *, char *); 149*fcf3ce44SJohn Forte 150*fcf3ce44SJohn Forte /* static for g_dev_map_init related routines */ 151*fcf3ce44SJohn Forte 152*fcf3ce44SJohn Forte static int update_map_dev_fc_prop(impl_map_dev_prop_t **, uint32_t, 153*fcf3ce44SJohn Forte uchar_t *, uchar_t *, int, int); 154*fcf3ce44SJohn Forte static int update_map_dev_FCP_prop(impl_map_dev_prop_t **, uchar_t *, int, int); 155*fcf3ce44SJohn Forte static int handle_map_dev_FCP_prop(minor_t, la_wwn_t, impl_map_dev_prop_t **); 156*fcf3ce44SJohn Forte static void free_prop_list(impl_map_dev_prop_t **); 157*fcf3ce44SJohn Forte static void free_child_list(impl_map_dev_t **); 158*fcf3ce44SJohn Forte static u_longlong_t wwnConversion(uchar_t *wwn); 159*fcf3ce44SJohn Forte 160*fcf3ce44SJohn Forte uchar_t g_switch_to_alpa[] = { 161*fcf3ce44SJohn Forte 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 162*fcf3ce44SJohn Forte 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 163*fcf3ce44SJohn Forte 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 164*fcf3ce44SJohn Forte 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 165*fcf3ce44SJohn Forte 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97, 166*fcf3ce44SJohn Forte 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 167*fcf3ce44SJohn Forte 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 168*fcf3ce44SJohn Forte 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56, 169*fcf3ce44SJohn Forte 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 170*fcf3ce44SJohn Forte 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35, 171*fcf3ce44SJohn Forte 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 172*fcf3ce44SJohn Forte 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 173*fcf3ce44SJohn Forte 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01 174*fcf3ce44SJohn Forte }; 175*fcf3ce44SJohn Forte 176*fcf3ce44SJohn Forte uchar_t g_sf_alpa_to_switch[] = { 177*fcf3ce44SJohn Forte 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 178*fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 179*fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 180*fcf3ce44SJohn Forte 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 181*fcf3ce44SJohn Forte 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 182*fcf3ce44SJohn Forte 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 183*fcf3ce44SJohn Forte 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 184*fcf3ce44SJohn Forte 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 185*fcf3ce44SJohn Forte 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 186*fcf3ce44SJohn Forte 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 187*fcf3ce44SJohn Forte 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 188*fcf3ce44SJohn Forte 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 189*fcf3ce44SJohn Forte 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 190*fcf3ce44SJohn Forte 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 191*fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 192*fcf3ce44SJohn Forte 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 193*fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 194*fcf3ce44SJohn Forte 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 195*fcf3ce44SJohn Forte 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 196*fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 197*fcf3ce44SJohn Forte 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 198*fcf3ce44SJohn Forte 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 199*fcf3ce44SJohn Forte 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 200*fcf3ce44SJohn Forte 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 201*fcf3ce44SJohn Forte }; 202*fcf3ce44SJohn Forte 203*fcf3ce44SJohn Forte 204*fcf3ce44SJohn Forte 205*fcf3ce44SJohn Forte /* 206*fcf3ce44SJohn Forte * Check if device is in the map. 207*fcf3ce44SJohn Forte * 208*fcf3ce44SJohn Forte * PARAMS: 209*fcf3ce44SJohn Forte * map - loop map returned from fc port 210*fcf3ce44SJohn Forte * tid - device ID for private map or 24-bit alpa for fabric map 211*fcf3ce44SJohn Forte * 212*fcf3ce44SJohn Forte * RETURNS: 213*fcf3ce44SJohn Forte * 1 if device present in the map. 214*fcf3ce44SJohn Forte * 0 otherwise. 215*fcf3ce44SJohn Forte * 216*fcf3ce44SJohn Forte */ 217*fcf3ce44SJohn Forte int 218*fcf3ce44SJohn Forte g_device_in_map(gfc_map_t *map, int tid) 219*fcf3ce44SJohn Forte { 220*fcf3ce44SJohn Forte int i, j; 221*fcf3ce44SJohn Forte gfc_port_dev_info_t *dev_ptr; 222*fcf3ce44SJohn Forte 223*fcf3ce44SJohn Forte dev_ptr = map->dev_addr; 224*fcf3ce44SJohn Forte if ((map->hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) || 225*fcf3ce44SJohn Forte (map->hba_addr.port_topology == FC_TOP_FABRIC)) { 226*fcf3ce44SJohn Forte for (i = 0; i < map->count; i++, dev_ptr++) { 227*fcf3ce44SJohn Forte if (dev_ptr-> 228*fcf3ce44SJohn Forte gfc_port_dev.pub_port.dev_did.port_id == tid) { 229*fcf3ce44SJohn Forte /* Does not count if WWN == 0 */ 230*fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++) 231*fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.pub_port. 232*fcf3ce44SJohn Forte dev_pwwn.raw_wwn[j] != 0) 233*fcf3ce44SJohn Forte return (1); 234*fcf3ce44SJohn Forte } 235*fcf3ce44SJohn Forte } 236*fcf3ce44SJohn Forte } else { 237*fcf3ce44SJohn Forte for (i = 0; i < map->count; i++, dev_ptr++) { 238*fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.priv_port.sf_al_pa == 239*fcf3ce44SJohn Forte (int)g_switch_to_alpa[tid]) { 240*fcf3ce44SJohn Forte /* Does not count if WWN == 0 */ 241*fcf3ce44SJohn Forte for (j = 0; j < WWN_SIZE; j++) 242*fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.priv_port. 243*fcf3ce44SJohn Forte sf_port_wwn[j] != 0) 244*fcf3ce44SJohn Forte return (1); 245*fcf3ce44SJohn Forte } 246*fcf3ce44SJohn Forte } 247*fcf3ce44SJohn Forte } 248*fcf3ce44SJohn Forte return (0); 249*fcf3ce44SJohn Forte } 250*fcf3ce44SJohn Forte 251*fcf3ce44SJohn Forte /* 252*fcf3ce44SJohn Forte * Inserts any missing port wwns for mpxio device paths 253*fcf3ce44SJohn Forte * which are in ONLINE or STANDBY state. 254*fcf3ce44SJohn Forte */ 255*fcf3ce44SJohn Forte static int 256*fcf3ce44SJohn Forte insert_missing_pwwn(char *phys_path, struct wwn_list_struct **wwn_list_ptr) 257*fcf3ce44SJohn Forte { 258*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 259*fcf3ce44SJohn Forte int i, pathcnt, match; 260*fcf3ce44SJohn Forte struct wwn_list_struct *new_wwn, *wwn_list_s, *wwn_list_found; 261*fcf3ce44SJohn Forte char pwwn1[WWN_S_LEN]; 262*fcf3ce44SJohn Forte 263*fcf3ce44SJohn Forte /* 264*fcf3ce44SJohn Forte * Now check each scsi_vhci device path to find any missed 265*fcf3ce44SJohn Forte * port wwns and insert a new wwn list entry for the missed 266*fcf3ce44SJohn Forte * port wwn 267*fcf3ce44SJohn Forte */ 268*fcf3ce44SJohn Forte if (g_get_pathlist(phys_path, &pathlist)) { 269*fcf3ce44SJohn Forte /* Free memory for pathlist before return */ 270*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 271*fcf3ce44SJohn Forte return (L_INVALID_PATH); 272*fcf3ce44SJohn Forte } 273*fcf3ce44SJohn Forte 274*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 275*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 276*fcf3ce44SJohn Forte /* 277*fcf3ce44SJohn Forte * Just search for ONLINE and STANDBY paths as 278*fcf3ce44SJohn Forte * those should be the only missing wwn entries. 279*fcf3ce44SJohn Forte * There is a very small window for an offline 280*fcf3ce44SJohn Forte * to have occurred between the time we retrieved 281*fcf3ce44SJohn Forte * the device list and a call to this function. 282*fcf3ce44SJohn Forte * If that happens, we just won't add it to 283*fcf3ce44SJohn Forte * the list which is probably a good thing. 284*fcf3ce44SJohn Forte */ 285*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 286*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE || 287*fcf3ce44SJohn Forte pathlist.path_info[i].path_state == 288*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 289*fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr, 290*fcf3ce44SJohn Forte WWN_S_LEN - 1); 291*fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0'; 292*fcf3ce44SJohn Forte /* 293*fcf3ce44SJohn Forte * Now search through wwn list for matching 294*fcf3ce44SJohn Forte * device path AND pwwn 295*fcf3ce44SJohn Forte * If it's found, continue to next path. 296*fcf3ce44SJohn Forte * If it's not found, add it the wwn list. 297*fcf3ce44SJohn Forte */ 298*fcf3ce44SJohn Forte match = 0; 299*fcf3ce44SJohn Forte 300*fcf3ce44SJohn Forte for (wwn_list_s = *wwn_list_ptr; wwn_list_s != NULL; 301*fcf3ce44SJohn Forte wwn_list_s = wwn_list_s->wwn_next) { 302*fcf3ce44SJohn Forte if (strncmp(phys_path, 303*fcf3ce44SJohn Forte wwn_list_s->physical_path, 304*fcf3ce44SJohn Forte strlen(phys_path)) == 0) { 305*fcf3ce44SJohn Forte wwn_list_found = wwn_list_s; 306*fcf3ce44SJohn Forte if (strncmp(pwwn1, 307*fcf3ce44SJohn Forte wwn_list_s->port_wwn_s, 308*fcf3ce44SJohn Forte WWN_S_LEN) == 0) { 309*fcf3ce44SJohn Forte match++; 310*fcf3ce44SJohn Forte break; 311*fcf3ce44SJohn Forte } 312*fcf3ce44SJohn Forte } 313*fcf3ce44SJohn Forte } 314*fcf3ce44SJohn Forte if (match) { 315*fcf3ce44SJohn Forte continue; 316*fcf3ce44SJohn Forte } else { 317*fcf3ce44SJohn Forte /* 318*fcf3ce44SJohn Forte * didn't find a match but the mpxio 319*fcf3ce44SJohn Forte * device is in the list. Retrieve 320*fcf3ce44SJohn Forte * the info from the wwn_list_found 321*fcf3ce44SJohn Forte * and add it to the list. 322*fcf3ce44SJohn Forte */ 323*fcf3ce44SJohn Forte if ((new_wwn = (struct wwn_list_struct *) 324*fcf3ce44SJohn Forte calloc(1, 325*fcf3ce44SJohn Forte sizeof (struct wwn_list_struct))) 326*fcf3ce44SJohn Forte == NULL) { 327*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 328*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 329*fcf3ce44SJohn Forte } 330*fcf3ce44SJohn Forte if ((new_wwn->physical_path = (char *) 331*fcf3ce44SJohn Forte calloc(1, 332*fcf3ce44SJohn Forte strlen(wwn_list_found->physical_path) 333*fcf3ce44SJohn Forte +1)) == NULL) { 334*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 335*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 336*fcf3ce44SJohn Forte } 337*fcf3ce44SJohn Forte if ((new_wwn->logical_path = (char *) 338*fcf3ce44SJohn Forte calloc(1, 339*fcf3ce44SJohn Forte strlen(wwn_list_found->logical_path) 340*fcf3ce44SJohn Forte + 1)) == NULL) { 341*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 342*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 343*fcf3ce44SJohn Forte } 344*fcf3ce44SJohn Forte 345*fcf3ce44SJohn Forte /* 346*fcf3ce44SJohn Forte * Insert new_wwn at the beginning of the list. 347*fcf3ce44SJohn Forte */ 348*fcf3ce44SJohn Forte new_wwn->wwn_next = *wwn_list_ptr; 349*fcf3ce44SJohn Forte (*wwn_list_ptr)->wwn_prev = new_wwn; 350*fcf3ce44SJohn Forte 351*fcf3ce44SJohn Forte /* set new starting ptr */ 352*fcf3ce44SJohn Forte *wwn_list_ptr = new_wwn; 353*fcf3ce44SJohn Forte 354*fcf3ce44SJohn Forte memcpy(new_wwn->physical_path, 355*fcf3ce44SJohn Forte wwn_list_found->physical_path, 356*fcf3ce44SJohn Forte strlen(wwn_list_found->physical_path)); 357*fcf3ce44SJohn Forte memcpy(new_wwn->logical_path, 358*fcf3ce44SJohn Forte wwn_list_found->logical_path, 359*fcf3ce44SJohn Forte strlen(wwn_list_found->logical_path)); 360*fcf3ce44SJohn Forte /* 361*fcf3ce44SJohn Forte * Copy found node wwn data to this new entry 362*fcf3ce44SJohn Forte * Node wwn is required for the wwn_list 363*fcf3ce44SJohn Forte * however for mpxio devices it is not 364*fcf3ce44SJohn Forte * relevant as it may apply to multiple 365*fcf3ce44SJohn Forte * target controllers, so just use what 366*fcf3ce44SJohn Forte * we already have in wwn_list_found. 367*fcf3ce44SJohn Forte */ 368*fcf3ce44SJohn Forte memcpy(new_wwn->node_wwn_s, 369*fcf3ce44SJohn Forte wwn_list_found->node_wwn_s, WWN_S_LEN); 370*fcf3ce44SJohn Forte memcpy(new_wwn->w_node_wwn, 371*fcf3ce44SJohn Forte wwn_list_found->w_node_wwn, WWN_SIZE); 372*fcf3ce44SJohn Forte new_wwn->device_type = 373*fcf3ce44SJohn Forte wwn_list_found->device_type; 374*fcf3ce44SJohn Forte memcpy(new_wwn->port_wwn_s, pwwn1, WWN_S_LEN); 375*fcf3ce44SJohn Forte } 376*fcf3ce44SJohn Forte } 377*fcf3ce44SJohn Forte } 378*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 379*fcf3ce44SJohn Forte return (0); 380*fcf3ce44SJohn Forte } 381*fcf3ce44SJohn Forte 382*fcf3ce44SJohn Forte /* 383*fcf3ce44SJohn Forte * gets the port wwn for a scsi_vhci device using ONLINE path priority 384*fcf3ce44SJohn Forte */ 385*fcf3ce44SJohn Forte static int 386*fcf3ce44SJohn Forte get_scsi_vhci_port_wwn(char *phys_path, uchar_t *port_wwn) 387*fcf3ce44SJohn Forte { 388*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 389*fcf3ce44SJohn Forte int i, pathcnt, found; 390*fcf3ce44SJohn Forte char pwwn1[WWN_S_LEN]; 391*fcf3ce44SJohn Forte 392*fcf3ce44SJohn Forte if (g_get_pathlist(phys_path, &pathlist)) { 393*fcf3ce44SJohn Forte return (L_INVALID_PATH); 394*fcf3ce44SJohn Forte } 395*fcf3ce44SJohn Forte 396*fcf3ce44SJohn Forte found = 0; 397*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 398*fcf3ce44SJohn Forte /* 399*fcf3ce44SJohn Forte * Look for an ONLINE path first. 400*fcf3ce44SJohn Forte * If that fails, get the STANDBY path port WWN 401*fcf3ce44SJohn Forte * If that fails, give up 402*fcf3ce44SJohn Forte */ 403*fcf3ce44SJohn Forte for (i = 0; found == 0 && i < pathcnt; i++) { 404*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 405*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 406*fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr, 407*fcf3ce44SJohn Forte WWN_S_LEN - 1); 408*fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0'; 409*fcf3ce44SJohn Forte found++; 410*fcf3ce44SJohn Forte } 411*fcf3ce44SJohn Forte } 412*fcf3ce44SJohn Forte 413*fcf3ce44SJohn Forte for (i = 0; found == 0 && i < pathcnt; i++) { 414*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 415*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 416*fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr, 417*fcf3ce44SJohn Forte WWN_S_LEN - 1); 418*fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0'; 419*fcf3ce44SJohn Forte found++; 420*fcf3ce44SJohn Forte } 421*fcf3ce44SJohn Forte } 422*fcf3ce44SJohn Forte 423*fcf3ce44SJohn Forte S_FREE(pathlist.path_info); 424*fcf3ce44SJohn Forte if (found) { 425*fcf3ce44SJohn Forte return (string_to_wwn((uchar_t *)pwwn1, port_wwn)); 426*fcf3ce44SJohn Forte } else { 427*fcf3ce44SJohn Forte return (-1); 428*fcf3ce44SJohn Forte } 429*fcf3ce44SJohn Forte } 430*fcf3ce44SJohn Forte 431*fcf3ce44SJohn Forte /* 432*fcf3ce44SJohn Forte * searches wwn_list_found for the pwwn passed in 433*fcf3ce44SJohn Forte * and sets the corresponding nwwn on return. 434*fcf3ce44SJohn Forte * If no match is found, -1 is returned and nwwn is not set. 435*fcf3ce44SJohn Forte */ 436*fcf3ce44SJohn Forte static int 437*fcf3ce44SJohn Forte search_wwn_entry(struct wwn_list_found_struct *wwn_list_found, uchar_t *pwwn, 438*fcf3ce44SJohn Forte uchar_t *nwwn) 439*fcf3ce44SJohn Forte { 440*fcf3ce44SJohn Forte struct wwn_list_found_struct *wwn_list_s; 441*fcf3ce44SJohn Forte 442*fcf3ce44SJohn Forte for (wwn_list_s = wwn_list_found; wwn_list_s != NULL; 443*fcf3ce44SJohn Forte wwn_list_s = wwn_list_s->wwn_next) { 444*fcf3ce44SJohn Forte if (memcmp(pwwn, 445*fcf3ce44SJohn Forte wwn_list_s->port_wwn, WWN_SIZE) == 0) { 446*fcf3ce44SJohn Forte memcpy(nwwn, wwn_list_s->node_wwn, WWN_SIZE); 447*fcf3ce44SJohn Forte return (0); 448*fcf3ce44SJohn Forte } 449*fcf3ce44SJohn Forte } 450*fcf3ce44SJohn Forte return (-1); 451*fcf3ce44SJohn Forte } 452*fcf3ce44SJohn Forte 453*fcf3ce44SJohn Forte /* 454*fcf3ce44SJohn Forte * adds a nwwn, pwwn entry to the next entry in wwn_list_found list 455*fcf3ce44SJohn Forte */ 456*fcf3ce44SJohn Forte static int 457*fcf3ce44SJohn Forte add_wwn_entry(struct wwn_list_found_struct **wwn_list_found, uchar_t *pwwn, 458*fcf3ce44SJohn Forte uchar_t *nwwn) 459*fcf3ce44SJohn Forte { 460*fcf3ce44SJohn Forte struct wwn_list_found_struct *new_wwn, *temp_wwn_list_found = NULL; 461*fcf3ce44SJohn Forte 462*fcf3ce44SJohn Forte /* Got wwns, load data in list */ 463*fcf3ce44SJohn Forte if ((new_wwn = (struct wwn_list_found_struct *) 464*fcf3ce44SJohn Forte calloc(1, sizeof (struct wwn_list_found_struct))) 465*fcf3ce44SJohn Forte == NULL) { 466*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 467*fcf3ce44SJohn Forte } 468*fcf3ce44SJohn Forte 469*fcf3ce44SJohn Forte memcpy(new_wwn->node_wwn, nwwn, WWN_SIZE); 470*fcf3ce44SJohn Forte memcpy(new_wwn->port_wwn, pwwn, WWN_SIZE); 471*fcf3ce44SJohn Forte 472*fcf3ce44SJohn Forte /* 473*fcf3ce44SJohn Forte * Insert new_wwn in the list 474*fcf3ce44SJohn Forte */ 475*fcf3ce44SJohn Forte if (*wwn_list_found != NULL) { 476*fcf3ce44SJohn Forte temp_wwn_list_found = (*wwn_list_found)->wwn_next; 477*fcf3ce44SJohn Forte (*wwn_list_found)->wwn_next = new_wwn; 478*fcf3ce44SJohn Forte } else { 479*fcf3ce44SJohn Forte *wwn_list_found = new_wwn; 480*fcf3ce44SJohn Forte } 481*fcf3ce44SJohn Forte new_wwn->wwn_next = temp_wwn_list_found; 482*fcf3ce44SJohn Forte 483*fcf3ce44SJohn Forte return (0); 484*fcf3ce44SJohn Forte } 485*fcf3ce44SJohn Forte 486*fcf3ce44SJohn Forte 487*fcf3ce44SJohn Forte /* 488*fcf3ce44SJohn Forte * Create a linked list of all the WWN's for all FC_AL disks and 489*fcf3ce44SJohn Forte * tapes that are attached to this host. 490*fcf3ce44SJohn Forte * 491*fcf3ce44SJohn Forte * RETURN VALUES: 0 O.K. 492*fcf3ce44SJohn Forte * 493*fcf3ce44SJohn Forte * wwn_list pointer: 494*fcf3ce44SJohn Forte * NULL: No devices found. 495*fcf3ce44SJohn Forte * !NULL: Devices found 496*fcf3ce44SJohn Forte * wwn_list points to a linked list of wwn's. 497*fcf3ce44SJohn Forte */ 498*fcf3ce44SJohn Forte int 499*fcf3ce44SJohn Forte g_get_wwn_list(struct wwn_list_struct **wwn_list_ptr, int verbose) 500*fcf3ce44SJohn Forte { 501*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list_p = NULL, *wwn_list_tmp_p = NULL; 502*fcf3ce44SJohn Forte struct wwn_list_found_struct *wwn_list_found = NULL; 503*fcf3ce44SJohn Forte int err; 504*fcf3ce44SJohn Forte int al_pa; 505*fcf3ce44SJohn Forte uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE]; 506*fcf3ce44SJohn Forte hrtime_t start_time, end_time; 507*fcf3ce44SJohn Forte char *env = NULL; 508*fcf3ce44SJohn Forte 509*fcf3ce44SJohn Forte /* return L_NULL_WWN_LIST if wwn_list_ptr is NULL */ 510*fcf3ce44SJohn Forte if (wwn_list_ptr == NULL) { 511*fcf3ce44SJohn Forte return (L_NULL_WWN_LIST); 512*fcf3ce44SJohn Forte } 513*fcf3ce44SJohn Forte 514*fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) { 515*fcf3ce44SJohn Forte start_time = gethrtime(); 516*fcf3ce44SJohn Forte } 517*fcf3ce44SJohn Forte 518*fcf3ce44SJohn Forte if ((err = g_devices_get_all(wwn_list_ptr)) 519*fcf3ce44SJohn Forte != 0) { 520*fcf3ce44SJohn Forte return (err); 521*fcf3ce44SJohn Forte } 522*fcf3ce44SJohn Forte 523*fcf3ce44SJohn Forte /* 524*fcf3ce44SJohn Forte * retain backward compatibility with g_get_wwn_list 525*fcf3ce44SJohn Forte * and retrieve the WWN for scsi_vhci devices in the 526*fcf3ce44SJohn Forte * same fashion 527*fcf3ce44SJohn Forte * Note that for scsi_vhci devices, the wwn fields are 528*fcf3ce44SJohn Forte * not relevant but in the previous versions 529*fcf3ce44SJohn Forte * we loaded the wwns so... 530*fcf3ce44SJohn Forte */ 531*fcf3ce44SJohn Forte wwn_list_p = *wwn_list_ptr; 532*fcf3ce44SJohn Forte while (wwn_list_p != NULL) { 533*fcf3ce44SJohn Forte if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) { 534*fcf3ce44SJohn Forte /* get port wwn of first ONLINE, STANDBY */ 535*fcf3ce44SJohn Forte if ((get_scsi_vhci_port_wwn(wwn_list_p->physical_path, 536*fcf3ce44SJohn Forte port_wwn)) == 0) { 537*fcf3ce44SJohn Forte if ((search_wwn_entry(wwn_list_found, port_wwn, 538*fcf3ce44SJohn Forte node_wwn)) != 0) { 539*fcf3ce44SJohn Forte if ((err = get_wwns(wwn_list_p->physical_path, port_wwn, 540*fcf3ce44SJohn Forte node_wwn, &al_pa, &wwn_list_found)) != 0) { 541*fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found); 542*fcf3ce44SJohn Forte return (err); 543*fcf3ce44SJohn Forte } 544*fcf3ce44SJohn Forte } 545*fcf3ce44SJohn Forte } else { 546*fcf3ce44SJohn Forte /* Use g_get_wwn as a last resort */ 547*fcf3ce44SJohn Forte if ((err = g_get_wwn(wwn_list_p->physical_path, port_wwn, 548*fcf3ce44SJohn Forte node_wwn, &al_pa, 0)) != 0) { 549*fcf3ce44SJohn Forte /* 550*fcf3ce44SJohn Forte * this is a bad WWN. remove it from the 551*fcf3ce44SJohn Forte * wwn_list. 552*fcf3ce44SJohn Forte * 553*fcf3ce44SJohn Forte * After removing the bad WWN, wwn_list_p 554*fcf3ce44SJohn Forte * should point to the next node in the list 555*fcf3ce44SJohn Forte */ 556*fcf3ce44SJohn Forte if ((wwn_list_p->wwn_prev == NULL) && 557*fcf3ce44SJohn Forte (wwn_list_p->wwn_next == NULL)) { 558*fcf3ce44SJohn Forte *wwn_list_ptr = NULL; 559*fcf3ce44SJohn Forte free(wwn_list_p); 560*fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found); 561*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 562*fcf3ce44SJohn Forte } else if (wwn_list_p->wwn_prev == NULL) { 563*fcf3ce44SJohn Forte *wwn_list_ptr = wwn_list_p->wwn_next; 564*fcf3ce44SJohn Forte free(wwn_list_p); 565*fcf3ce44SJohn Forte wwn_list_p = *wwn_list_ptr; 566*fcf3ce44SJohn Forte wwn_list_p->wwn_prev = NULL; 567*fcf3ce44SJohn Forte } else if (wwn_list_p->wwn_next == NULL) { 568*fcf3ce44SJohn Forte wwn_list_p->wwn_prev->wwn_next = NULL; 569*fcf3ce44SJohn Forte free(wwn_list_p); 570*fcf3ce44SJohn Forte wwn_list_p = NULL; 571*fcf3ce44SJohn Forte } else { 572*fcf3ce44SJohn Forte wwn_list_tmp_p = wwn_list_p->wwn_next; 573*fcf3ce44SJohn Forte wwn_list_p->wwn_prev->wwn_next = 574*fcf3ce44SJohn Forte wwn_list_p->wwn_next; 575*fcf3ce44SJohn Forte wwn_list_p->wwn_next->wwn_prev = 576*fcf3ce44SJohn Forte wwn_list_p->wwn_prev; 577*fcf3ce44SJohn Forte free(wwn_list_p); 578*fcf3ce44SJohn Forte wwn_list_p = wwn_list_tmp_p; 579*fcf3ce44SJohn Forte } 580*fcf3ce44SJohn Forte continue; 581*fcf3ce44SJohn Forte } 582*fcf3ce44SJohn Forte } 583*fcf3ce44SJohn Forte copy_wwn_data_to_str(wwn_list_p->node_wwn_s, node_wwn); 584*fcf3ce44SJohn Forte copy_wwn_data_to_str(wwn_list_p->port_wwn_s, port_wwn); 585*fcf3ce44SJohn Forte memcpy(wwn_list_p->w_node_wwn, node_wwn, WWN_SIZE); 586*fcf3ce44SJohn Forte } 587*fcf3ce44SJohn Forte wwn_list_p = wwn_list_p->wwn_next; 588*fcf3ce44SJohn Forte } 589*fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found); 590*fcf3ce44SJohn Forte 591*fcf3ce44SJohn Forte /* 592*fcf3ce44SJohn Forte * Now go through the list one more time to add entries for 593*fcf3ce44SJohn Forte * any missing port wwns. 594*fcf3ce44SJohn Forte * This allows a search on port wwn for any paths which are 595*fcf3ce44SJohn Forte * ONLINE or STANDBY. We don't care about OFFLINE as those won't 596*fcf3ce44SJohn Forte * and should not show up in the list 597*fcf3ce44SJohn Forte */ 598*fcf3ce44SJohn Forte for (wwn_list_p = *wwn_list_ptr; wwn_list_p != NULL; 599*fcf3ce44SJohn Forte wwn_list_p = wwn_list_p->wwn_next) { 600*fcf3ce44SJohn Forte if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) { 601*fcf3ce44SJohn Forte if ((err = insert_missing_pwwn(wwn_list_p->physical_path, 602*fcf3ce44SJohn Forte wwn_list_ptr)) != 0) 603*fcf3ce44SJohn Forte return (err); 604*fcf3ce44SJohn Forte } 605*fcf3ce44SJohn Forte } 606*fcf3ce44SJohn Forte 607*fcf3ce44SJohn Forte if (env != NULL) { 608*fcf3ce44SJohn Forte end_time = gethrtime(); 609*fcf3ce44SJohn Forte fprintf(stdout, " g_get_wwn_list: " 610*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 611*fcf3ce44SJohn Forte (end_time - start_time)/1000000); 612*fcf3ce44SJohn Forte } 613*fcf3ce44SJohn Forte return (0); 614*fcf3ce44SJohn Forte 615*fcf3ce44SJohn Forte } 616*fcf3ce44SJohn Forte 617*fcf3ce44SJohn Forte int 618*fcf3ce44SJohn Forte g_devices_get_all(struct wwn_list_struct **wwn_list_ptr) 619*fcf3ce44SJohn Forte { 620*fcf3ce44SJohn Forte struct wwn_list_struct *tape_ptr = NULL; 621*fcf3ce44SJohn Forte struct wwn_list_struct *tmp; 622*fcf3ce44SJohn Forte int err; 623*fcf3ce44SJohn Forte di_node_t root; 624*fcf3ce44SJohn Forte hrtime_t start_time, end_time; 625*fcf3ce44SJohn Forte char *env = NULL; 626*fcf3ce44SJohn Forte 627*fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) { 628*fcf3ce44SJohn Forte start_time = gethrtime(); 629*fcf3ce44SJohn Forte } 630*fcf3ce44SJohn Forte 631*fcf3ce44SJohn Forte /* 632*fcf3ce44SJohn Forte * Try to prime di_drv_first_node() 633*fcf3ce44SJohn Forte * If there are no nodes bound, di_drv_first_node() 634*fcf3ce44SJohn Forte * will return nothing. 635*fcf3ce44SJohn Forte */ 636*fcf3ce44SJohn Forte init_drv(DEV_TAPE_DIR, DIR_MATCH_ST, SLSH_DRV_NAME_ST); 637*fcf3ce44SJohn Forte init_drv(DEV_RDIR, DIR_MATCH_SSD, SLSH_DRV_NAME_SSD); 638*fcf3ce44SJohn Forte 639*fcf3ce44SJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 640*fcf3ce44SJohn Forte return (L_DEV_SNAPSHOT_FAILED); 641*fcf3ce44SJohn Forte } 642*fcf3ce44SJohn Forte 643*fcf3ce44SJohn Forte if (env != NULL) { 644*fcf3ce44SJohn Forte end_time = gethrtime(); 645*fcf3ce44SJohn Forte fprintf(stdout, " di_init - /: " 646*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 647*fcf3ce44SJohn Forte (end_time - start_time)/1000000); 648*fcf3ce44SJohn Forte } 649*fcf3ce44SJohn Forte 650*fcf3ce44SJohn Forte if (env != NULL) { 651*fcf3ce44SJohn Forte start_time = gethrtime(); 652*fcf3ce44SJohn Forte } 653*fcf3ce44SJohn Forte 654*fcf3ce44SJohn Forte if ((err = devices_get_all(root, SSD_DRVR_NAME, SSD_MINOR_NAME, 655*fcf3ce44SJohn Forte wwn_list_ptr)) != 0) { 656*fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) { 657*fcf3ce44SJohn Forte di_fini(root); 658*fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr); 659*fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr); 660*fcf3ce44SJohn Forte return (err); 661*fcf3ce44SJohn Forte } 662*fcf3ce44SJohn Forte } 663*fcf3ce44SJohn Forte 664*fcf3ce44SJohn Forte if (env != NULL) { 665*fcf3ce44SJohn Forte end_time = gethrtime(); 666*fcf3ce44SJohn Forte fprintf(stdout, " devices_get_all - ssd: " 667*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 668*fcf3ce44SJohn Forte (end_time - start_time)/1000000); 669*fcf3ce44SJohn Forte } 670*fcf3ce44SJohn Forte 671*fcf3ce44SJohn Forte if (env != NULL) { 672*fcf3ce44SJohn Forte start_time = gethrtime(); 673*fcf3ce44SJohn Forte } 674*fcf3ce44SJohn Forte 675*fcf3ce44SJohn Forte if ((err = devices_get_all(root, ST_DRVR_NAME, ST_MINOR_NAME, 676*fcf3ce44SJohn Forte &tape_ptr)) != 0) { 677*fcf3ce44SJohn Forte di_fini(root); 678*fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) { 679*fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr); 680*fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr); 681*fcf3ce44SJohn Forte return (err); 682*fcf3ce44SJohn Forte } else { 683*fcf3ce44SJohn Forte /* 684*fcf3ce44SJohn Forte * if *wwn_list_ptr == NULL 685*fcf3ce44SJohn Forte * we have disks but no tapes 686*fcf3ce44SJohn Forte * Just return 687*fcf3ce44SJohn Forte */ 688*fcf3ce44SJohn Forte if (*wwn_list_ptr != NULL) { 689*fcf3ce44SJohn Forte return (0); 690*fcf3ce44SJohn Forte } else { 691*fcf3ce44SJohn Forte /* 692*fcf3ce44SJohn Forte * No disks or tapes 693*fcf3ce44SJohn Forte */ 694*fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr); 695*fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr); 696*fcf3ce44SJohn Forte return (err); 697*fcf3ce44SJohn Forte } 698*fcf3ce44SJohn Forte } 699*fcf3ce44SJohn Forte } 700*fcf3ce44SJohn Forte 701*fcf3ce44SJohn Forte if (env != NULL) { 702*fcf3ce44SJohn Forte end_time = gethrtime(); 703*fcf3ce44SJohn Forte fprintf(stdout, " devices_get_all - st: " 704*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 705*fcf3ce44SJohn Forte (end_time - start_time)/1000000); 706*fcf3ce44SJohn Forte } 707*fcf3ce44SJohn Forte 708*fcf3ce44SJohn Forte /* Now link the two together */ 709*fcf3ce44SJohn Forte if (*wwn_list_ptr != NULL) { /* We have both disks and tapes */ 710*fcf3ce44SJohn Forte /* Walk to the end of it */ 711*fcf3ce44SJohn Forte for (tmp = *wwn_list_ptr; tmp->wwn_next != NULL; 712*fcf3ce44SJohn Forte tmp = tmp->wwn_next); 713*fcf3ce44SJohn Forte tmp->wwn_next = tape_ptr; 714*fcf3ce44SJohn Forte tape_ptr->wwn_prev = tmp; 715*fcf3ce44SJohn Forte di_fini(root); 716*fcf3ce44SJohn Forte return (0); 717*fcf3ce44SJohn Forte } 718*fcf3ce44SJohn Forte 719*fcf3ce44SJohn Forte /* else we have no disks */ 720*fcf3ce44SJohn Forte *wwn_list_ptr = tape_ptr; 721*fcf3ce44SJohn Forte di_fini(root); 722*fcf3ce44SJohn Forte return (0); 723*fcf3ce44SJohn Forte } 724*fcf3ce44SJohn Forte 725*fcf3ce44SJohn Forte void 726*fcf3ce44SJohn Forte g_free_wwn_list_found(struct wwn_list_found_struct **wwn_list_found) { 727*fcf3ce44SJohn Forte WWN_list_found *next = NULL; 728*fcf3ce44SJohn Forte 729*fcf3ce44SJohn Forte /* return if wwn_list_found is NULL */ 730*fcf3ce44SJohn Forte if (wwn_list_found == NULL) { 731*fcf3ce44SJohn Forte return; 732*fcf3ce44SJohn Forte } 733*fcf3ce44SJohn Forte for (; *wwn_list_found != NULL; *wwn_list_found = next) { 734*fcf3ce44SJohn Forte next = (*wwn_list_found)->wwn_next; 735*fcf3ce44SJohn Forte g_destroy_data(*wwn_list_found); 736*fcf3ce44SJohn Forte *wwn_list_found = NULL; 737*fcf3ce44SJohn Forte } 738*fcf3ce44SJohn Forte } 739*fcf3ce44SJohn Forte 740*fcf3ce44SJohn Forte void 741*fcf3ce44SJohn Forte g_free_wwn_list(struct wwn_list_struct **wwn_list) 742*fcf3ce44SJohn Forte { 743*fcf3ce44SJohn Forte WWN_list *next = NULL; 744*fcf3ce44SJohn Forte 745*fcf3ce44SJohn Forte /* return if wwn_list is NULL */ 746*fcf3ce44SJohn Forte if (wwn_list == NULL) { 747*fcf3ce44SJohn Forte return; 748*fcf3ce44SJohn Forte } 749*fcf3ce44SJohn Forte 750*fcf3ce44SJohn Forte for (; *wwn_list != NULL; *wwn_list = next) { 751*fcf3ce44SJohn Forte next = (*wwn_list)->wwn_next; 752*fcf3ce44SJohn Forte if ((*wwn_list)->physical_path != NULL) 753*fcf3ce44SJohn Forte (void) g_destroy_data((*wwn_list)->physical_path); 754*fcf3ce44SJohn Forte if ((*wwn_list)->logical_path != NULL) 755*fcf3ce44SJohn Forte (void) g_destroy_data((*wwn_list)->logical_path); 756*fcf3ce44SJohn Forte (void) g_destroy_data(*wwn_list); 757*fcf3ce44SJohn Forte } 758*fcf3ce44SJohn Forte wwn_list = NULL; 759*fcf3ce44SJohn Forte } 760*fcf3ce44SJohn Forte 761*fcf3ce44SJohn Forte 762*fcf3ce44SJohn Forte 763*fcf3ce44SJohn Forte 764*fcf3ce44SJohn Forte void 765*fcf3ce44SJohn Forte g_sort_wwn_list(struct wwn_list_struct **wwn_list) 766*fcf3ce44SJohn Forte { 767*fcf3ce44SJohn Forte int i, n; 768*fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array; 769*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list_ptr; 770*fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array_ptr1; 771*fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array_ptr2; 772*fcf3ce44SJohn Forte 773*fcf3ce44SJohn Forte /* 774*fcf3ce44SJohn Forte * Count the number of wwn_list in the list 775*fcf3ce44SJohn Forte */ 776*fcf3ce44SJohn Forte for (n = 0, wwn_list_ptr = *wwn_list; 777*fcf3ce44SJohn Forte wwn_list_ptr != NULL; 778*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 779*fcf3ce44SJohn Forte n++; 780*fcf3ce44SJohn Forte } 781*fcf3ce44SJohn Forte if (n <= 1) { 782*fcf3ce44SJohn Forte return; 783*fcf3ce44SJohn Forte } 784*fcf3ce44SJohn Forte 785*fcf3ce44SJohn Forte /* 786*fcf3ce44SJohn Forte * Allocate a simple wwn_list array and fill it in 787*fcf3ce44SJohn Forte */ 788*fcf3ce44SJohn Forte wwn_list_array = (struct wwn_list_struct **) 789*fcf3ce44SJohn Forte g_zalloc((n+1) * sizeof (struct wwn_list_struct *)); 790*fcf3ce44SJohn Forte 791*fcf3ce44SJohn Forte wwn_list_array_ptr1 = wwn_list_array; 792*fcf3ce44SJohn Forte for (wwn_list_ptr = *wwn_list; 793*fcf3ce44SJohn Forte wwn_list_ptr != NULL; 794*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 795*fcf3ce44SJohn Forte *wwn_list_array_ptr1++ = wwn_list_ptr; 796*fcf3ce44SJohn Forte } 797*fcf3ce44SJohn Forte *wwn_list_array_ptr1 = NULL; 798*fcf3ce44SJohn Forte 799*fcf3ce44SJohn Forte /* 800*fcf3ce44SJohn Forte * Sort the wwn_list array 801*fcf3ce44SJohn Forte */ 802*fcf3ce44SJohn Forte qsort((void *) wwn_list_array, n, 803*fcf3ce44SJohn Forte sizeof (struct wwn_list_struct *), wwn_list_name_compare); 804*fcf3ce44SJohn Forte 805*fcf3ce44SJohn Forte /* 806*fcf3ce44SJohn Forte * Rebuild the linked list wwn_list structure 807*fcf3ce44SJohn Forte */ 808*fcf3ce44SJohn Forte wwn_list_array_ptr1 = wwn_list_array; 809*fcf3ce44SJohn Forte *wwn_list = *wwn_list_array_ptr1; 810*fcf3ce44SJohn Forte wwn_list_array_ptr2 = wwn_list_array_ptr1 + 1; 811*fcf3ce44SJohn Forte (*wwn_list_array_ptr1)->wwn_prev = NULL; 812*fcf3ce44SJohn Forte for (i = 0; i < n - 1; i++) { 813*fcf3ce44SJohn Forte (*wwn_list_array_ptr2)->wwn_prev = *wwn_list_array_ptr1; 814*fcf3ce44SJohn Forte (*wwn_list_array_ptr1++)->wwn_next = *wwn_list_array_ptr2++; 815*fcf3ce44SJohn Forte } 816*fcf3ce44SJohn Forte (*wwn_list_array_ptr1)->wwn_next = NULL; 817*fcf3ce44SJohn Forte 818*fcf3ce44SJohn Forte /* 819*fcf3ce44SJohn Forte * Clean up 820*fcf3ce44SJohn Forte */ 821*fcf3ce44SJohn Forte (void) g_destroy_data((void *)wwn_list_array); 822*fcf3ce44SJohn Forte } 823*fcf3ce44SJohn Forte 824*fcf3ce44SJohn Forte int 825*fcf3ce44SJohn Forte wwn_list_name_compare(const void *arg1, const void *arg2) 826*fcf3ce44SJohn Forte { 827*fcf3ce44SJohn Forte char *s1, *s2; 828*fcf3ce44SJohn Forte int n1, n2; 829*fcf3ce44SJohn Forte char *p1, *p2; 830*fcf3ce44SJohn Forte 831*fcf3ce44SJohn Forte s1 = (*((struct wwn_list_struct **)arg1))->logical_path; 832*fcf3ce44SJohn Forte s2 = (*((struct wwn_list_struct **)arg2))->logical_path; 833*fcf3ce44SJohn Forte for (;;) { 834*fcf3ce44SJohn Forte if (*s1 == 0 || *s2 == 0) 835*fcf3ce44SJohn Forte break; 836*fcf3ce44SJohn Forte if ((isdigit(*s1) && isdigit(*s2))) { 837*fcf3ce44SJohn Forte n1 = strtol(s1, &p1, 10); 838*fcf3ce44SJohn Forte n2 = strtol(s2, &p2, 10); 839*fcf3ce44SJohn Forte if (n1 != n2) { 840*fcf3ce44SJohn Forte return (n1 - n2); 841*fcf3ce44SJohn Forte } 842*fcf3ce44SJohn Forte s1 = p1; 843*fcf3ce44SJohn Forte s2 = p2; 844*fcf3ce44SJohn Forte } else if (*s1 != *s2) { 845*fcf3ce44SJohn Forte break; 846*fcf3ce44SJohn Forte } else { 847*fcf3ce44SJohn Forte s1++; 848*fcf3ce44SJohn Forte s2++; 849*fcf3ce44SJohn Forte } 850*fcf3ce44SJohn Forte } 851*fcf3ce44SJohn Forte return (*s1 - *s2); 852*fcf3ce44SJohn Forte } 853*fcf3ce44SJohn Forte 854*fcf3ce44SJohn Forte /* 855*fcf3ce44SJohn Forte * Get the limited map for FC4 devices. 856*fcf3ce44SJohn Forte * This function is specific to FC4 857*fcf3ce44SJohn Forte * devices and doesn't work for FC (leadville) devices. 858*fcf3ce44SJohn Forte * 859*fcf3ce44SJohn Forte * RETURN VALUES: 860*fcf3ce44SJohn Forte * 0 O.K. 861*fcf3ce44SJohn Forte * non-zero otherwise 862*fcf3ce44SJohn Forte * 863*fcf3ce44SJohn Forte * lilpmap *map_ptr: 864*fcf3ce44SJohn Forte * NULL: No devices found 865*fcf3ce44SJohn Forte * !NULL: if devices found 866*fcf3ce44SJohn Forte */ 867*fcf3ce44SJohn Forte int 868*fcf3ce44SJohn Forte g_get_limited_map(char *path, struct lilpmap *map_ptr, int verbose) 869*fcf3ce44SJohn Forte { 870*fcf3ce44SJohn Forte int fd, i; 871*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN]; 872*fcf3ce44SJohn Forte struct stat stbuf; 873*fcf3ce44SJohn Forte 874*fcf3ce44SJohn Forte 875*fcf3ce44SJohn Forte /* initialize map */ 876*fcf3ce44SJohn Forte (void) memset(map_ptr, 0, sizeof (struct lilpmap)); 877*fcf3ce44SJohn Forte 878*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 879*fcf3ce44SJohn Forte /* 880*fcf3ce44SJohn Forte * Get the path to the :devctl driver 881*fcf3ce44SJohn Forte * 882*fcf3ce44SJohn Forte * This assumes the path looks something like this: 883*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 884*fcf3ce44SJohn Forte * or 885*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0 886*fcf3ce44SJohn Forte * or 887*fcf3ce44SJohn Forte * a 1 level PCI type driver 888*fcf3ce44SJohn Forte */ 889*fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) { 890*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 891*fcf3ce44SJohn Forte } 892*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 893*fcf3ce44SJohn Forte /* append a port. Just try 0 since they did not give us one */ 894*fcf3ce44SJohn Forte (void) strcat(drvr_path, ":0"); 895*fcf3ce44SJohn Forte } 896*fcf3ce44SJohn Forte 897*fcf3ce44SJohn Forte P_DPRINTF(" g_get_limited_map: Geting drive map from:" 898*fcf3ce44SJohn Forte " %s\n", drvr_path); 899*fcf3ce44SJohn Forte 900*fcf3ce44SJohn Forte /* open controller */ 901*fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) 902*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 903*fcf3ce44SJohn Forte 904*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_GETMAP, map_ptr) != 0) { 905*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GETMAP ioctl failed\n"); 906*fcf3ce44SJohn Forte (void) close(fd); 907*fcf3ce44SJohn Forte return (L_FCIO_GETMAP_IOCTL_FAIL); 908*fcf3ce44SJohn Forte } 909*fcf3ce44SJohn Forte (void) close(fd); 910*fcf3ce44SJohn Forte 911*fcf3ce44SJohn Forte /* 912*fcf3ce44SJohn Forte * Check for reasonableness. 913*fcf3ce44SJohn Forte */ 914*fcf3ce44SJohn Forte if ((map_ptr->lilp_length > 126) || (map_ptr->lilp_magic != 0x1107)) { 915*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 916*fcf3ce44SJohn Forte } 917*fcf3ce44SJohn Forte for (i = 0; i < (uint_t)map_ptr->lilp_length; i++) { 918*fcf3ce44SJohn Forte if (map_ptr->lilp_list[i] > 0xef) { 919*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 920*fcf3ce44SJohn Forte } 921*fcf3ce44SJohn Forte } 922*fcf3ce44SJohn Forte 923*fcf3ce44SJohn Forte return (0); 924*fcf3ce44SJohn Forte } 925*fcf3ce44SJohn Forte 926*fcf3ce44SJohn Forte 927*fcf3ce44SJohn Forte /* 928*fcf3ce44SJohn Forte * For leadville specific HBA's ONLY. 929*fcf3ce44SJohn Forte * Get the host specific parameters, 930*fcf3ce44SJohn Forte * al_pa, hard address, node/port WWN etc. 931*fcf3ce44SJohn Forte * 932*fcf3ce44SJohn Forte * OUTPUT: 933*fcf3ce44SJohn Forte * fc_port_dev_t structure. 934*fcf3ce44SJohn Forte * 935*fcf3ce44SJohn Forte * RETURNS: 936*fcf3ce44SJohn Forte * 0 if OK 937*fcf3ce44SJohn Forte * non-zero in case of error. 938*fcf3ce44SJohn Forte */ 939*fcf3ce44SJohn Forte int 940*fcf3ce44SJohn Forte g_get_host_params(char *host_path, fc_port_dev_t *host_val, int verbose) 941*fcf3ce44SJohn Forte { 942*fcf3ce44SJohn Forte int err; 943*fcf3ce44SJohn Forte int fd; 944*fcf3ce44SJohn Forte int dev_type; 945*fcf3ce44SJohn Forte fcio_t fcio; 946*fcf3ce44SJohn Forte 947*fcf3ce44SJohn Forte /* return invalid path if host_path is NULL */ 948*fcf3ce44SJohn Forte if (host_path == NULL) { 949*fcf3ce44SJohn Forte return (L_INVALID_PATH); 950*fcf3ce44SJohn Forte } 951*fcf3ce44SJohn Forte /* return invalid arg if host_val is NULL */ 952*fcf3ce44SJohn Forte if (host_val == NULL) { 953*fcf3ce44SJohn Forte return (L_INVALID_ARG); 954*fcf3ce44SJohn Forte } 955*fcf3ce44SJohn Forte 956*fcf3ce44SJohn Forte dev_type = g_get_path_type(host_path); 957*fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) { 958*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 959*fcf3ce44SJohn Forte } 960*fcf3ce44SJohn Forte if ((fd = g_object_open(host_path, O_NDELAY | O_RDONLY)) == -1) { 961*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 962*fcf3ce44SJohn Forte } 963*fcf3ce44SJohn Forte 964*fcf3ce44SJohn Forte /* initialize structure */ 965*fcf3ce44SJohn Forte (void) memset(host_val, 0, sizeof (struct fc_port_dev)); 966*fcf3ce44SJohn Forte 967*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_HOST_PARAMS; 968*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 969*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)host_val; 970*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (fc_port_dev_t); 971*fcf3ce44SJohn Forte 972*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) { 973*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n"); 974*fcf3ce44SJohn Forte (void) close(fd); 975*fcf3ce44SJohn Forte return (L_FCIO_GET_HOST_PARAMS_FAIL); 976*fcf3ce44SJohn Forte } 977*fcf3ce44SJohn Forte (void) close(fd); 978*fcf3ce44SJohn Forte 979*fcf3ce44SJohn Forte /* get the inquiry information for the leadville HBA. */ 980*fcf3ce44SJohn Forte if ((err = get_fca_inq_dtype(host_path, host_val->dev_pwwn, 981*fcf3ce44SJohn Forte &host_val->dev_dtype)) != 0) { 982*fcf3ce44SJohn Forte return (err); 983*fcf3ce44SJohn Forte } 984*fcf3ce44SJohn Forte return (0); 985*fcf3ce44SJohn Forte } 986*fcf3ce44SJohn Forte 987*fcf3ce44SJohn Forte 988*fcf3ce44SJohn Forte 989*fcf3ce44SJohn Forte /* 990*fcf3ce44SJohn Forte * Issue FCIO ioctls to the port(fp) driver. 991*fcf3ce44SJohn Forte * FCIO ioctl needs to be retried when it 992*fcf3ce44SJohn Forte * is returned with an EINVAL error, wait 993*fcf3ce44SJohn Forte * time between retries should be atleast 994*fcf3ce44SJohn Forte * WAIT_FCIO_IOCTL (too much of a time to wait!!) 995*fcf3ce44SJohn Forte * 996*fcf3ce44SJohn Forte * OUTPUT: 997*fcf3ce44SJohn Forte * fcio_t structure 998*fcf3ce44SJohn Forte * 999*fcf3ce44SJohn Forte * RETURNS: 1000*fcf3ce44SJohn Forte * 0 if O.K. 1001*fcf3ce44SJohn Forte * non-zero otherwise. 1002*fcf3ce44SJohn Forte */ 1003*fcf3ce44SJohn Forte int 1004*fcf3ce44SJohn Forte g_issue_fcio_ioctl(int fd, fcio_t *fcio, int verbose) 1005*fcf3ce44SJohn Forte { 1006*fcf3ce44SJohn Forte int ntries; 1007*fcf3ce44SJohn Forte 1008*fcf3ce44SJohn Forte for (ntries = 0; ntries < RETRY_FCIO_IOCTL; ntries++) { 1009*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, fcio) != 0) { 1010*fcf3ce44SJohn Forte if ((errno == EAGAIN) && 1011*fcf3ce44SJohn Forte (ntries+1 < RETRY_FCIO_IOCTL)) { 1012*fcf3ce44SJohn Forte /* wait WAIT_FCIO_IOCTL */ 1013*fcf3ce44SJohn Forte (void) usleep(WAIT_FCIO_IOCTL); 1014*fcf3ce44SJohn Forte continue; 1015*fcf3ce44SJohn Forte } 1016*fcf3ce44SJohn Forte I_DPRINTF("FCIO ioctl failed.\n" 1017*fcf3ce44SJohn Forte "Error: %s. fc_error = %d (0x%x)\n", 1018*fcf3ce44SJohn Forte strerror(errno), fcio->fcio_errno, fcio->fcio_errno); 1019*fcf3ce44SJohn Forte if (errno == EINVAL) { 1020*fcf3ce44SJohn Forte if (fcio->fcio_errno == FC_TOOMANY) { 1021*fcf3ce44SJohn Forte return (L_INVALID_DEVICE_COUNT); 1022*fcf3ce44SJohn Forte } else { 1023*fcf3ce44SJohn Forte return (errno); 1024*fcf3ce44SJohn Forte } 1025*fcf3ce44SJohn Forte } 1026*fcf3ce44SJohn Forte /* 1027*fcf3ce44SJohn Forte * When port is offlined, qlc 1028*fcf3ce44SJohn Forte * returns the FC_OFFLINE error and errno 1029*fcf3ce44SJohn Forte * is set to EIO. 1030*fcf3ce44SJohn Forte * We do want to ignore this error, 1031*fcf3ce44SJohn Forte * especially when an enclosure is 1032*fcf3ce44SJohn Forte * removed from the loop. 1033*fcf3ce44SJohn Forte */ 1034*fcf3ce44SJohn Forte if (fcio->fcio_errno == FC_OFFLINE) 1035*fcf3ce44SJohn Forte break; 1036*fcf3ce44SJohn Forte return (-1); 1037*fcf3ce44SJohn Forte } 1038*fcf3ce44SJohn Forte break; 1039*fcf3ce44SJohn Forte } 1040*fcf3ce44SJohn Forte 1041*fcf3ce44SJohn Forte return (0); 1042*fcf3ce44SJohn Forte } 1043*fcf3ce44SJohn Forte 1044*fcf3ce44SJohn Forte /* 1045*fcf3ce44SJohn Forte * This function issues the FCP_TGT_INQUIRY ioctl to 1046*fcf3ce44SJohn Forte * the fcp module 1047*fcf3ce44SJohn Forte * 1048*fcf3ce44SJohn Forte * OUTPUT: 1049*fcf3ce44SJohn Forte * fcp_ioctl structure in fcp_data is filled in by fcp 1050*fcf3ce44SJohn Forte * 1051*fcf3ce44SJohn Forte * RETURN VALUES : 1052*fcf3ce44SJohn Forte * 0 on Success 1053*fcf3ce44SJohn Forte * Non-zero otherwise 1054*fcf3ce44SJohn Forte */ 1055*fcf3ce44SJohn Forte static int 1056*fcf3ce44SJohn Forte g_issue_fcp_ioctl(int fd, struct fcp_ioctl *fcp_data, int verbose) 1057*fcf3ce44SJohn Forte { 1058*fcf3ce44SJohn Forte int num_tries = 0; 1059*fcf3ce44SJohn Forte struct device_data *dev_data = NULL; 1060*fcf3ce44SJohn Forte 1061*fcf3ce44SJohn Forte /* 1062*fcf3ce44SJohn Forte * Issue the ioctl to FCP 1063*fcf3ce44SJohn Forte * The retries are required because the driver may 1064*fcf3ce44SJohn Forte * need some time to respond at times. 1065*fcf3ce44SJohn Forte */ 1066*fcf3ce44SJohn Forte while (num_tries++ < RETRY_FCP_IOCTL) { 1067*fcf3ce44SJohn Forte /* if ioctl fails it is an error from Solaris operation. */ 1068*fcf3ce44SJohn Forte if (ioctl(fd, FCP_TGT_INQUIRY, fcp_data) == -1) { 1069*fcf3ce44SJohn Forte if (errno == EAGAIN) { 1070*fcf3ce44SJohn Forte (void) usleep(WAIT_FCP_IOCTL); 1071*fcf3ce44SJohn Forte continue; 1072*fcf3ce44SJohn Forte } else { 1073*fcf3ce44SJohn Forte break; 1074*fcf3ce44SJohn Forte } 1075*fcf3ce44SJohn Forte } 1076*fcf3ce44SJohn Forte dev_data = (struct device_data *)((void *)(fcp_data->list)); 1077*fcf3ce44SJohn Forte if (dev_data->dev_status == 0) { 1078*fcf3ce44SJohn Forte return (0); 1079*fcf3ce44SJohn Forte } 1080*fcf3ce44SJohn Forte 1081*fcf3ce44SJohn Forte if (dev_data->dev_status == EAGAIN) { 1082*fcf3ce44SJohn Forte (void) usleep(WAIT_FCP_IOCTL); 1083*fcf3ce44SJohn Forte continue; 1084*fcf3ce44SJohn Forte } else { 1085*fcf3ce44SJohn Forte dev_data->dev0_type = DTYPE_UNKNOWN; 1086*fcf3ce44SJohn Forte return (0); 1087*fcf3ce44SJohn Forte } 1088*fcf3ce44SJohn Forte } 1089*fcf3ce44SJohn Forte 1090*fcf3ce44SJohn Forte return (L_FCP_TGT_INQUIRY_FAIL); 1091*fcf3ce44SJohn Forte } 1092*fcf3ce44SJohn Forte 1093*fcf3ce44SJohn Forte /* 1094*fcf3ce44SJohn Forte * Get the number of devices and also 1095*fcf3ce44SJohn Forte * a list of devices accessible through 1096*fcf3ce44SJohn Forte * the device's port as specified by path. 1097*fcf3ce44SJohn Forte * The calling function * is responsible for freeing the dev_list. 1098*fcf3ce44SJohn Forte * 1099*fcf3ce44SJohn Forte * Acquires inq_dtype from g_get_inq_dtype() and 1100*fcf3ce44SJohn Forte * stores into dev_dtype field of fc_port_dev. 1101*fcf3ce44SJohn Forte * 1102*fcf3ce44SJohn Forte * For fabric devices call FCIO_DEV_LOGIN (if necessary) to execute port login 1103*fcf3ce44SJohn Forte * and get inq dtype. 1104*fcf3ce44SJohn Forte * 1105*fcf3ce44SJohn Forte * dev_list: 1106*fcf3ce44SJohn Forte * NULL: No devices found, in case of an error 1107*fcf3ce44SJohn Forte * Non-NULL: Devices found. 1108*fcf3ce44SJohn Forte * ndevs: 1109*fcf3ce44SJohn Forte * set to the number of devices 1110*fcf3ce44SJohn Forte * accessible through the port. 1111*fcf3ce44SJohn Forte * 1112*fcf3ce44SJohn Forte * RETURNS: 1113*fcf3ce44SJohn Forte * 0 if O.K. 1114*fcf3ce44SJohn Forte * non-zero otherwise 1115*fcf3ce44SJohn Forte */ 1116*fcf3ce44SJohn Forte int 1117*fcf3ce44SJohn Forte g_get_dev_list(char *path, fc_port_dev_t **dev_list, int *ndevs) 1118*fcf3ce44SJohn Forte { 1119*fcf3ce44SJohn Forte int num_devices = 0; 1120*fcf3ce44SJohn Forte int i, err, ulp_failure = 0, new_count = 0; 1121*fcf3ce44SJohn Forte int dev_type; 1122*fcf3ce44SJohn Forte int fd; 1123*fcf3ce44SJohn Forte char fcapath[MAXPATHLEN]; 1124*fcf3ce44SJohn Forte char *char_ptr; 1125*fcf3ce44SJohn Forte struct stat stbuf; 1126*fcf3ce44SJohn Forte fcio_t fcio; 1127*fcf3ce44SJohn Forte uint32_t port_top; 1128*fcf3ce44SJohn Forte fc_port_dev_t *dlist; 1129*fcf3ce44SJohn Forte 1130*fcf3ce44SJohn Forte *dev_list = dlist = NULL; 1131*fcf3ce44SJohn Forte (void) strcpy(fcapath, path); 1132*fcf3ce44SJohn Forte /* 1133*fcf3ce44SJohn Forte * Get the path to the :devctl driver 1134*fcf3ce44SJohn Forte * 1135*fcf3ce44SJohn Forte * This assumes the path looks something like this: 1136*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 1137*fcf3ce44SJohn Forte * or 1138*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0 1139*fcf3ce44SJohn Forte * or 1140*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 1141*fcf3ce44SJohn Forte * or 1142*fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl 1143*fcf3ce44SJohn Forte */ 1144*fcf3ce44SJohn Forte if (strstr(fcapath, DRV_NAME_SSD) || strstr(fcapath, SES_NAME)) { 1145*fcf3ce44SJohn Forte if ((char_ptr = strrchr(fcapath, '/')) == NULL) { 1146*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1147*fcf3ce44SJohn Forte } 1148*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */ 1149*fcf3ce44SJohn Forte /* append controller */ 1150*fcf3ce44SJohn Forte (void) strcat(fcapath, FC_CTLR); 1151*fcf3ce44SJohn Forte } else { 1152*fcf3ce44SJohn Forte if (stat(fcapath, &stbuf) < 0) { 1153*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 1154*fcf3ce44SJohn Forte } 1155*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 1156*fcf3ce44SJohn Forte /* append controller */ 1157*fcf3ce44SJohn Forte (void) strcat(fcapath, FC_CTLR); 1158*fcf3ce44SJohn Forte } 1159*fcf3ce44SJohn Forte } 1160*fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath); 1161*fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) { 1162*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 1163*fcf3ce44SJohn Forte } 1164*fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) { 1165*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1166*fcf3ce44SJohn Forte } 1167*fcf3ce44SJohn Forte 1168*fcf3ce44SJohn Forte /* 1169*fcf3ce44SJohn Forte * Get the device list from port driver 1170*fcf3ce44SJohn Forte */ 1171*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_NUM_DEVS; 1172*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (num_devices); 1173*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 1174*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&num_devices; 1175*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) { 1176*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n"); 1177*fcf3ce44SJohn Forte (void) close(fd); 1178*fcf3ce44SJohn Forte return (L_FCIO_GET_NUM_DEVS_FAIL); 1179*fcf3ce44SJohn Forte } 1180*fcf3ce44SJohn Forte if (num_devices == 0) { 1181*fcf3ce44SJohn Forte *ndevs = 0; 1182*fcf3ce44SJohn Forte (void) close(fd); 1183*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 1184*fcf3ce44SJohn Forte } 1185*fcf3ce44SJohn Forte 1186*fcf3ce44SJohn Forte if ((dlist = (fc_port_dev_t *)calloc(num_devices, 1187*fcf3ce44SJohn Forte sizeof (fc_port_dev_t))) == NULL) { 1188*fcf3ce44SJohn Forte (void) close(fd); 1189*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1190*fcf3ce44SJohn Forte } 1191*fcf3ce44SJohn Forte bzero((caddr_t)&fcio, sizeof (fcio)); 1192*fcf3ce44SJohn Forte /* Get the device list */ 1193*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST; 1194*fcf3ce44SJohn Forte /* Information read operation */ 1195*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 1196*fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t); 1197*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)dlist; 1198*fcf3ce44SJohn Forte /* new device count */ 1199*fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count); 1200*fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count; 1201*fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) { 1202*fcf3ce44SJohn Forte if (err == L_INVALID_DEVICE_COUNT) { 1203*fcf3ce44SJohn Forte /* 1204*fcf3ce44SJohn Forte * original buffer was small so allocate buffer 1205*fcf3ce44SJohn Forte * with a new count and retry. 1206*fcf3ce44SJohn Forte */ 1207*fcf3ce44SJohn Forte free(dlist); 1208*fcf3ce44SJohn Forte num_devices = new_count; 1209*fcf3ce44SJohn Forte new_count = 0; 1210*fcf3ce44SJohn Forte if ((dlist = (fc_port_dev_t *)calloc(num_devices, 1211*fcf3ce44SJohn Forte sizeof (fc_port_dev_t))) == NULL) { 1212*fcf3ce44SJohn Forte (void) close(fd); 1213*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1214*fcf3ce44SJohn Forte } 1215*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST; 1216*fcf3ce44SJohn Forte /* Information read operation */ 1217*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 1218*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)dlist; 1219*fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t); 1220*fcf3ce44SJohn Forte /* new device count */ 1221*fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count); 1222*fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count; 1223*fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) { 1224*fcf3ce44SJohn Forte if (err == L_INVALID_DEVICE_COUNT) { 1225*fcf3ce44SJohn Forte /* 1226*fcf3ce44SJohn Forte * No more retry. There may be severe hardware 1227*fcf3ce44SJohn Forte * problem so return error here. 1228*fcf3ce44SJohn Forte */ 1229*fcf3ce44SJohn Forte I_DPRINTF(" Device count was %d" 1230*fcf3ce44SJohn Forte " should have been %d\n", 1231*fcf3ce44SJohn Forte num_devices, new_count); 1232*fcf3ce44SJohn Forte } else { 1233*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed."); 1234*fcf3ce44SJohn Forte err = L_FCIO_GET_DEV_LIST_FAIL; 1235*fcf3ce44SJohn Forte } 1236*fcf3ce44SJohn Forte free(dlist); 1237*fcf3ce44SJohn Forte (void) close(fd); 1238*fcf3ce44SJohn Forte return (err); 1239*fcf3ce44SJohn Forte } 1240*fcf3ce44SJohn Forte } else { 1241*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed."); 1242*fcf3ce44SJohn Forte free(dlist); 1243*fcf3ce44SJohn Forte (void) close(fd); 1244*fcf3ce44SJohn Forte return (L_FCIO_GET_DEV_LIST_FAIL); 1245*fcf3ce44SJohn Forte } 1246*fcf3ce44SJohn Forte } 1247*fcf3ce44SJohn Forte 1248*fcf3ce44SJohn Forte /* 1249*fcf3ce44SJohn Forte * if new count is smaller than the original number from 1250*fcf3ce44SJohn Forte * FCIO_GET_NUM_DEVS, adjust new count and buffer size 1251*fcf3ce44SJohn Forte * and continue. 1252*fcf3ce44SJohn Forte */ 1253*fcf3ce44SJohn Forte if (new_count < num_devices) { 1254*fcf3ce44SJohn Forte if (new_count == 0) { 1255*fcf3ce44SJohn Forte *ndevs = 0; 1256*fcf3ce44SJohn Forte (void) close(fd); 1257*fcf3ce44SJohn Forte S_FREE(dlist); 1258*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 1259*fcf3ce44SJohn Forte } 1260*fcf3ce44SJohn Forte num_devices = new_count; 1261*fcf3ce44SJohn Forte if ((dlist = (fc_port_dev_t *)realloc(dlist, 1262*fcf3ce44SJohn Forte (new_count * sizeof (fc_port_dev_t)))) 1263*fcf3ce44SJohn Forte == NULL) { 1264*fcf3ce44SJohn Forte S_FREE(dlist); 1265*fcf3ce44SJohn Forte (void) close(fd); 1266*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1267*fcf3ce44SJohn Forte } 1268*fcf3ce44SJohn Forte } 1269*fcf3ce44SJohn Forte 1270*fcf3ce44SJohn Forte *dev_list = dlist; 1271*fcf3ce44SJohn Forte *ndevs = num_devices; 1272*fcf3ce44SJohn Forte 1273*fcf3ce44SJohn Forte /* close here since fcapath will be passed to other routines. */ 1274*fcf3ce44SJohn Forte (void) close(fd); 1275*fcf3ce44SJohn Forte 1276*fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) { 1277*fcf3ce44SJohn Forte free(*dev_list); 1278*fcf3ce44SJohn Forte *dev_list = NULL; 1279*fcf3ce44SJohn Forte return (err); 1280*fcf3ce44SJohn Forte } 1281*fcf3ce44SJohn Forte 1282*fcf3ce44SJohn Forte /* Get the inq_dtype for each device on dev list. */ 1283*fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dlist++) { 1284*fcf3ce44SJohn Forte /* Get the inq_dtype for each device. */ 1285*fcf3ce44SJohn Forte if ((err = g_get_inq_dtype(fcapath, dlist->dev_pwwn, 1286*fcf3ce44SJohn Forte &dlist->dev_dtype)) != 0) { 1287*fcf3ce44SJohn Forte /* 1288*fcf3ce44SJohn Forte * if g_get_inq_dtype failed on g_dev_login 1289*fcf3ce44SJohn Forte * or g_issue_fcp_ioctl, continue to the next 1290*fcf3ce44SJohn Forte * dev on dlist. 1291*fcf3ce44SJohn Forte * L_GET_DEV_LIST_ULP_FAILURE is returned 1292*fcf3ce44SJohn Forte * after processing the whole dlist. 1293*fcf3ce44SJohn Forte */ 1294*fcf3ce44SJohn Forte if ((err == L_FCIO_DEV_LOGIN_FAIL) || 1295*fcf3ce44SJohn Forte (err == L_FCP_TGT_INQUIRY_FAIL)) { 1296*fcf3ce44SJohn Forte ulp_failure = 1; 1297*fcf3ce44SJohn Forte dlist->dev_dtype = GFC_ERR_INQ_DTYPE; 1298*fcf3ce44SJohn Forte } else { 1299*fcf3ce44SJohn Forte (void) free(*dev_list); 1300*fcf3ce44SJohn Forte *dev_list = NULL; 1301*fcf3ce44SJohn Forte return (err); 1302*fcf3ce44SJohn Forte } 1303*fcf3ce44SJohn Forte } 1304*fcf3ce44SJohn Forte } 1305*fcf3ce44SJohn Forte 1306*fcf3ce44SJohn Forte if (ulp_failure) { 1307*fcf3ce44SJohn Forte return (L_GET_DEV_LIST_ULP_FAILURE); 1308*fcf3ce44SJohn Forte } else { 1309*fcf3ce44SJohn Forte return (0); 1310*fcf3ce44SJohn Forte } 1311*fcf3ce44SJohn Forte } 1312*fcf3ce44SJohn Forte 1313*fcf3ce44SJohn Forte 1314*fcf3ce44SJohn Forte /* Constant used by g_get_inq_dtype() */ 1315*fcf3ce44SJohn Forte #define FCP_PATH "/devices/pseudo/fcp@0:fcp" 1316*fcf3ce44SJohn Forte 1317*fcf3ce44SJohn Forte /* 1318*fcf3ce44SJohn Forte * Gets the inq_dtype for devices on the fabric FC driver 1319*fcf3ce44SJohn Forte * through an ioctl to the FCP module. 1320*fcf3ce44SJohn Forte * 1321*fcf3ce44SJohn Forte * OUTPUT: 1322*fcf3ce44SJohn Forte * inq_dtype is set to the dtype on success 1323*fcf3ce44SJohn Forte * 1324*fcf3ce44SJohn Forte * RETURN VALUES: 1325*fcf3ce44SJohn Forte * 0 on Success 1326*fcf3ce44SJohn Forte * Non-zero on error 1327*fcf3ce44SJohn Forte */ 1328*fcf3ce44SJohn Forte int 1329*fcf3ce44SJohn Forte g_get_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype) 1330*fcf3ce44SJohn Forte { 1331*fcf3ce44SJohn Forte int dev_type, fd; 1332*fcf3ce44SJohn Forte int err, fcp_fd; 1333*fcf3ce44SJohn Forte uint32_t state; 1334*fcf3ce44SJohn Forte uint32_t port_top = 0; 1335*fcf3ce44SJohn Forte struct fcp_ioctl fcp_data; 1336*fcf3ce44SJohn Forte struct device_data inq_data; 1337*fcf3ce44SJohn Forte struct stat sbuf; 1338*fcf3ce44SJohn Forte 1339*fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath); 1340*fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) { 1341*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 1342*fcf3ce44SJohn Forte } 1343*fcf3ce44SJohn Forte 1344*fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) { 1345*fcf3ce44SJohn Forte return (err); 1346*fcf3ce44SJohn Forte } 1347*fcf3ce44SJohn Forte 1348*fcf3ce44SJohn Forte if ((port_top == FC_TOP_FABRIC) || (port_top == FC_TOP_PUBLIC_LOOP)) { 1349*fcf3ce44SJohn Forte /* 1350*fcf3ce44SJohn Forte * if there is an error on getting port state we will 1351*fcf3ce44SJohn Forte * continue to login. 1352*fcf3ce44SJohn Forte * state can be either of 1353*fcf3ce44SJohn Forte * PORT_DEVICE_INVALID, PORT_DEVICE_VALID, 1354*fcf3ce44SJohn Forte * PORT_DEVICE_LOGGED_IN. Trying port login 1355*fcf3ce44SJohn Forte * unless already logged in. 1356*fcf3ce44SJohn Forte * It will be examined if there is an adverse 1357*fcf3ce44SJohn Forte * effect on invalid state device. 1358*fcf3ce44SJohn Forte */ 1359*fcf3ce44SJohn Forte if (((err = g_get_dev_port_state(fcapath, pwwn, &state)) 1360*fcf3ce44SJohn Forte != 0) || (state != PORT_DEVICE_LOGGED_IN)) { 1361*fcf3ce44SJohn Forte /* do port login to fabric device. */ 1362*fcf3ce44SJohn Forte if ((err = g_dev_login(fcapath, pwwn)) != 0) { 1363*fcf3ce44SJohn Forte return (err); 1364*fcf3ce44SJohn Forte } 1365*fcf3ce44SJohn Forte } 1366*fcf3ce44SJohn Forte } 1367*fcf3ce44SJohn Forte 1368*fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) 1369*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1370*fcf3ce44SJohn Forte 1371*fcf3ce44SJohn Forte if (fstat(fd, &sbuf) == -1) { 1372*fcf3ce44SJohn Forte (void) close(fd); 1373*fcf3ce44SJohn Forte return (L_FSTAT_ERROR); 1374*fcf3ce44SJohn Forte } 1375*fcf3ce44SJohn Forte 1376*fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) { 1377*fcf3ce44SJohn Forte (void) close(fd); 1378*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1379*fcf3ce44SJohn Forte } 1380*fcf3ce44SJohn Forte 1381*fcf3ce44SJohn Forte /* Get the minor number for an fp instance */ 1382*fcf3ce44SJohn Forte fcp_data.fp_minor = minor(sbuf.st_rdev); 1383*fcf3ce44SJohn Forte 1384*fcf3ce44SJohn Forte fcp_data.listlen = 1; 1385*fcf3ce44SJohn Forte inq_data.dev_pwwn = pwwn; /* The port WWN as passed */ 1386*fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data; 1387*fcf3ce44SJohn Forte 1388*fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) { 1389*fcf3ce44SJohn Forte close(fd); 1390*fcf3ce44SJohn Forte close(fcp_fd); 1391*fcf3ce44SJohn Forte return (err); 1392*fcf3ce44SJohn Forte } 1393*fcf3ce44SJohn Forte *inq_dtype = inq_data.dev0_type; 1394*fcf3ce44SJohn Forte 1395*fcf3ce44SJohn Forte close(fd); 1396*fcf3ce44SJohn Forte close(fcp_fd); 1397*fcf3ce44SJohn Forte 1398*fcf3ce44SJohn Forte return (err); 1399*fcf3ce44SJohn Forte } 1400*fcf3ce44SJohn Forte 1401*fcf3ce44SJohn Forte /* 1402*fcf3ce44SJohn Forte * Gets the inq_dtype for devices on the fabric FC driver 1403*fcf3ce44SJohn Forte * through an ioctl to the FCP module. 1404*fcf3ce44SJohn Forte * 1405*fcf3ce44SJohn Forte * This is exactly same as g_get_inq_dtype except that it does not do 1406*fcf3ce44SJohn Forte * g_dev_login(). That is for the case when the FCA tries to get its own 1407*fcf3ce44SJohn Forte * inq_dtype and in such a case, it cannot PLOGI into itself. 1408*fcf3ce44SJohn Forte * 1409*fcf3ce44SJohn Forte * OUTPUT: 1410*fcf3ce44SJohn Forte * inq_dtype is set to the dtype on success 1411*fcf3ce44SJohn Forte * 1412*fcf3ce44SJohn Forte * RETURN VALUES: 1413*fcf3ce44SJohn Forte * 0 on Success 1414*fcf3ce44SJohn Forte * Non-zero on error 1415*fcf3ce44SJohn Forte */ 1416*fcf3ce44SJohn Forte static int 1417*fcf3ce44SJohn Forte get_fca_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype) 1418*fcf3ce44SJohn Forte { 1419*fcf3ce44SJohn Forte int dev_type, fd; 1420*fcf3ce44SJohn Forte int err, fcp_fd; 1421*fcf3ce44SJohn Forte struct fcp_ioctl fcp_data; 1422*fcf3ce44SJohn Forte struct device_data inq_data; 1423*fcf3ce44SJohn Forte struct stat sbuf; 1424*fcf3ce44SJohn Forte 1425*fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath); 1426*fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) { 1427*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 1428*fcf3ce44SJohn Forte } 1429*fcf3ce44SJohn Forte 1430*fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) { 1431*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1432*fcf3ce44SJohn Forte } 1433*fcf3ce44SJohn Forte 1434*fcf3ce44SJohn Forte if (fstat(fd, &sbuf) == -1) { 1435*fcf3ce44SJohn Forte (void) close(fd); 1436*fcf3ce44SJohn Forte return (L_FSTAT_ERROR); 1437*fcf3ce44SJohn Forte } 1438*fcf3ce44SJohn Forte 1439*fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) { 1440*fcf3ce44SJohn Forte (void) close(fd); 1441*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 1442*fcf3ce44SJohn Forte } 1443*fcf3ce44SJohn Forte 1444*fcf3ce44SJohn Forte /* Get the minor number for an fp instance */ 1445*fcf3ce44SJohn Forte fcp_data.fp_minor = minor(sbuf.st_rdev); 1446*fcf3ce44SJohn Forte 1447*fcf3ce44SJohn Forte fcp_data.listlen = 1; 1448*fcf3ce44SJohn Forte inq_data.dev_pwwn = pwwn; /* The port WWN as passed */ 1449*fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data; 1450*fcf3ce44SJohn Forte 1451*fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) { 1452*fcf3ce44SJohn Forte close(fd); 1453*fcf3ce44SJohn Forte close(fcp_fd); 1454*fcf3ce44SJohn Forte return (err); 1455*fcf3ce44SJohn Forte } 1456*fcf3ce44SJohn Forte *inq_dtype = inq_data.dev0_type; 1457*fcf3ce44SJohn Forte 1458*fcf3ce44SJohn Forte close(fd); 1459*fcf3ce44SJohn Forte close(fcp_fd); 1460*fcf3ce44SJohn Forte 1461*fcf3ce44SJohn Forte return (0); 1462*fcf3ce44SJohn Forte } 1463*fcf3ce44SJohn Forte 1464*fcf3ce44SJohn Forte /* 1465*fcf3ce44SJohn Forte * This function returns the traditional g_get_dev_map. Device list 1466*fcf3ce44SJohn Forte * and local hba seperate. 1467*fcf3ce44SJohn Forte */ 1468*fcf3ce44SJohn Forte int 1469*fcf3ce44SJohn Forte g_get_dev_map(char *path, gfc_map_t *map_ptr, int verbose) 1470*fcf3ce44SJohn Forte { 1471*fcf3ce44SJohn Forte return (create_map(path, map_ptr, verbose, MAP_FORMAT_STANDARD)); 1472*fcf3ce44SJohn Forte } 1473*fcf3ce44SJohn Forte 1474*fcf3ce44SJohn Forte /* 1475*fcf3ce44SJohn Forte * This function returns the device map with local hba in physical 1476*fcf3ce44SJohn Forte * order. Note: Physical order is only returned properly for 1477*fcf3ce44SJohn Forte * private loop. local hba is also included seperate 1478*fcf3ce44SJohn Forte */ 1479*fcf3ce44SJohn Forte int 1480*fcf3ce44SJohn Forte g_get_lilp_map(char *path, gfc_map_t *map_ptr, int verbose) 1481*fcf3ce44SJohn Forte { 1482*fcf3ce44SJohn Forte return (create_map(path, map_ptr, verbose, MAP_FORMAT_LILP)); 1483*fcf3ce44SJohn Forte } 1484*fcf3ce44SJohn Forte 1485*fcf3ce44SJohn Forte /* 1486*fcf3ce44SJohn Forte * Gets device map from nexus driver 1487*fcf3ce44SJohn Forte * 1488*fcf3ce44SJohn Forte * PARAMS: 1489*fcf3ce44SJohn Forte * path - must be the physical path to a device 1490*fcf3ce44SJohn Forte * map - loop map returned from fc port. 1491*fcf3ce44SJohn Forte * verbose - options. 1492*fcf3ce44SJohn Forte * 1493*fcf3ce44SJohn Forte * LOGIC: 1494*fcf3ce44SJohn Forte * 1. check the validity of path via g_get_path_type. 1495*fcf3ce44SJohn Forte * 2. If FC path, get the topology of the path via 1496*fcf3ce44SJohn Forte * g_get_fca_port_topology. 1497*fcf3ce44SJohn Forte * 1498*fcf3ce44SJohn Forte * 3. If FC type(Leadville statck) 1499*fcf3ce44SJohn Forte * g_get_dev_list to get the device node list of fc_port_dev_t. 1500*fcf3ce44SJohn Forte * g_get_host_params to get the fca port node of fc_port_dev_t. 1501*fcf3ce44SJohn Forte * 1502*fcf3ce44SJohn Forte * Case of fabric or public loop topology 1503*fcf3ce44SJohn Forte * Check if the port id > 0xffff. 1504*fcf3ce44SJohn Forte * Move device node and fca port node to 1505*fcf3ce44SJohn Forte * gfc_map structure via gfc_port_dev_info_t 1506*fcf3ce44SJohn Forte * pub_port union. 1507*fcf3ce44SJohn Forte * Issue g_get_inq_dtype to get FCP inquiry data 1508*fcf3ce44SJohn Forte * and store it into gfc_port_dev_info_t. 1509*fcf3ce44SJohn Forte * 1510*fcf3ce44SJohn Forte * Case of private loop topology 1511*fcf3ce44SJohn Forte * Check if the port id < 0xff. 1512*fcf3ce44SJohn Forte * Move device node and fca port node to 1513*fcf3ce44SJohn Forte * gfc_map structure via gfc_port_dev_info_t 1514*fcf3ce44SJohn Forte * priv_port union. 1515*fcf3ce44SJohn Forte * Issue g_get_inq_dtype to get FCP inquiry data 1516*fcf3ce44SJohn Forte * and store it into gfc_port_dev_info_t. 1517*fcf3ce44SJohn Forte * 1518*fcf3ce44SJohn Forte * else FC4 type(socal/sf or ifp stack) 1519*fcf3ce44SJohn Forte * SFIOCGMAP ioctl to get the device and hba nodes of 1520*fcf3ce44SJohn Forte * sf_addr_pair_t. 1521*fcf3ce44SJohn Forte * 1522*fcf3ce44SJohn Forte * 1523*fcf3ce44SJohn Forte * RETURNS: 1524*fcf3ce44SJohn Forte * 0 : if OK 1525*fcf3ce44SJohn Forte * non-zero: otherwise 1526*fcf3ce44SJohn Forte */ 1527*fcf3ce44SJohn Forte int 1528*fcf3ce44SJohn Forte create_map(char *path, gfc_map_t *map_ptr, int verbose, int map_type) 1529*fcf3ce44SJohn Forte { 1530*fcf3ce44SJohn Forte int fd, i, j, num_devices = 0, err, pathcnt = 1; 1531*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN]; 1532*fcf3ce44SJohn Forte char *char_ptr; 1533*fcf3ce44SJohn Forte struct stat stbuf; 1534*fcf3ce44SJohn Forte fc_port_dev_t *dev_list, *dlistptr; 1535*fcf3ce44SJohn Forte uint32_t hba_port_top = 0; 1536*fcf3ce44SJohn Forte uint_t dev_type; 1537*fcf3ce44SJohn Forte sf_al_map_t sf_map; 1538*fcf3ce44SJohn Forte gfc_port_dev_info_t *dev_ptr; 1539*fcf3ce44SJohn Forte fc_port_dev_t fp_hba_port; 1540*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 1541*fcf3ce44SJohn Forte int p_on = 0, p_st = 0; 1542*fcf3ce44SJohn Forte 1543*fcf3ce44SJohn Forte /* return invalid path if path is NULL */ 1544*fcf3ce44SJohn Forte if (path == NULL) { 1545*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1546*fcf3ce44SJohn Forte } 1547*fcf3ce44SJohn Forte /* return invalid arg if map_ptr is NULL */ 1548*fcf3ce44SJohn Forte if (map_ptr == NULL) { 1549*fcf3ce44SJohn Forte return (L_INVALID_ARG); 1550*fcf3ce44SJohn Forte } 1551*fcf3ce44SJohn Forte 1552*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1553*fcf3ce44SJohn Forte map_ptr->count = 0; 1554*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 1555*fcf3ce44SJohn Forte /* 1556*fcf3ce44SJohn Forte * Get the path to the :devctl driver 1557*fcf3ce44SJohn Forte * 1558*fcf3ce44SJohn Forte * This assumes the path looks something like this: 1559*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 1560*fcf3ce44SJohn Forte * or 1561*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0 1562*fcf3ce44SJohn Forte * or 1563*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 1564*fcf3ce44SJohn Forte * or 1565*fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl 1566*fcf3ce44SJohn Forte */ 1567*fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) { 1568*fcf3ce44SJohn Forte (void) strcpy(drvr_path0, path); 1569*fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path0, &pathlist)) { 1570*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1571*fcf3ce44SJohn Forte } 1572*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 1573*fcf3ce44SJohn Forte p_on = p_st = 0; 1574*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 1575*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 1576*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 1577*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 1578*fcf3ce44SJohn Forte p_on = i; 1579*fcf3ce44SJohn Forte break; 1580*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 1581*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 1582*fcf3ce44SJohn Forte p_st = i; 1583*fcf3ce44SJohn Forte } 1584*fcf3ce44SJohn Forte } 1585*fcf3ce44SJohn Forte } 1586*fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state == 1587*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 1588*fcf3ce44SJohn Forte /* on_line path */ 1589*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 1590*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 1591*fcf3ce44SJohn Forte } else { 1592*fcf3ce44SJohn Forte /* standby or path0 */ 1593*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 1594*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 1595*fcf3ce44SJohn Forte } 1596*fcf3ce44SJohn Forte free(pathlist.path_info); 1597*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 1598*fcf3ce44SJohn Forte } else { 1599*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 1600*fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) || 1601*fcf3ce44SJohn Forte strstr(drvr_path, SES_NAME) || 1602*fcf3ce44SJohn Forte strstr(drvr_path, DRV_NAME_ST)) { 1603*fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) { 1604*fcf3ce44SJohn Forte return (L_INVALID_PATH); 1605*fcf3ce44SJohn Forte } 1606*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */ 1607*fcf3ce44SJohn Forte /* append controller */ 1608*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 1609*fcf3ce44SJohn Forte } else { 1610*fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) { 1611*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 1612*fcf3ce44SJohn Forte } 1613*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 1614*fcf3ce44SJohn Forte /* append controller */ 1615*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 1616*fcf3ce44SJohn Forte } 1617*fcf3ce44SJohn Forte } 1618*fcf3ce44SJohn Forte } 1619*fcf3ce44SJohn Forte 1620*fcf3ce44SJohn Forte P_DPRINTF(" g_get_dev_map: Geting drive map from:" 1621*fcf3ce44SJohn Forte " %s\n", drvr_path); 1622*fcf3ce44SJohn Forte 1623*fcf3ce44SJohn Forte dev_type = g_get_path_type(drvr_path); 1624*fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & XPORT_MASK)) { 1625*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 1626*fcf3ce44SJohn Forte } 1627*fcf3ce44SJohn Forte 1628*fcf3ce44SJohn Forte /* get fiber topology */ 1629*fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(drvr_path, 1630*fcf3ce44SJohn Forte &hba_port_top, verbose)) != 0) { 1631*fcf3ce44SJohn Forte return (err); 1632*fcf3ce44SJohn Forte } 1633*fcf3ce44SJohn Forte 1634*fcf3ce44SJohn Forte /* for FC devices. */ 1635*fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) { 1636*fcf3ce44SJohn Forte /* 1637*fcf3ce44SJohn Forte * if g_get_dev_list fails with L_NO_DEVICES_FOUND 1638*fcf3ce44SJohn Forte * we still want to call g_get_host_params to try to find the 1639*fcf3ce44SJohn Forte * HBA. If we do not see any HBAs on the loop, the 1640*fcf3ce44SJohn Forte * g_get_host_params will fail when it trys to issue the target 1641*fcf3ce44SJohn Forte * inquiry ioctl. In this case, we would still like to return 1642*fcf3ce44SJohn Forte * L_NO_DEVICES_FOUND. 1643*fcf3ce44SJohn Forte * 1644*fcf3ce44SJohn Forte * If g_get_dev_list fails with L_NO_DEVICES_FOUND and 1645*fcf3ce44SJohn Forte * g_get_host_params fails, the function returns 1646*fcf3ce44SJohn Forte * L_NO_DEVICES_FOUND 1647*fcf3ce44SJohn Forte */ 1648*fcf3ce44SJohn Forte if ((err = g_get_dev_list(drvr_path, &dev_list, 1649*fcf3ce44SJohn Forte &num_devices)) != 0) { 1650*fcf3ce44SJohn Forte /* 1651*fcf3ce44SJohn Forte * g_get_dev_map doesn't allow ulp failure 1652*fcf3ce44SJohn Forte * to continue thus we need to free dev_list 1653*fcf3ce44SJohn Forte * here. 1654*fcf3ce44SJohn Forte */ 1655*fcf3ce44SJohn Forte if (err == L_GET_DEV_LIST_ULP_FAILURE) { 1656*fcf3ce44SJohn Forte (void) free(dev_list); 1657*fcf3ce44SJohn Forte } 1658*fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) { 1659*fcf3ce44SJohn Forte return (err); 1660*fcf3ce44SJohn Forte } 1661*fcf3ce44SJohn Forte } 1662*fcf3ce44SJohn Forte 1663*fcf3ce44SJohn Forte /* Get local HBA information */ 1664*fcf3ce44SJohn Forte if ((err = g_get_host_params(drvr_path, &fp_hba_port, 1665*fcf3ce44SJohn Forte verbose)) != 0) { 1666*fcf3ce44SJohn Forte (void) free(dev_list); 1667*fcf3ce44SJohn Forte if (num_devices == 0) 1668*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 1669*fcf3ce44SJohn Forte else 1670*fcf3ce44SJohn Forte return (err); 1671*fcf3ce44SJohn Forte } 1672*fcf3ce44SJohn Forte 1673*fcf3ce44SJohn Forte /* If devices, other than local HBA are found */ 1674*fcf3ce44SJohn Forte /* allocate space for them in the gfc_map. */ 1675*fcf3ce44SJohn Forte if (num_devices > 0) { 1676*fcf3ce44SJohn Forte 1677*fcf3ce44SJohn Forte /* If map type is on MAP_FORMAT_LILP we need */ 1678*fcf3ce44SJohn Forte /* to add space for the local HBA */ 1679*fcf3ce44SJohn Forte if (map_type == MAP_FORMAT_LILP) { 1680*fcf3ce44SJohn Forte map_ptr->count = ++num_devices; 1681*fcf3ce44SJohn Forte } else { 1682*fcf3ce44SJohn Forte map_ptr->count = num_devices; 1683*fcf3ce44SJohn Forte } 1684*fcf3ce44SJohn Forte 1685*fcf3ce44SJohn Forte if ((map_ptr->dev_addr = (gfc_port_dev_info_t *) 1686*fcf3ce44SJohn Forte calloc(map_ptr->count, 1687*fcf3ce44SJohn Forte sizeof (gfc_port_dev_info_t))) == NULL) { 1688*fcf3ce44SJohn Forte (void) free(dev_list); 1689*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1690*fcf3ce44SJohn Forte } 1691*fcf3ce44SJohn Forte } 1692*fcf3ce44SJohn Forte 1693*fcf3ce44SJohn Forte /* If we want the lilp map then we need to do a little */ 1694*fcf3ce44SJohn Forte /* work here. The lilp map contains the local hba in */ 1695*fcf3ce44SJohn Forte /* the dev_addr. Once this has been added qsort the */ 1696*fcf3ce44SJohn Forte /* dev_addr array so it's in physical order. */ 1697*fcf3ce44SJohn Forte /* The lilp map will contain the local hba in the */ 1698*fcf3ce44SJohn Forte /* dev_addr array only when num_devices > 0 */ 1699*fcf3ce44SJohn Forte if (map_type == MAP_FORMAT_LILP && num_devices > 0) { 1700*fcf3ce44SJohn Forte 1701*fcf3ce44SJohn Forte /* First we need to allocate one additional */ 1702*fcf3ce44SJohn Forte /* device to the dev_addr structure, for the */ 1703*fcf3ce44SJohn Forte /* local hba */ 1704*fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)realloc(dev_list, 1705*fcf3ce44SJohn Forte (num_devices * sizeof (fc_port_dev_t)))) 1706*fcf3ce44SJohn Forte == NULL) { 1707*fcf3ce44SJohn Forte S_FREE(dev_list); 1708*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1709*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1710*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1711*fcf3ce44SJohn Forte } 1712*fcf3ce44SJohn Forte 1713*fcf3ce44SJohn Forte /* Next, copy the local hba into this new loc. */ 1714*fcf3ce44SJohn Forte if (memcpy(dev_list+(num_devices-1), &fp_hba_port, 1715*fcf3ce44SJohn Forte sizeof (fc_port_dev_t)) == NULL) { 1716*fcf3ce44SJohn Forte (void) free(dev_list); 1717*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1718*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1719*fcf3ce44SJohn Forte return (L_MEMCPY_FAILED); 1720*fcf3ce44SJohn Forte } 1721*fcf3ce44SJohn Forte 1722*fcf3ce44SJohn Forte /* Now sort by physical location */ 1723*fcf3ce44SJohn Forte qsort((void*)dev_list, num_devices, 1724*fcf3ce44SJohn Forte sizeof (fc_port_dev_t), lilp_map_cmp); 1725*fcf3ce44SJohn Forte } 1726*fcf3ce44SJohn Forte 1727*fcf3ce44SJohn Forte dlistptr = dev_list; 1728*fcf3ce44SJohn Forte dev_ptr = map_ptr->dev_addr; 1729*fcf3ce44SJohn Forte 1730*fcf3ce44SJohn Forte switch (hba_port_top) { 1731*fcf3ce44SJohn Forte case FC_TOP_FABRIC: 1732*fcf3ce44SJohn Forte case FC_TOP_PUBLIC_LOOP: 1733*fcf3ce44SJohn Forte if (fp_hba_port.dev_did.port_id <= 0xffff) { 1734*fcf3ce44SJohn Forte (void) free(dlistptr); 1735*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1736*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1737*fcf3ce44SJohn Forte return (L_INVALID_FABRIC_ADDRESS); 1738*fcf3ce44SJohn Forte } else { 1739*fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top; 1740*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.pub_port = 1741*fcf3ce44SJohn Forte fp_hba_port; 1742*fcf3ce44SJohn Forte } 1743*fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_ptr++, 1744*fcf3ce44SJohn Forte dev_list++) { 1745*fcf3ce44SJohn Forte if (dev_list->dev_did.port_id <= 0xffff) { 1746*fcf3ce44SJohn Forte (void) free(dlistptr); 1747*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1748*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1749*fcf3ce44SJohn Forte return (L_INVALID_FABRIC_ADDRESS); 1750*fcf3ce44SJohn Forte } else { 1751*fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top; 1752*fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.pub_port = 1753*fcf3ce44SJohn Forte *dev_list; 1754*fcf3ce44SJohn Forte } 1755*fcf3ce44SJohn Forte } 1756*fcf3ce44SJohn Forte break; 1757*fcf3ce44SJohn Forte case FC_TOP_PRIVATE_LOOP: 1758*fcf3ce44SJohn Forte /* 1759*fcf3ce44SJohn Forte * Map the (new->old) structures here. 1760*fcf3ce44SJohn Forte * Checking (i < SF_NUM_ENTRIES_IN_MAP) just to 1761*fcf3ce44SJohn Forte * make sure that we don't overrun the map structure 1762*fcf3ce44SJohn Forte * since it can hold data for upto 126 devices. 1763*fcf3ce44SJohn Forte */ 1764*fcf3ce44SJohn Forte if (fp_hba_port.dev_did.port_id > 0xff) { 1765*fcf3ce44SJohn Forte (void) free(dlistptr); 1766*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1767*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1768*fcf3ce44SJohn Forte return (L_INVALID_PRIVATE_LOOP_ADDRESS); 1769*fcf3ce44SJohn Forte } else { 1770*fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top; 1771*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev. 1772*fcf3ce44SJohn Forte priv_port.sf_al_pa = 1773*fcf3ce44SJohn Forte (uchar_t)fp_hba_port.dev_did.port_id; 1774*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev. 1775*fcf3ce44SJohn Forte priv_port.sf_hard_address = (uchar_t) 1776*fcf3ce44SJohn Forte fp_hba_port.dev_hard_addr.hard_addr; 1777*fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++) { 1778*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev. 1779*fcf3ce44SJohn Forte priv_port.sf_node_wwn[j] = 1780*fcf3ce44SJohn Forte fp_hba_port.dev_nwwn.raw_wwn[j]; 1781*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev. 1782*fcf3ce44SJohn Forte priv_port.sf_port_wwn[j] = 1783*fcf3ce44SJohn Forte fp_hba_port.dev_pwwn.raw_wwn[j]; 1784*fcf3ce44SJohn Forte } 1785*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev. 1786*fcf3ce44SJohn Forte priv_port.sf_inq_dtype = 1787*fcf3ce44SJohn Forte fp_hba_port.dev_dtype; 1788*fcf3ce44SJohn Forte } 1789*fcf3ce44SJohn Forte 1790*fcf3ce44SJohn Forte for (i = 0; (i < num_devices && 1791*fcf3ce44SJohn Forte i < SF_NUM_ENTRIES_IN_MAP); 1792*fcf3ce44SJohn Forte i++, dev_ptr++, dev_list++) { 1793*fcf3ce44SJohn Forte /* 1794*fcf3ce44SJohn Forte * Out of 24 bits of port_id, copy only 1795*fcf3ce44SJohn Forte * 8 bits to al_pa. This works okay for 1796*fcf3ce44SJohn Forte * devices that're on a private loop. 1797*fcf3ce44SJohn Forte */ 1798*fcf3ce44SJohn Forte if (dev_list->dev_did.port_id > 0xff) { 1799*fcf3ce44SJohn Forte (void) free(dlistptr); 1800*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1801*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1802*fcf3ce44SJohn Forte return (L_INVALID_PRIVATE_LOOP_ADDRESS); 1803*fcf3ce44SJohn Forte } 1804*fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top; 1805*fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port.sf_al_pa 1806*fcf3ce44SJohn Forte = (uchar_t)dev_list->dev_did.port_id; 1807*fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port.sf_hard_address 1808*fcf3ce44SJohn Forte = (uchar_t)dev_list->dev_hard_addr. 1809*fcf3ce44SJohn Forte hard_addr; 1810*fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++) { 1811*fcf3ce44SJohn Forte dev_ptr-> 1812*fcf3ce44SJohn Forte gfc_port_dev.priv_port.sf_node_wwn[j] = 1813*fcf3ce44SJohn Forte dev_list->dev_nwwn.raw_wwn[j]; 1814*fcf3ce44SJohn Forte dev_ptr-> 1815*fcf3ce44SJohn Forte gfc_port_dev.priv_port.sf_port_wwn[j] = 1816*fcf3ce44SJohn Forte dev_list->dev_pwwn.raw_wwn[j]; 1817*fcf3ce44SJohn Forte } 1818*fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port.sf_inq_dtype = 1819*fcf3ce44SJohn Forte dev_list->dev_dtype; 1820*fcf3ce44SJohn Forte } 1821*fcf3ce44SJohn Forte break; 1822*fcf3ce44SJohn Forte case FC_TOP_PT_PT: 1823*fcf3ce44SJohn Forte (void) free(dlistptr); 1824*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1825*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1826*fcf3ce44SJohn Forte return (L_PT_PT_FC_TOP_NOT_SUPPORTED); 1827*fcf3ce44SJohn Forte default: 1828*fcf3ce44SJohn Forte (void) free(dlistptr); 1829*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1830*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1831*fcf3ce44SJohn Forte return (L_UNEXPECTED_FC_TOPOLOGY); 1832*fcf3ce44SJohn Forte } /* End of switch on port_topology */ 1833*fcf3ce44SJohn Forte (void) free(dlistptr); 1834*fcf3ce44SJohn Forte 1835*fcf3ce44SJohn Forte } else { /* sf and fc4/pci devices */ 1836*fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) 1837*fcf3ce44SJohn Forte return (errno); 1838*fcf3ce44SJohn Forte /* initialize map */ 1839*fcf3ce44SJohn Forte (void) memset(&sf_map, 0, sizeof (struct sf_al_map)); 1840*fcf3ce44SJohn Forte if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) { 1841*fcf3ce44SJohn Forte I_DPRINTF(" SFIOCGMAP ioctl failed.\n"); 1842*fcf3ce44SJohn Forte (void) close(fd); 1843*fcf3ce44SJohn Forte return (L_SFIOCGMAP_IOCTL_FAIL); 1844*fcf3ce44SJohn Forte } 1845*fcf3ce44SJohn Forte /* Check for reasonableness. */ 1846*fcf3ce44SJohn Forte if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) { 1847*fcf3ce44SJohn Forte (void) close(fd); 1848*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 1849*fcf3ce44SJohn Forte } 1850*fcf3ce44SJohn Forte if (sf_map.sf_count == 0) { 1851*fcf3ce44SJohn Forte (void) close(fd); 1852*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 1853*fcf3ce44SJohn Forte } 1854*fcf3ce44SJohn Forte 1855*fcf3ce44SJohn Forte map_ptr->count = sf_map.sf_count; 1856*fcf3ce44SJohn Forte if ((map_ptr->dev_addr = 1857*fcf3ce44SJohn Forte (gfc_port_dev_info_t *)calloc(map_ptr->count, 1858*fcf3ce44SJohn Forte sizeof (gfc_port_dev_info_t))) == NULL) { 1859*fcf3ce44SJohn Forte (void) close(fd); 1860*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1861*fcf3ce44SJohn Forte } 1862*fcf3ce44SJohn Forte dev_ptr = map_ptr->dev_addr; 1863*fcf3ce44SJohn Forte for (i = 0; i < sf_map.sf_count; i++, dev_ptr++) { 1864*fcf3ce44SJohn Forte if (sf_map.sf_addr_pair[i].sf_al_pa > 0xef) { 1865*fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr); 1866*fcf3ce44SJohn Forte map_ptr->dev_addr = NULL; 1867*fcf3ce44SJohn Forte (void) close(fd); 1868*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 1869*fcf3ce44SJohn Forte } 1870*fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top; 1871*fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port = 1872*fcf3ce44SJohn Forte sf_map.sf_addr_pair[i]; 1873*fcf3ce44SJohn Forte } 1874*fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top; 1875*fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.priv_port = 1876*fcf3ce44SJohn Forte sf_map.sf_hba_addr; 1877*fcf3ce44SJohn Forte (void) close(fd); 1878*fcf3ce44SJohn Forte } 1879*fcf3ce44SJohn Forte 1880*fcf3ce44SJohn Forte return (0); 1881*fcf3ce44SJohn Forte } 1882*fcf3ce44SJohn Forte 1883*fcf3ce44SJohn Forte /* 1884*fcf3ce44SJohn Forte * This function consturct FC proerty list using map_dev_fc_prop_list. 1885*fcf3ce44SJohn Forte * 1886*fcf3ce44SJohn Forte * port WWN, node WWN, port addr and hard addr properties is constructed. 1887*fcf3ce44SJohn Forte * 1888*fcf3ce44SJohn Forte * return 0 if OK. 1889*fcf3ce44SJohn Forte * otherwise returns error code. 1890*fcf3ce44SJohn Forte */ 1891*fcf3ce44SJohn Forte static int 1892*fcf3ce44SJohn Forte update_map_dev_fc_prop( 1893*fcf3ce44SJohn Forte impl_map_dev_prop_t **prop_list, uint32_t map_topo, 1894*fcf3ce44SJohn Forte uchar_t *port_wwn, uchar_t *node_wwn, int port_addr, 1895*fcf3ce44SJohn Forte int hard_addr) 1896*fcf3ce44SJohn Forte { 1897*fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_ptr, *pl_start = NULL, *pl_end = NULL; 1898*fcf3ce44SJohn Forte uchar_t *port_wwn_data, *node_wwn_data; 1899*fcf3ce44SJohn Forte int *port_addr_data, *hard_addr_data; 1900*fcf3ce44SJohn Forte 1901*fcf3ce44SJohn Forte /* consrtruct port addr property. */ 1902*fcf3ce44SJohn Forte if ((map_topo == FC_TOP_FABRIC) || 1903*fcf3ce44SJohn Forte (map_topo == FC_TOP_PUBLIC_LOOP)) { 1904*fcf3ce44SJohn Forte if (port_addr <= 0xffff) { 1905*fcf3ce44SJohn Forte return (L_INVALID_FABRIC_ADDRESS); 1906*fcf3ce44SJohn Forte } 1907*fcf3ce44SJohn Forte } else if (map_topo == FC_TOP_PRIVATE_LOOP) { 1908*fcf3ce44SJohn Forte if (port_addr > 0xff) { 1909*fcf3ce44SJohn Forte return (L_INVALID_PRIVATE_LOOP_ADDRESS); 1910*fcf3ce44SJohn Forte } 1911*fcf3ce44SJohn Forte } 1912*fcf3ce44SJohn Forte 1913*fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc( 1914*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_prop_t))) == NULL) { 1915*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1916*fcf3ce44SJohn Forte } 1917*fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, PORT_ADDR_PROP, 1918*fcf3ce44SJohn Forte strlen(PORT_ADDR_PROP)); 1919*fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_INT; 1920*fcf3ce44SJohn Forte 1921*fcf3ce44SJohn Forte if ((port_addr_data = (int *)calloc(1, sizeof (int))) == NULL) { 1922*fcf3ce44SJohn Forte free(prop_ptr); 1923*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1924*fcf3ce44SJohn Forte } 1925*fcf3ce44SJohn Forte *port_addr_data = port_addr; 1926*fcf3ce44SJohn Forte prop_ptr->prop_data = port_addr_data; 1927*fcf3ce44SJohn Forte 1928*fcf3ce44SJohn Forte pl_start = pl_end = prop_ptr; 1929*fcf3ce44SJohn Forte 1930*fcf3ce44SJohn Forte /* consrtruct port WWN property. */ 1931*fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc( 1932*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_prop_t))) == NULL) { 1933*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1934*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1935*fcf3ce44SJohn Forte } 1936*fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, PORT_WWN_PROP, 1937*fcf3ce44SJohn Forte strlen(PORT_WWN_PROP)); 1938*fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES; 1939*fcf3ce44SJohn Forte 1940*fcf3ce44SJohn Forte if ((port_wwn_data = (uchar_t *)calloc( 1941*fcf3ce44SJohn Forte 1, FC_WWN_SIZE)) == NULL) { 1942*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1943*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1944*fcf3ce44SJohn Forte } 1945*fcf3ce44SJohn Forte memcpy(port_wwn_data, port_wwn, FC_WWN_SIZE); 1946*fcf3ce44SJohn Forte prop_ptr->prop_data = port_wwn_data; 1947*fcf3ce44SJohn Forte prop_ptr->prop_size = FC_WWN_SIZE; 1948*fcf3ce44SJohn Forte pl_end->next = prop_ptr; 1949*fcf3ce44SJohn Forte pl_end = prop_ptr; 1950*fcf3ce44SJohn Forte 1951*fcf3ce44SJohn Forte /* consrtruct node WWN property. */ 1952*fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc( 1953*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_prop_t))) == NULL) { 1954*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1955*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1956*fcf3ce44SJohn Forte } 1957*fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, NODE_WWN_PROP, 1958*fcf3ce44SJohn Forte strlen(NODE_WWN_PROP)); 1959*fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES; 1960*fcf3ce44SJohn Forte 1961*fcf3ce44SJohn Forte if ((node_wwn_data = (uchar_t *)calloc( 1962*fcf3ce44SJohn Forte 1, FC_WWN_SIZE)) == NULL) { 1963*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1964*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1965*fcf3ce44SJohn Forte } 1966*fcf3ce44SJohn Forte memcpy(node_wwn_data, node_wwn, FC_WWN_SIZE); 1967*fcf3ce44SJohn Forte prop_ptr->prop_data = node_wwn_data; 1968*fcf3ce44SJohn Forte prop_ptr->prop_size = FC_WWN_SIZE; 1969*fcf3ce44SJohn Forte pl_end->next = prop_ptr; 1970*fcf3ce44SJohn Forte pl_end = prop_ptr; 1971*fcf3ce44SJohn Forte 1972*fcf3ce44SJohn Forte /* consrtruct hard addr property. */ 1973*fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc( 1974*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_prop_t))) == NULL) { 1975*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1976*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1977*fcf3ce44SJohn Forte } 1978*fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, HARD_ADDR_PROP, 1979*fcf3ce44SJohn Forte strlen(HARD_ADDR_PROP)); 1980*fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_INT; 1981*fcf3ce44SJohn Forte 1982*fcf3ce44SJohn Forte if ((hard_addr_data = (int *)calloc( 1983*fcf3ce44SJohn Forte 1, sizeof (int))) == NULL) { 1984*fcf3ce44SJohn Forte free_prop_list(&pl_start); 1985*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 1986*fcf3ce44SJohn Forte } 1987*fcf3ce44SJohn Forte *hard_addr_data = hard_addr; 1988*fcf3ce44SJohn Forte prop_ptr->prop_data = hard_addr_data; 1989*fcf3ce44SJohn Forte pl_end->next = prop_ptr; 1990*fcf3ce44SJohn Forte pl_end = prop_ptr; 1991*fcf3ce44SJohn Forte 1992*fcf3ce44SJohn Forte if (*prop_list == NULL) { 1993*fcf3ce44SJohn Forte *prop_list = pl_start; 1994*fcf3ce44SJohn Forte } else { 1995*fcf3ce44SJohn Forte pl_end->next = (*prop_list)->next; 1996*fcf3ce44SJohn Forte *prop_list = pl_start; 1997*fcf3ce44SJohn Forte } 1998*fcf3ce44SJohn Forte 1999*fcf3ce44SJohn Forte return (0); 2000*fcf3ce44SJohn Forte } 2001*fcf3ce44SJohn Forte 2002*fcf3ce44SJohn Forte /* 2003*fcf3ce44SJohn Forte * This function consturct FCP inq dtype propery. 2004*fcf3ce44SJohn Forte * if inq_dtype is null the property is constrcted with err info. 2005*fcf3ce44SJohn Forte * 2006*fcf3ce44SJohn Forte * L_MALLOC_FAILED is the only possible error. 2007*fcf3ce44SJohn Forte */ 2008*fcf3ce44SJohn Forte static int 2009*fcf3ce44SJohn Forte update_map_dev_FCP_prop( 2010*fcf3ce44SJohn Forte impl_map_dev_prop_t **prop_list, 2011*fcf3ce44SJohn Forte uchar_t *inq_dtype, int err, int exist) 2012*fcf3ce44SJohn Forte { 2013*fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_ptr, *old_prop_ptr; 2014*fcf3ce44SJohn Forte uchar_t *inq_dtype_data; 2015*fcf3ce44SJohn Forte 2016*fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc( 2017*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_prop_t))) == NULL) { 2018*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 2019*fcf3ce44SJohn Forte } 2020*fcf3ce44SJohn Forte 2021*fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, INQ_DTYPE_PROP, 2022*fcf3ce44SJohn Forte strlen(INQ_DTYPE_PROP)); 2023*fcf3ce44SJohn Forte 2024*fcf3ce44SJohn Forte if (inq_dtype == NULL) { 2025*fcf3ce44SJohn Forte prop_ptr->prop_data = NULL; 2026*fcf3ce44SJohn Forte prop_ptr->prop_error = err; 2027*fcf3ce44SJohn Forte } else { 2028*fcf3ce44SJohn Forte if ((inq_dtype_data = (uchar_t *)calloc( 2029*fcf3ce44SJohn Forte 1, sizeof (uchar_t))) == NULL) { 2030*fcf3ce44SJohn Forte free(prop_ptr); 2031*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 2032*fcf3ce44SJohn Forte } 2033*fcf3ce44SJohn Forte memcpy(inq_dtype_data, inq_dtype, sizeof (uchar_t)); 2034*fcf3ce44SJohn Forte prop_ptr->prop_data = inq_dtype_data; 2035*fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES; 2036*fcf3ce44SJohn Forte prop_ptr->prop_size = sizeof (uchar_t); 2037*fcf3ce44SJohn Forte } 2038*fcf3ce44SJohn Forte 2039*fcf3ce44SJohn Forte if (*prop_list == NULL) { 2040*fcf3ce44SJohn Forte *prop_list = prop_ptr; 2041*fcf3ce44SJohn Forte } else { 2042*fcf3ce44SJohn Forte if (exist == PROP_EXIST) { 2043*fcf3ce44SJohn Forte prop_ptr->next = (*prop_list)->next; 2044*fcf3ce44SJohn Forte old_prop_ptr = *prop_list; 2045*fcf3ce44SJohn Forte *prop_list = prop_ptr; 2046*fcf3ce44SJohn Forte free((uchar_t *)(old_prop_ptr->prop_data)); 2047*fcf3ce44SJohn Forte old_prop_ptr->prop_data = NULL; 2048*fcf3ce44SJohn Forte S_FREE(old_prop_ptr); 2049*fcf3ce44SJohn Forte } else { 2050*fcf3ce44SJohn Forte prop_ptr->next = *prop_list; 2051*fcf3ce44SJohn Forte *prop_list = prop_ptr; 2052*fcf3ce44SJohn Forte } 2053*fcf3ce44SJohn Forte } 2054*fcf3ce44SJohn Forte 2055*fcf3ce44SJohn Forte return (0); 2056*fcf3ce44SJohn Forte } 2057*fcf3ce44SJohn Forte 2058*fcf3ce44SJohn Forte /* 2059*fcf3ce44SJohn Forte * This function calls FCP_TGT_INQUIRY via g_issue_fcp_ioctl() 2060*fcf3ce44SJohn Forte * to get the inq_dtype of input device and calls update_map_dev_FCP_prop(). 2061*fcf3ce44SJohn Forte * inq_dtype is set to NULL and pass error code if inq_dtype data is not 2062*fcf3ce44SJohn Forte * requried. 2063*fcf3ce44SJohn Forte * 2064*fcf3ce44SJohn Forte * return error from update_map_dev_FCP_prop(). 2065*fcf3ce44SJohn Forte */ 2066*fcf3ce44SJohn Forte static int 2067*fcf3ce44SJohn Forte handle_map_dev_FCP_prop( 2068*fcf3ce44SJohn Forte minor_t fp_xport_minor, 2069*fcf3ce44SJohn Forte la_wwn_t port_wwn, 2070*fcf3ce44SJohn Forte impl_map_dev_prop_t **prop_list) 2071*fcf3ce44SJohn Forte { 2072*fcf3ce44SJohn Forte struct device_data inq_data; 2073*fcf3ce44SJohn Forte int fcp_fd, err; 2074*fcf3ce44SJohn Forte struct fcp_ioctl fcp_data; 2075*fcf3ce44SJohn Forte uchar_t inq_dtype; 2076*fcf3ce44SJohn Forte 2077*fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) { 2078*fcf3ce44SJohn Forte update_map_dev_FCP_prop(prop_list, NULL, 2079*fcf3ce44SJohn Forte L_OPEN_PATH_FAIL, PROP_NOEXIST); 2080*fcf3ce44SJohn Forte } 2081*fcf3ce44SJohn Forte 2082*fcf3ce44SJohn Forte /* Get the minor number for an fp instance */ 2083*fcf3ce44SJohn Forte fcp_data.fp_minor = fp_xport_minor; 2084*fcf3ce44SJohn Forte 2085*fcf3ce44SJohn Forte /* Get FCP prop for the hba first. */ 2086*fcf3ce44SJohn Forte fcp_data.listlen = 1; 2087*fcf3ce44SJohn Forte inq_data.dev_pwwn = port_wwn; 2088*fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data; 2089*fcf3ce44SJohn Forte 2090*fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) { 2091*fcf3ce44SJohn Forte /* if ioctl error then set the prop_error. */ 2092*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop( 2093*fcf3ce44SJohn Forte prop_list, NULL, err, PROP_NOEXIST)) != 0) { 2094*fcf3ce44SJohn Forte return (err); 2095*fcf3ce44SJohn Forte } 2096*fcf3ce44SJohn Forte } else { 2097*fcf3ce44SJohn Forte inq_dtype = inq_data.dev0_type; 2098*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop( 2099*fcf3ce44SJohn Forte prop_list, &inq_dtype, 0, PROP_NOEXIST)) != 0) { 2100*fcf3ce44SJohn Forte return (err); 2101*fcf3ce44SJohn Forte } 2102*fcf3ce44SJohn Forte } 2103*fcf3ce44SJohn Forte 2104*fcf3ce44SJohn Forte return (0); 2105*fcf3ce44SJohn Forte } 2106*fcf3ce44SJohn Forte 2107*fcf3ce44SJohn Forte /* 2108*fcf3ce44SJohn Forte * Construct device map tree from nexus driver 2109*fcf3ce44SJohn Forte * 2110*fcf3ce44SJohn Forte * PARAMS: 2111*fcf3ce44SJohn Forte * path - must be the physical path to a device 2112*fcf3ce44SJohn Forte * l_err - ptr to an error code. Set when NULL is returned. 2113*fcf3ce44SJohn Forte * flag - device map fomat and property type. 2114*fcf3ce44SJohn Forte * 2115*fcf3ce44SJohn Forte * LOGIC: 2116*fcf3ce44SJohn Forte * 1. check the validity of path via g_get_path_type. 2117*fcf3ce44SJohn Forte * 2. If FC path, get the topology of the path via 2118*fcf3ce44SJohn Forte * g_get_fca_port_topology. 2119*fcf3ce44SJohn Forte * 2120*fcf3ce44SJohn Forte * 3. If FC type(Leadville statck) 2121*fcf3ce44SJohn Forte * FCIO_GET_DEV_LIST to get the device node list of fc_port_dev_t. 2122*fcf3ce44SJohn Forte * FCIO_GET_HOST_PARAMS to get the fca port node of fc_port_dev_t. 2123*fcf3ce44SJohn Forte * 2124*fcf3ce44SJohn Forte * root of tree is set with host_params info 2125*fcf3ce44SJohn Forte * FC propery is set. 2126*fcf3ce44SJohn Forte * FCP property is set if reqyested through flag. 2127*fcf3ce44SJohn Forte * Issue g_issue_fcp_ioctl to get FCP inquiry data 2128*fcf3ce44SJohn Forte * consruruct list of children via dev_list. 2129*fcf3ce44SJohn Forte * FC property is set. 2130*fcf3ce44SJohn Forte * FCP property is set if reqyested through flag. 2131*fcf3ce44SJohn Forte * Issue FCIO_DEV_LOGIN if it is fabric device. 2132*fcf3ce44SJohn Forte * Issue g_issue_fcp_ioctl to get FCP inquiry data. 2133*fcf3ce44SJohn Forte * 2134*fcf3ce44SJohn Forte * else FC4 type(socal/sf or ifp stack) 2135*fcf3ce44SJohn Forte * SFIOCGMAP ioctl to get the device and hba nodes of 2136*fcf3ce44SJohn Forte * sf_addr_pair_t. 2137*fcf3ce44SJohn Forte * FCIO_GETMAP ioctl to get hba port info. 2138*fcf3ce44SJohn Forte * consturct map and child tree list and 2139*fcf3ce44SJohn Forte * set the properties as private loop devices. 2140*fcf3ce44SJohn Forte * 2141*fcf3ce44SJohn Forte * RETURNS: 2142*fcf3ce44SJohn Forte * ptr to map is returned if OK. 2143*fcf3ce44SJohn Forte * NULL and l_err is set otherwise. 2144*fcf3ce44SJohn Forte */ 2145*fcf3ce44SJohn Forte gfc_dev_t 2146*fcf3ce44SJohn Forte g_dev_map_init(char *path, int *l_err, int flag) 2147*fcf3ce44SJohn Forte { 2148*fcf3ce44SJohn Forte int fd, i, num_devices = 0, err, pathcnt = 1, new_count = 0; 2149*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN]; 2150*fcf3ce44SJohn Forte char *char_ptr, *nexus_path; 2151*fcf3ce44SJohn Forte struct stat stbuf; 2152*fcf3ce44SJohn Forte fc_port_dev_t *dev_list = NULL, *dlist; 2153*fcf3ce44SJohn Forte uint32_t hba_port_top, state; 2154*fcf3ce44SJohn Forte uint_t path_type; 2155*fcf3ce44SJohn Forte sf_al_map_t sf_map; 2156*fcf3ce44SJohn Forte fc_port_dev_t fp_hba_port; 2157*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 2158*fcf3ce44SJohn Forte int p_on = 0, p_st = 0, hba_alpa_found = 0, nexus_fd; 2159*fcf3ce44SJohn Forte fcio_t fcio; 2160*fcf3ce44SJohn Forte struct lilpmap limited_map; 2161*fcf3ce44SJohn Forte impl_map_dev_t *impl_map, *impl_dev, *mdl_start = NULL, *mdl_end = NULL; 2162*fcf3ce44SJohn Forte struct stat sbuf; 2163*fcf3ce44SJohn Forte 2164*fcf3ce44SJohn Forte if (l_err == NULL) { 2165*fcf3ce44SJohn Forte return (NULL); 2166*fcf3ce44SJohn Forte } 2167*fcf3ce44SJohn Forte 2168*fcf3ce44SJohn Forte if (path == NULL) { 2169*fcf3ce44SJohn Forte *l_err = L_INVALID_PATH; 2170*fcf3ce44SJohn Forte return (NULL); 2171*fcf3ce44SJohn Forte } 2172*fcf3ce44SJohn Forte 2173*fcf3ce44SJohn Forte *l_err = 0; 2174*fcf3ce44SJohn Forte 2175*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 2176*fcf3ce44SJohn Forte /* 2177*fcf3ce44SJohn Forte * Get the path to the :devctl driver 2178*fcf3ce44SJohn Forte * 2179*fcf3ce44SJohn Forte * This assumes the path looks something like this: 2180*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 2181*fcf3ce44SJohn Forte * or 2182*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0 2183*fcf3ce44SJohn Forte * or 2184*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 2185*fcf3ce44SJohn Forte * or 2186*fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl 2187*fcf3ce44SJohn Forte */ 2188*fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) { 2189*fcf3ce44SJohn Forte (void) strcpy(drvr_path0, path); 2190*fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path0, &pathlist)) { 2191*fcf3ce44SJohn Forte *l_err = L_INVALID_PATH; 2192*fcf3ce44SJohn Forte return (NULL); 2193*fcf3ce44SJohn Forte } 2194*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 2195*fcf3ce44SJohn Forte p_on = p_st = 0; 2196*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 2197*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 2198*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 2199*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 2200*fcf3ce44SJohn Forte p_on = i; 2201*fcf3ce44SJohn Forte break; 2202*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 2203*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 2204*fcf3ce44SJohn Forte p_st = i; 2205*fcf3ce44SJohn Forte } 2206*fcf3ce44SJohn Forte } 2207*fcf3ce44SJohn Forte } 2208*fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state == 2209*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 2210*fcf3ce44SJohn Forte /* on_line path */ 2211*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 2212*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 2213*fcf3ce44SJohn Forte } else { 2214*fcf3ce44SJohn Forte /* standby or path0 */ 2215*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 2216*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 2217*fcf3ce44SJohn Forte } 2218*fcf3ce44SJohn Forte free(pathlist.path_info); 2219*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 2220*fcf3ce44SJohn Forte } else { 2221*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 2222*fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) || 2223*fcf3ce44SJohn Forte strstr(drvr_path, SES_NAME) || 2224*fcf3ce44SJohn Forte strstr(drvr_path, DRV_NAME_ST)) { 2225*fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) { 2226*fcf3ce44SJohn Forte *l_err = L_INVALID_PATH; 2227*fcf3ce44SJohn Forte return (NULL); 2228*fcf3ce44SJohn Forte } 2229*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */ 2230*fcf3ce44SJohn Forte /* append controller */ 2231*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 2232*fcf3ce44SJohn Forte } else { 2233*fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) { 2234*fcf3ce44SJohn Forte *l_err = L_LSTAT_ERROR; 2235*fcf3ce44SJohn Forte return (NULL); 2236*fcf3ce44SJohn Forte } 2237*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 2238*fcf3ce44SJohn Forte /* append controller */ 2239*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 2240*fcf3ce44SJohn Forte } 2241*fcf3ce44SJohn Forte } 2242*fcf3ce44SJohn Forte } 2243*fcf3ce44SJohn Forte 2244*fcf3ce44SJohn Forte P_DPRINTF(" g_dev_map_init: Geting drive map from:" 2245*fcf3ce44SJohn Forte " %s\n", drvr_path); 2246*fcf3ce44SJohn Forte 2247*fcf3ce44SJohn Forte path_type = g_get_path_type(drvr_path); 2248*fcf3ce44SJohn Forte if ((path_type == 0) || !(path_type & XPORT_MASK)) { 2249*fcf3ce44SJohn Forte *l_err = L_INVALID_PATH_TYPE; 2250*fcf3ce44SJohn Forte return (NULL); 2251*fcf3ce44SJohn Forte } 2252*fcf3ce44SJohn Forte 2253*fcf3ce44SJohn Forte /* get fiber topology */ 2254*fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(drvr_path, 2255*fcf3ce44SJohn Forte &hba_port_top, 0)) != 0) { 2256*fcf3ce44SJohn Forte *l_err = err; 2257*fcf3ce44SJohn Forte return (NULL); 2258*fcf3ce44SJohn Forte } 2259*fcf3ce44SJohn Forte 2260*fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) { 2261*fcf3ce44SJohn Forte *l_err = errno; 2262*fcf3ce44SJohn Forte return (NULL); 2263*fcf3ce44SJohn Forte } 2264*fcf3ce44SJohn Forte 2265*fcf3ce44SJohn Forte /* for FC devices. */ 2266*fcf3ce44SJohn Forte if (path_type & FC_FCA_MASK) { 2267*fcf3ce44SJohn Forte /* get the number of device first. */ 2268*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_NUM_DEVS; 2269*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (num_devices); 2270*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 2271*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&num_devices; 2272*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) { 2273*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n"); 2274*fcf3ce44SJohn Forte (void) close(fd); 2275*fcf3ce44SJohn Forte *l_err = L_FCIO_GET_NUM_DEVS_FAIL; 2276*fcf3ce44SJohn Forte return (NULL); 2277*fcf3ce44SJohn Forte } 2278*fcf3ce44SJohn Forte if (num_devices != 0) { 2279*fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)calloc(num_devices, 2280*fcf3ce44SJohn Forte sizeof (fc_port_dev_t))) == NULL) { 2281*fcf3ce44SJohn Forte (void) close(fd); 2282*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2283*fcf3ce44SJohn Forte return (NULL); 2284*fcf3ce44SJohn Forte } 2285*fcf3ce44SJohn Forte 2286*fcf3ce44SJohn Forte bzero((caddr_t)&fcio, sizeof (fcio)); 2287*fcf3ce44SJohn Forte /* Get the device list */ 2288*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST; 2289*fcf3ce44SJohn Forte /* Information read operation */ 2290*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 2291*fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t); 2292*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)dev_list; 2293*fcf3ce44SJohn Forte /* new device count */ 2294*fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count); 2295*fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count; 2296*fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) { 2297*fcf3ce44SJohn Forte if (err == L_INVALID_DEVICE_COUNT) { 2298*fcf3ce44SJohn Forte /* 2299*fcf3ce44SJohn Forte * original buffer was small so allocate buffer 2300*fcf3ce44SJohn Forte * with a new count and retry. 2301*fcf3ce44SJohn Forte */ 2302*fcf3ce44SJohn Forte free(dev_list); 2303*fcf3ce44SJohn Forte num_devices = new_count; 2304*fcf3ce44SJohn Forte new_count = 0; 2305*fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)calloc(num_devices, 2306*fcf3ce44SJohn Forte sizeof (fc_port_dev_t))) == NULL) { 2307*fcf3ce44SJohn Forte (void) close(fd); 2308*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2309*fcf3ce44SJohn Forte return (NULL); 2310*fcf3ce44SJohn Forte } 2311*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST; 2312*fcf3ce44SJohn Forte /* Information read operation */ 2313*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 2314*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)dev_list; 2315*fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t); 2316*fcf3ce44SJohn Forte /* new device count */ 2317*fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count); 2318*fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count; 2319*fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) { 2320*fcf3ce44SJohn Forte if (err == L_INVALID_DEVICE_COUNT) { 2321*fcf3ce44SJohn Forte /* 2322*fcf3ce44SJohn Forte * No more retry. There may be severe hardware 2323*fcf3ce44SJohn Forte * problem so return error here. 2324*fcf3ce44SJohn Forte */ 2325*fcf3ce44SJohn Forte I_DPRINTF(" Device count was %d" 2326*fcf3ce44SJohn Forte " should have been %d\n", 2327*fcf3ce44SJohn Forte num_devices, new_count); 2328*fcf3ce44SJohn Forte free(dev_list); 2329*fcf3ce44SJohn Forte (void) close(fd); 2330*fcf3ce44SJohn Forte *l_err = L_INVALID_DEVICE_COUNT; 2331*fcf3ce44SJohn Forte return (NULL); 2332*fcf3ce44SJohn Forte } else { 2333*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed."); 2334*fcf3ce44SJohn Forte free(dev_list); 2335*fcf3ce44SJohn Forte (void) close(fd); 2336*fcf3ce44SJohn Forte *l_err = L_FCIO_GET_DEV_LIST_FAIL; 2337*fcf3ce44SJohn Forte return (NULL); 2338*fcf3ce44SJohn Forte } 2339*fcf3ce44SJohn Forte } 2340*fcf3ce44SJohn Forte } 2341*fcf3ce44SJohn Forte } 2342*fcf3ce44SJohn Forte } 2343*fcf3ce44SJohn Forte 2344*fcf3ce44SJohn Forte /* 2345*fcf3ce44SJohn Forte * if new count is smaller than the original number from 2346*fcf3ce44SJohn Forte * FCIO_GET_NUM_DEVS, adjust new count and buffer size 2347*fcf3ce44SJohn Forte * and continue. 2348*fcf3ce44SJohn Forte */ 2349*fcf3ce44SJohn Forte if (new_count < num_devices) { 2350*fcf3ce44SJohn Forte num_devices = new_count; 2351*fcf3ce44SJohn Forte if (new_count > 0) { 2352*fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)realloc(dev_list, 2353*fcf3ce44SJohn Forte (new_count * sizeof (fc_port_dev_t)))) 2354*fcf3ce44SJohn Forte == NULL) { 2355*fcf3ce44SJohn Forte S_FREE(dev_list); 2356*fcf3ce44SJohn Forte (void) close(fd); 2357*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2358*fcf3ce44SJohn Forte return (NULL); 2359*fcf3ce44SJohn Forte } 2360*fcf3ce44SJohn Forte } 2361*fcf3ce44SJohn Forte } 2362*fcf3ce44SJohn Forte 2363*fcf3ce44SJohn Forte /* get the host param info */ 2364*fcf3ce44SJohn Forte (void) memset(&fp_hba_port, 0, sizeof (struct fc_port_dev)); 2365*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_HOST_PARAMS; 2366*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 2367*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&fp_hba_port; 2368*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (fc_port_dev_t); 2369*fcf3ce44SJohn Forte 2370*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) { 2371*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n"); 2372*fcf3ce44SJohn Forte (void) close(fd); 2373*fcf3ce44SJohn Forte if (num_devices == 0) { 2374*fcf3ce44SJohn Forte *l_err = L_NO_DEVICES_FOUND; 2375*fcf3ce44SJohn Forte } else { 2376*fcf3ce44SJohn Forte free(dev_list); 2377*fcf3ce44SJohn Forte *l_err = L_FCIO_GET_HOST_PARAMS_FAIL; 2378*fcf3ce44SJohn Forte } 2379*fcf3ce44SJohn Forte (void) close(fd); 2380*fcf3ce44SJohn Forte return (NULL); 2381*fcf3ce44SJohn Forte } 2382*fcf3ce44SJohn Forte 2383*fcf3ce44SJohn Forte /* If we want the lilp map then we need to do a little */ 2384*fcf3ce44SJohn Forte /* work here. The lilp map contains the local hba in */ 2385*fcf3ce44SJohn Forte /* the dev_addr. Once this has been added qsort the */ 2386*fcf3ce44SJohn Forte /* dev_addr array so it's in physical order. */ 2387*fcf3ce44SJohn Forte if ((flag & MAP_FORMAT_LILP) == MAP_FORMAT_LILP) { 2388*fcf3ce44SJohn Forte /* First we need to allocate one additional */ 2389*fcf3ce44SJohn Forte /* device to the dev_addr structure, for the */ 2390*fcf3ce44SJohn Forte /* local hba */ 2391*fcf3ce44SJohn Forte if (num_devices > 0) { 2392*fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)realloc(dev_list, 2393*fcf3ce44SJohn Forte (++num_devices * sizeof (fc_port_dev_t)))) == NULL) { 2394*fcf3ce44SJohn Forte (void) close(fd); 2395*fcf3ce44SJohn Forte /* in case dev_list is not null free it. */ 2396*fcf3ce44SJohn Forte S_FREE(dev_list); 2397*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2398*fcf3ce44SJohn Forte return (NULL); 2399*fcf3ce44SJohn Forte } 2400*fcf3ce44SJohn Forte 2401*fcf3ce44SJohn Forte /* Next, copy the local hba into this new loc. */ 2402*fcf3ce44SJohn Forte if (memcpy(dev_list+(num_devices-1), &fp_hba_port, 2403*fcf3ce44SJohn Forte sizeof (fc_port_dev_t)) == NULL) { 2404*fcf3ce44SJohn Forte (void) free(dev_list); 2405*fcf3ce44SJohn Forte (void) close(fd); 2406*fcf3ce44SJohn Forte *l_err = L_MEMCPY_FAILED; 2407*fcf3ce44SJohn Forte return (NULL); 2408*fcf3ce44SJohn Forte } 2409*fcf3ce44SJohn Forte 2410*fcf3ce44SJohn Forte /* Now sort by physical location */ 2411*fcf3ce44SJohn Forte qsort((void*)dev_list, num_devices, 2412*fcf3ce44SJohn Forte sizeof (fc_port_dev_t), lilp_map_cmp); 2413*fcf3ce44SJohn Forte } 2414*fcf3ce44SJohn Forte } 2415*fcf3ce44SJohn Forte 2416*fcf3ce44SJohn Forte 2417*fcf3ce44SJohn Forte /* We have dev list info and host param info. */ 2418*fcf3ce44SJohn Forte /* Now constructs map tree with these info. */ 2419*fcf3ce44SJohn Forte /* First consturct the root of the map tree */ 2420*fcf3ce44SJohn Forte /* with host param. */ 2421*fcf3ce44SJohn Forte if ((impl_map = (impl_map_dev_t *)calloc( 2422*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_t))) == NULL) { 2423*fcf3ce44SJohn Forte (void) free(dev_list); 2424*fcf3ce44SJohn Forte (void) close(fd); 2425*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2426*fcf3ce44SJohn Forte return (NULL); 2427*fcf3ce44SJohn Forte } 2428*fcf3ce44SJohn Forte impl_map->flag = flag; 2429*fcf3ce44SJohn Forte impl_map->topo = hba_port_top; 2430*fcf3ce44SJohn Forte 2431*fcf3ce44SJohn Forte /* consturct hba property list. */ 2432*fcf3ce44SJohn Forte if ((err = update_map_dev_fc_prop(&impl_map->prop_list, 2433*fcf3ce44SJohn Forte hba_port_top, fp_hba_port.dev_pwwn.raw_wwn, 2434*fcf3ce44SJohn Forte fp_hba_port.dev_nwwn.raw_wwn, fp_hba_port.dev_did.port_id, 2435*fcf3ce44SJohn Forte fp_hba_port.dev_hard_addr.hard_addr)) != 0) { 2436*fcf3ce44SJohn Forte (void) free(dev_list); 2437*fcf3ce44SJohn Forte (void) close(fd); 2438*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2439*fcf3ce44SJohn Forte *l_err = err; 2440*fcf3ce44SJohn Forte return (NULL); 2441*fcf3ce44SJohn Forte } 2442*fcf3ce44SJohn Forte 2443*fcf3ce44SJohn Forte if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) { 2444*fcf3ce44SJohn Forte if (fstat(fd, &sbuf) == -1) { 2445*fcf3ce44SJohn Forte (void) free(dev_list); 2446*fcf3ce44SJohn Forte (void) close(fd); 2447*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2448*fcf3ce44SJohn Forte *l_err = L_FSTAT_ERROR; 2449*fcf3ce44SJohn Forte return (NULL); 2450*fcf3ce44SJohn Forte } 2451*fcf3ce44SJohn Forte if ((err = handle_map_dev_FCP_prop(minor(sbuf.st_rdev), 2452*fcf3ce44SJohn Forte fp_hba_port.dev_pwwn, &impl_map->prop_list)) != 0) { 2453*fcf3ce44SJohn Forte (void) free(dev_list); 2454*fcf3ce44SJohn Forte (void) close(fd); 2455*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2456*fcf3ce44SJohn Forte *l_err = err; 2457*fcf3ce44SJohn Forte return (NULL); 2458*fcf3ce44SJohn Forte } 2459*fcf3ce44SJohn Forte } 2460*fcf3ce44SJohn Forte 2461*fcf3ce44SJohn Forte /* consturct child for each device and */ 2462*fcf3ce44SJohn Forte /* set device property list. */ 2463*fcf3ce44SJohn Forte dlist = dev_list; 2464*fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dlist++) { 2465*fcf3ce44SJohn Forte if ((impl_dev = (impl_map_dev_t *)calloc( 2466*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_t))) == NULL) { 2467*fcf3ce44SJohn Forte (void) free(dev_list); 2468*fcf3ce44SJohn Forte (void) close(fd); 2469*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2470*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2471*fcf3ce44SJohn Forte return (NULL); 2472*fcf3ce44SJohn Forte } 2473*fcf3ce44SJohn Forte /* set the map as parent */ 2474*fcf3ce44SJohn Forte impl_dev->parent = impl_map; 2475*fcf3ce44SJohn Forte if ((err = update_map_dev_fc_prop(&impl_dev->prop_list, 2476*fcf3ce44SJohn Forte hba_port_top, dlist->dev_pwwn.raw_wwn, 2477*fcf3ce44SJohn Forte dlist->dev_nwwn.raw_wwn, dlist->dev_did.port_id, 2478*fcf3ce44SJohn Forte dlist->dev_hard_addr.hard_addr)) != 0) { 2479*fcf3ce44SJohn Forte (void) free(dev_list); 2480*fcf3ce44SJohn Forte (void) close(fd); 2481*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2482*fcf3ce44SJohn Forte *l_err = err; 2483*fcf3ce44SJohn Forte return (NULL); 2484*fcf3ce44SJohn Forte } 2485*fcf3ce44SJohn Forte if (i == 0) { 2486*fcf3ce44SJohn Forte mdl_start = mdl_end = impl_dev; 2487*fcf3ce44SJohn Forte } else { 2488*fcf3ce44SJohn Forte mdl_end->next = impl_dev; 2489*fcf3ce44SJohn Forte mdl_end = impl_dev; 2490*fcf3ce44SJohn Forte } 2491*fcf3ce44SJohn Forte if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) { 2492*fcf3ce44SJohn Forte if (((hba_port_top == FC_TOP_PUBLIC_LOOP) || 2493*fcf3ce44SJohn Forte (hba_port_top == FC_TOP_FABRIC)) && 2494*fcf3ce44SJohn Forte (memcmp(fp_hba_port.dev_pwwn.raw_wwn, 2495*fcf3ce44SJohn Forte dlist->dev_pwwn.raw_wwn, FC_WWN_SIZE) != 0)) { 2496*fcf3ce44SJohn Forte (void) memset(&fcio, 0, sizeof (fcio_t)); 2497*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_STATE; 2498*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (dlist->dev_pwwn); 2499*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&dlist->dev_pwwn; 2500*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ | FCIO_XFER_WRITE; 2501*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t); 2502*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&state; 2503*fcf3ce44SJohn Forte fcio.fcio_alen = 0; 2504*fcf3ce44SJohn Forte fcio.fcio_abuf = NULL; 2505*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) { 2506*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_STATE ioctl failed.\n"); 2507*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop( 2508*fcf3ce44SJohn Forte &impl_dev->prop_list, NULL, 2509*fcf3ce44SJohn Forte L_FCIO_GET_STATE_FAIL, PROP_NOEXIST)) != 0) { 2510*fcf3ce44SJohn Forte (void) free(dev_list); 2511*fcf3ce44SJohn Forte (void) close(fd); 2512*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2513*fcf3ce44SJohn Forte *l_err = err; 2514*fcf3ce44SJohn Forte return (NULL); 2515*fcf3ce44SJohn Forte } 2516*fcf3ce44SJohn Forte } 2517*fcf3ce44SJohn Forte if (state != PORT_DEVICE_LOGGED_IN) { 2518*fcf3ce44SJohn Forte (void) close(fd); 2519*fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, 2520*fcf3ce44SJohn Forte O_NDELAY | O_RDONLY | O_EXCL)) == -1) { 2521*fcf3ce44SJohn Forte (void) free(dev_list); 2522*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2523*fcf3ce44SJohn Forte *l_err = L_OPEN_PATH_FAIL; 2524*fcf3ce44SJohn Forte return (NULL); 2525*fcf3ce44SJohn Forte } 2526*fcf3ce44SJohn Forte (void) memset(&fcio, 0, sizeof (fcio_t)); 2527*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_DEV_LOGIN; 2528*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (dlist->dev_pwwn); 2529*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&dlist->dev_pwwn; 2530*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 2531*fcf3ce44SJohn Forte fcio.fcio_olen = fcio.fcio_alen = 0; 2532*fcf3ce44SJohn Forte fcio.fcio_obuf = fcio.fcio_abuf = NULL; 2533*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) { 2534*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_DEV_LOGIN ioctl failed.\n"); 2535*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop( 2536*fcf3ce44SJohn Forte &impl_dev->prop_list, NULL, 2537*fcf3ce44SJohn Forte L_FCIO_DEV_LOGIN_FAIL, 2538*fcf3ce44SJohn Forte PROP_NOEXIST)) != 0) { 2539*fcf3ce44SJohn Forte (void) free(dev_list); 2540*fcf3ce44SJohn Forte (void) close(fd); 2541*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2542*fcf3ce44SJohn Forte *l_err = err; 2543*fcf3ce44SJohn Forte return (NULL); 2544*fcf3ce44SJohn Forte } 2545*fcf3ce44SJohn Forte /* plogi failed continue to next dev */ 2546*fcf3ce44SJohn Forte continue; 2547*fcf3ce44SJohn Forte } 2548*fcf3ce44SJohn Forte } 2549*fcf3ce44SJohn Forte } 2550*fcf3ce44SJohn Forte /* sbuf should be set from hba_port handling. */ 2551*fcf3ce44SJohn Forte if ((err = handle_map_dev_FCP_prop(minor(sbuf.st_rdev), 2552*fcf3ce44SJohn Forte dlist->dev_pwwn, &impl_dev->prop_list)) != 0) { 2553*fcf3ce44SJohn Forte (void) free(dev_list); 2554*fcf3ce44SJohn Forte (void) close(fd); 2555*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2556*fcf3ce44SJohn Forte *l_err = err; 2557*fcf3ce44SJohn Forte return (NULL); 2558*fcf3ce44SJohn Forte } 2559*fcf3ce44SJohn Forte } 2560*fcf3ce44SJohn Forte } 2561*fcf3ce44SJohn Forte /* connect the children to to map. */ 2562*fcf3ce44SJohn Forte impl_map->child = mdl_start; 2563*fcf3ce44SJohn Forte S_FREE(dev_list); 2564*fcf3ce44SJohn Forte 2565*fcf3ce44SJohn Forte } else { /* sf and fc4/pci devices */ 2566*fcf3ce44SJohn Forte /* initialize map */ 2567*fcf3ce44SJohn Forte (void) memset(&sf_map, 0, sizeof (struct sf_al_map)); 2568*fcf3ce44SJohn Forte if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) { 2569*fcf3ce44SJohn Forte I_DPRINTF(" SFIOCGMAP ioctl failed.\n"); 2570*fcf3ce44SJohn Forte (void) close(fd); 2571*fcf3ce44SJohn Forte *l_err = L_SFIOCGMAP_IOCTL_FAIL; 2572*fcf3ce44SJohn Forte return (NULL); 2573*fcf3ce44SJohn Forte } 2574*fcf3ce44SJohn Forte /* Check for reasonableness. */ 2575*fcf3ce44SJohn Forte if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) { 2576*fcf3ce44SJohn Forte (void) close(fd); 2577*fcf3ce44SJohn Forte *l_err = L_INVALID_LOOP_MAP; 2578*fcf3ce44SJohn Forte return (NULL); 2579*fcf3ce44SJohn Forte } 2580*fcf3ce44SJohn Forte 2581*fcf3ce44SJohn Forte if (sf_map.sf_count == 0) { 2582*fcf3ce44SJohn Forte (void) close(fd); 2583*fcf3ce44SJohn Forte *l_err = L_NO_DEVICES_FOUND; 2584*fcf3ce44SJohn Forte return (NULL); 2585*fcf3ce44SJohn Forte } 2586*fcf3ce44SJohn Forte 2587*fcf3ce44SJohn Forte if ((err = g_get_nexus_path(drvr_path, &nexus_path)) != 0) { 2588*fcf3ce44SJohn Forte (void) close(fd); 2589*fcf3ce44SJohn Forte *l_err = err; 2590*fcf3ce44SJohn Forte return (NULL); 2591*fcf3ce44SJohn Forte } 2592*fcf3ce44SJohn Forte 2593*fcf3ce44SJohn Forte if ((nexus_fd = g_object_open(nexus_path, O_NDELAY | O_RDONLY)) == 2594*fcf3ce44SJohn Forte -1) { 2595*fcf3ce44SJohn Forte (void) close(fd); 2596*fcf3ce44SJohn Forte S_FREE(nexus_path); 2597*fcf3ce44SJohn Forte *l_err = errno; 2598*fcf3ce44SJohn Forte return (NULL); 2599*fcf3ce44SJohn Forte } 2600*fcf3ce44SJohn Forte 2601*fcf3ce44SJohn Forte /* get limited map to get hba param info */ 2602*fcf3ce44SJohn Forte if (ioctl(nexus_fd, FCIO_GETMAP, &limited_map) != 0) { 2603*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GETMAP ioctl failed\n"); 2604*fcf3ce44SJohn Forte (void) close(fd); 2605*fcf3ce44SJohn Forte (void) close(nexus_fd); 2606*fcf3ce44SJohn Forte S_FREE(nexus_path); 2607*fcf3ce44SJohn Forte *l_err = L_FCIO_GETMAP_IOCTL_FAIL; 2608*fcf3ce44SJohn Forte return (NULL); 2609*fcf3ce44SJohn Forte } 2610*fcf3ce44SJohn Forte (void) close(nexus_fd); 2611*fcf3ce44SJohn Forte S_FREE(nexus_path); 2612*fcf3ce44SJohn Forte 2613*fcf3ce44SJohn Forte for (i = 0; i < sf_map.sf_count; i++) { 2614*fcf3ce44SJohn Forte if (sf_map.sf_addr_pair[i].sf_al_pa == 2615*fcf3ce44SJohn Forte limited_map.lilp_myalpa) { 2616*fcf3ce44SJohn Forte sf_map.sf_hba_addr = sf_map.sf_addr_pair[i]; 2617*fcf3ce44SJohn Forte hba_alpa_found = 1; 2618*fcf3ce44SJohn Forte } 2619*fcf3ce44SJohn Forte } 2620*fcf3ce44SJohn Forte 2621*fcf3ce44SJohn Forte if (!(hba_alpa_found)) { 2622*fcf3ce44SJohn Forte (void) close(fd); 2623*fcf3ce44SJohn Forte *l_err = L_INVALID_LOOP_MAP; 2624*fcf3ce44SJohn Forte return (NULL); 2625*fcf3ce44SJohn Forte } 2626*fcf3ce44SJohn Forte 2627*fcf3ce44SJohn Forte /* We have dev list info and host param info. */ 2628*fcf3ce44SJohn Forte /* Now constructs map tree with these info. */ 2629*fcf3ce44SJohn Forte /* First consturct the root of the map tree */ 2630*fcf3ce44SJohn Forte /* with host param. */ 2631*fcf3ce44SJohn Forte if ((impl_map = (impl_map_dev_t *)calloc( 2632*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_t))) == NULL) { 2633*fcf3ce44SJohn Forte (void) close(fd); 2634*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2635*fcf3ce44SJohn Forte return (NULL); 2636*fcf3ce44SJohn Forte } 2637*fcf3ce44SJohn Forte impl_map->flag = flag; 2638*fcf3ce44SJohn Forte impl_map->topo = hba_port_top; 2639*fcf3ce44SJohn Forte 2640*fcf3ce44SJohn Forte /* consturct hba property list. */ 2641*fcf3ce44SJohn Forte if ((err = update_map_dev_fc_prop(&impl_map->prop_list, 2642*fcf3ce44SJohn Forte hba_port_top, sf_map.sf_hba_addr.sf_port_wwn, 2643*fcf3ce44SJohn Forte sf_map.sf_hba_addr.sf_node_wwn, 2644*fcf3ce44SJohn Forte (int)sf_map.sf_hba_addr.sf_al_pa, 2645*fcf3ce44SJohn Forte (int)sf_map.sf_hba_addr.sf_hard_address)) != 0) { 2646*fcf3ce44SJohn Forte (void) close(fd); 2647*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2648*fcf3ce44SJohn Forte *l_err = err; 2649*fcf3ce44SJohn Forte return (NULL); 2650*fcf3ce44SJohn Forte } 2651*fcf3ce44SJohn Forte 2652*fcf3ce44SJohn Forte if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) { 2653*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop(&impl_map->prop_list, 2654*fcf3ce44SJohn Forte &sf_map.sf_hba_addr.sf_inq_dtype, 0, PROP_NOEXIST)) != 0) { 2655*fcf3ce44SJohn Forte (void) close(fd); 2656*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2657*fcf3ce44SJohn Forte *l_err = err; 2658*fcf3ce44SJohn Forte return (NULL); 2659*fcf3ce44SJohn Forte } 2660*fcf3ce44SJohn Forte } 2661*fcf3ce44SJohn Forte 2662*fcf3ce44SJohn Forte for (i = 0; i < sf_map.sf_count; i++) { 2663*fcf3ce44SJohn Forte if ((impl_dev = (impl_map_dev_t *)calloc( 2664*fcf3ce44SJohn Forte 1, sizeof (impl_map_dev_t))) == NULL) { 2665*fcf3ce44SJohn Forte (void) close(fd); 2666*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2667*fcf3ce44SJohn Forte *l_err = L_MALLOC_FAILED; 2668*fcf3ce44SJohn Forte return (NULL); 2669*fcf3ce44SJohn Forte } 2670*fcf3ce44SJohn Forte /* set the map as parent */ 2671*fcf3ce44SJohn Forte impl_dev->parent = impl_map; 2672*fcf3ce44SJohn Forte if ((err = update_map_dev_fc_prop(&impl_dev->prop_list, 2673*fcf3ce44SJohn Forte hba_port_top, sf_map.sf_addr_pair[i].sf_port_wwn, 2674*fcf3ce44SJohn Forte sf_map.sf_addr_pair[i].sf_node_wwn, 2675*fcf3ce44SJohn Forte (int)(sf_map.sf_addr_pair[i].sf_al_pa), 2676*fcf3ce44SJohn Forte (int)(sf_map.sf_addr_pair[i].sf_hard_address))) != 0) { 2677*fcf3ce44SJohn Forte (void) close(fd); 2678*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2679*fcf3ce44SJohn Forte *l_err = err; 2680*fcf3ce44SJohn Forte return (NULL); 2681*fcf3ce44SJohn Forte } 2682*fcf3ce44SJohn Forte if (i == 0) { 2683*fcf3ce44SJohn Forte mdl_start = mdl_end = impl_dev; 2684*fcf3ce44SJohn Forte } else { 2685*fcf3ce44SJohn Forte mdl_end->next = impl_dev; 2686*fcf3ce44SJohn Forte mdl_end = impl_dev; 2687*fcf3ce44SJohn Forte } 2688*fcf3ce44SJohn Forte if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) { 2689*fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop(&impl_dev->prop_list, 2690*fcf3ce44SJohn Forte &sf_map.sf_addr_pair[i].sf_inq_dtype, 0, 2691*fcf3ce44SJohn Forte PROP_NOEXIST)) != 0) { 2692*fcf3ce44SJohn Forte (void) close(fd); 2693*fcf3ce44SJohn Forte g_dev_map_fini(impl_map); 2694*fcf3ce44SJohn Forte *l_err = err; 2695*fcf3ce44SJohn Forte return (NULL); 2696*fcf3ce44SJohn Forte } 2697*fcf3ce44SJohn Forte } 2698*fcf3ce44SJohn Forte } /* end of for loop */ 2699*fcf3ce44SJohn Forte 2700*fcf3ce44SJohn Forte impl_map->child = mdl_start; 2701*fcf3ce44SJohn Forte } /* end of else */ 2702*fcf3ce44SJohn Forte 2703*fcf3ce44SJohn Forte close(fd); 2704*fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_map)); 2705*fcf3ce44SJohn Forte } 2706*fcf3ce44SJohn Forte 2707*fcf3ce44SJohn Forte /* 2708*fcf3ce44SJohn Forte * This function deallocates memory for propery list. 2709*fcf3ce44SJohn Forte */ 2710*fcf3ce44SJohn Forte static void 2711*fcf3ce44SJohn Forte free_prop_list(impl_map_dev_prop_t **prop_list) 2712*fcf3ce44SJohn Forte { 2713*fcf3ce44SJohn Forte impl_map_dev_prop_t *lp, *olp; 2714*fcf3ce44SJohn Forte 2715*fcf3ce44SJohn Forte lp = *prop_list; 2716*fcf3ce44SJohn Forte while (lp != NULL) { 2717*fcf3ce44SJohn Forte switch (lp->prop_type) { 2718*fcf3ce44SJohn Forte case GFC_PROP_TYPE_BYTES: 2719*fcf3ce44SJohn Forte free((uchar_t *)(lp->prop_data)); 2720*fcf3ce44SJohn Forte break; 2721*fcf3ce44SJohn Forte case GFC_PROP_TYPE_INT: 2722*fcf3ce44SJohn Forte free((int *)(lp->prop_data)); 2723*fcf3ce44SJohn Forte break; 2724*fcf3ce44SJohn Forte case GFC_PROP_TYPE_STRING: 2725*fcf3ce44SJohn Forte free((char *)(lp->prop_data)); 2726*fcf3ce44SJohn Forte break; 2727*fcf3ce44SJohn Forte default: 2728*fcf3ce44SJohn Forte break; 2729*fcf3ce44SJohn Forte } 2730*fcf3ce44SJohn Forte lp->prop_data = NULL; 2731*fcf3ce44SJohn Forte olp = lp; 2732*fcf3ce44SJohn Forte lp = olp->next; 2733*fcf3ce44SJohn Forte S_FREE(olp); 2734*fcf3ce44SJohn Forte } 2735*fcf3ce44SJohn Forte 2736*fcf3ce44SJohn Forte *prop_list = NULL; 2737*fcf3ce44SJohn Forte } 2738*fcf3ce44SJohn Forte 2739*fcf3ce44SJohn Forte /* 2740*fcf3ce44SJohn Forte * This function deallocates memory for children list. 2741*fcf3ce44SJohn Forte */ 2742*fcf3ce44SJohn Forte static void 2743*fcf3ce44SJohn Forte free_child_list(impl_map_dev_t **dev_list) 2744*fcf3ce44SJohn Forte { 2745*fcf3ce44SJohn Forte impl_map_dev_t *lp, *olp; 2746*fcf3ce44SJohn Forte 2747*fcf3ce44SJohn Forte lp = *dev_list; 2748*fcf3ce44SJohn Forte while (lp != NULL) { 2749*fcf3ce44SJohn Forte free_prop_list(&lp->prop_list); 2750*fcf3ce44SJohn Forte olp = lp; 2751*fcf3ce44SJohn Forte lp = olp->next; 2752*fcf3ce44SJohn Forte S_FREE(olp); 2753*fcf3ce44SJohn Forte } 2754*fcf3ce44SJohn Forte 2755*fcf3ce44SJohn Forte *dev_list = NULL; 2756*fcf3ce44SJohn Forte } 2757*fcf3ce44SJohn Forte 2758*fcf3ce44SJohn Forte /* 2759*fcf3ce44SJohn Forte * This function deallocates memory for the whole map. 2760*fcf3ce44SJohn Forte */ 2761*fcf3ce44SJohn Forte void 2762*fcf3ce44SJohn Forte g_dev_map_fini(gfc_dev_t map) 2763*fcf3ce44SJohn Forte { 2764*fcf3ce44SJohn Forte impl_map_dev_t *impl_map; 2765*fcf3ce44SJohn Forte 2766*fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map; 2767*fcf3ce44SJohn Forte 2768*fcf3ce44SJohn Forte if (impl_map != NULL) { 2769*fcf3ce44SJohn Forte free_prop_list(&impl_map->prop_list); 2770*fcf3ce44SJohn Forte free_child_list(&impl_map->child); 2771*fcf3ce44SJohn Forte S_FREE(impl_map); 2772*fcf3ce44SJohn Forte } 2773*fcf3ce44SJohn Forte } 2774*fcf3ce44SJohn Forte 2775*fcf3ce44SJohn Forte /* 2776*fcf3ce44SJohn Forte * This function passes back topology of the input map. 2777*fcf3ce44SJohn Forte * input should be a handle form g_dev_map_init(). 2778*fcf3ce44SJohn Forte * 2779*fcf3ce44SJohn Forte * return 0 if OK. 2780*fcf3ce44SJohn Forte * return error code otherwise. 2781*fcf3ce44SJohn Forte */ 2782*fcf3ce44SJohn Forte int 2783*fcf3ce44SJohn Forte g_get_map_topology( 2784*fcf3ce44SJohn Forte gfc_dev_t map, 2785*fcf3ce44SJohn Forte uint_t *topology) 2786*fcf3ce44SJohn Forte { 2787*fcf3ce44SJohn Forte impl_map_dev_t *impl_map; 2788*fcf3ce44SJohn Forte 2789*fcf3ce44SJohn Forte if (map == NULL) { 2790*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 2791*fcf3ce44SJohn Forte } 2792*fcf3ce44SJohn Forte 2793*fcf3ce44SJohn Forte if (topology == NULL) { 2794*fcf3ce44SJohn Forte return (L_INVALID_ARG); 2795*fcf3ce44SJohn Forte } 2796*fcf3ce44SJohn Forte 2797*fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map; 2798*fcf3ce44SJohn Forte 2799*fcf3ce44SJohn Forte *topology = impl_map->topo; 2800*fcf3ce44SJohn Forte 2801*fcf3ce44SJohn Forte return (0); 2802*fcf3ce44SJohn Forte } 2803*fcf3ce44SJohn Forte 2804*fcf3ce44SJohn Forte /* 2805*fcf3ce44SJohn Forte * This function returns the first device handle of the input map. 2806*fcf3ce44SJohn Forte * map input should be a handle form g_dev_map_init(). 2807*fcf3ce44SJohn Forte * 2808*fcf3ce44SJohn Forte * l_err set to 0 if OK. 2809*fcf3ce44SJohn Forte * l_err set to error code otherwise. 2810*fcf3ce44SJohn Forte */ 2811*fcf3ce44SJohn Forte gfc_dev_t 2812*fcf3ce44SJohn Forte g_get_first_dev( 2813*fcf3ce44SJohn Forte gfc_dev_t map, 2814*fcf3ce44SJohn Forte int *l_err) 2815*fcf3ce44SJohn Forte { 2816*fcf3ce44SJohn Forte impl_map_dev_t *impl_map; 2817*fcf3ce44SJohn Forte 2818*fcf3ce44SJohn Forte if (l_err == NULL) { 2819*fcf3ce44SJohn Forte return (NULL); 2820*fcf3ce44SJohn Forte } 2821*fcf3ce44SJohn Forte 2822*fcf3ce44SJohn Forte *l_err = 0; 2823*fcf3ce44SJohn Forte 2824*fcf3ce44SJohn Forte if (map == NULL) { 2825*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR; 2826*fcf3ce44SJohn Forte return (NULL); 2827*fcf3ce44SJohn Forte } 2828*fcf3ce44SJohn Forte 2829*fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map; 2830*fcf3ce44SJohn Forte 2831*fcf3ce44SJohn Forte if (impl_map->child == NULL) { 2832*fcf3ce44SJohn Forte *l_err = L_NO_SUCH_DEV_FOUND; 2833*fcf3ce44SJohn Forte } 2834*fcf3ce44SJohn Forte 2835*fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_map->child)); 2836*fcf3ce44SJohn Forte } 2837*fcf3ce44SJohn Forte 2838*fcf3ce44SJohn Forte /* 2839*fcf3ce44SJohn Forte * This function returns the next device handle of the input map. 2840*fcf3ce44SJohn Forte * map_dev input should be a handle for device. 2841*fcf3ce44SJohn Forte * 2842*fcf3ce44SJohn Forte * l_err set to 0 if OK. 2843*fcf3ce44SJohn Forte * l_err set to error code otherwise. 2844*fcf3ce44SJohn Forte */ 2845*fcf3ce44SJohn Forte gfc_dev_t 2846*fcf3ce44SJohn Forte g_get_next_dev( 2847*fcf3ce44SJohn Forte gfc_dev_t map_dev, 2848*fcf3ce44SJohn Forte int *l_err) 2849*fcf3ce44SJohn Forte { 2850*fcf3ce44SJohn Forte impl_map_dev_t *impl_dev; 2851*fcf3ce44SJohn Forte 2852*fcf3ce44SJohn Forte if (l_err == NULL) { 2853*fcf3ce44SJohn Forte return (NULL); 2854*fcf3ce44SJohn Forte } 2855*fcf3ce44SJohn Forte 2856*fcf3ce44SJohn Forte *l_err = 0; 2857*fcf3ce44SJohn Forte 2858*fcf3ce44SJohn Forte if (map_dev == NULL) { 2859*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR; 2860*fcf3ce44SJohn Forte return (NULL); 2861*fcf3ce44SJohn Forte } 2862*fcf3ce44SJohn Forte 2863*fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev; 2864*fcf3ce44SJohn Forte 2865*fcf3ce44SJohn Forte if (impl_dev->next == NULL) { 2866*fcf3ce44SJohn Forte *l_err = L_NO_SUCH_DEV_FOUND; 2867*fcf3ce44SJohn Forte } 2868*fcf3ce44SJohn Forte 2869*fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_dev->next)); 2870*fcf3ce44SJohn Forte } 2871*fcf3ce44SJohn Forte 2872*fcf3ce44SJohn Forte /* 2873*fcf3ce44SJohn Forte * This function passes back uchar_t type property and its count. 2874*fcf3ce44SJohn Forte * map_dev input should be a handle for device. 2875*fcf3ce44SJohn Forte * 2876*fcf3ce44SJohn Forte * return 0 if OK. 2877*fcf3ce44SJohn Forte * return error code otherwise. 2878*fcf3ce44SJohn Forte */ 2879*fcf3ce44SJohn Forte int 2880*fcf3ce44SJohn Forte g_dev_prop_lookup_bytes( 2881*fcf3ce44SJohn Forte gfc_dev_t map_dev, 2882*fcf3ce44SJohn Forte const char *prop_name, 2883*fcf3ce44SJohn Forte int *prop_data_count, 2884*fcf3ce44SJohn Forte uchar_t **prop_data) 2885*fcf3ce44SJohn Forte { 2886*fcf3ce44SJohn Forte impl_map_dev_t *impl_dev; 2887*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 2888*fcf3ce44SJohn Forte int err; 2889*fcf3ce44SJohn Forte 2890*fcf3ce44SJohn Forte if (map_dev == NULL) { 2891*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 2892*fcf3ce44SJohn Forte } 2893*fcf3ce44SJohn Forte 2894*fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL) || 2895*fcf3ce44SJohn Forte (prop_data_count == NULL)) { 2896*fcf3ce44SJohn Forte return (L_INVALID_ARG); 2897*fcf3ce44SJohn Forte } 2898*fcf3ce44SJohn Forte 2899*fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev; 2900*fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list; 2901*fcf3ce44SJohn Forte 2902*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME; 2903*fcf3ce44SJohn Forte 2904*fcf3ce44SJohn Forte while (impl_prop) { 2905*fcf3ce44SJohn Forte if (strncmp(impl_prop->prop_name, prop_name, 2906*fcf3ce44SJohn Forte strlen(prop_name)) == 0) { 2907*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) { 2908*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_TYPE; 2909*fcf3ce44SJohn Forte break; 2910*fcf3ce44SJohn Forte } 2911*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 2912*fcf3ce44SJohn Forte *prop_data = (uchar_t *)(impl_prop->prop_data); 2913*fcf3ce44SJohn Forte *prop_data_count = impl_prop->prop_size; 2914*fcf3ce44SJohn Forte return (0); 2915*fcf3ce44SJohn Forte } else { 2916*fcf3ce44SJohn Forte err = impl_prop->prop_error; 2917*fcf3ce44SJohn Forte } 2918*fcf3ce44SJohn Forte break; 2919*fcf3ce44SJohn Forte } 2920*fcf3ce44SJohn Forte impl_prop = impl_prop->next; 2921*fcf3ce44SJohn Forte } 2922*fcf3ce44SJohn Forte 2923*fcf3ce44SJohn Forte return (err); 2924*fcf3ce44SJohn Forte } 2925*fcf3ce44SJohn Forte 2926*fcf3ce44SJohn Forte /* 2927*fcf3ce44SJohn Forte * This function passes back int type property. 2928*fcf3ce44SJohn Forte * map_dev input should be a handle for device. 2929*fcf3ce44SJohn Forte * 2930*fcf3ce44SJohn Forte * return 0 if OK. 2931*fcf3ce44SJohn Forte * return error code otherwise. 2932*fcf3ce44SJohn Forte */ 2933*fcf3ce44SJohn Forte int 2934*fcf3ce44SJohn Forte g_dev_prop_lookup_ints( 2935*fcf3ce44SJohn Forte gfc_dev_t map_dev, 2936*fcf3ce44SJohn Forte const char *prop_name, 2937*fcf3ce44SJohn Forte int **prop_data) 2938*fcf3ce44SJohn Forte { 2939*fcf3ce44SJohn Forte impl_map_dev_t *impl_dev; 2940*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 2941*fcf3ce44SJohn Forte int err; 2942*fcf3ce44SJohn Forte 2943*fcf3ce44SJohn Forte if (map_dev == NULL) { 2944*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 2945*fcf3ce44SJohn Forte } 2946*fcf3ce44SJohn Forte 2947*fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL)) { 2948*fcf3ce44SJohn Forte return (L_INVALID_ARG); 2949*fcf3ce44SJohn Forte } 2950*fcf3ce44SJohn Forte 2951*fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev; 2952*fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list; 2953*fcf3ce44SJohn Forte 2954*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME; 2955*fcf3ce44SJohn Forte 2956*fcf3ce44SJohn Forte while (impl_prop) { 2957*fcf3ce44SJohn Forte if (strncmp(impl_prop->prop_name, prop_name, 2958*fcf3ce44SJohn Forte strlen(prop_name)) == 0) { 2959*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_INT) { 2960*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_TYPE; 2961*fcf3ce44SJohn Forte break; 2962*fcf3ce44SJohn Forte } 2963*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 2964*fcf3ce44SJohn Forte *prop_data = (int *)(impl_prop->prop_data); 2965*fcf3ce44SJohn Forte return (0); 2966*fcf3ce44SJohn Forte } else { 2967*fcf3ce44SJohn Forte err = impl_prop->prop_error; 2968*fcf3ce44SJohn Forte } 2969*fcf3ce44SJohn Forte break; 2970*fcf3ce44SJohn Forte } 2971*fcf3ce44SJohn Forte impl_prop = impl_prop->next; 2972*fcf3ce44SJohn Forte } 2973*fcf3ce44SJohn Forte 2974*fcf3ce44SJohn Forte return (err); 2975*fcf3ce44SJohn Forte } 2976*fcf3ce44SJohn Forte 2977*fcf3ce44SJohn Forte /* 2978*fcf3ce44SJohn Forte * This function passes back int type property. 2979*fcf3ce44SJohn Forte * map_dev input should be a handle for device. 2980*fcf3ce44SJohn Forte * 2981*fcf3ce44SJohn Forte * return 0 if OK. 2982*fcf3ce44SJohn Forte * return error code otherwise. 2983*fcf3ce44SJohn Forte */ 2984*fcf3ce44SJohn Forte int 2985*fcf3ce44SJohn Forte g_dev_prop_lookup_strings( 2986*fcf3ce44SJohn Forte gfc_dev_t map_dev, 2987*fcf3ce44SJohn Forte const char *prop_name, 2988*fcf3ce44SJohn Forte char **prop_data) 2989*fcf3ce44SJohn Forte { 2990*fcf3ce44SJohn Forte impl_map_dev_t *impl_dev; 2991*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 2992*fcf3ce44SJohn Forte int err; 2993*fcf3ce44SJohn Forte 2994*fcf3ce44SJohn Forte if (map_dev == NULL) { 2995*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 2996*fcf3ce44SJohn Forte } 2997*fcf3ce44SJohn Forte 2998*fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL)) { 2999*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3000*fcf3ce44SJohn Forte } 3001*fcf3ce44SJohn Forte 3002*fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev; 3003*fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list; 3004*fcf3ce44SJohn Forte 3005*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME; 3006*fcf3ce44SJohn Forte 3007*fcf3ce44SJohn Forte while (impl_prop) { 3008*fcf3ce44SJohn Forte if (strncmp(impl_prop->prop_name, prop_name, 3009*fcf3ce44SJohn Forte strlen(prop_name)) == 0) { 3010*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) { 3011*fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_TYPE; 3012*fcf3ce44SJohn Forte break; 3013*fcf3ce44SJohn Forte } 3014*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 3015*fcf3ce44SJohn Forte *prop_data = (char *)(impl_prop->prop_data); 3016*fcf3ce44SJohn Forte return (0); 3017*fcf3ce44SJohn Forte } else { 3018*fcf3ce44SJohn Forte err = impl_prop->prop_error; 3019*fcf3ce44SJohn Forte } 3020*fcf3ce44SJohn Forte break; 3021*fcf3ce44SJohn Forte } 3022*fcf3ce44SJohn Forte impl_prop = impl_prop->next; 3023*fcf3ce44SJohn Forte } 3024*fcf3ce44SJohn Forte 3025*fcf3ce44SJohn Forte return (err); 3026*fcf3ce44SJohn Forte } 3027*fcf3ce44SJohn Forte 3028*fcf3ce44SJohn Forte /* 3029*fcf3ce44SJohn Forte * This function returns the handle for the first property of the input device. 3030*fcf3ce44SJohn Forte * map_dev input should be a handle form a device. 3031*fcf3ce44SJohn Forte * 3032*fcf3ce44SJohn Forte * l_err set to 0 if OK. 3033*fcf3ce44SJohn Forte * l_err set to error code otherwise. 3034*fcf3ce44SJohn Forte */ 3035*fcf3ce44SJohn Forte gfc_prop_t 3036*fcf3ce44SJohn Forte g_get_first_dev_prop( 3037*fcf3ce44SJohn Forte gfc_dev_t map_dev, 3038*fcf3ce44SJohn Forte int *l_err) 3039*fcf3ce44SJohn Forte { 3040*fcf3ce44SJohn Forte impl_map_dev_t *impl_dev; 3041*fcf3ce44SJohn Forte 3042*fcf3ce44SJohn Forte if (l_err == NULL) { 3043*fcf3ce44SJohn Forte return (NULL); 3044*fcf3ce44SJohn Forte } 3045*fcf3ce44SJohn Forte 3046*fcf3ce44SJohn Forte *l_err = 0; 3047*fcf3ce44SJohn Forte 3048*fcf3ce44SJohn Forte if (map_dev == NULL) { 3049*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR; 3050*fcf3ce44SJohn Forte return (NULL); 3051*fcf3ce44SJohn Forte } 3052*fcf3ce44SJohn Forte 3053*fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev; 3054*fcf3ce44SJohn Forte 3055*fcf3ce44SJohn Forte if (impl_dev->prop_list == NULL) { 3056*fcf3ce44SJohn Forte *l_err = L_NO_SUCH_PROP_FOUND; 3057*fcf3ce44SJohn Forte } 3058*fcf3ce44SJohn Forte 3059*fcf3ce44SJohn Forte return ((gfc_prop_t)(impl_dev->prop_list)); 3060*fcf3ce44SJohn Forte } 3061*fcf3ce44SJohn Forte 3062*fcf3ce44SJohn Forte /* 3063*fcf3ce44SJohn Forte * This function returns the handle for next property handle of the input prop. 3064*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3065*fcf3ce44SJohn Forte * 3066*fcf3ce44SJohn Forte * l_err set to 0 if OK. 3067*fcf3ce44SJohn Forte * l_err set to error code otherwise. 3068*fcf3ce44SJohn Forte */ 3069*fcf3ce44SJohn Forte gfc_prop_t 3070*fcf3ce44SJohn Forte g_get_next_dev_prop( 3071*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3072*fcf3ce44SJohn Forte int *l_err) 3073*fcf3ce44SJohn Forte { 3074*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3075*fcf3ce44SJohn Forte 3076*fcf3ce44SJohn Forte if (l_err == NULL) { 3077*fcf3ce44SJohn Forte return (NULL); 3078*fcf3ce44SJohn Forte } 3079*fcf3ce44SJohn Forte 3080*fcf3ce44SJohn Forte *l_err = 0; 3081*fcf3ce44SJohn Forte 3082*fcf3ce44SJohn Forte if (map_prop == NULL) { 3083*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP; 3084*fcf3ce44SJohn Forte return (NULL); 3085*fcf3ce44SJohn Forte } 3086*fcf3ce44SJohn Forte 3087*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3088*fcf3ce44SJohn Forte 3089*fcf3ce44SJohn Forte if (impl_prop->next == NULL) { 3090*fcf3ce44SJohn Forte *l_err = L_NO_SUCH_PROP_FOUND; 3091*fcf3ce44SJohn Forte } 3092*fcf3ce44SJohn Forte 3093*fcf3ce44SJohn Forte return ((gfc_prop_t)(impl_prop->next)); 3094*fcf3ce44SJohn Forte } 3095*fcf3ce44SJohn Forte 3096*fcf3ce44SJohn Forte /* 3097*fcf3ce44SJohn Forte * This function returns the name of the property of the input prop. 3098*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3099*fcf3ce44SJohn Forte * 3100*fcf3ce44SJohn Forte * return name string if OK. 3101*fcf3ce44SJohn Forte * returns NULL and l_err set to error code otherwise. 3102*fcf3ce44SJohn Forte */ 3103*fcf3ce44SJohn Forte char * 3104*fcf3ce44SJohn Forte g_get_dev_prop_name( 3105*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3106*fcf3ce44SJohn Forte int *l_err) 3107*fcf3ce44SJohn Forte { 3108*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3109*fcf3ce44SJohn Forte 3110*fcf3ce44SJohn Forte if (l_err == NULL) { 3111*fcf3ce44SJohn Forte return (NULL); 3112*fcf3ce44SJohn Forte } 3113*fcf3ce44SJohn Forte 3114*fcf3ce44SJohn Forte *l_err = 0; 3115*fcf3ce44SJohn Forte 3116*fcf3ce44SJohn Forte if (map_prop == NULL) { 3117*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP; 3118*fcf3ce44SJohn Forte return (NULL); 3119*fcf3ce44SJohn Forte } 3120*fcf3ce44SJohn Forte 3121*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3122*fcf3ce44SJohn Forte 3123*fcf3ce44SJohn Forte return (impl_prop->prop_name); 3124*fcf3ce44SJohn Forte } 3125*fcf3ce44SJohn Forte 3126*fcf3ce44SJohn Forte /* 3127*fcf3ce44SJohn Forte * This function returns the type of the property of the input prop. 3128*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3129*fcf3ce44SJohn Forte * 3130*fcf3ce44SJohn Forte * return type if OK. 3131*fcf3ce44SJohn Forte * returns GFC_PROP_TYPE_UNKNOWN and l_err set to error code otherwise. 3132*fcf3ce44SJohn Forte */ 3133*fcf3ce44SJohn Forte int 3134*fcf3ce44SJohn Forte g_get_dev_prop_type( 3135*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3136*fcf3ce44SJohn Forte int *l_err) 3137*fcf3ce44SJohn Forte { 3138*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3139*fcf3ce44SJohn Forte 3140*fcf3ce44SJohn Forte if (l_err != NULL) { 3141*fcf3ce44SJohn Forte *l_err = 0; 3142*fcf3ce44SJohn Forte } else { 3143*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3144*fcf3ce44SJohn Forte } 3145*fcf3ce44SJohn Forte 3146*fcf3ce44SJohn Forte if (map_prop == NULL) { 3147*fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP; 3148*fcf3ce44SJohn Forte return (GFC_PROP_TYPE_UNKNOWN); 3149*fcf3ce44SJohn Forte } 3150*fcf3ce44SJohn Forte 3151*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3152*fcf3ce44SJohn Forte 3153*fcf3ce44SJohn Forte return (impl_prop->prop_type); 3154*fcf3ce44SJohn Forte } 3155*fcf3ce44SJohn Forte 3156*fcf3ce44SJohn Forte /* 3157*fcf3ce44SJohn Forte * This function passes back uchar_t type property and its count. 3158*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3159*fcf3ce44SJohn Forte * 3160*fcf3ce44SJohn Forte * return 0 if OK. 3161*fcf3ce44SJohn Forte * return error code otherwise. 3162*fcf3ce44SJohn Forte */ 3163*fcf3ce44SJohn Forte int 3164*fcf3ce44SJohn Forte g_get_dev_prop_bytes( 3165*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3166*fcf3ce44SJohn Forte int *prop_data_count, 3167*fcf3ce44SJohn Forte uchar_t **prop_data) 3168*fcf3ce44SJohn Forte { 3169*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3170*fcf3ce44SJohn Forte 3171*fcf3ce44SJohn Forte if (map_prop == NULL) { 3172*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 3173*fcf3ce44SJohn Forte } 3174*fcf3ce44SJohn Forte 3175*fcf3ce44SJohn Forte if ((prop_data == NULL) || (prop_data_count == NULL)) { 3176*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3177*fcf3ce44SJohn Forte } 3178*fcf3ce44SJohn Forte 3179*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3180*fcf3ce44SJohn Forte 3181*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) { 3182*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_PROP_TYPE); 3183*fcf3ce44SJohn Forte } 3184*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 3185*fcf3ce44SJohn Forte *prop_data = (uchar_t *)(impl_prop->prop_data); 3186*fcf3ce44SJohn Forte *prop_data_count = impl_prop->prop_size; 3187*fcf3ce44SJohn Forte } else { 3188*fcf3ce44SJohn Forte return (impl_prop->prop_error); 3189*fcf3ce44SJohn Forte } 3190*fcf3ce44SJohn Forte 3191*fcf3ce44SJohn Forte return (0); 3192*fcf3ce44SJohn Forte } 3193*fcf3ce44SJohn Forte 3194*fcf3ce44SJohn Forte /* 3195*fcf3ce44SJohn Forte * This function passes back int type property. 3196*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3197*fcf3ce44SJohn Forte * 3198*fcf3ce44SJohn Forte * return 0 if OK. 3199*fcf3ce44SJohn Forte * return error code otherwise. 3200*fcf3ce44SJohn Forte */ 3201*fcf3ce44SJohn Forte int 3202*fcf3ce44SJohn Forte g_get_dev_prop_ints( 3203*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3204*fcf3ce44SJohn Forte int **prop_data) 3205*fcf3ce44SJohn Forte { 3206*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3207*fcf3ce44SJohn Forte 3208*fcf3ce44SJohn Forte if (map_prop == NULL) { 3209*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 3210*fcf3ce44SJohn Forte } 3211*fcf3ce44SJohn Forte 3212*fcf3ce44SJohn Forte if (prop_data == NULL) { 3213*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3214*fcf3ce44SJohn Forte } 3215*fcf3ce44SJohn Forte 3216*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3217*fcf3ce44SJohn Forte 3218*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_INT) { 3219*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_PROP_TYPE); 3220*fcf3ce44SJohn Forte } 3221*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 3222*fcf3ce44SJohn Forte *prop_data = (int *)(impl_prop->prop_data); 3223*fcf3ce44SJohn Forte } else { 3224*fcf3ce44SJohn Forte return (impl_prop->prop_error); 3225*fcf3ce44SJohn Forte } 3226*fcf3ce44SJohn Forte 3227*fcf3ce44SJohn Forte return (0); 3228*fcf3ce44SJohn Forte } 3229*fcf3ce44SJohn Forte 3230*fcf3ce44SJohn Forte /* 3231*fcf3ce44SJohn Forte * This function passes back string type property. 3232*fcf3ce44SJohn Forte * map_prop input should be a handle for property. 3233*fcf3ce44SJohn Forte * 3234*fcf3ce44SJohn Forte * return 0 if OK. 3235*fcf3ce44SJohn Forte * return error code otherwise. 3236*fcf3ce44SJohn Forte */ 3237*fcf3ce44SJohn Forte int 3238*fcf3ce44SJohn Forte g_get_dev_prop_strings( 3239*fcf3ce44SJohn Forte gfc_prop_t map_prop, 3240*fcf3ce44SJohn Forte char **prop_data) 3241*fcf3ce44SJohn Forte { 3242*fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop; 3243*fcf3ce44SJohn Forte 3244*fcf3ce44SJohn Forte if (map_prop == NULL) { 3245*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR); 3246*fcf3ce44SJohn Forte } 3247*fcf3ce44SJohn Forte 3248*fcf3ce44SJohn Forte if (prop_data == NULL) { 3249*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3250*fcf3ce44SJohn Forte } 3251*fcf3ce44SJohn Forte 3252*fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop; 3253*fcf3ce44SJohn Forte 3254*fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) { 3255*fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_PROP_TYPE); 3256*fcf3ce44SJohn Forte } 3257*fcf3ce44SJohn Forte if (impl_prop->prop_data) { 3258*fcf3ce44SJohn Forte *prop_data = (char *)(impl_prop->prop_data); 3259*fcf3ce44SJohn Forte } else { 3260*fcf3ce44SJohn Forte return (impl_prop->prop_error); 3261*fcf3ce44SJohn Forte } 3262*fcf3ce44SJohn Forte 3263*fcf3ce44SJohn Forte return (0); 3264*fcf3ce44SJohn Forte } 3265*fcf3ce44SJohn Forte 3266*fcf3ce44SJohn Forte /* 3267*fcf3ce44SJohn Forte * Free the linked list allocated by g_rdls() 3268*fcf3ce44SJohn Forte */ 3269*fcf3ce44SJohn Forte static void 3270*fcf3ce44SJohn Forte g_free_rls(AL_rls *rlsptr) 3271*fcf3ce44SJohn Forte { 3272*fcf3ce44SJohn Forte AL_rls *trlsptr; 3273*fcf3ce44SJohn Forte 3274*fcf3ce44SJohn Forte while (rlsptr != NULL) { 3275*fcf3ce44SJohn Forte trlsptr = rlsptr->next; 3276*fcf3ce44SJohn Forte free(rlsptr); 3277*fcf3ce44SJohn Forte rlsptr = trlsptr; 3278*fcf3ce44SJohn Forte } 3279*fcf3ce44SJohn Forte } 3280*fcf3ce44SJohn Forte 3281*fcf3ce44SJohn Forte /* 3282*fcf3ce44SJohn Forte * Read the extended link error status block 3283*fcf3ce44SJohn Forte * from the specified device and Host Adapter. 3284*fcf3ce44SJohn Forte * 3285*fcf3ce44SJohn Forte * PARAMS: 3286*fcf3ce44SJohn Forte * path_phys - physical path to an FC device 3287*fcf3ce44SJohn Forte * rls_ptr - pointer to read link state structure 3288*fcf3ce44SJohn Forte * 3289*fcf3ce44SJohn Forte * RETURNS: 3290*fcf3ce44SJohn Forte * 0 : if OK 3291*fcf3ce44SJohn Forte * non-zero: otherwise 3292*fcf3ce44SJohn Forte */ 3293*fcf3ce44SJohn Forte int 3294*fcf3ce44SJohn Forte g_rdls(char *path_phys, struct al_rls **rls_ptr, int verbose) 3295*fcf3ce44SJohn Forte { 3296*fcf3ce44SJohn Forte char nexus_path[MAXPATHLEN], *nexus_path_ptr; 3297*fcf3ce44SJohn Forte int fd, fp_fd, err, length, exp_map_flag = 0, *port_addr; 3298*fcf3ce44SJohn Forte struct lilpmap map; 3299*fcf3ce44SJohn Forte AL_rls *rls, *c1 = NULL, *c2 = NULL; 3300*fcf3ce44SJohn Forte uchar_t i, *port_wwn_byte; 3301*fcf3ce44SJohn Forte la_wwn_t port_wwn; 3302*fcf3ce44SJohn Forte sf_al_map_t exp_map; 3303*fcf3ce44SJohn Forte char *charPtr, fp_path[MAXPATHLEN]; 3304*fcf3ce44SJohn Forte uint_t dev_type; 3305*fcf3ce44SJohn Forte struct stat stbuf; 3306*fcf3ce44SJohn Forte fcio_t fcio; 3307*fcf3ce44SJohn Forte fc_portid_t rls_req; 3308*fcf3ce44SJohn Forte fc_rls_acc_t rls_payload; 3309*fcf3ce44SJohn Forte gfc_dev_t map_root, map_dev; 3310*fcf3ce44SJohn Forte uint32_t hba_port_top, state; 3311*fcf3ce44SJohn Forte int pathcnt = 1, count; 3312*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 3313*fcf3ce44SJohn Forte int p_on = 0, p_st = 0; 3314*fcf3ce44SJohn Forte 3315*fcf3ce44SJohn Forte /* return invalid path if path_phys is NULL */ 3316*fcf3ce44SJohn Forte if (path_phys == NULL) { 3317*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3318*fcf3ce44SJohn Forte } 3319*fcf3ce44SJohn Forte /* return invalid arg if rls_ptr is NULL */ 3320*fcf3ce44SJohn Forte if (rls_ptr == NULL) { 3321*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3322*fcf3ce44SJohn Forte } 3323*fcf3ce44SJohn Forte 3324*fcf3ce44SJohn Forte *rls_ptr = rls = NULL; 3325*fcf3ce44SJohn Forte 3326*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) { 3327*fcf3ce44SJohn Forte (void) strcpy(fp_path, path_phys); 3328*fcf3ce44SJohn Forte if (g_get_pathlist(fp_path, &pathlist)) { 3329*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3330*fcf3ce44SJohn Forte } 3331*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 3332*fcf3ce44SJohn Forte p_on = p_st = 0; 3333*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 3334*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 3335*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 3336*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 3337*fcf3ce44SJohn Forte p_on = i; 3338*fcf3ce44SJohn Forte break; 3339*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 3340*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 3341*fcf3ce44SJohn Forte p_st = i; 3342*fcf3ce44SJohn Forte } 3343*fcf3ce44SJohn Forte } 3344*fcf3ce44SJohn Forte } 3345*fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state == 3346*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 3347*fcf3ce44SJohn Forte /* on_line path */ 3348*fcf3ce44SJohn Forte (void) strcpy(fp_path, 3349*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 3350*fcf3ce44SJohn Forte } else { 3351*fcf3ce44SJohn Forte /* standby or path0 */ 3352*fcf3ce44SJohn Forte (void) strcpy(fp_path, 3353*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 3354*fcf3ce44SJohn Forte } 3355*fcf3ce44SJohn Forte free(pathlist.path_info); 3356*fcf3ce44SJohn Forte } else { 3357*fcf3ce44SJohn Forte (void) strcpy(fp_path, path_phys); 3358*fcf3ce44SJohn Forte } 3359*fcf3ce44SJohn Forte 3360*fcf3ce44SJohn Forte /* Get map of devices on this loop. */ 3361*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fp_path)) == 0) { 3362*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3363*fcf3ce44SJohn Forte } 3364*fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) { 3365*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) { 3366*fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR); 3367*fcf3ce44SJohn Forte } else if (strstr(fp_path, DRV_NAME_SSD) || 3368*fcf3ce44SJohn Forte strstr(fp_path, DRV_NAME_ST) || 3369*fcf3ce44SJohn Forte strstr(fp_path, SES_NAME)) { 3370*fcf3ce44SJohn Forte if ((charPtr = strrchr(fp_path, '/')) == NULL) { 3371*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3372*fcf3ce44SJohn Forte } 3373*fcf3ce44SJohn Forte *charPtr = '\0'; 3374*fcf3ce44SJohn Forte /* append devctl to the path */ 3375*fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR); 3376*fcf3ce44SJohn Forte } else { 3377*fcf3ce44SJohn Forte if (stat(fp_path, &stbuf) < 0) { 3378*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 3379*fcf3ce44SJohn Forte } 3380*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 3381*fcf3ce44SJohn Forte /* append devctl to the path */ 3382*fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR); 3383*fcf3ce44SJohn Forte } 3384*fcf3ce44SJohn Forte } 3385*fcf3ce44SJohn Forte 3386*fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(fp_path, &err, 3387*fcf3ce44SJohn Forte MAP_XPORT_PROP_ONLY)) == NULL) { 3388*fcf3ce44SJohn Forte return (err); 3389*fcf3ce44SJohn Forte } 3390*fcf3ce44SJohn Forte 3391*fcf3ce44SJohn Forte } else { /* FC4_FCA_MASK type path */ 3392*fcf3ce44SJohn Forte (void) memset(&map, 0, sizeof (struct lilpmap)); 3393*fcf3ce44SJohn Forte 3394*fcf3ce44SJohn Forte if ((err = g_get_nexus_path(path_phys, 3395*fcf3ce44SJohn Forte &nexus_path_ptr)) != 0) { 3396*fcf3ce44SJohn Forte return (err); 3397*fcf3ce44SJohn Forte } 3398*fcf3ce44SJohn Forte (void) strcpy(nexus_path, nexus_path_ptr); 3399*fcf3ce44SJohn Forte g_destroy_data(nexus_path_ptr); 3400*fcf3ce44SJohn Forte 3401*fcf3ce44SJohn Forte /* open driver */ 3402*fcf3ce44SJohn Forte if ((fd = g_object_open(nexus_path, 3403*fcf3ce44SJohn Forte O_NDELAY | O_RDONLY)) == -1) 3404*fcf3ce44SJohn Forte return (errno); 3405*fcf3ce44SJohn Forte 3406*fcf3ce44SJohn Forte /* 3407*fcf3ce44SJohn Forte * First try using the socal version of the map. 3408*fcf3ce44SJohn Forte * If that fails get the expanded vesion. 3409*fcf3ce44SJohn Forte */ 3410*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_GETMAP, &map) != 0) { 3411*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GETMAP ioctl failed.\n"); 3412*fcf3ce44SJohn Forte if (ioctl(fd, SFIOCGMAP, &exp_map) != 0) { 3413*fcf3ce44SJohn Forte I_DPRINTF(" SFIOCGMAP ioctl failed.\n"); 3414*fcf3ce44SJohn Forte (void) close(fd); 3415*fcf3ce44SJohn Forte return (L_SFIOCGMAP_IOCTL_FAIL); 3416*fcf3ce44SJohn Forte } 3417*fcf3ce44SJohn Forte /* Check for reasonableness. */ 3418*fcf3ce44SJohn Forte if ((exp_map.sf_count > 126) || 3419*fcf3ce44SJohn Forte (exp_map.sf_count < 0)) { 3420*fcf3ce44SJohn Forte (void) close(fd); 3421*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 3422*fcf3ce44SJohn Forte } 3423*fcf3ce44SJohn Forte for (i = 0; i < exp_map.sf_count; i++) { 3424*fcf3ce44SJohn Forte if (exp_map.sf_addr_pair[i].sf_al_pa > 0xef) { 3425*fcf3ce44SJohn Forte (void) close(fd); 3426*fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP); 3427*fcf3ce44SJohn Forte } 3428*fcf3ce44SJohn Forte } 3429*fcf3ce44SJohn Forte length = exp_map.sf_count; 3430*fcf3ce44SJohn Forte exp_map_flag++; 3431*fcf3ce44SJohn Forte } else { 3432*fcf3ce44SJohn Forte I_DPRINTF(" g_rdls:" 3433*fcf3ce44SJohn Forte " FCIO_GETMAP ioctl returned %d entries.\n", 3434*fcf3ce44SJohn Forte map.lilp_length); 3435*fcf3ce44SJohn Forte /* Check for reasonableness. */ 3436*fcf3ce44SJohn Forte if (map.lilp_length > sizeof (map.lilp_list)) { 3437*fcf3ce44SJohn Forte (void) close(fd); 3438*fcf3ce44SJohn Forte return (L_FCIOGETMAP_INVLD_LEN); 3439*fcf3ce44SJohn Forte } 3440*fcf3ce44SJohn Forte length = map.lilp_length; 3441*fcf3ce44SJohn Forte } 3442*fcf3ce44SJohn Forte for (i = 0; i < length; i++) { 3443*fcf3ce44SJohn Forte if ((c2 = (struct al_rls *) 3444*fcf3ce44SJohn Forte g_zalloc(sizeof (struct al_rls))) == NULL) { 3445*fcf3ce44SJohn Forte close(fd); 3446*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 3447*fcf3ce44SJohn Forte } 3448*fcf3ce44SJohn Forte if (rls == NULL) { 3449*fcf3ce44SJohn Forte c1 = rls = c2; 3450*fcf3ce44SJohn Forte } else { 3451*fcf3ce44SJohn Forte for (c1 = rls; c1->next; c1 = c1->next) {}; 3452*fcf3ce44SJohn Forte c1 = c1->next = c2; 3453*fcf3ce44SJohn Forte } 3454*fcf3ce44SJohn Forte (void) strcpy(c1->driver_path, nexus_path); 3455*fcf3ce44SJohn Forte if (exp_map_flag) { 3456*fcf3ce44SJohn Forte c1->payload.rls_portno = c1->al_ha = 3457*fcf3ce44SJohn Forte exp_map.sf_addr_pair[i].sf_al_pa; 3458*fcf3ce44SJohn Forte } else { 3459*fcf3ce44SJohn Forte c1->payload.rls_portno = c1->al_ha = map.lilp_list[i]; 3460*fcf3ce44SJohn Forte } 3461*fcf3ce44SJohn Forte c1->payload.rls_linkfail = 3462*fcf3ce44SJohn Forte (uint_t)0xff000000; /* get LESB for this port */ 3463*fcf3ce44SJohn Forte I_DPRINTF(" g_rdls:" " al_pa 0x%x\n", c1->payload.rls_portno); 3464*fcf3ce44SJohn Forte 3465*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LINKSTATUS, &c1->payload) != 0) { 3466*fcf3ce44SJohn Forte /* 3467*fcf3ce44SJohn Forte * The ifp driver will return ENXIO when rls 3468*fcf3ce44SJohn Forte * is issued for same initiator on loop when 3469*fcf3ce44SJohn Forte * there is more than one on the loop. 3470*fcf3ce44SJohn Forte * Rather than completely fail, continue on. 3471*fcf3ce44SJohn Forte * Set values in the payload struct to -1 as 3472*fcf3ce44SJohn Forte * this is what socal is currently doing for 3473*fcf3ce44SJohn Forte * the case of same initiator rls. 3474*fcf3ce44SJohn Forte */ 3475*fcf3ce44SJohn Forte if ((dev_type & FC4_PCI_FCA) && (errno == ENXIO)) { 3476*fcf3ce44SJohn Forte c1->payload.rls_linkfail = 3477*fcf3ce44SJohn Forte c1->payload.rls_syncfail = 3478*fcf3ce44SJohn Forte c1->payload.rls_sigfail = 3479*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = 3480*fcf3ce44SJohn Forte c1->payload.rls_invalidword = 3481*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = (uint_t)0xffffffff; 3482*fcf3ce44SJohn Forte } else { 3483*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_LINKSTATUS ioctl" 3484*fcf3ce44SJohn Forte " failed with errno %d.\n", errno); 3485*fcf3ce44SJohn Forte g_free_rls(rls); 3486*fcf3ce44SJohn Forte (void) close(fd); 3487*fcf3ce44SJohn Forte return (L_FCIO_LINKSTATUS_FAILED); 3488*fcf3ce44SJohn Forte } 3489*fcf3ce44SJohn Forte } 3490*fcf3ce44SJohn Forte I_DPRINTF(" g_rdls: al_pa returned by ioctl 0x%x\n", 3491*fcf3ce44SJohn Forte c1->payload.rls_portno); 3492*fcf3ce44SJohn Forte } 3493*fcf3ce44SJohn Forte *rls_ptr = rls; /* Pass back pointer */ 3494*fcf3ce44SJohn Forte 3495*fcf3ce44SJohn Forte (void) close(fd); 3496*fcf3ce44SJohn Forte return (0); 3497*fcf3ce44SJohn Forte } 3498*fcf3ce44SJohn Forte 3499*fcf3ce44SJohn Forte /* Now we need to take care of FC_FCA_MASK case. */ 3500*fcf3ce44SJohn Forte /* we have map created already via g_dev_map_init. */ 3501*fcf3ce44SJohn Forte if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) { 3502*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3503*fcf3ce44SJohn Forte return (err); 3504*fcf3ce44SJohn Forte } 3505*fcf3ce44SJohn Forte 3506*fcf3ce44SJohn Forte if ((map_dev = g_get_first_dev(map_root, &err)) == NULL) { 3507*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3508*fcf3ce44SJohn Forte if (err != L_NO_SUCH_DEV_FOUND) { 3509*fcf3ce44SJohn Forte return (err); 3510*fcf3ce44SJohn Forte } else { 3511*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 3512*fcf3ce44SJohn Forte } 3513*fcf3ce44SJohn Forte } 3514*fcf3ce44SJohn Forte 3515*fcf3ce44SJohn Forte while (map_dev) { 3516*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_ints( 3517*fcf3ce44SJohn Forte map_dev, PORT_ADDR_PROP, &port_addr)) != 0) { 3518*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3519*fcf3ce44SJohn Forte g_free_rls(rls); 3520*fcf3ce44SJohn Forte return (err); 3521*fcf3ce44SJohn Forte } 3522*fcf3ce44SJohn Forte 3523*fcf3ce44SJohn Forte if ((c2 = (struct al_rls *) 3524*fcf3ce44SJohn Forte g_zalloc(sizeof (struct al_rls))) == NULL) { 3525*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3526*fcf3ce44SJohn Forte g_free_rls(rls); 3527*fcf3ce44SJohn Forte close(fd); 3528*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 3529*fcf3ce44SJohn Forte } 3530*fcf3ce44SJohn Forte if (rls == NULL) { 3531*fcf3ce44SJohn Forte c1 = rls = c2; 3532*fcf3ce44SJohn Forte } else { 3533*fcf3ce44SJohn Forte for (c1 = rls; c1->next; c1 = c1->next) {}; 3534*fcf3ce44SJohn Forte c1 = c1->next = c2; 3535*fcf3ce44SJohn Forte } 3536*fcf3ce44SJohn Forte /* Set the al_ha here */ 3537*fcf3ce44SJohn Forte c1->al_ha = rls_req.port_id = *port_addr; 3538*fcf3ce44SJohn Forte 3539*fcf3ce44SJohn Forte /* 3540*fcf3ce44SJohn Forte * fp uses different input/output structures for 3541*fcf3ce44SJohn Forte * rls. Load the values returned for the fp ioctl 3542*fcf3ce44SJohn Forte * into the structure passed back to the caller 3543*fcf3ce44SJohn Forte * Note: There is no reason for the path 3544*fcf3ce44SJohn Forte * to be loaded into AL_rls as is done for socal/ifp 3545*fcf3ce44SJohn Forte * above. 3546*fcf3ce44SJohn Forte */ 3547*fcf3ce44SJohn Forte if ((hba_port_top == FC_TOP_FABRIC) || 3548*fcf3ce44SJohn Forte (hba_port_top == FC_TOP_PUBLIC_LOOP)) { 3549*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_bytes( 3550*fcf3ce44SJohn Forte map_dev, PORT_WWN_PROP, &count, &port_wwn_byte)) != 0) { 3551*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3552*fcf3ce44SJohn Forte g_free_rls(rls); 3553*fcf3ce44SJohn Forte return (err); 3554*fcf3ce44SJohn Forte } 3555*fcf3ce44SJohn Forte memcpy(port_wwn.raw_wwn, port_wwn_byte, FC_WWN_SIZE); 3556*fcf3ce44SJohn Forte if ((err = g_get_dev_port_state( 3557*fcf3ce44SJohn Forte fp_path, port_wwn, &state)) == 0) { 3558*fcf3ce44SJohn Forte if (state != PORT_DEVICE_LOGGED_IN) { 3559*fcf3ce44SJohn Forte if ((err = g_dev_login(fp_path, port_wwn)) != 0) { 3560*fcf3ce44SJohn Forte c1->payload.rls_linkfail = 3561*fcf3ce44SJohn Forte c1->payload.rls_syncfail = 3562*fcf3ce44SJohn Forte c1->payload.rls_sigfail = 3563*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = 3564*fcf3ce44SJohn Forte c1->payload.rls_invalidword = 3565*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = (uint_t)0xffffffff; 3566*fcf3ce44SJohn Forte if (((map_dev = 3567*fcf3ce44SJohn Forte g_get_next_dev(map_dev, &err)) 3568*fcf3ce44SJohn Forte == NULL) && 3569*fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) { 3570*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3571*fcf3ce44SJohn Forte g_free_rls(rls); 3572*fcf3ce44SJohn Forte return (err); 3573*fcf3ce44SJohn Forte } 3574*fcf3ce44SJohn Forte continue; 3575*fcf3ce44SJohn Forte } 3576*fcf3ce44SJohn Forte } 3577*fcf3ce44SJohn Forte } /* if g_get_dev_port_state fails proceed. */ 3578*fcf3ce44SJohn Forte } 3579*fcf3ce44SJohn Forte 3580*fcf3ce44SJohn Forte fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT; 3581*fcf3ce44SJohn Forte if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) { 3582*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3583*fcf3ce44SJohn Forte g_free_rls(rls); 3584*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 3585*fcf3ce44SJohn Forte } 3586*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_LINK_STATUS; 3587*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&rls_req; 3588*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (rls_req); 3589*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_RW; 3590*fcf3ce44SJohn Forte fcio.fcio_flags = 0; 3591*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&rls_payload; 3592*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (rls_payload); 3593*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) { 3594*fcf3ce44SJohn Forte c1->payload.rls_linkfail = 3595*fcf3ce44SJohn Forte c1->payload.rls_syncfail = 3596*fcf3ce44SJohn Forte c1->payload.rls_sigfail = 3597*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = 3598*fcf3ce44SJohn Forte c1->payload.rls_invalidword = 3599*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = (uint_t)0xffffffff; 3600*fcf3ce44SJohn Forte } else { 3601*fcf3ce44SJohn Forte /* 3602*fcf3ce44SJohn Forte * Load the values into the struct passed 3603*fcf3ce44SJohn Forte * back to the caller 3604*fcf3ce44SJohn Forte */ 3605*fcf3ce44SJohn Forte c1->payload.rls_linkfail = rls_payload.rls_link_fail; 3606*fcf3ce44SJohn Forte c1->payload.rls_syncfail = rls_payload.rls_sync_loss; 3607*fcf3ce44SJohn Forte c1->payload.rls_sigfail = rls_payload.rls_sig_loss; 3608*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = rls_payload.rls_prim_seq_err; 3609*fcf3ce44SJohn Forte c1->payload.rls_invalidword = rls_payload.rls_invalid_word; 3610*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = rls_payload.rls_invalid_crc; 3611*fcf3ce44SJohn Forte } 3612*fcf3ce44SJohn Forte (void) close(fp_fd); 3613*fcf3ce44SJohn Forte 3614*fcf3ce44SJohn Forte if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) && 3615*fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) { 3616*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3617*fcf3ce44SJohn Forte g_free_rls(rls); 3618*fcf3ce44SJohn Forte return (err); 3619*fcf3ce44SJohn Forte } 3620*fcf3ce44SJohn Forte } 3621*fcf3ce44SJohn Forte 3622*fcf3ce44SJohn Forte /* for Leadville issue a final call for the initiator */ 3623*fcf3ce44SJohn Forte 3624*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_ints( 3625*fcf3ce44SJohn Forte map_root, PORT_ADDR_PROP, &port_addr)) != 0) { 3626*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3627*fcf3ce44SJohn Forte g_free_rls(rls); 3628*fcf3ce44SJohn Forte return (err); 3629*fcf3ce44SJohn Forte } 3630*fcf3ce44SJohn Forte 3631*fcf3ce44SJohn Forte if ((c2 = (struct al_rls *) 3632*fcf3ce44SJohn Forte g_zalloc(sizeof (struct al_rls))) == NULL) { 3633*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3634*fcf3ce44SJohn Forte g_free_rls(rls); 3635*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 3636*fcf3ce44SJohn Forte } 3637*fcf3ce44SJohn Forte if (rls == NULL) { 3638*fcf3ce44SJohn Forte c1 = rls = c2; 3639*fcf3ce44SJohn Forte } else { 3640*fcf3ce44SJohn Forte for (c1 = rls; c1->next; c1 = c1->next) {}; 3641*fcf3ce44SJohn Forte c1 = c1->next = c2; 3642*fcf3ce44SJohn Forte } 3643*fcf3ce44SJohn Forte 3644*fcf3ce44SJohn Forte c1->al_ha = rls_req.port_id = *port_addr; 3645*fcf3ce44SJohn Forte 3646*fcf3ce44SJohn Forte if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) { 3647*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3648*fcf3ce44SJohn Forte g_free_rls(rls); 3649*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 3650*fcf3ce44SJohn Forte } 3651*fcf3ce44SJohn Forte 3652*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_LINK_STATUS; 3653*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&rls_req; 3654*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (rls_req); 3655*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_RW; 3656*fcf3ce44SJohn Forte fcio.fcio_flags = 0; 3657*fcf3ce44SJohn Forte fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT; 3658*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&rls_payload; 3659*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (rls_payload); 3660*fcf3ce44SJohn Forte 3661*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) { 3662*fcf3ce44SJohn Forte c1->payload.rls_linkfail = 3663*fcf3ce44SJohn Forte c1->payload.rls_syncfail = 3664*fcf3ce44SJohn Forte c1->payload.rls_sigfail = 3665*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = 3666*fcf3ce44SJohn Forte c1->payload.rls_invalidword = 3667*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = (uint_t)0xffffffff; 3668*fcf3ce44SJohn Forte } else { 3669*fcf3ce44SJohn Forte /* 3670*fcf3ce44SJohn Forte * Load the values into the struct passed 3671*fcf3ce44SJohn Forte * back to the caller 3672*fcf3ce44SJohn Forte */ 3673*fcf3ce44SJohn Forte c1->payload.rls_linkfail = rls_payload.rls_link_fail; 3674*fcf3ce44SJohn Forte c1->payload.rls_syncfail = rls_payload.rls_sync_loss; 3675*fcf3ce44SJohn Forte c1->payload.rls_sigfail = rls_payload.rls_sig_loss; 3676*fcf3ce44SJohn Forte c1->payload.rls_primitiverr = rls_payload.rls_prim_seq_err; 3677*fcf3ce44SJohn Forte c1->payload.rls_invalidword = rls_payload.rls_invalid_word; 3678*fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = rls_payload.rls_invalid_crc; 3679*fcf3ce44SJohn Forte (void) close(fp_fd); 3680*fcf3ce44SJohn Forte } 3681*fcf3ce44SJohn Forte (void) close(fp_fd); 3682*fcf3ce44SJohn Forte 3683*fcf3ce44SJohn Forte *rls_ptr = rls; /* Pass back pointer */ 3684*fcf3ce44SJohn Forte 3685*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3686*fcf3ce44SJohn Forte return (0); 3687*fcf3ce44SJohn Forte } 3688*fcf3ce44SJohn Forte 3689*fcf3ce44SJohn Forte static u_longlong_t wwnConversion(uchar_t *wwn) 3690*fcf3ce44SJohn Forte { 3691*fcf3ce44SJohn Forte u_longlong_t tmp; 3692*fcf3ce44SJohn Forte memcpy(&tmp, wwn, sizeof (u_longlong_t)); 3693*fcf3ce44SJohn Forte return (tmp); 3694*fcf3ce44SJohn Forte } 3695*fcf3ce44SJohn Forte 3696*fcf3ce44SJohn Forte /* 3697*fcf3ce44SJohn Forte * Get device World Wide Name (port and node) for device at path 3698*fcf3ce44SJohn Forte * and add all WWNs to the wwn_list_found list. 3699*fcf3ce44SJohn Forte * 3700*fcf3ce44SJohn Forte * RETURN: 0 O.K. 3701*fcf3ce44SJohn Forte * 3702*fcf3ce44SJohn Forte * INPUTS: 3703*fcf3ce44SJohn Forte * - path_phys must be of a device, either an IB or disk. 3704*fcf3ce44SJohn Forte */ 3705*fcf3ce44SJohn Forte static int 3706*fcf3ce44SJohn Forte get_wwns(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[], int *al_pa, 3707*fcf3ce44SJohn Forte struct wwn_list_found_struct **wwn_list_found) 3708*fcf3ce44SJohn Forte { 3709*fcf3ce44SJohn Forte uint32_t hba_port_top; 3710*fcf3ce44SJohn Forte int i, err, count; 3711*fcf3ce44SJohn Forte char *char_ptr, *ptr; 3712*fcf3ce44SJohn Forte int found = 0, pathcnt, *port_addr; 3713*fcf3ce44SJohn Forte unsigned long long pwwn; 3714*fcf3ce44SJohn Forte uchar_t *port_wwn_byte, *node_wwn_byte; 3715*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN]; 3716*fcf3ce44SJohn Forte int p_on = 0, p_st = 0; 3717*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 3718*fcf3ce44SJohn Forte char pwwn1[WWN_S_LEN]; 3719*fcf3ce44SJohn Forte gfc_dev_t map_root, map_dev; 3720*fcf3ce44SJohn Forte hrtime_t start_time, end_time; 3721*fcf3ce44SJohn Forte char *env = NULL; 3722*fcf3ce44SJohn Forte 3723*fcf3ce44SJohn Forte P_DPRINTF(" g_get_wwn: Getting device WWN" 3724*fcf3ce44SJohn Forte " and al_pa for device: %s\n", 3725*fcf3ce44SJohn Forte path_phys); 3726*fcf3ce44SJohn Forte 3727*fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) { 3728*fcf3ce44SJohn Forte start_time = gethrtime(); 3729*fcf3ce44SJohn Forte } 3730*fcf3ce44SJohn Forte 3731*fcf3ce44SJohn Forte /* 3732*fcf3ce44SJohn Forte * Get the loop identifier (switch setting) from the path. 3733*fcf3ce44SJohn Forte * 3734*fcf3ce44SJohn Forte * This assumes the path looks something like this: 3735*fcf3ce44SJohn Forte * /devices/.../SUNW,socal@3,0/SUNW,sf@0,0/SUNW,ssd@x,0 3736*fcf3ce44SJohn Forte * or 3737*fcf3ce44SJohn Forte * /devices/.../SUNW,qlc@5/SUNW,fp@0,0/SUNW,ssd@x,0 3738*fcf3ce44SJohn Forte */ 3739*fcf3ce44SJohn Forte if ((char_ptr = strrchr(path_phys, '@')) == NULL) { 3740*fcf3ce44SJohn Forte return (L_INVLD_PATH_NO_ATSIGN_FND); 3741*fcf3ce44SJohn Forte } 3742*fcf3ce44SJohn Forte char_ptr++; /* point to the loop identifier or WWN */ 3743*fcf3ce44SJohn Forte 3744*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path_phys); 3745*fcf3ce44SJohn Forte /* This function allocs mem for map.dev_addr on success */ 3746*fcf3ce44SJohn Forte if (strstr(drvr_path, SCSI_VHCI)) { 3747*fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) { 3748*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3749*fcf3ce44SJohn Forte } 3750*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 3751*fcf3ce44SJohn Forte p_on = p_st = 0; 3752*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 3753*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 3754*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 3755*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 3756*fcf3ce44SJohn Forte p_on = i; 3757*fcf3ce44SJohn Forte break; 3758*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 3759*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 3760*fcf3ce44SJohn Forte p_st = i; 3761*fcf3ce44SJohn Forte } 3762*fcf3ce44SJohn Forte } 3763*fcf3ce44SJohn Forte } 3764*fcf3ce44SJohn Forte if (p_on == i) { 3765*fcf3ce44SJohn Forte /* on_line path */ 3766*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 3767*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 3768*fcf3ce44SJohn Forte (void) strncpy(pwwn1, 3769*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_addr, 3770*fcf3ce44SJohn Forte WWN_S_LEN - 1); 3771*fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0'; 3772*fcf3ce44SJohn Forte } else { 3773*fcf3ce44SJohn Forte /* standby or path0 */ 3774*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 3775*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 3776*fcf3ce44SJohn Forte (void) strncpy(pwwn1, 3777*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_addr, 3778*fcf3ce44SJohn Forte WWN_S_LEN - 1); 3779*fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0'; 3780*fcf3ce44SJohn Forte } 3781*fcf3ce44SJohn Forte free(pathlist.path_info); 3782*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 3783*fcf3ce44SJohn Forte } 3784*fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(drvr_path, &err, 3785*fcf3ce44SJohn Forte MAP_XPORT_PROP_ONLY)) == NULL) { 3786*fcf3ce44SJohn Forte return (err); 3787*fcf3ce44SJohn Forte } 3788*fcf3ce44SJohn Forte 3789*fcf3ce44SJohn Forte if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) { 3790*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3791*fcf3ce44SJohn Forte return (err); 3792*fcf3ce44SJohn Forte } 3793*fcf3ce44SJohn Forte 3794*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI)) { 3795*fcf3ce44SJohn Forte char_ptr = pwwn1; 3796*fcf3ce44SJohn Forte } else { 3797*fcf3ce44SJohn Forte /* 3798*fcf3ce44SJohn Forte * Format of WWN is 3799*fcf3ce44SJohn Forte * ssd@w2200002037000f96,0:a,raw 3800*fcf3ce44SJohn Forte */ 3801*fcf3ce44SJohn Forte if (*char_ptr != 'w') { 3802*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3803*fcf3ce44SJohn Forte return (L_INVLD_WWN_FORMAT); 3804*fcf3ce44SJohn Forte } 3805*fcf3ce44SJohn Forte char_ptr++; 3806*fcf3ce44SJohn Forte } 3807*fcf3ce44SJohn Forte pwwn = strtoull(char_ptr, &ptr, 16); 3808*fcf3ce44SJohn Forte if (ptr == char_ptr) { 3809*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3810*fcf3ce44SJohn Forte return (L_NO_WWN_FOUND_IN_PATH); 3811*fcf3ce44SJohn Forte } 3812*fcf3ce44SJohn Forte P_DPRINTF(" g_get_wwn: Looking for WWN " 3813*fcf3ce44SJohn Forte "0x%llx\n", pwwn); 3814*fcf3ce44SJohn Forte 3815*fcf3ce44SJohn Forte if (((map_dev = g_get_first_dev(map_root, &err)) == NULL) && 3816*fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) { 3817*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3818*fcf3ce44SJohn Forte return (err); 3819*fcf3ce44SJohn Forte } 3820*fcf3ce44SJohn Forte 3821*fcf3ce44SJohn Forte while (map_dev) { 3822*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_bytes(map_dev, 3823*fcf3ce44SJohn Forte PORT_WWN_PROP, &count, &port_wwn_byte)) != 0) { 3824*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3825*fcf3ce44SJohn Forte return (err); 3826*fcf3ce44SJohn Forte } 3827*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_bytes(map_dev, 3828*fcf3ce44SJohn Forte NODE_WWN_PROP, &count, &node_wwn_byte)) != 0) { 3829*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3830*fcf3ce44SJohn Forte return (err); 3831*fcf3ce44SJohn Forte } 3832*fcf3ce44SJohn Forte 3833*fcf3ce44SJohn Forte if (pwwn == wwnConversion(port_wwn_byte) && found != 1) { 3834*fcf3ce44SJohn Forte found = 1; 3835*fcf3ce44SJohn Forte memcpy(port_wwn, port_wwn_byte, FC_WWN_SIZE); 3836*fcf3ce44SJohn Forte memcpy(node_wwn, node_wwn_byte, FC_WWN_SIZE); 3837*fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_ints( 3838*fcf3ce44SJohn Forte map_dev, PORT_ADDR_PROP, &port_addr)) != 0) { 3839*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3840*fcf3ce44SJohn Forte return (err); 3841*fcf3ce44SJohn Forte } 3842*fcf3ce44SJohn Forte *al_pa = *port_addr; 3843*fcf3ce44SJohn Forte } 3844*fcf3ce44SJohn Forte add_wwn_entry(wwn_list_found, port_wwn_byte, 3845*fcf3ce44SJohn Forte node_wwn_byte); 3846*fcf3ce44SJohn Forte 3847*fcf3ce44SJohn Forte if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) && 3848*fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) { 3849*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3850*fcf3ce44SJohn Forte return (err); 3851*fcf3ce44SJohn Forte } 3852*fcf3ce44SJohn Forte } 3853*fcf3ce44SJohn Forte if (!found) { 3854*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3855*fcf3ce44SJohn Forte return (L_NO_LOOP_ADDRS_FOUND); 3856*fcf3ce44SJohn Forte } 3857*fcf3ce44SJohn Forte 3858*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 3859*fcf3ce44SJohn Forte if (env != NULL) { 3860*fcf3ce44SJohn Forte end_time = gethrtime(); 3861*fcf3ce44SJohn Forte fprintf(stdout, " get_wwns: " 3862*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 3863*fcf3ce44SJohn Forte (end_time - start_time)/1000000); 3864*fcf3ce44SJohn Forte } 3865*fcf3ce44SJohn Forte return (0); 3866*fcf3ce44SJohn Forte } 3867*fcf3ce44SJohn Forte 3868*fcf3ce44SJohn Forte /* 3869*fcf3ce44SJohn Forte * Get device World Wide Name and AL_PA for device at path 3870*fcf3ce44SJohn Forte * 3871*fcf3ce44SJohn Forte * RETURN: 0 O.K. 3872*fcf3ce44SJohn Forte * 3873*fcf3ce44SJohn Forte * INPUTS: 3874*fcf3ce44SJohn Forte * - path_phys must be of a device, either an IB or disk. 3875*fcf3ce44SJohn Forte */ 3876*fcf3ce44SJohn Forte int 3877*fcf3ce44SJohn Forte g_get_wwn(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[], 3878*fcf3ce44SJohn Forte int *al_pa, int verbose) 3879*fcf3ce44SJohn Forte { 3880*fcf3ce44SJohn Forte struct wwn_list_found_struct *wwn_list_found = NULL; 3881*fcf3ce44SJohn Forte int ret; 3882*fcf3ce44SJohn Forte 3883*fcf3ce44SJohn Forte /* return invalid path if the argument is NULL */ 3884*fcf3ce44SJohn Forte if (path_phys == NULL) { 3885*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3886*fcf3ce44SJohn Forte } 3887*fcf3ce44SJohn Forte /* return invalid arg if the argument is NULL */ 3888*fcf3ce44SJohn Forte if ((port_wwn == NULL) || 3889*fcf3ce44SJohn Forte (node_wwn == NULL) || (al_pa == NULL)) { 3890*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3891*fcf3ce44SJohn Forte } 3892*fcf3ce44SJohn Forte 3893*fcf3ce44SJohn Forte ret = get_wwns(path_phys, port_wwn, node_wwn, al_pa, &wwn_list_found); 3894*fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found); 3895*fcf3ce44SJohn Forte return (ret); 3896*fcf3ce44SJohn Forte } 3897*fcf3ce44SJohn Forte 3898*fcf3ce44SJohn Forte int 3899*fcf3ce44SJohn Forte g_get_serial_number(char *path, uchar_t *serial_number, 3900*fcf3ce44SJohn Forte size_t *serial_number_len) 3901*fcf3ce44SJohn Forte { 3902*fcf3ce44SJohn Forte int fd, status = 0; 3903*fcf3ce44SJohn Forte L_inquiry80 inq80; 3904*fcf3ce44SJohn Forte 3905*fcf3ce44SJohn Forte /* return invalid path if path is NULL */ 3906*fcf3ce44SJohn Forte if (path == NULL) { 3907*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3908*fcf3ce44SJohn Forte } 3909*fcf3ce44SJohn Forte /* return invalid arg if serial_number is NULL */ 3910*fcf3ce44SJohn Forte if (serial_number == NULL) { 3911*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3912*fcf3ce44SJohn Forte } 3913*fcf3ce44SJohn Forte 3914*fcf3ce44SJohn Forte P_DPRINTF(" g_get_serial_number: path: %s\n", path); 3915*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) { 3916*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 3917*fcf3ce44SJohn Forte } 3918*fcf3ce44SJohn Forte /* 3919*fcf3ce44SJohn Forte * Call the inquiry cmd on page 0x80 only if the vendor 3920*fcf3ce44SJohn Forte * supports page 0x80. 3921*fcf3ce44SJohn Forte */ 3922*fcf3ce44SJohn Forte if ((g_find_supported_inq_page(fd, 0x80))) { 3923*fcf3ce44SJohn Forte /* 3924*fcf3ce44SJohn Forte * Let's retrieve the serial number from page 0x80 3925*fcf3ce44SJohn Forte * and store it in the inquiry structure 3926*fcf3ce44SJohn Forte */ 3927*fcf3ce44SJohn Forte status = g_scsi_inquiry_cmd80(fd, 3928*fcf3ce44SJohn Forte (uchar_t *)&inq80, 3929*fcf3ce44SJohn Forte sizeof (struct l_inquiry80_struct)); 3930*fcf3ce44SJohn Forte if (status == 0) { 3931*fcf3ce44SJohn Forte if (*serial_number_len > inq80.inq_page_len) 3932*fcf3ce44SJohn Forte *serial_number_len = inq80.inq_page_len; 3933*fcf3ce44SJohn Forte strncpy((char *)serial_number, (char *)inq80.inq_serial, 3934*fcf3ce44SJohn Forte *serial_number_len); 3935*fcf3ce44SJohn Forte } else { 3936*fcf3ce44SJohn Forte char unavail[] = "Unavailable"; 3937*fcf3ce44SJohn Forte status = 0; 3938*fcf3ce44SJohn Forte if (*serial_number_len > strlen(unavail)) 3939*fcf3ce44SJohn Forte *serial_number_len = strlen(unavail); 3940*fcf3ce44SJohn Forte strncpy((char *)serial_number, unavail, 3941*fcf3ce44SJohn Forte *serial_number_len); 3942*fcf3ce44SJohn Forte } 3943*fcf3ce44SJohn Forte } else { 3944*fcf3ce44SJohn Forte /* 3945*fcf3ce44SJohn Forte * page 0x80 is not supported, so print the 3946*fcf3ce44SJohn Forte * appropriate message. 3947*fcf3ce44SJohn Forte */ 3948*fcf3ce44SJohn Forte char unsupp[] = "Unsupported"; 3949*fcf3ce44SJohn Forte if (*serial_number_len > strlen(unsupp)) 3950*fcf3ce44SJohn Forte *serial_number_len = strlen(unsupp); 3951*fcf3ce44SJohn Forte strncpy((char *)serial_number, unsupp, 3952*fcf3ce44SJohn Forte *serial_number_len); 3953*fcf3ce44SJohn Forte } 3954*fcf3ce44SJohn Forte (void) close(fd); 3955*fcf3ce44SJohn Forte return (status); 3956*fcf3ce44SJohn Forte } 3957*fcf3ce44SJohn Forte 3958*fcf3ce44SJohn Forte int 3959*fcf3ce44SJohn Forte g_get_inquiry(char *path, L_inquiry *l_inquiry) 3960*fcf3ce44SJohn Forte { 3961*fcf3ce44SJohn Forte int fd, status; 3962*fcf3ce44SJohn Forte 3963*fcf3ce44SJohn Forte /* return invalid path if path is NULL */ 3964*fcf3ce44SJohn Forte if (path == NULL) { 3965*fcf3ce44SJohn Forte return (L_INVALID_PATH); 3966*fcf3ce44SJohn Forte } 3967*fcf3ce44SJohn Forte /* return invalid arg if l_inquiry is NULL */ 3968*fcf3ce44SJohn Forte if (l_inquiry == NULL) { 3969*fcf3ce44SJohn Forte return (L_INVALID_ARG); 3970*fcf3ce44SJohn Forte } 3971*fcf3ce44SJohn Forte 3972*fcf3ce44SJohn Forte P_DPRINTF(" g_get_inquiry: path: %s\n", path); 3973*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 3974*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 3975*fcf3ce44SJohn Forte status = g_scsi_inquiry_cmd(fd, 3976*fcf3ce44SJohn Forte (uchar_t *)l_inquiry, sizeof (struct l_inquiry_struct)); 3977*fcf3ce44SJohn Forte 3978*fcf3ce44SJohn Forte (void) close(fd); 3979*fcf3ce44SJohn Forte return (status); 3980*fcf3ce44SJohn Forte } 3981*fcf3ce44SJohn Forte 3982*fcf3ce44SJohn Forte /* 3983*fcf3ce44SJohn Forte * Function to retrieve inquiry page 0x80 from the device 3984*fcf3ce44SJohn Forte */ 3985*fcf3ce44SJohn Forte static int 3986*fcf3ce44SJohn Forte g_scsi_inquiry_cmd80(int fd, uchar_t *buf_ptr, int buf_len) 3987*fcf3ce44SJohn Forte { 3988*fcf3ce44SJohn Forte struct uscsi_cmd ucmd; 3989*fcf3ce44SJohn Forte my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0x80, 0, 0x10, 0}; 3990*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 3991*fcf3ce44SJohn Forte 3992*fcf3ce44SJohn Forte (void) memset(buf_ptr, 0, buf_len); 3993*fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd)); 3994*fcf3ce44SJohn Forte cdb.count = (uchar_t)buf_len; 3995*fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb; 3996*fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0; 3997*fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = (caddr_t)buf_ptr; 3998*fcf3ce44SJohn Forte ucmd.uscsi_buflen = buf_len; 3999*fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense; 4000*fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense); 4001*fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60; 4002*fcf3ce44SJohn Forte return (cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT)); 4003*fcf3ce44SJohn Forte } 4004*fcf3ce44SJohn Forte 4005*fcf3ce44SJohn Forte /* 4006*fcf3ce44SJohn Forte * Function to determine if the given page is supported by vendor. 4007*fcf3ce44SJohn Forte */ 4008*fcf3ce44SJohn Forte static int 4009*fcf3ce44SJohn Forte g_find_supported_inq_page(int fd, int page_num) 4010*fcf3ce44SJohn Forte { 4011*fcf3ce44SJohn Forte struct uscsi_cmd ucmd; 4012*fcf3ce44SJohn Forte my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0, 0, 0xff, 0}; 4013*fcf3ce44SJohn Forte struct scsi_extended_sense sense; 4014*fcf3ce44SJohn Forte L_inquiry00 inq00; 4015*fcf3ce44SJohn Forte uchar_t *data; 4016*fcf3ce44SJohn Forte int status = 0; 4017*fcf3ce44SJohn Forte int index; 4018*fcf3ce44SJohn Forte 4019*fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd)); 4020*fcf3ce44SJohn Forte cdb.count = (uchar_t)(sizeof (L_inquiry00)); 4021*fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb; 4022*fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0; 4023*fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = (caddr_t)&inq00; 4024*fcf3ce44SJohn Forte ucmd.uscsi_buflen = sizeof (inq00); 4025*fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense; 4026*fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense); 4027*fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60; 4028*fcf3ce44SJohn Forte status = cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT); 4029*fcf3ce44SJohn Forte if (status) { 4030*fcf3ce44SJohn Forte return (0); 4031*fcf3ce44SJohn Forte } 4032*fcf3ce44SJohn Forte data = (uchar_t *)&inq00; 4033*fcf3ce44SJohn Forte for (index = 4; (index <= inq00.len+3)&& 4034*fcf3ce44SJohn Forte (data[index] <= page_num); index ++) { 4035*fcf3ce44SJohn Forte if (data[index] == page_num) { 4036*fcf3ce44SJohn Forte return (1); 4037*fcf3ce44SJohn Forte } 4038*fcf3ce44SJohn Forte } 4039*fcf3ce44SJohn Forte return (0); 4040*fcf3ce44SJohn Forte } 4041*fcf3ce44SJohn Forte 4042*fcf3ce44SJohn Forte int 4043*fcf3ce44SJohn Forte g_get_perf_statistics(char *path, uchar_t *perf_ptr) 4044*fcf3ce44SJohn Forte { 4045*fcf3ce44SJohn Forte int fd; 4046*fcf3ce44SJohn Forte 4047*fcf3ce44SJohn Forte P_DPRINTF(" g_get_perf_statistics: Get Performance Statistics:" 4048*fcf3ce44SJohn Forte "\n Path:%s\n", 4049*fcf3ce44SJohn Forte path); 4050*fcf3ce44SJohn Forte 4051*fcf3ce44SJohn Forte /* initialize tables */ 4052*fcf3ce44SJohn Forte (void) memset(perf_ptr, 0, sizeof (int)); 4053*fcf3ce44SJohn Forte 4054*fcf3ce44SJohn Forte /* open controller */ 4055*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 4056*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4057*fcf3ce44SJohn Forte 4058*fcf3ce44SJohn Forte 4059*fcf3ce44SJohn Forte /* update parameters in the performance table */ 4060*fcf3ce44SJohn Forte 4061*fcf3ce44SJohn Forte /* get the period in seconds */ 4062*fcf3ce44SJohn Forte 4063*fcf3ce44SJohn Forte 4064*fcf3ce44SJohn Forte (void) close(fd); 4065*fcf3ce44SJohn Forte 4066*fcf3ce44SJohn Forte return (0); 4067*fcf3ce44SJohn Forte } 4068*fcf3ce44SJohn Forte 4069*fcf3ce44SJohn Forte 4070*fcf3ce44SJohn Forte int 4071*fcf3ce44SJohn Forte g_start(char *path) 4072*fcf3ce44SJohn Forte { 4073*fcf3ce44SJohn Forte int status; 4074*fcf3ce44SJohn Forte int fd; 4075*fcf3ce44SJohn Forte 4076*fcf3ce44SJohn Forte P_DPRINTF(" g_start: Start: Path %s\n", path); 4077*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 4078*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4079*fcf3ce44SJohn Forte status = g_scsi_start_cmd(fd); 4080*fcf3ce44SJohn Forte (void) close(fd); 4081*fcf3ce44SJohn Forte return (status); 4082*fcf3ce44SJohn Forte } 4083*fcf3ce44SJohn Forte 4084*fcf3ce44SJohn Forte int 4085*fcf3ce44SJohn Forte g_stop(char *path, int immediate_flag) 4086*fcf3ce44SJohn Forte { 4087*fcf3ce44SJohn Forte int status, fd; 4088*fcf3ce44SJohn Forte 4089*fcf3ce44SJohn Forte P_DPRINTF(" g_stop: Stop: Path %s\n", path); 4090*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 4091*fcf3ce44SJohn Forte return (errno); 4092*fcf3ce44SJohn Forte status = g_scsi_stop_cmd(fd, immediate_flag); 4093*fcf3ce44SJohn Forte (void) close(fd); 4094*fcf3ce44SJohn Forte return (status); 4095*fcf3ce44SJohn Forte } 4096*fcf3ce44SJohn Forte 4097*fcf3ce44SJohn Forte int 4098*fcf3ce44SJohn Forte g_reserve(char *path) 4099*fcf3ce44SJohn Forte { 4100*fcf3ce44SJohn Forte int fd, status; 4101*fcf3ce44SJohn Forte 4102*fcf3ce44SJohn Forte P_DPRINTF(" g_reserve: Reserve: Path %s\n", path); 4103*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 4104*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4105*fcf3ce44SJohn Forte status = g_scsi_reserve_cmd(fd); 4106*fcf3ce44SJohn Forte (void) close(fd); 4107*fcf3ce44SJohn Forte return (status); 4108*fcf3ce44SJohn Forte } 4109*fcf3ce44SJohn Forte 4110*fcf3ce44SJohn Forte int 4111*fcf3ce44SJohn Forte g_release(char *path) 4112*fcf3ce44SJohn Forte { 4113*fcf3ce44SJohn Forte int fd, status; 4114*fcf3ce44SJohn Forte 4115*fcf3ce44SJohn Forte P_DPRINTF(" g_release: Release: Path %s\n", path); 4116*fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) 4117*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4118*fcf3ce44SJohn Forte status = g_scsi_release_cmd(fd); 4119*fcf3ce44SJohn Forte (void) close(fd); 4120*fcf3ce44SJohn Forte return (status); 4121*fcf3ce44SJohn Forte } 4122*fcf3ce44SJohn Forte 4123*fcf3ce44SJohn Forte static char 4124*fcf3ce44SJohn Forte ctoi(char c) 4125*fcf3ce44SJohn Forte { 4126*fcf3ce44SJohn Forte if ((c >= '0') && (c <= '9')) 4127*fcf3ce44SJohn Forte c -= '0'; 4128*fcf3ce44SJohn Forte else if ((c >= 'A') && (c <= 'F')) 4129*fcf3ce44SJohn Forte c = c - 'A' + 10; 4130*fcf3ce44SJohn Forte else if ((c >= 'a') && (c <= 'f')) 4131*fcf3ce44SJohn Forte c = c - 'a' + 10; 4132*fcf3ce44SJohn Forte else 4133*fcf3ce44SJohn Forte c = -1; 4134*fcf3ce44SJohn Forte return (c); 4135*fcf3ce44SJohn Forte } 4136*fcf3ce44SJohn Forte 4137*fcf3ce44SJohn Forte int 4138*fcf3ce44SJohn Forte g_string_to_wwn(uchar_t *wwn, uchar_t *wwnp) 4139*fcf3ce44SJohn Forte { 4140*fcf3ce44SJohn Forte int i; 4141*fcf3ce44SJohn Forte char c, c1; 4142*fcf3ce44SJohn Forte 4143*fcf3ce44SJohn Forte *wwnp++ = 0; 4144*fcf3ce44SJohn Forte *wwnp++ = 0; 4145*fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE - 2; i++, wwnp++) { 4146*fcf3ce44SJohn Forte c = ctoi(*wwn++); 4147*fcf3ce44SJohn Forte c1 = ctoi(*wwn++); 4148*fcf3ce44SJohn Forte if (c == -1 || c1 == -1) 4149*fcf3ce44SJohn Forte return (-1); 4150*fcf3ce44SJohn Forte *wwnp = ((c << 4) + c1); 4151*fcf3ce44SJohn Forte } 4152*fcf3ce44SJohn Forte 4153*fcf3ce44SJohn Forte return (0); 4154*fcf3ce44SJohn Forte 4155*fcf3ce44SJohn Forte } 4156*fcf3ce44SJohn Forte 4157*fcf3ce44SJohn Forte /* 4158*fcf3ce44SJohn Forte * Converts a string of WWN ASCII characters to a 4159*fcf3ce44SJohn Forte * binary representation. 4160*fcf3ce44SJohn Forte * 4161*fcf3ce44SJohn Forte * Input: string - pointer to uchar_t array 4162*fcf3ce44SJohn Forte * WWN in ASCII 4163*fcf3ce44SJohn Forte * length: 16 bytes 4164*fcf3ce44SJohn Forte * Output: wwn - pointer to uchar_t array 4165*fcf3ce44SJohn Forte * containing WWN result 4166*fcf3ce44SJohn Forte * length: 8 bytes 4167*fcf3ce44SJohn Forte * Returns: 4168*fcf3ce44SJohn Forte * non-zero on error 4169*fcf3ce44SJohn Forte * zero on success 4170*fcf3ce44SJohn Forte */ 4171*fcf3ce44SJohn Forte int 4172*fcf3ce44SJohn Forte string_to_wwn(uchar_t *string, uchar_t *wwn) 4173*fcf3ce44SJohn Forte { 4174*fcf3ce44SJohn Forte int i; 4175*fcf3ce44SJohn Forte char c, c1; 4176*fcf3ce44SJohn Forte uchar_t *wwnp; 4177*fcf3ce44SJohn Forte 4178*fcf3ce44SJohn Forte wwnp = wwn; 4179*fcf3ce44SJohn Forte 4180*fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE; i++, wwnp++) { 4181*fcf3ce44SJohn Forte 4182*fcf3ce44SJohn Forte c = ctoi(*string++); 4183*fcf3ce44SJohn Forte c1 = ctoi(*string++); 4184*fcf3ce44SJohn Forte if (c == -1 || c1 == -1) 4185*fcf3ce44SJohn Forte return (-1); 4186*fcf3ce44SJohn Forte *wwnp = ((c << 4) + c1); 4187*fcf3ce44SJohn Forte } 4188*fcf3ce44SJohn Forte 4189*fcf3ce44SJohn Forte return (0); 4190*fcf3ce44SJohn Forte 4191*fcf3ce44SJohn Forte } 4192*fcf3ce44SJohn Forte 4193*fcf3ce44SJohn Forte 4194*fcf3ce44SJohn Forte /* 4195*fcf3ce44SJohn Forte * Get multiple paths to a given device port. 4196*fcf3ce44SJohn Forte * INPUTS: 4197*fcf3ce44SJohn Forte * port WWN string. 4198*fcf3ce44SJohn Forte */ 4199*fcf3ce44SJohn Forte int 4200*fcf3ce44SJohn Forte g_get_port_multipath(char *port_wwn_s, struct dlist **dlh, int verbose) 4201*fcf3ce44SJohn Forte { 4202*fcf3ce44SJohn Forte int err; 4203*fcf3ce44SJohn Forte WWN_list *wwn_list, *wwn_list_ptr; 4204*fcf3ce44SJohn Forte struct dlist *dlt, *dl; 4205*fcf3ce44SJohn Forte 4206*fcf3ce44SJohn Forte 4207*fcf3ce44SJohn Forte /* Initialize list structures. */ 4208*fcf3ce44SJohn Forte dl = *dlh = dlt = (struct dlist *)NULL; 4209*fcf3ce44SJohn Forte wwn_list = wwn_list_ptr = NULL; 4210*fcf3ce44SJohn Forte 4211*fcf3ce44SJohn Forte H_DPRINTF(" g_get_port_multipath: Looking for multiple paths for" 4212*fcf3ce44SJohn Forte " device with\n port WWW:" 4213*fcf3ce44SJohn Forte "%s\n", port_wwn_s); 4214*fcf3ce44SJohn Forte 4215*fcf3ce44SJohn Forte if (err = g_get_wwn_list(&wwn_list, verbose)) { 4216*fcf3ce44SJohn Forte return (err); 4217*fcf3ce44SJohn Forte } 4218*fcf3ce44SJohn Forte 4219*fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL; 4220*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 4221*fcf3ce44SJohn Forte if (strcmp(port_wwn_s, wwn_list_ptr->port_wwn_s) == 0) { 4222*fcf3ce44SJohn Forte if ((dl = (struct dlist *) 4223*fcf3ce44SJohn Forte g_zalloc(sizeof (struct dlist))) == NULL) { 4224*fcf3ce44SJohn Forte while (*dlh != NULL) { 4225*fcf3ce44SJohn Forte dl = (*dlh)->next; 4226*fcf3ce44SJohn Forte (void) g_destroy_data(*dlh); 4227*fcf3ce44SJohn Forte *dlh = dl; 4228*fcf3ce44SJohn Forte } 4229*fcf3ce44SJohn Forte (void) g_free_wwn_list(&wwn_list); 4230*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 4231*fcf3ce44SJohn Forte } 4232*fcf3ce44SJohn Forte H_DPRINTF(" g_get_port_multipath:" 4233*fcf3ce44SJohn Forte " Found multipath:\n %s\n", 4234*fcf3ce44SJohn Forte wwn_list_ptr->physical_path); 4235*fcf3ce44SJohn Forte dl->dev_path = strdup(wwn_list_ptr->physical_path); 4236*fcf3ce44SJohn Forte dl->logical_path = strdup(wwn_list_ptr->logical_path); 4237*fcf3ce44SJohn Forte if (*dlh == NULL) { 4238*fcf3ce44SJohn Forte *dlh = dlt = dl; 4239*fcf3ce44SJohn Forte } else { 4240*fcf3ce44SJohn Forte dlt->next = dl; 4241*fcf3ce44SJohn Forte dl->prev = dlt; 4242*fcf3ce44SJohn Forte dlt = dl; 4243*fcf3ce44SJohn Forte } 4244*fcf3ce44SJohn Forte } 4245*fcf3ce44SJohn Forte } 4246*fcf3ce44SJohn Forte (void) g_free_wwn_list(&wwn_list); 4247*fcf3ce44SJohn Forte return (0); 4248*fcf3ce44SJohn Forte } 4249*fcf3ce44SJohn Forte 4250*fcf3ce44SJohn Forte 4251*fcf3ce44SJohn Forte 4252*fcf3ce44SJohn Forte /* 4253*fcf3ce44SJohn Forte * Get multiple paths to a given disk/tape device. 4254*fcf3ce44SJohn Forte * The arg: devpath should be the physical path to device. 4255*fcf3ce44SJohn Forte * 4256*fcf3ce44SJohn Forte * OUTPUT: 4257*fcf3ce44SJohn Forte * multipath_list points to a list of multiple paths to the device. 4258*fcf3ce44SJohn Forte * NOTE: The caller must free the allocated list (dlist). 4259*fcf3ce44SJohn Forte * 4260*fcf3ce44SJohn Forte * RETURNS: 4261*fcf3ce44SJohn Forte * 0 if O.K. 4262*fcf3ce44SJohn Forte * non-zero otherwise 4263*fcf3ce44SJohn Forte */ 4264*fcf3ce44SJohn Forte int 4265*fcf3ce44SJohn Forte g_get_multipath(char *devpath, struct dlist **multipath_list, 4266*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list, int verbose) 4267*fcf3ce44SJohn Forte { 4268*fcf3ce44SJohn Forte int err; 4269*fcf3ce44SJohn Forte 4270*fcf3ce44SJohn Forte H_DPRINTF(" g_get_multipath: Looking for multiple paths for" 4271*fcf3ce44SJohn Forte " device at path: %s\n", devpath); 4272*fcf3ce44SJohn Forte 4273*fcf3ce44SJohn Forte /* return invalid path if devpath is NULL */ 4274*fcf3ce44SJohn Forte if (devpath == NULL) { 4275*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4276*fcf3ce44SJohn Forte } 4277*fcf3ce44SJohn Forte /* return invalid arg if argument is NULL */ 4278*fcf3ce44SJohn Forte if ((multipath_list == NULL) || (wwn_list == NULL)) { 4279*fcf3ce44SJohn Forte return (L_INVALID_ARG); 4280*fcf3ce44SJohn Forte } 4281*fcf3ce44SJohn Forte 4282*fcf3ce44SJohn Forte if (strstr(devpath, DRV_NAME_SSD) != NULL) { 4283*fcf3ce44SJohn Forte err = get_multipath_disk(devpath, multipath_list, wwn_list); 4284*fcf3ce44SJohn Forte } else { 4285*fcf3ce44SJohn Forte err = get_multipath(devpath, multipath_list, wwn_list); 4286*fcf3ce44SJohn Forte } 4287*fcf3ce44SJohn Forte 4288*fcf3ce44SJohn Forte return (err); 4289*fcf3ce44SJohn Forte } 4290*fcf3ce44SJohn Forte 4291*fcf3ce44SJohn Forte 4292*fcf3ce44SJohn Forte /* 4293*fcf3ce44SJohn Forte * Returns multipath information for a ssd device. 4294*fcf3ce44SJohn Forte * Inputs: 4295*fcf3ce44SJohn Forte * devpath: device path to for requested multipath info 4296*fcf3ce44SJohn Forte * wwn_list: returned from g_get_wwn_list or devices_get_all 4297*fcf3ce44SJohn Forte * Output: 4298*fcf3ce44SJohn Forte * multipath_list: dlist list of paths 4299*fcf3ce44SJohn Forte * Returns: 4300*fcf3ce44SJohn Forte * 0 on success 4301*fcf3ce44SJohn Forte * non-zero on failure 4302*fcf3ce44SJohn Forte */ 4303*fcf3ce44SJohn Forte int 4304*fcf3ce44SJohn Forte get_multipath_disk(char *devpath, struct dlist **multipath_list, 4305*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list) 4306*fcf3ce44SJohn Forte { 4307*fcf3ce44SJohn Forte WWN_list *wwn_list_ptr; 4308*fcf3ce44SJohn Forte struct dlist *dl = NULL, *dlt = NULL; 4309*fcf3ce44SJohn Forte ddi_devid_t devid = NULL; 4310*fcf3ce44SJohn Forte int err; 4311*fcf3ce44SJohn Forte di_node_t root; 4312*fcf3ce44SJohn Forte struct mplist_struct *mplistp = NULL, *mplisth = NULL; 4313*fcf3ce44SJohn Forte 4314*fcf3ce44SJohn Forte if (wwn_list == NULL || multipath_list == NULL || devpath == NULL) { 4315*fcf3ce44SJohn Forte return (L_NULL_WWN_LIST); 4316*fcf3ce44SJohn Forte } 4317*fcf3ce44SJohn Forte 4318*fcf3ce44SJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 4319*fcf3ce44SJohn Forte return (L_DEV_SNAPSHOT_FAILED); 4320*fcf3ce44SJohn Forte } 4321*fcf3ce44SJohn Forte 4322*fcf3ce44SJohn Forte if ((err = g_devid_get(devpath, &devid, root, SSD_DRVR_NAME)) != 0) { 4323*fcf3ce44SJohn Forte di_fini(root); 4324*fcf3ce44SJohn Forte return (err); 4325*fcf3ce44SJohn Forte } 4326*fcf3ce44SJohn Forte 4327*fcf3ce44SJohn Forte *multipath_list = (struct dlist *)NULL; 4328*fcf3ce44SJohn Forte if ((err = devid_get_all(devid, root, SSD_DRVR_NAME, &mplisth)) != 0) { 4329*fcf3ce44SJohn Forte di_fini(root); 4330*fcf3ce44SJohn Forte return (err); 4331*fcf3ce44SJohn Forte } 4332*fcf3ce44SJohn Forte 4333*fcf3ce44SJohn Forte if (mplisth == NULL) { 4334*fcf3ce44SJohn Forte di_fini(root); 4335*fcf3ce44SJohn Forte return (L_NULL_WWN_LIST); 4336*fcf3ce44SJohn Forte } 4337*fcf3ce44SJohn Forte 4338*fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL; 4339*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 4340*fcf3ce44SJohn Forte /* 4341*fcf3ce44SJohn Forte * When a path is found from the list, load the logical 4342*fcf3ce44SJohn Forte * and physical dev path 4343*fcf3ce44SJohn Forte */ 4344*fcf3ce44SJohn Forte for (mplistp = mplisth; mplistp != NULL; 4345*fcf3ce44SJohn Forte mplistp = mplistp->next) { 4346*fcf3ce44SJohn Forte if (strncmp(mplistp->devpath, wwn_list_ptr->physical_path, 4347*fcf3ce44SJohn Forte strlen(mplistp->devpath)) == 0) { 4348*fcf3ce44SJohn Forte 4349*fcf3ce44SJohn Forte /* Load multipath list */ 4350*fcf3ce44SJohn Forte if ((dl = (struct dlist *) 4351*fcf3ce44SJohn Forte calloc(1, sizeof (struct dlist))) == NULL) { 4352*fcf3ce44SJohn Forte while (*multipath_list != NULL) { 4353*fcf3ce44SJohn Forte dl = dlt->next; 4354*fcf3ce44SJohn Forte g_destroy_data(dlt); 4355*fcf3ce44SJohn Forte dlt = dl; 4356*fcf3ce44SJohn Forte } 4357*fcf3ce44SJohn Forte di_fini(root); 4358*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 4359*fcf3ce44SJohn Forte } 4360*fcf3ce44SJohn Forte H_DPRINTF(" g_get_multipath: Found multipath=%s\n", 4361*fcf3ce44SJohn Forte wwn_list_ptr->physical_path); 4362*fcf3ce44SJohn Forte dl->logical_path = strdup(wwn_list_ptr->logical_path); 4363*fcf3ce44SJohn Forte dl->dev_path = strdup(wwn_list_ptr->physical_path); 4364*fcf3ce44SJohn Forte if (*multipath_list == NULL) { 4365*fcf3ce44SJohn Forte *multipath_list = dlt = dl; 4366*fcf3ce44SJohn Forte } else { 4367*fcf3ce44SJohn Forte dlt->next = dl; 4368*fcf3ce44SJohn Forte dl->prev = dlt; 4369*fcf3ce44SJohn Forte dlt = dl; 4370*fcf3ce44SJohn Forte } 4371*fcf3ce44SJohn Forte } 4372*fcf3ce44SJohn Forte } 4373*fcf3ce44SJohn Forte } 4374*fcf3ce44SJohn Forte di_fini(root); 4375*fcf3ce44SJohn Forte mplist_free(mplisth); 4376*fcf3ce44SJohn Forte return (0); 4377*fcf3ce44SJohn Forte } 4378*fcf3ce44SJohn Forte 4379*fcf3ce44SJohn Forte int 4380*fcf3ce44SJohn Forte get_multipath(char *devpath, struct dlist **multipath_list, 4381*fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list) 4382*fcf3ce44SJohn Forte { 4383*fcf3ce44SJohn Forte WWN_list *wwn_list_ptr; 4384*fcf3ce44SJohn Forte struct dlist *dl, *dlt; 4385*fcf3ce44SJohn Forte char path[MAXPATHLEN], m_phys_path[MAXPATHLEN], *ptr; 4386*fcf3ce44SJohn Forte int len; 4387*fcf3ce44SJohn Forte int lun_a = -1; 4388*fcf3ce44SJohn Forte char node_wwn_s[WWN_S_LEN]; 4389*fcf3ce44SJohn Forte 4390*fcf3ce44SJohn Forte if (devpath == NULL) { 4391*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4392*fcf3ce44SJohn Forte } 4393*fcf3ce44SJohn Forte 4394*fcf3ce44SJohn Forte /* Strip partition information. */ 4395*fcf3ce44SJohn Forte if ((ptr = strrchr(devpath, ':')) != NULL) { 4396*fcf3ce44SJohn Forte len = strlen(devpath) - strlen(ptr); 4397*fcf3ce44SJohn Forte (void) strncpy(path, devpath, len); 4398*fcf3ce44SJohn Forte path[len] = '\0'; 4399*fcf3ce44SJohn Forte } else { 4400*fcf3ce44SJohn Forte (void) strcpy(path, devpath); 4401*fcf3ce44SJohn Forte } 4402*fcf3ce44SJohn Forte 4403*fcf3ce44SJohn Forte *multipath_list = dl = dlt = (struct dlist *)NULL; 4404*fcf3ce44SJohn Forte 4405*fcf3ce44SJohn Forte 4406*fcf3ce44SJohn Forte if (wwn_list == NULL) { 4407*fcf3ce44SJohn Forte return (L_NULL_WWN_LIST); 4408*fcf3ce44SJohn Forte } 4409*fcf3ce44SJohn Forte 4410*fcf3ce44SJohn Forte for (*node_wwn_s = NULL, wwn_list_ptr = wwn_list; 4411*fcf3ce44SJohn Forte wwn_list_ptr != NULL; 4412*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 4413*fcf3ce44SJohn Forte 4414*fcf3ce44SJohn Forte if ((ptr = strrchr(wwn_list_ptr->physical_path, ':')) != NULL) { 4415*fcf3ce44SJohn Forte len = strlen(wwn_list_ptr->physical_path) - strlen(ptr); 4416*fcf3ce44SJohn Forte (void) strncpy(m_phys_path, wwn_list_ptr->physical_path, 4417*fcf3ce44SJohn Forte len); 4418*fcf3ce44SJohn Forte m_phys_path[len] = '\0'; 4419*fcf3ce44SJohn Forte } else { 4420*fcf3ce44SJohn Forte (void) strcpy(m_phys_path, wwn_list_ptr->physical_path); 4421*fcf3ce44SJohn Forte } 4422*fcf3ce44SJohn Forte 4423*fcf3ce44SJohn Forte if (strcasecmp(m_phys_path, path) == 0) { 4424*fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, wwn_list_ptr->node_wwn_s); 4425*fcf3ce44SJohn Forte break; 4426*fcf3ce44SJohn Forte } 4427*fcf3ce44SJohn Forte } 4428*fcf3ce44SJohn Forte 4429*fcf3ce44SJohn Forte if (*node_wwn_s == NULL) { 4430*fcf3ce44SJohn Forte H_DPRINTF("node_wwn_s is NULL!\n"); 4431*fcf3ce44SJohn Forte return (L_NO_NODE_WWN_IN_WWNLIST); 4432*fcf3ce44SJohn Forte } 4433*fcf3ce44SJohn Forte 4434*fcf3ce44SJohn Forte lun_a = g_get_lun_number(wwn_list_ptr->physical_path); 4435*fcf3ce44SJohn Forte 4436*fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL; 4437*fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) { 4438*fcf3ce44SJohn Forte if ((strcmp(node_wwn_s, wwn_list_ptr->node_wwn_s) == 0) && 4439*fcf3ce44SJohn Forte ((lun_a < 0) || (lun_a == 4440*fcf3ce44SJohn Forte g_get_lun_number(wwn_list_ptr->physical_path)))) { 4441*fcf3ce44SJohn Forte 4442*fcf3ce44SJohn Forte if ((dl = (struct dlist *) 4443*fcf3ce44SJohn Forte g_zalloc(sizeof (struct dlist))) == NULL) { 4444*fcf3ce44SJohn Forte while (*multipath_list != NULL) { 4445*fcf3ce44SJohn Forte dl = dlt->next; 4446*fcf3ce44SJohn Forte (void) g_destroy_data(dlt); 4447*fcf3ce44SJohn Forte dlt = dl; 4448*fcf3ce44SJohn Forte } 4449*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 4450*fcf3ce44SJohn Forte } 4451*fcf3ce44SJohn Forte H_DPRINTF(" g_get_multipath: Found multipath=%s\n", 4452*fcf3ce44SJohn Forte wwn_list_ptr->physical_path); 4453*fcf3ce44SJohn Forte dl->dev_path = strdup(wwn_list_ptr->physical_path); 4454*fcf3ce44SJohn Forte dl->logical_path = strdup(wwn_list_ptr->logical_path); 4455*fcf3ce44SJohn Forte if (*multipath_list == NULL) { 4456*fcf3ce44SJohn Forte *multipath_list = dlt = dl; 4457*fcf3ce44SJohn Forte } else { 4458*fcf3ce44SJohn Forte dlt->next = dl; 4459*fcf3ce44SJohn Forte dl->prev = dlt; 4460*fcf3ce44SJohn Forte dlt = dl; 4461*fcf3ce44SJohn Forte } 4462*fcf3ce44SJohn Forte } 4463*fcf3ce44SJohn Forte } 4464*fcf3ce44SJohn Forte return (0); 4465*fcf3ce44SJohn Forte } 4466*fcf3ce44SJohn Forte 4467*fcf3ce44SJohn Forte /* 4468*fcf3ce44SJohn Forte * Free a multipath list 4469*fcf3ce44SJohn Forte * 4470*fcf3ce44SJohn Forte */ 4471*fcf3ce44SJohn Forte void 4472*fcf3ce44SJohn Forte g_free_multipath(struct dlist *dlh) 4473*fcf3ce44SJohn Forte { 4474*fcf3ce44SJohn Forte struct dlist *dl; 4475*fcf3ce44SJohn Forte 4476*fcf3ce44SJohn Forte while (dlh != NULL) { 4477*fcf3ce44SJohn Forte dl = dlh->next; 4478*fcf3ce44SJohn Forte if (dlh->dev_path != NULL) 4479*fcf3ce44SJohn Forte (void) g_destroy_data(dlh->dev_path); 4480*fcf3ce44SJohn Forte if (dlh->logical_path != NULL) 4481*fcf3ce44SJohn Forte (void) g_destroy_data(dlh->logical_path); 4482*fcf3ce44SJohn Forte (void) g_destroy_data(dlh); 4483*fcf3ce44SJohn Forte dlh = dl; 4484*fcf3ce44SJohn Forte } 4485*fcf3ce44SJohn Forte } 4486*fcf3ce44SJohn Forte 4487*fcf3ce44SJohn Forte 4488*fcf3ce44SJohn Forte 4489*fcf3ce44SJohn Forte /* 4490*fcf3ce44SJohn Forte * Get the path to the nexus (HBA) driver. 4491*fcf3ce44SJohn Forte * This assumes the path looks something like this: 4492*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 4493*fcf3ce44SJohn Forte * or maybe this 4494*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0 4495*fcf3ce44SJohn Forte * or 4496*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0 4497*fcf3ce44SJohn Forte * or 4498*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 4499*fcf3ce44SJohn Forte * or 4500*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 4501*fcf3ce44SJohn Forte * (or "qlc" instead of "socal" and "fp" for "sf") 4502*fcf3ce44SJohn Forte * 4503*fcf3ce44SJohn Forte * Which should resolve to a path like this: 4504*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 4505*fcf3ce44SJohn Forte * or 4506*fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5 4507*fcf3ce44SJohn Forte * 4508*fcf3ce44SJohn Forte * or 4509*fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0 4510*fcf3ce44SJohn Forte * which should resolve to 4511*fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1:devctl 4512*fcf3ce44SJohn Forte */ 4513*fcf3ce44SJohn Forte int 4514*fcf3ce44SJohn Forte g_get_nexus_path(char *path_phys, char **nexus_path) 4515*fcf3ce44SJohn Forte { 4516*fcf3ce44SJohn Forte uchar_t port = 0; 4517*fcf3ce44SJohn Forte int port_flag = 0, i = 0, pathcnt = 1; 4518*fcf3ce44SJohn Forte char *char_ptr; 4519*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN]; 4520*fcf3ce44SJohn Forte char buf[MAXPATHLEN]; 4521*fcf3ce44SJohn Forte char temp_buf[MAXPATHLEN]; 4522*fcf3ce44SJohn Forte struct stat stbuf; 4523*fcf3ce44SJohn Forte uint_t path_type; 4524*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 4525*fcf3ce44SJohn Forte int p_on = 0, p_st = 0; 4526*fcf3ce44SJohn Forte 4527*fcf3ce44SJohn Forte /* return invalid path if the path_phys is NULL */ 4528*fcf3ce44SJohn Forte if (path_phys == NULL) { 4529*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4530*fcf3ce44SJohn Forte } 4531*fcf3ce44SJohn Forte 4532*fcf3ce44SJohn Forte *nexus_path = NULL; 4533*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path_phys); 4534*fcf3ce44SJohn Forte 4535*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI)) { 4536*fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) { 4537*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4538*fcf3ce44SJohn Forte } 4539*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 4540*fcf3ce44SJohn Forte p_on = p_st = 0; 4541*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 4542*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 4543*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 4544*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 4545*fcf3ce44SJohn Forte p_on = i; 4546*fcf3ce44SJohn Forte break; 4547*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 4548*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 4549*fcf3ce44SJohn Forte p_st = i; 4550*fcf3ce44SJohn Forte } 4551*fcf3ce44SJohn Forte } 4552*fcf3ce44SJohn Forte } 4553*fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state == 4554*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 4555*fcf3ce44SJohn Forte /* on_line path */ 4556*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 4557*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 4558*fcf3ce44SJohn Forte } else { 4559*fcf3ce44SJohn Forte /* standby or path0 */ 4560*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 4561*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 4562*fcf3ce44SJohn Forte } 4563*fcf3ce44SJohn Forte free(pathlist.path_info); 4564*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 4565*fcf3ce44SJohn Forte } else { 4566*fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) || strstr(drvr_path, 4567*fcf3ce44SJohn Forte DRV_NAME_ST) || strstr(drvr_path, SES_NAME)) { 4568*fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) { 4569*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4570*fcf3ce44SJohn Forte } 4571*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */ 4572*fcf3ce44SJohn Forte } 4573*fcf3ce44SJohn Forte 4574*fcf3ce44SJohn Forte path_type = g_get_path_type(drvr_path); 4575*fcf3ce44SJohn Forte 4576*fcf3ce44SJohn Forte if (path_type & FC4_SF_XPORT) { 4577*fcf3ce44SJohn Forte 4578*fcf3ce44SJohn Forte /* sf driver in path so capture the port # */ 4579*fcf3ce44SJohn Forte if ((char_ptr = strstr(drvr_path, "sf@")) == NULL) { 4580*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4581*fcf3ce44SJohn Forte } 4582*fcf3ce44SJohn Forte port = atoi(char_ptr + 3); 4583*fcf3ce44SJohn Forte if (port > 1) { 4584*fcf3ce44SJohn Forte return (L_INVLD_PORT_IN_PATH); 4585*fcf3ce44SJohn Forte } 4586*fcf3ce44SJohn Forte 4587*fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) { 4588*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4589*fcf3ce44SJohn Forte } 4590*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */ 4591*fcf3ce44SJohn Forte port_flag++; 4592*fcf3ce44SJohn Forte 4593*fcf3ce44SJohn Forte L_DPRINTF(" g_get_nexus_path:" 4594*fcf3ce44SJohn Forte " sf driver in path so use port #%d.\n", 4595*fcf3ce44SJohn Forte port); 4596*fcf3ce44SJohn Forte } else if (path_type & FC_GEN_XPORT) { 4597*fcf3ce44SJohn Forte /* 4598*fcf3ce44SJohn Forte * check to see if it 3rd party vendor FCA. 4599*fcf3ce44SJohn Forte * if it is return error for this operation since 4600*fcf3ce44SJohn Forte * we don't know how they creates FCA port related minor node. 4601*fcf3ce44SJohn Forte * 4602*fcf3ce44SJohn Forte * As of now there is no supported operation on FCA node so 4603*fcf3ce44SJohn Forte * this should be okay. 4604*fcf3ce44SJohn Forte */ 4605*fcf3ce44SJohn Forte if ((path_type & FC_FCA_MASK) == FC_FCA_MASK) { 4606*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 4607*fcf3ce44SJohn Forte } 4608*fcf3ce44SJohn Forte /* 4609*fcf3ce44SJohn Forte * For current Sun FCA driver, appending 4610*fcf3ce44SJohn Forte * port # doesn't work. Just remove transport layer from 4611*fcf3ce44SJohn Forte * input path. 4612*fcf3ce44SJohn Forte */ 4613*fcf3ce44SJohn Forte if ((char_ptr = strstr(drvr_path, "/fp@")) == NULL) { 4614*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4615*fcf3ce44SJohn Forte } 4616*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */ 4617*fcf3ce44SJohn Forte } 4618*fcf3ce44SJohn Forte 4619*fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) != 0) { 4620*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 4621*fcf3ce44SJohn Forte } 4622*fcf3ce44SJohn Forte 4623*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 4624*fcf3ce44SJohn Forte /* 4625*fcf3ce44SJohn Forte * Found a directory. 4626*fcf3ce44SJohn Forte * Now append a port number or devctl to the path. 4627*fcf3ce44SJohn Forte */ 4628*fcf3ce44SJohn Forte if (port_flag) { 4629*fcf3ce44SJohn Forte /* append port */ 4630*fcf3ce44SJohn Forte (void) sprintf(buf, ":%d", port); 4631*fcf3ce44SJohn Forte } else { 4632*fcf3ce44SJohn Forte /* Try adding port 0 and see if node exists. */ 4633*fcf3ce44SJohn Forte (void) sprintf(temp_buf, "%s:0", drvr_path); 4634*fcf3ce44SJohn Forte if (stat(temp_buf, &stbuf) != 0) { 4635*fcf3ce44SJohn Forte /* 4636*fcf3ce44SJohn Forte * Path we guessed at does not 4637*fcf3ce44SJohn Forte * exist so it may be a driver 4638*fcf3ce44SJohn Forte * that ends in :devctl. 4639*fcf3ce44SJohn Forte */ 4640*fcf3ce44SJohn Forte (void) sprintf(buf, ":devctl"); 4641*fcf3ce44SJohn Forte } else { 4642*fcf3ce44SJohn Forte /* 4643*fcf3ce44SJohn Forte * The path that was entered 4644*fcf3ce44SJohn Forte * did not include a port number 4645*fcf3ce44SJohn Forte * so the port was set to zero, and 4646*fcf3ce44SJohn Forte * then checked. The default path 4647*fcf3ce44SJohn Forte * did exist. 4648*fcf3ce44SJohn Forte */ 4649*fcf3ce44SJohn Forte ER_DPRINTF("Since a complete path" 4650*fcf3ce44SJohn Forte " was not supplied " 4651*fcf3ce44SJohn Forte "a default path is being" 4652*fcf3ce44SJohn Forte " used:\n %s\n", 4653*fcf3ce44SJohn Forte temp_buf); 4654*fcf3ce44SJohn Forte (void) sprintf(buf, ":0"); 4655*fcf3ce44SJohn Forte } 4656*fcf3ce44SJohn Forte } 4657*fcf3ce44SJohn Forte 4658*fcf3ce44SJohn Forte (void) strcat(drvr_path, buf); 4659*fcf3ce44SJohn Forte } 4660*fcf3ce44SJohn Forte 4661*fcf3ce44SJohn Forte } 4662*fcf3ce44SJohn Forte *nexus_path = g_alloc_string(drvr_path); 4663*fcf3ce44SJohn Forte L_DPRINTF(" g_get_nexus_path: Nexus path = %s\n", drvr_path); 4664*fcf3ce44SJohn Forte return (0); 4665*fcf3ce44SJohn Forte } 4666*fcf3ce44SJohn Forte 4667*fcf3ce44SJohn Forte 4668*fcf3ce44SJohn Forte /* 4669*fcf3ce44SJohn Forte * Get the FC topology for the input device or nexus(HBA) path. 4670*fcf3ce44SJohn Forte * 4671*fcf3ce44SJohn Forte * The routine calls g_get_path_type to determine the stack of 4672*fcf3ce44SJohn Forte * the input path. 4673*fcf3ce44SJohn Forte * 4674*fcf3ce44SJohn Forte * If it a socal path 4675*fcf3ce44SJohn Forte * it returns FC_TOP_PRIVATE_LOOP 4676*fcf3ce44SJohn Forte * else 4677*fcf3ce44SJohn Forte * calls fc_get_topology ioctl to 4678*fcf3ce44SJohn Forte * get the fp topolgy from the driver. 4679*fcf3ce44SJohn Forte * 4680*fcf3ce44SJohn Forte * INPUTS: 4681*fcf3ce44SJohn Forte * path - a string of device path, transport path. 4682*fcf3ce44SJohn Forte * NOTE: "path" SHOULD NOT BE OPEN BEFORE CALLING 4683*fcf3ce44SJohn Forte * THIS FUNCTION BECAUSE THIS FUNCTION DOES 4684*fcf3ce44SJohn Forte * AN "O_EXCL" OPEN. 4685*fcf3ce44SJohn Forte * port_top - a pointer to the toplogy type. 4686*fcf3ce44SJohn Forte * 4687*fcf3ce44SJohn Forte * RETURNS: 4688*fcf3ce44SJohn Forte * 0 if there is no error. 4689*fcf3ce44SJohn Forte * error code. 4690*fcf3ce44SJohn Forte * 4691*fcf3ce44SJohn Forte * The input path is expected to be something like below: 4692*fcf3ce44SJohn Forte * 1) 4693*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 4694*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ssd@.. 4695*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0 4696*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0 4697*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 4698*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 4699*fcf3ce44SJohn Forte * (or "qlc" instead of "socal" and "fp" for "sf") 4700*fcf3ce44SJohn Forte * 4701*fcf3ce44SJohn Forte * Which should resolve to a path like this: 4702*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 4703*fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5 4704*fcf3ce44SJohn Forte * 4705*fcf3ce44SJohn Forte * 2) 4706*fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0 4707*fcf3ce44SJohn Forte * which should resolve to 4708*fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1:devctl 4709*fcf3ce44SJohn Forte * 4710*fcf3ce44SJohn Forte * 3) The nexus(hba or nexus) path will get an error only for qlc 4711*fcf3ce44SJohn Forte * since the routine need to open fp :devctl node for fcio ioctl. 4712*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0 4713*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1 4714*fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5 => error 4715*fcf3ce44SJohn Forte */ 4716*fcf3ce44SJohn Forte int 4717*fcf3ce44SJohn Forte g_get_fca_port_topology(char *path, uint32_t *port_top, int verbose) 4718*fcf3ce44SJohn Forte { 4719*fcf3ce44SJohn Forte fcio_t fcio; 4720*fcf3ce44SJohn Forte int fd, i = 0, pathcnt = 1; 4721*fcf3ce44SJohn Forte char drvr_path[MAXPATHLEN]; 4722*fcf3ce44SJohn Forte char *char_ptr; 4723*fcf3ce44SJohn Forte struct stat stbuf; 4724*fcf3ce44SJohn Forte uint_t dev_type; 4725*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 4726*fcf3ce44SJohn Forte int p_on = 0, p_st = 0; 4727*fcf3ce44SJohn Forte 4728*fcf3ce44SJohn Forte /* return invalid path if the path is NULL */ 4729*fcf3ce44SJohn Forte if (path == NULL) { 4730*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4731*fcf3ce44SJohn Forte } 4732*fcf3ce44SJohn Forte /* return invalid arg if the argument is NULL */ 4733*fcf3ce44SJohn Forte if (port_top == NULL) { 4734*fcf3ce44SJohn Forte return (L_INVALID_ARG); 4735*fcf3ce44SJohn Forte } 4736*fcf3ce44SJohn Forte 4737*fcf3ce44SJohn Forte (void) strcpy(drvr_path, path); 4738*fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) { 4739*fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) { 4740*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4741*fcf3ce44SJohn Forte } 4742*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 4743*fcf3ce44SJohn Forte p_on = p_st = 0; 4744*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 4745*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) { 4746*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 4747*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 4748*fcf3ce44SJohn Forte p_on = i; 4749*fcf3ce44SJohn Forte break; 4750*fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state == 4751*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 4752*fcf3ce44SJohn Forte p_st = i; 4753*fcf3ce44SJohn Forte } 4754*fcf3ce44SJohn Forte } 4755*fcf3ce44SJohn Forte } 4756*fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state == 4757*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 4758*fcf3ce44SJohn Forte /* on_line path */ 4759*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 4760*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 4761*fcf3ce44SJohn Forte } else { 4762*fcf3ce44SJohn Forte /* standby or path0 */ 4763*fcf3ce44SJohn Forte (void) strcpy(drvr_path, 4764*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 4765*fcf3ce44SJohn Forte } 4766*fcf3ce44SJohn Forte free(pathlist.path_info); 4767*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 4768*fcf3ce44SJohn Forte } else { 4769*fcf3ce44SJohn Forte /* 4770*fcf3ce44SJohn Forte * Get the path to the :devctl driver 4771*fcf3ce44SJohn Forte * 4772*fcf3ce44SJohn Forte * This assumes the path looks something like this: 4773*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0 4774*fcf3ce44SJohn Forte * or 4775*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0 4776*fcf3ce44SJohn Forte * or 4777*fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl 4778*fcf3ce44SJohn Forte * or 4779*fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl 4780*fcf3ce44SJohn Forte * (or "qlc" in the place of "socal" and "fp" for "sf") 4781*fcf3ce44SJohn Forte * 4782*fcf3ce44SJohn Forte * The dir below doesn't have corresponding :devctl node. 4783*fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5 4784*fcf3ce44SJohn Forte * /devices/sbus@2,0/SUNW,socal@1,0 4785*fcf3ce44SJohn Forte * 4786*fcf3ce44SJohn Forte */ 4787*fcf3ce44SJohn Forte if ((strstr(drvr_path, DRV_NAME_SSD) || 4788*fcf3ce44SJohn Forte strstr(drvr_path, SES_NAME)) || 4789*fcf3ce44SJohn Forte strstr(drvr_path, DRV_NAME_ST)) { 4790*fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) { 4791*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4792*fcf3ce44SJohn Forte } 4793*fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */ 4794*fcf3ce44SJohn Forte /* append controller */ 4795*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 4796*fcf3ce44SJohn Forte } else { 4797*fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) { 4798*fcf3ce44SJohn Forte return (L_LSTAT_ERROR); 4799*fcf3ce44SJohn Forte } 4800*fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 4801*fcf3ce44SJohn Forte /* append controller */ 4802*fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR); 4803*fcf3ce44SJohn Forte } 4804*fcf3ce44SJohn Forte } 4805*fcf3ce44SJohn Forte } 4806*fcf3ce44SJohn Forte 4807*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(drvr_path)) == 0) { 4808*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4809*fcf3ce44SJohn Forte } 4810*fcf3ce44SJohn Forte 4811*fcf3ce44SJohn Forte if ((dev_type & FC4_XPORT_MASK) || (dev_type & FC4_FCA_MASK)) { 4812*fcf3ce44SJohn Forte *port_top = FC_TOP_PRIVATE_LOOP; 4813*fcf3ce44SJohn Forte return (0); 4814*fcf3ce44SJohn Forte } 4815*fcf3ce44SJohn Forte 4816*fcf3ce44SJohn Forte /* To contiue the path type should be fp :devctl node */ 4817*fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) { 4818*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4819*fcf3ce44SJohn Forte } 4820*fcf3ce44SJohn Forte 4821*fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) 4822*fcf3ce44SJohn Forte return (errno); 4823*fcf3ce44SJohn Forte 4824*fcf3ce44SJohn Forte P_DPRINTF(" g_get_fca_port_topology: Geting topology from:" 4825*fcf3ce44SJohn Forte " %s\n", drvr_path); 4826*fcf3ce44SJohn Forte 4827*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_TOPOLOGY; 4828*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t); 4829*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 4830*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)port_top; 4831*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) { 4832*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_TOPOLOGY ioctl failed.\n"); 4833*fcf3ce44SJohn Forte close(fd); 4834*fcf3ce44SJohn Forte return (L_FCIO_GET_TOPOLOGY_FAIL); 4835*fcf3ce44SJohn Forte } 4836*fcf3ce44SJohn Forte close(fd); 4837*fcf3ce44SJohn Forte return (0); 4838*fcf3ce44SJohn Forte } 4839*fcf3ce44SJohn Forte 4840*fcf3ce44SJohn Forte 4841*fcf3ce44SJohn Forte /* 4842*fcf3ce44SJohn Forte * This functions enables or disables a FCA port depending on the 4843*fcf3ce44SJohn Forte * argument, cmd, passed to it. If cmd is PORT_OFFLINE, the function 4844*fcf3ce44SJohn Forte * tries to disable the port specified by the argument 'phys_path'. If 4845*fcf3ce44SJohn Forte * cmd is PORT_ONLINE, the function tries to enable the port specified 4846*fcf3ce44SJohn Forte * by the argument 'phys_path'. 4847*fcf3ce44SJohn Forte * INPUTS : 4848*fcf3ce44SJohn Forte * nexus_port_ptr - Pointer to the nexus path of the FCA port to 4849*fcf3ce44SJohn Forte * operate on 4850*fcf3ce44SJohn Forte * cmd - PORT_OFFLINE or PORT_ONLINE 4851*fcf3ce44SJohn Forte * RETURNS : 4852*fcf3ce44SJohn Forte * 0 on success and non-zero otherwise 4853*fcf3ce44SJohn Forte */ 4854*fcf3ce44SJohn Forte static int 4855*fcf3ce44SJohn Forte g_set_port_state(char *nexus_port_ptr, int cmd) 4856*fcf3ce44SJohn Forte { 4857*fcf3ce44SJohn Forte int path_type, fd; 4858*fcf3ce44SJohn Forte 4859*fcf3ce44SJohn Forte if ((path_type = g_get_path_type(nexus_port_ptr)) == 0) { 4860*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4861*fcf3ce44SJohn Forte } 4862*fcf3ce44SJohn Forte 4863*fcf3ce44SJohn Forte if ((fd = g_object_open(nexus_port_ptr, O_NDELAY|O_RDONLY)) == -1) { 4864*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4865*fcf3ce44SJohn Forte } 4866*fcf3ce44SJohn Forte 4867*fcf3ce44SJohn Forte switch (cmd) { 4868*fcf3ce44SJohn Forte case PORT_OFFLINE: 4869*fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) { 4870*fcf3ce44SJohn Forte /* 4871*fcf3ce44SJohn Forte * Socal/sf drivers - 4872*fcf3ce44SJohn Forte * The socal driver currently returns EFAULT 4873*fcf3ce44SJohn Forte * even if the ioctl has completed successfully. 4874*fcf3ce44SJohn Forte */ 4875*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_INTERNAL, 4876*fcf3ce44SJohn Forte NULL) == -1) { 4877*fcf3ce44SJohn Forte close(fd); 4878*fcf3ce44SJohn Forte return (L_PORT_OFFLINE_FAIL); 4879*fcf3ce44SJohn Forte } 4880*fcf3ce44SJohn Forte } else { 4881*fcf3ce44SJohn Forte /* 4882*fcf3ce44SJohn Forte * QLogic card - 4883*fcf3ce44SJohn Forte * Can't do much here since the driver currently 4884*fcf3ce44SJohn Forte * doesn't support this feature. We'll just fail 4885*fcf3ce44SJohn Forte * for now. Support can be added when the driver 4886*fcf3ce44SJohn Forte * is enabled with the feature at a later date. 4887*fcf3ce44SJohn Forte */ 4888*fcf3ce44SJohn Forte close(fd); 4889*fcf3ce44SJohn Forte return (L_PORT_OFFLINE_UNSUPPORTED); 4890*fcf3ce44SJohn Forte } 4891*fcf3ce44SJohn Forte break; 4892*fcf3ce44SJohn Forte case PORT_ONLINE: 4893*fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) { 4894*fcf3ce44SJohn Forte /* 4895*fcf3ce44SJohn Forte * Socal/sf drivers 4896*fcf3ce44SJohn Forte * The socal driver currently returns EFAULT 4897*fcf3ce44SJohn Forte * even if the ioctl has completed successfully. 4898*fcf3ce44SJohn Forte */ 4899*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) { 4900*fcf3ce44SJohn Forte close(fd); 4901*fcf3ce44SJohn Forte return (L_PORT_ONLINE_FAIL); 4902*fcf3ce44SJohn Forte } 4903*fcf3ce44SJohn Forte } else { 4904*fcf3ce44SJohn Forte /* 4905*fcf3ce44SJohn Forte * QLogic card - 4906*fcf3ce44SJohn Forte * Can't do much here since the driver currently 4907*fcf3ce44SJohn Forte * doesn't support this feature. We'll just fail 4908*fcf3ce44SJohn Forte * for now. Support can be added when the driver 4909*fcf3ce44SJohn Forte * is enabled with the feature at a later date. 4910*fcf3ce44SJohn Forte */ 4911*fcf3ce44SJohn Forte close(fd); 4912*fcf3ce44SJohn Forte return (L_PORT_ONLINE_UNSUPPORTED); 4913*fcf3ce44SJohn Forte } 4914*fcf3ce44SJohn Forte break; 4915*fcf3ce44SJohn Forte default: 4916*fcf3ce44SJohn Forte close(fd); 4917*fcf3ce44SJohn Forte return (-1); 4918*fcf3ce44SJohn Forte } 4919*fcf3ce44SJohn Forte close(fd); 4920*fcf3ce44SJohn Forte return (0); 4921*fcf3ce44SJohn Forte } 4922*fcf3ce44SJohn Forte 4923*fcf3ce44SJohn Forte /* 4924*fcf3ce44SJohn Forte * The interfaces defined below (g_port_offline() and g_port_online()) 4925*fcf3ce44SJohn Forte * are what will be exposed to applications. We will hide g_set_port_state(). 4926*fcf3ce44SJohn Forte * They have to be functions (as against macros) because making them 4927*fcf3ce44SJohn Forte * macros will mean exposing g_set_port_state() and we dont want to do that 4928*fcf3ce44SJohn Forte */ 4929*fcf3ce44SJohn Forte 4930*fcf3ce44SJohn Forte int 4931*fcf3ce44SJohn Forte g_port_offline(char *path) 4932*fcf3ce44SJohn Forte { 4933*fcf3ce44SJohn Forte return (g_set_port_state(path, PORT_OFFLINE)); 4934*fcf3ce44SJohn Forte } 4935*fcf3ce44SJohn Forte 4936*fcf3ce44SJohn Forte int 4937*fcf3ce44SJohn Forte g_port_online(char *path) 4938*fcf3ce44SJohn Forte { 4939*fcf3ce44SJohn Forte return (g_set_port_state(path, PORT_ONLINE)); 4940*fcf3ce44SJohn Forte } 4941*fcf3ce44SJohn Forte 4942*fcf3ce44SJohn Forte /* 4943*fcf3ce44SJohn Forte * This function sets the loopback mode for a port on a HBA 4944*fcf3ce44SJohn Forte * INPUTS : 4945*fcf3ce44SJohn Forte * portpath - Pointer to the path of the FCA port on which to 4946*fcf3ce44SJohn Forte * set the loopback mode 4947*fcf3ce44SJohn Forte * cmd - EXT_LPBACK 4948*fcf3ce44SJohn Forte * INT_LPBACK 4949*fcf3ce44SJohn Forte * NO_LPBACK 4950*fcf3ce44SJohn Forte * RETURNS : 4951*fcf3ce44SJohn Forte * 0 on success and non-zero otherwise 4952*fcf3ce44SJohn Forte */ 4953*fcf3ce44SJohn Forte int 4954*fcf3ce44SJohn Forte g_loopback_mode(char *portpath, int cmd) 4955*fcf3ce44SJohn Forte { 4956*fcf3ce44SJohn Forte int path_type, fd; 4957*fcf3ce44SJohn Forte 4958*fcf3ce44SJohn Forte if ((path_type = g_get_path_type(portpath)) == 0) { 4959*fcf3ce44SJohn Forte return (L_INVALID_PATH); 4960*fcf3ce44SJohn Forte } 4961*fcf3ce44SJohn Forte 4962*fcf3ce44SJohn Forte if ((fd = g_object_open(portpath, O_NDELAY|O_RDONLY|O_EXCL)) == -1) { 4963*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 4964*fcf3ce44SJohn Forte } 4965*fcf3ce44SJohn Forte 4966*fcf3ce44SJohn Forte /* 4967*fcf3ce44SJohn Forte * The loopback calls are currently not fully supported 4968*fcf3ce44SJohn Forte * via fp. 4969*fcf3ce44SJohn Forte * 4970*fcf3ce44SJohn Forte * A fp based general solution is required to support Leadville FCAs 4971*fcf3ce44SJohn Forte * including Qlgc and 3rd party FCA. As of now qlgc provides 4972*fcf3ce44SJohn Forte * some diag functions like echo through qlc private ioctl 4973*fcf3ce44SJohn Forte * which is not supproted by luxadm and libraries. 4974*fcf3ce44SJohn Forte */ 4975*fcf3ce44SJohn Forte switch (cmd) { 4976*fcf3ce44SJohn Forte case EXT_LPBACK: 4977*fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) { 4978*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_MANUAL, 4979*fcf3ce44SJohn Forte NULL) == -1) { 4980*fcf3ce44SJohn Forte /* Check for previous mode set */ 4981*fcf3ce44SJohn Forte if (errno != EALREADY) { 4982*fcf3ce44SJohn Forte close(fd); 4983*fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED); 4984*fcf3ce44SJohn Forte } 4985*fcf3ce44SJohn Forte } 4986*fcf3ce44SJohn Forte } else { 4987*fcf3ce44SJohn Forte /* 4988*fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so.. 4989*fcf3ce44SJohn Forte */ 4990*fcf3ce44SJohn Forte close(fd); 4991*fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED); 4992*fcf3ce44SJohn Forte } 4993*fcf3ce44SJohn Forte break; 4994*fcf3ce44SJohn Forte case NO_LPBACK: 4995*fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) { 4996*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) { 4997*fcf3ce44SJohn Forte close(fd); 4998*fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED); 4999*fcf3ce44SJohn Forte } 5000*fcf3ce44SJohn Forte } else { 5001*fcf3ce44SJohn Forte /* 5002*fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so.. 5003*fcf3ce44SJohn Forte */ 5004*fcf3ce44SJohn Forte close(fd); 5005*fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED); 5006*fcf3ce44SJohn Forte } 5007*fcf3ce44SJohn Forte break; 5008*fcf3ce44SJohn Forte case INT_LPBACK: 5009*fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) { 5010*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_INTERNAL, 5011*fcf3ce44SJohn Forte NULL) == -1) { 5012*fcf3ce44SJohn Forte /* Check for previous mode set */ 5013*fcf3ce44SJohn Forte if (errno != EALREADY) { 5014*fcf3ce44SJohn Forte close(fd); 5015*fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED); 5016*fcf3ce44SJohn Forte } 5017*fcf3ce44SJohn Forte } 5018*fcf3ce44SJohn Forte } else { 5019*fcf3ce44SJohn Forte /* 5020*fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so.. 5021*fcf3ce44SJohn Forte */ 5022*fcf3ce44SJohn Forte close(fd); 5023*fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED); 5024*fcf3ce44SJohn Forte } 5025*fcf3ce44SJohn Forte break; 5026*fcf3ce44SJohn Forte default: 5027*fcf3ce44SJohn Forte close(fd); 5028*fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED); 5029*fcf3ce44SJohn Forte } 5030*fcf3ce44SJohn Forte close(fd); 5031*fcf3ce44SJohn Forte return (0); 5032*fcf3ce44SJohn Forte } 5033*fcf3ce44SJohn Forte 5034*fcf3ce44SJohn Forte /* 5035*fcf3ce44SJohn Forte * g_get_port_state(char *portpath, int port_state) 5036*fcf3ce44SJohn Forte * Purpose: Get port state for a path 5037*fcf3ce44SJohn Forte * Input: portpath 5038*fcf3ce44SJohn Forte * set to path of port 5039*fcf3ce44SJohn Forte * Output: port_state 5040*fcf3ce44SJohn Forte * Set to one of the following: 5041*fcf3ce44SJohn Forte * PORT_CONNECTED 5042*fcf3ce44SJohn Forte * PORT_NOTCONNECTED 5043*fcf3ce44SJohn Forte * Returns: 0 on success 5044*fcf3ce44SJohn Forte * non-zero on failure 5045*fcf3ce44SJohn Forte */ 5046*fcf3ce44SJohn Forte int 5047*fcf3ce44SJohn Forte g_get_port_state(char *portpath, int *portstate, int verbose) 5048*fcf3ce44SJohn Forte { 5049*fcf3ce44SJohn Forte int fd, err, num_devices = 0; 5050*fcf3ce44SJohn Forte struct lilpmap map; 5051*fcf3ce44SJohn Forte uint_t dev_type; 5052*fcf3ce44SJohn Forte gfc_dev_t map_root; 5053*fcf3ce44SJohn Forte 5054*fcf3ce44SJohn Forte 5055*fcf3ce44SJohn Forte (void) memset(&map, 0, sizeof (struct lilpmap)); 5056*fcf3ce44SJohn Forte 5057*fcf3ce44SJohn Forte /* return invalid path if portpath is NULL */ 5058*fcf3ce44SJohn Forte if (portpath == NULL) { 5059*fcf3ce44SJohn Forte return (L_INVALID_PATH); 5060*fcf3ce44SJohn Forte } 5061*fcf3ce44SJohn Forte /* return invalid arg if argument is NULL */ 5062*fcf3ce44SJohn Forte if ((portpath == NULL) || (portstate == NULL)) { 5063*fcf3ce44SJohn Forte return (L_INVALID_ARG); 5064*fcf3ce44SJohn Forte } 5065*fcf3ce44SJohn Forte 5066*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(portpath)) == 0) { 5067*fcf3ce44SJohn Forte return (L_INVALID_PATH); 5068*fcf3ce44SJohn Forte } 5069*fcf3ce44SJohn Forte 5070*fcf3ce44SJohn Forte /* 5071*fcf3ce44SJohn Forte * FCIO_GETMAP returns error when there are * no devices attached. 5072*fcf3ce44SJohn Forte * ENOMEM is returned when no devices are attached. 5073*fcf3ce44SJohn Forte * g_get_first_dev returns NULL without error when there is no 5074*fcf3ce44SJohn Forte * devices are attached. 5075*fcf3ce44SJohn Forte */ 5076*fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) { 5077*fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(portpath, &err, 5078*fcf3ce44SJohn Forte MAP_XPORT_PROP_ONLY)) == NULL) { 5079*fcf3ce44SJohn Forte return (err); 5080*fcf3ce44SJohn Forte } 5081*fcf3ce44SJohn Forte 5082*fcf3ce44SJohn Forte if (g_get_first_dev(map_root, &err) == NULL) { 5083*fcf3ce44SJohn Forte /* no device is found if err == 0 */ 5084*fcf3ce44SJohn Forte if (err == L_NO_SUCH_DEV_FOUND) { 5085*fcf3ce44SJohn Forte *portstate = PORT_NOTCONNECTED; 5086*fcf3ce44SJohn Forte } 5087*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 5088*fcf3ce44SJohn Forte return (0); 5089*fcf3ce44SJohn Forte } else { 5090*fcf3ce44SJohn Forte /* Device found okay */ 5091*fcf3ce44SJohn Forte *portstate = PORT_CONNECTED; 5092*fcf3ce44SJohn Forte g_dev_map_fini(map_root); 5093*fcf3ce44SJohn Forte } 5094*fcf3ce44SJohn Forte 5095*fcf3ce44SJohn Forte } else { 5096*fcf3ce44SJohn Forte /* open controller */ 5097*fcf3ce44SJohn Forte if ((fd = g_object_open(portpath, O_NDELAY | O_RDONLY)) == -1) { 5098*fcf3ce44SJohn Forte return (errno); 5099*fcf3ce44SJohn Forte } 5100*fcf3ce44SJohn Forte 5101*fcf3ce44SJohn Forte /* 5102*fcf3ce44SJohn Forte * Note: There is only one error returned by this ioctl. ENOMEM. 5103*fcf3ce44SJohn Forte * Hence the lack of return on error. 5104*fcf3ce44SJohn Forte */ 5105*fcf3ce44SJohn Forte if (ioctl(fd, FCIO_GETMAP, &map) != 0) { 5106*fcf3ce44SJohn Forte map.lilp_length = 0; 5107*fcf3ce44SJohn Forte } 5108*fcf3ce44SJohn Forte num_devices = map.lilp_length; 5109*fcf3ce44SJohn Forte 5110*fcf3ce44SJohn Forte /* Non-Leadville stacks report the FCA in the count */ 5111*fcf3ce44SJohn Forte *portstate = (num_devices > 1) ? PORT_CONNECTED : 5112*fcf3ce44SJohn Forte PORT_NOTCONNECTED; 5113*fcf3ce44SJohn Forte (void) close(fd); 5114*fcf3ce44SJohn Forte } 5115*fcf3ce44SJohn Forte return (0); 5116*fcf3ce44SJohn Forte } 5117*fcf3ce44SJohn Forte 5118*fcf3ce44SJohn Forte /* 5119*fcf3ce44SJohn Forte * g_dev_login(char *port_path, la_wwn_t port_wwn) 5120*fcf3ce44SJohn Forte * Purpose: port login via g_dev_log_in_out() 5121*fcf3ce44SJohn Forte * Input: port_path 5122*fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology 5123*fcf3ce44SJohn Forte * port_wwn 5124*fcf3ce44SJohn Forte * port wwn of device node to login 5125*fcf3ce44SJohn Forte * 5126*fcf3ce44SJohn Forte * Returns: return code from g_dev_log_in_out() 5127*fcf3ce44SJohn Forte */ 5128*fcf3ce44SJohn Forte int 5129*fcf3ce44SJohn Forte g_dev_login(char *port_path, la_wwn_t port_wwn) 5130*fcf3ce44SJohn Forte { 5131*fcf3ce44SJohn Forte return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGIN)); 5132*fcf3ce44SJohn Forte } 5133*fcf3ce44SJohn Forte 5134*fcf3ce44SJohn Forte 5135*fcf3ce44SJohn Forte /* 5136*fcf3ce44SJohn Forte * g_dev_logout(char *port_path, la_wwn_t port_wwn) 5137*fcf3ce44SJohn Forte * Purpose: port login via g_dev_log_in_out() 5138*fcf3ce44SJohn Forte * Input: port_path 5139*fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology 5140*fcf3ce44SJohn Forte * port_wwn 5141*fcf3ce44SJohn Forte * port wwn of device node to logout 5142*fcf3ce44SJohn Forte * 5143*fcf3ce44SJohn Forte * Returns: return code from g_dev_log_in_out() 5144*fcf3ce44SJohn Forte */ 5145*fcf3ce44SJohn Forte int 5146*fcf3ce44SJohn Forte g_dev_logout(char *port_path, la_wwn_t port_wwn) 5147*fcf3ce44SJohn Forte { 5148*fcf3ce44SJohn Forte return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGOUT)); 5149*fcf3ce44SJohn Forte } 5150*fcf3ce44SJohn Forte 5151*fcf3ce44SJohn Forte 5152*fcf3ce44SJohn Forte /* 5153*fcf3ce44SJohn Forte * g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd) 5154*fcf3ce44SJohn Forte * Purpose: port login via FCIO_DEV_LOGOUT and port logout via FCIO_DEV_LOGOUT 5155*fcf3ce44SJohn Forte * IOCTL requires EXCLUSIVE open. 5156*fcf3ce44SJohn Forte * Input: port_path 5157*fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology 5158*fcf3ce44SJohn Forte * port_wwn 5159*fcf3ce44SJohn Forte * port wwn of device node to logout 5160*fcf3ce44SJohn Forte * cmd 5161*fcf3ce44SJohn Forte * FCIO_DEV_LOGON or FCIO_DEV_LOGOUT 5162*fcf3ce44SJohn Forte * 5163*fcf3ce44SJohn Forte * Returns: 0 on success 5164*fcf3ce44SJohn Forte * non-zero on failure 5165*fcf3ce44SJohn Forte */ 5166*fcf3ce44SJohn Forte static int 5167*fcf3ce44SJohn Forte g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd) 5168*fcf3ce44SJohn Forte { 5169*fcf3ce44SJohn Forte int fd, err; 5170*fcf3ce44SJohn Forte uint32_t hba_port_top; 5171*fcf3ce44SJohn Forte fcio_t fcio; 5172*fcf3ce44SJohn Forte int verbose = 0; 5173*fcf3ce44SJohn Forte 5174*fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(port_path, 5175*fcf3ce44SJohn Forte &hba_port_top, verbose)) != 0) { 5176*fcf3ce44SJohn Forte return (err); 5177*fcf3ce44SJohn Forte } 5178*fcf3ce44SJohn Forte 5179*fcf3ce44SJohn Forte if (!((hba_port_top == FC_TOP_PUBLIC_LOOP) || 5180*fcf3ce44SJohn Forte (hba_port_top == FC_TOP_FABRIC))) { 5181*fcf3ce44SJohn Forte return (L_OPNOSUPP_ON_TOPOLOGY); 5182*fcf3ce44SJohn Forte } 5183*fcf3ce44SJohn Forte 5184*fcf3ce44SJohn Forte /* open controller */ 5185*fcf3ce44SJohn Forte if ((fd = g_object_open(port_path, O_NDELAY | O_RDONLY | O_EXCL)) == -1) 5186*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 5187*fcf3ce44SJohn Forte 5188*fcf3ce44SJohn Forte /* 5189*fcf3ce44SJohn Forte * stores port_wwn to la_wwn_t raw_wwn field 5190*fcf3ce44SJohn Forte * and construct fcio structures for FCIO_DEV_LOGIN. 5191*fcf3ce44SJohn Forte */ 5192*fcf3ce44SJohn Forte fcio.fcio_cmd = cmd; 5193*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (port_wwn); 5194*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&port_wwn; 5195*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 5196*fcf3ce44SJohn Forte fcio.fcio_olen = fcio.fcio_alen = 0; 5197*fcf3ce44SJohn Forte fcio.fcio_obuf = fcio.fcio_abuf = NULL; 5198*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) { 5199*fcf3ce44SJohn Forte I_DPRINTF((cmd == FCIO_DEV_LOGIN) ? 5200*fcf3ce44SJohn Forte " FCIO_DEV_LOGIN ioctl failed.\n" 5201*fcf3ce44SJohn Forte : " FCIO_DEV_LOGOUT ioctl failed.\n"); 5202*fcf3ce44SJohn Forte (void) close(fd); 5203*fcf3ce44SJohn Forte return ((cmd == FCIO_DEV_LOGIN) ? 5204*fcf3ce44SJohn Forte L_FCIO_DEV_LOGIN_FAIL 5205*fcf3ce44SJohn Forte : L_FCIO_DEV_LOGOUT_FAIL); 5206*fcf3ce44SJohn Forte } else { 5207*fcf3ce44SJohn Forte (void) close(fd); 5208*fcf3ce44SJohn Forte return (0); 5209*fcf3ce44SJohn Forte } 5210*fcf3ce44SJohn Forte } 5211*fcf3ce44SJohn Forte 5212*fcf3ce44SJohn Forte /* 5213*fcf3ce44SJohn Forte * This function will verify if a FC device (represented by input WWN 5214*fcf3ce44SJohn Forte * is connected on a FCA port by searching the device list from 5215*fcf3ce44SJohn Forte * g_get_dev_list() for a WWN match. 5216*fcf3ce44SJohn Forte * 5217*fcf3ce44SJohn Forte * input: 5218*fcf3ce44SJohn Forte * fca_path: pointer to the physical path string, path to a fp node. 5219*fcf3ce44SJohn Forte * possible forms are 5220*fcf3ce44SJohn Forte * /devices/pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0:devctl 5221*fcf3ce44SJohn Forte * dev_wwn: WWN string 5222*fcf3ce44SJohn Forte * flag: indicate that the input WWN is node or port 5223*fcf3ce44SJohn Forte * 5224*fcf3ce44SJohn Forte * returned values 5225*fcf3ce44SJohn Forte * 0: if a match is found. 5226*fcf3ce44SJohn Forte * L_WWN_NOT_FOUND_IN_DEV_LIST: if no match found 5227*fcf3ce44SJohn Forte * L_UNEXPECTED_FC_TOPOLOGY: existing error code for an error 5228*fcf3ce44SJohn Forte * from the topology checking of the input fca path. 5229*fcf3ce44SJohn Forte * L_MALLOC_FAILED: existing error code for allocation eror from the 5230*fcf3ce44SJohn Forte * g_get_dev_list(). 5231*fcf3ce44SJohn Forte * L_FCIO_GETMAP_IOCTL_FAIL: existing error code for an error from the 5232*fcf3ce44SJohn Forte * FCIO ioctl called by the g_get_dev_list() 5233*fcf3ce44SJohn Forte * -1: other failure 5234*fcf3ce44SJohn Forte * 5235*fcf3ce44SJohn Forte */ 5236*fcf3ce44SJohn Forte int 5237*fcf3ce44SJohn Forte g_wwn_in_dev_list(char *fca_path, la_wwn_t dev_wwn, int flag) 5238*fcf3ce44SJohn Forte { 5239*fcf3ce44SJohn Forte uint_t dev_type; 5240*fcf3ce44SJohn Forte int i, err; 5241*fcf3ce44SJohn Forte fc_port_dev_t *dev_list; 5242*fcf3ce44SJohn Forte fc_port_dev_t *dev_list_save; 5243*fcf3ce44SJohn Forte int num_devices = 0; 5244*fcf3ce44SJohn Forte 5245*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fca_path)) == 0) { 5246*fcf3ce44SJohn Forte return (L_INVALID_PATH); 5247*fcf3ce44SJohn Forte } 5248*fcf3ce44SJohn Forte 5249*fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) { 5250*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 5251*fcf3ce44SJohn Forte } 5252*fcf3ce44SJohn Forte 5253*fcf3ce44SJohn Forte if (((err = g_get_dev_list(fca_path, &dev_list, &num_devices)) 5254*fcf3ce44SJohn Forte != 0) && (err != L_GET_DEV_LIST_ULP_FAILURE)) { 5255*fcf3ce44SJohn Forte return (err); 5256*fcf3ce44SJohn Forte } 5257*fcf3ce44SJohn Forte 5258*fcf3ce44SJohn Forte dev_list_save = dev_list; 5259*fcf3ce44SJohn Forte 5260*fcf3ce44SJohn Forte switch (flag) { 5261*fcf3ce44SJohn Forte case MATCH_NODE_WWN: 5262*fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_list++) { 5263*fcf3ce44SJohn Forte if (memcmp(dev_list->dev_nwwn.raw_wwn, 5264*fcf3ce44SJohn Forte dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) { 5265*fcf3ce44SJohn Forte (void) free(dev_list_save); 5266*fcf3ce44SJohn Forte return (0); 5267*fcf3ce44SJohn Forte } 5268*fcf3ce44SJohn Forte } 5269*fcf3ce44SJohn Forte (void) free(dev_list_save); 5270*fcf3ce44SJohn Forte /* consider a new error code for not found. */ 5271*fcf3ce44SJohn Forte return (L_WWN_NOT_FOUND_IN_DEV_LIST); 5272*fcf3ce44SJohn Forte 5273*fcf3ce44SJohn Forte case MATCH_PORT_WWN: 5274*fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_list++) { 5275*fcf3ce44SJohn Forte if (memcmp(dev_list->dev_pwwn.raw_wwn, 5276*fcf3ce44SJohn Forte dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) { 5277*fcf3ce44SJohn Forte (void) free(dev_list_save); 5278*fcf3ce44SJohn Forte return (0); 5279*fcf3ce44SJohn Forte } 5280*fcf3ce44SJohn Forte } 5281*fcf3ce44SJohn Forte (void) free(dev_list_save); 5282*fcf3ce44SJohn Forte /* consider a new error code for not found. */ 5283*fcf3ce44SJohn Forte return (L_WWN_NOT_FOUND_IN_DEV_LIST); 5284*fcf3ce44SJohn Forte } 5285*fcf3ce44SJohn Forte (void) free(dev_list_save); 5286*fcf3ce44SJohn Forte return (-1); 5287*fcf3ce44SJohn Forte } 5288*fcf3ce44SJohn Forte 5289*fcf3ce44SJohn Forte 5290*fcf3ce44SJohn Forte /* 5291*fcf3ce44SJohn Forte * g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state) 5292*fcf3ce44SJohn Forte * Purpose: get the state of device port login via FCIO_GET_STATE ioctl. 5293*fcf3ce44SJohn Forte * 5294*fcf3ce44SJohn Forte * Input: fca_path 5295*fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology 5296*fcf3ce44SJohn Forte * port_wwn 5297*fcf3ce44SJohn Forte * port wwn of device node to logout 5298*fcf3ce44SJohn Forte * state 5299*fcf3ce44SJohn Forte * port login or not 5300*fcf3ce44SJohn Forte * 5301*fcf3ce44SJohn Forte * Returns: 0 on success 5302*fcf3ce44SJohn Forte * non-zero on failure 5303*fcf3ce44SJohn Forte */ 5304*fcf3ce44SJohn Forte static int 5305*fcf3ce44SJohn Forte g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state) 5306*fcf3ce44SJohn Forte { 5307*fcf3ce44SJohn Forte int fd; 5308*fcf3ce44SJohn Forte int dev_type; 5309*fcf3ce44SJohn Forte fcio_t fcio; 5310*fcf3ce44SJohn Forte int verbose = 0; 5311*fcf3ce44SJohn Forte 5312*fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fca_path)) == 0) { 5313*fcf3ce44SJohn Forte return (L_INVALID_PATH); 5314*fcf3ce44SJohn Forte } 5315*fcf3ce44SJohn Forte 5316*fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) { 5317*fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE); 5318*fcf3ce44SJohn Forte } 5319*fcf3ce44SJohn Forte 5320*fcf3ce44SJohn Forte /* open controller */ 5321*fcf3ce44SJohn Forte if ((fd = g_object_open(fca_path, O_NDELAY | O_RDONLY)) == -1) 5322*fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL); 5323*fcf3ce44SJohn Forte 5324*fcf3ce44SJohn Forte /* 5325*fcf3ce44SJohn Forte * stores port_wwn to la_wwn_t raw_wwn field 5326*fcf3ce44SJohn Forte * and construct fcio structures for FCIO_DEV_LOGIN. 5327*fcf3ce44SJohn Forte */ 5328*fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_STATE; 5329*fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (port_wwn); 5330*fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&port_wwn; 5331*fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ | FCIO_XFER_WRITE; 5332*fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t); 5333*fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)state; 5334*fcf3ce44SJohn Forte fcio.fcio_alen = 0; 5335*fcf3ce44SJohn Forte fcio.fcio_abuf = NULL; 5336*fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) { 5337*fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_STATE ioctl failed.\n"); 5338*fcf3ce44SJohn Forte (void) close(fd); 5339*fcf3ce44SJohn Forte return (L_FCIO_GET_STATE_FAIL); 5340*fcf3ce44SJohn Forte } else { 5341*fcf3ce44SJohn Forte (void) close(fd); 5342*fcf3ce44SJohn Forte return (0); 5343*fcf3ce44SJohn Forte } 5344*fcf3ce44SJohn Forte } 5345*fcf3ce44SJohn Forte 5346*fcf3ce44SJohn Forte /* 5347*fcf3ce44SJohn Forte * Name: lilp_map_cmp 5348*fcf3ce44SJohn Forte * 5349*fcf3ce44SJohn Forte * Description: This function is used to compare the physical location 5350*fcf3ce44SJohn Forte * of to fc devices in a gfc_map_t.dev_addr arrary. 5351*fcf3ce44SJohn Forte * 5352*fcf3ce44SJohn Forte * Params: 5353*fcf3ce44SJohn Forte * First device to compare 5354*fcf3ce44SJohn Forte * Second device to compare 5355*fcf3ce44SJohn Forte * 5356*fcf3ce44SJohn Forte * Return: 5357*fcf3ce44SJohn Forte * 0 = Devices at equal phyiscal location, How did this happen? 5358*fcf3ce44SJohn Forte * >0 = First device have a higher physical location than second 5359*fcf3ce44SJohn Forte * <0 = Second device have a higher physical location than first 5360*fcf3ce44SJohn Forte */ 5361*fcf3ce44SJohn Forte static int lilp_map_cmp(const void* dev1, const void* dev2) { 5362*fcf3ce44SJohn Forte int i_dev1 = ((fc_port_dev_t *)dev1)->dev_did.priv_lilp_posit; 5363*fcf3ce44SJohn Forte int i_dev2 = ((fc_port_dev_t *)dev2)->dev_did.priv_lilp_posit; 5364*fcf3ce44SJohn Forte 5365*fcf3ce44SJohn Forte if (i_dev1 > i_dev2) 5366*fcf3ce44SJohn Forte return (1); 5367*fcf3ce44SJohn Forte if (i_dev1 < i_dev2) 5368*fcf3ce44SJohn Forte return (-1); 5369*fcf3ce44SJohn Forte return (0); 5370*fcf3ce44SJohn Forte } 5371*fcf3ce44SJohn Forte 5372*fcf3ce44SJohn Forte /* 5373*fcf3ce44SJohn Forte * Description: 5374*fcf3ce44SJohn Forte * Retrieves multiple paths to a device based on devid 5375*fcf3ce44SJohn Forte * Caller must use mplist_free to free mplist structure 5376*fcf3ce44SJohn Forte * This currently only supports ssd devices. 5377*fcf3ce44SJohn Forte * The st driver does not register a device id. 5378*fcf3ce44SJohn Forte * 5379*fcf3ce44SJohn Forte * Input Values: 5380*fcf3ce44SJohn Forte * 5381*fcf3ce44SJohn Forte * devid: ptr to valid ddi_devid_t struct 5382*fcf3ce44SJohn Forte * root: root handle to device tree snapshot 5383*fcf3ce44SJohn Forte * drvr_name: driver name to start the node tree search 5384*fcf3ce44SJohn Forte * 5385*fcf3ce44SJohn Forte * Return Value: 5386*fcf3ce44SJohn Forte * 0 on success 5387*fcf3ce44SJohn Forte * non-zero on failure 5388*fcf3ce44SJohn Forte */ 5389*fcf3ce44SJohn Forte 5390*fcf3ce44SJohn Forte static int 5391*fcf3ce44SJohn Forte devid_get_all(ddi_devid_t devid, di_node_t root, char *drvr_name, 5392*fcf3ce44SJohn Forte struct mplist_struct **mplistp) 5393*fcf3ce44SJohn Forte { 5394*fcf3ce44SJohn Forte ddi_devid_t mydevid; 5395*fcf3ce44SJohn Forte di_node_t node; 5396*fcf3ce44SJohn Forte char *devfs_path = NULL; 5397*fcf3ce44SJohn Forte struct mplist_struct *mpl, *mpln; 5398*fcf3ce44SJohn Forte 5399*fcf3ce44SJohn Forte if (devid == NULL || root == NULL || drvr_name == NULL || 5400*fcf3ce44SJohn Forte mplistp == NULL || 5401*fcf3ce44SJohn Forte (strncmp(drvr_name, SSD_DRVR_NAME, strlen(SSD_DRVR_NAME)) 5402*fcf3ce44SJohn Forte != 0)) { 5403*fcf3ce44SJohn Forte return (EINVAL); 5404*fcf3ce44SJohn Forte } 5405*fcf3ce44SJohn Forte 5406*fcf3ce44SJohn Forte *mplistp = mpl = mpln = (struct mplist_struct *)NULL; 5407*fcf3ce44SJohn Forte 5408*fcf3ce44SJohn Forte /* point to first node which matches portdrvr */ 5409*fcf3ce44SJohn Forte node = di_drv_first_node(drvr_name, root); 5410*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) { 5411*fcf3ce44SJohn Forte return (L_NO_DRIVER_NODES_FOUND); 5412*fcf3ce44SJohn Forte } 5413*fcf3ce44SJohn Forte 5414*fcf3ce44SJohn Forte while (node != DI_NODE_NIL) { 5415*fcf3ce44SJohn Forte if ((mydevid = di_devid(node)) != NULL) { 5416*fcf3ce44SJohn Forte if (((devid_compare(mydevid, devid)) == 0)) { 5417*fcf3ce44SJohn Forte /* Load multipath list */ 5418*fcf3ce44SJohn Forte if ((mpl = (struct mplist_struct *) 5419*fcf3ce44SJohn Forte calloc(1, sizeof (struct mplist_struct))) 5420*fcf3ce44SJohn Forte == NULL) { 5421*fcf3ce44SJohn Forte mplist_free(*mplistp); 5422*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 5423*fcf3ce44SJohn Forte } 5424*fcf3ce44SJohn Forte if ((devfs_path = my_devfs_path(node)) == NULL) { 5425*fcf3ce44SJohn Forte node = di_drv_next_node(node); 5426*fcf3ce44SJohn Forte S_FREE(mpl); 5427*fcf3ce44SJohn Forte continue; 5428*fcf3ce44SJohn Forte } 5429*fcf3ce44SJohn Forte mpl->devpath = (char *)calloc(1, 5430*fcf3ce44SJohn Forte strlen(devfs_path) + 5431*fcf3ce44SJohn Forte strlen(SSD_MINOR_NAME) + 1); 5432*fcf3ce44SJohn Forte if (mpl->devpath == NULL) { 5433*fcf3ce44SJohn Forte S_FREE(mpl); 5434*fcf3ce44SJohn Forte mplist_free(*mplistp); 5435*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5436*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 5437*fcf3ce44SJohn Forte } 5438*fcf3ce44SJohn Forte sprintf(mpl->devpath, "%s%s", devfs_path, 5439*fcf3ce44SJohn Forte SSD_MINOR_NAME); 5440*fcf3ce44SJohn Forte if (*mplistp == NULL) { 5441*fcf3ce44SJohn Forte *mplistp = mpln = mpl; 5442*fcf3ce44SJohn Forte } else { 5443*fcf3ce44SJohn Forte mpln->next = mpl; 5444*fcf3ce44SJohn Forte mpln = mpl; 5445*fcf3ce44SJohn Forte } 5446*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5447*fcf3ce44SJohn Forte } 5448*fcf3ce44SJohn Forte } 5449*fcf3ce44SJohn Forte node = di_drv_next_node(node); 5450*fcf3ce44SJohn Forte } 5451*fcf3ce44SJohn Forte return (0); 5452*fcf3ce44SJohn Forte } 5453*fcf3ce44SJohn Forte 5454*fcf3ce44SJohn Forte /* 5455*fcf3ce44SJohn Forte * Frees a previously allocated mplist_struct 5456*fcf3ce44SJohn Forte */ 5457*fcf3ce44SJohn Forte static void 5458*fcf3ce44SJohn Forte mplist_free(struct mplist_struct *mplistp) 5459*fcf3ce44SJohn Forte { 5460*fcf3ce44SJohn Forte struct mplist_struct *mplistn; 5461*fcf3ce44SJohn Forte 5462*fcf3ce44SJohn Forte while (mplistp != NULL) { 5463*fcf3ce44SJohn Forte mplistn = mplistp->next; 5464*fcf3ce44SJohn Forte if (mplistp->devpath != NULL) { 5465*fcf3ce44SJohn Forte free(mplistp->devpath); 5466*fcf3ce44SJohn Forte mplistp->devpath = NULL; 5467*fcf3ce44SJohn Forte } 5468*fcf3ce44SJohn Forte free(mplistp); 5469*fcf3ce44SJohn Forte mplistp = mplistn; 5470*fcf3ce44SJohn Forte } 5471*fcf3ce44SJohn Forte } 5472*fcf3ce44SJohn Forte 5473*fcf3ce44SJohn Forte /* 5474*fcf3ce44SJohn Forte * Description 5475*fcf3ce44SJohn Forte * Retrieves all device nodes based on drvr_name 5476*fcf3ce44SJohn Forte * Currently supports SSD_DRVR_NAME, ST_DRVR_NAME 5477*fcf3ce44SJohn Forte * There will be a device node in the libdevinfo 5478*fcf3ce44SJohn Forte * snapshot only if there is at least one node bound. 5479*fcf3ce44SJohn Forte * 5480*fcf3ce44SJohn Forte * Input values: 5481*fcf3ce44SJohn Forte * root valid snapshot handle from di_init(3DEVINFO) 5482*fcf3ce44SJohn Forte * drvr_name name of driver to start node search 5483*fcf3ce44SJohn Forte * wwn_list_ptr ptr to ptr to WWN_list struct 5484*fcf3ce44SJohn Forte * 5485*fcf3ce44SJohn Forte * 5486*fcf3ce44SJohn Forte */ 5487*fcf3ce44SJohn Forte static int 5488*fcf3ce44SJohn Forte devices_get_all(di_node_t root, char *drvr_name, char *minor_name, 5489*fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_ptr) 5490*fcf3ce44SJohn Forte { 5491*fcf3ce44SJohn Forte di_node_t node; 5492*fcf3ce44SJohn Forte char *devfs_path; 5493*fcf3ce44SJohn Forte char devicepath[MAXPATHLEN]; 5494*fcf3ce44SJohn Forte uchar_t *nwwn = NULL, *pwwn = NULL; 5495*fcf3ce44SJohn Forte uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE]; 5496*fcf3ce44SJohn Forte WWN_list *wwn_list, *l1, *l2; 5497*fcf3ce44SJohn Forte int scsi_vhci = 0; 5498*fcf3ce44SJohn Forte int err, devtype; 5499*fcf3ce44SJohn Forte 5500*fcf3ce44SJohn Forte if (root == DI_NODE_NIL || drvr_name == NULL || 5501*fcf3ce44SJohn Forte wwn_list_ptr == NULL) { 5502*fcf3ce44SJohn Forte return (EINVAL); 5503*fcf3ce44SJohn Forte } 5504*fcf3ce44SJohn Forte 5505*fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr = NULL; 5506*fcf3ce44SJohn Forte 5507*fcf3ce44SJohn Forte memset(port_wwn, 0, sizeof (port_wwn)); 5508*fcf3ce44SJohn Forte memset(node_wwn, 0, sizeof (node_wwn)); 5509*fcf3ce44SJohn Forte 5510*fcf3ce44SJohn Forte if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) { 5511*fcf3ce44SJohn Forte devtype = DTYPE_DIRECT; 5512*fcf3ce44SJohn Forte } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) { 5513*fcf3ce44SJohn Forte devtype = DTYPE_SEQUENTIAL; 5514*fcf3ce44SJohn Forte } else { 5515*fcf3ce44SJohn Forte /* 5516*fcf3ce44SJohn Forte * An unsupported driver name was passed in 5517*fcf3ce44SJohn Forte */ 5518*fcf3ce44SJohn Forte return (L_DRIVER_NOTSUPP); 5519*fcf3ce44SJohn Forte } 5520*fcf3ce44SJohn Forte 5521*fcf3ce44SJohn Forte /* point to first node which matches portdrvr */ 5522*fcf3ce44SJohn Forte node = di_drv_first_node(drvr_name, root); 5523*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) { 5524*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 5525*fcf3ce44SJohn Forte } 5526*fcf3ce44SJohn Forte 5527*fcf3ce44SJohn Forte while (node != DI_NODE_NIL) { 5528*fcf3ce44SJohn Forte 5529*fcf3ce44SJohn Forte if ((devfs_path = my_devfs_path(node)) != NULL) { 5530*fcf3ce44SJohn Forte 5531*fcf3ce44SJohn Forte /* 5532*fcf3ce44SJohn Forte * Check for offline state 5533*fcf3ce44SJohn Forte */ 5534*fcf3ce44SJohn Forte if ((di_state(node) & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE) { 5535*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5536*fcf3ce44SJohn Forte node = di_drv_next_node(node); 5537*fcf3ce44SJohn Forte continue; 5538*fcf3ce44SJohn Forte } 5539*fcf3ce44SJohn Forte 5540*fcf3ce44SJohn Forte /* 5541*fcf3ce44SJohn Forte * Only support st, ssd nodes 5542*fcf3ce44SJohn Forte */ 5543*fcf3ce44SJohn Forte if (!strstr(devfs_path, SLSH_DRV_NAME_SSD) && 5544*fcf3ce44SJohn Forte !strstr(devfs_path, SLSH_DRV_NAME_ST)) { 5545*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5546*fcf3ce44SJohn Forte node = di_drv_next_node(node); 5547*fcf3ce44SJohn Forte continue; 5548*fcf3ce44SJohn Forte } 5549*fcf3ce44SJohn Forte 5550*fcf3ce44SJohn Forte devicepath[0] = '\0'; 5551*fcf3ce44SJohn Forte 5552*fcf3ce44SJohn Forte /* 5553*fcf3ce44SJohn Forte * form device path 5554*fcf3ce44SJohn Forte */ 5555*fcf3ce44SJohn Forte sprintf(devicepath, "%s%s", devfs_path, minor_name); 5556*fcf3ce44SJohn Forte 5557*fcf3ce44SJohn Forte if ((strstr(devicepath, SCSI_VHCI) == NULL)) { 5558*fcf3ce44SJohn Forte if ((err = get_wwn_data(node, &nwwn, &pwwn)) != 0) { 5559*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5560*fcf3ce44SJohn Forte return (err); 5561*fcf3ce44SJohn Forte } else { 5562*fcf3ce44SJohn Forte memcpy(node_wwn, nwwn, sizeof (node_wwn)); 5563*fcf3ce44SJohn Forte memcpy(port_wwn, pwwn, sizeof (port_wwn)); 5564*fcf3ce44SJohn Forte } 5565*fcf3ce44SJohn Forte } else { 5566*fcf3ce44SJohn Forte /* 5567*fcf3ce44SJohn Forte * Clear values for SCSI VHCI devices. 5568*fcf3ce44SJohn Forte * node wwn, port wwn are irrevelant at 5569*fcf3ce44SJohn Forte * the SCSI VHCI level 5570*fcf3ce44SJohn Forte */ 5571*fcf3ce44SJohn Forte scsi_vhci++; 5572*fcf3ce44SJohn Forte memset(port_wwn, 0, sizeof (port_wwn)); 5573*fcf3ce44SJohn Forte memset(node_wwn, 0, sizeof (node_wwn)); 5574*fcf3ce44SJohn Forte } 5575*fcf3ce44SJohn Forte 5576*fcf3ce44SJohn Forte /* Got wwns, load data in list */ 5577*fcf3ce44SJohn Forte if ((l2 = (struct wwn_list_struct *) 5578*fcf3ce44SJohn Forte calloc(1, sizeof (struct wwn_list_struct))) == NULL) { 5579*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5580*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 5581*fcf3ce44SJohn Forte } 5582*fcf3ce44SJohn Forte if ((l2->physical_path = (char *) 5583*fcf3ce44SJohn Forte calloc(1, strlen(devicepath) +1)) == NULL) { 5584*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5585*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 5586*fcf3ce44SJohn Forte } 5587*fcf3ce44SJohn Forte 5588*fcf3ce44SJohn Forte memcpy(l2->w_node_wwn, node_wwn, WWN_SIZE); 5589*fcf3ce44SJohn Forte 5590*fcf3ce44SJohn Forte if (scsi_vhci) { 5591*fcf3ce44SJohn Forte strcpy(l2->node_wwn_s, MSGSTR(12000, "N/A")); 5592*fcf3ce44SJohn Forte } else { 5593*fcf3ce44SJohn Forte copy_wwn_data_to_str(l2->node_wwn_s, node_wwn); 5594*fcf3ce44SJohn Forte copy_wwn_data_to_str(l2->port_wwn_s, port_wwn); 5595*fcf3ce44SJohn Forte } 5596*fcf3ce44SJohn Forte 5597*fcf3ce44SJohn Forte strcpy(l2->physical_path, devicepath); 5598*fcf3ce44SJohn Forte 5599*fcf3ce44SJohn Forte l2->device_type = devtype; 5600*fcf3ce44SJohn Forte if (wwn_list == NULL) { 5601*fcf3ce44SJohn Forte l1 = wwn_list = l2; 5602*fcf3ce44SJohn Forte } else { 5603*fcf3ce44SJohn Forte l2->wwn_prev = l1; 5604*fcf3ce44SJohn Forte l1 = l1->wwn_next = l2; 5605*fcf3ce44SJohn Forte } 5606*fcf3ce44SJohn Forte my_devfs_path_free(devfs_path); 5607*fcf3ce44SJohn Forte scsi_vhci = 0; 5608*fcf3ce44SJohn Forte } 5609*fcf3ce44SJohn Forte node = di_drv_next_node(node); 5610*fcf3ce44SJohn Forte } 5611*fcf3ce44SJohn Forte 5612*fcf3ce44SJohn Forte *wwn_list_ptr = wwn_list; /* pass back ptr to list */ 5613*fcf3ce44SJohn Forte 5614*fcf3ce44SJohn Forte if (*wwn_list_ptr == NULL) { 5615*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 5616*fcf3ce44SJohn Forte } else { 5617*fcf3ce44SJohn Forte /* 5618*fcf3ce44SJohn Forte * Now load the /dev/ paths 5619*fcf3ce44SJohn Forte */ 5620*fcf3ce44SJohn Forte if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) { 5621*fcf3ce44SJohn Forte if ((err = get_dev_path(wwn_list_ptr, DEV_RDIR, 5622*fcf3ce44SJohn Forte DIR_MATCH_SSD)) != 0) { 5623*fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr); 5624*fcf3ce44SJohn Forte return (err); 5625*fcf3ce44SJohn Forte } 5626*fcf3ce44SJohn Forte } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) { 5627*fcf3ce44SJohn Forte if ((err = get_dev_path(wwn_list_ptr, DEV_TAPE_DIR, 5628*fcf3ce44SJohn Forte DIR_MATCH_ST)) != 0) { 5629*fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr); 5630*fcf3ce44SJohn Forte return (err); 5631*fcf3ce44SJohn Forte } 5632*fcf3ce44SJohn Forte } 5633*fcf3ce44SJohn Forte return (0); 5634*fcf3ce44SJohn Forte } 5635*fcf3ce44SJohn Forte } 5636*fcf3ce44SJohn Forte 5637*fcf3ce44SJohn Forte 5638*fcf3ce44SJohn Forte /* 5639*fcf3ce44SJohn Forte * Access the properties for the node to get the node-wwn, port-wwn property 5640*fcf3ce44SJohn Forte * On error, contents of nwwn, pwwn are unspecified. 5641*fcf3ce44SJohn Forte * On successful return nwwn and pwwn are WWN_SIZE bytes. 5642*fcf3ce44SJohn Forte */ 5643*fcf3ce44SJohn Forte static int 5644*fcf3ce44SJohn Forte get_wwn_data(di_node_t node, uchar_t **nwwn, uchar_t **pwwn) 5645*fcf3ce44SJohn Forte { 5646*fcf3ce44SJohn Forte if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP, 5647*fcf3ce44SJohn Forte nwwn) != WWN_SIZE) { 5648*fcf3ce44SJohn Forte /* If we didn't get back the right count, return error */ 5649*fcf3ce44SJohn Forte return (L_NO_WWN_PROP_FOUND); 5650*fcf3ce44SJohn Forte } 5651*fcf3ce44SJohn Forte if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, PORT_WWN_PROP, 5652*fcf3ce44SJohn Forte pwwn) != WWN_SIZE) { 5653*fcf3ce44SJohn Forte /* If we didn't get back the right count, return error */ 5654*fcf3ce44SJohn Forte return (L_NO_WWN_PROP_FOUND); 5655*fcf3ce44SJohn Forte } 5656*fcf3ce44SJohn Forte return (0); 5657*fcf3ce44SJohn Forte } 5658*fcf3ce44SJohn Forte 5659*fcf3ce44SJohn Forte /* 5660*fcf3ce44SJohn Forte * Description 5661*fcf3ce44SJohn Forte * retrieves the /dev logical path for a WWN_list of devices. 5662*fcf3ce44SJohn Forte * Input values 5663*fcf3ce44SJohn Forte * wwn_list_ptr ptr to list returned by devices_get_all 5664*fcf3ce44SJohn Forte * dir_name /dev/ directory to search 5665*fcf3ce44SJohn Forte * 5666*fcf3ce44SJohn Forte */ 5667*fcf3ce44SJohn Forte static int 5668*fcf3ce44SJohn Forte get_dev_path(struct wwn_list_struct **wwn_list_ptr, char *dir_name, 5669*fcf3ce44SJohn Forte char *pattern_match) 5670*fcf3ce44SJohn Forte { 5671*fcf3ce44SJohn Forte DIR *dirp; 5672*fcf3ce44SJohn Forte struct dirent *entp; 5673*fcf3ce44SJohn Forte char namebuf[MAXPATHLEN]; 5674*fcf3ce44SJohn Forte char *result = NULL; 5675*fcf3ce44SJohn Forte WWN_list *wwn_list, *wwn_list_save; 5676*fcf3ce44SJohn Forte char *env; 5677*fcf3ce44SJohn Forte hrtime_t start_time, end_time; 5678*fcf3ce44SJohn Forte 5679*fcf3ce44SJohn Forte if (wwn_list_ptr == NULL || *wwn_list_ptr == NULL || 5680*fcf3ce44SJohn Forte dir_name == NULL || pattern_match == NULL) { 5681*fcf3ce44SJohn Forte return (EINVAL); 5682*fcf3ce44SJohn Forte } 5683*fcf3ce44SJohn Forte 5684*fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) { 5685*fcf3ce44SJohn Forte start_time = gethrtime(); 5686*fcf3ce44SJohn Forte } 5687*fcf3ce44SJohn Forte 5688*fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr; 5689*fcf3ce44SJohn Forte 5690*fcf3ce44SJohn Forte if ((dirp = opendir(dir_name)) == NULL) { 5691*fcf3ce44SJohn Forte P_DPRINTF(" get_dev_path: No devices found\n"); 5692*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 5693*fcf3ce44SJohn Forte } 5694*fcf3ce44SJohn Forte 5695*fcf3ce44SJohn Forte while ((entp = readdir(dirp)) != NULL) { 5696*fcf3ce44SJohn Forte /* 5697*fcf3ce44SJohn Forte * Ignore current directory and parent directory 5698*fcf3ce44SJohn Forte * entries. 5699*fcf3ce44SJohn Forte */ 5700*fcf3ce44SJohn Forte if ((strcmp(entp->d_name, ".") == 0) || 5701*fcf3ce44SJohn Forte (strcmp(entp->d_name, "..") == 0) || 5702*fcf3ce44SJohn Forte (fnmatch(pattern_match, entp->d_name, 0) != 0)) 5703*fcf3ce44SJohn Forte continue; 5704*fcf3ce44SJohn Forte 5705*fcf3ce44SJohn Forte memset(namebuf, 0, sizeof (namebuf)); 5706*fcf3ce44SJohn Forte sprintf(namebuf, "%s/%s", dir_name, entp->d_name); 5707*fcf3ce44SJohn Forte 5708*fcf3ce44SJohn Forte if ((result = g_get_physical_name_from_link(namebuf)) == NULL) { 5709*fcf3ce44SJohn Forte ER_DPRINTF(" Warning: Get physical name from" 5710*fcf3ce44SJohn Forte " link failed. Link=%s\n", namebuf); 5711*fcf3ce44SJohn Forte continue; 5712*fcf3ce44SJohn Forte } 5713*fcf3ce44SJohn Forte for (wwn_list = *wwn_list_ptr; wwn_list != NULL; 5714*fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next) { 5715*fcf3ce44SJohn Forte if (strcmp(wwn_list->physical_path, result) == 0) { 5716*fcf3ce44SJohn Forte /* 5717*fcf3ce44SJohn Forte * Add information to the list. 5718*fcf3ce44SJohn Forte */ 5719*fcf3ce44SJohn Forte if ((wwn_list->logical_path = (char *) 5720*fcf3ce44SJohn Forte calloc(1, strlen(namebuf) + 1)) == NULL) { 5721*fcf3ce44SJohn Forte free(result); 5722*fcf3ce44SJohn Forte return (L_MALLOC_FAILED); 5723*fcf3ce44SJohn Forte } 5724*fcf3ce44SJohn Forte strcpy(wwn_list->logical_path, namebuf); 5725*fcf3ce44SJohn Forte break; 5726*fcf3ce44SJohn Forte } 5727*fcf3ce44SJohn Forte } 5728*fcf3ce44SJohn Forte free(result); 5729*fcf3ce44SJohn Forte } 5730*fcf3ce44SJohn Forte closedir(dirp); 5731*fcf3ce44SJohn Forte 5732*fcf3ce44SJohn Forte /* 5733*fcf3ce44SJohn Forte * Did we load all of the paths? 5734*fcf3ce44SJohn Forte * Note: if there is a missing entry in /dev then 5735*fcf3ce44SJohn Forte * the user probably did a cleanup of /dev. 5736*fcf3ce44SJohn Forte * Whatever the case, remove the entry as it 5737*fcf3ce44SJohn Forte * is invalid. 5738*fcf3ce44SJohn Forte */ 5739*fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr; 5740*fcf3ce44SJohn Forte while (wwn_list != NULL) { 5741*fcf3ce44SJohn Forte if (wwn_list->logical_path == NULL) { 5742*fcf3ce44SJohn Forte free(wwn_list->physical_path); 5743*fcf3ce44SJohn Forte wwn_list_save = wwn_list; 5744*fcf3ce44SJohn Forte if (wwn_list->wwn_prev != NULL) { 5745*fcf3ce44SJohn Forte wwn_list->wwn_prev->wwn_next = 5746*fcf3ce44SJohn Forte wwn_list->wwn_next; 5747*fcf3ce44SJohn Forte } else { 5748*fcf3ce44SJohn Forte /* 5749*fcf3ce44SJohn Forte * No previous entries 5750*fcf3ce44SJohn Forte */ 5751*fcf3ce44SJohn Forte *wwn_list_ptr = wwn_list->wwn_next; 5752*fcf3ce44SJohn Forte } 5753*fcf3ce44SJohn Forte if (wwn_list->wwn_next != NULL) { 5754*fcf3ce44SJohn Forte wwn_list->wwn_next->wwn_prev = 5755*fcf3ce44SJohn Forte wwn_list->wwn_prev; 5756*fcf3ce44SJohn Forte } 5757*fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next; 5758*fcf3ce44SJohn Forte free(wwn_list_save); 5759*fcf3ce44SJohn Forte } else { 5760*fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next; 5761*fcf3ce44SJohn Forte } 5762*fcf3ce44SJohn Forte } 5763*fcf3ce44SJohn Forte 5764*fcf3ce44SJohn Forte if (env != NULL) { 5765*fcf3ce44SJohn Forte end_time = gethrtime(); 5766*fcf3ce44SJohn Forte fprintf(stdout, 5767*fcf3ce44SJohn Forte " get_dev_path %s: " 5768*fcf3ce44SJohn Forte "\t\tTime = %lld millisec\n", 5769*fcf3ce44SJohn Forte dir_name, (end_time - start_time)/1000000); 5770*fcf3ce44SJohn Forte } 5771*fcf3ce44SJohn Forte 5772*fcf3ce44SJohn Forte if (*wwn_list_ptr == NULL) { 5773*fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND); 5774*fcf3ce44SJohn Forte } else { 5775*fcf3ce44SJohn Forte return (0); 5776*fcf3ce44SJohn Forte } 5777*fcf3ce44SJohn Forte } 5778*fcf3ce44SJohn Forte 5779*fcf3ce44SJohn Forte /* 5780*fcf3ce44SJohn Forte * This functions calls di_devfs_path and gets the path associated with a 5781*fcf3ce44SJohn Forte * given devinfo node. If the path returned does not have a '@' in it, it 5782*fcf3ce44SJohn Forte * checks if the driver is detached and creates a path after looking at the 5783*fcf3ce44SJohn Forte * driver properties. 5784*fcf3ce44SJohn Forte * 5785*fcf3ce44SJohn Forte * di_devfs_path_free is called internally. 5786*fcf3ce44SJohn Forte * 5787*fcf3ce44SJohn Forte * The argument 'path' points to the final value upon return. 5788*fcf3ce44SJohn Forte * Caller must use my_devfs_path_free on returned char * 5789*fcf3ce44SJohn Forte * Note: Only support FC/SCSI_VHCI devices, 5790*fcf3ce44SJohn Forte * for FC check for node-wwn prop 5791*fcf3ce44SJohn Forte * 5792*fcf3ce44SJohn Forte */ 5793*fcf3ce44SJohn Forte static char * 5794*fcf3ce44SJohn Forte my_devfs_path(di_node_t node) 5795*fcf3ce44SJohn Forte { 5796*fcf3ce44SJohn Forte uchar_t *pwwn = NULL; 5797*fcf3ce44SJohn Forte char pwwns[WWN_SIZE*2+1]; 5798*fcf3ce44SJohn Forte char *mypath; 5799*fcf3ce44SJohn Forte int scsi_vhci = 0; 5800*fcf3ce44SJohn Forte char *tptr = NULL, *lun_guid = NULL; 5801*fcf3ce44SJohn Forte int *lunnump = NULL; 5802*fcf3ce44SJohn Forte 5803*fcf3ce44SJohn Forte /* sanity check */ 5804*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) { 5805*fcf3ce44SJohn Forte return (NULL); 5806*fcf3ce44SJohn Forte } 5807*fcf3ce44SJohn Forte 5808*fcf3ce44SJohn Forte /* Now go get the path for this node */ 5809*fcf3ce44SJohn Forte if ((tptr = di_devfs_path(node)) == NULL) { 5810*fcf3ce44SJohn Forte return (NULL); 5811*fcf3ce44SJohn Forte } 5812*fcf3ce44SJohn Forte 5813*fcf3ce44SJohn Forte if ((mypath = (char *)calloc(1, MAXPATHLEN + 1)) == NULL) { 5814*fcf3ce44SJohn Forte di_devfs_path_free(tptr); 5815*fcf3ce44SJohn Forte return (NULL); 5816*fcf3ce44SJohn Forte } 5817*fcf3ce44SJohn Forte 5818*fcf3ce44SJohn Forte /* Prepend "/devices" to libdevinfo-returned paths */ 5819*fcf3ce44SJohn Forte sprintf(mypath, "%s%s", DEVICES_DIR, tptr); 5820*fcf3ce44SJohn Forte 5821*fcf3ce44SJohn Forte di_devfs_path_free(tptr); 5822*fcf3ce44SJohn Forte 5823*fcf3ce44SJohn Forte 5824*fcf3ce44SJohn Forte /* 5825*fcf3ce44SJohn Forte * Is this a FC device? 5826*fcf3ce44SJohn Forte * Check the pwwn property 5827*fcf3ce44SJohn Forte */ 5828*fcf3ce44SJohn Forte if (strstr(mypath, SCSI_VHCI) == NULL) { 5829*fcf3ce44SJohn Forte if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, PORT_WWN_PROP, 5830*fcf3ce44SJohn Forte &pwwn) < 0) { 5831*fcf3ce44SJohn Forte /* Not a FC device. Free path and return */ 5832*fcf3ce44SJohn Forte free(mypath); 5833*fcf3ce44SJohn Forte return (NULL); 5834*fcf3ce44SJohn Forte } 5835*fcf3ce44SJohn Forte } else { 5836*fcf3ce44SJohn Forte scsi_vhci++; 5837*fcf3ce44SJohn Forte } 5838*fcf3ce44SJohn Forte 5839*fcf3ce44SJohn Forte if ((tptr = strrchr(mypath, '/')) == NULL) { 5840*fcf3ce44SJohn Forte free(mypath); 5841*fcf3ce44SJohn Forte return (NULL); 5842*fcf3ce44SJohn Forte } 5843*fcf3ce44SJohn Forte 5844*fcf3ce44SJohn Forte if (strchr(tptr, '@') != NULL) { 5845*fcf3ce44SJohn Forte return (mypath); 5846*fcf3ce44SJohn Forte } 5847*fcf3ce44SJohn Forte 5848*fcf3ce44SJohn Forte /* 5849*fcf3ce44SJohn Forte * No '@' in path. This can happen when driver is detached. 5850*fcf3ce44SJohn Forte * We'll check if the state is detached and if it is, we'll construct 5851*fcf3ce44SJohn Forte * the path by looking at the properties. 5852*fcf3ce44SJohn Forte */ 5853*fcf3ce44SJohn Forte 5854*fcf3ce44SJohn Forte if ((di_state(node) & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { 5855*fcf3ce44SJohn Forte /* 5856*fcf3ce44SJohn Forte * Driver is not detached and no '@' in path. 5857*fcf3ce44SJohn Forte * Can't handle it. 5858*fcf3ce44SJohn Forte */ 5859*fcf3ce44SJohn Forte free(mypath); 5860*fcf3ce44SJohn Forte return (NULL); 5861*fcf3ce44SJohn Forte } 5862*fcf3ce44SJohn Forte 5863*fcf3ce44SJohn Forte if (!scsi_vhci) { 5864*fcf3ce44SJohn Forte copy_wwn_data_to_str(pwwns, pwwn); 5865*fcf3ce44SJohn Forte di_prop_lookup_ints(DDI_DEV_T_ANY, node, LUN_PROP, &lunnump); 5866*fcf3ce44SJohn Forte sprintf(&mypath[strlen(mypath)], "@w%s,%x", pwwn, *lunnump); 5867*fcf3ce44SJohn Forte } else { 5868*fcf3ce44SJohn Forte di_prop_lookup_strings(DDI_DEV_T_ANY, node, 5869*fcf3ce44SJohn Forte LUN_GUID_PROP, &lun_guid); 5870*fcf3ce44SJohn Forte sprintf(&mypath[strlen(mypath)], "@g%s", lun_guid); 5871*fcf3ce44SJohn Forte } 5872*fcf3ce44SJohn Forte return (mypath); 5873*fcf3ce44SJohn Forte } 5874*fcf3ce44SJohn Forte 5875*fcf3ce44SJohn Forte static void 5876*fcf3ce44SJohn Forte my_devfs_path_free(char *path) 5877*fcf3ce44SJohn Forte { 5878*fcf3ce44SJohn Forte if (path != NULL) { 5879*fcf3ce44SJohn Forte free(path); 5880*fcf3ce44SJohn Forte } 5881*fcf3ce44SJohn Forte } 5882*fcf3ce44SJohn Forte 5883*fcf3ce44SJohn Forte /* 5884*fcf3ce44SJohn Forte * from_ptr: ptr to uchar_t array of size WWN_SIZE 5885*fcf3ce44SJohn Forte * to_ptr: char ptr to string of size WWN_SIZE*2+1 5886*fcf3ce44SJohn Forte */ 5887*fcf3ce44SJohn Forte static void 5888*fcf3ce44SJohn Forte copy_wwn_data_to_str(char *to_ptr, const uchar_t *from_ptr) 5889*fcf3ce44SJohn Forte { 5890*fcf3ce44SJohn Forte if ((to_ptr == NULL) || (from_ptr == NULL)) 5891*fcf3ce44SJohn Forte return; 5892*fcf3ce44SJohn Forte 5893*fcf3ce44SJohn Forte sprintf(to_ptr, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x", 5894*fcf3ce44SJohn Forte from_ptr[0], from_ptr[1], from_ptr[2], from_ptr[3], 5895*fcf3ce44SJohn Forte from_ptr[4], from_ptr[5], from_ptr[6], from_ptr[7]); 5896*fcf3ce44SJohn Forte } 5897*fcf3ce44SJohn Forte 5898*fcf3ce44SJohn Forte /* 5899*fcf3ce44SJohn Forte * Open the requested directory and get one valid open. 5900*fcf3ce44SJohn Forte * If a device is busy, return. 5901*fcf3ce44SJohn Forte * Only need to open one device since 5902*fcf3ce44SJohn Forte * that implies there will be a node returned from 5903*fcf3ce44SJohn Forte * di_drv_first_node() 5904*fcf3ce44SJohn Forte * dir_name: logical device name directory 5905*fcf3ce44SJohn Forte * (DEV_TAPE_DIR, DEV_RDIR) 5906*fcf3ce44SJohn Forte * pattern_match: used by fnmatch on directory entry 5907*fcf3ce44SJohn Forte * (DIR_MATCH_SSD, DIR_MATCH_ST) 5908*fcf3ce44SJohn Forte * drvr_path: path type to verify ("/ssd@", "/st@") 5909*fcf3ce44SJohn Forte * (SLSH_DRV_NAME_ST, SLSH_DRV_NAME_SSD) 5910*fcf3ce44SJohn Forte * 5911*fcf3ce44SJohn Forte * Returns: None 5912*fcf3ce44SJohn Forte */ 5913*fcf3ce44SJohn Forte static void 5914*fcf3ce44SJohn Forte init_drv(char *dir_name, char *pattern_match, char *drvr_path) 5915*fcf3ce44SJohn Forte { 5916*fcf3ce44SJohn Forte DIR *dirp; 5917*fcf3ce44SJohn Forte struct dirent *entp; 5918*fcf3ce44SJohn Forte char namebuf[MAXPATHLEN]; 5919*fcf3ce44SJohn Forte char *result = NULL; 5920*fcf3ce44SJohn Forte int fd; 5921*fcf3ce44SJohn Forte 5922*fcf3ce44SJohn Forte if ((dirp = opendir(dir_name)) == NULL) { 5923*fcf3ce44SJohn Forte return; 5924*fcf3ce44SJohn Forte } 5925*fcf3ce44SJohn Forte 5926*fcf3ce44SJohn Forte while ((entp = readdir(dirp)) != NULL) { 5927*fcf3ce44SJohn Forte /* 5928*fcf3ce44SJohn Forte * Ignore current directory and parent directory 5929*fcf3ce44SJohn Forte * entries. 5930*fcf3ce44SJohn Forte */ 5931*fcf3ce44SJohn Forte if ((strcmp(entp->d_name, ".") == 0) || 5932*fcf3ce44SJohn Forte (strcmp(entp->d_name, "..") == 0) || 5933*fcf3ce44SJohn Forte (fnmatch(pattern_match, entp->d_name, 0) != 0)) { 5934*fcf3ce44SJohn Forte continue; 5935*fcf3ce44SJohn Forte } 5936*fcf3ce44SJohn Forte 5937*fcf3ce44SJohn Forte memset(namebuf, 0, sizeof (namebuf)); 5938*fcf3ce44SJohn Forte sprintf(namebuf, "%s/%s", dir_name, entp->d_name); 5939*fcf3ce44SJohn Forte 5940*fcf3ce44SJohn Forte if ((result = g_get_physical_name_from_link(namebuf)) == NULL) { 5941*fcf3ce44SJohn Forte ER_DPRINTF(" Warning: Get physical name from" 5942*fcf3ce44SJohn Forte " link failed. Link=%s\n", namebuf); 5943*fcf3ce44SJohn Forte continue; 5944*fcf3ce44SJohn Forte } 5945*fcf3ce44SJohn Forte 5946*fcf3ce44SJohn Forte if (strstr(result, drvr_path) == NULL) { 5947*fcf3ce44SJohn Forte free(result); 5948*fcf3ce44SJohn Forte result = NULL; 5949*fcf3ce44SJohn Forte continue; 5950*fcf3ce44SJohn Forte } 5951*fcf3ce44SJohn Forte 5952*fcf3ce44SJohn Forte if ((fd = g_object_open(result, O_NDELAY | O_RDONLY)) != -1) { 5953*fcf3ce44SJohn Forte close(fd); 5954*fcf3ce44SJohn Forte break; 5955*fcf3ce44SJohn Forte } else if (errno != EBUSY) { 5956*fcf3ce44SJohn Forte free(result); 5957*fcf3ce44SJohn Forte result = NULL; 5958*fcf3ce44SJohn Forte continue; 5959*fcf3ce44SJohn Forte } else { 5960*fcf3ce44SJohn Forte break; 5961*fcf3ce44SJohn Forte } 5962*fcf3ce44SJohn Forte } 5963*fcf3ce44SJohn Forte free(result); 5964*fcf3ce44SJohn Forte closedir(dirp); 5965*fcf3ce44SJohn Forte } 5966