OpenSolaris_b135/cmd/pcidr/plugins/default/pcidr_cfga.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <string.h>
#include <sys/param.h>
#include <assert.h>
#include <pcidr.h>
#include <pcidr_cfga.h>


/*
 * misc config_admin(3cfgadm) related routines
 */

static struct {
	cfga_stat_t stat;
	char *name;
} pcidr_cfga_stat_nametab[] = {
	{CFGA_STAT_NONE, "CFGA_STAT_NONE"},
	{CFGA_STAT_EMPTY, "CFGA_STAT_EMPTY"},
	{CFGA_STAT_DISCONNECTED, "CFGA_STAT_DISCONNECTED"},
	{CFGA_STAT_CONNECTED, "CFGA_STAT_CONNECTED"},
	{CFGA_STAT_UNCONFIGURED, "CFGA_STAT_UNCONFIGURED"},
	{CFGA_STAT_CONFIGURED, "CFGA_STAT_CONFIGURED"},
};
static int pcidr_cfga_stat_nametab_len =
    sizeof (pcidr_cfga_stat_nametab) / sizeof (pcidr_cfga_stat_nametab[0]);

char *
pcidr_cfga_stat_name(cfga_stat_t val)
{
	int i;

	for (i = 0; i < pcidr_cfga_stat_nametab_len; i++) {
		if (pcidr_cfga_stat_nametab[i].stat == val)
			return (pcidr_cfga_stat_nametab[i].name);
	}
	return (NULL);
}


static struct {
	cfga_stat_t cmd;
	char *name;
} pcidr_cfga_cmd_nametab[] = {
	{CFGA_CMD_NONE, "CFGA_CMD_NONE"},
	{CFGA_CMD_LOAD, "CFGA_CMD_LOAD"},
	{CFGA_CMD_UNLOAD, "CFGA_CMD_UNLOAD"},
	{CFGA_CMD_CONNECT, "CFGA_CMD_CONNECT"},
	{CFGA_CMD_DISCONNECT, "CFGA_CMD_DISCONNECT"},
	{CFGA_CMD_CONFIGURE, "CFGA_CMD_CONFIGURE"},
	{CFGA_CMD_UNCONFIGURE, "CFGA_CMD_UNCONFIGURE"},
};
static int pcidr_cfga_cmd_nametab_len =
    sizeof (pcidr_cfga_cmd_nametab) / sizeof (pcidr_cfga_cmd_nametab[0]);

char *
pcidr_cfga_cmd_name(cfga_cmd_t val)
{
	int i;

	for (i = 0; i < pcidr_cfga_cmd_nametab_len; i++) {
		if (pcidr_cfga_cmd_nametab[i].cmd == val)
			return (pcidr_cfga_cmd_nametab[i].name);
	}
	return (NULL);
}


static struct {
	cfga_cond_t cond;
	char *name;
} pcidr_cfga_cond_nametab[] = {
	{CFGA_COND_UNKNOWN, "CFGA_COND_UNKNOWN"},
	{CFGA_COND_OK, "CFGA_COND_OK"},
	{CFGA_COND_FAILING, "CFGA_COND_FAILING"},
	{CFGA_COND_FAILED, "CFGA_COND_FAILED"},
	{CFGA_COND_UNUSABLE, "CFGA_COND_UNUSABLE"},
};
static int pcidr_cfga_cond_nametab_len =
    sizeof (pcidr_cfga_cond_nametab) / sizeof (pcidr_cfga_cond_nametab[0]);

char *
pcidr_cfga_cond_name(cfga_cond_t val)
{
	int i;

	for (i = 0; i < pcidr_cfga_cond_nametab_len; i++) {
		if (pcidr_cfga_cond_nametab[i].cond == val)
			return (pcidr_cfga_cond_nametab[i].name);
	}
	return (NULL);
}


static struct {
	cfga_err_t err;
	char *name;
} pcidr_cfga_err_nametab[] = {
	{CFGA_OK, "CFGA_OK"},
	{CFGA_NACK, "CFGA_NACK"},
	{CFGA_NOTSUPP, "CFGA_NOTSUPP"},
	{CFGA_OPNOTSUPP, "CFGA_OPNOTSUPP"},
	{CFGA_PRIV, "CFGA_PRIV"},
	{CFGA_BUSY, "CFGA_BUSY"},
	{CFGA_SYSTEM_BUSY, "CFGA_SYSTEM_BUSY"},
	{CFGA_DATA_ERROR, "CFGA_DATA_ERROR"},
	{CFGA_LIB_ERROR, "CFGA_LIB_ERROR"},
	{CFGA_NO_LIB, "CFGA_NO_LIB"},
	{CFGA_INSUFFICENT_CONDITION, "CFGA_INSUFFICENT_CONDITION"},
	{CFGA_INVAL, "CFGA_INVAL"},
	{CFGA_ERROR, "CFGA_ERROR"},
	{CFGA_APID_NOEXIST, "CFGA_APID_NOEXIST"},
	{CFGA_ATTR_INVAL, "CFGA_ATTR_INVAL"},
};
static int pcidr_cfga_err_nametab_len =
    sizeof (pcidr_cfga_err_nametab) / sizeof (pcidr_cfga_err_nametab[0]);

char *
pcidr_cfga_err_name(cfga_err_t val)
{
	int i;

	for (i = 0; i < pcidr_cfga_err_nametab_len; i++) {
		if (pcidr_cfga_err_nametab[i].err == val)
			return (pcidr_cfga_err_nametab[i].name);
	}
	return (NULL);
}


void
pcidr_print_cfga(dlvl_t lvl, cfga_list_data_t *datap, char *prestr)
{
	char *str;

	if (prestr == NULL)
		prestr = "";

	dprint(lvl, "%slogical APID = %s\n", prestr, datap->ap_log_id);
	dprint(lvl, "%sphyiscal APID = %s\n", prestr, datap->ap_phys_id);
	dprint(lvl, "%sAP class = %s\n", prestr, datap->ap_class);

	str = pcidr_cfga_stat_name(datap->ap_r_state);
	if (str == NULL)
		str = "(unrecognized cfga_stat_t value!)";
	dprint(lvl, "%sAP receptacle state = %s\n", prestr, str);

	str = pcidr_cfga_stat_name(datap->ap_o_state);
	if (str == NULL)
		str = "(unrecognized cfga_stat_t value!)";
	dprint(lvl, "%sAP occupant state = %s\n", prestr, str);

	str = pcidr_cfga_cond_name(datap->ap_cond);
	if (str == NULL)
		str = "(unrecognized cfga_cond_t value!)";
	dprint(lvl, "%sAP condition = %s\n", prestr, str);

	dprint(lvl, "%sAP busy indicator = %d\n", prestr, datap->ap_busy);

	str = ctime(&datap->ap_status_time);
	str[strlen(str) - 1] = '\0';	/* get rid of newline */
	dprint(lvl, "%sAP last change time = %ld (%s)\n", prestr,
	    datap->ap_status_time, str);

	dprint(lvl, "%sAP info = %s\n", prestr, datap->ap_info);
	dprint(lvl, "%sAP type = %s\n", prestr, datap->ap_type);
}


/*
 * for use with config_admin(3cfgadm) functions in their
 * <struct cfga_msg *msgp> parameter
 */
int
pcidr_cfga_msg_func(void *datap, const char *msg)
{
	pcidr_cfga_msg_data_t *dp = (pcidr_cfga_msg_data_t *)datap;
	char *prestr = dp->prestr;

	if (prestr == NULL)
		prestr = "";

	dprint(dp->dlvl, "%s%s", prestr, msg);
	return (0);
}


/*
 * for use with config_admin(3cfgadm) functions in their
 * <struct cfga_confirm *confp> parameter
 */
/*ARGSUSED*/
int
pcidr_cfga_confirm_func(void *datap, const char *msg)
{
	return (1);
}


/*
 * returns 0 if successful, -1 if unusuccesful, 1 if the AP already had
 * <cmd> performed on it
 */
int
pcidr_cfga_do_cmd(cfga_cmd_t cmd, cfga_list_data_t *cfga_listp)
{
	char *fn = "pcidr_cfga_do_cmd";
	int rv, i, j;
	char *cmdnm, *cfga_errstr, *apid, *str;
	int cmdarr[2];
	int cmdarr_len = sizeof (cmdarr) / sizeof (cmdarr[0]);

	struct cfga_msg cfga_msg;
	pcidr_cfga_msg_data_t cfga_msg_data;
	struct cfga_confirm cfga_confirm;
	cfga_flags_t cfga_flags;

	cmdnm = pcidr_cfga_cmd_name(cmd);
	assert(cmdnm != NULL);

	apid = cfga_listp->ap_phys_id;
	cfga_msg_data.dlvl = DDEBUG;
	cfga_msg_data.prestr = "pcidr_cfga_do_cmd(msg): ";
	cfga_msg.message_routine = pcidr_cfga_msg_func;
	cfga_msg.appdata_ptr = (void *)&cfga_msg_data;
	cfga_confirm.confirm = pcidr_cfga_confirm_func;
	cfga_confirm.appdata_ptr = NULL;
	cfga_flags = CFGA_FLAG_VERBOSE;

	if (cfga_listp->ap_busy != 0) {
		dprint(DDEBUG, "%s: apid = %s is busy\n",
		    fn, cfga_listp->ap_phys_id);
		return (-1);
	}

	/*
	 * explicitly perform each step that would otherwise be done
	 * implicitly by cfgadm to isolate errors
	 */
	j = 0;
	switch (cmd) {
	case CFGA_CMD_CONFIGURE:
		if (cfga_listp->ap_o_state < CFGA_STAT_CONNECTED) {
			cmdarr[j] = CFGA_CMD_CONNECT;
			j++;
		}
		if (cfga_listp->ap_o_state < CFGA_STAT_CONFIGURED) {
			cmdarr[j] = CFGA_CMD_CONFIGURE;
			j++;
		}
		if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED)
			goto ALREADY;
		break;
	case CFGA_CMD_DISCONNECT:
		if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED) {
			cmdarr[j] = CFGA_CMD_UNCONFIGURE;
			j++;
		}
		if (cfga_listp->ap_o_state >= CFGA_STAT_CONNECTED) {
			cmdarr[j] = CFGA_CMD_DISCONNECT;
			j++;
		}
		if (cfga_listp->ap_r_state <= CFGA_STAT_DISCONNECTED)
			goto ALREADY;
		break;
	default:
		dprint(DDEBUG, "%s: unsupported cmd %d\n", cmd);
		return (-1);
	}
	assert(j <= cmdarr_len);

	for (i = 0; i < j; i++) {
		cmd = cmdarr[i];
		cmdnm = pcidr_cfga_cmd_name(cmd);
		assert(cmdnm != NULL);

		rv = config_change_state(cmd, 1, &apid, NULL, &cfga_confirm,
		    &cfga_msg, &cfga_errstr, cfga_flags);
		if (rv != CFGA_OK) {
			dprint(DDEBUG, "%s: command %s failed on apid %s",
			    fn, cmdnm, apid);

			str = pcidr_cfga_err_name(rv);
			if (str == NULL)
				str = "unrecognized rv!";
			dprint(DDEBUG, ": rv = %d (%s)", rv, str);

			if (cfga_errstr != NULL) {
				dprint(DDEBUG, ", error string = "
				    "\"%s\"", cfga_errstr);
				free(cfga_errstr);
			}
			dprint(DDEBUG, "\n");
			return (-1);
		}
	}

	return (0);
	/*NOTREACHED*/
ALREADY:
	dprint(DDEBUG, "%s: command %s already done on apid %s\n",
	    fn, cmdnm, apid);
	return (1);
}