170025d76Sjohnny /*
270025d76Sjohnny * CDDL HEADER START
370025d76Sjohnny *
470025d76Sjohnny * The contents of this file are subject to the terms of the
570025d76Sjohnny * Common Development and Distribution License, Version 1.0 only
670025d76Sjohnny * (the "License"). You may not use this file except in compliance
770025d76Sjohnny * with the License.
870025d76Sjohnny *
970025d76Sjohnny * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1070025d76Sjohnny * or http://www.opensolaris.org/os/licensing.
1170025d76Sjohnny * See the License for the specific language governing permissions
1270025d76Sjohnny * and limitations under the License.
1370025d76Sjohnny *
1470025d76Sjohnny * When distributing Covered Code, include this CDDL HEADER in each
1570025d76Sjohnny * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1670025d76Sjohnny * If applicable, add the following below this CDDL HEADER, with the
1770025d76Sjohnny * fields enclosed by brackets "[]" replaced with your own identifying
1870025d76Sjohnny * information: Portions Copyright [yyyy] [name of copyright owner]
1970025d76Sjohnny *
2070025d76Sjohnny * CDDL HEADER END
2170025d76Sjohnny */
2270025d76Sjohnny /*
2370025d76Sjohnny * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2470025d76Sjohnny * Use is subject to license terms.
2570025d76Sjohnny */
2670025d76Sjohnny
2770025d76Sjohnny #include <string.h>
2870025d76Sjohnny #include <sys/param.h>
2970025d76Sjohnny #include <assert.h>
3070025d76Sjohnny #include <pcidr.h>
3170025d76Sjohnny #include <pcidr_cfga.h>
3270025d76Sjohnny
3370025d76Sjohnny
3470025d76Sjohnny /*
3570025d76Sjohnny * misc config_admin(3cfgadm) related routines
3670025d76Sjohnny */
3770025d76Sjohnny
3870025d76Sjohnny static struct {
3970025d76Sjohnny cfga_stat_t stat;
4070025d76Sjohnny char *name;
4170025d76Sjohnny } pcidr_cfga_stat_nametab[] = {
4270025d76Sjohnny {CFGA_STAT_NONE, "CFGA_STAT_NONE"},
4370025d76Sjohnny {CFGA_STAT_EMPTY, "CFGA_STAT_EMPTY"},
4470025d76Sjohnny {CFGA_STAT_DISCONNECTED, "CFGA_STAT_DISCONNECTED"},
4570025d76Sjohnny {CFGA_STAT_CONNECTED, "CFGA_STAT_CONNECTED"},
4670025d76Sjohnny {CFGA_STAT_UNCONFIGURED, "CFGA_STAT_UNCONFIGURED"},
4770025d76Sjohnny {CFGA_STAT_CONFIGURED, "CFGA_STAT_CONFIGURED"},
4870025d76Sjohnny };
4970025d76Sjohnny static int pcidr_cfga_stat_nametab_len =
5070025d76Sjohnny sizeof (pcidr_cfga_stat_nametab) / sizeof (pcidr_cfga_stat_nametab[0]);
5170025d76Sjohnny
5270025d76Sjohnny char *
pcidr_cfga_stat_name(cfga_stat_t val)5370025d76Sjohnny pcidr_cfga_stat_name(cfga_stat_t val)
5470025d76Sjohnny {
5570025d76Sjohnny int i;
5670025d76Sjohnny
5770025d76Sjohnny for (i = 0; i < pcidr_cfga_stat_nametab_len; i++) {
5870025d76Sjohnny if (pcidr_cfga_stat_nametab[i].stat == val)
5970025d76Sjohnny return (pcidr_cfga_stat_nametab[i].name);
6070025d76Sjohnny }
6170025d76Sjohnny return (NULL);
6270025d76Sjohnny }
6370025d76Sjohnny
6470025d76Sjohnny
6570025d76Sjohnny static struct {
66*2c2d21e9SRichard Lowe cfga_cmd_t cmd;
6770025d76Sjohnny char *name;
6870025d76Sjohnny } pcidr_cfga_cmd_nametab[] = {
6970025d76Sjohnny {CFGA_CMD_NONE, "CFGA_CMD_NONE"},
7070025d76Sjohnny {CFGA_CMD_LOAD, "CFGA_CMD_LOAD"},
7170025d76Sjohnny {CFGA_CMD_UNLOAD, "CFGA_CMD_UNLOAD"},
7270025d76Sjohnny {CFGA_CMD_CONNECT, "CFGA_CMD_CONNECT"},
7370025d76Sjohnny {CFGA_CMD_DISCONNECT, "CFGA_CMD_DISCONNECT"},
7470025d76Sjohnny {CFGA_CMD_CONFIGURE, "CFGA_CMD_CONFIGURE"},
7570025d76Sjohnny {CFGA_CMD_UNCONFIGURE, "CFGA_CMD_UNCONFIGURE"},
7670025d76Sjohnny };
7770025d76Sjohnny static int pcidr_cfga_cmd_nametab_len =
7870025d76Sjohnny sizeof (pcidr_cfga_cmd_nametab) / sizeof (pcidr_cfga_cmd_nametab[0]);
7970025d76Sjohnny
8070025d76Sjohnny char *
pcidr_cfga_cmd_name(cfga_cmd_t val)8170025d76Sjohnny pcidr_cfga_cmd_name(cfga_cmd_t val)
8270025d76Sjohnny {
8370025d76Sjohnny int i;
8470025d76Sjohnny
8570025d76Sjohnny for (i = 0; i < pcidr_cfga_cmd_nametab_len; i++) {
8670025d76Sjohnny if (pcidr_cfga_cmd_nametab[i].cmd == val)
8770025d76Sjohnny return (pcidr_cfga_cmd_nametab[i].name);
8870025d76Sjohnny }
8970025d76Sjohnny return (NULL);
9070025d76Sjohnny }
9170025d76Sjohnny
9270025d76Sjohnny
9370025d76Sjohnny static struct {
9470025d76Sjohnny cfga_cond_t cond;
9570025d76Sjohnny char *name;
9670025d76Sjohnny } pcidr_cfga_cond_nametab[] = {
9770025d76Sjohnny {CFGA_COND_UNKNOWN, "CFGA_COND_UNKNOWN"},
9870025d76Sjohnny {CFGA_COND_OK, "CFGA_COND_OK"},
9970025d76Sjohnny {CFGA_COND_FAILING, "CFGA_COND_FAILING"},
10070025d76Sjohnny {CFGA_COND_FAILED, "CFGA_COND_FAILED"},
10170025d76Sjohnny {CFGA_COND_UNUSABLE, "CFGA_COND_UNUSABLE"},
10270025d76Sjohnny };
10370025d76Sjohnny static int pcidr_cfga_cond_nametab_len =
10470025d76Sjohnny sizeof (pcidr_cfga_cond_nametab) / sizeof (pcidr_cfga_cond_nametab[0]);
10570025d76Sjohnny
10670025d76Sjohnny char *
pcidr_cfga_cond_name(cfga_cond_t val)10770025d76Sjohnny pcidr_cfga_cond_name(cfga_cond_t val)
10870025d76Sjohnny {
10970025d76Sjohnny int i;
11070025d76Sjohnny
11170025d76Sjohnny for (i = 0; i < pcidr_cfga_cond_nametab_len; i++) {
11270025d76Sjohnny if (pcidr_cfga_cond_nametab[i].cond == val)
11370025d76Sjohnny return (pcidr_cfga_cond_nametab[i].name);
11470025d76Sjohnny }
11570025d76Sjohnny return (NULL);
11670025d76Sjohnny }
11770025d76Sjohnny
11870025d76Sjohnny
11970025d76Sjohnny static struct {
12070025d76Sjohnny cfga_err_t err;
12170025d76Sjohnny char *name;
12270025d76Sjohnny } pcidr_cfga_err_nametab[] = {
12370025d76Sjohnny {CFGA_OK, "CFGA_OK"},
12470025d76Sjohnny {CFGA_NACK, "CFGA_NACK"},
12570025d76Sjohnny {CFGA_NOTSUPP, "CFGA_NOTSUPP"},
12670025d76Sjohnny {CFGA_OPNOTSUPP, "CFGA_OPNOTSUPP"},
12770025d76Sjohnny {CFGA_PRIV, "CFGA_PRIV"},
12870025d76Sjohnny {CFGA_BUSY, "CFGA_BUSY"},
12970025d76Sjohnny {CFGA_SYSTEM_BUSY, "CFGA_SYSTEM_BUSY"},
13070025d76Sjohnny {CFGA_DATA_ERROR, "CFGA_DATA_ERROR"},
13170025d76Sjohnny {CFGA_LIB_ERROR, "CFGA_LIB_ERROR"},
13270025d76Sjohnny {CFGA_NO_LIB, "CFGA_NO_LIB"},
13370025d76Sjohnny {CFGA_INSUFFICENT_CONDITION, "CFGA_INSUFFICENT_CONDITION"},
13470025d76Sjohnny {CFGA_INVAL, "CFGA_INVAL"},
13570025d76Sjohnny {CFGA_ERROR, "CFGA_ERROR"},
13670025d76Sjohnny {CFGA_APID_NOEXIST, "CFGA_APID_NOEXIST"},
13770025d76Sjohnny {CFGA_ATTR_INVAL, "CFGA_ATTR_INVAL"},
13870025d76Sjohnny };
13970025d76Sjohnny static int pcidr_cfga_err_nametab_len =
14070025d76Sjohnny sizeof (pcidr_cfga_err_nametab) / sizeof (pcidr_cfga_err_nametab[0]);
14170025d76Sjohnny
14270025d76Sjohnny char *
pcidr_cfga_err_name(cfga_err_t val)14370025d76Sjohnny pcidr_cfga_err_name(cfga_err_t val)
14470025d76Sjohnny {
14570025d76Sjohnny int i;
14670025d76Sjohnny
14770025d76Sjohnny for (i = 0; i < pcidr_cfga_err_nametab_len; i++) {
14870025d76Sjohnny if (pcidr_cfga_err_nametab[i].err == val)
14970025d76Sjohnny return (pcidr_cfga_err_nametab[i].name);
15070025d76Sjohnny }
15170025d76Sjohnny return (NULL);
15270025d76Sjohnny }
15370025d76Sjohnny
15470025d76Sjohnny
15570025d76Sjohnny void
pcidr_print_cfga(dlvl_t lvl,cfga_list_data_t * datap,char * prestr)15670025d76Sjohnny pcidr_print_cfga(dlvl_t lvl, cfga_list_data_t *datap, char *prestr)
15770025d76Sjohnny {
15870025d76Sjohnny char *str;
15970025d76Sjohnny
16070025d76Sjohnny if (prestr == NULL)
16170025d76Sjohnny prestr = "";
16270025d76Sjohnny
16370025d76Sjohnny dprint(lvl, "%slogical APID = %s\n", prestr, datap->ap_log_id);
16470025d76Sjohnny dprint(lvl, "%sphyiscal APID = %s\n", prestr, datap->ap_phys_id);
16570025d76Sjohnny dprint(lvl, "%sAP class = %s\n", prestr, datap->ap_class);
16670025d76Sjohnny
16770025d76Sjohnny str = pcidr_cfga_stat_name(datap->ap_r_state);
16870025d76Sjohnny if (str == NULL)
16970025d76Sjohnny str = "(unrecognized cfga_stat_t value!)";
17070025d76Sjohnny dprint(lvl, "%sAP receptacle state = %s\n", prestr, str);
17170025d76Sjohnny
17270025d76Sjohnny str = pcidr_cfga_stat_name(datap->ap_o_state);
17370025d76Sjohnny if (str == NULL)
17470025d76Sjohnny str = "(unrecognized cfga_stat_t value!)";
17570025d76Sjohnny dprint(lvl, "%sAP occupant state = %s\n", prestr, str);
17670025d76Sjohnny
17770025d76Sjohnny str = pcidr_cfga_cond_name(datap->ap_cond);
17870025d76Sjohnny if (str == NULL)
17970025d76Sjohnny str = "(unrecognized cfga_cond_t value!)";
18070025d76Sjohnny dprint(lvl, "%sAP condition = %s\n", prestr, str);
18170025d76Sjohnny
18270025d76Sjohnny dprint(lvl, "%sAP busy indicator = %d\n", prestr, datap->ap_busy);
18370025d76Sjohnny
18470025d76Sjohnny str = ctime(&datap->ap_status_time);
18570025d76Sjohnny str[strlen(str) - 1] = '\0'; /* get rid of newline */
18670025d76Sjohnny dprint(lvl, "%sAP last change time = %ld (%s)\n", prestr,
18770025d76Sjohnny datap->ap_status_time, str);
18870025d76Sjohnny
18970025d76Sjohnny dprint(lvl, "%sAP info = %s\n", prestr, datap->ap_info);
19070025d76Sjohnny dprint(lvl, "%sAP type = %s\n", prestr, datap->ap_type);
19170025d76Sjohnny }
19270025d76Sjohnny
19370025d76Sjohnny
19470025d76Sjohnny /*
19570025d76Sjohnny * for use with config_admin(3cfgadm) functions in their
19670025d76Sjohnny * <struct cfga_msg *msgp> parameter
19770025d76Sjohnny */
19870025d76Sjohnny int
pcidr_cfga_msg_func(void * datap,const char * msg)19970025d76Sjohnny pcidr_cfga_msg_func(void *datap, const char *msg)
20070025d76Sjohnny {
20170025d76Sjohnny pcidr_cfga_msg_data_t *dp = (pcidr_cfga_msg_data_t *)datap;
20270025d76Sjohnny char *prestr = dp->prestr;
20370025d76Sjohnny
20470025d76Sjohnny if (prestr == NULL)
20570025d76Sjohnny prestr = "";
20670025d76Sjohnny
20770025d76Sjohnny dprint(dp->dlvl, "%s%s", prestr, msg);
20870025d76Sjohnny return (0);
20970025d76Sjohnny }
21070025d76Sjohnny
21170025d76Sjohnny
21270025d76Sjohnny /*
21370025d76Sjohnny * for use with config_admin(3cfgadm) functions in their
21470025d76Sjohnny * <struct cfga_confirm *confp> parameter
21570025d76Sjohnny */
21670025d76Sjohnny /*ARGSUSED*/
21770025d76Sjohnny int
pcidr_cfga_confirm_func(void * datap,const char * msg)21870025d76Sjohnny pcidr_cfga_confirm_func(void *datap, const char *msg)
21970025d76Sjohnny {
22070025d76Sjohnny return (1);
22170025d76Sjohnny }
22270025d76Sjohnny
22370025d76Sjohnny
22470025d76Sjohnny /*
22570025d76Sjohnny * returns 0 if successful, -1 if unusuccesful, 1 if the AP already had
22670025d76Sjohnny * <cmd> performed on it
22770025d76Sjohnny */
22870025d76Sjohnny int
pcidr_cfga_do_cmd(cfga_cmd_t cmd,cfga_list_data_t * cfga_listp)22970025d76Sjohnny pcidr_cfga_do_cmd(cfga_cmd_t cmd, cfga_list_data_t *cfga_listp)
23070025d76Sjohnny {
23170025d76Sjohnny char *fn = "pcidr_cfga_do_cmd";
23270025d76Sjohnny int rv, i, j;
23370025d76Sjohnny char *cmdnm, *cfga_errstr, *apid, *str;
23470025d76Sjohnny int cmdarr[2];
23570025d76Sjohnny int cmdarr_len = sizeof (cmdarr) / sizeof (cmdarr[0]);
23670025d76Sjohnny
23770025d76Sjohnny struct cfga_msg cfga_msg;
23870025d76Sjohnny pcidr_cfga_msg_data_t cfga_msg_data;
23970025d76Sjohnny struct cfga_confirm cfga_confirm;
24070025d76Sjohnny cfga_flags_t cfga_flags;
24170025d76Sjohnny
24270025d76Sjohnny cmdnm = pcidr_cfga_cmd_name(cmd);
24370025d76Sjohnny assert(cmdnm != NULL);
24470025d76Sjohnny
24570025d76Sjohnny apid = cfga_listp->ap_phys_id;
24670025d76Sjohnny cfga_msg_data.dlvl = DDEBUG;
24770025d76Sjohnny cfga_msg_data.prestr = "pcidr_cfga_do_cmd(msg): ";
24870025d76Sjohnny cfga_msg.message_routine = pcidr_cfga_msg_func;
24970025d76Sjohnny cfga_msg.appdata_ptr = (void *)&cfga_msg_data;
25070025d76Sjohnny cfga_confirm.confirm = pcidr_cfga_confirm_func;
25170025d76Sjohnny cfga_confirm.appdata_ptr = NULL;
25270025d76Sjohnny cfga_flags = CFGA_FLAG_VERBOSE;
25370025d76Sjohnny
25470025d76Sjohnny if (cfga_listp->ap_busy != 0) {
25570025d76Sjohnny dprint(DDEBUG, "%s: apid = %s is busy\n",
25670025d76Sjohnny fn, cfga_listp->ap_phys_id);
25770025d76Sjohnny return (-1);
25870025d76Sjohnny }
25970025d76Sjohnny
26070025d76Sjohnny /*
26170025d76Sjohnny * explicitly perform each step that would otherwise be done
26270025d76Sjohnny * implicitly by cfgadm to isolate errors
26370025d76Sjohnny */
26470025d76Sjohnny j = 0;
26570025d76Sjohnny switch (cmd) {
26670025d76Sjohnny case CFGA_CMD_CONFIGURE:
26770025d76Sjohnny if (cfga_listp->ap_o_state < CFGA_STAT_CONNECTED) {
26870025d76Sjohnny cmdarr[j] = CFGA_CMD_CONNECT;
26970025d76Sjohnny j++;
27070025d76Sjohnny }
27170025d76Sjohnny if (cfga_listp->ap_o_state < CFGA_STAT_CONFIGURED) {
27270025d76Sjohnny cmdarr[j] = CFGA_CMD_CONFIGURE;
27370025d76Sjohnny j++;
27470025d76Sjohnny }
27570025d76Sjohnny if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED)
27670025d76Sjohnny goto ALREADY;
27770025d76Sjohnny break;
27870025d76Sjohnny case CFGA_CMD_DISCONNECT:
27970025d76Sjohnny if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED) {
28070025d76Sjohnny cmdarr[j] = CFGA_CMD_UNCONFIGURE;
28170025d76Sjohnny j++;
28270025d76Sjohnny }
28370025d76Sjohnny if (cfga_listp->ap_o_state >= CFGA_STAT_CONNECTED) {
28470025d76Sjohnny cmdarr[j] = CFGA_CMD_DISCONNECT;
28570025d76Sjohnny j++;
28670025d76Sjohnny }
28770025d76Sjohnny if (cfga_listp->ap_r_state <= CFGA_STAT_DISCONNECTED)
28870025d76Sjohnny goto ALREADY;
28970025d76Sjohnny break;
29070025d76Sjohnny default:
29170025d76Sjohnny dprint(DDEBUG, "%s: unsupported cmd %d\n", cmd);
29270025d76Sjohnny return (-1);
29370025d76Sjohnny }
29470025d76Sjohnny assert(j <= cmdarr_len);
29570025d76Sjohnny
29670025d76Sjohnny for (i = 0; i < j; i++) {
29770025d76Sjohnny cmd = cmdarr[i];
29870025d76Sjohnny cmdnm = pcidr_cfga_cmd_name(cmd);
29970025d76Sjohnny assert(cmdnm != NULL);
30070025d76Sjohnny
30170025d76Sjohnny rv = config_change_state(cmd, 1, &apid, NULL, &cfga_confirm,
30270025d76Sjohnny &cfga_msg, &cfga_errstr, cfga_flags);
30370025d76Sjohnny if (rv != CFGA_OK) {
30470025d76Sjohnny dprint(DDEBUG, "%s: command %s failed on apid %s",
30570025d76Sjohnny fn, cmdnm, apid);
30670025d76Sjohnny
30770025d76Sjohnny str = pcidr_cfga_err_name(rv);
30870025d76Sjohnny if (str == NULL)
30970025d76Sjohnny str = "unrecognized rv!";
31070025d76Sjohnny dprint(DDEBUG, ": rv = %d (%s)", rv, str);
31170025d76Sjohnny
31270025d76Sjohnny if (cfga_errstr != NULL) {
31370025d76Sjohnny dprint(DDEBUG, ", error string = "
31470025d76Sjohnny "\"%s\"", cfga_errstr);
31570025d76Sjohnny free(cfga_errstr);
31670025d76Sjohnny }
31770025d76Sjohnny dprint(DDEBUG, "\n");
31870025d76Sjohnny return (-1);
31970025d76Sjohnny }
32070025d76Sjohnny }
32170025d76Sjohnny
32270025d76Sjohnny return (0);
32370025d76Sjohnny /*NOTREACHED*/
32470025d76Sjohnny ALREADY:
32570025d76Sjohnny dprint(DDEBUG, "%s: command %s already done on apid %s\n",
32670025d76Sjohnny fn, cmdnm, apid);
32770025d76Sjohnny return (1);
32870025d76Sjohnny }
329