17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
22*11547SBill.Gumbrell@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
237836SJohn.Forte@Sun.COM * Use is subject to license terms.
247836SJohn.Forte@Sun.COM */
257836SJohn.Forte@Sun.COM
267836SJohn.Forte@Sun.COM
277836SJohn.Forte@Sun.COM /*LINTLIBRARY*/
287836SJohn.Forte@Sun.COM
297836SJohn.Forte@Sun.COM /*
307836SJohn.Forte@Sun.COM * I18N message number ranges
317836SJohn.Forte@Sun.COM * This file: 12000 - 12499
327836SJohn.Forte@Sun.COM * Shared common messages: 1 - 1999
337836SJohn.Forte@Sun.COM */
347836SJohn.Forte@Sun.COM
357836SJohn.Forte@Sun.COM /*
367836SJohn.Forte@Sun.COM * This module is part of the Fibre Channel Interface library.
377836SJohn.Forte@Sun.COM */
387836SJohn.Forte@Sun.COM
397836SJohn.Forte@Sun.COM /* #define _POSIX_SOURCE 1 */
407836SJohn.Forte@Sun.COM
417836SJohn.Forte@Sun.COM
427836SJohn.Forte@Sun.COM /* Includes */
437836SJohn.Forte@Sun.COM #include <stdlib.h>
447836SJohn.Forte@Sun.COM #include <stdio.h>
457836SJohn.Forte@Sun.COM #include <sys/file.h>
467836SJohn.Forte@Sun.COM #include <sys/types.h>
477836SJohn.Forte@Sun.COM #include <sys/stat.h>
487836SJohn.Forte@Sun.COM #include <sys/mkdev.h>
497836SJohn.Forte@Sun.COM #include <sys/param.h>
507836SJohn.Forte@Sun.COM #include <fcntl.h>
517836SJohn.Forte@Sun.COM #include <unistd.h>
527836SJohn.Forte@Sun.COM #include <string.h>
537836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
547836SJohn.Forte@Sun.COM #include <dirent.h> /* for DIR */
557836SJohn.Forte@Sun.COM #include <sys/vtoc.h>
567836SJohn.Forte@Sun.COM #include <nl_types.h>
577836SJohn.Forte@Sun.COM #include <strings.h>
587836SJohn.Forte@Sun.COM #include <errno.h>
597836SJohn.Forte@Sun.COM #include <sys/ddi.h> /* for max */
607836SJohn.Forte@Sun.COM #include <fnmatch.h>
617836SJohn.Forte@Sun.COM #include <l_common.h>
627836SJohn.Forte@Sun.COM #include <stgcom.h>
637836SJohn.Forte@Sun.COM #include <l_error.h>
647836SJohn.Forte@Sun.COM #include <g_state.h>
657836SJohn.Forte@Sun.COM #include <g_scsi.h>
667836SJohn.Forte@Sun.COM #include <sys/fibre-channel/ulp/fcp_util.h>
677836SJohn.Forte@Sun.COM #include <sys/fibre-channel/impl/fc_error.h>
687836SJohn.Forte@Sun.COM #include <sys/fibre-channel/impl/fcph.h>
697836SJohn.Forte@Sun.COM #include <sys/socalio.h>
707836SJohn.Forte@Sun.COM #include <libdevinfo.h>
717836SJohn.Forte@Sun.COM #include <ctype.h>
727836SJohn.Forte@Sun.COM #include <devid.h>
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM /* Some forward declarations of static functions */
757836SJohn.Forte@Sun.COM /*
767836SJohn.Forte@Sun.COM * becomes extern interface for Tapestry.
777836SJohn.Forte@Sun.COM * static int g_get_inq_dtype(char *, la_wwn_t, uchar_t *);
787836SJohn.Forte@Sun.COM * static int g_get_dev_list(char *, fc_port_dev_t **, int *, int);
797836SJohn.Forte@Sun.COM */
807836SJohn.Forte@Sun.COM static int g_issue_fcp_ioctl(int, struct fcp_ioctl *, int);
817836SJohn.Forte@Sun.COM static int g_set_port_state(char *, int);
827836SJohn.Forte@Sun.COM static int g_dev_log_in_out(char *, la_wwn_t, uint16_t);
837836SJohn.Forte@Sun.COM static int g_get_dev_port_state(char *, la_wwn_t, uint32_t *);
847836SJohn.Forte@Sun.COM static void g_free_rls(AL_rls *);
857836SJohn.Forte@Sun.COM static int g_scsi_inquiry_cmd80(int, uchar_t *, int);
867836SJohn.Forte@Sun.COM static int get_fca_inq_dtype(char *, la_wwn_t, uchar_t *);
877836SJohn.Forte@Sun.COM static int g_find_supported_inq_page(int, int);
887836SJohn.Forte@Sun.COM static int wwn_list_name_compare(const void *, const void *);
897836SJohn.Forte@Sun.COM static int devid_get_all(ddi_devid_t, di_node_t, char *,
907836SJohn.Forte@Sun.COM struct mplist_struct **);
917836SJohn.Forte@Sun.COM static int get_multipath(char *, struct dlist **,
927836SJohn.Forte@Sun.COM struct wwn_list_struct *);
937836SJohn.Forte@Sun.COM static int get_multipath_disk(char *, struct dlist **,
947836SJohn.Forte@Sun.COM struct wwn_list_struct *);
957836SJohn.Forte@Sun.COM static void mplist_free(struct mplist_struct *);
967836SJohn.Forte@Sun.COM static int get_wwn_data(di_node_t, uchar_t **, uchar_t **);
977836SJohn.Forte@Sun.COM static int get_dev_path(struct wwn_list_struct **, char *, char *);
987836SJohn.Forte@Sun.COM static int insert_missing_pwwn(char *, struct wwn_list_struct **);
997836SJohn.Forte@Sun.COM static int get_scsi_vhci_port_wwn(char *, uchar_t *);
1007836SJohn.Forte@Sun.COM static int search_wwn_entry(struct wwn_list_found_struct *, uchar_t *,
1017836SJohn.Forte@Sun.COM uchar_t *);
1027836SJohn.Forte@Sun.COM static int add_wwn_entry(struct wwn_list_found_struct **, uchar_t *,
1037836SJohn.Forte@Sun.COM uchar_t *);
1047836SJohn.Forte@Sun.COM static int string_to_wwn(uchar_t *, uchar_t *);
1057836SJohn.Forte@Sun.COM static int get_wwns(char *, uchar_t *, uchar_t *, int *,
1067836SJohn.Forte@Sun.COM struct wwn_list_found_struct **);
1077836SJohn.Forte@Sun.COM
1087836SJohn.Forte@Sun.COM /* type for g_dev_map_init related routines */
1097836SJohn.Forte@Sun.COM
1107836SJohn.Forte@Sun.COM #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
1117836SJohn.Forte@Sun.COM
1127836SJohn.Forte@Sun.COM typedef struct impl_map_dev_prop {
1137836SJohn.Forte@Sun.COM char prop_name[MAXNAMELEN];
1147836SJohn.Forte@Sun.COM int prop_type;
1157836SJohn.Forte@Sun.COM int prop_size;
1167836SJohn.Forte@Sun.COM void *prop_data;
1177836SJohn.Forte@Sun.COM int prop_error;
1187836SJohn.Forte@Sun.COM struct impl_map_dev_prop *next;
1197836SJohn.Forte@Sun.COM } impl_map_dev_prop_t;
1207836SJohn.Forte@Sun.COM
1217836SJohn.Forte@Sun.COM typedef struct impl_map_dev {
1227836SJohn.Forte@Sun.COM int flag;
1237836SJohn.Forte@Sun.COM uint_t topo;
1247836SJohn.Forte@Sun.COM impl_map_dev_prop_t *prop_list;
1257836SJohn.Forte@Sun.COM struct impl_map_dev *parent;
1267836SJohn.Forte@Sun.COM struct impl_map_dev *child;
1277836SJohn.Forte@Sun.COM struct impl_map_dev *next;
1287836SJohn.Forte@Sun.COM } impl_map_dev_t;
1297836SJohn.Forte@Sun.COM
1307836SJohn.Forte@Sun.COM /* Defines */
1317836SJohn.Forte@Sun.COM #define VERBPRINT if (verbose) (void) printf
1327836SJohn.Forte@Sun.COM
1337836SJohn.Forte@Sun.COM #define DIR_MATCH_ST "*[0-9+]n"
1347836SJohn.Forte@Sun.COM #define DIR_MATCH_SSD "*s2"
1357836SJohn.Forte@Sun.COM
1367836SJohn.Forte@Sun.COM #define PROP_NOEXIST 0
1377836SJohn.Forte@Sun.COM #define PROP_EXIST 1
1387836SJohn.Forte@Sun.COM
1397836SJohn.Forte@Sun.COM /* Prototypes */
1407836SJohn.Forte@Sun.COM static int create_map(char *, gfc_map_t *, int, int);
1417836SJohn.Forte@Sun.COM static char ctoi(char);
1427836SJohn.Forte@Sun.COM static int lilp_map_cmp(const void*, const void*);
1437836SJohn.Forte@Sun.COM static int devices_get_all(di_node_t, char *, char *,
1447836SJohn.Forte@Sun.COM struct wwn_list_struct **);
1457836SJohn.Forte@Sun.COM static char *my_devfs_path(di_node_t);
1467836SJohn.Forte@Sun.COM static void my_devfs_path_free(char *path);
1477836SJohn.Forte@Sun.COM static void copy_wwn_data_to_str(char *, const uchar_t *);
1487836SJohn.Forte@Sun.COM static void init_drv(char *, char *, char *);
1497836SJohn.Forte@Sun.COM
1507836SJohn.Forte@Sun.COM /* static for g_dev_map_init related routines */
1517836SJohn.Forte@Sun.COM
1527836SJohn.Forte@Sun.COM static int update_map_dev_fc_prop(impl_map_dev_prop_t **, uint32_t,
1537836SJohn.Forte@Sun.COM uchar_t *, uchar_t *, int, int);
1547836SJohn.Forte@Sun.COM static int update_map_dev_FCP_prop(impl_map_dev_prop_t **, uchar_t *, int, int);
1557836SJohn.Forte@Sun.COM static int handle_map_dev_FCP_prop(minor_t, la_wwn_t, impl_map_dev_prop_t **);
1567836SJohn.Forte@Sun.COM static void free_prop_list(impl_map_dev_prop_t **);
1577836SJohn.Forte@Sun.COM static void free_child_list(impl_map_dev_t **);
1587836SJohn.Forte@Sun.COM static u_longlong_t wwnConversion(uchar_t *wwn);
1597836SJohn.Forte@Sun.COM
1607836SJohn.Forte@Sun.COM uchar_t g_switch_to_alpa[] = {
1617836SJohn.Forte@Sun.COM 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
1627836SJohn.Forte@Sun.COM 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
1637836SJohn.Forte@Sun.COM 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
1647836SJohn.Forte@Sun.COM 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
1657836SJohn.Forte@Sun.COM 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
1667836SJohn.Forte@Sun.COM 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
1677836SJohn.Forte@Sun.COM 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
1687836SJohn.Forte@Sun.COM 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
1697836SJohn.Forte@Sun.COM 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
1707836SJohn.Forte@Sun.COM 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
1717836SJohn.Forte@Sun.COM 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
1727836SJohn.Forte@Sun.COM 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
1737836SJohn.Forte@Sun.COM 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
1747836SJohn.Forte@Sun.COM };
1757836SJohn.Forte@Sun.COM
1767836SJohn.Forte@Sun.COM uchar_t g_sf_alpa_to_switch[] = {
1777836SJohn.Forte@Sun.COM 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1787836SJohn.Forte@Sun.COM 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1797836SJohn.Forte@Sun.COM 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1807836SJohn.Forte@Sun.COM 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1817836SJohn.Forte@Sun.COM 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1827836SJohn.Forte@Sun.COM 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1837836SJohn.Forte@Sun.COM 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1847836SJohn.Forte@Sun.COM 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1857836SJohn.Forte@Sun.COM 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1867836SJohn.Forte@Sun.COM 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1877836SJohn.Forte@Sun.COM 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1887836SJohn.Forte@Sun.COM 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1897836SJohn.Forte@Sun.COM 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1907836SJohn.Forte@Sun.COM 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1917836SJohn.Forte@Sun.COM 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1927836SJohn.Forte@Sun.COM 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1937836SJohn.Forte@Sun.COM 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1947836SJohn.Forte@Sun.COM 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1957836SJohn.Forte@Sun.COM 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1967836SJohn.Forte@Sun.COM 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1977836SJohn.Forte@Sun.COM 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1987836SJohn.Forte@Sun.COM 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1997836SJohn.Forte@Sun.COM 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
2007836SJohn.Forte@Sun.COM 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2017836SJohn.Forte@Sun.COM };
2027836SJohn.Forte@Sun.COM
2037836SJohn.Forte@Sun.COM
2047836SJohn.Forte@Sun.COM
2057836SJohn.Forte@Sun.COM /*
2067836SJohn.Forte@Sun.COM * Check if device is in the map.
2077836SJohn.Forte@Sun.COM *
2087836SJohn.Forte@Sun.COM * PARAMS:
2097836SJohn.Forte@Sun.COM * map - loop map returned from fc port
2107836SJohn.Forte@Sun.COM * tid - device ID for private map or 24-bit alpa for fabric map
2117836SJohn.Forte@Sun.COM *
2127836SJohn.Forte@Sun.COM * RETURNS:
2137836SJohn.Forte@Sun.COM * 1 if device present in the map.
2147836SJohn.Forte@Sun.COM * 0 otherwise.
2157836SJohn.Forte@Sun.COM *
2167836SJohn.Forte@Sun.COM */
2177836SJohn.Forte@Sun.COM int
g_device_in_map(gfc_map_t * map,int tid)2187836SJohn.Forte@Sun.COM g_device_in_map(gfc_map_t *map, int tid)
2197836SJohn.Forte@Sun.COM {
2207836SJohn.Forte@Sun.COM int i, j;
2217836SJohn.Forte@Sun.COM gfc_port_dev_info_t *dev_ptr;
2227836SJohn.Forte@Sun.COM
2237836SJohn.Forte@Sun.COM dev_ptr = map->dev_addr;
2247836SJohn.Forte@Sun.COM if ((map->hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
225*11547SBill.Gumbrell@Sun.COM (map->hba_addr.port_topology == FC_TOP_FABRIC)) {
2267836SJohn.Forte@Sun.COM for (i = 0; i < map->count; i++, dev_ptr++) {
2277836SJohn.Forte@Sun.COM if (dev_ptr->
228*11547SBill.Gumbrell@Sun.COM gfc_port_dev.pub_port.dev_did.port_id == tid) {
2297836SJohn.Forte@Sun.COM /* Does not count if WWN == 0 */
2307836SJohn.Forte@Sun.COM for (j = 0; j < FC_WWN_SIZE; j++)
2317836SJohn.Forte@Sun.COM if (dev_ptr->gfc_port_dev.pub_port.
232*11547SBill.Gumbrell@Sun.COM dev_pwwn.raw_wwn[j] != 0)
2337836SJohn.Forte@Sun.COM return (1);
2347836SJohn.Forte@Sun.COM }
2357836SJohn.Forte@Sun.COM }
2367836SJohn.Forte@Sun.COM } else {
2377836SJohn.Forte@Sun.COM for (i = 0; i < map->count; i++, dev_ptr++) {
2387836SJohn.Forte@Sun.COM if (dev_ptr->gfc_port_dev.priv_port.sf_al_pa ==
239*11547SBill.Gumbrell@Sun.COM (int)g_switch_to_alpa[tid]) {
2407836SJohn.Forte@Sun.COM /* Does not count if WWN == 0 */
2417836SJohn.Forte@Sun.COM for (j = 0; j < WWN_SIZE; j++)
2427836SJohn.Forte@Sun.COM if (dev_ptr->gfc_port_dev.priv_port.
243*11547SBill.Gumbrell@Sun.COM sf_port_wwn[j] != 0)
2447836SJohn.Forte@Sun.COM return (1);
2457836SJohn.Forte@Sun.COM }
2467836SJohn.Forte@Sun.COM }
2477836SJohn.Forte@Sun.COM }
2487836SJohn.Forte@Sun.COM return (0);
2497836SJohn.Forte@Sun.COM }
2507836SJohn.Forte@Sun.COM
2517836SJohn.Forte@Sun.COM /*
2527836SJohn.Forte@Sun.COM * Inserts any missing port wwns for mpxio device paths
2537836SJohn.Forte@Sun.COM * which are in ONLINE or STANDBY state.
2547836SJohn.Forte@Sun.COM */
2557836SJohn.Forte@Sun.COM static int
insert_missing_pwwn(char * phys_path,struct wwn_list_struct ** wwn_list_ptr)2567836SJohn.Forte@Sun.COM insert_missing_pwwn(char *phys_path, struct wwn_list_struct **wwn_list_ptr)
2577836SJohn.Forte@Sun.COM {
258*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
259*11547SBill.Gumbrell@Sun.COM int i, pathcnt, match;
260*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *new_wwn, *wwn_list_s, *wwn_list_found;
261*11547SBill.Gumbrell@Sun.COM char pwwn1[WWN_S_LEN];
2627836SJohn.Forte@Sun.COM
2637836SJohn.Forte@Sun.COM /*
2647836SJohn.Forte@Sun.COM * Now check each scsi_vhci device path to find any missed
2657836SJohn.Forte@Sun.COM * port wwns and insert a new wwn list entry for the missed
2667836SJohn.Forte@Sun.COM * port wwn
2677836SJohn.Forte@Sun.COM */
2687836SJohn.Forte@Sun.COM if (g_get_pathlist(phys_path, &pathlist)) {
2697836SJohn.Forte@Sun.COM /* Free memory for pathlist before return */
2707836SJohn.Forte@Sun.COM S_FREE(pathlist.path_info);
2717836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
2727836SJohn.Forte@Sun.COM }
2737836SJohn.Forte@Sun.COM
2747836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
2757836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
2767836SJohn.Forte@Sun.COM /*
2777836SJohn.Forte@Sun.COM * Just search for ONLINE and STANDBY paths as
2787836SJohn.Forte@Sun.COM * those should be the only missing wwn entries.
2797836SJohn.Forte@Sun.COM * There is a very small window for an offline
2807836SJohn.Forte@Sun.COM * to have occurred between the time we retrieved
2817836SJohn.Forte@Sun.COM * the device list and a call to this function.
2827836SJohn.Forte@Sun.COM * If that happens, we just won't add it to
2837836SJohn.Forte@Sun.COM * the list which is probably a good thing.
2847836SJohn.Forte@Sun.COM */
2857836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
2867836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE ||
2877836SJohn.Forte@Sun.COM pathlist.path_info[i].path_state ==
2887836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
2897836SJohn.Forte@Sun.COM (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
290*11547SBill.Gumbrell@Sun.COM WWN_S_LEN - 1);
2917836SJohn.Forte@Sun.COM pwwn1[WWN_S_LEN - 1] = '\0';
2927836SJohn.Forte@Sun.COM /*
2937836SJohn.Forte@Sun.COM * Now search through wwn list for matching
2947836SJohn.Forte@Sun.COM * device path AND pwwn
2957836SJohn.Forte@Sun.COM * If it's found, continue to next path.
2967836SJohn.Forte@Sun.COM * If it's not found, add it the wwn list.
2977836SJohn.Forte@Sun.COM */
2987836SJohn.Forte@Sun.COM match = 0;
2997836SJohn.Forte@Sun.COM
3007836SJohn.Forte@Sun.COM for (wwn_list_s = *wwn_list_ptr; wwn_list_s != NULL;
3017836SJohn.Forte@Sun.COM wwn_list_s = wwn_list_s->wwn_next) {
3027836SJohn.Forte@Sun.COM if (strncmp(phys_path,
303*11547SBill.Gumbrell@Sun.COM wwn_list_s->physical_path,
304*11547SBill.Gumbrell@Sun.COM strlen(phys_path)) == 0) {
3057836SJohn.Forte@Sun.COM wwn_list_found = wwn_list_s;
3067836SJohn.Forte@Sun.COM if (strncmp(pwwn1,
307*11547SBill.Gumbrell@Sun.COM wwn_list_s->port_wwn_s,
308*11547SBill.Gumbrell@Sun.COM WWN_S_LEN) == 0) {
3097836SJohn.Forte@Sun.COM match++;
3107836SJohn.Forte@Sun.COM break;
3117836SJohn.Forte@Sun.COM }
3127836SJohn.Forte@Sun.COM }
3137836SJohn.Forte@Sun.COM }
3147836SJohn.Forte@Sun.COM if (match) {
3157836SJohn.Forte@Sun.COM continue;
3167836SJohn.Forte@Sun.COM } else {
3177836SJohn.Forte@Sun.COM /*
3187836SJohn.Forte@Sun.COM * didn't find a match but the mpxio
3197836SJohn.Forte@Sun.COM * device is in the list. Retrieve
3207836SJohn.Forte@Sun.COM * the info from the wwn_list_found
3217836SJohn.Forte@Sun.COM * and add it to the list.
3227836SJohn.Forte@Sun.COM */
3237836SJohn.Forte@Sun.COM if ((new_wwn = (struct wwn_list_struct *)
324*11547SBill.Gumbrell@Sun.COM calloc(1,
325*11547SBill.Gumbrell@Sun.COM sizeof (struct wwn_list_struct)))
326*11547SBill.Gumbrell@Sun.COM == NULL) {
327*11547SBill.Gumbrell@Sun.COM S_FREE(pathlist.path_info);
328*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
3297836SJohn.Forte@Sun.COM }
3307836SJohn.Forte@Sun.COM if ((new_wwn->physical_path = (char *)
331*11547SBill.Gumbrell@Sun.COM calloc(1,
332*11547SBill.Gumbrell@Sun.COM strlen(wwn_list_found->physical_path)
333*11547SBill.Gumbrell@Sun.COM + 1)) == NULL) {
334*11547SBill.Gumbrell@Sun.COM S_FREE(pathlist.path_info);
335*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
3367836SJohn.Forte@Sun.COM }
3377836SJohn.Forte@Sun.COM if ((new_wwn->logical_path = (char *)
338*11547SBill.Gumbrell@Sun.COM calloc(1,
339*11547SBill.Gumbrell@Sun.COM strlen(wwn_list_found->logical_path)
340*11547SBill.Gumbrell@Sun.COM + 1)) == NULL) {
341*11547SBill.Gumbrell@Sun.COM S_FREE(pathlist.path_info);
342*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
3437836SJohn.Forte@Sun.COM }
3447836SJohn.Forte@Sun.COM
3457836SJohn.Forte@Sun.COM /*
3467836SJohn.Forte@Sun.COM * Insert new_wwn at the beginning of the list.
3477836SJohn.Forte@Sun.COM */
3487836SJohn.Forte@Sun.COM new_wwn->wwn_next = *wwn_list_ptr;
3497836SJohn.Forte@Sun.COM (*wwn_list_ptr)->wwn_prev = new_wwn;
3507836SJohn.Forte@Sun.COM
3517836SJohn.Forte@Sun.COM /* set new starting ptr */
3527836SJohn.Forte@Sun.COM *wwn_list_ptr = new_wwn;
3537836SJohn.Forte@Sun.COM
3547836SJohn.Forte@Sun.COM memcpy(new_wwn->physical_path,
3557836SJohn.Forte@Sun.COM wwn_list_found->physical_path,
356*11547SBill.Gumbrell@Sun.COM strlen(wwn_list_found->physical_path));
3577836SJohn.Forte@Sun.COM memcpy(new_wwn->logical_path,
3587836SJohn.Forte@Sun.COM wwn_list_found->logical_path,
359*11547SBill.Gumbrell@Sun.COM strlen(wwn_list_found->logical_path));
3607836SJohn.Forte@Sun.COM /*
3617836SJohn.Forte@Sun.COM * Copy found node wwn data to this new entry
3627836SJohn.Forte@Sun.COM * Node wwn is required for the wwn_list
3637836SJohn.Forte@Sun.COM * however for mpxio devices it is not
3647836SJohn.Forte@Sun.COM * relevant as it may apply to multiple
3657836SJohn.Forte@Sun.COM * target controllers, so just use what
3667836SJohn.Forte@Sun.COM * we already have in wwn_list_found.
3677836SJohn.Forte@Sun.COM */
3687836SJohn.Forte@Sun.COM memcpy(new_wwn->node_wwn_s,
3697836SJohn.Forte@Sun.COM wwn_list_found->node_wwn_s, WWN_S_LEN);
3707836SJohn.Forte@Sun.COM memcpy(new_wwn->w_node_wwn,
3717836SJohn.Forte@Sun.COM wwn_list_found->w_node_wwn, WWN_SIZE);
3727836SJohn.Forte@Sun.COM new_wwn->device_type =
3737836SJohn.Forte@Sun.COM wwn_list_found->device_type;
3747836SJohn.Forte@Sun.COM memcpy(new_wwn->port_wwn_s, pwwn1, WWN_S_LEN);
3757836SJohn.Forte@Sun.COM }
3767836SJohn.Forte@Sun.COM }
3777836SJohn.Forte@Sun.COM }
3787836SJohn.Forte@Sun.COM S_FREE(pathlist.path_info);
3797836SJohn.Forte@Sun.COM return (0);
3807836SJohn.Forte@Sun.COM }
3817836SJohn.Forte@Sun.COM
3827836SJohn.Forte@Sun.COM /*
3837836SJohn.Forte@Sun.COM * gets the port wwn for a scsi_vhci device using ONLINE path priority
3847836SJohn.Forte@Sun.COM */
3857836SJohn.Forte@Sun.COM static int
get_scsi_vhci_port_wwn(char * phys_path,uchar_t * port_wwn)3867836SJohn.Forte@Sun.COM get_scsi_vhci_port_wwn(char *phys_path, uchar_t *port_wwn)
3877836SJohn.Forte@Sun.COM {
388*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
389*11547SBill.Gumbrell@Sun.COM int i, pathcnt, found;
390*11547SBill.Gumbrell@Sun.COM char pwwn1[WWN_S_LEN];
3917836SJohn.Forte@Sun.COM
3927836SJohn.Forte@Sun.COM if (g_get_pathlist(phys_path, &pathlist)) {
3937836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
3947836SJohn.Forte@Sun.COM }
3957836SJohn.Forte@Sun.COM
3967836SJohn.Forte@Sun.COM found = 0;
3977836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
3987836SJohn.Forte@Sun.COM /*
3997836SJohn.Forte@Sun.COM * Look for an ONLINE path first.
4007836SJohn.Forte@Sun.COM * If that fails, get the STANDBY path port WWN
4017836SJohn.Forte@Sun.COM * If that fails, give up
4027836SJohn.Forte@Sun.COM */
4037836SJohn.Forte@Sun.COM for (i = 0; found == 0 && i < pathcnt; i++) {
4047836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
4057836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
4067836SJohn.Forte@Sun.COM (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
407*11547SBill.Gumbrell@Sun.COM WWN_S_LEN - 1);
4087836SJohn.Forte@Sun.COM pwwn1[WWN_S_LEN - 1] = '\0';
4097836SJohn.Forte@Sun.COM found++;
4107836SJohn.Forte@Sun.COM }
4117836SJohn.Forte@Sun.COM }
4127836SJohn.Forte@Sun.COM
4137836SJohn.Forte@Sun.COM for (i = 0; found == 0 && i < pathcnt; i++) {
4147836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
4157836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
4167836SJohn.Forte@Sun.COM (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
417*11547SBill.Gumbrell@Sun.COM WWN_S_LEN - 1);
4187836SJohn.Forte@Sun.COM pwwn1[WWN_S_LEN - 1] = '\0';
4197836SJohn.Forte@Sun.COM found++;
4207836SJohn.Forte@Sun.COM }
4217836SJohn.Forte@Sun.COM }
4227836SJohn.Forte@Sun.COM
4237836SJohn.Forte@Sun.COM S_FREE(pathlist.path_info);
4247836SJohn.Forte@Sun.COM if (found) {
4257836SJohn.Forte@Sun.COM return (string_to_wwn((uchar_t *)pwwn1, port_wwn));
4267836SJohn.Forte@Sun.COM } else {
4277836SJohn.Forte@Sun.COM return (-1);
4287836SJohn.Forte@Sun.COM }
4297836SJohn.Forte@Sun.COM }
4307836SJohn.Forte@Sun.COM
4317836SJohn.Forte@Sun.COM /*
4327836SJohn.Forte@Sun.COM * searches wwn_list_found for the pwwn passed in
4337836SJohn.Forte@Sun.COM * and sets the corresponding nwwn on return.
4347836SJohn.Forte@Sun.COM * If no match is found, -1 is returned and nwwn is not set.
4357836SJohn.Forte@Sun.COM */
4367836SJohn.Forte@Sun.COM static int
search_wwn_entry(struct wwn_list_found_struct * wwn_list_found,uchar_t * pwwn,uchar_t * nwwn)4377836SJohn.Forte@Sun.COM search_wwn_entry(struct wwn_list_found_struct *wwn_list_found, uchar_t *pwwn,
438*11547SBill.Gumbrell@Sun.COM uchar_t *nwwn)
4397836SJohn.Forte@Sun.COM {
440*11547SBill.Gumbrell@Sun.COM struct wwn_list_found_struct *wwn_list_s;
4417836SJohn.Forte@Sun.COM
4427836SJohn.Forte@Sun.COM for (wwn_list_s = wwn_list_found; wwn_list_s != NULL;
4437836SJohn.Forte@Sun.COM wwn_list_s = wwn_list_s->wwn_next) {
444*11547SBill.Gumbrell@Sun.COM if (memcmp(pwwn, wwn_list_s->port_wwn, WWN_SIZE) == 0) {
4457836SJohn.Forte@Sun.COM memcpy(nwwn, wwn_list_s->node_wwn, WWN_SIZE);
4467836SJohn.Forte@Sun.COM return (0);
4477836SJohn.Forte@Sun.COM }
4487836SJohn.Forte@Sun.COM }
4497836SJohn.Forte@Sun.COM return (-1);
4507836SJohn.Forte@Sun.COM }
4517836SJohn.Forte@Sun.COM
4527836SJohn.Forte@Sun.COM /*
4537836SJohn.Forte@Sun.COM * adds a nwwn, pwwn entry to the next entry in wwn_list_found list
4547836SJohn.Forte@Sun.COM */
4557836SJohn.Forte@Sun.COM static int
add_wwn_entry(struct wwn_list_found_struct ** wwn_list_found,uchar_t * pwwn,uchar_t * nwwn)4567836SJohn.Forte@Sun.COM add_wwn_entry(struct wwn_list_found_struct **wwn_list_found, uchar_t *pwwn,
457*11547SBill.Gumbrell@Sun.COM uchar_t *nwwn)
4587836SJohn.Forte@Sun.COM {
459*11547SBill.Gumbrell@Sun.COM struct wwn_list_found_struct *new_wwn, *temp_wwn_list_found = NULL;
4607836SJohn.Forte@Sun.COM
4617836SJohn.Forte@Sun.COM /* Got wwns, load data in list */
4627836SJohn.Forte@Sun.COM if ((new_wwn = (struct wwn_list_found_struct *)
463*11547SBill.Gumbrell@Sun.COM calloc(1, sizeof (struct wwn_list_found_struct))) == NULL) {
4647836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
4657836SJohn.Forte@Sun.COM }
4667836SJohn.Forte@Sun.COM
4677836SJohn.Forte@Sun.COM memcpy(new_wwn->node_wwn, nwwn, WWN_SIZE);
4687836SJohn.Forte@Sun.COM memcpy(new_wwn->port_wwn, pwwn, WWN_SIZE);
4697836SJohn.Forte@Sun.COM
4707836SJohn.Forte@Sun.COM /*
4717836SJohn.Forte@Sun.COM * Insert new_wwn in the list
4727836SJohn.Forte@Sun.COM */
4737836SJohn.Forte@Sun.COM if (*wwn_list_found != NULL) {
4747836SJohn.Forte@Sun.COM temp_wwn_list_found = (*wwn_list_found)->wwn_next;
4757836SJohn.Forte@Sun.COM (*wwn_list_found)->wwn_next = new_wwn;
4767836SJohn.Forte@Sun.COM } else {
4777836SJohn.Forte@Sun.COM *wwn_list_found = new_wwn;
4787836SJohn.Forte@Sun.COM }
4797836SJohn.Forte@Sun.COM new_wwn->wwn_next = temp_wwn_list_found;
4807836SJohn.Forte@Sun.COM
4817836SJohn.Forte@Sun.COM return (0);
4827836SJohn.Forte@Sun.COM }
4837836SJohn.Forte@Sun.COM
4847836SJohn.Forte@Sun.COM
4857836SJohn.Forte@Sun.COM /*
4867836SJohn.Forte@Sun.COM * Create a linked list of all the WWN's for all FC_AL disks and
4877836SJohn.Forte@Sun.COM * tapes that are attached to this host.
4887836SJohn.Forte@Sun.COM *
4897836SJohn.Forte@Sun.COM * RETURN VALUES: 0 O.K.
4907836SJohn.Forte@Sun.COM *
4917836SJohn.Forte@Sun.COM * wwn_list pointer:
4927836SJohn.Forte@Sun.COM * NULL: No devices found.
4937836SJohn.Forte@Sun.COM * !NULL: Devices found
4947836SJohn.Forte@Sun.COM * wwn_list points to a linked list of wwn's.
4957836SJohn.Forte@Sun.COM */
4967836SJohn.Forte@Sun.COM int
g_get_wwn_list(struct wwn_list_struct ** wwn_list_ptr,int verbose)4977836SJohn.Forte@Sun.COM g_get_wwn_list(struct wwn_list_struct **wwn_list_ptr, int verbose)
4987836SJohn.Forte@Sun.COM {
499*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *wwn_list_p = NULL, *wwn_list_tmp_p = NULL;
500*11547SBill.Gumbrell@Sun.COM struct wwn_list_found_struct *wwn_list_found = NULL;
501*11547SBill.Gumbrell@Sun.COM int err;
502*11547SBill.Gumbrell@Sun.COM int al_pa;
503*11547SBill.Gumbrell@Sun.COM uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
504*11547SBill.Gumbrell@Sun.COM hrtime_t start_time, end_time;
505*11547SBill.Gumbrell@Sun.COM char *env = NULL;
5067836SJohn.Forte@Sun.COM
5077836SJohn.Forte@Sun.COM /* return L_NULL_WWN_LIST if wwn_list_ptr is NULL */
5087836SJohn.Forte@Sun.COM if (wwn_list_ptr == NULL) {
5097836SJohn.Forte@Sun.COM return (L_NULL_WWN_LIST);
5107836SJohn.Forte@Sun.COM }
5117836SJohn.Forte@Sun.COM
5127836SJohn.Forte@Sun.COM if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
5137836SJohn.Forte@Sun.COM start_time = gethrtime();
5147836SJohn.Forte@Sun.COM }
5157836SJohn.Forte@Sun.COM
516*11547SBill.Gumbrell@Sun.COM if ((err = g_devices_get_all(wwn_list_ptr)) != 0) {
5177836SJohn.Forte@Sun.COM return (err);
5187836SJohn.Forte@Sun.COM }
5197836SJohn.Forte@Sun.COM
5207836SJohn.Forte@Sun.COM /*
5217836SJohn.Forte@Sun.COM * retain backward compatibility with g_get_wwn_list
5227836SJohn.Forte@Sun.COM * and retrieve the WWN for scsi_vhci devices in the
5237836SJohn.Forte@Sun.COM * same fashion
5247836SJohn.Forte@Sun.COM * Note that for scsi_vhci devices, the wwn fields are
5257836SJohn.Forte@Sun.COM * not relevant but in the previous versions
5267836SJohn.Forte@Sun.COM * we loaded the wwns so...
5277836SJohn.Forte@Sun.COM */
5287836SJohn.Forte@Sun.COM wwn_list_p = *wwn_list_ptr;
5297836SJohn.Forte@Sun.COM while (wwn_list_p != NULL) {
530*11547SBill.Gumbrell@Sun.COM if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) {
531*11547SBill.Gumbrell@Sun.COM /* get port wwn of first ONLINE, STANDBY */
532*11547SBill.Gumbrell@Sun.COM if ((get_scsi_vhci_port_wwn(wwn_list_p->physical_path,
533*11547SBill.Gumbrell@Sun.COM port_wwn)) == 0) {
534*11547SBill.Gumbrell@Sun.COM if ((search_wwn_entry(wwn_list_found, port_wwn,
535*11547SBill.Gumbrell@Sun.COM node_wwn)) != 0) {
536*11547SBill.Gumbrell@Sun.COM if ((err =
537*11547SBill.Gumbrell@Sun.COM get_wwns(wwn_list_p->physical_path,
538*11547SBill.Gumbrell@Sun.COM port_wwn,
539*11547SBill.Gumbrell@Sun.COM node_wwn, &al_pa,
540*11547SBill.Gumbrell@Sun.COM &wwn_list_found)) != 0) {
541*11547SBill.Gumbrell@Sun.COM g_free_wwn_list_found(
542*11547SBill.Gumbrell@Sun.COM &wwn_list_found);
543*11547SBill.Gumbrell@Sun.COM return (err);
544*11547SBill.Gumbrell@Sun.COM }
545*11547SBill.Gumbrell@Sun.COM }
546*11547SBill.Gumbrell@Sun.COM } else {
547*11547SBill.Gumbrell@Sun.COM /* Use g_get_wwn as a last resort */
548*11547SBill.Gumbrell@Sun.COM if ((err = g_get_wwn(wwn_list_p->physical_path,
549*11547SBill.Gumbrell@Sun.COM port_wwn, node_wwn, &al_pa, 0)) != 0) {
550*11547SBill.Gumbrell@Sun.COM /*
551*11547SBill.Gumbrell@Sun.COM * this is a bad WWN.
552*11547SBill.Gumbrell@Sun.COM * remove it from the wwn_list.
553*11547SBill.Gumbrell@Sun.COM *
554*11547SBill.Gumbrell@Sun.COM * After removing the bad WWN,
555*11547SBill.Gumbrell@Sun.COM * wwn_list_p should point to the next
556*11547SBill.Gumbrell@Sun.COM * node in the list.
557*11547SBill.Gumbrell@Sun.COM */
558*11547SBill.Gumbrell@Sun.COM if ((wwn_list_p->wwn_prev == NULL) &&
559*11547SBill.Gumbrell@Sun.COM (wwn_list_p->wwn_next == NULL)) {
560*11547SBill.Gumbrell@Sun.COM *wwn_list_ptr = NULL;
561*11547SBill.Gumbrell@Sun.COM free(wwn_list_p);
562*11547SBill.Gumbrell@Sun.COM g_free_wwn_list_found(
563*11547SBill.Gumbrell@Sun.COM &wwn_list_found);
564*11547SBill.Gumbrell@Sun.COM return (L_NO_DEVICES_FOUND);
565*11547SBill.Gumbrell@Sun.COM } else if (
566*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_prev == NULL) {
567*11547SBill.Gumbrell@Sun.COM *wwn_list_ptr =
568*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_next;
569*11547SBill.Gumbrell@Sun.COM free(wwn_list_p);
570*11547SBill.Gumbrell@Sun.COM wwn_list_p = *wwn_list_ptr;
571*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_prev = NULL;
572*11547SBill.Gumbrell@Sun.COM } else if (
573*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_next == NULL) {
574*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_prev->wwn_next =
575*11547SBill.Gumbrell@Sun.COM NULL;
576*11547SBill.Gumbrell@Sun.COM free(wwn_list_p);
577*11547SBill.Gumbrell@Sun.COM wwn_list_p = NULL;
578*11547SBill.Gumbrell@Sun.COM } else {
579*11547SBill.Gumbrell@Sun.COM wwn_list_tmp_p =
580*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_next;
581*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_prev->wwn_next =
582*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_next;
583*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_next->wwn_prev =
584*11547SBill.Gumbrell@Sun.COM wwn_list_p->wwn_prev;
585*11547SBill.Gumbrell@Sun.COM free(wwn_list_p);
586*11547SBill.Gumbrell@Sun.COM wwn_list_p = wwn_list_tmp_p;
587*11547SBill.Gumbrell@Sun.COM }
588*11547SBill.Gumbrell@Sun.COM continue;
589*11547SBill.Gumbrell@Sun.COM }
5907836SJohn.Forte@Sun.COM }
591*11547SBill.Gumbrell@Sun.COM copy_wwn_data_to_str(wwn_list_p->node_wwn_s, node_wwn);
592*11547SBill.Gumbrell@Sun.COM copy_wwn_data_to_str(wwn_list_p->port_wwn_s, port_wwn);
593*11547SBill.Gumbrell@Sun.COM memcpy(wwn_list_p->w_node_wwn, node_wwn, WWN_SIZE);
5947836SJohn.Forte@Sun.COM }
595*11547SBill.Gumbrell@Sun.COM wwn_list_p = wwn_list_p->wwn_next;
5967836SJohn.Forte@Sun.COM }
5977836SJohn.Forte@Sun.COM g_free_wwn_list_found(&wwn_list_found);
5987836SJohn.Forte@Sun.COM
5997836SJohn.Forte@Sun.COM /*
6007836SJohn.Forte@Sun.COM * Now go through the list one more time to add entries for
6017836SJohn.Forte@Sun.COM * any missing port wwns.
6027836SJohn.Forte@Sun.COM * This allows a search on port wwn for any paths which are
6037836SJohn.Forte@Sun.COM * ONLINE or STANDBY. We don't care about OFFLINE as those won't
6047836SJohn.Forte@Sun.COM * and should not show up in the list
6057836SJohn.Forte@Sun.COM */
6067836SJohn.Forte@Sun.COM for (wwn_list_p = *wwn_list_ptr; wwn_list_p != NULL;
6077836SJohn.Forte@Sun.COM wwn_list_p = wwn_list_p->wwn_next) {
608*11547SBill.Gumbrell@Sun.COM if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) {
609*11547SBill.Gumbrell@Sun.COM if ((err = insert_missing_pwwn(
610*11547SBill.Gumbrell@Sun.COM wwn_list_p->physical_path, wwn_list_ptr)) != 0)
611*11547SBill.Gumbrell@Sun.COM return (err);
612*11547SBill.Gumbrell@Sun.COM }
6137836SJohn.Forte@Sun.COM }
6147836SJohn.Forte@Sun.COM
6157836SJohn.Forte@Sun.COM if (env != NULL) {
6167836SJohn.Forte@Sun.COM end_time = gethrtime();
6177836SJohn.Forte@Sun.COM fprintf(stdout, " g_get_wwn_list: "
618*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
619*11547SBill.Gumbrell@Sun.COM (end_time - start_time)/1000000);
6207836SJohn.Forte@Sun.COM }
6217836SJohn.Forte@Sun.COM return (0);
6227836SJohn.Forte@Sun.COM
6237836SJohn.Forte@Sun.COM }
6247836SJohn.Forte@Sun.COM
6257836SJohn.Forte@Sun.COM int
g_devices_get_all(struct wwn_list_struct ** wwn_list_ptr)6267836SJohn.Forte@Sun.COM g_devices_get_all(struct wwn_list_struct **wwn_list_ptr)
6277836SJohn.Forte@Sun.COM {
628*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *tape_ptr = NULL;
629*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *tmp;
630*11547SBill.Gumbrell@Sun.COM int err;
631*11547SBill.Gumbrell@Sun.COM di_node_t root;
632*11547SBill.Gumbrell@Sun.COM hrtime_t start_time, end_time;
633*11547SBill.Gumbrell@Sun.COM char *env = NULL;
6347836SJohn.Forte@Sun.COM
6357836SJohn.Forte@Sun.COM if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
6367836SJohn.Forte@Sun.COM start_time = gethrtime();
6377836SJohn.Forte@Sun.COM }
6387836SJohn.Forte@Sun.COM
6397836SJohn.Forte@Sun.COM /*
6407836SJohn.Forte@Sun.COM * Try to prime di_drv_first_node()
6417836SJohn.Forte@Sun.COM * If there are no nodes bound, di_drv_first_node()
6427836SJohn.Forte@Sun.COM * will return nothing.
6437836SJohn.Forte@Sun.COM */
6447836SJohn.Forte@Sun.COM init_drv(DEV_TAPE_DIR, DIR_MATCH_ST, SLSH_DRV_NAME_ST);
6457836SJohn.Forte@Sun.COM init_drv(DEV_RDIR, DIR_MATCH_SSD, SLSH_DRV_NAME_SSD);
6467836SJohn.Forte@Sun.COM
6477836SJohn.Forte@Sun.COM if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
6487836SJohn.Forte@Sun.COM return (L_DEV_SNAPSHOT_FAILED);
6497836SJohn.Forte@Sun.COM }
6507836SJohn.Forte@Sun.COM
6517836SJohn.Forte@Sun.COM if (env != NULL) {
6527836SJohn.Forte@Sun.COM end_time = gethrtime();
6537836SJohn.Forte@Sun.COM fprintf(stdout, " di_init - /: "
654*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
655*11547SBill.Gumbrell@Sun.COM (end_time - start_time)/1000000);
6567836SJohn.Forte@Sun.COM }
6577836SJohn.Forte@Sun.COM
6587836SJohn.Forte@Sun.COM if (env != NULL) {
6597836SJohn.Forte@Sun.COM start_time = gethrtime();
6607836SJohn.Forte@Sun.COM }
6617836SJohn.Forte@Sun.COM
6627836SJohn.Forte@Sun.COM if ((err = devices_get_all(root, SSD_DRVR_NAME, SSD_MINOR_NAME,
663*11547SBill.Gumbrell@Sun.COM wwn_list_ptr)) != 0) {
6647836SJohn.Forte@Sun.COM if (err != L_NO_DEVICES_FOUND) {
6657836SJohn.Forte@Sun.COM di_fini(root);
6667836SJohn.Forte@Sun.COM g_free_wwn_list(&tape_ptr);
6677836SJohn.Forte@Sun.COM g_free_wwn_list(wwn_list_ptr);
6687836SJohn.Forte@Sun.COM return (err);
6697836SJohn.Forte@Sun.COM }
6707836SJohn.Forte@Sun.COM }
6717836SJohn.Forte@Sun.COM
6727836SJohn.Forte@Sun.COM if (env != NULL) {
6737836SJohn.Forte@Sun.COM end_time = gethrtime();
6747836SJohn.Forte@Sun.COM fprintf(stdout, " devices_get_all - ssd: "
675*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
676*11547SBill.Gumbrell@Sun.COM (end_time - start_time)/1000000);
6777836SJohn.Forte@Sun.COM }
6787836SJohn.Forte@Sun.COM
6797836SJohn.Forte@Sun.COM if (env != NULL) {
6807836SJohn.Forte@Sun.COM start_time = gethrtime();
6817836SJohn.Forte@Sun.COM }
6827836SJohn.Forte@Sun.COM
6837836SJohn.Forte@Sun.COM if ((err = devices_get_all(root, ST_DRVR_NAME, ST_MINOR_NAME,
684*11547SBill.Gumbrell@Sun.COM &tape_ptr)) != 0) {
6857836SJohn.Forte@Sun.COM di_fini(root);
6867836SJohn.Forte@Sun.COM if (err != L_NO_DEVICES_FOUND) {
6877836SJohn.Forte@Sun.COM g_free_wwn_list(&tape_ptr);
6887836SJohn.Forte@Sun.COM g_free_wwn_list(wwn_list_ptr);
6897836SJohn.Forte@Sun.COM return (err);
6907836SJohn.Forte@Sun.COM } else {
6917836SJohn.Forte@Sun.COM /*
6927836SJohn.Forte@Sun.COM * if *wwn_list_ptr == NULL
6937836SJohn.Forte@Sun.COM * we have disks but no tapes
6947836SJohn.Forte@Sun.COM * Just return
6957836SJohn.Forte@Sun.COM */
6967836SJohn.Forte@Sun.COM if (*wwn_list_ptr != NULL) {
6977836SJohn.Forte@Sun.COM return (0);
6987836SJohn.Forte@Sun.COM } else {
6997836SJohn.Forte@Sun.COM /*
7007836SJohn.Forte@Sun.COM * No disks or tapes
7017836SJohn.Forte@Sun.COM */
7027836SJohn.Forte@Sun.COM g_free_wwn_list(&tape_ptr);
7037836SJohn.Forte@Sun.COM g_free_wwn_list(wwn_list_ptr);
7047836SJohn.Forte@Sun.COM return (err);
7057836SJohn.Forte@Sun.COM }
7067836SJohn.Forte@Sun.COM }
7077836SJohn.Forte@Sun.COM }
7087836SJohn.Forte@Sun.COM
7097836SJohn.Forte@Sun.COM if (env != NULL) {
7107836SJohn.Forte@Sun.COM end_time = gethrtime();
7117836SJohn.Forte@Sun.COM fprintf(stdout, " devices_get_all - st: "
712*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
713*11547SBill.Gumbrell@Sun.COM (end_time - start_time)/1000000);
7147836SJohn.Forte@Sun.COM }
7157836SJohn.Forte@Sun.COM
7167836SJohn.Forte@Sun.COM /* Now link the two together */
7177836SJohn.Forte@Sun.COM if (*wwn_list_ptr != NULL) { /* We have both disks and tapes */
7187836SJohn.Forte@Sun.COM /* Walk to the end of it */
7197836SJohn.Forte@Sun.COM for (tmp = *wwn_list_ptr; tmp->wwn_next != NULL;
720*11547SBill.Gumbrell@Sun.COM tmp = tmp->wwn_next)
721*11547SBill.Gumbrell@Sun.COM ;
7227836SJohn.Forte@Sun.COM tmp->wwn_next = tape_ptr;
7237836SJohn.Forte@Sun.COM tape_ptr->wwn_prev = tmp;
7247836SJohn.Forte@Sun.COM di_fini(root);
7257836SJohn.Forte@Sun.COM return (0);
7267836SJohn.Forte@Sun.COM }
7277836SJohn.Forte@Sun.COM
7287836SJohn.Forte@Sun.COM /* else we have no disks */
7297836SJohn.Forte@Sun.COM *wwn_list_ptr = tape_ptr;
7307836SJohn.Forte@Sun.COM di_fini(root);
7317836SJohn.Forte@Sun.COM return (0);
7327836SJohn.Forte@Sun.COM }
7337836SJohn.Forte@Sun.COM
7347836SJohn.Forte@Sun.COM void
g_free_wwn_list_found(struct wwn_list_found_struct ** wwn_list_found)7357836SJohn.Forte@Sun.COM g_free_wwn_list_found(struct wwn_list_found_struct **wwn_list_found) {
7367836SJohn.Forte@Sun.COM WWN_list_found *next = NULL;
7377836SJohn.Forte@Sun.COM
7387836SJohn.Forte@Sun.COM /* return if wwn_list_found is NULL */
7397836SJohn.Forte@Sun.COM if (wwn_list_found == NULL) {
7407836SJohn.Forte@Sun.COM return;
7417836SJohn.Forte@Sun.COM }
7427836SJohn.Forte@Sun.COM for (; *wwn_list_found != NULL; *wwn_list_found = next) {
7437836SJohn.Forte@Sun.COM next = (*wwn_list_found)->wwn_next;
7447836SJohn.Forte@Sun.COM g_destroy_data(*wwn_list_found);
7457836SJohn.Forte@Sun.COM *wwn_list_found = NULL;
7467836SJohn.Forte@Sun.COM }
7477836SJohn.Forte@Sun.COM }
7487836SJohn.Forte@Sun.COM
7497836SJohn.Forte@Sun.COM void
g_free_wwn_list(struct wwn_list_struct ** wwn_list)7507836SJohn.Forte@Sun.COM g_free_wwn_list(struct wwn_list_struct **wwn_list)
7517836SJohn.Forte@Sun.COM {
752*11547SBill.Gumbrell@Sun.COM WWN_list *next = NULL;
7537836SJohn.Forte@Sun.COM
7547836SJohn.Forte@Sun.COM /* return if wwn_list is NULL */
7557836SJohn.Forte@Sun.COM if (wwn_list == NULL) {
7567836SJohn.Forte@Sun.COM return;
7577836SJohn.Forte@Sun.COM }
7587836SJohn.Forte@Sun.COM
7597836SJohn.Forte@Sun.COM for (; *wwn_list != NULL; *wwn_list = next) {
7607836SJohn.Forte@Sun.COM next = (*wwn_list)->wwn_next;
7617836SJohn.Forte@Sun.COM if ((*wwn_list)->physical_path != NULL)
7627836SJohn.Forte@Sun.COM (void) g_destroy_data((*wwn_list)->physical_path);
7637836SJohn.Forte@Sun.COM if ((*wwn_list)->logical_path != NULL)
7647836SJohn.Forte@Sun.COM (void) g_destroy_data((*wwn_list)->logical_path);
7657836SJohn.Forte@Sun.COM (void) g_destroy_data(*wwn_list);
7667836SJohn.Forte@Sun.COM }
7677836SJohn.Forte@Sun.COM wwn_list = NULL;
7687836SJohn.Forte@Sun.COM }
7697836SJohn.Forte@Sun.COM
7707836SJohn.Forte@Sun.COM
7717836SJohn.Forte@Sun.COM
7727836SJohn.Forte@Sun.COM
7737836SJohn.Forte@Sun.COM void
g_sort_wwn_list(struct wwn_list_struct ** wwn_list)7747836SJohn.Forte@Sun.COM g_sort_wwn_list(struct wwn_list_struct **wwn_list)
7757836SJohn.Forte@Sun.COM {
7767836SJohn.Forte@Sun.COM int i, n;
7777836SJohn.Forte@Sun.COM struct wwn_list_struct **wwn_list_array;
7787836SJohn.Forte@Sun.COM struct wwn_list_struct *wwn_list_ptr;
7797836SJohn.Forte@Sun.COM struct wwn_list_struct **wwn_list_array_ptr1;
7807836SJohn.Forte@Sun.COM struct wwn_list_struct **wwn_list_array_ptr2;
7817836SJohn.Forte@Sun.COM
7827836SJohn.Forte@Sun.COM /*
7837836SJohn.Forte@Sun.COM * Count the number of wwn_list in the list
7847836SJohn.Forte@Sun.COM */
7857836SJohn.Forte@Sun.COM for (n = 0, wwn_list_ptr = *wwn_list;
7867836SJohn.Forte@Sun.COM wwn_list_ptr != NULL;
7877836SJohn.Forte@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
7887836SJohn.Forte@Sun.COM n++;
7897836SJohn.Forte@Sun.COM }
7907836SJohn.Forte@Sun.COM if (n <= 1) {
7917836SJohn.Forte@Sun.COM return;
7927836SJohn.Forte@Sun.COM }
7937836SJohn.Forte@Sun.COM
7947836SJohn.Forte@Sun.COM /*
7957836SJohn.Forte@Sun.COM * Allocate a simple wwn_list array and fill it in
7967836SJohn.Forte@Sun.COM */
7977836SJohn.Forte@Sun.COM wwn_list_array = (struct wwn_list_struct **)
7987836SJohn.Forte@Sun.COM g_zalloc((n+1) * sizeof (struct wwn_list_struct *));
7997836SJohn.Forte@Sun.COM
8007836SJohn.Forte@Sun.COM wwn_list_array_ptr1 = wwn_list_array;
8017836SJohn.Forte@Sun.COM for (wwn_list_ptr = *wwn_list;
8027836SJohn.Forte@Sun.COM wwn_list_ptr != NULL;
8037836SJohn.Forte@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
8047836SJohn.Forte@Sun.COM *wwn_list_array_ptr1++ = wwn_list_ptr;
8057836SJohn.Forte@Sun.COM }
8067836SJohn.Forte@Sun.COM *wwn_list_array_ptr1 = NULL;
8077836SJohn.Forte@Sun.COM
8087836SJohn.Forte@Sun.COM /*
8097836SJohn.Forte@Sun.COM * Sort the wwn_list array
8107836SJohn.Forte@Sun.COM */
8117836SJohn.Forte@Sun.COM qsort((void *) wwn_list_array, n,
8127836SJohn.Forte@Sun.COM sizeof (struct wwn_list_struct *), wwn_list_name_compare);
8137836SJohn.Forte@Sun.COM
8147836SJohn.Forte@Sun.COM /*
8157836SJohn.Forte@Sun.COM * Rebuild the linked list wwn_list structure
8167836SJohn.Forte@Sun.COM */
8177836SJohn.Forte@Sun.COM wwn_list_array_ptr1 = wwn_list_array;
8187836SJohn.Forte@Sun.COM *wwn_list = *wwn_list_array_ptr1;
8197836SJohn.Forte@Sun.COM wwn_list_array_ptr2 = wwn_list_array_ptr1 + 1;
8207836SJohn.Forte@Sun.COM (*wwn_list_array_ptr1)->wwn_prev = NULL;
8217836SJohn.Forte@Sun.COM for (i = 0; i < n - 1; i++) {
822*11547SBill.Gumbrell@Sun.COM (*wwn_list_array_ptr2)->wwn_prev = *wwn_list_array_ptr1;
823*11547SBill.Gumbrell@Sun.COM (*wwn_list_array_ptr1++)->wwn_next = *wwn_list_array_ptr2++;
8247836SJohn.Forte@Sun.COM }
8257836SJohn.Forte@Sun.COM (*wwn_list_array_ptr1)->wwn_next = NULL;
8267836SJohn.Forte@Sun.COM
8277836SJohn.Forte@Sun.COM /*
8287836SJohn.Forte@Sun.COM * Clean up
8297836SJohn.Forte@Sun.COM */
8307836SJohn.Forte@Sun.COM (void) g_destroy_data((void *)wwn_list_array);
8317836SJohn.Forte@Sun.COM }
8327836SJohn.Forte@Sun.COM
8337836SJohn.Forte@Sun.COM int
wwn_list_name_compare(const void * arg1,const void * arg2)8347836SJohn.Forte@Sun.COM wwn_list_name_compare(const void *arg1, const void *arg2)
8357836SJohn.Forte@Sun.COM {
8367836SJohn.Forte@Sun.COM char *s1, *s2;
8377836SJohn.Forte@Sun.COM int n1, n2;
8387836SJohn.Forte@Sun.COM char *p1, *p2;
8397836SJohn.Forte@Sun.COM
8407836SJohn.Forte@Sun.COM s1 = (*((struct wwn_list_struct **)arg1))->logical_path;
8417836SJohn.Forte@Sun.COM s2 = (*((struct wwn_list_struct **)arg2))->logical_path;
8427836SJohn.Forte@Sun.COM for (;;) {
8437836SJohn.Forte@Sun.COM if (*s1 == 0 || *s2 == 0)
8447836SJohn.Forte@Sun.COM break;
8457836SJohn.Forte@Sun.COM if ((isdigit(*s1) && isdigit(*s2))) {
8467836SJohn.Forte@Sun.COM n1 = strtol(s1, &p1, 10);
8477836SJohn.Forte@Sun.COM n2 = strtol(s2, &p2, 10);
8487836SJohn.Forte@Sun.COM if (n1 != n2) {
8497836SJohn.Forte@Sun.COM return (n1 - n2);
8507836SJohn.Forte@Sun.COM }
8517836SJohn.Forte@Sun.COM s1 = p1;
8527836SJohn.Forte@Sun.COM s2 = p2;
8537836SJohn.Forte@Sun.COM } else if (*s1 != *s2) {
8547836SJohn.Forte@Sun.COM break;
8557836SJohn.Forte@Sun.COM } else {
8567836SJohn.Forte@Sun.COM s1++;
8577836SJohn.Forte@Sun.COM s2++;
8587836SJohn.Forte@Sun.COM }
8597836SJohn.Forte@Sun.COM }
8607836SJohn.Forte@Sun.COM return (*s1 - *s2);
8617836SJohn.Forte@Sun.COM }
8627836SJohn.Forte@Sun.COM
8637836SJohn.Forte@Sun.COM /*
8647836SJohn.Forte@Sun.COM * Get the limited map for FC4 devices.
8657836SJohn.Forte@Sun.COM * This function is specific to FC4
8667836SJohn.Forte@Sun.COM * devices and doesn't work for FC (leadville) devices.
8677836SJohn.Forte@Sun.COM *
8687836SJohn.Forte@Sun.COM * RETURN VALUES:
8697836SJohn.Forte@Sun.COM * 0 O.K.
8707836SJohn.Forte@Sun.COM * non-zero otherwise
8717836SJohn.Forte@Sun.COM *
8727836SJohn.Forte@Sun.COM * lilpmap *map_ptr:
8737836SJohn.Forte@Sun.COM * NULL: No devices found
8747836SJohn.Forte@Sun.COM * !NULL: if devices found
8757836SJohn.Forte@Sun.COM */
8767836SJohn.Forte@Sun.COM int
g_get_limited_map(char * path,struct lilpmap * map_ptr,int verbose)8777836SJohn.Forte@Sun.COM g_get_limited_map(char *path, struct lilpmap *map_ptr, int verbose)
8787836SJohn.Forte@Sun.COM {
879*11547SBill.Gumbrell@Sun.COM int fd, i;
880*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN];
881*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
8827836SJohn.Forte@Sun.COM
8837836SJohn.Forte@Sun.COM
8847836SJohn.Forte@Sun.COM /* initialize map */
8857836SJohn.Forte@Sun.COM (void) memset(map_ptr, 0, sizeof (struct lilpmap));
8867836SJohn.Forte@Sun.COM
8877836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
8887836SJohn.Forte@Sun.COM /*
8897836SJohn.Forte@Sun.COM * Get the path to the :devctl driver
8907836SJohn.Forte@Sun.COM *
8917836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
8927836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
8937836SJohn.Forte@Sun.COM * or
8947836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0
8957836SJohn.Forte@Sun.COM * or
8967836SJohn.Forte@Sun.COM * a 1 level PCI type driver
8977836SJohn.Forte@Sun.COM */
8987836SJohn.Forte@Sun.COM if (stat(drvr_path, &stbuf) < 0) {
8997836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
9007836SJohn.Forte@Sun.COM }
9017836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
9027836SJohn.Forte@Sun.COM /* append a port. Just try 0 since they did not give us one */
9037836SJohn.Forte@Sun.COM (void) strcat(drvr_path, ":0");
9047836SJohn.Forte@Sun.COM }
9057836SJohn.Forte@Sun.COM
9067836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_limited_map: Geting drive map from:"
907*11547SBill.Gumbrell@Sun.COM " %s\n", drvr_path);
9087836SJohn.Forte@Sun.COM
9097836SJohn.Forte@Sun.COM /* open controller */
9107836SJohn.Forte@Sun.COM if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
9117836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
9127836SJohn.Forte@Sun.COM
9137836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_GETMAP, map_ptr) != 0) {
9147836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GETMAP ioctl failed\n");
9157836SJohn.Forte@Sun.COM (void) close(fd);
9167836SJohn.Forte@Sun.COM return (L_FCIO_GETMAP_IOCTL_FAIL);
9177836SJohn.Forte@Sun.COM }
9187836SJohn.Forte@Sun.COM (void) close(fd);
9197836SJohn.Forte@Sun.COM
9207836SJohn.Forte@Sun.COM /*
9217836SJohn.Forte@Sun.COM * Check for reasonableness.
9227836SJohn.Forte@Sun.COM */
9237836SJohn.Forte@Sun.COM if ((map_ptr->lilp_length > 126) || (map_ptr->lilp_magic != 0x1107)) {
9247836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
9257836SJohn.Forte@Sun.COM }
9267836SJohn.Forte@Sun.COM for (i = 0; i < (uint_t)map_ptr->lilp_length; i++) {
9277836SJohn.Forte@Sun.COM if (map_ptr->lilp_list[i] > 0xef) {
9287836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
9297836SJohn.Forte@Sun.COM }
9307836SJohn.Forte@Sun.COM }
9317836SJohn.Forte@Sun.COM
9327836SJohn.Forte@Sun.COM return (0);
9337836SJohn.Forte@Sun.COM }
9347836SJohn.Forte@Sun.COM
9357836SJohn.Forte@Sun.COM
9367836SJohn.Forte@Sun.COM /*
9377836SJohn.Forte@Sun.COM * For leadville specific HBA's ONLY.
9387836SJohn.Forte@Sun.COM * Get the host specific parameters,
9397836SJohn.Forte@Sun.COM * al_pa, hard address, node/port WWN etc.
9407836SJohn.Forte@Sun.COM *
9417836SJohn.Forte@Sun.COM * OUTPUT:
9427836SJohn.Forte@Sun.COM * fc_port_dev_t structure.
9437836SJohn.Forte@Sun.COM *
9447836SJohn.Forte@Sun.COM * RETURNS:
9457836SJohn.Forte@Sun.COM * 0 if OK
9467836SJohn.Forte@Sun.COM * non-zero in case of error.
9477836SJohn.Forte@Sun.COM */
9487836SJohn.Forte@Sun.COM int
g_get_host_params(char * host_path,fc_port_dev_t * host_val,int verbose)9497836SJohn.Forte@Sun.COM g_get_host_params(char *host_path, fc_port_dev_t *host_val, int verbose)
9507836SJohn.Forte@Sun.COM {
951*11547SBill.Gumbrell@Sun.COM int err;
952*11547SBill.Gumbrell@Sun.COM int fd;
953*11547SBill.Gumbrell@Sun.COM int dev_type;
954*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
9557836SJohn.Forte@Sun.COM
9567836SJohn.Forte@Sun.COM /* return invalid path if host_path is NULL */
9577836SJohn.Forte@Sun.COM if (host_path == NULL) {
9587836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
9597836SJohn.Forte@Sun.COM }
9607836SJohn.Forte@Sun.COM /* return invalid arg if host_val is NULL */
9617836SJohn.Forte@Sun.COM if (host_val == NULL) {
9627836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
9637836SJohn.Forte@Sun.COM }
9647836SJohn.Forte@Sun.COM
9657836SJohn.Forte@Sun.COM dev_type = g_get_path_type(host_path);
9667836SJohn.Forte@Sun.COM if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
9677836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
9687836SJohn.Forte@Sun.COM }
9697836SJohn.Forte@Sun.COM if ((fd = g_object_open(host_path, O_NDELAY | O_RDONLY)) == -1) {
9707836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
9717836SJohn.Forte@Sun.COM }
9727836SJohn.Forte@Sun.COM
9737836SJohn.Forte@Sun.COM /* initialize structure */
9747836SJohn.Forte@Sun.COM (void) memset(host_val, 0, sizeof (struct fc_port_dev));
9757836SJohn.Forte@Sun.COM
9767836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_HOST_PARAMS;
9777836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
9787836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)host_val;
9797836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (fc_port_dev_t);
9807836SJohn.Forte@Sun.COM
9817836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
9827836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n");
9837836SJohn.Forte@Sun.COM (void) close(fd);
9847836SJohn.Forte@Sun.COM return (L_FCIO_GET_HOST_PARAMS_FAIL);
9857836SJohn.Forte@Sun.COM }
9867836SJohn.Forte@Sun.COM (void) close(fd);
9877836SJohn.Forte@Sun.COM
9887836SJohn.Forte@Sun.COM /* get the inquiry information for the leadville HBA. */
9897836SJohn.Forte@Sun.COM if ((err = get_fca_inq_dtype(host_path, host_val->dev_pwwn,
990*11547SBill.Gumbrell@Sun.COM &host_val->dev_dtype)) != 0) {
9917836SJohn.Forte@Sun.COM return (err);
9927836SJohn.Forte@Sun.COM }
9937836SJohn.Forte@Sun.COM return (0);
9947836SJohn.Forte@Sun.COM }
9957836SJohn.Forte@Sun.COM
9967836SJohn.Forte@Sun.COM
9977836SJohn.Forte@Sun.COM
9987836SJohn.Forte@Sun.COM /*
9997836SJohn.Forte@Sun.COM * Issue FCIO ioctls to the port(fp) driver.
10007836SJohn.Forte@Sun.COM * FCIO ioctl needs to be retried when it
10017836SJohn.Forte@Sun.COM * is returned with an EINVAL error, wait
10027836SJohn.Forte@Sun.COM * time between retries should be atleast
10037836SJohn.Forte@Sun.COM * WAIT_FCIO_IOCTL (too much of a time to wait!!)
10047836SJohn.Forte@Sun.COM *
10057836SJohn.Forte@Sun.COM * OUTPUT:
10067836SJohn.Forte@Sun.COM * fcio_t structure
10077836SJohn.Forte@Sun.COM *
10087836SJohn.Forte@Sun.COM * RETURNS:
10097836SJohn.Forte@Sun.COM * 0 if O.K.
10107836SJohn.Forte@Sun.COM * non-zero otherwise.
10117836SJohn.Forte@Sun.COM */
10127836SJohn.Forte@Sun.COM int
g_issue_fcio_ioctl(int fd,fcio_t * fcio,int verbose)10137836SJohn.Forte@Sun.COM g_issue_fcio_ioctl(int fd, fcio_t *fcio, int verbose)
10147836SJohn.Forte@Sun.COM {
1015*11547SBill.Gumbrell@Sun.COM int ntries;
10167836SJohn.Forte@Sun.COM
10177836SJohn.Forte@Sun.COM for (ntries = 0; ntries < RETRY_FCIO_IOCTL; ntries++) {
10187836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_CMD, fcio) != 0) {
10197836SJohn.Forte@Sun.COM if ((errno == EAGAIN) &&
1020*11547SBill.Gumbrell@Sun.COM (ntries+1 < RETRY_FCIO_IOCTL)) {
10217836SJohn.Forte@Sun.COM /* wait WAIT_FCIO_IOCTL */
10227836SJohn.Forte@Sun.COM (void) usleep(WAIT_FCIO_IOCTL);
10237836SJohn.Forte@Sun.COM continue;
10247836SJohn.Forte@Sun.COM }
10257836SJohn.Forte@Sun.COM I_DPRINTF("FCIO ioctl failed.\n"
1026*11547SBill.Gumbrell@Sun.COM "Error: %s. fc_error = %d (0x%x)\n",
1027*11547SBill.Gumbrell@Sun.COM strerror(errno), fcio->fcio_errno,
1028*11547SBill.Gumbrell@Sun.COM fcio->fcio_errno);
10297836SJohn.Forte@Sun.COM if (errno == EINVAL) {
10307836SJohn.Forte@Sun.COM if (fcio->fcio_errno == FC_TOOMANY) {
10317836SJohn.Forte@Sun.COM return (L_INVALID_DEVICE_COUNT);
10327836SJohn.Forte@Sun.COM } else {
10337836SJohn.Forte@Sun.COM return (errno);
10347836SJohn.Forte@Sun.COM }
10357836SJohn.Forte@Sun.COM }
10367836SJohn.Forte@Sun.COM /*
10377836SJohn.Forte@Sun.COM * When port is offlined, qlc
10387836SJohn.Forte@Sun.COM * returns the FC_OFFLINE error and errno
10397836SJohn.Forte@Sun.COM * is set to EIO.
10407836SJohn.Forte@Sun.COM * We do want to ignore this error,
10417836SJohn.Forte@Sun.COM * especially when an enclosure is
10427836SJohn.Forte@Sun.COM * removed from the loop.
10437836SJohn.Forte@Sun.COM */
10447836SJohn.Forte@Sun.COM if (fcio->fcio_errno == FC_OFFLINE)
10457836SJohn.Forte@Sun.COM break;
10467836SJohn.Forte@Sun.COM return (-1);
10477836SJohn.Forte@Sun.COM }
10487836SJohn.Forte@Sun.COM break;
10497836SJohn.Forte@Sun.COM }
10507836SJohn.Forte@Sun.COM
10517836SJohn.Forte@Sun.COM return (0);
10527836SJohn.Forte@Sun.COM }
10537836SJohn.Forte@Sun.COM
10547836SJohn.Forte@Sun.COM /*
10557836SJohn.Forte@Sun.COM * This function issues the FCP_TGT_INQUIRY ioctl to
10567836SJohn.Forte@Sun.COM * the fcp module
10577836SJohn.Forte@Sun.COM *
10587836SJohn.Forte@Sun.COM * OUTPUT:
10597836SJohn.Forte@Sun.COM * fcp_ioctl structure in fcp_data is filled in by fcp
10607836SJohn.Forte@Sun.COM *
10617836SJohn.Forte@Sun.COM * RETURN VALUES :
10627836SJohn.Forte@Sun.COM * 0 on Success
10637836SJohn.Forte@Sun.COM * Non-zero otherwise
10647836SJohn.Forte@Sun.COM */
10657836SJohn.Forte@Sun.COM static int
g_issue_fcp_ioctl(int fd,struct fcp_ioctl * fcp_data,int verbose)10667836SJohn.Forte@Sun.COM g_issue_fcp_ioctl(int fd, struct fcp_ioctl *fcp_data, int verbose)
10677836SJohn.Forte@Sun.COM {
10687836SJohn.Forte@Sun.COM int num_tries = 0;
10697836SJohn.Forte@Sun.COM struct device_data *dev_data = NULL;
10707836SJohn.Forte@Sun.COM
10717836SJohn.Forte@Sun.COM /*
10727836SJohn.Forte@Sun.COM * Issue the ioctl to FCP
10737836SJohn.Forte@Sun.COM * The retries are required because the driver may
10747836SJohn.Forte@Sun.COM * need some time to respond at times.
10757836SJohn.Forte@Sun.COM */
10767836SJohn.Forte@Sun.COM while (num_tries++ < RETRY_FCP_IOCTL) {
10777836SJohn.Forte@Sun.COM /* if ioctl fails it is an error from Solaris operation. */
10787836SJohn.Forte@Sun.COM if (ioctl(fd, FCP_TGT_INQUIRY, fcp_data) == -1) {
10797836SJohn.Forte@Sun.COM if (errno == EAGAIN) {
10807836SJohn.Forte@Sun.COM (void) usleep(WAIT_FCP_IOCTL);
10817836SJohn.Forte@Sun.COM continue;
10827836SJohn.Forte@Sun.COM } else {
10837836SJohn.Forte@Sun.COM break;
10847836SJohn.Forte@Sun.COM }
10857836SJohn.Forte@Sun.COM }
10867836SJohn.Forte@Sun.COM dev_data = (struct device_data *)((void *)(fcp_data->list));
10877836SJohn.Forte@Sun.COM if (dev_data->dev_status == 0) {
10887836SJohn.Forte@Sun.COM return (0);
10897836SJohn.Forte@Sun.COM }
10907836SJohn.Forte@Sun.COM
10917836SJohn.Forte@Sun.COM if (dev_data->dev_status == EAGAIN) {
10927836SJohn.Forte@Sun.COM (void) usleep(WAIT_FCP_IOCTL);
10937836SJohn.Forte@Sun.COM continue;
10947836SJohn.Forte@Sun.COM } else {
10957836SJohn.Forte@Sun.COM dev_data->dev0_type = DTYPE_UNKNOWN;
10967836SJohn.Forte@Sun.COM return (0);
10977836SJohn.Forte@Sun.COM }
10987836SJohn.Forte@Sun.COM }
10997836SJohn.Forte@Sun.COM
11007836SJohn.Forte@Sun.COM return (L_FCP_TGT_INQUIRY_FAIL);
11017836SJohn.Forte@Sun.COM }
11027836SJohn.Forte@Sun.COM
11037836SJohn.Forte@Sun.COM /*
11047836SJohn.Forte@Sun.COM * Get the number of devices and also
11057836SJohn.Forte@Sun.COM * a list of devices accessible through
11067836SJohn.Forte@Sun.COM * the device's port as specified by path.
11077836SJohn.Forte@Sun.COM * The calling function * is responsible for freeing the dev_list.
11087836SJohn.Forte@Sun.COM *
11097836SJohn.Forte@Sun.COM * Acquires inq_dtype from g_get_inq_dtype() and
11107836SJohn.Forte@Sun.COM * stores into dev_dtype field of fc_port_dev.
11117836SJohn.Forte@Sun.COM *
11127836SJohn.Forte@Sun.COM * For fabric devices call FCIO_DEV_LOGIN (if necessary) to execute port login
11137836SJohn.Forte@Sun.COM * and get inq dtype.
11147836SJohn.Forte@Sun.COM *
11157836SJohn.Forte@Sun.COM * dev_list:
11167836SJohn.Forte@Sun.COM * NULL: No devices found, in case of an error
11177836SJohn.Forte@Sun.COM * Non-NULL: Devices found.
11187836SJohn.Forte@Sun.COM * ndevs:
11197836SJohn.Forte@Sun.COM * set to the number of devices
11207836SJohn.Forte@Sun.COM * accessible through the port.
11217836SJohn.Forte@Sun.COM *
11227836SJohn.Forte@Sun.COM * RETURNS:
11237836SJohn.Forte@Sun.COM * 0 if O.K.
11247836SJohn.Forte@Sun.COM * non-zero otherwise
11257836SJohn.Forte@Sun.COM */
11267836SJohn.Forte@Sun.COM int
g_get_dev_list(char * path,fc_port_dev_t ** dev_list,int * ndevs)11277836SJohn.Forte@Sun.COM g_get_dev_list(char *path, fc_port_dev_t **dev_list, int *ndevs)
11287836SJohn.Forte@Sun.COM {
1129*11547SBill.Gumbrell@Sun.COM int num_devices = 0;
1130*11547SBill.Gumbrell@Sun.COM int i, err, ulp_failure = 0, new_count = 0;
1131*11547SBill.Gumbrell@Sun.COM int dev_type;
1132*11547SBill.Gumbrell@Sun.COM int fd;
1133*11547SBill.Gumbrell@Sun.COM char fcapath[MAXPATHLEN];
1134*11547SBill.Gumbrell@Sun.COM char *char_ptr;
1135*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
1136*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
1137*11547SBill.Gumbrell@Sun.COM uint32_t port_top;
1138*11547SBill.Gumbrell@Sun.COM fc_port_dev_t *dlist;
11397836SJohn.Forte@Sun.COM
11407836SJohn.Forte@Sun.COM *dev_list = dlist = NULL;
11417836SJohn.Forte@Sun.COM (void) strcpy(fcapath, path);
11427836SJohn.Forte@Sun.COM /*
11437836SJohn.Forte@Sun.COM * Get the path to the :devctl driver
11447836SJohn.Forte@Sun.COM *
11457836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
11467836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
11477836SJohn.Forte@Sun.COM * or
11487836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
11497836SJohn.Forte@Sun.COM * or
11507836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
11517836SJohn.Forte@Sun.COM * or
11527836SJohn.Forte@Sun.COM * a 1 level PCI type driver but still :devctl
11537836SJohn.Forte@Sun.COM */
11547836SJohn.Forte@Sun.COM if (strstr(fcapath, DRV_NAME_SSD) || strstr(fcapath, SES_NAME)) {
11557836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(fcapath, '/')) == NULL) {
11567836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
11577836SJohn.Forte@Sun.COM }
11587836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate sting */
11597836SJohn.Forte@Sun.COM /* append controller */
11607836SJohn.Forte@Sun.COM (void) strcat(fcapath, FC_CTLR);
11617836SJohn.Forte@Sun.COM } else {
11627836SJohn.Forte@Sun.COM if (stat(fcapath, &stbuf) < 0) {
11637836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
11647836SJohn.Forte@Sun.COM }
11657836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
11667836SJohn.Forte@Sun.COM /* append controller */
11677836SJohn.Forte@Sun.COM (void) strcat(fcapath, FC_CTLR);
11687836SJohn.Forte@Sun.COM }
11697836SJohn.Forte@Sun.COM }
11707836SJohn.Forte@Sun.COM dev_type = g_get_path_type(fcapath);
11717836SJohn.Forte@Sun.COM if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
11727836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
11737836SJohn.Forte@Sun.COM }
11747836SJohn.Forte@Sun.COM if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) {
11757836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
11767836SJohn.Forte@Sun.COM }
11777836SJohn.Forte@Sun.COM
11787836SJohn.Forte@Sun.COM /*
11797836SJohn.Forte@Sun.COM * Get the device list from port driver
11807836SJohn.Forte@Sun.COM */
11817836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_NUM_DEVS;
11827836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (num_devices);
11837836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
11847836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&num_devices;
11857836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
11867836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n");
11877836SJohn.Forte@Sun.COM (void) close(fd);
11887836SJohn.Forte@Sun.COM return (L_FCIO_GET_NUM_DEVS_FAIL);
11897836SJohn.Forte@Sun.COM }
11907836SJohn.Forte@Sun.COM if (num_devices == 0) {
11917836SJohn.Forte@Sun.COM *ndevs = 0;
11927836SJohn.Forte@Sun.COM (void) close(fd);
11937836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
11947836SJohn.Forte@Sun.COM }
11957836SJohn.Forte@Sun.COM
11967836SJohn.Forte@Sun.COM if ((dlist = (fc_port_dev_t *)calloc(num_devices,
1197*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t))) == NULL) {
11987836SJohn.Forte@Sun.COM (void) close(fd);
11997836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
12007836SJohn.Forte@Sun.COM }
12017836SJohn.Forte@Sun.COM bzero((caddr_t)&fcio, sizeof (fcio));
12027836SJohn.Forte@Sun.COM /* Get the device list */
12037836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_DEV_LIST;
12047836SJohn.Forte@Sun.COM /* Information read operation */
12057836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
12067836SJohn.Forte@Sun.COM fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
12077836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)dlist;
12087836SJohn.Forte@Sun.COM /* new device count */
12097836SJohn.Forte@Sun.COM fcio.fcio_alen = sizeof (new_count);
12107836SJohn.Forte@Sun.COM fcio.fcio_abuf = (caddr_t)&new_count;
12117836SJohn.Forte@Sun.COM if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
1212*11547SBill.Gumbrell@Sun.COM if (err == L_INVALID_DEVICE_COUNT) {
1213*11547SBill.Gumbrell@Sun.COM /*
1214*11547SBill.Gumbrell@Sun.COM * original buffer was small so allocate buffer
1215*11547SBill.Gumbrell@Sun.COM * with a new count and retry.
1216*11547SBill.Gumbrell@Sun.COM */
1217*11547SBill.Gumbrell@Sun.COM free(dlist);
1218*11547SBill.Gumbrell@Sun.COM num_devices = new_count;
1219*11547SBill.Gumbrell@Sun.COM new_count = 0;
1220*11547SBill.Gumbrell@Sun.COM if ((dlist = (fc_port_dev_t *)calloc(num_devices,
1221*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t))) == NULL) {
1222*11547SBill.Gumbrell@Sun.COM (void) close(fd);
1223*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
1224*11547SBill.Gumbrell@Sun.COM }
1225*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_GET_DEV_LIST;
1226*11547SBill.Gumbrell@Sun.COM /* Information read operation */
1227*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
1228*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)dlist;
1229*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
1230*11547SBill.Gumbrell@Sun.COM /* new device count */
1231*11547SBill.Gumbrell@Sun.COM fcio.fcio_alen = sizeof (new_count);
1232*11547SBill.Gumbrell@Sun.COM fcio.fcio_abuf = (caddr_t)&new_count;
1233*11547SBill.Gumbrell@Sun.COM if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
1234*11547SBill.Gumbrell@Sun.COM if (err == L_INVALID_DEVICE_COUNT) {
1235*11547SBill.Gumbrell@Sun.COM /*
1236*11547SBill.Gumbrell@Sun.COM * No more retry. There may be severe
1237*11547SBill.Gumbrell@Sun.COM * hardware problem so return error
1238*11547SBill.Gumbrell@Sun.COM * here.
1239*11547SBill.Gumbrell@Sun.COM */
1240*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" Device count was %d"
1241*11547SBill.Gumbrell@Sun.COM " should have been %d\n",
1242*11547SBill.Gumbrell@Sun.COM num_devices, new_count);
1243*11547SBill.Gumbrell@Sun.COM } else {
1244*11547SBill.Gumbrell@Sun.COM I_DPRINTF(
1245*11547SBill.Gumbrell@Sun.COM " FCIO_GET_DEV_LIST ioctl failed.");
1246*11547SBill.Gumbrell@Sun.COM err = L_FCIO_GET_DEV_LIST_FAIL;
1247*11547SBill.Gumbrell@Sun.COM }
1248*11547SBill.Gumbrell@Sun.COM free(dlist);
1249*11547SBill.Gumbrell@Sun.COM (void) close(fd);
1250*11547SBill.Gumbrell@Sun.COM return (err);
1251*11547SBill.Gumbrell@Sun.COM }
1252*11547SBill.Gumbrell@Sun.COM } else {
1253*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed.");
1254*11547SBill.Gumbrell@Sun.COM free(dlist);
12557836SJohn.Forte@Sun.COM (void) close(fd);
1256*11547SBill.Gumbrell@Sun.COM return (L_FCIO_GET_DEV_LIST_FAIL);
12577836SJohn.Forte@Sun.COM }
12587836SJohn.Forte@Sun.COM }
12597836SJohn.Forte@Sun.COM
12607836SJohn.Forte@Sun.COM /*
12617836SJohn.Forte@Sun.COM * if new count is smaller than the original number from
12627836SJohn.Forte@Sun.COM * FCIO_GET_NUM_DEVS, adjust new count and buffer size
12637836SJohn.Forte@Sun.COM * and continue.
12647836SJohn.Forte@Sun.COM */
12657836SJohn.Forte@Sun.COM if (new_count < num_devices) {
12667836SJohn.Forte@Sun.COM if (new_count == 0) {
12677836SJohn.Forte@Sun.COM *ndevs = 0;
12687836SJohn.Forte@Sun.COM (void) close(fd);
12697836SJohn.Forte@Sun.COM S_FREE(dlist);
12707836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
12717836SJohn.Forte@Sun.COM }
12727836SJohn.Forte@Sun.COM num_devices = new_count;
12737836SJohn.Forte@Sun.COM if ((dlist = (fc_port_dev_t *)realloc(dlist,
1274*11547SBill.Gumbrell@Sun.COM (new_count * sizeof (fc_port_dev_t))))
1275*11547SBill.Gumbrell@Sun.COM == NULL) {
12767836SJohn.Forte@Sun.COM S_FREE(dlist);
12777836SJohn.Forte@Sun.COM (void) close(fd);
12787836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
12797836SJohn.Forte@Sun.COM }
12807836SJohn.Forte@Sun.COM }
12817836SJohn.Forte@Sun.COM
12827836SJohn.Forte@Sun.COM *dev_list = dlist;
12837836SJohn.Forte@Sun.COM *ndevs = num_devices;
12847836SJohn.Forte@Sun.COM
12857836SJohn.Forte@Sun.COM /* close here since fcapath will be passed to other routines. */
12867836SJohn.Forte@Sun.COM (void) close(fd);
12877836SJohn.Forte@Sun.COM
12887836SJohn.Forte@Sun.COM if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) {
12897836SJohn.Forte@Sun.COM free(*dev_list);
12907836SJohn.Forte@Sun.COM *dev_list = NULL;
12917836SJohn.Forte@Sun.COM return (err);
12927836SJohn.Forte@Sun.COM }
12937836SJohn.Forte@Sun.COM
12947836SJohn.Forte@Sun.COM /* Get the inq_dtype for each device on dev list. */
12957836SJohn.Forte@Sun.COM for (i = 0; i < num_devices; i++, dlist++) {
12967836SJohn.Forte@Sun.COM /* Get the inq_dtype for each device. */
12977836SJohn.Forte@Sun.COM if ((err = g_get_inq_dtype(fcapath, dlist->dev_pwwn,
1298*11547SBill.Gumbrell@Sun.COM &dlist->dev_dtype)) != 0) {
12997836SJohn.Forte@Sun.COM /*
13007836SJohn.Forte@Sun.COM * if g_get_inq_dtype failed on g_dev_login
13017836SJohn.Forte@Sun.COM * or g_issue_fcp_ioctl, continue to the next
13027836SJohn.Forte@Sun.COM * dev on dlist.
13037836SJohn.Forte@Sun.COM * L_GET_DEV_LIST_ULP_FAILURE is returned
13047836SJohn.Forte@Sun.COM * after processing the whole dlist.
13057836SJohn.Forte@Sun.COM */
13067836SJohn.Forte@Sun.COM if ((err == L_FCIO_DEV_LOGIN_FAIL) ||
1307*11547SBill.Gumbrell@Sun.COM (err == L_FCP_TGT_INQUIRY_FAIL)) {
13087836SJohn.Forte@Sun.COM ulp_failure = 1;
13097836SJohn.Forte@Sun.COM dlist->dev_dtype = GFC_ERR_INQ_DTYPE;
13107836SJohn.Forte@Sun.COM } else {
13117836SJohn.Forte@Sun.COM (void) free(*dev_list);
13127836SJohn.Forte@Sun.COM *dev_list = NULL;
13137836SJohn.Forte@Sun.COM return (err);
13147836SJohn.Forte@Sun.COM }
13157836SJohn.Forte@Sun.COM }
13167836SJohn.Forte@Sun.COM }
13177836SJohn.Forte@Sun.COM
13187836SJohn.Forte@Sun.COM if (ulp_failure) {
13197836SJohn.Forte@Sun.COM return (L_GET_DEV_LIST_ULP_FAILURE);
13207836SJohn.Forte@Sun.COM } else {
13217836SJohn.Forte@Sun.COM return (0);
13227836SJohn.Forte@Sun.COM }
13237836SJohn.Forte@Sun.COM }
13247836SJohn.Forte@Sun.COM
13257836SJohn.Forte@Sun.COM
13267836SJohn.Forte@Sun.COM /* Constant used by g_get_inq_dtype() */
13277836SJohn.Forte@Sun.COM #define FCP_PATH "/devices/pseudo/fcp@0:fcp"
13287836SJohn.Forte@Sun.COM
13297836SJohn.Forte@Sun.COM /*
13307836SJohn.Forte@Sun.COM * Gets the inq_dtype for devices on the fabric FC driver
13317836SJohn.Forte@Sun.COM * through an ioctl to the FCP module.
13327836SJohn.Forte@Sun.COM *
13337836SJohn.Forte@Sun.COM * OUTPUT:
13347836SJohn.Forte@Sun.COM * inq_dtype is set to the dtype on success
13357836SJohn.Forte@Sun.COM *
13367836SJohn.Forte@Sun.COM * RETURN VALUES:
13377836SJohn.Forte@Sun.COM * 0 on Success
13387836SJohn.Forte@Sun.COM * Non-zero on error
13397836SJohn.Forte@Sun.COM */
13407836SJohn.Forte@Sun.COM int
g_get_inq_dtype(char * fcapath,la_wwn_t pwwn,uchar_t * inq_dtype)13417836SJohn.Forte@Sun.COM g_get_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype)
13427836SJohn.Forte@Sun.COM {
13437836SJohn.Forte@Sun.COM int dev_type, fd;
13447836SJohn.Forte@Sun.COM int err, fcp_fd;
13457836SJohn.Forte@Sun.COM uint32_t state;
13467836SJohn.Forte@Sun.COM uint32_t port_top = 0;
13477836SJohn.Forte@Sun.COM struct fcp_ioctl fcp_data;
13487836SJohn.Forte@Sun.COM struct device_data inq_data;
13497836SJohn.Forte@Sun.COM struct stat sbuf;
13507836SJohn.Forte@Sun.COM
13517836SJohn.Forte@Sun.COM dev_type = g_get_path_type(fcapath);
13527836SJohn.Forte@Sun.COM if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
13537836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
13547836SJohn.Forte@Sun.COM }
13557836SJohn.Forte@Sun.COM
13567836SJohn.Forte@Sun.COM if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) {
13577836SJohn.Forte@Sun.COM return (err);
13587836SJohn.Forte@Sun.COM }
13597836SJohn.Forte@Sun.COM
13607836SJohn.Forte@Sun.COM if ((port_top == FC_TOP_FABRIC) || (port_top == FC_TOP_PUBLIC_LOOP)) {
13617836SJohn.Forte@Sun.COM /*
13627836SJohn.Forte@Sun.COM * if there is an error on getting port state we will
13637836SJohn.Forte@Sun.COM * continue to login.
13647836SJohn.Forte@Sun.COM * state can be either of
13657836SJohn.Forte@Sun.COM * PORT_DEVICE_INVALID, PORT_DEVICE_VALID,
13667836SJohn.Forte@Sun.COM * PORT_DEVICE_LOGGED_IN. Trying port login
13677836SJohn.Forte@Sun.COM * unless already logged in.
13687836SJohn.Forte@Sun.COM * It will be examined if there is an adverse
13697836SJohn.Forte@Sun.COM * effect on invalid state device.
13707836SJohn.Forte@Sun.COM */
13717836SJohn.Forte@Sun.COM if (((err = g_get_dev_port_state(fcapath, pwwn, &state))
1372*11547SBill.Gumbrell@Sun.COM != 0) || (state != PORT_DEVICE_LOGGED_IN)) {
13737836SJohn.Forte@Sun.COM /* do port login to fabric device. */
13747836SJohn.Forte@Sun.COM if ((err = g_dev_login(fcapath, pwwn)) != 0) {
13757836SJohn.Forte@Sun.COM return (err);
13767836SJohn.Forte@Sun.COM }
13777836SJohn.Forte@Sun.COM }
13787836SJohn.Forte@Sun.COM }
13797836SJohn.Forte@Sun.COM
13807836SJohn.Forte@Sun.COM if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1)
13817836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
13827836SJohn.Forte@Sun.COM
13837836SJohn.Forte@Sun.COM if (fstat(fd, &sbuf) == -1) {
13847836SJohn.Forte@Sun.COM (void) close(fd);
13857836SJohn.Forte@Sun.COM return (L_FSTAT_ERROR);
13867836SJohn.Forte@Sun.COM }
13877836SJohn.Forte@Sun.COM
13887836SJohn.Forte@Sun.COM if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
13897836SJohn.Forte@Sun.COM (void) close(fd);
13907836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
13917836SJohn.Forte@Sun.COM }
13927836SJohn.Forte@Sun.COM
13937836SJohn.Forte@Sun.COM /* Get the minor number for an fp instance */
13947836SJohn.Forte@Sun.COM fcp_data.fp_minor = minor(sbuf.st_rdev);
13957836SJohn.Forte@Sun.COM
13967836SJohn.Forte@Sun.COM fcp_data.listlen = 1;
13977836SJohn.Forte@Sun.COM inq_data.dev_pwwn = pwwn; /* The port WWN as passed */
13987836SJohn.Forte@Sun.COM fcp_data.list = (caddr_t)&inq_data;
13997836SJohn.Forte@Sun.COM
14007836SJohn.Forte@Sun.COM if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
14017836SJohn.Forte@Sun.COM close(fd);
14027836SJohn.Forte@Sun.COM close(fcp_fd);
14037836SJohn.Forte@Sun.COM return (err);
14047836SJohn.Forte@Sun.COM }
14057836SJohn.Forte@Sun.COM *inq_dtype = inq_data.dev0_type;
14067836SJohn.Forte@Sun.COM
14077836SJohn.Forte@Sun.COM close(fd);
14087836SJohn.Forte@Sun.COM close(fcp_fd);
14097836SJohn.Forte@Sun.COM
14107836SJohn.Forte@Sun.COM return (err);
14117836SJohn.Forte@Sun.COM }
14127836SJohn.Forte@Sun.COM
14137836SJohn.Forte@Sun.COM /*
14147836SJohn.Forte@Sun.COM * Gets the inq_dtype for devices on the fabric FC driver
14157836SJohn.Forte@Sun.COM * through an ioctl to the FCP module.
14167836SJohn.Forte@Sun.COM *
14177836SJohn.Forte@Sun.COM * This is exactly same as g_get_inq_dtype except that it does not do
14187836SJohn.Forte@Sun.COM * g_dev_login(). That is for the case when the FCA tries to get its own
14197836SJohn.Forte@Sun.COM * inq_dtype and in such a case, it cannot PLOGI into itself.
14207836SJohn.Forte@Sun.COM *
14217836SJohn.Forte@Sun.COM * OUTPUT:
14227836SJohn.Forte@Sun.COM * inq_dtype is set to the dtype on success
14237836SJohn.Forte@Sun.COM *
14247836SJohn.Forte@Sun.COM * RETURN VALUES:
14257836SJohn.Forte@Sun.COM * 0 on Success
14267836SJohn.Forte@Sun.COM * Non-zero on error
14277836SJohn.Forte@Sun.COM */
14287836SJohn.Forte@Sun.COM static int
get_fca_inq_dtype(char * fcapath,la_wwn_t pwwn,uchar_t * inq_dtype)14297836SJohn.Forte@Sun.COM get_fca_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype)
14307836SJohn.Forte@Sun.COM {
14317836SJohn.Forte@Sun.COM int dev_type, fd;
14327836SJohn.Forte@Sun.COM int err, fcp_fd;
14337836SJohn.Forte@Sun.COM struct fcp_ioctl fcp_data;
14347836SJohn.Forte@Sun.COM struct device_data inq_data;
14357836SJohn.Forte@Sun.COM struct stat sbuf;
14367836SJohn.Forte@Sun.COM
14377836SJohn.Forte@Sun.COM dev_type = g_get_path_type(fcapath);
14387836SJohn.Forte@Sun.COM if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
14397836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
14407836SJohn.Forte@Sun.COM }
14417836SJohn.Forte@Sun.COM
14427836SJohn.Forte@Sun.COM if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) {
14437836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
14447836SJohn.Forte@Sun.COM }
14457836SJohn.Forte@Sun.COM
14467836SJohn.Forte@Sun.COM if (fstat(fd, &sbuf) == -1) {
14477836SJohn.Forte@Sun.COM (void) close(fd);
14487836SJohn.Forte@Sun.COM return (L_FSTAT_ERROR);
14497836SJohn.Forte@Sun.COM }
14507836SJohn.Forte@Sun.COM
14517836SJohn.Forte@Sun.COM if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
14527836SJohn.Forte@Sun.COM (void) close(fd);
14537836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
14547836SJohn.Forte@Sun.COM }
14557836SJohn.Forte@Sun.COM
14567836SJohn.Forte@Sun.COM /* Get the minor number for an fp instance */
14577836SJohn.Forte@Sun.COM fcp_data.fp_minor = minor(sbuf.st_rdev);
14587836SJohn.Forte@Sun.COM
14597836SJohn.Forte@Sun.COM fcp_data.listlen = 1;
14607836SJohn.Forte@Sun.COM inq_data.dev_pwwn = pwwn; /* The port WWN as passed */
14617836SJohn.Forte@Sun.COM fcp_data.list = (caddr_t)&inq_data;
14627836SJohn.Forte@Sun.COM
14637836SJohn.Forte@Sun.COM if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
14647836SJohn.Forte@Sun.COM close(fd);
14657836SJohn.Forte@Sun.COM close(fcp_fd);
14667836SJohn.Forte@Sun.COM return (err);
14677836SJohn.Forte@Sun.COM }
14687836SJohn.Forte@Sun.COM *inq_dtype = inq_data.dev0_type;
14697836SJohn.Forte@Sun.COM
14707836SJohn.Forte@Sun.COM close(fd);
14717836SJohn.Forte@Sun.COM close(fcp_fd);
14727836SJohn.Forte@Sun.COM
14737836SJohn.Forte@Sun.COM return (0);
14747836SJohn.Forte@Sun.COM }
14757836SJohn.Forte@Sun.COM
14767836SJohn.Forte@Sun.COM /*
14777836SJohn.Forte@Sun.COM * This function returns the traditional g_get_dev_map. Device list
14787836SJohn.Forte@Sun.COM * and local hba seperate.
14797836SJohn.Forte@Sun.COM */
14807836SJohn.Forte@Sun.COM int
g_get_dev_map(char * path,gfc_map_t * map_ptr,int verbose)14817836SJohn.Forte@Sun.COM g_get_dev_map(char *path, gfc_map_t *map_ptr, int verbose)
14827836SJohn.Forte@Sun.COM {
14837836SJohn.Forte@Sun.COM return (create_map(path, map_ptr, verbose, MAP_FORMAT_STANDARD));
14847836SJohn.Forte@Sun.COM }
14857836SJohn.Forte@Sun.COM
14867836SJohn.Forte@Sun.COM /*
14877836SJohn.Forte@Sun.COM * This function returns the device map with local hba in physical
14887836SJohn.Forte@Sun.COM * order. Note: Physical order is only returned properly for
14897836SJohn.Forte@Sun.COM * private loop. local hba is also included seperate
14907836SJohn.Forte@Sun.COM */
14917836SJohn.Forte@Sun.COM int
g_get_lilp_map(char * path,gfc_map_t * map_ptr,int verbose)14927836SJohn.Forte@Sun.COM g_get_lilp_map(char *path, gfc_map_t *map_ptr, int verbose)
14937836SJohn.Forte@Sun.COM {
14947836SJohn.Forte@Sun.COM return (create_map(path, map_ptr, verbose, MAP_FORMAT_LILP));
14957836SJohn.Forte@Sun.COM }
14967836SJohn.Forte@Sun.COM
14977836SJohn.Forte@Sun.COM /*
14987836SJohn.Forte@Sun.COM * Gets device map from nexus driver
14997836SJohn.Forte@Sun.COM *
15007836SJohn.Forte@Sun.COM * PARAMS:
15017836SJohn.Forte@Sun.COM * path - must be the physical path to a device
15027836SJohn.Forte@Sun.COM * map - loop map returned from fc port.
15037836SJohn.Forte@Sun.COM * verbose - options.
15047836SJohn.Forte@Sun.COM *
15057836SJohn.Forte@Sun.COM * LOGIC:
15067836SJohn.Forte@Sun.COM * 1. check the validity of path via g_get_path_type.
15077836SJohn.Forte@Sun.COM * 2. If FC path, get the topology of the path via
15087836SJohn.Forte@Sun.COM * g_get_fca_port_topology.
15097836SJohn.Forte@Sun.COM *
15107836SJohn.Forte@Sun.COM * 3. If FC type(Leadville statck)
15117836SJohn.Forte@Sun.COM * g_get_dev_list to get the device node list of fc_port_dev_t.
15127836SJohn.Forte@Sun.COM * g_get_host_params to get the fca port node of fc_port_dev_t.
15137836SJohn.Forte@Sun.COM *
15147836SJohn.Forte@Sun.COM * Case of fabric or public loop topology
15157836SJohn.Forte@Sun.COM * Check if the port id > 0xffff.
15167836SJohn.Forte@Sun.COM * Move device node and fca port node to
15177836SJohn.Forte@Sun.COM * gfc_map structure via gfc_port_dev_info_t
15187836SJohn.Forte@Sun.COM * pub_port union.
15197836SJohn.Forte@Sun.COM * Issue g_get_inq_dtype to get FCP inquiry data
15207836SJohn.Forte@Sun.COM * and store it into gfc_port_dev_info_t.
15217836SJohn.Forte@Sun.COM *
15227836SJohn.Forte@Sun.COM * Case of private loop topology
15237836SJohn.Forte@Sun.COM * Check if the port id < 0xff.
15247836SJohn.Forte@Sun.COM * Move device node and fca port node to
15257836SJohn.Forte@Sun.COM * gfc_map structure via gfc_port_dev_info_t
15267836SJohn.Forte@Sun.COM * priv_port union.
15277836SJohn.Forte@Sun.COM * Issue g_get_inq_dtype to get FCP inquiry data
15287836SJohn.Forte@Sun.COM * and store it into gfc_port_dev_info_t.
15297836SJohn.Forte@Sun.COM *
15307836SJohn.Forte@Sun.COM * else FC4 type(socal/sf or ifp stack)
15317836SJohn.Forte@Sun.COM * SFIOCGMAP ioctl to get the device and hba nodes of
15327836SJohn.Forte@Sun.COM * sf_addr_pair_t.
15337836SJohn.Forte@Sun.COM *
15347836SJohn.Forte@Sun.COM *
15357836SJohn.Forte@Sun.COM * RETURNS:
15367836SJohn.Forte@Sun.COM * 0 : if OK
15377836SJohn.Forte@Sun.COM * non-zero: otherwise
15387836SJohn.Forte@Sun.COM */
15397836SJohn.Forte@Sun.COM int
create_map(char * path,gfc_map_t * map_ptr,int verbose,int map_type)15407836SJohn.Forte@Sun.COM create_map(char *path, gfc_map_t *map_ptr, int verbose, int map_type)
15417836SJohn.Forte@Sun.COM {
1542*11547SBill.Gumbrell@Sun.COM int fd, i, j, num_devices = 0, err, pathcnt = 1;
1543*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN];
1544*11547SBill.Gumbrell@Sun.COM char *char_ptr;
1545*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
1546*11547SBill.Gumbrell@Sun.COM fc_port_dev_t *dev_list, *dlistptr;
1547*11547SBill.Gumbrell@Sun.COM uint32_t hba_port_top = 0;
1548*11547SBill.Gumbrell@Sun.COM uint_t dev_type;
1549*11547SBill.Gumbrell@Sun.COM sf_al_map_t sf_map;
1550*11547SBill.Gumbrell@Sun.COM gfc_port_dev_info_t *dev_ptr;
1551*11547SBill.Gumbrell@Sun.COM fc_port_dev_t fp_hba_port;
1552*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
1553*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0;
15547836SJohn.Forte@Sun.COM
15557836SJohn.Forte@Sun.COM /* return invalid path if path is NULL */
15567836SJohn.Forte@Sun.COM if (path == NULL) {
15577836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
15587836SJohn.Forte@Sun.COM }
15597836SJohn.Forte@Sun.COM /* return invalid arg if map_ptr is NULL */
15607836SJohn.Forte@Sun.COM if (map_ptr == NULL) {
15617836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
15627836SJohn.Forte@Sun.COM }
15637836SJohn.Forte@Sun.COM
15647836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
15657836SJohn.Forte@Sun.COM map_ptr->count = 0;
15667836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
15677836SJohn.Forte@Sun.COM /*
15687836SJohn.Forte@Sun.COM * Get the path to the :devctl driver
15697836SJohn.Forte@Sun.COM *
15707836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
15717836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
15727836SJohn.Forte@Sun.COM * or
15737836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
15747836SJohn.Forte@Sun.COM * or
15757836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
15767836SJohn.Forte@Sun.COM * or
15777836SJohn.Forte@Sun.COM * a 1 level PCI type driver but still :devctl
15787836SJohn.Forte@Sun.COM */
15797836SJohn.Forte@Sun.COM if (strstr(path, SCSI_VHCI)) {
15807836SJohn.Forte@Sun.COM (void) strcpy(drvr_path0, path);
15817836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path0, &pathlist)) {
15827836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
15837836SJohn.Forte@Sun.COM }
15847836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
15857836SJohn.Forte@Sun.COM p_on = p_st = 0;
15867836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
15877836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
15887836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
1589*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
15907836SJohn.Forte@Sun.COM p_on = i;
15917836SJohn.Forte@Sun.COM break;
15927836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
1593*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
15947836SJohn.Forte@Sun.COM p_st = i;
15957836SJohn.Forte@Sun.COM }
15967836SJohn.Forte@Sun.COM }
15977836SJohn.Forte@Sun.COM }
15987836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
15997836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
16007836SJohn.Forte@Sun.COM /* on_line path */
16017836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
1602*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
16037836SJohn.Forte@Sun.COM } else {
16047836SJohn.Forte@Sun.COM /* standby or path0 */
16057836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
1606*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
16077836SJohn.Forte@Sun.COM }
16087836SJohn.Forte@Sun.COM free(pathlist.path_info);
16097836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
16107836SJohn.Forte@Sun.COM } else {
16117836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
16127836SJohn.Forte@Sun.COM if (strstr(drvr_path, DRV_NAME_SSD) ||
1613*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, SES_NAME) ||
1614*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, DRV_NAME_ST)) {
16157836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
16167836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
16177836SJohn.Forte@Sun.COM }
16187836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate sting */
16197836SJohn.Forte@Sun.COM /* append controller */
16207836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
16217836SJohn.Forte@Sun.COM } else {
16227836SJohn.Forte@Sun.COM if (stat(drvr_path, &stbuf) < 0) {
16237836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
16247836SJohn.Forte@Sun.COM }
16257836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
16267836SJohn.Forte@Sun.COM /* append controller */
16277836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
16287836SJohn.Forte@Sun.COM }
16297836SJohn.Forte@Sun.COM }
16307836SJohn.Forte@Sun.COM }
16317836SJohn.Forte@Sun.COM
16327836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_dev_map: Geting drive map from:"
1633*11547SBill.Gumbrell@Sun.COM " %s\n", drvr_path);
16347836SJohn.Forte@Sun.COM
16357836SJohn.Forte@Sun.COM dev_type = g_get_path_type(drvr_path);
16367836SJohn.Forte@Sun.COM if ((dev_type == 0) || !(dev_type & XPORT_MASK)) {
16377836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
16387836SJohn.Forte@Sun.COM }
16397836SJohn.Forte@Sun.COM
16407836SJohn.Forte@Sun.COM /* get fiber topology */
16417836SJohn.Forte@Sun.COM if ((err = g_get_fca_port_topology(drvr_path,
1642*11547SBill.Gumbrell@Sun.COM &hba_port_top, verbose)) != 0) {
16437836SJohn.Forte@Sun.COM return (err);
16447836SJohn.Forte@Sun.COM }
16457836SJohn.Forte@Sun.COM
16467836SJohn.Forte@Sun.COM /* for FC devices. */
16477836SJohn.Forte@Sun.COM if (dev_type & FC_FCA_MASK) {
16487836SJohn.Forte@Sun.COM /*
16497836SJohn.Forte@Sun.COM * if g_get_dev_list fails with L_NO_DEVICES_FOUND
16507836SJohn.Forte@Sun.COM * we still want to call g_get_host_params to try to find the
16517836SJohn.Forte@Sun.COM * HBA. If we do not see any HBAs on the loop, the
16527836SJohn.Forte@Sun.COM * g_get_host_params will fail when it trys to issue the target
16537836SJohn.Forte@Sun.COM * inquiry ioctl. In this case, we would still like to return
16547836SJohn.Forte@Sun.COM * L_NO_DEVICES_FOUND.
16557836SJohn.Forte@Sun.COM *
16567836SJohn.Forte@Sun.COM * If g_get_dev_list fails with L_NO_DEVICES_FOUND and
16577836SJohn.Forte@Sun.COM * g_get_host_params fails, the function returns
16587836SJohn.Forte@Sun.COM * L_NO_DEVICES_FOUND
16597836SJohn.Forte@Sun.COM */
16607836SJohn.Forte@Sun.COM if ((err = g_get_dev_list(drvr_path, &dev_list,
1661*11547SBill.Gumbrell@Sun.COM &num_devices)) != 0) {
16627836SJohn.Forte@Sun.COM /*
16637836SJohn.Forte@Sun.COM * g_get_dev_map doesn't allow ulp failure
16647836SJohn.Forte@Sun.COM * to continue thus we need to free dev_list
16657836SJohn.Forte@Sun.COM * here.
16667836SJohn.Forte@Sun.COM */
16677836SJohn.Forte@Sun.COM if (err == L_GET_DEV_LIST_ULP_FAILURE) {
16687836SJohn.Forte@Sun.COM (void) free(dev_list);
16697836SJohn.Forte@Sun.COM }
16707836SJohn.Forte@Sun.COM if (err != L_NO_DEVICES_FOUND) {
16717836SJohn.Forte@Sun.COM return (err);
16727836SJohn.Forte@Sun.COM }
16737836SJohn.Forte@Sun.COM }
16747836SJohn.Forte@Sun.COM
16757836SJohn.Forte@Sun.COM /* Get local HBA information */
16767836SJohn.Forte@Sun.COM if ((err = g_get_host_params(drvr_path, &fp_hba_port,
1677*11547SBill.Gumbrell@Sun.COM verbose)) != 0) {
16787836SJohn.Forte@Sun.COM (void) free(dev_list);
16797836SJohn.Forte@Sun.COM if (num_devices == 0)
16807836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
16817836SJohn.Forte@Sun.COM else
16827836SJohn.Forte@Sun.COM return (err);
16837836SJohn.Forte@Sun.COM }
16847836SJohn.Forte@Sun.COM
16857836SJohn.Forte@Sun.COM /* If devices, other than local HBA are found */
16867836SJohn.Forte@Sun.COM /* allocate space for them in the gfc_map. */
16877836SJohn.Forte@Sun.COM if (num_devices > 0) {
16887836SJohn.Forte@Sun.COM
16897836SJohn.Forte@Sun.COM /* If map type is on MAP_FORMAT_LILP we need */
16907836SJohn.Forte@Sun.COM /* to add space for the local HBA */
16917836SJohn.Forte@Sun.COM if (map_type == MAP_FORMAT_LILP) {
16927836SJohn.Forte@Sun.COM map_ptr->count = ++num_devices;
16937836SJohn.Forte@Sun.COM } else {
16947836SJohn.Forte@Sun.COM map_ptr->count = num_devices;
16957836SJohn.Forte@Sun.COM }
16967836SJohn.Forte@Sun.COM
16977836SJohn.Forte@Sun.COM if ((map_ptr->dev_addr = (gfc_port_dev_info_t *)
16987836SJohn.Forte@Sun.COM calloc(map_ptr->count,
1699*11547SBill.Gumbrell@Sun.COM sizeof (gfc_port_dev_info_t))) == NULL) {
1700*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
1701*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
17027836SJohn.Forte@Sun.COM }
17037836SJohn.Forte@Sun.COM }
17047836SJohn.Forte@Sun.COM
17057836SJohn.Forte@Sun.COM /* If we want the lilp map then we need to do a little */
17067836SJohn.Forte@Sun.COM /* work here. The lilp map contains the local hba in */
17077836SJohn.Forte@Sun.COM /* the dev_addr. Once this has been added qsort the */
17087836SJohn.Forte@Sun.COM /* dev_addr array so it's in physical order. */
17097836SJohn.Forte@Sun.COM /* The lilp map will contain the local hba in the */
17107836SJohn.Forte@Sun.COM /* dev_addr array only when num_devices > 0 */
17117836SJohn.Forte@Sun.COM if (map_type == MAP_FORMAT_LILP && num_devices > 0) {
17127836SJohn.Forte@Sun.COM
17137836SJohn.Forte@Sun.COM /* First we need to allocate one additional */
17147836SJohn.Forte@Sun.COM /* device to the dev_addr structure, for the */
17157836SJohn.Forte@Sun.COM /* local hba */
17167836SJohn.Forte@Sun.COM if ((dev_list = (fc_port_dev_t *)realloc(dev_list,
1717*11547SBill.Gumbrell@Sun.COM (num_devices * sizeof (fc_port_dev_t))))
1718*11547SBill.Gumbrell@Sun.COM == NULL) {
17197836SJohn.Forte@Sun.COM S_FREE(dev_list);
17207836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
17217836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
17227836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
17237836SJohn.Forte@Sun.COM }
17247836SJohn.Forte@Sun.COM
17257836SJohn.Forte@Sun.COM /* Next, copy the local hba into this new loc. */
17267836SJohn.Forte@Sun.COM if (memcpy(dev_list+(num_devices-1), &fp_hba_port,
1727*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t)) == NULL) {
17287836SJohn.Forte@Sun.COM (void) free(dev_list);
17297836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
17307836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
17317836SJohn.Forte@Sun.COM return (L_MEMCPY_FAILED);
17327836SJohn.Forte@Sun.COM }
17337836SJohn.Forte@Sun.COM
17347836SJohn.Forte@Sun.COM /* Now sort by physical location */
17357836SJohn.Forte@Sun.COM qsort((void*)dev_list, num_devices,
1736*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t), lilp_map_cmp);
17377836SJohn.Forte@Sun.COM }
17387836SJohn.Forte@Sun.COM
17397836SJohn.Forte@Sun.COM dlistptr = dev_list;
17407836SJohn.Forte@Sun.COM dev_ptr = map_ptr->dev_addr;
17417836SJohn.Forte@Sun.COM
17427836SJohn.Forte@Sun.COM switch (hba_port_top) {
17437836SJohn.Forte@Sun.COM case FC_TOP_FABRIC:
17447836SJohn.Forte@Sun.COM case FC_TOP_PUBLIC_LOOP:
17457836SJohn.Forte@Sun.COM if (fp_hba_port.dev_did.port_id <= 0xffff) {
17467836SJohn.Forte@Sun.COM (void) free(dlistptr);
17477836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
17487836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
17497836SJohn.Forte@Sun.COM return (L_INVALID_FABRIC_ADDRESS);
17507836SJohn.Forte@Sun.COM } else {
17517836SJohn.Forte@Sun.COM map_ptr->hba_addr.port_topology = hba_port_top;
17527836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.pub_port =
1753*11547SBill.Gumbrell@Sun.COM fp_hba_port;
17547836SJohn.Forte@Sun.COM }
17557836SJohn.Forte@Sun.COM for (i = 0; i < num_devices; i++, dev_ptr++,
1756*11547SBill.Gumbrell@Sun.COM dev_list++) {
17577836SJohn.Forte@Sun.COM if (dev_list->dev_did.port_id <= 0xffff) {
17587836SJohn.Forte@Sun.COM (void) free(dlistptr);
17597836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
17607836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
17617836SJohn.Forte@Sun.COM return (L_INVALID_FABRIC_ADDRESS);
17627836SJohn.Forte@Sun.COM } else {
17637836SJohn.Forte@Sun.COM dev_ptr->port_topology = hba_port_top;
17647836SJohn.Forte@Sun.COM dev_ptr->gfc_port_dev.pub_port =
1765*11547SBill.Gumbrell@Sun.COM *dev_list;
17667836SJohn.Forte@Sun.COM }
17677836SJohn.Forte@Sun.COM }
17687836SJohn.Forte@Sun.COM break;
17697836SJohn.Forte@Sun.COM case FC_TOP_PRIVATE_LOOP:
17707836SJohn.Forte@Sun.COM /*
17717836SJohn.Forte@Sun.COM * Map the (new->old) structures here.
17727836SJohn.Forte@Sun.COM * Checking (i < SF_NUM_ENTRIES_IN_MAP) just to
17737836SJohn.Forte@Sun.COM * make sure that we don't overrun the map structure
17747836SJohn.Forte@Sun.COM * since it can hold data for upto 126 devices.
17757836SJohn.Forte@Sun.COM */
17767836SJohn.Forte@Sun.COM if (fp_hba_port.dev_did.port_id > 0xff) {
17777836SJohn.Forte@Sun.COM (void) free(dlistptr);
17787836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
17797836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
17807836SJohn.Forte@Sun.COM return (L_INVALID_PRIVATE_LOOP_ADDRESS);
17817836SJohn.Forte@Sun.COM } else {
17827836SJohn.Forte@Sun.COM map_ptr->hba_addr.port_topology = hba_port_top;
17837836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.
1784*11547SBill.Gumbrell@Sun.COM priv_port.sf_al_pa =
1785*11547SBill.Gumbrell@Sun.COM (uchar_t)fp_hba_port.dev_did.port_id;
17867836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.
1787*11547SBill.Gumbrell@Sun.COM priv_port.sf_hard_address = (uchar_t)
1788*11547SBill.Gumbrell@Sun.COM fp_hba_port.dev_hard_addr.hard_addr;
17897836SJohn.Forte@Sun.COM for (j = 0; j < FC_WWN_SIZE; j++) {
17907836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.
1791*11547SBill.Gumbrell@Sun.COM priv_port.sf_node_wwn[j] =
1792*11547SBill.Gumbrell@Sun.COM fp_hba_port.dev_nwwn.raw_wwn[j];
17937836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.
1794*11547SBill.Gumbrell@Sun.COM priv_port.sf_port_wwn[j] =
1795*11547SBill.Gumbrell@Sun.COM fp_hba_port.dev_pwwn.raw_wwn[j];
17967836SJohn.Forte@Sun.COM }
17977836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.
1798*11547SBill.Gumbrell@Sun.COM priv_port.sf_inq_dtype =
1799*11547SBill.Gumbrell@Sun.COM fp_hba_port.dev_dtype;
18007836SJohn.Forte@Sun.COM }
18017836SJohn.Forte@Sun.COM
18027836SJohn.Forte@Sun.COM for (i = 0; (i < num_devices &&
1803*11547SBill.Gumbrell@Sun.COM i < SF_NUM_ENTRIES_IN_MAP);
1804*11547SBill.Gumbrell@Sun.COM i++, dev_ptr++, dev_list++) {
18057836SJohn.Forte@Sun.COM /*
18067836SJohn.Forte@Sun.COM * Out of 24 bits of port_id, copy only
18077836SJohn.Forte@Sun.COM * 8 bits to al_pa. This works okay for
18087836SJohn.Forte@Sun.COM * devices that're on a private loop.
18097836SJohn.Forte@Sun.COM */
18107836SJohn.Forte@Sun.COM if (dev_list->dev_did.port_id > 0xff) {
18117836SJohn.Forte@Sun.COM (void) free(dlistptr);
18127836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
18137836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
18147836SJohn.Forte@Sun.COM return (L_INVALID_PRIVATE_LOOP_ADDRESS);
18157836SJohn.Forte@Sun.COM }
18167836SJohn.Forte@Sun.COM dev_ptr->port_topology = hba_port_top;
18177836SJohn.Forte@Sun.COM dev_ptr->gfc_port_dev.priv_port.sf_al_pa
1818*11547SBill.Gumbrell@Sun.COM = (uchar_t)dev_list->dev_did.port_id;
1819*11547SBill.Gumbrell@Sun.COM
1820*11547SBill.Gumbrell@Sun.COM /* Code refactorization is needed for C style */
1821*11547SBill.Gumbrell@Sun.COM dev_ptr->gfc_port_dev.priv_port.sf_hard_address
1822*11547SBill.Gumbrell@Sun.COM = (uchar_t)dev_list->dev_hard_addr.hard_addr;
1823*11547SBill.Gumbrell@Sun.COM
18247836SJohn.Forte@Sun.COM for (j = 0; j < FC_WWN_SIZE; j++) {
1825*11547SBill.Gumbrell@Sun.COM
1826*11547SBill.Gumbrell@Sun.COM dev_ptr->gfc_port_dev.priv_port.sf_node_wwn[j] =
1827*11547SBill.Gumbrell@Sun.COM dev_list->dev_nwwn.raw_wwn[j];
1828*11547SBill.Gumbrell@Sun.COM dev_ptr->gfc_port_dev.priv_port.sf_port_wwn[j] =
1829*11547SBill.Gumbrell@Sun.COM dev_list->dev_pwwn.raw_wwn[j];
1830*11547SBill.Gumbrell@Sun.COM
18317836SJohn.Forte@Sun.COM }
18327836SJohn.Forte@Sun.COM dev_ptr->gfc_port_dev.priv_port.sf_inq_dtype =
1833*11547SBill.Gumbrell@Sun.COM dev_list->dev_dtype;
18347836SJohn.Forte@Sun.COM }
18357836SJohn.Forte@Sun.COM break;
18367836SJohn.Forte@Sun.COM case FC_TOP_PT_PT:
18377836SJohn.Forte@Sun.COM (void) free(dlistptr);
18387836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
18397836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
18407836SJohn.Forte@Sun.COM return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
18417836SJohn.Forte@Sun.COM default:
18427836SJohn.Forte@Sun.COM (void) free(dlistptr);
18437836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
18447836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
18457836SJohn.Forte@Sun.COM return (L_UNEXPECTED_FC_TOPOLOGY);
18467836SJohn.Forte@Sun.COM } /* End of switch on port_topology */
18477836SJohn.Forte@Sun.COM (void) free(dlistptr);
18487836SJohn.Forte@Sun.COM
18497836SJohn.Forte@Sun.COM } else { /* sf and fc4/pci devices */
18507836SJohn.Forte@Sun.COM if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
18517836SJohn.Forte@Sun.COM return (errno);
18527836SJohn.Forte@Sun.COM /* initialize map */
18537836SJohn.Forte@Sun.COM (void) memset(&sf_map, 0, sizeof (struct sf_al_map));
18547836SJohn.Forte@Sun.COM if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
18557836SJohn.Forte@Sun.COM I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
18567836SJohn.Forte@Sun.COM (void) close(fd);
18577836SJohn.Forte@Sun.COM return (L_SFIOCGMAP_IOCTL_FAIL);
18587836SJohn.Forte@Sun.COM }
18597836SJohn.Forte@Sun.COM /* Check for reasonableness. */
18607836SJohn.Forte@Sun.COM if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) {
18617836SJohn.Forte@Sun.COM (void) close(fd);
18627836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
18637836SJohn.Forte@Sun.COM }
18647836SJohn.Forte@Sun.COM if (sf_map.sf_count == 0) {
18657836SJohn.Forte@Sun.COM (void) close(fd);
18667836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
18677836SJohn.Forte@Sun.COM }
18687836SJohn.Forte@Sun.COM
18697836SJohn.Forte@Sun.COM map_ptr->count = sf_map.sf_count;
18707836SJohn.Forte@Sun.COM if ((map_ptr->dev_addr =
1871*11547SBill.Gumbrell@Sun.COM (gfc_port_dev_info_t *)calloc(map_ptr->count,
1872*11547SBill.Gumbrell@Sun.COM sizeof (gfc_port_dev_info_t))) == NULL) {
18737836SJohn.Forte@Sun.COM (void) close(fd);
18747836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
18757836SJohn.Forte@Sun.COM }
18767836SJohn.Forte@Sun.COM dev_ptr = map_ptr->dev_addr;
18777836SJohn.Forte@Sun.COM for (i = 0; i < sf_map.sf_count; i++, dev_ptr++) {
18787836SJohn.Forte@Sun.COM if (sf_map.sf_addr_pair[i].sf_al_pa > 0xef) {
18797836SJohn.Forte@Sun.COM (void) free(map_ptr->dev_addr);
18807836SJohn.Forte@Sun.COM map_ptr->dev_addr = NULL;
18817836SJohn.Forte@Sun.COM (void) close(fd);
18827836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
18837836SJohn.Forte@Sun.COM }
18847836SJohn.Forte@Sun.COM dev_ptr->port_topology = hba_port_top;
18857836SJohn.Forte@Sun.COM dev_ptr->gfc_port_dev.priv_port =
1886*11547SBill.Gumbrell@Sun.COM sf_map.sf_addr_pair[i];
18877836SJohn.Forte@Sun.COM }
18887836SJohn.Forte@Sun.COM map_ptr->hba_addr.port_topology = hba_port_top;
18897836SJohn.Forte@Sun.COM map_ptr->hba_addr.gfc_port_dev.priv_port =
1890*11547SBill.Gumbrell@Sun.COM sf_map.sf_hba_addr;
18917836SJohn.Forte@Sun.COM (void) close(fd);
18927836SJohn.Forte@Sun.COM }
18937836SJohn.Forte@Sun.COM
18947836SJohn.Forte@Sun.COM return (0);
18957836SJohn.Forte@Sun.COM }
18967836SJohn.Forte@Sun.COM
18977836SJohn.Forte@Sun.COM /*
18987836SJohn.Forte@Sun.COM * This function consturct FC proerty list using map_dev_fc_prop_list.
18997836SJohn.Forte@Sun.COM *
19007836SJohn.Forte@Sun.COM * port WWN, node WWN, port addr and hard addr properties is constructed.
19017836SJohn.Forte@Sun.COM *
19027836SJohn.Forte@Sun.COM * return 0 if OK.
19037836SJohn.Forte@Sun.COM * otherwise returns error code.
19047836SJohn.Forte@Sun.COM */
19057836SJohn.Forte@Sun.COM static int
update_map_dev_fc_prop(impl_map_dev_prop_t ** prop_list,uint32_t map_topo,uchar_t * port_wwn,uchar_t * node_wwn,int port_addr,int hard_addr)1906*11547SBill.Gumbrell@Sun.COM update_map_dev_fc_prop(impl_map_dev_prop_t **prop_list, uint32_t map_topo,
1907*11547SBill.Gumbrell@Sun.COM uchar_t *port_wwn, uchar_t *node_wwn, int port_addr, int hard_addr)
19087836SJohn.Forte@Sun.COM {
19097836SJohn.Forte@Sun.COM impl_map_dev_prop_t *prop_ptr, *pl_start = NULL, *pl_end = NULL;
19107836SJohn.Forte@Sun.COM uchar_t *port_wwn_data, *node_wwn_data;
19117836SJohn.Forte@Sun.COM int *port_addr_data, *hard_addr_data;
19127836SJohn.Forte@Sun.COM
19137836SJohn.Forte@Sun.COM /* consrtruct port addr property. */
1914*11547SBill.Gumbrell@Sun.COM if ((map_topo == FC_TOP_FABRIC) || (map_topo == FC_TOP_PUBLIC_LOOP)) {
19157836SJohn.Forte@Sun.COM if (port_addr <= 0xffff) {
1916*11547SBill.Gumbrell@Sun.COM return (L_INVALID_FABRIC_ADDRESS);
19177836SJohn.Forte@Sun.COM }
19187836SJohn.Forte@Sun.COM } else if (map_topo == FC_TOP_PRIVATE_LOOP) {
19197836SJohn.Forte@Sun.COM if (port_addr > 0xff) {
1920*11547SBill.Gumbrell@Sun.COM return (L_INVALID_PRIVATE_LOOP_ADDRESS);
19217836SJohn.Forte@Sun.COM }
19227836SJohn.Forte@Sun.COM }
19237836SJohn.Forte@Sun.COM
19247836SJohn.Forte@Sun.COM if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1925*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_prop_t))) == NULL) {
19267836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19277836SJohn.Forte@Sun.COM }
19287836SJohn.Forte@Sun.COM (void) strncpy(prop_ptr->prop_name, PORT_ADDR_PROP,
1929*11547SBill.Gumbrell@Sun.COM strlen(PORT_ADDR_PROP));
19307836SJohn.Forte@Sun.COM prop_ptr->prop_type = GFC_PROP_TYPE_INT;
19317836SJohn.Forte@Sun.COM
19327836SJohn.Forte@Sun.COM if ((port_addr_data = (int *)calloc(1, sizeof (int))) == NULL) {
19337836SJohn.Forte@Sun.COM free(prop_ptr);
19347836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19357836SJohn.Forte@Sun.COM }
19367836SJohn.Forte@Sun.COM *port_addr_data = port_addr;
19377836SJohn.Forte@Sun.COM prop_ptr->prop_data = port_addr_data;
19387836SJohn.Forte@Sun.COM
19397836SJohn.Forte@Sun.COM pl_start = pl_end = prop_ptr;
19407836SJohn.Forte@Sun.COM
19417836SJohn.Forte@Sun.COM /* consrtruct port WWN property. */
19427836SJohn.Forte@Sun.COM if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1943*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_prop_t))) == NULL) {
19447836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19457836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19467836SJohn.Forte@Sun.COM }
19477836SJohn.Forte@Sun.COM (void) strncpy(prop_ptr->prop_name, PORT_WWN_PROP,
1948*11547SBill.Gumbrell@Sun.COM strlen(PORT_WWN_PROP));
19497836SJohn.Forte@Sun.COM prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
19507836SJohn.Forte@Sun.COM
1951*11547SBill.Gumbrell@Sun.COM if ((port_wwn_data = (uchar_t *)calloc(1, FC_WWN_SIZE)) == NULL) {
19527836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19537836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19547836SJohn.Forte@Sun.COM }
19557836SJohn.Forte@Sun.COM memcpy(port_wwn_data, port_wwn, FC_WWN_SIZE);
19567836SJohn.Forte@Sun.COM prop_ptr->prop_data = port_wwn_data;
19577836SJohn.Forte@Sun.COM prop_ptr->prop_size = FC_WWN_SIZE;
19587836SJohn.Forte@Sun.COM pl_end->next = prop_ptr;
19597836SJohn.Forte@Sun.COM pl_end = prop_ptr;
19607836SJohn.Forte@Sun.COM
19617836SJohn.Forte@Sun.COM /* consrtruct node WWN property. */
19627836SJohn.Forte@Sun.COM if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1963*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_prop_t))) == NULL) {
19647836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19657836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19667836SJohn.Forte@Sun.COM }
19677836SJohn.Forte@Sun.COM (void) strncpy(prop_ptr->prop_name, NODE_WWN_PROP,
1968*11547SBill.Gumbrell@Sun.COM strlen(NODE_WWN_PROP));
19697836SJohn.Forte@Sun.COM prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
19707836SJohn.Forte@Sun.COM
19717836SJohn.Forte@Sun.COM if ((node_wwn_data = (uchar_t *)calloc(
1972*11547SBill.Gumbrell@Sun.COM 1, FC_WWN_SIZE)) == NULL) {
19737836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19747836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19757836SJohn.Forte@Sun.COM }
19767836SJohn.Forte@Sun.COM memcpy(node_wwn_data, node_wwn, FC_WWN_SIZE);
19777836SJohn.Forte@Sun.COM prop_ptr->prop_data = node_wwn_data;
19787836SJohn.Forte@Sun.COM prop_ptr->prop_size = FC_WWN_SIZE;
19797836SJohn.Forte@Sun.COM pl_end->next = prop_ptr;
19807836SJohn.Forte@Sun.COM pl_end = prop_ptr;
19817836SJohn.Forte@Sun.COM
19827836SJohn.Forte@Sun.COM /* consrtruct hard addr property. */
19837836SJohn.Forte@Sun.COM if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1984*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_prop_t))) == NULL) {
19857836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19867836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19877836SJohn.Forte@Sun.COM }
19887836SJohn.Forte@Sun.COM (void) strncpy(prop_ptr->prop_name, HARD_ADDR_PROP,
1989*11547SBill.Gumbrell@Sun.COM strlen(HARD_ADDR_PROP));
19907836SJohn.Forte@Sun.COM prop_ptr->prop_type = GFC_PROP_TYPE_INT;
19917836SJohn.Forte@Sun.COM
1992*11547SBill.Gumbrell@Sun.COM if ((hard_addr_data = (int *)calloc(1, sizeof (int))) == NULL) {
19937836SJohn.Forte@Sun.COM free_prop_list(&pl_start);
19947836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
19957836SJohn.Forte@Sun.COM }
19967836SJohn.Forte@Sun.COM *hard_addr_data = hard_addr;
19977836SJohn.Forte@Sun.COM prop_ptr->prop_data = hard_addr_data;
19987836SJohn.Forte@Sun.COM pl_end->next = prop_ptr;
19997836SJohn.Forte@Sun.COM pl_end = prop_ptr;
20007836SJohn.Forte@Sun.COM
20017836SJohn.Forte@Sun.COM if (*prop_list == NULL) {
20027836SJohn.Forte@Sun.COM *prop_list = pl_start;
20037836SJohn.Forte@Sun.COM } else {
20047836SJohn.Forte@Sun.COM pl_end->next = (*prop_list)->next;
20057836SJohn.Forte@Sun.COM *prop_list = pl_start;
20067836SJohn.Forte@Sun.COM }
20077836SJohn.Forte@Sun.COM
20087836SJohn.Forte@Sun.COM return (0);
20097836SJohn.Forte@Sun.COM }
20107836SJohn.Forte@Sun.COM
20117836SJohn.Forte@Sun.COM /*
20127836SJohn.Forte@Sun.COM * This function consturct FCP inq dtype propery.
20137836SJohn.Forte@Sun.COM * if inq_dtype is null the property is constrcted with err info.
20147836SJohn.Forte@Sun.COM *
20157836SJohn.Forte@Sun.COM * L_MALLOC_FAILED is the only possible error.
20167836SJohn.Forte@Sun.COM */
20177836SJohn.Forte@Sun.COM static int
update_map_dev_FCP_prop(impl_map_dev_prop_t ** prop_list,uchar_t * inq_dtype,int err,int exist)2018*11547SBill.Gumbrell@Sun.COM update_map_dev_FCP_prop(impl_map_dev_prop_t **prop_list,
2019*11547SBill.Gumbrell@Sun.COM uchar_t *inq_dtype, int err, int exist)
20207836SJohn.Forte@Sun.COM {
20217836SJohn.Forte@Sun.COM impl_map_dev_prop_t *prop_ptr, *old_prop_ptr;
20227836SJohn.Forte@Sun.COM uchar_t *inq_dtype_data;
20237836SJohn.Forte@Sun.COM
20247836SJohn.Forte@Sun.COM if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
2025*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_prop_t))) == NULL) {
20267836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
20277836SJohn.Forte@Sun.COM }
20287836SJohn.Forte@Sun.COM
20297836SJohn.Forte@Sun.COM (void) strncpy(prop_ptr->prop_name, INQ_DTYPE_PROP,
2030*11547SBill.Gumbrell@Sun.COM strlen(INQ_DTYPE_PROP));
20317836SJohn.Forte@Sun.COM
20327836SJohn.Forte@Sun.COM if (inq_dtype == NULL) {
20337836SJohn.Forte@Sun.COM prop_ptr->prop_data = NULL;
20347836SJohn.Forte@Sun.COM prop_ptr->prop_error = err;
20357836SJohn.Forte@Sun.COM } else {
20367836SJohn.Forte@Sun.COM if ((inq_dtype_data = (uchar_t *)calloc(
2037*11547SBill.Gumbrell@Sun.COM 1, sizeof (uchar_t))) == NULL) {
20387836SJohn.Forte@Sun.COM free(prop_ptr);
20397836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
20407836SJohn.Forte@Sun.COM }
20417836SJohn.Forte@Sun.COM memcpy(inq_dtype_data, inq_dtype, sizeof (uchar_t));
20427836SJohn.Forte@Sun.COM prop_ptr->prop_data = inq_dtype_data;
20437836SJohn.Forte@Sun.COM prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
20447836SJohn.Forte@Sun.COM prop_ptr->prop_size = sizeof (uchar_t);
20457836SJohn.Forte@Sun.COM }
20467836SJohn.Forte@Sun.COM
20477836SJohn.Forte@Sun.COM if (*prop_list == NULL) {
20487836SJohn.Forte@Sun.COM *prop_list = prop_ptr;
20497836SJohn.Forte@Sun.COM } else {
20507836SJohn.Forte@Sun.COM if (exist == PROP_EXIST) {
20517836SJohn.Forte@Sun.COM prop_ptr->next = (*prop_list)->next;
20527836SJohn.Forte@Sun.COM old_prop_ptr = *prop_list;
20537836SJohn.Forte@Sun.COM *prop_list = prop_ptr;
20547836SJohn.Forte@Sun.COM free((uchar_t *)(old_prop_ptr->prop_data));
20557836SJohn.Forte@Sun.COM old_prop_ptr->prop_data = NULL;
20567836SJohn.Forte@Sun.COM S_FREE(old_prop_ptr);
20577836SJohn.Forte@Sun.COM } else {
20587836SJohn.Forte@Sun.COM prop_ptr->next = *prop_list;
20597836SJohn.Forte@Sun.COM *prop_list = prop_ptr;
20607836SJohn.Forte@Sun.COM }
20617836SJohn.Forte@Sun.COM }
20627836SJohn.Forte@Sun.COM
20637836SJohn.Forte@Sun.COM return (0);
20647836SJohn.Forte@Sun.COM }
20657836SJohn.Forte@Sun.COM
20667836SJohn.Forte@Sun.COM /*
20677836SJohn.Forte@Sun.COM * This function calls FCP_TGT_INQUIRY via g_issue_fcp_ioctl()
20687836SJohn.Forte@Sun.COM * to get the inq_dtype of input device and calls update_map_dev_FCP_prop().
20697836SJohn.Forte@Sun.COM * inq_dtype is set to NULL and pass error code if inq_dtype data is not
20707836SJohn.Forte@Sun.COM * requried.
20717836SJohn.Forte@Sun.COM *
20727836SJohn.Forte@Sun.COM * return error from update_map_dev_FCP_prop().
20737836SJohn.Forte@Sun.COM */
20747836SJohn.Forte@Sun.COM static int
handle_map_dev_FCP_prop(minor_t fp_xport_minor,la_wwn_t port_wwn,impl_map_dev_prop_t ** prop_list)2075*11547SBill.Gumbrell@Sun.COM handle_map_dev_FCP_prop(minor_t fp_xport_minor, la_wwn_t port_wwn,
2076*11547SBill.Gumbrell@Sun.COM impl_map_dev_prop_t **prop_list)
20777836SJohn.Forte@Sun.COM {
20787836SJohn.Forte@Sun.COM struct device_data inq_data;
20797836SJohn.Forte@Sun.COM int fcp_fd, err;
20807836SJohn.Forte@Sun.COM struct fcp_ioctl fcp_data;
20817836SJohn.Forte@Sun.COM uchar_t inq_dtype;
20827836SJohn.Forte@Sun.COM
20837836SJohn.Forte@Sun.COM if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
20847836SJohn.Forte@Sun.COM update_map_dev_FCP_prop(prop_list, NULL,
2085*11547SBill.Gumbrell@Sun.COM L_OPEN_PATH_FAIL, PROP_NOEXIST);
20867836SJohn.Forte@Sun.COM }
20877836SJohn.Forte@Sun.COM
20887836SJohn.Forte@Sun.COM /* Get the minor number for an fp instance */
20897836SJohn.Forte@Sun.COM fcp_data.fp_minor = fp_xport_minor;
20907836SJohn.Forte@Sun.COM
20917836SJohn.Forte@Sun.COM /* Get FCP prop for the hba first. */
20927836SJohn.Forte@Sun.COM fcp_data.listlen = 1;
20937836SJohn.Forte@Sun.COM inq_data.dev_pwwn = port_wwn;
20947836SJohn.Forte@Sun.COM fcp_data.list = (caddr_t)&inq_data;
20957836SJohn.Forte@Sun.COM
20967836SJohn.Forte@Sun.COM if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
20977836SJohn.Forte@Sun.COM /* if ioctl error then set the prop_error. */
2098*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(
2099*11547SBill.Gumbrell@Sun.COM prop_list, NULL, err, PROP_NOEXIST)) != 0) {
2100*11547SBill.Gumbrell@Sun.COM return (err);
2101*11547SBill.Gumbrell@Sun.COM }
21027836SJohn.Forte@Sun.COM } else {
2103*11547SBill.Gumbrell@Sun.COM inq_dtype = inq_data.dev0_type;
2104*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(
2105*11547SBill.Gumbrell@Sun.COM prop_list, &inq_dtype, 0, PROP_NOEXIST)) != 0) {
2106*11547SBill.Gumbrell@Sun.COM return (err);
2107*11547SBill.Gumbrell@Sun.COM }
21087836SJohn.Forte@Sun.COM }
21097836SJohn.Forte@Sun.COM
21107836SJohn.Forte@Sun.COM return (0);
21117836SJohn.Forte@Sun.COM }
21127836SJohn.Forte@Sun.COM
21137836SJohn.Forte@Sun.COM /*
21147836SJohn.Forte@Sun.COM * Construct device map tree from nexus driver
21157836SJohn.Forte@Sun.COM *
21167836SJohn.Forte@Sun.COM * PARAMS:
21177836SJohn.Forte@Sun.COM * path - must be the physical path to a device
21187836SJohn.Forte@Sun.COM * l_err - ptr to an error code. Set when NULL is returned.
21197836SJohn.Forte@Sun.COM * flag - device map fomat and property type.
21207836SJohn.Forte@Sun.COM *
21217836SJohn.Forte@Sun.COM * LOGIC:
21227836SJohn.Forte@Sun.COM * 1. check the validity of path via g_get_path_type.
21237836SJohn.Forte@Sun.COM * 2. If FC path, get the topology of the path via
21247836SJohn.Forte@Sun.COM * g_get_fca_port_topology.
21257836SJohn.Forte@Sun.COM *
21267836SJohn.Forte@Sun.COM * 3. If FC type(Leadville statck)
21277836SJohn.Forte@Sun.COM * FCIO_GET_DEV_LIST to get the device node list of fc_port_dev_t.
21287836SJohn.Forte@Sun.COM * FCIO_GET_HOST_PARAMS to get the fca port node of fc_port_dev_t.
21297836SJohn.Forte@Sun.COM *
21307836SJohn.Forte@Sun.COM * root of tree is set with host_params info
21317836SJohn.Forte@Sun.COM * FC propery is set.
21327836SJohn.Forte@Sun.COM * FCP property is set if reqyested through flag.
21337836SJohn.Forte@Sun.COM * Issue g_issue_fcp_ioctl to get FCP inquiry data
21347836SJohn.Forte@Sun.COM * consruruct list of children via dev_list.
21357836SJohn.Forte@Sun.COM * FC property is set.
21367836SJohn.Forte@Sun.COM * FCP property is set if reqyested through flag.
21377836SJohn.Forte@Sun.COM * Issue FCIO_DEV_LOGIN if it is fabric device.
21387836SJohn.Forte@Sun.COM * Issue g_issue_fcp_ioctl to get FCP inquiry data.
21397836SJohn.Forte@Sun.COM *
21407836SJohn.Forte@Sun.COM * else FC4 type(socal/sf or ifp stack)
21417836SJohn.Forte@Sun.COM * SFIOCGMAP ioctl to get the device and hba nodes of
21427836SJohn.Forte@Sun.COM * sf_addr_pair_t.
21437836SJohn.Forte@Sun.COM * FCIO_GETMAP ioctl to get hba port info.
21447836SJohn.Forte@Sun.COM * consturct map and child tree list and
21457836SJohn.Forte@Sun.COM * set the properties as private loop devices.
21467836SJohn.Forte@Sun.COM *
21477836SJohn.Forte@Sun.COM * RETURNS:
21487836SJohn.Forte@Sun.COM * ptr to map is returned if OK.
21497836SJohn.Forte@Sun.COM * NULL and l_err is set otherwise.
21507836SJohn.Forte@Sun.COM */
21517836SJohn.Forte@Sun.COM gfc_dev_t
g_dev_map_init(char * path,int * l_err,int flag)21527836SJohn.Forte@Sun.COM g_dev_map_init(char *path, int *l_err, int flag)
21537836SJohn.Forte@Sun.COM {
2154*11547SBill.Gumbrell@Sun.COM int fd, i, num_devices = 0, err, pathcnt = 1, new_count = 0;
2155*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN];
2156*11547SBill.Gumbrell@Sun.COM char *char_ptr, *nexus_path;
2157*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
2158*11547SBill.Gumbrell@Sun.COM fc_port_dev_t *dev_list = NULL, *dlist;
2159*11547SBill.Gumbrell@Sun.COM uint32_t hba_port_top, state;
2160*11547SBill.Gumbrell@Sun.COM uint_t path_type;
2161*11547SBill.Gumbrell@Sun.COM sf_al_map_t sf_map;
2162*11547SBill.Gumbrell@Sun.COM fc_port_dev_t fp_hba_port;
2163*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
2164*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0, hba_alpa_found = 0, nexus_fd;
2165*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
2166*11547SBill.Gumbrell@Sun.COM struct lilpmap limited_map;
2167*11547SBill.Gumbrell@Sun.COM impl_map_dev_t *impl_map, *impl_dev;
2168*11547SBill.Gumbrell@Sun.COM impl_map_dev_t *mdl_start = NULL, *mdl_end = NULL;
2169*11547SBill.Gumbrell@Sun.COM struct stat sbuf;
21707836SJohn.Forte@Sun.COM
21717836SJohn.Forte@Sun.COM if (l_err == NULL) {
21727836SJohn.Forte@Sun.COM return (NULL);
21737836SJohn.Forte@Sun.COM }
21747836SJohn.Forte@Sun.COM
21757836SJohn.Forte@Sun.COM if (path == NULL) {
21767836SJohn.Forte@Sun.COM *l_err = L_INVALID_PATH;
21777836SJohn.Forte@Sun.COM return (NULL);
21787836SJohn.Forte@Sun.COM }
21797836SJohn.Forte@Sun.COM
21807836SJohn.Forte@Sun.COM *l_err = 0;
21817836SJohn.Forte@Sun.COM
21827836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
21837836SJohn.Forte@Sun.COM /*
21847836SJohn.Forte@Sun.COM * Get the path to the :devctl driver
21857836SJohn.Forte@Sun.COM *
21867836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
21877836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
21887836SJohn.Forte@Sun.COM * or
21897836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
21907836SJohn.Forte@Sun.COM * or
21917836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
21927836SJohn.Forte@Sun.COM * or
21937836SJohn.Forte@Sun.COM * a 1 level PCI type driver but still :devctl
21947836SJohn.Forte@Sun.COM */
21957836SJohn.Forte@Sun.COM if (strstr(path, SCSI_VHCI)) {
21967836SJohn.Forte@Sun.COM (void) strcpy(drvr_path0, path);
21977836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path0, &pathlist)) {
21987836SJohn.Forte@Sun.COM *l_err = L_INVALID_PATH;
21997836SJohn.Forte@Sun.COM return (NULL);
22007836SJohn.Forte@Sun.COM }
22017836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
22027836SJohn.Forte@Sun.COM p_on = p_st = 0;
22037836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
22047836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
22057836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
2206*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
22077836SJohn.Forte@Sun.COM p_on = i;
22087836SJohn.Forte@Sun.COM break;
22097836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
2210*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
22117836SJohn.Forte@Sun.COM p_st = i;
22127836SJohn.Forte@Sun.COM }
22137836SJohn.Forte@Sun.COM }
22147836SJohn.Forte@Sun.COM }
22157836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
22167836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
22177836SJohn.Forte@Sun.COM /* on_line path */
22187836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
2219*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
22207836SJohn.Forte@Sun.COM } else {
22217836SJohn.Forte@Sun.COM /* standby or path0 */
22227836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
2223*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
22247836SJohn.Forte@Sun.COM }
22257836SJohn.Forte@Sun.COM free(pathlist.path_info);
22267836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
22277836SJohn.Forte@Sun.COM } else {
22287836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
22297836SJohn.Forte@Sun.COM if (strstr(drvr_path, DRV_NAME_SSD) ||
2230*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, SES_NAME) ||
2231*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, DRV_NAME_ST)) {
22327836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
22337836SJohn.Forte@Sun.COM *l_err = L_INVALID_PATH;
22347836SJohn.Forte@Sun.COM return (NULL);
22357836SJohn.Forte@Sun.COM }
22367836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate sting */
22377836SJohn.Forte@Sun.COM /* append controller */
22387836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
22397836SJohn.Forte@Sun.COM } else {
22407836SJohn.Forte@Sun.COM if (stat(drvr_path, &stbuf) < 0) {
22417836SJohn.Forte@Sun.COM *l_err = L_LSTAT_ERROR;
22427836SJohn.Forte@Sun.COM return (NULL);
22437836SJohn.Forte@Sun.COM }
22447836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
22457836SJohn.Forte@Sun.COM /* append controller */
22467836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
22477836SJohn.Forte@Sun.COM }
22487836SJohn.Forte@Sun.COM }
22497836SJohn.Forte@Sun.COM }
22507836SJohn.Forte@Sun.COM
22517836SJohn.Forte@Sun.COM P_DPRINTF(" g_dev_map_init: Geting drive map from:"
2252*11547SBill.Gumbrell@Sun.COM " %s\n", drvr_path);
22537836SJohn.Forte@Sun.COM
22547836SJohn.Forte@Sun.COM path_type = g_get_path_type(drvr_path);
22557836SJohn.Forte@Sun.COM if ((path_type == 0) || !(path_type & XPORT_MASK)) {
22567836SJohn.Forte@Sun.COM *l_err = L_INVALID_PATH_TYPE;
22577836SJohn.Forte@Sun.COM return (NULL);
22587836SJohn.Forte@Sun.COM }
22597836SJohn.Forte@Sun.COM
22607836SJohn.Forte@Sun.COM /* get fiber topology */
22617836SJohn.Forte@Sun.COM if ((err = g_get_fca_port_topology(drvr_path,
2262*11547SBill.Gumbrell@Sun.COM &hba_port_top, 0)) != 0) {
22637836SJohn.Forte@Sun.COM *l_err = err;
22647836SJohn.Forte@Sun.COM return (NULL);
22657836SJohn.Forte@Sun.COM }
22667836SJohn.Forte@Sun.COM
22677836SJohn.Forte@Sun.COM if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) {
22687836SJohn.Forte@Sun.COM *l_err = errno;
22697836SJohn.Forte@Sun.COM return (NULL);
22707836SJohn.Forte@Sun.COM }
22717836SJohn.Forte@Sun.COM
22727836SJohn.Forte@Sun.COM /* for FC devices. */
22737836SJohn.Forte@Sun.COM if (path_type & FC_FCA_MASK) {
22747836SJohn.Forte@Sun.COM /* get the number of device first. */
2275*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_GET_NUM_DEVS;
2276*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = sizeof (num_devices);
2277*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
2278*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)&num_devices;
2279*11547SBill.Gumbrell@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2280*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n");
2281*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2282*11547SBill.Gumbrell@Sun.COM *l_err = L_FCIO_GET_NUM_DEVS_FAIL;
2283*11547SBill.Gumbrell@Sun.COM return (NULL);
22847836SJohn.Forte@Sun.COM }
2285*11547SBill.Gumbrell@Sun.COM if (num_devices != 0) {
22867836SJohn.Forte@Sun.COM if ((dev_list = (fc_port_dev_t *)calloc(num_devices,
2287*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t))) == NULL) {
2288*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2289*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2290*11547SBill.Gumbrell@Sun.COM return (NULL);
22917836SJohn.Forte@Sun.COM }
2292*11547SBill.Gumbrell@Sun.COM
2293*11547SBill.Gumbrell@Sun.COM bzero((caddr_t)&fcio, sizeof (fcio));
2294*11547SBill.Gumbrell@Sun.COM /* Get the device list */
22957836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_DEV_LIST;
22967836SJohn.Forte@Sun.COM /* Information read operation */
22977836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
2298*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
22997836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)dev_list;
23007836SJohn.Forte@Sun.COM /* new device count */
23017836SJohn.Forte@Sun.COM fcio.fcio_alen = sizeof (new_count);
23027836SJohn.Forte@Sun.COM fcio.fcio_abuf = (caddr_t)&new_count;
23037836SJohn.Forte@Sun.COM if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
2304*11547SBill.Gumbrell@Sun.COM if (err == L_INVALID_DEVICE_COUNT) {
2305*11547SBill.Gumbrell@Sun.COM /*
2306*11547SBill.Gumbrell@Sun.COM * original buffer was small so allocate
2307*11547SBill.Gumbrell@Sun.COM * buffer with a new count and retry.
2308*11547SBill.Gumbrell@Sun.COM */
2309*11547SBill.Gumbrell@Sun.COM free(dev_list);
2310*11547SBill.Gumbrell@Sun.COM num_devices = new_count;
2311*11547SBill.Gumbrell@Sun.COM new_count = 0;
2312*11547SBill.Gumbrell@Sun.COM if ((dev_list = (fc_port_dev_t *)
2313*11547SBill.Gumbrell@Sun.COM calloc(num_devices,
2314*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t))) == NULL) {
2315*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2316*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2317*11547SBill.Gumbrell@Sun.COM return (NULL);
2318*11547SBill.Gumbrell@Sun.COM }
2319*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_GET_DEV_LIST;
2320*11547SBill.Gumbrell@Sun.COM /* Information read operation */
2321*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
2322*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)dev_list;
2323*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = num_devices *
2324*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t);
2325*11547SBill.Gumbrell@Sun.COM /* new device count */
2326*11547SBill.Gumbrell@Sun.COM fcio.fcio_alen = sizeof (new_count);
2327*11547SBill.Gumbrell@Sun.COM fcio.fcio_abuf = (caddr_t)&new_count;
2328*11547SBill.Gumbrell@Sun.COM if ((err = g_issue_fcio_ioctl(fd, &fcio,
2329*11547SBill.Gumbrell@Sun.COM 0)) != 0) {
2330*11547SBill.Gumbrell@Sun.COM if (err ==
2331*11547SBill.Gumbrell@Sun.COM L_INVALID_DEVICE_COUNT) {
2332*11547SBill.Gumbrell@Sun.COM /*
2333*11547SBill.Gumbrell@Sun.COM * No more retry. There
2334*11547SBill.Gumbrell@Sun.COM * may be severe
2335*11547SBill.Gumbrell@Sun.COM * hardware problem so
2336*11547SBill.Gumbrell@Sun.COM * return error here.
2337*11547SBill.Gumbrell@Sun.COM */
2338*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" Device"
2339*11547SBill.Gumbrell@Sun.COM " count was %d"
2340*11547SBill.Gumbrell@Sun.COM " should have been"
2341*11547SBill.Gumbrell@Sun.COM " %d\n",
2342*11547SBill.Gumbrell@Sun.COM num_devices,
2343*11547SBill.Gumbrell@Sun.COM new_count);
2344*11547SBill.Gumbrell@Sun.COM free(dev_list);
2345*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2346*11547SBill.Gumbrell@Sun.COM
2347*11547SBill.Gumbrell@Sun.COM *l_err = L_INVALID_DEVICE_COUNT;
2348*11547SBill.Gumbrell@Sun.COM
2349*11547SBill.Gumbrell@Sun.COM return (NULL);
2350*11547SBill.Gumbrell@Sun.COM } else {
2351*11547SBill.Gumbrell@Sun.COM
2352*11547SBill.Gumbrell@Sun.COM /* Code refactorization is needed for C style */
23537836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed.");
2354*11547SBill.Gumbrell@Sun.COM
2355*11547SBill.Gumbrell@Sun.COM free(dev_list);
2356*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2357*11547SBill.Gumbrell@Sun.COM
2358*11547SBill.Gumbrell@Sun.COM *l_err = L_FCIO_GET_DEV_LIST_FAIL;
2359*11547SBill.Gumbrell@Sun.COM
2360*11547SBill.Gumbrell@Sun.COM return (NULL);
2361*11547SBill.Gumbrell@Sun.COM }
2362*11547SBill.Gumbrell@Sun.COM }
2363*11547SBill.Gumbrell@Sun.COM }
23647836SJohn.Forte@Sun.COM }
23657836SJohn.Forte@Sun.COM }
23667836SJohn.Forte@Sun.COM
23677836SJohn.Forte@Sun.COM /*
23687836SJohn.Forte@Sun.COM * if new count is smaller than the original number from
23697836SJohn.Forte@Sun.COM * FCIO_GET_NUM_DEVS, adjust new count and buffer size
23707836SJohn.Forte@Sun.COM * and continue.
23717836SJohn.Forte@Sun.COM */
2372*11547SBill.Gumbrell@Sun.COM if (new_count < num_devices) {
2373*11547SBill.Gumbrell@Sun.COM num_devices = new_count;
2374*11547SBill.Gumbrell@Sun.COM if (new_count > 0) {
2375*11547SBill.Gumbrell@Sun.COM if ((dev_list = (fc_port_dev_t *)
2376*11547SBill.Gumbrell@Sun.COM realloc(dev_list,
2377*11547SBill.Gumbrell@Sun.COM (new_count * sizeof (fc_port_dev_t))))
2378*11547SBill.Gumbrell@Sun.COM == NULL) {
2379*11547SBill.Gumbrell@Sun.COM S_FREE(dev_list);
2380*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2381*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2382*11547SBill.Gumbrell@Sun.COM return (NULL);
2383*11547SBill.Gumbrell@Sun.COM }
2384*11547SBill.Gumbrell@Sun.COM }
23857836SJohn.Forte@Sun.COM }
23867836SJohn.Forte@Sun.COM
23877836SJohn.Forte@Sun.COM /* get the host param info */
2388*11547SBill.Gumbrell@Sun.COM (void) memset(&fp_hba_port, 0, sizeof (struct fc_port_dev));
2389*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_GET_HOST_PARAMS;
2390*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
2391*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)&fp_hba_port;
2392*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = sizeof (fc_port_dev_t);
2393*11547SBill.Gumbrell@Sun.COM
2394*11547SBill.Gumbrell@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2395*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n");
2396*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2397*11547SBill.Gumbrell@Sun.COM if (num_devices == 0) {
2398*11547SBill.Gumbrell@Sun.COM *l_err = L_NO_DEVICES_FOUND;
2399*11547SBill.Gumbrell@Sun.COM } else {
2400*11547SBill.Gumbrell@Sun.COM free(dev_list);
2401*11547SBill.Gumbrell@Sun.COM *l_err = L_FCIO_GET_HOST_PARAMS_FAIL;
2402*11547SBill.Gumbrell@Sun.COM }
2403*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2404*11547SBill.Gumbrell@Sun.COM return (NULL);
24057836SJohn.Forte@Sun.COM }
24067836SJohn.Forte@Sun.COM
24077836SJohn.Forte@Sun.COM /* If we want the lilp map then we need to do a little */
24087836SJohn.Forte@Sun.COM /* work here. The lilp map contains the local hba in */
24097836SJohn.Forte@Sun.COM /* the dev_addr. Once this has been added qsort the */
24107836SJohn.Forte@Sun.COM /* dev_addr array so it's in physical order. */
2411*11547SBill.Gumbrell@Sun.COM if ((flag & MAP_FORMAT_LILP) == MAP_FORMAT_LILP) {
2412*11547SBill.Gumbrell@Sun.COM /* First we need to allocate one additional */
2413*11547SBill.Gumbrell@Sun.COM /* device to the dev_addr structure, for the */
2414*11547SBill.Gumbrell@Sun.COM /* local hba */
2415*11547SBill.Gumbrell@Sun.COM if (num_devices > 0) {
2416*11547SBill.Gumbrell@Sun.COM if ((dev_list = (fc_port_dev_t *)
2417*11547SBill.Gumbrell@Sun.COM realloc(dev_list,
2418*11547SBill.Gumbrell@Sun.COM (++num_devices *
2419*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t)))) == NULL) {
2420*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2421*11547SBill.Gumbrell@Sun.COM /*
2422*11547SBill.Gumbrell@Sun.COM * In case dev_list is not null free
2423*11547SBill.Gumbrell@Sun.COM * it.
2424*11547SBill.Gumbrell@Sun.COM */
2425*11547SBill.Gumbrell@Sun.COM S_FREE(dev_list);
2426*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2427*11547SBill.Gumbrell@Sun.COM return (NULL);
2428*11547SBill.Gumbrell@Sun.COM }
2429*11547SBill.Gumbrell@Sun.COM
2430*11547SBill.Gumbrell@Sun.COM /*
2431*11547SBill.Gumbrell@Sun.COM * Next, copy the local hba into this new
2432*11547SBill.Gumbrell@Sun.COM * loc.
2433*11547SBill.Gumbrell@Sun.COM */
2434*11547SBill.Gumbrell@Sun.COM if (memcpy(dev_list+(num_devices-1),
2435*11547SBill.Gumbrell@Sun.COM &fp_hba_port,
2436*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t)) == NULL) {
2437*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2438*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2439*11547SBill.Gumbrell@Sun.COM *l_err = L_MEMCPY_FAILED;
2440*11547SBill.Gumbrell@Sun.COM return (NULL);
2441*11547SBill.Gumbrell@Sun.COM }
2442*11547SBill.Gumbrell@Sun.COM
2443*11547SBill.Gumbrell@Sun.COM /* Now sort by physical location */
2444*11547SBill.Gumbrell@Sun.COM qsort((void*)dev_list, num_devices,
2445*11547SBill.Gumbrell@Sun.COM sizeof (fc_port_dev_t), lilp_map_cmp);
2446*11547SBill.Gumbrell@Sun.COM }
24477836SJohn.Forte@Sun.COM }
24487836SJohn.Forte@Sun.COM
24497836SJohn.Forte@Sun.COM
24507836SJohn.Forte@Sun.COM /* We have dev list info and host param info. */
24517836SJohn.Forte@Sun.COM /* Now constructs map tree with these info. */
24527836SJohn.Forte@Sun.COM /* First consturct the root of the map tree */
24537836SJohn.Forte@Sun.COM /* with host param. */
2454*11547SBill.Gumbrell@Sun.COM if ((impl_map = (impl_map_dev_t *)calloc(
2455*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_t))) == NULL) {
2456*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2457*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2458*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2459*11547SBill.Gumbrell@Sun.COM return (NULL);
2460*11547SBill.Gumbrell@Sun.COM }
2461*11547SBill.Gumbrell@Sun.COM impl_map->flag = flag;
2462*11547SBill.Gumbrell@Sun.COM impl_map->topo = hba_port_top;
24637836SJohn.Forte@Sun.COM
24647836SJohn.Forte@Sun.COM /* consturct hba property list. */
2465*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_fc_prop(&impl_map->prop_list,
24667836SJohn.Forte@Sun.COM hba_port_top, fp_hba_port.dev_pwwn.raw_wwn,
24677836SJohn.Forte@Sun.COM fp_hba_port.dev_nwwn.raw_wwn, fp_hba_port.dev_did.port_id,
24687836SJohn.Forte@Sun.COM fp_hba_port.dev_hard_addr.hard_addr)) != 0) {
24697836SJohn.Forte@Sun.COM (void) free(dev_list);
24707836SJohn.Forte@Sun.COM (void) close(fd);
24717836SJohn.Forte@Sun.COM g_dev_map_fini(impl_map);
24727836SJohn.Forte@Sun.COM *l_err = err;
24737836SJohn.Forte@Sun.COM return (NULL);
2474*11547SBill.Gumbrell@Sun.COM }
2475*11547SBill.Gumbrell@Sun.COM
2476*11547SBill.Gumbrell@Sun.COM if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) {
2477*11547SBill.Gumbrell@Sun.COM if (fstat(fd, &sbuf) == -1) {
2478*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2479*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2480*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2481*11547SBill.Gumbrell@Sun.COM *l_err = L_FSTAT_ERROR;
2482*11547SBill.Gumbrell@Sun.COM return (NULL);
2483*11547SBill.Gumbrell@Sun.COM }
2484*11547SBill.Gumbrell@Sun.COM if ((err = handle_map_dev_FCP_prop(minor(sbuf.st_rdev),
2485*11547SBill.Gumbrell@Sun.COM fp_hba_port.dev_pwwn, &impl_map->prop_list)) != 0) {
2486*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2487*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2488*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2489*11547SBill.Gumbrell@Sun.COM *l_err = err;
2490*11547SBill.Gumbrell@Sun.COM return (NULL);
2491*11547SBill.Gumbrell@Sun.COM }
24927836SJohn.Forte@Sun.COM }
2493*11547SBill.Gumbrell@Sun.COM
2494*11547SBill.Gumbrell@Sun.COM /* consturct child for each device and */
2495*11547SBill.Gumbrell@Sun.COM /* set device property list. */
2496*11547SBill.Gumbrell@Sun.COM dlist = dev_list;
2497*11547SBill.Gumbrell@Sun.COM for (i = 0; i < num_devices; i++, dlist++) {
2498*11547SBill.Gumbrell@Sun.COM if ((impl_dev = (impl_map_dev_t *)calloc(
2499*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_t))) == NULL) {
2500*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2501*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2502*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2503*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2504*11547SBill.Gumbrell@Sun.COM return (NULL);
2505*11547SBill.Gumbrell@Sun.COM }
2506*11547SBill.Gumbrell@Sun.COM /* set the map as parent */
2507*11547SBill.Gumbrell@Sun.COM impl_dev->parent = impl_map;
2508*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_fc_prop(&impl_dev->prop_list,
2509*11547SBill.Gumbrell@Sun.COM hba_port_top, dlist->dev_pwwn.raw_wwn,
2510*11547SBill.Gumbrell@Sun.COM dlist->dev_nwwn.raw_wwn, dlist->dev_did.port_id,
2511*11547SBill.Gumbrell@Sun.COM dlist->dev_hard_addr.hard_addr)) != 0) {
2512*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2513*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2514*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2515*11547SBill.Gumbrell@Sun.COM *l_err = err;
2516*11547SBill.Gumbrell@Sun.COM return (NULL);
2517*11547SBill.Gumbrell@Sun.COM }
2518*11547SBill.Gumbrell@Sun.COM if (i == 0) {
2519*11547SBill.Gumbrell@Sun.COM mdl_start = mdl_end = impl_dev;
2520*11547SBill.Gumbrell@Sun.COM } else {
2521*11547SBill.Gumbrell@Sun.COM mdl_end->next = impl_dev;
2522*11547SBill.Gumbrell@Sun.COM mdl_end = impl_dev;
2523*11547SBill.Gumbrell@Sun.COM }
2524*11547SBill.Gumbrell@Sun.COM if ((flag & MAP_XPORT_PROP_ONLY) !=
2525*11547SBill.Gumbrell@Sun.COM MAP_XPORT_PROP_ONLY) {
2526*11547SBill.Gumbrell@Sun.COM if (((hba_port_top == FC_TOP_PUBLIC_LOOP) ||
2527*11547SBill.Gumbrell@Sun.COM (hba_port_top == FC_TOP_FABRIC)) &&
2528*11547SBill.Gumbrell@Sun.COM (memcmp(fp_hba_port.dev_pwwn.raw_wwn,
2529*11547SBill.Gumbrell@Sun.COM dlist->dev_pwwn.raw_wwn, FC_WWN_SIZE) != 0)) {
2530*11547SBill.Gumbrell@Sun.COM (void) memset(&fcio, 0, sizeof (fcio_t));
2531*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_GET_STATE;
2532*11547SBill.Gumbrell@Sun.COM fcio.fcio_ilen = sizeof (dlist->dev_pwwn);
2533*11547SBill.Gumbrell@Sun.COM fcio.fcio_ibuf = (caddr_t)&dlist->dev_pwwn;
2534*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ |
2535*11547SBill.Gumbrell@Sun.COM FCIO_XFER_WRITE;
2536*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = sizeof (uint32_t);
2537*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)&state;
2538*11547SBill.Gumbrell@Sun.COM fcio.fcio_alen = 0;
2539*11547SBill.Gumbrell@Sun.COM fcio.fcio_abuf = NULL;
2540*11547SBill.Gumbrell@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2541*11547SBill.Gumbrell@Sun.COM I_DPRINTF(
2542*11547SBill.Gumbrell@Sun.COM " FCIO_GET_STATE ioctl failed.\n");
2543*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(
2544*11547SBill.Gumbrell@Sun.COM &impl_dev->prop_list, NULL,
2545*11547SBill.Gumbrell@Sun.COM L_FCIO_GET_STATE_FAIL,
2546*11547SBill.Gumbrell@Sun.COM PROP_NOEXIST)) != 0) {
2547*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2548*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2549*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2550*11547SBill.Gumbrell@Sun.COM *l_err = err;
2551*11547SBill.Gumbrell@Sun.COM return (NULL);
2552*11547SBill.Gumbrell@Sun.COM }
2553*11547SBill.Gumbrell@Sun.COM }
2554*11547SBill.Gumbrell@Sun.COM if (state != PORT_DEVICE_LOGGED_IN) {
2555*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2556*11547SBill.Gumbrell@Sun.COM if ((fd = g_object_open(drvr_path,
2557*11547SBill.Gumbrell@Sun.COM O_NDELAY | O_RDONLY | O_EXCL)) ==
2558*11547SBill.Gumbrell@Sun.COM -1) {
2559*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2560*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2561*11547SBill.Gumbrell@Sun.COM *l_err = L_OPEN_PATH_FAIL;
2562*11547SBill.Gumbrell@Sun.COM return (NULL);
2563*11547SBill.Gumbrell@Sun.COM }
2564*11547SBill.Gumbrell@Sun.COM (void) memset(&fcio, 0,
2565*11547SBill.Gumbrell@Sun.COM sizeof (fcio_t));
2566*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_DEV_LOGIN;
2567*11547SBill.Gumbrell@Sun.COM fcio.fcio_ilen =
2568*11547SBill.Gumbrell@Sun.COM sizeof (dlist->dev_pwwn);
2569*11547SBill.Gumbrell@Sun.COM fcio.fcio_ibuf =
2570*11547SBill.Gumbrell@Sun.COM (caddr_t)&dlist->dev_pwwn;
2571*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_WRITE;
2572*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = fcio.fcio_alen = 0;
2573*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = fcio.fcio_abuf = NULL;
2574*11547SBill.Gumbrell@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, 0) !=
2575*11547SBill.Gumbrell@Sun.COM 0) {
2576*11547SBill.Gumbrell@Sun.COM
2577*11547SBill.Gumbrell@Sun.COM /* Code refactorization is needed for C style */
2578*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_DEV_LOGIN ioctl failed.\n");
2579*11547SBill.Gumbrell@Sun.COM
2580*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(
2581*11547SBill.Gumbrell@Sun.COM &impl_dev->prop_list, NULL,
2582*11547SBill.Gumbrell@Sun.COM L_FCIO_DEV_LOGIN_FAIL,
2583*11547SBill.Gumbrell@Sun.COM PROP_NOEXIST)) != 0) {
2584*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2585*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2586*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2587*11547SBill.Gumbrell@Sun.COM *l_err = err;
2588*11547SBill.Gumbrell@Sun.COM return (NULL);
2589*11547SBill.Gumbrell@Sun.COM }
2590*11547SBill.Gumbrell@Sun.COM
2591*11547SBill.Gumbrell@Sun.COM /*
2592*11547SBill.Gumbrell@Sun.COM * plogi failed continue
2593*11547SBill.Gumbrell@Sun.COM * to next dev
2594*11547SBill.Gumbrell@Sun.COM */
2595*11547SBill.Gumbrell@Sun.COM continue;
2596*11547SBill.Gumbrell@Sun.COM }
2597*11547SBill.Gumbrell@Sun.COM }
2598*11547SBill.Gumbrell@Sun.COM }
2599*11547SBill.Gumbrell@Sun.COM /* sbuf should be set from hba_port handling. */
2600*11547SBill.Gumbrell@Sun.COM if ((err = handle_map_dev_FCP_prop(
2601*11547SBill.Gumbrell@Sun.COM minor(sbuf.st_rdev),
2602*11547SBill.Gumbrell@Sun.COM dlist->dev_pwwn, &impl_dev->prop_list)) !=
2603*11547SBill.Gumbrell@Sun.COM 0) {
2604*11547SBill.Gumbrell@Sun.COM (void) free(dev_list);
2605*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2606*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2607*11547SBill.Gumbrell@Sun.COM *l_err = err;
2608*11547SBill.Gumbrell@Sun.COM return (NULL);
2609*11547SBill.Gumbrell@Sun.COM }
2610*11547SBill.Gumbrell@Sun.COM }
2611*11547SBill.Gumbrell@Sun.COM }
26127836SJohn.Forte@Sun.COM /* connect the children to to map. */
2613*11547SBill.Gumbrell@Sun.COM impl_map->child = mdl_start;
2614*11547SBill.Gumbrell@Sun.COM S_FREE(dev_list);
26157836SJohn.Forte@Sun.COM
26167836SJohn.Forte@Sun.COM } else { /* sf and fc4/pci devices */
2617*11547SBill.Gumbrell@Sun.COM /* initialize map */
2618*11547SBill.Gumbrell@Sun.COM (void) memset(&sf_map, 0, sizeof (struct sf_al_map));
2619*11547SBill.Gumbrell@Sun.COM if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
2620*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
2621*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2622*11547SBill.Gumbrell@Sun.COM *l_err = L_SFIOCGMAP_IOCTL_FAIL;
2623*11547SBill.Gumbrell@Sun.COM return (NULL);
2624*11547SBill.Gumbrell@Sun.COM }
26257836SJohn.Forte@Sun.COM /* Check for reasonableness. */
2626*11547SBill.Gumbrell@Sun.COM if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) {
2627*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2628*11547SBill.Gumbrell@Sun.COM *l_err = L_INVALID_LOOP_MAP;
2629*11547SBill.Gumbrell@Sun.COM return (NULL);
2630*11547SBill.Gumbrell@Sun.COM }
2631*11547SBill.Gumbrell@Sun.COM
2632*11547SBill.Gumbrell@Sun.COM if (sf_map.sf_count == 0) {
2633*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2634*11547SBill.Gumbrell@Sun.COM *l_err = L_NO_DEVICES_FOUND;
2635*11547SBill.Gumbrell@Sun.COM return (NULL);
2636*11547SBill.Gumbrell@Sun.COM }
2637*11547SBill.Gumbrell@Sun.COM
2638*11547SBill.Gumbrell@Sun.COM if ((err = g_get_nexus_path(drvr_path, &nexus_path)) != 0) {
2639*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2640*11547SBill.Gumbrell@Sun.COM *l_err = err;
2641*11547SBill.Gumbrell@Sun.COM return (NULL);
2642*11547SBill.Gumbrell@Sun.COM }
2643*11547SBill.Gumbrell@Sun.COM
2644*11547SBill.Gumbrell@Sun.COM if ((nexus_fd =
2645*11547SBill.Gumbrell@Sun.COM g_object_open(nexus_path, O_NDELAY | O_RDONLY)) == -1) {
2646*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2647*11547SBill.Gumbrell@Sun.COM S_FREE(nexus_path);
2648*11547SBill.Gumbrell@Sun.COM *l_err = errno;
2649*11547SBill.Gumbrell@Sun.COM return (NULL);
2650*11547SBill.Gumbrell@Sun.COM }
26517836SJohn.Forte@Sun.COM
26527836SJohn.Forte@Sun.COM /* get limited map to get hba param info */
2653*11547SBill.Gumbrell@Sun.COM if (ioctl(nexus_fd, FCIO_GETMAP, &limited_map) != 0) {
2654*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_GETMAP ioctl failed\n");
2655*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2656*11547SBill.Gumbrell@Sun.COM (void) close(nexus_fd);
2657*11547SBill.Gumbrell@Sun.COM S_FREE(nexus_path);
2658*11547SBill.Gumbrell@Sun.COM *l_err = L_FCIO_GETMAP_IOCTL_FAIL;
2659*11547SBill.Gumbrell@Sun.COM return (NULL);
2660*11547SBill.Gumbrell@Sun.COM }
26617836SJohn.Forte@Sun.COM (void) close(nexus_fd);
26627836SJohn.Forte@Sun.COM S_FREE(nexus_path);
2663*11547SBill.Gumbrell@Sun.COM
2664*11547SBill.Gumbrell@Sun.COM for (i = 0; i < sf_map.sf_count; i++) {
2665*11547SBill.Gumbrell@Sun.COM if (sf_map.sf_addr_pair[i].sf_al_pa ==
2666*11547SBill.Gumbrell@Sun.COM limited_map.lilp_myalpa) {
2667*11547SBill.Gumbrell@Sun.COM sf_map.sf_hba_addr = sf_map.sf_addr_pair[i];
2668*11547SBill.Gumbrell@Sun.COM hba_alpa_found = 1;
2669*11547SBill.Gumbrell@Sun.COM }
26707836SJohn.Forte@Sun.COM }
2671*11547SBill.Gumbrell@Sun.COM
2672*11547SBill.Gumbrell@Sun.COM if (!(hba_alpa_found)) {
2673*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2674*11547SBill.Gumbrell@Sun.COM *l_err = L_INVALID_LOOP_MAP;
2675*11547SBill.Gumbrell@Sun.COM return (NULL);
2676*11547SBill.Gumbrell@Sun.COM }
26777836SJohn.Forte@Sun.COM
26787836SJohn.Forte@Sun.COM /* We have dev list info and host param info. */
26797836SJohn.Forte@Sun.COM /* Now constructs map tree with these info. */
26807836SJohn.Forte@Sun.COM /* First consturct the root of the map tree */
26817836SJohn.Forte@Sun.COM /* with host param. */
2682*11547SBill.Gumbrell@Sun.COM if ((impl_map = (impl_map_dev_t *)calloc(
2683*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_t))) == NULL) {
2684*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2685*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2686*11547SBill.Gumbrell@Sun.COM return (NULL);
2687*11547SBill.Gumbrell@Sun.COM }
2688*11547SBill.Gumbrell@Sun.COM impl_map->flag = flag;
2689*11547SBill.Gumbrell@Sun.COM impl_map->topo = hba_port_top;
26907836SJohn.Forte@Sun.COM
26917836SJohn.Forte@Sun.COM /* consturct hba property list. */
2692*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_fc_prop(&impl_map->prop_list,
26937836SJohn.Forte@Sun.COM hba_port_top, sf_map.sf_hba_addr.sf_port_wwn,
26947836SJohn.Forte@Sun.COM sf_map.sf_hba_addr.sf_node_wwn,
26957836SJohn.Forte@Sun.COM (int)sf_map.sf_hba_addr.sf_al_pa,
26967836SJohn.Forte@Sun.COM (int)sf_map.sf_hba_addr.sf_hard_address)) != 0) {
26977836SJohn.Forte@Sun.COM (void) close(fd);
26987836SJohn.Forte@Sun.COM g_dev_map_fini(impl_map);
26997836SJohn.Forte@Sun.COM *l_err = err;
27007836SJohn.Forte@Sun.COM return (NULL);
2701*11547SBill.Gumbrell@Sun.COM }
2702*11547SBill.Gumbrell@Sun.COM
2703*11547SBill.Gumbrell@Sun.COM if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) {
2704*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(&impl_map->prop_list,
2705*11547SBill.Gumbrell@Sun.COM &sf_map.sf_hba_addr.sf_inq_dtype, 0,
2706*11547SBill.Gumbrell@Sun.COM PROP_NOEXIST)) != 0) {
2707*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2708*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2709*11547SBill.Gumbrell@Sun.COM *l_err = err;
2710*11547SBill.Gumbrell@Sun.COM return (NULL);
2711*11547SBill.Gumbrell@Sun.COM }
27127836SJohn.Forte@Sun.COM }
2713*11547SBill.Gumbrell@Sun.COM
2714*11547SBill.Gumbrell@Sun.COM for (i = 0; i < sf_map.sf_count; i++) {
2715*11547SBill.Gumbrell@Sun.COM if ((impl_dev = (impl_map_dev_t *)calloc(
2716*11547SBill.Gumbrell@Sun.COM 1, sizeof (impl_map_dev_t))) == NULL) {
2717*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2718*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2719*11547SBill.Gumbrell@Sun.COM *l_err = L_MALLOC_FAILED;
2720*11547SBill.Gumbrell@Sun.COM return (NULL);
2721*11547SBill.Gumbrell@Sun.COM }
2722*11547SBill.Gumbrell@Sun.COM /* set the map as parent */
2723*11547SBill.Gumbrell@Sun.COM impl_dev->parent = impl_map;
2724*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_fc_prop(&impl_dev->prop_list,
2725*11547SBill.Gumbrell@Sun.COM hba_port_top, sf_map.sf_addr_pair[i].sf_port_wwn,
2726*11547SBill.Gumbrell@Sun.COM sf_map.sf_addr_pair[i].sf_node_wwn,
2727*11547SBill.Gumbrell@Sun.COM (int)(sf_map.sf_addr_pair[i].sf_al_pa),
2728*11547SBill.Gumbrell@Sun.COM (int)(sf_map.sf_addr_pair[i].sf_hard_address))) !=
2729*11547SBill.Gumbrell@Sun.COM 0) {
2730*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2731*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2732*11547SBill.Gumbrell@Sun.COM *l_err = err;
2733*11547SBill.Gumbrell@Sun.COM return (NULL);
2734*11547SBill.Gumbrell@Sun.COM }
2735*11547SBill.Gumbrell@Sun.COM if (i == 0) {
2736*11547SBill.Gumbrell@Sun.COM mdl_start = mdl_end = impl_dev;
2737*11547SBill.Gumbrell@Sun.COM } else {
2738*11547SBill.Gumbrell@Sun.COM mdl_end->next = impl_dev;
2739*11547SBill.Gumbrell@Sun.COM mdl_end = impl_dev;
2740*11547SBill.Gumbrell@Sun.COM }
2741*11547SBill.Gumbrell@Sun.COM if ((flag & MAP_XPORT_PROP_ONLY) !=
2742*11547SBill.Gumbrell@Sun.COM MAP_XPORT_PROP_ONLY) {
2743*11547SBill.Gumbrell@Sun.COM if ((err = update_map_dev_FCP_prop(
2744*11547SBill.Gumbrell@Sun.COM &impl_dev->prop_list,
2745*11547SBill.Gumbrell@Sun.COM &sf_map.sf_addr_pair[i].sf_inq_dtype, 0,
2746*11547SBill.Gumbrell@Sun.COM PROP_NOEXIST)) != 0) {
2747*11547SBill.Gumbrell@Sun.COM (void) close(fd);
2748*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(impl_map);
2749*11547SBill.Gumbrell@Sun.COM *l_err = err;
2750*11547SBill.Gumbrell@Sun.COM return (NULL);
2751*11547SBill.Gumbrell@Sun.COM }
2752*11547SBill.Gumbrell@Sun.COM }
2753*11547SBill.Gumbrell@Sun.COM } /* end of for loop */
2754*11547SBill.Gumbrell@Sun.COM
2755*11547SBill.Gumbrell@Sun.COM impl_map->child = mdl_start;
27567836SJohn.Forte@Sun.COM } /* end of else */
27577836SJohn.Forte@Sun.COM
27587836SJohn.Forte@Sun.COM close(fd);
27597836SJohn.Forte@Sun.COM return ((gfc_dev_t)(impl_map));
27607836SJohn.Forte@Sun.COM }
27617836SJohn.Forte@Sun.COM
27627836SJohn.Forte@Sun.COM /*
27637836SJohn.Forte@Sun.COM * This function deallocates memory for propery list.
27647836SJohn.Forte@Sun.COM */
27657836SJohn.Forte@Sun.COM static void
free_prop_list(impl_map_dev_prop_t ** prop_list)27667836SJohn.Forte@Sun.COM free_prop_list(impl_map_dev_prop_t **prop_list)
27677836SJohn.Forte@Sun.COM {
27687836SJohn.Forte@Sun.COM impl_map_dev_prop_t *lp, *olp;
27697836SJohn.Forte@Sun.COM
27707836SJohn.Forte@Sun.COM lp = *prop_list;
27717836SJohn.Forte@Sun.COM while (lp != NULL) {
27727836SJohn.Forte@Sun.COM switch (lp->prop_type) {
27737836SJohn.Forte@Sun.COM case GFC_PROP_TYPE_BYTES:
27747836SJohn.Forte@Sun.COM free((uchar_t *)(lp->prop_data));
27757836SJohn.Forte@Sun.COM break;
27767836SJohn.Forte@Sun.COM case GFC_PROP_TYPE_INT:
27777836SJohn.Forte@Sun.COM free((int *)(lp->prop_data));
27787836SJohn.Forte@Sun.COM break;
27797836SJohn.Forte@Sun.COM case GFC_PROP_TYPE_STRING:
27807836SJohn.Forte@Sun.COM free((char *)(lp->prop_data));
27817836SJohn.Forte@Sun.COM break;
27827836SJohn.Forte@Sun.COM default:
27837836SJohn.Forte@Sun.COM break;
27847836SJohn.Forte@Sun.COM }
27857836SJohn.Forte@Sun.COM lp->prop_data = NULL;
27867836SJohn.Forte@Sun.COM olp = lp;
27877836SJohn.Forte@Sun.COM lp = olp->next;
27887836SJohn.Forte@Sun.COM S_FREE(olp);
27897836SJohn.Forte@Sun.COM }
27907836SJohn.Forte@Sun.COM
27917836SJohn.Forte@Sun.COM *prop_list = NULL;
27927836SJohn.Forte@Sun.COM }
27937836SJohn.Forte@Sun.COM
27947836SJohn.Forte@Sun.COM /*
27957836SJohn.Forte@Sun.COM * This function deallocates memory for children list.
27967836SJohn.Forte@Sun.COM */
27977836SJohn.Forte@Sun.COM static void
free_child_list(impl_map_dev_t ** dev_list)27987836SJohn.Forte@Sun.COM free_child_list(impl_map_dev_t **dev_list)
27997836SJohn.Forte@Sun.COM {
28007836SJohn.Forte@Sun.COM impl_map_dev_t *lp, *olp;
28017836SJohn.Forte@Sun.COM
28027836SJohn.Forte@Sun.COM lp = *dev_list;
28037836SJohn.Forte@Sun.COM while (lp != NULL) {
28047836SJohn.Forte@Sun.COM free_prop_list(&lp->prop_list);
28057836SJohn.Forte@Sun.COM olp = lp;
28067836SJohn.Forte@Sun.COM lp = olp->next;
28077836SJohn.Forte@Sun.COM S_FREE(olp);
28087836SJohn.Forte@Sun.COM }
28097836SJohn.Forte@Sun.COM
28107836SJohn.Forte@Sun.COM *dev_list = NULL;
28117836SJohn.Forte@Sun.COM }
28127836SJohn.Forte@Sun.COM
28137836SJohn.Forte@Sun.COM /*
28147836SJohn.Forte@Sun.COM * This function deallocates memory for the whole map.
28157836SJohn.Forte@Sun.COM */
28167836SJohn.Forte@Sun.COM void
g_dev_map_fini(gfc_dev_t map)28177836SJohn.Forte@Sun.COM g_dev_map_fini(gfc_dev_t map)
28187836SJohn.Forte@Sun.COM {
28197836SJohn.Forte@Sun.COM impl_map_dev_t *impl_map;
28207836SJohn.Forte@Sun.COM
28217836SJohn.Forte@Sun.COM impl_map = (impl_map_dev_t *)map;
28227836SJohn.Forte@Sun.COM
28237836SJohn.Forte@Sun.COM if (impl_map != NULL) {
2824*11547SBill.Gumbrell@Sun.COM free_prop_list(&impl_map->prop_list);
2825*11547SBill.Gumbrell@Sun.COM free_child_list(&impl_map->child);
2826*11547SBill.Gumbrell@Sun.COM S_FREE(impl_map);
28277836SJohn.Forte@Sun.COM }
28287836SJohn.Forte@Sun.COM }
28297836SJohn.Forte@Sun.COM
28307836SJohn.Forte@Sun.COM /*
28317836SJohn.Forte@Sun.COM * This function passes back topology of the input map.
28327836SJohn.Forte@Sun.COM * input should be a handle form g_dev_map_init().
28337836SJohn.Forte@Sun.COM *
28347836SJohn.Forte@Sun.COM * return 0 if OK.
28357836SJohn.Forte@Sun.COM * return error code otherwise.
28367836SJohn.Forte@Sun.COM */
28377836SJohn.Forte@Sun.COM int
g_get_map_topology(gfc_dev_t map,uint_t * topology)2838*11547SBill.Gumbrell@Sun.COM g_get_map_topology(gfc_dev_t map, uint_t *topology)
28397836SJohn.Forte@Sun.COM {
28407836SJohn.Forte@Sun.COM impl_map_dev_t *impl_map;
28417836SJohn.Forte@Sun.COM
28427836SJohn.Forte@Sun.COM if (map == NULL) {
28437836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
28447836SJohn.Forte@Sun.COM }
28457836SJohn.Forte@Sun.COM
28467836SJohn.Forte@Sun.COM if (topology == NULL) {
28477836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
28487836SJohn.Forte@Sun.COM }
28497836SJohn.Forte@Sun.COM
28507836SJohn.Forte@Sun.COM impl_map = (impl_map_dev_t *)map;
28517836SJohn.Forte@Sun.COM
28527836SJohn.Forte@Sun.COM *topology = impl_map->topo;
28537836SJohn.Forte@Sun.COM
28547836SJohn.Forte@Sun.COM return (0);
28557836SJohn.Forte@Sun.COM }
28567836SJohn.Forte@Sun.COM
28577836SJohn.Forte@Sun.COM /*
28587836SJohn.Forte@Sun.COM * This function returns the first device handle of the input map.
28597836SJohn.Forte@Sun.COM * map input should be a handle form g_dev_map_init().
28607836SJohn.Forte@Sun.COM *
28617836SJohn.Forte@Sun.COM * l_err set to 0 if OK.
28627836SJohn.Forte@Sun.COM * l_err set to error code otherwise.
28637836SJohn.Forte@Sun.COM */
28647836SJohn.Forte@Sun.COM gfc_dev_t
g_get_first_dev(gfc_dev_t map,int * l_err)2865*11547SBill.Gumbrell@Sun.COM g_get_first_dev(gfc_dev_t map, int *l_err)
28667836SJohn.Forte@Sun.COM {
28677836SJohn.Forte@Sun.COM impl_map_dev_t *impl_map;
28687836SJohn.Forte@Sun.COM
28697836SJohn.Forte@Sun.COM if (l_err == NULL) {
28707836SJohn.Forte@Sun.COM return (NULL);
28717836SJohn.Forte@Sun.COM }
28727836SJohn.Forte@Sun.COM
28737836SJohn.Forte@Sun.COM *l_err = 0;
28747836SJohn.Forte@Sun.COM
28757836SJohn.Forte@Sun.COM if (map == NULL) {
28767836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_ADDR;
28777836SJohn.Forte@Sun.COM return (NULL);
28787836SJohn.Forte@Sun.COM }
28797836SJohn.Forte@Sun.COM
28807836SJohn.Forte@Sun.COM impl_map = (impl_map_dev_t *)map;
28817836SJohn.Forte@Sun.COM
28827836SJohn.Forte@Sun.COM if (impl_map->child == NULL) {
28837836SJohn.Forte@Sun.COM *l_err = L_NO_SUCH_DEV_FOUND;
28847836SJohn.Forte@Sun.COM }
28857836SJohn.Forte@Sun.COM
28867836SJohn.Forte@Sun.COM return ((gfc_dev_t)(impl_map->child));
28877836SJohn.Forte@Sun.COM }
28887836SJohn.Forte@Sun.COM
28897836SJohn.Forte@Sun.COM /*
28907836SJohn.Forte@Sun.COM * This function returns the next device handle of the input map.
28917836SJohn.Forte@Sun.COM * map_dev input should be a handle for device.
28927836SJohn.Forte@Sun.COM *
28937836SJohn.Forte@Sun.COM * l_err set to 0 if OK.
28947836SJohn.Forte@Sun.COM * l_err set to error code otherwise.
28957836SJohn.Forte@Sun.COM */
28967836SJohn.Forte@Sun.COM gfc_dev_t
g_get_next_dev(gfc_dev_t map_dev,int * l_err)2897*11547SBill.Gumbrell@Sun.COM g_get_next_dev(gfc_dev_t map_dev, int *l_err)
28987836SJohn.Forte@Sun.COM {
28997836SJohn.Forte@Sun.COM impl_map_dev_t *impl_dev;
29007836SJohn.Forte@Sun.COM
29017836SJohn.Forte@Sun.COM if (l_err == NULL) {
29027836SJohn.Forte@Sun.COM return (NULL);
29037836SJohn.Forte@Sun.COM }
29047836SJohn.Forte@Sun.COM
29057836SJohn.Forte@Sun.COM *l_err = 0;
29067836SJohn.Forte@Sun.COM
29077836SJohn.Forte@Sun.COM if (map_dev == NULL) {
29087836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_ADDR;
29097836SJohn.Forte@Sun.COM return (NULL);
29107836SJohn.Forte@Sun.COM }
29117836SJohn.Forte@Sun.COM
29127836SJohn.Forte@Sun.COM impl_dev = (impl_map_dev_t *)map_dev;
29137836SJohn.Forte@Sun.COM
29147836SJohn.Forte@Sun.COM if (impl_dev->next == NULL) {
29157836SJohn.Forte@Sun.COM *l_err = L_NO_SUCH_DEV_FOUND;
29167836SJohn.Forte@Sun.COM }
29177836SJohn.Forte@Sun.COM
29187836SJohn.Forte@Sun.COM return ((gfc_dev_t)(impl_dev->next));
29197836SJohn.Forte@Sun.COM }
29207836SJohn.Forte@Sun.COM
29217836SJohn.Forte@Sun.COM /*
29227836SJohn.Forte@Sun.COM * This function passes back uchar_t type property and its count.
29237836SJohn.Forte@Sun.COM * map_dev input should be a handle for device.
29247836SJohn.Forte@Sun.COM *
29257836SJohn.Forte@Sun.COM * return 0 if OK.
29267836SJohn.Forte@Sun.COM * return error code otherwise.
29277836SJohn.Forte@Sun.COM */
29287836SJohn.Forte@Sun.COM int
g_dev_prop_lookup_bytes(gfc_dev_t map_dev,const char * prop_name,int * prop_data_count,uchar_t ** prop_data)2929*11547SBill.Gumbrell@Sun.COM g_dev_prop_lookup_bytes(gfc_dev_t map_dev, const char *prop_name,
2930*11547SBill.Gumbrell@Sun.COM int *prop_data_count, uchar_t **prop_data)
29317836SJohn.Forte@Sun.COM {
29327836SJohn.Forte@Sun.COM impl_map_dev_t *impl_dev;
29337836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
29347836SJohn.Forte@Sun.COM int err;
29357836SJohn.Forte@Sun.COM
29367836SJohn.Forte@Sun.COM if (map_dev == NULL) {
29377836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
29387836SJohn.Forte@Sun.COM }
29397836SJohn.Forte@Sun.COM
29407836SJohn.Forte@Sun.COM if ((prop_name == NULL) || (prop_data == NULL) ||
2941*11547SBill.Gumbrell@Sun.COM (prop_data_count == NULL)) {
29427836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
29437836SJohn.Forte@Sun.COM }
29447836SJohn.Forte@Sun.COM
29457836SJohn.Forte@Sun.COM impl_dev = (impl_map_dev_t *)map_dev;
29467836SJohn.Forte@Sun.COM impl_prop = impl_dev->prop_list;
29477836SJohn.Forte@Sun.COM
29487836SJohn.Forte@Sun.COM err = L_INVALID_MAP_DEV_PROP_NAME;
29497836SJohn.Forte@Sun.COM
29507836SJohn.Forte@Sun.COM while (impl_prop) {
2951*11547SBill.Gumbrell@Sun.COM if (strncmp(impl_prop->prop_name, prop_name,
2952*11547SBill.Gumbrell@Sun.COM strlen(prop_name)) == 0) {
2953*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) {
2954*11547SBill.Gumbrell@Sun.COM err = L_INVALID_MAP_DEV_PROP_TYPE;
2955*11547SBill.Gumbrell@Sun.COM break;
2956*11547SBill.Gumbrell@Sun.COM }
2957*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_data) {
2958*11547SBill.Gumbrell@Sun.COM *prop_data = (uchar_t *)(impl_prop->prop_data);
2959*11547SBill.Gumbrell@Sun.COM *prop_data_count = impl_prop->prop_size;
2960*11547SBill.Gumbrell@Sun.COM return (0);
2961*11547SBill.Gumbrell@Sun.COM } else {
2962*11547SBill.Gumbrell@Sun.COM err = impl_prop->prop_error;
2963*11547SBill.Gumbrell@Sun.COM }
2964*11547SBill.Gumbrell@Sun.COM break;
29657836SJohn.Forte@Sun.COM }
2966*11547SBill.Gumbrell@Sun.COM impl_prop = impl_prop->next;
29677836SJohn.Forte@Sun.COM }
29687836SJohn.Forte@Sun.COM
29697836SJohn.Forte@Sun.COM return (err);
29707836SJohn.Forte@Sun.COM }
29717836SJohn.Forte@Sun.COM
29727836SJohn.Forte@Sun.COM /*
29737836SJohn.Forte@Sun.COM * This function passes back int type property.
29747836SJohn.Forte@Sun.COM * map_dev input should be a handle for device.
29757836SJohn.Forte@Sun.COM *
29767836SJohn.Forte@Sun.COM * return 0 if OK.
29777836SJohn.Forte@Sun.COM * return error code otherwise.
29787836SJohn.Forte@Sun.COM */
29797836SJohn.Forte@Sun.COM int
g_dev_prop_lookup_ints(gfc_dev_t map_dev,const char * prop_name,int ** prop_data)2980*11547SBill.Gumbrell@Sun.COM g_dev_prop_lookup_ints(gfc_dev_t map_dev, const char *prop_name,
2981*11547SBill.Gumbrell@Sun.COM int **prop_data)
29827836SJohn.Forte@Sun.COM {
29837836SJohn.Forte@Sun.COM impl_map_dev_t *impl_dev;
29847836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
29857836SJohn.Forte@Sun.COM int err;
29867836SJohn.Forte@Sun.COM
29877836SJohn.Forte@Sun.COM if (map_dev == NULL) {
29887836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
29897836SJohn.Forte@Sun.COM }
29907836SJohn.Forte@Sun.COM
29917836SJohn.Forte@Sun.COM if ((prop_name == NULL) || (prop_data == NULL)) {
29927836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
29937836SJohn.Forte@Sun.COM }
29947836SJohn.Forte@Sun.COM
29957836SJohn.Forte@Sun.COM impl_dev = (impl_map_dev_t *)map_dev;
29967836SJohn.Forte@Sun.COM impl_prop = impl_dev->prop_list;
29977836SJohn.Forte@Sun.COM
29987836SJohn.Forte@Sun.COM err = L_INVALID_MAP_DEV_PROP_NAME;
29997836SJohn.Forte@Sun.COM
30007836SJohn.Forte@Sun.COM while (impl_prop) {
3001*11547SBill.Gumbrell@Sun.COM if (strncmp(impl_prop->prop_name, prop_name,
3002*11547SBill.Gumbrell@Sun.COM strlen(prop_name)) == 0) {
3003*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_INT) {
3004*11547SBill.Gumbrell@Sun.COM err = L_INVALID_MAP_DEV_PROP_TYPE;
3005*11547SBill.Gumbrell@Sun.COM break;
3006*11547SBill.Gumbrell@Sun.COM }
3007*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_data) {
3008*11547SBill.Gumbrell@Sun.COM *prop_data = (int *)(impl_prop->prop_data);
3009*11547SBill.Gumbrell@Sun.COM return (0);
3010*11547SBill.Gumbrell@Sun.COM } else {
3011*11547SBill.Gumbrell@Sun.COM err = impl_prop->prop_error;
3012*11547SBill.Gumbrell@Sun.COM }
3013*11547SBill.Gumbrell@Sun.COM break;
30147836SJohn.Forte@Sun.COM }
3015*11547SBill.Gumbrell@Sun.COM impl_prop = impl_prop->next;
30167836SJohn.Forte@Sun.COM }
30177836SJohn.Forte@Sun.COM
30187836SJohn.Forte@Sun.COM return (err);
30197836SJohn.Forte@Sun.COM }
30207836SJohn.Forte@Sun.COM
30217836SJohn.Forte@Sun.COM /*
30227836SJohn.Forte@Sun.COM * This function passes back int type property.
30237836SJohn.Forte@Sun.COM * map_dev input should be a handle for device.
30247836SJohn.Forte@Sun.COM *
30257836SJohn.Forte@Sun.COM * return 0 if OK.
30267836SJohn.Forte@Sun.COM * return error code otherwise.
30277836SJohn.Forte@Sun.COM */
30287836SJohn.Forte@Sun.COM int
g_dev_prop_lookup_strings(gfc_dev_t map_dev,const char * prop_name,char ** prop_data)3029*11547SBill.Gumbrell@Sun.COM g_dev_prop_lookup_strings(gfc_dev_t map_dev, const char *prop_name,
3030*11547SBill.Gumbrell@Sun.COM char **prop_data)
30317836SJohn.Forte@Sun.COM {
30327836SJohn.Forte@Sun.COM impl_map_dev_t *impl_dev;
30337836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
30347836SJohn.Forte@Sun.COM int err;
30357836SJohn.Forte@Sun.COM
30367836SJohn.Forte@Sun.COM if (map_dev == NULL) {
30377836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
30387836SJohn.Forte@Sun.COM }
30397836SJohn.Forte@Sun.COM
30407836SJohn.Forte@Sun.COM if ((prop_name == NULL) || (prop_data == NULL)) {
30417836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
30427836SJohn.Forte@Sun.COM }
30437836SJohn.Forte@Sun.COM
30447836SJohn.Forte@Sun.COM impl_dev = (impl_map_dev_t *)map_dev;
30457836SJohn.Forte@Sun.COM impl_prop = impl_dev->prop_list;
30467836SJohn.Forte@Sun.COM
30477836SJohn.Forte@Sun.COM err = L_INVALID_MAP_DEV_PROP_NAME;
30487836SJohn.Forte@Sun.COM
30497836SJohn.Forte@Sun.COM while (impl_prop) {
3050*11547SBill.Gumbrell@Sun.COM if (strncmp(impl_prop->prop_name, prop_name,
3051*11547SBill.Gumbrell@Sun.COM strlen(prop_name)) == 0) {
3052*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) {
3053*11547SBill.Gumbrell@Sun.COM err = L_INVALID_MAP_DEV_PROP_TYPE;
3054*11547SBill.Gumbrell@Sun.COM break;
3055*11547SBill.Gumbrell@Sun.COM }
3056*11547SBill.Gumbrell@Sun.COM if (impl_prop->prop_data) {
3057*11547SBill.Gumbrell@Sun.COM *prop_data = (char *)(impl_prop->prop_data);
3058*11547SBill.Gumbrell@Sun.COM return (0);
3059*11547SBill.Gumbrell@Sun.COM } else {
3060*11547SBill.Gumbrell@Sun.COM err = impl_prop->prop_error;
3061*11547SBill.Gumbrell@Sun.COM }
3062*11547SBill.Gumbrell@Sun.COM break;
30637836SJohn.Forte@Sun.COM }
3064*11547SBill.Gumbrell@Sun.COM impl_prop = impl_prop->next;
30657836SJohn.Forte@Sun.COM }
30667836SJohn.Forte@Sun.COM
30677836SJohn.Forte@Sun.COM return (err);
30687836SJohn.Forte@Sun.COM }
30697836SJohn.Forte@Sun.COM
30707836SJohn.Forte@Sun.COM /*
30717836SJohn.Forte@Sun.COM * This function returns the handle for the first property of the input device.
30727836SJohn.Forte@Sun.COM * map_dev input should be a handle form a device.
30737836SJohn.Forte@Sun.COM *
30747836SJohn.Forte@Sun.COM * l_err set to 0 if OK.
30757836SJohn.Forte@Sun.COM * l_err set to error code otherwise.
30767836SJohn.Forte@Sun.COM */
30777836SJohn.Forte@Sun.COM gfc_prop_t
g_get_first_dev_prop(gfc_dev_t map_dev,int * l_err)3078*11547SBill.Gumbrell@Sun.COM g_get_first_dev_prop(gfc_dev_t map_dev, int *l_err)
30797836SJohn.Forte@Sun.COM {
30807836SJohn.Forte@Sun.COM impl_map_dev_t *impl_dev;
30817836SJohn.Forte@Sun.COM
30827836SJohn.Forte@Sun.COM if (l_err == NULL) {
30837836SJohn.Forte@Sun.COM return (NULL);
30847836SJohn.Forte@Sun.COM }
30857836SJohn.Forte@Sun.COM
30867836SJohn.Forte@Sun.COM *l_err = 0;
30877836SJohn.Forte@Sun.COM
30887836SJohn.Forte@Sun.COM if (map_dev == NULL) {
30897836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_ADDR;
30907836SJohn.Forte@Sun.COM return (NULL);
30917836SJohn.Forte@Sun.COM }
30927836SJohn.Forte@Sun.COM
30937836SJohn.Forte@Sun.COM impl_dev = (impl_map_dev_t *)map_dev;
30947836SJohn.Forte@Sun.COM
30957836SJohn.Forte@Sun.COM if (impl_dev->prop_list == NULL) {
30967836SJohn.Forte@Sun.COM *l_err = L_NO_SUCH_PROP_FOUND;
30977836SJohn.Forte@Sun.COM }
30987836SJohn.Forte@Sun.COM
30997836SJohn.Forte@Sun.COM return ((gfc_prop_t)(impl_dev->prop_list));
31007836SJohn.Forte@Sun.COM }
31017836SJohn.Forte@Sun.COM
31027836SJohn.Forte@Sun.COM /*
31037836SJohn.Forte@Sun.COM * This function returns the handle for next property handle of the input prop.
31047836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
31057836SJohn.Forte@Sun.COM *
31067836SJohn.Forte@Sun.COM * l_err set to 0 if OK.
31077836SJohn.Forte@Sun.COM * l_err set to error code otherwise.
31087836SJohn.Forte@Sun.COM */
31097836SJohn.Forte@Sun.COM gfc_prop_t
g_get_next_dev_prop(gfc_prop_t map_prop,int * l_err)3110*11547SBill.Gumbrell@Sun.COM g_get_next_dev_prop(gfc_prop_t map_prop, int *l_err)
31117836SJohn.Forte@Sun.COM {
31127836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
31137836SJohn.Forte@Sun.COM
31147836SJohn.Forte@Sun.COM if (l_err == NULL) {
31157836SJohn.Forte@Sun.COM return (NULL);
31167836SJohn.Forte@Sun.COM }
31177836SJohn.Forte@Sun.COM
31187836SJohn.Forte@Sun.COM *l_err = 0;
31197836SJohn.Forte@Sun.COM
31207836SJohn.Forte@Sun.COM if (map_prop == NULL) {
31217836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_PROP;
31227836SJohn.Forte@Sun.COM return (NULL);
31237836SJohn.Forte@Sun.COM }
31247836SJohn.Forte@Sun.COM
31257836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
31267836SJohn.Forte@Sun.COM
31277836SJohn.Forte@Sun.COM if (impl_prop->next == NULL) {
31287836SJohn.Forte@Sun.COM *l_err = L_NO_SUCH_PROP_FOUND;
31297836SJohn.Forte@Sun.COM }
31307836SJohn.Forte@Sun.COM
31317836SJohn.Forte@Sun.COM return ((gfc_prop_t)(impl_prop->next));
31327836SJohn.Forte@Sun.COM }
31337836SJohn.Forte@Sun.COM
31347836SJohn.Forte@Sun.COM /*
31357836SJohn.Forte@Sun.COM * This function returns the name of the property of the input prop.
31367836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
31377836SJohn.Forte@Sun.COM *
31387836SJohn.Forte@Sun.COM * return name string if OK.
31397836SJohn.Forte@Sun.COM * returns NULL and l_err set to error code otherwise.
31407836SJohn.Forte@Sun.COM */
31417836SJohn.Forte@Sun.COM char *
g_get_dev_prop_name(gfc_prop_t map_prop,int * l_err)3142*11547SBill.Gumbrell@Sun.COM g_get_dev_prop_name(gfc_prop_t map_prop, int *l_err)
31437836SJohn.Forte@Sun.COM {
31447836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
31457836SJohn.Forte@Sun.COM
31467836SJohn.Forte@Sun.COM if (l_err == NULL) {
31477836SJohn.Forte@Sun.COM return (NULL);
31487836SJohn.Forte@Sun.COM }
31497836SJohn.Forte@Sun.COM
31507836SJohn.Forte@Sun.COM *l_err = 0;
31517836SJohn.Forte@Sun.COM
31527836SJohn.Forte@Sun.COM if (map_prop == NULL) {
31537836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_PROP;
31547836SJohn.Forte@Sun.COM return (NULL);
31557836SJohn.Forte@Sun.COM }
31567836SJohn.Forte@Sun.COM
31577836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
31587836SJohn.Forte@Sun.COM
31597836SJohn.Forte@Sun.COM return (impl_prop->prop_name);
31607836SJohn.Forte@Sun.COM }
31617836SJohn.Forte@Sun.COM
31627836SJohn.Forte@Sun.COM /*
31637836SJohn.Forte@Sun.COM * This function returns the type of the property of the input prop.
31647836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
31657836SJohn.Forte@Sun.COM *
31667836SJohn.Forte@Sun.COM * return type if OK.
31677836SJohn.Forte@Sun.COM * returns GFC_PROP_TYPE_UNKNOWN and l_err set to error code otherwise.
31687836SJohn.Forte@Sun.COM */
31697836SJohn.Forte@Sun.COM int
g_get_dev_prop_type(gfc_prop_t map_prop,int * l_err)3170*11547SBill.Gumbrell@Sun.COM g_get_dev_prop_type(gfc_prop_t map_prop, int *l_err)
31717836SJohn.Forte@Sun.COM {
31727836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
31737836SJohn.Forte@Sun.COM
31747836SJohn.Forte@Sun.COM if (l_err != NULL) {
31757836SJohn.Forte@Sun.COM *l_err = 0;
31767836SJohn.Forte@Sun.COM } else {
31777836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
31787836SJohn.Forte@Sun.COM }
31797836SJohn.Forte@Sun.COM
31807836SJohn.Forte@Sun.COM if (map_prop == NULL) {
31817836SJohn.Forte@Sun.COM *l_err = L_INVALID_MAP_DEV_PROP;
31827836SJohn.Forte@Sun.COM return (GFC_PROP_TYPE_UNKNOWN);
31837836SJohn.Forte@Sun.COM }
31847836SJohn.Forte@Sun.COM
31857836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
31867836SJohn.Forte@Sun.COM
31877836SJohn.Forte@Sun.COM return (impl_prop->prop_type);
31887836SJohn.Forte@Sun.COM }
31897836SJohn.Forte@Sun.COM
31907836SJohn.Forte@Sun.COM /*
31917836SJohn.Forte@Sun.COM * This function passes back uchar_t type property and its count.
31927836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
31937836SJohn.Forte@Sun.COM *
31947836SJohn.Forte@Sun.COM * return 0 if OK.
31957836SJohn.Forte@Sun.COM * return error code otherwise.
31967836SJohn.Forte@Sun.COM */
31977836SJohn.Forte@Sun.COM int
g_get_dev_prop_bytes(gfc_prop_t map_prop,int * prop_data_count,uchar_t ** prop_data)3198*11547SBill.Gumbrell@Sun.COM g_get_dev_prop_bytes(gfc_prop_t map_prop, int *prop_data_count,
3199*11547SBill.Gumbrell@Sun.COM uchar_t **prop_data)
32007836SJohn.Forte@Sun.COM {
32017836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
32027836SJohn.Forte@Sun.COM
32037836SJohn.Forte@Sun.COM if (map_prop == NULL) {
32047836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
32057836SJohn.Forte@Sun.COM }
32067836SJohn.Forte@Sun.COM
32077836SJohn.Forte@Sun.COM if ((prop_data == NULL) || (prop_data_count == NULL)) {
32087836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
32097836SJohn.Forte@Sun.COM }
32107836SJohn.Forte@Sun.COM
32117836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
32127836SJohn.Forte@Sun.COM
32137836SJohn.Forte@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) {
3214*11547SBill.Gumbrell@Sun.COM return (L_INVALID_MAP_DEV_PROP_TYPE);
32157836SJohn.Forte@Sun.COM }
32167836SJohn.Forte@Sun.COM if (impl_prop->prop_data) {
3217*11547SBill.Gumbrell@Sun.COM *prop_data = (uchar_t *)(impl_prop->prop_data);
3218*11547SBill.Gumbrell@Sun.COM *prop_data_count = impl_prop->prop_size;
32197836SJohn.Forte@Sun.COM } else {
3220*11547SBill.Gumbrell@Sun.COM return (impl_prop->prop_error);
32217836SJohn.Forte@Sun.COM }
32227836SJohn.Forte@Sun.COM
32237836SJohn.Forte@Sun.COM return (0);
32247836SJohn.Forte@Sun.COM }
32257836SJohn.Forte@Sun.COM
32267836SJohn.Forte@Sun.COM /*
32277836SJohn.Forte@Sun.COM * This function passes back int type property.
32287836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
32297836SJohn.Forte@Sun.COM *
32307836SJohn.Forte@Sun.COM * return 0 if OK.
32317836SJohn.Forte@Sun.COM * return error code otherwise.
32327836SJohn.Forte@Sun.COM */
32337836SJohn.Forte@Sun.COM int
g_get_dev_prop_ints(gfc_prop_t map_prop,int ** prop_data)3234*11547SBill.Gumbrell@Sun.COM g_get_dev_prop_ints(gfc_prop_t map_prop, int **prop_data)
32357836SJohn.Forte@Sun.COM {
32367836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
32377836SJohn.Forte@Sun.COM
32387836SJohn.Forte@Sun.COM if (map_prop == NULL) {
32397836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
32407836SJohn.Forte@Sun.COM }
32417836SJohn.Forte@Sun.COM
32427836SJohn.Forte@Sun.COM if (prop_data == NULL) {
32437836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
32447836SJohn.Forte@Sun.COM }
32457836SJohn.Forte@Sun.COM
32467836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
32477836SJohn.Forte@Sun.COM
32487836SJohn.Forte@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_INT) {
3249*11547SBill.Gumbrell@Sun.COM return (L_INVALID_MAP_DEV_PROP_TYPE);
32507836SJohn.Forte@Sun.COM }
32517836SJohn.Forte@Sun.COM if (impl_prop->prop_data) {
3252*11547SBill.Gumbrell@Sun.COM *prop_data = (int *)(impl_prop->prop_data);
32537836SJohn.Forte@Sun.COM } else {
3254*11547SBill.Gumbrell@Sun.COM return (impl_prop->prop_error);
32557836SJohn.Forte@Sun.COM }
32567836SJohn.Forte@Sun.COM
32577836SJohn.Forte@Sun.COM return (0);
32587836SJohn.Forte@Sun.COM }
32597836SJohn.Forte@Sun.COM
32607836SJohn.Forte@Sun.COM /*
32617836SJohn.Forte@Sun.COM * This function passes back string type property.
32627836SJohn.Forte@Sun.COM * map_prop input should be a handle for property.
32637836SJohn.Forte@Sun.COM *
32647836SJohn.Forte@Sun.COM * return 0 if OK.
32657836SJohn.Forte@Sun.COM * return error code otherwise.
32667836SJohn.Forte@Sun.COM */
32677836SJohn.Forte@Sun.COM int
g_get_dev_prop_strings(gfc_prop_t map_prop,char ** prop_data)3268*11547SBill.Gumbrell@Sun.COM g_get_dev_prop_strings(gfc_prop_t map_prop, char **prop_data)
32697836SJohn.Forte@Sun.COM {
32707836SJohn.Forte@Sun.COM impl_map_dev_prop_t *impl_prop;
32717836SJohn.Forte@Sun.COM
32727836SJohn.Forte@Sun.COM if (map_prop == NULL) {
32737836SJohn.Forte@Sun.COM return (L_INVALID_MAP_DEV_ADDR);
32747836SJohn.Forte@Sun.COM }
32757836SJohn.Forte@Sun.COM
32767836SJohn.Forte@Sun.COM if (prop_data == NULL) {
32777836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
32787836SJohn.Forte@Sun.COM }
32797836SJohn.Forte@Sun.COM
32807836SJohn.Forte@Sun.COM impl_prop = (impl_map_dev_prop_t *)map_prop;
32817836SJohn.Forte@Sun.COM
32827836SJohn.Forte@Sun.COM if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) {
3283*11547SBill.Gumbrell@Sun.COM return (L_INVALID_MAP_DEV_PROP_TYPE);
32847836SJohn.Forte@Sun.COM }
32857836SJohn.Forte@Sun.COM if (impl_prop->prop_data) {
3286*11547SBill.Gumbrell@Sun.COM *prop_data = (char *)(impl_prop->prop_data);
32877836SJohn.Forte@Sun.COM } else {
3288*11547SBill.Gumbrell@Sun.COM return (impl_prop->prop_error);
32897836SJohn.Forte@Sun.COM }
32907836SJohn.Forte@Sun.COM
32917836SJohn.Forte@Sun.COM return (0);
32927836SJohn.Forte@Sun.COM }
32937836SJohn.Forte@Sun.COM
32947836SJohn.Forte@Sun.COM /*
32957836SJohn.Forte@Sun.COM * Free the linked list allocated by g_rdls()
32967836SJohn.Forte@Sun.COM */
32977836SJohn.Forte@Sun.COM static void
g_free_rls(AL_rls * rlsptr)32987836SJohn.Forte@Sun.COM g_free_rls(AL_rls *rlsptr)
32997836SJohn.Forte@Sun.COM {
33007836SJohn.Forte@Sun.COM AL_rls *trlsptr;
33017836SJohn.Forte@Sun.COM
33027836SJohn.Forte@Sun.COM while (rlsptr != NULL) {
33037836SJohn.Forte@Sun.COM trlsptr = rlsptr->next;
33047836SJohn.Forte@Sun.COM free(rlsptr);
33057836SJohn.Forte@Sun.COM rlsptr = trlsptr;
33067836SJohn.Forte@Sun.COM }
33077836SJohn.Forte@Sun.COM }
33087836SJohn.Forte@Sun.COM
33097836SJohn.Forte@Sun.COM /*
33107836SJohn.Forte@Sun.COM * Read the extended link error status block
33117836SJohn.Forte@Sun.COM * from the specified device and Host Adapter.
33127836SJohn.Forte@Sun.COM *
33137836SJohn.Forte@Sun.COM * PARAMS:
33147836SJohn.Forte@Sun.COM * path_phys - physical path to an FC device
33157836SJohn.Forte@Sun.COM * rls_ptr - pointer to read link state structure
33167836SJohn.Forte@Sun.COM *
33177836SJohn.Forte@Sun.COM * RETURNS:
33187836SJohn.Forte@Sun.COM * 0 : if OK
33197836SJohn.Forte@Sun.COM * non-zero: otherwise
33207836SJohn.Forte@Sun.COM */
33217836SJohn.Forte@Sun.COM int
g_rdls(char * path_phys,struct al_rls ** rls_ptr,int verbose)33227836SJohn.Forte@Sun.COM g_rdls(char *path_phys, struct al_rls **rls_ptr, int verbose)
33237836SJohn.Forte@Sun.COM {
3324*11547SBill.Gumbrell@Sun.COM char nexus_path[MAXPATHLEN], *nexus_path_ptr;
3325*11547SBill.Gumbrell@Sun.COM int fd, fp_fd, err, length, exp_map_flag = 0, *port_addr;
3326*11547SBill.Gumbrell@Sun.COM struct lilpmap map;
3327*11547SBill.Gumbrell@Sun.COM AL_rls *rls, *c1 = NULL, *c2 = NULL;
3328*11547SBill.Gumbrell@Sun.COM uchar_t i, *port_wwn_byte;
3329*11547SBill.Gumbrell@Sun.COM la_wwn_t port_wwn;
3330*11547SBill.Gumbrell@Sun.COM sf_al_map_t exp_map;
3331*11547SBill.Gumbrell@Sun.COM char *charPtr, fp_path[MAXPATHLEN];
3332*11547SBill.Gumbrell@Sun.COM uint_t dev_type;
3333*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
3334*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
3335*11547SBill.Gumbrell@Sun.COM fc_portid_t rls_req;
3336*11547SBill.Gumbrell@Sun.COM fc_rls_acc_t rls_payload;
3337*11547SBill.Gumbrell@Sun.COM gfc_dev_t map_root, map_dev;
3338*11547SBill.Gumbrell@Sun.COM uint32_t hba_port_top, state;
3339*11547SBill.Gumbrell@Sun.COM int pathcnt = 1, count;
3340*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
3341*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0;
33427836SJohn.Forte@Sun.COM
33437836SJohn.Forte@Sun.COM /* return invalid path if path_phys is NULL */
33447836SJohn.Forte@Sun.COM if (path_phys == NULL) {
33457836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
33467836SJohn.Forte@Sun.COM }
33477836SJohn.Forte@Sun.COM /* return invalid arg if rls_ptr is NULL */
33487836SJohn.Forte@Sun.COM if (rls_ptr == NULL) {
33497836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
33507836SJohn.Forte@Sun.COM }
33517836SJohn.Forte@Sun.COM
33527836SJohn.Forte@Sun.COM *rls_ptr = rls = NULL;
33537836SJohn.Forte@Sun.COM
33547836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI) != NULL) {
33557836SJohn.Forte@Sun.COM (void) strcpy(fp_path, path_phys);
33567836SJohn.Forte@Sun.COM if (g_get_pathlist(fp_path, &pathlist)) {
33577836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
33587836SJohn.Forte@Sun.COM }
33597836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
33607836SJohn.Forte@Sun.COM p_on = p_st = 0;
33617836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
33627836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
33637836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
3364*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
33657836SJohn.Forte@Sun.COM p_on = i;
33667836SJohn.Forte@Sun.COM break;
33677836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
3368*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
33697836SJohn.Forte@Sun.COM p_st = i;
33707836SJohn.Forte@Sun.COM }
33717836SJohn.Forte@Sun.COM }
33727836SJohn.Forte@Sun.COM }
33737836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
33747836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
33757836SJohn.Forte@Sun.COM /* on_line path */
33767836SJohn.Forte@Sun.COM (void) strcpy(fp_path,
3377*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
33787836SJohn.Forte@Sun.COM } else {
33797836SJohn.Forte@Sun.COM /* standby or path0 */
33807836SJohn.Forte@Sun.COM (void) strcpy(fp_path,
3381*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
33827836SJohn.Forte@Sun.COM }
33837836SJohn.Forte@Sun.COM free(pathlist.path_info);
33847836SJohn.Forte@Sun.COM } else {
33857836SJohn.Forte@Sun.COM (void) strcpy(fp_path, path_phys);
33867836SJohn.Forte@Sun.COM }
33877836SJohn.Forte@Sun.COM
33887836SJohn.Forte@Sun.COM /* Get map of devices on this loop. */
33897836SJohn.Forte@Sun.COM if ((dev_type = g_get_path_type(fp_path)) == 0) {
33907836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
33917836SJohn.Forte@Sun.COM }
33927836SJohn.Forte@Sun.COM if (dev_type & FC_FCA_MASK) {
33937836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI) != NULL) {
33947836SJohn.Forte@Sun.COM (void) strcat(fp_path, FC_CTLR);
33957836SJohn.Forte@Sun.COM } else if (strstr(fp_path, DRV_NAME_SSD) ||
33967836SJohn.Forte@Sun.COM strstr(fp_path, DRV_NAME_ST) ||
3397*11547SBill.Gumbrell@Sun.COM strstr(fp_path, SES_NAME)) {
33987836SJohn.Forte@Sun.COM if ((charPtr = strrchr(fp_path, '/')) == NULL) {
33997836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
34007836SJohn.Forte@Sun.COM }
34017836SJohn.Forte@Sun.COM *charPtr = '\0';
34027836SJohn.Forte@Sun.COM /* append devctl to the path */
34037836SJohn.Forte@Sun.COM (void) strcat(fp_path, FC_CTLR);
34047836SJohn.Forte@Sun.COM } else {
34057836SJohn.Forte@Sun.COM if (stat(fp_path, &stbuf) < 0) {
34067836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
34077836SJohn.Forte@Sun.COM }
34087836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
34097836SJohn.Forte@Sun.COM /* append devctl to the path */
34107836SJohn.Forte@Sun.COM (void) strcat(fp_path, FC_CTLR);
34117836SJohn.Forte@Sun.COM }
34127836SJohn.Forte@Sun.COM }
34137836SJohn.Forte@Sun.COM
34147836SJohn.Forte@Sun.COM if ((map_root = g_dev_map_init(fp_path, &err,
3415*11547SBill.Gumbrell@Sun.COM MAP_XPORT_PROP_ONLY)) == NULL) {
34167836SJohn.Forte@Sun.COM return (err);
34177836SJohn.Forte@Sun.COM }
34187836SJohn.Forte@Sun.COM
34197836SJohn.Forte@Sun.COM } else { /* FC4_FCA_MASK type path */
3420*11547SBill.Gumbrell@Sun.COM (void) memset(&map, 0, sizeof (struct lilpmap));
3421*11547SBill.Gumbrell@Sun.COM
3422*11547SBill.Gumbrell@Sun.COM if ((err = g_get_nexus_path(path_phys,
34237836SJohn.Forte@Sun.COM &nexus_path_ptr)) != 0) {
3424*11547SBill.Gumbrell@Sun.COM return (err);
3425*11547SBill.Gumbrell@Sun.COM }
3426*11547SBill.Gumbrell@Sun.COM (void) strcpy(nexus_path, nexus_path_ptr);
3427*11547SBill.Gumbrell@Sun.COM g_destroy_data(nexus_path_ptr);
34287836SJohn.Forte@Sun.COM
34297836SJohn.Forte@Sun.COM /* open driver */
3430*11547SBill.Gumbrell@Sun.COM if ((fd = g_object_open(nexus_path,
3431*11547SBill.Gumbrell@Sun.COM O_NDELAY | O_RDONLY)) == -1)
3432*11547SBill.Gumbrell@Sun.COM return (errno);
34337836SJohn.Forte@Sun.COM
34347836SJohn.Forte@Sun.COM /*
34357836SJohn.Forte@Sun.COM * First try using the socal version of the map.
34367836SJohn.Forte@Sun.COM * If that fails get the expanded vesion.
34377836SJohn.Forte@Sun.COM */
3438*11547SBill.Gumbrell@Sun.COM if (ioctl(fd, FCIO_GETMAP, &map) != 0) {
3439*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_GETMAP ioctl failed.\n");
3440*11547SBill.Gumbrell@Sun.COM if (ioctl(fd, SFIOCGMAP, &exp_map) != 0) {
3441*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
3442*11547SBill.Gumbrell@Sun.COM (void) close(fd);
3443*11547SBill.Gumbrell@Sun.COM return (L_SFIOCGMAP_IOCTL_FAIL);
3444*11547SBill.Gumbrell@Sun.COM }
3445*11547SBill.Gumbrell@Sun.COM /* Check for reasonableness. */
3446*11547SBill.Gumbrell@Sun.COM if ((exp_map.sf_count > 126) ||
3447*11547SBill.Gumbrell@Sun.COM (exp_map.sf_count < 0)) {
34487836SJohn.Forte@Sun.COM (void) close(fd);
34497836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
34507836SJohn.Forte@Sun.COM }
3451*11547SBill.Gumbrell@Sun.COM for (i = 0; i < exp_map.sf_count; i++) {
3452*11547SBill.Gumbrell@Sun.COM if (exp_map.sf_addr_pair[i].sf_al_pa > 0xef) {
3453*11547SBill.Gumbrell@Sun.COM (void) close(fd);
3454*11547SBill.Gumbrell@Sun.COM return (L_INVALID_LOOP_MAP);
3455*11547SBill.Gumbrell@Sun.COM }
3456*11547SBill.Gumbrell@Sun.COM }
3457*11547SBill.Gumbrell@Sun.COM length = exp_map.sf_count;
3458*11547SBill.Gumbrell@Sun.COM exp_map_flag++;
34597836SJohn.Forte@Sun.COM } else {
3460*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" g_rdls:"
3461*11547SBill.Gumbrell@Sun.COM " FCIO_GETMAP ioctl returned %d entries.\n",
3462*11547SBill.Gumbrell@Sun.COM map.lilp_length);
3463*11547SBill.Gumbrell@Sun.COM /* Check for reasonableness. */
3464*11547SBill.Gumbrell@Sun.COM if (map.lilp_length > sizeof (map.lilp_list)) {
3465*11547SBill.Gumbrell@Sun.COM (void) close(fd);
3466*11547SBill.Gumbrell@Sun.COM return (L_FCIOGETMAP_INVLD_LEN);
3467*11547SBill.Gumbrell@Sun.COM }
3468*11547SBill.Gumbrell@Sun.COM length = map.lilp_length;
34697836SJohn.Forte@Sun.COM }
3470*11547SBill.Gumbrell@Sun.COM for (i = 0; i < length; i++) {
3471*11547SBill.Gumbrell@Sun.COM if ((c2 = (struct al_rls *)
3472*11547SBill.Gumbrell@Sun.COM g_zalloc(sizeof (struct al_rls))) == NULL) {
3473*11547SBill.Gumbrell@Sun.COM close(fd);
3474*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
3475*11547SBill.Gumbrell@Sun.COM }
3476*11547SBill.Gumbrell@Sun.COM if (rls == NULL) {
3477*11547SBill.Gumbrell@Sun.COM c1 = rls = c2;
3478*11547SBill.Gumbrell@Sun.COM } else {
3479*11547SBill.Gumbrell@Sun.COM for (c1 = rls; c1->next; c1 = c1->next) {};
3480*11547SBill.Gumbrell@Sun.COM c1 = c1->next = c2;
3481*11547SBill.Gumbrell@Sun.COM }
3482*11547SBill.Gumbrell@Sun.COM (void) strcpy(c1->driver_path, nexus_path);
3483*11547SBill.Gumbrell@Sun.COM if (exp_map_flag) {
3484*11547SBill.Gumbrell@Sun.COM c1->payload.rls_portno = c1->al_ha =
3485*11547SBill.Gumbrell@Sun.COM exp_map.sf_addr_pair[i].sf_al_pa;
34867836SJohn.Forte@Sun.COM } else {
3487*11547SBill.Gumbrell@Sun.COM c1->payload.rls_portno = c1->al_ha =
3488*11547SBill.Gumbrell@Sun.COM map.lilp_list[i];
34897836SJohn.Forte@Sun.COM }
3490*11547SBill.Gumbrell@Sun.COM c1->payload.rls_linkfail =
3491*11547SBill.Gumbrell@Sun.COM (uint_t)0xff000000; /* get LESB for this port */
3492*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" g_rdls:"
3493*11547SBill.Gumbrell@Sun.COM " al_pa 0x%x\n", c1->payload.rls_portno);
3494*11547SBill.Gumbrell@Sun.COM
3495*11547SBill.Gumbrell@Sun.COM if (ioctl(fd, FCIO_LINKSTATUS, &c1->payload) != 0) {
3496*11547SBill.Gumbrell@Sun.COM /*
3497*11547SBill.Gumbrell@Sun.COM * The ifp driver will return ENXIO when rls
3498*11547SBill.Gumbrell@Sun.COM * is issued for same initiator on loop when
3499*11547SBill.Gumbrell@Sun.COM * there is more than one on the loop.
3500*11547SBill.Gumbrell@Sun.COM * Rather than completely fail, continue on.
3501*11547SBill.Gumbrell@Sun.COM * Set values in the payload struct to -1 as
3502*11547SBill.Gumbrell@Sun.COM * this is what socal is currently doing for
3503*11547SBill.Gumbrell@Sun.COM * the case of same initiator rls.
3504*11547SBill.Gumbrell@Sun.COM */
3505*11547SBill.Gumbrell@Sun.COM if ((dev_type & FC4_PCI_FCA) &&
3506*11547SBill.Gumbrell@Sun.COM (errno == ENXIO)) {
3507*11547SBill.Gumbrell@Sun.COM c1->payload.rls_linkfail =
3508*11547SBill.Gumbrell@Sun.COM c1->payload.rls_syncfail =
3509*11547SBill.Gumbrell@Sun.COM c1->payload.rls_sigfail =
3510*11547SBill.Gumbrell@Sun.COM c1->payload.rls_primitiverr =
3511*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidword =
3512*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidcrc =
3513*11547SBill.Gumbrell@Sun.COM (uint_t)0xffffffff;
3514*11547SBill.Gumbrell@Sun.COM } else {
3515*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" FCIO_LINKSTATUS ioctl"
3516*11547SBill.Gumbrell@Sun.COM " failed with errno %d.\n", errno);
3517*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3518*11547SBill.Gumbrell@Sun.COM (void) close(fd);
3519*11547SBill.Gumbrell@Sun.COM return (L_FCIO_LINKSTATUS_FAILED);
3520*11547SBill.Gumbrell@Sun.COM }
3521*11547SBill.Gumbrell@Sun.COM }
3522*11547SBill.Gumbrell@Sun.COM I_DPRINTF(" g_rdls: al_pa returned by ioctl 0x%x\n",
3523*11547SBill.Gumbrell@Sun.COM c1->payload.rls_portno);
35247836SJohn.Forte@Sun.COM }
3525*11547SBill.Gumbrell@Sun.COM *rls_ptr = rls; /* Pass back pointer */
3526*11547SBill.Gumbrell@Sun.COM
3527*11547SBill.Gumbrell@Sun.COM (void) close(fd);
3528*11547SBill.Gumbrell@Sun.COM return (0);
35297836SJohn.Forte@Sun.COM }
35307836SJohn.Forte@Sun.COM
35317836SJohn.Forte@Sun.COM /* Now we need to take care of FC_FCA_MASK case. */
35327836SJohn.Forte@Sun.COM /* we have map created already via g_dev_map_init. */
35337836SJohn.Forte@Sun.COM if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) {
35347836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
35357836SJohn.Forte@Sun.COM return (err);
35367836SJohn.Forte@Sun.COM }
35377836SJohn.Forte@Sun.COM
35387836SJohn.Forte@Sun.COM if ((map_dev = g_get_first_dev(map_root, &err)) == NULL) {
35397836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
35407836SJohn.Forte@Sun.COM if (err != L_NO_SUCH_DEV_FOUND) {
35417836SJohn.Forte@Sun.COM return (err);
35427836SJohn.Forte@Sun.COM } else {
35437836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
35447836SJohn.Forte@Sun.COM }
35457836SJohn.Forte@Sun.COM }
35467836SJohn.Forte@Sun.COM
35477836SJohn.Forte@Sun.COM while (map_dev) {
3548*11547SBill.Gumbrell@Sun.COM if ((err = g_dev_prop_lookup_ints(
3549*11547SBill.Gumbrell@Sun.COM map_dev, PORT_ADDR_PROP, &port_addr)) != 0) {
3550*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(map_root);
3551*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3552*11547SBill.Gumbrell@Sun.COM return (err);
3553*11547SBill.Gumbrell@Sun.COM }
3554*11547SBill.Gumbrell@Sun.COM
3555*11547SBill.Gumbrell@Sun.COM if ((c2 = (struct al_rls *)
3556*11547SBill.Gumbrell@Sun.COM g_zalloc(sizeof (struct al_rls))) == NULL) {
3557*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(map_root);
3558*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3559*11547SBill.Gumbrell@Sun.COM close(fd);
3560*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
3561*11547SBill.Gumbrell@Sun.COM }
3562*11547SBill.Gumbrell@Sun.COM if (rls == NULL) {
3563*11547SBill.Gumbrell@Sun.COM c1 = rls = c2;
3564*11547SBill.Gumbrell@Sun.COM } else {
3565*11547SBill.Gumbrell@Sun.COM for (c1 = rls; c1->next; c1 = c1->next) {};
3566*11547SBill.Gumbrell@Sun.COM c1 = c1->next = c2;
3567*11547SBill.Gumbrell@Sun.COM }
3568*11547SBill.Gumbrell@Sun.COM /* Set the al_ha here */
3569*11547SBill.Gumbrell@Sun.COM c1->al_ha = rls_req.port_id = *port_addr;
35707836SJohn.Forte@Sun.COM
35717836SJohn.Forte@Sun.COM /*
35727836SJohn.Forte@Sun.COM * fp uses different input/output structures for
35737836SJohn.Forte@Sun.COM * rls. Load the values returned for the fp ioctl
35747836SJohn.Forte@Sun.COM * into the structure passed back to the caller
35757836SJohn.Forte@Sun.COM * Note: There is no reason for the path
35767836SJohn.Forte@Sun.COM * to be loaded into AL_rls as is done for socal/ifp
35777836SJohn.Forte@Sun.COM * above.
35787836SJohn.Forte@Sun.COM */
3579*11547SBill.Gumbrell@Sun.COM if ((hba_port_top == FC_TOP_FABRIC) ||
3580*11547SBill.Gumbrell@Sun.COM (hba_port_top == FC_TOP_PUBLIC_LOOP)) {
3581*11547SBill.Gumbrell@Sun.COM if ((err = g_dev_prop_lookup_bytes(
3582*11547SBill.Gumbrell@Sun.COM map_dev, PORT_WWN_PROP, &count,
3583*11547SBill.Gumbrell@Sun.COM &port_wwn_byte)) != 0) {
3584*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(map_root);
3585*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3586*11547SBill.Gumbrell@Sun.COM return (err);
3587*11547SBill.Gumbrell@Sun.COM }
3588*11547SBill.Gumbrell@Sun.COM memcpy(port_wwn.raw_wwn, port_wwn_byte, FC_WWN_SIZE);
3589*11547SBill.Gumbrell@Sun.COM if ((err = g_get_dev_port_state(
3590*11547SBill.Gumbrell@Sun.COM fp_path, port_wwn, &state)) == 0) {
3591*11547SBill.Gumbrell@Sun.COM if (state != PORT_DEVICE_LOGGED_IN) {
3592*11547SBill.Gumbrell@Sun.COM if ((err = g_dev_login(fp_path,
3593*11547SBill.Gumbrell@Sun.COM port_wwn)) != 0) {
3594*11547SBill.Gumbrell@Sun.COM
3595*11547SBill.Gumbrell@Sun.COM c1->payload.rls_linkfail =
3596*11547SBill.Gumbrell@Sun.COM c1->payload.rls_syncfail =
3597*11547SBill.Gumbrell@Sun.COM c1->payload.rls_sigfail =
3598*11547SBill.Gumbrell@Sun.COM c1->payload.rls_primitiverr =
3599*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidword =
3600*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidcrc =
3601*11547SBill.Gumbrell@Sun.COM (uint_t)0xffffffff;
3602*11547SBill.Gumbrell@Sun.COM if (((map_dev =
3603*11547SBill.Gumbrell@Sun.COM g_get_next_dev(map_dev,
3604*11547SBill.Gumbrell@Sun.COM &err))
3605*11547SBill.Gumbrell@Sun.COM == NULL) &&
3606*11547SBill.Gumbrell@Sun.COM (err !=
3607*11547SBill.Gumbrell@Sun.COM L_NO_SUCH_DEV_FOUND)) {
3608*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(
3609*11547SBill.Gumbrell@Sun.COM map_root);
3610*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3611*11547SBill.Gumbrell@Sun.COM return (err);
3612*11547SBill.Gumbrell@Sun.COM }
3613*11547SBill.Gumbrell@Sun.COM continue;
3614*11547SBill.Gumbrell@Sun.COM }
3615*11547SBill.Gumbrell@Sun.COM }
3616*11547SBill.Gumbrell@Sun.COM } /* if g_get_dev_port_state fails proceed. */
3617*11547SBill.Gumbrell@Sun.COM }
3618*11547SBill.Gumbrell@Sun.COM
3619*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
3620*11547SBill.Gumbrell@Sun.COM if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) {
3621*11547SBill.Gumbrell@Sun.COM g_dev_map_fini(map_root);
3622*11547SBill.Gumbrell@Sun.COM g_free_rls(rls);
3623*11547SBill.Gumbrell@Sun.COM return (L_OPEN_PATH_FAIL);
3624*11547SBill.Gumbrell@Sun.COM }
3625*11547SBill.Gumbrell@Sun.COM fcio.fcio_cmd = FCIO_LINK_STATUS;
3626*11547SBill.Gumbrell@Sun.COM fcio.fcio_ibuf = (caddr_t)&rls_req;
3627*11547SBill.Gumbrell@Sun.COM fcio.fcio_ilen = sizeof (rls_req);
3628*11547SBill.Gumbrell@Sun.COM fcio.fcio_xfer = FCIO_XFER_RW;
3629*11547SBill.Gumbrell@Sun.COM fcio.fcio_flags = 0;
3630*11547SBill.Gumbrell@Sun.COM fcio.fcio_obuf = (caddr_t)&rls_payload;
3631*11547SBill.Gumbrell@Sun.COM fcio.fcio_olen = sizeof (rls_payload);
3632*11547SBill.Gumbrell@Sun.COM if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) {
3633*11547SBill.Gumbrell@Sun.COM c1->payload.rls_linkfail =
3634*11547SBill.Gumbrell@Sun.COM c1->payload.rls_syncfail =
3635*11547SBill.Gumbrell@Sun.COM c1->payload.rls_sigfail =
3636*11547SBill.Gumbrell@Sun.COM c1->payload.rls_primitiverr =
3637*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidword =
3638*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidcrc = (uint_t)0xffffffff;
3639*11547SBill.Gumbrell@Sun.COM } else {
3640*11547SBill.Gumbrell@Sun.COM /*
3641*11547SBill.Gumbrell@Sun.COM * Load the values into the struct passed
3642*11547SBill.Gumbrell@Sun.COM * back to the caller
3643*11547SBill.Gumbrell@Sun.COM */
3644*11547SBill.Gumbrell@Sun.COM c1->payload.rls_linkfail = rls_payload.rls_link_fail;
3645*11547SBill.Gumbrell@Sun.COM c1->payload.rls_syncfail = rls_payload.rls_sync_loss;
3646*11547SBill.Gumbrell@Sun.COM c1->payload.rls_sigfail = rls_payload.rls_sig_loss;
3647*11547SBill.Gumbrell@Sun.COM c1->payload.rls_primitiverr =
3648*11547SBill.Gumbrell@Sun.COM rls_payload.rls_prim_seq_err;
3649*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidword =
3650*11547SBill.Gumbrell@Sun.COM rls_payload.rls_invalid_word;
3651*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidcrc =
3652*11547SBill.Gumbrell@Sun.COM rls_payload.rls_invalid_crc;
3653*11547SBill.Gumbrell@Sun.COM }
3654*11547SBill.Gumbrell@Sun.COM (void) close(fp_fd);
3655*11547SBill.Gumbrell@Sun.COM
3656*11547SBill.Gumbrell@Sun.COM if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) &&
3657*11547SBill.Gumbrell@Sun.COM (err != L_NO_SUCH_DEV_FOUND)) {
36587836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
36597836SJohn.Forte@Sun.COM g_free_rls(rls);
36607836SJohn.Forte@Sun.COM return (err);
36617836SJohn.Forte@Sun.COM }
36627836SJohn.Forte@Sun.COM }
36637836SJohn.Forte@Sun.COM
36647836SJohn.Forte@Sun.COM /* for Leadville issue a final call for the initiator */
36657836SJohn.Forte@Sun.COM
36667836SJohn.Forte@Sun.COM if ((err = g_dev_prop_lookup_ints(
3667*11547SBill.Gumbrell@Sun.COM map_root, PORT_ADDR_PROP, &port_addr)) != 0) {
36687836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
36697836SJohn.Forte@Sun.COM g_free_rls(rls);
36707836SJohn.Forte@Sun.COM return (err);
36717836SJohn.Forte@Sun.COM }
36727836SJohn.Forte@Sun.COM
36737836SJohn.Forte@Sun.COM if ((c2 = (struct al_rls *)
36747836SJohn.Forte@Sun.COM g_zalloc(sizeof (struct al_rls))) == NULL) {
36757836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
36767836SJohn.Forte@Sun.COM g_free_rls(rls);
36777836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
36787836SJohn.Forte@Sun.COM }
36797836SJohn.Forte@Sun.COM if (rls == NULL) {
36807836SJohn.Forte@Sun.COM c1 = rls = c2;
36817836SJohn.Forte@Sun.COM } else {
36827836SJohn.Forte@Sun.COM for (c1 = rls; c1->next; c1 = c1->next) {};
36837836SJohn.Forte@Sun.COM c1 = c1->next = c2;
36847836SJohn.Forte@Sun.COM }
36857836SJohn.Forte@Sun.COM
36867836SJohn.Forte@Sun.COM c1->al_ha = rls_req.port_id = *port_addr;
36877836SJohn.Forte@Sun.COM
36887836SJohn.Forte@Sun.COM if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) {
36897836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
36907836SJohn.Forte@Sun.COM g_free_rls(rls);
36917836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
36927836SJohn.Forte@Sun.COM }
36937836SJohn.Forte@Sun.COM
36947836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_LINK_STATUS;
36957836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&rls_req;
36967836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (rls_req);
36977836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_RW;
36987836SJohn.Forte@Sun.COM fcio.fcio_flags = 0;
36997836SJohn.Forte@Sun.COM fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
37007836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&rls_payload;
37017836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (rls_payload);
37027836SJohn.Forte@Sun.COM
37037836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) {
37047836SJohn.Forte@Sun.COM c1->payload.rls_linkfail =
3705*11547SBill.Gumbrell@Sun.COM c1->payload.rls_syncfail =
3706*11547SBill.Gumbrell@Sun.COM c1->payload.rls_sigfail =
3707*11547SBill.Gumbrell@Sun.COM c1->payload.rls_primitiverr =
3708*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidword =
3709*11547SBill.Gumbrell@Sun.COM c1->payload.rls_invalidcrc = (uint_t)0xffffffff;
37107836SJohn.Forte@Sun.COM } else {
37117836SJohn.Forte@Sun.COM /*
37127836SJohn.Forte@Sun.COM * Load the values into the struct passed
37137836SJohn.Forte@Sun.COM * back to the caller
37147836SJohn.Forte@Sun.COM */
37157836SJohn.Forte@Sun.COM c1->payload.rls_linkfail = rls_payload.rls_link_fail;
37167836SJohn.Forte@Sun.COM c1->payload.rls_syncfail = rls_payload.rls_sync_loss;
37177836SJohn.Forte@Sun.COM c1->payload.rls_sigfail = rls_payload.rls_sig_loss;
37187836SJohn.Forte@Sun.COM c1->payload.rls_primitiverr = rls_payload.rls_prim_seq_err;
37197836SJohn.Forte@Sun.COM c1->payload.rls_invalidword = rls_payload.rls_invalid_word;
37207836SJohn.Forte@Sun.COM c1->payload.rls_invalidcrc = rls_payload.rls_invalid_crc;
37217836SJohn.Forte@Sun.COM (void) close(fp_fd);
37227836SJohn.Forte@Sun.COM }
37237836SJohn.Forte@Sun.COM (void) close(fp_fd);
37247836SJohn.Forte@Sun.COM
37257836SJohn.Forte@Sun.COM *rls_ptr = rls; /* Pass back pointer */
37267836SJohn.Forte@Sun.COM
37277836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
37287836SJohn.Forte@Sun.COM return (0);
37297836SJohn.Forte@Sun.COM }
37307836SJohn.Forte@Sun.COM
wwnConversion(uchar_t * wwn)37317836SJohn.Forte@Sun.COM static u_longlong_t wwnConversion(uchar_t *wwn)
37327836SJohn.Forte@Sun.COM {
37337836SJohn.Forte@Sun.COM u_longlong_t tmp;
37347836SJohn.Forte@Sun.COM memcpy(&tmp, wwn, sizeof (u_longlong_t));
37357836SJohn.Forte@Sun.COM return (tmp);
37367836SJohn.Forte@Sun.COM }
37377836SJohn.Forte@Sun.COM
37387836SJohn.Forte@Sun.COM /*
37397836SJohn.Forte@Sun.COM * Get device World Wide Name (port and node) for device at path
37407836SJohn.Forte@Sun.COM * and add all WWNs to the wwn_list_found list.
37417836SJohn.Forte@Sun.COM *
37427836SJohn.Forte@Sun.COM * RETURN: 0 O.K.
37437836SJohn.Forte@Sun.COM *
37447836SJohn.Forte@Sun.COM * INPUTS:
37457836SJohn.Forte@Sun.COM * - path_phys must be of a device, either an IB or disk.
37467836SJohn.Forte@Sun.COM */
37477836SJohn.Forte@Sun.COM static int
get_wwns(char * path_phys,uchar_t port_wwn[],uchar_t node_wwn[],int * al_pa,struct wwn_list_found_struct ** wwn_list_found)37487836SJohn.Forte@Sun.COM get_wwns(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[], int *al_pa,
3749*11547SBill.Gumbrell@Sun.COM struct wwn_list_found_struct **wwn_list_found)
37507836SJohn.Forte@Sun.COM {
3751*11547SBill.Gumbrell@Sun.COM uint32_t hba_port_top;
3752*11547SBill.Gumbrell@Sun.COM int i, err, count;
3753*11547SBill.Gumbrell@Sun.COM char *char_ptr, *ptr;
3754*11547SBill.Gumbrell@Sun.COM int found = 0, pathcnt, *port_addr;
3755*11547SBill.Gumbrell@Sun.COM unsigned long long pwwn;
3756*11547SBill.Gumbrell@Sun.COM uchar_t *port_wwn_byte, *node_wwn_byte;
3757*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN];
3758*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0;
3759*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
3760*11547SBill.Gumbrell@Sun.COM char pwwn1[WWN_S_LEN];
3761*11547SBill.Gumbrell@Sun.COM gfc_dev_t map_root, map_dev;
3762*11547SBill.Gumbrell@Sun.COM hrtime_t start_time, end_time;
3763*11547SBill.Gumbrell@Sun.COM char *env = NULL;
37647836SJohn.Forte@Sun.COM
37657836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_wwn: Getting device WWN"
3766*11547SBill.Gumbrell@Sun.COM " and al_pa for device: %s\n",
3767*11547SBill.Gumbrell@Sun.COM path_phys);
37687836SJohn.Forte@Sun.COM
37697836SJohn.Forte@Sun.COM if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
37707836SJohn.Forte@Sun.COM start_time = gethrtime();
37717836SJohn.Forte@Sun.COM }
37727836SJohn.Forte@Sun.COM
37737836SJohn.Forte@Sun.COM /*
37747836SJohn.Forte@Sun.COM * Get the loop identifier (switch setting) from the path.
37757836SJohn.Forte@Sun.COM *
37767836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
37777836SJohn.Forte@Sun.COM * /devices/.../SUNW,socal@3,0/SUNW,sf@0,0/SUNW,ssd@x,0
37787836SJohn.Forte@Sun.COM * or
37797836SJohn.Forte@Sun.COM * /devices/.../SUNW,qlc@5/SUNW,fp@0,0/SUNW,ssd@x,0
37807836SJohn.Forte@Sun.COM */
37817836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(path_phys, '@')) == NULL) {
37827836SJohn.Forte@Sun.COM return (L_INVLD_PATH_NO_ATSIGN_FND);
37837836SJohn.Forte@Sun.COM }
37847836SJohn.Forte@Sun.COM char_ptr++; /* point to the loop identifier or WWN */
37857836SJohn.Forte@Sun.COM
37867836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path_phys);
37877836SJohn.Forte@Sun.COM /* This function allocs mem for map.dev_addr on success */
37887836SJohn.Forte@Sun.COM if (strstr(drvr_path, SCSI_VHCI)) {
37897836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path, &pathlist)) {
37907836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
37917836SJohn.Forte@Sun.COM }
37927836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
37937836SJohn.Forte@Sun.COM p_on = p_st = 0;
37947836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
37957836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
37967836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
3797*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
37987836SJohn.Forte@Sun.COM p_on = i;
37997836SJohn.Forte@Sun.COM break;
38007836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
3801*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
38027836SJohn.Forte@Sun.COM p_st = i;
38037836SJohn.Forte@Sun.COM }
38047836SJohn.Forte@Sun.COM }
38057836SJohn.Forte@Sun.COM }
38067836SJohn.Forte@Sun.COM if (p_on == i) {
38077836SJohn.Forte@Sun.COM /* on_line path */
38087836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
3809*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
38107836SJohn.Forte@Sun.COM (void) strncpy(pwwn1,
3811*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_addr,
3812*11547SBill.Gumbrell@Sun.COM WWN_S_LEN - 1);
38137836SJohn.Forte@Sun.COM pwwn1[WWN_S_LEN - 1] = '\0';
38147836SJohn.Forte@Sun.COM } else {
38157836SJohn.Forte@Sun.COM /* standby or path0 */
38167836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
3817*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
38187836SJohn.Forte@Sun.COM (void) strncpy(pwwn1,
3819*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_addr,
3820*11547SBill.Gumbrell@Sun.COM WWN_S_LEN - 1);
38217836SJohn.Forte@Sun.COM pwwn1[WWN_S_LEN - 1] = '\0';
38227836SJohn.Forte@Sun.COM }
38237836SJohn.Forte@Sun.COM free(pathlist.path_info);
38247836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
38257836SJohn.Forte@Sun.COM }
38267836SJohn.Forte@Sun.COM if ((map_root = g_dev_map_init(drvr_path, &err,
3827*11547SBill.Gumbrell@Sun.COM MAP_XPORT_PROP_ONLY)) == NULL) {
38287836SJohn.Forte@Sun.COM return (err);
38297836SJohn.Forte@Sun.COM }
38307836SJohn.Forte@Sun.COM
38317836SJohn.Forte@Sun.COM if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) {
38327836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38337836SJohn.Forte@Sun.COM return (err);
38347836SJohn.Forte@Sun.COM }
38357836SJohn.Forte@Sun.COM
38367836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI)) {
38377836SJohn.Forte@Sun.COM char_ptr = pwwn1;
38387836SJohn.Forte@Sun.COM } else {
38397836SJohn.Forte@Sun.COM /*
38407836SJohn.Forte@Sun.COM * Format of WWN is
38417836SJohn.Forte@Sun.COM * ssd@w2200002037000f96,0:a,raw
38427836SJohn.Forte@Sun.COM */
38437836SJohn.Forte@Sun.COM if (*char_ptr != 'w') {
38447836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38457836SJohn.Forte@Sun.COM return (L_INVLD_WWN_FORMAT);
38467836SJohn.Forte@Sun.COM }
38477836SJohn.Forte@Sun.COM char_ptr++;
38487836SJohn.Forte@Sun.COM }
38497836SJohn.Forte@Sun.COM pwwn = strtoull(char_ptr, &ptr, 16);
38507836SJohn.Forte@Sun.COM if (ptr == char_ptr) {
38517836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38527836SJohn.Forte@Sun.COM return (L_NO_WWN_FOUND_IN_PATH);
38537836SJohn.Forte@Sun.COM }
38547836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_wwn: Looking for WWN "
38557836SJohn.Forte@Sun.COM "0x%llx\n", pwwn);
38567836SJohn.Forte@Sun.COM
38577836SJohn.Forte@Sun.COM if (((map_dev = g_get_first_dev(map_root, &err)) == NULL) &&
38587836SJohn.Forte@Sun.COM (err != L_NO_SUCH_DEV_FOUND)) {
38597836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38607836SJohn.Forte@Sun.COM return (err);
38617836SJohn.Forte@Sun.COM }
38627836SJohn.Forte@Sun.COM
38637836SJohn.Forte@Sun.COM while (map_dev) {
38647836SJohn.Forte@Sun.COM if ((err = g_dev_prop_lookup_bytes(map_dev,
3865*11547SBill.Gumbrell@Sun.COM PORT_WWN_PROP, &count, &port_wwn_byte)) != 0) {
38667836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38677836SJohn.Forte@Sun.COM return (err);
38687836SJohn.Forte@Sun.COM }
38697836SJohn.Forte@Sun.COM if ((err = g_dev_prop_lookup_bytes(map_dev,
3870*11547SBill.Gumbrell@Sun.COM NODE_WWN_PROP, &count, &node_wwn_byte)) != 0) {
38717836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38727836SJohn.Forte@Sun.COM return (err);
38737836SJohn.Forte@Sun.COM }
38747836SJohn.Forte@Sun.COM
38757836SJohn.Forte@Sun.COM if (pwwn == wwnConversion(port_wwn_byte) && found != 1) {
38767836SJohn.Forte@Sun.COM found = 1;
38777836SJohn.Forte@Sun.COM memcpy(port_wwn, port_wwn_byte, FC_WWN_SIZE);
38787836SJohn.Forte@Sun.COM memcpy(node_wwn, node_wwn_byte, FC_WWN_SIZE);
38797836SJohn.Forte@Sun.COM if ((err = g_dev_prop_lookup_ints(
3880*11547SBill.Gumbrell@Sun.COM map_dev, PORT_ADDR_PROP, &port_addr)) != 0) {
38817836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38827836SJohn.Forte@Sun.COM return (err);
38837836SJohn.Forte@Sun.COM }
38847836SJohn.Forte@Sun.COM *al_pa = *port_addr;
38857836SJohn.Forte@Sun.COM }
38867836SJohn.Forte@Sun.COM add_wwn_entry(wwn_list_found, port_wwn_byte,
38877836SJohn.Forte@Sun.COM node_wwn_byte);
38887836SJohn.Forte@Sun.COM
38897836SJohn.Forte@Sun.COM if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) &&
38907836SJohn.Forte@Sun.COM (err != L_NO_SUCH_DEV_FOUND)) {
38917836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38927836SJohn.Forte@Sun.COM return (err);
38937836SJohn.Forte@Sun.COM }
38947836SJohn.Forte@Sun.COM }
38957836SJohn.Forte@Sun.COM if (!found) {
38967836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
38977836SJohn.Forte@Sun.COM return (L_NO_LOOP_ADDRS_FOUND);
38987836SJohn.Forte@Sun.COM }
38997836SJohn.Forte@Sun.COM
39007836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
39017836SJohn.Forte@Sun.COM if (env != NULL) {
39027836SJohn.Forte@Sun.COM end_time = gethrtime();
39037836SJohn.Forte@Sun.COM fprintf(stdout, " get_wwns: "
3904*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
3905*11547SBill.Gumbrell@Sun.COM (end_time - start_time)/1000000);
39067836SJohn.Forte@Sun.COM }
39077836SJohn.Forte@Sun.COM return (0);
39087836SJohn.Forte@Sun.COM }
39097836SJohn.Forte@Sun.COM
39107836SJohn.Forte@Sun.COM /*
39117836SJohn.Forte@Sun.COM * Get device World Wide Name and AL_PA for device at path
39127836SJohn.Forte@Sun.COM *
39137836SJohn.Forte@Sun.COM * RETURN: 0 O.K.
39147836SJohn.Forte@Sun.COM *
39157836SJohn.Forte@Sun.COM * INPUTS:
39167836SJohn.Forte@Sun.COM * - path_phys must be of a device, either an IB or disk.
39177836SJohn.Forte@Sun.COM */
39187836SJohn.Forte@Sun.COM int
g_get_wwn(char * path_phys,uchar_t port_wwn[],uchar_t node_wwn[],int * al_pa,int verbose)39197836SJohn.Forte@Sun.COM g_get_wwn(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[],
3920*11547SBill.Gumbrell@Sun.COM int *al_pa, int verbose)
39217836SJohn.Forte@Sun.COM {
39227836SJohn.Forte@Sun.COM struct wwn_list_found_struct *wwn_list_found = NULL;
39237836SJohn.Forte@Sun.COM int ret;
39247836SJohn.Forte@Sun.COM
39257836SJohn.Forte@Sun.COM /* return invalid path if the argument is NULL */
39267836SJohn.Forte@Sun.COM if (path_phys == NULL) {
39277836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
39287836SJohn.Forte@Sun.COM }
39297836SJohn.Forte@Sun.COM /* return invalid arg if the argument is NULL */
3930*11547SBill.Gumbrell@Sun.COM if ((port_wwn == NULL) || (node_wwn == NULL) || (al_pa == NULL)) {
39317836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
39327836SJohn.Forte@Sun.COM }
39337836SJohn.Forte@Sun.COM
39347836SJohn.Forte@Sun.COM ret = get_wwns(path_phys, port_wwn, node_wwn, al_pa, &wwn_list_found);
39357836SJohn.Forte@Sun.COM g_free_wwn_list_found(&wwn_list_found);
39367836SJohn.Forte@Sun.COM return (ret);
39377836SJohn.Forte@Sun.COM }
39387836SJohn.Forte@Sun.COM
39397836SJohn.Forte@Sun.COM int
g_get_serial_number(char * path,uchar_t * serial_number,size_t * serial_number_len)39407836SJohn.Forte@Sun.COM g_get_serial_number(char *path, uchar_t *serial_number,
39417836SJohn.Forte@Sun.COM size_t *serial_number_len)
39427836SJohn.Forte@Sun.COM {
3943*11547SBill.Gumbrell@Sun.COM int fd, status = 0;
3944*11547SBill.Gumbrell@Sun.COM L_inquiry80 inq80;
39457836SJohn.Forte@Sun.COM
39467836SJohn.Forte@Sun.COM /* return invalid path if path is NULL */
39477836SJohn.Forte@Sun.COM if (path == NULL) {
39487836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
39497836SJohn.Forte@Sun.COM }
39507836SJohn.Forte@Sun.COM /* return invalid arg if serial_number is NULL */
39517836SJohn.Forte@Sun.COM if (serial_number == NULL) {
39527836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
39537836SJohn.Forte@Sun.COM }
39547836SJohn.Forte@Sun.COM
39557836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_serial_number: path: %s\n", path);
39567836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) {
39577836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
39587836SJohn.Forte@Sun.COM }
39597836SJohn.Forte@Sun.COM /*
39607836SJohn.Forte@Sun.COM * Call the inquiry cmd on page 0x80 only if the vendor
39617836SJohn.Forte@Sun.COM * supports page 0x80.
39627836SJohn.Forte@Sun.COM */
39637836SJohn.Forte@Sun.COM if ((g_find_supported_inq_page(fd, 0x80))) {
39647836SJohn.Forte@Sun.COM /*
39657836SJohn.Forte@Sun.COM * Let's retrieve the serial number from page 0x80
39667836SJohn.Forte@Sun.COM * and store it in the inquiry structure
39677836SJohn.Forte@Sun.COM */
39687836SJohn.Forte@Sun.COM status = g_scsi_inquiry_cmd80(fd,
39697836SJohn.Forte@Sun.COM (uchar_t *)&inq80,
39707836SJohn.Forte@Sun.COM sizeof (struct l_inquiry80_struct));
39717836SJohn.Forte@Sun.COM if (status == 0) {
39727836SJohn.Forte@Sun.COM if (*serial_number_len > inq80.inq_page_len)
39737836SJohn.Forte@Sun.COM *serial_number_len = inq80.inq_page_len;
39747836SJohn.Forte@Sun.COM strncpy((char *)serial_number, (char *)inq80.inq_serial,
39757836SJohn.Forte@Sun.COM *serial_number_len);
39767836SJohn.Forte@Sun.COM } else {
39777836SJohn.Forte@Sun.COM char unavail[] = "Unavailable";
39787836SJohn.Forte@Sun.COM status = 0;
39797836SJohn.Forte@Sun.COM if (*serial_number_len > strlen(unavail))
39807836SJohn.Forte@Sun.COM *serial_number_len = strlen(unavail);
39817836SJohn.Forte@Sun.COM strncpy((char *)serial_number, unavail,
39827836SJohn.Forte@Sun.COM *serial_number_len);
39837836SJohn.Forte@Sun.COM }
39847836SJohn.Forte@Sun.COM } else {
39857836SJohn.Forte@Sun.COM /*
39867836SJohn.Forte@Sun.COM * page 0x80 is not supported, so print the
39877836SJohn.Forte@Sun.COM * appropriate message.
39887836SJohn.Forte@Sun.COM */
39897836SJohn.Forte@Sun.COM char unsupp[] = "Unsupported";
39907836SJohn.Forte@Sun.COM if (*serial_number_len > strlen(unsupp))
39917836SJohn.Forte@Sun.COM *serial_number_len = strlen(unsupp);
39927836SJohn.Forte@Sun.COM strncpy((char *)serial_number, unsupp,
39937836SJohn.Forte@Sun.COM *serial_number_len);
39947836SJohn.Forte@Sun.COM }
39957836SJohn.Forte@Sun.COM (void) close(fd);
39967836SJohn.Forte@Sun.COM return (status);
39977836SJohn.Forte@Sun.COM }
39987836SJohn.Forte@Sun.COM
39997836SJohn.Forte@Sun.COM int
g_get_inquiry(char * path,L_inquiry * l_inquiry)40007836SJohn.Forte@Sun.COM g_get_inquiry(char *path, L_inquiry *l_inquiry)
40017836SJohn.Forte@Sun.COM {
4002*11547SBill.Gumbrell@Sun.COM int fd, status;
40037836SJohn.Forte@Sun.COM
40047836SJohn.Forte@Sun.COM /* return invalid path if path is NULL */
40057836SJohn.Forte@Sun.COM if (path == NULL) {
40067836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
40077836SJohn.Forte@Sun.COM }
40087836SJohn.Forte@Sun.COM /* return invalid arg if l_inquiry is NULL */
40097836SJohn.Forte@Sun.COM if (l_inquiry == NULL) {
40107836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
40117836SJohn.Forte@Sun.COM }
40127836SJohn.Forte@Sun.COM
40137836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_inquiry: path: %s\n", path);
40147836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
40157836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
40167836SJohn.Forte@Sun.COM status = g_scsi_inquiry_cmd(fd,
4017*11547SBill.Gumbrell@Sun.COM (uchar_t *)l_inquiry, sizeof (struct l_inquiry_struct));
40187836SJohn.Forte@Sun.COM
40197836SJohn.Forte@Sun.COM (void) close(fd);
40207836SJohn.Forte@Sun.COM return (status);
40217836SJohn.Forte@Sun.COM }
40227836SJohn.Forte@Sun.COM
40237836SJohn.Forte@Sun.COM /*
40247836SJohn.Forte@Sun.COM * Function to retrieve inquiry page 0x80 from the device
40257836SJohn.Forte@Sun.COM */
40267836SJohn.Forte@Sun.COM static int
g_scsi_inquiry_cmd80(int fd,uchar_t * buf_ptr,int buf_len)40277836SJohn.Forte@Sun.COM g_scsi_inquiry_cmd80(int fd, uchar_t *buf_ptr, int buf_len)
40287836SJohn.Forte@Sun.COM {
4029*11547SBill.Gumbrell@Sun.COM struct uscsi_cmd ucmd;
4030*11547SBill.Gumbrell@Sun.COM my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0x80, 0, 0x10, 0};
4031*11547SBill.Gumbrell@Sun.COM struct scsi_extended_sense sense;
40327836SJohn.Forte@Sun.COM
40337836SJohn.Forte@Sun.COM (void) memset(buf_ptr, 0, buf_len);
40347836SJohn.Forte@Sun.COM (void) memset((char *)&ucmd, 0, sizeof (ucmd));
40357836SJohn.Forte@Sun.COM cdb.count = (uchar_t)buf_len;
40367836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = (caddr_t)&cdb;
40377836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP0;
40387836SJohn.Forte@Sun.COM ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
40397836SJohn.Forte@Sun.COM ucmd.uscsi_buflen = buf_len;
40407836SJohn.Forte@Sun.COM ucmd.uscsi_rqbuf = (caddr_t)&sense;
40417836SJohn.Forte@Sun.COM ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense);
40427836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = 60;
40437836SJohn.Forte@Sun.COM return (cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT));
40447836SJohn.Forte@Sun.COM }
40457836SJohn.Forte@Sun.COM
40467836SJohn.Forte@Sun.COM /*
40477836SJohn.Forte@Sun.COM * Function to determine if the given page is supported by vendor.
40487836SJohn.Forte@Sun.COM */
40497836SJohn.Forte@Sun.COM static int
g_find_supported_inq_page(int fd,int page_num)40507836SJohn.Forte@Sun.COM g_find_supported_inq_page(int fd, int page_num)
40517836SJohn.Forte@Sun.COM {
4052*11547SBill.Gumbrell@Sun.COM struct uscsi_cmd ucmd;
4053*11547SBill.Gumbrell@Sun.COM my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0, 0, 0xff, 0};
4054*11547SBill.Gumbrell@Sun.COM struct scsi_extended_sense sense;
4055*11547SBill.Gumbrell@Sun.COM L_inquiry00 inq00;
4056*11547SBill.Gumbrell@Sun.COM uchar_t *data;
4057*11547SBill.Gumbrell@Sun.COM int status = 0;
4058*11547SBill.Gumbrell@Sun.COM int index;
40597836SJohn.Forte@Sun.COM
40607836SJohn.Forte@Sun.COM (void) memset((char *)&ucmd, 0, sizeof (ucmd));
40617836SJohn.Forte@Sun.COM cdb.count = (uchar_t)(sizeof (L_inquiry00));
40627836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = (caddr_t)&cdb;
40637836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP0;
40647836SJohn.Forte@Sun.COM ucmd.uscsi_bufaddr = (caddr_t)&inq00;
40657836SJohn.Forte@Sun.COM ucmd.uscsi_buflen = sizeof (inq00);
40667836SJohn.Forte@Sun.COM ucmd.uscsi_rqbuf = (caddr_t)&sense;
40677836SJohn.Forte@Sun.COM ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense);
40687836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = 60;
40697836SJohn.Forte@Sun.COM status = cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT);
40707836SJohn.Forte@Sun.COM if (status) {
40717836SJohn.Forte@Sun.COM return (0);
40727836SJohn.Forte@Sun.COM }
40737836SJohn.Forte@Sun.COM data = (uchar_t *)&inq00;
40747836SJohn.Forte@Sun.COM for (index = 4; (index <= inq00.len+3)&&
40757836SJohn.Forte@Sun.COM (data[index] <= page_num); index ++) {
40767836SJohn.Forte@Sun.COM if (data[index] == page_num) {
40777836SJohn.Forte@Sun.COM return (1);
40787836SJohn.Forte@Sun.COM }
40797836SJohn.Forte@Sun.COM }
40807836SJohn.Forte@Sun.COM return (0);
40817836SJohn.Forte@Sun.COM }
40827836SJohn.Forte@Sun.COM
40837836SJohn.Forte@Sun.COM int
g_get_perf_statistics(char * path,uchar_t * perf_ptr)40847836SJohn.Forte@Sun.COM g_get_perf_statistics(char *path, uchar_t *perf_ptr)
40857836SJohn.Forte@Sun.COM {
4086*11547SBill.Gumbrell@Sun.COM int fd;
40877836SJohn.Forte@Sun.COM
40887836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_perf_statistics: Get Performance Statistics:"
4089*11547SBill.Gumbrell@Sun.COM "\n Path:%s\n",
4090*11547SBill.Gumbrell@Sun.COM path);
40917836SJohn.Forte@Sun.COM
40927836SJohn.Forte@Sun.COM /* initialize tables */
40937836SJohn.Forte@Sun.COM (void) memset(perf_ptr, 0, sizeof (int));
40947836SJohn.Forte@Sun.COM
40957836SJohn.Forte@Sun.COM /* open controller */
40967836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
40977836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
40987836SJohn.Forte@Sun.COM
40997836SJohn.Forte@Sun.COM
41007836SJohn.Forte@Sun.COM /* update parameters in the performance table */
41017836SJohn.Forte@Sun.COM
41027836SJohn.Forte@Sun.COM /* get the period in seconds */
41037836SJohn.Forte@Sun.COM
41047836SJohn.Forte@Sun.COM
41057836SJohn.Forte@Sun.COM (void) close(fd);
41067836SJohn.Forte@Sun.COM
41077836SJohn.Forte@Sun.COM return (0);
41087836SJohn.Forte@Sun.COM }
41097836SJohn.Forte@Sun.COM
41107836SJohn.Forte@Sun.COM
41117836SJohn.Forte@Sun.COM int
g_start(char * path)41127836SJohn.Forte@Sun.COM g_start(char *path)
41137836SJohn.Forte@Sun.COM {
4114*11547SBill.Gumbrell@Sun.COM int status;
4115*11547SBill.Gumbrell@Sun.COM int fd;
41167836SJohn.Forte@Sun.COM
41177836SJohn.Forte@Sun.COM P_DPRINTF(" g_start: Start: Path %s\n", path);
41187836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
41197836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
41207836SJohn.Forte@Sun.COM status = g_scsi_start_cmd(fd);
41217836SJohn.Forte@Sun.COM (void) close(fd);
41227836SJohn.Forte@Sun.COM return (status);
41237836SJohn.Forte@Sun.COM }
41247836SJohn.Forte@Sun.COM
41257836SJohn.Forte@Sun.COM int
g_stop(char * path,int immediate_flag)41267836SJohn.Forte@Sun.COM g_stop(char *path, int immediate_flag)
41277836SJohn.Forte@Sun.COM {
4128*11547SBill.Gumbrell@Sun.COM int status, fd;
41297836SJohn.Forte@Sun.COM
41307836SJohn.Forte@Sun.COM P_DPRINTF(" g_stop: Stop: Path %s\n", path);
41317836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
41327836SJohn.Forte@Sun.COM return (errno);
41337836SJohn.Forte@Sun.COM status = g_scsi_stop_cmd(fd, immediate_flag);
41347836SJohn.Forte@Sun.COM (void) close(fd);
41357836SJohn.Forte@Sun.COM return (status);
41367836SJohn.Forte@Sun.COM }
41377836SJohn.Forte@Sun.COM
41387836SJohn.Forte@Sun.COM int
g_reserve(char * path)41397836SJohn.Forte@Sun.COM g_reserve(char *path)
41407836SJohn.Forte@Sun.COM {
4141*11547SBill.Gumbrell@Sun.COM int fd, status;
41427836SJohn.Forte@Sun.COM
41437836SJohn.Forte@Sun.COM P_DPRINTF(" g_reserve: Reserve: Path %s\n", path);
41447836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
41457836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
41467836SJohn.Forte@Sun.COM status = g_scsi_reserve_cmd(fd);
41477836SJohn.Forte@Sun.COM (void) close(fd);
41487836SJohn.Forte@Sun.COM return (status);
41497836SJohn.Forte@Sun.COM }
41507836SJohn.Forte@Sun.COM
41517836SJohn.Forte@Sun.COM int
g_release(char * path)41527836SJohn.Forte@Sun.COM g_release(char *path)
41537836SJohn.Forte@Sun.COM {
4154*11547SBill.Gumbrell@Sun.COM int fd, status;
41557836SJohn.Forte@Sun.COM
41567836SJohn.Forte@Sun.COM P_DPRINTF(" g_release: Release: Path %s\n", path);
41577836SJohn.Forte@Sun.COM if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
41587836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
41597836SJohn.Forte@Sun.COM status = g_scsi_release_cmd(fd);
41607836SJohn.Forte@Sun.COM (void) close(fd);
41617836SJohn.Forte@Sun.COM return (status);
41627836SJohn.Forte@Sun.COM }
41637836SJohn.Forte@Sun.COM
41647836SJohn.Forte@Sun.COM static char
ctoi(char c)41657836SJohn.Forte@Sun.COM ctoi(char c)
41667836SJohn.Forte@Sun.COM {
41677836SJohn.Forte@Sun.COM if ((c >= '0') && (c <= '9'))
41687836SJohn.Forte@Sun.COM c -= '0';
41697836SJohn.Forte@Sun.COM else if ((c >= 'A') && (c <= 'F'))
41707836SJohn.Forte@Sun.COM c = c - 'A' + 10;
41717836SJohn.Forte@Sun.COM else if ((c >= 'a') && (c <= 'f'))
41727836SJohn.Forte@Sun.COM c = c - 'a' + 10;
41737836SJohn.Forte@Sun.COM else
41747836SJohn.Forte@Sun.COM c = -1;
41757836SJohn.Forte@Sun.COM return (c);
41767836SJohn.Forte@Sun.COM }
41777836SJohn.Forte@Sun.COM
41787836SJohn.Forte@Sun.COM int
g_string_to_wwn(uchar_t * wwn,uchar_t * wwnp)41797836SJohn.Forte@Sun.COM g_string_to_wwn(uchar_t *wwn, uchar_t *wwnp)
41807836SJohn.Forte@Sun.COM {
41817836SJohn.Forte@Sun.COM int i;
41827836SJohn.Forte@Sun.COM char c, c1;
41837836SJohn.Forte@Sun.COM
41847836SJohn.Forte@Sun.COM *wwnp++ = 0;
41857836SJohn.Forte@Sun.COM *wwnp++ = 0;
41867836SJohn.Forte@Sun.COM for (i = 0; i < WWN_SIZE - 2; i++, wwnp++) {
41877836SJohn.Forte@Sun.COM c = ctoi(*wwn++);
41887836SJohn.Forte@Sun.COM c1 = ctoi(*wwn++);
41897836SJohn.Forte@Sun.COM if (c == -1 || c1 == -1)
41907836SJohn.Forte@Sun.COM return (-1);
41917836SJohn.Forte@Sun.COM *wwnp = ((c << 4) + c1);
41927836SJohn.Forte@Sun.COM }
41937836SJohn.Forte@Sun.COM
41947836SJohn.Forte@Sun.COM return (0);
41957836SJohn.Forte@Sun.COM
41967836SJohn.Forte@Sun.COM }
41977836SJohn.Forte@Sun.COM
41987836SJohn.Forte@Sun.COM /*
41997836SJohn.Forte@Sun.COM * Converts a string of WWN ASCII characters to a
42007836SJohn.Forte@Sun.COM * binary representation.
42017836SJohn.Forte@Sun.COM *
42027836SJohn.Forte@Sun.COM * Input: string - pointer to uchar_t array
42037836SJohn.Forte@Sun.COM * WWN in ASCII
42047836SJohn.Forte@Sun.COM * length: 16 bytes
42057836SJohn.Forte@Sun.COM * Output: wwn - pointer to uchar_t array
42067836SJohn.Forte@Sun.COM * containing WWN result
42077836SJohn.Forte@Sun.COM * length: 8 bytes
42087836SJohn.Forte@Sun.COM * Returns:
42097836SJohn.Forte@Sun.COM * non-zero on error
42107836SJohn.Forte@Sun.COM * zero on success
42117836SJohn.Forte@Sun.COM */
42127836SJohn.Forte@Sun.COM int
string_to_wwn(uchar_t * string,uchar_t * wwn)42137836SJohn.Forte@Sun.COM string_to_wwn(uchar_t *string, uchar_t *wwn)
42147836SJohn.Forte@Sun.COM {
42157836SJohn.Forte@Sun.COM int i;
42167836SJohn.Forte@Sun.COM char c, c1;
42177836SJohn.Forte@Sun.COM uchar_t *wwnp;
42187836SJohn.Forte@Sun.COM
42197836SJohn.Forte@Sun.COM wwnp = wwn;
42207836SJohn.Forte@Sun.COM
42217836SJohn.Forte@Sun.COM for (i = 0; i < WWN_SIZE; i++, wwnp++) {
42227836SJohn.Forte@Sun.COM
42237836SJohn.Forte@Sun.COM c = ctoi(*string++);
42247836SJohn.Forte@Sun.COM c1 = ctoi(*string++);
42257836SJohn.Forte@Sun.COM if (c == -1 || c1 == -1)
42267836SJohn.Forte@Sun.COM return (-1);
42277836SJohn.Forte@Sun.COM *wwnp = ((c << 4) + c1);
42287836SJohn.Forte@Sun.COM }
42297836SJohn.Forte@Sun.COM
42307836SJohn.Forte@Sun.COM return (0);
42317836SJohn.Forte@Sun.COM
42327836SJohn.Forte@Sun.COM }
42337836SJohn.Forte@Sun.COM
42347836SJohn.Forte@Sun.COM
42357836SJohn.Forte@Sun.COM /*
42367836SJohn.Forte@Sun.COM * Get multiple paths to a given device port.
42377836SJohn.Forte@Sun.COM * INPUTS:
42387836SJohn.Forte@Sun.COM * port WWN string.
42397836SJohn.Forte@Sun.COM */
42407836SJohn.Forte@Sun.COM int
g_get_port_multipath(char * port_wwn_s,struct dlist ** dlh,int verbose)42417836SJohn.Forte@Sun.COM g_get_port_multipath(char *port_wwn_s, struct dlist **dlh, int verbose)
42427836SJohn.Forte@Sun.COM {
4243*11547SBill.Gumbrell@Sun.COM int err;
4244*11547SBill.Gumbrell@Sun.COM WWN_list *wwn_list, *wwn_list_ptr;
4245*11547SBill.Gumbrell@Sun.COM struct dlist *dlt, *dl;
42467836SJohn.Forte@Sun.COM
42477836SJohn.Forte@Sun.COM
42487836SJohn.Forte@Sun.COM /* Initialize list structures. */
42497836SJohn.Forte@Sun.COM dl = *dlh = dlt = (struct dlist *)NULL;
42507836SJohn.Forte@Sun.COM wwn_list = wwn_list_ptr = NULL;
42517836SJohn.Forte@Sun.COM
42527836SJohn.Forte@Sun.COM H_DPRINTF(" g_get_port_multipath: Looking for multiple paths for"
4253*11547SBill.Gumbrell@Sun.COM " device with\n port WWW:"
4254*11547SBill.Gumbrell@Sun.COM "%s\n", port_wwn_s);
42557836SJohn.Forte@Sun.COM
42567836SJohn.Forte@Sun.COM if (err = g_get_wwn_list(&wwn_list, verbose)) {
42577836SJohn.Forte@Sun.COM return (err);
42587836SJohn.Forte@Sun.COM }
42597836SJohn.Forte@Sun.COM
42607836SJohn.Forte@Sun.COM for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4261*11547SBill.Gumbrell@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
42627836SJohn.Forte@Sun.COM if (strcmp(port_wwn_s, wwn_list_ptr->port_wwn_s) == 0) {
42637836SJohn.Forte@Sun.COM if ((dl = (struct dlist *)
4264*11547SBill.Gumbrell@Sun.COM g_zalloc(sizeof (struct dlist))) == NULL) {
42657836SJohn.Forte@Sun.COM while (*dlh != NULL) {
42667836SJohn.Forte@Sun.COM dl = (*dlh)->next;
42677836SJohn.Forte@Sun.COM (void) g_destroy_data(*dlh);
42687836SJohn.Forte@Sun.COM *dlh = dl;
42697836SJohn.Forte@Sun.COM }
42707836SJohn.Forte@Sun.COM (void) g_free_wwn_list(&wwn_list);
42717836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
42727836SJohn.Forte@Sun.COM }
42737836SJohn.Forte@Sun.COM H_DPRINTF(" g_get_port_multipath:"
4274*11547SBill.Gumbrell@Sun.COM " Found multipath:\n %s\n",
4275*11547SBill.Gumbrell@Sun.COM wwn_list_ptr->physical_path);
42767836SJohn.Forte@Sun.COM dl->dev_path = strdup(wwn_list_ptr->physical_path);
42777836SJohn.Forte@Sun.COM dl->logical_path = strdup(wwn_list_ptr->logical_path);
42787836SJohn.Forte@Sun.COM if (*dlh == NULL) {
42797836SJohn.Forte@Sun.COM *dlh = dlt = dl;
42807836SJohn.Forte@Sun.COM } else {
42817836SJohn.Forte@Sun.COM dlt->next = dl;
42827836SJohn.Forte@Sun.COM dl->prev = dlt;
42837836SJohn.Forte@Sun.COM dlt = dl;
42847836SJohn.Forte@Sun.COM }
42857836SJohn.Forte@Sun.COM }
42867836SJohn.Forte@Sun.COM }
42877836SJohn.Forte@Sun.COM (void) g_free_wwn_list(&wwn_list);
42887836SJohn.Forte@Sun.COM return (0);
42897836SJohn.Forte@Sun.COM }
42907836SJohn.Forte@Sun.COM
42917836SJohn.Forte@Sun.COM
42927836SJohn.Forte@Sun.COM
42937836SJohn.Forte@Sun.COM /*
42947836SJohn.Forte@Sun.COM * Get multiple paths to a given disk/tape device.
42957836SJohn.Forte@Sun.COM * The arg: devpath should be the physical path to device.
42967836SJohn.Forte@Sun.COM *
42977836SJohn.Forte@Sun.COM * OUTPUT:
42987836SJohn.Forte@Sun.COM * multipath_list points to a list of multiple paths to the device.
42997836SJohn.Forte@Sun.COM * NOTE: The caller must free the allocated list (dlist).
43007836SJohn.Forte@Sun.COM *
43017836SJohn.Forte@Sun.COM * RETURNS:
43027836SJohn.Forte@Sun.COM * 0 if O.K.
43037836SJohn.Forte@Sun.COM * non-zero otherwise
43047836SJohn.Forte@Sun.COM */
43057836SJohn.Forte@Sun.COM int
g_get_multipath(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list,int verbose)43067836SJohn.Forte@Sun.COM g_get_multipath(char *devpath, struct dlist **multipath_list,
4307*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *wwn_list, int verbose)
43087836SJohn.Forte@Sun.COM {
4309*11547SBill.Gumbrell@Sun.COM int err;
43107836SJohn.Forte@Sun.COM
43117836SJohn.Forte@Sun.COM H_DPRINTF(" g_get_multipath: Looking for multiple paths for"
4312*11547SBill.Gumbrell@Sun.COM " device at path: %s\n", devpath);
43137836SJohn.Forte@Sun.COM
43147836SJohn.Forte@Sun.COM /* return invalid path if devpath is NULL */
43157836SJohn.Forte@Sun.COM if (devpath == NULL) {
43167836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
43177836SJohn.Forte@Sun.COM }
43187836SJohn.Forte@Sun.COM /* return invalid arg if argument is NULL */
43197836SJohn.Forte@Sun.COM if ((multipath_list == NULL) || (wwn_list == NULL)) {
43207836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
43217836SJohn.Forte@Sun.COM }
43227836SJohn.Forte@Sun.COM
43237836SJohn.Forte@Sun.COM if (strstr(devpath, DRV_NAME_SSD) != NULL) {
43247836SJohn.Forte@Sun.COM err = get_multipath_disk(devpath, multipath_list, wwn_list);
43257836SJohn.Forte@Sun.COM } else {
43267836SJohn.Forte@Sun.COM err = get_multipath(devpath, multipath_list, wwn_list);
43277836SJohn.Forte@Sun.COM }
43287836SJohn.Forte@Sun.COM
43297836SJohn.Forte@Sun.COM return (err);
43307836SJohn.Forte@Sun.COM }
43317836SJohn.Forte@Sun.COM
43327836SJohn.Forte@Sun.COM
43337836SJohn.Forte@Sun.COM /*
43347836SJohn.Forte@Sun.COM * Returns multipath information for a ssd device.
43357836SJohn.Forte@Sun.COM * Inputs:
43367836SJohn.Forte@Sun.COM * devpath: device path to for requested multipath info
43377836SJohn.Forte@Sun.COM * wwn_list: returned from g_get_wwn_list or devices_get_all
43387836SJohn.Forte@Sun.COM * Output:
43397836SJohn.Forte@Sun.COM * multipath_list: dlist list of paths
43407836SJohn.Forte@Sun.COM * Returns:
43417836SJohn.Forte@Sun.COM * 0 on success
43427836SJohn.Forte@Sun.COM * non-zero on failure
43437836SJohn.Forte@Sun.COM */
43447836SJohn.Forte@Sun.COM int
get_multipath_disk(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list)43457836SJohn.Forte@Sun.COM get_multipath_disk(char *devpath, struct dlist **multipath_list,
4346*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct *wwn_list)
43477836SJohn.Forte@Sun.COM {
4348*11547SBill.Gumbrell@Sun.COM WWN_list *wwn_list_ptr;
4349*11547SBill.Gumbrell@Sun.COM struct dlist *dl = NULL, *dlt = NULL;
4350*11547SBill.Gumbrell@Sun.COM ddi_devid_t devid = NULL;
4351*11547SBill.Gumbrell@Sun.COM int err;
4352*11547SBill.Gumbrell@Sun.COM di_node_t root;
4353*11547SBill.Gumbrell@Sun.COM struct mplist_struct *mplistp = NULL, *mplisth = NULL;
43547836SJohn.Forte@Sun.COM
43557836SJohn.Forte@Sun.COM if (wwn_list == NULL || multipath_list == NULL || devpath == NULL) {
43567836SJohn.Forte@Sun.COM return (L_NULL_WWN_LIST);
43577836SJohn.Forte@Sun.COM }
43587836SJohn.Forte@Sun.COM
43597836SJohn.Forte@Sun.COM if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
43607836SJohn.Forte@Sun.COM return (L_DEV_SNAPSHOT_FAILED);
43617836SJohn.Forte@Sun.COM }
43627836SJohn.Forte@Sun.COM
43637836SJohn.Forte@Sun.COM if ((err = g_devid_get(devpath, &devid, root, SSD_DRVR_NAME)) != 0) {
43647836SJohn.Forte@Sun.COM di_fini(root);
43657836SJohn.Forte@Sun.COM return (err);
43667836SJohn.Forte@Sun.COM }
43677836SJohn.Forte@Sun.COM
43687836SJohn.Forte@Sun.COM *multipath_list = (struct dlist *)NULL;
43697836SJohn.Forte@Sun.COM if ((err = devid_get_all(devid, root, SSD_DRVR_NAME, &mplisth)) != 0) {
43707836SJohn.Forte@Sun.COM di_fini(root);
43717836SJohn.Forte@Sun.COM return (err);
43727836SJohn.Forte@Sun.COM }
43737836SJohn.Forte@Sun.COM
43747836SJohn.Forte@Sun.COM if (mplisth == NULL) {
43757836SJohn.Forte@Sun.COM di_fini(root);
43767836SJohn.Forte@Sun.COM return (L_NULL_WWN_LIST);
43777836SJohn.Forte@Sun.COM }
43787836SJohn.Forte@Sun.COM
43797836SJohn.Forte@Sun.COM for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4380*11547SBill.Gumbrell@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
43817836SJohn.Forte@Sun.COM /*
43827836SJohn.Forte@Sun.COM * When a path is found from the list, load the logical
43837836SJohn.Forte@Sun.COM * and physical dev path
43847836SJohn.Forte@Sun.COM */
43857836SJohn.Forte@Sun.COM for (mplistp = mplisth; mplistp != NULL;
4386*11547SBill.Gumbrell@Sun.COM mplistp = mplistp->next) {
4387*11547SBill.Gumbrell@Sun.COM if (strncmp(mplistp->devpath,
4388*11547SBill.Gumbrell@Sun.COM wwn_list_ptr->physical_path,
4389*11547SBill.Gumbrell@Sun.COM strlen(mplistp->devpath)) == 0) {
4390*11547SBill.Gumbrell@Sun.COM
4391*11547SBill.Gumbrell@Sun.COM /* Load multipath list */
4392*11547SBill.Gumbrell@Sun.COM if ((dl = (struct dlist *)
4393*11547SBill.Gumbrell@Sun.COM calloc(1, sizeof (struct dlist))) == NULL) {
4394*11547SBill.Gumbrell@Sun.COM while (*multipath_list != NULL) {
4395*11547SBill.Gumbrell@Sun.COM dl = dlt->next;
4396*11547SBill.Gumbrell@Sun.COM g_destroy_data(dlt);
4397*11547SBill.Gumbrell@Sun.COM dlt = dl;
4398*11547SBill.Gumbrell@Sun.COM }
4399*11547SBill.Gumbrell@Sun.COM di_fini(root);
4400*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
4401*11547SBill.Gumbrell@Sun.COM }
4402*11547SBill.Gumbrell@Sun.COM H_DPRINTF(
4403*11547SBill.Gumbrell@Sun.COM " g_get_multipath: Found multipath=%s\n",
4404*11547SBill.Gumbrell@Sun.COM wwn_list_ptr->physical_path);
4405*11547SBill.Gumbrell@Sun.COM dl->logical_path =
4406*11547SBill.Gumbrell@Sun.COM strdup(wwn_list_ptr->logical_path);
4407*11547SBill.Gumbrell@Sun.COM dl->dev_path =
4408*11547SBill.Gumbrell@Sun.COM strdup(wwn_list_ptr->physical_path);
4409*11547SBill.Gumbrell@Sun.COM if (*multipath_list == NULL) {
4410*11547SBill.Gumbrell@Sun.COM *multipath_list = dlt = dl;
4411*11547SBill.Gumbrell@Sun.COM } else {
4412*11547SBill.Gumbrell@Sun.COM dlt->next = dl;
4413*11547SBill.Gumbrell@Sun.COM dl->prev = dlt;
44147836SJohn.Forte@Sun.COM dlt = dl;
44157836SJohn.Forte@Sun.COM }
44167836SJohn.Forte@Sun.COM }
44177836SJohn.Forte@Sun.COM }
44187836SJohn.Forte@Sun.COM }
44197836SJohn.Forte@Sun.COM di_fini(root);
44207836SJohn.Forte@Sun.COM mplist_free(mplisth);
44217836SJohn.Forte@Sun.COM return (0);
44227836SJohn.Forte@Sun.COM }
44237836SJohn.Forte@Sun.COM
44247836SJohn.Forte@Sun.COM int
get_multipath(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list)44257836SJohn.Forte@Sun.COM get_multipath(char *devpath, struct dlist **multipath_list,
44267836SJohn.Forte@Sun.COM struct wwn_list_struct *wwn_list)
44277836SJohn.Forte@Sun.COM {
4428*11547SBill.Gumbrell@Sun.COM WWN_list *wwn_list_ptr;
4429*11547SBill.Gumbrell@Sun.COM struct dlist *dl, *dlt;
4430*11547SBill.Gumbrell@Sun.COM char path[MAXPATHLEN], m_phys_path[MAXPATHLEN], *ptr;
4431*11547SBill.Gumbrell@Sun.COM int len;
4432*11547SBill.Gumbrell@Sun.COM int lun_a = -1;
4433*11547SBill.Gumbrell@Sun.COM char node_wwn_s[WWN_S_LEN];
44347836SJohn.Forte@Sun.COM
44357836SJohn.Forte@Sun.COM if (devpath == NULL) {
44367836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
44377836SJohn.Forte@Sun.COM }
44387836SJohn.Forte@Sun.COM
44397836SJohn.Forte@Sun.COM /* Strip partition information. */
44407836SJohn.Forte@Sun.COM if ((ptr = strrchr(devpath, ':')) != NULL) {
44417836SJohn.Forte@Sun.COM len = strlen(devpath) - strlen(ptr);
44427836SJohn.Forte@Sun.COM (void) strncpy(path, devpath, len);
44437836SJohn.Forte@Sun.COM path[len] = '\0';
44447836SJohn.Forte@Sun.COM } else {
44457836SJohn.Forte@Sun.COM (void) strcpy(path, devpath);
44467836SJohn.Forte@Sun.COM }
44477836SJohn.Forte@Sun.COM
44487836SJohn.Forte@Sun.COM *multipath_list = dl = dlt = (struct dlist *)NULL;
44497836SJohn.Forte@Sun.COM
44507836SJohn.Forte@Sun.COM
44517836SJohn.Forte@Sun.COM if (wwn_list == NULL) {
44527836SJohn.Forte@Sun.COM return (L_NULL_WWN_LIST);
44537836SJohn.Forte@Sun.COM }
44547836SJohn.Forte@Sun.COM
44557836SJohn.Forte@Sun.COM for (*node_wwn_s = NULL, wwn_list_ptr = wwn_list;
4456*11547SBill.Gumbrell@Sun.COM wwn_list_ptr != NULL;
4457*11547SBill.Gumbrell@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
44587836SJohn.Forte@Sun.COM
44597836SJohn.Forte@Sun.COM if ((ptr = strrchr(wwn_list_ptr->physical_path, ':')) != NULL) {
44607836SJohn.Forte@Sun.COM len = strlen(wwn_list_ptr->physical_path) - strlen(ptr);
44617836SJohn.Forte@Sun.COM (void) strncpy(m_phys_path, wwn_list_ptr->physical_path,
4462*11547SBill.Gumbrell@Sun.COM len);
44637836SJohn.Forte@Sun.COM m_phys_path[len] = '\0';
44647836SJohn.Forte@Sun.COM } else {
44657836SJohn.Forte@Sun.COM (void) strcpy(m_phys_path, wwn_list_ptr->physical_path);
44667836SJohn.Forte@Sun.COM }
44677836SJohn.Forte@Sun.COM
44687836SJohn.Forte@Sun.COM if (strcasecmp(m_phys_path, path) == 0) {
44697836SJohn.Forte@Sun.COM (void) strcpy(node_wwn_s, wwn_list_ptr->node_wwn_s);
44707836SJohn.Forte@Sun.COM break;
44717836SJohn.Forte@Sun.COM }
44727836SJohn.Forte@Sun.COM }
44737836SJohn.Forte@Sun.COM
44747836SJohn.Forte@Sun.COM if (*node_wwn_s == NULL) {
44757836SJohn.Forte@Sun.COM H_DPRINTF("node_wwn_s is NULL!\n");
44767836SJohn.Forte@Sun.COM return (L_NO_NODE_WWN_IN_WWNLIST);
44777836SJohn.Forte@Sun.COM }
44787836SJohn.Forte@Sun.COM
44797836SJohn.Forte@Sun.COM lun_a = g_get_lun_number(wwn_list_ptr->physical_path);
44807836SJohn.Forte@Sun.COM
44817836SJohn.Forte@Sun.COM for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4482*11547SBill.Gumbrell@Sun.COM wwn_list_ptr = wwn_list_ptr->wwn_next) {
44837836SJohn.Forte@Sun.COM if ((strcmp(node_wwn_s, wwn_list_ptr->node_wwn_s) == 0) &&
4484*11547SBill.Gumbrell@Sun.COM ((lun_a < 0) || (lun_a ==
4485*11547SBill.Gumbrell@Sun.COM g_get_lun_number(wwn_list_ptr->physical_path)))) {
44867836SJohn.Forte@Sun.COM
44877836SJohn.Forte@Sun.COM if ((dl = (struct dlist *)
4488*11547SBill.Gumbrell@Sun.COM g_zalloc(sizeof (struct dlist))) == NULL) {
44897836SJohn.Forte@Sun.COM while (*multipath_list != NULL) {
44907836SJohn.Forte@Sun.COM dl = dlt->next;
44917836SJohn.Forte@Sun.COM (void) g_destroy_data(dlt);
44927836SJohn.Forte@Sun.COM dlt = dl;
44937836SJohn.Forte@Sun.COM }
44947836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
44957836SJohn.Forte@Sun.COM }
44967836SJohn.Forte@Sun.COM H_DPRINTF(" g_get_multipath: Found multipath=%s\n",
4497*11547SBill.Gumbrell@Sun.COM wwn_list_ptr->physical_path);
44987836SJohn.Forte@Sun.COM dl->dev_path = strdup(wwn_list_ptr->physical_path);
44997836SJohn.Forte@Sun.COM dl->logical_path = strdup(wwn_list_ptr->logical_path);
45007836SJohn.Forte@Sun.COM if (*multipath_list == NULL) {
45017836SJohn.Forte@Sun.COM *multipath_list = dlt = dl;
45027836SJohn.Forte@Sun.COM } else {
45037836SJohn.Forte@Sun.COM dlt->next = dl;
45047836SJohn.Forte@Sun.COM dl->prev = dlt;
45057836SJohn.Forte@Sun.COM dlt = dl;
45067836SJohn.Forte@Sun.COM }
45077836SJohn.Forte@Sun.COM }
45087836SJohn.Forte@Sun.COM }
45097836SJohn.Forte@Sun.COM return (0);
45107836SJohn.Forte@Sun.COM }
45117836SJohn.Forte@Sun.COM
45127836SJohn.Forte@Sun.COM /*
45137836SJohn.Forte@Sun.COM * Free a multipath list
45147836SJohn.Forte@Sun.COM *
45157836SJohn.Forte@Sun.COM */
45167836SJohn.Forte@Sun.COM void
g_free_multipath(struct dlist * dlh)45177836SJohn.Forte@Sun.COM g_free_multipath(struct dlist *dlh)
45187836SJohn.Forte@Sun.COM {
4519*11547SBill.Gumbrell@Sun.COM struct dlist *dl;
45207836SJohn.Forte@Sun.COM
45217836SJohn.Forte@Sun.COM while (dlh != NULL) {
45227836SJohn.Forte@Sun.COM dl = dlh->next;
45237836SJohn.Forte@Sun.COM if (dlh->dev_path != NULL)
45247836SJohn.Forte@Sun.COM (void) g_destroy_data(dlh->dev_path);
45257836SJohn.Forte@Sun.COM if (dlh->logical_path != NULL)
45267836SJohn.Forte@Sun.COM (void) g_destroy_data(dlh->logical_path);
45277836SJohn.Forte@Sun.COM (void) g_destroy_data(dlh);
45287836SJohn.Forte@Sun.COM dlh = dl;
45297836SJohn.Forte@Sun.COM }
45307836SJohn.Forte@Sun.COM }
45317836SJohn.Forte@Sun.COM
45327836SJohn.Forte@Sun.COM
45337836SJohn.Forte@Sun.COM
45347836SJohn.Forte@Sun.COM /*
45357836SJohn.Forte@Sun.COM * Get the path to the nexus (HBA) driver.
45367836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
45377836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
45387836SJohn.Forte@Sun.COM * or maybe this
45397836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0
45407836SJohn.Forte@Sun.COM * or
45417836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0
45427836SJohn.Forte@Sun.COM * or
45437836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
45447836SJohn.Forte@Sun.COM * or
45457836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
45467836SJohn.Forte@Sun.COM * (or "qlc" instead of "socal" and "fp" for "sf")
45477836SJohn.Forte@Sun.COM *
45487836SJohn.Forte@Sun.COM * Which should resolve to a path like this:
45497836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
45507836SJohn.Forte@Sun.COM * or
45517836SJohn.Forte@Sun.COM * /devices/pci@6,2000/pci@2/SUNW,qlc@5
45527836SJohn.Forte@Sun.COM *
45537836SJohn.Forte@Sun.COM * or
45547836SJohn.Forte@Sun.COM * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0
45557836SJohn.Forte@Sun.COM * which should resolve to
45567836SJohn.Forte@Sun.COM * /devices/pci@4,2000/scsi@1:devctl
45577836SJohn.Forte@Sun.COM */
45587836SJohn.Forte@Sun.COM int
g_get_nexus_path(char * path_phys,char ** nexus_path)45597836SJohn.Forte@Sun.COM g_get_nexus_path(char *path_phys, char **nexus_path)
45607836SJohn.Forte@Sun.COM {
4561*11547SBill.Gumbrell@Sun.COM uchar_t port = 0;
4562*11547SBill.Gumbrell@Sun.COM int port_flag = 0, i = 0, pathcnt = 1;
4563*11547SBill.Gumbrell@Sun.COM char *char_ptr;
4564*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN];
4565*11547SBill.Gumbrell@Sun.COM char buf[MAXPATHLEN];
4566*11547SBill.Gumbrell@Sun.COM char temp_buf[MAXPATHLEN];
4567*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
4568*11547SBill.Gumbrell@Sun.COM uint_t path_type;
4569*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
4570*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0;
45717836SJohn.Forte@Sun.COM
45727836SJohn.Forte@Sun.COM /* return invalid path if the path_phys is NULL */
45737836SJohn.Forte@Sun.COM if (path_phys == NULL) {
45747836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
45757836SJohn.Forte@Sun.COM }
45767836SJohn.Forte@Sun.COM
45777836SJohn.Forte@Sun.COM *nexus_path = NULL;
45787836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path_phys);
45797836SJohn.Forte@Sun.COM
45807836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI)) {
45817836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path, &pathlist)) {
45827836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
45837836SJohn.Forte@Sun.COM }
45847836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
45857836SJohn.Forte@Sun.COM p_on = p_st = 0;
45867836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
45877836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
45887836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
4589*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
45907836SJohn.Forte@Sun.COM p_on = i;
45917836SJohn.Forte@Sun.COM break;
45927836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
4593*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
45947836SJohn.Forte@Sun.COM p_st = i;
45957836SJohn.Forte@Sun.COM }
45967836SJohn.Forte@Sun.COM }
45977836SJohn.Forte@Sun.COM }
45987836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
45997836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
46007836SJohn.Forte@Sun.COM /* on_line path */
46017836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
4602*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
46037836SJohn.Forte@Sun.COM } else {
46047836SJohn.Forte@Sun.COM /* standby or path0 */
46057836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
4606*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
46077836SJohn.Forte@Sun.COM }
46087836SJohn.Forte@Sun.COM free(pathlist.path_info);
46097836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
46107836SJohn.Forte@Sun.COM } else {
46117836SJohn.Forte@Sun.COM if (strstr(drvr_path, DRV_NAME_SSD) || strstr(drvr_path,
4612*11547SBill.Gumbrell@Sun.COM DRV_NAME_ST) || strstr(drvr_path, SES_NAME)) {
46137836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
46147836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
46157836SJohn.Forte@Sun.COM }
46167836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate string */
46177836SJohn.Forte@Sun.COM }
46187836SJohn.Forte@Sun.COM
46197836SJohn.Forte@Sun.COM path_type = g_get_path_type(drvr_path);
46207836SJohn.Forte@Sun.COM
46217836SJohn.Forte@Sun.COM if (path_type & FC4_SF_XPORT) {
46227836SJohn.Forte@Sun.COM
46237836SJohn.Forte@Sun.COM /* sf driver in path so capture the port # */
46247836SJohn.Forte@Sun.COM if ((char_ptr = strstr(drvr_path, "sf@")) == NULL) {
46257836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
46267836SJohn.Forte@Sun.COM }
46277836SJohn.Forte@Sun.COM port = atoi(char_ptr + 3);
46287836SJohn.Forte@Sun.COM if (port > 1) {
46297836SJohn.Forte@Sun.COM return (L_INVLD_PORT_IN_PATH);
46307836SJohn.Forte@Sun.COM }
46317836SJohn.Forte@Sun.COM
46327836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
46337836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
46347836SJohn.Forte@Sun.COM }
46357836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate string */
46367836SJohn.Forte@Sun.COM port_flag++;
46377836SJohn.Forte@Sun.COM
46387836SJohn.Forte@Sun.COM L_DPRINTF(" g_get_nexus_path:"
4639*11547SBill.Gumbrell@Sun.COM " sf driver in path so use port #%d.\n",
4640*11547SBill.Gumbrell@Sun.COM port);
46417836SJohn.Forte@Sun.COM } else if (path_type & FC_GEN_XPORT) {
46427836SJohn.Forte@Sun.COM /*
46437836SJohn.Forte@Sun.COM * check to see if it 3rd party vendor FCA.
46447836SJohn.Forte@Sun.COM * if it is return error for this operation since
46457836SJohn.Forte@Sun.COM * we don't know how they creates FCA port related minor node.
46467836SJohn.Forte@Sun.COM *
46477836SJohn.Forte@Sun.COM * As of now there is no supported operation on FCA node so
46487836SJohn.Forte@Sun.COM * this should be okay.
46497836SJohn.Forte@Sun.COM */
46507836SJohn.Forte@Sun.COM if ((path_type & FC_FCA_MASK) == FC_FCA_MASK) {
46517836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
46527836SJohn.Forte@Sun.COM }
46537836SJohn.Forte@Sun.COM /*
46547836SJohn.Forte@Sun.COM * For current Sun FCA driver, appending
46557836SJohn.Forte@Sun.COM * port # doesn't work. Just remove transport layer from
46567836SJohn.Forte@Sun.COM * input path.
46577836SJohn.Forte@Sun.COM */
46587836SJohn.Forte@Sun.COM if ((char_ptr = strstr(drvr_path, "/fp@")) == NULL) {
46597836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
46607836SJohn.Forte@Sun.COM }
46617836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate string */
46627836SJohn.Forte@Sun.COM }
46637836SJohn.Forte@Sun.COM
46647836SJohn.Forte@Sun.COM if (stat(drvr_path, &stbuf) != 0) {
46657836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
46667836SJohn.Forte@Sun.COM }
46677836SJohn.Forte@Sun.COM
46687836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
46697836SJohn.Forte@Sun.COM /*
46707836SJohn.Forte@Sun.COM * Found a directory.
46717836SJohn.Forte@Sun.COM * Now append a port number or devctl to the path.
46727836SJohn.Forte@Sun.COM */
46737836SJohn.Forte@Sun.COM if (port_flag) {
46747836SJohn.Forte@Sun.COM /* append port */
46757836SJohn.Forte@Sun.COM (void) sprintf(buf, ":%d", port);
46767836SJohn.Forte@Sun.COM } else {
46777836SJohn.Forte@Sun.COM /* Try adding port 0 and see if node exists. */
46787836SJohn.Forte@Sun.COM (void) sprintf(temp_buf, "%s:0", drvr_path);
46797836SJohn.Forte@Sun.COM if (stat(temp_buf, &stbuf) != 0) {
46807836SJohn.Forte@Sun.COM /*
46817836SJohn.Forte@Sun.COM * Path we guessed at does not
46827836SJohn.Forte@Sun.COM * exist so it may be a driver
46837836SJohn.Forte@Sun.COM * that ends in :devctl.
46847836SJohn.Forte@Sun.COM */
46857836SJohn.Forte@Sun.COM (void) sprintf(buf, ":devctl");
46867836SJohn.Forte@Sun.COM } else {
46877836SJohn.Forte@Sun.COM /*
46887836SJohn.Forte@Sun.COM * The path that was entered
46897836SJohn.Forte@Sun.COM * did not include a port number
46907836SJohn.Forte@Sun.COM * so the port was set to zero, and
46917836SJohn.Forte@Sun.COM * then checked. The default path
46927836SJohn.Forte@Sun.COM * did exist.
46937836SJohn.Forte@Sun.COM */
46947836SJohn.Forte@Sun.COM ER_DPRINTF("Since a complete path"
4695*11547SBill.Gumbrell@Sun.COM " was not supplied "
4696*11547SBill.Gumbrell@Sun.COM "a default path is being"
4697*11547SBill.Gumbrell@Sun.COM " used:\n %s\n",
4698*11547SBill.Gumbrell@Sun.COM temp_buf);
46997836SJohn.Forte@Sun.COM (void) sprintf(buf, ":0");
47007836SJohn.Forte@Sun.COM }
47017836SJohn.Forte@Sun.COM }
47027836SJohn.Forte@Sun.COM
47037836SJohn.Forte@Sun.COM (void) strcat(drvr_path, buf);
47047836SJohn.Forte@Sun.COM }
47057836SJohn.Forte@Sun.COM
47067836SJohn.Forte@Sun.COM }
47077836SJohn.Forte@Sun.COM *nexus_path = g_alloc_string(drvr_path);
47087836SJohn.Forte@Sun.COM L_DPRINTF(" g_get_nexus_path: Nexus path = %s\n", drvr_path);
47097836SJohn.Forte@Sun.COM return (0);
47107836SJohn.Forte@Sun.COM }
47117836SJohn.Forte@Sun.COM
47127836SJohn.Forte@Sun.COM
47137836SJohn.Forte@Sun.COM /*
47147836SJohn.Forte@Sun.COM * Get the FC topology for the input device or nexus(HBA) path.
47157836SJohn.Forte@Sun.COM *
47167836SJohn.Forte@Sun.COM * The routine calls g_get_path_type to determine the stack of
47177836SJohn.Forte@Sun.COM * the input path.
47187836SJohn.Forte@Sun.COM *
47197836SJohn.Forte@Sun.COM * If it a socal path
47207836SJohn.Forte@Sun.COM * it returns FC_TOP_PRIVATE_LOOP
47217836SJohn.Forte@Sun.COM * else
47227836SJohn.Forte@Sun.COM * calls fc_get_topology ioctl to
47237836SJohn.Forte@Sun.COM * get the fp topolgy from the driver.
47247836SJohn.Forte@Sun.COM *
47257836SJohn.Forte@Sun.COM * INPUTS:
47267836SJohn.Forte@Sun.COM * path - a string of device path, transport path.
47277836SJohn.Forte@Sun.COM * NOTE: "path" SHOULD NOT BE OPEN BEFORE CALLING
47287836SJohn.Forte@Sun.COM * THIS FUNCTION BECAUSE THIS FUNCTION DOES
47297836SJohn.Forte@Sun.COM * AN "O_EXCL" OPEN.
47307836SJohn.Forte@Sun.COM * port_top - a pointer to the toplogy type.
47317836SJohn.Forte@Sun.COM *
47327836SJohn.Forte@Sun.COM * RETURNS:
47337836SJohn.Forte@Sun.COM * 0 if there is no error.
47347836SJohn.Forte@Sun.COM * error code.
47357836SJohn.Forte@Sun.COM *
47367836SJohn.Forte@Sun.COM * The input path is expected to be something like below:
47377836SJohn.Forte@Sun.COM * 1)
47387836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
47397836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ssd@..
47407836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0
47417836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0
47427836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
47437836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
47447836SJohn.Forte@Sun.COM * (or "qlc" instead of "socal" and "fp" for "sf")
47457836SJohn.Forte@Sun.COM *
47467836SJohn.Forte@Sun.COM * Which should resolve to a path like this:
47477836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
47487836SJohn.Forte@Sun.COM * /devices/pci@6,2000/pci@2/SUNW,qlc@5
47497836SJohn.Forte@Sun.COM *
47507836SJohn.Forte@Sun.COM * 2)
47517836SJohn.Forte@Sun.COM * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0
47527836SJohn.Forte@Sun.COM * which should resolve to
47537836SJohn.Forte@Sun.COM * /devices/pci@4,2000/scsi@1:devctl
47547836SJohn.Forte@Sun.COM *
47557836SJohn.Forte@Sun.COM * 3) The nexus(hba or nexus) path will get an error only for qlc
47567836SJohn.Forte@Sun.COM * since the routine need to open fp :devctl node for fcio ioctl.
47577836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0
47587836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0:1
47597836SJohn.Forte@Sun.COM * /devices/pci@6,2000/pci@2/SUNW,qlc@5 => error
47607836SJohn.Forte@Sun.COM */
47617836SJohn.Forte@Sun.COM int
g_get_fca_port_topology(char * path,uint32_t * port_top,int verbose)47627836SJohn.Forte@Sun.COM g_get_fca_port_topology(char *path, uint32_t *port_top, int verbose)
47637836SJohn.Forte@Sun.COM {
4764*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
4765*11547SBill.Gumbrell@Sun.COM int fd, i = 0, pathcnt = 1;
4766*11547SBill.Gumbrell@Sun.COM char drvr_path[MAXPATHLEN];
4767*11547SBill.Gumbrell@Sun.COM char *char_ptr;
4768*11547SBill.Gumbrell@Sun.COM struct stat stbuf;
4769*11547SBill.Gumbrell@Sun.COM uint_t dev_type;
4770*11547SBill.Gumbrell@Sun.COM mp_pathlist_t pathlist;
4771*11547SBill.Gumbrell@Sun.COM int p_on = 0, p_st = 0;
47727836SJohn.Forte@Sun.COM
47737836SJohn.Forte@Sun.COM /* return invalid path if the path is NULL */
47747836SJohn.Forte@Sun.COM if (path == NULL) {
47757836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
47767836SJohn.Forte@Sun.COM }
47777836SJohn.Forte@Sun.COM /* return invalid arg if the argument is NULL */
47787836SJohn.Forte@Sun.COM if (port_top == NULL) {
47797836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
47807836SJohn.Forte@Sun.COM }
47817836SJohn.Forte@Sun.COM
47827836SJohn.Forte@Sun.COM (void) strcpy(drvr_path, path);
47837836SJohn.Forte@Sun.COM if (strstr(path, SCSI_VHCI)) {
47847836SJohn.Forte@Sun.COM if (g_get_pathlist(drvr_path, &pathlist)) {
47857836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
47867836SJohn.Forte@Sun.COM }
47877836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
47887836SJohn.Forte@Sun.COM p_on = p_st = 0;
47897836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
47907836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
47917836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
4792*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
47937836SJohn.Forte@Sun.COM p_on = i;
47947836SJohn.Forte@Sun.COM break;
47957836SJohn.Forte@Sun.COM } else if (pathlist.path_info[i].path_state ==
4796*11547SBill.Gumbrell@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
47977836SJohn.Forte@Sun.COM p_st = i;
47987836SJohn.Forte@Sun.COM }
47997836SJohn.Forte@Sun.COM }
48007836SJohn.Forte@Sun.COM }
48017836SJohn.Forte@Sun.COM if (pathlist.path_info[p_on].path_state ==
48027836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
48037836SJohn.Forte@Sun.COM /* on_line path */
48047836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
4805*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_on].path_hba);
48067836SJohn.Forte@Sun.COM } else {
48077836SJohn.Forte@Sun.COM /* standby or path0 */
48087836SJohn.Forte@Sun.COM (void) strcpy(drvr_path,
4809*11547SBill.Gumbrell@Sun.COM pathlist.path_info[p_st].path_hba);
48107836SJohn.Forte@Sun.COM }
48117836SJohn.Forte@Sun.COM free(pathlist.path_info);
48127836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
48137836SJohn.Forte@Sun.COM } else {
48147836SJohn.Forte@Sun.COM /*
48157836SJohn.Forte@Sun.COM * Get the path to the :devctl driver
48167836SJohn.Forte@Sun.COM *
48177836SJohn.Forte@Sun.COM * This assumes the path looks something like this:
48187836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
48197836SJohn.Forte@Sun.COM * or
48207836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
48217836SJohn.Forte@Sun.COM * or
48227836SJohn.Forte@Sun.COM * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
48237836SJohn.Forte@Sun.COM * or
48247836SJohn.Forte@Sun.COM * a 1 level PCI type driver but still :devctl
48257836SJohn.Forte@Sun.COM * (or "qlc" in the place of "socal" and "fp" for "sf")
48267836SJohn.Forte@Sun.COM *
48277836SJohn.Forte@Sun.COM * The dir below doesn't have corresponding :devctl node.
48287836SJohn.Forte@Sun.COM * /devices/pci@6,2000/pci@2/SUNW,qlc@5
48297836SJohn.Forte@Sun.COM * /devices/sbus@2,0/SUNW,socal@1,0
48307836SJohn.Forte@Sun.COM *
48317836SJohn.Forte@Sun.COM */
48327836SJohn.Forte@Sun.COM if ((strstr(drvr_path, DRV_NAME_SSD) ||
4833*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, SES_NAME)) ||
4834*11547SBill.Gumbrell@Sun.COM strstr(drvr_path, DRV_NAME_ST)) {
48357836SJohn.Forte@Sun.COM if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
48367836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
48377836SJohn.Forte@Sun.COM }
48387836SJohn.Forte@Sun.COM *char_ptr = '\0'; /* Terminate sting */
48397836SJohn.Forte@Sun.COM /* append controller */
48407836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
48417836SJohn.Forte@Sun.COM } else {
48427836SJohn.Forte@Sun.COM if (stat(drvr_path, &stbuf) < 0) {
48437836SJohn.Forte@Sun.COM return (L_LSTAT_ERROR);
48447836SJohn.Forte@Sun.COM }
48457836SJohn.Forte@Sun.COM if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
48467836SJohn.Forte@Sun.COM /* append controller */
48477836SJohn.Forte@Sun.COM (void) strcat(drvr_path, FC_CTLR);
48487836SJohn.Forte@Sun.COM }
48497836SJohn.Forte@Sun.COM }
48507836SJohn.Forte@Sun.COM }
48517836SJohn.Forte@Sun.COM
48527836SJohn.Forte@Sun.COM if ((dev_type = g_get_path_type(drvr_path)) == 0) {
48537836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
48547836SJohn.Forte@Sun.COM }
48557836SJohn.Forte@Sun.COM
48567836SJohn.Forte@Sun.COM if ((dev_type & FC4_XPORT_MASK) || (dev_type & FC4_FCA_MASK)) {
48577836SJohn.Forte@Sun.COM *port_top = FC_TOP_PRIVATE_LOOP;
48587836SJohn.Forte@Sun.COM return (0);
48597836SJohn.Forte@Sun.COM }
48607836SJohn.Forte@Sun.COM
48617836SJohn.Forte@Sun.COM /* To contiue the path type should be fp :devctl node */
48627836SJohn.Forte@Sun.COM if (!(dev_type & FC_XPORT_MASK)) {
48637836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
48647836SJohn.Forte@Sun.COM }
48657836SJohn.Forte@Sun.COM
48667836SJohn.Forte@Sun.COM if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
48677836SJohn.Forte@Sun.COM return (errno);
48687836SJohn.Forte@Sun.COM
48697836SJohn.Forte@Sun.COM P_DPRINTF(" g_get_fca_port_topology: Geting topology from:"
4870*11547SBill.Gumbrell@Sun.COM " %s\n", drvr_path);
48717836SJohn.Forte@Sun.COM
48727836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_TOPOLOGY;
48737836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (uint32_t);
48747836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
48757836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)port_top;
48767836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
48777836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GET_TOPOLOGY ioctl failed.\n");
48787836SJohn.Forte@Sun.COM close(fd);
48797836SJohn.Forte@Sun.COM return (L_FCIO_GET_TOPOLOGY_FAIL);
48807836SJohn.Forte@Sun.COM }
48817836SJohn.Forte@Sun.COM close(fd);
48827836SJohn.Forte@Sun.COM return (0);
48837836SJohn.Forte@Sun.COM }
48847836SJohn.Forte@Sun.COM
48857836SJohn.Forte@Sun.COM
48867836SJohn.Forte@Sun.COM /*
48877836SJohn.Forte@Sun.COM * This functions enables or disables a FCA port depending on the
48887836SJohn.Forte@Sun.COM * argument, cmd, passed to it. If cmd is PORT_OFFLINE, the function
48897836SJohn.Forte@Sun.COM * tries to disable the port specified by the argument 'phys_path'. If
48907836SJohn.Forte@Sun.COM * cmd is PORT_ONLINE, the function tries to enable the port specified
48917836SJohn.Forte@Sun.COM * by the argument 'phys_path'.
48927836SJohn.Forte@Sun.COM * INPUTS :
48937836SJohn.Forte@Sun.COM * nexus_port_ptr - Pointer to the nexus path of the FCA port to
48947836SJohn.Forte@Sun.COM * operate on
48957836SJohn.Forte@Sun.COM * cmd - PORT_OFFLINE or PORT_ONLINE
48967836SJohn.Forte@Sun.COM * RETURNS :
48977836SJohn.Forte@Sun.COM * 0 on success and non-zero otherwise
48987836SJohn.Forte@Sun.COM */
48997836SJohn.Forte@Sun.COM static int
g_set_port_state(char * nexus_port_ptr,int cmd)49007836SJohn.Forte@Sun.COM g_set_port_state(char *nexus_port_ptr, int cmd)
49017836SJohn.Forte@Sun.COM {
49027836SJohn.Forte@Sun.COM int path_type, fd;
49037836SJohn.Forte@Sun.COM
49047836SJohn.Forte@Sun.COM if ((path_type = g_get_path_type(nexus_port_ptr)) == 0) {
49057836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
49067836SJohn.Forte@Sun.COM }
49077836SJohn.Forte@Sun.COM
49087836SJohn.Forte@Sun.COM if ((fd = g_object_open(nexus_port_ptr, O_NDELAY|O_RDONLY)) == -1) {
49097836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
49107836SJohn.Forte@Sun.COM }
49117836SJohn.Forte@Sun.COM
49127836SJohn.Forte@Sun.COM switch (cmd) {
49137836SJohn.Forte@Sun.COM case PORT_OFFLINE:
49147836SJohn.Forte@Sun.COM if (path_type & FC4_SOCAL_FCA) {
49157836SJohn.Forte@Sun.COM /*
49167836SJohn.Forte@Sun.COM * Socal/sf drivers -
49177836SJohn.Forte@Sun.COM * The socal driver currently returns EFAULT
49187836SJohn.Forte@Sun.COM * even if the ioctl has completed successfully.
49197836SJohn.Forte@Sun.COM */
49207836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_LOOPBACK_INTERNAL,
4921*11547SBill.Gumbrell@Sun.COM NULL) == -1) {
49227836SJohn.Forte@Sun.COM close(fd);
49237836SJohn.Forte@Sun.COM return (L_PORT_OFFLINE_FAIL);
49247836SJohn.Forte@Sun.COM }
49257836SJohn.Forte@Sun.COM } else {
49267836SJohn.Forte@Sun.COM /*
49277836SJohn.Forte@Sun.COM * QLogic card -
49287836SJohn.Forte@Sun.COM * Can't do much here since the driver currently
49297836SJohn.Forte@Sun.COM * doesn't support this feature. We'll just fail
49307836SJohn.Forte@Sun.COM * for now. Support can be added when the driver
49317836SJohn.Forte@Sun.COM * is enabled with the feature at a later date.
49327836SJohn.Forte@Sun.COM */
49337836SJohn.Forte@Sun.COM close(fd);
49347836SJohn.Forte@Sun.COM return (L_PORT_OFFLINE_UNSUPPORTED);
49357836SJohn.Forte@Sun.COM }
49367836SJohn.Forte@Sun.COM break;
49377836SJohn.Forte@Sun.COM case PORT_ONLINE:
49387836SJohn.Forte@Sun.COM if (path_type & FC4_SOCAL_FCA) {
49397836SJohn.Forte@Sun.COM /*
49407836SJohn.Forte@Sun.COM * Socal/sf drivers
49417836SJohn.Forte@Sun.COM * The socal driver currently returns EFAULT
49427836SJohn.Forte@Sun.COM * even if the ioctl has completed successfully.
49437836SJohn.Forte@Sun.COM */
49447836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) {
49457836SJohn.Forte@Sun.COM close(fd);
49467836SJohn.Forte@Sun.COM return (L_PORT_ONLINE_FAIL);
49477836SJohn.Forte@Sun.COM }
49487836SJohn.Forte@Sun.COM } else {
49497836SJohn.Forte@Sun.COM /*
49507836SJohn.Forte@Sun.COM * QLogic card -
49517836SJohn.Forte@Sun.COM * Can't do much here since the driver currently
49527836SJohn.Forte@Sun.COM * doesn't support this feature. We'll just fail
49537836SJohn.Forte@Sun.COM * for now. Support can be added when the driver
49547836SJohn.Forte@Sun.COM * is enabled with the feature at a later date.
49557836SJohn.Forte@Sun.COM */
49567836SJohn.Forte@Sun.COM close(fd);
49577836SJohn.Forte@Sun.COM return (L_PORT_ONLINE_UNSUPPORTED);
49587836SJohn.Forte@Sun.COM }
49597836SJohn.Forte@Sun.COM break;
49607836SJohn.Forte@Sun.COM default:
49617836SJohn.Forte@Sun.COM close(fd);
49627836SJohn.Forte@Sun.COM return (-1);
49637836SJohn.Forte@Sun.COM }
49647836SJohn.Forte@Sun.COM close(fd);
49657836SJohn.Forte@Sun.COM return (0);
49667836SJohn.Forte@Sun.COM }
49677836SJohn.Forte@Sun.COM
49687836SJohn.Forte@Sun.COM /*
49697836SJohn.Forte@Sun.COM * The interfaces defined below (g_port_offline() and g_port_online())
49707836SJohn.Forte@Sun.COM * are what will be exposed to applications. We will hide g_set_port_state().
49717836SJohn.Forte@Sun.COM * They have to be functions (as against macros) because making them
49727836SJohn.Forte@Sun.COM * macros will mean exposing g_set_port_state() and we dont want to do that
49737836SJohn.Forte@Sun.COM */
49747836SJohn.Forte@Sun.COM
49757836SJohn.Forte@Sun.COM int
g_port_offline(char * path)49767836SJohn.Forte@Sun.COM g_port_offline(char *path)
49777836SJohn.Forte@Sun.COM {
49787836SJohn.Forte@Sun.COM return (g_set_port_state(path, PORT_OFFLINE));
49797836SJohn.Forte@Sun.COM }
49807836SJohn.Forte@Sun.COM
49817836SJohn.Forte@Sun.COM int
g_port_online(char * path)49827836SJohn.Forte@Sun.COM g_port_online(char *path)
49837836SJohn.Forte@Sun.COM {
49847836SJohn.Forte@Sun.COM return (g_set_port_state(path, PORT_ONLINE));
49857836SJohn.Forte@Sun.COM }
49867836SJohn.Forte@Sun.COM
49877836SJohn.Forte@Sun.COM /*
49887836SJohn.Forte@Sun.COM * This function sets the loopback mode for a port on a HBA
49897836SJohn.Forte@Sun.COM * INPUTS :
49907836SJohn.Forte@Sun.COM * portpath - Pointer to the path of the FCA port on which to
49917836SJohn.Forte@Sun.COM * set the loopback mode
49927836SJohn.Forte@Sun.COM * cmd - EXT_LPBACK
49937836SJohn.Forte@Sun.COM * INT_LPBACK
49947836SJohn.Forte@Sun.COM * NO_LPBACK
49957836SJohn.Forte@Sun.COM * RETURNS :
49967836SJohn.Forte@Sun.COM * 0 on success and non-zero otherwise
49977836SJohn.Forte@Sun.COM */
49987836SJohn.Forte@Sun.COM int
g_loopback_mode(char * portpath,int cmd)49997836SJohn.Forte@Sun.COM g_loopback_mode(char *portpath, int cmd)
50007836SJohn.Forte@Sun.COM {
50017836SJohn.Forte@Sun.COM int path_type, fd;
50027836SJohn.Forte@Sun.COM
50037836SJohn.Forte@Sun.COM if ((path_type = g_get_path_type(portpath)) == 0) {
50047836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
50057836SJohn.Forte@Sun.COM }
50067836SJohn.Forte@Sun.COM
50077836SJohn.Forte@Sun.COM if ((fd = g_object_open(portpath, O_NDELAY|O_RDONLY|O_EXCL)) == -1) {
50087836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
50097836SJohn.Forte@Sun.COM }
50107836SJohn.Forte@Sun.COM
50117836SJohn.Forte@Sun.COM /*
50127836SJohn.Forte@Sun.COM * The loopback calls are currently not fully supported
50137836SJohn.Forte@Sun.COM * via fp.
50147836SJohn.Forte@Sun.COM *
50157836SJohn.Forte@Sun.COM * A fp based general solution is required to support Leadville FCAs
50167836SJohn.Forte@Sun.COM * including Qlgc and 3rd party FCA. As of now qlgc provides
50177836SJohn.Forte@Sun.COM * some diag functions like echo through qlc private ioctl
50187836SJohn.Forte@Sun.COM * which is not supproted by luxadm and libraries.
50197836SJohn.Forte@Sun.COM */
50207836SJohn.Forte@Sun.COM switch (cmd) {
50217836SJohn.Forte@Sun.COM case EXT_LPBACK:
50227836SJohn.Forte@Sun.COM if (path_type & FC4_SOCAL_FCA) {
50237836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_LOOPBACK_MANUAL,
5024*11547SBill.Gumbrell@Sun.COM NULL) == -1) {
50257836SJohn.Forte@Sun.COM /* Check for previous mode set */
50267836SJohn.Forte@Sun.COM if (errno != EALREADY) {
50277836SJohn.Forte@Sun.COM close(fd);
50287836SJohn.Forte@Sun.COM return (L_LOOPBACK_FAILED);
50297836SJohn.Forte@Sun.COM }
50307836SJohn.Forte@Sun.COM }
50317836SJohn.Forte@Sun.COM } else {
50327836SJohn.Forte@Sun.COM /*
50337836SJohn.Forte@Sun.COM * Well, it wasn't one of the above cards so..
50347836SJohn.Forte@Sun.COM */
50357836SJohn.Forte@Sun.COM close(fd);
50367836SJohn.Forte@Sun.COM return (L_LOOPBACK_UNSUPPORTED);
50377836SJohn.Forte@Sun.COM }
50387836SJohn.Forte@Sun.COM break;
50397836SJohn.Forte@Sun.COM case NO_LPBACK:
50407836SJohn.Forte@Sun.COM if (path_type & FC4_SOCAL_FCA) {
50417836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) {
50427836SJohn.Forte@Sun.COM close(fd);
50437836SJohn.Forte@Sun.COM return (L_LOOPBACK_FAILED);
50447836SJohn.Forte@Sun.COM }
50457836SJohn.Forte@Sun.COM } else {
50467836SJohn.Forte@Sun.COM /*
50477836SJohn.Forte@Sun.COM * Well, it wasn't one of the above cards so..
50487836SJohn.Forte@Sun.COM */
50497836SJohn.Forte@Sun.COM close(fd);
50507836SJohn.Forte@Sun.COM return (L_LOOPBACK_UNSUPPORTED);
50517836SJohn.Forte@Sun.COM }
50527836SJohn.Forte@Sun.COM break;
50537836SJohn.Forte@Sun.COM case INT_LPBACK:
50547836SJohn.Forte@Sun.COM if (path_type & FC4_SOCAL_FCA) {
50557836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_LOOPBACK_INTERNAL,
5056*11547SBill.Gumbrell@Sun.COM NULL) == -1) {
50577836SJohn.Forte@Sun.COM /* Check for previous mode set */
50587836SJohn.Forte@Sun.COM if (errno != EALREADY) {
50597836SJohn.Forte@Sun.COM close(fd);
50607836SJohn.Forte@Sun.COM return (L_LOOPBACK_FAILED);
50617836SJohn.Forte@Sun.COM }
50627836SJohn.Forte@Sun.COM }
50637836SJohn.Forte@Sun.COM } else {
50647836SJohn.Forte@Sun.COM /*
50657836SJohn.Forte@Sun.COM * Well, it wasn't one of the above cards so..
50667836SJohn.Forte@Sun.COM */
50677836SJohn.Forte@Sun.COM close(fd);
50687836SJohn.Forte@Sun.COM return (L_LOOPBACK_UNSUPPORTED);
50697836SJohn.Forte@Sun.COM }
50707836SJohn.Forte@Sun.COM break;
50717836SJohn.Forte@Sun.COM default:
50727836SJohn.Forte@Sun.COM close(fd);
50737836SJohn.Forte@Sun.COM return (L_LOOPBACK_UNSUPPORTED);
50747836SJohn.Forte@Sun.COM }
50757836SJohn.Forte@Sun.COM close(fd);
50767836SJohn.Forte@Sun.COM return (0);
50777836SJohn.Forte@Sun.COM }
50787836SJohn.Forte@Sun.COM
50797836SJohn.Forte@Sun.COM /*
50807836SJohn.Forte@Sun.COM * g_get_port_state(char *portpath, int port_state)
50817836SJohn.Forte@Sun.COM * Purpose: Get port state for a path
50827836SJohn.Forte@Sun.COM * Input: portpath
50837836SJohn.Forte@Sun.COM * set to path of port
50847836SJohn.Forte@Sun.COM * Output: port_state
50857836SJohn.Forte@Sun.COM * Set to one of the following:
50867836SJohn.Forte@Sun.COM * PORT_CONNECTED
50877836SJohn.Forte@Sun.COM * PORT_NOTCONNECTED
50887836SJohn.Forte@Sun.COM * Returns: 0 on success
50897836SJohn.Forte@Sun.COM * non-zero on failure
50907836SJohn.Forte@Sun.COM */
50917836SJohn.Forte@Sun.COM int
g_get_port_state(char * portpath,int * portstate,int verbose)50927836SJohn.Forte@Sun.COM g_get_port_state(char *portpath, int *portstate, int verbose)
50937836SJohn.Forte@Sun.COM {
50947836SJohn.Forte@Sun.COM int fd, err, num_devices = 0;
50957836SJohn.Forte@Sun.COM struct lilpmap map;
50967836SJohn.Forte@Sun.COM uint_t dev_type;
50977836SJohn.Forte@Sun.COM gfc_dev_t map_root;
50987836SJohn.Forte@Sun.COM
50997836SJohn.Forte@Sun.COM
51007836SJohn.Forte@Sun.COM (void) memset(&map, 0, sizeof (struct lilpmap));
51017836SJohn.Forte@Sun.COM
51027836SJohn.Forte@Sun.COM /* return invalid path if portpath is NULL */
51037836SJohn.Forte@Sun.COM if (portpath == NULL) {
51047836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
51057836SJohn.Forte@Sun.COM }
51067836SJohn.Forte@Sun.COM /* return invalid arg if argument is NULL */
51077836SJohn.Forte@Sun.COM if ((portpath == NULL) || (portstate == NULL)) {
51087836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
51097836SJohn.Forte@Sun.COM }
51107836SJohn.Forte@Sun.COM
51117836SJohn.Forte@Sun.COM if ((dev_type = g_get_path_type(portpath)) == 0) {
51127836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
51137836SJohn.Forte@Sun.COM }
51147836SJohn.Forte@Sun.COM
51157836SJohn.Forte@Sun.COM /*
51167836SJohn.Forte@Sun.COM * FCIO_GETMAP returns error when there are * no devices attached.
51177836SJohn.Forte@Sun.COM * ENOMEM is returned when no devices are attached.
51187836SJohn.Forte@Sun.COM * g_get_first_dev returns NULL without error when there is no
51197836SJohn.Forte@Sun.COM * devices are attached.
51207836SJohn.Forte@Sun.COM */
51217836SJohn.Forte@Sun.COM if (dev_type & FC_FCA_MASK) {
51227836SJohn.Forte@Sun.COM if ((map_root = g_dev_map_init(portpath, &err,
5123*11547SBill.Gumbrell@Sun.COM MAP_XPORT_PROP_ONLY)) == NULL) {
51247836SJohn.Forte@Sun.COM return (err);
51257836SJohn.Forte@Sun.COM }
51267836SJohn.Forte@Sun.COM
51277836SJohn.Forte@Sun.COM if (g_get_first_dev(map_root, &err) == NULL) {
51287836SJohn.Forte@Sun.COM /* no device is found if err == 0 */
51297836SJohn.Forte@Sun.COM if (err == L_NO_SUCH_DEV_FOUND) {
51307836SJohn.Forte@Sun.COM *portstate = PORT_NOTCONNECTED;
51317836SJohn.Forte@Sun.COM }
51327836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
51337836SJohn.Forte@Sun.COM return (0);
51347836SJohn.Forte@Sun.COM } else {
51357836SJohn.Forte@Sun.COM /* Device found okay */
51367836SJohn.Forte@Sun.COM *portstate = PORT_CONNECTED;
51377836SJohn.Forte@Sun.COM g_dev_map_fini(map_root);
51387836SJohn.Forte@Sun.COM }
51397836SJohn.Forte@Sun.COM
51407836SJohn.Forte@Sun.COM } else {
51417836SJohn.Forte@Sun.COM /* open controller */
51427836SJohn.Forte@Sun.COM if ((fd = g_object_open(portpath, O_NDELAY | O_RDONLY)) == -1) {
51437836SJohn.Forte@Sun.COM return (errno);
51447836SJohn.Forte@Sun.COM }
51457836SJohn.Forte@Sun.COM
51467836SJohn.Forte@Sun.COM /*
51477836SJohn.Forte@Sun.COM * Note: There is only one error returned by this ioctl. ENOMEM.
51487836SJohn.Forte@Sun.COM * Hence the lack of return on error.
51497836SJohn.Forte@Sun.COM */
51507836SJohn.Forte@Sun.COM if (ioctl(fd, FCIO_GETMAP, &map) != 0) {
51517836SJohn.Forte@Sun.COM map.lilp_length = 0;
51527836SJohn.Forte@Sun.COM }
51537836SJohn.Forte@Sun.COM num_devices = map.lilp_length;
51547836SJohn.Forte@Sun.COM
51557836SJohn.Forte@Sun.COM /* Non-Leadville stacks report the FCA in the count */
51567836SJohn.Forte@Sun.COM *portstate = (num_devices > 1) ? PORT_CONNECTED :
5157*11547SBill.Gumbrell@Sun.COM PORT_NOTCONNECTED;
51587836SJohn.Forte@Sun.COM (void) close(fd);
51597836SJohn.Forte@Sun.COM }
51607836SJohn.Forte@Sun.COM return (0);
51617836SJohn.Forte@Sun.COM }
51627836SJohn.Forte@Sun.COM
51637836SJohn.Forte@Sun.COM /*
51647836SJohn.Forte@Sun.COM * g_dev_login(char *port_path, la_wwn_t port_wwn)
51657836SJohn.Forte@Sun.COM * Purpose: port login via g_dev_log_in_out()
51667836SJohn.Forte@Sun.COM * Input: port_path
51677836SJohn.Forte@Sun.COM * fc transport port with fabric/public loop topology
51687836SJohn.Forte@Sun.COM * port_wwn
51697836SJohn.Forte@Sun.COM * port wwn of device node to login
51707836SJohn.Forte@Sun.COM *
51717836SJohn.Forte@Sun.COM * Returns: return code from g_dev_log_in_out()
51727836SJohn.Forte@Sun.COM */
51737836SJohn.Forte@Sun.COM int
g_dev_login(char * port_path,la_wwn_t port_wwn)51747836SJohn.Forte@Sun.COM g_dev_login(char *port_path, la_wwn_t port_wwn)
51757836SJohn.Forte@Sun.COM {
51767836SJohn.Forte@Sun.COM return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGIN));
51777836SJohn.Forte@Sun.COM }
51787836SJohn.Forte@Sun.COM
51797836SJohn.Forte@Sun.COM
51807836SJohn.Forte@Sun.COM /*
51817836SJohn.Forte@Sun.COM * g_dev_logout(char *port_path, la_wwn_t port_wwn)
51827836SJohn.Forte@Sun.COM * Purpose: port login via g_dev_log_in_out()
51837836SJohn.Forte@Sun.COM * Input: port_path
51847836SJohn.Forte@Sun.COM * fc transport port with fabric/public loop topology
51857836SJohn.Forte@Sun.COM * port_wwn
51867836SJohn.Forte@Sun.COM * port wwn of device node to logout
51877836SJohn.Forte@Sun.COM *
51887836SJohn.Forte@Sun.COM * Returns: return code from g_dev_log_in_out()
51897836SJohn.Forte@Sun.COM */
51907836SJohn.Forte@Sun.COM int
g_dev_logout(char * port_path,la_wwn_t port_wwn)51917836SJohn.Forte@Sun.COM g_dev_logout(char *port_path, la_wwn_t port_wwn)
51927836SJohn.Forte@Sun.COM {
51937836SJohn.Forte@Sun.COM return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGOUT));
51947836SJohn.Forte@Sun.COM }
51957836SJohn.Forte@Sun.COM
51967836SJohn.Forte@Sun.COM
51977836SJohn.Forte@Sun.COM /*
51987836SJohn.Forte@Sun.COM * g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd)
51997836SJohn.Forte@Sun.COM * Purpose: port login via FCIO_DEV_LOGOUT and port logout via FCIO_DEV_LOGOUT
52007836SJohn.Forte@Sun.COM * IOCTL requires EXCLUSIVE open.
52017836SJohn.Forte@Sun.COM * Input: port_path
52027836SJohn.Forte@Sun.COM * fc transport port with fabric/public loop topology
52037836SJohn.Forte@Sun.COM * port_wwn
52047836SJohn.Forte@Sun.COM * port wwn of device node to logout
52057836SJohn.Forte@Sun.COM * cmd
52067836SJohn.Forte@Sun.COM * FCIO_DEV_LOGON or FCIO_DEV_LOGOUT
52077836SJohn.Forte@Sun.COM *
52087836SJohn.Forte@Sun.COM * Returns: 0 on success
52097836SJohn.Forte@Sun.COM * non-zero on failure
52107836SJohn.Forte@Sun.COM */
52117836SJohn.Forte@Sun.COM static int
g_dev_log_in_out(char * port_path,la_wwn_t port_wwn,uint16_t cmd)52127836SJohn.Forte@Sun.COM g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd)
52137836SJohn.Forte@Sun.COM {
5214*11547SBill.Gumbrell@Sun.COM int fd, err;
5215*11547SBill.Gumbrell@Sun.COM uint32_t hba_port_top;
5216*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
5217*11547SBill.Gumbrell@Sun.COM int verbose = 0;
52187836SJohn.Forte@Sun.COM
52197836SJohn.Forte@Sun.COM if ((err = g_get_fca_port_topology(port_path,
5220*11547SBill.Gumbrell@Sun.COM &hba_port_top, verbose)) != 0) {
52217836SJohn.Forte@Sun.COM return (err);
52227836SJohn.Forte@Sun.COM }
52237836SJohn.Forte@Sun.COM
52247836SJohn.Forte@Sun.COM if (!((hba_port_top == FC_TOP_PUBLIC_LOOP) ||
5225*11547SBill.Gumbrell@Sun.COM (hba_port_top == FC_TOP_FABRIC))) {
52267836SJohn.Forte@Sun.COM return (L_OPNOSUPP_ON_TOPOLOGY);
52277836SJohn.Forte@Sun.COM }
52287836SJohn.Forte@Sun.COM
52297836SJohn.Forte@Sun.COM /* open controller */
52307836SJohn.Forte@Sun.COM if ((fd = g_object_open(port_path, O_NDELAY | O_RDONLY | O_EXCL)) == -1)
52317836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
52327836SJohn.Forte@Sun.COM
52337836SJohn.Forte@Sun.COM /*
52347836SJohn.Forte@Sun.COM * stores port_wwn to la_wwn_t raw_wwn field
52357836SJohn.Forte@Sun.COM * and construct fcio structures for FCIO_DEV_LOGIN.
52367836SJohn.Forte@Sun.COM */
52377836SJohn.Forte@Sun.COM fcio.fcio_cmd = cmd;
52387836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (port_wwn);
52397836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&port_wwn;
52407836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_WRITE;
52417836SJohn.Forte@Sun.COM fcio.fcio_olen = fcio.fcio_alen = 0;
52427836SJohn.Forte@Sun.COM fcio.fcio_obuf = fcio.fcio_abuf = NULL;
52437836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
52447836SJohn.Forte@Sun.COM I_DPRINTF((cmd == FCIO_DEV_LOGIN) ?
5245*11547SBill.Gumbrell@Sun.COM " FCIO_DEV_LOGIN ioctl failed.\n"
5246*11547SBill.Gumbrell@Sun.COM : " FCIO_DEV_LOGOUT ioctl failed.\n");
52477836SJohn.Forte@Sun.COM (void) close(fd);
52487836SJohn.Forte@Sun.COM return ((cmd == FCIO_DEV_LOGIN) ?
5249*11547SBill.Gumbrell@Sun.COM L_FCIO_DEV_LOGIN_FAIL
5250*11547SBill.Gumbrell@Sun.COM : L_FCIO_DEV_LOGOUT_FAIL);
52517836SJohn.Forte@Sun.COM } else {
52527836SJohn.Forte@Sun.COM (void) close(fd);
52537836SJohn.Forte@Sun.COM return (0);
52547836SJohn.Forte@Sun.COM }
52557836SJohn.Forte@Sun.COM }
52567836SJohn.Forte@Sun.COM
52577836SJohn.Forte@Sun.COM /*
52587836SJohn.Forte@Sun.COM * This function will verify if a FC device (represented by input WWN
52597836SJohn.Forte@Sun.COM * is connected on a FCA port by searching the device list from
52607836SJohn.Forte@Sun.COM * g_get_dev_list() for a WWN match.
52617836SJohn.Forte@Sun.COM *
52627836SJohn.Forte@Sun.COM * input:
52637836SJohn.Forte@Sun.COM * fca_path: pointer to the physical path string, path to a fp node.
52647836SJohn.Forte@Sun.COM * possible forms are
52657836SJohn.Forte@Sun.COM * /devices/pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0:devctl
52667836SJohn.Forte@Sun.COM * dev_wwn: WWN string
52677836SJohn.Forte@Sun.COM * flag: indicate that the input WWN is node or port
52687836SJohn.Forte@Sun.COM *
52697836SJohn.Forte@Sun.COM * returned values
52707836SJohn.Forte@Sun.COM * 0: if a match is found.
52717836SJohn.Forte@Sun.COM * L_WWN_NOT_FOUND_IN_DEV_LIST: if no match found
52727836SJohn.Forte@Sun.COM * L_UNEXPECTED_FC_TOPOLOGY: existing error code for an error
52737836SJohn.Forte@Sun.COM * from the topology checking of the input fca path.
52747836SJohn.Forte@Sun.COM * L_MALLOC_FAILED: existing error code for allocation eror from the
52757836SJohn.Forte@Sun.COM * g_get_dev_list().
52767836SJohn.Forte@Sun.COM * L_FCIO_GETMAP_IOCTL_FAIL: existing error code for an error from the
52777836SJohn.Forte@Sun.COM * FCIO ioctl called by the g_get_dev_list()
52787836SJohn.Forte@Sun.COM * -1: other failure
52797836SJohn.Forte@Sun.COM *
52807836SJohn.Forte@Sun.COM */
52817836SJohn.Forte@Sun.COM int
g_wwn_in_dev_list(char * fca_path,la_wwn_t dev_wwn,int flag)52827836SJohn.Forte@Sun.COM g_wwn_in_dev_list(char *fca_path, la_wwn_t dev_wwn, int flag)
52837836SJohn.Forte@Sun.COM {
5284*11547SBill.Gumbrell@Sun.COM uint_t dev_type;
5285*11547SBill.Gumbrell@Sun.COM int i, err;
5286*11547SBill.Gumbrell@Sun.COM fc_port_dev_t *dev_list;
5287*11547SBill.Gumbrell@Sun.COM fc_port_dev_t *dev_list_save;
5288*11547SBill.Gumbrell@Sun.COM int num_devices = 0;
52897836SJohn.Forte@Sun.COM
52907836SJohn.Forte@Sun.COM if ((dev_type = g_get_path_type(fca_path)) == 0) {
52917836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
52927836SJohn.Forte@Sun.COM }
52937836SJohn.Forte@Sun.COM
52947836SJohn.Forte@Sun.COM if (!(dev_type & FC_XPORT_MASK)) {
52957836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
52967836SJohn.Forte@Sun.COM }
52977836SJohn.Forte@Sun.COM
52987836SJohn.Forte@Sun.COM if (((err = g_get_dev_list(fca_path, &dev_list, &num_devices))
5299*11547SBill.Gumbrell@Sun.COM != 0) && (err != L_GET_DEV_LIST_ULP_FAILURE)) {
53007836SJohn.Forte@Sun.COM return (err);
53017836SJohn.Forte@Sun.COM }
53027836SJohn.Forte@Sun.COM
53037836SJohn.Forte@Sun.COM dev_list_save = dev_list;
53047836SJohn.Forte@Sun.COM
53057836SJohn.Forte@Sun.COM switch (flag) {
53067836SJohn.Forte@Sun.COM case MATCH_NODE_WWN:
53077836SJohn.Forte@Sun.COM for (i = 0; i < num_devices; i++, dev_list++) {
53087836SJohn.Forte@Sun.COM if (memcmp(dev_list->dev_nwwn.raw_wwn,
5309*11547SBill.Gumbrell@Sun.COM dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) {
53107836SJohn.Forte@Sun.COM (void) free(dev_list_save);
53117836SJohn.Forte@Sun.COM return (0);
53127836SJohn.Forte@Sun.COM }
53137836SJohn.Forte@Sun.COM }
53147836SJohn.Forte@Sun.COM (void) free(dev_list_save);
53157836SJohn.Forte@Sun.COM /* consider a new error code for not found. */
53167836SJohn.Forte@Sun.COM return (L_WWN_NOT_FOUND_IN_DEV_LIST);
53177836SJohn.Forte@Sun.COM
53187836SJohn.Forte@Sun.COM case MATCH_PORT_WWN:
53197836SJohn.Forte@Sun.COM for (i = 0; i < num_devices; i++, dev_list++) {
53207836SJohn.Forte@Sun.COM if (memcmp(dev_list->dev_pwwn.raw_wwn,
5321*11547SBill.Gumbrell@Sun.COM dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) {
53227836SJohn.Forte@Sun.COM (void) free(dev_list_save);
53237836SJohn.Forte@Sun.COM return (0);
53247836SJohn.Forte@Sun.COM }
53257836SJohn.Forte@Sun.COM }
53267836SJohn.Forte@Sun.COM (void) free(dev_list_save);
53277836SJohn.Forte@Sun.COM /* consider a new error code for not found. */
53287836SJohn.Forte@Sun.COM return (L_WWN_NOT_FOUND_IN_DEV_LIST);
53297836SJohn.Forte@Sun.COM }
53307836SJohn.Forte@Sun.COM (void) free(dev_list_save);
53317836SJohn.Forte@Sun.COM return (-1);
53327836SJohn.Forte@Sun.COM }
53337836SJohn.Forte@Sun.COM
53347836SJohn.Forte@Sun.COM
53357836SJohn.Forte@Sun.COM /*
53367836SJohn.Forte@Sun.COM * g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state)
53377836SJohn.Forte@Sun.COM * Purpose: get the state of device port login via FCIO_GET_STATE ioctl.
53387836SJohn.Forte@Sun.COM *
53397836SJohn.Forte@Sun.COM * Input: fca_path
53407836SJohn.Forte@Sun.COM * fc transport port with fabric/public loop topology
53417836SJohn.Forte@Sun.COM * port_wwn
53427836SJohn.Forte@Sun.COM * port wwn of device node to logout
53437836SJohn.Forte@Sun.COM * state
53447836SJohn.Forte@Sun.COM * port login or not
53457836SJohn.Forte@Sun.COM *
53467836SJohn.Forte@Sun.COM * Returns: 0 on success
53477836SJohn.Forte@Sun.COM * non-zero on failure
53487836SJohn.Forte@Sun.COM */
53497836SJohn.Forte@Sun.COM static int
g_get_dev_port_state(char * fca_path,la_wwn_t port_wwn,uint32_t * state)53507836SJohn.Forte@Sun.COM g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state)
53517836SJohn.Forte@Sun.COM {
5352*11547SBill.Gumbrell@Sun.COM int fd;
5353*11547SBill.Gumbrell@Sun.COM int dev_type;
5354*11547SBill.Gumbrell@Sun.COM fcio_t fcio;
5355*11547SBill.Gumbrell@Sun.COM int verbose = 0;
53567836SJohn.Forte@Sun.COM
53577836SJohn.Forte@Sun.COM if ((dev_type = g_get_path_type(fca_path)) == 0) {
53587836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
53597836SJohn.Forte@Sun.COM }
53607836SJohn.Forte@Sun.COM
53617836SJohn.Forte@Sun.COM if (!(dev_type & FC_XPORT_MASK)) {
53627836SJohn.Forte@Sun.COM return (L_INVALID_PATH_TYPE);
53637836SJohn.Forte@Sun.COM }
53647836SJohn.Forte@Sun.COM
53657836SJohn.Forte@Sun.COM /* open controller */
53667836SJohn.Forte@Sun.COM if ((fd = g_object_open(fca_path, O_NDELAY | O_RDONLY)) == -1)
53677836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
53687836SJohn.Forte@Sun.COM
53697836SJohn.Forte@Sun.COM /*
53707836SJohn.Forte@Sun.COM * stores port_wwn to la_wwn_t raw_wwn field
53717836SJohn.Forte@Sun.COM * and construct fcio structures for FCIO_DEV_LOGIN.
53727836SJohn.Forte@Sun.COM */
53737836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_STATE;
53747836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (port_wwn);
53757836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&port_wwn;
53767836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ | FCIO_XFER_WRITE;
53777836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (uint32_t);
53787836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)state;
53797836SJohn.Forte@Sun.COM fcio.fcio_alen = 0;
53807836SJohn.Forte@Sun.COM fcio.fcio_abuf = NULL;
53817836SJohn.Forte@Sun.COM if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
53827836SJohn.Forte@Sun.COM I_DPRINTF(" FCIO_GET_STATE ioctl failed.\n");
53837836SJohn.Forte@Sun.COM (void) close(fd);
53847836SJohn.Forte@Sun.COM return (L_FCIO_GET_STATE_FAIL);
53857836SJohn.Forte@Sun.COM } else {
53867836SJohn.Forte@Sun.COM (void) close(fd);
53877836SJohn.Forte@Sun.COM return (0);
53887836SJohn.Forte@Sun.COM }
53897836SJohn.Forte@Sun.COM }
53907836SJohn.Forte@Sun.COM
53917836SJohn.Forte@Sun.COM /*
53927836SJohn.Forte@Sun.COM * Name: lilp_map_cmp
53937836SJohn.Forte@Sun.COM *
53947836SJohn.Forte@Sun.COM * Description: This function is used to compare the physical location
53957836SJohn.Forte@Sun.COM * of to fc devices in a gfc_map_t.dev_addr arrary.
53967836SJohn.Forte@Sun.COM *
53977836SJohn.Forte@Sun.COM * Params:
53987836SJohn.Forte@Sun.COM * First device to compare
53997836SJohn.Forte@Sun.COM * Second device to compare
54007836SJohn.Forte@Sun.COM *
54017836SJohn.Forte@Sun.COM * Return:
54027836SJohn.Forte@Sun.COM * 0 = Devices at equal phyiscal location, How did this happen?
54037836SJohn.Forte@Sun.COM * >0 = First device have a higher physical location than second
54047836SJohn.Forte@Sun.COM * <0 = Second device have a higher physical location than first
54057836SJohn.Forte@Sun.COM */
lilp_map_cmp(const void * dev1,const void * dev2)54067836SJohn.Forte@Sun.COM static int lilp_map_cmp(const void* dev1, const void* dev2) {
54077836SJohn.Forte@Sun.COM int i_dev1 = ((fc_port_dev_t *)dev1)->dev_did.priv_lilp_posit;
54087836SJohn.Forte@Sun.COM int i_dev2 = ((fc_port_dev_t *)dev2)->dev_did.priv_lilp_posit;
54097836SJohn.Forte@Sun.COM
54107836SJohn.Forte@Sun.COM if (i_dev1 > i_dev2)
54117836SJohn.Forte@Sun.COM return (1);
54127836SJohn.Forte@Sun.COM if (i_dev1 < i_dev2)
54137836SJohn.Forte@Sun.COM return (-1);
54147836SJohn.Forte@Sun.COM return (0);
54157836SJohn.Forte@Sun.COM }
54167836SJohn.Forte@Sun.COM
54177836SJohn.Forte@Sun.COM /*
54187836SJohn.Forte@Sun.COM * Description:
54197836SJohn.Forte@Sun.COM * Retrieves multiple paths to a device based on devid
54207836SJohn.Forte@Sun.COM * Caller must use mplist_free to free mplist structure
54217836SJohn.Forte@Sun.COM * This currently only supports ssd devices.
54227836SJohn.Forte@Sun.COM * The st driver does not register a device id.
54237836SJohn.Forte@Sun.COM *
54247836SJohn.Forte@Sun.COM * Input Values:
54257836SJohn.Forte@Sun.COM *
54267836SJohn.Forte@Sun.COM * devid: ptr to valid ddi_devid_t struct
54277836SJohn.Forte@Sun.COM * root: root handle to device tree snapshot
54287836SJohn.Forte@Sun.COM * drvr_name: driver name to start the node tree search
54297836SJohn.Forte@Sun.COM *
54307836SJohn.Forte@Sun.COM * Return Value:
54317836SJohn.Forte@Sun.COM * 0 on success
54327836SJohn.Forte@Sun.COM * non-zero on failure
54337836SJohn.Forte@Sun.COM */
54347836SJohn.Forte@Sun.COM
54357836SJohn.Forte@Sun.COM static int
devid_get_all(ddi_devid_t devid,di_node_t root,char * drvr_name,struct mplist_struct ** mplistp)54367836SJohn.Forte@Sun.COM devid_get_all(ddi_devid_t devid, di_node_t root, char *drvr_name,
5437*11547SBill.Gumbrell@Sun.COM struct mplist_struct **mplistp)
54387836SJohn.Forte@Sun.COM {
5439*11547SBill.Gumbrell@Sun.COM ddi_devid_t mydevid;
5440*11547SBill.Gumbrell@Sun.COM di_node_t node;
5441*11547SBill.Gumbrell@Sun.COM char *devfs_path = NULL;
5442*11547SBill.Gumbrell@Sun.COM struct mplist_struct *mpl, *mpln;
54437836SJohn.Forte@Sun.COM
54447836SJohn.Forte@Sun.COM if (devid == NULL || root == NULL || drvr_name == NULL ||
5445*11547SBill.Gumbrell@Sun.COM mplistp == NULL ||
5446*11547SBill.Gumbrell@Sun.COM (strncmp(drvr_name, SSD_DRVR_NAME, strlen(SSD_DRVR_NAME))
5447*11547SBill.Gumbrell@Sun.COM != 0)) {
54487836SJohn.Forte@Sun.COM return (EINVAL);
54497836SJohn.Forte@Sun.COM }
54507836SJohn.Forte@Sun.COM
54517836SJohn.Forte@Sun.COM *mplistp = mpl = mpln = (struct mplist_struct *)NULL;
54527836SJohn.Forte@Sun.COM
54537836SJohn.Forte@Sun.COM /* point to first node which matches portdrvr */
54547836SJohn.Forte@Sun.COM node = di_drv_first_node(drvr_name, root);
54557836SJohn.Forte@Sun.COM if (node == DI_NODE_NIL) {
54567836SJohn.Forte@Sun.COM return (L_NO_DRIVER_NODES_FOUND);
54577836SJohn.Forte@Sun.COM }
54587836SJohn.Forte@Sun.COM
54597836SJohn.Forte@Sun.COM while (node != DI_NODE_NIL) {
54607836SJohn.Forte@Sun.COM if ((mydevid = di_devid(node)) != NULL) {
54617836SJohn.Forte@Sun.COM if (((devid_compare(mydevid, devid)) == 0)) {
5462*11547SBill.Gumbrell@Sun.COM /* Load multipath list */
5463*11547SBill.Gumbrell@Sun.COM if ((mpl = (struct mplist_struct *)
5464*11547SBill.Gumbrell@Sun.COM calloc(1, sizeof (struct mplist_struct)))
5465*11547SBill.Gumbrell@Sun.COM == NULL) {
5466*11547SBill.Gumbrell@Sun.COM mplist_free(*mplistp);
5467*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
5468*11547SBill.Gumbrell@Sun.COM }
5469*11547SBill.Gumbrell@Sun.COM if ((devfs_path = my_devfs_path(node)) ==
5470*11547SBill.Gumbrell@Sun.COM NULL) {
5471*11547SBill.Gumbrell@Sun.COM node = di_drv_next_node(node);
5472*11547SBill.Gumbrell@Sun.COM S_FREE(mpl);
5473*11547SBill.Gumbrell@Sun.COM continue;
5474*11547SBill.Gumbrell@Sun.COM }
5475*11547SBill.Gumbrell@Sun.COM mpl->devpath = (char *)calloc(1,
5476*11547SBill.Gumbrell@Sun.COM strlen(devfs_path) +
5477*11547SBill.Gumbrell@Sun.COM strlen(SSD_MINOR_NAME) + 1);
5478*11547SBill.Gumbrell@Sun.COM if (mpl->devpath == NULL) {
5479*11547SBill.Gumbrell@Sun.COM S_FREE(mpl);
5480*11547SBill.Gumbrell@Sun.COM mplist_free(*mplistp);
5481*11547SBill.Gumbrell@Sun.COM my_devfs_path_free(devfs_path);
5482*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
5483*11547SBill.Gumbrell@Sun.COM }
5484*11547SBill.Gumbrell@Sun.COM sprintf(mpl->devpath, "%s%s", devfs_path,
5485*11547SBill.Gumbrell@Sun.COM SSD_MINOR_NAME);
5486*11547SBill.Gumbrell@Sun.COM if (*mplistp == NULL) {
5487*11547SBill.Gumbrell@Sun.COM *mplistp = mpln = mpl;
5488*11547SBill.Gumbrell@Sun.COM } else {
5489*11547SBill.Gumbrell@Sun.COM mpln->next = mpl;
5490*11547SBill.Gumbrell@Sun.COM mpln = mpl;
5491*11547SBill.Gumbrell@Sun.COM }
54927836SJohn.Forte@Sun.COM my_devfs_path_free(devfs_path);
54937836SJohn.Forte@Sun.COM }
54947836SJohn.Forte@Sun.COM }
54957836SJohn.Forte@Sun.COM node = di_drv_next_node(node);
54967836SJohn.Forte@Sun.COM }
54977836SJohn.Forte@Sun.COM return (0);
54987836SJohn.Forte@Sun.COM }
54997836SJohn.Forte@Sun.COM
55007836SJohn.Forte@Sun.COM /*
55017836SJohn.Forte@Sun.COM * Frees a previously allocated mplist_struct
55027836SJohn.Forte@Sun.COM */
55037836SJohn.Forte@Sun.COM static void
mplist_free(struct mplist_struct * mplistp)55047836SJohn.Forte@Sun.COM mplist_free(struct mplist_struct *mplistp)
55057836SJohn.Forte@Sun.COM {
5506*11547SBill.Gumbrell@Sun.COM struct mplist_struct *mplistn;
55077836SJohn.Forte@Sun.COM
55087836SJohn.Forte@Sun.COM while (mplistp != NULL) {
55097836SJohn.Forte@Sun.COM mplistn = mplistp->next;
55107836SJohn.Forte@Sun.COM if (mplistp->devpath != NULL) {
55117836SJohn.Forte@Sun.COM free(mplistp->devpath);
55127836SJohn.Forte@Sun.COM mplistp->devpath = NULL;
55137836SJohn.Forte@Sun.COM }
55147836SJohn.Forte@Sun.COM free(mplistp);
55157836SJohn.Forte@Sun.COM mplistp = mplistn;
55167836SJohn.Forte@Sun.COM }
55177836SJohn.Forte@Sun.COM }
55187836SJohn.Forte@Sun.COM
55197836SJohn.Forte@Sun.COM /*
55207836SJohn.Forte@Sun.COM * Description
55217836SJohn.Forte@Sun.COM * Retrieves all device nodes based on drvr_name
55227836SJohn.Forte@Sun.COM * Currently supports SSD_DRVR_NAME, ST_DRVR_NAME
55237836SJohn.Forte@Sun.COM * There will be a device node in the libdevinfo
55247836SJohn.Forte@Sun.COM * snapshot only if there is at least one node bound.
55257836SJohn.Forte@Sun.COM *
55267836SJohn.Forte@Sun.COM * Input values:
55277836SJohn.Forte@Sun.COM * root valid snapshot handle from di_init(3DEVINFO)
55287836SJohn.Forte@Sun.COM * drvr_name name of driver to start node search
55297836SJohn.Forte@Sun.COM * wwn_list_ptr ptr to ptr to WWN_list struct
55307836SJohn.Forte@Sun.COM *
55317836SJohn.Forte@Sun.COM *
55327836SJohn.Forte@Sun.COM */
55337836SJohn.Forte@Sun.COM static int
devices_get_all(di_node_t root,char * drvr_name,char * minor_name,struct wwn_list_struct ** wwn_list_ptr)55347836SJohn.Forte@Sun.COM devices_get_all(di_node_t root, char *drvr_name, char *minor_name,
5535*11547SBill.Gumbrell@Sun.COM struct wwn_list_struct **wwn_list_ptr)
55367836SJohn.Forte@Sun.COM {
5537*11547SBill.Gumbrell@Sun.COM di_node_t node;
5538*11547SBill.Gumbrell@Sun.COM char *devfs_path;
5539*11547SBill.Gumbrell@Sun.COM char devicepath[MAXPATHLEN];
5540*11547SBill.Gumbrell@Sun.COM uchar_t *nwwn = NULL, *pwwn = NULL;
5541*11547SBill.Gumbrell@Sun.COM uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
5542*11547SBill.Gumbrell@Sun.COM WWN_list *wwn_list, *l1, *l2;
5543*11547SBill.Gumbrell@Sun.COM int scsi_vhci = 0;
5544*11547SBill.Gumbrell@Sun.COM int err, devtype;
55457836SJohn.Forte@Sun.COM
55467836SJohn.Forte@Sun.COM if (root == DI_NODE_NIL || drvr_name == NULL ||
5547*11547SBill.Gumbrell@Sun.COM wwn_list_ptr == NULL) {
55487836SJohn.Forte@Sun.COM return (EINVAL);
55497836SJohn.Forte@Sun.COM }
55507836SJohn.Forte@Sun.COM
55517836SJohn.Forte@Sun.COM wwn_list = *wwn_list_ptr = NULL;
55527836SJohn.Forte@Sun.COM
55537836SJohn.Forte@Sun.COM memset(port_wwn, 0, sizeof (port_wwn));
55547836SJohn.Forte@Sun.COM memset(node_wwn, 0, sizeof (node_wwn));
55557836SJohn.Forte@Sun.COM
55567836SJohn.Forte@Sun.COM if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) {
55577836SJohn.Forte@Sun.COM devtype = DTYPE_DIRECT;
55587836SJohn.Forte@Sun.COM } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) {
55597836SJohn.Forte@Sun.COM devtype = DTYPE_SEQUENTIAL;
55607836SJohn.Forte@Sun.COM } else {
55617836SJohn.Forte@Sun.COM /*
55627836SJohn.Forte@Sun.COM * An unsupported driver name was passed in
55637836SJohn.Forte@Sun.COM */
55647836SJohn.Forte@Sun.COM return (L_DRIVER_NOTSUPP);
55657836SJohn.Forte@Sun.COM }
55667836SJohn.Forte@Sun.COM
55677836SJohn.Forte@Sun.COM /* point to first node which matches portdrvr */
55687836SJohn.Forte@Sun.COM node = di_drv_first_node(drvr_name, root);
55697836SJohn.Forte@Sun.COM if (node == DI_NODE_NIL) {
55707836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
55717836SJohn.Forte@Sun.COM }
55727836SJohn.Forte@Sun.COM
55737836SJohn.Forte@Sun.COM while (node != DI_NODE_NIL) {
55747836SJohn.Forte@Sun.COM
5575*11547SBill.Gumbrell@Sun.COM if ((devfs_path = my_devfs_path(node)) != NULL) {
5576*11547SBill.Gumbrell@Sun.COM
5577*11547SBill.Gumbrell@Sun.COM /*
5578*11547SBill.Gumbrell@Sun.COM * Check for offline state
5579*11547SBill.Gumbrell@Sun.COM */
5580*11547SBill.Gumbrell@Sun.COM if ((di_state(node) &
5581*11547SBill.Gumbrell@Sun.COM DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE) {
55827836SJohn.Forte@Sun.COM my_devfs_path_free(devfs_path);
5583*11547SBill.Gumbrell@Sun.COM node = di_drv_next_node(node);
5584*11547SBill.Gumbrell@Sun.COM continue;
55857836SJohn.Forte@Sun.COM }
5586*11547SBill.Gumbrell@Sun.COM
5587*11547SBill.Gumbrell@Sun.COM /*
5588*11547SBill.Gumbrell@Sun.COM * Only support st, ssd nodes
5589*11547SBill.Gumbrell@Sun.COM */
5590*11547SBill.Gumbrell@Sun.COM if (!strstr(devfs_path, SLSH_DRV_NAME_SSD) &&
5591*11547SBill.Gumbrell@Sun.COM !strstr(devfs_path, SLSH_DRV_NAME_ST)) {
5592*11547SBill.Gumbrell@Sun.COM my_devfs_path_free(devfs_path);
5593*11547SBill.Gumbrell@Sun.COM node = di_drv_next_node(node);
5594*11547SBill.Gumbrell@Sun.COM continue;
5595*11547SBill.Gumbrell@Sun.COM }
5596*11547SBill.Gumbrell@Sun.COM
5597*11547SBill.Gumbrell@Sun.COM devicepath[0] = '\0';
5598*11547SBill.Gumbrell@Sun.COM
55997836SJohn.Forte@Sun.COM /*
5600*11547SBill.Gumbrell@Sun.COM * form device path
56017836SJohn.Forte@Sun.COM */
5602*11547SBill.Gumbrell@Sun.COM sprintf(devicepath, "%s%s", devfs_path, minor_name);
5603*11547SBill.Gumbrell@Sun.COM
5604*11547SBill.Gumbrell@Sun.COM if ((strstr(devicepath, SCSI_VHCI) == NULL)) {
5605*11547SBill.Gumbrell@Sun.COM if ((err = get_wwn_data(node, &nwwn, &pwwn)) !=
5606*11547SBill.Gumbrell@Sun.COM 0) {
5607*11547SBill.Gumbrell@Sun.COM my_devfs_path_free(devfs_path);
5608*11547SBill.Gumbrell@Sun.COM return (err);
5609*11547SBill.Gumbrell@Sun.COM } else {
5610*11547SBill.Gumbrell@Sun.COM memcpy(node_wwn, nwwn,
5611*11547SBill.Gumbrell@Sun.COM sizeof (node_wwn));
5612*11547SBill.Gumbrell@Sun.COM memcpy(port_wwn, pwwn,
5613*11547SBill.Gumbrell@Sun.COM sizeof (port_wwn));
5614*11547SBill.Gumbrell@Sun.COM }
5615*11547SBill.Gumbrell@Sun.COM } else {
5616*11547SBill.Gumbrell@Sun.COM /*
5617*11547SBill.Gumbrell@Sun.COM * Clear values for SCSI VHCI devices.
5618*11547SBill.Gumbrell@Sun.COM * node wwn, port wwn are irrevelant at
5619*11547SBill.Gumbrell@Sun.COM * the SCSI VHCI level
5620*11547SBill.Gumbrell@Sun.COM */
5621*11547SBill.Gumbrell@Sun.COM scsi_vhci++;
5622*11547SBill.Gumbrell@Sun.COM memset(port_wwn, 0, sizeof (port_wwn));
5623*11547SBill.Gumbrell@Sun.COM memset(node_wwn, 0, sizeof (node_wwn));
5624*11547SBill.Gumbrell@Sun.COM }
5625*11547SBill.Gumbrell@Sun.COM
5626*11547SBill.Gumbrell@Sun.COM /* Got wwns, load data in list */
5627*11547SBill.Gumbrell@Sun.COM if ((l2 = (struct wwn_list_struct *)
5628*11547SBill.Gumbrell@Sun.COM calloc(1, sizeof (struct wwn_list_struct))) ==
5629*11547SBill.Gumbrell@Sun.COM NULL) {
5630*11547SBill.Gumbrell@Sun.COM my_devfs_path_free(devfs_path);
5631*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
5632*11547SBill.Gumbrell@Sun.COM }
5633*11547SBill.Gumbrell@Sun.COM if ((l2->physical_path = (char *)
5634*11547SBill.Gumbrell@Sun.COM calloc(1, strlen(devicepath) +1)) == NULL) {
5635*11547SBill.Gumbrell@Sun.COM my_devfs_path_free(devfs_path);
5636*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
5637*11547SBill.Gumbrell@Sun.COM }
5638*11547SBill.Gumbrell@Sun.COM
5639*11547SBill.Gumbrell@Sun.COM memcpy(l2->w_node_wwn, node_wwn, WWN_SIZE);
5640*11547SBill.Gumbrell@Sun.COM
5641*11547SBill.Gumbrell@Sun.COM if (scsi_vhci) {
5642*11547SBill.Gumbrell@Sun.COM strcpy(l2->node_wwn_s, MSGSTR(12000, "N/A"));
5643*11547SBill.Gumbrell@Sun.COM } else {
5644*11547SBill.Gumbrell@Sun.COM copy_wwn_data_to_str(l2->node_wwn_s, node_wwn);
5645*11547SBill.Gumbrell@Sun.COM copy_wwn_data_to_str(l2->port_wwn_s, port_wwn);
5646*11547SBill.Gumbrell@Sun.COM }
5647*11547SBill.Gumbrell@Sun.COM
5648*11547SBill.Gumbrell@Sun.COM strcpy(l2->physical_path, devicepath);
5649*11547SBill.Gumbrell@Sun.COM
5650*11547SBill.Gumbrell@Sun.COM l2->device_type = devtype;
5651*11547SBill.Gumbrell@Sun.COM if (wwn_list == NULL) {
5652*11547SBill.Gumbrell@Sun.COM l1 = wwn_list = l2;
5653*11547SBill.Gumbrell@Sun.COM } else {
5654*11547SBill.Gumbrell@Sun.COM l2->wwn_prev = l1;
5655*11547SBill.Gumbrell@Sun.COM l1 = l1->wwn_next = l2;
5656*11547SBill.Gumbrell@Sun.COM }
56577836SJohn.Forte@Sun.COM my_devfs_path_free(devfs_path);
5658*11547SBill.Gumbrell@Sun.COM scsi_vhci = 0;
56597836SJohn.Forte@Sun.COM }
5660*11547SBill.Gumbrell@Sun.COM node = di_drv_next_node(node);
56617836SJohn.Forte@Sun.COM }
56627836SJohn.Forte@Sun.COM
56637836SJohn.Forte@Sun.COM *wwn_list_ptr = wwn_list; /* pass back ptr to list */
56647836SJohn.Forte@Sun.COM
56657836SJohn.Forte@Sun.COM if (*wwn_list_ptr == NULL) {
56667836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
56677836SJohn.Forte@Sun.COM } else {
56687836SJohn.Forte@Sun.COM /*
56697836SJohn.Forte@Sun.COM * Now load the /dev/ paths
56707836SJohn.Forte@Sun.COM */
56717836SJohn.Forte@Sun.COM if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) {
56727836SJohn.Forte@Sun.COM if ((err = get_dev_path(wwn_list_ptr, DEV_RDIR,
5673*11547SBill.Gumbrell@Sun.COM DIR_MATCH_SSD)) != 0) {
56747836SJohn.Forte@Sun.COM g_free_wwn_list(wwn_list_ptr);
56757836SJohn.Forte@Sun.COM return (err);
56767836SJohn.Forte@Sun.COM }
56777836SJohn.Forte@Sun.COM } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) {
56787836SJohn.Forte@Sun.COM if ((err = get_dev_path(wwn_list_ptr, DEV_TAPE_DIR,
5679*11547SBill.Gumbrell@Sun.COM DIR_MATCH_ST)) != 0) {
56807836SJohn.Forte@Sun.COM g_free_wwn_list(wwn_list_ptr);
56817836SJohn.Forte@Sun.COM return (err);
56827836SJohn.Forte@Sun.COM }
56837836SJohn.Forte@Sun.COM }
56847836SJohn.Forte@Sun.COM return (0);
56857836SJohn.Forte@Sun.COM }
56867836SJohn.Forte@Sun.COM }
56877836SJohn.Forte@Sun.COM
56887836SJohn.Forte@Sun.COM
56897836SJohn.Forte@Sun.COM /*
56907836SJohn.Forte@Sun.COM * Access the properties for the node to get the node-wwn, port-wwn property
56917836SJohn.Forte@Sun.COM * On error, contents of nwwn, pwwn are unspecified.
56927836SJohn.Forte@Sun.COM * On successful return nwwn and pwwn are WWN_SIZE bytes.
56937836SJohn.Forte@Sun.COM */
56947836SJohn.Forte@Sun.COM static int
get_wwn_data(di_node_t node,uchar_t ** nwwn,uchar_t ** pwwn)56957836SJohn.Forte@Sun.COM get_wwn_data(di_node_t node, uchar_t **nwwn, uchar_t **pwwn)
56967836SJohn.Forte@Sun.COM {
56977836SJohn.Forte@Sun.COM if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP,
5698*11547SBill.Gumbrell@Sun.COM nwwn) != WWN_SIZE) {
5699*11547SBill.Gumbrell@Sun.COM /* If we didn't get back the right count, return error */
57007836SJohn.Forte@Sun.COM return (L_NO_WWN_PROP_FOUND);
57017836SJohn.Forte@Sun.COM }
57027836SJohn.Forte@Sun.COM if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, PORT_WWN_PROP,
5703*11547SBill.Gumbrell@Sun.COM pwwn) != WWN_SIZE) {
5704*11547SBill.Gumbrell@Sun.COM /* If we didn't get back the right count, return error */
57057836SJohn.Forte@Sun.COM return (L_NO_WWN_PROP_FOUND);
57067836SJohn.Forte@Sun.COM }
57077836SJohn.Forte@Sun.COM return (0);
57087836SJohn.Forte@Sun.COM }
57097836SJohn.Forte@Sun.COM
57107836SJohn.Forte@Sun.COM /*
57117836SJohn.Forte@Sun.COM * Description
57127836SJohn.Forte@Sun.COM * retrieves the /dev logical path for a WWN_list of devices.
57137836SJohn.Forte@Sun.COM * Input values
57147836SJohn.Forte@Sun.COM * wwn_list_ptr ptr to list returned by devices_get_all
57157836SJohn.Forte@Sun.COM * dir_name /dev/ directory to search
57167836SJohn.Forte@Sun.COM *
57177836SJohn.Forte@Sun.COM */
57187836SJohn.Forte@Sun.COM static int
get_dev_path(struct wwn_list_struct ** wwn_list_ptr,char * dir_name,char * pattern_match)57197836SJohn.Forte@Sun.COM get_dev_path(struct wwn_list_struct **wwn_list_ptr, char *dir_name,
5720*11547SBill.Gumbrell@Sun.COM char *pattern_match)
57217836SJohn.Forte@Sun.COM {
5722*11547SBill.Gumbrell@Sun.COM DIR *dirp;
5723*11547SBill.Gumbrell@Sun.COM struct dirent *entp;
5724*11547SBill.Gumbrell@Sun.COM char namebuf[MAXPATHLEN];
5725*11547SBill.Gumbrell@Sun.COM char *result = NULL;
5726*11547SBill.Gumbrell@Sun.COM WWN_list *wwn_list, *wwn_list_save;
5727*11547SBill.Gumbrell@Sun.COM char *env;
5728*11547SBill.Gumbrell@Sun.COM hrtime_t start_time, end_time;
57297836SJohn.Forte@Sun.COM
57307836SJohn.Forte@Sun.COM if (wwn_list_ptr == NULL || *wwn_list_ptr == NULL ||
5731*11547SBill.Gumbrell@Sun.COM dir_name == NULL || pattern_match == NULL) {
57327836SJohn.Forte@Sun.COM return (EINVAL);
57337836SJohn.Forte@Sun.COM }
57347836SJohn.Forte@Sun.COM
57357836SJohn.Forte@Sun.COM if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
57367836SJohn.Forte@Sun.COM start_time = gethrtime();
57377836SJohn.Forte@Sun.COM }
57387836SJohn.Forte@Sun.COM
57397836SJohn.Forte@Sun.COM wwn_list = *wwn_list_ptr;
57407836SJohn.Forte@Sun.COM
57417836SJohn.Forte@Sun.COM if ((dirp = opendir(dir_name)) == NULL) {
57427836SJohn.Forte@Sun.COM P_DPRINTF(" get_dev_path: No devices found\n");
57437836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
57447836SJohn.Forte@Sun.COM }
57457836SJohn.Forte@Sun.COM
57467836SJohn.Forte@Sun.COM while ((entp = readdir(dirp)) != NULL) {
57477836SJohn.Forte@Sun.COM /*
57487836SJohn.Forte@Sun.COM * Ignore current directory and parent directory
57497836SJohn.Forte@Sun.COM * entries.
57507836SJohn.Forte@Sun.COM */
57517836SJohn.Forte@Sun.COM if ((strcmp(entp->d_name, ".") == 0) ||
57527836SJohn.Forte@Sun.COM (strcmp(entp->d_name, "..") == 0) ||
57537836SJohn.Forte@Sun.COM (fnmatch(pattern_match, entp->d_name, 0) != 0))
57547836SJohn.Forte@Sun.COM continue;
57557836SJohn.Forte@Sun.COM
57567836SJohn.Forte@Sun.COM memset(namebuf, 0, sizeof (namebuf));
57577836SJohn.Forte@Sun.COM sprintf(namebuf, "%s/%s", dir_name, entp->d_name);
57587836SJohn.Forte@Sun.COM
57597836SJohn.Forte@Sun.COM if ((result = g_get_physical_name_from_link(namebuf)) == NULL) {
57607836SJohn.Forte@Sun.COM ER_DPRINTF(" Warning: Get physical name from"
5761*11547SBill.Gumbrell@Sun.COM " link failed. Link=%s\n", namebuf);
57627836SJohn.Forte@Sun.COM continue;
57637836SJohn.Forte@Sun.COM }
57647836SJohn.Forte@Sun.COM for (wwn_list = *wwn_list_ptr; wwn_list != NULL;
57657836SJohn.Forte@Sun.COM wwn_list = wwn_list->wwn_next) {
5766*11547SBill.Gumbrell@Sun.COM if (strcmp(wwn_list->physical_path, result) == 0) {
5767*11547SBill.Gumbrell@Sun.COM /*
5768*11547SBill.Gumbrell@Sun.COM * Add information to the list.
5769*11547SBill.Gumbrell@Sun.COM */
5770*11547SBill.Gumbrell@Sun.COM if ((wwn_list->logical_path = (char *)
5771*11547SBill.Gumbrell@Sun.COM calloc(1, strlen(namebuf) + 1)) == NULL) {
5772*11547SBill.Gumbrell@Sun.COM free(result);
5773*11547SBill.Gumbrell@Sun.COM return (L_MALLOC_FAILED);
5774*11547SBill.Gumbrell@Sun.COM }
5775*11547SBill.Gumbrell@Sun.COM strcpy(wwn_list->logical_path, namebuf);
5776*11547SBill.Gumbrell@Sun.COM break;
57777836SJohn.Forte@Sun.COM }
57787836SJohn.Forte@Sun.COM }
57797836SJohn.Forte@Sun.COM free(result);
57807836SJohn.Forte@Sun.COM }
57817836SJohn.Forte@Sun.COM closedir(dirp);
57827836SJohn.Forte@Sun.COM
57837836SJohn.Forte@Sun.COM /*
57847836SJohn.Forte@Sun.COM * Did we load all of the paths?
57857836SJohn.Forte@Sun.COM * Note: if there is a missing entry in /dev then
57867836SJohn.Forte@Sun.COM * the user probably did a cleanup of /dev.
57877836SJohn.Forte@Sun.COM * Whatever the case, remove the entry as it
57887836SJohn.Forte@Sun.COM * is invalid.
57897836SJohn.Forte@Sun.COM */
57907836SJohn.Forte@Sun.COM wwn_list = *wwn_list_ptr;
57917836SJohn.Forte@Sun.COM while (wwn_list != NULL) {
57927836SJohn.Forte@Sun.COM if (wwn_list->logical_path == NULL) {
57937836SJohn.Forte@Sun.COM free(wwn_list->physical_path);
57947836SJohn.Forte@Sun.COM wwn_list_save = wwn_list;
57957836SJohn.Forte@Sun.COM if (wwn_list->wwn_prev != NULL) {
57967836SJohn.Forte@Sun.COM wwn_list->wwn_prev->wwn_next =
5797*11547SBill.Gumbrell@Sun.COM wwn_list->wwn_next;
57987836SJohn.Forte@Sun.COM } else {
57997836SJohn.Forte@Sun.COM /*
58007836SJohn.Forte@Sun.COM * No previous entries
58017836SJohn.Forte@Sun.COM */
58027836SJohn.Forte@Sun.COM *wwn_list_ptr = wwn_list->wwn_next;
58037836SJohn.Forte@Sun.COM }
58047836SJohn.Forte@Sun.COM if (wwn_list->wwn_next != NULL) {
58057836SJohn.Forte@Sun.COM wwn_list->wwn_next->wwn_prev =
5806*11547SBill.Gumbrell@Sun.COM wwn_list->wwn_prev;
58077836SJohn.Forte@Sun.COM }
58087836SJohn.Forte@Sun.COM wwn_list = wwn_list->wwn_next;
58097836SJohn.Forte@Sun.COM free(wwn_list_save);
58107836SJohn.Forte@Sun.COM } else {
58117836SJohn.Forte@Sun.COM wwn_list = wwn_list->wwn_next;
58127836SJohn.Forte@Sun.COM }
58137836SJohn.Forte@Sun.COM }
58147836SJohn.Forte@Sun.COM
58157836SJohn.Forte@Sun.COM if (env != NULL) {
58167836SJohn.Forte@Sun.COM end_time = gethrtime();
58177836SJohn.Forte@Sun.COM fprintf(stdout,
5818*11547SBill.Gumbrell@Sun.COM " get_dev_path %s: "
5819*11547SBill.Gumbrell@Sun.COM "\t\tTime = %lld millisec\n",
5820*11547SBill.Gumbrell@Sun.COM dir_name, (end_time - start_time)/1000000);
58217836SJohn.Forte@Sun.COM }
58227836SJohn.Forte@Sun.COM
58237836SJohn.Forte@Sun.COM if (*wwn_list_ptr == NULL) {
58247836SJohn.Forte@Sun.COM return (L_NO_DEVICES_FOUND);
58257836SJohn.Forte@Sun.COM } else {
58267836SJohn.Forte@Sun.COM return (0);
58277836SJohn.Forte@Sun.COM }
58287836SJohn.Forte@Sun.COM }
58297836SJohn.Forte@Sun.COM
58307836SJohn.Forte@Sun.COM /*
58317836SJohn.Forte@Sun.COM * This functions calls di_devfs_path and gets the path associated with a
58327836SJohn.Forte@Sun.COM * given devinfo node. If the path returned does not have a '@' in it, it
58337836SJohn.Forte@Sun.COM * checks if the driver is detached and creates a path after looking at the
58347836SJohn.Forte@Sun.COM * driver properties.
58357836SJohn.Forte@Sun.COM *
58367836SJohn.Forte@Sun.COM * di_devfs_path_free is called internally.
58377836SJohn.Forte@Sun.COM *
58387836SJohn.Forte@Sun.COM * The argument 'path' points to the final value upon return.
58397836SJohn.Forte@Sun.COM * Caller must use my_devfs_path_free on returned char *
58407836SJohn.Forte@Sun.COM * Note: Only support FC/SCSI_VHCI devices,
5841*11547SBill.Gumbrell@Sun.COM * for FC check for initiator-interconnect-type prop
58427836SJohn.Forte@Sun.COM *
58437836SJohn.Forte@Sun.COM */
58447836SJohn.Forte@Sun.COM static char *
my_devfs_path(di_node_t node)58457836SJohn.Forte@Sun.COM my_devfs_path(di_node_t node)
58467836SJohn.Forte@Sun.COM {
58477836SJohn.Forte@Sun.COM uchar_t *pwwn = NULL;
5848*11547SBill.Gumbrell@Sun.COM char *interconnect = NULL;
58497836SJohn.Forte@Sun.COM char pwwns[WWN_SIZE*2+1];
58507836SJohn.Forte@Sun.COM char *mypath;
58517836SJohn.Forte@Sun.COM int scsi_vhci = 0;
5852*11547SBill.Gumbrell@Sun.COM int rval;
58537836SJohn.Forte@Sun.COM char *tptr = NULL, *lun_guid = NULL;
58547836SJohn.Forte@Sun.COM int *lunnump = NULL;
5855*11547SBill.Gumbrell@Sun.COM di_node_t parentnode;
58567836SJohn.Forte@Sun.COM
58577836SJohn.Forte@Sun.COM /* sanity check */
58587836SJohn.Forte@Sun.COM if (node == DI_NODE_NIL) {
58597836SJohn.Forte@Sun.COM return (NULL);
58607836SJohn.Forte@Sun.COM }
58617836SJohn.Forte@Sun.COM
58627836SJohn.Forte@Sun.COM /* Now go get the path for this node */
58637836SJohn.Forte@Sun.COM if ((tptr = di_devfs_path(node)) == NULL) {
58647836SJohn.Forte@Sun.COM return (NULL);
58657836SJohn.Forte@Sun.COM }
58667836SJohn.Forte@Sun.COM
5867*11547SBill.Gumbrell@Sun.COM parentnode = di_parent_node(node);
5868*11547SBill.Gumbrell@Sun.COM
58697836SJohn.Forte@Sun.COM if ((mypath = (char *)calloc(1, MAXPATHLEN + 1)) == NULL) {
58707836SJohn.Forte@Sun.COM di_devfs_path_free(tptr);
58717836SJohn.Forte@Sun.COM return (NULL);
58727836SJohn.Forte@Sun.COM }
58737836SJohn.Forte@Sun.COM
58747836SJohn.Forte@Sun.COM /* Prepend "/devices" to libdevinfo-returned paths */
58757836SJohn.Forte@Sun.COM sprintf(mypath, "%s%s", DEVICES_DIR, tptr);
58767836SJohn.Forte@Sun.COM
58777836SJohn.Forte@Sun.COM di_devfs_path_free(tptr);
58787836SJohn.Forte@Sun.COM
58797836SJohn.Forte@Sun.COM /*
58807836SJohn.Forte@Sun.COM * Is this a FC device?
5881*11547SBill.Gumbrell@Sun.COM * Check initiator-interconnect-type property
58827836SJohn.Forte@Sun.COM */
58837836SJohn.Forte@Sun.COM if (strstr(mypath, SCSI_VHCI) == NULL) {
5884*11547SBill.Gumbrell@Sun.COM rval = di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode,
5885*11547SBill.Gumbrell@Sun.COM "initiator-interconnect-type", &interconnect);
5886*11547SBill.Gumbrell@Sun.COM /* Check for INTERCONNECT_FABRIC_STR & INTERCONNECT_FIBRE_STR */
5887*11547SBill.Gumbrell@Sun.COM if ((rval <= 0) ||
5888*11547SBill.Gumbrell@Sun.COM ((strcmp(interconnect, "FABRIC") != 0) &&
5889*11547SBill.Gumbrell@Sun.COM (strcmp(interconnect, "FIBRE") != 0))) {
58907836SJohn.Forte@Sun.COM /* Not a FC device. Free path and return */
58917836SJohn.Forte@Sun.COM free(mypath);
58927836SJohn.Forte@Sun.COM return (NULL);
58937836SJohn.Forte@Sun.COM }
58947836SJohn.Forte@Sun.COM } else {
58957836SJohn.Forte@Sun.COM scsi_vhci++;
58967836SJohn.Forte@Sun.COM }
58977836SJohn.Forte@Sun.COM
58987836SJohn.Forte@Sun.COM if ((tptr = strrchr(mypath, '/')) == NULL) {
58997836SJohn.Forte@Sun.COM free(mypath);
59007836SJohn.Forte@Sun.COM return (NULL);
59017836SJohn.Forte@Sun.COM }
59027836SJohn.Forte@Sun.COM
59037836SJohn.Forte@Sun.COM if (strchr(tptr, '@') != NULL) {
59047836SJohn.Forte@Sun.COM return (mypath);
59057836SJohn.Forte@Sun.COM }
59067836SJohn.Forte@Sun.COM
59077836SJohn.Forte@Sun.COM /*
59087836SJohn.Forte@Sun.COM * No '@' in path. This can happen when driver is detached.
59097836SJohn.Forte@Sun.COM * We'll check if the state is detached and if it is, we'll construct
59107836SJohn.Forte@Sun.COM * the path by looking at the properties.
59117836SJohn.Forte@Sun.COM */
59127836SJohn.Forte@Sun.COM
59137836SJohn.Forte@Sun.COM if ((di_state(node) & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) {
59147836SJohn.Forte@Sun.COM /*
59157836SJohn.Forte@Sun.COM * Driver is not detached and no '@' in path.
59167836SJohn.Forte@Sun.COM * Can't handle it.
59177836SJohn.Forte@Sun.COM */
59187836SJohn.Forte@Sun.COM free(mypath);
59197836SJohn.Forte@Sun.COM return (NULL);
59207836SJohn.Forte@Sun.COM }
59217836SJohn.Forte@Sun.COM
59227836SJohn.Forte@Sun.COM if (!scsi_vhci) {
59237836SJohn.Forte@Sun.COM copy_wwn_data_to_str(pwwns, pwwn);
59247836SJohn.Forte@Sun.COM di_prop_lookup_ints(DDI_DEV_T_ANY, node, LUN_PROP, &lunnump);
59257836SJohn.Forte@Sun.COM sprintf(&mypath[strlen(mypath)], "@w%s,%x", pwwn, *lunnump);
59267836SJohn.Forte@Sun.COM } else {
59277836SJohn.Forte@Sun.COM di_prop_lookup_strings(DDI_DEV_T_ANY, node,
5928*11547SBill.Gumbrell@Sun.COM LUN_GUID_PROP, &lun_guid);
59297836SJohn.Forte@Sun.COM sprintf(&mypath[strlen(mypath)], "@g%s", lun_guid);
59307836SJohn.Forte@Sun.COM }
59317836SJohn.Forte@Sun.COM return (mypath);
59327836SJohn.Forte@Sun.COM }
59337836SJohn.Forte@Sun.COM
59347836SJohn.Forte@Sun.COM static void
my_devfs_path_free(char * path)59357836SJohn.Forte@Sun.COM my_devfs_path_free(char *path)
59367836SJohn.Forte@Sun.COM {
59377836SJohn.Forte@Sun.COM if (path != NULL) {
59387836SJohn.Forte@Sun.COM free(path);
59397836SJohn.Forte@Sun.COM }
59407836SJohn.Forte@Sun.COM }
59417836SJohn.Forte@Sun.COM
59427836SJohn.Forte@Sun.COM /*
59437836SJohn.Forte@Sun.COM * from_ptr: ptr to uchar_t array of size WWN_SIZE
59447836SJohn.Forte@Sun.COM * to_ptr: char ptr to string of size WWN_SIZE*2+1
59457836SJohn.Forte@Sun.COM */
59467836SJohn.Forte@Sun.COM static void
copy_wwn_data_to_str(char * to_ptr,const uchar_t * from_ptr)59477836SJohn.Forte@Sun.COM copy_wwn_data_to_str(char *to_ptr, const uchar_t *from_ptr)
59487836SJohn.Forte@Sun.COM {
59497836SJohn.Forte@Sun.COM if ((to_ptr == NULL) || (from_ptr == NULL))
59507836SJohn.Forte@Sun.COM return;
59517836SJohn.Forte@Sun.COM
59527836SJohn.Forte@Sun.COM sprintf(to_ptr, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
5953*11547SBill.Gumbrell@Sun.COM from_ptr[0], from_ptr[1], from_ptr[2], from_ptr[3],
5954*11547SBill.Gumbrell@Sun.COM from_ptr[4], from_ptr[5], from_ptr[6], from_ptr[7]);
59557836SJohn.Forte@Sun.COM }
59567836SJohn.Forte@Sun.COM
59577836SJohn.Forte@Sun.COM /*
59587836SJohn.Forte@Sun.COM * Open the requested directory and get one valid open.
59597836SJohn.Forte@Sun.COM * If a device is busy, return.
59607836SJohn.Forte@Sun.COM * Only need to open one device since
59617836SJohn.Forte@Sun.COM * that implies there will be a node returned from
59627836SJohn.Forte@Sun.COM * di_drv_first_node()
59637836SJohn.Forte@Sun.COM * dir_name: logical device name directory
59647836SJohn.Forte@Sun.COM * (DEV_TAPE_DIR, DEV_RDIR)
59657836SJohn.Forte@Sun.COM * pattern_match: used by fnmatch on directory entry
59667836SJohn.Forte@Sun.COM * (DIR_MATCH_SSD, DIR_MATCH_ST)
59677836SJohn.Forte@Sun.COM * drvr_path: path type to verify ("/ssd@", "/st@")
59687836SJohn.Forte@Sun.COM * (SLSH_DRV_NAME_ST, SLSH_DRV_NAME_SSD)
59697836SJohn.Forte@Sun.COM *
59707836SJohn.Forte@Sun.COM * Returns: None
59717836SJohn.Forte@Sun.COM */
59727836SJohn.Forte@Sun.COM static void
init_drv(char * dir_name,char * pattern_match,char * drvr_path)59737836SJohn.Forte@Sun.COM init_drv(char *dir_name, char *pattern_match, char *drvr_path)
59747836SJohn.Forte@Sun.COM {
5975*11547SBill.Gumbrell@Sun.COM DIR *dirp;
5976*11547SBill.Gumbrell@Sun.COM struct dirent *entp;
5977*11547SBill.Gumbrell@Sun.COM char namebuf[MAXPATHLEN];
5978*11547SBill.Gumbrell@Sun.COM char *result = NULL;
5979*11547SBill.Gumbrell@Sun.COM int fd;
59807836SJohn.Forte@Sun.COM
59817836SJohn.Forte@Sun.COM if ((dirp = opendir(dir_name)) == NULL) {
59827836SJohn.Forte@Sun.COM return;
59837836SJohn.Forte@Sun.COM }
59847836SJohn.Forte@Sun.COM
59857836SJohn.Forte@Sun.COM while ((entp = readdir(dirp)) != NULL) {
59867836SJohn.Forte@Sun.COM /*
59877836SJohn.Forte@Sun.COM * Ignore current directory and parent directory
59887836SJohn.Forte@Sun.COM * entries.
59897836SJohn.Forte@Sun.COM */
59907836SJohn.Forte@Sun.COM if ((strcmp(entp->d_name, ".") == 0) ||
59917836SJohn.Forte@Sun.COM (strcmp(entp->d_name, "..") == 0) ||
59927836SJohn.Forte@Sun.COM (fnmatch(pattern_match, entp->d_name, 0) != 0)) {
59937836SJohn.Forte@Sun.COM continue;
59947836SJohn.Forte@Sun.COM }
59957836SJohn.Forte@Sun.COM
59967836SJohn.Forte@Sun.COM memset(namebuf, 0, sizeof (namebuf));
59977836SJohn.Forte@Sun.COM sprintf(namebuf, "%s/%s", dir_name, entp->d_name);
59987836SJohn.Forte@Sun.COM
59997836SJohn.Forte@Sun.COM if ((result = g_get_physical_name_from_link(namebuf)) == NULL) {
60007836SJohn.Forte@Sun.COM ER_DPRINTF(" Warning: Get physical name from"
6001*11547SBill.Gumbrell@Sun.COM " link failed. Link=%s\n", namebuf);
60027836SJohn.Forte@Sun.COM continue;
60037836SJohn.Forte@Sun.COM }
60047836SJohn.Forte@Sun.COM
60057836SJohn.Forte@Sun.COM if (strstr(result, drvr_path) == NULL) {
60067836SJohn.Forte@Sun.COM free(result);
60077836SJohn.Forte@Sun.COM result = NULL;
60087836SJohn.Forte@Sun.COM continue;
60097836SJohn.Forte@Sun.COM }
60107836SJohn.Forte@Sun.COM
60117836SJohn.Forte@Sun.COM if ((fd = g_object_open(result, O_NDELAY | O_RDONLY)) != -1) {
60127836SJohn.Forte@Sun.COM close(fd);
60137836SJohn.Forte@Sun.COM break;
60147836SJohn.Forte@Sun.COM } else if (errno != EBUSY) {
60157836SJohn.Forte@Sun.COM free(result);
60167836SJohn.Forte@Sun.COM result = NULL;
60177836SJohn.Forte@Sun.COM continue;
60187836SJohn.Forte@Sun.COM } else {
60197836SJohn.Forte@Sun.COM break;
60207836SJohn.Forte@Sun.COM }
60217836SJohn.Forte@Sun.COM }
60227836SJohn.Forte@Sun.COM free(result);
60237836SJohn.Forte@Sun.COM closedir(dirp);
60247836SJohn.Forte@Sun.COM }
6025