view usr/src/lib/cfgadm_plugins/scsi/common/cfga_scsi.c @ 10696:cd0f390dd9e2

PSARC 2008/672 thebe SAS/SATA driver PSARC 2008/755 ddi_ssoft_state(9F) and ddi_isoft_state(9F) PSARC 2008/764 Cfgadm SCSI-Plugin MPxIO Support PSARC 2009/125 scsi_device property interfaces 6726110 pmcs driver (driver for thebe) 6726867 SCSAv3
author dh142964 <David.Hollister@Sun.COM>
date Wed, 30 Sep 2009 13:40:27 -0600
parents 68f95e015346
children
line wrap: on
line source

/*
 * 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
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include "cfga_scsi.h"

/*
 * This file contains the entry points to the plug-in as defined in the
 * config_admin(3X) man page.
 */

/*
 * Set the version number
 */
int cfga_version = CFGA_HSL_V2;

/*
 * For debugging - higher values increase verbosity
 */
int _scfga_debug = 0;

#pragma init(_cfgadm_scsi_init)

static void
_cfgadm_scsi_init()
{
	char *tstr;

	if (tstr = getenv("SCFGA_DEBUG")) {
		_scfga_debug = atoi(tstr);
	}
}

/*ARGSUSED*/
cfga_err_t
cfga_change_state(
	cfga_cmd_t state_change_cmd,
	const char *ap_id,
	const char *options,
	struct cfga_confirm *confp,
	struct cfga_msg *msgp,
	char **errstring,
	cfga_flags_t flags)
{
	apid_t apidt = {NULL};
	scfga_ret_t ret;

	if (errstring != NULL) {
		*errstring = NULL;
	}

	/*
	 * All sub-commands which can change state of device require
	 * root privileges.
	 */
	if (geteuid() != 0) {
		return (CFGA_PRIV);
	}

	if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) {
		cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
		return (CFGA_ERROR);
	}

	if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
		return (err_cvt(ret));
	}

	if (options != NULL)
		apidt.flags |= FLAG_DISABLE_RCM;

	/* A dynamic component indicates a device, else it is the bus */
	if (apidt.dyncomp != NULL) {
		ret = dev_change_state(state_change_cmd, &apidt, flags,
		    errstring);
	} else {
		ret = bus_change_state(state_change_cmd, &apidt, confp, flags,
		    errstring);
	}

	apidt_free(&apidt);
	return (err_cvt(ret));
}

/*ARGSUSED*/
cfga_err_t
cfga_private_func(
	const char *func,
	const char *ap_id,
	const char *options,
	struct cfga_confirm *confp,
	struct cfga_msg *msgp,
	char **errstring,
	cfga_flags_t flags)
{
	apid_t apidt = {NULL};
	prompt_t args = {NULL};
	scfga_ret_t ret;

	if (errstring != NULL)
		*errstring = NULL;

	if (geteuid() != 0) {
		return (CFGA_PRIV);
	}

	if (func == NULL) {
		return (CFGA_ERROR);
	}

	if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) {
		cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
		return (CFGA_ERROR);
	}

	if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
		return (err_cvt(ret));
	}

	if (apidt.dyntype == PATH_APID) {
		return (CFGA_OPNOTSUPP);
	}

	if (options != NULL)
		apidt.flags |= FLAG_DISABLE_RCM;

	args.confp = confp;
	args.msgp = msgp;

	/*
	 * Process command
	 */
	ret = invoke_cmd(func, &apidt, &args, flags, errstring);

	apidt_free(&apidt);
	return (err_cvt(ret));
}

/*ARGSUSED*/
cfga_err_t
cfga_test(
	const char *ap_id,
	const char *options,
	struct cfga_msg *msgp,
	char **errstring,
	cfga_flags_t flags)
{
	if (errstring != NULL) {
		*errstring = NULL;
	}

	if (geteuid() != 0) {
		return (CFGA_PRIV);
	}

	return (CFGA_OPNOTSUPP);
}

/*ARGSUSED*/
cfga_err_t
cfga_list_ext(
	const char *ap_id,
	cfga_list_data_t **ap_id_list,
	int *nlistp,
	const char *options,
	const char *listopts,
	char **errstring,
	cfga_flags_t flags)
{
	int hba, expand, nelem;
	ldata_list_t *llp = NULL;
	apid_t apidt = {NULL};
	scfga_cmd_t cmd;
	scfga_ret_t ret;

	if (errstring != NULL) {
		*errstring = NULL;
	}

	if (ap_id_list == NULL || nlistp == NULL) {
		return (CFGA_ERROR);
	}

	*ap_id_list = NULL;
	*nlistp = 0;

	/*
	 * There is no RCM involvement in "list" operations.
	 * The only supported option is OPT_USE_DIFORCE.
	 */
	if (options != NULL && strcmp(options, OPT_USE_DIFORCE) != 0) {
		cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
		return (CFGA_ERROR);
	}

	hba = 0;
	if (GET_DYN(ap_id) == NULL) {
		hba = 1;
	}

	expand = 0;
	if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
		expand = 1;
	}

	/*
	 * We expand published attachment points but not
	 * dynamic attachment points
	 */

	if (!hba) { /* Stat a single device - no expansion for devices */
		cmd = SCFGA_STAT_DEV;
	} else if (!expand) { /* Stat only the HBA */
		cmd = SCFGA_STAT_BUS;
	} else { /* Expand HBA attachment point */
		cmd = SCFGA_STAT_ALL;
	}

	if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
		return (err_cvt(ret));
	}

	/*
	 * Currently only 1 option supported
	 */
	if (options)
		apidt.flags |= FLAG_USE_DIFORCE;

	llp = NULL;
	nelem = 0;

	ret = do_list(&apidt, cmd, &llp, &nelem, errstring);
	if (ret != SCFGA_OK) {
		goto out;
	}

	assert(llp != NULL);

	if (list_ext_postprocess(&llp, nelem, ap_id_list, nlistp,
	    errstring) != SCFGA_OK) {
		assert(*ap_id_list == NULL && *nlistp == 0);
		ret = SCFGA_LIB_ERR;
	} else {
		assert(*ap_id_list != NULL && *nlistp == nelem);
		ret = SCFGA_OK;
	}

	/* FALLTHROUGH */
out:
	list_free(&llp);
	apidt_free(&apidt);
	return (err_cvt(ret));
}


/*ARGSUSED*/
cfga_err_t
cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
{
	cfga_msg(msgp, MSG_HELP_HDR, MSG_HELP_USAGE, 0);

	return (CFGA_OK);
}

/*
 * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
 */