xref: /onnv-gate/usr/src/lib/cfgadm_plugins/fp/common/cfga_cvt.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM 
27*7836SJohn.Forte@Sun.COM #include "cfga_fp.h"
28*7836SJohn.Forte@Sun.COM 
29*7836SJohn.Forte@Sun.COM /* Function prototypes */
30*7836SJohn.Forte@Sun.COM 
31*7836SJohn.Forte@Sun.COM static fpcfga_ret_t get_xport_devlink(const char *hba_phys,
32*7836SJohn.Forte@Sun.COM     char **hba_logpp, int *l_errnop);
33*7836SJohn.Forte@Sun.COM static char ctoi(char c);
34*7836SJohn.Forte@Sun.COM static fpcfga_ret_t is_apid_configured(const char *xport_phys,
35*7836SJohn.Forte@Sun.COM 	const char *dyncomp, struct luninfo_list **lunlistpp, int *l_errnop);
36*7836SJohn.Forte@Sun.COM static fpcfga_ret_t insert_lun_to_lunlist(struct luninfo_list **lunlistpp,
37*7836SJohn.Forte@Sun.COM 	const char *dyncomp, di_node_t devnode, int *l_errnop);
38*7836SJohn.Forte@Sun.COM static fpcfga_ret_t update_lunlist(struct luninfo_list **lunlistpp, int lun,
39*7836SJohn.Forte@Sun.COM 	uint_t	state, char *pathp, int	*l_errnop);
40*7836SJohn.Forte@Sun.COM 
41*7836SJohn.Forte@Sun.COM 
42*7836SJohn.Forte@Sun.COM /* Globals */
43*7836SJohn.Forte@Sun.COM 
44*7836SJohn.Forte@Sun.COM /* Various conversions routines */
45*7836SJohn.Forte@Sun.COM 
46*7836SJohn.Forte@Sun.COM void
cvt_lawwn_to_dyncomp(const la_wwn_t * pwwn,char ** dyncomp,int * l_errnop)47*7836SJohn.Forte@Sun.COM cvt_lawwn_to_dyncomp(const la_wwn_t *pwwn, char **dyncomp, int *l_errnop)
48*7836SJohn.Forte@Sun.COM {
49*7836SJohn.Forte@Sun.COM 	*dyncomp = calloc(1, WWN_SIZE*2 + 1);
50*7836SJohn.Forte@Sun.COM 	if (*dyncomp == NULL) {
51*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
52*7836SJohn.Forte@Sun.COM 	}
53*7836SJohn.Forte@Sun.COM 
54*7836SJohn.Forte@Sun.COM 	(void) sprintf(*dyncomp, "%016llx",
55*7836SJohn.Forte@Sun.COM 	(wwnConversion((uchar_t *)pwwn->raw_wwn)));
56*7836SJohn.Forte@Sun.COM }
57*7836SJohn.Forte@Sun.COM 
58*7836SJohn.Forte@Sun.COM 
59*7836SJohn.Forte@Sun.COM int
cvt_dyncomp_to_lawwn(const char * dyncomp,la_wwn_t * port_wwn)60*7836SJohn.Forte@Sun.COM cvt_dyncomp_to_lawwn(const char *dyncomp, la_wwn_t *port_wwn)
61*7836SJohn.Forte@Sun.COM {
62*7836SJohn.Forte@Sun.COM 	int	i;
63*7836SJohn.Forte@Sun.COM 	char	c, c1;
64*7836SJohn.Forte@Sun.COM 	uchar_t	*wwnp;
65*7836SJohn.Forte@Sun.COM 
66*7836SJohn.Forte@Sun.COM 	wwnp = port_wwn->raw_wwn;
67*7836SJohn.Forte@Sun.COM 	for (i = 0; i < WWN_SIZE; i++, wwnp++) {
68*7836SJohn.Forte@Sun.COM 
69*7836SJohn.Forte@Sun.COM 		c = ctoi(*dyncomp++);
70*7836SJohn.Forte@Sun.COM 		c1 = ctoi(*dyncomp++);
71*7836SJohn.Forte@Sun.COM 		if (c == -1 || c1 == -1)
72*7836SJohn.Forte@Sun.COM 			return (-1);
73*7836SJohn.Forte@Sun.COM 		*wwnp = ((c << 4) + c1);
74*7836SJohn.Forte@Sun.COM 	}
75*7836SJohn.Forte@Sun.COM 
76*7836SJohn.Forte@Sun.COM 	return (0);
77*7836SJohn.Forte@Sun.COM }
78*7836SJohn.Forte@Sun.COM 
79*7836SJohn.Forte@Sun.COM 
80*7836SJohn.Forte@Sun.COM static char
ctoi(char c)81*7836SJohn.Forte@Sun.COM ctoi(char c)
82*7836SJohn.Forte@Sun.COM {
83*7836SJohn.Forte@Sun.COM 	if ((c >= '0') && (c <= '9'))
84*7836SJohn.Forte@Sun.COM 		c -= '0';
85*7836SJohn.Forte@Sun.COM 	else if ((c >= 'A') && (c <= 'F'))
86*7836SJohn.Forte@Sun.COM 		c = c - 'A' + 10;
87*7836SJohn.Forte@Sun.COM 	else if ((c >= 'a') && (c <= 'f'))
88*7836SJohn.Forte@Sun.COM 		c = c - 'a' + 10;
89*7836SJohn.Forte@Sun.COM 	else
90*7836SJohn.Forte@Sun.COM 		c = -1;
91*7836SJohn.Forte@Sun.COM 	return (c);
92*7836SJohn.Forte@Sun.COM }
93*7836SJohn.Forte@Sun.COM 
94*7836SJohn.Forte@Sun.COM 
95*7836SJohn.Forte@Sun.COM /*
96*7836SJohn.Forte@Sun.COM  * Generates the HBA logical ap_id from physical ap_id.
97*7836SJohn.Forte@Sun.COM  */
98*7836SJohn.Forte@Sun.COM fpcfga_ret_t
make_xport_logid(const char * xport_phys,char ** xport_logpp,int * l_errnop)99*7836SJohn.Forte@Sun.COM make_xport_logid(const char *xport_phys, char **xport_logpp, int *l_errnop)
100*7836SJohn.Forte@Sun.COM {
101*7836SJohn.Forte@Sun.COM 	if (*xport_logpp != NULL) {
102*7836SJohn.Forte@Sun.COM 		return (FPCFGA_ERR);
103*7836SJohn.Forte@Sun.COM 	}
104*7836SJohn.Forte@Sun.COM 
105*7836SJohn.Forte@Sun.COM 	/*
106*7836SJohn.Forte@Sun.COM 	 * A devlink for the XPORT should exist.  Without the /dev/cfg link
107*7836SJohn.Forte@Sun.COM 	 * driver name and instance number based based link needs to be
108*7836SJohn.Forte@Sun.COM 	 * constructed for the minor node type of DDI_NT_FC_ATTACHMENT_POINT.
109*7836SJohn.Forte@Sun.COM 	 * sunddi.h defines DDI_NT_FC_ATTACHMENT_POINT for
110*7836SJohn.Forte@Sun.COM 	 * ddi_ctl:attachment_point:fc
111*7836SJohn.Forte@Sun.COM 	 */
112*7836SJohn.Forte@Sun.COM 	if (get_xport_devlink(xport_phys, xport_logpp, l_errnop) == FPCFGA_OK) {
113*7836SJohn.Forte@Sun.COM 		assert(*xport_logpp != NULL);
114*7836SJohn.Forte@Sun.COM 		return (FPCFGA_OK);
115*7836SJohn.Forte@Sun.COM 	} else {
116*7836SJohn.Forte@Sun.COM 		return (FPCFGA_ERR);
117*7836SJohn.Forte@Sun.COM 	}
118*7836SJohn.Forte@Sun.COM }
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM static fpcfga_ret_t
get_xport_devlink(const char * xport_phys,char ** xport_logpp,int * l_errnop)121*7836SJohn.Forte@Sun.COM get_xport_devlink(const char *xport_phys, char **xport_logpp, int *l_errnop)
122*7836SJohn.Forte@Sun.COM {
123*7836SJohn.Forte@Sun.COM 	int match_minor;
124*7836SJohn.Forte@Sun.COM 	size_t len;
125*7836SJohn.Forte@Sun.COM 	fpcfga_ret_t ret;
126*7836SJohn.Forte@Sun.COM 
127*7836SJohn.Forte@Sun.COM 	match_minor = 1;
128*7836SJohn.Forte@Sun.COM 	ret = physpath_to_devlink(CFGA_DEV_DIR, (char *)xport_phys,
129*7836SJohn.Forte@Sun.COM 	    xport_logpp, l_errnop, match_minor);
130*7836SJohn.Forte@Sun.COM 	if (ret != FPCFGA_OK) {
131*7836SJohn.Forte@Sun.COM 		return (ret);
132*7836SJohn.Forte@Sun.COM 	}
133*7836SJohn.Forte@Sun.COM 
134*7836SJohn.Forte@Sun.COM 	assert(*xport_logpp != NULL);
135*7836SJohn.Forte@Sun.COM 
136*7836SJohn.Forte@Sun.COM 	/* Remove the "/dev/cfg/"  prefix */
137*7836SJohn.Forte@Sun.COM 	len = strlen(CFGA_DEV_DIR SLASH);
138*7836SJohn.Forte@Sun.COM 
139*7836SJohn.Forte@Sun.COM 	(void) memmove(*xport_logpp, *xport_logpp + len,
140*7836SJohn.Forte@Sun.COM 	    strlen(*xport_logpp + len) + 1);
141*7836SJohn.Forte@Sun.COM 
142*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
143*7836SJohn.Forte@Sun.COM }
144*7836SJohn.Forte@Sun.COM 
145*7836SJohn.Forte@Sun.COM 
146*7836SJohn.Forte@Sun.COM /*
147*7836SJohn.Forte@Sun.COM  * Given a xport path and dynamic ap_id, returns the physical
148*7836SJohn.Forte@Sun.COM  * path in pathpp.  If the dynamic ap is not configured pathpp set to NULL
149*7836SJohn.Forte@Sun.COM  * and returns FPCFGA_APID_NOCONFIGURE.
150*7836SJohn.Forte@Sun.COM  */
151*7836SJohn.Forte@Sun.COM fpcfga_ret_t
dyn_apid_to_path(const char * xport_phys,const char * dyncomp,struct luninfo_list ** lunlistpp,int * l_errnop)152*7836SJohn.Forte@Sun.COM dyn_apid_to_path(
153*7836SJohn.Forte@Sun.COM 	const char *xport_phys,
154*7836SJohn.Forte@Sun.COM 	const char *dyncomp,
155*7836SJohn.Forte@Sun.COM 	struct luninfo_list **lunlistpp,
156*7836SJohn.Forte@Sun.COM 	int *l_errnop)
157*7836SJohn.Forte@Sun.COM {
158*7836SJohn.Forte@Sun.COM 	fpcfga_ret_t 	ret;
159*7836SJohn.Forte@Sun.COM 
160*7836SJohn.Forte@Sun.COM 	/* A device MUST have a dynamic component */
161*7836SJohn.Forte@Sun.COM 	if (dyncomp == NULL) {
162*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
163*7836SJohn.Forte@Sun.COM 	}
164*7836SJohn.Forte@Sun.COM 
165*7836SJohn.Forte@Sun.COM 	ret = is_apid_configured(xport_phys, dyncomp, lunlistpp, l_errnop);
166*7836SJohn.Forte@Sun.COM 
167*7836SJohn.Forte@Sun.COM 	assert(ret != FPCFGA_OK);
168*7836SJohn.Forte@Sun.COM 
169*7836SJohn.Forte@Sun.COM 	return (ret);
170*7836SJohn.Forte@Sun.COM }
171*7836SJohn.Forte@Sun.COM 
172*7836SJohn.Forte@Sun.COM /*
173*7836SJohn.Forte@Sun.COM  * When both the transport and dynamic comp are given this function
174*7836SJohn.Forte@Sun.COM  * checks to see if the dynamic ap is configured on the dev tree.
175*7836SJohn.Forte@Sun.COM  * If it is configured the devfs path will be stored in pathpp.
176*7836SJohn.Forte@Sun.COM  * When the dynamic comp is null this function check to see if the transport
177*7836SJohn.Forte@Sun.COM  * node has any child.
178*7836SJohn.Forte@Sun.COM  *
179*7836SJohn.Forte@Sun.COM  * Retrun value: FPCFGA_OK if the apid is configured.
180*7836SJohn.Forte@Sun.COM  *		 FPCFGA_APID_NOCONFIGURE if the apid is not configured.
181*7836SJohn.Forte@Sun.COM  *		 FPCFGA_LIB_ERR for other errors.
182*7836SJohn.Forte@Sun.COM  */
183*7836SJohn.Forte@Sun.COM static fpcfga_ret_t
is_apid_configured(const char * xport_phys,const char * dyncomp,struct luninfo_list ** lunlistpp,int * l_errnop)184*7836SJohn.Forte@Sun.COM is_apid_configured(
185*7836SJohn.Forte@Sun.COM 	const char *xport_phys,
186*7836SJohn.Forte@Sun.COM 	const char *dyncomp,
187*7836SJohn.Forte@Sun.COM 	struct luninfo_list **lunlistpp,
188*7836SJohn.Forte@Sun.COM 	int *l_errnop)
189*7836SJohn.Forte@Sun.COM {
190*7836SJohn.Forte@Sun.COM 	char 		*devfs_phys, *devfs_fp_path, *client_path, *cp,
191*7836SJohn.Forte@Sun.COM 			*pathp = NULL;
192*7836SJohn.Forte@Sun.COM 	char 		path_name[MAXPATHLEN];
193*7836SJohn.Forte@Sun.COM 	di_node_t	tree_root, root, fpnode, dev_node, client_node;
194*7836SJohn.Forte@Sun.COM 	di_path_t 	path = DI_PATH_NIL;
195*7836SJohn.Forte@Sun.COM 	di_prop_t	prop = DI_PROP_NIL;
196*7836SJohn.Forte@Sun.COM 	uchar_t		*port_wwn_data = NULL;
197*7836SJohn.Forte@Sun.COM 	char		*lun_guid = NULL;
198*7836SJohn.Forte@Sun.COM 	char		port_wwn[WWN_SIZE*2+1];
199*7836SJohn.Forte@Sun.COM 	int		count, *lunnump, devlen,
200*7836SJohn.Forte@Sun.COM 			found_fp = 0;
201*7836SJohn.Forte@Sun.COM 	uint_t		state;
202*7836SJohn.Forte@Sun.COM 	uint_t		statep;
203*7836SJohn.Forte@Sun.COM 	fpcfga_ret_t 	ret;
204*7836SJohn.Forte@Sun.COM 
205*7836SJohn.Forte@Sun.COM 	if (*lunlistpp != NULL) {
206*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
207*7836SJohn.Forte@Sun.COM 	}
208*7836SJohn.Forte@Sun.COM 
209*7836SJohn.Forte@Sun.COM 	ret = FPCFGA_APID_NOCONFIGURE;
210*7836SJohn.Forte@Sun.COM 
211*7836SJohn.Forte@Sun.COM 	if ((devfs_phys = strdup(xport_phys)) == NULL) {
212*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
213*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
214*7836SJohn.Forte@Sun.COM 	}
215*7836SJohn.Forte@Sun.COM 
216*7836SJohn.Forte@Sun.COM 	if (strncmp(devfs_phys, DEVICES_DIR SLASH, strlen(DEVICES_DIR) +
217*7836SJohn.Forte@Sun.COM 			strlen(SLASH)) == 0) {
218*7836SJohn.Forte@Sun.COM 		cp = devfs_phys + strlen(DEVICES_DIR);
219*7836SJohn.Forte@Sun.COM 		(void) memmove(devfs_phys, cp, strlen(cp) + 1);
220*7836SJohn.Forte@Sun.COM 	}
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM 	if ((cp = strstr(devfs_phys, MINOR_SEP)) != NULL) {
223*7836SJohn.Forte@Sun.COM 		*cp = '\0';  /* Terminate string. */
224*7836SJohn.Forte@Sun.COM 	}
225*7836SJohn.Forte@Sun.COM 
226*7836SJohn.Forte@Sun.COM 	if ((tree_root = di_init("/", DINFOCPYALL | DINFOPATH))
227*7836SJohn.Forte@Sun.COM 			== DI_NODE_NIL) {
228*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
229*7836SJohn.Forte@Sun.COM 		S_FREE(devfs_phys);
230*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
231*7836SJohn.Forte@Sun.COM 	}
232*7836SJohn.Forte@Sun.COM 
233*7836SJohn.Forte@Sun.COM 	fpnode = di_drv_first_node("fp", tree_root);
234*7836SJohn.Forte@Sun.COM 
235*7836SJohn.Forte@Sun.COM 	while (fpnode) {
236*7836SJohn.Forte@Sun.COM 		devfs_fp_path = di_devfs_path(fpnode);
237*7836SJohn.Forte@Sun.COM 		if ((devfs_fp_path) && !(strncmp(devfs_fp_path,
238*7836SJohn.Forte@Sun.COM 				devfs_phys, strlen(devfs_phys)))) {
239*7836SJohn.Forte@Sun.COM 			found_fp = 1;
240*7836SJohn.Forte@Sun.COM 			di_devfs_path_free(devfs_fp_path);
241*7836SJohn.Forte@Sun.COM 			break;
242*7836SJohn.Forte@Sun.COM 		}
243*7836SJohn.Forte@Sun.COM 		di_devfs_path_free(devfs_fp_path);
244*7836SJohn.Forte@Sun.COM 		fpnode = di_drv_next_node(fpnode);
245*7836SJohn.Forte@Sun.COM 	}
246*7836SJohn.Forte@Sun.COM 	if (!(found_fp)) {
247*7836SJohn.Forte@Sun.COM 		ret = FPCFGA_LIB_ERR;
248*7836SJohn.Forte@Sun.COM 		goto out;
249*7836SJohn.Forte@Sun.COM 	} else {
250*7836SJohn.Forte@Sun.COM 		root = fpnode;
251*7836SJohn.Forte@Sun.COM 	}
252*7836SJohn.Forte@Sun.COM 
253*7836SJohn.Forte@Sun.COM 	/*
254*7836SJohn.Forte@Sun.COM 	 * when there is no child and path info node the
255*7836SJohn.Forte@Sun.COM 	 * FPCFGA_APID_NOCONFIGURE is returned
256*7836SJohn.Forte@Sun.COM 	 * regardless of the dynamic comp.
257*7836SJohn.Forte@Sun.COM 	 */
258*7836SJohn.Forte@Sun.COM 	dev_node = di_child_node(root);
259*7836SJohn.Forte@Sun.COM 	path = di_path_next_client(root, path);
260*7836SJohn.Forte@Sun.COM 	if ((dev_node == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
261*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
262*7836SJohn.Forte@Sun.COM 		ret = FPCFGA_APID_NOCONFIGURE;
263*7836SJohn.Forte@Sun.COM 		goto out;
264*7836SJohn.Forte@Sun.COM 	}
265*7836SJohn.Forte@Sun.COM 
266*7836SJohn.Forte@Sun.COM 	/*
267*7836SJohn.Forte@Sun.COM 	 * when dyn comp is null the function just checks if there is any
268*7836SJohn.Forte@Sun.COM 	 * child under fp transport attachment point.
269*7836SJohn.Forte@Sun.COM 	 */
270*7836SJohn.Forte@Sun.COM 	if (dyncomp == NULL) {
271*7836SJohn.Forte@Sun.COM 		ret = FPCFGA_OK;
272*7836SJohn.Forte@Sun.COM 		goto out;
273*7836SJohn.Forte@Sun.COM 	}
274*7836SJohn.Forte@Sun.COM 
275*7836SJohn.Forte@Sun.COM 	/*
276*7836SJohn.Forte@Sun.COM 	 * now checks the children node to find
277*7836SJohn.Forte@Sun.COM 	 * if dynamic ap is configured. if there are multiple luns
278*7836SJohn.Forte@Sun.COM 	 * store into lunlist.
279*7836SJohn.Forte@Sun.COM 	 */
280*7836SJohn.Forte@Sun.COM 	if (dev_node != DI_NODE_NIL) {
281*7836SJohn.Forte@Sun.COM 		do {
282*7836SJohn.Forte@Sun.COM 			while ((prop = di_prop_next(dev_node, prop)) !=
283*7836SJohn.Forte@Sun.COM 					DI_PROP_NIL) {
284*7836SJohn.Forte@Sun.COM 				/* is property name port-wwn */
285*7836SJohn.Forte@Sun.COM 				if ((!(strcmp(PORT_WWN_PROP,
286*7836SJohn.Forte@Sun.COM 					di_prop_name(prop)))) &&
287*7836SJohn.Forte@Sun.COM 					(di_prop_type(prop) ==
288*7836SJohn.Forte@Sun.COM 					DI_PROP_TYPE_BYTE)) {
289*7836SJohn.Forte@Sun.COM 					break;
290*7836SJohn.Forte@Sun.COM 				}
291*7836SJohn.Forte@Sun.COM 			}
292*7836SJohn.Forte@Sun.COM 
293*7836SJohn.Forte@Sun.COM 			if (prop != DI_PROP_NIL) {
294*7836SJohn.Forte@Sun.COM 				count = di_prop_bytes(prop, &port_wwn_data);
295*7836SJohn.Forte@Sun.COM 				if (count != WWN_SIZE) {
296*7836SJohn.Forte@Sun.COM 					ret = FPCFGA_LIB_ERR;
297*7836SJohn.Forte@Sun.COM 					goto out;
298*7836SJohn.Forte@Sun.COM 				} else {
299*7836SJohn.Forte@Sun.COM 					(void) sprintf(port_wwn,
300*7836SJohn.Forte@Sun.COM 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
301*7836SJohn.Forte@Sun.COM 					port_wwn_data[0], port_wwn_data[1],
302*7836SJohn.Forte@Sun.COM 					port_wwn_data[2], port_wwn_data[3],
303*7836SJohn.Forte@Sun.COM 					port_wwn_data[4], port_wwn_data[5],
304*7836SJohn.Forte@Sun.COM 					port_wwn_data[6], port_wwn_data[7]);
305*7836SJohn.Forte@Sun.COM 					if (!(strncmp(port_wwn, dyncomp,
306*7836SJohn.Forte@Sun.COM 							WWN_SIZE*2))) {
307*7836SJohn.Forte@Sun.COM 						ret = insert_lun_to_lunlist(
308*7836SJohn.Forte@Sun.COM 							lunlistpp, dyncomp,
309*7836SJohn.Forte@Sun.COM 							dev_node, l_errnop);
310*7836SJohn.Forte@Sun.COM 						if (ret != FPCFGA_OK) {
311*7836SJohn.Forte@Sun.COM 							goto out;
312*7836SJohn.Forte@Sun.COM 						}
313*7836SJohn.Forte@Sun.COM 					}
314*7836SJohn.Forte@Sun.COM 				}
315*7836SJohn.Forte@Sun.COM 			}
316*7836SJohn.Forte@Sun.COM 			dev_node = di_sibling_node(dev_node);
317*7836SJohn.Forte@Sun.COM 			prop = DI_PROP_NIL;
318*7836SJohn.Forte@Sun.COM 		} while (dev_node != DI_NODE_NIL);
319*7836SJohn.Forte@Sun.COM 	}
320*7836SJohn.Forte@Sun.COM 
321*7836SJohn.Forte@Sun.COM 	/*
322*7836SJohn.Forte@Sun.COM 	 * now checks the path info node to find
323*7836SJohn.Forte@Sun.COM 	 * if dynamic ap is configured. if there are multiple luns
324*7836SJohn.Forte@Sun.COM 	 * store into lunlist.
325*7836SJohn.Forte@Sun.COM 	 */
326*7836SJohn.Forte@Sun.COM 	if (path != DI_PATH_NIL) {
327*7836SJohn.Forte@Sun.COM 		/*
328*7836SJohn.Forte@Sun.COM 		 * now parse the path info node.
329*7836SJohn.Forte@Sun.COM 		 */
330*7836SJohn.Forte@Sun.COM 		do {
331*7836SJohn.Forte@Sun.COM 			count = di_path_prop_lookup_bytes(path, PORT_WWN_PROP,
332*7836SJohn.Forte@Sun.COM 				&port_wwn_data);
333*7836SJohn.Forte@Sun.COM 			if (count != WWN_SIZE) {
334*7836SJohn.Forte@Sun.COM 				ret = FPCFGA_LIB_ERR;
335*7836SJohn.Forte@Sun.COM 				goto out;
336*7836SJohn.Forte@Sun.COM 			}
337*7836SJohn.Forte@Sun.COM 
338*7836SJohn.Forte@Sun.COM 			(void) sprintf(port_wwn,
339*7836SJohn.Forte@Sun.COM 				"%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
340*7836SJohn.Forte@Sun.COM 				port_wwn_data[0], port_wwn_data[1],
341*7836SJohn.Forte@Sun.COM 				port_wwn_data[2], port_wwn_data[3],
342*7836SJohn.Forte@Sun.COM 				port_wwn_data[4], port_wwn_data[5],
343*7836SJohn.Forte@Sun.COM 				port_wwn_data[6], port_wwn_data[7]);
344*7836SJohn.Forte@Sun.COM 
345*7836SJohn.Forte@Sun.COM 			/* if matches get the path of scsi_vhci child node. */
346*7836SJohn.Forte@Sun.COM 			if (!(strncmp(port_wwn, dyncomp, WWN_SIZE*2))) {
347*7836SJohn.Forte@Sun.COM 				client_node = di_path_client_node(path);
348*7836SJohn.Forte@Sun.COM 				if (client_node == DI_NODE_NIL) {
349*7836SJohn.Forte@Sun.COM 					ret = FPCFGA_LIB_ERR;
350*7836SJohn.Forte@Sun.COM 					*l_errnop = errno;
351*7836SJohn.Forte@Sun.COM 					goto out;
352*7836SJohn.Forte@Sun.COM 				}
353*7836SJohn.Forte@Sun.COM 				count = di_path_prop_lookup_ints(path,
354*7836SJohn.Forte@Sun.COM 						LUN_PROP, &lunnump);
355*7836SJohn.Forte@Sun.COM 				client_path = di_devfs_path(client_node);
356*7836SJohn.Forte@Sun.COM 				strcpy(path_name, client_path);
357*7836SJohn.Forte@Sun.COM 				di_devfs_path_free(client_path);
358*7836SJohn.Forte@Sun.COM 				state = di_state(client_node);
359*7836SJohn.Forte@Sun.COM 				statep = di_path_state(path);
360*7836SJohn.Forte@Sun.COM 
361*7836SJohn.Forte@Sun.COM 				/*
362*7836SJohn.Forte@Sun.COM 				 * If the node is
363*7836SJohn.Forte@Sun.COM 				 * state then check the devfs_path to
364*7836SJohn.Forte@Sun.COM 				 * see if it has a complete path.
365*7836SJohn.Forte@Sun.COM 				 * For non scsi_vhci node the path
366*7836SJohn.Forte@Sun.COM 				 * doesn't contain @w(portwwn) part
367*7836SJohn.Forte@Sun.COM 				 * consistently.  For scsi_vhci
368*7836SJohn.Forte@Sun.COM 				 * this behavior may not be there.
369*7836SJohn.Forte@Sun.COM 				 * To be safe @g(guid) is attempted
370*7836SJohn.Forte@Sun.COM 				 * to be added here.
371*7836SJohn.Forte@Sun.COM 				 */
372*7836SJohn.Forte@Sun.COM 				if ((state & DI_DRIVER_DETACHED) &&
373*7836SJohn.Forte@Sun.COM 					(strstr(path_name, "@g") == NULL)) {
374*7836SJohn.Forte@Sun.COM 					prop = DI_PROP_NIL;
375*7836SJohn.Forte@Sun.COM 					while ((prop = di_prop_next(client_node,
376*7836SJohn.Forte@Sun.COM 							prop)) != DI_PROP_NIL) {
377*7836SJohn.Forte@Sun.COM 						/* is property name lun-wwn */
378*7836SJohn.Forte@Sun.COM 						if ((!(strcmp(LUN_GUID_PROP,
379*7836SJohn.Forte@Sun.COM 							di_prop_name(prop)))) &&
380*7836SJohn.Forte@Sun.COM 							(di_prop_type(prop) ==
381*7836SJohn.Forte@Sun.COM 							DI_PROP_TYPE_STRING)) {
382*7836SJohn.Forte@Sun.COM 							break;
383*7836SJohn.Forte@Sun.COM 						}
384*7836SJohn.Forte@Sun.COM 					}
385*7836SJohn.Forte@Sun.COM 
386*7836SJohn.Forte@Sun.COM 					if (prop != DI_PROP_NIL) {
387*7836SJohn.Forte@Sun.COM 						count = di_prop_strings(
388*7836SJohn.Forte@Sun.COM 							prop, &lun_guid);
389*7836SJohn.Forte@Sun.COM 						sprintf(&path_name[
390*7836SJohn.Forte@Sun.COM 							strlen(path_name)],
391*7836SJohn.Forte@Sun.COM 							"@g%s", lun_guid);
392*7836SJohn.Forte@Sun.COM 					} else {
393*7836SJohn.Forte@Sun.COM 						ret = FPCFGA_LIB_ERR;
394*7836SJohn.Forte@Sun.COM 						goto out;
395*7836SJohn.Forte@Sun.COM 					}
396*7836SJohn.Forte@Sun.COM 				}
397*7836SJohn.Forte@Sun.COM 
398*7836SJohn.Forte@Sun.COM 				devlen = strlen(DEVICES_DIR) +
399*7836SJohn.Forte@Sun.COM 						strlen(path_name) + 1;
400*7836SJohn.Forte@Sun.COM 				if ((pathp = calloc(1, devlen))
401*7836SJohn.Forte@Sun.COM 						== NULL) {
402*7836SJohn.Forte@Sun.COM 					*l_errnop = errno;
403*7836SJohn.Forte@Sun.COM 					return (FPCFGA_LIB_ERR);
404*7836SJohn.Forte@Sun.COM 				} else {
405*7836SJohn.Forte@Sun.COM 					(void) snprintf(pathp, devlen,
406*7836SJohn.Forte@Sun.COM 					"%s%s", DEVICES_DIR, path_name);
407*7836SJohn.Forte@Sun.COM 				}
408*7836SJohn.Forte@Sun.COM 				if ((ret = (update_lunlist(lunlistpp, *lunnump,
409*7836SJohn.Forte@Sun.COM 						statep, pathp, l_errnop))) !=
410*7836SJohn.Forte@Sun.COM 						FPCFGA_OK) {
411*7836SJohn.Forte@Sun.COM 					S_FREE(pathp);
412*7836SJohn.Forte@Sun.COM 					goto out;
413*7836SJohn.Forte@Sun.COM 				}
414*7836SJohn.Forte@Sun.COM 			}
415*7836SJohn.Forte@Sun.COM 			path = di_path_next_client(root, path);
416*7836SJohn.Forte@Sun.COM 		} while (path != DI_PATH_NIL);
417*7836SJohn.Forte@Sun.COM 	}
418*7836SJohn.Forte@Sun.COM 
419*7836SJohn.Forte@Sun.COM out:
420*7836SJohn.Forte@Sun.COM 	di_fini(tree_root);
421*7836SJohn.Forte@Sun.COM 	S_FREE(devfs_phys);
422*7836SJohn.Forte@Sun.COM 	return (ret);
423*7836SJohn.Forte@Sun.COM }
424*7836SJohn.Forte@Sun.COM 
425*7836SJohn.Forte@Sun.COM static fpcfga_ret_t
insert_lun_to_lunlist(struct luninfo_list ** lunlistpp,const char * dyncomp,di_node_t dev_node,int * l_errnop)426*7836SJohn.Forte@Sun.COM insert_lun_to_lunlist(
427*7836SJohn.Forte@Sun.COM 	struct luninfo_list **lunlistpp,
428*7836SJohn.Forte@Sun.COM 	const char *dyncomp,
429*7836SJohn.Forte@Sun.COM 	di_node_t dev_node,
430*7836SJohn.Forte@Sun.COM 	int *l_errnop)
431*7836SJohn.Forte@Sun.COM {
432*7836SJohn.Forte@Sun.COM 	char		path_name[MAXPATHLEN];
433*7836SJohn.Forte@Sun.COM 	char 		*pathp, *dev_phys;
434*7836SJohn.Forte@Sun.COM 	di_prop_t	prop_lun = DI_PROP_NIL;
435*7836SJohn.Forte@Sun.COM 	uint_t 		state;
436*7836SJohn.Forte@Sun.COM 	int		count, devlen;
437*7836SJohn.Forte@Sun.COM 	int		*lunp;
438*7836SJohn.Forte@Sun.COM 
439*7836SJohn.Forte@Sun.COM 	while ((prop_lun = di_prop_next(dev_node, prop_lun)) != DI_PROP_NIL) {
440*7836SJohn.Forte@Sun.COM 		if (!(strcmp(LUN_PROP, di_prop_name(prop_lun))) &&
441*7836SJohn.Forte@Sun.COM 				(di_prop_type(prop_lun) == DI_PROP_TYPE_INT)) {
442*7836SJohn.Forte@Sun.COM 			count = di_prop_ints(prop_lun, &lunp);
443*7836SJohn.Forte@Sun.COM 			if (count <= 0) {
444*7836SJohn.Forte@Sun.COM 				return (FPCFGA_LIB_ERR);
445*7836SJohn.Forte@Sun.COM 			}
446*7836SJohn.Forte@Sun.COM 			break;
447*7836SJohn.Forte@Sun.COM 		}
448*7836SJohn.Forte@Sun.COM 	}
449*7836SJohn.Forte@Sun.COM 
450*7836SJohn.Forte@Sun.COM 	if (prop_lun == DI_PROP_NIL) {
451*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
452*7836SJohn.Forte@Sun.COM 	}
453*7836SJohn.Forte@Sun.COM 
454*7836SJohn.Forte@Sun.COM 	/*
455*7836SJohn.Forte@Sun.COM 	 * stores state info in state.
456*7836SJohn.Forte@Sun.COM 	 * This information is used to get the
457*7836SJohn.Forte@Sun.COM 	 * validity of path.
458*7836SJohn.Forte@Sun.COM 	 * if driver_detached don't try to get
459*7836SJohn.Forte@Sun.COM 	 * the devfs_path since it is not
460*7836SJohn.Forte@Sun.COM 	 * complete. ex, /pci@1f,2000/pci@1/
461*7836SJohn.Forte@Sun.COM 	 * SUNW,qlc@5/fp@0,0/ssd
462*7836SJohn.Forte@Sun.COM 	 * which doesn't contain the port wwn
463*7836SJohn.Forte@Sun.COM 	 * part.  The attached node looks like
464*7836SJohn.Forte@Sun.COM 	 * /pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0/
465*7836SJohn.Forte@Sun.COM 	 * ssd@w2100002037006b14,0
466*7836SJohn.Forte@Sun.COM 	 */
467*7836SJohn.Forte@Sun.COM 	state = di_state(dev_node);
468*7836SJohn.Forte@Sun.COM 
469*7836SJohn.Forte@Sun.COM 	dev_phys = di_devfs_path(dev_node);
470*7836SJohn.Forte@Sun.COM 	if (dev_phys == NULL) {
471*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
472*7836SJohn.Forte@Sun.COM 	}
473*7836SJohn.Forte@Sun.COM 
474*7836SJohn.Forte@Sun.COM 	strcpy(path_name, dev_phys);
475*7836SJohn.Forte@Sun.COM 
476*7836SJohn.Forte@Sun.COM 	di_devfs_path_free(dev_phys);
477*7836SJohn.Forte@Sun.COM 
478*7836SJohn.Forte@Sun.COM 	if ((state & DI_DRIVER_DETACHED) &&
479*7836SJohn.Forte@Sun.COM 		(strstr(path_name, "@w") == NULL)) {
480*7836SJohn.Forte@Sun.COM 		sprintf(&path_name[strlen(path_name)], "@w%s,%x", dyncomp,
481*7836SJohn.Forte@Sun.COM 									*lunp);
482*7836SJohn.Forte@Sun.COM 	}
483*7836SJohn.Forte@Sun.COM 
484*7836SJohn.Forte@Sun.COM 	devlen = strlen(DEVICES_DIR) + strlen(path_name) + 1;
485*7836SJohn.Forte@Sun.COM 
486*7836SJohn.Forte@Sun.COM 	if ((pathp = calloc(1, devlen))
487*7836SJohn.Forte@Sun.COM 			== NULL) {
488*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
489*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
490*7836SJohn.Forte@Sun.COM 	} else {
491*7836SJohn.Forte@Sun.COM 		(void) snprintf(pathp, devlen, "%s%s", DEVICES_DIR, path_name);
492*7836SJohn.Forte@Sun.COM 	}
493*7836SJohn.Forte@Sun.COM 
494*7836SJohn.Forte@Sun.COM 	return (update_lunlist(lunlistpp, *lunp, state, pathp, l_errnop));
495*7836SJohn.Forte@Sun.COM }
496*7836SJohn.Forte@Sun.COM 
497*7836SJohn.Forte@Sun.COM static fpcfga_ret_t
update_lunlist(struct luninfo_list ** lunlistpp,int lun,uint_t state,char * pathp,int * l_errnop)498*7836SJohn.Forte@Sun.COM update_lunlist(
499*7836SJohn.Forte@Sun.COM 	struct luninfo_list **lunlistpp,
500*7836SJohn.Forte@Sun.COM 	int	lun,
501*7836SJohn.Forte@Sun.COM 	uint_t	state,
502*7836SJohn.Forte@Sun.COM 	char 	*pathp,
503*7836SJohn.Forte@Sun.COM 	int 	*l_errnop)
504*7836SJohn.Forte@Sun.COM {
505*7836SJohn.Forte@Sun.COM 	struct luninfo_list *newlun, *curlun, *prevlun;
506*7836SJohn.Forte@Sun.COM 
507*7836SJohn.Forte@Sun.COM 	newlun = curlun = prevlun = (struct luninfo_list *)NULL;
508*7836SJohn.Forte@Sun.COM 
509*7836SJohn.Forte@Sun.COM 	newlun = calloc(1, sizeof (struct luninfo_list));
510*7836SJohn.Forte@Sun.COM 	if (newlun == NULL) {
511*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
512*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
513*7836SJohn.Forte@Sun.COM 	}
514*7836SJohn.Forte@Sun.COM 
515*7836SJohn.Forte@Sun.COM 	newlun->lunnum = lun;
516*7836SJohn.Forte@Sun.COM 	newlun->node_state = state;
517*7836SJohn.Forte@Sun.COM 	newlun->path = pathp;
518*7836SJohn.Forte@Sun.COM 	newlun->next = (struct luninfo_list *)NULL;
519*7836SJohn.Forte@Sun.COM 
520*7836SJohn.Forte@Sun.COM 	/* if lunlist is empty add the new lun info and return. */
521*7836SJohn.Forte@Sun.COM 	if (*lunlistpp == NULL) {
522*7836SJohn.Forte@Sun.COM 		*lunlistpp = newlun;
523*7836SJohn.Forte@Sun.COM 		return (FPCFGA_OK);
524*7836SJohn.Forte@Sun.COM 	}
525*7836SJohn.Forte@Sun.COM 
526*7836SJohn.Forte@Sun.COM 	/* if the first lun in the list is the same as the new lun return. */
527*7836SJohn.Forte@Sun.COM 	if ((*lunlistpp)->lunnum == lun) {
528*7836SJohn.Forte@Sun.COM 		S_FREE(newlun);
529*7836SJohn.Forte@Sun.COM 		return (FPCFGA_OK);
530*7836SJohn.Forte@Sun.COM 	}
531*7836SJohn.Forte@Sun.COM 
532*7836SJohn.Forte@Sun.COM 	/*
533*7836SJohn.Forte@Sun.COM 	 * if the first lun in the list is less than the new lun add the
534*7836SJohn.Forte@Sun.COM 	 * new lun as the first lun and return.
535*7836SJohn.Forte@Sun.COM 	 */
536*7836SJohn.Forte@Sun.COM 	if ((*lunlistpp)->lunnum < lun) {
537*7836SJohn.Forte@Sun.COM 		newlun->next = *lunlistpp;
538*7836SJohn.Forte@Sun.COM 		*lunlistpp = newlun;
539*7836SJohn.Forte@Sun.COM 		return (FPCFGA_OK);
540*7836SJohn.Forte@Sun.COM 	}
541*7836SJohn.Forte@Sun.COM 
542*7836SJohn.Forte@Sun.COM 	/*
543*7836SJohn.Forte@Sun.COM 	 * if the first lun in the list is greater than the new lun and
544*7836SJohn.Forte@Sun.COM 	 * there is a single lun add new lun after the first lun and return.
545*7836SJohn.Forte@Sun.COM 	 */
546*7836SJohn.Forte@Sun.COM 	if ((*lunlistpp)->next == NULL) {
547*7836SJohn.Forte@Sun.COM 		(*lunlistpp)->next = newlun;
548*7836SJohn.Forte@Sun.COM 		return (FPCFGA_OK);
549*7836SJohn.Forte@Sun.COM 	}
550*7836SJohn.Forte@Sun.COM 
551*7836SJohn.Forte@Sun.COM 	/*
552*7836SJohn.Forte@Sun.COM 	 * now there is more than two luns in the list and the first lun
553*7836SJohn.Forte@Sun.COM 	 * is greter than the input lun.
554*7836SJohn.Forte@Sun.COM 	 */
555*7836SJohn.Forte@Sun.COM 	curlun = (*lunlistpp)->next;
556*7836SJohn.Forte@Sun.COM 	prevlun = *lunlistpp;
557*7836SJohn.Forte@Sun.COM 
558*7836SJohn.Forte@Sun.COM 	while (curlun != NULL) {
559*7836SJohn.Forte@Sun.COM 		if (curlun->lunnum == lun) {
560*7836SJohn.Forte@Sun.COM 			S_FREE(newlun);
561*7836SJohn.Forte@Sun.COM 			return (FPCFGA_OK);
562*7836SJohn.Forte@Sun.COM 		} else if (curlun->lunnum < lun) {
563*7836SJohn.Forte@Sun.COM 			newlun->next = curlun;
564*7836SJohn.Forte@Sun.COM 			prevlun->next = newlun;
565*7836SJohn.Forte@Sun.COM 			return (FPCFGA_OK);
566*7836SJohn.Forte@Sun.COM 		} else {
567*7836SJohn.Forte@Sun.COM 			prevlun = curlun;
568*7836SJohn.Forte@Sun.COM 			curlun = curlun->next;
569*7836SJohn.Forte@Sun.COM 		}
570*7836SJohn.Forte@Sun.COM 	}
571*7836SJohn.Forte@Sun.COM 
572*7836SJohn.Forte@Sun.COM 	/* add the new lun at the end of list. */
573*7836SJohn.Forte@Sun.COM 	prevlun->next = newlun;
574*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
575*7836SJohn.Forte@Sun.COM 
576*7836SJohn.Forte@Sun.COM }
577*7836SJohn.Forte@Sun.COM 
578*7836SJohn.Forte@Sun.COM 
579*7836SJohn.Forte@Sun.COM fpcfga_ret_t
make_dyncomp_from_dinode(const di_node_t node,char ** dyncompp,int * l_errnop)580*7836SJohn.Forte@Sun.COM make_dyncomp_from_dinode(
581*7836SJohn.Forte@Sun.COM 	const di_node_t node,
582*7836SJohn.Forte@Sun.COM 	char **dyncompp,
583*7836SJohn.Forte@Sun.COM 	int *l_errnop)
584*7836SJohn.Forte@Sun.COM {
585*7836SJohn.Forte@Sun.COM 	di_prop_t	prop = DI_PROP_NIL;
586*7836SJohn.Forte@Sun.COM 	uchar_t		*port_wwn_data;
587*7836SJohn.Forte@Sun.COM 	int		count;
588*7836SJohn.Forte@Sun.COM 
589*7836SJohn.Forte@Sun.COM 	*l_errnop = 0;
590*7836SJohn.Forte@Sun.COM 	*dyncompp = calloc(1, WWN_SIZE*2 + 1);
591*7836SJohn.Forte@Sun.COM 	if (*dyncompp == NULL) {
592*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
593*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
594*7836SJohn.Forte@Sun.COM 	}
595*7836SJohn.Forte@Sun.COM 
596*7836SJohn.Forte@Sun.COM 	/* now get port-wwn for the input node. */
597*7836SJohn.Forte@Sun.COM 	while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) {
598*7836SJohn.Forte@Sun.COM 		if (!(strcmp(PORT_WWN_PROP, di_prop_name(prop))) &&
599*7836SJohn.Forte@Sun.COM 			(di_prop_type(prop) == DI_PROP_TYPE_BYTE)) {
600*7836SJohn.Forte@Sun.COM 			break;
601*7836SJohn.Forte@Sun.COM 		}
602*7836SJohn.Forte@Sun.COM 	}
603*7836SJohn.Forte@Sun.COM 
604*7836SJohn.Forte@Sun.COM 	if (prop != DI_PROP_NIL) {
605*7836SJohn.Forte@Sun.COM 		count = di_prop_bytes(prop, &port_wwn_data);
606*7836SJohn.Forte@Sun.COM 		if (count != WWN_SIZE) {
607*7836SJohn.Forte@Sun.COM 			S_FREE(*dyncompp);
608*7836SJohn.Forte@Sun.COM 			return (FPCFGA_LIB_ERR);
609*7836SJohn.Forte@Sun.COM 		}
610*7836SJohn.Forte@Sun.COM 
611*7836SJohn.Forte@Sun.COM 		(void) sprintf(*dyncompp, "%016llx",
612*7836SJohn.Forte@Sun.COM 			(wwnConversion(port_wwn_data)));
613*7836SJohn.Forte@Sun.COM 	} else {
614*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
615*7836SJohn.Forte@Sun.COM 		S_FREE(*dyncompp);
616*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
617*7836SJohn.Forte@Sun.COM 	}
618*7836SJohn.Forte@Sun.COM 
619*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
620*7836SJohn.Forte@Sun.COM }
621*7836SJohn.Forte@Sun.COM 
622*7836SJohn.Forte@Sun.COM fpcfga_ret_t
make_portwwn_luncomp_from_dinode(const di_node_t node,char ** dyncompp,int ** luncompp,int * l_errnop)623*7836SJohn.Forte@Sun.COM make_portwwn_luncomp_from_dinode(
624*7836SJohn.Forte@Sun.COM 	const di_node_t node,
625*7836SJohn.Forte@Sun.COM 	char **dyncompp,
626*7836SJohn.Forte@Sun.COM 	int **luncompp,
627*7836SJohn.Forte@Sun.COM 	int *l_errnop)
628*7836SJohn.Forte@Sun.COM {
629*7836SJohn.Forte@Sun.COM 	uchar_t		*port_wwn_data;
630*7836SJohn.Forte@Sun.COM 	int		pwwn_ret, lun_ret;
631*7836SJohn.Forte@Sun.COM 
632*7836SJohn.Forte@Sun.COM 	*l_errnop = 0;
633*7836SJohn.Forte@Sun.COM 
634*7836SJohn.Forte@Sun.COM 	if ((dyncompp != NULL) &&
635*7836SJohn.Forte@Sun.COM 			((pwwn_ret = di_prop_lookup_bytes(DDI_DEV_T_ANY,
636*7836SJohn.Forte@Sun.COM 			node, PORT_WWN_PROP, &port_wwn_data)) <= 0)) {
637*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
638*7836SJohn.Forte@Sun.COM 	}
639*7836SJohn.Forte@Sun.COM 	if ((luncompp != NULL) &&
640*7836SJohn.Forte@Sun.COM 			((lun_ret = di_prop_lookup_ints(DDI_DEV_T_ANY,
641*7836SJohn.Forte@Sun.COM 			node, LUN_PROP, luncompp)) <= 0)) {
642*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
643*7836SJohn.Forte@Sun.COM 	}
644*7836SJohn.Forte@Sun.COM 
645*7836SJohn.Forte@Sun.COM 	/*
646*7836SJohn.Forte@Sun.COM 	 * di_prop* returns the number of entries found or 0 if not found
647*7836SJohn.Forte@Sun.COM 	 * or -1 for othere failure.
648*7836SJohn.Forte@Sun.COM 	 */
649*7836SJohn.Forte@Sun.COM 	if ((pwwn_ret <= 0) || (lun_ret <= 0)) {
650*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
651*7836SJohn.Forte@Sun.COM 	}
652*7836SJohn.Forte@Sun.COM 
653*7836SJohn.Forte@Sun.COM 	*dyncompp = calloc(1, WWN_SIZE*2+1);
654*7836SJohn.Forte@Sun.COM 	if (*dyncompp == NULL) {
655*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
656*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
657*7836SJohn.Forte@Sun.COM 	}
658*7836SJohn.Forte@Sun.COM 
659*7836SJohn.Forte@Sun.COM 	(void) sprintf(*dyncompp, "%016llx", (wwnConversion(port_wwn_data)));
660*7836SJohn.Forte@Sun.COM 
661*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
662*7836SJohn.Forte@Sun.COM }
663*7836SJohn.Forte@Sun.COM 
664*7836SJohn.Forte@Sun.COM fpcfga_ret_t
make_portwwn_luncomp_from_pinode(const di_path_t pinode,char ** dyncompp,int ** luncompp,int * l_errnop)665*7836SJohn.Forte@Sun.COM make_portwwn_luncomp_from_pinode(
666*7836SJohn.Forte@Sun.COM 	const di_path_t pinode,
667*7836SJohn.Forte@Sun.COM 	char **dyncompp,
668*7836SJohn.Forte@Sun.COM 	int **luncompp,
669*7836SJohn.Forte@Sun.COM 	int *l_errnop)
670*7836SJohn.Forte@Sun.COM {
671*7836SJohn.Forte@Sun.COM 	uchar_t		*port_wwn_data;
672*7836SJohn.Forte@Sun.COM 	int		pwwn_ret, lun_ret;
673*7836SJohn.Forte@Sun.COM 
674*7836SJohn.Forte@Sun.COM 	*l_errnop = 0;
675*7836SJohn.Forte@Sun.COM 
676*7836SJohn.Forte@Sun.COM 	if ((dyncompp != NULL) &&
677*7836SJohn.Forte@Sun.COM 			((pwwn_ret = di_path_prop_lookup_bytes(pinode,
678*7836SJohn.Forte@Sun.COM 			PORT_WWN_PROP, &port_wwn_data)) <= 0)) {
679*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
680*7836SJohn.Forte@Sun.COM 	}
681*7836SJohn.Forte@Sun.COM 	if ((luncompp != NULL) &&
682*7836SJohn.Forte@Sun.COM 			((lun_ret = di_path_prop_lookup_ints(pinode,
683*7836SJohn.Forte@Sun.COM 			LUN_PROP, luncompp)) <= 0)) {
684*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
685*7836SJohn.Forte@Sun.COM 	}
686*7836SJohn.Forte@Sun.COM 
687*7836SJohn.Forte@Sun.COM 	/*
688*7836SJohn.Forte@Sun.COM 	 * di_prop* returns the number of entries found or 0 if not found
689*7836SJohn.Forte@Sun.COM 	 * or -1 for othere failure.
690*7836SJohn.Forte@Sun.COM 	 */
691*7836SJohn.Forte@Sun.COM 	if ((pwwn_ret <= 0) || (lun_ret <= 0)) {
692*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
693*7836SJohn.Forte@Sun.COM 	}
694*7836SJohn.Forte@Sun.COM 
695*7836SJohn.Forte@Sun.COM 	*dyncompp = calloc(1, WWN_SIZE*2+1);
696*7836SJohn.Forte@Sun.COM 	if (*dyncompp == NULL) {
697*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
698*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
699*7836SJohn.Forte@Sun.COM 	}
700*7836SJohn.Forte@Sun.COM 
701*7836SJohn.Forte@Sun.COM 	(void) sprintf(*dyncompp, "%016llx", (wwnConversion(port_wwn_data)));
702*7836SJohn.Forte@Sun.COM 
703*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
704*7836SJohn.Forte@Sun.COM }
705*7836SJohn.Forte@Sun.COM 
706*7836SJohn.Forte@Sun.COM fpcfga_ret_t
construct_nodepath_from_dinode(const di_node_t node,char ** node_pathp,int * l_errnop)707*7836SJohn.Forte@Sun.COM construct_nodepath_from_dinode(
708*7836SJohn.Forte@Sun.COM 	const di_node_t node,
709*7836SJohn.Forte@Sun.COM 	char **node_pathp,
710*7836SJohn.Forte@Sun.COM 	int *l_errnop)
711*7836SJohn.Forte@Sun.COM {
712*7836SJohn.Forte@Sun.COM 	char *devfs_path, path_name[MAXPATHLEN], *lun_guid, *port_wwn;
713*7836SJohn.Forte@Sun.COM 	uchar_t *port_wwn_data;
714*7836SJohn.Forte@Sun.COM 	int is_scsi_vhci_dev, di_ret, devlen;
715*7836SJohn.Forte@Sun.COM 	uint_t	state;
716*7836SJohn.Forte@Sun.COM 
717*7836SJohn.Forte@Sun.COM 	devfs_path = di_devfs_path(node);
718*7836SJohn.Forte@Sun.COM 	strcpy(path_name, devfs_path);
719*7836SJohn.Forte@Sun.COM 	di_devfs_path_free(devfs_path);
720*7836SJohn.Forte@Sun.COM 	state = di_state(node);
721*7836SJohn.Forte@Sun.COM 
722*7836SJohn.Forte@Sun.COM 	is_scsi_vhci_dev = (strstr(path_name, SCSI_VHCI_DRVR) != NULL) ? 1 : 0;
723*7836SJohn.Forte@Sun.COM 
724*7836SJohn.Forte@Sun.COM 	/*
725*7836SJohn.Forte@Sun.COM 	 * If the node is
726*7836SJohn.Forte@Sun.COM 	 * state then check the devfs_path to
727*7836SJohn.Forte@Sun.COM 	 * see if it has a complete path.
728*7836SJohn.Forte@Sun.COM 	 * For non scsi_vhci node the path
729*7836SJohn.Forte@Sun.COM 	 * doesn't contain @w(portwwn) part
730*7836SJohn.Forte@Sun.COM 	 * consistently.  For scsi_vhci
731*7836SJohn.Forte@Sun.COM 	 * this behavior may not be there.
732*7836SJohn.Forte@Sun.COM 	 * To be safe @g(guid) is attempted
733*7836SJohn.Forte@Sun.COM 	 * to be added here.
734*7836SJohn.Forte@Sun.COM 	 */
735*7836SJohn.Forte@Sun.COM 	if (state & DI_DRIVER_DETACHED) {
736*7836SJohn.Forte@Sun.COM 		if (is_scsi_vhci_dev &&
737*7836SJohn.Forte@Sun.COM 			(strstr(path_name, "@g") == NULL)) {
738*7836SJohn.Forte@Sun.COM 			di_ret = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
739*7836SJohn.Forte@Sun.COM 				LUN_GUID_PROP, &lun_guid);
740*7836SJohn.Forte@Sun.COM 			if (di_ret == -1) {
741*7836SJohn.Forte@Sun.COM 				*l_errnop = errno;
742*7836SJohn.Forte@Sun.COM 				return (FPCFGA_LIB_ERR);
743*7836SJohn.Forte@Sun.COM 			} else {
744*7836SJohn.Forte@Sun.COM 				sprintf(&path_name[strlen(path_name)],
745*7836SJohn.Forte@Sun.COM 					"@g%s", lun_guid);
746*7836SJohn.Forte@Sun.COM 			}
747*7836SJohn.Forte@Sun.COM 		} else if (!is_scsi_vhci_dev &&
748*7836SJohn.Forte@Sun.COM 			(strstr(path_name, "@w") == NULL)) {
749*7836SJohn.Forte@Sun.COM 			di_ret = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
750*7836SJohn.Forte@Sun.COM 				PORT_WWN_PROP, &port_wwn_data);
751*7836SJohn.Forte@Sun.COM 			if (di_ret == -1) {
752*7836SJohn.Forte@Sun.COM 				*l_errnop = errno;
753*7836SJohn.Forte@Sun.COM 				return (FPCFGA_LIB_ERR);
754*7836SJohn.Forte@Sun.COM 			} else {
755*7836SJohn.Forte@Sun.COM 				if ((port_wwn = calloc(1, WWN_SIZE*2 + 1))
756*7836SJohn.Forte@Sun.COM 						== NULL) {
757*7836SJohn.Forte@Sun.COM 					*l_errnop = errno;
758*7836SJohn.Forte@Sun.COM 					return (FPCFGA_LIB_ERR);
759*7836SJohn.Forte@Sun.COM 				}
760*7836SJohn.Forte@Sun.COM 
761*7836SJohn.Forte@Sun.COM 				(void) sprintf(port_wwn, "%016llx",
762*7836SJohn.Forte@Sun.COM 					(wwnConversion(port_wwn_data)));
763*7836SJohn.Forte@Sun.COM 				(void) sprintf(&path_name[strlen(path_name)],
764*7836SJohn.Forte@Sun.COM 					"@w%s", port_wwn);
765*7836SJohn.Forte@Sun.COM 				S_FREE(port_wwn);
766*7836SJohn.Forte@Sun.COM 			}
767*7836SJohn.Forte@Sun.COM 		}
768*7836SJohn.Forte@Sun.COM 	}
769*7836SJohn.Forte@Sun.COM 
770*7836SJohn.Forte@Sun.COM 	devlen = strlen(DEVICES_DIR) + strlen(path_name) + 1;
771*7836SJohn.Forte@Sun.COM 	if ((*node_pathp = calloc(1, devlen)) == NULL) {
772*7836SJohn.Forte@Sun.COM 		*l_errnop = errno;
773*7836SJohn.Forte@Sun.COM 		return (FPCFGA_LIB_ERR);
774*7836SJohn.Forte@Sun.COM 	} else {
775*7836SJohn.Forte@Sun.COM 		(void) snprintf(*node_pathp, devlen,
776*7836SJohn.Forte@Sun.COM 		"%s%s", DEVICES_DIR, path_name);
777*7836SJohn.Forte@Sun.COM 	}
778*7836SJohn.Forte@Sun.COM 
779*7836SJohn.Forte@Sun.COM 	return (FPCFGA_OK);
780*7836SJohn.Forte@Sun.COM }
781*7836SJohn.Forte@Sun.COM 
782*7836SJohn.Forte@Sun.COM u_longlong_t
wwnConversion(uchar_t * wwn)783*7836SJohn.Forte@Sun.COM wwnConversion(uchar_t *wwn)
784*7836SJohn.Forte@Sun.COM {
785*7836SJohn.Forte@Sun.COM 	u_longlong_t tmp;
786*7836SJohn.Forte@Sun.COM 	memcpy(&tmp, wwn, sizeof (u_longlong_t));
787*7836SJohn.Forte@Sun.COM 	return (ntohll(tmp));
788*7836SJohn.Forte@Sun.COM }
789