/*
* 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 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <macros.h>
#include <libdevinfo.h>
#define CFGA_PLUGIN_LIB
#include <config_admin.h>
#include "ap.h"
int cfga_version = CFGA_HSL_V2;
/*ARGSUSED*/
cfga_err_t
cfga_change_state(
cfga_cmd_t cfga_cmd,
const char *ap_id,
const char *options,
struct cfga_confirm *confp,
struct cfga_msg *msgp,
char **errstring,
cfga_flags_t flags)
{
int cmd;
const char *name;
apd_t *a;
cfga_err_t rc;
if ((rc = ap_state_cmd(cfga_cmd, &cmd)) != CFGA_OK)
return (rc);
rc = CFGA_LIB_ERROR;
if ((a = apd_alloc(ap_id, flags, errstring, msgp, confp)) == NULL)
return (rc);
name = ap_cmd_name(cmd);
if ((rc = ap_cmd_parse(a, name, options, NULL)) == CFGA_OK)
rc = ap_cmd_seq(a, cmd);
apd_free(a);
return (rc);
}
/*
* Check if this is a valid -x command.
*/
static int
private_func(const char *function)
{
char **f;
static char *
private_funcs[] = {
"assign",
"unassign",
"poweron",
"poweroff",
"passthru",
"errtest",
NULL
};
for (f = private_funcs; *f != NULL; f++)
if (strcmp(*f, function) == 0)
break;
return (*f == NULL ? CFGA_INVAL : CFGA_OK);
}
/*ARGSUSED*/
cfga_err_t
cfga_private_func(
const char *function,
const char *ap_id,
const char *options,
struct cfga_confirm *confp,
struct cfga_msg *msgp,
char **errstring,
cfga_flags_t flags)
{
int cmd;
apd_t *a;
cfga_err_t rc;
DBG("cfga_private_func(%s)\n", ap_id);
rc = CFGA_LIB_ERROR;
if ((a = apd_alloc(ap_id, flags, errstring, msgp, confp)) == NULL)
return (rc);
else if ((rc = private_func(function)) != CFGA_OK) {
ap_err(a, ERR_CMD_INVAL, function);
goto done;
} else if ((rc = ap_cmd_parse(a, function, options, &cmd)) != CFGA_OK)
goto done;
else if (cmd == CMD_ERRTEST)
rc = ap_test_err(a, options);
else
rc = ap_cmd_exec(a, cmd);
done:
apd_free(a);
return (rc);
}
/*ARGSUSED*/
cfga_err_t
cfga_test(
const char *ap_id,
const char *options,
struct cfga_msg *msgp,
char **errstring,
cfga_flags_t flags)
{
int cmd;
const char *f;
apd_t *a;
cfga_err_t rc;
DBG("cfga_test(%s)\n", ap_id);
f = "test";
rc = CFGA_LIB_ERROR;
/*
* A test that is not sequenced by a change
* state operation should be forced.
*/
flags |= CFGA_FLAG_FORCE;
if ((a = apd_alloc(ap_id, flags, errstring, msgp, NULL)) == NULL)
return (rc);
else if ((rc = ap_cmd_parse(a, f, options, &cmd)) != CFGA_OK)
goto done;
else
rc = ap_cmd_exec(a, cmd);
done:
apd_free(a);
return (rc);
}
/*ARGSUSED*/
cfga_err_t
cfga_list_ext(
const char *ap_id,
cfga_list_data_t **ap_id_list,
int *nlist,
const char *options,
const char *listopts,
char **errstring,
cfga_flags_t flags)
{
int i;
int apcnt;
const char *f;
apd_t *a;
size_t szl, szp;
cfga_list_data_t *aplist, *ap;
cfga_err_t rc;
rc = CFGA_LIB_ERROR;
aplist = NULL;
f = ap_cmd_name(CMD_STATUS);
DBG("cfga_list_ext(%s %x)\n", ap_id, flags);
if ((a = apd_alloc(ap_id, flags, errstring, NULL, NULL)) == NULL)
return (rc);
else if ((rc = ap_cmd_parse(a, f, options, NULL)) != CFGA_OK)
goto done;
apcnt = ap_cnt(a);
DBG("apcnt=%d\n", apcnt);
if ((aplist = calloc(apcnt, sizeof (*aplist))) == NULL) {
rc = CFGA_LIB_ERROR;
ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
goto done;
}
ap = aplist;
szl = sizeof (ap->ap_log_id);
szp = sizeof (ap->ap_phys_id);
/*
* Initialize the AP specified directly by the caller.
* The target ID for the 0th element already includes
* the (potential) dynamic portion. The dynamic portion
* does need to be appended to the path to form the
* physical apid for components.
*/
(void) strncpy(ap->ap_log_id, a->target, szl - 1);
(void) snprintf(ap->ap_phys_id, szp, "%s%s%s", a->path,
a->tgt != AP_BOARD ? "::" : "",
a->tgt != AP_BOARD ? a->cid : "");
DBG("ap_phys_id=%s ap_log_id=%s\n", ap->ap_phys_id, ap->ap_log_id);
if (a->tgt == AP_BOARD) {
ap_init(a, ap++);
/*
* Initialize the components, if any.
*/
for (i = 0; i < apcnt - 1; i++, ap++) {
char dyn[MAXPATHLEN];
ap_cm_id(a, i, dyn, sizeof (dyn));
(void) snprintf(ap->ap_log_id, szl, "%s::%s",
a->target, dyn);
(void) snprintf(ap->ap_phys_id, szp, "%s::%s",
a->path, dyn);
ap_cm_init(a, ap, i);
DBG("ap_phys_id=%s ap_log_id=%s\n",
ap->ap_phys_id, ap->ap_log_id);
}
} else
ap_cm_init(a, ap, 0);
apd_free(a);
*ap_id_list = aplist;
*nlist = apcnt;
return (CFGA_OK);
done:
s_free(aplist);
apd_free(a);
return (rc);
}
/*ARGSUSED*/
cfga_err_t
cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
{
return (ap_help(msgp, options, flags));
}
/*
* cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
*/