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