sun_sas.c revision 9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/byteorder.h>
#include <sun_sas.h>
/*
* creates a handle each time Sun_sas_OpenAdapter() is called.
*
* a open_handle_struct was created to keep track of which handles are currently
* open. This prevents a user from using an old handle that corresponds to
* an hba that has already been closed.
*/
CreateHandle(int adapterIndex)
{
const char ROUTINE[] = "CreateHandle";
struct open_handle *new_open_handle;
HBA_UINT8 max_handle_wrap = 0;
if (global_hba_head == NULL) {
"an error as occurred. global_hba_head is "
"NULL. Library may not be loaded yet.");
return (HANDLE_ERROR);
}
if (open_handle_index == 0) {
/*
* If open_handle_index wraps back to zero again,
* that means all handles are currently in use.
* Spec only allows for 16 bits of handles
*/
if (max_handle_wrap == 1) {
"Max number of handles reached.");
return (HANDLE_ERROR);
}
open_handle_index = 1;
max_handle_wrap = 1;
}
}
sizeof (struct open_handle))) == NULL) {
return (HANDLE_ERROR);
}
/* add new open handle struct to the open_handles list */
} else {
}
if (open_handle_index == 0) {
open_handle_index = 1;
}
return (new_handle_index);
}
/*
* given a handle, returns the adapterIndex number.
*
* This functions checkes to see if the given handle corresponds to an open
* HBA. If it does, the adapterIndex is returned.
*/
int
{
struct open_handle *open_handle_ptr;
if (open_handle_ptr == NULL) {
return (-1);
}
return (open_handle_ptr->adapterIndex);
}
/*
* Given a handle, returns the open_handle structure
* The routine assumes that the open_handles_lock has already
* been taken.
*/
struct open_handle *
{
const char ROUTINE[] = "RetrieveOpenHandle";
if (global_hba_head == NULL) {
return (NULL);
}
open_handle_ptr != NULL;
break;
}
}
return (open_handle_ptr);
}
/*
* Given an adapterIndex, this functions returns a pointer to the handle
* structure. This handle structure holds the hba's information
* Caller must take all_hbas_lock first.
*/
struct sun_sas_hba *
RetrieveHandle(int index)
{
break;
}
return (hba_ptr);
}
/*
* Given an adapterIndex, this functions returns a pointer to the handle
* structure and extracts it from the global list.
*
* all_hbas_lock must be taken already.
*/
struct sun_sas_hba *
ExtractHandle(int index)
{
for (hba_ptr = global_hba_head;
if (last) {
} else {
/* Hmm, must be the head of the list. */
}
break;
}
}
return (hba_ptr);
}
/*
* Given an handle, this functions returns a pointer to the handle structure
* for that hba
*
* Caller must take all_hbas_lock first.
*/
struct sun_sas_hba *
{
const char ROUTINE[] = "Retrieve_Sun_sasHandle";
int index;
/* Retrieve fp device path from handle */
if (index == -1) {
"handle could not be found.");
return (handle_struct);
}
if (handle_struct == NULL) {
"could not find index in the handle list.");
return (handle_struct);
}
return (handle_struct);
}
/*
* Take a mutex lock. The routine will try, and if it fails,
* it will loop for a while and retry. If it fails many times,
* it will start writing to the log file.
*/
void
{
int status;
int loop = 0;
const char ROUTINE[] = "lock";
do {
loop++;
switch (status) {
case 0:
break;
case EFAULT:
"Lock failed: fault 0x%x", mp);
break;
case EINVAL:
"Lock failed: invalid 0x%x", mp);
break;
case EBUSY:
if (loop > DEADLOCK_WARNING) {
"Lock busy, possible deadlock:0x%x",
mp);
}
break;
case EOWNERDEAD:
"Lock failed: owner dead 0x%x",
mp);
break;
case ELOCKUNMAPPED:
"Lock failed: unmapped 0x%x",
mp);
break;
case ENOTRECOVERABLE:
"Lock failed: not recoverable 0x%x", mp);
default:
if (loop > DEADLOCK_WARNING) {
"Lock failed: %s 0x%x",
break;
}
}
if (status) {
(void) sleep(LOCK_SLEEP);
}
} while (status);
}
/*
* Unlock a mutex lock.
*/
void
{
(void) mutex_unlock(mp);
}
/*
* Get the Port WWN of the first adapter port. This routine
* is used by the old V1 interfaces so that they can call
* the new V2 interfaces and exhibit the same behavior.
* In the event of error the WWN will be zero.
*
* This function will transition to PAA state but it will not
* verfiy whether data is stale or not
*/
{
const char ROUTINE[] = "getFirstAdapterPortWWN";
int index = 0;
return (pwwn); /* zero WWN */
}
/* Check for stale data */
if (status != HBA_STATUS_OK) {
return (pwwn);
}
/* This is probably an internal failure of the library */
if (hba_ptr->device_path) {
"Internal failure: Adapter %s contains no "
} else {
"Internal failure: Adapter at index %d contains "
}
return (pwwn); /* zero WWN */
}
/* Set the WWN now and return it */
return (pwwn);
}
{
return (tmp);
}
/*
* Using ioctl to send uscsi command out
*/
{
const char ROUTINE[] = "send_uscsi_cmd";
int fd;
/* set default timeout to 200 */
/* reset errno. */
errno = 0;
return (HBA_STATUS_ERROR);
}
} else {
}
"ioctl send uscsi to devpath: %s failed: %s",
return (ret);
}
return (HBA_STATUS_OK);
}
/*
* Check whether the given Domain Address is valid.
*/
{
return (HBA_STATUS_OK);
}
return (HBA_STATUS_ERROR);
}