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