Blame adapt.c

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