xref: /titanic_52/usr/src/lib/sun_sas/common/sun_sas.c (revision 0778188f242b11e5d53f771c9e8a069354b3d5d4)
19e86db79SHyon Kim /*
29e86db79SHyon Kim  * CDDL HEADER START
39e86db79SHyon Kim  *
49e86db79SHyon Kim  * The contents of this file are subject to the terms of the
59e86db79SHyon Kim  * Common Development and Distribution License (the "License").
69e86db79SHyon Kim  * You may not use this file except in compliance with the License.
79e86db79SHyon Kim  *
89e86db79SHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e86db79SHyon Kim  * or http://www.opensolaris.org/os/licensing.
109e86db79SHyon Kim  * See the License for the specific language governing permissions
119e86db79SHyon Kim  * and limitations under the License.
129e86db79SHyon Kim  *
139e86db79SHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
149e86db79SHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e86db79SHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
169e86db79SHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
179e86db79SHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
189e86db79SHyon Kim  *
199e86db79SHyon Kim  * CDDL HEADER END
209e86db79SHyon Kim  */
219e86db79SHyon Kim 
229e86db79SHyon Kim /*
239e86db79SHyon Kim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249e86db79SHyon Kim  * Use is subject to license terms.
259e86db79SHyon Kim  */
269e86db79SHyon Kim 
279e86db79SHyon Kim 
289e86db79SHyon Kim #include <sys/byteorder.h>
299e86db79SHyon Kim #include <sun_sas.h>
309e86db79SHyon Kim 
319e86db79SHyon Kim /*
329e86db79SHyon Kim  * creates a handle each time Sun_sas_OpenAdapter() is called.
339e86db79SHyon Kim  *
349e86db79SHyon Kim  * a open_handle_struct was created to keep track of which handles are currently
359e86db79SHyon Kim  * open.  This prevents a user from using an old handle that corresponds to
369e86db79SHyon Kim  * an hba that has already been closed.
379e86db79SHyon Kim  */
389e86db79SHyon Kim HBA_HANDLE
399e86db79SHyon Kim CreateHandle(int adapterIndex)
409e86db79SHyon Kim {
419e86db79SHyon Kim 	const char		ROUTINE[] = "CreateHandle";
429e86db79SHyon Kim 	struct open_handle	*new_open_handle;
439e86db79SHyon Kim 	HBA_UINT32		new_handle_index;
449e86db79SHyon Kim 	HBA_UINT8		max_handle_wrap = 0;
459e86db79SHyon Kim 
469e86db79SHyon Kim 	if (global_hba_head == NULL) {
479e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
489e86db79SHyon Kim 		    "an error as occurred.  global_hba_head is "
499e86db79SHyon Kim 		    "NULL.  Library may not be loaded yet.");
509e86db79SHyon Kim 		return (HANDLE_ERROR);
519e86db79SHyon Kim 	}
529e86db79SHyon Kim 
539e86db79SHyon Kim 	while (RetrieveIndex(open_handle_index) != -1)  {
549e86db79SHyon Kim 		open_handle_index = open_handle_index + 1;
559e86db79SHyon Kim 		if (open_handle_index == 0) {
569e86db79SHyon Kim 			/*
579e86db79SHyon Kim 			 * If open_handle_index wraps back to zero again,
589e86db79SHyon Kim 			 * that means all handles are currently in use.
599e86db79SHyon Kim 			 * Spec only allows for 16 bits of handles
609e86db79SHyon Kim 			 */
619e86db79SHyon Kim 			if (max_handle_wrap == 1) {
629e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
639e86db79SHyon Kim 				    "Max number of handles reached.");
649e86db79SHyon Kim 				return (HANDLE_ERROR);
659e86db79SHyon Kim 			}
669e86db79SHyon Kim 			open_handle_index = 1;
679e86db79SHyon Kim 			max_handle_wrap = 1;
689e86db79SHyon Kim 		}
699e86db79SHyon Kim 	}
709e86db79SHyon Kim 
719e86db79SHyon Kim 	new_handle_index = open_handle_index;
729e86db79SHyon Kim 	if ((new_open_handle = (struct open_handle *)calloc(1,
739e86db79SHyon Kim 	    sizeof (struct open_handle))) == NULL) {
749e86db79SHyon Kim 		OUT_OF_MEMORY(ROUTINE);
759e86db79SHyon Kim 		return (HANDLE_ERROR);
769e86db79SHyon Kim 	}
779e86db79SHyon Kim 	(void) memset(new_open_handle, 0, sizeof (struct open_handle));
789e86db79SHyon Kim 	new_open_handle->adapterIndex = adapterIndex;
799e86db79SHyon Kim 	new_open_handle->handle = new_handle_index;
809e86db79SHyon Kim 
819e86db79SHyon Kim 	lock(&open_handles_lock);
829e86db79SHyon Kim 
839e86db79SHyon Kim 	/* add new open handle struct to the open_handles list */
849e86db79SHyon Kim 	if (global_hba_head->open_handles == NULL) {
859e86db79SHyon Kim 		global_hba_head->open_handles = new_open_handle;
869e86db79SHyon Kim 	} else {
879e86db79SHyon Kim 		new_open_handle->next = global_hba_head->open_handles;
889e86db79SHyon Kim 		global_hba_head->open_handles = new_open_handle;
899e86db79SHyon Kim 	}
909e86db79SHyon Kim 
919e86db79SHyon Kim 	unlock(&open_handles_lock);
929e86db79SHyon Kim 	open_handle_index = open_handle_index + 1;
939e86db79SHyon Kim 	if (open_handle_index == 0) {
949e86db79SHyon Kim 		open_handle_index = 1;
959e86db79SHyon Kim 	}
969e86db79SHyon Kim 
979e86db79SHyon Kim 	return (new_handle_index);
989e86db79SHyon Kim }
999e86db79SHyon Kim 
1009e86db79SHyon Kim /*
1019e86db79SHyon Kim  * given a handle, returns the adapterIndex number.
1029e86db79SHyon Kim  *
1039e86db79SHyon Kim  * This functions checkes to see if the given handle corresponds to an open
1049e86db79SHyon Kim  * HBA.  If it does, the adapterIndex is returned.
1059e86db79SHyon Kim  */
1069e86db79SHyon Kim int
1079e86db79SHyon Kim RetrieveIndex(HBA_HANDLE handle)
1089e86db79SHyon Kim {
1099e86db79SHyon Kim 
1109e86db79SHyon Kim 	struct open_handle	*open_handle_ptr;
1119e86db79SHyon Kim 
1129e86db79SHyon Kim 	lock(&open_handles_lock);
1139e86db79SHyon Kim 
1149e86db79SHyon Kim 	open_handle_ptr = RetrieveOpenHandle(handle);
1159e86db79SHyon Kim 
1169e86db79SHyon Kim 	unlock(&open_handles_lock);
1179e86db79SHyon Kim 	if (open_handle_ptr == NULL) {
1189e86db79SHyon Kim 		return (-1);
1199e86db79SHyon Kim 	}
1209e86db79SHyon Kim 
1219e86db79SHyon Kim 	return (open_handle_ptr->adapterIndex);
1229e86db79SHyon Kim }
1239e86db79SHyon Kim /*
1249e86db79SHyon Kim  * Given a handle, returns the open_handle structure
1259e86db79SHyon Kim  * The routine assumes that the open_handles_lock has already
1269e86db79SHyon Kim  * been taken.
1279e86db79SHyon Kim  */
1289e86db79SHyon Kim struct open_handle *
1299e86db79SHyon Kim RetrieveOpenHandle(HBA_HANDLE handle)
1309e86db79SHyon Kim {
1319e86db79SHyon Kim 
1329e86db79SHyon Kim 	const char		ROUTINE[] = "RetrieveOpenHandle";
1339e86db79SHyon Kim 	struct open_handle	*open_handle_ptr = NULL;
1349e86db79SHyon Kim 
1359e86db79SHyon Kim 	if (global_hba_head == NULL) {
136*0778188fSHengqing Hu 		log(LOG_DEBUG, ROUTINE, "No adapter is found.");
1379e86db79SHyon Kim 		return (NULL);
1389e86db79SHyon Kim 	}
1399e86db79SHyon Kim 
1409e86db79SHyon Kim 	for (open_handle_ptr = global_hba_head->open_handles;
1419e86db79SHyon Kim 	    open_handle_ptr != NULL;
1429e86db79SHyon Kim 	    open_handle_ptr = open_handle_ptr->next) {
1439e86db79SHyon Kim 		if (open_handle_ptr->handle == handle) {
1449e86db79SHyon Kim 			break;
1459e86db79SHyon Kim 		}
1469e86db79SHyon Kim 	}
1479e86db79SHyon Kim 
1489e86db79SHyon Kim 	return (open_handle_ptr);
1499e86db79SHyon Kim }
1509e86db79SHyon Kim 
1519e86db79SHyon Kim /*
1529e86db79SHyon Kim  * Given an adapterIndex, this functions returns a pointer to the handle
1539e86db79SHyon Kim  * structure.  This handle structure holds the hba's information
1549e86db79SHyon Kim  * Caller must take all_hbas_lock first.
1559e86db79SHyon Kim  */
1569e86db79SHyon Kim struct sun_sas_hba *
1579e86db79SHyon Kim RetrieveHandle(int index)
1589e86db79SHyon Kim {
1599e86db79SHyon Kim 	struct sun_sas_hba 	*hba_ptr = NULL;
1609e86db79SHyon Kim 
1619e86db79SHyon Kim 	for (hba_ptr = global_hba_head; hba_ptr != NULL;
1629e86db79SHyon Kim 	    hba_ptr = hba_ptr->next) {
1639e86db79SHyon Kim 		if (hba_ptr->index == index)
1649e86db79SHyon Kim 			break;
1659e86db79SHyon Kim 	}
1669e86db79SHyon Kim 
1679e86db79SHyon Kim 	return (hba_ptr);
1689e86db79SHyon Kim }
1699e86db79SHyon Kim 
1709e86db79SHyon Kim /*
1719e86db79SHyon Kim  * Given an adapterIndex, this functions returns a pointer to the handle
1729e86db79SHyon Kim  * structure and extracts it from the global list.
1739e86db79SHyon Kim  *
1749e86db79SHyon Kim  * all_hbas_lock must be taken already.
1759e86db79SHyon Kim  */
1769e86db79SHyon Kim struct sun_sas_hba *
1779e86db79SHyon Kim ExtractHandle(int index)
1789e86db79SHyon Kim {
1799e86db79SHyon Kim 	struct sun_sas_hba 	*last = NULL;
1809e86db79SHyon Kim 	struct sun_sas_hba 	*hba_ptr = NULL;
1819e86db79SHyon Kim 
1829e86db79SHyon Kim 	for (hba_ptr = global_hba_head;
1839e86db79SHyon Kim 	    hba_ptr != NULL;
1849e86db79SHyon Kim 	    last = hba_ptr, hba_ptr = hba_ptr->next) {
1859e86db79SHyon Kim 		if (hba_ptr->index == index) {
1869e86db79SHyon Kim 			if (last) {
1879e86db79SHyon Kim 				last->next = hba_ptr->next;
1889e86db79SHyon Kim 			} else {
1899e86db79SHyon Kim 				/* Hmm, must be the head of the list. */
1909e86db79SHyon Kim 				global_hba_head = hba_ptr->next;
1919e86db79SHyon Kim 			}
1929e86db79SHyon Kim 			hba_ptr->next = NULL; /* Zap it to be safe */
1939e86db79SHyon Kim 			break;
1949e86db79SHyon Kim 		}
1959e86db79SHyon Kim 	}
1969e86db79SHyon Kim 
1979e86db79SHyon Kim 	return (hba_ptr);
1989e86db79SHyon Kim }
1999e86db79SHyon Kim 
2009e86db79SHyon Kim 
2019e86db79SHyon Kim /*
2029e86db79SHyon Kim  * Given an handle, this functions returns a pointer to the handle structure
2039e86db79SHyon Kim  * for that hba
2049e86db79SHyon Kim  *
2059e86db79SHyon Kim  * Caller must take all_hbas_lock first.
2069e86db79SHyon Kim  */
2079e86db79SHyon Kim struct sun_sas_hba *
2089e86db79SHyon Kim Retrieve_Sun_sasHandle(HBA_HANDLE handle)
2099e86db79SHyon Kim {
2109e86db79SHyon Kim 	const char		    ROUTINE[] = "Retrieve_Sun_sasHandle";
2119e86db79SHyon Kim 	struct	sun_sas_hba	    *handle_struct = NULL;
2129e86db79SHyon Kim 	int			    index;
2139e86db79SHyon Kim 
2149e86db79SHyon Kim 	/* Retrieve fp device path from handle */
2159e86db79SHyon Kim 	index = RetrieveIndex(handle);
2169e86db79SHyon Kim 	if (index == -1) {
2179e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2189e86db79SHyon Kim 		    "handle could not be found.");
2199e86db79SHyon Kim 		return (handle_struct);
2209e86db79SHyon Kim 	}
2219e86db79SHyon Kim 	lock(&open_handles_lock);
2229e86db79SHyon Kim 	handle_struct = RetrieveHandle(index);
2239e86db79SHyon Kim 	if (handle_struct == NULL) {
2249e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2259e86db79SHyon Kim 		    "could not find index in the handle list.");
2269e86db79SHyon Kim 		unlock(&open_handles_lock);
2279e86db79SHyon Kim 		return (handle_struct);
2289e86db79SHyon Kim 	}
2299e86db79SHyon Kim 	unlock(&open_handles_lock);
2309e86db79SHyon Kim 
2319e86db79SHyon Kim 	return (handle_struct);
2329e86db79SHyon Kim }
2339e86db79SHyon Kim 
2349e86db79SHyon Kim /*
2359e86db79SHyon Kim  * Take a mutex lock.  The routine will try, and if it fails,
2369e86db79SHyon Kim  * it will loop for a while and retry.  If it fails many times,
2379e86db79SHyon Kim  * it will start writing to the log file.
2389e86db79SHyon Kim  */
2399e86db79SHyon Kim void
2409e86db79SHyon Kim lock(mutex_t *mp)
2419e86db79SHyon Kim {
2429e86db79SHyon Kim 	int status;
2439e86db79SHyon Kim 	int loop = 0;
2449e86db79SHyon Kim 	const char ROUTINE[] = "lock";
2459e86db79SHyon Kim 
2469e86db79SHyon Kim 	do {
2479e86db79SHyon Kim 		loop++;
2489e86db79SHyon Kim 		status = mutex_trylock(mp);
2499e86db79SHyon Kim 		switch (status) {
2509e86db79SHyon Kim 			case 0:
2519e86db79SHyon Kim 				break;
2529e86db79SHyon Kim 			case EFAULT:
2539e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
2549e86db79SHyon Kim 				    "Lock failed: fault 0x%x", mp);
2559e86db79SHyon Kim 				break;
2569e86db79SHyon Kim 			case EINVAL:
2579e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
2589e86db79SHyon Kim 				    "Lock failed: invalid 0x%x", mp);
2599e86db79SHyon Kim 				break;
2609e86db79SHyon Kim 			case EBUSY:
2619e86db79SHyon Kim 				if (loop > DEADLOCK_WARNING) {
2629e86db79SHyon Kim 					log(LOG_DEBUG, ROUTINE,
2639e86db79SHyon Kim 					    "Lock busy, possible deadlock:0x%x",
2649e86db79SHyon Kim 					    mp);
2659e86db79SHyon Kim 				}
2669e86db79SHyon Kim 				break;
2679e86db79SHyon Kim 			case EOWNERDEAD:
2689e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
2699e86db79SHyon Kim 				    "Lock failed: owner dead 0x%x",
2709e86db79SHyon Kim 				    mp);
2719e86db79SHyon Kim 				break;
2729e86db79SHyon Kim 			case ELOCKUNMAPPED:
2739e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
2749e86db79SHyon Kim 				    "Lock failed: unmapped 0x%x",
2759e86db79SHyon Kim 				    mp);
2769e86db79SHyon Kim 				break;
2779e86db79SHyon Kim 			case ENOTRECOVERABLE:
2789e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
2799e86db79SHyon Kim 				    "Lock failed: not recoverable 0x%x", mp);
2809e86db79SHyon Kim 			default:
2819e86db79SHyon Kim 				if (loop > DEADLOCK_WARNING) {
2829e86db79SHyon Kim 					log(LOG_DEBUG, ROUTINE,
2839e86db79SHyon Kim 					    "Lock failed: %s 0x%x",
2849e86db79SHyon Kim 					    strerror(status), mp);
2859e86db79SHyon Kim 					break;
2869e86db79SHyon Kim 				}
2879e86db79SHyon Kim 		}
2889e86db79SHyon Kim 
2899e86db79SHyon Kim 		if (status) {
2909e86db79SHyon Kim 			(void) sleep(LOCK_SLEEP);
2919e86db79SHyon Kim 		}
2929e86db79SHyon Kim 
2939e86db79SHyon Kim 	} while (status);
2949e86db79SHyon Kim }
2959e86db79SHyon Kim 
2969e86db79SHyon Kim /*
2979e86db79SHyon Kim  * Unlock a mutex lock.
2989e86db79SHyon Kim  */
2999e86db79SHyon Kim void
3009e86db79SHyon Kim unlock(mutex_t *mp)
3019e86db79SHyon Kim {
3029e86db79SHyon Kim 	(void) mutex_unlock(mp);
3039e86db79SHyon Kim }
3049e86db79SHyon Kim 
3059e86db79SHyon Kim 
3069e86db79SHyon Kim /*
3079e86db79SHyon Kim  * Get the Port WWN of the first adapter port.  This routine
3089e86db79SHyon Kim  * is used by the old V1 interfaces so that they can call
3099e86db79SHyon Kim  * the new V2 interfaces and exhibit the same behavior.
3109e86db79SHyon Kim  * In the event of error the WWN will be zero.
3119e86db79SHyon Kim  *
3129e86db79SHyon Kim  * This function will transition to PAA state but it will not
3139e86db79SHyon Kim  * verfiy whether data is stale or not
3149e86db79SHyon Kim  */
3159e86db79SHyon Kim HBA_WWN
3169e86db79SHyon Kim getFirstAdapterPortWWN(HBA_HANDLE handle)
3179e86db79SHyon Kim {
3189e86db79SHyon Kim 	const char	ROUTINE[] = "getFirstAdapterPortWWN";
3199e86db79SHyon Kim 	HBA_WWN			pwwn = {0, 0, 0, 0, 0, 0, 0, 0};
3209e86db79SHyon Kim 	struct sun_sas_hba	*hba_ptr = NULL;
3219e86db79SHyon Kim 	int			index = 0;
3229e86db79SHyon Kim 	HBA_STATUS		status;
3239e86db79SHyon Kim 
3249e86db79SHyon Kim 	lock(&all_hbas_lock);
3259e86db79SHyon Kim 	index = RetrieveIndex(handle);
3269e86db79SHyon Kim 	lock(&open_handles_lock);
3279e86db79SHyon Kim 	hba_ptr = RetrieveHandle(index);
3289e86db79SHyon Kim 	if (hba_ptr == NULL) {
3299e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
3309e86db79SHyon Kim 		unlock(&open_handles_lock);
3319e86db79SHyon Kim 		unlock(&all_hbas_lock);
3329e86db79SHyon Kim 		return (pwwn); /* zero WWN */
3339e86db79SHyon Kim 	}
3349e86db79SHyon Kim 
3359e86db79SHyon Kim 	/* Check for stale data */
3369e86db79SHyon Kim 	status = verifyAdapter(hba_ptr);
3379e86db79SHyon Kim 	if (status != HBA_STATUS_OK) {
3389e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
3399e86db79SHyon Kim 		unlock(&open_handles_lock);
3409e86db79SHyon Kim 		unlock(&all_hbas_lock);
3419e86db79SHyon Kim 		return (pwwn);
3429e86db79SHyon Kim 	}
3439e86db79SHyon Kim 
3449e86db79SHyon Kim 	if (hba_ptr->first_port == NULL) {
3459e86db79SHyon Kim 		/* This is probably an internal failure of the library */
3469e86db79SHyon Kim 		if (hba_ptr->device_path) {
3479e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
3489e86db79SHyon Kim 			    "Internal failure:  Adapter %s contains no "
3499e86db79SHyon Kim 			    "port data", hba_ptr->device_path);
3509e86db79SHyon Kim 		} else {
3519e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
3529e86db79SHyon Kim 			    "Internal failure:  Adapter at index %d contains "
3539e86db79SHyon Kim 			    " no support data", hba_ptr->index);
3549e86db79SHyon Kim 		}
3559e86db79SHyon Kim 		unlock(&open_handles_lock);
3569e86db79SHyon Kim 		unlock(&all_hbas_lock);
3579e86db79SHyon Kim 		return (pwwn); /* zero WWN */
3589e86db79SHyon Kim 	}
3599e86db79SHyon Kim 	/* Set the WWN now and return it */
3609e86db79SHyon Kim 	pwwn = hba_ptr->first_port->port_attributes.PortSpecificAttribute.\
3619e86db79SHyon Kim 	    SASPort->LocalSASAddress;
3629e86db79SHyon Kim 	unlock(&open_handles_lock);
3639e86db79SHyon Kim 	unlock(&all_hbas_lock);
3649e86db79SHyon Kim 
3659e86db79SHyon Kim 	return (pwwn);
3669e86db79SHyon Kim }
3679e86db79SHyon Kim 
3689e86db79SHyon Kim u_longlong_t
3699e86db79SHyon Kim wwnConversion(uchar_t *wwn)
3709e86db79SHyon Kim {
3719e86db79SHyon Kim 	u_longlong_t tmp;
3729e86db79SHyon Kim 	(void) memcpy(&tmp, wwn, sizeof (u_longlong_t));
3739e86db79SHyon Kim 	tmp = ntohll(tmp);
3749e86db79SHyon Kim 	return (tmp);
3759e86db79SHyon Kim }
3769e86db79SHyon Kim 
3779e86db79SHyon Kim /*
3789e86db79SHyon Kim  * Using ioctl to send uscsi command out
3799e86db79SHyon Kim  */
3809e86db79SHyon Kim HBA_STATUS
3819e86db79SHyon Kim send_uscsi_cmd(const char *devpath, struct uscsi_cmd *ucmd)
3829e86db79SHyon Kim {
3839e86db79SHyon Kim 	const char	ROUTINE[] = "send_uscsi_cmd";
3849e86db79SHyon Kim 	int		fd;
3859e86db79SHyon Kim 	HBA_STATUS	ret;
3869e86db79SHyon Kim 
3879e86db79SHyon Kim 	/* set default timeout to 200 */
3889e86db79SHyon Kim 	ucmd->uscsi_timeout = 200;
3899e86db79SHyon Kim 
3909e86db79SHyon Kim 	/* reset errno. */
3919e86db79SHyon Kim 	errno = 0;
3929e86db79SHyon Kim 	if ((fd = open(devpath, O_RDONLY | O_NDELAY)) == -1) {
3939e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
3949e86db79SHyon Kim 		    "open devpath %s failed: %s", devpath, strerror(errno));
3959e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
3969e86db79SHyon Kim 	}
3979e86db79SHyon Kim 
3989e86db79SHyon Kim 	if (ioctl(fd, USCSICMD, ucmd) == -1) {
3999e86db79SHyon Kim 		if (errno == EBUSY) {
4009e86db79SHyon Kim 			ret = HBA_STATUS_ERROR_BUSY;
4019e86db79SHyon Kim 		} else if (errno == EAGAIN) {
4029e86db79SHyon Kim 			ret = HBA_STATUS_ERROR_TRY_AGAIN;
4039e86db79SHyon Kim 		} else {
4049e86db79SHyon Kim 			ret = HBA_STATUS_ERROR;
4059e86db79SHyon Kim 		}
4069e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
4079e86db79SHyon Kim 		    "ioctl send uscsi to devpath: %s failed: %s",
4089e86db79SHyon Kim 		    devpath, strerror(errno));
4099e86db79SHyon Kim 		(void) close(fd);
4109e86db79SHyon Kim 		return (ret);
4119e86db79SHyon Kim 	}
4129e86db79SHyon Kim 
4139e86db79SHyon Kim 	(void) close(fd);
4149e86db79SHyon Kim 
4159e86db79SHyon Kim 	return (HBA_STATUS_OK);
4169e86db79SHyon Kim }
4179e86db79SHyon Kim 
4189e86db79SHyon Kim /*
4199e86db79SHyon Kim  * Check whether the given Domain Address is valid.
4209e86db79SHyon Kim  */
4219e86db79SHyon Kim HBA_STATUS
4229e86db79SHyon Kim validateDomainAddress(struct sun_sas_port *hba_port_ptr, HBA_WWN DomainAddr)
4239e86db79SHyon Kim {
4249e86db79SHyon Kim 	if (hba_port_ptr->first_phy != NULL &&
4259e86db79SHyon Kim 	    wwnConversion(hba_port_ptr->first_phy->
4269e86db79SHyon Kim 	    phy.domainPortWWN.wwn) ==
4279e86db79SHyon Kim 	    wwnConversion(DomainAddr.wwn)) {
4289e86db79SHyon Kim 		return (HBA_STATUS_OK);
4299e86db79SHyon Kim 	}
4309e86db79SHyon Kim 	return (HBA_STATUS_ERROR);
4319e86db79SHyon Kim }
432