xref: /onnv-gate/usr/src/cmd/pcidr/plugins/default/pcidr_cfga.c (revision 881:e6bc7f4b8a33)
1*881Sjohnny /*
2*881Sjohnny  * CDDL HEADER START
3*881Sjohnny  *
4*881Sjohnny  * The contents of this file are subject to the terms of the
5*881Sjohnny  * Common Development and Distribution License, Version 1.0 only
6*881Sjohnny  * (the "License").  You may not use this file except in compliance
7*881Sjohnny  * with the License.
8*881Sjohnny  *
9*881Sjohnny  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*881Sjohnny  * or http://www.opensolaris.org/os/licensing.
11*881Sjohnny  * See the License for the specific language governing permissions
12*881Sjohnny  * and limitations under the License.
13*881Sjohnny  *
14*881Sjohnny  * When distributing Covered Code, include this CDDL HEADER in each
15*881Sjohnny  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*881Sjohnny  * If applicable, add the following below this CDDL HEADER, with the
17*881Sjohnny  * fields enclosed by brackets "[]" replaced with your own identifying
18*881Sjohnny  * information: Portions Copyright [yyyy] [name of copyright owner]
19*881Sjohnny  *
20*881Sjohnny  * CDDL HEADER END
21*881Sjohnny  */
22*881Sjohnny /*
23*881Sjohnny  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*881Sjohnny  * Use is subject to license terms.
25*881Sjohnny  */
26*881Sjohnny 
27*881Sjohnny #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*881Sjohnny 
29*881Sjohnny #include <string.h>
30*881Sjohnny #include <sys/param.h>
31*881Sjohnny #include <assert.h>
32*881Sjohnny #include <pcidr.h>
33*881Sjohnny #include <pcidr_cfga.h>
34*881Sjohnny 
35*881Sjohnny 
36*881Sjohnny /*
37*881Sjohnny  * misc config_admin(3cfgadm) related routines
38*881Sjohnny  */
39*881Sjohnny 
40*881Sjohnny static struct {
41*881Sjohnny 	cfga_stat_t stat;
42*881Sjohnny 	char *name;
43*881Sjohnny } pcidr_cfga_stat_nametab[] = {
44*881Sjohnny 	{CFGA_STAT_NONE, "CFGA_STAT_NONE"},
45*881Sjohnny 	{CFGA_STAT_EMPTY, "CFGA_STAT_EMPTY"},
46*881Sjohnny 	{CFGA_STAT_DISCONNECTED, "CFGA_STAT_DISCONNECTED"},
47*881Sjohnny 	{CFGA_STAT_CONNECTED, "CFGA_STAT_CONNECTED"},
48*881Sjohnny 	{CFGA_STAT_UNCONFIGURED, "CFGA_STAT_UNCONFIGURED"},
49*881Sjohnny 	{CFGA_STAT_CONFIGURED, "CFGA_STAT_CONFIGURED"},
50*881Sjohnny };
51*881Sjohnny static int pcidr_cfga_stat_nametab_len =
52*881Sjohnny     sizeof (pcidr_cfga_stat_nametab) / sizeof (pcidr_cfga_stat_nametab[0]);
53*881Sjohnny 
54*881Sjohnny char *
pcidr_cfga_stat_name(cfga_stat_t val)55*881Sjohnny pcidr_cfga_stat_name(cfga_stat_t val)
56*881Sjohnny {
57*881Sjohnny 	int i;
58*881Sjohnny 
59*881Sjohnny 	for (i = 0; i < pcidr_cfga_stat_nametab_len; i++) {
60*881Sjohnny 		if (pcidr_cfga_stat_nametab[i].stat == val)
61*881Sjohnny 			return (pcidr_cfga_stat_nametab[i].name);
62*881Sjohnny 	}
63*881Sjohnny 	return (NULL);
64*881Sjohnny }
65*881Sjohnny 
66*881Sjohnny 
67*881Sjohnny static struct {
68*881Sjohnny 	cfga_stat_t cmd;
69*881Sjohnny 	char *name;
70*881Sjohnny } pcidr_cfga_cmd_nametab[] = {
71*881Sjohnny 	{CFGA_CMD_NONE, "CFGA_CMD_NONE"},
72*881Sjohnny 	{CFGA_CMD_LOAD, "CFGA_CMD_LOAD"},
73*881Sjohnny 	{CFGA_CMD_UNLOAD, "CFGA_CMD_UNLOAD"},
74*881Sjohnny 	{CFGA_CMD_CONNECT, "CFGA_CMD_CONNECT"},
75*881Sjohnny 	{CFGA_CMD_DISCONNECT, "CFGA_CMD_DISCONNECT"},
76*881Sjohnny 	{CFGA_CMD_CONFIGURE, "CFGA_CMD_CONFIGURE"},
77*881Sjohnny 	{CFGA_CMD_UNCONFIGURE, "CFGA_CMD_UNCONFIGURE"},
78*881Sjohnny };
79*881Sjohnny static int pcidr_cfga_cmd_nametab_len =
80*881Sjohnny     sizeof (pcidr_cfga_cmd_nametab) / sizeof (pcidr_cfga_cmd_nametab[0]);
81*881Sjohnny 
82*881Sjohnny char *
pcidr_cfga_cmd_name(cfga_cmd_t val)83*881Sjohnny pcidr_cfga_cmd_name(cfga_cmd_t val)
84*881Sjohnny {
85*881Sjohnny 	int i;
86*881Sjohnny 
87*881Sjohnny 	for (i = 0; i < pcidr_cfga_cmd_nametab_len; i++) {
88*881Sjohnny 		if (pcidr_cfga_cmd_nametab[i].cmd == val)
89*881Sjohnny 			return (pcidr_cfga_cmd_nametab[i].name);
90*881Sjohnny 	}
91*881Sjohnny 	return (NULL);
92*881Sjohnny }
93*881Sjohnny 
94*881Sjohnny 
95*881Sjohnny static struct {
96*881Sjohnny 	cfga_cond_t cond;
97*881Sjohnny 	char *name;
98*881Sjohnny } pcidr_cfga_cond_nametab[] = {
99*881Sjohnny 	{CFGA_COND_UNKNOWN, "CFGA_COND_UNKNOWN"},
100*881Sjohnny 	{CFGA_COND_OK, "CFGA_COND_OK"},
101*881Sjohnny 	{CFGA_COND_FAILING, "CFGA_COND_FAILING"},
102*881Sjohnny 	{CFGA_COND_FAILED, "CFGA_COND_FAILED"},
103*881Sjohnny 	{CFGA_COND_UNUSABLE, "CFGA_COND_UNUSABLE"},
104*881Sjohnny };
105*881Sjohnny static int pcidr_cfga_cond_nametab_len =
106*881Sjohnny     sizeof (pcidr_cfga_cond_nametab) / sizeof (pcidr_cfga_cond_nametab[0]);
107*881Sjohnny 
108*881Sjohnny char *
pcidr_cfga_cond_name(cfga_cond_t val)109*881Sjohnny pcidr_cfga_cond_name(cfga_cond_t val)
110*881Sjohnny {
111*881Sjohnny 	int i;
112*881Sjohnny 
113*881Sjohnny 	for (i = 0; i < pcidr_cfga_cond_nametab_len; i++) {
114*881Sjohnny 		if (pcidr_cfga_cond_nametab[i].cond == val)
115*881Sjohnny 			return (pcidr_cfga_cond_nametab[i].name);
116*881Sjohnny 	}
117*881Sjohnny 	return (NULL);
118*881Sjohnny }
119*881Sjohnny 
120*881Sjohnny 
121*881Sjohnny static struct {
122*881Sjohnny 	cfga_err_t err;
123*881Sjohnny 	char *name;
124*881Sjohnny } pcidr_cfga_err_nametab[] = {
125*881Sjohnny 	{CFGA_OK, "CFGA_OK"},
126*881Sjohnny 	{CFGA_NACK, "CFGA_NACK"},
127*881Sjohnny 	{CFGA_NOTSUPP, "CFGA_NOTSUPP"},
128*881Sjohnny 	{CFGA_OPNOTSUPP, "CFGA_OPNOTSUPP"},
129*881Sjohnny 	{CFGA_PRIV, "CFGA_PRIV"},
130*881Sjohnny 	{CFGA_BUSY, "CFGA_BUSY"},
131*881Sjohnny 	{CFGA_SYSTEM_BUSY, "CFGA_SYSTEM_BUSY"},
132*881Sjohnny 	{CFGA_DATA_ERROR, "CFGA_DATA_ERROR"},
133*881Sjohnny 	{CFGA_LIB_ERROR, "CFGA_LIB_ERROR"},
134*881Sjohnny 	{CFGA_NO_LIB, "CFGA_NO_LIB"},
135*881Sjohnny 	{CFGA_INSUFFICENT_CONDITION, "CFGA_INSUFFICENT_CONDITION"},
136*881Sjohnny 	{CFGA_INVAL, "CFGA_INVAL"},
137*881Sjohnny 	{CFGA_ERROR, "CFGA_ERROR"},
138*881Sjohnny 	{CFGA_APID_NOEXIST, "CFGA_APID_NOEXIST"},
139*881Sjohnny 	{CFGA_ATTR_INVAL, "CFGA_ATTR_INVAL"},
140*881Sjohnny };
141*881Sjohnny static int pcidr_cfga_err_nametab_len =
142*881Sjohnny     sizeof (pcidr_cfga_err_nametab) / sizeof (pcidr_cfga_err_nametab[0]);
143*881Sjohnny 
144*881Sjohnny char *
pcidr_cfga_err_name(cfga_err_t val)145*881Sjohnny pcidr_cfga_err_name(cfga_err_t val)
146*881Sjohnny {
147*881Sjohnny 	int i;
148*881Sjohnny 
149*881Sjohnny 	for (i = 0; i < pcidr_cfga_err_nametab_len; i++) {
150*881Sjohnny 		if (pcidr_cfga_err_nametab[i].err == val)
151*881Sjohnny 			return (pcidr_cfga_err_nametab[i].name);
152*881Sjohnny 	}
153*881Sjohnny 	return (NULL);
154*881Sjohnny }
155*881Sjohnny 
156*881Sjohnny 
157*881Sjohnny void
pcidr_print_cfga(dlvl_t lvl,cfga_list_data_t * datap,char * prestr)158*881Sjohnny pcidr_print_cfga(dlvl_t lvl, cfga_list_data_t *datap, char *prestr)
159*881Sjohnny {
160*881Sjohnny 	char *str;
161*881Sjohnny 
162*881Sjohnny 	if (prestr == NULL)
163*881Sjohnny 		prestr = "";
164*881Sjohnny 
165*881Sjohnny 	dprint(lvl, "%slogical APID = %s\n", prestr, datap->ap_log_id);
166*881Sjohnny 	dprint(lvl, "%sphyiscal APID = %s\n", prestr, datap->ap_phys_id);
167*881Sjohnny 	dprint(lvl, "%sAP class = %s\n", prestr, datap->ap_class);
168*881Sjohnny 
169*881Sjohnny 	str = pcidr_cfga_stat_name(datap->ap_r_state);
170*881Sjohnny 	if (str == NULL)
171*881Sjohnny 		str = "(unrecognized cfga_stat_t value!)";
172*881Sjohnny 	dprint(lvl, "%sAP receptacle state = %s\n", prestr, str);
173*881Sjohnny 
174*881Sjohnny 	str = pcidr_cfga_stat_name(datap->ap_o_state);
175*881Sjohnny 	if (str == NULL)
176*881Sjohnny 		str = "(unrecognized cfga_stat_t value!)";
177*881Sjohnny 	dprint(lvl, "%sAP occupant state = %s\n", prestr, str);
178*881Sjohnny 
179*881Sjohnny 	str = pcidr_cfga_cond_name(datap->ap_cond);
180*881Sjohnny 	if (str == NULL)
181*881Sjohnny 		str = "(unrecognized cfga_cond_t value!)";
182*881Sjohnny 	dprint(lvl, "%sAP condition = %s\n", prestr, str);
183*881Sjohnny 
184*881Sjohnny 	dprint(lvl, "%sAP busy indicator = %d\n", prestr, datap->ap_busy);
185*881Sjohnny 
186*881Sjohnny 	str = ctime(&datap->ap_status_time);
187*881Sjohnny 	str[strlen(str) - 1] = '\0';	/* get rid of newline */
188*881Sjohnny 	dprint(lvl, "%sAP last change time = %ld (%s)\n", prestr,
189*881Sjohnny 	    datap->ap_status_time, str);
190*881Sjohnny 
191*881Sjohnny 	dprint(lvl, "%sAP info = %s\n", prestr, datap->ap_info);
192*881Sjohnny 	dprint(lvl, "%sAP type = %s\n", prestr, datap->ap_type);
193*881Sjohnny }
194*881Sjohnny 
195*881Sjohnny 
196*881Sjohnny /*
197*881Sjohnny  * for use with config_admin(3cfgadm) functions in their
198*881Sjohnny  * <struct cfga_msg *msgp> parameter
199*881Sjohnny  */
200*881Sjohnny int
pcidr_cfga_msg_func(void * datap,const char * msg)201*881Sjohnny pcidr_cfga_msg_func(void *datap, const char *msg)
202*881Sjohnny {
203*881Sjohnny 	pcidr_cfga_msg_data_t *dp = (pcidr_cfga_msg_data_t *)datap;
204*881Sjohnny 	char *prestr = dp->prestr;
205*881Sjohnny 
206*881Sjohnny 	if (prestr == NULL)
207*881Sjohnny 		prestr = "";
208*881Sjohnny 
209*881Sjohnny 	dprint(dp->dlvl, "%s%s", prestr, msg);
210*881Sjohnny 	return (0);
211*881Sjohnny }
212*881Sjohnny 
213*881Sjohnny 
214*881Sjohnny /*
215*881Sjohnny  * for use with config_admin(3cfgadm) functions in their
216*881Sjohnny  * <struct cfga_confirm *confp> parameter
217*881Sjohnny  */
218*881Sjohnny /*ARGSUSED*/
219*881Sjohnny int
pcidr_cfga_confirm_func(void * datap,const char * msg)220*881Sjohnny pcidr_cfga_confirm_func(void *datap, const char *msg)
221*881Sjohnny {
222*881Sjohnny 	return (1);
223*881Sjohnny }
224*881Sjohnny 
225*881Sjohnny 
226*881Sjohnny /*
227*881Sjohnny  * returns 0 if successful, -1 if unusuccesful, 1 if the AP already had
228*881Sjohnny  * <cmd> performed on it
229*881Sjohnny  */
230*881Sjohnny int
pcidr_cfga_do_cmd(cfga_cmd_t cmd,cfga_list_data_t * cfga_listp)231*881Sjohnny pcidr_cfga_do_cmd(cfga_cmd_t cmd, cfga_list_data_t *cfga_listp)
232*881Sjohnny {
233*881Sjohnny 	char *fn = "pcidr_cfga_do_cmd";
234*881Sjohnny 	int rv, i, j;
235*881Sjohnny 	char *cmdnm, *cfga_errstr, *apid, *str;
236*881Sjohnny 	int cmdarr[2];
237*881Sjohnny 	int cmdarr_len = sizeof (cmdarr) / sizeof (cmdarr[0]);
238*881Sjohnny 
239*881Sjohnny 	struct cfga_msg cfga_msg;
240*881Sjohnny 	pcidr_cfga_msg_data_t cfga_msg_data;
241*881Sjohnny 	struct cfga_confirm cfga_confirm;
242*881Sjohnny 	cfga_flags_t cfga_flags;
243*881Sjohnny 
244*881Sjohnny 	cmdnm = pcidr_cfga_cmd_name(cmd);
245*881Sjohnny 	assert(cmdnm != NULL);
246*881Sjohnny 
247*881Sjohnny 	apid = cfga_listp->ap_phys_id;
248*881Sjohnny 	cfga_msg_data.dlvl = DDEBUG;
249*881Sjohnny 	cfga_msg_data.prestr = "pcidr_cfga_do_cmd(msg): ";
250*881Sjohnny 	cfga_msg.message_routine = pcidr_cfga_msg_func;
251*881Sjohnny 	cfga_msg.appdata_ptr = (void *)&cfga_msg_data;
252*881Sjohnny 	cfga_confirm.confirm = pcidr_cfga_confirm_func;
253*881Sjohnny 	cfga_confirm.appdata_ptr = NULL;
254*881Sjohnny 	cfga_flags = CFGA_FLAG_VERBOSE;
255*881Sjohnny 
256*881Sjohnny 	if (cfga_listp->ap_busy != 0) {
257*881Sjohnny 		dprint(DDEBUG, "%s: apid = %s is busy\n",
258*881Sjohnny 		    fn, cfga_listp->ap_phys_id);
259*881Sjohnny 		return (-1);
260*881Sjohnny 	}
261*881Sjohnny 
262*881Sjohnny 	/*
263*881Sjohnny 	 * explicitly perform each step that would otherwise be done
264*881Sjohnny 	 * implicitly by cfgadm to isolate errors
265*881Sjohnny 	 */
266*881Sjohnny 	j = 0;
267*881Sjohnny 	switch (cmd) {
268*881Sjohnny 	case CFGA_CMD_CONFIGURE:
269*881Sjohnny 		if (cfga_listp->ap_o_state < CFGA_STAT_CONNECTED) {
270*881Sjohnny 			cmdarr[j] = CFGA_CMD_CONNECT;
271*881Sjohnny 			j++;
272*881Sjohnny 		}
273*881Sjohnny 		if (cfga_listp->ap_o_state < CFGA_STAT_CONFIGURED) {
274*881Sjohnny 			cmdarr[j] = CFGA_CMD_CONFIGURE;
275*881Sjohnny 			j++;
276*881Sjohnny 		}
277*881Sjohnny 		if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED)
278*881Sjohnny 			goto ALREADY;
279*881Sjohnny 		break;
280*881Sjohnny 	case CFGA_CMD_DISCONNECT:
281*881Sjohnny 		if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED) {
282*881Sjohnny 			cmdarr[j] = CFGA_CMD_UNCONFIGURE;
283*881Sjohnny 			j++;
284*881Sjohnny 		}
285*881Sjohnny 		if (cfga_listp->ap_o_state >= CFGA_STAT_CONNECTED) {
286*881Sjohnny 			cmdarr[j] = CFGA_CMD_DISCONNECT;
287*881Sjohnny 			j++;
288*881Sjohnny 		}
289*881Sjohnny 		if (cfga_listp->ap_r_state <= CFGA_STAT_DISCONNECTED)
290*881Sjohnny 			goto ALREADY;
291*881Sjohnny 		break;
292*881Sjohnny 	default:
293*881Sjohnny 		dprint(DDEBUG, "%s: unsupported cmd %d\n", cmd);
294*881Sjohnny 		return (-1);
295*881Sjohnny 	}
296*881Sjohnny 	assert(j <= cmdarr_len);
297*881Sjohnny 
298*881Sjohnny 	for (i = 0; i < j; i++) {
299*881Sjohnny 		cmd = cmdarr[i];
300*881Sjohnny 		cmdnm = pcidr_cfga_cmd_name(cmd);
301*881Sjohnny 		assert(cmdnm != NULL);
302*881Sjohnny 
303*881Sjohnny 		rv = config_change_state(cmd, 1, &apid, NULL, &cfga_confirm,
304*881Sjohnny 		    &cfga_msg, &cfga_errstr, cfga_flags);
305*881Sjohnny 		if (rv != CFGA_OK) {
306*881Sjohnny 			dprint(DDEBUG, "%s: command %s failed on apid %s",
307*881Sjohnny 			    fn, cmdnm, apid);
308*881Sjohnny 
309*881Sjohnny 			str = pcidr_cfga_err_name(rv);
310*881Sjohnny 			if (str == NULL)
311*881Sjohnny 				str = "unrecognized rv!";
312*881Sjohnny 			dprint(DDEBUG, ": rv = %d (%s)", rv, str);
313*881Sjohnny 
314*881Sjohnny 			if (cfga_errstr != NULL) {
315*881Sjohnny 				dprint(DDEBUG, ", error string = "
316*881Sjohnny 				    "\"%s\"", cfga_errstr);
317*881Sjohnny 				free(cfga_errstr);
318*881Sjohnny 			}
319*881Sjohnny 			dprint(DDEBUG, "\n");
320*881Sjohnny 			return (-1);
321*881Sjohnny 		}
322*881Sjohnny 	}
323*881Sjohnny 
324*881Sjohnny 	return (0);
325*881Sjohnny 	/*NOTREACHED*/
326*881Sjohnny ALREADY:
327*881Sjohnny 	dprint(DDEBUG, "%s: command %s already done on apid %s\n",
328*881Sjohnny 	    fn, cmdnm, apid);
329*881Sjohnny 	return (1);
330*881Sjohnny }
331