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