1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22063d642aSBill Gumbrell * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte
27fcf3ce44SJohn Forte /*LINTLIBRARY*/
28fcf3ce44SJohn Forte
29fcf3ce44SJohn Forte /*
30fcf3ce44SJohn Forte * I18N message number ranges
31fcf3ce44SJohn Forte * This file: 12000 - 12499
32fcf3ce44SJohn Forte * Shared common messages: 1 - 1999
33fcf3ce44SJohn Forte */
34fcf3ce44SJohn Forte
35fcf3ce44SJohn Forte /*
36fcf3ce44SJohn Forte * This module is part of the Fibre Channel Interface library.
37fcf3ce44SJohn Forte */
38fcf3ce44SJohn Forte
39fcf3ce44SJohn Forte /* #define _POSIX_SOURCE 1 */
40fcf3ce44SJohn Forte
41fcf3ce44SJohn Forte
42fcf3ce44SJohn Forte /* Includes */
43fcf3ce44SJohn Forte #include <stdlib.h>
44fcf3ce44SJohn Forte #include <stdio.h>
45fcf3ce44SJohn Forte #include <sys/file.h>
46fcf3ce44SJohn Forte #include <sys/types.h>
47fcf3ce44SJohn Forte #include <sys/stat.h>
48fcf3ce44SJohn Forte #include <sys/mkdev.h>
49fcf3ce44SJohn Forte #include <sys/param.h>
50fcf3ce44SJohn Forte #include <fcntl.h>
51fcf3ce44SJohn Forte #include <unistd.h>
52fcf3ce44SJohn Forte #include <string.h>
53fcf3ce44SJohn Forte #include <sys/scsi/scsi.h>
54fcf3ce44SJohn Forte #include <dirent.h> /* for DIR */
55fcf3ce44SJohn Forte #include <sys/vtoc.h>
56fcf3ce44SJohn Forte #include <nl_types.h>
57fcf3ce44SJohn Forte #include <strings.h>
58fcf3ce44SJohn Forte #include <errno.h>
59fcf3ce44SJohn Forte #include <sys/ddi.h> /* for max */
60fcf3ce44SJohn Forte #include <fnmatch.h>
61fcf3ce44SJohn Forte #include <l_common.h>
62fcf3ce44SJohn Forte #include <stgcom.h>
63fcf3ce44SJohn Forte #include <l_error.h>
64fcf3ce44SJohn Forte #include <g_state.h>
65fcf3ce44SJohn Forte #include <g_scsi.h>
66fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcp_util.h>
67fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h>
68fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fcph.h>
69fcf3ce44SJohn Forte #include <sys/socalio.h>
70fcf3ce44SJohn Forte #include <libdevinfo.h>
71fcf3ce44SJohn Forte #include <ctype.h>
72fcf3ce44SJohn Forte #include <devid.h>
73fcf3ce44SJohn Forte
74fcf3ce44SJohn Forte /* Some forward declarations of static functions */
75fcf3ce44SJohn Forte /*
76fcf3ce44SJohn Forte * becomes extern interface for Tapestry.
77fcf3ce44SJohn Forte * static int g_get_inq_dtype(char *, la_wwn_t, uchar_t *);
78fcf3ce44SJohn Forte * static int g_get_dev_list(char *, fc_port_dev_t **, int *, int);
79fcf3ce44SJohn Forte */
80fcf3ce44SJohn Forte static int g_issue_fcp_ioctl(int, struct fcp_ioctl *, int);
81fcf3ce44SJohn Forte static int g_set_port_state(char *, int);
82fcf3ce44SJohn Forte static int g_dev_log_in_out(char *, la_wwn_t, uint16_t);
83fcf3ce44SJohn Forte static int g_get_dev_port_state(char *, la_wwn_t, uint32_t *);
84fcf3ce44SJohn Forte static void g_free_rls(AL_rls *);
85fcf3ce44SJohn Forte static int g_scsi_inquiry_cmd80(int, uchar_t *, int);
86fcf3ce44SJohn Forte static int get_fca_inq_dtype(char *, la_wwn_t, uchar_t *);
87fcf3ce44SJohn Forte static int g_find_supported_inq_page(int, int);
88fcf3ce44SJohn Forte static int wwn_list_name_compare(const void *, const void *);
89fcf3ce44SJohn Forte static int devid_get_all(ddi_devid_t, di_node_t, char *,
90fcf3ce44SJohn Forte struct mplist_struct **);
91fcf3ce44SJohn Forte static int get_multipath(char *, struct dlist **,
92fcf3ce44SJohn Forte struct wwn_list_struct *);
93fcf3ce44SJohn Forte static int get_multipath_disk(char *, struct dlist **,
94fcf3ce44SJohn Forte struct wwn_list_struct *);
95fcf3ce44SJohn Forte static void mplist_free(struct mplist_struct *);
96fcf3ce44SJohn Forte static int get_wwn_data(di_node_t, uchar_t **, uchar_t **);
97fcf3ce44SJohn Forte static int get_dev_path(struct wwn_list_struct **, char *, char *);
98fcf3ce44SJohn Forte static int insert_missing_pwwn(char *, struct wwn_list_struct **);
99fcf3ce44SJohn Forte static int get_scsi_vhci_port_wwn(char *, uchar_t *);
100fcf3ce44SJohn Forte static int search_wwn_entry(struct wwn_list_found_struct *, uchar_t *,
101fcf3ce44SJohn Forte uchar_t *);
102fcf3ce44SJohn Forte static int add_wwn_entry(struct wwn_list_found_struct **, uchar_t *,
103fcf3ce44SJohn Forte uchar_t *);
104fcf3ce44SJohn Forte static int string_to_wwn(uchar_t *, uchar_t *);
105fcf3ce44SJohn Forte static int get_wwns(char *, uchar_t *, uchar_t *, int *,
106fcf3ce44SJohn Forte struct wwn_list_found_struct **);
107fcf3ce44SJohn Forte
108fcf3ce44SJohn Forte /* type for g_dev_map_init related routines */
109fcf3ce44SJohn Forte
110fcf3ce44SJohn Forte #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
111fcf3ce44SJohn Forte
112fcf3ce44SJohn Forte typedef struct impl_map_dev_prop {
113fcf3ce44SJohn Forte char prop_name[MAXNAMELEN];
114fcf3ce44SJohn Forte int prop_type;
115fcf3ce44SJohn Forte int prop_size;
116*926d645fSToomas Soome void *prop_data;
117*926d645fSToomas Soome int prop_error;
118fcf3ce44SJohn Forte struct impl_map_dev_prop *next;
119fcf3ce44SJohn Forte } impl_map_dev_prop_t;
120fcf3ce44SJohn Forte
121fcf3ce44SJohn Forte typedef struct impl_map_dev {
122fcf3ce44SJohn Forte int flag;
123fcf3ce44SJohn Forte uint_t topo;
124fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_list;
125fcf3ce44SJohn Forte struct impl_map_dev *parent;
126fcf3ce44SJohn Forte struct impl_map_dev *child;
127*926d645fSToomas Soome struct impl_map_dev *next;
128fcf3ce44SJohn Forte } impl_map_dev_t;
129fcf3ce44SJohn Forte
130*926d645fSToomas Soome /* Defines */
131fcf3ce44SJohn Forte #define VERBPRINT if (verbose) (void) printf
132fcf3ce44SJohn Forte
133fcf3ce44SJohn Forte #define DIR_MATCH_ST "*[0-9+]n"
134fcf3ce44SJohn Forte #define DIR_MATCH_SSD "*s2"
135fcf3ce44SJohn Forte
136fcf3ce44SJohn Forte #define PROP_NOEXIST 0
137fcf3ce44SJohn Forte #define PROP_EXIST 1
138fcf3ce44SJohn Forte
139fcf3ce44SJohn Forte /* Prototypes */
140fcf3ce44SJohn Forte static int create_map(char *, gfc_map_t *, int, int);
141fcf3ce44SJohn Forte static char ctoi(char);
142fcf3ce44SJohn Forte static int lilp_map_cmp(const void*, const void*);
143fcf3ce44SJohn Forte static int devices_get_all(di_node_t, char *, char *,
144fcf3ce44SJohn Forte struct wwn_list_struct **);
145fcf3ce44SJohn Forte static char *my_devfs_path(di_node_t);
146fcf3ce44SJohn Forte static void my_devfs_path_free(char *path);
147fcf3ce44SJohn Forte static void copy_wwn_data_to_str(char *, const uchar_t *);
148fcf3ce44SJohn Forte static void init_drv(char *, char *, char *);
149fcf3ce44SJohn Forte
150fcf3ce44SJohn Forte /* static for g_dev_map_init related routines */
151fcf3ce44SJohn Forte
152fcf3ce44SJohn Forte static int update_map_dev_fc_prop(impl_map_dev_prop_t **, uint32_t,
153fcf3ce44SJohn Forte uchar_t *, uchar_t *, int, int);
154fcf3ce44SJohn Forte static int update_map_dev_FCP_prop(impl_map_dev_prop_t **, uchar_t *, int, int);
155fcf3ce44SJohn Forte static int handle_map_dev_FCP_prop(minor_t, la_wwn_t, impl_map_dev_prop_t **);
156fcf3ce44SJohn Forte static void free_prop_list(impl_map_dev_prop_t **);
157fcf3ce44SJohn Forte static void free_child_list(impl_map_dev_t **);
158fcf3ce44SJohn Forte static u_longlong_t wwnConversion(uchar_t *wwn);
159fcf3ce44SJohn Forte
160fcf3ce44SJohn Forte uchar_t g_switch_to_alpa[] = {
161fcf3ce44SJohn Forte 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
162fcf3ce44SJohn Forte 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
163fcf3ce44SJohn Forte 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
164fcf3ce44SJohn Forte 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
165fcf3ce44SJohn Forte 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
166fcf3ce44SJohn Forte 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
167fcf3ce44SJohn Forte 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
168fcf3ce44SJohn Forte 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
169fcf3ce44SJohn Forte 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
170fcf3ce44SJohn Forte 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
171fcf3ce44SJohn Forte 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
172fcf3ce44SJohn Forte 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
173fcf3ce44SJohn Forte 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
174fcf3ce44SJohn Forte };
175fcf3ce44SJohn Forte
176fcf3ce44SJohn Forte uchar_t g_sf_alpa_to_switch[] = {
177fcf3ce44SJohn Forte 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
178fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
179fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
180fcf3ce44SJohn Forte 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
181fcf3ce44SJohn Forte 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
182fcf3ce44SJohn Forte 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
183fcf3ce44SJohn Forte 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
184fcf3ce44SJohn Forte 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
185fcf3ce44SJohn Forte 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
186fcf3ce44SJohn Forte 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
187fcf3ce44SJohn Forte 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
188fcf3ce44SJohn Forte 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
189fcf3ce44SJohn Forte 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
190fcf3ce44SJohn Forte 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
191fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
192fcf3ce44SJohn Forte 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
193fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
194fcf3ce44SJohn Forte 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
195fcf3ce44SJohn Forte 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
196fcf3ce44SJohn Forte 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
197fcf3ce44SJohn Forte 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
198fcf3ce44SJohn Forte 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
199fcf3ce44SJohn Forte 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
200fcf3ce44SJohn Forte 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
201fcf3ce44SJohn Forte };
202fcf3ce44SJohn Forte
203fcf3ce44SJohn Forte
204fcf3ce44SJohn Forte
205fcf3ce44SJohn Forte /*
206fcf3ce44SJohn Forte * Check if device is in the map.
207fcf3ce44SJohn Forte *
208fcf3ce44SJohn Forte * PARAMS:
209fcf3ce44SJohn Forte * map - loop map returned from fc port
210fcf3ce44SJohn Forte * tid - device ID for private map or 24-bit alpa for fabric map
211fcf3ce44SJohn Forte *
212fcf3ce44SJohn Forte * RETURNS:
213fcf3ce44SJohn Forte * 1 if device present in the map.
214fcf3ce44SJohn Forte * 0 otherwise.
215fcf3ce44SJohn Forte *
216fcf3ce44SJohn Forte */
217fcf3ce44SJohn Forte int
g_device_in_map(gfc_map_t * map,int tid)218fcf3ce44SJohn Forte g_device_in_map(gfc_map_t *map, int tid)
219fcf3ce44SJohn Forte {
220fcf3ce44SJohn Forte int i, j;
221fcf3ce44SJohn Forte gfc_port_dev_info_t *dev_ptr;
222fcf3ce44SJohn Forte
223fcf3ce44SJohn Forte dev_ptr = map->dev_addr;
224fcf3ce44SJohn Forte if ((map->hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
225063d642aSBill Gumbrell (map->hba_addr.port_topology == FC_TOP_FABRIC)) {
226fcf3ce44SJohn Forte for (i = 0; i < map->count; i++, dev_ptr++) {
227fcf3ce44SJohn Forte if (dev_ptr->
228063d642aSBill Gumbrell gfc_port_dev.pub_port.dev_did.port_id == tid) {
229fcf3ce44SJohn Forte /* Does not count if WWN == 0 */
230fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++)
231fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.pub_port.
232063d642aSBill Gumbrell dev_pwwn.raw_wwn[j] != 0)
233fcf3ce44SJohn Forte return (1);
234fcf3ce44SJohn Forte }
235fcf3ce44SJohn Forte }
236fcf3ce44SJohn Forte } else {
237fcf3ce44SJohn Forte for (i = 0; i < map->count; i++, dev_ptr++) {
238fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.priv_port.sf_al_pa ==
239063d642aSBill Gumbrell (int)g_switch_to_alpa[tid]) {
240fcf3ce44SJohn Forte /* Does not count if WWN == 0 */
241fcf3ce44SJohn Forte for (j = 0; j < WWN_SIZE; j++)
242fcf3ce44SJohn Forte if (dev_ptr->gfc_port_dev.priv_port.
243063d642aSBill Gumbrell sf_port_wwn[j] != 0)
244fcf3ce44SJohn Forte return (1);
245fcf3ce44SJohn Forte }
246fcf3ce44SJohn Forte }
247fcf3ce44SJohn Forte }
248fcf3ce44SJohn Forte return (0);
249fcf3ce44SJohn Forte }
250fcf3ce44SJohn Forte
251fcf3ce44SJohn Forte /*
252fcf3ce44SJohn Forte * Inserts any missing port wwns for mpxio device paths
253fcf3ce44SJohn Forte * which are in ONLINE or STANDBY state.
254fcf3ce44SJohn Forte */
255fcf3ce44SJohn Forte static int
insert_missing_pwwn(char * phys_path,struct wwn_list_struct ** wwn_list_ptr)256fcf3ce44SJohn Forte insert_missing_pwwn(char *phys_path, struct wwn_list_struct **wwn_list_ptr)
257fcf3ce44SJohn Forte {
258063d642aSBill Gumbrell mp_pathlist_t pathlist;
259063d642aSBill Gumbrell int i, pathcnt, match;
260063d642aSBill Gumbrell struct wwn_list_struct *new_wwn, *wwn_list_s, *wwn_list_found;
261063d642aSBill Gumbrell char pwwn1[WWN_S_LEN];
262fcf3ce44SJohn Forte
263fcf3ce44SJohn Forte /*
264fcf3ce44SJohn Forte * Now check each scsi_vhci device path to find any missed
265fcf3ce44SJohn Forte * port wwns and insert a new wwn list entry for the missed
266fcf3ce44SJohn Forte * port wwn
267fcf3ce44SJohn Forte */
268fcf3ce44SJohn Forte if (g_get_pathlist(phys_path, &pathlist)) {
269fcf3ce44SJohn Forte /* Free memory for pathlist before return */
270fcf3ce44SJohn Forte S_FREE(pathlist.path_info);
271fcf3ce44SJohn Forte return (L_INVALID_PATH);
272fcf3ce44SJohn Forte }
273fcf3ce44SJohn Forte
274fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
275fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
276fcf3ce44SJohn Forte /*
277fcf3ce44SJohn Forte * Just search for ONLINE and STANDBY paths as
278fcf3ce44SJohn Forte * those should be the only missing wwn entries.
279fcf3ce44SJohn Forte * There is a very small window for an offline
280fcf3ce44SJohn Forte * to have occurred between the time we retrieved
281fcf3ce44SJohn Forte * the device list and a call to this function.
282fcf3ce44SJohn Forte * If that happens, we just won't add it to
283fcf3ce44SJohn Forte * the list which is probably a good thing.
284fcf3ce44SJohn Forte */
285fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
286fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE ||
287fcf3ce44SJohn Forte pathlist.path_info[i].path_state ==
288fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) {
289fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
290063d642aSBill Gumbrell WWN_S_LEN - 1);
291fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0';
292fcf3ce44SJohn Forte /*
293fcf3ce44SJohn Forte * Now search through wwn list for matching
294fcf3ce44SJohn Forte * device path AND pwwn
295fcf3ce44SJohn Forte * If it's found, continue to next path.
296fcf3ce44SJohn Forte * If it's not found, add it the wwn list.
297fcf3ce44SJohn Forte */
298fcf3ce44SJohn Forte match = 0;
299fcf3ce44SJohn Forte
300fcf3ce44SJohn Forte for (wwn_list_s = *wwn_list_ptr; wwn_list_s != NULL;
301fcf3ce44SJohn Forte wwn_list_s = wwn_list_s->wwn_next) {
302fcf3ce44SJohn Forte if (strncmp(phys_path,
303063d642aSBill Gumbrell wwn_list_s->physical_path,
304063d642aSBill Gumbrell strlen(phys_path)) == 0) {
305fcf3ce44SJohn Forte wwn_list_found = wwn_list_s;
306fcf3ce44SJohn Forte if (strncmp(pwwn1,
307063d642aSBill Gumbrell wwn_list_s->port_wwn_s,
308063d642aSBill Gumbrell WWN_S_LEN) == 0) {
309fcf3ce44SJohn Forte match++;
310fcf3ce44SJohn Forte break;
311fcf3ce44SJohn Forte }
312fcf3ce44SJohn Forte }
313fcf3ce44SJohn Forte }
314fcf3ce44SJohn Forte if (match) {
315fcf3ce44SJohn Forte continue;
316fcf3ce44SJohn Forte } else {
317fcf3ce44SJohn Forte /*
318fcf3ce44SJohn Forte * didn't find a match but the mpxio
319fcf3ce44SJohn Forte * device is in the list. Retrieve
320fcf3ce44SJohn Forte * the info from the wwn_list_found
321fcf3ce44SJohn Forte * and add it to the list.
322fcf3ce44SJohn Forte */
323fcf3ce44SJohn Forte if ((new_wwn = (struct wwn_list_struct *)
324063d642aSBill Gumbrell calloc(1,
325063d642aSBill Gumbrell sizeof (struct wwn_list_struct)))
326063d642aSBill Gumbrell == NULL) {
327063d642aSBill Gumbrell S_FREE(pathlist.path_info);
328063d642aSBill Gumbrell return (L_MALLOC_FAILED);
329fcf3ce44SJohn Forte }
330fcf3ce44SJohn Forte if ((new_wwn->physical_path = (char *)
331063d642aSBill Gumbrell calloc(1,
332063d642aSBill Gumbrell strlen(wwn_list_found->physical_path)
333063d642aSBill Gumbrell + 1)) == NULL) {
334063d642aSBill Gumbrell S_FREE(pathlist.path_info);
335063d642aSBill Gumbrell return (L_MALLOC_FAILED);
336fcf3ce44SJohn Forte }
337fcf3ce44SJohn Forte if ((new_wwn->logical_path = (char *)
338063d642aSBill Gumbrell calloc(1,
339063d642aSBill Gumbrell strlen(wwn_list_found->logical_path)
340063d642aSBill Gumbrell + 1)) == NULL) {
341063d642aSBill Gumbrell S_FREE(pathlist.path_info);
342063d642aSBill Gumbrell return (L_MALLOC_FAILED);
343fcf3ce44SJohn Forte }
344fcf3ce44SJohn Forte
345fcf3ce44SJohn Forte /*
346fcf3ce44SJohn Forte * Insert new_wwn at the beginning of the list.
347fcf3ce44SJohn Forte */
348fcf3ce44SJohn Forte new_wwn->wwn_next = *wwn_list_ptr;
349fcf3ce44SJohn Forte (*wwn_list_ptr)->wwn_prev = new_wwn;
350fcf3ce44SJohn Forte
351fcf3ce44SJohn Forte /* set new starting ptr */
352fcf3ce44SJohn Forte *wwn_list_ptr = new_wwn;
353fcf3ce44SJohn Forte
354fcf3ce44SJohn Forte memcpy(new_wwn->physical_path,
355fcf3ce44SJohn Forte wwn_list_found->physical_path,
356063d642aSBill Gumbrell strlen(wwn_list_found->physical_path));
357fcf3ce44SJohn Forte memcpy(new_wwn->logical_path,
358fcf3ce44SJohn Forte wwn_list_found->logical_path,
359063d642aSBill Gumbrell strlen(wwn_list_found->logical_path));
360fcf3ce44SJohn Forte /*
361fcf3ce44SJohn Forte * Copy found node wwn data to this new entry
362fcf3ce44SJohn Forte * Node wwn is required for the wwn_list
363fcf3ce44SJohn Forte * however for mpxio devices it is not
364fcf3ce44SJohn Forte * relevant as it may apply to multiple
365fcf3ce44SJohn Forte * target controllers, so just use what
366fcf3ce44SJohn Forte * we already have in wwn_list_found.
367fcf3ce44SJohn Forte */
368fcf3ce44SJohn Forte memcpy(new_wwn->node_wwn_s,
369fcf3ce44SJohn Forte wwn_list_found->node_wwn_s, WWN_S_LEN);
370fcf3ce44SJohn Forte memcpy(new_wwn->w_node_wwn,
371fcf3ce44SJohn Forte wwn_list_found->w_node_wwn, WWN_SIZE);
372fcf3ce44SJohn Forte new_wwn->device_type =
373fcf3ce44SJohn Forte wwn_list_found->device_type;
374fcf3ce44SJohn Forte memcpy(new_wwn->port_wwn_s, pwwn1, WWN_S_LEN);
375fcf3ce44SJohn Forte }
376fcf3ce44SJohn Forte }
377fcf3ce44SJohn Forte }
378fcf3ce44SJohn Forte S_FREE(pathlist.path_info);
379fcf3ce44SJohn Forte return (0);
380fcf3ce44SJohn Forte }
381fcf3ce44SJohn Forte
382fcf3ce44SJohn Forte /*
383fcf3ce44SJohn Forte * gets the port wwn for a scsi_vhci device using ONLINE path priority
384fcf3ce44SJohn Forte */
385fcf3ce44SJohn Forte static int
get_scsi_vhci_port_wwn(char * phys_path,uchar_t * port_wwn)386fcf3ce44SJohn Forte get_scsi_vhci_port_wwn(char *phys_path, uchar_t *port_wwn)
387fcf3ce44SJohn Forte {
388063d642aSBill Gumbrell mp_pathlist_t pathlist;
389063d642aSBill Gumbrell int i, pathcnt, found;
390063d642aSBill Gumbrell char pwwn1[WWN_S_LEN];
391fcf3ce44SJohn Forte
392fcf3ce44SJohn Forte if (g_get_pathlist(phys_path, &pathlist)) {
393fcf3ce44SJohn Forte return (L_INVALID_PATH);
394fcf3ce44SJohn Forte }
395fcf3ce44SJohn Forte
396fcf3ce44SJohn Forte found = 0;
397fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
398fcf3ce44SJohn Forte /*
399fcf3ce44SJohn Forte * Look for an ONLINE path first.
400fcf3ce44SJohn Forte * If that fails, get the STANDBY path port WWN
401fcf3ce44SJohn Forte * If that fails, give up
402fcf3ce44SJohn Forte */
403fcf3ce44SJohn Forte for (i = 0; found == 0 && i < pathcnt; i++) {
404fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
405fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
406fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
407063d642aSBill Gumbrell WWN_S_LEN - 1);
408fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0';
409fcf3ce44SJohn Forte found++;
410fcf3ce44SJohn Forte }
411fcf3ce44SJohn Forte }
412fcf3ce44SJohn Forte
413fcf3ce44SJohn Forte for (i = 0; found == 0 && i < pathcnt; i++) {
414fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
415fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) {
416fcf3ce44SJohn Forte (void) strncpy(pwwn1, pathlist.path_info[i].path_addr,
417063d642aSBill Gumbrell WWN_S_LEN - 1);
418fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0';
419fcf3ce44SJohn Forte found++;
420fcf3ce44SJohn Forte }
421fcf3ce44SJohn Forte }
422fcf3ce44SJohn Forte
423fcf3ce44SJohn Forte S_FREE(pathlist.path_info);
424fcf3ce44SJohn Forte if (found) {
425fcf3ce44SJohn Forte return (string_to_wwn((uchar_t *)pwwn1, port_wwn));
426fcf3ce44SJohn Forte } else {
427fcf3ce44SJohn Forte return (-1);
428fcf3ce44SJohn Forte }
429fcf3ce44SJohn Forte }
430fcf3ce44SJohn Forte
431fcf3ce44SJohn Forte /*
432fcf3ce44SJohn Forte * searches wwn_list_found for the pwwn passed in
433fcf3ce44SJohn Forte * and sets the corresponding nwwn on return.
434fcf3ce44SJohn Forte * If no match is found, -1 is returned and nwwn is not set.
435fcf3ce44SJohn Forte */
436fcf3ce44SJohn Forte static int
search_wwn_entry(struct wwn_list_found_struct * wwn_list_found,uchar_t * pwwn,uchar_t * nwwn)437fcf3ce44SJohn Forte search_wwn_entry(struct wwn_list_found_struct *wwn_list_found, uchar_t *pwwn,
438063d642aSBill Gumbrell uchar_t *nwwn)
439fcf3ce44SJohn Forte {
440063d642aSBill Gumbrell struct wwn_list_found_struct *wwn_list_s;
441fcf3ce44SJohn Forte
442fcf3ce44SJohn Forte for (wwn_list_s = wwn_list_found; wwn_list_s != NULL;
443fcf3ce44SJohn Forte wwn_list_s = wwn_list_s->wwn_next) {
444063d642aSBill Gumbrell if (memcmp(pwwn, wwn_list_s->port_wwn, WWN_SIZE) == 0) {
445fcf3ce44SJohn Forte memcpy(nwwn, wwn_list_s->node_wwn, WWN_SIZE);
446fcf3ce44SJohn Forte return (0);
447fcf3ce44SJohn Forte }
448fcf3ce44SJohn Forte }
449fcf3ce44SJohn Forte return (-1);
450fcf3ce44SJohn Forte }
451fcf3ce44SJohn Forte
452fcf3ce44SJohn Forte /*
453fcf3ce44SJohn Forte * adds a nwwn, pwwn entry to the next entry in wwn_list_found list
454fcf3ce44SJohn Forte */
455fcf3ce44SJohn Forte static int
add_wwn_entry(struct wwn_list_found_struct ** wwn_list_found,uchar_t * pwwn,uchar_t * nwwn)456fcf3ce44SJohn Forte add_wwn_entry(struct wwn_list_found_struct **wwn_list_found, uchar_t *pwwn,
457063d642aSBill Gumbrell uchar_t *nwwn)
458fcf3ce44SJohn Forte {
459063d642aSBill Gumbrell struct wwn_list_found_struct *new_wwn, *temp_wwn_list_found = NULL;
460fcf3ce44SJohn Forte
461fcf3ce44SJohn Forte /* Got wwns, load data in list */
462fcf3ce44SJohn Forte if ((new_wwn = (struct wwn_list_found_struct *)
463063d642aSBill Gumbrell calloc(1, sizeof (struct wwn_list_found_struct))) == NULL) {
464fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
465fcf3ce44SJohn Forte }
466fcf3ce44SJohn Forte
467fcf3ce44SJohn Forte memcpy(new_wwn->node_wwn, nwwn, WWN_SIZE);
468fcf3ce44SJohn Forte memcpy(new_wwn->port_wwn, pwwn, WWN_SIZE);
469fcf3ce44SJohn Forte
470fcf3ce44SJohn Forte /*
471fcf3ce44SJohn Forte * Insert new_wwn in the list
472fcf3ce44SJohn Forte */
473fcf3ce44SJohn Forte if (*wwn_list_found != NULL) {
474fcf3ce44SJohn Forte temp_wwn_list_found = (*wwn_list_found)->wwn_next;
475fcf3ce44SJohn Forte (*wwn_list_found)->wwn_next = new_wwn;
476fcf3ce44SJohn Forte } else {
477fcf3ce44SJohn Forte *wwn_list_found = new_wwn;
478fcf3ce44SJohn Forte }
479fcf3ce44SJohn Forte new_wwn->wwn_next = temp_wwn_list_found;
480fcf3ce44SJohn Forte
481fcf3ce44SJohn Forte return (0);
482fcf3ce44SJohn Forte }
483fcf3ce44SJohn Forte
484fcf3ce44SJohn Forte
485fcf3ce44SJohn Forte /*
486fcf3ce44SJohn Forte * Create a linked list of all the WWN's for all FC_AL disks and
487fcf3ce44SJohn Forte * tapes that are attached to this host.
488fcf3ce44SJohn Forte *
489fcf3ce44SJohn Forte * RETURN VALUES: 0 O.K.
490fcf3ce44SJohn Forte *
491fcf3ce44SJohn Forte * wwn_list pointer:
492fcf3ce44SJohn Forte * NULL: No devices found.
493fcf3ce44SJohn Forte * !NULL: Devices found
494fcf3ce44SJohn Forte * wwn_list points to a linked list of wwn's.
495fcf3ce44SJohn Forte */
496fcf3ce44SJohn Forte int
g_get_wwn_list(struct wwn_list_struct ** wwn_list_ptr,int verbose)497fcf3ce44SJohn Forte g_get_wwn_list(struct wwn_list_struct **wwn_list_ptr, int verbose)
498fcf3ce44SJohn Forte {
499063d642aSBill Gumbrell struct wwn_list_struct *wwn_list_p = NULL, *wwn_list_tmp_p = NULL;
500063d642aSBill Gumbrell struct wwn_list_found_struct *wwn_list_found = NULL;
501063d642aSBill Gumbrell int err;
502063d642aSBill Gumbrell int al_pa;
503063d642aSBill Gumbrell uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
504063d642aSBill Gumbrell hrtime_t start_time, end_time;
505063d642aSBill Gumbrell char *env = NULL;
506fcf3ce44SJohn Forte
507fcf3ce44SJohn Forte /* return L_NULL_WWN_LIST if wwn_list_ptr is NULL */
508fcf3ce44SJohn Forte if (wwn_list_ptr == NULL) {
509fcf3ce44SJohn Forte return (L_NULL_WWN_LIST);
510fcf3ce44SJohn Forte }
511fcf3ce44SJohn Forte
512fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
513fcf3ce44SJohn Forte start_time = gethrtime();
514fcf3ce44SJohn Forte }
515fcf3ce44SJohn Forte
516063d642aSBill Gumbrell if ((err = g_devices_get_all(wwn_list_ptr)) != 0) {
517fcf3ce44SJohn Forte return (err);
518fcf3ce44SJohn Forte }
519fcf3ce44SJohn Forte
520fcf3ce44SJohn Forte /*
521fcf3ce44SJohn Forte * retain backward compatibility with g_get_wwn_list
522fcf3ce44SJohn Forte * and retrieve the WWN for scsi_vhci devices in the
523fcf3ce44SJohn Forte * same fashion
524fcf3ce44SJohn Forte * Note that for scsi_vhci devices, the wwn fields are
525fcf3ce44SJohn Forte * not relevant but in the previous versions
526fcf3ce44SJohn Forte * we loaded the wwns so...
527fcf3ce44SJohn Forte */
528fcf3ce44SJohn Forte wwn_list_p = *wwn_list_ptr;
529fcf3ce44SJohn Forte while (wwn_list_p != NULL) {
530063d642aSBill Gumbrell if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) {
531063d642aSBill Gumbrell /* get port wwn of first ONLINE, STANDBY */
532063d642aSBill Gumbrell if ((get_scsi_vhci_port_wwn(wwn_list_p->physical_path,
533063d642aSBill Gumbrell port_wwn)) == 0) {
534063d642aSBill Gumbrell if ((search_wwn_entry(wwn_list_found, port_wwn,
535063d642aSBill Gumbrell node_wwn)) != 0) {
536063d642aSBill Gumbrell if ((err =
537063d642aSBill Gumbrell get_wwns(wwn_list_p->physical_path,
538063d642aSBill Gumbrell port_wwn,
539063d642aSBill Gumbrell node_wwn, &al_pa,
540063d642aSBill Gumbrell &wwn_list_found)) != 0) {
541063d642aSBill Gumbrell g_free_wwn_list_found(
542063d642aSBill Gumbrell &wwn_list_found);
543063d642aSBill Gumbrell return (err);
544063d642aSBill Gumbrell }
545063d642aSBill Gumbrell }
546fcf3ce44SJohn Forte } else {
547063d642aSBill Gumbrell /* Use g_get_wwn as a last resort */
548063d642aSBill Gumbrell if ((err = g_get_wwn(wwn_list_p->physical_path,
549063d642aSBill Gumbrell port_wwn, node_wwn, &al_pa, 0)) != 0) {
550063d642aSBill Gumbrell /*
551063d642aSBill Gumbrell * this is a bad WWN.
552063d642aSBill Gumbrell * remove it from the wwn_list.
553063d642aSBill Gumbrell *
554063d642aSBill Gumbrell * After removing the bad WWN,
555063d642aSBill Gumbrell * wwn_list_p should point to the next
556063d642aSBill Gumbrell * node in the list.
557063d642aSBill Gumbrell */
558063d642aSBill Gumbrell if ((wwn_list_p->wwn_prev == NULL) &&
559063d642aSBill Gumbrell (wwn_list_p->wwn_next == NULL)) {
560063d642aSBill Gumbrell *wwn_list_ptr = NULL;
561063d642aSBill Gumbrell free(wwn_list_p);
562063d642aSBill Gumbrell g_free_wwn_list_found(
563063d642aSBill Gumbrell &wwn_list_found);
564063d642aSBill Gumbrell return (L_NO_DEVICES_FOUND);
565063d642aSBill Gumbrell } else if (
566063d642aSBill Gumbrell wwn_list_p->wwn_prev == NULL) {
567063d642aSBill Gumbrell *wwn_list_ptr =
568063d642aSBill Gumbrell wwn_list_p->wwn_next;
569063d642aSBill Gumbrell free(wwn_list_p);
570063d642aSBill Gumbrell wwn_list_p = *wwn_list_ptr;
571063d642aSBill Gumbrell wwn_list_p->wwn_prev = NULL;
572063d642aSBill Gumbrell } else if (
573063d642aSBill Gumbrell wwn_list_p->wwn_next == NULL) {
574063d642aSBill Gumbrell wwn_list_p->wwn_prev->wwn_next =
575063d642aSBill Gumbrell NULL;
576063d642aSBill Gumbrell free(wwn_list_p);
577063d642aSBill Gumbrell wwn_list_p = NULL;
578063d642aSBill Gumbrell } else {
579063d642aSBill Gumbrell wwn_list_tmp_p =
580063d642aSBill Gumbrell wwn_list_p->wwn_next;
581063d642aSBill Gumbrell wwn_list_p->wwn_prev->wwn_next =
582063d642aSBill Gumbrell wwn_list_p->wwn_next;
583063d642aSBill Gumbrell wwn_list_p->wwn_next->wwn_prev =
584063d642aSBill Gumbrell wwn_list_p->wwn_prev;
585063d642aSBill Gumbrell free(wwn_list_p);
586063d642aSBill Gumbrell wwn_list_p = wwn_list_tmp_p;
587063d642aSBill Gumbrell }
588063d642aSBill Gumbrell continue;
589063d642aSBill Gumbrell }
590fcf3ce44SJohn Forte }
591063d642aSBill Gumbrell copy_wwn_data_to_str(wwn_list_p->node_wwn_s, node_wwn);
592063d642aSBill Gumbrell copy_wwn_data_to_str(wwn_list_p->port_wwn_s, port_wwn);
593063d642aSBill Gumbrell memcpy(wwn_list_p->w_node_wwn, node_wwn, WWN_SIZE);
594fcf3ce44SJohn Forte }
595063d642aSBill Gumbrell wwn_list_p = wwn_list_p->wwn_next;
596fcf3ce44SJohn Forte }
597fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found);
598fcf3ce44SJohn Forte
599fcf3ce44SJohn Forte /*
600fcf3ce44SJohn Forte * Now go through the list one more time to add entries for
601fcf3ce44SJohn Forte * any missing port wwns.
602fcf3ce44SJohn Forte * This allows a search on port wwn for any paths which are
603fcf3ce44SJohn Forte * ONLINE or STANDBY. We don't care about OFFLINE as those won't
604fcf3ce44SJohn Forte * and should not show up in the list
605fcf3ce44SJohn Forte */
606fcf3ce44SJohn Forte for (wwn_list_p = *wwn_list_ptr; wwn_list_p != NULL;
607fcf3ce44SJohn Forte wwn_list_p = wwn_list_p->wwn_next) {
608063d642aSBill Gumbrell if (strstr(wwn_list_p->physical_path, SCSI_VHCI) != NULL) {
609063d642aSBill Gumbrell if ((err = insert_missing_pwwn(
610063d642aSBill Gumbrell wwn_list_p->physical_path, wwn_list_ptr)) != 0)
611063d642aSBill Gumbrell return (err);
612063d642aSBill Gumbrell }
613fcf3ce44SJohn Forte }
614fcf3ce44SJohn Forte
615fcf3ce44SJohn Forte if (env != NULL) {
616fcf3ce44SJohn Forte end_time = gethrtime();
617fcf3ce44SJohn Forte fprintf(stdout, " g_get_wwn_list: "
618063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
619063d642aSBill Gumbrell (end_time - start_time)/1000000);
620fcf3ce44SJohn Forte }
621fcf3ce44SJohn Forte return (0);
622fcf3ce44SJohn Forte
623fcf3ce44SJohn Forte }
624fcf3ce44SJohn Forte
625fcf3ce44SJohn Forte int
g_devices_get_all(struct wwn_list_struct ** wwn_list_ptr)626fcf3ce44SJohn Forte g_devices_get_all(struct wwn_list_struct **wwn_list_ptr)
627fcf3ce44SJohn Forte {
628063d642aSBill Gumbrell struct wwn_list_struct *tape_ptr = NULL;
629063d642aSBill Gumbrell struct wwn_list_struct *tmp;
630063d642aSBill Gumbrell int err;
631063d642aSBill Gumbrell di_node_t root;
632063d642aSBill Gumbrell hrtime_t start_time, end_time;
633063d642aSBill Gumbrell char *env = NULL;
634fcf3ce44SJohn Forte
635fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
636fcf3ce44SJohn Forte start_time = gethrtime();
637fcf3ce44SJohn Forte }
638fcf3ce44SJohn Forte
639fcf3ce44SJohn Forte /*
640fcf3ce44SJohn Forte * Try to prime di_drv_first_node()
641fcf3ce44SJohn Forte * If there are no nodes bound, di_drv_first_node()
642fcf3ce44SJohn Forte * will return nothing.
643fcf3ce44SJohn Forte */
644fcf3ce44SJohn Forte init_drv(DEV_TAPE_DIR, DIR_MATCH_ST, SLSH_DRV_NAME_ST);
645fcf3ce44SJohn Forte init_drv(DEV_RDIR, DIR_MATCH_SSD, SLSH_DRV_NAME_SSD);
646fcf3ce44SJohn Forte
647fcf3ce44SJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
648fcf3ce44SJohn Forte return (L_DEV_SNAPSHOT_FAILED);
649fcf3ce44SJohn Forte }
650fcf3ce44SJohn Forte
651fcf3ce44SJohn Forte if (env != NULL) {
652fcf3ce44SJohn Forte end_time = gethrtime();
653fcf3ce44SJohn Forte fprintf(stdout, " di_init - /: "
654063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
655063d642aSBill Gumbrell (end_time - start_time)/1000000);
656fcf3ce44SJohn Forte }
657fcf3ce44SJohn Forte
658fcf3ce44SJohn Forte if (env != NULL) {
659fcf3ce44SJohn Forte start_time = gethrtime();
660fcf3ce44SJohn Forte }
661fcf3ce44SJohn Forte
662fcf3ce44SJohn Forte if ((err = devices_get_all(root, SSD_DRVR_NAME, SSD_MINOR_NAME,
663063d642aSBill Gumbrell wwn_list_ptr)) != 0) {
664fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) {
665fcf3ce44SJohn Forte di_fini(root);
666fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr);
667fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr);
668fcf3ce44SJohn Forte return (err);
669fcf3ce44SJohn Forte }
670fcf3ce44SJohn Forte }
671fcf3ce44SJohn Forte
672fcf3ce44SJohn Forte if (env != NULL) {
673fcf3ce44SJohn Forte end_time = gethrtime();
674fcf3ce44SJohn Forte fprintf(stdout, " devices_get_all - ssd: "
675063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
676063d642aSBill Gumbrell (end_time - start_time)/1000000);
677fcf3ce44SJohn Forte }
678fcf3ce44SJohn Forte
679fcf3ce44SJohn Forte if (env != NULL) {
680fcf3ce44SJohn Forte start_time = gethrtime();
681fcf3ce44SJohn Forte }
682fcf3ce44SJohn Forte
683fcf3ce44SJohn Forte if ((err = devices_get_all(root, ST_DRVR_NAME, ST_MINOR_NAME,
684063d642aSBill Gumbrell &tape_ptr)) != 0) {
685fcf3ce44SJohn Forte di_fini(root);
686fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) {
687fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr);
688fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr);
689fcf3ce44SJohn Forte return (err);
690fcf3ce44SJohn Forte } else {
691fcf3ce44SJohn Forte /*
692fcf3ce44SJohn Forte * if *wwn_list_ptr == NULL
693fcf3ce44SJohn Forte * we have disks but no tapes
694fcf3ce44SJohn Forte * Just return
695fcf3ce44SJohn Forte */
696fcf3ce44SJohn Forte if (*wwn_list_ptr != NULL) {
697fcf3ce44SJohn Forte return (0);
698fcf3ce44SJohn Forte } else {
699fcf3ce44SJohn Forte /*
700fcf3ce44SJohn Forte * No disks or tapes
701fcf3ce44SJohn Forte */
702fcf3ce44SJohn Forte g_free_wwn_list(&tape_ptr);
703fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr);
704fcf3ce44SJohn Forte return (err);
705fcf3ce44SJohn Forte }
706fcf3ce44SJohn Forte }
707fcf3ce44SJohn Forte }
708fcf3ce44SJohn Forte
709fcf3ce44SJohn Forte if (env != NULL) {
710fcf3ce44SJohn Forte end_time = gethrtime();
711fcf3ce44SJohn Forte fprintf(stdout, " devices_get_all - st: "
712063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
713063d642aSBill Gumbrell (end_time - start_time)/1000000);
714fcf3ce44SJohn Forte }
715fcf3ce44SJohn Forte
716fcf3ce44SJohn Forte /* Now link the two together */
717fcf3ce44SJohn Forte if (*wwn_list_ptr != NULL) { /* We have both disks and tapes */
718fcf3ce44SJohn Forte /* Walk to the end of it */
719fcf3ce44SJohn Forte for (tmp = *wwn_list_ptr; tmp->wwn_next != NULL;
720063d642aSBill Gumbrell tmp = tmp->wwn_next)
721063d642aSBill Gumbrell ;
722fcf3ce44SJohn Forte tmp->wwn_next = tape_ptr;
723fcf3ce44SJohn Forte tape_ptr->wwn_prev = tmp;
724fcf3ce44SJohn Forte di_fini(root);
725fcf3ce44SJohn Forte return (0);
726fcf3ce44SJohn Forte }
727fcf3ce44SJohn Forte
728fcf3ce44SJohn Forte /* else we have no disks */
729fcf3ce44SJohn Forte *wwn_list_ptr = tape_ptr;
730fcf3ce44SJohn Forte di_fini(root);
731fcf3ce44SJohn Forte return (0);
732fcf3ce44SJohn Forte }
733fcf3ce44SJohn Forte
734fcf3ce44SJohn Forte void
g_free_wwn_list_found(struct wwn_list_found_struct ** wwn_list_found)735*926d645fSToomas Soome g_free_wwn_list_found(struct wwn_list_found_struct **wwn_list_found)
736*926d645fSToomas Soome {
737fcf3ce44SJohn Forte WWN_list_found *next = NULL;
738fcf3ce44SJohn Forte
739fcf3ce44SJohn Forte /* return if wwn_list_found is NULL */
740fcf3ce44SJohn Forte if (wwn_list_found == NULL) {
741fcf3ce44SJohn Forte return;
742fcf3ce44SJohn Forte }
743fcf3ce44SJohn Forte for (; *wwn_list_found != NULL; *wwn_list_found = next) {
744fcf3ce44SJohn Forte next = (*wwn_list_found)->wwn_next;
745fcf3ce44SJohn Forte g_destroy_data(*wwn_list_found);
746fcf3ce44SJohn Forte *wwn_list_found = NULL;
747fcf3ce44SJohn Forte }
748fcf3ce44SJohn Forte }
749fcf3ce44SJohn Forte
750fcf3ce44SJohn Forte void
g_free_wwn_list(struct wwn_list_struct ** wwn_list)751fcf3ce44SJohn Forte g_free_wwn_list(struct wwn_list_struct **wwn_list)
752fcf3ce44SJohn Forte {
753063d642aSBill Gumbrell WWN_list *next = NULL;
754fcf3ce44SJohn Forte
755fcf3ce44SJohn Forte /* return if wwn_list is NULL */
756fcf3ce44SJohn Forte if (wwn_list == NULL) {
757fcf3ce44SJohn Forte return;
758fcf3ce44SJohn Forte }
759fcf3ce44SJohn Forte
760fcf3ce44SJohn Forte for (; *wwn_list != NULL; *wwn_list = next) {
761fcf3ce44SJohn Forte next = (*wwn_list)->wwn_next;
762fcf3ce44SJohn Forte if ((*wwn_list)->physical_path != NULL)
763fcf3ce44SJohn Forte (void) g_destroy_data((*wwn_list)->physical_path);
764fcf3ce44SJohn Forte if ((*wwn_list)->logical_path != NULL)
765fcf3ce44SJohn Forte (void) g_destroy_data((*wwn_list)->logical_path);
766fcf3ce44SJohn Forte (void) g_destroy_data(*wwn_list);
767fcf3ce44SJohn Forte }
768fcf3ce44SJohn Forte wwn_list = NULL;
769fcf3ce44SJohn Forte }
770fcf3ce44SJohn Forte
771fcf3ce44SJohn Forte
772fcf3ce44SJohn Forte
773fcf3ce44SJohn Forte
774fcf3ce44SJohn Forte void
g_sort_wwn_list(struct wwn_list_struct ** wwn_list)775fcf3ce44SJohn Forte g_sort_wwn_list(struct wwn_list_struct **wwn_list)
776fcf3ce44SJohn Forte {
777fcf3ce44SJohn Forte int i, n;
778fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array;
779fcf3ce44SJohn Forte struct wwn_list_struct *wwn_list_ptr;
780fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array_ptr1;
781fcf3ce44SJohn Forte struct wwn_list_struct **wwn_list_array_ptr2;
782fcf3ce44SJohn Forte
783fcf3ce44SJohn Forte /*
784fcf3ce44SJohn Forte * Count the number of wwn_list in the list
785fcf3ce44SJohn Forte */
786fcf3ce44SJohn Forte for (n = 0, wwn_list_ptr = *wwn_list;
787fcf3ce44SJohn Forte wwn_list_ptr != NULL;
788fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) {
789fcf3ce44SJohn Forte n++;
790fcf3ce44SJohn Forte }
791fcf3ce44SJohn Forte if (n <= 1) {
792fcf3ce44SJohn Forte return;
793fcf3ce44SJohn Forte }
794fcf3ce44SJohn Forte
795fcf3ce44SJohn Forte /*
796fcf3ce44SJohn Forte * Allocate a simple wwn_list array and fill it in
797fcf3ce44SJohn Forte */
798fcf3ce44SJohn Forte wwn_list_array = (struct wwn_list_struct **)
799fcf3ce44SJohn Forte g_zalloc((n+1) * sizeof (struct wwn_list_struct *));
800fcf3ce44SJohn Forte
801fcf3ce44SJohn Forte wwn_list_array_ptr1 = wwn_list_array;
802fcf3ce44SJohn Forte for (wwn_list_ptr = *wwn_list;
803fcf3ce44SJohn Forte wwn_list_ptr != NULL;
804fcf3ce44SJohn Forte wwn_list_ptr = wwn_list_ptr->wwn_next) {
805fcf3ce44SJohn Forte *wwn_list_array_ptr1++ = wwn_list_ptr;
806fcf3ce44SJohn Forte }
807fcf3ce44SJohn Forte *wwn_list_array_ptr1 = NULL;
808fcf3ce44SJohn Forte
809fcf3ce44SJohn Forte /*
810fcf3ce44SJohn Forte * Sort the wwn_list array
811fcf3ce44SJohn Forte */
812fcf3ce44SJohn Forte qsort((void *) wwn_list_array, n,
813fcf3ce44SJohn Forte sizeof (struct wwn_list_struct *), wwn_list_name_compare);
814fcf3ce44SJohn Forte
815fcf3ce44SJohn Forte /*
816fcf3ce44SJohn Forte * Rebuild the linked list wwn_list structure
817fcf3ce44SJohn Forte */
818fcf3ce44SJohn Forte wwn_list_array_ptr1 = wwn_list_array;
819fcf3ce44SJohn Forte *wwn_list = *wwn_list_array_ptr1;
820fcf3ce44SJohn Forte wwn_list_array_ptr2 = wwn_list_array_ptr1 + 1;
821fcf3ce44SJohn Forte (*wwn_list_array_ptr1)->wwn_prev = NULL;
822fcf3ce44SJohn Forte for (i = 0; i < n - 1; i++) {
823063d642aSBill Gumbrell (*wwn_list_array_ptr2)->wwn_prev = *wwn_list_array_ptr1;
824063d642aSBill Gumbrell (*wwn_list_array_ptr1++)->wwn_next = *wwn_list_array_ptr2++;
825fcf3ce44SJohn Forte }
826fcf3ce44SJohn Forte (*wwn_list_array_ptr1)->wwn_next = NULL;
827fcf3ce44SJohn Forte
828fcf3ce44SJohn Forte /*
829fcf3ce44SJohn Forte * Clean up
830fcf3ce44SJohn Forte */
831fcf3ce44SJohn Forte (void) g_destroy_data((void *)wwn_list_array);
832fcf3ce44SJohn Forte }
833fcf3ce44SJohn Forte
834fcf3ce44SJohn Forte int
wwn_list_name_compare(const void * arg1,const void * arg2)835fcf3ce44SJohn Forte wwn_list_name_compare(const void *arg1, const void *arg2)
836fcf3ce44SJohn Forte {
837fcf3ce44SJohn Forte char *s1, *s2;
838fcf3ce44SJohn Forte int n1, n2;
839fcf3ce44SJohn Forte char *p1, *p2;
840fcf3ce44SJohn Forte
841fcf3ce44SJohn Forte s1 = (*((struct wwn_list_struct **)arg1))->logical_path;
842fcf3ce44SJohn Forte s2 = (*((struct wwn_list_struct **)arg2))->logical_path;
843fcf3ce44SJohn Forte for (;;) {
844fcf3ce44SJohn Forte if (*s1 == 0 || *s2 == 0)
845fcf3ce44SJohn Forte break;
846fcf3ce44SJohn Forte if ((isdigit(*s1) && isdigit(*s2))) {
847fcf3ce44SJohn Forte n1 = strtol(s1, &p1, 10);
848fcf3ce44SJohn Forte n2 = strtol(s2, &p2, 10);
849fcf3ce44SJohn Forte if (n1 != n2) {
850fcf3ce44SJohn Forte return (n1 - n2);
851fcf3ce44SJohn Forte }
852fcf3ce44SJohn Forte s1 = p1;
853fcf3ce44SJohn Forte s2 = p2;
854fcf3ce44SJohn Forte } else if (*s1 != *s2) {
855fcf3ce44SJohn Forte break;
856fcf3ce44SJohn Forte } else {
857fcf3ce44SJohn Forte s1++;
858fcf3ce44SJohn Forte s2++;
859fcf3ce44SJohn Forte }
860fcf3ce44SJohn Forte }
861fcf3ce44SJohn Forte return (*s1 - *s2);
862fcf3ce44SJohn Forte }
863fcf3ce44SJohn Forte
864fcf3ce44SJohn Forte /*
865fcf3ce44SJohn Forte * Get the limited map for FC4 devices.
866fcf3ce44SJohn Forte * This function is specific to FC4
867fcf3ce44SJohn Forte * devices and doesn't work for FC (leadville) devices.
868fcf3ce44SJohn Forte *
869fcf3ce44SJohn Forte * RETURN VALUES:
870fcf3ce44SJohn Forte * 0 O.K.
871fcf3ce44SJohn Forte * non-zero otherwise
872fcf3ce44SJohn Forte *
873fcf3ce44SJohn Forte * lilpmap *map_ptr:
874fcf3ce44SJohn Forte * NULL: No devices found
875fcf3ce44SJohn Forte * !NULL: if devices found
876fcf3ce44SJohn Forte */
877fcf3ce44SJohn Forte int
g_get_limited_map(char * path,struct lilpmap * map_ptr,int verbose)878fcf3ce44SJohn Forte g_get_limited_map(char *path, struct lilpmap *map_ptr, int verbose)
879fcf3ce44SJohn Forte {
880063d642aSBill Gumbrell int fd, i;
881063d642aSBill Gumbrell char drvr_path[MAXPATHLEN];
882063d642aSBill Gumbrell struct stat stbuf;
883fcf3ce44SJohn Forte
884fcf3ce44SJohn Forte
885fcf3ce44SJohn Forte /* initialize map */
886fcf3ce44SJohn Forte (void) memset(map_ptr, 0, sizeof (struct lilpmap));
887fcf3ce44SJohn Forte
888fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
889fcf3ce44SJohn Forte /*
890fcf3ce44SJohn Forte * Get the path to the :devctl driver
891fcf3ce44SJohn Forte *
892fcf3ce44SJohn Forte * This assumes the path looks something like this:
893fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1
894fcf3ce44SJohn Forte * or
895fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0
896fcf3ce44SJohn Forte * or
897fcf3ce44SJohn Forte * a 1 level PCI type driver
898fcf3ce44SJohn Forte */
899fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) {
900fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
901fcf3ce44SJohn Forte }
902fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
903fcf3ce44SJohn Forte /* append a port. Just try 0 since they did not give us one */
904fcf3ce44SJohn Forte (void) strcat(drvr_path, ":0");
905fcf3ce44SJohn Forte }
906fcf3ce44SJohn Forte
907fcf3ce44SJohn Forte P_DPRINTF(" g_get_limited_map: Geting drive map from:"
908063d642aSBill Gumbrell " %s\n", drvr_path);
909fcf3ce44SJohn Forte
910fcf3ce44SJohn Forte /* open controller */
911fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
912fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
913fcf3ce44SJohn Forte
914fcf3ce44SJohn Forte if (ioctl(fd, FCIO_GETMAP, map_ptr) != 0) {
915fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GETMAP ioctl failed\n");
916fcf3ce44SJohn Forte (void) close(fd);
917fcf3ce44SJohn Forte return (L_FCIO_GETMAP_IOCTL_FAIL);
918fcf3ce44SJohn Forte }
919fcf3ce44SJohn Forte (void) close(fd);
920fcf3ce44SJohn Forte
921fcf3ce44SJohn Forte /*
922fcf3ce44SJohn Forte * Check for reasonableness.
923fcf3ce44SJohn Forte */
924fcf3ce44SJohn Forte if ((map_ptr->lilp_length > 126) || (map_ptr->lilp_magic != 0x1107)) {
925fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP);
926fcf3ce44SJohn Forte }
927fcf3ce44SJohn Forte for (i = 0; i < (uint_t)map_ptr->lilp_length; i++) {
928fcf3ce44SJohn Forte if (map_ptr->lilp_list[i] > 0xef) {
929fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP);
930fcf3ce44SJohn Forte }
931fcf3ce44SJohn Forte }
932fcf3ce44SJohn Forte
933fcf3ce44SJohn Forte return (0);
934fcf3ce44SJohn Forte }
935fcf3ce44SJohn Forte
936fcf3ce44SJohn Forte
937fcf3ce44SJohn Forte /*
938fcf3ce44SJohn Forte * For leadville specific HBA's ONLY.
939fcf3ce44SJohn Forte * Get the host specific parameters,
940fcf3ce44SJohn Forte * al_pa, hard address, node/port WWN etc.
941fcf3ce44SJohn Forte *
942fcf3ce44SJohn Forte * OUTPUT:
943fcf3ce44SJohn Forte * fc_port_dev_t structure.
944fcf3ce44SJohn Forte *
945fcf3ce44SJohn Forte * RETURNS:
946fcf3ce44SJohn Forte * 0 if OK
947fcf3ce44SJohn Forte * non-zero in case of error.
948fcf3ce44SJohn Forte */
949fcf3ce44SJohn Forte int
g_get_host_params(char * host_path,fc_port_dev_t * host_val,int verbose)950fcf3ce44SJohn Forte g_get_host_params(char *host_path, fc_port_dev_t *host_val, int verbose)
951fcf3ce44SJohn Forte {
952063d642aSBill Gumbrell int err;
953063d642aSBill Gumbrell int fd;
954063d642aSBill Gumbrell int dev_type;
955063d642aSBill Gumbrell fcio_t fcio;
956fcf3ce44SJohn Forte
957fcf3ce44SJohn Forte /* return invalid path if host_path is NULL */
958fcf3ce44SJohn Forte if (host_path == NULL) {
959fcf3ce44SJohn Forte return (L_INVALID_PATH);
960fcf3ce44SJohn Forte }
961fcf3ce44SJohn Forte /* return invalid arg if host_val is NULL */
962fcf3ce44SJohn Forte if (host_val == NULL) {
963fcf3ce44SJohn Forte return (L_INVALID_ARG);
964fcf3ce44SJohn Forte }
965fcf3ce44SJohn Forte
966fcf3ce44SJohn Forte dev_type = g_get_path_type(host_path);
967fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
968fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
969fcf3ce44SJohn Forte }
970fcf3ce44SJohn Forte if ((fd = g_object_open(host_path, O_NDELAY | O_RDONLY)) == -1) {
971fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
972fcf3ce44SJohn Forte }
973fcf3ce44SJohn Forte
974fcf3ce44SJohn Forte /* initialize structure */
975fcf3ce44SJohn Forte (void) memset(host_val, 0, sizeof (struct fc_port_dev));
976fcf3ce44SJohn Forte
977fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_HOST_PARAMS;
978fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
979fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)host_val;
980fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (fc_port_dev_t);
981fcf3ce44SJohn Forte
982fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
983fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n");
984fcf3ce44SJohn Forte (void) close(fd);
985fcf3ce44SJohn Forte return (L_FCIO_GET_HOST_PARAMS_FAIL);
986fcf3ce44SJohn Forte }
987fcf3ce44SJohn Forte (void) close(fd);
988fcf3ce44SJohn Forte
989fcf3ce44SJohn Forte /* get the inquiry information for the leadville HBA. */
990fcf3ce44SJohn Forte if ((err = get_fca_inq_dtype(host_path, host_val->dev_pwwn,
991063d642aSBill Gumbrell &host_val->dev_dtype)) != 0) {
992fcf3ce44SJohn Forte return (err);
993fcf3ce44SJohn Forte }
994fcf3ce44SJohn Forte return (0);
995fcf3ce44SJohn Forte }
996fcf3ce44SJohn Forte
997fcf3ce44SJohn Forte
998fcf3ce44SJohn Forte
999fcf3ce44SJohn Forte /*
1000fcf3ce44SJohn Forte * Issue FCIO ioctls to the port(fp) driver.
1001fcf3ce44SJohn Forte * FCIO ioctl needs to be retried when it
1002fcf3ce44SJohn Forte * is returned with an EINVAL error, wait
1003fcf3ce44SJohn Forte * time between retries should be atleast
1004fcf3ce44SJohn Forte * WAIT_FCIO_IOCTL (too much of a time to wait!!)
1005fcf3ce44SJohn Forte *
1006fcf3ce44SJohn Forte * OUTPUT:
1007fcf3ce44SJohn Forte * fcio_t structure
1008fcf3ce44SJohn Forte *
1009fcf3ce44SJohn Forte * RETURNS:
1010fcf3ce44SJohn Forte * 0 if O.K.
1011fcf3ce44SJohn Forte * non-zero otherwise.
1012fcf3ce44SJohn Forte */
1013fcf3ce44SJohn Forte int
g_issue_fcio_ioctl(int fd,fcio_t * fcio,int verbose)1014fcf3ce44SJohn Forte g_issue_fcio_ioctl(int fd, fcio_t *fcio, int verbose)
1015fcf3ce44SJohn Forte {
1016063d642aSBill Gumbrell int ntries;
1017fcf3ce44SJohn Forte
1018fcf3ce44SJohn Forte for (ntries = 0; ntries < RETRY_FCIO_IOCTL; ntries++) {
1019fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, fcio) != 0) {
1020fcf3ce44SJohn Forte if ((errno == EAGAIN) &&
1021063d642aSBill Gumbrell (ntries+1 < RETRY_FCIO_IOCTL)) {
1022fcf3ce44SJohn Forte /* wait WAIT_FCIO_IOCTL */
1023fcf3ce44SJohn Forte (void) usleep(WAIT_FCIO_IOCTL);
1024fcf3ce44SJohn Forte continue;
1025fcf3ce44SJohn Forte }
1026fcf3ce44SJohn Forte I_DPRINTF("FCIO ioctl failed.\n"
1027063d642aSBill Gumbrell "Error: %s. fc_error = %d (0x%x)\n",
1028063d642aSBill Gumbrell strerror(errno), fcio->fcio_errno,
1029063d642aSBill Gumbrell fcio->fcio_errno);
1030fcf3ce44SJohn Forte if (errno == EINVAL) {
1031fcf3ce44SJohn Forte if (fcio->fcio_errno == FC_TOOMANY) {
1032fcf3ce44SJohn Forte return (L_INVALID_DEVICE_COUNT);
1033fcf3ce44SJohn Forte } else {
1034fcf3ce44SJohn Forte return (errno);
1035fcf3ce44SJohn Forte }
1036fcf3ce44SJohn Forte }
1037fcf3ce44SJohn Forte /*
1038fcf3ce44SJohn Forte * When port is offlined, qlc
1039fcf3ce44SJohn Forte * returns the FC_OFFLINE error and errno
1040fcf3ce44SJohn Forte * is set to EIO.
1041fcf3ce44SJohn Forte * We do want to ignore this error,
1042fcf3ce44SJohn Forte * especially when an enclosure is
1043fcf3ce44SJohn Forte * removed from the loop.
1044fcf3ce44SJohn Forte */
1045fcf3ce44SJohn Forte if (fcio->fcio_errno == FC_OFFLINE)
1046fcf3ce44SJohn Forte break;
1047fcf3ce44SJohn Forte return (-1);
1048fcf3ce44SJohn Forte }
1049fcf3ce44SJohn Forte break;
1050fcf3ce44SJohn Forte }
1051fcf3ce44SJohn Forte
1052fcf3ce44SJohn Forte return (0);
1053fcf3ce44SJohn Forte }
1054fcf3ce44SJohn Forte
1055fcf3ce44SJohn Forte /*
1056fcf3ce44SJohn Forte * This function issues the FCP_TGT_INQUIRY ioctl to
1057fcf3ce44SJohn Forte * the fcp module
1058fcf3ce44SJohn Forte *
1059fcf3ce44SJohn Forte * OUTPUT:
1060fcf3ce44SJohn Forte * fcp_ioctl structure in fcp_data is filled in by fcp
1061fcf3ce44SJohn Forte *
1062fcf3ce44SJohn Forte * RETURN VALUES :
1063fcf3ce44SJohn Forte * 0 on Success
1064fcf3ce44SJohn Forte * Non-zero otherwise
1065fcf3ce44SJohn Forte */
1066fcf3ce44SJohn Forte static int
g_issue_fcp_ioctl(int fd,struct fcp_ioctl * fcp_data,int verbose)1067fcf3ce44SJohn Forte g_issue_fcp_ioctl(int fd, struct fcp_ioctl *fcp_data, int verbose)
1068fcf3ce44SJohn Forte {
1069*926d645fSToomas Soome int num_tries = 0;
1070fcf3ce44SJohn Forte struct device_data *dev_data = NULL;
1071fcf3ce44SJohn Forte
1072fcf3ce44SJohn Forte /*
1073fcf3ce44SJohn Forte * Issue the ioctl to FCP
1074fcf3ce44SJohn Forte * The retries are required because the driver may
1075fcf3ce44SJohn Forte * need some time to respond at times.
1076fcf3ce44SJohn Forte */
1077fcf3ce44SJohn Forte while (num_tries++ < RETRY_FCP_IOCTL) {
1078fcf3ce44SJohn Forte /* if ioctl fails it is an error from Solaris operation. */
1079fcf3ce44SJohn Forte if (ioctl(fd, FCP_TGT_INQUIRY, fcp_data) == -1) {
1080fcf3ce44SJohn Forte if (errno == EAGAIN) {
1081fcf3ce44SJohn Forte (void) usleep(WAIT_FCP_IOCTL);
1082fcf3ce44SJohn Forte continue;
1083fcf3ce44SJohn Forte } else {
1084fcf3ce44SJohn Forte break;
1085fcf3ce44SJohn Forte }
1086fcf3ce44SJohn Forte }
1087fcf3ce44SJohn Forte dev_data = (struct device_data *)((void *)(fcp_data->list));
1088fcf3ce44SJohn Forte if (dev_data->dev_status == 0) {
1089fcf3ce44SJohn Forte return (0);
1090fcf3ce44SJohn Forte }
1091fcf3ce44SJohn Forte
1092fcf3ce44SJohn Forte if (dev_data->dev_status == EAGAIN) {
1093fcf3ce44SJohn Forte (void) usleep(WAIT_FCP_IOCTL);
1094fcf3ce44SJohn Forte continue;
1095fcf3ce44SJohn Forte } else {
1096fcf3ce44SJohn Forte dev_data->dev0_type = DTYPE_UNKNOWN;
1097fcf3ce44SJohn Forte return (0);
1098fcf3ce44SJohn Forte }
1099fcf3ce44SJohn Forte }
1100fcf3ce44SJohn Forte
1101fcf3ce44SJohn Forte return (L_FCP_TGT_INQUIRY_FAIL);
1102fcf3ce44SJohn Forte }
1103fcf3ce44SJohn Forte
1104fcf3ce44SJohn Forte /*
1105fcf3ce44SJohn Forte * Get the number of devices and also
1106fcf3ce44SJohn Forte * a list of devices accessible through
1107fcf3ce44SJohn Forte * the device's port as specified by path.
1108fcf3ce44SJohn Forte * The calling function * is responsible for freeing the dev_list.
1109fcf3ce44SJohn Forte *
1110fcf3ce44SJohn Forte * Acquires inq_dtype from g_get_inq_dtype() and
1111fcf3ce44SJohn Forte * stores into dev_dtype field of fc_port_dev.
1112fcf3ce44SJohn Forte *
1113fcf3ce44SJohn Forte * For fabric devices call FCIO_DEV_LOGIN (if necessary) to execute port login
1114fcf3ce44SJohn Forte * and get inq dtype.
1115fcf3ce44SJohn Forte *
1116fcf3ce44SJohn Forte * dev_list:
1117fcf3ce44SJohn Forte * NULL: No devices found, in case of an error
1118fcf3ce44SJohn Forte * Non-NULL: Devices found.
1119fcf3ce44SJohn Forte * ndevs:
1120fcf3ce44SJohn Forte * set to the number of devices
1121fcf3ce44SJohn Forte * accessible through the port.
1122fcf3ce44SJohn Forte *
1123fcf3ce44SJohn Forte * RETURNS:
1124fcf3ce44SJohn Forte * 0 if O.K.
1125fcf3ce44SJohn Forte * non-zero otherwise
1126fcf3ce44SJohn Forte */
1127fcf3ce44SJohn Forte int
g_get_dev_list(char * path,fc_port_dev_t ** dev_list,int * ndevs)1128fcf3ce44SJohn Forte g_get_dev_list(char *path, fc_port_dev_t **dev_list, int *ndevs)
1129fcf3ce44SJohn Forte {
1130063d642aSBill Gumbrell int num_devices = 0;
1131063d642aSBill Gumbrell int i, err, ulp_failure = 0, new_count = 0;
1132063d642aSBill Gumbrell int dev_type;
1133063d642aSBill Gumbrell int fd;
1134063d642aSBill Gumbrell char fcapath[MAXPATHLEN];
1135063d642aSBill Gumbrell char *char_ptr;
1136063d642aSBill Gumbrell struct stat stbuf;
1137063d642aSBill Gumbrell fcio_t fcio;
1138063d642aSBill Gumbrell uint32_t port_top;
1139063d642aSBill Gumbrell fc_port_dev_t *dlist;
1140fcf3ce44SJohn Forte
1141fcf3ce44SJohn Forte *dev_list = dlist = NULL;
1142fcf3ce44SJohn Forte (void) strcpy(fcapath, path);
1143fcf3ce44SJohn Forte /*
1144fcf3ce44SJohn Forte * Get the path to the :devctl driver
1145fcf3ce44SJohn Forte *
1146fcf3ce44SJohn Forte * This assumes the path looks something like this:
1147fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
1148fcf3ce44SJohn Forte * or
1149fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
1150fcf3ce44SJohn Forte * or
1151fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
1152fcf3ce44SJohn Forte * or
1153fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl
1154fcf3ce44SJohn Forte */
1155fcf3ce44SJohn Forte if (strstr(fcapath, DRV_NAME_SSD) || strstr(fcapath, SES_NAME)) {
1156fcf3ce44SJohn Forte if ((char_ptr = strrchr(fcapath, '/')) == NULL) {
1157fcf3ce44SJohn Forte return (L_INVALID_PATH);
1158fcf3ce44SJohn Forte }
1159fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */
1160fcf3ce44SJohn Forte /* append controller */
1161fcf3ce44SJohn Forte (void) strcat(fcapath, FC_CTLR);
1162fcf3ce44SJohn Forte } else {
1163fcf3ce44SJohn Forte if (stat(fcapath, &stbuf) < 0) {
1164fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
1165fcf3ce44SJohn Forte }
1166fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
1167fcf3ce44SJohn Forte /* append controller */
1168fcf3ce44SJohn Forte (void) strcat(fcapath, FC_CTLR);
1169fcf3ce44SJohn Forte }
1170fcf3ce44SJohn Forte }
1171fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath);
1172fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
1173fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
1174fcf3ce44SJohn Forte }
1175fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) {
1176fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
1177fcf3ce44SJohn Forte }
1178fcf3ce44SJohn Forte
1179fcf3ce44SJohn Forte /*
1180fcf3ce44SJohn Forte * Get the device list from port driver
1181fcf3ce44SJohn Forte */
1182fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_NUM_DEVS;
1183fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (num_devices);
1184fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
1185fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&num_devices;
1186fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
1187fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n");
1188fcf3ce44SJohn Forte (void) close(fd);
1189fcf3ce44SJohn Forte return (L_FCIO_GET_NUM_DEVS_FAIL);
1190fcf3ce44SJohn Forte }
1191fcf3ce44SJohn Forte if (num_devices == 0) {
1192fcf3ce44SJohn Forte *ndevs = 0;
1193fcf3ce44SJohn Forte (void) close(fd);
1194fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
1195fcf3ce44SJohn Forte }
1196fcf3ce44SJohn Forte
1197fcf3ce44SJohn Forte if ((dlist = (fc_port_dev_t *)calloc(num_devices,
1198063d642aSBill Gumbrell sizeof (fc_port_dev_t))) == NULL) {
1199fcf3ce44SJohn Forte (void) close(fd);
1200fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1201fcf3ce44SJohn Forte }
1202fcf3ce44SJohn Forte bzero((caddr_t)&fcio, sizeof (fcio));
1203fcf3ce44SJohn Forte /* Get the device list */
1204fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST;
1205fcf3ce44SJohn Forte /* Information read operation */
1206fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
1207fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
1208fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)dlist;
1209fcf3ce44SJohn Forte /* new device count */
1210fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count);
1211fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count;
1212fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
1213063d642aSBill Gumbrell if (err == L_INVALID_DEVICE_COUNT) {
1214fcf3ce44SJohn Forte /*
1215063d642aSBill Gumbrell * original buffer was small so allocate buffer
1216063d642aSBill Gumbrell * with a new count and retry.
1217fcf3ce44SJohn Forte */
1218063d642aSBill Gumbrell free(dlist);
1219063d642aSBill Gumbrell num_devices = new_count;
1220063d642aSBill Gumbrell new_count = 0;
1221063d642aSBill Gumbrell if ((dlist = (fc_port_dev_t *)calloc(num_devices,
1222063d642aSBill Gumbrell sizeof (fc_port_dev_t))) == NULL) {
1223063d642aSBill Gumbrell (void) close(fd);
1224063d642aSBill Gumbrell return (L_MALLOC_FAILED);
1225063d642aSBill Gumbrell }
1226063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_GET_DEV_LIST;
1227063d642aSBill Gumbrell /* Information read operation */
1228063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_READ;
1229063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)dlist;
1230063d642aSBill Gumbrell fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
1231063d642aSBill Gumbrell /* new device count */
1232063d642aSBill Gumbrell fcio.fcio_alen = sizeof (new_count);
1233063d642aSBill Gumbrell fcio.fcio_abuf = (caddr_t)&new_count;
1234063d642aSBill Gumbrell if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
1235063d642aSBill Gumbrell if (err == L_INVALID_DEVICE_COUNT) {
1236063d642aSBill Gumbrell /*
1237063d642aSBill Gumbrell * No more retry. There may be severe
1238063d642aSBill Gumbrell * hardware problem so return error
1239063d642aSBill Gumbrell * here.
1240063d642aSBill Gumbrell */
1241063d642aSBill Gumbrell I_DPRINTF(" Device count was %d"
1242063d642aSBill Gumbrell " should have been %d\n",
1243063d642aSBill Gumbrell num_devices, new_count);
1244063d642aSBill Gumbrell } else {
1245063d642aSBill Gumbrell I_DPRINTF(
1246063d642aSBill Gumbrell " FCIO_GET_DEV_LIST ioctl failed.");
1247063d642aSBill Gumbrell err = L_FCIO_GET_DEV_LIST_FAIL;
1248063d642aSBill Gumbrell }
1249063d642aSBill Gumbrell free(dlist);
1250063d642aSBill Gumbrell (void) close(fd);
1251063d642aSBill Gumbrell return (err);
1252063d642aSBill Gumbrell }
1253063d642aSBill Gumbrell } else {
1254fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed.");
1255063d642aSBill Gumbrell free(dlist);
1256063d642aSBill Gumbrell (void) close(fd);
1257063d642aSBill Gumbrell return (L_FCIO_GET_DEV_LIST_FAIL);
1258063d642aSBill Gumbrell }
1259fcf3ce44SJohn Forte }
1260fcf3ce44SJohn Forte
1261fcf3ce44SJohn Forte /*
1262fcf3ce44SJohn Forte * if new count is smaller than the original number from
1263fcf3ce44SJohn Forte * FCIO_GET_NUM_DEVS, adjust new count and buffer size
1264fcf3ce44SJohn Forte * and continue.
1265fcf3ce44SJohn Forte */
1266fcf3ce44SJohn Forte if (new_count < num_devices) {
1267fcf3ce44SJohn Forte if (new_count == 0) {
1268fcf3ce44SJohn Forte *ndevs = 0;
1269fcf3ce44SJohn Forte (void) close(fd);
1270fcf3ce44SJohn Forte S_FREE(dlist);
1271fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
1272fcf3ce44SJohn Forte }
1273fcf3ce44SJohn Forte num_devices = new_count;
1274fcf3ce44SJohn Forte if ((dlist = (fc_port_dev_t *)realloc(dlist,
1275063d642aSBill Gumbrell (new_count * sizeof (fc_port_dev_t))))
1276063d642aSBill Gumbrell == NULL) {
1277fcf3ce44SJohn Forte S_FREE(dlist);
1278fcf3ce44SJohn Forte (void) close(fd);
1279fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1280fcf3ce44SJohn Forte }
1281fcf3ce44SJohn Forte }
1282fcf3ce44SJohn Forte
1283fcf3ce44SJohn Forte *dev_list = dlist;
1284fcf3ce44SJohn Forte *ndevs = num_devices;
1285fcf3ce44SJohn Forte
1286fcf3ce44SJohn Forte /* close here since fcapath will be passed to other routines. */
1287fcf3ce44SJohn Forte (void) close(fd);
1288fcf3ce44SJohn Forte
1289fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) {
1290fcf3ce44SJohn Forte free(*dev_list);
1291fcf3ce44SJohn Forte *dev_list = NULL;
1292fcf3ce44SJohn Forte return (err);
1293fcf3ce44SJohn Forte }
1294fcf3ce44SJohn Forte
1295fcf3ce44SJohn Forte /* Get the inq_dtype for each device on dev list. */
1296fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dlist++) {
1297fcf3ce44SJohn Forte /* Get the inq_dtype for each device. */
1298fcf3ce44SJohn Forte if ((err = g_get_inq_dtype(fcapath, dlist->dev_pwwn,
1299063d642aSBill Gumbrell &dlist->dev_dtype)) != 0) {
1300fcf3ce44SJohn Forte /*
1301fcf3ce44SJohn Forte * if g_get_inq_dtype failed on g_dev_login
1302fcf3ce44SJohn Forte * or g_issue_fcp_ioctl, continue to the next
1303fcf3ce44SJohn Forte * dev on dlist.
1304fcf3ce44SJohn Forte * L_GET_DEV_LIST_ULP_FAILURE is returned
1305fcf3ce44SJohn Forte * after processing the whole dlist.
1306fcf3ce44SJohn Forte */
1307fcf3ce44SJohn Forte if ((err == L_FCIO_DEV_LOGIN_FAIL) ||
1308063d642aSBill Gumbrell (err == L_FCP_TGT_INQUIRY_FAIL)) {
1309fcf3ce44SJohn Forte ulp_failure = 1;
1310fcf3ce44SJohn Forte dlist->dev_dtype = GFC_ERR_INQ_DTYPE;
1311fcf3ce44SJohn Forte } else {
1312fcf3ce44SJohn Forte (void) free(*dev_list);
1313fcf3ce44SJohn Forte *dev_list = NULL;
1314fcf3ce44SJohn Forte return (err);
1315fcf3ce44SJohn Forte }
1316fcf3ce44SJohn Forte }
1317fcf3ce44SJohn Forte }
1318fcf3ce44SJohn Forte
1319fcf3ce44SJohn Forte if (ulp_failure) {
1320fcf3ce44SJohn Forte return (L_GET_DEV_LIST_ULP_FAILURE);
1321fcf3ce44SJohn Forte } else {
1322fcf3ce44SJohn Forte return (0);
1323fcf3ce44SJohn Forte }
1324fcf3ce44SJohn Forte }
1325fcf3ce44SJohn Forte
1326fcf3ce44SJohn Forte
1327fcf3ce44SJohn Forte /* Constant used by g_get_inq_dtype() */
1328fcf3ce44SJohn Forte #define FCP_PATH "/devices/pseudo/fcp@0:fcp"
1329fcf3ce44SJohn Forte
1330fcf3ce44SJohn Forte /*
1331fcf3ce44SJohn Forte * Gets the inq_dtype for devices on the fabric FC driver
1332fcf3ce44SJohn Forte * through an ioctl to the FCP module.
1333fcf3ce44SJohn Forte *
1334fcf3ce44SJohn Forte * OUTPUT:
1335fcf3ce44SJohn Forte * inq_dtype is set to the dtype on success
1336fcf3ce44SJohn Forte *
1337fcf3ce44SJohn Forte * RETURN VALUES:
1338fcf3ce44SJohn Forte * 0 on Success
1339fcf3ce44SJohn Forte * Non-zero on error
1340fcf3ce44SJohn Forte */
1341fcf3ce44SJohn Forte int
g_get_inq_dtype(char * fcapath,la_wwn_t pwwn,uchar_t * inq_dtype)1342fcf3ce44SJohn Forte g_get_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype)
1343fcf3ce44SJohn Forte {
1344fcf3ce44SJohn Forte int dev_type, fd;
1345fcf3ce44SJohn Forte int err, fcp_fd;
1346fcf3ce44SJohn Forte uint32_t state;
1347fcf3ce44SJohn Forte uint32_t port_top = 0;
1348fcf3ce44SJohn Forte struct fcp_ioctl fcp_data;
1349fcf3ce44SJohn Forte struct device_data inq_data;
1350fcf3ce44SJohn Forte struct stat sbuf;
1351fcf3ce44SJohn Forte
1352fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath);
1353fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
1354fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
1355fcf3ce44SJohn Forte }
1356fcf3ce44SJohn Forte
1357fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(fcapath, &port_top, 0)) != 0) {
1358fcf3ce44SJohn Forte return (err);
1359fcf3ce44SJohn Forte }
1360fcf3ce44SJohn Forte
1361fcf3ce44SJohn Forte if ((port_top == FC_TOP_FABRIC) || (port_top == FC_TOP_PUBLIC_LOOP)) {
1362fcf3ce44SJohn Forte /*
1363fcf3ce44SJohn Forte * if there is an error on getting port state we will
1364fcf3ce44SJohn Forte * continue to login.
1365fcf3ce44SJohn Forte * state can be either of
1366fcf3ce44SJohn Forte * PORT_DEVICE_INVALID, PORT_DEVICE_VALID,
1367fcf3ce44SJohn Forte * PORT_DEVICE_LOGGED_IN. Trying port login
1368fcf3ce44SJohn Forte * unless already logged in.
1369fcf3ce44SJohn Forte * It will be examined if there is an adverse
1370fcf3ce44SJohn Forte * effect on invalid state device.
1371fcf3ce44SJohn Forte */
1372fcf3ce44SJohn Forte if (((err = g_get_dev_port_state(fcapath, pwwn, &state))
1373063d642aSBill Gumbrell != 0) || (state != PORT_DEVICE_LOGGED_IN)) {
1374fcf3ce44SJohn Forte /* do port login to fabric device. */
1375fcf3ce44SJohn Forte if ((err = g_dev_login(fcapath, pwwn)) != 0) {
1376fcf3ce44SJohn Forte return (err);
1377fcf3ce44SJohn Forte }
1378fcf3ce44SJohn Forte }
1379fcf3ce44SJohn Forte }
1380fcf3ce44SJohn Forte
1381fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1)
1382fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
1383fcf3ce44SJohn Forte
1384fcf3ce44SJohn Forte if (fstat(fd, &sbuf) == -1) {
1385fcf3ce44SJohn Forte (void) close(fd);
1386fcf3ce44SJohn Forte return (L_FSTAT_ERROR);
1387fcf3ce44SJohn Forte }
1388fcf3ce44SJohn Forte
1389fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
1390fcf3ce44SJohn Forte (void) close(fd);
1391fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
1392fcf3ce44SJohn Forte }
1393fcf3ce44SJohn Forte
1394fcf3ce44SJohn Forte /* Get the minor number for an fp instance */
1395fcf3ce44SJohn Forte fcp_data.fp_minor = minor(sbuf.st_rdev);
1396fcf3ce44SJohn Forte
1397fcf3ce44SJohn Forte fcp_data.listlen = 1;
1398fcf3ce44SJohn Forte inq_data.dev_pwwn = pwwn; /* The port WWN as passed */
1399fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data;
1400fcf3ce44SJohn Forte
1401fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
1402fcf3ce44SJohn Forte close(fd);
1403fcf3ce44SJohn Forte close(fcp_fd);
1404fcf3ce44SJohn Forte return (err);
1405fcf3ce44SJohn Forte }
1406fcf3ce44SJohn Forte *inq_dtype = inq_data.dev0_type;
1407fcf3ce44SJohn Forte
1408fcf3ce44SJohn Forte close(fd);
1409fcf3ce44SJohn Forte close(fcp_fd);
1410fcf3ce44SJohn Forte
1411fcf3ce44SJohn Forte return (err);
1412fcf3ce44SJohn Forte }
1413fcf3ce44SJohn Forte
1414fcf3ce44SJohn Forte /*
1415fcf3ce44SJohn Forte * Gets the inq_dtype for devices on the fabric FC driver
1416fcf3ce44SJohn Forte * through an ioctl to the FCP module.
1417fcf3ce44SJohn Forte *
1418fcf3ce44SJohn Forte * This is exactly same as g_get_inq_dtype except that it does not do
1419fcf3ce44SJohn Forte * g_dev_login(). That is for the case when the FCA tries to get its own
1420fcf3ce44SJohn Forte * inq_dtype and in such a case, it cannot PLOGI into itself.
1421fcf3ce44SJohn Forte *
1422fcf3ce44SJohn Forte * OUTPUT:
1423fcf3ce44SJohn Forte * inq_dtype is set to the dtype on success
1424fcf3ce44SJohn Forte *
1425fcf3ce44SJohn Forte * RETURN VALUES:
1426fcf3ce44SJohn Forte * 0 on Success
1427fcf3ce44SJohn Forte * Non-zero on error
1428fcf3ce44SJohn Forte */
1429fcf3ce44SJohn Forte static int
get_fca_inq_dtype(char * fcapath,la_wwn_t pwwn,uchar_t * inq_dtype)1430fcf3ce44SJohn Forte get_fca_inq_dtype(char *fcapath, la_wwn_t pwwn, uchar_t *inq_dtype)
1431fcf3ce44SJohn Forte {
1432fcf3ce44SJohn Forte int dev_type, fd;
1433fcf3ce44SJohn Forte int err, fcp_fd;
1434fcf3ce44SJohn Forte struct fcp_ioctl fcp_data;
1435fcf3ce44SJohn Forte struct device_data inq_data;
1436fcf3ce44SJohn Forte struct stat sbuf;
1437fcf3ce44SJohn Forte
1438fcf3ce44SJohn Forte dev_type = g_get_path_type(fcapath);
1439fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & FC_GEN_XPORT)) {
1440fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
1441fcf3ce44SJohn Forte }
1442fcf3ce44SJohn Forte
1443fcf3ce44SJohn Forte if ((fd = g_object_open(fcapath, O_NDELAY | O_RDONLY)) == -1) {
1444fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
1445fcf3ce44SJohn Forte }
1446fcf3ce44SJohn Forte
1447fcf3ce44SJohn Forte if (fstat(fd, &sbuf) == -1) {
1448fcf3ce44SJohn Forte (void) close(fd);
1449fcf3ce44SJohn Forte return (L_FSTAT_ERROR);
1450fcf3ce44SJohn Forte }
1451fcf3ce44SJohn Forte
1452fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
1453fcf3ce44SJohn Forte (void) close(fd);
1454fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
1455fcf3ce44SJohn Forte }
1456fcf3ce44SJohn Forte
1457fcf3ce44SJohn Forte /* Get the minor number for an fp instance */
1458fcf3ce44SJohn Forte fcp_data.fp_minor = minor(sbuf.st_rdev);
1459fcf3ce44SJohn Forte
1460fcf3ce44SJohn Forte fcp_data.listlen = 1;
1461fcf3ce44SJohn Forte inq_data.dev_pwwn = pwwn; /* The port WWN as passed */
1462fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data;
1463fcf3ce44SJohn Forte
1464fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
1465fcf3ce44SJohn Forte close(fd);
1466fcf3ce44SJohn Forte close(fcp_fd);
1467fcf3ce44SJohn Forte return (err);
1468fcf3ce44SJohn Forte }
1469fcf3ce44SJohn Forte *inq_dtype = inq_data.dev0_type;
1470fcf3ce44SJohn Forte
1471fcf3ce44SJohn Forte close(fd);
1472fcf3ce44SJohn Forte close(fcp_fd);
1473fcf3ce44SJohn Forte
1474fcf3ce44SJohn Forte return (0);
1475fcf3ce44SJohn Forte }
1476fcf3ce44SJohn Forte
1477fcf3ce44SJohn Forte /*
1478fcf3ce44SJohn Forte * This function returns the traditional g_get_dev_map. Device list
1479fcf3ce44SJohn Forte * and local hba seperate.
1480fcf3ce44SJohn Forte */
1481fcf3ce44SJohn Forte int
g_get_dev_map(char * path,gfc_map_t * map_ptr,int verbose)1482fcf3ce44SJohn Forte g_get_dev_map(char *path, gfc_map_t *map_ptr, int verbose)
1483fcf3ce44SJohn Forte {
1484fcf3ce44SJohn Forte return (create_map(path, map_ptr, verbose, MAP_FORMAT_STANDARD));
1485fcf3ce44SJohn Forte }
1486fcf3ce44SJohn Forte
1487fcf3ce44SJohn Forte /*
1488fcf3ce44SJohn Forte * This function returns the device map with local hba in physical
1489fcf3ce44SJohn Forte * order. Note: Physical order is only returned properly for
1490fcf3ce44SJohn Forte * private loop. local hba is also included seperate
1491fcf3ce44SJohn Forte */
1492fcf3ce44SJohn Forte int
g_get_lilp_map(char * path,gfc_map_t * map_ptr,int verbose)1493fcf3ce44SJohn Forte g_get_lilp_map(char *path, gfc_map_t *map_ptr, int verbose)
1494fcf3ce44SJohn Forte {
1495fcf3ce44SJohn Forte return (create_map(path, map_ptr, verbose, MAP_FORMAT_LILP));
1496fcf3ce44SJohn Forte }
1497fcf3ce44SJohn Forte
1498fcf3ce44SJohn Forte /*
1499fcf3ce44SJohn Forte * Gets device map from nexus driver
1500fcf3ce44SJohn Forte *
1501fcf3ce44SJohn Forte * PARAMS:
1502fcf3ce44SJohn Forte * path - must be the physical path to a device
1503fcf3ce44SJohn Forte * map - loop map returned from fc port.
1504fcf3ce44SJohn Forte * verbose - options.
1505fcf3ce44SJohn Forte *
1506fcf3ce44SJohn Forte * LOGIC:
1507fcf3ce44SJohn Forte * 1. check the validity of path via g_get_path_type.
1508fcf3ce44SJohn Forte * 2. If FC path, get the topology of the path via
1509fcf3ce44SJohn Forte * g_get_fca_port_topology.
1510fcf3ce44SJohn Forte *
1511fcf3ce44SJohn Forte * 3. If FC type(Leadville statck)
1512fcf3ce44SJohn Forte * g_get_dev_list to get the device node list of fc_port_dev_t.
1513fcf3ce44SJohn Forte * g_get_host_params to get the fca port node of fc_port_dev_t.
1514fcf3ce44SJohn Forte *
1515fcf3ce44SJohn Forte * Case of fabric or public loop topology
1516fcf3ce44SJohn Forte * Check if the port id > 0xffff.
1517fcf3ce44SJohn Forte * Move device node and fca port node to
1518fcf3ce44SJohn Forte * gfc_map structure via gfc_port_dev_info_t
1519fcf3ce44SJohn Forte * pub_port union.
1520fcf3ce44SJohn Forte * Issue g_get_inq_dtype to get FCP inquiry data
1521fcf3ce44SJohn Forte * and store it into gfc_port_dev_info_t.
1522fcf3ce44SJohn Forte *
1523fcf3ce44SJohn Forte * Case of private loop topology
1524fcf3ce44SJohn Forte * Check if the port id < 0xff.
1525fcf3ce44SJohn Forte * Move device node and fca port node to
1526fcf3ce44SJohn Forte * gfc_map structure via gfc_port_dev_info_t
1527fcf3ce44SJohn Forte * priv_port union.
1528fcf3ce44SJohn Forte * Issue g_get_inq_dtype to get FCP inquiry data
1529fcf3ce44SJohn Forte * and store it into gfc_port_dev_info_t.
1530fcf3ce44SJohn Forte *
1531fcf3ce44SJohn Forte * else FC4 type(socal/sf or ifp stack)
1532fcf3ce44SJohn Forte * SFIOCGMAP ioctl to get the device and hba nodes of
1533fcf3ce44SJohn Forte * sf_addr_pair_t.
1534fcf3ce44SJohn Forte *
1535fcf3ce44SJohn Forte *
1536fcf3ce44SJohn Forte * RETURNS:
1537fcf3ce44SJohn Forte * 0 : if OK
1538fcf3ce44SJohn Forte * non-zero: otherwise
1539fcf3ce44SJohn Forte */
1540fcf3ce44SJohn Forte int
create_map(char * path,gfc_map_t * map_ptr,int verbose,int map_type)1541fcf3ce44SJohn Forte create_map(char *path, gfc_map_t *map_ptr, int verbose, int map_type)
1542fcf3ce44SJohn Forte {
1543063d642aSBill Gumbrell int fd, i, j, num_devices = 0, err, pathcnt = 1;
1544063d642aSBill Gumbrell char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN];
1545063d642aSBill Gumbrell char *char_ptr;
1546063d642aSBill Gumbrell struct stat stbuf;
1547063d642aSBill Gumbrell fc_port_dev_t *dev_list, *dlistptr;
1548063d642aSBill Gumbrell uint32_t hba_port_top = 0;
1549063d642aSBill Gumbrell uint_t dev_type;
1550063d642aSBill Gumbrell sf_al_map_t sf_map;
1551063d642aSBill Gumbrell gfc_port_dev_info_t *dev_ptr;
1552063d642aSBill Gumbrell fc_port_dev_t fp_hba_port;
1553063d642aSBill Gumbrell mp_pathlist_t pathlist;
1554063d642aSBill Gumbrell int p_on = 0, p_st = 0;
1555fcf3ce44SJohn Forte
1556fcf3ce44SJohn Forte /* return invalid path if path is NULL */
1557fcf3ce44SJohn Forte if (path == NULL) {
1558fcf3ce44SJohn Forte return (L_INVALID_PATH);
1559fcf3ce44SJohn Forte }
1560fcf3ce44SJohn Forte /* return invalid arg if map_ptr is NULL */
1561fcf3ce44SJohn Forte if (map_ptr == NULL) {
1562fcf3ce44SJohn Forte return (L_INVALID_ARG);
1563fcf3ce44SJohn Forte }
1564fcf3ce44SJohn Forte
1565fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1566fcf3ce44SJohn Forte map_ptr->count = 0;
1567fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
1568fcf3ce44SJohn Forte /*
1569fcf3ce44SJohn Forte * Get the path to the :devctl driver
1570fcf3ce44SJohn Forte *
1571fcf3ce44SJohn Forte * This assumes the path looks something like this:
1572fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
1573fcf3ce44SJohn Forte * or
1574fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
1575fcf3ce44SJohn Forte * or
1576fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
1577fcf3ce44SJohn Forte * or
1578fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl
1579fcf3ce44SJohn Forte */
1580fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) {
1581fcf3ce44SJohn Forte (void) strcpy(drvr_path0, path);
1582fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path0, &pathlist)) {
1583fcf3ce44SJohn Forte return (L_INVALID_PATH);
1584fcf3ce44SJohn Forte }
1585fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
1586fcf3ce44SJohn Forte p_on = p_st = 0;
1587fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
1588fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
1589fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
1590063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
1591fcf3ce44SJohn Forte p_on = i;
1592fcf3ce44SJohn Forte break;
1593fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
1594063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
1595fcf3ce44SJohn Forte p_st = i;
1596fcf3ce44SJohn Forte }
1597fcf3ce44SJohn Forte }
1598fcf3ce44SJohn Forte }
1599fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state ==
1600fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
1601fcf3ce44SJohn Forte /* on_line path */
1602fcf3ce44SJohn Forte (void) strcpy(drvr_path,
1603063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
1604fcf3ce44SJohn Forte } else {
1605fcf3ce44SJohn Forte /* standby or path0 */
1606fcf3ce44SJohn Forte (void) strcpy(drvr_path,
1607063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
1608fcf3ce44SJohn Forte }
1609fcf3ce44SJohn Forte free(pathlist.path_info);
1610fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
1611fcf3ce44SJohn Forte } else {
1612fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
1613fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) ||
1614063d642aSBill Gumbrell strstr(drvr_path, SES_NAME) ||
1615063d642aSBill Gumbrell strstr(drvr_path, DRV_NAME_ST)) {
1616fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
1617fcf3ce44SJohn Forte return (L_INVALID_PATH);
1618fcf3ce44SJohn Forte }
1619fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */
1620fcf3ce44SJohn Forte /* append controller */
1621fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
1622fcf3ce44SJohn Forte } else {
1623fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) {
1624fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
1625fcf3ce44SJohn Forte }
1626fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
1627fcf3ce44SJohn Forte /* append controller */
1628fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
1629fcf3ce44SJohn Forte }
1630fcf3ce44SJohn Forte }
1631fcf3ce44SJohn Forte }
1632fcf3ce44SJohn Forte
1633fcf3ce44SJohn Forte P_DPRINTF(" g_get_dev_map: Geting drive map from:"
1634063d642aSBill Gumbrell " %s\n", drvr_path);
1635fcf3ce44SJohn Forte
1636fcf3ce44SJohn Forte dev_type = g_get_path_type(drvr_path);
1637fcf3ce44SJohn Forte if ((dev_type == 0) || !(dev_type & XPORT_MASK)) {
1638fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
1639fcf3ce44SJohn Forte }
1640fcf3ce44SJohn Forte
1641fcf3ce44SJohn Forte /* get fiber topology */
1642fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(drvr_path,
1643063d642aSBill Gumbrell &hba_port_top, verbose)) != 0) {
1644fcf3ce44SJohn Forte return (err);
1645fcf3ce44SJohn Forte }
1646fcf3ce44SJohn Forte
1647fcf3ce44SJohn Forte /* for FC devices. */
1648fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) {
1649fcf3ce44SJohn Forte /*
1650fcf3ce44SJohn Forte * if g_get_dev_list fails with L_NO_DEVICES_FOUND
1651fcf3ce44SJohn Forte * we still want to call g_get_host_params to try to find the
1652fcf3ce44SJohn Forte * HBA. If we do not see any HBAs on the loop, the
1653fcf3ce44SJohn Forte * g_get_host_params will fail when it trys to issue the target
1654fcf3ce44SJohn Forte * inquiry ioctl. In this case, we would still like to return
1655fcf3ce44SJohn Forte * L_NO_DEVICES_FOUND.
1656fcf3ce44SJohn Forte *
1657fcf3ce44SJohn Forte * If g_get_dev_list fails with L_NO_DEVICES_FOUND and
1658fcf3ce44SJohn Forte * g_get_host_params fails, the function returns
1659fcf3ce44SJohn Forte * L_NO_DEVICES_FOUND
1660fcf3ce44SJohn Forte */
1661fcf3ce44SJohn Forte if ((err = g_get_dev_list(drvr_path, &dev_list,
1662063d642aSBill Gumbrell &num_devices)) != 0) {
1663fcf3ce44SJohn Forte /*
1664fcf3ce44SJohn Forte * g_get_dev_map doesn't allow ulp failure
1665fcf3ce44SJohn Forte * to continue thus we need to free dev_list
1666fcf3ce44SJohn Forte * here.
1667fcf3ce44SJohn Forte */
1668fcf3ce44SJohn Forte if (err == L_GET_DEV_LIST_ULP_FAILURE) {
1669fcf3ce44SJohn Forte (void) free(dev_list);
1670fcf3ce44SJohn Forte }
1671fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) {
1672fcf3ce44SJohn Forte return (err);
1673fcf3ce44SJohn Forte }
1674fcf3ce44SJohn Forte }
1675fcf3ce44SJohn Forte
1676fcf3ce44SJohn Forte /* Get local HBA information */
1677fcf3ce44SJohn Forte if ((err = g_get_host_params(drvr_path, &fp_hba_port,
1678063d642aSBill Gumbrell verbose)) != 0) {
1679fcf3ce44SJohn Forte (void) free(dev_list);
1680fcf3ce44SJohn Forte if (num_devices == 0)
1681fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
1682fcf3ce44SJohn Forte else
1683fcf3ce44SJohn Forte return (err);
1684fcf3ce44SJohn Forte }
1685fcf3ce44SJohn Forte
1686fcf3ce44SJohn Forte /* If devices, other than local HBA are found */
1687fcf3ce44SJohn Forte /* allocate space for them in the gfc_map. */
1688fcf3ce44SJohn Forte if (num_devices > 0) {
1689fcf3ce44SJohn Forte
1690fcf3ce44SJohn Forte /* If map type is on MAP_FORMAT_LILP we need */
1691fcf3ce44SJohn Forte /* to add space for the local HBA */
1692fcf3ce44SJohn Forte if (map_type == MAP_FORMAT_LILP) {
1693fcf3ce44SJohn Forte map_ptr->count = ++num_devices;
1694fcf3ce44SJohn Forte } else {
1695fcf3ce44SJohn Forte map_ptr->count = num_devices;
1696fcf3ce44SJohn Forte }
1697fcf3ce44SJohn Forte
1698fcf3ce44SJohn Forte if ((map_ptr->dev_addr = (gfc_port_dev_info_t *)
1699fcf3ce44SJohn Forte calloc(map_ptr->count,
1700063d642aSBill Gumbrell sizeof (gfc_port_dev_info_t))) == NULL) {
1701063d642aSBill Gumbrell (void) free(dev_list);
1702063d642aSBill Gumbrell return (L_MALLOC_FAILED);
1703fcf3ce44SJohn Forte }
1704fcf3ce44SJohn Forte }
1705fcf3ce44SJohn Forte
1706fcf3ce44SJohn Forte /* If we want the lilp map then we need to do a little */
1707fcf3ce44SJohn Forte /* work here. The lilp map contains the local hba in */
1708fcf3ce44SJohn Forte /* the dev_addr. Once this has been added qsort the */
1709fcf3ce44SJohn Forte /* dev_addr array so it's in physical order. */
1710fcf3ce44SJohn Forte /* The lilp map will contain the local hba in the */
1711fcf3ce44SJohn Forte /* dev_addr array only when num_devices > 0 */
1712fcf3ce44SJohn Forte if (map_type == MAP_FORMAT_LILP && num_devices > 0) {
1713fcf3ce44SJohn Forte
1714fcf3ce44SJohn Forte /* First we need to allocate one additional */
1715*926d645fSToomas Soome /* device to the dev_addr structure, for the */
1716fcf3ce44SJohn Forte /* local hba */
1717fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)realloc(dev_list,
1718063d642aSBill Gumbrell (num_devices * sizeof (fc_port_dev_t))))
1719063d642aSBill Gumbrell == NULL) {
1720fcf3ce44SJohn Forte S_FREE(dev_list);
1721fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1722fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1723fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1724fcf3ce44SJohn Forte }
1725fcf3ce44SJohn Forte
1726fcf3ce44SJohn Forte /* Next, copy the local hba into this new loc. */
1727fcf3ce44SJohn Forte if (memcpy(dev_list+(num_devices-1), &fp_hba_port,
1728063d642aSBill Gumbrell sizeof (fc_port_dev_t)) == NULL) {
1729fcf3ce44SJohn Forte (void) free(dev_list);
1730fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1731fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1732fcf3ce44SJohn Forte return (L_MEMCPY_FAILED);
1733fcf3ce44SJohn Forte }
1734fcf3ce44SJohn Forte
1735fcf3ce44SJohn Forte /* Now sort by physical location */
1736fcf3ce44SJohn Forte qsort((void*)dev_list, num_devices,
1737063d642aSBill Gumbrell sizeof (fc_port_dev_t), lilp_map_cmp);
1738fcf3ce44SJohn Forte }
1739fcf3ce44SJohn Forte
1740fcf3ce44SJohn Forte dlistptr = dev_list;
1741fcf3ce44SJohn Forte dev_ptr = map_ptr->dev_addr;
1742fcf3ce44SJohn Forte
1743fcf3ce44SJohn Forte switch (hba_port_top) {
1744fcf3ce44SJohn Forte case FC_TOP_FABRIC:
1745fcf3ce44SJohn Forte case FC_TOP_PUBLIC_LOOP:
1746fcf3ce44SJohn Forte if (fp_hba_port.dev_did.port_id <= 0xffff) {
1747fcf3ce44SJohn Forte (void) free(dlistptr);
1748fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1749fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1750fcf3ce44SJohn Forte return (L_INVALID_FABRIC_ADDRESS);
1751fcf3ce44SJohn Forte } else {
1752fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top;
1753fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.pub_port =
1754063d642aSBill Gumbrell fp_hba_port;
1755fcf3ce44SJohn Forte }
1756fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_ptr++,
1757063d642aSBill Gumbrell dev_list++) {
1758fcf3ce44SJohn Forte if (dev_list->dev_did.port_id <= 0xffff) {
1759fcf3ce44SJohn Forte (void) free(dlistptr);
1760fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1761fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1762fcf3ce44SJohn Forte return (L_INVALID_FABRIC_ADDRESS);
1763fcf3ce44SJohn Forte } else {
1764fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top;
1765fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.pub_port =
1766063d642aSBill Gumbrell *dev_list;
1767fcf3ce44SJohn Forte }
1768fcf3ce44SJohn Forte }
1769fcf3ce44SJohn Forte break;
1770fcf3ce44SJohn Forte case FC_TOP_PRIVATE_LOOP:
1771fcf3ce44SJohn Forte /*
1772fcf3ce44SJohn Forte * Map the (new->old) structures here.
1773fcf3ce44SJohn Forte * Checking (i < SF_NUM_ENTRIES_IN_MAP) just to
1774fcf3ce44SJohn Forte * make sure that we don't overrun the map structure
1775fcf3ce44SJohn Forte * since it can hold data for upto 126 devices.
1776fcf3ce44SJohn Forte */
1777fcf3ce44SJohn Forte if (fp_hba_port.dev_did.port_id > 0xff) {
1778fcf3ce44SJohn Forte (void) free(dlistptr);
1779fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1780fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1781fcf3ce44SJohn Forte return (L_INVALID_PRIVATE_LOOP_ADDRESS);
1782fcf3ce44SJohn Forte } else {
1783fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top;
1784fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.
1785063d642aSBill Gumbrell priv_port.sf_al_pa =
1786063d642aSBill Gumbrell (uchar_t)fp_hba_port.dev_did.port_id;
1787fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.
1788063d642aSBill Gumbrell priv_port.sf_hard_address = (uchar_t)
1789063d642aSBill Gumbrell fp_hba_port.dev_hard_addr.hard_addr;
1790fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++) {
1791fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.
1792063d642aSBill Gumbrell priv_port.sf_node_wwn[j] =
1793063d642aSBill Gumbrell fp_hba_port.dev_nwwn.raw_wwn[j];
1794fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.
1795063d642aSBill Gumbrell priv_port.sf_port_wwn[j] =
1796063d642aSBill Gumbrell fp_hba_port.dev_pwwn.raw_wwn[j];
1797fcf3ce44SJohn Forte }
1798fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.
1799063d642aSBill Gumbrell priv_port.sf_inq_dtype =
1800063d642aSBill Gumbrell fp_hba_port.dev_dtype;
1801fcf3ce44SJohn Forte }
1802fcf3ce44SJohn Forte
1803fcf3ce44SJohn Forte for (i = 0; (i < num_devices &&
1804063d642aSBill Gumbrell i < SF_NUM_ENTRIES_IN_MAP);
1805063d642aSBill Gumbrell i++, dev_ptr++, dev_list++) {
1806fcf3ce44SJohn Forte /*
1807fcf3ce44SJohn Forte * Out of 24 bits of port_id, copy only
1808fcf3ce44SJohn Forte * 8 bits to al_pa. This works okay for
1809fcf3ce44SJohn Forte * devices that're on a private loop.
1810fcf3ce44SJohn Forte */
1811fcf3ce44SJohn Forte if (dev_list->dev_did.port_id > 0xff) {
1812fcf3ce44SJohn Forte (void) free(dlistptr);
1813fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1814fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1815fcf3ce44SJohn Forte return (L_INVALID_PRIVATE_LOOP_ADDRESS);
1816fcf3ce44SJohn Forte }
1817fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top;
1818fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port.sf_al_pa
1819063d642aSBill Gumbrell = (uchar_t)dev_list->dev_did.port_id;
1820063d642aSBill Gumbrell
1821063d642aSBill Gumbrell /* Code refactorization is needed for C style */
1822063d642aSBill Gumbrell dev_ptr->gfc_port_dev.priv_port.sf_hard_address
1823063d642aSBill Gumbrell = (uchar_t)dev_list->dev_hard_addr.hard_addr;
1824063d642aSBill Gumbrell
1825fcf3ce44SJohn Forte for (j = 0; j < FC_WWN_SIZE; j++) {
1826063d642aSBill Gumbrell
1827063d642aSBill Gumbrell dev_ptr->gfc_port_dev.priv_port.sf_node_wwn[j] =
1828063d642aSBill Gumbrell dev_list->dev_nwwn.raw_wwn[j];
1829063d642aSBill Gumbrell dev_ptr->gfc_port_dev.priv_port.sf_port_wwn[j] =
1830063d642aSBill Gumbrell dev_list->dev_pwwn.raw_wwn[j];
1831063d642aSBill Gumbrell
1832fcf3ce44SJohn Forte }
1833fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port.sf_inq_dtype =
1834063d642aSBill Gumbrell dev_list->dev_dtype;
1835fcf3ce44SJohn Forte }
1836fcf3ce44SJohn Forte break;
1837fcf3ce44SJohn Forte case FC_TOP_PT_PT:
1838fcf3ce44SJohn Forte (void) free(dlistptr);
1839fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1840fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1841fcf3ce44SJohn Forte return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
1842fcf3ce44SJohn Forte default:
1843fcf3ce44SJohn Forte (void) free(dlistptr);
1844fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1845fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1846fcf3ce44SJohn Forte return (L_UNEXPECTED_FC_TOPOLOGY);
1847fcf3ce44SJohn Forte } /* End of switch on port_topology */
1848fcf3ce44SJohn Forte (void) free(dlistptr);
1849fcf3ce44SJohn Forte
1850fcf3ce44SJohn Forte } else { /* sf and fc4/pci devices */
1851fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
1852fcf3ce44SJohn Forte return (errno);
1853fcf3ce44SJohn Forte /* initialize map */
1854fcf3ce44SJohn Forte (void) memset(&sf_map, 0, sizeof (struct sf_al_map));
1855fcf3ce44SJohn Forte if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
1856fcf3ce44SJohn Forte I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
1857fcf3ce44SJohn Forte (void) close(fd);
1858fcf3ce44SJohn Forte return (L_SFIOCGMAP_IOCTL_FAIL);
1859fcf3ce44SJohn Forte }
1860fcf3ce44SJohn Forte /* Check for reasonableness. */
1861fcf3ce44SJohn Forte if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) {
1862fcf3ce44SJohn Forte (void) close(fd);
1863fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP);
1864fcf3ce44SJohn Forte }
1865fcf3ce44SJohn Forte if (sf_map.sf_count == 0) {
1866fcf3ce44SJohn Forte (void) close(fd);
1867fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
1868fcf3ce44SJohn Forte }
1869fcf3ce44SJohn Forte
1870fcf3ce44SJohn Forte map_ptr->count = sf_map.sf_count;
1871fcf3ce44SJohn Forte if ((map_ptr->dev_addr =
1872063d642aSBill Gumbrell (gfc_port_dev_info_t *)calloc(map_ptr->count,
1873063d642aSBill Gumbrell sizeof (gfc_port_dev_info_t))) == NULL) {
1874fcf3ce44SJohn Forte (void) close(fd);
1875fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1876fcf3ce44SJohn Forte }
1877fcf3ce44SJohn Forte dev_ptr = map_ptr->dev_addr;
1878fcf3ce44SJohn Forte for (i = 0; i < sf_map.sf_count; i++, dev_ptr++) {
1879fcf3ce44SJohn Forte if (sf_map.sf_addr_pair[i].sf_al_pa > 0xef) {
1880fcf3ce44SJohn Forte (void) free(map_ptr->dev_addr);
1881fcf3ce44SJohn Forte map_ptr->dev_addr = NULL;
1882fcf3ce44SJohn Forte (void) close(fd);
1883fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP);
1884fcf3ce44SJohn Forte }
1885fcf3ce44SJohn Forte dev_ptr->port_topology = hba_port_top;
1886fcf3ce44SJohn Forte dev_ptr->gfc_port_dev.priv_port =
1887063d642aSBill Gumbrell sf_map.sf_addr_pair[i];
1888fcf3ce44SJohn Forte }
1889fcf3ce44SJohn Forte map_ptr->hba_addr.port_topology = hba_port_top;
1890fcf3ce44SJohn Forte map_ptr->hba_addr.gfc_port_dev.priv_port =
1891063d642aSBill Gumbrell sf_map.sf_hba_addr;
1892fcf3ce44SJohn Forte (void) close(fd);
1893fcf3ce44SJohn Forte }
1894fcf3ce44SJohn Forte
1895fcf3ce44SJohn Forte return (0);
1896fcf3ce44SJohn Forte }
1897fcf3ce44SJohn Forte
1898fcf3ce44SJohn Forte /*
1899fcf3ce44SJohn Forte * This function consturct FC proerty list using map_dev_fc_prop_list.
1900fcf3ce44SJohn Forte *
1901fcf3ce44SJohn Forte * port WWN, node WWN, port addr and hard addr properties is constructed.
1902fcf3ce44SJohn Forte *
1903fcf3ce44SJohn Forte * return 0 if OK.
1904fcf3ce44SJohn Forte * otherwise returns error code.
1905fcf3ce44SJohn Forte */
1906fcf3ce44SJohn Forte 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)1907063d642aSBill Gumbrell update_map_dev_fc_prop(impl_map_dev_prop_t **prop_list, uint32_t map_topo,
1908063d642aSBill Gumbrell uchar_t *port_wwn, uchar_t *node_wwn, int port_addr, int hard_addr)
1909fcf3ce44SJohn Forte {
1910fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_ptr, *pl_start = NULL, *pl_end = NULL;
1911fcf3ce44SJohn Forte uchar_t *port_wwn_data, *node_wwn_data;
1912fcf3ce44SJohn Forte int *port_addr_data, *hard_addr_data;
1913fcf3ce44SJohn Forte
1914fcf3ce44SJohn Forte /* consrtruct port addr property. */
1915063d642aSBill Gumbrell if ((map_topo == FC_TOP_FABRIC) || (map_topo == FC_TOP_PUBLIC_LOOP)) {
1916fcf3ce44SJohn Forte if (port_addr <= 0xffff) {
1917063d642aSBill Gumbrell return (L_INVALID_FABRIC_ADDRESS);
1918fcf3ce44SJohn Forte }
1919fcf3ce44SJohn Forte } else if (map_topo == FC_TOP_PRIVATE_LOOP) {
1920fcf3ce44SJohn Forte if (port_addr > 0xff) {
1921063d642aSBill Gumbrell return (L_INVALID_PRIVATE_LOOP_ADDRESS);
1922fcf3ce44SJohn Forte }
1923fcf3ce44SJohn Forte }
1924fcf3ce44SJohn Forte
1925fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1926063d642aSBill Gumbrell 1, sizeof (impl_map_dev_prop_t))) == NULL) {
1927fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1928fcf3ce44SJohn Forte }
1929fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, PORT_ADDR_PROP,
1930063d642aSBill Gumbrell strlen(PORT_ADDR_PROP));
1931fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_INT;
1932fcf3ce44SJohn Forte
1933fcf3ce44SJohn Forte if ((port_addr_data = (int *)calloc(1, sizeof (int))) == NULL) {
1934fcf3ce44SJohn Forte free(prop_ptr);
1935fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1936fcf3ce44SJohn Forte }
1937fcf3ce44SJohn Forte *port_addr_data = port_addr;
1938fcf3ce44SJohn Forte prop_ptr->prop_data = port_addr_data;
1939fcf3ce44SJohn Forte
1940fcf3ce44SJohn Forte pl_start = pl_end = prop_ptr;
1941fcf3ce44SJohn Forte
1942fcf3ce44SJohn Forte /* consrtruct port WWN property. */
1943fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1944063d642aSBill Gumbrell 1, sizeof (impl_map_dev_prop_t))) == NULL) {
1945fcf3ce44SJohn Forte free_prop_list(&pl_start);
1946fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1947fcf3ce44SJohn Forte }
1948fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, PORT_WWN_PROP,
1949063d642aSBill Gumbrell strlen(PORT_WWN_PROP));
1950fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
1951fcf3ce44SJohn Forte
1952063d642aSBill Gumbrell if ((port_wwn_data = (uchar_t *)calloc(1, FC_WWN_SIZE)) == NULL) {
1953fcf3ce44SJohn Forte free_prop_list(&pl_start);
1954fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1955fcf3ce44SJohn Forte }
1956fcf3ce44SJohn Forte memcpy(port_wwn_data, port_wwn, FC_WWN_SIZE);
1957fcf3ce44SJohn Forte prop_ptr->prop_data = port_wwn_data;
1958fcf3ce44SJohn Forte prop_ptr->prop_size = FC_WWN_SIZE;
1959fcf3ce44SJohn Forte pl_end->next = prop_ptr;
1960fcf3ce44SJohn Forte pl_end = prop_ptr;
1961fcf3ce44SJohn Forte
1962fcf3ce44SJohn Forte /* consrtruct node WWN property. */
1963fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1964063d642aSBill Gumbrell 1, sizeof (impl_map_dev_prop_t))) == NULL) {
1965fcf3ce44SJohn Forte free_prop_list(&pl_start);
1966fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1967fcf3ce44SJohn Forte }
1968fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, NODE_WWN_PROP,
1969063d642aSBill Gumbrell strlen(NODE_WWN_PROP));
1970fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
1971fcf3ce44SJohn Forte
1972fcf3ce44SJohn Forte if ((node_wwn_data = (uchar_t *)calloc(
1973063d642aSBill Gumbrell 1, FC_WWN_SIZE)) == NULL) {
1974fcf3ce44SJohn Forte free_prop_list(&pl_start);
1975fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1976fcf3ce44SJohn Forte }
1977fcf3ce44SJohn Forte memcpy(node_wwn_data, node_wwn, FC_WWN_SIZE);
1978fcf3ce44SJohn Forte prop_ptr->prop_data = node_wwn_data;
1979fcf3ce44SJohn Forte prop_ptr->prop_size = FC_WWN_SIZE;
1980fcf3ce44SJohn Forte pl_end->next = prop_ptr;
1981fcf3ce44SJohn Forte pl_end = prop_ptr;
1982fcf3ce44SJohn Forte
1983fcf3ce44SJohn Forte /* consrtruct hard addr property. */
1984fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
1985063d642aSBill Gumbrell 1, sizeof (impl_map_dev_prop_t))) == NULL) {
1986fcf3ce44SJohn Forte free_prop_list(&pl_start);
1987fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1988fcf3ce44SJohn Forte }
1989fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, HARD_ADDR_PROP,
1990063d642aSBill Gumbrell strlen(HARD_ADDR_PROP));
1991fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_INT;
1992fcf3ce44SJohn Forte
1993063d642aSBill Gumbrell if ((hard_addr_data = (int *)calloc(1, sizeof (int))) == NULL) {
1994fcf3ce44SJohn Forte free_prop_list(&pl_start);
1995fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
1996fcf3ce44SJohn Forte }
1997fcf3ce44SJohn Forte *hard_addr_data = hard_addr;
1998fcf3ce44SJohn Forte prop_ptr->prop_data = hard_addr_data;
1999fcf3ce44SJohn Forte pl_end->next = prop_ptr;
2000fcf3ce44SJohn Forte pl_end = prop_ptr;
2001fcf3ce44SJohn Forte
2002fcf3ce44SJohn Forte if (*prop_list == NULL) {
2003fcf3ce44SJohn Forte *prop_list = pl_start;
2004fcf3ce44SJohn Forte } else {
2005fcf3ce44SJohn Forte pl_end->next = (*prop_list)->next;
2006fcf3ce44SJohn Forte *prop_list = pl_start;
2007fcf3ce44SJohn Forte }
2008fcf3ce44SJohn Forte
2009fcf3ce44SJohn Forte return (0);
2010fcf3ce44SJohn Forte }
2011fcf3ce44SJohn Forte
2012fcf3ce44SJohn Forte /*
2013fcf3ce44SJohn Forte * This function consturct FCP inq dtype propery.
2014fcf3ce44SJohn Forte * if inq_dtype is null the property is constrcted with err info.
2015fcf3ce44SJohn Forte *
2016fcf3ce44SJohn Forte * L_MALLOC_FAILED is the only possible error.
2017fcf3ce44SJohn Forte */
2018fcf3ce44SJohn Forte static int
update_map_dev_FCP_prop(impl_map_dev_prop_t ** prop_list,uchar_t * inq_dtype,int err,int exist)2019063d642aSBill Gumbrell update_map_dev_FCP_prop(impl_map_dev_prop_t **prop_list,
2020063d642aSBill Gumbrell uchar_t *inq_dtype, int err, int exist)
2021fcf3ce44SJohn Forte {
2022fcf3ce44SJohn Forte impl_map_dev_prop_t *prop_ptr, *old_prop_ptr;
2023fcf3ce44SJohn Forte uchar_t *inq_dtype_data;
2024fcf3ce44SJohn Forte
2025fcf3ce44SJohn Forte if ((prop_ptr = (impl_map_dev_prop_t *)calloc(
2026063d642aSBill Gumbrell 1, sizeof (impl_map_dev_prop_t))) == NULL) {
2027fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
2028fcf3ce44SJohn Forte }
2029fcf3ce44SJohn Forte
2030fcf3ce44SJohn Forte (void) strncpy(prop_ptr->prop_name, INQ_DTYPE_PROP,
2031063d642aSBill Gumbrell strlen(INQ_DTYPE_PROP));
2032fcf3ce44SJohn Forte
2033fcf3ce44SJohn Forte if (inq_dtype == NULL) {
2034fcf3ce44SJohn Forte prop_ptr->prop_data = NULL;
2035fcf3ce44SJohn Forte prop_ptr->prop_error = err;
2036fcf3ce44SJohn Forte } else {
2037fcf3ce44SJohn Forte if ((inq_dtype_data = (uchar_t *)calloc(
2038063d642aSBill Gumbrell 1, sizeof (uchar_t))) == NULL) {
2039fcf3ce44SJohn Forte free(prop_ptr);
2040fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
2041fcf3ce44SJohn Forte }
2042fcf3ce44SJohn Forte memcpy(inq_dtype_data, inq_dtype, sizeof (uchar_t));
2043fcf3ce44SJohn Forte prop_ptr->prop_data = inq_dtype_data;
2044fcf3ce44SJohn Forte prop_ptr->prop_type = GFC_PROP_TYPE_BYTES;
2045fcf3ce44SJohn Forte prop_ptr->prop_size = sizeof (uchar_t);
2046fcf3ce44SJohn Forte }
2047fcf3ce44SJohn Forte
2048fcf3ce44SJohn Forte if (*prop_list == NULL) {
2049fcf3ce44SJohn Forte *prop_list = prop_ptr;
2050fcf3ce44SJohn Forte } else {
2051fcf3ce44SJohn Forte if (exist == PROP_EXIST) {
2052fcf3ce44SJohn Forte prop_ptr->next = (*prop_list)->next;
2053fcf3ce44SJohn Forte old_prop_ptr = *prop_list;
2054fcf3ce44SJohn Forte *prop_list = prop_ptr;
2055fcf3ce44SJohn Forte free((uchar_t *)(old_prop_ptr->prop_data));
2056fcf3ce44SJohn Forte old_prop_ptr->prop_data = NULL;
2057fcf3ce44SJohn Forte S_FREE(old_prop_ptr);
2058fcf3ce44SJohn Forte } else {
2059fcf3ce44SJohn Forte prop_ptr->next = *prop_list;
2060fcf3ce44SJohn Forte *prop_list = prop_ptr;
2061fcf3ce44SJohn Forte }
2062fcf3ce44SJohn Forte }
2063fcf3ce44SJohn Forte
2064fcf3ce44SJohn Forte return (0);
2065fcf3ce44SJohn Forte }
2066fcf3ce44SJohn Forte
2067fcf3ce44SJohn Forte /*
2068fcf3ce44SJohn Forte * This function calls FCP_TGT_INQUIRY via g_issue_fcp_ioctl()
2069fcf3ce44SJohn Forte * to get the inq_dtype of input device and calls update_map_dev_FCP_prop().
2070fcf3ce44SJohn Forte * inq_dtype is set to NULL and pass error code if inq_dtype data is not
2071fcf3ce44SJohn Forte * requried.
2072fcf3ce44SJohn Forte *
2073fcf3ce44SJohn Forte * return error from update_map_dev_FCP_prop().
2074fcf3ce44SJohn Forte */
2075fcf3ce44SJohn Forte static int
handle_map_dev_FCP_prop(minor_t fp_xport_minor,la_wwn_t port_wwn,impl_map_dev_prop_t ** prop_list)2076063d642aSBill Gumbrell handle_map_dev_FCP_prop(minor_t fp_xport_minor, la_wwn_t port_wwn,
2077063d642aSBill Gumbrell impl_map_dev_prop_t **prop_list)
2078fcf3ce44SJohn Forte {
2079fcf3ce44SJohn Forte struct device_data inq_data;
2080*926d645fSToomas Soome int fcp_fd, err;
2081fcf3ce44SJohn Forte struct fcp_ioctl fcp_data;
2082fcf3ce44SJohn Forte uchar_t inq_dtype;
2083fcf3ce44SJohn Forte
2084fcf3ce44SJohn Forte if ((fcp_fd = g_object_open(FCP_PATH, O_RDONLY)) == -1) {
2085fcf3ce44SJohn Forte update_map_dev_FCP_prop(prop_list, NULL,
2086063d642aSBill Gumbrell L_OPEN_PATH_FAIL, PROP_NOEXIST);
2087fcf3ce44SJohn Forte }
2088fcf3ce44SJohn Forte
2089fcf3ce44SJohn Forte /* Get the minor number for an fp instance */
2090fcf3ce44SJohn Forte fcp_data.fp_minor = fp_xport_minor;
2091fcf3ce44SJohn Forte
2092fcf3ce44SJohn Forte /* Get FCP prop for the hba first. */
2093fcf3ce44SJohn Forte fcp_data.listlen = 1;
2094fcf3ce44SJohn Forte inq_data.dev_pwwn = port_wwn;
2095fcf3ce44SJohn Forte fcp_data.list = (caddr_t)&inq_data;
2096fcf3ce44SJohn Forte
2097fcf3ce44SJohn Forte if (err = g_issue_fcp_ioctl(fcp_fd, &fcp_data, 0)) {
2098fcf3ce44SJohn Forte /* if ioctl error then set the prop_error. */
2099063d642aSBill Gumbrell if ((err = update_map_dev_FCP_prop(
2100063d642aSBill Gumbrell prop_list, NULL, err, PROP_NOEXIST)) != 0) {
2101063d642aSBill Gumbrell return (err);
2102063d642aSBill Gumbrell }
2103fcf3ce44SJohn Forte } else {
2104063d642aSBill Gumbrell inq_dtype = inq_data.dev0_type;
2105063d642aSBill Gumbrell if ((err = update_map_dev_FCP_prop(
2106063d642aSBill Gumbrell prop_list, &inq_dtype, 0, PROP_NOEXIST)) != 0) {
2107063d642aSBill Gumbrell return (err);
2108063d642aSBill Gumbrell }
2109fcf3ce44SJohn Forte }
2110fcf3ce44SJohn Forte
2111fcf3ce44SJohn Forte return (0);
2112fcf3ce44SJohn Forte }
2113fcf3ce44SJohn Forte
2114fcf3ce44SJohn Forte /*
2115fcf3ce44SJohn Forte * Construct device map tree from nexus driver
2116fcf3ce44SJohn Forte *
2117fcf3ce44SJohn Forte * PARAMS:
2118fcf3ce44SJohn Forte * path - must be the physical path to a device
2119fcf3ce44SJohn Forte * l_err - ptr to an error code. Set when NULL is returned.
2120fcf3ce44SJohn Forte * flag - device map fomat and property type.
2121fcf3ce44SJohn Forte *
2122fcf3ce44SJohn Forte * LOGIC:
2123fcf3ce44SJohn Forte * 1. check the validity of path via g_get_path_type.
2124fcf3ce44SJohn Forte * 2. If FC path, get the topology of the path via
2125fcf3ce44SJohn Forte * g_get_fca_port_topology.
2126fcf3ce44SJohn Forte *
2127fcf3ce44SJohn Forte * 3. If FC type(Leadville statck)
2128fcf3ce44SJohn Forte * FCIO_GET_DEV_LIST to get the device node list of fc_port_dev_t.
2129fcf3ce44SJohn Forte * FCIO_GET_HOST_PARAMS to get the fca port node of fc_port_dev_t.
2130fcf3ce44SJohn Forte *
2131fcf3ce44SJohn Forte * root of tree is set with host_params info
2132fcf3ce44SJohn Forte * FC propery is set.
2133fcf3ce44SJohn Forte * FCP property is set if reqyested through flag.
2134fcf3ce44SJohn Forte * Issue g_issue_fcp_ioctl to get FCP inquiry data
2135fcf3ce44SJohn Forte * consruruct list of children via dev_list.
2136fcf3ce44SJohn Forte * FC property is set.
2137fcf3ce44SJohn Forte * FCP property is set if reqyested through flag.
2138fcf3ce44SJohn Forte * Issue FCIO_DEV_LOGIN if it is fabric device.
2139fcf3ce44SJohn Forte * Issue g_issue_fcp_ioctl to get FCP inquiry data.
2140fcf3ce44SJohn Forte *
2141fcf3ce44SJohn Forte * else FC4 type(socal/sf or ifp stack)
2142fcf3ce44SJohn Forte * SFIOCGMAP ioctl to get the device and hba nodes of
2143fcf3ce44SJohn Forte * sf_addr_pair_t.
2144fcf3ce44SJohn Forte * FCIO_GETMAP ioctl to get hba port info.
2145fcf3ce44SJohn Forte * consturct map and child tree list and
2146fcf3ce44SJohn Forte * set the properties as private loop devices.
2147fcf3ce44SJohn Forte *
2148fcf3ce44SJohn Forte * RETURNS:
2149fcf3ce44SJohn Forte * ptr to map is returned if OK.
2150fcf3ce44SJohn Forte * NULL and l_err is set otherwise.
2151fcf3ce44SJohn Forte */
2152fcf3ce44SJohn Forte gfc_dev_t
g_dev_map_init(char * path,int * l_err,int flag)2153fcf3ce44SJohn Forte g_dev_map_init(char *path, int *l_err, int flag)
2154fcf3ce44SJohn Forte {
2155063d642aSBill Gumbrell int fd, i, num_devices = 0, err, pathcnt = 1, new_count = 0;
2156063d642aSBill Gumbrell char drvr_path[MAXPATHLEN], drvr_path0[MAXPATHLEN];
2157063d642aSBill Gumbrell char *char_ptr, *nexus_path;
2158063d642aSBill Gumbrell struct stat stbuf;
2159063d642aSBill Gumbrell fc_port_dev_t *dev_list = NULL, *dlist;
2160063d642aSBill Gumbrell uint32_t hba_port_top, state;
2161063d642aSBill Gumbrell uint_t path_type;
2162063d642aSBill Gumbrell sf_al_map_t sf_map;
2163063d642aSBill Gumbrell fc_port_dev_t fp_hba_port;
2164063d642aSBill Gumbrell mp_pathlist_t pathlist;
2165063d642aSBill Gumbrell int p_on = 0, p_st = 0, hba_alpa_found = 0, nexus_fd;
2166063d642aSBill Gumbrell fcio_t fcio;
2167063d642aSBill Gumbrell struct lilpmap limited_map;
2168063d642aSBill Gumbrell impl_map_dev_t *impl_map, *impl_dev;
2169063d642aSBill Gumbrell impl_map_dev_t *mdl_start = NULL, *mdl_end = NULL;
2170063d642aSBill Gumbrell struct stat sbuf;
2171fcf3ce44SJohn Forte
2172fcf3ce44SJohn Forte if (l_err == NULL) {
2173fcf3ce44SJohn Forte return (NULL);
2174fcf3ce44SJohn Forte }
2175fcf3ce44SJohn Forte
2176fcf3ce44SJohn Forte if (path == NULL) {
2177fcf3ce44SJohn Forte *l_err = L_INVALID_PATH;
2178fcf3ce44SJohn Forte return (NULL);
2179fcf3ce44SJohn Forte }
2180fcf3ce44SJohn Forte
2181fcf3ce44SJohn Forte *l_err = 0;
2182fcf3ce44SJohn Forte
2183fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
2184fcf3ce44SJohn Forte /*
2185fcf3ce44SJohn Forte * Get the path to the :devctl driver
2186fcf3ce44SJohn Forte *
2187fcf3ce44SJohn Forte * This assumes the path looks something like this:
2188fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
2189fcf3ce44SJohn Forte * or
2190fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
2191fcf3ce44SJohn Forte * or
2192fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
2193fcf3ce44SJohn Forte * or
2194fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl
2195fcf3ce44SJohn Forte */
2196fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) {
2197fcf3ce44SJohn Forte (void) strcpy(drvr_path0, path);
2198fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path0, &pathlist)) {
2199fcf3ce44SJohn Forte *l_err = L_INVALID_PATH;
2200fcf3ce44SJohn Forte return (NULL);
2201fcf3ce44SJohn Forte }
2202fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
2203fcf3ce44SJohn Forte p_on = p_st = 0;
2204fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
2205fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
2206fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
2207063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
2208fcf3ce44SJohn Forte p_on = i;
2209fcf3ce44SJohn Forte break;
2210fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
2211063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
2212fcf3ce44SJohn Forte p_st = i;
2213fcf3ce44SJohn Forte }
2214fcf3ce44SJohn Forte }
2215fcf3ce44SJohn Forte }
2216fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state ==
2217fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
2218fcf3ce44SJohn Forte /* on_line path */
2219fcf3ce44SJohn Forte (void) strcpy(drvr_path,
2220063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
2221fcf3ce44SJohn Forte } else {
2222fcf3ce44SJohn Forte /* standby or path0 */
2223fcf3ce44SJohn Forte (void) strcpy(drvr_path,
2224063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
2225fcf3ce44SJohn Forte }
2226fcf3ce44SJohn Forte free(pathlist.path_info);
2227fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
2228fcf3ce44SJohn Forte } else {
2229fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
2230fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) ||
2231063d642aSBill Gumbrell strstr(drvr_path, SES_NAME) ||
2232063d642aSBill Gumbrell strstr(drvr_path, DRV_NAME_ST)) {
2233fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
2234fcf3ce44SJohn Forte *l_err = L_INVALID_PATH;
2235fcf3ce44SJohn Forte return (NULL);
2236fcf3ce44SJohn Forte }
2237fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */
2238fcf3ce44SJohn Forte /* append controller */
2239fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
2240fcf3ce44SJohn Forte } else {
2241fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) {
2242fcf3ce44SJohn Forte *l_err = L_LSTAT_ERROR;
2243fcf3ce44SJohn Forte return (NULL);
2244fcf3ce44SJohn Forte }
2245fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
2246fcf3ce44SJohn Forte /* append controller */
2247fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
2248fcf3ce44SJohn Forte }
2249fcf3ce44SJohn Forte }
2250fcf3ce44SJohn Forte }
2251fcf3ce44SJohn Forte
2252fcf3ce44SJohn Forte P_DPRINTF(" g_dev_map_init: Geting drive map from:"
2253063d642aSBill Gumbrell " %s\n", drvr_path);
2254fcf3ce44SJohn Forte
2255fcf3ce44SJohn Forte path_type = g_get_path_type(drvr_path);
2256fcf3ce44SJohn Forte if ((path_type == 0) || !(path_type & XPORT_MASK)) {
2257fcf3ce44SJohn Forte *l_err = L_INVALID_PATH_TYPE;
2258fcf3ce44SJohn Forte return (NULL);
2259fcf3ce44SJohn Forte }
2260fcf3ce44SJohn Forte
2261fcf3ce44SJohn Forte /* get fiber topology */
2262fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(drvr_path,
2263063d642aSBill Gumbrell &hba_port_top, 0)) != 0) {
2264fcf3ce44SJohn Forte *l_err = err;
2265fcf3ce44SJohn Forte return (NULL);
2266fcf3ce44SJohn Forte }
2267fcf3ce44SJohn Forte
2268fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1) {
2269fcf3ce44SJohn Forte *l_err = errno;
2270fcf3ce44SJohn Forte return (NULL);
2271fcf3ce44SJohn Forte }
2272fcf3ce44SJohn Forte
2273fcf3ce44SJohn Forte /* for FC devices. */
2274fcf3ce44SJohn Forte if (path_type & FC_FCA_MASK) {
2275fcf3ce44SJohn Forte /* get the number of device first. */
2276063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_GET_NUM_DEVS;
2277063d642aSBill Gumbrell fcio.fcio_olen = sizeof (num_devices);
2278fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
2279063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)&num_devices;
2280063d642aSBill Gumbrell if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2281063d642aSBill Gumbrell I_DPRINTF(" FCIO_GET_NUM_DEVS ioctl failed.\n");
2282063d642aSBill Gumbrell (void) close(fd);
2283063d642aSBill Gumbrell *l_err = L_FCIO_GET_NUM_DEVS_FAIL;
2284063d642aSBill Gumbrell return (NULL);
2285063d642aSBill Gumbrell }
2286063d642aSBill Gumbrell if (num_devices != 0) {
2287fcf3ce44SJohn Forte if ((dev_list = (fc_port_dev_t *)calloc(num_devices,
2288063d642aSBill Gumbrell sizeof (fc_port_dev_t))) == NULL) {
2289063d642aSBill Gumbrell (void) close(fd);
2290063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2291063d642aSBill Gumbrell return (NULL);
2292fcf3ce44SJohn Forte }
2293063d642aSBill Gumbrell
2294063d642aSBill Gumbrell bzero((caddr_t)&fcio, sizeof (fcio));
2295063d642aSBill Gumbrell /* Get the device list */
2296fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DEV_LIST;
2297fcf3ce44SJohn Forte /* Information read operation */
2298fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
2299fcf3ce44SJohn Forte fcio.fcio_olen = num_devices * sizeof (fc_port_dev_t);
2300063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)dev_list;
2301fcf3ce44SJohn Forte /* new device count */
2302fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (new_count);
2303fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)&new_count;
2304fcf3ce44SJohn Forte if ((err = g_issue_fcio_ioctl(fd, &fcio, 0)) != 0) {
2305063d642aSBill Gumbrell if (err == L_INVALID_DEVICE_COUNT) {
2306063d642aSBill Gumbrell /*
2307063d642aSBill Gumbrell * original buffer was small so allocate
2308063d642aSBill Gumbrell * buffer with a new count and retry.
2309063d642aSBill Gumbrell */
2310063d642aSBill Gumbrell free(dev_list);
2311063d642aSBill Gumbrell num_devices = new_count;
2312063d642aSBill Gumbrell new_count = 0;
2313063d642aSBill Gumbrell if ((dev_list = (fc_port_dev_t *)
2314063d642aSBill Gumbrell calloc(num_devices,
2315063d642aSBill Gumbrell sizeof (fc_port_dev_t))) == NULL) {
2316063d642aSBill Gumbrell (void) close(fd);
2317063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2318063d642aSBill Gumbrell return (NULL);
2319063d642aSBill Gumbrell }
2320063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_GET_DEV_LIST;
2321063d642aSBill Gumbrell /* Information read operation */
2322063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_READ;
2323063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)dev_list;
2324063d642aSBill Gumbrell fcio.fcio_olen = num_devices *
2325063d642aSBill Gumbrell sizeof (fc_port_dev_t);
2326063d642aSBill Gumbrell /* new device count */
2327063d642aSBill Gumbrell fcio.fcio_alen = sizeof (new_count);
2328063d642aSBill Gumbrell fcio.fcio_abuf = (caddr_t)&new_count;
2329063d642aSBill Gumbrell if ((err = g_issue_fcio_ioctl(fd, &fcio,
2330063d642aSBill Gumbrell 0)) != 0) {
2331063d642aSBill Gumbrell if (err ==
2332063d642aSBill Gumbrell L_INVALID_DEVICE_COUNT) {
2333063d642aSBill Gumbrell /*
2334063d642aSBill Gumbrell * No more retry. There
2335063d642aSBill Gumbrell * may be severe
2336063d642aSBill Gumbrell * hardware problem so
2337063d642aSBill Gumbrell * return error here.
2338063d642aSBill Gumbrell */
2339063d642aSBill Gumbrell I_DPRINTF(" Device"
2340063d642aSBill Gumbrell " count was %d"
2341063d642aSBill Gumbrell " should have been"
2342063d642aSBill Gumbrell " %d\n",
2343063d642aSBill Gumbrell num_devices,
2344063d642aSBill Gumbrell new_count);
2345063d642aSBill Gumbrell free(dev_list);
2346063d642aSBill Gumbrell (void) close(fd);
2347063d642aSBill Gumbrell
2348063d642aSBill Gumbrell *l_err = L_INVALID_DEVICE_COUNT;
2349063d642aSBill Gumbrell
2350063d642aSBill Gumbrell return (NULL);
2351063d642aSBill Gumbrell } else {
2352063d642aSBill Gumbrell
2353063d642aSBill Gumbrell /* Code refactorization is needed for C style */
2354fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_DEV_LIST ioctl failed.");
2355063d642aSBill Gumbrell
2356063d642aSBill Gumbrell free(dev_list);
2357063d642aSBill Gumbrell (void) close(fd);
2358063d642aSBill Gumbrell
2359063d642aSBill Gumbrell *l_err = L_FCIO_GET_DEV_LIST_FAIL;
2360063d642aSBill Gumbrell
2361063d642aSBill Gumbrell return (NULL);
2362063d642aSBill Gumbrell }
2363063d642aSBill Gumbrell }
2364063d642aSBill Gumbrell }
2365fcf3ce44SJohn Forte }
2366fcf3ce44SJohn Forte }
2367fcf3ce44SJohn Forte
2368fcf3ce44SJohn Forte /*
2369fcf3ce44SJohn Forte * if new count is smaller than the original number from
2370fcf3ce44SJohn Forte * FCIO_GET_NUM_DEVS, adjust new count and buffer size
2371fcf3ce44SJohn Forte * and continue.
2372fcf3ce44SJohn Forte */
2373063d642aSBill Gumbrell if (new_count < num_devices) {
2374063d642aSBill Gumbrell num_devices = new_count;
2375063d642aSBill Gumbrell if (new_count > 0) {
2376063d642aSBill Gumbrell if ((dev_list = (fc_port_dev_t *)
2377063d642aSBill Gumbrell realloc(dev_list,
2378063d642aSBill Gumbrell (new_count * sizeof (fc_port_dev_t))))
2379063d642aSBill Gumbrell == NULL) {
2380063d642aSBill Gumbrell S_FREE(dev_list);
2381063d642aSBill Gumbrell (void) close(fd);
2382063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2383063d642aSBill Gumbrell return (NULL);
2384063d642aSBill Gumbrell }
2385063d642aSBill Gumbrell }
2386fcf3ce44SJohn Forte }
2387fcf3ce44SJohn Forte
2388fcf3ce44SJohn Forte /* get the host param info */
2389063d642aSBill Gumbrell (void) memset(&fp_hba_port, 0, sizeof (struct fc_port_dev));
2390063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_GET_HOST_PARAMS;
2391063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_READ;
2392063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)&fp_hba_port;
2393063d642aSBill Gumbrell fcio.fcio_olen = sizeof (fc_port_dev_t);
2394fcf3ce44SJohn Forte
2395063d642aSBill Gumbrell if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2396063d642aSBill Gumbrell I_DPRINTF(" FCIO_GET_HOST_PARAMS ioctl failed.\n");
2397063d642aSBill Gumbrell (void) close(fd);
2398063d642aSBill Gumbrell if (num_devices == 0) {
2399063d642aSBill Gumbrell *l_err = L_NO_DEVICES_FOUND;
2400063d642aSBill Gumbrell } else {
2401063d642aSBill Gumbrell free(dev_list);
2402063d642aSBill Gumbrell *l_err = L_FCIO_GET_HOST_PARAMS_FAIL;
2403063d642aSBill Gumbrell }
2404063d642aSBill Gumbrell (void) close(fd);
2405063d642aSBill Gumbrell return (NULL);
2406fcf3ce44SJohn Forte }
2407fcf3ce44SJohn Forte
2408fcf3ce44SJohn Forte /* If we want the lilp map then we need to do a little */
2409fcf3ce44SJohn Forte /* work here. The lilp map contains the local hba in */
2410fcf3ce44SJohn Forte /* the dev_addr. Once this has been added qsort the */
2411fcf3ce44SJohn Forte /* dev_addr array so it's in physical order. */
2412063d642aSBill Gumbrell if ((flag & MAP_FORMAT_LILP) == MAP_FORMAT_LILP) {
2413063d642aSBill Gumbrell /* First we need to allocate one additional */
2414*926d645fSToomas Soome /* device to the dev_addr structure, for the */
2415063d642aSBill Gumbrell /* local hba */
2416063d642aSBill Gumbrell if (num_devices > 0) {
2417063d642aSBill Gumbrell if ((dev_list = (fc_port_dev_t *)
2418063d642aSBill Gumbrell realloc(dev_list,
2419063d642aSBill Gumbrell (++num_devices *
2420063d642aSBill Gumbrell sizeof (fc_port_dev_t)))) == NULL) {
2421063d642aSBill Gumbrell (void) close(fd);
2422063d642aSBill Gumbrell /*
2423063d642aSBill Gumbrell * In case dev_list is not null free
2424063d642aSBill Gumbrell * it.
2425063d642aSBill Gumbrell */
2426063d642aSBill Gumbrell S_FREE(dev_list);
2427063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2428063d642aSBill Gumbrell return (NULL);
2429063d642aSBill Gumbrell }
2430fcf3ce44SJohn Forte
2431063d642aSBill Gumbrell /*
2432063d642aSBill Gumbrell * Next, copy the local hba into this new
2433063d642aSBill Gumbrell * loc.
2434063d642aSBill Gumbrell */
2435063d642aSBill Gumbrell if (memcpy(dev_list+(num_devices-1),
2436063d642aSBill Gumbrell &fp_hba_port,
2437063d642aSBill Gumbrell sizeof (fc_port_dev_t)) == NULL) {
2438063d642aSBill Gumbrell (void) free(dev_list);
2439063d642aSBill Gumbrell (void) close(fd);
2440063d642aSBill Gumbrell *l_err = L_MEMCPY_FAILED;
2441063d642aSBill Gumbrell return (NULL);
2442063d642aSBill Gumbrell }
2443fcf3ce44SJohn Forte
2444063d642aSBill Gumbrell /* Now sort by physical location */
2445063d642aSBill Gumbrell qsort((void*)dev_list, num_devices,
2446063d642aSBill Gumbrell sizeof (fc_port_dev_t), lilp_map_cmp);
2447063d642aSBill Gumbrell }
2448fcf3ce44SJohn Forte }
2449fcf3ce44SJohn Forte
2450fcf3ce44SJohn Forte
2451fcf3ce44SJohn Forte /* We have dev list info and host param info. */
2452fcf3ce44SJohn Forte /* Now constructs map tree with these info. */
2453fcf3ce44SJohn Forte /* First consturct the root of the map tree */
2454fcf3ce44SJohn Forte /* with host param. */
2455063d642aSBill Gumbrell if ((impl_map = (impl_map_dev_t *)calloc(
2456063d642aSBill Gumbrell 1, sizeof (impl_map_dev_t))) == NULL) {
2457063d642aSBill Gumbrell (void) free(dev_list);
2458063d642aSBill Gumbrell (void) close(fd);
2459063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2460063d642aSBill Gumbrell return (NULL);
2461063d642aSBill Gumbrell }
2462063d642aSBill Gumbrell impl_map->flag = flag;
2463063d642aSBill Gumbrell impl_map->topo = hba_port_top;
2464fcf3ce44SJohn Forte
2465fcf3ce44SJohn Forte /* consturct hba property list. */
2466063d642aSBill Gumbrell if ((err = update_map_dev_fc_prop(&impl_map->prop_list,
2467fcf3ce44SJohn Forte hba_port_top, fp_hba_port.dev_pwwn.raw_wwn,
2468fcf3ce44SJohn Forte fp_hba_port.dev_nwwn.raw_wwn, fp_hba_port.dev_did.port_id,
2469fcf3ce44SJohn Forte fp_hba_port.dev_hard_addr.hard_addr)) != 0) {
2470063d642aSBill Gumbrell (void) free(dev_list);
2471063d642aSBill Gumbrell (void) close(fd);
2472063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2473063d642aSBill Gumbrell *l_err = err;
2474063d642aSBill Gumbrell return (NULL);
2475fcf3ce44SJohn Forte }
2476063d642aSBill Gumbrell
2477fcf3ce44SJohn Forte if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) {
2478063d642aSBill Gumbrell if (fstat(fd, &sbuf) == -1) {
2479063d642aSBill Gumbrell (void) free(dev_list);
2480063d642aSBill Gumbrell (void) close(fd);
2481063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2482063d642aSBill Gumbrell *l_err = L_FSTAT_ERROR;
2483063d642aSBill Gumbrell return (NULL);
2484063d642aSBill Gumbrell }
2485063d642aSBill Gumbrell if ((err = handle_map_dev_FCP_prop(minor(sbuf.st_rdev),
2486063d642aSBill Gumbrell fp_hba_port.dev_pwwn, &impl_map->prop_list)) != 0) {
2487fcf3ce44SJohn Forte (void) free(dev_list);
2488fcf3ce44SJohn Forte (void) close(fd);
2489fcf3ce44SJohn Forte g_dev_map_fini(impl_map);
2490fcf3ce44SJohn Forte *l_err = err;
2491fcf3ce44SJohn Forte return (NULL);
2492fcf3ce44SJohn Forte }
2493063d642aSBill Gumbrell }
2494063d642aSBill Gumbrell
2495063d642aSBill Gumbrell /* consturct child for each device and */
2496063d642aSBill Gumbrell /* set device property list. */
2497063d642aSBill Gumbrell dlist = dev_list;
2498063d642aSBill Gumbrell for (i = 0; i < num_devices; i++, dlist++) {
2499063d642aSBill Gumbrell if ((impl_dev = (impl_map_dev_t *)calloc(
2500063d642aSBill Gumbrell 1, sizeof (impl_map_dev_t))) == NULL) {
2501063d642aSBill Gumbrell (void) free(dev_list);
2502063d642aSBill Gumbrell (void) close(fd);
2503063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2504063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2505063d642aSBill Gumbrell return (NULL);
2506063d642aSBill Gumbrell }
2507063d642aSBill Gumbrell /* set the map as parent */
2508063d642aSBill Gumbrell impl_dev->parent = impl_map;
2509063d642aSBill Gumbrell if ((err = update_map_dev_fc_prop(&impl_dev->prop_list,
2510063d642aSBill Gumbrell hba_port_top, dlist->dev_pwwn.raw_wwn,
2511063d642aSBill Gumbrell dlist->dev_nwwn.raw_wwn, dlist->dev_did.port_id,
2512063d642aSBill Gumbrell dlist->dev_hard_addr.hard_addr)) != 0) {
2513fcf3ce44SJohn Forte (void) free(dev_list);
2514063d642aSBill Gumbrell (void) close(fd);
2515fcf3ce44SJohn Forte g_dev_map_fini(impl_map);
2516063d642aSBill Gumbrell *l_err = err;
2517fcf3ce44SJohn Forte return (NULL);
2518063d642aSBill Gumbrell }
2519063d642aSBill Gumbrell if (i == 0) {
2520063d642aSBill Gumbrell mdl_start = mdl_end = impl_dev;
2521063d642aSBill Gumbrell } else {
2522063d642aSBill Gumbrell mdl_end->next = impl_dev;
2523063d642aSBill Gumbrell mdl_end = impl_dev;
2524063d642aSBill Gumbrell }
2525063d642aSBill Gumbrell if ((flag & MAP_XPORT_PROP_ONLY) !=
2526063d642aSBill Gumbrell MAP_XPORT_PROP_ONLY) {
2527063d642aSBill Gumbrell if (((hba_port_top == FC_TOP_PUBLIC_LOOP) ||
2528063d642aSBill Gumbrell (hba_port_top == FC_TOP_FABRIC)) &&
2529063d642aSBill Gumbrell (memcmp(fp_hba_port.dev_pwwn.raw_wwn,
2530063d642aSBill Gumbrell dlist->dev_pwwn.raw_wwn, FC_WWN_SIZE) != 0)) {
2531063d642aSBill Gumbrell (void) memset(&fcio, 0, sizeof (fcio_t));
2532063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_GET_STATE;
2533063d642aSBill Gumbrell fcio.fcio_ilen = sizeof (dlist->dev_pwwn);
2534063d642aSBill Gumbrell fcio.fcio_ibuf = (caddr_t)&dlist->dev_pwwn;
2535063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_READ |
2536063d642aSBill Gumbrell FCIO_XFER_WRITE;
2537063d642aSBill Gumbrell fcio.fcio_olen = sizeof (uint32_t);
2538063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)&state;
2539063d642aSBill Gumbrell fcio.fcio_alen = 0;
2540063d642aSBill Gumbrell fcio.fcio_abuf = NULL;
2541063d642aSBill Gumbrell if (g_issue_fcio_ioctl(fd, &fcio, 0) != 0) {
2542063d642aSBill Gumbrell I_DPRINTF(
2543063d642aSBill Gumbrell " FCIO_GET_STATE ioctl failed.\n");
2544063d642aSBill Gumbrell if ((err = update_map_dev_FCP_prop(
2545063d642aSBill Gumbrell &impl_dev->prop_list, NULL,
2546063d642aSBill Gumbrell L_FCIO_GET_STATE_FAIL,
2547063d642aSBill Gumbrell PROP_NOEXIST)) != 0) {
2548063d642aSBill Gumbrell (void) free(dev_list);
2549063d642aSBill Gumbrell (void) close(fd);
2550063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2551063d642aSBill Gumbrell *l_err = err;
2552063d642aSBill Gumbrell return (NULL);
2553063d642aSBill Gumbrell }
2554063d642aSBill Gumbrell }
2555063d642aSBill Gumbrell if (state != PORT_DEVICE_LOGGED_IN) {
2556063d642aSBill Gumbrell (void) close(fd);
2557063d642aSBill Gumbrell if ((fd = g_object_open(drvr_path,
2558063d642aSBill Gumbrell O_NDELAY | O_RDONLY | O_EXCL)) ==
2559063d642aSBill Gumbrell -1) {
2560063d642aSBill Gumbrell (void) free(dev_list);
2561063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2562063d642aSBill Gumbrell *l_err = L_OPEN_PATH_FAIL;
2563063d642aSBill Gumbrell return (NULL);
2564063d642aSBill Gumbrell }
2565063d642aSBill Gumbrell (void) memset(&fcio, 0,
2566063d642aSBill Gumbrell sizeof (fcio_t));
2567063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_DEV_LOGIN;
2568063d642aSBill Gumbrell fcio.fcio_ilen =
2569063d642aSBill Gumbrell sizeof (dlist->dev_pwwn);
2570063d642aSBill Gumbrell fcio.fcio_ibuf =
2571063d642aSBill Gumbrell (caddr_t)&dlist->dev_pwwn;
2572063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_WRITE;
2573063d642aSBill Gumbrell fcio.fcio_olen = fcio.fcio_alen = 0;
2574063d642aSBill Gumbrell fcio.fcio_obuf = fcio.fcio_abuf = NULL;
2575063d642aSBill Gumbrell if (g_issue_fcio_ioctl(fd, &fcio, 0) !=
2576063d642aSBill Gumbrell 0) {
2577063d642aSBill Gumbrell
2578063d642aSBill Gumbrell /* Code refactorization is needed for C style */
2579fcf3ce44SJohn Forte I_DPRINTF(" FCIO_DEV_LOGIN ioctl failed.\n");
2580063d642aSBill Gumbrell
2581fcf3ce44SJohn Forte if ((err = update_map_dev_FCP_prop(
2582fcf3ce44SJohn Forte &impl_dev->prop_list, NULL,
2583fcf3ce44SJohn Forte L_FCIO_DEV_LOGIN_FAIL,
2584fcf3ce44SJohn Forte PROP_NOEXIST)) != 0) {
2585063d642aSBill Gumbrell (void) free(dev_list);
2586063d642aSBill Gumbrell (void) close(fd);
2587063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2588063d642aSBill Gumbrell *l_err = err;
2589063d642aSBill Gumbrell return (NULL);
2590063d642aSBill Gumbrell }
2591063d642aSBill Gumbrell
2592063d642aSBill Gumbrell /*
2593063d642aSBill Gumbrell * plogi failed continue
2594063d642aSBill Gumbrell * to next dev
2595063d642aSBill Gumbrell */
2596063d642aSBill Gumbrell continue;
2597063d642aSBill Gumbrell }
2598063d642aSBill Gumbrell }
2599063d642aSBill Gumbrell }
2600063d642aSBill Gumbrell /* sbuf should be set from hba_port handling. */
2601063d642aSBill Gumbrell if ((err = handle_map_dev_FCP_prop(
2602063d642aSBill Gumbrell minor(sbuf.st_rdev),
2603063d642aSBill Gumbrell dlist->dev_pwwn, &impl_dev->prop_list)) !=
2604063d642aSBill Gumbrell 0) {
2605063d642aSBill Gumbrell (void) free(dev_list);
2606063d642aSBill Gumbrell (void) close(fd);
2607063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2608063d642aSBill Gumbrell *l_err = err;
2609063d642aSBill Gumbrell return (NULL);
2610fcf3ce44SJohn Forte }
2611fcf3ce44SJohn Forte }
2612fcf3ce44SJohn Forte }
2613fcf3ce44SJohn Forte /* connect the children to to map. */
2614063d642aSBill Gumbrell impl_map->child = mdl_start;
2615063d642aSBill Gumbrell S_FREE(dev_list);
2616fcf3ce44SJohn Forte
2617fcf3ce44SJohn Forte } else { /* sf and fc4/pci devices */
2618063d642aSBill Gumbrell /* initialize map */
2619063d642aSBill Gumbrell (void) memset(&sf_map, 0, sizeof (struct sf_al_map));
2620063d642aSBill Gumbrell if (ioctl(fd, SFIOCGMAP, &sf_map) != 0) {
2621063d642aSBill Gumbrell I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
2622063d642aSBill Gumbrell (void) close(fd);
2623063d642aSBill Gumbrell *l_err = L_SFIOCGMAP_IOCTL_FAIL;
2624063d642aSBill Gumbrell return (NULL);
2625063d642aSBill Gumbrell }
2626fcf3ce44SJohn Forte /* Check for reasonableness. */
2627063d642aSBill Gumbrell if ((sf_map.sf_count > 126) || (sf_map.sf_count < 0)) {
2628063d642aSBill Gumbrell (void) close(fd);
2629063d642aSBill Gumbrell *l_err = L_INVALID_LOOP_MAP;
2630063d642aSBill Gumbrell return (NULL);
2631063d642aSBill Gumbrell }
2632fcf3ce44SJohn Forte
2633063d642aSBill Gumbrell if (sf_map.sf_count == 0) {
2634063d642aSBill Gumbrell (void) close(fd);
2635063d642aSBill Gumbrell *l_err = L_NO_DEVICES_FOUND;
2636063d642aSBill Gumbrell return (NULL);
2637063d642aSBill Gumbrell }
2638fcf3ce44SJohn Forte
2639063d642aSBill Gumbrell if ((err = g_get_nexus_path(drvr_path, &nexus_path)) != 0) {
2640063d642aSBill Gumbrell (void) close(fd);
2641063d642aSBill Gumbrell *l_err = err;
2642063d642aSBill Gumbrell return (NULL);
2643063d642aSBill Gumbrell }
2644fcf3ce44SJohn Forte
2645063d642aSBill Gumbrell if ((nexus_fd =
2646063d642aSBill Gumbrell g_object_open(nexus_path, O_NDELAY | O_RDONLY)) == -1) {
2647063d642aSBill Gumbrell (void) close(fd);
2648063d642aSBill Gumbrell S_FREE(nexus_path);
2649063d642aSBill Gumbrell *l_err = errno;
2650063d642aSBill Gumbrell return (NULL);
2651063d642aSBill Gumbrell }
2652fcf3ce44SJohn Forte
2653fcf3ce44SJohn Forte /* get limited map to get hba param info */
2654063d642aSBill Gumbrell if (ioctl(nexus_fd, FCIO_GETMAP, &limited_map) != 0) {
2655063d642aSBill Gumbrell I_DPRINTF(" FCIO_GETMAP ioctl failed\n");
2656063d642aSBill Gumbrell (void) close(fd);
2657063d642aSBill Gumbrell (void) close(nexus_fd);
2658063d642aSBill Gumbrell S_FREE(nexus_path);
2659063d642aSBill Gumbrell *l_err = L_FCIO_GETMAP_IOCTL_FAIL;
2660063d642aSBill Gumbrell return (NULL);
2661063d642aSBill Gumbrell }
2662fcf3ce44SJohn Forte (void) close(nexus_fd);
2663fcf3ce44SJohn Forte S_FREE(nexus_path);
2664fcf3ce44SJohn Forte
2665063d642aSBill Gumbrell for (i = 0; i < sf_map.sf_count; i++) {
2666063d642aSBill Gumbrell if (sf_map.sf_addr_pair[i].sf_al_pa ==
2667063d642aSBill Gumbrell limited_map.lilp_myalpa) {
2668063d642aSBill Gumbrell sf_map.sf_hba_addr = sf_map.sf_addr_pair[i];
2669063d642aSBill Gumbrell hba_alpa_found = 1;
2670063d642aSBill Gumbrell }
2671fcf3ce44SJohn Forte }
2672fcf3ce44SJohn Forte
2673063d642aSBill Gumbrell if (!(hba_alpa_found)) {
2674063d642aSBill Gumbrell (void) close(fd);
2675063d642aSBill Gumbrell *l_err = L_INVALID_LOOP_MAP;
2676063d642aSBill Gumbrell return (NULL);
2677063d642aSBill Gumbrell }
2678fcf3ce44SJohn Forte
2679fcf3ce44SJohn Forte /* We have dev list info and host param info. */
2680fcf3ce44SJohn Forte /* Now constructs map tree with these info. */
2681fcf3ce44SJohn Forte /* First consturct the root of the map tree */
2682fcf3ce44SJohn Forte /* with host param. */
2683063d642aSBill Gumbrell if ((impl_map = (impl_map_dev_t *)calloc(
2684063d642aSBill Gumbrell 1, sizeof (impl_map_dev_t))) == NULL) {
2685063d642aSBill Gumbrell (void) close(fd);
2686063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2687063d642aSBill Gumbrell return (NULL);
2688063d642aSBill Gumbrell }
2689063d642aSBill Gumbrell impl_map->flag = flag;
2690063d642aSBill Gumbrell impl_map->topo = hba_port_top;
2691fcf3ce44SJohn Forte
2692fcf3ce44SJohn Forte /* consturct hba property list. */
2693063d642aSBill Gumbrell if ((err = update_map_dev_fc_prop(&impl_map->prop_list,
2694fcf3ce44SJohn Forte hba_port_top, sf_map.sf_hba_addr.sf_port_wwn,
2695fcf3ce44SJohn Forte sf_map.sf_hba_addr.sf_node_wwn,
2696fcf3ce44SJohn Forte (int)sf_map.sf_hba_addr.sf_al_pa,
2697fcf3ce44SJohn Forte (int)sf_map.sf_hba_addr.sf_hard_address)) != 0) {
2698fcf3ce44SJohn Forte (void) close(fd);
2699fcf3ce44SJohn Forte g_dev_map_fini(impl_map);
2700fcf3ce44SJohn Forte *l_err = err;
2701fcf3ce44SJohn Forte return (NULL);
2702fcf3ce44SJohn Forte }
2703fcf3ce44SJohn Forte
2704063d642aSBill Gumbrell if ((flag & MAP_XPORT_PROP_ONLY) != MAP_XPORT_PROP_ONLY) {
2705063d642aSBill Gumbrell if ((err = update_map_dev_FCP_prop(&impl_map->prop_list,
2706063d642aSBill Gumbrell &sf_map.sf_hba_addr.sf_inq_dtype, 0,
2707063d642aSBill Gumbrell PROP_NOEXIST)) != 0) {
2708063d642aSBill Gumbrell (void) close(fd);
2709063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2710063d642aSBill Gumbrell *l_err = err;
2711063d642aSBill Gumbrell return (NULL);
2712063d642aSBill Gumbrell }
2713063d642aSBill Gumbrell }
2714063d642aSBill Gumbrell
2715063d642aSBill Gumbrell for (i = 0; i < sf_map.sf_count; i++) {
2716063d642aSBill Gumbrell if ((impl_dev = (impl_map_dev_t *)calloc(
2717063d642aSBill Gumbrell 1, sizeof (impl_map_dev_t))) == NULL) {
2718063d642aSBill Gumbrell (void) close(fd);
2719063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2720063d642aSBill Gumbrell *l_err = L_MALLOC_FAILED;
2721063d642aSBill Gumbrell return (NULL);
2722063d642aSBill Gumbrell }
2723063d642aSBill Gumbrell /* set the map as parent */
2724063d642aSBill Gumbrell impl_dev->parent = impl_map;
2725063d642aSBill Gumbrell if ((err = update_map_dev_fc_prop(&impl_dev->prop_list,
2726063d642aSBill Gumbrell hba_port_top, sf_map.sf_addr_pair[i].sf_port_wwn,
2727063d642aSBill Gumbrell sf_map.sf_addr_pair[i].sf_node_wwn,
2728063d642aSBill Gumbrell (int)(sf_map.sf_addr_pair[i].sf_al_pa),
2729063d642aSBill Gumbrell (int)(sf_map.sf_addr_pair[i].sf_hard_address))) !=
2730063d642aSBill Gumbrell 0) {
2731063d642aSBill Gumbrell (void) close(fd);
2732063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2733063d642aSBill Gumbrell *l_err = err;
2734063d642aSBill Gumbrell return (NULL);
2735063d642aSBill Gumbrell }
2736063d642aSBill Gumbrell if (i == 0) {
2737063d642aSBill Gumbrell mdl_start = mdl_end = impl_dev;
2738063d642aSBill Gumbrell } else {
2739063d642aSBill Gumbrell mdl_end->next = impl_dev;
2740063d642aSBill Gumbrell mdl_end = impl_dev;
2741063d642aSBill Gumbrell }
2742063d642aSBill Gumbrell if ((flag & MAP_XPORT_PROP_ONLY) !=
2743063d642aSBill Gumbrell MAP_XPORT_PROP_ONLY) {
2744063d642aSBill Gumbrell if ((err = update_map_dev_FCP_prop(
2745063d642aSBill Gumbrell &impl_dev->prop_list,
2746063d642aSBill Gumbrell &sf_map.sf_addr_pair[i].sf_inq_dtype, 0,
2747063d642aSBill Gumbrell PROP_NOEXIST)) != 0) {
2748063d642aSBill Gumbrell (void) close(fd);
2749063d642aSBill Gumbrell g_dev_map_fini(impl_map);
2750063d642aSBill Gumbrell *l_err = err;
2751063d642aSBill Gumbrell return (NULL);
2752063d642aSBill Gumbrell }
2753063d642aSBill Gumbrell }
2754063d642aSBill Gumbrell } /* end of for loop */
2755063d642aSBill Gumbrell
2756063d642aSBill Gumbrell impl_map->child = mdl_start;
2757fcf3ce44SJohn Forte } /* end of else */
2758fcf3ce44SJohn Forte
2759fcf3ce44SJohn Forte close(fd);
2760fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_map));
2761fcf3ce44SJohn Forte }
2762fcf3ce44SJohn Forte
2763fcf3ce44SJohn Forte /*
2764fcf3ce44SJohn Forte * This function deallocates memory for propery list.
2765fcf3ce44SJohn Forte */
2766fcf3ce44SJohn Forte static void
free_prop_list(impl_map_dev_prop_t ** prop_list)2767fcf3ce44SJohn Forte free_prop_list(impl_map_dev_prop_t **prop_list)
2768fcf3ce44SJohn Forte {
2769fcf3ce44SJohn Forte impl_map_dev_prop_t *lp, *olp;
2770fcf3ce44SJohn Forte
2771fcf3ce44SJohn Forte lp = *prop_list;
2772fcf3ce44SJohn Forte while (lp != NULL) {
2773fcf3ce44SJohn Forte switch (lp->prop_type) {
2774fcf3ce44SJohn Forte case GFC_PROP_TYPE_BYTES:
2775fcf3ce44SJohn Forte free((uchar_t *)(lp->prop_data));
2776fcf3ce44SJohn Forte break;
2777fcf3ce44SJohn Forte case GFC_PROP_TYPE_INT:
2778fcf3ce44SJohn Forte free((int *)(lp->prop_data));
2779fcf3ce44SJohn Forte break;
2780fcf3ce44SJohn Forte case GFC_PROP_TYPE_STRING:
2781fcf3ce44SJohn Forte free((char *)(lp->prop_data));
2782fcf3ce44SJohn Forte break;
2783fcf3ce44SJohn Forte default:
2784fcf3ce44SJohn Forte break;
2785fcf3ce44SJohn Forte }
2786fcf3ce44SJohn Forte lp->prop_data = NULL;
2787fcf3ce44SJohn Forte olp = lp;
2788fcf3ce44SJohn Forte lp = olp->next;
2789fcf3ce44SJohn Forte S_FREE(olp);
2790fcf3ce44SJohn Forte }
2791fcf3ce44SJohn Forte
2792fcf3ce44SJohn Forte *prop_list = NULL;
2793fcf3ce44SJohn Forte }
2794fcf3ce44SJohn Forte
2795fcf3ce44SJohn Forte /*
2796fcf3ce44SJohn Forte * This function deallocates memory for children list.
2797fcf3ce44SJohn Forte */
2798fcf3ce44SJohn Forte static void
free_child_list(impl_map_dev_t ** dev_list)2799fcf3ce44SJohn Forte free_child_list(impl_map_dev_t **dev_list)
2800fcf3ce44SJohn Forte {
2801fcf3ce44SJohn Forte impl_map_dev_t *lp, *olp;
2802fcf3ce44SJohn Forte
2803fcf3ce44SJohn Forte lp = *dev_list;
2804fcf3ce44SJohn Forte while (lp != NULL) {
2805fcf3ce44SJohn Forte free_prop_list(&lp->prop_list);
2806fcf3ce44SJohn Forte olp = lp;
2807fcf3ce44SJohn Forte lp = olp->next;
2808fcf3ce44SJohn Forte S_FREE(olp);
2809fcf3ce44SJohn Forte }
2810fcf3ce44SJohn Forte
2811fcf3ce44SJohn Forte *dev_list = NULL;
2812fcf3ce44SJohn Forte }
2813fcf3ce44SJohn Forte
2814fcf3ce44SJohn Forte /*
2815fcf3ce44SJohn Forte * This function deallocates memory for the whole map.
2816fcf3ce44SJohn Forte */
2817fcf3ce44SJohn Forte void
g_dev_map_fini(gfc_dev_t map)2818fcf3ce44SJohn Forte g_dev_map_fini(gfc_dev_t map)
2819fcf3ce44SJohn Forte {
2820fcf3ce44SJohn Forte impl_map_dev_t *impl_map;
2821fcf3ce44SJohn Forte
2822fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map;
2823fcf3ce44SJohn Forte
2824fcf3ce44SJohn Forte if (impl_map != NULL) {
2825063d642aSBill Gumbrell free_prop_list(&impl_map->prop_list);
2826063d642aSBill Gumbrell free_child_list(&impl_map->child);
2827063d642aSBill Gumbrell S_FREE(impl_map);
2828fcf3ce44SJohn Forte }
2829fcf3ce44SJohn Forte }
2830fcf3ce44SJohn Forte
2831fcf3ce44SJohn Forte /*
2832fcf3ce44SJohn Forte * This function passes back topology of the input map.
2833fcf3ce44SJohn Forte * input should be a handle form g_dev_map_init().
2834fcf3ce44SJohn Forte *
2835fcf3ce44SJohn Forte * return 0 if OK.
2836fcf3ce44SJohn Forte * return error code otherwise.
2837fcf3ce44SJohn Forte */
2838fcf3ce44SJohn Forte int
g_get_map_topology(gfc_dev_t map,uint_t * topology)2839063d642aSBill Gumbrell g_get_map_topology(gfc_dev_t map, uint_t *topology)
2840fcf3ce44SJohn Forte {
2841fcf3ce44SJohn Forte impl_map_dev_t *impl_map;
2842fcf3ce44SJohn Forte
2843fcf3ce44SJohn Forte if (map == NULL) {
2844fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
2845fcf3ce44SJohn Forte }
2846fcf3ce44SJohn Forte
2847fcf3ce44SJohn Forte if (topology == NULL) {
2848fcf3ce44SJohn Forte return (L_INVALID_ARG);
2849fcf3ce44SJohn Forte }
2850fcf3ce44SJohn Forte
2851fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map;
2852fcf3ce44SJohn Forte
2853fcf3ce44SJohn Forte *topology = impl_map->topo;
2854fcf3ce44SJohn Forte
2855fcf3ce44SJohn Forte return (0);
2856fcf3ce44SJohn Forte }
2857fcf3ce44SJohn Forte
2858fcf3ce44SJohn Forte /*
2859fcf3ce44SJohn Forte * This function returns the first device handle of the input map.
2860fcf3ce44SJohn Forte * map input should be a handle form g_dev_map_init().
2861fcf3ce44SJohn Forte *
2862fcf3ce44SJohn Forte * l_err set to 0 if OK.
2863fcf3ce44SJohn Forte * l_err set to error code otherwise.
2864fcf3ce44SJohn Forte */
2865fcf3ce44SJohn Forte gfc_dev_t
g_get_first_dev(gfc_dev_t map,int * l_err)2866063d642aSBill Gumbrell g_get_first_dev(gfc_dev_t map, int *l_err)
2867fcf3ce44SJohn Forte {
2868fcf3ce44SJohn Forte impl_map_dev_t *impl_map;
2869fcf3ce44SJohn Forte
2870fcf3ce44SJohn Forte if (l_err == NULL) {
2871fcf3ce44SJohn Forte return (NULL);
2872fcf3ce44SJohn Forte }
2873fcf3ce44SJohn Forte
2874fcf3ce44SJohn Forte *l_err = 0;
2875fcf3ce44SJohn Forte
2876fcf3ce44SJohn Forte if (map == NULL) {
2877fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR;
2878fcf3ce44SJohn Forte return (NULL);
2879fcf3ce44SJohn Forte }
2880fcf3ce44SJohn Forte
2881fcf3ce44SJohn Forte impl_map = (impl_map_dev_t *)map;
2882fcf3ce44SJohn Forte
2883fcf3ce44SJohn Forte if (impl_map->child == NULL) {
2884fcf3ce44SJohn Forte *l_err = L_NO_SUCH_DEV_FOUND;
2885fcf3ce44SJohn Forte }
2886fcf3ce44SJohn Forte
2887fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_map->child));
2888fcf3ce44SJohn Forte }
2889fcf3ce44SJohn Forte
2890fcf3ce44SJohn Forte /*
2891fcf3ce44SJohn Forte * This function returns the next device handle of the input map.
2892fcf3ce44SJohn Forte * map_dev input should be a handle for device.
2893fcf3ce44SJohn Forte *
2894fcf3ce44SJohn Forte * l_err set to 0 if OK.
2895fcf3ce44SJohn Forte * l_err set to error code otherwise.
2896fcf3ce44SJohn Forte */
2897fcf3ce44SJohn Forte gfc_dev_t
g_get_next_dev(gfc_dev_t map_dev,int * l_err)2898063d642aSBill Gumbrell g_get_next_dev(gfc_dev_t map_dev, int *l_err)
2899fcf3ce44SJohn Forte {
2900fcf3ce44SJohn Forte impl_map_dev_t *impl_dev;
2901fcf3ce44SJohn Forte
2902fcf3ce44SJohn Forte if (l_err == NULL) {
2903fcf3ce44SJohn Forte return (NULL);
2904fcf3ce44SJohn Forte }
2905fcf3ce44SJohn Forte
2906fcf3ce44SJohn Forte *l_err = 0;
2907fcf3ce44SJohn Forte
2908fcf3ce44SJohn Forte if (map_dev == NULL) {
2909fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR;
2910fcf3ce44SJohn Forte return (NULL);
2911fcf3ce44SJohn Forte }
2912fcf3ce44SJohn Forte
2913fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev;
2914fcf3ce44SJohn Forte
2915fcf3ce44SJohn Forte if (impl_dev->next == NULL) {
2916fcf3ce44SJohn Forte *l_err = L_NO_SUCH_DEV_FOUND;
2917fcf3ce44SJohn Forte }
2918fcf3ce44SJohn Forte
2919fcf3ce44SJohn Forte return ((gfc_dev_t)(impl_dev->next));
2920fcf3ce44SJohn Forte }
2921fcf3ce44SJohn Forte
2922fcf3ce44SJohn Forte /*
2923fcf3ce44SJohn Forte * This function passes back uchar_t type property and its count.
2924fcf3ce44SJohn Forte * map_dev input should be a handle for device.
2925fcf3ce44SJohn Forte *
2926fcf3ce44SJohn Forte * return 0 if OK.
2927fcf3ce44SJohn Forte * return error code otherwise.
2928fcf3ce44SJohn Forte */
2929fcf3ce44SJohn Forte int
g_dev_prop_lookup_bytes(gfc_dev_t map_dev,const char * prop_name,int * prop_data_count,uchar_t ** prop_data)2930063d642aSBill Gumbrell g_dev_prop_lookup_bytes(gfc_dev_t map_dev, const char *prop_name,
2931063d642aSBill Gumbrell int *prop_data_count, uchar_t **prop_data)
2932fcf3ce44SJohn Forte {
2933fcf3ce44SJohn Forte impl_map_dev_t *impl_dev;
2934fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
2935fcf3ce44SJohn Forte int err;
2936fcf3ce44SJohn Forte
2937fcf3ce44SJohn Forte if (map_dev == NULL) {
2938fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
2939fcf3ce44SJohn Forte }
2940fcf3ce44SJohn Forte
2941fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL) ||
2942063d642aSBill Gumbrell (prop_data_count == NULL)) {
2943fcf3ce44SJohn Forte return (L_INVALID_ARG);
2944fcf3ce44SJohn Forte }
2945fcf3ce44SJohn Forte
2946fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev;
2947fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list;
2948fcf3ce44SJohn Forte
2949fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME;
2950fcf3ce44SJohn Forte
2951fcf3ce44SJohn Forte while (impl_prop) {
2952063d642aSBill Gumbrell if (strncmp(impl_prop->prop_name, prop_name,
2953063d642aSBill Gumbrell strlen(prop_name)) == 0) {
2954063d642aSBill Gumbrell if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) {
2955063d642aSBill Gumbrell err = L_INVALID_MAP_DEV_PROP_TYPE;
2956063d642aSBill Gumbrell break;
2957063d642aSBill Gumbrell }
2958063d642aSBill Gumbrell if (impl_prop->prop_data) {
2959063d642aSBill Gumbrell *prop_data = (uchar_t *)(impl_prop->prop_data);
2960063d642aSBill Gumbrell *prop_data_count = impl_prop->prop_size;
2961063d642aSBill Gumbrell return (0);
2962063d642aSBill Gumbrell } else {
2963063d642aSBill Gumbrell err = impl_prop->prop_error;
2964063d642aSBill Gumbrell }
2965063d642aSBill Gumbrell break;
2966fcf3ce44SJohn Forte }
2967063d642aSBill Gumbrell impl_prop = impl_prop->next;
2968fcf3ce44SJohn Forte }
2969fcf3ce44SJohn Forte
2970fcf3ce44SJohn Forte return (err);
2971fcf3ce44SJohn Forte }
2972fcf3ce44SJohn Forte
2973fcf3ce44SJohn Forte /*
2974fcf3ce44SJohn Forte * This function passes back int type property.
2975fcf3ce44SJohn Forte * map_dev input should be a handle for device.
2976fcf3ce44SJohn Forte *
2977fcf3ce44SJohn Forte * return 0 if OK.
2978fcf3ce44SJohn Forte * return error code otherwise.
2979fcf3ce44SJohn Forte */
2980fcf3ce44SJohn Forte int
g_dev_prop_lookup_ints(gfc_dev_t map_dev,const char * prop_name,int ** prop_data)2981063d642aSBill Gumbrell g_dev_prop_lookup_ints(gfc_dev_t map_dev, const char *prop_name,
2982063d642aSBill Gumbrell int **prop_data)
2983fcf3ce44SJohn Forte {
2984fcf3ce44SJohn Forte impl_map_dev_t *impl_dev;
2985fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
2986fcf3ce44SJohn Forte int err;
2987fcf3ce44SJohn Forte
2988fcf3ce44SJohn Forte if (map_dev == NULL) {
2989fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
2990fcf3ce44SJohn Forte }
2991fcf3ce44SJohn Forte
2992fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL)) {
2993fcf3ce44SJohn Forte return (L_INVALID_ARG);
2994fcf3ce44SJohn Forte }
2995fcf3ce44SJohn Forte
2996fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev;
2997fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list;
2998fcf3ce44SJohn Forte
2999fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME;
3000fcf3ce44SJohn Forte
3001fcf3ce44SJohn Forte while (impl_prop) {
3002063d642aSBill Gumbrell if (strncmp(impl_prop->prop_name, prop_name,
3003063d642aSBill Gumbrell strlen(prop_name)) == 0) {
3004063d642aSBill Gumbrell if (impl_prop->prop_type != GFC_PROP_TYPE_INT) {
3005063d642aSBill Gumbrell err = L_INVALID_MAP_DEV_PROP_TYPE;
3006063d642aSBill Gumbrell break;
3007063d642aSBill Gumbrell }
3008063d642aSBill Gumbrell if (impl_prop->prop_data) {
3009063d642aSBill Gumbrell *prop_data = (int *)(impl_prop->prop_data);
3010063d642aSBill Gumbrell return (0);
3011063d642aSBill Gumbrell } else {
3012063d642aSBill Gumbrell err = impl_prop->prop_error;
3013063d642aSBill Gumbrell }
3014063d642aSBill Gumbrell break;
3015fcf3ce44SJohn Forte }
3016063d642aSBill Gumbrell impl_prop = impl_prop->next;
3017fcf3ce44SJohn Forte }
3018fcf3ce44SJohn Forte
3019fcf3ce44SJohn Forte return (err);
3020fcf3ce44SJohn Forte }
3021fcf3ce44SJohn Forte
3022fcf3ce44SJohn Forte /*
3023fcf3ce44SJohn Forte * This function passes back int type property.
3024fcf3ce44SJohn Forte * map_dev input should be a handle for device.
3025fcf3ce44SJohn Forte *
3026fcf3ce44SJohn Forte * return 0 if OK.
3027fcf3ce44SJohn Forte * return error code otherwise.
3028fcf3ce44SJohn Forte */
3029fcf3ce44SJohn Forte int
g_dev_prop_lookup_strings(gfc_dev_t map_dev,const char * prop_name,char ** prop_data)3030063d642aSBill Gumbrell g_dev_prop_lookup_strings(gfc_dev_t map_dev, const char *prop_name,
3031063d642aSBill Gumbrell char **prop_data)
3032fcf3ce44SJohn Forte {
3033fcf3ce44SJohn Forte impl_map_dev_t *impl_dev;
3034fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3035fcf3ce44SJohn Forte int err;
3036fcf3ce44SJohn Forte
3037fcf3ce44SJohn Forte if (map_dev == NULL) {
3038fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
3039fcf3ce44SJohn Forte }
3040fcf3ce44SJohn Forte
3041fcf3ce44SJohn Forte if ((prop_name == NULL) || (prop_data == NULL)) {
3042fcf3ce44SJohn Forte return (L_INVALID_ARG);
3043fcf3ce44SJohn Forte }
3044fcf3ce44SJohn Forte
3045fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev;
3046fcf3ce44SJohn Forte impl_prop = impl_dev->prop_list;
3047fcf3ce44SJohn Forte
3048fcf3ce44SJohn Forte err = L_INVALID_MAP_DEV_PROP_NAME;
3049fcf3ce44SJohn Forte
3050fcf3ce44SJohn Forte while (impl_prop) {
3051063d642aSBill Gumbrell if (strncmp(impl_prop->prop_name, prop_name,
3052063d642aSBill Gumbrell strlen(prop_name)) == 0) {
3053063d642aSBill Gumbrell if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) {
3054063d642aSBill Gumbrell err = L_INVALID_MAP_DEV_PROP_TYPE;
3055063d642aSBill Gumbrell break;
3056063d642aSBill Gumbrell }
3057063d642aSBill Gumbrell if (impl_prop->prop_data) {
3058063d642aSBill Gumbrell *prop_data = (char *)(impl_prop->prop_data);
3059063d642aSBill Gumbrell return (0);
3060063d642aSBill Gumbrell } else {
3061063d642aSBill Gumbrell err = impl_prop->prop_error;
3062063d642aSBill Gumbrell }
3063063d642aSBill Gumbrell break;
3064fcf3ce44SJohn Forte }
3065063d642aSBill Gumbrell impl_prop = impl_prop->next;
3066fcf3ce44SJohn Forte }
3067fcf3ce44SJohn Forte
3068fcf3ce44SJohn Forte return (err);
3069fcf3ce44SJohn Forte }
3070fcf3ce44SJohn Forte
3071fcf3ce44SJohn Forte /*
3072fcf3ce44SJohn Forte * This function returns the handle for the first property of the input device.
3073fcf3ce44SJohn Forte * map_dev input should be a handle form a device.
3074fcf3ce44SJohn Forte *
3075fcf3ce44SJohn Forte * l_err set to 0 if OK.
3076fcf3ce44SJohn Forte * l_err set to error code otherwise.
3077fcf3ce44SJohn Forte */
3078fcf3ce44SJohn Forte gfc_prop_t
g_get_first_dev_prop(gfc_dev_t map_dev,int * l_err)3079063d642aSBill Gumbrell g_get_first_dev_prop(gfc_dev_t map_dev, int *l_err)
3080fcf3ce44SJohn Forte {
3081fcf3ce44SJohn Forte impl_map_dev_t *impl_dev;
3082fcf3ce44SJohn Forte
3083fcf3ce44SJohn Forte if (l_err == NULL) {
3084fcf3ce44SJohn Forte return (NULL);
3085fcf3ce44SJohn Forte }
3086fcf3ce44SJohn Forte
3087fcf3ce44SJohn Forte *l_err = 0;
3088fcf3ce44SJohn Forte
3089fcf3ce44SJohn Forte if (map_dev == NULL) {
3090fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_ADDR;
3091fcf3ce44SJohn Forte return (NULL);
3092fcf3ce44SJohn Forte }
3093fcf3ce44SJohn Forte
3094fcf3ce44SJohn Forte impl_dev = (impl_map_dev_t *)map_dev;
3095fcf3ce44SJohn Forte
3096fcf3ce44SJohn Forte if (impl_dev->prop_list == NULL) {
3097fcf3ce44SJohn Forte *l_err = L_NO_SUCH_PROP_FOUND;
3098fcf3ce44SJohn Forte }
3099fcf3ce44SJohn Forte
3100fcf3ce44SJohn Forte return ((gfc_prop_t)(impl_dev->prop_list));
3101fcf3ce44SJohn Forte }
3102fcf3ce44SJohn Forte
3103fcf3ce44SJohn Forte /*
3104fcf3ce44SJohn Forte * This function returns the handle for next property handle of the input prop.
3105fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3106fcf3ce44SJohn Forte *
3107fcf3ce44SJohn Forte * l_err set to 0 if OK.
3108fcf3ce44SJohn Forte * l_err set to error code otherwise.
3109fcf3ce44SJohn Forte */
3110fcf3ce44SJohn Forte gfc_prop_t
g_get_next_dev_prop(gfc_prop_t map_prop,int * l_err)3111063d642aSBill Gumbrell g_get_next_dev_prop(gfc_prop_t map_prop, int *l_err)
3112fcf3ce44SJohn Forte {
3113fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3114fcf3ce44SJohn Forte
3115fcf3ce44SJohn Forte if (l_err == NULL) {
3116fcf3ce44SJohn Forte return (NULL);
3117fcf3ce44SJohn Forte }
3118fcf3ce44SJohn Forte
3119fcf3ce44SJohn Forte *l_err = 0;
3120fcf3ce44SJohn Forte
3121fcf3ce44SJohn Forte if (map_prop == NULL) {
3122fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP;
3123fcf3ce44SJohn Forte return (NULL);
3124fcf3ce44SJohn Forte }
3125fcf3ce44SJohn Forte
3126fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3127fcf3ce44SJohn Forte
3128fcf3ce44SJohn Forte if (impl_prop->next == NULL) {
3129fcf3ce44SJohn Forte *l_err = L_NO_SUCH_PROP_FOUND;
3130fcf3ce44SJohn Forte }
3131fcf3ce44SJohn Forte
3132fcf3ce44SJohn Forte return ((gfc_prop_t)(impl_prop->next));
3133fcf3ce44SJohn Forte }
3134fcf3ce44SJohn Forte
3135fcf3ce44SJohn Forte /*
3136fcf3ce44SJohn Forte * This function returns the name of the property of the input prop.
3137fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3138fcf3ce44SJohn Forte *
3139fcf3ce44SJohn Forte * return name string if OK.
3140fcf3ce44SJohn Forte * returns NULL and l_err set to error code otherwise.
3141fcf3ce44SJohn Forte */
3142fcf3ce44SJohn Forte char *
g_get_dev_prop_name(gfc_prop_t map_prop,int * l_err)3143063d642aSBill Gumbrell g_get_dev_prop_name(gfc_prop_t map_prop, int *l_err)
3144fcf3ce44SJohn Forte {
3145fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3146fcf3ce44SJohn Forte
3147fcf3ce44SJohn Forte if (l_err == NULL) {
3148fcf3ce44SJohn Forte return (NULL);
3149fcf3ce44SJohn Forte }
3150fcf3ce44SJohn Forte
3151fcf3ce44SJohn Forte *l_err = 0;
3152fcf3ce44SJohn Forte
3153fcf3ce44SJohn Forte if (map_prop == NULL) {
3154fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP;
3155fcf3ce44SJohn Forte return (NULL);
3156fcf3ce44SJohn Forte }
3157fcf3ce44SJohn Forte
3158fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3159fcf3ce44SJohn Forte
3160fcf3ce44SJohn Forte return (impl_prop->prop_name);
3161fcf3ce44SJohn Forte }
3162fcf3ce44SJohn Forte
3163fcf3ce44SJohn Forte /*
3164fcf3ce44SJohn Forte * This function returns the type of the property of the input prop.
3165fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3166fcf3ce44SJohn Forte *
3167fcf3ce44SJohn Forte * return type if OK.
3168fcf3ce44SJohn Forte * returns GFC_PROP_TYPE_UNKNOWN and l_err set to error code otherwise.
3169fcf3ce44SJohn Forte */
3170fcf3ce44SJohn Forte int
g_get_dev_prop_type(gfc_prop_t map_prop,int * l_err)3171063d642aSBill Gumbrell g_get_dev_prop_type(gfc_prop_t map_prop, int *l_err)
3172fcf3ce44SJohn Forte {
3173fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3174fcf3ce44SJohn Forte
3175fcf3ce44SJohn Forte if (l_err != NULL) {
3176fcf3ce44SJohn Forte *l_err = 0;
3177fcf3ce44SJohn Forte } else {
3178fcf3ce44SJohn Forte return (L_INVALID_ARG);
3179fcf3ce44SJohn Forte }
3180fcf3ce44SJohn Forte
3181fcf3ce44SJohn Forte if (map_prop == NULL) {
3182fcf3ce44SJohn Forte *l_err = L_INVALID_MAP_DEV_PROP;
3183fcf3ce44SJohn Forte return (GFC_PROP_TYPE_UNKNOWN);
3184fcf3ce44SJohn Forte }
3185fcf3ce44SJohn Forte
3186fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3187fcf3ce44SJohn Forte
3188fcf3ce44SJohn Forte return (impl_prop->prop_type);
3189fcf3ce44SJohn Forte }
3190fcf3ce44SJohn Forte
3191fcf3ce44SJohn Forte /*
3192fcf3ce44SJohn Forte * This function passes back uchar_t type property and its count.
3193fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3194fcf3ce44SJohn Forte *
3195fcf3ce44SJohn Forte * return 0 if OK.
3196fcf3ce44SJohn Forte * return error code otherwise.
3197fcf3ce44SJohn Forte */
3198fcf3ce44SJohn Forte int
g_get_dev_prop_bytes(gfc_prop_t map_prop,int * prop_data_count,uchar_t ** prop_data)3199063d642aSBill Gumbrell g_get_dev_prop_bytes(gfc_prop_t map_prop, int *prop_data_count,
3200063d642aSBill Gumbrell uchar_t **prop_data)
3201fcf3ce44SJohn Forte {
3202fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3203fcf3ce44SJohn Forte
3204fcf3ce44SJohn Forte if (map_prop == NULL) {
3205fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
3206fcf3ce44SJohn Forte }
3207fcf3ce44SJohn Forte
3208fcf3ce44SJohn Forte if ((prop_data == NULL) || (prop_data_count == NULL)) {
3209fcf3ce44SJohn Forte return (L_INVALID_ARG);
3210fcf3ce44SJohn Forte }
3211fcf3ce44SJohn Forte
3212fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3213fcf3ce44SJohn Forte
3214fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_BYTES) {
3215063d642aSBill Gumbrell return (L_INVALID_MAP_DEV_PROP_TYPE);
3216fcf3ce44SJohn Forte }
3217fcf3ce44SJohn Forte if (impl_prop->prop_data) {
3218063d642aSBill Gumbrell *prop_data = (uchar_t *)(impl_prop->prop_data);
3219063d642aSBill Gumbrell *prop_data_count = impl_prop->prop_size;
3220fcf3ce44SJohn Forte } else {
3221063d642aSBill Gumbrell return (impl_prop->prop_error);
3222fcf3ce44SJohn Forte }
3223fcf3ce44SJohn Forte
3224fcf3ce44SJohn Forte return (0);
3225fcf3ce44SJohn Forte }
3226fcf3ce44SJohn Forte
3227fcf3ce44SJohn Forte /*
3228fcf3ce44SJohn Forte * This function passes back int type property.
3229fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3230fcf3ce44SJohn Forte *
3231fcf3ce44SJohn Forte * return 0 if OK.
3232fcf3ce44SJohn Forte * return error code otherwise.
3233fcf3ce44SJohn Forte */
3234fcf3ce44SJohn Forte int
g_get_dev_prop_ints(gfc_prop_t map_prop,int ** prop_data)3235063d642aSBill Gumbrell g_get_dev_prop_ints(gfc_prop_t map_prop, int **prop_data)
3236fcf3ce44SJohn Forte {
3237fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3238fcf3ce44SJohn Forte
3239fcf3ce44SJohn Forte if (map_prop == NULL) {
3240fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
3241fcf3ce44SJohn Forte }
3242fcf3ce44SJohn Forte
3243fcf3ce44SJohn Forte if (prop_data == NULL) {
3244fcf3ce44SJohn Forte return (L_INVALID_ARG);
3245fcf3ce44SJohn Forte }
3246fcf3ce44SJohn Forte
3247fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3248fcf3ce44SJohn Forte
3249fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_INT) {
3250063d642aSBill Gumbrell return (L_INVALID_MAP_DEV_PROP_TYPE);
3251fcf3ce44SJohn Forte }
3252fcf3ce44SJohn Forte if (impl_prop->prop_data) {
3253063d642aSBill Gumbrell *prop_data = (int *)(impl_prop->prop_data);
3254fcf3ce44SJohn Forte } else {
3255063d642aSBill Gumbrell return (impl_prop->prop_error);
3256fcf3ce44SJohn Forte }
3257fcf3ce44SJohn Forte
3258fcf3ce44SJohn Forte return (0);
3259fcf3ce44SJohn Forte }
3260fcf3ce44SJohn Forte
3261fcf3ce44SJohn Forte /*
3262fcf3ce44SJohn Forte * This function passes back string type property.
3263fcf3ce44SJohn Forte * map_prop input should be a handle for property.
3264fcf3ce44SJohn Forte *
3265fcf3ce44SJohn Forte * return 0 if OK.
3266fcf3ce44SJohn Forte * return error code otherwise.
3267fcf3ce44SJohn Forte */
3268fcf3ce44SJohn Forte int
g_get_dev_prop_strings(gfc_prop_t map_prop,char ** prop_data)3269063d642aSBill Gumbrell g_get_dev_prop_strings(gfc_prop_t map_prop, char **prop_data)
3270fcf3ce44SJohn Forte {
3271fcf3ce44SJohn Forte impl_map_dev_prop_t *impl_prop;
3272fcf3ce44SJohn Forte
3273fcf3ce44SJohn Forte if (map_prop == NULL) {
3274fcf3ce44SJohn Forte return (L_INVALID_MAP_DEV_ADDR);
3275fcf3ce44SJohn Forte }
3276fcf3ce44SJohn Forte
3277fcf3ce44SJohn Forte if (prop_data == NULL) {
3278fcf3ce44SJohn Forte return (L_INVALID_ARG);
3279fcf3ce44SJohn Forte }
3280fcf3ce44SJohn Forte
3281fcf3ce44SJohn Forte impl_prop = (impl_map_dev_prop_t *)map_prop;
3282fcf3ce44SJohn Forte
3283fcf3ce44SJohn Forte if (impl_prop->prop_type != GFC_PROP_TYPE_STRING) {
3284063d642aSBill Gumbrell return (L_INVALID_MAP_DEV_PROP_TYPE);
3285fcf3ce44SJohn Forte }
3286fcf3ce44SJohn Forte if (impl_prop->prop_data) {
3287063d642aSBill Gumbrell *prop_data = (char *)(impl_prop->prop_data);
3288fcf3ce44SJohn Forte } else {
3289063d642aSBill Gumbrell return (impl_prop->prop_error);
3290fcf3ce44SJohn Forte }
3291fcf3ce44SJohn Forte
3292fcf3ce44SJohn Forte return (0);
3293fcf3ce44SJohn Forte }
3294fcf3ce44SJohn Forte
3295fcf3ce44SJohn Forte /*
3296fcf3ce44SJohn Forte * Free the linked list allocated by g_rdls()
3297fcf3ce44SJohn Forte */
3298fcf3ce44SJohn Forte static void
g_free_rls(AL_rls * rlsptr)3299fcf3ce44SJohn Forte g_free_rls(AL_rls *rlsptr)
3300fcf3ce44SJohn Forte {
3301fcf3ce44SJohn Forte AL_rls *trlsptr;
3302fcf3ce44SJohn Forte
3303fcf3ce44SJohn Forte while (rlsptr != NULL) {
3304fcf3ce44SJohn Forte trlsptr = rlsptr->next;
3305fcf3ce44SJohn Forte free(rlsptr);
3306fcf3ce44SJohn Forte rlsptr = trlsptr;
3307fcf3ce44SJohn Forte }
3308fcf3ce44SJohn Forte }
3309fcf3ce44SJohn Forte
3310fcf3ce44SJohn Forte /*
3311fcf3ce44SJohn Forte * Read the extended link error status block
3312fcf3ce44SJohn Forte * from the specified device and Host Adapter.
3313fcf3ce44SJohn Forte *
3314fcf3ce44SJohn Forte * PARAMS:
3315fcf3ce44SJohn Forte * path_phys - physical path to an FC device
3316fcf3ce44SJohn Forte * rls_ptr - pointer to read link state structure
3317fcf3ce44SJohn Forte *
3318fcf3ce44SJohn Forte * RETURNS:
3319fcf3ce44SJohn Forte * 0 : if OK
3320fcf3ce44SJohn Forte * non-zero: otherwise
3321fcf3ce44SJohn Forte */
3322fcf3ce44SJohn Forte int
g_rdls(char * path_phys,struct al_rls ** rls_ptr,int verbose)3323fcf3ce44SJohn Forte g_rdls(char *path_phys, struct al_rls **rls_ptr, int verbose)
3324fcf3ce44SJohn Forte {
3325063d642aSBill Gumbrell char nexus_path[MAXPATHLEN], *nexus_path_ptr;
3326063d642aSBill Gumbrell int fd, fp_fd, err, length, exp_map_flag = 0, *port_addr;
3327063d642aSBill Gumbrell struct lilpmap map;
3328063d642aSBill Gumbrell AL_rls *rls, *c1 = NULL, *c2 = NULL;
3329063d642aSBill Gumbrell uchar_t i, *port_wwn_byte;
3330063d642aSBill Gumbrell la_wwn_t port_wwn;
3331063d642aSBill Gumbrell sf_al_map_t exp_map;
3332063d642aSBill Gumbrell char *charPtr, fp_path[MAXPATHLEN];
3333063d642aSBill Gumbrell uint_t dev_type;
3334063d642aSBill Gumbrell struct stat stbuf;
3335063d642aSBill Gumbrell fcio_t fcio;
3336063d642aSBill Gumbrell fc_portid_t rls_req;
3337063d642aSBill Gumbrell fc_rls_acc_t rls_payload;
3338063d642aSBill Gumbrell gfc_dev_t map_root, map_dev;
3339063d642aSBill Gumbrell uint32_t hba_port_top, state;
3340063d642aSBill Gumbrell int pathcnt = 1, count;
3341063d642aSBill Gumbrell mp_pathlist_t pathlist;
3342063d642aSBill Gumbrell int p_on = 0, p_st = 0;
3343fcf3ce44SJohn Forte
3344fcf3ce44SJohn Forte /* return invalid path if path_phys is NULL */
3345fcf3ce44SJohn Forte if (path_phys == NULL) {
3346fcf3ce44SJohn Forte return (L_INVALID_PATH);
3347fcf3ce44SJohn Forte }
3348fcf3ce44SJohn Forte /* return invalid arg if rls_ptr is NULL */
3349fcf3ce44SJohn Forte if (rls_ptr == NULL) {
3350fcf3ce44SJohn Forte return (L_INVALID_ARG);
3351fcf3ce44SJohn Forte }
3352fcf3ce44SJohn Forte
3353fcf3ce44SJohn Forte *rls_ptr = rls = NULL;
3354fcf3ce44SJohn Forte
3355fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) {
3356fcf3ce44SJohn Forte (void) strcpy(fp_path, path_phys);
3357fcf3ce44SJohn Forte if (g_get_pathlist(fp_path, &pathlist)) {
3358fcf3ce44SJohn Forte return (L_INVALID_PATH);
3359fcf3ce44SJohn Forte }
3360fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
3361fcf3ce44SJohn Forte p_on = p_st = 0;
3362fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
3363fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
3364fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
3365063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
3366fcf3ce44SJohn Forte p_on = i;
3367fcf3ce44SJohn Forte break;
3368fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
3369063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
3370fcf3ce44SJohn Forte p_st = i;
3371fcf3ce44SJohn Forte }
3372fcf3ce44SJohn Forte }
3373fcf3ce44SJohn Forte }
3374fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state ==
3375fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
3376fcf3ce44SJohn Forte /* on_line path */
3377fcf3ce44SJohn Forte (void) strcpy(fp_path,
3378063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
3379fcf3ce44SJohn Forte } else {
3380fcf3ce44SJohn Forte /* standby or path0 */
3381fcf3ce44SJohn Forte (void) strcpy(fp_path,
3382063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
3383fcf3ce44SJohn Forte }
3384fcf3ce44SJohn Forte free(pathlist.path_info);
3385fcf3ce44SJohn Forte } else {
3386fcf3ce44SJohn Forte (void) strcpy(fp_path, path_phys);
3387fcf3ce44SJohn Forte }
3388fcf3ce44SJohn Forte
3389fcf3ce44SJohn Forte /* Get map of devices on this loop. */
3390fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fp_path)) == 0) {
3391fcf3ce44SJohn Forte return (L_INVALID_PATH);
3392fcf3ce44SJohn Forte }
3393fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) {
3394fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) {
3395fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR);
3396fcf3ce44SJohn Forte } else if (strstr(fp_path, DRV_NAME_SSD) ||
3397fcf3ce44SJohn Forte strstr(fp_path, DRV_NAME_ST) ||
3398063d642aSBill Gumbrell strstr(fp_path, SES_NAME)) {
3399fcf3ce44SJohn Forte if ((charPtr = strrchr(fp_path, '/')) == NULL) {
3400fcf3ce44SJohn Forte return (L_INVALID_PATH);
3401fcf3ce44SJohn Forte }
3402fcf3ce44SJohn Forte *charPtr = '\0';
3403fcf3ce44SJohn Forte /* append devctl to the path */
3404fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR);
3405fcf3ce44SJohn Forte } else {
3406fcf3ce44SJohn Forte if (stat(fp_path, &stbuf) < 0) {
3407fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
3408fcf3ce44SJohn Forte }
3409fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
3410fcf3ce44SJohn Forte /* append devctl to the path */
3411fcf3ce44SJohn Forte (void) strcat(fp_path, FC_CTLR);
3412fcf3ce44SJohn Forte }
3413fcf3ce44SJohn Forte }
3414fcf3ce44SJohn Forte
3415fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(fp_path, &err,
3416063d642aSBill Gumbrell MAP_XPORT_PROP_ONLY)) == NULL) {
3417fcf3ce44SJohn Forte return (err);
3418fcf3ce44SJohn Forte }
3419fcf3ce44SJohn Forte
3420fcf3ce44SJohn Forte } else { /* FC4_FCA_MASK type path */
3421063d642aSBill Gumbrell (void) memset(&map, 0, sizeof (struct lilpmap));
3422fcf3ce44SJohn Forte
3423063d642aSBill Gumbrell if ((err = g_get_nexus_path(path_phys,
3424fcf3ce44SJohn Forte &nexus_path_ptr)) != 0) {
3425063d642aSBill Gumbrell return (err);
3426063d642aSBill Gumbrell }
3427063d642aSBill Gumbrell (void) strcpy(nexus_path, nexus_path_ptr);
3428063d642aSBill Gumbrell g_destroy_data(nexus_path_ptr);
3429fcf3ce44SJohn Forte
3430fcf3ce44SJohn Forte /* open driver */
3431063d642aSBill Gumbrell if ((fd = g_object_open(nexus_path,
3432063d642aSBill Gumbrell O_NDELAY | O_RDONLY)) == -1)
3433063d642aSBill Gumbrell return (errno);
3434fcf3ce44SJohn Forte
3435fcf3ce44SJohn Forte /*
3436fcf3ce44SJohn Forte * First try using the socal version of the map.
3437fcf3ce44SJohn Forte * If that fails get the expanded vesion.
3438fcf3ce44SJohn Forte */
3439063d642aSBill Gumbrell if (ioctl(fd, FCIO_GETMAP, &map) != 0) {
3440063d642aSBill Gumbrell I_DPRINTF(" FCIO_GETMAP ioctl failed.\n");
3441063d642aSBill Gumbrell if (ioctl(fd, SFIOCGMAP, &exp_map) != 0) {
3442063d642aSBill Gumbrell I_DPRINTF(" SFIOCGMAP ioctl failed.\n");
3443063d642aSBill Gumbrell (void) close(fd);
3444063d642aSBill Gumbrell return (L_SFIOCGMAP_IOCTL_FAIL);
3445063d642aSBill Gumbrell }
3446063d642aSBill Gumbrell /* Check for reasonableness. */
3447063d642aSBill Gumbrell if ((exp_map.sf_count > 126) ||
3448063d642aSBill Gumbrell (exp_map.sf_count < 0)) {
3449fcf3ce44SJohn Forte (void) close(fd);
3450fcf3ce44SJohn Forte return (L_INVALID_LOOP_MAP);
3451fcf3ce44SJohn Forte }
3452063d642aSBill Gumbrell for (i = 0; i < exp_map.sf_count; i++) {
3453063d642aSBill Gumbrell if (exp_map.sf_addr_pair[i].sf_al_pa > 0xef) {
3454063d642aSBill Gumbrell (void) close(fd);
3455063d642aSBill Gumbrell return (L_INVALID_LOOP_MAP);
3456063d642aSBill Gumbrell }
3457063d642aSBill Gumbrell }
3458063d642aSBill Gumbrell length = exp_map.sf_count;
3459063d642aSBill Gumbrell exp_map_flag++;
3460fcf3ce44SJohn Forte } else {
3461063d642aSBill Gumbrell I_DPRINTF(" g_rdls:"
3462063d642aSBill Gumbrell " FCIO_GETMAP ioctl returned %d entries.\n",
3463063d642aSBill Gumbrell map.lilp_length);
3464063d642aSBill Gumbrell /* Check for reasonableness. */
3465063d642aSBill Gumbrell if (map.lilp_length > sizeof (map.lilp_list)) {
3466063d642aSBill Gumbrell (void) close(fd);
3467063d642aSBill Gumbrell return (L_FCIOGETMAP_INVLD_LEN);
3468063d642aSBill Gumbrell }
3469063d642aSBill Gumbrell length = map.lilp_length;
3470fcf3ce44SJohn Forte }
3471063d642aSBill Gumbrell for (i = 0; i < length; i++) {
3472063d642aSBill Gumbrell if ((c2 = (struct al_rls *)
3473063d642aSBill Gumbrell g_zalloc(sizeof (struct al_rls))) == NULL) {
3474063d642aSBill Gumbrell close(fd);
3475063d642aSBill Gumbrell return (L_MALLOC_FAILED);
3476063d642aSBill Gumbrell }
3477063d642aSBill Gumbrell if (rls == NULL) {
3478063d642aSBill Gumbrell c1 = rls = c2;
3479fcf3ce44SJohn Forte } else {
3480063d642aSBill Gumbrell for (c1 = rls; c1->next; c1 = c1->next) {};
3481063d642aSBill Gumbrell c1 = c1->next = c2;
3482063d642aSBill Gumbrell }
3483063d642aSBill Gumbrell (void) strcpy(c1->driver_path, nexus_path);
3484063d642aSBill Gumbrell if (exp_map_flag) {
3485063d642aSBill Gumbrell c1->payload.rls_portno = c1->al_ha =
3486063d642aSBill Gumbrell exp_map.sf_addr_pair[i].sf_al_pa;
3487063d642aSBill Gumbrell } else {
3488063d642aSBill Gumbrell c1->payload.rls_portno = c1->al_ha =
3489063d642aSBill Gumbrell map.lilp_list[i];
3490063d642aSBill Gumbrell }
3491063d642aSBill Gumbrell c1->payload.rls_linkfail =
3492063d642aSBill Gumbrell (uint_t)0xff000000; /* get LESB for this port */
3493063d642aSBill Gumbrell I_DPRINTF(" g_rdls:"
3494063d642aSBill Gumbrell " al_pa 0x%x\n", c1->payload.rls_portno);
3495063d642aSBill Gumbrell
3496063d642aSBill Gumbrell if (ioctl(fd, FCIO_LINKSTATUS, &c1->payload) != 0) {
3497063d642aSBill Gumbrell /*
3498063d642aSBill Gumbrell * The ifp driver will return ENXIO when rls
3499063d642aSBill Gumbrell * is issued for same initiator on loop when
3500063d642aSBill Gumbrell * there is more than one on the loop.
3501063d642aSBill Gumbrell * Rather than completely fail, continue on.
3502063d642aSBill Gumbrell * Set values in the payload struct to -1 as
3503063d642aSBill Gumbrell * this is what socal is currently doing for
3504063d642aSBill Gumbrell * the case of same initiator rls.
3505063d642aSBill Gumbrell */
3506063d642aSBill Gumbrell if ((dev_type & FC4_PCI_FCA) &&
3507063d642aSBill Gumbrell (errno == ENXIO)) {
3508063d642aSBill Gumbrell c1->payload.rls_linkfail =
3509063d642aSBill Gumbrell c1->payload.rls_syncfail =
3510063d642aSBill Gumbrell c1->payload.rls_sigfail =
3511063d642aSBill Gumbrell c1->payload.rls_primitiverr =
3512063d642aSBill Gumbrell c1->payload.rls_invalidword =
3513063d642aSBill Gumbrell c1->payload.rls_invalidcrc =
3514063d642aSBill Gumbrell (uint_t)0xffffffff;
3515063d642aSBill Gumbrell } else {
3516063d642aSBill Gumbrell I_DPRINTF(" FCIO_LINKSTATUS ioctl"
3517063d642aSBill Gumbrell " failed with errno %d.\n", errno);
3518063d642aSBill Gumbrell g_free_rls(rls);
3519063d642aSBill Gumbrell (void) close(fd);
3520063d642aSBill Gumbrell return (L_FCIO_LINKSTATUS_FAILED);
3521063d642aSBill Gumbrell }
3522fcf3ce44SJohn Forte }
3523063d642aSBill Gumbrell I_DPRINTF(" g_rdls: al_pa returned by ioctl 0x%x\n",
3524063d642aSBill Gumbrell c1->payload.rls_portno);
3525fcf3ce44SJohn Forte }
3526063d642aSBill Gumbrell *rls_ptr = rls; /* Pass back pointer */
3527fcf3ce44SJohn Forte
3528063d642aSBill Gumbrell (void) close(fd);
3529063d642aSBill Gumbrell return (0);
3530fcf3ce44SJohn Forte }
3531fcf3ce44SJohn Forte
3532fcf3ce44SJohn Forte /* Now we need to take care of FC_FCA_MASK case. */
3533fcf3ce44SJohn Forte /* we have map created already via g_dev_map_init. */
3534fcf3ce44SJohn Forte if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) {
3535fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3536fcf3ce44SJohn Forte return (err);
3537fcf3ce44SJohn Forte }
3538fcf3ce44SJohn Forte
3539fcf3ce44SJohn Forte if ((map_dev = g_get_first_dev(map_root, &err)) == NULL) {
3540fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3541fcf3ce44SJohn Forte if (err != L_NO_SUCH_DEV_FOUND) {
3542fcf3ce44SJohn Forte return (err);
3543fcf3ce44SJohn Forte } else {
3544fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
3545fcf3ce44SJohn Forte }
3546fcf3ce44SJohn Forte }
3547fcf3ce44SJohn Forte
3548fcf3ce44SJohn Forte while (map_dev) {
3549063d642aSBill Gumbrell if ((err = g_dev_prop_lookup_ints(
3550063d642aSBill Gumbrell map_dev, PORT_ADDR_PROP, &port_addr)) != 0) {
3551063d642aSBill Gumbrell g_dev_map_fini(map_root);
3552063d642aSBill Gumbrell g_free_rls(rls);
3553063d642aSBill Gumbrell return (err);
3554063d642aSBill Gumbrell }
3555fcf3ce44SJohn Forte
3556063d642aSBill Gumbrell if ((c2 = (struct al_rls *)
3557063d642aSBill Gumbrell g_zalloc(sizeof (struct al_rls))) == NULL) {
3558063d642aSBill Gumbrell g_dev_map_fini(map_root);
3559063d642aSBill Gumbrell g_free_rls(rls);
3560063d642aSBill Gumbrell close(fd);
3561063d642aSBill Gumbrell return (L_MALLOC_FAILED);
3562063d642aSBill Gumbrell }
3563063d642aSBill Gumbrell if (rls == NULL) {
3564063d642aSBill Gumbrell c1 = rls = c2;
3565063d642aSBill Gumbrell } else {
3566063d642aSBill Gumbrell for (c1 = rls; c1->next; c1 = c1->next) {};
3567063d642aSBill Gumbrell c1 = c1->next = c2;
3568063d642aSBill Gumbrell }
3569063d642aSBill Gumbrell /* Set the al_ha here */
3570063d642aSBill Gumbrell c1->al_ha = rls_req.port_id = *port_addr;
3571fcf3ce44SJohn Forte
3572fcf3ce44SJohn Forte /*
3573fcf3ce44SJohn Forte * fp uses different input/output structures for
3574fcf3ce44SJohn Forte * rls. Load the values returned for the fp ioctl
3575fcf3ce44SJohn Forte * into the structure passed back to the caller
3576fcf3ce44SJohn Forte * Note: There is no reason for the path
3577fcf3ce44SJohn Forte * to be loaded into AL_rls as is done for socal/ifp
3578fcf3ce44SJohn Forte * above.
3579fcf3ce44SJohn Forte */
3580063d642aSBill Gumbrell if ((hba_port_top == FC_TOP_FABRIC) ||
3581063d642aSBill Gumbrell (hba_port_top == FC_TOP_PUBLIC_LOOP)) {
3582063d642aSBill Gumbrell if ((err = g_dev_prop_lookup_bytes(
3583063d642aSBill Gumbrell map_dev, PORT_WWN_PROP, &count,
3584063d642aSBill Gumbrell &port_wwn_byte)) != 0) {
3585063d642aSBill Gumbrell g_dev_map_fini(map_root);
3586063d642aSBill Gumbrell g_free_rls(rls);
3587063d642aSBill Gumbrell return (err);
3588063d642aSBill Gumbrell }
3589063d642aSBill Gumbrell memcpy(port_wwn.raw_wwn, port_wwn_byte, FC_WWN_SIZE);
3590063d642aSBill Gumbrell if ((err = g_get_dev_port_state(
3591063d642aSBill Gumbrell fp_path, port_wwn, &state)) == 0) {
3592063d642aSBill Gumbrell if (state != PORT_DEVICE_LOGGED_IN) {
3593063d642aSBill Gumbrell if ((err = g_dev_login(fp_path,
3594063d642aSBill Gumbrell port_wwn)) != 0) {
3595063d642aSBill Gumbrell
3596063d642aSBill Gumbrell c1->payload.rls_linkfail =
3597063d642aSBill Gumbrell c1->payload.rls_syncfail =
3598063d642aSBill Gumbrell c1->payload.rls_sigfail =
3599063d642aSBill Gumbrell c1->payload.rls_primitiverr =
3600063d642aSBill Gumbrell c1->payload.rls_invalidword =
3601063d642aSBill Gumbrell c1->payload.rls_invalidcrc =
3602063d642aSBill Gumbrell (uint_t)0xffffffff;
3603063d642aSBill Gumbrell if (((map_dev =
3604063d642aSBill Gumbrell g_get_next_dev(map_dev,
3605063d642aSBill Gumbrell &err))
3606063d642aSBill Gumbrell == NULL) &&
3607063d642aSBill Gumbrell (err !=
3608063d642aSBill Gumbrell L_NO_SUCH_DEV_FOUND)) {
3609063d642aSBill Gumbrell g_dev_map_fini(
3610063d642aSBill Gumbrell map_root);
3611063d642aSBill Gumbrell g_free_rls(rls);
3612063d642aSBill Gumbrell return (err);
3613063d642aSBill Gumbrell }
3614063d642aSBill Gumbrell continue;
3615063d642aSBill Gumbrell }
3616063d642aSBill Gumbrell }
3617063d642aSBill Gumbrell } /* if g_get_dev_port_state fails proceed. */
3618063d642aSBill Gumbrell }
3619063d642aSBill Gumbrell
3620063d642aSBill Gumbrell fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
3621063d642aSBill Gumbrell if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) {
3622fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3623fcf3ce44SJohn Forte g_free_rls(rls);
3624063d642aSBill Gumbrell return (L_OPEN_PATH_FAIL);
3625063d642aSBill Gumbrell }
3626063d642aSBill Gumbrell fcio.fcio_cmd = FCIO_LINK_STATUS;
3627063d642aSBill Gumbrell fcio.fcio_ibuf = (caddr_t)&rls_req;
3628063d642aSBill Gumbrell fcio.fcio_ilen = sizeof (rls_req);
3629063d642aSBill Gumbrell fcio.fcio_xfer = FCIO_XFER_RW;
3630063d642aSBill Gumbrell fcio.fcio_flags = 0;
3631063d642aSBill Gumbrell fcio.fcio_obuf = (caddr_t)&rls_payload;
3632063d642aSBill Gumbrell fcio.fcio_olen = sizeof (rls_payload);
3633063d642aSBill Gumbrell if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) {
3634063d642aSBill Gumbrell c1->payload.rls_linkfail =
3635063d642aSBill Gumbrell c1->payload.rls_syncfail =
3636063d642aSBill Gumbrell c1->payload.rls_sigfail =
3637063d642aSBill Gumbrell c1->payload.rls_primitiverr =
3638063d642aSBill Gumbrell c1->payload.rls_invalidword =
3639063d642aSBill Gumbrell c1->payload.rls_invalidcrc = (uint_t)0xffffffff;
3640063d642aSBill Gumbrell } else {
3641063d642aSBill Gumbrell /*
3642063d642aSBill Gumbrell * Load the values into the struct passed
3643063d642aSBill Gumbrell * back to the caller
3644063d642aSBill Gumbrell */
3645063d642aSBill Gumbrell c1->payload.rls_linkfail = rls_payload.rls_link_fail;
3646063d642aSBill Gumbrell c1->payload.rls_syncfail = rls_payload.rls_sync_loss;
3647063d642aSBill Gumbrell c1->payload.rls_sigfail = rls_payload.rls_sig_loss;
3648063d642aSBill Gumbrell c1->payload.rls_primitiverr =
3649063d642aSBill Gumbrell rls_payload.rls_prim_seq_err;
3650063d642aSBill Gumbrell c1->payload.rls_invalidword =
3651063d642aSBill Gumbrell rls_payload.rls_invalid_word;
3652063d642aSBill Gumbrell c1->payload.rls_invalidcrc =
3653063d642aSBill Gumbrell rls_payload.rls_invalid_crc;
3654fcf3ce44SJohn Forte }
3655063d642aSBill Gumbrell (void) close(fp_fd);
3656fcf3ce44SJohn Forte
3657063d642aSBill Gumbrell if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) &&
3658063d642aSBill Gumbrell (err != L_NO_SUCH_DEV_FOUND)) {
3659063d642aSBill Gumbrell g_dev_map_fini(map_root);
3660063d642aSBill Gumbrell g_free_rls(rls);
3661063d642aSBill Gumbrell return (err);
3662063d642aSBill Gumbrell }
3663fcf3ce44SJohn Forte }
3664fcf3ce44SJohn Forte
3665fcf3ce44SJohn Forte /* for Leadville issue a final call for the initiator */
3666fcf3ce44SJohn Forte
3667fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_ints(
3668063d642aSBill Gumbrell map_root, PORT_ADDR_PROP, &port_addr)) != 0) {
3669fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3670fcf3ce44SJohn Forte g_free_rls(rls);
3671fcf3ce44SJohn Forte return (err);
3672fcf3ce44SJohn Forte }
3673fcf3ce44SJohn Forte
3674fcf3ce44SJohn Forte if ((c2 = (struct al_rls *)
3675fcf3ce44SJohn Forte g_zalloc(sizeof (struct al_rls))) == NULL) {
3676fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3677fcf3ce44SJohn Forte g_free_rls(rls);
3678fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
3679fcf3ce44SJohn Forte }
3680fcf3ce44SJohn Forte if (rls == NULL) {
3681fcf3ce44SJohn Forte c1 = rls = c2;
3682fcf3ce44SJohn Forte } else {
3683fcf3ce44SJohn Forte for (c1 = rls; c1->next; c1 = c1->next) {};
3684fcf3ce44SJohn Forte c1 = c1->next = c2;
3685fcf3ce44SJohn Forte }
3686fcf3ce44SJohn Forte
3687fcf3ce44SJohn Forte c1->al_ha = rls_req.port_id = *port_addr;
3688fcf3ce44SJohn Forte
3689fcf3ce44SJohn Forte if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) {
3690fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3691fcf3ce44SJohn Forte g_free_rls(rls);
3692fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
3693fcf3ce44SJohn Forte }
3694fcf3ce44SJohn Forte
3695fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_LINK_STATUS;
3696fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&rls_req;
3697fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (rls_req);
3698fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_RW;
3699fcf3ce44SJohn Forte fcio.fcio_flags = 0;
3700fcf3ce44SJohn Forte fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
3701fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&rls_payload;
3702fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (rls_payload);
3703fcf3ce44SJohn Forte
3704fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) {
3705fcf3ce44SJohn Forte c1->payload.rls_linkfail =
3706063d642aSBill Gumbrell c1->payload.rls_syncfail =
3707063d642aSBill Gumbrell c1->payload.rls_sigfail =
3708063d642aSBill Gumbrell c1->payload.rls_primitiverr =
3709063d642aSBill Gumbrell c1->payload.rls_invalidword =
3710063d642aSBill Gumbrell c1->payload.rls_invalidcrc = (uint_t)0xffffffff;
3711fcf3ce44SJohn Forte } else {
3712fcf3ce44SJohn Forte /*
3713fcf3ce44SJohn Forte * Load the values into the struct passed
3714fcf3ce44SJohn Forte * back to the caller
3715fcf3ce44SJohn Forte */
3716fcf3ce44SJohn Forte c1->payload.rls_linkfail = rls_payload.rls_link_fail;
3717fcf3ce44SJohn Forte c1->payload.rls_syncfail = rls_payload.rls_sync_loss;
3718fcf3ce44SJohn Forte c1->payload.rls_sigfail = rls_payload.rls_sig_loss;
3719fcf3ce44SJohn Forte c1->payload.rls_primitiverr = rls_payload.rls_prim_seq_err;
3720fcf3ce44SJohn Forte c1->payload.rls_invalidword = rls_payload.rls_invalid_word;
3721fcf3ce44SJohn Forte c1->payload.rls_invalidcrc = rls_payload.rls_invalid_crc;
3722fcf3ce44SJohn Forte (void) close(fp_fd);
3723fcf3ce44SJohn Forte }
3724fcf3ce44SJohn Forte (void) close(fp_fd);
3725fcf3ce44SJohn Forte
3726fcf3ce44SJohn Forte *rls_ptr = rls; /* Pass back pointer */
3727fcf3ce44SJohn Forte
3728fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3729fcf3ce44SJohn Forte return (0);
3730fcf3ce44SJohn Forte }
3731fcf3ce44SJohn Forte
wwnConversion(uchar_t * wwn)3732fcf3ce44SJohn Forte static u_longlong_t wwnConversion(uchar_t *wwn)
3733fcf3ce44SJohn Forte {
3734fcf3ce44SJohn Forte u_longlong_t tmp;
3735fcf3ce44SJohn Forte memcpy(&tmp, wwn, sizeof (u_longlong_t));
3736fcf3ce44SJohn Forte return (tmp);
3737fcf3ce44SJohn Forte }
3738fcf3ce44SJohn Forte
3739fcf3ce44SJohn Forte /*
3740fcf3ce44SJohn Forte * Get device World Wide Name (port and node) for device at path
3741fcf3ce44SJohn Forte * and add all WWNs to the wwn_list_found list.
3742fcf3ce44SJohn Forte *
3743fcf3ce44SJohn Forte * RETURN: 0 O.K.
3744fcf3ce44SJohn Forte *
3745fcf3ce44SJohn Forte * INPUTS:
3746fcf3ce44SJohn Forte * - path_phys must be of a device, either an IB or disk.
3747fcf3ce44SJohn Forte */
3748fcf3ce44SJohn Forte 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)3749fcf3ce44SJohn Forte get_wwns(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[], int *al_pa,
3750063d642aSBill Gumbrell struct wwn_list_found_struct **wwn_list_found)
3751fcf3ce44SJohn Forte {
3752063d642aSBill Gumbrell uint32_t hba_port_top;
3753063d642aSBill Gumbrell int i, err, count;
3754063d642aSBill Gumbrell char *char_ptr, *ptr;
3755063d642aSBill Gumbrell int found = 0, pathcnt, *port_addr;
3756*926d645fSToomas Soome unsigned long long pwwn;
3757063d642aSBill Gumbrell uchar_t *port_wwn_byte, *node_wwn_byte;
3758063d642aSBill Gumbrell char drvr_path[MAXPATHLEN];
3759063d642aSBill Gumbrell int p_on = 0, p_st = 0;
3760063d642aSBill Gumbrell mp_pathlist_t pathlist;
3761063d642aSBill Gumbrell char pwwn1[WWN_S_LEN];
3762063d642aSBill Gumbrell gfc_dev_t map_root, map_dev;
3763063d642aSBill Gumbrell hrtime_t start_time, end_time;
3764063d642aSBill Gumbrell char *env = NULL;
3765fcf3ce44SJohn Forte
3766fcf3ce44SJohn Forte P_DPRINTF(" g_get_wwn: Getting device WWN"
3767063d642aSBill Gumbrell " and al_pa for device: %s\n",
3768063d642aSBill Gumbrell path_phys);
3769fcf3ce44SJohn Forte
3770fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
3771fcf3ce44SJohn Forte start_time = gethrtime();
3772fcf3ce44SJohn Forte }
3773fcf3ce44SJohn Forte
3774fcf3ce44SJohn Forte /*
3775fcf3ce44SJohn Forte * Get the loop identifier (switch setting) from the path.
3776fcf3ce44SJohn Forte *
3777fcf3ce44SJohn Forte * This assumes the path looks something like this:
3778fcf3ce44SJohn Forte * /devices/.../SUNW,socal@3,0/SUNW,sf@0,0/SUNW,ssd@x,0
3779fcf3ce44SJohn Forte * or
3780fcf3ce44SJohn Forte * /devices/.../SUNW,qlc@5/SUNW,fp@0,0/SUNW,ssd@x,0
3781fcf3ce44SJohn Forte */
3782fcf3ce44SJohn Forte if ((char_ptr = strrchr(path_phys, '@')) == NULL) {
3783fcf3ce44SJohn Forte return (L_INVLD_PATH_NO_ATSIGN_FND);
3784fcf3ce44SJohn Forte }
3785fcf3ce44SJohn Forte char_ptr++; /* point to the loop identifier or WWN */
3786fcf3ce44SJohn Forte
3787fcf3ce44SJohn Forte (void) strcpy(drvr_path, path_phys);
3788fcf3ce44SJohn Forte /* This function allocs mem for map.dev_addr on success */
3789fcf3ce44SJohn Forte if (strstr(drvr_path, SCSI_VHCI)) {
3790fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) {
3791fcf3ce44SJohn Forte return (L_INVALID_PATH);
3792fcf3ce44SJohn Forte }
3793fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
3794fcf3ce44SJohn Forte p_on = p_st = 0;
3795fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
3796fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
3797fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
3798063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
3799fcf3ce44SJohn Forte p_on = i;
3800fcf3ce44SJohn Forte break;
3801fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
3802063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
3803fcf3ce44SJohn Forte p_st = i;
3804fcf3ce44SJohn Forte }
3805fcf3ce44SJohn Forte }
3806fcf3ce44SJohn Forte }
3807fcf3ce44SJohn Forte if (p_on == i) {
3808fcf3ce44SJohn Forte /* on_line path */
3809fcf3ce44SJohn Forte (void) strcpy(drvr_path,
3810063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
3811fcf3ce44SJohn Forte (void) strncpy(pwwn1,
3812063d642aSBill Gumbrell pathlist.path_info[p_on].path_addr,
3813063d642aSBill Gumbrell WWN_S_LEN - 1);
3814fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0';
3815fcf3ce44SJohn Forte } else {
3816fcf3ce44SJohn Forte /* standby or path0 */
3817fcf3ce44SJohn Forte (void) strcpy(drvr_path,
3818063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
3819fcf3ce44SJohn Forte (void) strncpy(pwwn1,
3820063d642aSBill Gumbrell pathlist.path_info[p_st].path_addr,
3821063d642aSBill Gumbrell WWN_S_LEN - 1);
3822fcf3ce44SJohn Forte pwwn1[WWN_S_LEN - 1] = '\0';
3823fcf3ce44SJohn Forte }
3824fcf3ce44SJohn Forte free(pathlist.path_info);
3825fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
3826fcf3ce44SJohn Forte }
3827fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(drvr_path, &err,
3828063d642aSBill Gumbrell MAP_XPORT_PROP_ONLY)) == NULL) {
3829fcf3ce44SJohn Forte return (err);
3830fcf3ce44SJohn Forte }
3831fcf3ce44SJohn Forte
3832fcf3ce44SJohn Forte if ((err = g_get_map_topology(map_root, &hba_port_top)) != 0) {
3833fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3834fcf3ce44SJohn Forte return (err);
3835fcf3ce44SJohn Forte }
3836fcf3ce44SJohn Forte
3837fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI)) {
3838fcf3ce44SJohn Forte char_ptr = pwwn1;
3839fcf3ce44SJohn Forte } else {
3840fcf3ce44SJohn Forte /*
3841fcf3ce44SJohn Forte * Format of WWN is
3842fcf3ce44SJohn Forte * ssd@w2200002037000f96,0:a,raw
3843fcf3ce44SJohn Forte */
3844fcf3ce44SJohn Forte if (*char_ptr != 'w') {
3845fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3846fcf3ce44SJohn Forte return (L_INVLD_WWN_FORMAT);
3847fcf3ce44SJohn Forte }
3848fcf3ce44SJohn Forte char_ptr++;
3849fcf3ce44SJohn Forte }
3850fcf3ce44SJohn Forte pwwn = strtoull(char_ptr, &ptr, 16);
3851fcf3ce44SJohn Forte if (ptr == char_ptr) {
3852fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3853fcf3ce44SJohn Forte return (L_NO_WWN_FOUND_IN_PATH);
3854fcf3ce44SJohn Forte }
3855fcf3ce44SJohn Forte P_DPRINTF(" g_get_wwn: Looking for WWN "
3856fcf3ce44SJohn Forte "0x%llx\n", pwwn);
3857fcf3ce44SJohn Forte
3858fcf3ce44SJohn Forte if (((map_dev = g_get_first_dev(map_root, &err)) == NULL) &&
3859fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) {
3860fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3861fcf3ce44SJohn Forte return (err);
3862fcf3ce44SJohn Forte }
3863fcf3ce44SJohn Forte
3864fcf3ce44SJohn Forte while (map_dev) {
3865fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_bytes(map_dev,
3866063d642aSBill Gumbrell PORT_WWN_PROP, &count, &port_wwn_byte)) != 0) {
3867fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3868fcf3ce44SJohn Forte return (err);
3869fcf3ce44SJohn Forte }
3870fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_bytes(map_dev,
3871063d642aSBill Gumbrell NODE_WWN_PROP, &count, &node_wwn_byte)) != 0) {
3872fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3873fcf3ce44SJohn Forte return (err);
3874fcf3ce44SJohn Forte }
3875fcf3ce44SJohn Forte
3876fcf3ce44SJohn Forte if (pwwn == wwnConversion(port_wwn_byte) && found != 1) {
3877fcf3ce44SJohn Forte found = 1;
3878fcf3ce44SJohn Forte memcpy(port_wwn, port_wwn_byte, FC_WWN_SIZE);
3879fcf3ce44SJohn Forte memcpy(node_wwn, node_wwn_byte, FC_WWN_SIZE);
3880fcf3ce44SJohn Forte if ((err = g_dev_prop_lookup_ints(
3881063d642aSBill Gumbrell map_dev, PORT_ADDR_PROP, &port_addr)) != 0) {
3882fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3883fcf3ce44SJohn Forte return (err);
3884fcf3ce44SJohn Forte }
3885fcf3ce44SJohn Forte *al_pa = *port_addr;
3886fcf3ce44SJohn Forte }
3887fcf3ce44SJohn Forte add_wwn_entry(wwn_list_found, port_wwn_byte,
3888fcf3ce44SJohn Forte node_wwn_byte);
3889fcf3ce44SJohn Forte
3890fcf3ce44SJohn Forte if (((map_dev = g_get_next_dev(map_dev, &err)) == NULL) &&
3891fcf3ce44SJohn Forte (err != L_NO_SUCH_DEV_FOUND)) {
3892fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3893fcf3ce44SJohn Forte return (err);
3894fcf3ce44SJohn Forte }
3895fcf3ce44SJohn Forte }
3896fcf3ce44SJohn Forte if (!found) {
3897fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3898fcf3ce44SJohn Forte return (L_NO_LOOP_ADDRS_FOUND);
3899fcf3ce44SJohn Forte }
3900fcf3ce44SJohn Forte
3901fcf3ce44SJohn Forte g_dev_map_fini(map_root);
3902fcf3ce44SJohn Forte if (env != NULL) {
3903fcf3ce44SJohn Forte end_time = gethrtime();
3904fcf3ce44SJohn Forte fprintf(stdout, " get_wwns: "
3905063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
3906063d642aSBill Gumbrell (end_time - start_time)/1000000);
3907fcf3ce44SJohn Forte }
3908fcf3ce44SJohn Forte return (0);
3909fcf3ce44SJohn Forte }
3910fcf3ce44SJohn Forte
3911fcf3ce44SJohn Forte /*
3912fcf3ce44SJohn Forte * Get device World Wide Name and AL_PA for device at path
3913fcf3ce44SJohn Forte *
3914fcf3ce44SJohn Forte * RETURN: 0 O.K.
3915fcf3ce44SJohn Forte *
3916fcf3ce44SJohn Forte * INPUTS:
3917fcf3ce44SJohn Forte * - path_phys must be of a device, either an IB or disk.
3918fcf3ce44SJohn Forte */
3919fcf3ce44SJohn Forte int
g_get_wwn(char * path_phys,uchar_t port_wwn[],uchar_t node_wwn[],int * al_pa,int verbose)3920fcf3ce44SJohn Forte g_get_wwn(char *path_phys, uchar_t port_wwn[], uchar_t node_wwn[],
3921063d642aSBill Gumbrell int *al_pa, int verbose)
3922fcf3ce44SJohn Forte {
3923fcf3ce44SJohn Forte struct wwn_list_found_struct *wwn_list_found = NULL;
3924fcf3ce44SJohn Forte int ret;
3925fcf3ce44SJohn Forte
3926fcf3ce44SJohn Forte /* return invalid path if the argument is NULL */
3927fcf3ce44SJohn Forte if (path_phys == NULL) {
3928fcf3ce44SJohn Forte return (L_INVALID_PATH);
3929fcf3ce44SJohn Forte }
3930fcf3ce44SJohn Forte /* return invalid arg if the argument is NULL */
3931063d642aSBill Gumbrell if ((port_wwn == NULL) || (node_wwn == NULL) || (al_pa == NULL)) {
3932fcf3ce44SJohn Forte return (L_INVALID_ARG);
3933fcf3ce44SJohn Forte }
3934fcf3ce44SJohn Forte
3935fcf3ce44SJohn Forte ret = get_wwns(path_phys, port_wwn, node_wwn, al_pa, &wwn_list_found);
3936fcf3ce44SJohn Forte g_free_wwn_list_found(&wwn_list_found);
3937fcf3ce44SJohn Forte return (ret);
3938fcf3ce44SJohn Forte }
3939fcf3ce44SJohn Forte
3940fcf3ce44SJohn Forte int
g_get_serial_number(char * path,uchar_t * serial_number,size_t * serial_number_len)3941fcf3ce44SJohn Forte g_get_serial_number(char *path, uchar_t *serial_number,
3942fcf3ce44SJohn Forte size_t *serial_number_len)
3943fcf3ce44SJohn Forte {
3944063d642aSBill Gumbrell int fd, status = 0;
3945063d642aSBill Gumbrell L_inquiry80 inq80;
3946fcf3ce44SJohn Forte
3947fcf3ce44SJohn Forte /* return invalid path if path is NULL */
3948fcf3ce44SJohn Forte if (path == NULL) {
3949fcf3ce44SJohn Forte return (L_INVALID_PATH);
3950fcf3ce44SJohn Forte }
3951fcf3ce44SJohn Forte /* return invalid arg if serial_number is NULL */
3952fcf3ce44SJohn Forte if (serial_number == NULL) {
3953fcf3ce44SJohn Forte return (L_INVALID_ARG);
3954fcf3ce44SJohn Forte }
3955fcf3ce44SJohn Forte
3956fcf3ce44SJohn Forte P_DPRINTF(" g_get_serial_number: path: %s\n", path);
3957fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1) {
3958fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
3959fcf3ce44SJohn Forte }
3960fcf3ce44SJohn Forte /*
3961fcf3ce44SJohn Forte * Call the inquiry cmd on page 0x80 only if the vendor
3962fcf3ce44SJohn Forte * supports page 0x80.
3963fcf3ce44SJohn Forte */
3964fcf3ce44SJohn Forte if ((g_find_supported_inq_page(fd, 0x80))) {
3965fcf3ce44SJohn Forte /*
3966fcf3ce44SJohn Forte * Let's retrieve the serial number from page 0x80
3967fcf3ce44SJohn Forte * and store it in the inquiry structure
3968fcf3ce44SJohn Forte */
3969fcf3ce44SJohn Forte status = g_scsi_inquiry_cmd80(fd,
3970fcf3ce44SJohn Forte (uchar_t *)&inq80,
3971fcf3ce44SJohn Forte sizeof (struct l_inquiry80_struct));
3972fcf3ce44SJohn Forte if (status == 0) {
3973fcf3ce44SJohn Forte if (*serial_number_len > inq80.inq_page_len)
3974fcf3ce44SJohn Forte *serial_number_len = inq80.inq_page_len;
3975fcf3ce44SJohn Forte strncpy((char *)serial_number, (char *)inq80.inq_serial,
3976fcf3ce44SJohn Forte *serial_number_len);
3977fcf3ce44SJohn Forte } else {
3978fcf3ce44SJohn Forte char unavail[] = "Unavailable";
3979fcf3ce44SJohn Forte status = 0;
3980fcf3ce44SJohn Forte if (*serial_number_len > strlen(unavail))
3981fcf3ce44SJohn Forte *serial_number_len = strlen(unavail);
3982fcf3ce44SJohn Forte strncpy((char *)serial_number, unavail,
3983fcf3ce44SJohn Forte *serial_number_len);
3984fcf3ce44SJohn Forte }
3985fcf3ce44SJohn Forte } else {
3986fcf3ce44SJohn Forte /*
3987fcf3ce44SJohn Forte * page 0x80 is not supported, so print the
3988fcf3ce44SJohn Forte * appropriate message.
3989fcf3ce44SJohn Forte */
3990fcf3ce44SJohn Forte char unsupp[] = "Unsupported";
3991fcf3ce44SJohn Forte if (*serial_number_len > strlen(unsupp))
3992fcf3ce44SJohn Forte *serial_number_len = strlen(unsupp);
3993fcf3ce44SJohn Forte strncpy((char *)serial_number, unsupp,
3994fcf3ce44SJohn Forte *serial_number_len);
3995fcf3ce44SJohn Forte }
3996fcf3ce44SJohn Forte (void) close(fd);
3997fcf3ce44SJohn Forte return (status);
3998fcf3ce44SJohn Forte }
3999fcf3ce44SJohn Forte
4000fcf3ce44SJohn Forte int
g_get_inquiry(char * path,L_inquiry * l_inquiry)4001fcf3ce44SJohn Forte g_get_inquiry(char *path, L_inquiry *l_inquiry)
4002fcf3ce44SJohn Forte {
4003063d642aSBill Gumbrell int fd, status;
4004fcf3ce44SJohn Forte
4005fcf3ce44SJohn Forte /* return invalid path if path is NULL */
4006fcf3ce44SJohn Forte if (path == NULL) {
4007fcf3ce44SJohn Forte return (L_INVALID_PATH);
4008fcf3ce44SJohn Forte }
4009fcf3ce44SJohn Forte /* return invalid arg if l_inquiry is NULL */
4010fcf3ce44SJohn Forte if (l_inquiry == NULL) {
4011fcf3ce44SJohn Forte return (L_INVALID_ARG);
4012fcf3ce44SJohn Forte }
4013fcf3ce44SJohn Forte
4014fcf3ce44SJohn Forte P_DPRINTF(" g_get_inquiry: path: %s\n", path);
4015fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4016fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4017fcf3ce44SJohn Forte status = g_scsi_inquiry_cmd(fd,
4018063d642aSBill Gumbrell (uchar_t *)l_inquiry, sizeof (struct l_inquiry_struct));
4019fcf3ce44SJohn Forte
4020fcf3ce44SJohn Forte (void) close(fd);
4021fcf3ce44SJohn Forte return (status);
4022fcf3ce44SJohn Forte }
4023fcf3ce44SJohn Forte
4024fcf3ce44SJohn Forte /*
4025fcf3ce44SJohn Forte * Function to retrieve inquiry page 0x80 from the device
4026fcf3ce44SJohn Forte */
4027fcf3ce44SJohn Forte static int
g_scsi_inquiry_cmd80(int fd,uchar_t * buf_ptr,int buf_len)4028fcf3ce44SJohn Forte g_scsi_inquiry_cmd80(int fd, uchar_t *buf_ptr, int buf_len)
4029fcf3ce44SJohn Forte {
4030063d642aSBill Gumbrell struct uscsi_cmd ucmd;
4031063d642aSBill Gumbrell my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0x80, 0, 0x10, 0};
4032063d642aSBill Gumbrell struct scsi_extended_sense sense;
4033fcf3ce44SJohn Forte
4034fcf3ce44SJohn Forte (void) memset(buf_ptr, 0, buf_len);
4035fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd));
4036fcf3ce44SJohn Forte cdb.count = (uchar_t)buf_len;
4037fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb;
4038fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0;
4039fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
4040fcf3ce44SJohn Forte ucmd.uscsi_buflen = buf_len;
4041fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense;
4042fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense);
4043fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60;
4044fcf3ce44SJohn Forte return (cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT));
4045fcf3ce44SJohn Forte }
4046fcf3ce44SJohn Forte
4047fcf3ce44SJohn Forte /*
4048fcf3ce44SJohn Forte * Function to determine if the given page is supported by vendor.
4049fcf3ce44SJohn Forte */
4050fcf3ce44SJohn Forte static int
g_find_supported_inq_page(int fd,int page_num)4051fcf3ce44SJohn Forte g_find_supported_inq_page(int fd, int page_num)
4052fcf3ce44SJohn Forte {
4053063d642aSBill Gumbrell struct uscsi_cmd ucmd;
4054063d642aSBill Gumbrell my_cdb_g0 cdb = {SCMD_INQUIRY, 0x1, 0, 0, 0xff, 0};
4055063d642aSBill Gumbrell struct scsi_extended_sense sense;
4056063d642aSBill Gumbrell L_inquiry00 inq00;
4057063d642aSBill Gumbrell uchar_t *data;
4058063d642aSBill Gumbrell int status = 0;
4059063d642aSBill Gumbrell int index;
4060fcf3ce44SJohn Forte
4061fcf3ce44SJohn Forte (void) memset((char *)&ucmd, 0, sizeof (ucmd));
4062fcf3ce44SJohn Forte cdb.count = (uchar_t)(sizeof (L_inquiry00));
4063fcf3ce44SJohn Forte ucmd.uscsi_cdb = (caddr_t)&cdb;
4064fcf3ce44SJohn Forte ucmd.uscsi_cdblen = CDB_GROUP0;
4065fcf3ce44SJohn Forte ucmd.uscsi_bufaddr = (caddr_t)&inq00;
4066fcf3ce44SJohn Forte ucmd.uscsi_buflen = sizeof (inq00);
4067fcf3ce44SJohn Forte ucmd.uscsi_rqbuf = (caddr_t)&sense;
4068fcf3ce44SJohn Forte ucmd.uscsi_rqlen = sizeof (struct scsi_extended_sense);
4069fcf3ce44SJohn Forte ucmd.uscsi_timeout = 60;
4070fcf3ce44SJohn Forte status = cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT);
4071fcf3ce44SJohn Forte if (status) {
4072fcf3ce44SJohn Forte return (0);
4073fcf3ce44SJohn Forte }
4074fcf3ce44SJohn Forte data = (uchar_t *)&inq00;
4075fcf3ce44SJohn Forte for (index = 4; (index <= inq00.len+3)&&
4076fcf3ce44SJohn Forte (data[index] <= page_num); index ++) {
4077fcf3ce44SJohn Forte if (data[index] == page_num) {
4078fcf3ce44SJohn Forte return (1);
4079fcf3ce44SJohn Forte }
4080fcf3ce44SJohn Forte }
4081fcf3ce44SJohn Forte return (0);
4082fcf3ce44SJohn Forte }
4083fcf3ce44SJohn Forte
4084fcf3ce44SJohn Forte int
g_get_perf_statistics(char * path,uchar_t * perf_ptr)4085fcf3ce44SJohn Forte g_get_perf_statistics(char *path, uchar_t *perf_ptr)
4086fcf3ce44SJohn Forte {
4087063d642aSBill Gumbrell int fd;
4088fcf3ce44SJohn Forte
4089fcf3ce44SJohn Forte P_DPRINTF(" g_get_perf_statistics: Get Performance Statistics:"
4090063d642aSBill Gumbrell "\n Path:%s\n",
4091063d642aSBill Gumbrell path);
4092fcf3ce44SJohn Forte
4093fcf3ce44SJohn Forte /* initialize tables */
4094fcf3ce44SJohn Forte (void) memset(perf_ptr, 0, sizeof (int));
4095fcf3ce44SJohn Forte
4096fcf3ce44SJohn Forte /* open controller */
4097fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4098fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4099fcf3ce44SJohn Forte
4100fcf3ce44SJohn Forte
4101fcf3ce44SJohn Forte /* update parameters in the performance table */
4102fcf3ce44SJohn Forte
4103fcf3ce44SJohn Forte /* get the period in seconds */
4104fcf3ce44SJohn Forte
4105fcf3ce44SJohn Forte
4106fcf3ce44SJohn Forte (void) close(fd);
4107fcf3ce44SJohn Forte
4108fcf3ce44SJohn Forte return (0);
4109fcf3ce44SJohn Forte }
4110fcf3ce44SJohn Forte
4111fcf3ce44SJohn Forte
4112fcf3ce44SJohn Forte int
g_start(char * path)4113fcf3ce44SJohn Forte g_start(char *path)
4114fcf3ce44SJohn Forte {
4115063d642aSBill Gumbrell int status;
4116063d642aSBill Gumbrell int fd;
4117fcf3ce44SJohn Forte
4118fcf3ce44SJohn Forte P_DPRINTF(" g_start: Start: Path %s\n", path);
4119fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4120fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4121fcf3ce44SJohn Forte status = g_scsi_start_cmd(fd);
4122fcf3ce44SJohn Forte (void) close(fd);
4123fcf3ce44SJohn Forte return (status);
4124fcf3ce44SJohn Forte }
4125fcf3ce44SJohn Forte
4126fcf3ce44SJohn Forte int
g_stop(char * path,int immediate_flag)4127fcf3ce44SJohn Forte g_stop(char *path, int immediate_flag)
4128fcf3ce44SJohn Forte {
4129063d642aSBill Gumbrell int status, fd;
4130fcf3ce44SJohn Forte
4131fcf3ce44SJohn Forte P_DPRINTF(" g_stop: Stop: Path %s\n", path);
4132fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4133fcf3ce44SJohn Forte return (errno);
4134fcf3ce44SJohn Forte status = g_scsi_stop_cmd(fd, immediate_flag);
4135fcf3ce44SJohn Forte (void) close(fd);
4136fcf3ce44SJohn Forte return (status);
4137fcf3ce44SJohn Forte }
4138fcf3ce44SJohn Forte
4139fcf3ce44SJohn Forte int
g_reserve(char * path)4140fcf3ce44SJohn Forte g_reserve(char *path)
4141fcf3ce44SJohn Forte {
4142*926d645fSToomas Soome int fd, status;
4143fcf3ce44SJohn Forte
4144fcf3ce44SJohn Forte P_DPRINTF(" g_reserve: Reserve: Path %s\n", path);
4145fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4146fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4147fcf3ce44SJohn Forte status = g_scsi_reserve_cmd(fd);
4148fcf3ce44SJohn Forte (void) close(fd);
4149fcf3ce44SJohn Forte return (status);
4150fcf3ce44SJohn Forte }
4151fcf3ce44SJohn Forte
4152fcf3ce44SJohn Forte int
g_release(char * path)4153fcf3ce44SJohn Forte g_release(char *path)
4154fcf3ce44SJohn Forte {
4155*926d645fSToomas Soome int fd, status;
4156fcf3ce44SJohn Forte
4157fcf3ce44SJohn Forte P_DPRINTF(" g_release: Release: Path %s\n", path);
4158fcf3ce44SJohn Forte if ((fd = g_object_open(path, O_NDELAY | O_RDONLY)) == -1)
4159fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4160fcf3ce44SJohn Forte status = g_scsi_release_cmd(fd);
4161fcf3ce44SJohn Forte (void) close(fd);
4162fcf3ce44SJohn Forte return (status);
4163fcf3ce44SJohn Forte }
4164fcf3ce44SJohn Forte
4165fcf3ce44SJohn Forte static char
ctoi(char c)4166fcf3ce44SJohn Forte ctoi(char c)
4167fcf3ce44SJohn Forte {
4168fcf3ce44SJohn Forte if ((c >= '0') && (c <= '9'))
4169fcf3ce44SJohn Forte c -= '0';
4170fcf3ce44SJohn Forte else if ((c >= 'A') && (c <= 'F'))
4171fcf3ce44SJohn Forte c = c - 'A' + 10;
4172fcf3ce44SJohn Forte else if ((c >= 'a') && (c <= 'f'))
4173fcf3ce44SJohn Forte c = c - 'a' + 10;
4174fcf3ce44SJohn Forte else
4175fcf3ce44SJohn Forte c = -1;
4176fcf3ce44SJohn Forte return (c);
4177fcf3ce44SJohn Forte }
4178fcf3ce44SJohn Forte
4179fcf3ce44SJohn Forte int
g_string_to_wwn(uchar_t * wwn,uchar_t * wwnp)4180fcf3ce44SJohn Forte g_string_to_wwn(uchar_t *wwn, uchar_t *wwnp)
4181fcf3ce44SJohn Forte {
4182fcf3ce44SJohn Forte int i;
4183fcf3ce44SJohn Forte char c, c1;
4184fcf3ce44SJohn Forte
4185fcf3ce44SJohn Forte *wwnp++ = 0;
4186fcf3ce44SJohn Forte *wwnp++ = 0;
4187fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE - 2; i++, wwnp++) {
4188fcf3ce44SJohn Forte c = ctoi(*wwn++);
4189fcf3ce44SJohn Forte c1 = ctoi(*wwn++);
4190fcf3ce44SJohn Forte if (c == -1 || c1 == -1)
4191fcf3ce44SJohn Forte return (-1);
4192fcf3ce44SJohn Forte *wwnp = ((c << 4) + c1);
4193fcf3ce44SJohn Forte }
4194fcf3ce44SJohn Forte
4195fcf3ce44SJohn Forte return (0);
4196fcf3ce44SJohn Forte
4197fcf3ce44SJohn Forte }
4198fcf3ce44SJohn Forte
4199fcf3ce44SJohn Forte /*
4200fcf3ce44SJohn Forte * Converts a string of WWN ASCII characters to a
4201fcf3ce44SJohn Forte * binary representation.
4202fcf3ce44SJohn Forte *
4203fcf3ce44SJohn Forte * Input: string - pointer to uchar_t array
4204fcf3ce44SJohn Forte * WWN in ASCII
4205fcf3ce44SJohn Forte * length: 16 bytes
4206fcf3ce44SJohn Forte * Output: wwn - pointer to uchar_t array
4207fcf3ce44SJohn Forte * containing WWN result
4208fcf3ce44SJohn Forte * length: 8 bytes
4209fcf3ce44SJohn Forte * Returns:
4210fcf3ce44SJohn Forte * non-zero on error
4211fcf3ce44SJohn Forte * zero on success
4212fcf3ce44SJohn Forte */
4213fcf3ce44SJohn Forte int
string_to_wwn(uchar_t * string,uchar_t * wwn)4214fcf3ce44SJohn Forte string_to_wwn(uchar_t *string, uchar_t *wwn)
4215fcf3ce44SJohn Forte {
4216fcf3ce44SJohn Forte int i;
4217fcf3ce44SJohn Forte char c, c1;
4218fcf3ce44SJohn Forte uchar_t *wwnp;
4219fcf3ce44SJohn Forte
4220fcf3ce44SJohn Forte wwnp = wwn;
4221fcf3ce44SJohn Forte
4222fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE; i++, wwnp++) {
4223fcf3ce44SJohn Forte
4224fcf3ce44SJohn Forte c = ctoi(*string++);
4225fcf3ce44SJohn Forte c1 = ctoi(*string++);
4226fcf3ce44SJohn Forte if (c == -1 || c1 == -1)
4227fcf3ce44SJohn Forte return (-1);
4228fcf3ce44SJohn Forte *wwnp = ((c << 4) + c1);
4229fcf3ce44SJohn Forte }
4230fcf3ce44SJohn Forte
4231fcf3ce44SJohn Forte return (0);
4232fcf3ce44SJohn Forte
4233fcf3ce44SJohn Forte }
4234fcf3ce44SJohn Forte
4235fcf3ce44SJohn Forte
4236fcf3ce44SJohn Forte /*
4237fcf3ce44SJohn Forte * Get multiple paths to a given device port.
4238fcf3ce44SJohn Forte * INPUTS:
4239fcf3ce44SJohn Forte * port WWN string.
4240fcf3ce44SJohn Forte */
4241fcf3ce44SJohn Forte int
g_get_port_multipath(char * port_wwn_s,struct dlist ** dlh,int verbose)4242fcf3ce44SJohn Forte g_get_port_multipath(char *port_wwn_s, struct dlist **dlh, int verbose)
4243fcf3ce44SJohn Forte {
4244063d642aSBill Gumbrell int err;
4245063d642aSBill Gumbrell WWN_list *wwn_list, *wwn_list_ptr;
4246063d642aSBill Gumbrell struct dlist *dlt, *dl;
4247fcf3ce44SJohn Forte
4248fcf3ce44SJohn Forte
4249fcf3ce44SJohn Forte /* Initialize list structures. */
4250fcf3ce44SJohn Forte dl = *dlh = dlt = (struct dlist *)NULL;
4251fcf3ce44SJohn Forte wwn_list = wwn_list_ptr = NULL;
4252fcf3ce44SJohn Forte
4253fcf3ce44SJohn Forte H_DPRINTF(" g_get_port_multipath: Looking for multiple paths for"
4254063d642aSBill Gumbrell " device with\n port WWW:"
4255063d642aSBill Gumbrell "%s\n", port_wwn_s);
4256fcf3ce44SJohn Forte
4257fcf3ce44SJohn Forte if (err = g_get_wwn_list(&wwn_list, verbose)) {
4258fcf3ce44SJohn Forte return (err);
4259fcf3ce44SJohn Forte }
4260fcf3ce44SJohn Forte
4261fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4262063d642aSBill Gumbrell wwn_list_ptr = wwn_list_ptr->wwn_next) {
4263fcf3ce44SJohn Forte if (strcmp(port_wwn_s, wwn_list_ptr->port_wwn_s) == 0) {
4264fcf3ce44SJohn Forte if ((dl = (struct dlist *)
4265063d642aSBill Gumbrell g_zalloc(sizeof (struct dlist))) == NULL) {
4266fcf3ce44SJohn Forte while (*dlh != NULL) {
4267fcf3ce44SJohn Forte dl = (*dlh)->next;
4268fcf3ce44SJohn Forte (void) g_destroy_data(*dlh);
4269fcf3ce44SJohn Forte *dlh = dl;
4270fcf3ce44SJohn Forte }
4271fcf3ce44SJohn Forte (void) g_free_wwn_list(&wwn_list);
4272fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
4273fcf3ce44SJohn Forte }
4274fcf3ce44SJohn Forte H_DPRINTF(" g_get_port_multipath:"
4275063d642aSBill Gumbrell " Found multipath:\n %s\n",
4276063d642aSBill Gumbrell wwn_list_ptr->physical_path);
4277fcf3ce44SJohn Forte dl->dev_path = strdup(wwn_list_ptr->physical_path);
4278fcf3ce44SJohn Forte dl->logical_path = strdup(wwn_list_ptr->logical_path);
4279fcf3ce44SJohn Forte if (*dlh == NULL) {
4280fcf3ce44SJohn Forte *dlh = dlt = dl;
4281fcf3ce44SJohn Forte } else {
4282fcf3ce44SJohn Forte dlt->next = dl;
4283fcf3ce44SJohn Forte dl->prev = dlt;
4284fcf3ce44SJohn Forte dlt = dl;
4285fcf3ce44SJohn Forte }
4286fcf3ce44SJohn Forte }
4287fcf3ce44SJohn Forte }
4288fcf3ce44SJohn Forte (void) g_free_wwn_list(&wwn_list);
4289fcf3ce44SJohn Forte return (0);
4290fcf3ce44SJohn Forte }
4291fcf3ce44SJohn Forte
4292fcf3ce44SJohn Forte
4293fcf3ce44SJohn Forte
4294fcf3ce44SJohn Forte /*
4295fcf3ce44SJohn Forte * Get multiple paths to a given disk/tape device.
4296fcf3ce44SJohn Forte * The arg: devpath should be the physical path to device.
4297fcf3ce44SJohn Forte *
4298fcf3ce44SJohn Forte * OUTPUT:
4299fcf3ce44SJohn Forte * multipath_list points to a list of multiple paths to the device.
4300fcf3ce44SJohn Forte * NOTE: The caller must free the allocated list (dlist).
4301fcf3ce44SJohn Forte *
4302fcf3ce44SJohn Forte * RETURNS:
4303fcf3ce44SJohn Forte * 0 if O.K.
4304fcf3ce44SJohn Forte * non-zero otherwise
4305fcf3ce44SJohn Forte */
4306fcf3ce44SJohn Forte int
g_get_multipath(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list,int verbose)4307fcf3ce44SJohn Forte g_get_multipath(char *devpath, struct dlist **multipath_list,
4308063d642aSBill Gumbrell struct wwn_list_struct *wwn_list, int verbose)
4309fcf3ce44SJohn Forte {
4310063d642aSBill Gumbrell int err;
4311fcf3ce44SJohn Forte
4312fcf3ce44SJohn Forte H_DPRINTF(" g_get_multipath: Looking for multiple paths for"
4313063d642aSBill Gumbrell " device at path: %s\n", devpath);
4314fcf3ce44SJohn Forte
4315fcf3ce44SJohn Forte /* return invalid path if devpath is NULL */
4316fcf3ce44SJohn Forte if (devpath == NULL) {
4317fcf3ce44SJohn Forte return (L_INVALID_PATH);
4318fcf3ce44SJohn Forte }
4319fcf3ce44SJohn Forte /* return invalid arg if argument is NULL */
4320fcf3ce44SJohn Forte if ((multipath_list == NULL) || (wwn_list == NULL)) {
4321fcf3ce44SJohn Forte return (L_INVALID_ARG);
4322fcf3ce44SJohn Forte }
4323fcf3ce44SJohn Forte
4324fcf3ce44SJohn Forte if (strstr(devpath, DRV_NAME_SSD) != NULL) {
4325fcf3ce44SJohn Forte err = get_multipath_disk(devpath, multipath_list, wwn_list);
4326fcf3ce44SJohn Forte } else {
4327fcf3ce44SJohn Forte err = get_multipath(devpath, multipath_list, wwn_list);
4328fcf3ce44SJohn Forte }
4329fcf3ce44SJohn Forte
4330fcf3ce44SJohn Forte return (err);
4331fcf3ce44SJohn Forte }
4332fcf3ce44SJohn Forte
4333fcf3ce44SJohn Forte
4334fcf3ce44SJohn Forte /*
4335fcf3ce44SJohn Forte * Returns multipath information for a ssd device.
4336fcf3ce44SJohn Forte * Inputs:
4337fcf3ce44SJohn Forte * devpath: device path to for requested multipath info
4338fcf3ce44SJohn Forte * wwn_list: returned from g_get_wwn_list or devices_get_all
4339fcf3ce44SJohn Forte * Output:
4340fcf3ce44SJohn Forte * multipath_list: dlist list of paths
4341fcf3ce44SJohn Forte * Returns:
4342fcf3ce44SJohn Forte * 0 on success
4343fcf3ce44SJohn Forte * non-zero on failure
4344fcf3ce44SJohn Forte */
4345fcf3ce44SJohn Forte int
get_multipath_disk(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list)4346fcf3ce44SJohn Forte get_multipath_disk(char *devpath, struct dlist **multipath_list,
4347063d642aSBill Gumbrell struct wwn_list_struct *wwn_list)
4348fcf3ce44SJohn Forte {
4349063d642aSBill Gumbrell WWN_list *wwn_list_ptr;
4350063d642aSBill Gumbrell struct dlist *dl = NULL, *dlt = NULL;
4351063d642aSBill Gumbrell ddi_devid_t devid = NULL;
4352063d642aSBill Gumbrell int err;
4353063d642aSBill Gumbrell di_node_t root;
4354063d642aSBill Gumbrell struct mplist_struct *mplistp = NULL, *mplisth = NULL;
4355fcf3ce44SJohn Forte
4356fcf3ce44SJohn Forte if (wwn_list == NULL || multipath_list == NULL || devpath == NULL) {
4357fcf3ce44SJohn Forte return (L_NULL_WWN_LIST);
4358fcf3ce44SJohn Forte }
4359fcf3ce44SJohn Forte
4360fcf3ce44SJohn Forte if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
4361fcf3ce44SJohn Forte return (L_DEV_SNAPSHOT_FAILED);
4362fcf3ce44SJohn Forte }
4363fcf3ce44SJohn Forte
4364fcf3ce44SJohn Forte if ((err = g_devid_get(devpath, &devid, root, SSD_DRVR_NAME)) != 0) {
4365fcf3ce44SJohn Forte di_fini(root);
4366fcf3ce44SJohn Forte return (err);
4367fcf3ce44SJohn Forte }
4368fcf3ce44SJohn Forte
4369fcf3ce44SJohn Forte *multipath_list = (struct dlist *)NULL;
4370fcf3ce44SJohn Forte if ((err = devid_get_all(devid, root, SSD_DRVR_NAME, &mplisth)) != 0) {
4371fcf3ce44SJohn Forte di_fini(root);
4372fcf3ce44SJohn Forte return (err);
4373fcf3ce44SJohn Forte }
4374fcf3ce44SJohn Forte
4375fcf3ce44SJohn Forte if (mplisth == NULL) {
4376fcf3ce44SJohn Forte di_fini(root);
4377fcf3ce44SJohn Forte return (L_NULL_WWN_LIST);
4378fcf3ce44SJohn Forte }
4379fcf3ce44SJohn Forte
4380fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4381063d642aSBill Gumbrell wwn_list_ptr = wwn_list_ptr->wwn_next) {
4382fcf3ce44SJohn Forte /*
4383fcf3ce44SJohn Forte * When a path is found from the list, load the logical
4384fcf3ce44SJohn Forte * and physical dev path
4385fcf3ce44SJohn Forte */
4386fcf3ce44SJohn Forte for (mplistp = mplisth; mplistp != NULL;
4387063d642aSBill Gumbrell mplistp = mplistp->next) {
4388063d642aSBill Gumbrell if (strncmp(mplistp->devpath,
4389063d642aSBill Gumbrell wwn_list_ptr->physical_path,
4390063d642aSBill Gumbrell strlen(mplistp->devpath)) == 0) {
4391063d642aSBill Gumbrell
4392063d642aSBill Gumbrell /* Load multipath list */
4393063d642aSBill Gumbrell if ((dl = (struct dlist *)
4394063d642aSBill Gumbrell calloc(1, sizeof (struct dlist))) == NULL) {
4395063d642aSBill Gumbrell while (*multipath_list != NULL) {
4396063d642aSBill Gumbrell dl = dlt->next;
4397063d642aSBill Gumbrell g_destroy_data(dlt);
4398063d642aSBill Gumbrell dlt = dl;
4399063d642aSBill Gumbrell }
4400063d642aSBill Gumbrell di_fini(root);
4401063d642aSBill Gumbrell return (L_MALLOC_FAILED);
4402063d642aSBill Gumbrell }
4403063d642aSBill Gumbrell H_DPRINTF(
4404063d642aSBill Gumbrell " g_get_multipath: Found multipath=%s\n",
4405063d642aSBill Gumbrell wwn_list_ptr->physical_path);
4406063d642aSBill Gumbrell dl->logical_path =
4407063d642aSBill Gumbrell strdup(wwn_list_ptr->logical_path);
4408063d642aSBill Gumbrell dl->dev_path =
4409063d642aSBill Gumbrell strdup(wwn_list_ptr->physical_path);
4410063d642aSBill Gumbrell if (*multipath_list == NULL) {
4411063d642aSBill Gumbrell *multipath_list = dlt = dl;
4412063d642aSBill Gumbrell } else {
4413063d642aSBill Gumbrell dlt->next = dl;
4414063d642aSBill Gumbrell dl->prev = dlt;
4415fcf3ce44SJohn Forte dlt = dl;
4416fcf3ce44SJohn Forte }
4417fcf3ce44SJohn Forte }
4418fcf3ce44SJohn Forte }
4419fcf3ce44SJohn Forte }
4420fcf3ce44SJohn Forte di_fini(root);
4421fcf3ce44SJohn Forte mplist_free(mplisth);
4422fcf3ce44SJohn Forte return (0);
4423fcf3ce44SJohn Forte }
4424fcf3ce44SJohn Forte
4425fcf3ce44SJohn Forte int
get_multipath(char * devpath,struct dlist ** multipath_list,struct wwn_list_struct * wwn_list)4426fcf3ce44SJohn Forte get_multipath(char *devpath, struct dlist **multipath_list,
4427*926d645fSToomas Soome struct wwn_list_struct *wwn_list)
4428fcf3ce44SJohn Forte {
4429063d642aSBill Gumbrell WWN_list *wwn_list_ptr;
4430063d642aSBill Gumbrell struct dlist *dl, *dlt;
4431063d642aSBill Gumbrell char path[MAXPATHLEN], m_phys_path[MAXPATHLEN], *ptr;
4432063d642aSBill Gumbrell int len;
4433063d642aSBill Gumbrell int lun_a = -1;
4434063d642aSBill Gumbrell char node_wwn_s[WWN_S_LEN];
4435fcf3ce44SJohn Forte
4436fcf3ce44SJohn Forte if (devpath == NULL) {
4437fcf3ce44SJohn Forte return (L_INVALID_PATH);
4438fcf3ce44SJohn Forte }
4439fcf3ce44SJohn Forte
4440fcf3ce44SJohn Forte /* Strip partition information. */
4441fcf3ce44SJohn Forte if ((ptr = strrchr(devpath, ':')) != NULL) {
4442fcf3ce44SJohn Forte len = strlen(devpath) - strlen(ptr);
4443fcf3ce44SJohn Forte (void) strncpy(path, devpath, len);
4444fcf3ce44SJohn Forte path[len] = '\0';
4445fcf3ce44SJohn Forte } else {
4446fcf3ce44SJohn Forte (void) strcpy(path, devpath);
4447fcf3ce44SJohn Forte }
4448fcf3ce44SJohn Forte
4449fcf3ce44SJohn Forte *multipath_list = dl = dlt = (struct dlist *)NULL;
4450fcf3ce44SJohn Forte
4451fcf3ce44SJohn Forte
4452fcf3ce44SJohn Forte if (wwn_list == NULL) {
4453fcf3ce44SJohn Forte return (L_NULL_WWN_LIST);
4454fcf3ce44SJohn Forte }
4455fcf3ce44SJohn Forte
4456*926d645fSToomas Soome *node_wwn_s = '\0';
4457*926d645fSToomas Soome for (wwn_list_ptr = wwn_list;
4458063d642aSBill Gumbrell wwn_list_ptr != NULL;
4459063d642aSBill Gumbrell wwn_list_ptr = wwn_list_ptr->wwn_next) {
4460fcf3ce44SJohn Forte
4461fcf3ce44SJohn Forte if ((ptr = strrchr(wwn_list_ptr->physical_path, ':')) != NULL) {
4462fcf3ce44SJohn Forte len = strlen(wwn_list_ptr->physical_path) - strlen(ptr);
4463fcf3ce44SJohn Forte (void) strncpy(m_phys_path, wwn_list_ptr->physical_path,
4464063d642aSBill Gumbrell len);
4465fcf3ce44SJohn Forte m_phys_path[len] = '\0';
4466fcf3ce44SJohn Forte } else {
4467fcf3ce44SJohn Forte (void) strcpy(m_phys_path, wwn_list_ptr->physical_path);
4468fcf3ce44SJohn Forte }
4469fcf3ce44SJohn Forte
4470fcf3ce44SJohn Forte if (strcasecmp(m_phys_path, path) == 0) {
4471fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, wwn_list_ptr->node_wwn_s);
4472fcf3ce44SJohn Forte break;
4473fcf3ce44SJohn Forte }
4474fcf3ce44SJohn Forte }
4475fcf3ce44SJohn Forte
4476*926d645fSToomas Soome if (*node_wwn_s == '\0') {
4477*926d645fSToomas Soome H_DPRINTF("node_wwn_s is not found!\n");
4478fcf3ce44SJohn Forte return (L_NO_NODE_WWN_IN_WWNLIST);
4479fcf3ce44SJohn Forte }
4480fcf3ce44SJohn Forte
4481fcf3ce44SJohn Forte lun_a = g_get_lun_number(wwn_list_ptr->physical_path);
4482fcf3ce44SJohn Forte
4483fcf3ce44SJohn Forte for (wwn_list_ptr = wwn_list; wwn_list_ptr != NULL;
4484063d642aSBill Gumbrell wwn_list_ptr = wwn_list_ptr->wwn_next) {
4485fcf3ce44SJohn Forte if ((strcmp(node_wwn_s, wwn_list_ptr->node_wwn_s) == 0) &&
4486063d642aSBill Gumbrell ((lun_a < 0) || (lun_a ==
4487063d642aSBill Gumbrell g_get_lun_number(wwn_list_ptr->physical_path)))) {
4488fcf3ce44SJohn Forte
4489fcf3ce44SJohn Forte if ((dl = (struct dlist *)
4490063d642aSBill Gumbrell g_zalloc(sizeof (struct dlist))) == NULL) {
4491fcf3ce44SJohn Forte while (*multipath_list != NULL) {
4492fcf3ce44SJohn Forte dl = dlt->next;
4493fcf3ce44SJohn Forte (void) g_destroy_data(dlt);
4494fcf3ce44SJohn Forte dlt = dl;
4495fcf3ce44SJohn Forte }
4496fcf3ce44SJohn Forte return (L_MALLOC_FAILED);
4497fcf3ce44SJohn Forte }
4498fcf3ce44SJohn Forte H_DPRINTF(" g_get_multipath: Found multipath=%s\n",
4499063d642aSBill Gumbrell wwn_list_ptr->physical_path);
4500fcf3ce44SJohn Forte dl->dev_path = strdup(wwn_list_ptr->physical_path);
4501fcf3ce44SJohn Forte dl->logical_path = strdup(wwn_list_ptr->logical_path);
4502fcf3ce44SJohn Forte if (*multipath_list == NULL) {
4503fcf3ce44SJohn Forte *multipath_list = dlt = dl;
4504fcf3ce44SJohn Forte } else {
4505fcf3ce44SJohn Forte dlt->next = dl;
4506fcf3ce44SJohn Forte dl->prev = dlt;
4507fcf3ce44SJohn Forte dlt = dl;
4508fcf3ce44SJohn Forte }
4509fcf3ce44SJohn Forte }
4510fcf3ce44SJohn Forte }
4511fcf3ce44SJohn Forte return (0);
4512fcf3ce44SJohn Forte }
4513fcf3ce44SJohn Forte
4514fcf3ce44SJohn Forte /*
4515fcf3ce44SJohn Forte * Free a multipath list
4516fcf3ce44SJohn Forte *
4517fcf3ce44SJohn Forte */
4518fcf3ce44SJohn Forte void
g_free_multipath(struct dlist * dlh)4519fcf3ce44SJohn Forte g_free_multipath(struct dlist *dlh)
4520fcf3ce44SJohn Forte {
4521063d642aSBill Gumbrell struct dlist *dl;
4522fcf3ce44SJohn Forte
4523fcf3ce44SJohn Forte while (dlh != NULL) {
4524fcf3ce44SJohn Forte dl = dlh->next;
4525fcf3ce44SJohn Forte if (dlh->dev_path != NULL)
4526fcf3ce44SJohn Forte (void) g_destroy_data(dlh->dev_path);
4527fcf3ce44SJohn Forte if (dlh->logical_path != NULL)
4528fcf3ce44SJohn Forte (void) g_destroy_data(dlh->logical_path);
4529fcf3ce44SJohn Forte (void) g_destroy_data(dlh);
4530fcf3ce44SJohn Forte dlh = dl;
4531fcf3ce44SJohn Forte }
4532fcf3ce44SJohn Forte }
4533fcf3ce44SJohn Forte
4534fcf3ce44SJohn Forte
4535fcf3ce44SJohn Forte
4536fcf3ce44SJohn Forte /*
4537fcf3ce44SJohn Forte * Get the path to the nexus (HBA) driver.
4538fcf3ce44SJohn Forte * This assumes the path looks something like this:
4539fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
4540fcf3ce44SJohn Forte * or maybe this
4541fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0
4542fcf3ce44SJohn Forte * or
4543fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0
4544fcf3ce44SJohn Forte * or
4545fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1
4546fcf3ce44SJohn Forte * or
4547fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
4548fcf3ce44SJohn Forte * (or "qlc" instead of "socal" and "fp" for "sf")
4549fcf3ce44SJohn Forte *
4550fcf3ce44SJohn Forte * Which should resolve to a path like this:
4551fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0:1
4552fcf3ce44SJohn Forte * or
4553fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5
4554fcf3ce44SJohn Forte *
4555fcf3ce44SJohn Forte * or
4556fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0
4557fcf3ce44SJohn Forte * which should resolve to
4558fcf3ce44SJohn Forte * /devices/pci@4,2000/scsi@1:devctl
4559fcf3ce44SJohn Forte */
4560fcf3ce44SJohn Forte int
g_get_nexus_path(char * path_phys,char ** nexus_path)4561fcf3ce44SJohn Forte g_get_nexus_path(char *path_phys, char **nexus_path)
4562fcf3ce44SJohn Forte {
4563063d642aSBill Gumbrell uchar_t port = 0;
4564063d642aSBill Gumbrell int port_flag = 0, i = 0, pathcnt = 1;
4565063d642aSBill Gumbrell char *char_ptr;
4566063d642aSBill Gumbrell char drvr_path[MAXPATHLEN];
4567063d642aSBill Gumbrell char buf[MAXPATHLEN];
4568063d642aSBill Gumbrell char temp_buf[MAXPATHLEN];
4569063d642aSBill Gumbrell struct stat stbuf;
4570063d642aSBill Gumbrell uint_t path_type;
4571063d642aSBill Gumbrell mp_pathlist_t pathlist;
4572063d642aSBill Gumbrell int p_on = 0, p_st = 0;
4573fcf3ce44SJohn Forte
4574fcf3ce44SJohn Forte /* return invalid path if the path_phys is NULL */
4575fcf3ce44SJohn Forte if (path_phys == NULL) {
4576fcf3ce44SJohn Forte return (L_INVALID_PATH);
4577fcf3ce44SJohn Forte }
4578fcf3ce44SJohn Forte
4579fcf3ce44SJohn Forte *nexus_path = NULL;
4580fcf3ce44SJohn Forte (void) strcpy(drvr_path, path_phys);
4581fcf3ce44SJohn Forte
4582fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI)) {
4583fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) {
4584fcf3ce44SJohn Forte return (L_INVALID_PATH);
4585fcf3ce44SJohn Forte }
4586fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
4587fcf3ce44SJohn Forte p_on = p_st = 0;
4588fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
4589fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
4590fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
4591063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
4592fcf3ce44SJohn Forte p_on = i;
4593fcf3ce44SJohn Forte break;
4594fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
4595063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
4596fcf3ce44SJohn Forte p_st = i;
4597fcf3ce44SJohn Forte }
4598fcf3ce44SJohn Forte }
4599fcf3ce44SJohn Forte }
4600fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state ==
4601fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
4602fcf3ce44SJohn Forte /* on_line path */
4603fcf3ce44SJohn Forte (void) strcpy(drvr_path,
4604063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
4605fcf3ce44SJohn Forte } else {
4606fcf3ce44SJohn Forte /* standby or path0 */
4607fcf3ce44SJohn Forte (void) strcpy(drvr_path,
4608063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
4609fcf3ce44SJohn Forte }
4610fcf3ce44SJohn Forte free(pathlist.path_info);
4611fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
4612fcf3ce44SJohn Forte } else {
4613fcf3ce44SJohn Forte if (strstr(drvr_path, DRV_NAME_SSD) || strstr(drvr_path,
4614063d642aSBill Gumbrell DRV_NAME_ST) || strstr(drvr_path, SES_NAME)) {
4615fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
4616fcf3ce44SJohn Forte return (L_INVALID_PATH);
4617fcf3ce44SJohn Forte }
4618fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */
4619fcf3ce44SJohn Forte }
4620fcf3ce44SJohn Forte
4621fcf3ce44SJohn Forte path_type = g_get_path_type(drvr_path);
4622fcf3ce44SJohn Forte
4623fcf3ce44SJohn Forte if (path_type & FC4_SF_XPORT) {
4624fcf3ce44SJohn Forte
4625fcf3ce44SJohn Forte /* sf driver in path so capture the port # */
4626fcf3ce44SJohn Forte if ((char_ptr = strstr(drvr_path, "sf@")) == NULL) {
4627fcf3ce44SJohn Forte return (L_INVALID_PATH);
4628fcf3ce44SJohn Forte }
4629fcf3ce44SJohn Forte port = atoi(char_ptr + 3);
4630fcf3ce44SJohn Forte if (port > 1) {
4631fcf3ce44SJohn Forte return (L_INVLD_PORT_IN_PATH);
4632fcf3ce44SJohn Forte }
4633fcf3ce44SJohn Forte
4634fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
4635fcf3ce44SJohn Forte return (L_INVALID_PATH);
4636fcf3ce44SJohn Forte }
4637fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */
4638fcf3ce44SJohn Forte port_flag++;
4639fcf3ce44SJohn Forte
4640fcf3ce44SJohn Forte L_DPRINTF(" g_get_nexus_path:"
4641063d642aSBill Gumbrell " sf driver in path so use port #%d.\n",
4642063d642aSBill Gumbrell port);
4643fcf3ce44SJohn Forte } else if (path_type & FC_GEN_XPORT) {
4644fcf3ce44SJohn Forte /*
4645fcf3ce44SJohn Forte * check to see if it 3rd party vendor FCA.
4646fcf3ce44SJohn Forte * if it is return error for this operation since
4647fcf3ce44SJohn Forte * we don't know how they creates FCA port related minor node.
4648fcf3ce44SJohn Forte *
4649fcf3ce44SJohn Forte * As of now there is no supported operation on FCA node so
4650fcf3ce44SJohn Forte * this should be okay.
4651fcf3ce44SJohn Forte */
4652fcf3ce44SJohn Forte if ((path_type & FC_FCA_MASK) == FC_FCA_MASK) {
4653fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
4654fcf3ce44SJohn Forte }
4655fcf3ce44SJohn Forte /*
4656fcf3ce44SJohn Forte * For current Sun FCA driver, appending
4657fcf3ce44SJohn Forte * port # doesn't work. Just remove transport layer from
4658fcf3ce44SJohn Forte * input path.
4659fcf3ce44SJohn Forte */
4660fcf3ce44SJohn Forte if ((char_ptr = strstr(drvr_path, "/fp@")) == NULL) {
4661fcf3ce44SJohn Forte return (L_INVALID_PATH);
4662fcf3ce44SJohn Forte }
4663fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate string */
4664fcf3ce44SJohn Forte }
4665fcf3ce44SJohn Forte
4666fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) != 0) {
4667fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
4668fcf3ce44SJohn Forte }
4669fcf3ce44SJohn Forte
4670fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
4671fcf3ce44SJohn Forte /*
4672fcf3ce44SJohn Forte * Found a directory.
4673fcf3ce44SJohn Forte * Now append a port number or devctl to the path.
4674fcf3ce44SJohn Forte */
4675fcf3ce44SJohn Forte if (port_flag) {
4676fcf3ce44SJohn Forte /* append port */
4677fcf3ce44SJohn Forte (void) sprintf(buf, ":%d", port);
4678fcf3ce44SJohn Forte } else {
4679fcf3ce44SJohn Forte /* Try adding port 0 and see if node exists. */
4680fcf3ce44SJohn Forte (void) sprintf(temp_buf, "%s:0", drvr_path);
4681fcf3ce44SJohn Forte if (stat(temp_buf, &stbuf) != 0) {
4682fcf3ce44SJohn Forte /*
4683fcf3ce44SJohn Forte * Path we guessed at does not
4684fcf3ce44SJohn Forte * exist so it may be a driver
4685fcf3ce44SJohn Forte * that ends in :devctl.
4686fcf3ce44SJohn Forte */
4687fcf3ce44SJohn Forte (void) sprintf(buf, ":devctl");
4688fcf3ce44SJohn Forte } else {
4689fcf3ce44SJohn Forte /*
4690fcf3ce44SJohn Forte * The path that was entered
4691fcf3ce44SJohn Forte * did not include a port number
4692fcf3ce44SJohn Forte * so the port was set to zero, and
4693fcf3ce44SJohn Forte * then checked. The default path
4694fcf3ce44SJohn Forte * did exist.
4695fcf3ce44SJohn Forte */
4696fcf3ce44SJohn Forte ER_DPRINTF("Since a complete path"
4697063d642aSBill Gumbrell " was not supplied "
4698063d642aSBill Gumbrell "a default path is being"
4699063d642aSBill Gumbrell " used:\n %s\n",
4700063d642aSBill Gumbrell temp_buf);
4701fcf3ce44SJohn Forte (void) sprintf(buf, ":0");
4702fcf3ce44SJohn Forte }
4703fcf3ce44SJohn Forte }
4704fcf3ce44SJohn Forte
4705fcf3ce44SJohn Forte (void) strcat(drvr_path, buf);
4706fcf3ce44SJohn Forte }
4707fcf3ce44SJohn Forte
4708fcf3ce44SJohn Forte }
4709fcf3ce44SJohn Forte *nexus_path = g_alloc_string(drvr_path);
4710fcf3ce44SJohn Forte L_DPRINTF(" g_get_nexus_path: Nexus path = %s\n", drvr_path);
4711fcf3ce44SJohn Forte return (0);
4712fcf3ce44SJohn Forte }
4713fcf3ce44SJohn Forte
4714fcf3ce44SJohn Forte
4715fcf3ce44SJohn Forte /*
4716fcf3ce44SJohn Forte * Get the FC topology for the input device or nexus(HBA) path.
4717fcf3ce44SJohn Forte *
4718fcf3ce44SJohn Forte * The routine calls g_get_path_type to determine the stack of
4719fcf3ce44SJohn Forte * the input path.
4720fcf3ce44SJohn Forte *
4721*926d645fSToomas Soome * If it a socal path
4722fcf3ce44SJohn Forte * it returns FC_TOP_PRIVATE_LOOP
4723fcf3ce44SJohn Forte * else
4724fcf3ce44SJohn Forte * calls fc_get_topology ioctl to
4725fcf3ce44SJohn Forte * get the fp topolgy from the driver.
4726fcf3ce44SJohn Forte *
4727fcf3ce44SJohn Forte * INPUTS:
4728fcf3ce44SJohn Forte * path - a string of device path, transport path.
4729fcf3ce44SJohn Forte * NOTE: "path" SHOULD NOT BE OPEN BEFORE CALLING
4730fcf3ce44SJohn Forte * THIS FUNCTION BECAUSE THIS FUNCTION DOES
4731fcf3ce44SJohn Forte * AN "O_EXCL" OPEN.
4732fcf3ce44SJohn Forte * port_top - a pointer to the toplogy type.
4733fcf3ce44SJohn Forte *
4734fcf3ce44SJohn Forte * RETURNS:
4735fcf3ce44SJohn Forte * 0 if there is no error.
4736fcf3ce44SJohn Forte * error code.
4737fcf3ce44SJohn Forte *
4738fcf3ce44SJohn Forte * The input path is expected to be something like below:
4739*926d645fSToomas Soome * 1)
4740*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
4741*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ssd@..
4742*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@1,0
4743*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0
4744*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0:1
4745*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
4746*926d645fSToomas Soome * (or "qlc" instead of "socal" and "fp" for "sf")
4747fcf3ce44SJohn Forte *
4748*926d645fSToomas Soome * Which should resolve to a path like this:
4749*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0:1
4750*926d645fSToomas Soome * /devices/pci@6,2000/pci@2/SUNW,qlc@5
4751fcf3ce44SJohn Forte *
4752*926d645fSToomas Soome * 2)
4753*926d645fSToomas Soome * /devices/pci@4,2000/scsi@1/ses@w50800200000000d2,0:0
4754*926d645fSToomas Soome * which should resolve to
4755*926d645fSToomas Soome * /devices/pci@4,2000/scsi@1:devctl
4756fcf3ce44SJohn Forte *
4757*926d645fSToomas Soome * 3) The nexus(hba or nexus) path will get an error only for qlc
4758fcf3ce44SJohn Forte * since the routine need to open fp :devctl node for fcio ioctl.
4759*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0
4760*926d645fSToomas Soome * /devices/sbus@1f,0/SUNW,socal@1,0:1
4761*926d645fSToomas Soome * /devices/pci@6,2000/pci@2/SUNW,qlc@5 => error
4762fcf3ce44SJohn Forte */
4763fcf3ce44SJohn Forte int
g_get_fca_port_topology(char * path,uint32_t * port_top,int verbose)4764fcf3ce44SJohn Forte g_get_fca_port_topology(char *path, uint32_t *port_top, int verbose)
4765fcf3ce44SJohn Forte {
4766063d642aSBill Gumbrell fcio_t fcio;
4767063d642aSBill Gumbrell int fd, i = 0, pathcnt = 1;
4768063d642aSBill Gumbrell char drvr_path[MAXPATHLEN];
4769063d642aSBill Gumbrell char *char_ptr;
4770063d642aSBill Gumbrell struct stat stbuf;
4771063d642aSBill Gumbrell uint_t dev_type;
4772063d642aSBill Gumbrell mp_pathlist_t pathlist;
4773063d642aSBill Gumbrell int p_on = 0, p_st = 0;
4774fcf3ce44SJohn Forte
4775fcf3ce44SJohn Forte /* return invalid path if the path is NULL */
4776fcf3ce44SJohn Forte if (path == NULL) {
4777fcf3ce44SJohn Forte return (L_INVALID_PATH);
4778fcf3ce44SJohn Forte }
4779fcf3ce44SJohn Forte /* return invalid arg if the argument is NULL */
4780fcf3ce44SJohn Forte if (port_top == NULL) {
4781fcf3ce44SJohn Forte return (L_INVALID_ARG);
4782fcf3ce44SJohn Forte }
4783fcf3ce44SJohn Forte
4784fcf3ce44SJohn Forte (void) strcpy(drvr_path, path);
4785fcf3ce44SJohn Forte if (strstr(path, SCSI_VHCI)) {
4786fcf3ce44SJohn Forte if (g_get_pathlist(drvr_path, &pathlist)) {
4787fcf3ce44SJohn Forte return (L_INVALID_PATH);
4788fcf3ce44SJohn Forte }
4789fcf3ce44SJohn Forte pathcnt = pathlist.path_count;
4790fcf3ce44SJohn Forte p_on = p_st = 0;
4791fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) {
4792fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < MAXPATHSTATE) {
4793fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state ==
4794063d642aSBill Gumbrell MDI_PATHINFO_STATE_ONLINE) {
4795fcf3ce44SJohn Forte p_on = i;
4796fcf3ce44SJohn Forte break;
4797fcf3ce44SJohn Forte } else if (pathlist.path_info[i].path_state ==
4798063d642aSBill Gumbrell MDI_PATHINFO_STATE_STANDBY) {
4799fcf3ce44SJohn Forte p_st = i;
4800fcf3ce44SJohn Forte }
4801fcf3ce44SJohn Forte }
4802fcf3ce44SJohn Forte }
4803fcf3ce44SJohn Forte if (pathlist.path_info[p_on].path_state ==
4804fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) {
4805fcf3ce44SJohn Forte /* on_line path */
4806fcf3ce44SJohn Forte (void) strcpy(drvr_path,
4807063d642aSBill Gumbrell pathlist.path_info[p_on].path_hba);
4808fcf3ce44SJohn Forte } else {
4809fcf3ce44SJohn Forte /* standby or path0 */
4810fcf3ce44SJohn Forte (void) strcpy(drvr_path,
4811063d642aSBill Gumbrell pathlist.path_info[p_st].path_hba);
4812fcf3ce44SJohn Forte }
4813fcf3ce44SJohn Forte free(pathlist.path_info);
4814fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
4815fcf3ce44SJohn Forte } else {
4816fcf3ce44SJohn Forte /*
4817fcf3ce44SJohn Forte * Get the path to the :devctl driver
4818fcf3ce44SJohn Forte *
4819fcf3ce44SJohn Forte * This assumes the path looks something like this:
4820fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0/ses@e,0:0
4821fcf3ce44SJohn Forte * or
4822fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0
4823fcf3ce44SJohn Forte * or
4824fcf3ce44SJohn Forte * /devices/sbus@1f,0/SUNW,socal@1,0/SUNW,sf@0,0:devctl
4825fcf3ce44SJohn Forte * or
4826fcf3ce44SJohn Forte * a 1 level PCI type driver but still :devctl
4827fcf3ce44SJohn Forte * (or "qlc" in the place of "socal" and "fp" for "sf")
4828fcf3ce44SJohn Forte *
4829fcf3ce44SJohn Forte * The dir below doesn't have corresponding :devctl node.
4830fcf3ce44SJohn Forte * /devices/pci@6,2000/pci@2/SUNW,qlc@5
4831fcf3ce44SJohn Forte * /devices/sbus@2,0/SUNW,socal@1,0
4832fcf3ce44SJohn Forte *
4833fcf3ce44SJohn Forte */
4834fcf3ce44SJohn Forte if ((strstr(drvr_path, DRV_NAME_SSD) ||
4835063d642aSBill Gumbrell strstr(drvr_path, SES_NAME)) ||
4836063d642aSBill Gumbrell strstr(drvr_path, DRV_NAME_ST)) {
4837fcf3ce44SJohn Forte if ((char_ptr = strrchr(drvr_path, '/')) == NULL) {
4838fcf3ce44SJohn Forte return (L_INVALID_PATH);
4839fcf3ce44SJohn Forte }
4840fcf3ce44SJohn Forte *char_ptr = '\0'; /* Terminate sting */
4841fcf3ce44SJohn Forte /* append controller */
4842fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
4843fcf3ce44SJohn Forte } else {
4844fcf3ce44SJohn Forte if (stat(drvr_path, &stbuf) < 0) {
4845fcf3ce44SJohn Forte return (L_LSTAT_ERROR);
4846fcf3ce44SJohn Forte }
4847fcf3ce44SJohn Forte if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
4848fcf3ce44SJohn Forte /* append controller */
4849fcf3ce44SJohn Forte (void) strcat(drvr_path, FC_CTLR);
4850fcf3ce44SJohn Forte }
4851fcf3ce44SJohn Forte }
4852fcf3ce44SJohn Forte }
4853fcf3ce44SJohn Forte
4854fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(drvr_path)) == 0) {
4855fcf3ce44SJohn Forte return (L_INVALID_PATH);
4856fcf3ce44SJohn Forte }
4857fcf3ce44SJohn Forte
4858fcf3ce44SJohn Forte if ((dev_type & FC4_XPORT_MASK) || (dev_type & FC4_FCA_MASK)) {
4859fcf3ce44SJohn Forte *port_top = FC_TOP_PRIVATE_LOOP;
4860fcf3ce44SJohn Forte return (0);
4861fcf3ce44SJohn Forte }
4862fcf3ce44SJohn Forte
4863fcf3ce44SJohn Forte /* To contiue the path type should be fp :devctl node */
4864fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) {
4865fcf3ce44SJohn Forte return (L_INVALID_PATH);
4866fcf3ce44SJohn Forte }
4867fcf3ce44SJohn Forte
4868fcf3ce44SJohn Forte if ((fd = g_object_open(drvr_path, O_NDELAY | O_RDONLY)) == -1)
4869fcf3ce44SJohn Forte return (errno);
4870fcf3ce44SJohn Forte
4871fcf3ce44SJohn Forte P_DPRINTF(" g_get_fca_port_topology: Geting topology from:"
4872063d642aSBill Gumbrell " %s\n", drvr_path);
4873fcf3ce44SJohn Forte
4874fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_TOPOLOGY;
4875fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t);
4876fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
4877fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)port_top;
4878fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
4879fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_TOPOLOGY ioctl failed.\n");
4880fcf3ce44SJohn Forte close(fd);
4881fcf3ce44SJohn Forte return (L_FCIO_GET_TOPOLOGY_FAIL);
4882fcf3ce44SJohn Forte }
4883fcf3ce44SJohn Forte close(fd);
4884fcf3ce44SJohn Forte return (0);
4885fcf3ce44SJohn Forte }
4886fcf3ce44SJohn Forte
4887fcf3ce44SJohn Forte
4888fcf3ce44SJohn Forte /*
4889fcf3ce44SJohn Forte * This functions enables or disables a FCA port depending on the
4890fcf3ce44SJohn Forte * argument, cmd, passed to it. If cmd is PORT_OFFLINE, the function
4891fcf3ce44SJohn Forte * tries to disable the port specified by the argument 'phys_path'. If
4892fcf3ce44SJohn Forte * cmd is PORT_ONLINE, the function tries to enable the port specified
4893fcf3ce44SJohn Forte * by the argument 'phys_path'.
4894fcf3ce44SJohn Forte * INPUTS :
4895fcf3ce44SJohn Forte * nexus_port_ptr - Pointer to the nexus path of the FCA port to
4896fcf3ce44SJohn Forte * operate on
4897fcf3ce44SJohn Forte * cmd - PORT_OFFLINE or PORT_ONLINE
4898fcf3ce44SJohn Forte * RETURNS :
4899fcf3ce44SJohn Forte * 0 on success and non-zero otherwise
4900fcf3ce44SJohn Forte */
4901fcf3ce44SJohn Forte static int
g_set_port_state(char * nexus_port_ptr,int cmd)4902fcf3ce44SJohn Forte g_set_port_state(char *nexus_port_ptr, int cmd)
4903fcf3ce44SJohn Forte {
4904fcf3ce44SJohn Forte int path_type, fd;
4905fcf3ce44SJohn Forte
4906fcf3ce44SJohn Forte if ((path_type = g_get_path_type(nexus_port_ptr)) == 0) {
4907fcf3ce44SJohn Forte return (L_INVALID_PATH);
4908fcf3ce44SJohn Forte }
4909fcf3ce44SJohn Forte
4910fcf3ce44SJohn Forte if ((fd = g_object_open(nexus_port_ptr, O_NDELAY|O_RDONLY)) == -1) {
4911fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
4912fcf3ce44SJohn Forte }
4913fcf3ce44SJohn Forte
4914fcf3ce44SJohn Forte switch (cmd) {
4915fcf3ce44SJohn Forte case PORT_OFFLINE:
4916fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) {
4917fcf3ce44SJohn Forte /*
4918fcf3ce44SJohn Forte * Socal/sf drivers -
4919fcf3ce44SJohn Forte * The socal driver currently returns EFAULT
4920fcf3ce44SJohn Forte * even if the ioctl has completed successfully.
4921fcf3ce44SJohn Forte */
4922fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_INTERNAL,
4923063d642aSBill Gumbrell NULL) == -1) {
4924fcf3ce44SJohn Forte close(fd);
4925fcf3ce44SJohn Forte return (L_PORT_OFFLINE_FAIL);
4926fcf3ce44SJohn Forte }
4927fcf3ce44SJohn Forte } else {
4928fcf3ce44SJohn Forte /*
4929fcf3ce44SJohn Forte * QLogic card -
4930fcf3ce44SJohn Forte * Can't do much here since the driver currently
4931fcf3ce44SJohn Forte * doesn't support this feature. We'll just fail
4932fcf3ce44SJohn Forte * for now. Support can be added when the driver
4933fcf3ce44SJohn Forte * is enabled with the feature at a later date.
4934fcf3ce44SJohn Forte */
4935fcf3ce44SJohn Forte close(fd);
4936fcf3ce44SJohn Forte return (L_PORT_OFFLINE_UNSUPPORTED);
4937fcf3ce44SJohn Forte }
4938fcf3ce44SJohn Forte break;
4939fcf3ce44SJohn Forte case PORT_ONLINE:
4940fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) {
4941fcf3ce44SJohn Forte /*
4942fcf3ce44SJohn Forte * Socal/sf drivers
4943fcf3ce44SJohn Forte * The socal driver currently returns EFAULT
4944fcf3ce44SJohn Forte * even if the ioctl has completed successfully.
4945fcf3ce44SJohn Forte */
4946fcf3ce44SJohn Forte if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) {
4947fcf3ce44SJohn Forte close(fd);
4948fcf3ce44SJohn Forte return (L_PORT_ONLINE_FAIL);
4949fcf3ce44SJohn Forte }
4950fcf3ce44SJohn Forte } else {
4951fcf3ce44SJohn Forte /*
4952fcf3ce44SJohn Forte * QLogic card -
4953fcf3ce44SJohn Forte * Can't do much here since the driver currently
4954fcf3ce44SJohn Forte * doesn't support this feature. We'll just fail
4955fcf3ce44SJohn Forte * for now. Support can be added when the driver
4956fcf3ce44SJohn Forte * is enabled with the feature at a later date.
4957fcf3ce44SJohn Forte */
4958fcf3ce44SJohn Forte close(fd);
4959fcf3ce44SJohn Forte return (L_PORT_ONLINE_UNSUPPORTED);
4960fcf3ce44SJohn Forte }
4961fcf3ce44SJohn Forte break;
4962fcf3ce44SJohn Forte default:
4963fcf3ce44SJohn Forte close(fd);
4964fcf3ce44SJohn Forte return (-1);
4965fcf3ce44SJohn Forte }
4966fcf3ce44SJohn Forte close(fd);
4967fcf3ce44SJohn Forte return (0);
4968fcf3ce44SJohn Forte }
4969fcf3ce44SJohn Forte
4970fcf3ce44SJohn Forte /*
4971fcf3ce44SJohn Forte * The interfaces defined below (g_port_offline() and g_port_online())
4972fcf3ce44SJohn Forte * are what will be exposed to applications. We will hide g_set_port_state().
4973fcf3ce44SJohn Forte * They have to be functions (as against macros) because making them
4974fcf3ce44SJohn Forte * macros will mean exposing g_set_port_state() and we dont want to do that
4975fcf3ce44SJohn Forte */
4976fcf3ce44SJohn Forte
4977fcf3ce44SJohn Forte int
g_port_offline(char * path)4978fcf3ce44SJohn Forte g_port_offline(char *path)
4979fcf3ce44SJohn Forte {
4980fcf3ce44SJohn Forte return (g_set_port_state(path, PORT_OFFLINE));
4981fcf3ce44SJohn Forte }
4982fcf3ce44SJohn Forte
4983fcf3ce44SJohn Forte int
g_port_online(char * path)4984fcf3ce44SJohn Forte g_port_online(char *path)
4985fcf3ce44SJohn Forte {
4986fcf3ce44SJohn Forte return (g_set_port_state(path, PORT_ONLINE));
4987fcf3ce44SJohn Forte }
4988fcf3ce44SJohn Forte
4989fcf3ce44SJohn Forte /*
4990fcf3ce44SJohn Forte * This function sets the loopback mode for a port on a HBA
4991fcf3ce44SJohn Forte * INPUTS :
4992fcf3ce44SJohn Forte * portpath - Pointer to the path of the FCA port on which to
4993fcf3ce44SJohn Forte * set the loopback mode
4994*926d645fSToomas Soome * cmd - EXT_LPBACK
4995fcf3ce44SJohn Forte * INT_LPBACK
4996fcf3ce44SJohn Forte * NO_LPBACK
4997fcf3ce44SJohn Forte * RETURNS :
4998fcf3ce44SJohn Forte * 0 on success and non-zero otherwise
4999fcf3ce44SJohn Forte */
5000fcf3ce44SJohn Forte int
g_loopback_mode(char * portpath,int cmd)5001fcf3ce44SJohn Forte g_loopback_mode(char *portpath, int cmd)
5002fcf3ce44SJohn Forte {
5003fcf3ce44SJohn Forte int path_type, fd;
5004fcf3ce44SJohn Forte
5005fcf3ce44SJohn Forte if ((path_type = g_get_path_type(portpath)) == 0) {
5006fcf3ce44SJohn Forte return (L_INVALID_PATH);
5007fcf3ce44SJohn Forte }
5008fcf3ce44SJohn Forte
5009fcf3ce44SJohn Forte if ((fd = g_object_open(portpath, O_NDELAY|O_RDONLY|O_EXCL)) == -1) {
5010fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
5011fcf3ce44SJohn Forte }
5012fcf3ce44SJohn Forte
5013fcf3ce44SJohn Forte /*
5014fcf3ce44SJohn Forte * The loopback calls are currently not fully supported
5015fcf3ce44SJohn Forte * via fp.
5016fcf3ce44SJohn Forte *
5017fcf3ce44SJohn Forte * A fp based general solution is required to support Leadville FCAs
5018fcf3ce44SJohn Forte * including Qlgc and 3rd party FCA. As of now qlgc provides
5019fcf3ce44SJohn Forte * some diag functions like echo through qlc private ioctl
5020fcf3ce44SJohn Forte * which is not supproted by luxadm and libraries.
5021fcf3ce44SJohn Forte */
5022fcf3ce44SJohn Forte switch (cmd) {
5023fcf3ce44SJohn Forte case EXT_LPBACK:
5024fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) {
5025fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_MANUAL,
5026063d642aSBill Gumbrell NULL) == -1) {
5027fcf3ce44SJohn Forte /* Check for previous mode set */
5028fcf3ce44SJohn Forte if (errno != EALREADY) {
5029fcf3ce44SJohn Forte close(fd);
5030fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED);
5031fcf3ce44SJohn Forte }
5032fcf3ce44SJohn Forte }
5033fcf3ce44SJohn Forte } else {
5034fcf3ce44SJohn Forte /*
5035fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so..
5036fcf3ce44SJohn Forte */
5037fcf3ce44SJohn Forte close(fd);
5038fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED);
5039fcf3ce44SJohn Forte }
5040fcf3ce44SJohn Forte break;
5041fcf3ce44SJohn Forte case NO_LPBACK:
5042fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) {
5043fcf3ce44SJohn Forte if (ioctl(fd, FCIO_NO_LOOPBACK, NULL) == -1) {
5044fcf3ce44SJohn Forte close(fd);
5045fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED);
5046fcf3ce44SJohn Forte }
5047fcf3ce44SJohn Forte } else {
5048fcf3ce44SJohn Forte /*
5049fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so..
5050fcf3ce44SJohn Forte */
5051fcf3ce44SJohn Forte close(fd);
5052fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED);
5053fcf3ce44SJohn Forte }
5054fcf3ce44SJohn Forte break;
5055fcf3ce44SJohn Forte case INT_LPBACK:
5056fcf3ce44SJohn Forte if (path_type & FC4_SOCAL_FCA) {
5057fcf3ce44SJohn Forte if (ioctl(fd, FCIO_LOOPBACK_INTERNAL,
5058063d642aSBill Gumbrell NULL) == -1) {
5059fcf3ce44SJohn Forte /* Check for previous mode set */
5060fcf3ce44SJohn Forte if (errno != EALREADY) {
5061fcf3ce44SJohn Forte close(fd);
5062fcf3ce44SJohn Forte return (L_LOOPBACK_FAILED);
5063fcf3ce44SJohn Forte }
5064fcf3ce44SJohn Forte }
5065fcf3ce44SJohn Forte } else {
5066fcf3ce44SJohn Forte /*
5067fcf3ce44SJohn Forte * Well, it wasn't one of the above cards so..
5068fcf3ce44SJohn Forte */
5069fcf3ce44SJohn Forte close(fd);
5070fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED);
5071fcf3ce44SJohn Forte }
5072fcf3ce44SJohn Forte break;
5073fcf3ce44SJohn Forte default:
5074fcf3ce44SJohn Forte close(fd);
5075fcf3ce44SJohn Forte return (L_LOOPBACK_UNSUPPORTED);
5076fcf3ce44SJohn Forte }
5077fcf3ce44SJohn Forte close(fd);
5078fcf3ce44SJohn Forte return (0);
5079fcf3ce44SJohn Forte }
5080fcf3ce44SJohn Forte
5081fcf3ce44SJohn Forte /*
5082fcf3ce44SJohn Forte * g_get_port_state(char *portpath, int port_state)
5083fcf3ce44SJohn Forte * Purpose: Get port state for a path
5084fcf3ce44SJohn Forte * Input: portpath
5085fcf3ce44SJohn Forte * set to path of port
5086fcf3ce44SJohn Forte * Output: port_state
5087fcf3ce44SJohn Forte * Set to one of the following:
5088fcf3ce44SJohn Forte * PORT_CONNECTED
5089fcf3ce44SJohn Forte * PORT_NOTCONNECTED
5090fcf3ce44SJohn Forte * Returns: 0 on success
5091fcf3ce44SJohn Forte * non-zero on failure
5092fcf3ce44SJohn Forte */
5093fcf3ce44SJohn Forte int
g_get_port_state(char * portpath,int * portstate,int verbose)5094fcf3ce44SJohn Forte g_get_port_state(char *portpath, int *portstate, int verbose)
5095fcf3ce44SJohn Forte {
5096fcf3ce44SJohn Forte int fd, err, num_devices = 0;
5097fcf3ce44SJohn Forte struct lilpmap map;
5098fcf3ce44SJohn Forte uint_t dev_type;
5099fcf3ce44SJohn Forte gfc_dev_t map_root;
5100fcf3ce44SJohn Forte
5101fcf3ce44SJohn Forte
5102fcf3ce44SJohn Forte (void) memset(&map, 0, sizeof (struct lilpmap));
5103fcf3ce44SJohn Forte
5104fcf3ce44SJohn Forte /* return invalid path if portpath is NULL */
5105fcf3ce44SJohn Forte if (portpath == NULL) {
5106fcf3ce44SJohn Forte return (L_INVALID_PATH);
5107fcf3ce44SJohn Forte }
5108fcf3ce44SJohn Forte /* return invalid arg if argument is NULL */
5109fcf3ce44SJohn Forte if ((portpath == NULL) || (portstate == NULL)) {
5110fcf3ce44SJohn Forte return (L_INVALID_ARG);
5111fcf3ce44SJohn Forte }
5112fcf3ce44SJohn Forte
5113fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(portpath)) == 0) {
5114fcf3ce44SJohn Forte return (L_INVALID_PATH);
5115fcf3ce44SJohn Forte }
5116fcf3ce44SJohn Forte
5117fcf3ce44SJohn Forte /*
5118fcf3ce44SJohn Forte * FCIO_GETMAP returns error when there are * no devices attached.
5119fcf3ce44SJohn Forte * ENOMEM is returned when no devices are attached.
5120fcf3ce44SJohn Forte * g_get_first_dev returns NULL without error when there is no
5121fcf3ce44SJohn Forte * devices are attached.
5122fcf3ce44SJohn Forte */
5123fcf3ce44SJohn Forte if (dev_type & FC_FCA_MASK) {
5124fcf3ce44SJohn Forte if ((map_root = g_dev_map_init(portpath, &err,
5125063d642aSBill Gumbrell MAP_XPORT_PROP_ONLY)) == NULL) {
5126fcf3ce44SJohn Forte return (err);
5127fcf3ce44SJohn Forte }
5128fcf3ce44SJohn Forte
5129fcf3ce44SJohn Forte if (g_get_first_dev(map_root, &err) == NULL) {
5130fcf3ce44SJohn Forte /* no device is found if err == 0 */
5131fcf3ce44SJohn Forte if (err == L_NO_SUCH_DEV_FOUND) {
5132fcf3ce44SJohn Forte *portstate = PORT_NOTCONNECTED;
5133fcf3ce44SJohn Forte }
5134fcf3ce44SJohn Forte g_dev_map_fini(map_root);
5135fcf3ce44SJohn Forte return (0);
5136fcf3ce44SJohn Forte } else {
5137fcf3ce44SJohn Forte /* Device found okay */
5138fcf3ce44SJohn Forte *portstate = PORT_CONNECTED;
5139fcf3ce44SJohn Forte g_dev_map_fini(map_root);
5140fcf3ce44SJohn Forte }
5141fcf3ce44SJohn Forte
5142fcf3ce44SJohn Forte } else {
5143fcf3ce44SJohn Forte /* open controller */
5144fcf3ce44SJohn Forte if ((fd = g_object_open(portpath, O_NDELAY | O_RDONLY)) == -1) {
5145fcf3ce44SJohn Forte return (errno);
5146fcf3ce44SJohn Forte }
5147fcf3ce44SJohn Forte
5148fcf3ce44SJohn Forte /*
5149fcf3ce44SJohn Forte * Note: There is only one error returned by this ioctl. ENOMEM.
5150fcf3ce44SJohn Forte * Hence the lack of return on error.
5151fcf3ce44SJohn Forte */
5152fcf3ce44SJohn Forte if (ioctl(fd, FCIO_GETMAP, &map) != 0) {
5153fcf3ce44SJohn Forte map.lilp_length = 0;
5154fcf3ce44SJohn Forte }
5155fcf3ce44SJohn Forte num_devices = map.lilp_length;
5156fcf3ce44SJohn Forte
5157fcf3ce44SJohn Forte /* Non-Leadville stacks report the FCA in the count */
5158fcf3ce44SJohn Forte *portstate = (num_devices > 1) ? PORT_CONNECTED :
5159063d642aSBill Gumbrell PORT_NOTCONNECTED;
5160fcf3ce44SJohn Forte (void) close(fd);
5161fcf3ce44SJohn Forte }
5162fcf3ce44SJohn Forte return (0);
5163fcf3ce44SJohn Forte }
5164fcf3ce44SJohn Forte
5165fcf3ce44SJohn Forte /*
5166fcf3ce44SJohn Forte * g_dev_login(char *port_path, la_wwn_t port_wwn)
5167fcf3ce44SJohn Forte * Purpose: port login via g_dev_log_in_out()
5168fcf3ce44SJohn Forte * Input: port_path
5169fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology
5170fcf3ce44SJohn Forte * port_wwn
5171fcf3ce44SJohn Forte * port wwn of device node to login
5172fcf3ce44SJohn Forte *
5173fcf3ce44SJohn Forte * Returns: return code from g_dev_log_in_out()
5174fcf3ce44SJohn Forte */
5175fcf3ce44SJohn Forte int
g_dev_login(char * port_path,la_wwn_t port_wwn)5176fcf3ce44SJohn Forte g_dev_login(char *port_path, la_wwn_t port_wwn)
5177fcf3ce44SJohn Forte {
5178fcf3ce44SJohn Forte return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGIN));
5179fcf3ce44SJohn Forte }
5180fcf3ce44SJohn Forte
5181fcf3ce44SJohn Forte
5182fcf3ce44SJohn Forte /*
5183fcf3ce44SJohn Forte * g_dev_logout(char *port_path, la_wwn_t port_wwn)
5184fcf3ce44SJohn Forte * Purpose: port login via g_dev_log_in_out()
5185fcf3ce44SJohn Forte * Input: port_path
5186fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology
5187fcf3ce44SJohn Forte * port_wwn
5188fcf3ce44SJohn Forte * port wwn of device node to logout
5189fcf3ce44SJohn Forte *
5190fcf3ce44SJohn Forte * Returns: return code from g_dev_log_in_out()
5191fcf3ce44SJohn Forte */
5192fcf3ce44SJohn Forte int
g_dev_logout(char * port_path,la_wwn_t port_wwn)5193fcf3ce44SJohn Forte g_dev_logout(char *port_path, la_wwn_t port_wwn)
5194fcf3ce44SJohn Forte {
5195fcf3ce44SJohn Forte return (g_dev_log_in_out(port_path, port_wwn, FCIO_DEV_LOGOUT));
5196fcf3ce44SJohn Forte }
5197fcf3ce44SJohn Forte
5198fcf3ce44SJohn Forte
5199fcf3ce44SJohn Forte /*
5200fcf3ce44SJohn Forte * g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd)
5201fcf3ce44SJohn Forte * Purpose: port login via FCIO_DEV_LOGOUT and port logout via FCIO_DEV_LOGOUT
5202fcf3ce44SJohn Forte * IOCTL requires EXCLUSIVE open.
5203fcf3ce44SJohn Forte * Input: port_path
5204fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology
5205fcf3ce44SJohn Forte * port_wwn
5206fcf3ce44SJohn Forte * port wwn of device node to logout
5207fcf3ce44SJohn Forte * cmd
5208fcf3ce44SJohn Forte * FCIO_DEV_LOGON or FCIO_DEV_LOGOUT
5209fcf3ce44SJohn Forte *
5210fcf3ce44SJohn Forte * Returns: 0 on success
5211fcf3ce44SJohn Forte * non-zero on failure
5212fcf3ce44SJohn Forte */
5213fcf3ce44SJohn Forte static int
g_dev_log_in_out(char * port_path,la_wwn_t port_wwn,uint16_t cmd)5214fcf3ce44SJohn Forte g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd)
5215fcf3ce44SJohn Forte {
5216063d642aSBill Gumbrell int fd, err;
5217063d642aSBill Gumbrell uint32_t hba_port_top;
5218063d642aSBill Gumbrell fcio_t fcio;
5219063d642aSBill Gumbrell int verbose = 0;
5220fcf3ce44SJohn Forte
5221fcf3ce44SJohn Forte if ((err = g_get_fca_port_topology(port_path,
5222063d642aSBill Gumbrell &hba_port_top, verbose)) != 0) {
5223fcf3ce44SJohn Forte return (err);
5224fcf3ce44SJohn Forte }
5225fcf3ce44SJohn Forte
5226fcf3ce44SJohn Forte if (!((hba_port_top == FC_TOP_PUBLIC_LOOP) ||
5227063d642aSBill Gumbrell (hba_port_top == FC_TOP_FABRIC))) {
5228fcf3ce44SJohn Forte return (L_OPNOSUPP_ON_TOPOLOGY);
5229fcf3ce44SJohn Forte }
5230fcf3ce44SJohn Forte
5231fcf3ce44SJohn Forte /* open controller */
5232fcf3ce44SJohn Forte if ((fd = g_object_open(port_path, O_NDELAY | O_RDONLY | O_EXCL)) == -1)
5233fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
5234fcf3ce44SJohn Forte
5235fcf3ce44SJohn Forte /*
5236fcf3ce44SJohn Forte * stores port_wwn to la_wwn_t raw_wwn field
5237fcf3ce44SJohn Forte * and construct fcio structures for FCIO_DEV_LOGIN.
5238fcf3ce44SJohn Forte */
5239fcf3ce44SJohn Forte fcio.fcio_cmd = cmd;
5240fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (port_wwn);
5241fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&port_wwn;
5242fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE;
5243fcf3ce44SJohn Forte fcio.fcio_olen = fcio.fcio_alen = 0;
5244fcf3ce44SJohn Forte fcio.fcio_obuf = fcio.fcio_abuf = NULL;
5245fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
5246fcf3ce44SJohn Forte I_DPRINTF((cmd == FCIO_DEV_LOGIN) ?
5247063d642aSBill Gumbrell " FCIO_DEV_LOGIN ioctl failed.\n"
5248063d642aSBill Gumbrell : " FCIO_DEV_LOGOUT ioctl failed.\n");
5249fcf3ce44SJohn Forte (void) close(fd);
5250fcf3ce44SJohn Forte return ((cmd == FCIO_DEV_LOGIN) ?
5251063d642aSBill Gumbrell L_FCIO_DEV_LOGIN_FAIL
5252063d642aSBill Gumbrell : L_FCIO_DEV_LOGOUT_FAIL);
5253fcf3ce44SJohn Forte } else {
5254fcf3ce44SJohn Forte (void) close(fd);
5255fcf3ce44SJohn Forte return (0);
5256fcf3ce44SJohn Forte }
5257fcf3ce44SJohn Forte }
5258fcf3ce44SJohn Forte
5259fcf3ce44SJohn Forte /*
5260fcf3ce44SJohn Forte * This function will verify if a FC device (represented by input WWN
5261fcf3ce44SJohn Forte * is connected on a FCA port by searching the device list from
5262fcf3ce44SJohn Forte * g_get_dev_list() for a WWN match.
5263fcf3ce44SJohn Forte *
5264fcf3ce44SJohn Forte * input:
5265fcf3ce44SJohn Forte * fca_path: pointer to the physical path string, path to a fp node.
5266fcf3ce44SJohn Forte * possible forms are
5267fcf3ce44SJohn Forte * /devices/pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0:devctl
5268fcf3ce44SJohn Forte * dev_wwn: WWN string
5269fcf3ce44SJohn Forte * flag: indicate that the input WWN is node or port
5270fcf3ce44SJohn Forte *
5271fcf3ce44SJohn Forte * returned values
5272fcf3ce44SJohn Forte * 0: if a match is found.
5273fcf3ce44SJohn Forte * L_WWN_NOT_FOUND_IN_DEV_LIST: if no match found
5274fcf3ce44SJohn Forte * L_UNEXPECTED_FC_TOPOLOGY: existing error code for an error
5275fcf3ce44SJohn Forte * from the topology checking of the input fca path.
5276fcf3ce44SJohn Forte * L_MALLOC_FAILED: existing error code for allocation eror from the
5277fcf3ce44SJohn Forte * g_get_dev_list().
5278fcf3ce44SJohn Forte * L_FCIO_GETMAP_IOCTL_FAIL: existing error code for an error from the
5279fcf3ce44SJohn Forte * FCIO ioctl called by the g_get_dev_list()
5280fcf3ce44SJohn Forte * -1: other failure
5281fcf3ce44SJohn Forte *
5282fcf3ce44SJohn Forte */
5283fcf3ce44SJohn Forte int
g_wwn_in_dev_list(char * fca_path,la_wwn_t dev_wwn,int flag)5284fcf3ce44SJohn Forte g_wwn_in_dev_list(char *fca_path, la_wwn_t dev_wwn, int flag)
5285fcf3ce44SJohn Forte {
5286063d642aSBill Gumbrell uint_t dev_type;
5287063d642aSBill Gumbrell int i, err;
5288063d642aSBill Gumbrell fc_port_dev_t *dev_list;
5289063d642aSBill Gumbrell fc_port_dev_t *dev_list_save;
5290063d642aSBill Gumbrell int num_devices = 0;
5291fcf3ce44SJohn Forte
5292fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fca_path)) == 0) {
5293fcf3ce44SJohn Forte return (L_INVALID_PATH);
5294fcf3ce44SJohn Forte }
5295fcf3ce44SJohn Forte
5296fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) {
5297fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
5298fcf3ce44SJohn Forte }
5299fcf3ce44SJohn Forte
5300fcf3ce44SJohn Forte if (((err = g_get_dev_list(fca_path, &dev_list, &num_devices))
5301063d642aSBill Gumbrell != 0) && (err != L_GET_DEV_LIST_ULP_FAILURE)) {
5302fcf3ce44SJohn Forte return (err);
5303fcf3ce44SJohn Forte }
5304fcf3ce44SJohn Forte
5305fcf3ce44SJohn Forte dev_list_save = dev_list;
5306fcf3ce44SJohn Forte
5307fcf3ce44SJohn Forte switch (flag) {
5308fcf3ce44SJohn Forte case MATCH_NODE_WWN:
5309fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_list++) {
5310fcf3ce44SJohn Forte if (memcmp(dev_list->dev_nwwn.raw_wwn,
5311063d642aSBill Gumbrell dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) {
5312fcf3ce44SJohn Forte (void) free(dev_list_save);
5313fcf3ce44SJohn Forte return (0);
5314fcf3ce44SJohn Forte }
5315fcf3ce44SJohn Forte }
5316fcf3ce44SJohn Forte (void) free(dev_list_save);
5317fcf3ce44SJohn Forte /* consider a new error code for not found. */
5318fcf3ce44SJohn Forte return (L_WWN_NOT_FOUND_IN_DEV_LIST);
5319fcf3ce44SJohn Forte
5320fcf3ce44SJohn Forte case MATCH_PORT_WWN:
5321fcf3ce44SJohn Forte for (i = 0; i < num_devices; i++, dev_list++) {
5322fcf3ce44SJohn Forte if (memcmp(dev_list->dev_pwwn.raw_wwn,
5323063d642aSBill Gumbrell dev_wwn.raw_wwn, FC_WWN_SIZE) == 0) {
5324fcf3ce44SJohn Forte (void) free(dev_list_save);
5325fcf3ce44SJohn Forte return (0);
5326fcf3ce44SJohn Forte }
5327fcf3ce44SJohn Forte }
5328fcf3ce44SJohn Forte (void) free(dev_list_save);
5329fcf3ce44SJohn Forte /* consider a new error code for not found. */
5330fcf3ce44SJohn Forte return (L_WWN_NOT_FOUND_IN_DEV_LIST);
5331fcf3ce44SJohn Forte }
5332fcf3ce44SJohn Forte (void) free(dev_list_save);
5333fcf3ce44SJohn Forte return (-1);
5334fcf3ce44SJohn Forte }
5335fcf3ce44SJohn Forte
5336fcf3ce44SJohn Forte
5337fcf3ce44SJohn Forte /*
5338fcf3ce44SJohn Forte * g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state)
5339fcf3ce44SJohn Forte * Purpose: get the state of device port login via FCIO_GET_STATE ioctl.
5340fcf3ce44SJohn Forte *
5341fcf3ce44SJohn Forte * Input: fca_path
5342fcf3ce44SJohn Forte * fc transport port with fabric/public loop topology
5343fcf3ce44SJohn Forte * port_wwn
5344fcf3ce44SJohn Forte * port wwn of device node to logout
5345fcf3ce44SJohn Forte * state
5346fcf3ce44SJohn Forte * port login or not
5347fcf3ce44SJohn Forte *
5348fcf3ce44SJohn Forte * Returns: 0 on success
5349fcf3ce44SJohn Forte * non-zero on failure
5350fcf3ce44SJohn Forte */
5351fcf3ce44SJohn Forte static int
g_get_dev_port_state(char * fca_path,la_wwn_t port_wwn,uint32_t * state)5352fcf3ce44SJohn Forte g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state)
5353fcf3ce44SJohn Forte {
5354063d642aSBill Gumbrell int fd;
5355063d642aSBill Gumbrell int dev_type;
5356063d642aSBill Gumbrell fcio_t fcio;
5357063d642aSBill Gumbrell int verbose = 0;
5358fcf3ce44SJohn Forte
5359fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(fca_path)) == 0) {
5360fcf3ce44SJohn Forte return (L_INVALID_PATH);
5361fcf3ce44SJohn Forte }
5362fcf3ce44SJohn Forte
5363fcf3ce44SJohn Forte if (!(dev_type & FC_XPORT_MASK)) {
5364fcf3ce44SJohn Forte return (L_INVALID_PATH_TYPE);
5365fcf3ce44SJohn Forte }
5366fcf3ce44SJohn Forte
5367fcf3ce44SJohn Forte /* open controller */
5368fcf3ce44SJohn Forte if ((fd = g_object_open(fca_path, O_NDELAY | O_RDONLY)) == -1)
5369fcf3ce44SJohn Forte return (L_OPEN_PATH_FAIL);
5370fcf3ce44SJohn Forte
5371fcf3ce44SJohn Forte /*
5372fcf3ce44SJohn Forte * stores port_wwn to la_wwn_t raw_wwn field
5373fcf3ce44SJohn Forte * and construct fcio structures for FCIO_DEV_LOGIN.
5374fcf3ce44SJohn Forte */
5375fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_STATE;
5376fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (port_wwn);
5377fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&port_wwn;
5378fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ | FCIO_XFER_WRITE;
5379fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t);
5380fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)state;
5381fcf3ce44SJohn Forte fcio.fcio_alen = 0;
5382fcf3ce44SJohn Forte fcio.fcio_abuf = NULL;
5383fcf3ce44SJohn Forte if (g_issue_fcio_ioctl(fd, &fcio, verbose) != 0) {
5384fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_STATE ioctl failed.\n");
5385fcf3ce44SJohn Forte (void) close(fd);
5386fcf3ce44SJohn Forte return (L_FCIO_GET_STATE_FAIL);
5387fcf3ce44SJohn Forte } else {
5388fcf3ce44SJohn Forte (void) close(fd);
5389fcf3ce44SJohn Forte return (0);
5390fcf3ce44SJohn Forte }
5391fcf3ce44SJohn Forte }
5392fcf3ce44SJohn Forte
5393fcf3ce44SJohn Forte /*
5394fcf3ce44SJohn Forte * Name: lilp_map_cmp
5395fcf3ce44SJohn Forte *
5396fcf3ce44SJohn Forte * Description: This function is used to compare the physical location
5397fcf3ce44SJohn Forte * of to fc devices in a gfc_map_t.dev_addr arrary.
5398fcf3ce44SJohn Forte *
5399fcf3ce44SJohn Forte * Params:
5400fcf3ce44SJohn Forte * First device to compare
5401fcf3ce44SJohn Forte * Second device to compare
5402fcf3ce44SJohn Forte *
5403fcf3ce44SJohn Forte * Return:
5404fcf3ce44SJohn Forte * 0 = Devices at equal phyiscal location, How did this happen?
5405fcf3ce44SJohn Forte * >0 = First device have a higher physical location than second
5406fcf3ce44SJohn Forte * <0 = Second device have a higher physical location than first
5407fcf3ce44SJohn Forte */
lilp_map_cmp(const void * dev1,const void * dev2)5408fcf3ce44SJohn Forte static int lilp_map_cmp(const void* dev1, const void* dev2) {
5409fcf3ce44SJohn Forte int i_dev1 = ((fc_port_dev_t *)dev1)->dev_did.priv_lilp_posit;
5410fcf3ce44SJohn Forte int i_dev2 = ((fc_port_dev_t *)dev2)->dev_did.priv_lilp_posit;
5411fcf3ce44SJohn Forte
5412fcf3ce44SJohn Forte if (i_dev1 > i_dev2)
5413fcf3ce44SJohn Forte return (1);
5414fcf3ce44SJohn Forte if (i_dev1 < i_dev2)
5415fcf3ce44SJohn Forte return (-1);
5416fcf3ce44SJohn Forte return (0);
5417fcf3ce44SJohn Forte }
5418fcf3ce44SJohn Forte
5419fcf3ce44SJohn Forte /*
5420fcf3ce44SJohn Forte * Description:
5421fcf3ce44SJohn Forte * Retrieves multiple paths to a device based on devid
5422fcf3ce44SJohn Forte * Caller must use mplist_free to free mplist structure
5423fcf3ce44SJohn Forte * This currently only supports ssd devices.
5424fcf3ce44SJohn Forte * The st driver does not register a device id.
5425fcf3ce44SJohn Forte *
5426fcf3ce44SJohn Forte * Input Values:
5427fcf3ce44SJohn Forte *
5428fcf3ce44SJohn Forte * devid: ptr to valid ddi_devid_t struct
5429fcf3ce44SJohn Forte * root: root handle to device tree snapshot
5430fcf3ce44SJohn Forte * drvr_name: driver name to start the node tree search
5431fcf3ce44SJohn Forte *
5432fcf3ce44SJohn Forte * Return Value:
5433fcf3ce44SJohn Forte * 0 on success
5434fcf3ce44SJohn Forte * non-zero on failure
5435fcf3ce44SJohn Forte */
5436fcf3ce44SJohn Forte
5437fcf3ce44SJohn Forte static int
devid_get_all(ddi_devid_t devid,di_node_t root,char * drvr_name,struct mplist_struct ** mplistp)5438fcf3ce44SJohn Forte devid_get_all(ddi_devid_t devid, di_node_t root, char *drvr_name,
5439063d642aSBill Gumbrell struct mplist_struct **mplistp)
5440fcf3ce44SJohn Forte {
5441063d642aSBill Gumbrell ddi_devid_t mydevid;
5442063d642aSBill Gumbrell di_node_t node;
5443063d642aSBill Gumbrell char *devfs_path = NULL;
5444063d642aSBill Gumbrell struct mplist_struct *mpl, *mpln;
5445fcf3ce44SJohn Forte
5446fcf3ce44SJohn Forte if (devid == NULL || root == NULL || drvr_name == NULL ||
5447063d642aSBill Gumbrell mplistp == NULL ||
5448063d642aSBill Gumbrell (strncmp(drvr_name, SSD_DRVR_NAME, strlen(SSD_DRVR_NAME))
5449063d642aSBill Gumbrell != 0)) {
5450fcf3ce44SJohn Forte return (EINVAL);
5451fcf3ce44SJohn Forte }
5452fcf3ce44SJohn Forte
5453fcf3ce44SJohn Forte *mplistp = mpl = mpln = (struct mplist_struct *)NULL;
5454fcf3ce44SJohn Forte
5455fcf3ce44SJohn Forte /* point to first node which matches portdrvr */
5456fcf3ce44SJohn Forte node = di_drv_first_node(drvr_name, root);
5457fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
5458fcf3ce44SJohn Forte return (L_NO_DRIVER_NODES_FOUND);
5459fcf3ce44SJohn Forte }
5460fcf3ce44SJohn Forte
5461fcf3ce44SJohn Forte while (node != DI_NODE_NIL) {
5462fcf3ce44SJohn Forte if ((mydevid = di_devid(node)) != NULL) {
5463fcf3ce44SJohn Forte if (((devid_compare(mydevid, devid)) == 0)) {
5464063d642aSBill Gumbrell /* Load multipath list */
5465063d642aSBill Gumbrell if ((mpl = (struct mplist_struct *)
5466063d642aSBill Gumbrell calloc(1, sizeof (struct mplist_struct)))
5467063d642aSBill Gumbrell == NULL) {
5468063d642aSBill Gumbrell mplist_free(*mplistp);
5469063d642aSBill Gumbrell return (L_MALLOC_FAILED);
5470063d642aSBill Gumbrell }
5471063d642aSBill Gumbrell if ((devfs_path = my_devfs_path(node)) ==
5472063d642aSBill Gumbrell NULL) {
5473063d642aSBill Gumbrell node = di_drv_next_node(node);
5474063d642aSBill Gumbrell S_FREE(mpl);
5475063d642aSBill Gumbrell continue;
5476063d642aSBill Gumbrell }
5477063d642aSBill Gumbrell mpl->devpath = (char *)calloc(1,
5478063d642aSBill Gumbrell strlen(devfs_path) +
5479063d642aSBill Gumbrell strlen(SSD_MINOR_NAME) + 1);
5480063d642aSBill Gumbrell if (mpl->devpath == NULL) {
5481063d642aSBill Gumbrell S_FREE(mpl);
5482063d642aSBill Gumbrell mplist_free(*mplistp);
5483063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5484063d642aSBill Gumbrell return (L_MALLOC_FAILED);
5485063d642aSBill Gumbrell }
5486063d642aSBill Gumbrell sprintf(mpl->devpath, "%s%s", devfs_path,
5487063d642aSBill Gumbrell SSD_MINOR_NAME);
5488063d642aSBill Gumbrell if (*mplistp == NULL) {
5489063d642aSBill Gumbrell *mplistp = mpln = mpl;
5490063d642aSBill Gumbrell } else {
5491063d642aSBill Gumbrell mpln->next = mpl;
5492063d642aSBill Gumbrell mpln = mpl;
5493063d642aSBill Gumbrell }
5494fcf3ce44SJohn Forte my_devfs_path_free(devfs_path);
5495fcf3ce44SJohn Forte }
5496fcf3ce44SJohn Forte }
5497fcf3ce44SJohn Forte node = di_drv_next_node(node);
5498fcf3ce44SJohn Forte }
5499fcf3ce44SJohn Forte return (0);
5500fcf3ce44SJohn Forte }
5501fcf3ce44SJohn Forte
5502fcf3ce44SJohn Forte /*
5503fcf3ce44SJohn Forte * Frees a previously allocated mplist_struct
5504fcf3ce44SJohn Forte */
5505fcf3ce44SJohn Forte static void
mplist_free(struct mplist_struct * mplistp)5506fcf3ce44SJohn Forte mplist_free(struct mplist_struct *mplistp)
5507fcf3ce44SJohn Forte {
5508063d642aSBill Gumbrell struct mplist_struct *mplistn;
5509fcf3ce44SJohn Forte
5510fcf3ce44SJohn Forte while (mplistp != NULL) {
5511fcf3ce44SJohn Forte mplistn = mplistp->next;
5512fcf3ce44SJohn Forte if (mplistp->devpath != NULL) {
5513fcf3ce44SJohn Forte free(mplistp->devpath);
5514fcf3ce44SJohn Forte mplistp->devpath = NULL;
5515fcf3ce44SJohn Forte }
5516fcf3ce44SJohn Forte free(mplistp);
5517fcf3ce44SJohn Forte mplistp = mplistn;
5518fcf3ce44SJohn Forte }
5519fcf3ce44SJohn Forte }
5520fcf3ce44SJohn Forte
5521fcf3ce44SJohn Forte /*
5522fcf3ce44SJohn Forte * Description
5523fcf3ce44SJohn Forte * Retrieves all device nodes based on drvr_name
5524fcf3ce44SJohn Forte * Currently supports SSD_DRVR_NAME, ST_DRVR_NAME
5525fcf3ce44SJohn Forte * There will be a device node in the libdevinfo
5526fcf3ce44SJohn Forte * snapshot only if there is at least one node bound.
5527fcf3ce44SJohn Forte *
5528fcf3ce44SJohn Forte * Input values:
5529fcf3ce44SJohn Forte * root valid snapshot handle from di_init(3DEVINFO)
5530fcf3ce44SJohn Forte * drvr_name name of driver to start node search
5531fcf3ce44SJohn Forte * wwn_list_ptr ptr to ptr to WWN_list struct
5532fcf3ce44SJohn Forte *
5533fcf3ce44SJohn Forte *
5534fcf3ce44SJohn Forte */
5535fcf3ce44SJohn Forte static int
devices_get_all(di_node_t root,char * drvr_name,char * minor_name,struct wwn_list_struct ** wwn_list_ptr)5536fcf3ce44SJohn Forte devices_get_all(di_node_t root, char *drvr_name, char *minor_name,
5537063d642aSBill Gumbrell struct wwn_list_struct **wwn_list_ptr)
5538fcf3ce44SJohn Forte {
5539063d642aSBill Gumbrell di_node_t node;
5540063d642aSBill Gumbrell char *devfs_path;
5541063d642aSBill Gumbrell char devicepath[MAXPATHLEN];
5542063d642aSBill Gumbrell uchar_t *nwwn = NULL, *pwwn = NULL;
5543063d642aSBill Gumbrell uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
5544063d642aSBill Gumbrell WWN_list *wwn_list, *l1, *l2;
5545063d642aSBill Gumbrell int scsi_vhci = 0;
5546063d642aSBill Gumbrell int err, devtype;
5547fcf3ce44SJohn Forte
5548fcf3ce44SJohn Forte if (root == DI_NODE_NIL || drvr_name == NULL ||
5549063d642aSBill Gumbrell wwn_list_ptr == NULL) {
5550fcf3ce44SJohn Forte return (EINVAL);
5551fcf3ce44SJohn Forte }
5552fcf3ce44SJohn Forte
5553fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr = NULL;
5554fcf3ce44SJohn Forte
5555fcf3ce44SJohn Forte memset(port_wwn, 0, sizeof (port_wwn));
5556fcf3ce44SJohn Forte memset(node_wwn, 0, sizeof (node_wwn));
5557fcf3ce44SJohn Forte
5558fcf3ce44SJohn Forte if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) {
5559fcf3ce44SJohn Forte devtype = DTYPE_DIRECT;
5560fcf3ce44SJohn Forte } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) {
5561fcf3ce44SJohn Forte devtype = DTYPE_SEQUENTIAL;
5562fcf3ce44SJohn Forte } else {
5563fcf3ce44SJohn Forte /*
5564fcf3ce44SJohn Forte * An unsupported driver name was passed in
5565fcf3ce44SJohn Forte */
5566fcf3ce44SJohn Forte return (L_DRIVER_NOTSUPP);
5567fcf3ce44SJohn Forte }
5568fcf3ce44SJohn Forte
5569fcf3ce44SJohn Forte /* point to first node which matches portdrvr */
5570fcf3ce44SJohn Forte node = di_drv_first_node(drvr_name, root);
5571fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
5572fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
5573fcf3ce44SJohn Forte }
5574fcf3ce44SJohn Forte
5575fcf3ce44SJohn Forte while (node != DI_NODE_NIL) {
5576fcf3ce44SJohn Forte
5577063d642aSBill Gumbrell if ((devfs_path = my_devfs_path(node)) != NULL) {
5578fcf3ce44SJohn Forte
5579063d642aSBill Gumbrell /*
5580063d642aSBill Gumbrell * Check for offline state
5581063d642aSBill Gumbrell */
5582063d642aSBill Gumbrell if ((di_state(node) &
5583063d642aSBill Gumbrell DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE) {
5584063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5585063d642aSBill Gumbrell node = di_drv_next_node(node);
5586063d642aSBill Gumbrell continue;
5587063d642aSBill Gumbrell }
5588fcf3ce44SJohn Forte
5589063d642aSBill Gumbrell /*
5590063d642aSBill Gumbrell * Only support st, ssd nodes
5591063d642aSBill Gumbrell */
5592063d642aSBill Gumbrell if (!strstr(devfs_path, SLSH_DRV_NAME_SSD) &&
5593063d642aSBill Gumbrell !strstr(devfs_path, SLSH_DRV_NAME_ST)) {
5594063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5595063d642aSBill Gumbrell node = di_drv_next_node(node);
5596063d642aSBill Gumbrell continue;
5597063d642aSBill Gumbrell }
5598fcf3ce44SJohn Forte
5599063d642aSBill Gumbrell devicepath[0] = '\0';
5600fcf3ce44SJohn Forte
5601063d642aSBill Gumbrell /*
5602063d642aSBill Gumbrell * form device path
5603063d642aSBill Gumbrell */
5604063d642aSBill Gumbrell sprintf(devicepath, "%s%s", devfs_path, minor_name);
5605fcf3ce44SJohn Forte
5606063d642aSBill Gumbrell if ((strstr(devicepath, SCSI_VHCI) == NULL)) {
5607063d642aSBill Gumbrell if ((err = get_wwn_data(node, &nwwn, &pwwn)) !=
5608063d642aSBill Gumbrell 0) {
5609063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5610063d642aSBill Gumbrell return (err);
5611063d642aSBill Gumbrell } else {
5612063d642aSBill Gumbrell memcpy(node_wwn, nwwn,
5613063d642aSBill Gumbrell sizeof (node_wwn));
5614063d642aSBill Gumbrell memcpy(port_wwn, pwwn,
5615063d642aSBill Gumbrell sizeof (port_wwn));
5616063d642aSBill Gumbrell }
5617fcf3ce44SJohn Forte } else {
5618063d642aSBill Gumbrell /*
5619063d642aSBill Gumbrell * Clear values for SCSI VHCI devices.
5620063d642aSBill Gumbrell * node wwn, port wwn are irrevelant at
5621063d642aSBill Gumbrell * the SCSI VHCI level
5622063d642aSBill Gumbrell */
5623063d642aSBill Gumbrell scsi_vhci++;
5624063d642aSBill Gumbrell memset(port_wwn, 0, sizeof (port_wwn));
5625063d642aSBill Gumbrell memset(node_wwn, 0, sizeof (node_wwn));
5626fcf3ce44SJohn Forte }
5627fcf3ce44SJohn Forte
5628063d642aSBill Gumbrell /* Got wwns, load data in list */
5629063d642aSBill Gumbrell if ((l2 = (struct wwn_list_struct *)
5630063d642aSBill Gumbrell calloc(1, sizeof (struct wwn_list_struct))) ==
5631063d642aSBill Gumbrell NULL) {
5632063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5633063d642aSBill Gumbrell return (L_MALLOC_FAILED);
5634063d642aSBill Gumbrell }
5635063d642aSBill Gumbrell if ((l2->physical_path = (char *)
5636063d642aSBill Gumbrell calloc(1, strlen(devicepath) +1)) == NULL) {
5637063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5638063d642aSBill Gumbrell return (L_MALLOC_FAILED);
5639063d642aSBill Gumbrell }
5640fcf3ce44SJohn Forte
5641063d642aSBill Gumbrell memcpy(l2->w_node_wwn, node_wwn, WWN_SIZE);
5642fcf3ce44SJohn Forte
5643063d642aSBill Gumbrell if (scsi_vhci) {
5644063d642aSBill Gumbrell strcpy(l2->node_wwn_s, MSGSTR(12000, "N/A"));
5645063d642aSBill Gumbrell } else {
5646063d642aSBill Gumbrell copy_wwn_data_to_str(l2->node_wwn_s, node_wwn);
5647063d642aSBill Gumbrell copy_wwn_data_to_str(l2->port_wwn_s, port_wwn);
5648063d642aSBill Gumbrell }
5649fcf3ce44SJohn Forte
5650063d642aSBill Gumbrell strcpy(l2->physical_path, devicepath);
5651fcf3ce44SJohn Forte
5652063d642aSBill Gumbrell l2->device_type = devtype;
5653063d642aSBill Gumbrell if (wwn_list == NULL) {
5654063d642aSBill Gumbrell l1 = wwn_list = l2;
5655063d642aSBill Gumbrell } else {
5656063d642aSBill Gumbrell l2->wwn_prev = l1;
5657063d642aSBill Gumbrell l1 = l1->wwn_next = l2;
5658063d642aSBill Gumbrell }
5659063d642aSBill Gumbrell my_devfs_path_free(devfs_path);
5660063d642aSBill Gumbrell scsi_vhci = 0;
5661fcf3ce44SJohn Forte }
5662063d642aSBill Gumbrell node = di_drv_next_node(node);
5663fcf3ce44SJohn Forte }
5664fcf3ce44SJohn Forte
5665fcf3ce44SJohn Forte *wwn_list_ptr = wwn_list; /* pass back ptr to list */
5666fcf3ce44SJohn Forte
5667fcf3ce44SJohn Forte if (*wwn_list_ptr == NULL) {
5668fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
5669fcf3ce44SJohn Forte } else {
5670fcf3ce44SJohn Forte /*
5671fcf3ce44SJohn Forte * Now load the /dev/ paths
5672fcf3ce44SJohn Forte */
5673fcf3ce44SJohn Forte if (strcmp(drvr_name, SSD_DRVR_NAME) == 0) {
5674fcf3ce44SJohn Forte if ((err = get_dev_path(wwn_list_ptr, DEV_RDIR,
5675063d642aSBill Gumbrell DIR_MATCH_SSD)) != 0) {
5676fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr);
5677fcf3ce44SJohn Forte return (err);
5678fcf3ce44SJohn Forte }
5679fcf3ce44SJohn Forte } else if (strcmp(drvr_name, ST_DRVR_NAME) == 0) {
5680fcf3ce44SJohn Forte if ((err = get_dev_path(wwn_list_ptr, DEV_TAPE_DIR,
5681063d642aSBill Gumbrell DIR_MATCH_ST)) != 0) {
5682fcf3ce44SJohn Forte g_free_wwn_list(wwn_list_ptr);
5683fcf3ce44SJohn Forte return (err);
5684fcf3ce44SJohn Forte }
5685fcf3ce44SJohn Forte }
5686fcf3ce44SJohn Forte return (0);
5687fcf3ce44SJohn Forte }
5688fcf3ce44SJohn Forte }
5689fcf3ce44SJohn Forte
5690fcf3ce44SJohn Forte
5691fcf3ce44SJohn Forte /*
5692fcf3ce44SJohn Forte * Access the properties for the node to get the node-wwn, port-wwn property
5693fcf3ce44SJohn Forte * On error, contents of nwwn, pwwn are unspecified.
5694fcf3ce44SJohn Forte * On successful return nwwn and pwwn are WWN_SIZE bytes.
5695fcf3ce44SJohn Forte */
5696fcf3ce44SJohn Forte static int
get_wwn_data(di_node_t node,uchar_t ** nwwn,uchar_t ** pwwn)5697fcf3ce44SJohn Forte get_wwn_data(di_node_t node, uchar_t **nwwn, uchar_t **pwwn)
5698fcf3ce44SJohn Forte {
5699fcf3ce44SJohn Forte if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP,
5700063d642aSBill Gumbrell nwwn) != WWN_SIZE) {
5701063d642aSBill Gumbrell /* If we didn't get back the right count, return error */
5702fcf3ce44SJohn Forte return (L_NO_WWN_PROP_FOUND);
5703fcf3ce44SJohn Forte }
5704fcf3ce44SJohn Forte if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, PORT_WWN_PROP,
5705063d642aSBill Gumbrell pwwn) != WWN_SIZE) {
5706063d642aSBill Gumbrell /* If we didn't get back the right count, return error */
5707fcf3ce44SJohn Forte return (L_NO_WWN_PROP_FOUND);
5708fcf3ce44SJohn Forte }
5709fcf3ce44SJohn Forte return (0);
5710fcf3ce44SJohn Forte }
5711fcf3ce44SJohn Forte
5712fcf3ce44SJohn Forte /*
5713fcf3ce44SJohn Forte * Description
5714fcf3ce44SJohn Forte * retrieves the /dev logical path for a WWN_list of devices.
5715fcf3ce44SJohn Forte * Input values
5716fcf3ce44SJohn Forte * wwn_list_ptr ptr to list returned by devices_get_all
5717fcf3ce44SJohn Forte * dir_name /dev/ directory to search
5718fcf3ce44SJohn Forte *
5719fcf3ce44SJohn Forte */
5720fcf3ce44SJohn Forte static int
get_dev_path(struct wwn_list_struct ** wwn_list_ptr,char * dir_name,char * pattern_match)5721fcf3ce44SJohn Forte get_dev_path(struct wwn_list_struct **wwn_list_ptr, char *dir_name,
5722063d642aSBill Gumbrell char *pattern_match)
5723fcf3ce44SJohn Forte {
5724063d642aSBill Gumbrell DIR *dirp;
5725063d642aSBill Gumbrell struct dirent *entp;
5726063d642aSBill Gumbrell char namebuf[MAXPATHLEN];
5727063d642aSBill Gumbrell char *result = NULL;
5728063d642aSBill Gumbrell WWN_list *wwn_list, *wwn_list_save;
5729063d642aSBill Gumbrell char *env;
5730063d642aSBill Gumbrell hrtime_t start_time, end_time;
5731fcf3ce44SJohn Forte
5732fcf3ce44SJohn Forte if (wwn_list_ptr == NULL || *wwn_list_ptr == NULL ||
5733063d642aSBill Gumbrell dir_name == NULL || pattern_match == NULL) {
5734fcf3ce44SJohn Forte return (EINVAL);
5735fcf3ce44SJohn Forte }
5736fcf3ce44SJohn Forte
5737fcf3ce44SJohn Forte if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
5738fcf3ce44SJohn Forte start_time = gethrtime();
5739fcf3ce44SJohn Forte }
5740fcf3ce44SJohn Forte
5741fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr;
5742fcf3ce44SJohn Forte
5743fcf3ce44SJohn Forte if ((dirp = opendir(dir_name)) == NULL) {
5744fcf3ce44SJohn Forte P_DPRINTF(" get_dev_path: No devices found\n");
5745fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
5746fcf3ce44SJohn Forte }
5747fcf3ce44SJohn Forte
5748fcf3ce44SJohn Forte while ((entp = readdir(dirp)) != NULL) {
5749fcf3ce44SJohn Forte /*
5750fcf3ce44SJohn Forte * Ignore current directory and parent directory
5751fcf3ce44SJohn Forte * entries.
5752fcf3ce44SJohn Forte */
5753fcf3ce44SJohn Forte if ((strcmp(entp->d_name, ".") == 0) ||
5754fcf3ce44SJohn Forte (strcmp(entp->d_name, "..") == 0) ||
5755fcf3ce44SJohn Forte (fnmatch(pattern_match, entp->d_name, 0) != 0))
5756fcf3ce44SJohn Forte continue;
5757fcf3ce44SJohn Forte
5758fcf3ce44SJohn Forte memset(namebuf, 0, sizeof (namebuf));
5759fcf3ce44SJohn Forte sprintf(namebuf, "%s/%s", dir_name, entp->d_name);
5760fcf3ce44SJohn Forte
5761fcf3ce44SJohn Forte if ((result = g_get_physical_name_from_link(namebuf)) == NULL) {
5762fcf3ce44SJohn Forte ER_DPRINTF(" Warning: Get physical name from"
5763063d642aSBill Gumbrell " link failed. Link=%s\n", namebuf);
5764fcf3ce44SJohn Forte continue;
5765fcf3ce44SJohn Forte }
5766fcf3ce44SJohn Forte for (wwn_list = *wwn_list_ptr; wwn_list != NULL;
5767fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next) {
5768063d642aSBill Gumbrell if (strcmp(wwn_list->physical_path, result) == 0) {
5769063d642aSBill Gumbrell /*
5770063d642aSBill Gumbrell * Add information to the list.
5771063d642aSBill Gumbrell */
5772063d642aSBill Gumbrell if ((wwn_list->logical_path = (char *)
5773063d642aSBill Gumbrell calloc(1, strlen(namebuf) + 1)) == NULL) {
5774063d642aSBill Gumbrell free(result);
5775063d642aSBill Gumbrell return (L_MALLOC_FAILED);
5776063d642aSBill Gumbrell }
5777063d642aSBill Gumbrell strcpy(wwn_list->logical_path, namebuf);
5778063d642aSBill Gumbrell break;
5779fcf3ce44SJohn Forte }
5780fcf3ce44SJohn Forte }
5781fcf3ce44SJohn Forte free(result);
5782fcf3ce44SJohn Forte }
5783fcf3ce44SJohn Forte closedir(dirp);
5784fcf3ce44SJohn Forte
5785fcf3ce44SJohn Forte /*
5786fcf3ce44SJohn Forte * Did we load all of the paths?
5787fcf3ce44SJohn Forte * Note: if there is a missing entry in /dev then
5788fcf3ce44SJohn Forte * the user probably did a cleanup of /dev.
5789fcf3ce44SJohn Forte * Whatever the case, remove the entry as it
5790fcf3ce44SJohn Forte * is invalid.
5791fcf3ce44SJohn Forte */
5792fcf3ce44SJohn Forte wwn_list = *wwn_list_ptr;
5793fcf3ce44SJohn Forte while (wwn_list != NULL) {
5794fcf3ce44SJohn Forte if (wwn_list->logical_path == NULL) {
5795fcf3ce44SJohn Forte free(wwn_list->physical_path);
5796fcf3ce44SJohn Forte wwn_list_save = wwn_list;
5797fcf3ce44SJohn Forte if (wwn_list->wwn_prev != NULL) {
5798fcf3ce44SJohn Forte wwn_list->wwn_prev->wwn_next =
5799063d642aSBill Gumbrell wwn_list->wwn_next;
5800fcf3ce44SJohn Forte } else {
5801fcf3ce44SJohn Forte /*
5802fcf3ce44SJohn Forte * No previous entries
5803fcf3ce44SJohn Forte */
5804fcf3ce44SJohn Forte *wwn_list_ptr = wwn_list->wwn_next;
5805fcf3ce44SJohn Forte }
5806fcf3ce44SJohn Forte if (wwn_list->wwn_next != NULL) {
5807fcf3ce44SJohn Forte wwn_list->wwn_next->wwn_prev =
5808063d642aSBill Gumbrell wwn_list->wwn_prev;
5809fcf3ce44SJohn Forte }
5810fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next;
5811fcf3ce44SJohn Forte free(wwn_list_save);
5812fcf3ce44SJohn Forte } else {
5813fcf3ce44SJohn Forte wwn_list = wwn_list->wwn_next;
5814fcf3ce44SJohn Forte }
5815fcf3ce44SJohn Forte }
5816fcf3ce44SJohn Forte
5817fcf3ce44SJohn Forte if (env != NULL) {
5818fcf3ce44SJohn Forte end_time = gethrtime();
5819fcf3ce44SJohn Forte fprintf(stdout,
5820063d642aSBill Gumbrell " get_dev_path %s: "
5821063d642aSBill Gumbrell "\t\tTime = %lld millisec\n",
5822063d642aSBill Gumbrell dir_name, (end_time - start_time)/1000000);
5823fcf3ce44SJohn Forte }
5824fcf3ce44SJohn Forte
5825fcf3ce44SJohn Forte if (*wwn_list_ptr == NULL) {
5826fcf3ce44SJohn Forte return (L_NO_DEVICES_FOUND);
5827fcf3ce44SJohn Forte } else {
5828fcf3ce44SJohn Forte return (0);
5829fcf3ce44SJohn Forte }
5830fcf3ce44SJohn Forte }
5831fcf3ce44SJohn Forte
5832fcf3ce44SJohn Forte /*
5833fcf3ce44SJohn Forte * This functions calls di_devfs_path and gets the path associated with a
5834fcf3ce44SJohn Forte * given devinfo node. If the path returned does not have a '@' in it, it
5835fcf3ce44SJohn Forte * checks if the driver is detached and creates a path after looking at the
5836fcf3ce44SJohn Forte * driver properties.
5837fcf3ce44SJohn Forte *
5838fcf3ce44SJohn Forte * di_devfs_path_free is called internally.
5839fcf3ce44SJohn Forte *
5840fcf3ce44SJohn Forte * The argument 'path' points to the final value upon return.
5841fcf3ce44SJohn Forte * Caller must use my_devfs_path_free on returned char *
5842fcf3ce44SJohn Forte * Note: Only support FC/SCSI_VHCI devices,
5843063d642aSBill Gumbrell * for FC check for initiator-interconnect-type prop
5844fcf3ce44SJohn Forte *
5845fcf3ce44SJohn Forte */
5846fcf3ce44SJohn Forte static char *
my_devfs_path(di_node_t node)5847fcf3ce44SJohn Forte my_devfs_path(di_node_t node)
5848fcf3ce44SJohn Forte {
5849fcf3ce44SJohn Forte uchar_t *pwwn = NULL;
5850063d642aSBill Gumbrell char *interconnect = NULL;
5851fcf3ce44SJohn Forte char pwwns[WWN_SIZE*2+1];
5852fcf3ce44SJohn Forte char *mypath;
5853fcf3ce44SJohn Forte int scsi_vhci = 0;
5854063d642aSBill Gumbrell int rval;
5855fcf3ce44SJohn Forte char *tptr = NULL, *lun_guid = NULL;
5856fcf3ce44SJohn Forte int *lunnump = NULL;
5857063d642aSBill Gumbrell di_node_t parentnode;
5858fcf3ce44SJohn Forte
5859fcf3ce44SJohn Forte /* sanity check */
5860fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
5861fcf3ce44SJohn Forte return (NULL);
5862fcf3ce44SJohn Forte }
5863fcf3ce44SJohn Forte
5864fcf3ce44SJohn Forte /* Now go get the path for this node */
5865fcf3ce44SJohn Forte if ((tptr = di_devfs_path(node)) == NULL) {
5866fcf3ce44SJohn Forte return (NULL);
5867fcf3ce44SJohn Forte }
5868fcf3ce44SJohn Forte
5869063d642aSBill Gumbrell parentnode = di_parent_node(node);
5870063d642aSBill Gumbrell
5871fcf3ce44SJohn Forte if ((mypath = (char *)calloc(1, MAXPATHLEN + 1)) == NULL) {
5872fcf3ce44SJohn Forte di_devfs_path_free(tptr);
5873fcf3ce44SJohn Forte return (NULL);
5874fcf3ce44SJohn Forte }
5875fcf3ce44SJohn Forte
5876fcf3ce44SJohn Forte /* Prepend "/devices" to libdevinfo-returned paths */
5877fcf3ce44SJohn Forte sprintf(mypath, "%s%s", DEVICES_DIR, tptr);
5878fcf3ce44SJohn Forte
5879fcf3ce44SJohn Forte di_devfs_path_free(tptr);
5880fcf3ce44SJohn Forte
5881fcf3ce44SJohn Forte /*
5882fcf3ce44SJohn Forte * Is this a FC device?
5883063d642aSBill Gumbrell * Check initiator-interconnect-type property
5884fcf3ce44SJohn Forte */
5885fcf3ce44SJohn Forte if (strstr(mypath, SCSI_VHCI) == NULL) {
5886063d642aSBill Gumbrell rval = di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode,
5887063d642aSBill Gumbrell "initiator-interconnect-type", &interconnect);
5888063d642aSBill Gumbrell /* Check for INTERCONNECT_FABRIC_STR & INTERCONNECT_FIBRE_STR */
5889063d642aSBill Gumbrell if ((rval <= 0) ||
5890063d642aSBill Gumbrell ((strcmp(interconnect, "FABRIC") != 0) &&
5891063d642aSBill Gumbrell (strcmp(interconnect, "FIBRE") != 0))) {
5892fcf3ce44SJohn Forte /* Not a FC device. Free path and return */
5893fcf3ce44SJohn Forte free(mypath);
5894fcf3ce44SJohn Forte return (NULL);
5895fcf3ce44SJohn Forte }
5896fcf3ce44SJohn Forte } else {
5897fcf3ce44SJohn Forte scsi_vhci++;
5898fcf3ce44SJohn Forte }
5899fcf3ce44SJohn Forte
5900fcf3ce44SJohn Forte if ((tptr = strrchr(mypath, '/')) == NULL) {
5901fcf3ce44SJohn Forte free(mypath);
5902fcf3ce44SJohn Forte return (NULL);
5903fcf3ce44SJohn Forte }
5904fcf3ce44SJohn Forte
5905fcf3ce44SJohn Forte if (strchr(tptr, '@') != NULL) {
5906fcf3ce44SJohn Forte return (mypath);
5907fcf3ce44SJohn Forte }
5908fcf3ce44SJohn Forte
5909fcf3ce44SJohn Forte /*
5910fcf3ce44SJohn Forte * No '@' in path. This can happen when driver is detached.
5911fcf3ce44SJohn Forte * We'll check if the state is detached and if it is, we'll construct
5912fcf3ce44SJohn Forte * the path by looking at the properties.
5913fcf3ce44SJohn Forte */
5914fcf3ce44SJohn Forte
5915fcf3ce44SJohn Forte if ((di_state(node) & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) {
5916fcf3ce44SJohn Forte /*
5917fcf3ce44SJohn Forte * Driver is not detached and no '@' in path.
5918fcf3ce44SJohn Forte * Can't handle it.
5919fcf3ce44SJohn Forte */
5920fcf3ce44SJohn Forte free(mypath);
5921fcf3ce44SJohn Forte return (NULL);
5922fcf3ce44SJohn Forte }
5923fcf3ce44SJohn Forte
5924fcf3ce44SJohn Forte if (!scsi_vhci) {
5925fcf3ce44SJohn Forte copy_wwn_data_to_str(pwwns, pwwn);
5926fcf3ce44SJohn Forte di_prop_lookup_ints(DDI_DEV_T_ANY, node, LUN_PROP, &lunnump);
5927fcf3ce44SJohn Forte sprintf(&mypath[strlen(mypath)], "@w%s,%x", pwwn, *lunnump);
5928fcf3ce44SJohn Forte } else {
5929fcf3ce44SJohn Forte di_prop_lookup_strings(DDI_DEV_T_ANY, node,
5930063d642aSBill Gumbrell LUN_GUID_PROP, &lun_guid);
5931fcf3ce44SJohn Forte sprintf(&mypath[strlen(mypath)], "@g%s", lun_guid);
5932fcf3ce44SJohn Forte }
5933fcf3ce44SJohn Forte return (mypath);
5934fcf3ce44SJohn Forte }
5935fcf3ce44SJohn Forte
5936fcf3ce44SJohn Forte static void
my_devfs_path_free(char * path)5937fcf3ce44SJohn Forte my_devfs_path_free(char *path)
5938fcf3ce44SJohn Forte {
5939fcf3ce44SJohn Forte if (path != NULL) {
5940fcf3ce44SJohn Forte free(path);
5941fcf3ce44SJohn Forte }
5942fcf3ce44SJohn Forte }
5943fcf3ce44SJohn Forte
5944fcf3ce44SJohn Forte /*
5945fcf3ce44SJohn Forte * from_ptr: ptr to uchar_t array of size WWN_SIZE
5946fcf3ce44SJohn Forte * to_ptr: char ptr to string of size WWN_SIZE*2+1
5947fcf3ce44SJohn Forte */
5948fcf3ce44SJohn Forte static void
copy_wwn_data_to_str(char * to_ptr,const uchar_t * from_ptr)5949fcf3ce44SJohn Forte copy_wwn_data_to_str(char *to_ptr, const uchar_t *from_ptr)
5950fcf3ce44SJohn Forte {
5951fcf3ce44SJohn Forte if ((to_ptr == NULL) || (from_ptr == NULL))
5952fcf3ce44SJohn Forte return;
5953fcf3ce44SJohn Forte
5954fcf3ce44SJohn Forte sprintf(to_ptr, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
5955063d642aSBill Gumbrell from_ptr[0], from_ptr[1], from_ptr[2], from_ptr[3],
5956063d642aSBill Gumbrell from_ptr[4], from_ptr[5], from_ptr[6], from_ptr[7]);
5957fcf3ce44SJohn Forte }
5958fcf3ce44SJohn Forte
5959fcf3ce44SJohn Forte /*
5960fcf3ce44SJohn Forte * Open the requested directory and get one valid open.
5961fcf3ce44SJohn Forte * If a device is busy, return.
5962fcf3ce44SJohn Forte * Only need to open one device since
5963fcf3ce44SJohn Forte * that implies there will be a node returned from
5964fcf3ce44SJohn Forte * di_drv_first_node()
5965fcf3ce44SJohn Forte * dir_name: logical device name directory
5966fcf3ce44SJohn Forte * (DEV_TAPE_DIR, DEV_RDIR)
5967fcf3ce44SJohn Forte * pattern_match: used by fnmatch on directory entry
5968fcf3ce44SJohn Forte * (DIR_MATCH_SSD, DIR_MATCH_ST)
5969fcf3ce44SJohn Forte * drvr_path: path type to verify ("/ssd@", "/st@")
5970fcf3ce44SJohn Forte * (SLSH_DRV_NAME_ST, SLSH_DRV_NAME_SSD)
5971fcf3ce44SJohn Forte *
5972fcf3ce44SJohn Forte * Returns: None
5973fcf3ce44SJohn Forte */
5974fcf3ce44SJohn Forte static void
init_drv(char * dir_name,char * pattern_match,char * drvr_path)5975fcf3ce44SJohn Forte init_drv(char *dir_name, char *pattern_match, char *drvr_path)
5976fcf3ce44SJohn Forte {
5977063d642aSBill Gumbrell DIR *dirp;
5978063d642aSBill Gumbrell struct dirent *entp;
5979063d642aSBill Gumbrell char namebuf[MAXPATHLEN];
5980063d642aSBill Gumbrell char *result = NULL;
5981063d642aSBill Gumbrell int fd;
5982fcf3ce44SJohn Forte
5983fcf3ce44SJohn Forte if ((dirp = opendir(dir_name)) == NULL) {
5984fcf3ce44SJohn Forte return;
5985fcf3ce44SJohn Forte }
5986fcf3ce44SJohn Forte
5987fcf3ce44SJohn Forte while ((entp = readdir(dirp)) != NULL) {
5988fcf3ce44SJohn Forte /*
5989fcf3ce44SJohn Forte * Ignore current directory and parent directory
5990fcf3ce44SJohn Forte * entries.
5991fcf3ce44SJohn Forte */
5992fcf3ce44SJohn Forte if ((strcmp(entp->d_name, ".") == 0) ||
5993fcf3ce44SJohn Forte (strcmp(entp->d_name, "..") == 0) ||
5994fcf3ce44SJohn Forte (fnmatch(pattern_match, entp->d_name, 0) != 0)) {
5995fcf3ce44SJohn Forte continue;
5996fcf3ce44SJohn Forte }
5997fcf3ce44SJohn Forte
5998fcf3ce44SJohn Forte memset(namebuf, 0, sizeof (namebuf));
5999fcf3ce44SJohn Forte sprintf(namebuf, "%s/%s", dir_name, entp->d_name);
6000fcf3ce44SJohn Forte
6001fcf3ce44SJohn Forte if ((result = g_get_physical_name_from_link(namebuf)) == NULL) {
6002fcf3ce44SJohn Forte ER_DPRINTF(" Warning: Get physical name from"
6003063d642aSBill Gumbrell " link failed. Link=%s\n", namebuf);
6004fcf3ce44SJohn Forte continue;
6005fcf3ce44SJohn Forte }
6006fcf3ce44SJohn Forte
6007fcf3ce44SJohn Forte if (strstr(result, drvr_path) == NULL) {
6008fcf3ce44SJohn Forte free(result);
6009fcf3ce44SJohn Forte result = NULL;
6010fcf3ce44SJohn Forte continue;
6011fcf3ce44SJohn Forte }
6012fcf3ce44SJohn Forte
6013fcf3ce44SJohn Forte if ((fd = g_object_open(result, O_NDELAY | O_RDONLY)) != -1) {
6014fcf3ce44SJohn Forte close(fd);
6015fcf3ce44SJohn Forte break;
6016fcf3ce44SJohn Forte } else if (errno != EBUSY) {
6017fcf3ce44SJohn Forte free(result);
6018fcf3ce44SJohn Forte result = NULL;
6019fcf3ce44SJohn Forte continue;
6020fcf3ce44SJohn Forte } else {
6021fcf3ce44SJohn Forte break;
6022fcf3ce44SJohn Forte }
6023fcf3ce44SJohn Forte }
6024fcf3ce44SJohn Forte free(result);
6025fcf3ce44SJohn Forte closedir(dirp);
6026fcf3ce44SJohn Forte }
6027