Blame adapt.c

Packit Service 35c908
/*
Packit Service 35c908
 * Copyright (c) 2008, Intel Corporation.
Packit Service 35c908
 *
Packit Service 35c908
 * This program is free software; you can redistribute it and/or modify it
Packit Service 35c908
 * under the terms and conditions of the GNU Lesser General Public License,
Packit Service 35c908
 * version 2.1, as published by the Free Software Foundation.
Packit Service 35c908
 *
Packit Service 35c908
 * This program is distributed in the hope it will be useful, but WITHOUT
Packit Service 35c908
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit Service 35c908
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
Packit Service 35c908
 * for more details.
Packit Service 35c908
 *
Packit Service 35c908
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 35c908
 * along with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 35c908
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 35c908
 *
Packit Service 35c908
 */
Packit Service 35c908
Packit Service 35c908
#include "utils.h"
Packit Service 35c908
#include "api_lib.h"
Packit Service 35c908
#include "adapt_impl.h"
Packit Service 35c908
Packit Service 35c908
static struct sa_table adapter_table;
Packit Service 35c908
static const u_int32_t adapter_handle_offset = 0x100;
Packit Service 35c908
Packit Service 35c908
#define HBA_SHORT_NAME_LIMIT    64
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Support for adapter information.
Packit Service 35c908
 */
Packit Service 35c908
HBA_UINT32
Packit Service 35c908
adapter_get_count(void)
Packit Service 35c908
{
Packit Service 35c908
	return adapter_table.st_limit;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get adapter name.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_get_name(HBA_UINT32 index, char *buf)
Packit Service 35c908
{
Packit Service 35c908
	HBA_STATUS status;
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
Packit Service 35c908
	status = HBA_STATUS_ERROR_ILLEGAL_INDEX;
Packit Service 35c908
	ap = sa_table_lookup(&adapter_table, index);
Packit Service 35c908
	if (ap != NULL) {
Packit Service 35c908
		snprintf(buf, HBA_SHORT_NAME_LIMIT,
Packit Service 35c908
			"%s-%u", ap->ad_name, index);
Packit Service 35c908
		status = HBA_STATUS_OK;
Packit Service 35c908
	}
Packit Service 35c908
	return status;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Add an adapter to the table.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_create(struct adapter_info *ap)
Packit Service 35c908
{
Packit Service 35c908
	int index;
Packit Service 35c908
Packit Service 35c908
	index = sa_table_append(&adapter_table, ap);
Packit Service 35c908
	if (index < 0)
Packit Service 35c908
		return HBA_STATUS_ERROR;
Packit Service 35c908
	ap->ad_index = index;
Packit Service 35c908
	return HBA_STATUS_OK;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
void
Packit Service 35c908
adapter_destroy(struct adapter_info *ap)
Packit Service 35c908
{
Packit Service 35c908
	sa_table_destroy_all(&ap->ad_ports);
Packit Service 35c908
	free(ap);
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
void
Packit Service 35c908
adapter_destroy_all(void)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
	int i;
Packit Service 35c908
Packit Service 35c908
	for (i = 0; i < adapter_table.st_limit; i++) {
Packit Service 35c908
		ap = adapter_table.st_table[i];
Packit Service 35c908
		if (ap) {
Packit Service 35c908
			adapter_table.st_table[i] = NULL;
Packit Service 35c908
			adapter_destroy(ap);
Packit Service 35c908
		}
Packit Service 35c908
	}
Packit Service 35c908
	sa_table_destroy(&adapter_table);
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
struct adapter_info *
Packit Service 35c908
adapter_open_handle(HBA_HANDLE handle)
Packit Service 35c908
{
Packit Service 35c908
	return sa_table_lookup(&adapter_table, handle -
Packit Service 35c908
			       adapter_handle_offset);
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_port(HBA_HANDLE handle, HBA_UINT32 port)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
	struct port_info *pp = NULL;
Packit Service 35c908
Packit Service 35c908
	ap = adapter_open_handle(handle);
Packit Service 35c908
	if (ap)
Packit Service 35c908
		pp = sa_table_lookup(&ap->ad_ports, port);
Packit Service 35c908
	return pp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_rport(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 rport)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	struct port_info *rp = NULL;
Packit Service 35c908
Packit Service 35c908
	pp = adapter_get_port(handle, port);
Packit Service 35c908
	if (pp) {
Packit Service 35c908
		get_rport_info(pp);
Packit Service 35c908
		rp = sa_table_lookup(&pp->ap_rports, rport);
Packit Service 35c908
	}
Packit Service 35c908
	return rp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get the Nth discovered port information.
Packit Service 35c908
 */
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_rport_n(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 n)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	struct port_info *rp = NULL;
Packit Service 35c908
Packit Service 35c908
	pp = adapter_get_port(handle, port);
Packit Service 35c908
	if (pp) {
Packit Service 35c908
		get_rport_info(pp);
Packit Service 35c908
		rp = sa_table_lookup_n(&pp->ap_rports, n);
Packit Service 35c908
	}
Packit Service 35c908
	return rp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
static void *
Packit Service 35c908
adapter_target_match(void *rp_arg, void *target_arg)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp = rp_arg;
Packit Service 35c908
Packit Service 35c908
	if (rp->ap_scsi_target != *(u_int32_t *)target_arg)
Packit Service 35c908
		rp_arg = NULL;
Packit Service 35c908
	return rp_arg;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get the rport by scsi_target number.
Packit Service 35c908
 */
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_rport_target(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 n)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	struct port_info *rp = NULL;
Packit Service 35c908
Packit Service 35c908
	pp = adapter_get_port(handle, port);
Packit Service 35c908
	if (pp) {
Packit Service 35c908
		get_rport_info(pp);
Packit Service 35c908
		rp = sa_table_search(&pp->ap_rports,
Packit Service 35c908
				     adapter_target_match, &n);
Packit Service 35c908
	}
Packit Service 35c908
	return rp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
static void *
Packit Service 35c908
adapter_wwpn_match(void *rp_arg, void *wwpn_arg)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp = rp_arg;
Packit Service 35c908
Packit Service 35c908
	if (memcmp(&rp->ap_attr.PortWWN, wwpn_arg, sizeof(HBA_WWN)) != 0)
Packit Service 35c908
		rp_arg = NULL;
Packit Service 35c908
	return rp_arg;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_rport_by_wwn(struct port_info *pp, HBA_WWN wwpn)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp;
Packit Service 35c908
Packit Service 35c908
	get_rport_info(pp);
Packit Service 35c908
	rp = sa_table_search(&pp->ap_rports, adapter_wwpn_match, &wwpn);
Packit Service 35c908
	return rp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
static void *
Packit Service 35c908
adapter_fcid_match(void *rp_arg, void *fcid_arg)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp = rp_arg;
Packit Service 35c908
Packit Service 35c908
	if (rp->ap_attr.PortFcId != *(fc_fid_t *)fcid_arg)
Packit Service 35c908
		rp_arg = NULL;
Packit Service 35c908
	return rp_arg;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_rport_by_fcid(struct port_info *pp, fc_fid_t fcid)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp;
Packit Service 35c908
Packit Service 35c908
	get_rport_info(pp);
Packit Service 35c908
	rp = sa_table_search(&pp->ap_rports, adapter_fcid_match, &fcid);
Packit Service 35c908
	return rp;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Open adapter by name.
Packit Service 35c908
 */
Packit Service 35c908
HBA_HANDLE
Packit Service 35c908
adapter_open(char *name)
Packit Service 35c908
{
Packit Service 35c908
	char buf[256];
Packit Service 35c908
	HBA_HANDLE i;
Packit Service 35c908
	HBA_STATUS status;
Packit Service 35c908
Packit Service 35c908
	for (i = 0; i < adapter_table.st_limit; i++) {
Packit Service 35c908
		status = adapter_get_name(i, buf);
Packit Service 35c908
		if (status != HBA_STATUS_OK)
Packit Service 35c908
			return 0;
Packit Service 35c908
		if (!strcmp(buf, name))
Packit Service 35c908
			return adapter_handle_offset + i;
Packit Service 35c908
	}
Packit Service 35c908
	return 0;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get port by WWPN.
Packit Service 35c908
 * Returns NULL if WWN not unique.
Packit Service 35c908
 * If countp is non-NULL, the int it points to will be set to the
Packit Service 35c908
 * number found so that the caller can tell if the WWN was ambiguous.
Packit Service 35c908
 */
Packit Service 35c908
struct port_info *
Packit Service 35c908
adapter_get_port_by_wwn(HBA_HANDLE handle, HBA_WWN wwn, int *countp)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
	struct port_info *pp_found = NULL;
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	int count = 0;
Packit Service 35c908
	int p;
Packit Service 35c908
Packit Service 35c908
	ap = adapter_open_handle(handle);
Packit Service 35c908
	if (ap != NULL) {
Packit Service 35c908
		for (p = 0; p < ap->ad_ports.st_limit; p++) {
Packit Service 35c908
			pp = ap->ad_ports.st_table[p];
Packit Service 35c908
			if (pp &&
Packit Service 35c908
			    !memcmp(&pp->ap_attr.PortWWN, &wwn, sizeof(wwn))) {
Packit Service 35c908
				count++;
Packit Service 35c908
				pp_found = pp;
Packit Service 35c908
			}
Packit Service 35c908
		}
Packit Service 35c908
	}
Packit Service 35c908
	if (count > 1)
Packit Service 35c908
		pp_found = NULL;
Packit Service 35c908
	if (countp != NULL)
Packit Service 35c908
		*countp = count;
Packit Service 35c908
	return pp_found;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Open adapter by WWN.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_open_by_wwn(HBA_HANDLE *phandle, HBA_WWN wwn)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	HBA_HANDLE found_handle = 0;
Packit Service 35c908
	int count = 0;
Packit Service 35c908
	HBA_STATUS status;
Packit Service 35c908
	int i;
Packit Service 35c908
	int p;
Packit Service 35c908
Packit Service 35c908
	for (i = 0; i < adapter_table.st_limit; i++) {
Packit Service 35c908
		ap = adapter_table.st_table[i];
Packit Service 35c908
		if (!ap)
Packit Service 35c908
			continue;
Packit Service 35c908
		if (memcmp(&ap->ad_attr.NodeWWN, &wwn, sizeof(wwn)) == 0) {
Packit Service 35c908
			count++;
Packit Service 35c908
			found_handle = ap->ad_index + adapter_handle_offset;
Packit Service 35c908
		} else {
Packit Service 35c908
			for (p = 0; p < ap->ad_ports.st_limit; p++) {
Packit Service 35c908
				pp = ap->ad_ports.st_table[p];
Packit Service 35c908
				if (!pp)
Packit Service 35c908
					continue;
Packit Service 35c908
				if (memcmp(&pp->ap_attr.PortWWN,
Packit Service 35c908
					   &wwn, sizeof(wwn)) == 0) {
Packit Service 35c908
					count++;
Packit Service 35c908
					found_handle = ap->ad_index +
Packit Service 35c908
						       adapter_handle_offset;
Packit Service 35c908
				}
Packit Service 35c908
			}
Packit Service 35c908
		}
Packit Service 35c908
	}
Packit Service 35c908
Packit Service 35c908
	*phandle = HBA_HANDLE_INVALID;
Packit Service 35c908
	if (count == 1) {
Packit Service 35c908
		status = HBA_STATUS_OK;
Packit Service 35c908
		*phandle = found_handle;
Packit Service 35c908
	} else if (count > 1) {
Packit Service 35c908
		status = HBA_STATUS_ERROR_AMBIGUOUS_WWN;
Packit Service 35c908
	} else {
Packit Service 35c908
		status = HBA_STATUS_ERROR_ILLEGAL_WWN;
Packit Service 35c908
	}
Packit Service 35c908
	return status;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Close adapter.
Packit Service 35c908
 */
Packit Service 35c908
void
Packit Service 35c908
adapter_close(HBA_HANDLE handle)
Packit Service 35c908
{
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get adapter attributes.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_get_attr(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES *pattr)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
Packit Service 35c908
	ap = adapter_open_handle(handle);
Packit Service 35c908
	if (ap) {
Packit Service 35c908
		*pattr = ap->ad_attr;       /* struct copy */
Packit Service 35c908
		return HBA_STATUS_OK;
Packit Service 35c908
	}
Packit Service 35c908
	return HBA_STATUS_ERROR;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get adapter port attributes.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_get_port_attr(HBA_HANDLE handle, HBA_UINT32 port,
Packit Service 35c908
			HBA_PORTATTRIBUTES *pattr)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
Packit Service 35c908
	pp = adapter_get_port(handle, port);
Packit Service 35c908
	if (pp) {
Packit Service 35c908
		*pattr = pp->ap_attr;       /* struct copy */
Packit Service 35c908
		return HBA_STATUS_OK;
Packit Service 35c908
	}
Packit Service 35c908
	return HBA_STATUS_ERROR;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get discovered (remote) port attributes.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_get_rport_attr(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 rport,
Packit Service 35c908
			 HBA_PORTATTRIBUTES *pattr)
Packit Service 35c908
{
Packit Service 35c908
	struct port_info *rp;
Packit Service 35c908
Packit Service 35c908
	rp = adapter_get_rport_n(handle, port, rport);
Packit Service 35c908
	if (rp) {
Packit Service 35c908
		*pattr = rp->ap_attr;       /* struct copy */
Packit Service 35c908
		return HBA_STATUS_OK;
Packit Service 35c908
	}
Packit Service 35c908
	return HBA_STATUS_ERROR;
Packit Service 35c908
}
Packit Service 35c908
Packit Service 35c908
/*
Packit Service 35c908
 * Get adapter port attributes.
Packit Service 35c908
 */
Packit Service 35c908
HBA_STATUS
Packit Service 35c908
adapter_get_port_attr_by_wwn(HBA_HANDLE handle, HBA_WWN wwn,
Packit Service 35c908
			       HBA_PORTATTRIBUTES *pattr)
Packit Service 35c908
{
Packit Service 35c908
	struct adapter_info *ap;
Packit Service 35c908
	struct port_info *pp;
Packit Service 35c908
	struct port_info *pp_found = NULL;
Packit Service 35c908
	u_int32_t p;
Packit Service 35c908
	int count = 0;
Packit Service 35c908
	HBA_STATUS status;
Packit Service 35c908
Packit Service 35c908
	ap = adapter_open_handle(handle);
Packit Service 35c908
	if (ap != NULL) {
Packit Service 35c908
		for (p = 0; p < ap->ad_ports.st_limit; p++) {
Packit Service 35c908
			pp = ap->ad_ports.st_table[p];
Packit Service 35c908
			if (pp == NULL)
Packit Service 35c908
				continue;
Packit Service 35c908
			if (!memcmp(&pp->ap_attr.PortWWN, &wwn, sizeof(wwn))) {
Packit Service 35c908
				count++;
Packit Service 35c908
				pp_found = pp;
Packit Service 35c908
			}
Packit Service 35c908
			pp = sa_table_search(&pp->ap_rports,
Packit Service 35c908
					     adapter_wwpn_match,
Packit Service 35c908
					     &wwn);
Packit Service 35c908
			if (pp) {
Packit Service 35c908
				count++;
Packit Service 35c908
				pp_found = pp;
Packit Service 35c908
			}
Packit Service 35c908
		}
Packit Service 35c908
	}
Packit Service 35c908
	pp = pp_found;
Packit Service 35c908
	if (pp != NULL) {
Packit Service 35c908
		if (count > 1) {
Packit Service 35c908
			status = HBA_STATUS_ERROR_AMBIGUOUS_WWN;
Packit Service 35c908
		} else {
Packit Service 35c908
			*pattr = pp->ap_attr;       /* struct copy */
Packit Service 35c908
			status = HBA_STATUS_OK;
Packit Service 35c908
		}
Packit Service 35c908
	} else {
Packit Service 35c908
		status = HBA_STATUS_ERROR_ILLEGAL_WWN;
Packit Service 35c908
	}
Packit Service 35c908
	return status;
Packit Service 35c908
}
Packit Service 35c908