19087SZhong.Wang@Sun.COM /*
29087SZhong.Wang@Sun.COM  * CDDL HEADER START
39087SZhong.Wang@Sun.COM  *
49087SZhong.Wang@Sun.COM  * The contents of this file are subject to the terms of the
59087SZhong.Wang@Sun.COM  * Common Development and Distribution License (the "License").
69087SZhong.Wang@Sun.COM  * You may not use this file except in compliance with the License.
79087SZhong.Wang@Sun.COM  *
89087SZhong.Wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99087SZhong.Wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109087SZhong.Wang@Sun.COM  * See the License for the specific language governing permissions
119087SZhong.Wang@Sun.COM  * and limitations under the License.
129087SZhong.Wang@Sun.COM  *
139087SZhong.Wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149087SZhong.Wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159087SZhong.Wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169087SZhong.Wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179087SZhong.Wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189087SZhong.Wang@Sun.COM  *
199087SZhong.Wang@Sun.COM  * CDDL HEADER END
209087SZhong.Wang@Sun.COM  */
219087SZhong.Wang@Sun.COM /*
229087SZhong.Wang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
239087SZhong.Wang@Sun.COM  * Use is subject to license terms.
249087SZhong.Wang@Sun.COM  */
259087SZhong.Wang@Sun.COM 
269087SZhong.Wang@Sun.COM #include <stdlib.h>
279087SZhong.Wang@Sun.COM #include <stdio.h>
289087SZhong.Wang@Sun.COM #include <wchar.h>
299087SZhong.Wang@Sun.COM #include <strings.h>
309087SZhong.Wang@Sun.COM #include <sys/types.h>
319087SZhong.Wang@Sun.COM #include <sys/stat.h>
329087SZhong.Wang@Sun.COM #include <fcntl.h>
339087SZhong.Wang@Sun.COM #include <unistd.h>
349087SZhong.Wang@Sun.COM #include <libintl.h>
359087SZhong.Wang@Sun.COM #include <errno.h>
369087SZhong.Wang@Sun.COM #include <string.h>
379087SZhong.Wang@Sun.COM #include <assert.h>
389087SZhong.Wang@Sun.COM #include <syslog.h>
399087SZhong.Wang@Sun.COM #include <libfcoe.h>
409307Skelly.hu@Sun.COM #include <libdllink.h>
419087SZhong.Wang@Sun.COM #include <fcoeio.h>
42*9895SKevin.Yu@Sun.COM #include <libscf.h>
43*9895SKevin.Yu@Sun.COM #include <inttypes.h>
449087SZhong.Wang@Sun.COM 
459087SZhong.Wang@Sun.COM #define	FCOE_DEV_PATH	 "/devices/fcoe:admin"
469087SZhong.Wang@Sun.COM 
479087SZhong.Wang@Sun.COM #define	OPEN_FCOE 0
489087SZhong.Wang@Sun.COM #define	OPEN_EXCL_FCOE O_EXCL
499087SZhong.Wang@Sun.COM 
509087SZhong.Wang@Sun.COM /*
519087SZhong.Wang@Sun.COM  * Open for fcoe module
529087SZhong.Wang@Sun.COM  *
539087SZhong.Wang@Sun.COM  * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE)
549087SZhong.Wang@Sun.COM  * fd - pointer to integer. On success, contains the fcoe file descriptor
559087SZhong.Wang@Sun.COM  */
569087SZhong.Wang@Sun.COM static int
579087SZhong.Wang@Sun.COM openFcoe(int flag, int *fd)
589087SZhong.Wang@Sun.COM {
599087SZhong.Wang@Sun.COM 	int ret = FCOE_STATUS_ERROR;
609087SZhong.Wang@Sun.COM 
619087SZhong.Wang@Sun.COM 	if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
629087SZhong.Wang@Sun.COM 		ret = FCOE_STATUS_OK;
639087SZhong.Wang@Sun.COM 	} else {
649087SZhong.Wang@Sun.COM 		if (errno == EPERM || errno == EACCES) {
659087SZhong.Wang@Sun.COM 			ret = FCOE_STATUS_ERROR_PERM;
669087SZhong.Wang@Sun.COM 		} else {
679087SZhong.Wang@Sun.COM 			ret = FCOE_STATUS_ERROR_OPEN_DEV;
689087SZhong.Wang@Sun.COM 		}
699087SZhong.Wang@Sun.COM 		syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)",
709087SZhong.Wang@Sun.COM 		    FCOE_DEV_PATH, errno);
719087SZhong.Wang@Sun.COM 	}
729087SZhong.Wang@Sun.COM 
739087SZhong.Wang@Sun.COM 	return (ret);
749087SZhong.Wang@Sun.COM }
759087SZhong.Wang@Sun.COM 
76*9895SKevin.Yu@Sun.COM static void
77*9895SKevin.Yu@Sun.COM WWN2str(char *buf, FCOE_PORT_WWN *wwn) {
78*9895SKevin.Yu@Sun.COM 	int j;
79*9895SKevin.Yu@Sun.COM 	unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
80*9895SKevin.Yu@Sun.COM 	buf[0] = '\0';
81*9895SKevin.Yu@Sun.COM 	for (j = 0; j < 16; j += 2) {
82*9895SKevin.Yu@Sun.COM 		(void) sprintf(&buf[j], "%02X", (int)*pc++);
83*9895SKevin.Yu@Sun.COM 	}
84*9895SKevin.Yu@Sun.COM }
85*9895SKevin.Yu@Sun.COM 
869087SZhong.Wang@Sun.COM static int
879087SZhong.Wang@Sun.COM isWWNZero(FCOE_PORT_WWN portwwn)
889087SZhong.Wang@Sun.COM {
899087SZhong.Wang@Sun.COM 	int i;
909087SZhong.Wang@Sun.COM 	int size = sizeof (FCOE_PORT_WWN);
919087SZhong.Wang@Sun.COM 
929087SZhong.Wang@Sun.COM 	for (i = 0; i < size; i++) {
939087SZhong.Wang@Sun.COM 		if (portwwn.wwn[i] != 0) {
949087SZhong.Wang@Sun.COM 			return (0);
959087SZhong.Wang@Sun.COM 		}
969087SZhong.Wang@Sun.COM 	}
979087SZhong.Wang@Sun.COM 	return (1);
989087SZhong.Wang@Sun.COM }
999087SZhong.Wang@Sun.COM 
100*9895SKevin.Yu@Sun.COM /*
101*9895SKevin.Yu@Sun.COM  * Initialize scf fcoe service access
102*9895SKevin.Yu@Sun.COM  * handle - returned handle
103*9895SKevin.Yu@Sun.COM  * service - returned service handle
104*9895SKevin.Yu@Sun.COM  */
105*9895SKevin.Yu@Sun.COM static int
106*9895SKevin.Yu@Sun.COM fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service, int is_target)
107*9895SKevin.Yu@Sun.COM {
108*9895SKevin.Yu@Sun.COM 	scf_scope_t	*scope = NULL;
109*9895SKevin.Yu@Sun.COM 	int		ret;
110*9895SKevin.Yu@Sun.COM 
111*9895SKevin.Yu@Sun.COM 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
112*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_handle_create failed - %s",
113*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
114*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
115*9895SKevin.Yu@Sun.COM 		goto err;
116*9895SKevin.Yu@Sun.COM 	}
117*9895SKevin.Yu@Sun.COM 
118*9895SKevin.Yu@Sun.COM 	if (scf_handle_bind(*handle) == -1) {
119*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
120*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
121*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
122*9895SKevin.Yu@Sun.COM 		goto err;
123*9895SKevin.Yu@Sun.COM 	}
124*9895SKevin.Yu@Sun.COM 
125*9895SKevin.Yu@Sun.COM 	if ((*service = scf_service_create(*handle)) == NULL) {
126*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_service_create failed - %s",
127*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
128*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
129*9895SKevin.Yu@Sun.COM 		goto err;
130*9895SKevin.Yu@Sun.COM 	}
131*9895SKevin.Yu@Sun.COM 
132*9895SKevin.Yu@Sun.COM 	if ((scope = scf_scope_create(*handle)) == NULL) {
133*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_scope_create failed - %s",
134*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
135*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
136*9895SKevin.Yu@Sun.COM 		goto err;
137*9895SKevin.Yu@Sun.COM 	}
138*9895SKevin.Yu@Sun.COM 
139*9895SKevin.Yu@Sun.COM 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
140*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
141*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
142*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
143*9895SKevin.Yu@Sun.COM 		goto err;
144*9895SKevin.Yu@Sun.COM 	}
145*9895SKevin.Yu@Sun.COM 
146*9895SKevin.Yu@Sun.COM 	if (scf_scope_get_service(scope,
147*9895SKevin.Yu@Sun.COM 	    is_target ? FCOE_TARGET_SERVICE: FCOE_INITIATOR_SERVICE,
148*9895SKevin.Yu@Sun.COM 	    *service) == -1) {
149*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
150*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
151*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR_SERVICE_NOT_FOUND;
152*9895SKevin.Yu@Sun.COM 		goto err;
153*9895SKevin.Yu@Sun.COM 	}
154*9895SKevin.Yu@Sun.COM 
155*9895SKevin.Yu@Sun.COM 	scf_scope_destroy(scope);
156*9895SKevin.Yu@Sun.COM 
157*9895SKevin.Yu@Sun.COM 	return (FCOE_SUCCESS);
158*9895SKevin.Yu@Sun.COM 
159*9895SKevin.Yu@Sun.COM err:
160*9895SKevin.Yu@Sun.COM 	if (*handle != NULL) {
161*9895SKevin.Yu@Sun.COM 		scf_handle_destroy(*handle);
162*9895SKevin.Yu@Sun.COM 	}
163*9895SKevin.Yu@Sun.COM 	if (*service != NULL) {
164*9895SKevin.Yu@Sun.COM 		scf_service_destroy(*service);
165*9895SKevin.Yu@Sun.COM 		*service = NULL;
166*9895SKevin.Yu@Sun.COM 	}
167*9895SKevin.Yu@Sun.COM 	if (scope != NULL) {
168*9895SKevin.Yu@Sun.COM 		scf_scope_destroy(scope);
169*9895SKevin.Yu@Sun.COM 	}
170*9895SKevin.Yu@Sun.COM 	return (ret);
171*9895SKevin.Yu@Sun.COM }
172*9895SKevin.Yu@Sun.COM 
173*9895SKevin.Yu@Sun.COM static int
174*9895SKevin.Yu@Sun.COM fcoe_add_remove_scf_entry(char *mac_name,
175*9895SKevin.Yu@Sun.COM     char *pwwn, char *nwwn,
176*9895SKevin.Yu@Sun.COM     int is_target, int is_promiscuous, int addRemoveFlag)
177*9895SKevin.Yu@Sun.COM {
178*9895SKevin.Yu@Sun.COM 	scf_handle_t	*handle = NULL;
179*9895SKevin.Yu@Sun.COM 	scf_service_t	*svc = NULL;
180*9895SKevin.Yu@Sun.COM 	scf_propertygroup_t	*pg = NULL;
181*9895SKevin.Yu@Sun.COM 	scf_transaction_t	*tran = NULL;
182*9895SKevin.Yu@Sun.COM 	scf_transaction_entry_t	*entry = NULL;
183*9895SKevin.Yu@Sun.COM 	scf_property_t	*prop = NULL;
184*9895SKevin.Yu@Sun.COM 	scf_value_t	*valueLookup = NULL;
185*9895SKevin.Yu@Sun.COM 	scf_iter_t	*valueIter = NULL;
186*9895SKevin.Yu@Sun.COM 	scf_value_t	**valueSet = NULL;
187*9895SKevin.Yu@Sun.COM 	int	ret = FCOE_SUCCESS;
188*9895SKevin.Yu@Sun.COM 	boolean_t	createProp = B_FALSE;
189*9895SKevin.Yu@Sun.COM 	int	lastAlloc = 0;
190*9895SKevin.Yu@Sun.COM 	char	buf[FCOE_PORT_LIST_LENGTH] = {0};
191*9895SKevin.Yu@Sun.COM 	char	memberName[FCOE_PORT_LIST_LENGTH] = {0};
192*9895SKevin.Yu@Sun.COM 	boolean_t	found = B_FALSE;
193*9895SKevin.Yu@Sun.COM 	int	i = 0;
194*9895SKevin.Yu@Sun.COM 	int	valueArraySize = 0;
195*9895SKevin.Yu@Sun.COM 	int	commitRet;
196*9895SKevin.Yu@Sun.COM 	int portListAlloc = 100;
197*9895SKevin.Yu@Sun.COM 
198*9895SKevin.Yu@Sun.COM 	(void) snprintf(memberName, FCOE_PORT_LIST_LENGTH,
199*9895SKevin.Yu@Sun.COM 	    "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn,
200*9895SKevin.Yu@Sun.COM 	    is_target, is_promiscuous);
201*9895SKevin.Yu@Sun.COM 
202*9895SKevin.Yu@Sun.COM 	ret = fcoe_cfg_scf_init(&handle, &svc, is_target);
203*9895SKevin.Yu@Sun.COM 	if (ret != FCOE_SUCCESS) {
204*9895SKevin.Yu@Sun.COM 		goto out;
205*9895SKevin.Yu@Sun.COM 	}
206*9895SKevin.Yu@Sun.COM 
207*9895SKevin.Yu@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
208*9895SKevin.Yu@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
209*9895SKevin.Yu@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
210*9895SKevin.Yu@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
211*9895SKevin.Yu@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
212*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
213*9895SKevin.Yu@Sun.COM 		goto out;
214*9895SKevin.Yu@Sun.COM 	}
215*9895SKevin.Yu@Sun.COM 
216*9895SKevin.Yu@Sun.COM 	/* get property group or create it */
217*9895SKevin.Yu@Sun.COM 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
218*9895SKevin.Yu@Sun.COM 		if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
219*9895SKevin.Yu@Sun.COM 			if (scf_service_add_pg(svc, FCOE_PG_NAME,
220*9895SKevin.Yu@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
221*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
222*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
223*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
224*9895SKevin.Yu@Sun.COM 			} else {
225*9895SKevin.Yu@Sun.COM 				createProp = B_TRUE;
226*9895SKevin.Yu@Sun.COM 			}
227*9895SKevin.Yu@Sun.COM 		} else {
228*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
229*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
230*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
231*9895SKevin.Yu@Sun.COM 		}
232*9895SKevin.Yu@Sun.COM 		if (ret != FCOE_SUCCESS) {
233*9895SKevin.Yu@Sun.COM 			goto out;
234*9895SKevin.Yu@Sun.COM 		}
235*9895SKevin.Yu@Sun.COM 	}
236*9895SKevin.Yu@Sun.COM 
237*9895SKevin.Yu@Sun.COM 	/* to make sure property exists */
238*9895SKevin.Yu@Sun.COM 	if (createProp == B_FALSE) {
239*9895SKevin.Yu@Sun.COM 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
240*9895SKevin.Yu@Sun.COM 			if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
241*9895SKevin.Yu@Sun.COM 				createProp = B_TRUE;
242*9895SKevin.Yu@Sun.COM 			} else {
243*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "get property failed - %s",
244*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
245*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
246*9895SKevin.Yu@Sun.COM 				goto out;
247*9895SKevin.Yu@Sun.COM 			}
248*9895SKevin.Yu@Sun.COM 		}
249*9895SKevin.Yu@Sun.COM 	}
250*9895SKevin.Yu@Sun.COM 
251*9895SKevin.Yu@Sun.COM 	/* Begin the transaction */
252*9895SKevin.Yu@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
253*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
254*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
255*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR;
256*9895SKevin.Yu@Sun.COM 		goto out;
257*9895SKevin.Yu@Sun.COM 	}
258*9895SKevin.Yu@Sun.COM 
259*9895SKevin.Yu@Sun.COM 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
260*9895SKevin.Yu@Sun.COM 	    * (lastAlloc = portListAlloc));
261*9895SKevin.Yu@Sun.COM 	if (valueSet == NULL) {
262*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR_NOMEM;
263*9895SKevin.Yu@Sun.COM 		goto out;
264*9895SKevin.Yu@Sun.COM 	}
265*9895SKevin.Yu@Sun.COM 
266*9895SKevin.Yu@Sun.COM 	if (createProp) {
267*9895SKevin.Yu@Sun.COM 		if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST,
268*9895SKevin.Yu@Sun.COM 		    SCF_TYPE_USTRING) == -1) {
269*9895SKevin.Yu@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
270*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR_EXISTS;
271*9895SKevin.Yu@Sun.COM 			} else {
272*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR,
273*9895SKevin.Yu@Sun.COM 				    "transaction property new failed - %s",
274*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
275*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
276*9895SKevin.Yu@Sun.COM 			}
277*9895SKevin.Yu@Sun.COM 			goto out;
278*9895SKevin.Yu@Sun.COM 		}
279*9895SKevin.Yu@Sun.COM 	} else {
280*9895SKevin.Yu@Sun.COM 		if (scf_transaction_property_change(tran, entry,
281*9895SKevin.Yu@Sun.COM 		    FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) {
282*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR,
283*9895SKevin.Yu@Sun.COM 			    "transaction property change failed - %s",
284*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
285*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
286*9895SKevin.Yu@Sun.COM 			goto out;
287*9895SKevin.Yu@Sun.COM 		}
288*9895SKevin.Yu@Sun.COM 
289*9895SKevin.Yu@Sun.COM 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
290*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
291*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
292*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
293*9895SKevin.Yu@Sun.COM 			goto out;
294*9895SKevin.Yu@Sun.COM 		}
295*9895SKevin.Yu@Sun.COM 
296*9895SKevin.Yu@Sun.COM 		valueLookup = scf_value_create(handle);
297*9895SKevin.Yu@Sun.COM 		if (valueLookup == NULL) {
298*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
299*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
300*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
301*9895SKevin.Yu@Sun.COM 			goto out;
302*9895SKevin.Yu@Sun.COM 		}
303*9895SKevin.Yu@Sun.COM 
304*9895SKevin.Yu@Sun.COM 		if (scf_iter_property_values(valueIter, prop) == -1) {
305*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
306*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
307*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
308*9895SKevin.Yu@Sun.COM 			goto out;
309*9895SKevin.Yu@Sun.COM 		}
310*9895SKevin.Yu@Sun.COM 
311*9895SKevin.Yu@Sun.COM 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
312*9895SKevin.Yu@Sun.COM 			char *macnameIter = NULL;
313*9895SKevin.Yu@Sun.COM 			char buftmp[FCOE_PORT_LIST_LENGTH] = {0};
314*9895SKevin.Yu@Sun.COM 
315*9895SKevin.Yu@Sun.COM 			bzero(buf, sizeof (buf));
316*9895SKevin.Yu@Sun.COM 			if (scf_value_get_ustring(valueLookup,
317*9895SKevin.Yu@Sun.COM 			    buf, MAXNAMELEN) == -1) {
318*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "iter value failed- %s",
319*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
320*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
321*9895SKevin.Yu@Sun.COM 				break;
322*9895SKevin.Yu@Sun.COM 			}
323*9895SKevin.Yu@Sun.COM 			(void) strcpy(buftmp, buf);
324*9895SKevin.Yu@Sun.COM 			macnameIter = strtok(buftmp, ":");
325*9895SKevin.Yu@Sun.COM 			if (strcmp(macnameIter, mac_name) == 0) {
326*9895SKevin.Yu@Sun.COM 				if (addRemoveFlag == FCOE_SCF_ADD) {
327*9895SKevin.Yu@Sun.COM 					ret = FCOE_ERROR_EXISTS;
328*9895SKevin.Yu@Sun.COM 					break;
329*9895SKevin.Yu@Sun.COM 				} else {
330*9895SKevin.Yu@Sun.COM 					found = B_TRUE;
331*9895SKevin.Yu@Sun.COM 					continue;
332*9895SKevin.Yu@Sun.COM 				}
333*9895SKevin.Yu@Sun.COM 			}
334*9895SKevin.Yu@Sun.COM 
335*9895SKevin.Yu@Sun.COM 			valueSet[i] = scf_value_create(handle);
336*9895SKevin.Yu@Sun.COM 			if (valueSet[i] == NULL) {
337*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "scf value alloc failed - %s",
338*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
339*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
340*9895SKevin.Yu@Sun.COM 				break;
341*9895SKevin.Yu@Sun.COM 			}
342*9895SKevin.Yu@Sun.COM 
343*9895SKevin.Yu@Sun.COM 			if (scf_value_set_ustring(valueSet[i], buf) == -1) {
344*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "set value failed 1- %s",
345*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
346*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
347*9895SKevin.Yu@Sun.COM 				break;
348*9895SKevin.Yu@Sun.COM 			}
349*9895SKevin.Yu@Sun.COM 
350*9895SKevin.Yu@Sun.COM 			if (scf_entry_add_value(entry, valueSet[i]) == -1) {
351*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "add value failed - %s",
352*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
353*9895SKevin.Yu@Sun.COM 				ret = FCOE_ERROR;
354*9895SKevin.Yu@Sun.COM 				break;
355*9895SKevin.Yu@Sun.COM 			}
356*9895SKevin.Yu@Sun.COM 
357*9895SKevin.Yu@Sun.COM 			i++;
358*9895SKevin.Yu@Sun.COM 
359*9895SKevin.Yu@Sun.COM 			if (i >= lastAlloc) {
360*9895SKevin.Yu@Sun.COM 				lastAlloc += portListAlloc;
361*9895SKevin.Yu@Sun.COM 				valueSet = realloc(valueSet,
362*9895SKevin.Yu@Sun.COM 				    sizeof (*valueSet) * lastAlloc);
363*9895SKevin.Yu@Sun.COM 				if (valueSet == NULL) {
364*9895SKevin.Yu@Sun.COM 					ret = FCOE_ERROR;
365*9895SKevin.Yu@Sun.COM 					break;
366*9895SKevin.Yu@Sun.COM 				}
367*9895SKevin.Yu@Sun.COM 			}
368*9895SKevin.Yu@Sun.COM 		}
369*9895SKevin.Yu@Sun.COM 	}
370*9895SKevin.Yu@Sun.COM 
371*9895SKevin.Yu@Sun.COM 	valueArraySize = i;
372*9895SKevin.Yu@Sun.COM 	if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) {
373*9895SKevin.Yu@Sun.COM 		ret = FCOE_ERROR_MEMBER_NOT_FOUND;
374*9895SKevin.Yu@Sun.COM 	}
375*9895SKevin.Yu@Sun.COM 	if (ret != FCOE_SUCCESS) {
376*9895SKevin.Yu@Sun.COM 		goto out;
377*9895SKevin.Yu@Sun.COM 	}
378*9895SKevin.Yu@Sun.COM 
379*9895SKevin.Yu@Sun.COM 	if (addRemoveFlag == FCOE_SCF_ADD) {
380*9895SKevin.Yu@Sun.COM 		/*
381*9895SKevin.Yu@Sun.COM 		 * Now create the new entry
382*9895SKevin.Yu@Sun.COM 		 */
383*9895SKevin.Yu@Sun.COM 		valueSet[i] = scf_value_create(handle);
384*9895SKevin.Yu@Sun.COM 		if (valueSet[i] == NULL) {
385*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
386*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
387*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
388*9895SKevin.Yu@Sun.COM 			goto out;
389*9895SKevin.Yu@Sun.COM 		} else {
390*9895SKevin.Yu@Sun.COM 			valueArraySize++;
391*9895SKevin.Yu@Sun.COM 		}
392*9895SKevin.Yu@Sun.COM 
393*9895SKevin.Yu@Sun.COM 		/*
394*9895SKevin.Yu@Sun.COM 		 * Set the new member name
395*9895SKevin.Yu@Sun.COM 		 */
396*9895SKevin.Yu@Sun.COM 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
397*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "set value failed 2- %s",
398*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
399*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
400*9895SKevin.Yu@Sun.COM 			goto out;
401*9895SKevin.Yu@Sun.COM 		}
402*9895SKevin.Yu@Sun.COM 
403*9895SKevin.Yu@Sun.COM 		/*
404*9895SKevin.Yu@Sun.COM 		 * Add the new member
405*9895SKevin.Yu@Sun.COM 		 */
406*9895SKevin.Yu@Sun.COM 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
407*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
408*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
409*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
410*9895SKevin.Yu@Sun.COM 			goto out;
411*9895SKevin.Yu@Sun.COM 		}
412*9895SKevin.Yu@Sun.COM 	}
413*9895SKevin.Yu@Sun.COM 
414*9895SKevin.Yu@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
415*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
416*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
417*9895SKevin.Yu@Sun.COM 		if (commitRet == 0) {
418*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR_BUSY;
419*9895SKevin.Yu@Sun.COM 		} else {
420*9895SKevin.Yu@Sun.COM 			ret = FCOE_ERROR;
421*9895SKevin.Yu@Sun.COM 		}
422*9895SKevin.Yu@Sun.COM 		goto out;
423*9895SKevin.Yu@Sun.COM 	}
424*9895SKevin.Yu@Sun.COM 
425*9895SKevin.Yu@Sun.COM out:
426*9895SKevin.Yu@Sun.COM 	/*
427*9895SKevin.Yu@Sun.COM 	 * Free resources
428*9895SKevin.Yu@Sun.COM 	 */
429*9895SKevin.Yu@Sun.COM 	if (handle != NULL) {
430*9895SKevin.Yu@Sun.COM 		scf_handle_destroy(handle);
431*9895SKevin.Yu@Sun.COM 	}
432*9895SKevin.Yu@Sun.COM 	if (svc != NULL) {
433*9895SKevin.Yu@Sun.COM 		scf_service_destroy(svc);
434*9895SKevin.Yu@Sun.COM 	}
435*9895SKevin.Yu@Sun.COM 	if (pg != NULL) {
436*9895SKevin.Yu@Sun.COM 		scf_pg_destroy(pg);
437*9895SKevin.Yu@Sun.COM 	}
438*9895SKevin.Yu@Sun.COM 	if (tran != NULL) {
439*9895SKevin.Yu@Sun.COM 		scf_transaction_destroy(tran);
440*9895SKevin.Yu@Sun.COM 	}
441*9895SKevin.Yu@Sun.COM 	if (entry != NULL) {
442*9895SKevin.Yu@Sun.COM 		scf_entry_destroy(entry);
443*9895SKevin.Yu@Sun.COM 	}
444*9895SKevin.Yu@Sun.COM 	if (prop != NULL) {
445*9895SKevin.Yu@Sun.COM 		scf_property_destroy(prop);
446*9895SKevin.Yu@Sun.COM 	}
447*9895SKevin.Yu@Sun.COM 	if (valueIter != NULL) {
448*9895SKevin.Yu@Sun.COM 		scf_iter_destroy(valueIter);
449*9895SKevin.Yu@Sun.COM 	}
450*9895SKevin.Yu@Sun.COM 	if (valueLookup != NULL) {
451*9895SKevin.Yu@Sun.COM 		scf_value_destroy(valueLookup);
452*9895SKevin.Yu@Sun.COM 	}
453*9895SKevin.Yu@Sun.COM 
454*9895SKevin.Yu@Sun.COM 	/*
455*9895SKevin.Yu@Sun.COM 	 * Free valueSet scf resources
456*9895SKevin.Yu@Sun.COM 	 */
457*9895SKevin.Yu@Sun.COM 	if (valueArraySize > 0) {
458*9895SKevin.Yu@Sun.COM 		for (i = 0; i < valueArraySize; i++) {
459*9895SKevin.Yu@Sun.COM 			scf_value_destroy(valueSet[i]);
460*9895SKevin.Yu@Sun.COM 		}
461*9895SKevin.Yu@Sun.COM 	}
462*9895SKevin.Yu@Sun.COM 	/*
463*9895SKevin.Yu@Sun.COM 	 * Now free the pointer array to the resources
464*9895SKevin.Yu@Sun.COM 	 */
465*9895SKevin.Yu@Sun.COM 	if (valueSet != NULL) {
466*9895SKevin.Yu@Sun.COM 		free(valueSet);
467*9895SKevin.Yu@Sun.COM 	}
468*9895SKevin.Yu@Sun.COM 
469*9895SKevin.Yu@Sun.COM 	return (ret);
470*9895SKevin.Yu@Sun.COM }
471*9895SKevin.Yu@Sun.COM 
4729087SZhong.Wang@Sun.COM FCOE_STATUS
4739087SZhong.Wang@Sun.COM FCOE_CreatePort(
4749087SZhong.Wang@Sun.COM 	const FCOE_UINT8		*macLinkName,
4759087SZhong.Wang@Sun.COM 	FCOE_UINT8		portType,
4769087SZhong.Wang@Sun.COM 	FCOE_PORT_WWN		pwwn,
4779087SZhong.Wang@Sun.COM 	FCOE_PORT_WWN		nwwn,
4789087SZhong.Wang@Sun.COM 	FCOE_UINT8		promiscuous)
4799087SZhong.Wang@Sun.COM {
480*9895SKevin.Yu@Sun.COM 	FCOE_STATUS		status;
4819307Skelly.hu@Sun.COM 	int			fcoe_fd;
4829307Skelly.hu@Sun.COM 	fcoeio_t		fcoeio;
4839087SZhong.Wang@Sun.COM 	fcoeio_create_port_param_t	param;
4849307Skelly.hu@Sun.COM 	dladm_handle_t		handle;
4859307Skelly.hu@Sun.COM 	datalink_id_t		linkid;
4869307Skelly.hu@Sun.COM 	datalink_class_t	class;
4879087SZhong.Wang@Sun.COM 
4889087SZhong.Wang@Sun.COM 	bzero(&param, sizeof (fcoeio_create_port_param_t));
4899087SZhong.Wang@Sun.COM 
4909087SZhong.Wang@Sun.COM 	if (macLinkName == NULL) {
4919087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_INVAL_ARG);
4929087SZhong.Wang@Sun.COM 	}
4939087SZhong.Wang@Sun.COM 
4949307Skelly.hu@Sun.COM 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
4959307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR_MAC_LEN);
4969307Skelly.hu@Sun.COM 	}
4979307Skelly.hu@Sun.COM 
4989307Skelly.hu@Sun.COM 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
4999307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR);
5009307Skelly.hu@Sun.COM 	}
5019307Skelly.hu@Sun.COM 
5029307Skelly.hu@Sun.COM 	if (dladm_name2info(handle, (const char *)macLinkName,
5039307Skelly.hu@Sun.COM 	    &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) {
5049307Skelly.hu@Sun.COM 		dladm_close(handle);
505*9895SKevin.Yu@Sun.COM 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
506*9895SKevin.Yu@Sun.COM 		    "",
507*9895SKevin.Yu@Sun.COM 		    "",
508*9895SKevin.Yu@Sun.COM 		    portType,
509*9895SKevin.Yu@Sun.COM 		    0,
510*9895SKevin.Yu@Sun.COM 		    FCOE_SCF_REMOVE);
5119307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
5129307Skelly.hu@Sun.COM 	}
5139307Skelly.hu@Sun.COM 	dladm_close(handle);
5149307Skelly.hu@Sun.COM 
5159307Skelly.hu@Sun.COM 	if (class != DATALINK_CLASS_PHYS) {
5169307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT);
5179307Skelly.hu@Sun.COM 	}
5189307Skelly.hu@Sun.COM 
5199087SZhong.Wang@Sun.COM 	if (portType != FCOE_PORTTYPE_INITIATOR &&
5209087SZhong.Wang@Sun.COM 	    portType != FCOE_PORTTYPE_TARGET) {
5219087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_INVAL_ARG);
5229087SZhong.Wang@Sun.COM 	}
5239087SZhong.Wang@Sun.COM 
5249087SZhong.Wang@Sun.COM 	if (!isWWNZero(pwwn)) {
5259087SZhong.Wang@Sun.COM 		param.fcp_pwwn_provided = 1;
5269087SZhong.Wang@Sun.COM 		bcopy(pwwn.wwn, param.fcp_pwwn, 8);
5279087SZhong.Wang@Sun.COM 	}
5289087SZhong.Wang@Sun.COM 
5299087SZhong.Wang@Sun.COM 	if (!isWWNZero(nwwn)) {
5309087SZhong.Wang@Sun.COM 		param.fcp_nwwn_provided = 1;
5319087SZhong.Wang@Sun.COM 		bcopy(nwwn.wwn, param.fcp_nwwn, 8);
5329087SZhong.Wang@Sun.COM 	}
5339087SZhong.Wang@Sun.COM 
5349087SZhong.Wang@Sun.COM 	if (param.fcp_pwwn_provided == 1 &&
5359087SZhong.Wang@Sun.COM 	    param.fcp_nwwn_provided == 1 &&
5369087SZhong.Wang@Sun.COM 	    bcmp(&pwwn, &nwwn, 8) == 0) {
5379087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_WWN_SAME);
5389087SZhong.Wang@Sun.COM 	}
5399087SZhong.Wang@Sun.COM 
5409087SZhong.Wang@Sun.COM 	param.fcp_force_promisc = promiscuous;
5419307Skelly.hu@Sun.COM 	param.fcp_mac_linkid = linkid;
5429087SZhong.Wang@Sun.COM 	param.fcp_port_type = (fcoe_cli_type_t)portType;
5439087SZhong.Wang@Sun.COM 
5449087SZhong.Wang@Sun.COM 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
5459087SZhong.Wang@Sun.COM 		return (status);
5469087SZhong.Wang@Sun.COM 	}
5479087SZhong.Wang@Sun.COM 
5489087SZhong.Wang@Sun.COM 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
5499087SZhong.Wang@Sun.COM 	fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT;
5509087SZhong.Wang@Sun.COM 
5519087SZhong.Wang@Sun.COM 	fcoeio.fcoeio_ilen = sizeof (param);
5529087SZhong.Wang@Sun.COM 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
5539087SZhong.Wang@Sun.COM 	fcoeio.fcoeio_ibuf = (uintptr_t)&param;
5549087SZhong.Wang@Sun.COM 
5559087SZhong.Wang@Sun.COM 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
5569087SZhong.Wang@Sun.COM 		switch (fcoeio.fcoeio_status) {
5579087SZhong.Wang@Sun.COM 		case FCOEIOE_INVAL_ARG:
5589087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_INVAL_ARG;
5599087SZhong.Wang@Sun.COM 			break;
5609087SZhong.Wang@Sun.COM 
5619087SZhong.Wang@Sun.COM 		case FCOEIOE_BUSY:
5629087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_BUSY;
5639087SZhong.Wang@Sun.COM 			break;
5649087SZhong.Wang@Sun.COM 
5659087SZhong.Wang@Sun.COM 		case FCOEIOE_ALREADY:
5669087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_ALREADY;
5679087SZhong.Wang@Sun.COM 			break;
5689087SZhong.Wang@Sun.COM 
5699087SZhong.Wang@Sun.COM 		case FCOEIOE_PWWN_CONFLICTED:
5709087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_PWWN_CONFLICTED;
5719087SZhong.Wang@Sun.COM 			break;
5729087SZhong.Wang@Sun.COM 
5739087SZhong.Wang@Sun.COM 		case FCOEIOE_NWWN_CONFLICTED:
5749087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_NWWN_CONFLICTED;
5759087SZhong.Wang@Sun.COM 			break;
5769087SZhong.Wang@Sun.COM 
5779087SZhong.Wang@Sun.COM 		case FCOEIOE_CREATE_MAC:
5789087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_CREATE_MAC;
5799087SZhong.Wang@Sun.COM 			break;
5809087SZhong.Wang@Sun.COM 
5819087SZhong.Wang@Sun.COM 		case FCOEIOE_OPEN_MAC:
5829087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_OPEN_MAC;
5839087SZhong.Wang@Sun.COM 			break;
5849087SZhong.Wang@Sun.COM 
5859087SZhong.Wang@Sun.COM 		case FCOEIOE_CREATE_PORT:
5869087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_CREATE_PORT;
5879087SZhong.Wang@Sun.COM 			break;
5889087SZhong.Wang@Sun.COM 
5899087SZhong.Wang@Sun.COM 		case FCOEIOE_NEED_JUMBO_FRAME:
5909087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME;
5919087SZhong.Wang@Sun.COM 			break;
5929087SZhong.Wang@Sun.COM 
5939087SZhong.Wang@Sun.COM 		default:
5949087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR;
5959087SZhong.Wang@Sun.COM 		}
5969087SZhong.Wang@Sun.COM 	} else {
597*9895SKevin.Yu@Sun.COM 		char cpwwn[17], cnwwn[17];
598*9895SKevin.Yu@Sun.COM 
599*9895SKevin.Yu@Sun.COM 		WWN2str(cpwwn, &pwwn);
600*9895SKevin.Yu@Sun.COM 		WWN2str(cnwwn, &nwwn);
601*9895SKevin.Yu@Sun.COM 
602*9895SKevin.Yu@Sun.COM 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
603*9895SKevin.Yu@Sun.COM 		    cpwwn,
604*9895SKevin.Yu@Sun.COM 		    cnwwn,
605*9895SKevin.Yu@Sun.COM 		    portType,
606*9895SKevin.Yu@Sun.COM 		    promiscuous,
607*9895SKevin.Yu@Sun.COM 		    FCOE_SCF_ADD);
6089087SZhong.Wang@Sun.COM 		status = FCOE_STATUS_OK;
6099087SZhong.Wang@Sun.COM 	}
6109087SZhong.Wang@Sun.COM 	(void) close(fcoe_fd);
6119087SZhong.Wang@Sun.COM 	return (status);
6129087SZhong.Wang@Sun.COM }
6139087SZhong.Wang@Sun.COM 
6149087SZhong.Wang@Sun.COM FCOE_STATUS
6159087SZhong.Wang@Sun.COM FCOE_DeletePort(const FCOE_UINT8 *macLinkName)
6169087SZhong.Wang@Sun.COM {
6179087SZhong.Wang@Sun.COM 	FCOE_STATUS status = FCOE_STATUS_OK;
6189087SZhong.Wang@Sun.COM 	int fcoe_fd;
6199087SZhong.Wang@Sun.COM 	fcoeio_t	fcoeio;
6209307Skelly.hu@Sun.COM 	dladm_handle_t		handle;
6219307Skelly.hu@Sun.COM 	datalink_id_t		linkid;
6229307Skelly.hu@Sun.COM 	fcoeio_delete_port_param_t fc_del_port;
623*9895SKevin.Yu@Sun.COM 	uint64_t	is_target = 0;
624*9895SKevin.Yu@Sun.COM 	int		io_ret = 0;
6259087SZhong.Wang@Sun.COM 
6269087SZhong.Wang@Sun.COM 	if (macLinkName == NULL) {
6279087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_INVAL_ARG);
6289087SZhong.Wang@Sun.COM 	}
6299087SZhong.Wang@Sun.COM 
6309307Skelly.hu@Sun.COM 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
6319087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_MAC_LEN);
6329087SZhong.Wang@Sun.COM 	}
6339307Skelly.hu@Sun.COM 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
6349307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR);
6359307Skelly.hu@Sun.COM 	}
6369307Skelly.hu@Sun.COM 
6379307Skelly.hu@Sun.COM 	if (dladm_name2info(handle, (const char *)macLinkName,
6389307Skelly.hu@Sun.COM 	    &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) {
6399307Skelly.hu@Sun.COM 		dladm_close(handle);
6409307Skelly.hu@Sun.COM 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
6419307Skelly.hu@Sun.COM 	}
6429307Skelly.hu@Sun.COM 	dladm_close(handle);
6439087SZhong.Wang@Sun.COM 
6449087SZhong.Wang@Sun.COM 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
6459087SZhong.Wang@Sun.COM 		return (status);
6469087SZhong.Wang@Sun.COM 	}
6479087SZhong.Wang@Sun.COM 
6489307Skelly.hu@Sun.COM 	fc_del_port.fdp_mac_linkid = linkid;
6499307Skelly.hu@Sun.COM 
6509087SZhong.Wang@Sun.COM 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
6519087SZhong.Wang@Sun.COM 	fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT;
6529087SZhong.Wang@Sun.COM 
6539307Skelly.hu@Sun.COM 	/* only 4 bytes here, need to change */
6549307Skelly.hu@Sun.COM 	fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t);
655*9895SKevin.Yu@Sun.COM 	fcoeio.fcoeio_olen = sizeof (uint64_t);
656*9895SKevin.Yu@Sun.COM 	fcoeio.fcoeio_xfer = FCOEIO_XFER_RW;
6579307Skelly.hu@Sun.COM 	fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port;
658*9895SKevin.Yu@Sun.COM 	fcoeio.fcoeio_obuf = (uintptr_t)&is_target;
6599087SZhong.Wang@Sun.COM 
660*9895SKevin.Yu@Sun.COM 	io_ret = ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio);
661*9895SKevin.Yu@Sun.COM 	if (io_ret != 0) {
6629087SZhong.Wang@Sun.COM 		switch (fcoeio.fcoeio_status) {
6639087SZhong.Wang@Sun.COM 		case FCOEIOE_INVAL_ARG:
6649087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_INVAL_ARG;
6659087SZhong.Wang@Sun.COM 			break;
6669087SZhong.Wang@Sun.COM 
6679087SZhong.Wang@Sun.COM 		case FCOEIOE_BUSY:
6689087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_BUSY;
6699087SZhong.Wang@Sun.COM 			break;
6709087SZhong.Wang@Sun.COM 
6719087SZhong.Wang@Sun.COM 		case FCOEIOE_ALREADY:
6729087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_ALREADY;
6739087SZhong.Wang@Sun.COM 			break;
6749087SZhong.Wang@Sun.COM 
6759087SZhong.Wang@Sun.COM 		case FCOEIOE_MAC_NOT_FOUND:
6769087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_MAC_NOT_FOUND;
6779087SZhong.Wang@Sun.COM 			break;
6789087SZhong.Wang@Sun.COM 
6799087SZhong.Wang@Sun.COM 		case FCOEIOE_OFFLINE_FAILURE:
6809087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR_OFFLINE_DEV;
6819087SZhong.Wang@Sun.COM 			break;
6829087SZhong.Wang@Sun.COM 
6839087SZhong.Wang@Sun.COM 		default:
6849087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_ERROR;
6859087SZhong.Wang@Sun.COM 		}
6869087SZhong.Wang@Sun.COM 	} else {
687*9895SKevin.Yu@Sun.COM 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
688*9895SKevin.Yu@Sun.COM 		    "",
689*9895SKevin.Yu@Sun.COM 		    "",
690*9895SKevin.Yu@Sun.COM 		    is_target,
691*9895SKevin.Yu@Sun.COM 		    0,
692*9895SKevin.Yu@Sun.COM 		    FCOE_SCF_REMOVE);
6939087SZhong.Wang@Sun.COM 		status = FCOE_STATUS_OK;
6949087SZhong.Wang@Sun.COM 	}
695*9895SKevin.Yu@Sun.COM 
696*9895SKevin.Yu@Sun.COM 	if (io_ret == FCOEIOE_MAC_NOT_FOUND) {
697*9895SKevin.Yu@Sun.COM 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
698*9895SKevin.Yu@Sun.COM 		    "",
699*9895SKevin.Yu@Sun.COM 		    "",
700*9895SKevin.Yu@Sun.COM 		    0,
701*9895SKevin.Yu@Sun.COM 		    0,
702*9895SKevin.Yu@Sun.COM 		    FCOE_SCF_REMOVE);
703*9895SKevin.Yu@Sun.COM 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
704*9895SKevin.Yu@Sun.COM 		    "",
705*9895SKevin.Yu@Sun.COM 		    "",
706*9895SKevin.Yu@Sun.COM 		    1,
707*9895SKevin.Yu@Sun.COM 		    0,
708*9895SKevin.Yu@Sun.COM 		    FCOE_SCF_REMOVE);
709*9895SKevin.Yu@Sun.COM 	}
7109087SZhong.Wang@Sun.COM 	(void) close(fcoe_fd);
7119087SZhong.Wang@Sun.COM 	return (status);
7129087SZhong.Wang@Sun.COM }
7139087SZhong.Wang@Sun.COM 
7149087SZhong.Wang@Sun.COM FCOE_STATUS
7159087SZhong.Wang@Sun.COM FCOE_GetPortList(
7169087SZhong.Wang@Sun.COM 	FCOE_UINT32		*port_num,
7179087SZhong.Wang@Sun.COM 	FCOE_PORT_ATTRIBUTE	**portlist)
7189087SZhong.Wang@Sun.COM {
7199087SZhong.Wang@Sun.COM 	FCOE_STATUS	status = FCOE_STATUS_OK;
7209307Skelly.hu@Sun.COM 	int		fcoe_fd;
7219087SZhong.Wang@Sun.COM 	fcoeio_t	fcoeio;
7229307Skelly.hu@Sun.COM 	fcoe_port_list_t	*inportlist = NULL;
7239087SZhong.Wang@Sun.COM 	FCOE_PORT_ATTRIBUTE	*outportlist = NULL;
7249307Skelly.hu@Sun.COM 	int		i;
7259307Skelly.hu@Sun.COM 	int		size = 64; /* default first attempt */
7269307Skelly.hu@Sun.COM 	int		retry = 0;
7279307Skelly.hu@Sun.COM 	int		bufsize;
7289307Skelly.hu@Sun.COM 	dladm_handle_t	handle;
7299307Skelly.hu@Sun.COM 	char		mac_name[MAXLINKNAMELEN];
7309087SZhong.Wang@Sun.COM 
7319087SZhong.Wang@Sun.COM 	if (port_num == NULL || portlist == NULL) {
7329087SZhong.Wang@Sun.COM 		return (FCOE_STATUS_ERROR_INVAL_ARG);
7339087SZhong.Wang@Sun.COM 	}
7349087SZhong.Wang@Sun.COM 	*port_num = 0;
7359087SZhong.Wang@Sun.COM 
7369087SZhong.Wang@Sun.COM 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
7379087SZhong.Wang@Sun.COM 		return (status);
7389087SZhong.Wang@Sun.COM 	}
7399087SZhong.Wang@Sun.COM 
7409087SZhong.Wang@Sun.COM 	/* Get fcoe port list */
7419087SZhong.Wang@Sun.COM 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
7429087SZhong.Wang@Sun.COM 	retry = 0;
7439087SZhong.Wang@Sun.COM 
7449087SZhong.Wang@Sun.COM 	do {
7459087SZhong.Wang@Sun.COM 		bufsize = sizeof (fcoe_port_instance_t) * (size - 1) +
7469087SZhong.Wang@Sun.COM 		    sizeof (fcoe_port_list_t);
7479087SZhong.Wang@Sun.COM 		inportlist = (fcoe_port_list_t *)malloc(bufsize);
7489087SZhong.Wang@Sun.COM 		fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST;
7499087SZhong.Wang@Sun.COM 		fcoeio.fcoeio_olen = bufsize;
7509087SZhong.Wang@Sun.COM 		fcoeio.fcoeio_xfer = FCOEIO_XFER_READ;
7519087SZhong.Wang@Sun.COM 		fcoeio.fcoeio_obuf = (uintptr_t)inportlist;
7529087SZhong.Wang@Sun.COM 
7539087SZhong.Wang@Sun.COM 		if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
7549087SZhong.Wang@Sun.COM 			if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) {
7559087SZhong.Wang@Sun.COM 				size = inportlist->numPorts;
7569087SZhong.Wang@Sun.COM 			}
7579087SZhong.Wang@Sun.COM 			free(inportlist);
7589087SZhong.Wang@Sun.COM 			switch (fcoeio.fcoeio_status) {
7599087SZhong.Wang@Sun.COM 			case FCOEIOE_INVAL_ARG:
7609087SZhong.Wang@Sun.COM 				status = FCOE_STATUS_ERROR_INVAL_ARG;
7619087SZhong.Wang@Sun.COM 				(void) close(fcoe_fd);
7629087SZhong.Wang@Sun.COM 				return (status);
7639087SZhong.Wang@Sun.COM 
7649087SZhong.Wang@Sun.COM 			case FCOEIOE_BUSY:
7659087SZhong.Wang@Sun.COM 				status = FCOE_STATUS_ERROR_BUSY;
7669087SZhong.Wang@Sun.COM 				retry++;
7679087SZhong.Wang@Sun.COM 				break;
7689087SZhong.Wang@Sun.COM 
7699087SZhong.Wang@Sun.COM 			case FCOEIOE_MORE_DATA:
7709087SZhong.Wang@Sun.COM 				status = FCOE_STATUS_ERROR_MORE_DATA;
7719087SZhong.Wang@Sun.COM 				retry++;
7729087SZhong.Wang@Sun.COM 			default:
7739087SZhong.Wang@Sun.COM 				status = FCOE_STATUS_ERROR;
774*9895SKevin.Yu@Sun.COM 				(void) close(fcoe_fd);
775*9895SKevin.Yu@Sun.COM 				return (status);
7769087SZhong.Wang@Sun.COM 			}
7779087SZhong.Wang@Sun.COM 		} else {
7789087SZhong.Wang@Sun.COM 			status = FCOE_STATUS_OK;
7799087SZhong.Wang@Sun.COM 			break;
7809087SZhong.Wang@Sun.COM 		}
7819087SZhong.Wang@Sun.COM 	} while (retry <= 3 && status != FCOE_STATUS_OK);
7829087SZhong.Wang@Sun.COM 
7839307Skelly.hu@Sun.COM 	if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) {
7849307Skelly.hu@Sun.COM 		if (dladm_open(&handle) != DLADM_STATUS_OK) {
7859307Skelly.hu@Sun.COM 			handle = NULL;
7869307Skelly.hu@Sun.COM 		}
7879307Skelly.hu@Sun.COM 
7889087SZhong.Wang@Sun.COM 		outportlist = (PFCOE_PORT_ATTRIBUTE)
7899087SZhong.Wang@Sun.COM 		    malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts);
7909087SZhong.Wang@Sun.COM 
7919087SZhong.Wang@Sun.COM 		for (i = 0; i < inportlist->numPorts; i++) {
7929087SZhong.Wang@Sun.COM 			fcoe_port_instance_t *pi = &inportlist->ports[i];
7939087SZhong.Wang@Sun.COM 			FCOE_PORT_ATTRIBUTE *po = &outportlist[i];
7949087SZhong.Wang@Sun.COM 			bcopy(pi->fpi_pwwn, &po->port_wwn, 8);
7959307Skelly.hu@Sun.COM 
7969307Skelly.hu@Sun.COM 			if (handle == NULL ||
7979307Skelly.hu@Sun.COM 			    dladm_datalink_id2info(handle, pi->fpi_mac_linkid,
7989307Skelly.hu@Sun.COM 			    NULL, NULL, NULL, mac_name, sizeof (mac_name))
7999307Skelly.hu@Sun.COM 			    != DLADM_STATUS_OK) {
8009307Skelly.hu@Sun.COM 				(void) strcpy((char *)po->mac_link_name,
8019307Skelly.hu@Sun.COM 				    "<unknown>");
8029307Skelly.hu@Sun.COM 			} else {
8039307Skelly.hu@Sun.COM 				(void) strcpy((char *)po->mac_link_name,
8049307Skelly.hu@Sun.COM 				    mac_name);
8059307Skelly.hu@Sun.COM 			}
8069087SZhong.Wang@Sun.COM 			bcopy(pi->fpi_mac_factory_addr,
8079087SZhong.Wang@Sun.COM 			    po->mac_factory_addr, 6);
8089087SZhong.Wang@Sun.COM 			bcopy(pi->fpi_mac_current_addr,
8099087SZhong.Wang@Sun.COM 			    po->mac_current_addr, 6);
8109087SZhong.Wang@Sun.COM 			po->port_type = (FCOE_UINT8)pi->fpi_port_type;
8119087SZhong.Wang@Sun.COM 			po->mtu_size = pi->fpi_mtu_size;
8129087SZhong.Wang@Sun.COM 			po->mac_promisc = pi->fpi_mac_promisc;
8139087SZhong.Wang@Sun.COM 		}
8149307Skelly.hu@Sun.COM 
8159307Skelly.hu@Sun.COM 		if (handle != NULL) {
8169307Skelly.hu@Sun.COM 			dladm_close(handle);
8179307Skelly.hu@Sun.COM 		}
8189087SZhong.Wang@Sun.COM 		*port_num = inportlist->numPorts;
8199087SZhong.Wang@Sun.COM 		*portlist = outportlist;
8209087SZhong.Wang@Sun.COM 		free(inportlist);
8219087SZhong.Wang@Sun.COM 	} else {
8229087SZhong.Wang@Sun.COM 		*port_num = 0;
8239087SZhong.Wang@Sun.COM 		*portlist = NULL;
8249087SZhong.Wang@Sun.COM 	}
8259087SZhong.Wang@Sun.COM 	(void) close(fcoe_fd);
8269087SZhong.Wang@Sun.COM 	return (status);
8279087SZhong.Wang@Sun.COM }
828*9895SKevin.Yu@Sun.COM 
829*9895SKevin.Yu@Sun.COM FCOE_STATUS FCOE_LoadConfig(
830*9895SKevin.Yu@Sun.COM 	FCOE_UINT8		portType,
831*9895SKevin.Yu@Sun.COM     FCOE_SMF_PORT_LIST **portlist)
832*9895SKevin.Yu@Sun.COM {
833*9895SKevin.Yu@Sun.COM 	scf_handle_t	*handle = NULL;
834*9895SKevin.Yu@Sun.COM 	scf_service_t	*svc = NULL;
835*9895SKevin.Yu@Sun.COM 	scf_propertygroup_t	*pg = NULL;
836*9895SKevin.Yu@Sun.COM 	scf_transaction_t	*tran = NULL;
837*9895SKevin.Yu@Sun.COM 	scf_transaction_entry_t	*entry = NULL;
838*9895SKevin.Yu@Sun.COM 	scf_property_t		*prop = NULL;
839*9895SKevin.Yu@Sun.COM 	scf_value_t	*valueLookup = NULL;
840*9895SKevin.Yu@Sun.COM 	scf_iter_t	*valueIter = NULL;
841*9895SKevin.Yu@Sun.COM 	char		buf[FCOE_PORT_LIST_LENGTH] = {0};
842*9895SKevin.Yu@Sun.COM 	int		commitRet;
843*9895SKevin.Yu@Sun.COM 	FCOE_UINT32	portIndex;
844*9895SKevin.Yu@Sun.COM 	int		bufsize, retry;
845*9895SKevin.Yu@Sun.COM 	int		size = 10; /* default first attempt */
846*9895SKevin.Yu@Sun.COM 	int		pg_or_prop_not_found = 0;
847*9895SKevin.Yu@Sun.COM 
848*9895SKevin.Yu@Sun.COM 	commitRet = fcoe_cfg_scf_init(&handle, &svc, portType);
849*9895SKevin.Yu@Sun.COM 	if (commitRet != FCOE_SUCCESS) {
850*9895SKevin.Yu@Sun.COM 		goto out;
851*9895SKevin.Yu@Sun.COM 	}
852*9895SKevin.Yu@Sun.COM 
853*9895SKevin.Yu@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
854*9895SKevin.Yu@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
855*9895SKevin.Yu@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
856*9895SKevin.Yu@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
857*9895SKevin.Yu@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
858*9895SKevin.Yu@Sun.COM 		goto out;
859*9895SKevin.Yu@Sun.COM 	}
860*9895SKevin.Yu@Sun.COM 
861*9895SKevin.Yu@Sun.COM 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
862*9895SKevin.Yu@Sun.COM 		pg_or_prop_not_found = 1;
863*9895SKevin.Yu@Sun.COM 		goto out;
864*9895SKevin.Yu@Sun.COM 	}
865*9895SKevin.Yu@Sun.COM 
866*9895SKevin.Yu@Sun.COM 	if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
867*9895SKevin.Yu@Sun.COM 		pg_or_prop_not_found = 1;
868*9895SKevin.Yu@Sun.COM 		goto out;
869*9895SKevin.Yu@Sun.COM 	}
870*9895SKevin.Yu@Sun.COM 
871*9895SKevin.Yu@Sun.COM 	valueLookup = scf_value_create(handle);
872*9895SKevin.Yu@Sun.COM 	if (valueLookup == NULL) {
873*9895SKevin.Yu@Sun.COM 		syslog(LOG_ERR, "scf value alloc failed - %s",
874*9895SKevin.Yu@Sun.COM 		    scf_strerror(scf_error()));
875*9895SKevin.Yu@Sun.COM 		goto out;
876*9895SKevin.Yu@Sun.COM 	}
877*9895SKevin.Yu@Sun.COM 
878*9895SKevin.Yu@Sun.COM 	portIndex = 0;
879*9895SKevin.Yu@Sun.COM 
880*9895SKevin.Yu@Sun.COM 	do {
881*9895SKevin.Yu@Sun.COM 		if (scf_iter_property_values(valueIter, prop) == -1) {
882*9895SKevin.Yu@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
883*9895SKevin.Yu@Sun.COM 			    scf_strerror(scf_error()));
884*9895SKevin.Yu@Sun.COM 			goto out;
885*9895SKevin.Yu@Sun.COM 		}
886*9895SKevin.Yu@Sun.COM 
887*9895SKevin.Yu@Sun.COM 		retry = 0;
888*9895SKevin.Yu@Sun.COM 		bufsize = sizeof (FCOE_SMF_PORT_INSTANCE) * (size - 1) +
889*9895SKevin.Yu@Sun.COM 		    sizeof (FCOE_SMF_PORT_LIST);
890*9895SKevin.Yu@Sun.COM 		*portlist = (PFCOE_SMF_PORT_LIST)malloc(bufsize);
891*9895SKevin.Yu@Sun.COM 
892*9895SKevin.Yu@Sun.COM 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
893*9895SKevin.Yu@Sun.COM 			uint8_t *macLinkName = NULL;
894*9895SKevin.Yu@Sun.COM 			char *remainder = NULL;
895*9895SKevin.Yu@Sun.COM 			uint64_t	nodeWWN, portWWN;
896*9895SKevin.Yu@Sun.COM 			int is_target, is_promiscuous;
897*9895SKevin.Yu@Sun.COM 
898*9895SKevin.Yu@Sun.COM 			bzero(buf, sizeof (buf));
899*9895SKevin.Yu@Sun.COM 			if (scf_value_get_ustring(valueLookup, buf,
900*9895SKevin.Yu@Sun.COM 			    MAXNAMELEN) == -1) {
901*9895SKevin.Yu@Sun.COM 				syslog(LOG_ERR, "iter value failed - %s",
902*9895SKevin.Yu@Sun.COM 				    scf_strerror(scf_error()));
903*9895SKevin.Yu@Sun.COM 				break;
904*9895SKevin.Yu@Sun.COM 			}
905*9895SKevin.Yu@Sun.COM 			macLinkName = (uint8_t *)strtok(buf, ":");
906*9895SKevin.Yu@Sun.COM 			remainder = strtok(NULL, "#");
907*9895SKevin.Yu@Sun.COM 			(void) sscanf(remainder,
908*9895SKevin.Yu@Sun.COM 			    "%016" PRIx64 ":%016" PRIx64 ":%d:%d",
909*9895SKevin.Yu@Sun.COM 			    &portWWN, &nodeWWN, &is_target, &is_promiscuous);
910*9895SKevin.Yu@Sun.COM 
911*9895SKevin.Yu@Sun.COM 			if (portIndex >= size) {
912*9895SKevin.Yu@Sun.COM 				free(*portlist);
913*9895SKevin.Yu@Sun.COM 				retry = 1;
914*9895SKevin.Yu@Sun.COM 				size *= 2;
915*9895SKevin.Yu@Sun.COM 				break;
916*9895SKevin.Yu@Sun.COM 			} else {
917*9895SKevin.Yu@Sun.COM 				PFCOE_SMF_PORT_INSTANCE pi =
918*9895SKevin.Yu@Sun.COM 				    &(*portlist)->ports[portIndex++];
919*9895SKevin.Yu@Sun.COM 				(void) strcpy((char *)pi->mac_link_name,
920*9895SKevin.Yu@Sun.COM 				    (char *)macLinkName);
921*9895SKevin.Yu@Sun.COM 				pi->port_type = is_target ?
922*9895SKevin.Yu@Sun.COM 				    FCOE_PORTTYPE_TARGET:
923*9895SKevin.Yu@Sun.COM 				    FCOE_PORTTYPE_INITIATOR;
924*9895SKevin.Yu@Sun.COM 				portWWN = htonll(portWWN);
925*9895SKevin.Yu@Sun.COM 				nodeWWN = htonll(nodeWWN);
926*9895SKevin.Yu@Sun.COM 				(void) memcpy(&pi->port_pwwn, &portWWN,
927*9895SKevin.Yu@Sun.COM 				    sizeof (FCOE_PORT_WWN));
928*9895SKevin.Yu@Sun.COM 				(void) memcpy(&pi->port_nwwn, &nodeWWN,
929*9895SKevin.Yu@Sun.COM 				    sizeof (FCOE_PORT_WWN));
930*9895SKevin.Yu@Sun.COM 				pi->mac_promisc = is_promiscuous;
931*9895SKevin.Yu@Sun.COM 			}
932*9895SKevin.Yu@Sun.COM 		}
933*9895SKevin.Yu@Sun.COM 
934*9895SKevin.Yu@Sun.COM 		(*portlist)->port_num = portIndex;
935*9895SKevin.Yu@Sun.COM 	} while (retry == 1);
936*9895SKevin.Yu@Sun.COM 
937*9895SKevin.Yu@Sun.COM 	return (FCOE_STATUS_OK);
938*9895SKevin.Yu@Sun.COM out:
939*9895SKevin.Yu@Sun.COM 	/*
940*9895SKevin.Yu@Sun.COM 	 * Free resources
941*9895SKevin.Yu@Sun.COM 	 */
942*9895SKevin.Yu@Sun.COM 	if (handle != NULL) {
943*9895SKevin.Yu@Sun.COM 		scf_handle_destroy(handle);
944*9895SKevin.Yu@Sun.COM 	}
945*9895SKevin.Yu@Sun.COM 	if (svc != NULL) {
946*9895SKevin.Yu@Sun.COM 		scf_service_destroy(svc);
947*9895SKevin.Yu@Sun.COM 	}
948*9895SKevin.Yu@Sun.COM 	if (pg != NULL) {
949*9895SKevin.Yu@Sun.COM 		scf_pg_destroy(pg);
950*9895SKevin.Yu@Sun.COM 	}
951*9895SKevin.Yu@Sun.COM 	if (tran != NULL) {
952*9895SKevin.Yu@Sun.COM 		scf_transaction_destroy(tran);
953*9895SKevin.Yu@Sun.COM 	}
954*9895SKevin.Yu@Sun.COM 	if (entry != NULL) {
955*9895SKevin.Yu@Sun.COM 		scf_entry_destroy(entry);
956*9895SKevin.Yu@Sun.COM 	}
957*9895SKevin.Yu@Sun.COM 	if (prop != NULL) {
958*9895SKevin.Yu@Sun.COM 		scf_property_destroy(prop);
959*9895SKevin.Yu@Sun.COM 	}
960*9895SKevin.Yu@Sun.COM 	if (valueIter != NULL) {
961*9895SKevin.Yu@Sun.COM 		scf_iter_destroy(valueIter);
962*9895SKevin.Yu@Sun.COM 	}
963*9895SKevin.Yu@Sun.COM 	if (valueLookup != NULL) {
964*9895SKevin.Yu@Sun.COM 		scf_value_destroy(valueLookup);
965*9895SKevin.Yu@Sun.COM 	}
966*9895SKevin.Yu@Sun.COM 
967*9895SKevin.Yu@Sun.COM 	if (pg_or_prop_not_found == 1) {
968*9895SKevin.Yu@Sun.COM 		return (FCOE_STATUS_OK);
969*9895SKevin.Yu@Sun.COM 	} else {
970*9895SKevin.Yu@Sun.COM 		return (FCOE_STATUS_ERROR);
971*9895SKevin.Yu@Sun.COM 	}
972*9895SKevin.Yu@Sun.COM }
973