xref: /onnv-gate/usr/src/lib/cfgadm_plugins/sysctrl/common/cfga.c (revision 2305:7954d746a1b5)
1*2305Sstevel /*
2*2305Sstevel  * CDDL HEADER START
3*2305Sstevel  *
4*2305Sstevel  * The contents of this file are subject to the terms of the
5*2305Sstevel  * Common Development and Distribution License, Version 1.0 only
6*2305Sstevel  * (the "License").  You may not use this file except in compliance
7*2305Sstevel  * with the License.
8*2305Sstevel  *
9*2305Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*2305Sstevel  * or http://www.opensolaris.org/os/licensing.
11*2305Sstevel  * See the License for the specific language governing permissions
12*2305Sstevel  * and limitations under the License.
13*2305Sstevel  *
14*2305Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
15*2305Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*2305Sstevel  * If applicable, add the following below this CDDL HEADER, with the
17*2305Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
18*2305Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
19*2305Sstevel  *
20*2305Sstevel  * CDDL HEADER END
21*2305Sstevel  */
22*2305Sstevel /*
23*2305Sstevel  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*2305Sstevel  * Use is subject to license terms.
25*2305Sstevel  */
26*2305Sstevel 
27*2305Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2305Sstevel 
29*2305Sstevel #include <stddef.h>
30*2305Sstevel #include <locale.h>
31*2305Sstevel #include <ctype.h>
32*2305Sstevel #include <stdio.h>
33*2305Sstevel #include <stdlib.h>
34*2305Sstevel #include <string.h>
35*2305Sstevel #include <fcntl.h>
36*2305Sstevel #include <unistd.h>
37*2305Sstevel #include <errno.h>
38*2305Sstevel #include <locale.h>
39*2305Sstevel #include <langinfo.h>
40*2305Sstevel #include <time.h>
41*2305Sstevel #include <stdarg.h>
42*2305Sstevel #include <sys/types.h>
43*2305Sstevel #include <sys/ioctl.h>
44*2305Sstevel #include <sys/dditypes.h>
45*2305Sstevel #include <sys/modctl.h>
46*2305Sstevel #include <sys/obpdefs.h>
47*2305Sstevel #include <sys/fhc.h>
48*2305Sstevel #include <sys/sysctrl.h>
49*2305Sstevel #include <sys/openpromio.h>
50*2305Sstevel #ifdef	SIM
51*2305Sstevel #include <sys/stat.h>
52*2305Sstevel #endif
53*2305Sstevel #define	CFGA_PLUGIN_LIB
54*2305Sstevel #include <config_admin.h>
55*2305Sstevel 
56*2305Sstevel #ifdef	DEBUG
57*2305Sstevel #define	DBG	printf
58*2305Sstevel #define	DBG1	printf
59*2305Sstevel #define	DBG3	printf
60*2305Sstevel #define	DBG4	printf
61*2305Sstevel #else
62*2305Sstevel #define	DBG(a, b)
63*2305Sstevel #define	DBG1(a)
64*2305Sstevel #define	DBG3(a, b, c)
65*2305Sstevel #define	DBG4(a, b, c, d)
66*2305Sstevel #endif
67*2305Sstevel 
68*2305Sstevel #define	BD_CPU			1
69*2305Sstevel #define	BD_MEM			2
70*2305Sstevel #define	BD_IO_2SBUS		3
71*2305Sstevel #define	BD_IO_SBUS_FFB		4
72*2305Sstevel #define	BD_IO_PCI		5
73*2305Sstevel #define	BD_DISK			6
74*2305Sstevel #define	BD_IO_2SBUS_SOCPLUS	7
75*2305Sstevel #define	BD_IO_SBUS_FFB_SOCPLUS	8
76*2305Sstevel #define	BD_UNKNOWN		9
77*2305Sstevel #define	CMD_GETSTAT		10
78*2305Sstevel #define	CMD_LIST		11
79*2305Sstevel #define	CMD_CONNECT		12
80*2305Sstevel #define	CMD_DISCONNECT		13
81*2305Sstevel #define	CMD_CONFIGURE		14
82*2305Sstevel #define	CMD_UNCONFIGURE		15
83*2305Sstevel #define	CMD_QUIESCE		16
84*2305Sstevel #define	CMD_INSERT		17
85*2305Sstevel #define	CMD_REMOVE		18
86*2305Sstevel #define	CMD_SET_COND		19
87*2305Sstevel #define	OPT_ENABLE		20
88*2305Sstevel #define	OPT_DISABLE		21
89*2305Sstevel #define	ERR_PROM_OPEN		22
90*2305Sstevel #define	ERR_PROM_GETPROP	23
91*2305Sstevel #define	ERR_PROM_SETPROP	24
92*2305Sstevel #define	ERR_TRANS		25
93*2305Sstevel #define	ERR_CMD_INVAL		26
94*2305Sstevel #define	ERR_OPT_INVAL		27
95*2305Sstevel #define	ERR_AP_INVAL		28
96*2305Sstevel #define	ERR_DISABLED		29
97*2305Sstevel #define	DIAG_FORCE		30
98*2305Sstevel #define	DIAG_TRANS_OK		31
99*2305Sstevel #define	DIAG_FAILED		32
100*2305Sstevel #define	DIAG_WAS_ENABLED	33
101*2305Sstevel #define	DIAG_WAS_DISABLED	34
102*2305Sstevel #define	DIAG_WILL_ENABLE	35
103*2305Sstevel #define	DIAG_WILL_DISABLE	36
104*2305Sstevel #define	HELP_HEADER		37
105*2305Sstevel #define	HELP_QUIESCE		38
106*2305Sstevel #define	HELP_INSERT		39
107*2305Sstevel #define	HELP_REMOVE		40
108*2305Sstevel #define	HELP_SET_COND		41
109*2305Sstevel #define	HELP_ENABLE		42
110*2305Sstevel #define	HELP_DISABLE		43
111*2305Sstevel #define	HELP_UNKNOWN		44
112*2305Sstevel #define	ASK_CONNECT		45
113*2305Sstevel #define	STR_BD			46
114*2305Sstevel #define	STR_COL			47
115*2305Sstevel #define	COND_UNKNOWN		48
116*2305Sstevel #define	COND_OK			49
117*2305Sstevel #define	COND_FAILING		50
118*2305Sstevel #define	COND_FAILED		51
119*2305Sstevel #define	COND_UNUSABLE		52
120*2305Sstevel #define	SYSC_COOLING		53
121*2305Sstevel #define	SYSC_POWER		54
122*2305Sstevel #define	SYSC_PRECHARGE		55
123*2305Sstevel #define	SYSC_INTRANS		56
124*2305Sstevel #define	SYSC_UTHREAD		57
125*2305Sstevel #define	SYSC_KTHREAD		58
126*2305Sstevel #define	SYSC_DEV_ATTACH		59
127*2305Sstevel #define	SYSC_DEV_DETACH		60
128*2305Sstevel #define	SYSC_NDI_ATTACH		61
129*2305Sstevel #define	SYSC_NDI_DETACH		62
130*2305Sstevel #define	SYSC_CORE_RESOURCE	63
131*2305Sstevel #define	SYSC_OSTATE		64
132*2305Sstevel #define	SYSC_RSTATE		65
133*2305Sstevel #define	SYSC_COND		66
134*2305Sstevel #define	SYSC_PROM		67
135*2305Sstevel #define	SYSC_NOMEM		68
136*2305Sstevel #define	SYSC_HOTPLUG		69
137*2305Sstevel #define	SYSC_HW_COMPAT		70
138*2305Sstevel #define	SYSC_NON_DR_PROM	71
139*2305Sstevel #define	SYSC_SUSPEND		72
140*2305Sstevel #define	SYSC_RESUME		73
141*2305Sstevel #define	SYSC_UNKNOWN		74
142*2305Sstevel #define	SYSC_DEVSTR		75
143*2305Sstevel 
144*2305Sstevel /*
145*2305Sstevel  * The string table contains all the strings used by the platform
146*2305Sstevel  * library.  The comment next to each string specifies whether the
147*2305Sstevel  * string should be internationalized (y) or not (n).
148*2305Sstevel  * Note that there are calls to dgettext() with strings other than
149*2305Sstevel  * the ones below, they are marked by the li18 symbol.
150*2305Sstevel  */
151*2305Sstevel static char *
152*2305Sstevel cfga_strs[] = {
153*2305Sstevel 	/*   */ NULL,
154*2305Sstevel 	/* n */ "cpu/mem   ",
155*2305Sstevel 	/* n */ "mem       ",
156*2305Sstevel 	/* n */ "dual-sbus ",
157*2305Sstevel 	/* n */ "sbus-upa  ",
158*2305Sstevel 	/* n */ "dual-pci  ",
159*2305Sstevel 	/* n */ "disk      ",
160*2305Sstevel 	/* n */ "soc+sbus  ",
161*2305Sstevel 	/* n */ "soc+upa   ",
162*2305Sstevel 	/* n */ "unknown   ",
163*2305Sstevel 	/* n */ "get-status",
164*2305Sstevel 	/* n */ "list",
165*2305Sstevel 	/* n */ "connect",
166*2305Sstevel 	/* n */ "disconnect",
167*2305Sstevel 	/* n */ "configure",
168*2305Sstevel 	/* n */ "unconfigure",
169*2305Sstevel 	/* n */ "quiesce-test",
170*2305Sstevel 	/* n */ "insert-test",
171*2305Sstevel 	/* n */ "remove-test",
172*2305Sstevel 	/* n */ "set-condition-test",
173*2305Sstevel 	/* n */ "enable-at-boot",
174*2305Sstevel 	/* n */ "disable-at-boot",
175*2305Sstevel 	/* n */ "prom open",
176*2305Sstevel 	/* n */ "prom getprop",
177*2305Sstevel 	/* n */ "prom setprop",
178*2305Sstevel 	/* y */ "invalid transition",
179*2305Sstevel 	/* y */ "invalid command: ",
180*2305Sstevel 	/* y */ "invalid option: ",
181*2305Sstevel 	/* y */ "invalid attachment point: ",
182*2305Sstevel 	/* y */ "board is disabled: must override with ",
183*2305Sstevel 	/* n */ "[-f][-o enable-at-boot]",
184*2305Sstevel 	/* y */ "transition succeeded but ",
185*2305Sstevel 	/* y */ " failed: ",
186*2305Sstevel 	/* y */ "was already enabled at boot time",
187*2305Sstevel 	/* y */ "was already disabled at boot time",
188*2305Sstevel 	/* y */ "will be enabled at boot time",
189*2305Sstevel 	/* y */ "will be disabled at boot time",
190*2305Sstevel 	/* y */ "\nSysctrl specific commands/options:",
191*2305Sstevel 	/* n */ "\t-x quiesce-test ap_id [ap_id...]",
192*2305Sstevel 	/* n */ "\t-x insert-test  ap_id [ap_id...]",
193*2305Sstevel 	/* n */ "\t-x remove-test  ap_id [ap_id...]",
194*2305Sstevel 	/* n */ "\t-x set-condition-test=<condition>",
195*2305Sstevel 	/* n */ "\t-o enable-at-boot",
196*2305Sstevel 	/* n */ "\t-o disable-at-boot",
197*2305Sstevel 	/* y */ "\tunknown command or option: ",
198*2305Sstevel 	/* y */
199*2305Sstevel 	"system will be temporarily suspended to connect a board: proceed",
200*2305Sstevel 	/* y */ "board ",
201*2305Sstevel 	/* y */ ": ",
202*2305Sstevel 	/* n */ "unknown",
203*2305Sstevel 	/* n */ "ok",
204*2305Sstevel 	/* n */ "failing",
205*2305Sstevel 	/* n */ "failed",
206*2305Sstevel 	/* n */ "unusable",
207*2305Sstevel 	/* y */ "not enough cooling for a new board",
208*2305Sstevel 	/* y */ "not enough power for a new board",
209*2305Sstevel 	/* y */ "not enough precharge power for a new board",
210*2305Sstevel 	/* y */ "configuration operation already in progress on this board",
211*2305Sstevel 	/* y */ "could not suspend user process: ",
212*2305Sstevel 	/* y */ "could not suspend system processes",
213*2305Sstevel 	/* y */ "device did not attach",
214*2305Sstevel 	/* y */ "device did not detach",
215*2305Sstevel 	/* y */ "nexus error during attach",
216*2305Sstevel 	/* y */ "nexus error during detach",
217*2305Sstevel 	/* y */ "attempt to remove core system resource",
218*2305Sstevel 	/* y */ "invalid occupant state",
219*2305Sstevel 	/* y */ "invalid receptacle state",
220*2305Sstevel 	/* y */ "insufficient condition",
221*2305Sstevel 	/* y */ "firmware operation error",
222*2305Sstevel 	/* y */ "not enough memory",
223*2305Sstevel 	/* y */ "hotplug feature unavailable on this machine",
224*2305Sstevel 	/* y */ "board does not support dynamic reconfiguration",
225*2305Sstevel 	/* y */ "firmware does not support dynamic reconfiguration",
226*2305Sstevel 	/* y */ "system suspend error",
227*2305Sstevel 	/* y */ "system resume error",
228*2305Sstevel 	/* y */ "unknown system error",
229*2305Sstevel 	/*   */ NULL
230*2305Sstevel };
231*2305Sstevel 
232*2305Sstevel #define	cfga_str(i)		cfga_strs[(i)]
233*2305Sstevel 
234*2305Sstevel #define	cfga_eid(a, b)		(((a) << 8) + (b))
235*2305Sstevel 
236*2305Sstevel /*
237*2305Sstevel  *
238*2305Sstevel  *	Translation table for mapping from an <errno,sysc_err>
239*2305Sstevel  *	pair to an error string.
240*2305Sstevel  *
241*2305Sstevel  *
242*2305Sstevel  *	SYSC_COOLING,		EAGAIN,  SYSC_ERR_COOLING
243*2305Sstevel  *	SYSC_POWER,		EAGAIN,  SYSC_ERR_POWER
244*2305Sstevel  *	SYSC_PRECHARGE,		EAGAIN,  SYSC_ERR_PRECHARGE
245*2305Sstevel  *	SYSC_INTRANS,		EBUSY,   SYSC_ERR_INTRANS
246*2305Sstevel  *	SYSC_KTHREAD,		EBUSY,   SYSC_ERR_KTHREAD
247*2305Sstevel  *	SYSC_DEV_ATTACH,	EBUSY,   SYSC_ERR_NDI_ATTACH
248*2305Sstevel  *	SYSC_DEV_DETACH,	EBUSY,   SYSC_ERR_NDI_DETACH
249*2305Sstevel  *	SYSC_NDI_ATTACH,	EFAULT,  SYSC_ERR_NDI_ATTACH
250*2305Sstevel  *	SYSC_NDI_DETACH,	EFAULT,  SYSC_ERR_NDI_DETACH
251*2305Sstevel  *	SYSC_CORE_RESOURCE,	EINVAL,  SYSC_ERR_CORE_RESOURCE
252*2305Sstevel  *	SYSC_OSTATE,		EINVAL,  SYSC_ERR_OSTATE
253*2305Sstevel  *	SYSC_RSTATE,		EINVAL,  SYSC_ERR_RSTATE
254*2305Sstevel  *	SYSC_COND,		EINVAL,  SYSC_ERR_COND
255*2305Sstevel  *	SYSC_PROM,		EIO,     SYSC_ERR_PROM
256*2305Sstevel  *	SYSC_NOMEM,		ENOMEM,  SYSC_ERR_DR_INIT
257*2305Sstevel  *	SYSC_NOMEM,		ENOMEM,  SYSC_ERR_NDI_ATTACH
258*2305Sstevel  *	SYSC_NOMEM,		ENOMEM,  SYSC_ERR_NDI_DETACH
259*2305Sstevel  *	SYSC_HOTPLUG,		ENOTSUP, SYSC_ERR_HOTPLUG
260*2305Sstevel  *	SYSC_HW_COMPAT,		ENOTSUP, SYSC_ERR_HW_COMPAT
261*2305Sstevel  *	SYSC_NON_DR_PROM,	ENOTSUP, SYSC_ERR_NON_DR_PROM
262*2305Sstevel  *	SYSC_SUSPEND,		ENXIO,   SYSC_ERR_SUSPEND
263*2305Sstevel  *	SYSC_RESUME,		ENXIO,   SYSC_ERR_RESUME
264*2305Sstevel  *	SYSC_UTHREAD,		ESRCH,   SYSC_ERR_UTHREAD
265*2305Sstevel  */
266*2305Sstevel static int
cfga_sid(int err,int scerr)267*2305Sstevel cfga_sid(int err, int scerr)
268*2305Sstevel {
269*2305Sstevel 	if (scerr == SYSC_ERR_DEFAULT)
270*2305Sstevel 		return (SYSC_UNKNOWN);
271*2305Sstevel 
272*2305Sstevel 	switch (cfga_eid(err, scerr)) {
273*2305Sstevel 	case cfga_eid(EAGAIN, SYSC_ERR_COOLING):
274*2305Sstevel 		return (SYSC_COOLING);
275*2305Sstevel 	case cfga_eid(EAGAIN, SYSC_ERR_POWER):
276*2305Sstevel 		return (SYSC_POWER);
277*2305Sstevel 	case cfga_eid(EAGAIN, SYSC_ERR_PRECHARGE):
278*2305Sstevel 		return (SYSC_PRECHARGE);
279*2305Sstevel 	case cfga_eid(EBUSY, SYSC_ERR_INTRANS):
280*2305Sstevel 		return (SYSC_INTRANS);
281*2305Sstevel 	case cfga_eid(EBUSY, SYSC_ERR_KTHREAD):
282*2305Sstevel 		return (SYSC_KTHREAD);
283*2305Sstevel 	case cfga_eid(EBUSY, SYSC_ERR_NDI_ATTACH):
284*2305Sstevel 		return (SYSC_DEV_ATTACH);
285*2305Sstevel 	case cfga_eid(EBUSY, SYSC_ERR_NDI_DETACH):
286*2305Sstevel 		return (SYSC_DEV_DETACH);
287*2305Sstevel 	case cfga_eid(EFAULT, SYSC_ERR_NDI_ATTACH):
288*2305Sstevel 		return (SYSC_NDI_ATTACH);
289*2305Sstevel 	case cfga_eid(EFAULT, SYSC_ERR_NDI_DETACH):
290*2305Sstevel 		return (SYSC_NDI_DETACH);
291*2305Sstevel 	case cfga_eid(EINVAL, SYSC_ERR_CORE_RESOURCE):
292*2305Sstevel 		return (SYSC_CORE_RESOURCE);
293*2305Sstevel 	case cfga_eid(EINVAL, SYSC_ERR_OSTATE):
294*2305Sstevel 		return (SYSC_OSTATE);
295*2305Sstevel 	case cfga_eid(EINVAL, SYSC_ERR_RSTATE):
296*2305Sstevel 		return (SYSC_RSTATE);
297*2305Sstevel 	case cfga_eid(EINVAL, SYSC_ERR_COND):
298*2305Sstevel 		return (SYSC_COND);
299*2305Sstevel 	case cfga_eid(EIO, SYSC_ERR_PROM):
300*2305Sstevel 		return (SYSC_PROM);
301*2305Sstevel 	case cfga_eid(ENOMEM, SYSC_ERR_DR_INIT):
302*2305Sstevel 		return (SYSC_NOMEM);
303*2305Sstevel 	case cfga_eid(ENOMEM, SYSC_ERR_NDI_ATTACH):
304*2305Sstevel 		return (SYSC_NOMEM);
305*2305Sstevel 	case cfga_eid(ENOMEM, SYSC_ERR_NDI_DETACH):
306*2305Sstevel 		return (SYSC_NOMEM);
307*2305Sstevel 	case cfga_eid(ENOTSUP, SYSC_ERR_HOTPLUG):
308*2305Sstevel 		return (SYSC_HOTPLUG);
309*2305Sstevel 	case cfga_eid(ENOTSUP, SYSC_ERR_HW_COMPAT):
310*2305Sstevel 		return (SYSC_HW_COMPAT);
311*2305Sstevel 	case cfga_eid(ENOTSUP, SYSC_ERR_NON_DR_PROM):
312*2305Sstevel 		return (SYSC_NON_DR_PROM);
313*2305Sstevel 	case cfga_eid(ENXIO, SYSC_ERR_SUSPEND):
314*2305Sstevel 		return (SYSC_SUSPEND);
315*2305Sstevel 	case cfga_eid(ENXIO, SYSC_ERR_RESUME):
316*2305Sstevel 		return (SYSC_RESUME);
317*2305Sstevel 	case cfga_eid(ESRCH, SYSC_ERR_UTHREAD):
318*2305Sstevel 		return (SYSC_UTHREAD);
319*2305Sstevel 	default:
320*2305Sstevel 		break;
321*2305Sstevel 	}
322*2305Sstevel 
323*2305Sstevel 	return (SYSC_UNKNOWN);
324*2305Sstevel }
325*2305Sstevel 
326*2305Sstevel static void
sysc_cmd_init(sysc_cfga_cmd_t * sc,char * outputstr,int force)327*2305Sstevel sysc_cmd_init(sysc_cfga_cmd_t *sc, char *outputstr, int force)
328*2305Sstevel {
329*2305Sstevel 	sc->force = force;
330*2305Sstevel 	sc->outputstr = outputstr;
331*2305Sstevel 	sc->errtype = SYSC_ERR_DEFAULT;
332*2305Sstevel 
333*2305Sstevel 	(void) memset((void *)outputstr, 0, sizeof (outputstr));
334*2305Sstevel 
335*2305Sstevel 	cfga_str(SYSC_DEVSTR) = outputstr;
336*2305Sstevel }
337*2305Sstevel 
338*2305Sstevel /*
339*2305Sstevel  * cfga_err() accepts a variable number of message IDs and constructs
340*2305Sstevel  * a corresponding error string which is returned via the errstring argument.
341*2305Sstevel  * cfga_err() calls dgettext() to internationalize proper messages.
342*2305Sstevel  */
343*2305Sstevel static void
cfga_err(sysc_cfga_cmd_t * sc,char ** errstring,...)344*2305Sstevel cfga_err(sysc_cfga_cmd_t *sc, char **errstring, ...)
345*2305Sstevel {
346*2305Sstevel 	int a;
347*2305Sstevel 	int i;
348*2305Sstevel 	int n;
349*2305Sstevel 	int len;
350*2305Sstevel 	int flen;
351*2305Sstevel 	char *p;
352*2305Sstevel 	char *q;
353*2305Sstevel 	char *s[32];
354*2305Sstevel 	char *failed;
355*2305Sstevel 	va_list ap;
356*2305Sstevel 	char syserr_num[20];
357*2305Sstevel 
358*2305Sstevel 	/*
359*2305Sstevel 	 * If errstring is null it means user in not interested in getting
360*2305Sstevel 	 * error status. So we don't do all the work
361*2305Sstevel 	 */
362*2305Sstevel 	if (errstring == NULL) {
363*2305Sstevel 		return;
364*2305Sstevel 	}
365*2305Sstevel 	va_start(ap, errstring);
366*2305Sstevel 
367*2305Sstevel 	failed = dgettext(TEXT_DOMAIN, cfga_str(DIAG_FAILED));
368*2305Sstevel 	flen = strlen(failed);
369*2305Sstevel 
370*2305Sstevel 	for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
371*2305Sstevel 
372*2305Sstevel 		switch (a) {
373*2305Sstevel 		case ERR_PROM_OPEN:
374*2305Sstevel 		case ERR_PROM_GETPROP:
375*2305Sstevel 		case ERR_PROM_SETPROP:
376*2305Sstevel 		case CMD_GETSTAT:
377*2305Sstevel 		case CMD_LIST:
378*2305Sstevel 		case CMD_CONNECT:
379*2305Sstevel 		case CMD_DISCONNECT:
380*2305Sstevel 		case CMD_CONFIGURE:
381*2305Sstevel 		case CMD_UNCONFIGURE:
382*2305Sstevel 		case CMD_QUIESCE:
383*2305Sstevel 		case CMD_INSERT:
384*2305Sstevel 		case CMD_REMOVE:
385*2305Sstevel 		case CMD_SET_COND:
386*2305Sstevel 			p =  cfga_str(a);
387*2305Sstevel 			len += (strlen(p) + flen);
388*2305Sstevel 			s[n] = p;
389*2305Sstevel 			s[++n] = failed;
390*2305Sstevel 
391*2305Sstevel 			DBG("<%s>", p);
392*2305Sstevel 			DBG("<%s>", failed);
393*2305Sstevel 			break;
394*2305Sstevel 
395*2305Sstevel 		case OPT_ENABLE:
396*2305Sstevel 		case OPT_DISABLE:
397*2305Sstevel 			p = dgettext(TEXT_DOMAIN, cfga_str(DIAG_TRANS_OK));
398*2305Sstevel 			q = cfga_str(a);
399*2305Sstevel 			len += (strlen(p) + strlen(q) + flen);
400*2305Sstevel 			s[n] = p;
401*2305Sstevel 			s[++n] = q;
402*2305Sstevel 			s[++n] = failed;
403*2305Sstevel 
404*2305Sstevel 			DBG("<%s>", p);
405*2305Sstevel 			DBG("<%s>", q);
406*2305Sstevel 			DBG("<%s>", failed);
407*2305Sstevel 			break;
408*2305Sstevel 
409*2305Sstevel 		case ERR_CMD_INVAL:
410*2305Sstevel 		case ERR_AP_INVAL:
411*2305Sstevel 		case ERR_OPT_INVAL:
412*2305Sstevel 			p =  dgettext(TEXT_DOMAIN, cfga_str(a));
413*2305Sstevel 			q = va_arg(ap, char *);
414*2305Sstevel 			len += (strlen(p) + strlen(q));
415*2305Sstevel 			s[n] = p;
416*2305Sstevel 			s[++n] = q;
417*2305Sstevel 
418*2305Sstevel 			DBG("<%s>", p);
419*2305Sstevel 			DBG("<%s>", q);
420*2305Sstevel 			break;
421*2305Sstevel 
422*2305Sstevel 		case ERR_TRANS:
423*2305Sstevel 		case ERR_DISABLED:
424*2305Sstevel 			p =  dgettext(TEXT_DOMAIN, cfga_str(a));
425*2305Sstevel 			len += strlen(p);
426*2305Sstevel 			s[n] = p;
427*2305Sstevel 
428*2305Sstevel 			DBG("<%s>", p);
429*2305Sstevel 			break;
430*2305Sstevel 
431*2305Sstevel 		case DIAG_FORCE:
432*2305Sstevel 		default:
433*2305Sstevel 			p =  cfga_str(a);
434*2305Sstevel 			len += strlen(p);
435*2305Sstevel 			s[n] = p;
436*2305Sstevel 
437*2305Sstevel 			DBG("<%s>", p);
438*2305Sstevel 			break;
439*2305Sstevel 		}
440*2305Sstevel 	}
441*2305Sstevel 
442*2305Sstevel 	DBG1("\n");
443*2305Sstevel 	va_end(ap);
444*2305Sstevel 
445*2305Sstevel 	if (errno) {
446*2305Sstevel 		if (sc)
447*2305Sstevel 			i = cfga_sid(errno, (int)sc->errtype);
448*2305Sstevel 		else
449*2305Sstevel 			i = SYSC_UNKNOWN;
450*2305Sstevel 
451*2305Sstevel 		DBG4("cfga_sid(%d,%d)=%d\n", errno, sc->errtype, i);
452*2305Sstevel 
453*2305Sstevel 		if (i == SYSC_UNKNOWN) {
454*2305Sstevel 			p = strerror(errno);
455*2305Sstevel 			if (p == NULL) {
456*2305Sstevel 				(void) sprintf(syserr_num, "errno=%d", errno);
457*2305Sstevel 				p = syserr_num;
458*2305Sstevel 			}
459*2305Sstevel 		} else
460*2305Sstevel 			p = dgettext(TEXT_DOMAIN, cfga_str(i));
461*2305Sstevel 
462*2305Sstevel 		len += strlen(p);
463*2305Sstevel 		s[n++] = p;
464*2305Sstevel 		p = cfga_str(SYSC_DEVSTR);
465*2305Sstevel 		if (p && p[0]) {
466*2305Sstevel 			q = cfga_str(STR_COL);
467*2305Sstevel 
468*2305Sstevel 			len += strlen(q);
469*2305Sstevel 			s[n++] = q;
470*2305Sstevel 			len += strlen(p);
471*2305Sstevel 			s[n++] = p;
472*2305Sstevel 		}
473*2305Sstevel 	}
474*2305Sstevel 
475*2305Sstevel 	if ((p = (char *)calloc(len, 1)) == NULL)
476*2305Sstevel 		return;
477*2305Sstevel 
478*2305Sstevel 	for (i = 0; i < n; i++)
479*2305Sstevel 		(void) strcat(p, s[i]);
480*2305Sstevel 
481*2305Sstevel 	*errstring = p;
482*2305Sstevel #ifdef	SIM_MSG
483*2305Sstevel 	printf("%s\n", *errstring);
484*2305Sstevel #endif
485*2305Sstevel }
486*2305Sstevel 
487*2305Sstevel /*
488*2305Sstevel  * This routine accepts a variable number of message IDs and constructs
489*2305Sstevel  * a corresponding error string which is printed via the message print routine
490*2305Sstevel  * argument.  The HELP_UNKNOWN message ID has an argument string (the unknown
491*2305Sstevel  * help topic) that follows.
492*2305Sstevel  */
493*2305Sstevel static void
cfga_msg(struct cfga_msg * msgp,...)494*2305Sstevel cfga_msg(struct cfga_msg *msgp, ...)
495*2305Sstevel {
496*2305Sstevel 	int a;
497*2305Sstevel 	int i;
498*2305Sstevel 	int n;
499*2305Sstevel 	int len;
500*2305Sstevel 	char *p;
501*2305Sstevel 	char *s[32];
502*2305Sstevel 	va_list ap;
503*2305Sstevel 
504*2305Sstevel 	va_start(ap, msgp);
505*2305Sstevel 
506*2305Sstevel 	for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
507*2305Sstevel 		DBG("<%d>", a);
508*2305Sstevel 		p =  dgettext(TEXT_DOMAIN, cfga_str(a));
509*2305Sstevel 		len += strlen(p);
510*2305Sstevel 		s[n] = p;
511*2305Sstevel 		if (a == HELP_UNKNOWN) {
512*2305Sstevel 			p = va_arg(ap, char *);
513*2305Sstevel 			len += strlen(p);
514*2305Sstevel 			s[++n] = p;
515*2305Sstevel 		}
516*2305Sstevel 	}
517*2305Sstevel 
518*2305Sstevel 	va_end(ap);
519*2305Sstevel 
520*2305Sstevel 	if ((p = (char *)calloc(len + 1, 1)) == NULL)
521*2305Sstevel 		return;
522*2305Sstevel 
523*2305Sstevel 	for (i = 0; i < n; i++)
524*2305Sstevel 		(void) strcat(p, s[i]);
525*2305Sstevel 	(void) strcat(p, "\n");
526*2305Sstevel 
527*2305Sstevel #ifdef	SIM_MSG
528*2305Sstevel 	printf("%s", p);
529*2305Sstevel #else
530*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, p);
531*2305Sstevel #endif
532*2305Sstevel 	free(p);
533*2305Sstevel }
534*2305Sstevel 
535*2305Sstevel static sysc_cfga_stat_t *
sysc_stat(const char * ap_id,int * fdp)536*2305Sstevel sysc_stat(const char *ap_id, int *fdp)
537*2305Sstevel {
538*2305Sstevel 	int fd;
539*2305Sstevel 	static sysc_cfga_stat_t sc_list[MAX_BOARDS];
540*2305Sstevel 
541*2305Sstevel 
542*2305Sstevel 	if ((fd = open(ap_id, O_RDWR, 0)) == -1)
543*2305Sstevel 		return (NULL);
544*2305Sstevel 	else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sc_list) == -1) {
545*2305Sstevel 		(void) close(fd);
546*2305Sstevel 		return (NULL);
547*2305Sstevel 	} else if (fdp)
548*2305Sstevel 		*fdp = fd;
549*2305Sstevel 	else
550*2305Sstevel 		(void) close(fd);
551*2305Sstevel 
552*2305Sstevel 	return (sc_list);
553*2305Sstevel }
554*2305Sstevel 
555*2305Sstevel /*
556*2305Sstevel  * This code implementes the simulation of the ioctls that transition state.
557*2305Sstevel  * The GETSTAT ioctl is not simulated.  In this way a snapshot of the system
558*2305Sstevel  * state is read and manipulated by the simulation routines.  It is basically
559*2305Sstevel  * a useful debugging tool.
560*2305Sstevel  */
561*2305Sstevel #ifdef	SIM
562*2305Sstevel static int sim_idx;
563*2305Sstevel static int sim_fd = -1;
564*2305Sstevel static int sim_size = MAX_BOARDS * sizeof (sysc_cfga_stat_t);
565*2305Sstevel static sysc_cfga_stat_t sim_sc_list[MAX_BOARDS];
566*2305Sstevel 
567*2305Sstevel static sysc_cfga_stat_t *
sim_sysc_stat(const char * ap_id,int * fdp)568*2305Sstevel sim_sysc_stat(const char *ap_id, int *fdp)
569*2305Sstevel {
570*2305Sstevel 	int fd;
571*2305Sstevel 	struct stat buf;
572*2305Sstevel 
573*2305Sstevel 	if (sim_fd != -1)
574*2305Sstevel 		return (sim_sc_list);
575*2305Sstevel 
576*2305Sstevel 	if ((sim_fd = open("/tmp/cfga_simdata", O_RDWR|O_CREAT)) == -1) {
577*2305Sstevel 		perror("sim_open");
578*2305Sstevel 		exit(1);
579*2305Sstevel 	} else if (fstat(sim_fd, &buf) == -1) {
580*2305Sstevel 		perror("sim_stat");
581*2305Sstevel 		exit(1);
582*2305Sstevel 	}
583*2305Sstevel 
584*2305Sstevel 	if (buf.st_size) {
585*2305Sstevel 		if (buf.st_size != sim_size) {
586*2305Sstevel 			perror("sim_size");
587*2305Sstevel 			exit(1);
588*2305Sstevel 		} else if (read(sim_fd, sim_sc_list, sim_size) == -1) {
589*2305Sstevel 			perror("sim_read");
590*2305Sstevel 			exit(1);
591*2305Sstevel 		}
592*2305Sstevel 	} else if ((fd = open(ap_id, O_RDWR, 0)) == -1)
593*2305Sstevel 		return (NULL);
594*2305Sstevel 	else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sim_sc_list) == -1) {
595*2305Sstevel 		(void) close(fd);
596*2305Sstevel 		return (NULL);
597*2305Sstevel 	} else if (fdp)
598*2305Sstevel 		*fdp = fd;
599*2305Sstevel 
600*2305Sstevel 	return (sim_sc_list);
601*2305Sstevel }
602*2305Sstevel 
603*2305Sstevel static int
sim_open(char * a,int b,int c)604*2305Sstevel sim_open(char *a, int b, int c)
605*2305Sstevel {
606*2305Sstevel 	printf("sim_open(%s)\n", a);
607*2305Sstevel 
608*2305Sstevel 	if (strcmp(a, "/dev/openprom") == 0)
609*2305Sstevel 		return (open(a, b, c));
610*2305Sstevel 	return (0);
611*2305Sstevel }
612*2305Sstevel 
613*2305Sstevel static int
sim_close(int a)614*2305Sstevel sim_close(int a) { return (0); }
615*2305Sstevel 
616*2305Sstevel static int
sim_ioctl(int fd,int cmd,void * a)617*2305Sstevel sim_ioctl(int fd, int cmd, void *a)
618*2305Sstevel {
619*2305Sstevel 	printf("sim_ioctl(%d)\n", sim_idx);
620*2305Sstevel 
621*2305Sstevel 	switch (cmd) {
622*2305Sstevel 	case SYSC_CFGA_CMD_CONNECT:
623*2305Sstevel 		sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_CONNECTED;
624*2305Sstevel 		break;
625*2305Sstevel 	case SYSC_CFGA_CMD_CONFIGURE:
626*2305Sstevel 		sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_CONFIGURED;
627*2305Sstevel 		break;
628*2305Sstevel 	case SYSC_CFGA_CMD_UNCONFIGURE:
629*2305Sstevel 		sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
630*2305Sstevel 		break;
631*2305Sstevel 	case SYSC_CFGA_CMD_DISCONNECT:
632*2305Sstevel 		sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
633*2305Sstevel 		break;
634*2305Sstevel 	case SYSC_CFGA_CMD_QUIESCE_TEST:
635*2305Sstevel 	case SYSC_CFGA_CMD_TEST:
636*2305Sstevel 		return (0);
637*2305Sstevel 	case OPROMGETOPT:
638*2305Sstevel 		return (ioctl(fd, OPROMGETOPT, a));
639*2305Sstevel 	case OPROMSETOPT:
640*2305Sstevel 		return (ioctl(fd, OPROMSETOPT, a));
641*2305Sstevel 	}
642*2305Sstevel 
643*2305Sstevel 	if (lseek(sim_fd, SEEK_SET, 0) == -1) {
644*2305Sstevel 		perror("sim_seek");
645*2305Sstevel 		exit(1);
646*2305Sstevel 	}
647*2305Sstevel 	if (write(sim_fd, sim_sc_list, sim_size) == -1) {
648*2305Sstevel 		perror("sim_write");
649*2305Sstevel 		exit(1);
650*2305Sstevel 	}
651*2305Sstevel 
652*2305Sstevel 	return (0);
653*2305Sstevel }
654*2305Sstevel 
655*2305Sstevel #define	open(a, b, c)	sim_open((char *)(a), (int)(b), (int)(c))
656*2305Sstevel #define	close(a)	sim_close(a)
657*2305Sstevel #define	ioctl(a, b, c)	sim_ioctl((int)(a), (int)(b), (void *)(c))
658*2305Sstevel #define	sysc_stat(a, b)	sim_sysc_stat(a, b)
659*2305Sstevel #endif	/* SIM */
660*2305Sstevel 
661*2305Sstevel static char *promdev = "/dev/openprom";
662*2305Sstevel static char *dlprop = "disabled-board-list";
663*2305Sstevel 
664*2305Sstevel #define	BUFSIZE		128
665*2305Sstevel 
666*2305Sstevel typedef union {
667*2305Sstevel 	char buf[BUFSIZE];
668*2305Sstevel 	struct openpromio opp;
669*2305Sstevel } oppbuf_t;
670*2305Sstevel 
671*2305Sstevel static int
prom_get_prop(int prom_fd,char * var,char ** val)672*2305Sstevel prom_get_prop(int prom_fd, char *var, char **val)
673*2305Sstevel {
674*2305Sstevel 	static oppbuf_t oppbuf;
675*2305Sstevel 	struct openpromio *opp = &(oppbuf.opp);
676*2305Sstevel 
677*2305Sstevel 	(void) strncpy(opp->oprom_array, var, OBP_MAXPROPNAME);
678*2305Sstevel 	opp->oprom_array[OBP_MAXPROPNAME + 1] = '\0';
679*2305Sstevel 	opp->oprom_size = BUFSIZE;
680*2305Sstevel 
681*2305Sstevel 	DBG3("getprop(%s, %d)\n", opp->oprom_array, opp->oprom_size);
682*2305Sstevel 
683*2305Sstevel 	if (ioctl(prom_fd, OPROMGETOPT, opp) < 0)
684*2305Sstevel 		return (ERR_PROM_GETPROP);
685*2305Sstevel 	else if (opp->oprom_size > 0)
686*2305Sstevel 		*val = opp->oprom_array;
687*2305Sstevel 	else
688*2305Sstevel 		*val = NULL;
689*2305Sstevel 
690*2305Sstevel 	return (0);
691*2305Sstevel }
692*2305Sstevel 
693*2305Sstevel static cfga_err_t
prom_set_prop(int prom_fd,char * var,char * val)694*2305Sstevel prom_set_prop(int prom_fd, char *var, char *val)
695*2305Sstevel {
696*2305Sstevel 	oppbuf_t oppbuf;
697*2305Sstevel 	struct openpromio *opp = &(oppbuf.opp);
698*2305Sstevel 	int varlen = strlen(var) + 1;
699*2305Sstevel 	int vallen = strlen(val);
700*2305Sstevel 
701*2305Sstevel 	DBG("prom_set_prop(%s)\n", val);
702*2305Sstevel 
703*2305Sstevel 	(void) strcpy(opp->oprom_array, var);
704*2305Sstevel 	(void) strcpy(opp->oprom_array + varlen, val);
705*2305Sstevel 	opp->oprom_size = varlen + vallen;
706*2305Sstevel 
707*2305Sstevel 	if (ioctl(prom_fd, OPROMSETOPT, opp) < 0)
708*2305Sstevel 		return (ERR_PROM_SETPROP);
709*2305Sstevel 
710*2305Sstevel 	return (0);
711*2305Sstevel }
712*2305Sstevel 
713*2305Sstevel static int
dlist_find(int board,char ** dlist,int * disabled)714*2305Sstevel dlist_find(int board, char **dlist, int *disabled)
715*2305Sstevel {
716*2305Sstevel 	int i;
717*2305Sstevel 	int err;
718*2305Sstevel 	int prom_fd;
719*2305Sstevel 	char *p;
720*2305Sstevel 	char *dl;
721*2305Sstevel 	char b[2];
722*2305Sstevel 
723*2305Sstevel 	if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
724*2305Sstevel 		return (ERR_PROM_OPEN);
725*2305Sstevel 	else if (err = prom_get_prop(prom_fd, dlprop, dlist)) {
726*2305Sstevel 		(void) close(prom_fd);
727*2305Sstevel 		return (err);
728*2305Sstevel 	} else
729*2305Sstevel 		(void) close(prom_fd);
730*2305Sstevel 
731*2305Sstevel 	b[1] = 0;
732*2305Sstevel 	*disabled = 0;
733*2305Sstevel 
734*2305Sstevel 	if ((dl = *dlist) != NULL) {
735*2305Sstevel 		int len = strlen(dl);
736*2305Sstevel 
737*2305Sstevel 		for (i = 0; i < len; i++) {
738*2305Sstevel 			int bd;
739*2305Sstevel 
740*2305Sstevel 			b[0] = dl[i];
741*2305Sstevel 			bd = strtol(b, &p, 16);
742*2305Sstevel 
743*2305Sstevel 			if (p != b && bd == board)
744*2305Sstevel 				(*disabled)++;
745*2305Sstevel 		}
746*2305Sstevel 	}
747*2305Sstevel 
748*2305Sstevel 	return (0);
749*2305Sstevel }
750*2305Sstevel 
751*2305Sstevel static int
dlist_update(int board,int disable,char * dlist,struct cfga_msg * msgp,int verbose)752*2305Sstevel dlist_update(int board, int disable, char *dlist, struct cfga_msg *msgp,
753*2305Sstevel 	int verbose)
754*2305Sstevel {
755*2305Sstevel 	int i, j, n;
756*2305Sstevel 	int err;
757*2305Sstevel 	int found;
758*2305Sstevel 	int update;
759*2305Sstevel 	int prom_fd;
760*2305Sstevel 	char *p;
761*2305Sstevel 	char b[2];
762*2305Sstevel 	char ndlist[64];
763*2305Sstevel 
764*2305Sstevel 	b[1] = 0;
765*2305Sstevel 	ndlist[0] = 0;
766*2305Sstevel 	j = 0;
767*2305Sstevel 	found = 0;
768*2305Sstevel 	update = 0;
769*2305Sstevel 
770*2305Sstevel 	if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
771*2305Sstevel 		return (ERR_PROM_OPEN);
772*2305Sstevel 
773*2305Sstevel 	if (dlist) {
774*2305Sstevel 		int len = strlen(dlist);
775*2305Sstevel 
776*2305Sstevel 		for (i = 0; i < len; i++) {
777*2305Sstevel 			int bd;
778*2305Sstevel 
779*2305Sstevel 			b[0] = dlist[i];
780*2305Sstevel 			bd = strtol(b, &p, 16);
781*2305Sstevel 
782*2305Sstevel 			if (p != b && bd == board) {
783*2305Sstevel 
784*2305Sstevel 				found++;
785*2305Sstevel 				if (disable) {
786*2305Sstevel 					if (verbose)
787*2305Sstevel 						cfga_msg(msgp, STR_BD,
788*2305Sstevel 						    DIAG_WAS_DISABLED, 0);
789*2305Sstevel 				} else {
790*2305Sstevel 					if (verbose)
791*2305Sstevel 						cfga_msg(msgp, STR_BD,
792*2305Sstevel 						    DIAG_WILL_ENABLE, 0);
793*2305Sstevel 					update++;
794*2305Sstevel 					continue;
795*2305Sstevel 				}
796*2305Sstevel 			}
797*2305Sstevel 			ndlist[j++] = dlist[i];
798*2305Sstevel 		}
799*2305Sstevel 		ndlist[j] = 0;
800*2305Sstevel 	}
801*2305Sstevel 
802*2305Sstevel 	if (!found)
803*2305Sstevel 		if (disable) {
804*2305Sstevel 			if (verbose)
805*2305Sstevel 				cfga_msg(msgp, STR_BD, DIAG_WILL_DISABLE, 0);
806*2305Sstevel 			p = &ndlist[j];
807*2305Sstevel 			n = sprintf(p, "%x", board);
808*2305Sstevel 			p[n] = 0;
809*2305Sstevel 			update++;
810*2305Sstevel 		} else {
811*2305Sstevel 			if (verbose)
812*2305Sstevel 				cfga_msg(msgp, STR_BD, DIAG_WAS_ENABLED, 0);
813*2305Sstevel 		}
814*2305Sstevel 
815*2305Sstevel 	if (update)
816*2305Sstevel 		err = prom_set_prop(prom_fd, dlprop, ndlist);
817*2305Sstevel 	else
818*2305Sstevel 		err = 0;
819*2305Sstevel 
820*2305Sstevel 	(void) close(prom_fd);
821*2305Sstevel 
822*2305Sstevel 	return (err);
823*2305Sstevel }
824*2305Sstevel 
825*2305Sstevel static int
ap_idx(const char * ap_id)826*2305Sstevel ap_idx(const char *ap_id)
827*2305Sstevel {
828*2305Sstevel 	int id;
829*2305Sstevel 	char *s;
830*2305Sstevel 	static char *slot = "slot";
831*2305Sstevel 
832*2305Sstevel 	DBG("ap_idx(%s)\n", ap_id);
833*2305Sstevel 
834*2305Sstevel 	if ((s = strstr(ap_id, slot)) == NULL)
835*2305Sstevel 		return (-1);
836*2305Sstevel 	else {
837*2305Sstevel 		int n;
838*2305Sstevel 
839*2305Sstevel 		s += strlen(slot);
840*2305Sstevel 		n = strlen(s);
841*2305Sstevel 
842*2305Sstevel 		DBG3("ap_idx: s=%s, n=%d\n", s, n);
843*2305Sstevel 
844*2305Sstevel 		switch (n) {
845*2305Sstevel 		case 2:
846*2305Sstevel 			if (!isdigit(s[1]))
847*2305Sstevel 				return (-1);
848*2305Sstevel 		/* FALLTHROUGH */
849*2305Sstevel 		case 1:
850*2305Sstevel 			if (!isdigit(s[0]))
851*2305Sstevel 				return (-1);
852*2305Sstevel 			break;
853*2305Sstevel 		default:
854*2305Sstevel 			return (-1);
855*2305Sstevel 		}
856*2305Sstevel 	}
857*2305Sstevel 
858*2305Sstevel 	if ((id = atoi(s)) > MAX_BOARDS)
859*2305Sstevel 		return (-1);
860*2305Sstevel 
861*2305Sstevel 	DBG3("ap_idx(%s)=%d\n", s, id);
862*2305Sstevel 
863*2305Sstevel 	return (id);
864*2305Sstevel }
865*2305Sstevel 
866*2305Sstevel /*ARGSUSED*/
867*2305Sstevel 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)868*2305Sstevel cfga_change_state(
869*2305Sstevel 	cfga_cmd_t state_change_cmd,
870*2305Sstevel 	const char *ap_id,
871*2305Sstevel 	const char *options,
872*2305Sstevel 	struct cfga_confirm *confp,
873*2305Sstevel 	struct cfga_msg *msgp,
874*2305Sstevel 	char **errstring,
875*2305Sstevel 	cfga_flags_t flags)
876*2305Sstevel {
877*2305Sstevel 	int fd;
878*2305Sstevel 	int idx;
879*2305Sstevel 	int err;
880*2305Sstevel 	int force;
881*2305Sstevel 	int verbose;
882*2305Sstevel 	int opterr;
883*2305Sstevel 	int disable;
884*2305Sstevel 	int disabled;
885*2305Sstevel 	cfga_err_t rc;
886*2305Sstevel 	sysc_cfga_stat_t *ss;
887*2305Sstevel 	sysc_cfga_cmd_t *sc, sysc_cmd;
888*2305Sstevel 	sysc_cfga_rstate_t rs;
889*2305Sstevel 	sysc_cfga_ostate_t os;
890*2305Sstevel 	char *dlist;
891*2305Sstevel 	char outputstr[SYSC_OUTPUT_LEN];
892*2305Sstevel 
893*2305Sstevel 	if (errstring != NULL)
894*2305Sstevel 		*errstring = NULL;
895*2305Sstevel 
896*2305Sstevel 	rc = CFGA_ERROR;
897*2305Sstevel 
898*2305Sstevel 	if (options) {
899*2305Sstevel 		disable = 0;
900*2305Sstevel 		if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
901*2305Sstevel 			disable++;
902*2305Sstevel 		else if (strcmp(options, cfga_str(OPT_ENABLE))) {
903*2305Sstevel 			cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
904*2305Sstevel 			return (rc);
905*2305Sstevel 		}
906*2305Sstevel 	}
907*2305Sstevel 
908*2305Sstevel 	if ((idx = ap_idx(ap_id)) == -1) {
909*2305Sstevel 		cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
910*2305Sstevel 		return (rc);
911*2305Sstevel 	} else if ((ss = sysc_stat(ap_id, &fd)) == NULL) {
912*2305Sstevel 		cfga_err(NULL, errstring, CMD_GETSTAT, 0);
913*2305Sstevel 		return (rc);
914*2305Sstevel 	}
915*2305Sstevel #ifdef	SIM
916*2305Sstevel 	sim_idx = idx;
917*2305Sstevel #endif
918*2305Sstevel 	/*
919*2305Sstevel 	 * We disallow connecting on the disabled list unless
920*2305Sstevel 	 * either the FORCE flag or the enable-at-boot option
921*2305Sstevel 	 * is set. The check is made further below
922*2305Sstevel 	 */
923*2305Sstevel 	if (opterr = dlist_find(idx, &dlist, &disabled)) {
924*2305Sstevel 		err = disable ? OPT_DISABLE : OPT_ENABLE;
925*2305Sstevel 		cfga_err(NULL, errstring, err, opterr, 0);
926*2305Sstevel 		(void) close(fd);
927*2305Sstevel 		return (rc);
928*2305Sstevel 	} else
929*2305Sstevel 		force = flags & CFGA_FLAG_FORCE;
930*2305Sstevel 
931*2305Sstevel 	rs = ss[idx].rstate;
932*2305Sstevel 	os = ss[idx].ostate;
933*2305Sstevel 
934*2305Sstevel 	sc = &sysc_cmd;
935*2305Sstevel 	sysc_cmd_init(sc, outputstr, force);
936*2305Sstevel 	verbose = flags & CFGA_FLAG_VERBOSE;
937*2305Sstevel 
938*2305Sstevel 	switch (state_change_cmd) {
939*2305Sstevel 	case CFGA_CMD_CONNECT:
940*2305Sstevel 		if (rs != SYSC_CFGA_RSTATE_DISCONNECTED)
941*2305Sstevel 			cfga_err(NULL, errstring, ERR_TRANS, 0);
942*2305Sstevel 		else if (disabled && !(force || (options && !disable)))
943*2305Sstevel 			cfga_err(NULL, errstring, CMD_CONNECT,
944*2305Sstevel 				ERR_DISABLED, DIAG_FORCE, 0);
945*2305Sstevel 		else if (!(*confp->confirm)(confp->appdata_ptr,
946*2305Sstevel 		    cfga_str(ASK_CONNECT))) {
947*2305Sstevel 			(void) close(fd);
948*2305Sstevel 			return (CFGA_NACK);
949*2305Sstevel 		} else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1)
950*2305Sstevel 			cfga_err(sc, errstring, CMD_CONNECT, 0);
951*2305Sstevel 		else if (options && (opterr = dlist_update(idx, disable,
952*2305Sstevel 			dlist, msgp, verbose))) {
953*2305Sstevel 			err = disable ? OPT_DISABLE : OPT_ENABLE;
954*2305Sstevel 			cfga_err(NULL, errstring, err, opterr, 0);
955*2305Sstevel 		} else
956*2305Sstevel 			rc = CFGA_OK;
957*2305Sstevel 		break;
958*2305Sstevel 
959*2305Sstevel 	case CFGA_CMD_DISCONNECT:
960*2305Sstevel 		if ((os == SYSC_CFGA_OSTATE_CONFIGURED) &&
961*2305Sstevel 		    (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)) {
962*2305Sstevel 			cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
963*2305Sstevel 			(void) close(fd);
964*2305Sstevel 			return (CFGA_ERROR);
965*2305Sstevel 		} else
966*2305Sstevel 			sysc_cmd_init(sc, outputstr, force);
967*2305Sstevel 
968*2305Sstevel 		if (rs == SYSC_CFGA_RSTATE_CONNECTED) {
969*2305Sstevel 			if (ioctl(fd, SYSC_CFGA_CMD_DISCONNECT, sc) == -1)
970*2305Sstevel 				cfga_err(sc, errstring, CMD_DISCONNECT, 0);
971*2305Sstevel 			else if (options && (opterr = dlist_update(idx, disable,
972*2305Sstevel 			    dlist, msgp, verbose))) {
973*2305Sstevel 				err = disable ? OPT_DISABLE : OPT_ENABLE;
974*2305Sstevel 				cfga_err(NULL, errstring, err, opterr, 0);
975*2305Sstevel 			} else
976*2305Sstevel 				rc = CFGA_OK;
977*2305Sstevel 		} else
978*2305Sstevel 			cfga_err(NULL, errstring, ERR_TRANS, 0);
979*2305Sstevel 		break;
980*2305Sstevel 
981*2305Sstevel 	case CFGA_CMD_CONFIGURE:
982*2305Sstevel 		if (rs == SYSC_CFGA_RSTATE_DISCONNECTED)
983*2305Sstevel 			if (disabled && !(force || (options && !disable))) {
984*2305Sstevel 				cfga_err(NULL, errstring, CMD_CONFIGURE,
985*2305Sstevel 					ERR_DISABLED, DIAG_FORCE, 0);
986*2305Sstevel 				(void) close(fd);
987*2305Sstevel 				return (CFGA_ERROR);
988*2305Sstevel 			} else if (!(*confp->confirm)(confp->appdata_ptr,
989*2305Sstevel 			    cfga_str(ASK_CONNECT))) {
990*2305Sstevel 				(void) close(fd);
991*2305Sstevel 				return (CFGA_NACK);
992*2305Sstevel 			} else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1) {
993*2305Sstevel 				cfga_err(sc, errstring, CMD_CONNECT, 0);
994*2305Sstevel 				(void) close(fd);
995*2305Sstevel 				return (CFGA_ERROR);
996*2305Sstevel 			} else
997*2305Sstevel 				sysc_cmd_init(sc, outputstr, force);
998*2305Sstevel 
999*2305Sstevel 		if (os == SYSC_CFGA_OSTATE_UNCONFIGURED) {
1000*2305Sstevel 			if (ioctl(fd, SYSC_CFGA_CMD_CONFIGURE, sc) == -1)
1001*2305Sstevel 				cfga_err(sc, errstring, CMD_CONFIGURE, 0);
1002*2305Sstevel 			else if (options && (opterr = dlist_update(idx,
1003*2305Sstevel 				disable, dlist, msgp, verbose))) {
1004*2305Sstevel 				err = disable ? OPT_DISABLE : OPT_ENABLE;
1005*2305Sstevel 				cfga_err(NULL, errstring, err, opterr, 0);
1006*2305Sstevel 			} else
1007*2305Sstevel 				rc = CFGA_OK;
1008*2305Sstevel 		} else
1009*2305Sstevel 			cfga_err(NULL, errstring, ERR_TRANS, 0);
1010*2305Sstevel 		break;
1011*2305Sstevel 
1012*2305Sstevel 	case CFGA_CMD_UNCONFIGURE:
1013*2305Sstevel 		if (os != SYSC_CFGA_OSTATE_CONFIGURED)
1014*2305Sstevel 			cfga_err(NULL, errstring, ERR_TRANS, 0);
1015*2305Sstevel 		else if (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)
1016*2305Sstevel 			cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
1017*2305Sstevel 		else if (options && (opterr = dlist_update(idx, disable,
1018*2305Sstevel 			dlist, msgp, verbose))) {
1019*2305Sstevel 			err = disable ? OPT_DISABLE : OPT_ENABLE;
1020*2305Sstevel 			cfga_err(NULL, errstring, err, opterr, 0);
1021*2305Sstevel 		} else
1022*2305Sstevel 			rc = CFGA_OK;
1023*2305Sstevel 		break;
1024*2305Sstevel 
1025*2305Sstevel 	default:
1026*2305Sstevel 		rc = CFGA_OPNOTSUPP;
1027*2305Sstevel 		break;
1028*2305Sstevel 	}
1029*2305Sstevel 
1030*2305Sstevel 	(void) close(fd);
1031*2305Sstevel 	return (rc);
1032*2305Sstevel }
1033*2305Sstevel 
1034*2305Sstevel static int
str2cond(const char * cond)1035*2305Sstevel str2cond(const char *cond)
1036*2305Sstevel {
1037*2305Sstevel 	int c;
1038*2305Sstevel 
1039*2305Sstevel 	if (strcmp(cond, cfga_str(COND_UNKNOWN)) == 0)
1040*2305Sstevel 		c =  SYSC_CFGA_COND_UNKNOWN;
1041*2305Sstevel 	else if (strcmp(cond, cfga_str(COND_OK)) == 0)
1042*2305Sstevel 		c =  SYSC_CFGA_COND_OK;
1043*2305Sstevel 	else if (strcmp(cond, cfga_str(COND_FAILING)) == 0)
1044*2305Sstevel 		c =  SYSC_CFGA_COND_FAILING;
1045*2305Sstevel 	else if (strcmp(cond, cfga_str(COND_FAILED)) == 0)
1046*2305Sstevel 		c =  SYSC_CFGA_COND_FAILED;
1047*2305Sstevel 	else if (strcmp(cond, cfga_str(COND_UNUSABLE)) == 0)
1048*2305Sstevel 		c =  SYSC_CFGA_COND_UNUSABLE;
1049*2305Sstevel 	else
1050*2305Sstevel 		c = -1;
1051*2305Sstevel 
1052*2305Sstevel 	return (c);
1053*2305Sstevel }
1054*2305Sstevel 
1055*2305Sstevel /*ARGSUSED*/
1056*2305Sstevel 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)1057*2305Sstevel cfga_private_func(
1058*2305Sstevel 	const char *function,
1059*2305Sstevel 	const char *ap_id,
1060*2305Sstevel 	const char *options,
1061*2305Sstevel 	struct cfga_confirm *confp,
1062*2305Sstevel 	struct cfga_msg *msgp,
1063*2305Sstevel 	char **errstring,
1064*2305Sstevel 	cfga_flags_t flags)
1065*2305Sstevel {
1066*2305Sstevel 	int fd;
1067*2305Sstevel 	int idx;
1068*2305Sstevel 	int len;
1069*2305Sstevel 	int cmd;
1070*2305Sstevel 	int cond;
1071*2305Sstevel 	int err;
1072*2305Sstevel 	int opterr;
1073*2305Sstevel 	int verbose;
1074*2305Sstevel 	int disable;
1075*2305Sstevel 	int disabled;
1076*2305Sstevel 	cfga_err_t rc;
1077*2305Sstevel 	char *str;
1078*2305Sstevel 	char *dlist;
1079*2305Sstevel 	char outputstr[SYSC_OUTPUT_LEN];
1080*2305Sstevel 	sysc_cfga_cmd_t *sc, sysc_cmd;
1081*2305Sstevel 
1082*2305Sstevel 	if (errstring != NULL)
1083*2305Sstevel 		*errstring = NULL;
1084*2305Sstevel 
1085*2305Sstevel 	verbose = flags & CFGA_FLAG_VERBOSE;
1086*2305Sstevel 
1087*2305Sstevel 	rc = CFGA_ERROR;
1088*2305Sstevel 
1089*2305Sstevel 	if (options) {
1090*2305Sstevel 		disable = 0;
1091*2305Sstevel 		if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
1092*2305Sstevel 			disable++;
1093*2305Sstevel 		else if (strcmp(options, cfga_str(OPT_ENABLE))) {
1094*2305Sstevel 			cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
1095*2305Sstevel 			return (rc);
1096*2305Sstevel 		}
1097*2305Sstevel 	}
1098*2305Sstevel 
1099*2305Sstevel 	sc = &sysc_cmd;
1100*2305Sstevel 	str = cfga_str(CMD_SET_COND);
1101*2305Sstevel 	len = strlen(str);
1102*2305Sstevel 
1103*2305Sstevel 	if ((strncmp(function, str, len) == 0) && (function[len++] == '=') &&
1104*2305Sstevel 	    ((cond = (str2cond(&function[len]))) != -1)) {
1105*2305Sstevel 		cmd = SYSC_CFGA_CMD_TEST_SET_COND;
1106*2305Sstevel 		err = CMD_SET_COND;
1107*2305Sstevel 		sc->arg = cond;
1108*2305Sstevel 	} else if (strcmp(function, cfga_str(CMD_QUIESCE)) == 0) {
1109*2305Sstevel 		cmd = SYSC_CFGA_CMD_QUIESCE_TEST;
1110*2305Sstevel 		err = CMD_QUIESCE;
1111*2305Sstevel 	} else if (strcmp(function, cfga_str(CMD_INSERT)) == 0) {
1112*2305Sstevel 		cmd = SYSC_CFGA_CMD_TEST;
1113*2305Sstevel 		err = CMD_INSERT;
1114*2305Sstevel 	} else if (strcmp(function, cfga_str(CMD_REMOVE)) == 0) {
1115*2305Sstevel 		cmd = SYSC_CFGA_CMD_TEST;
1116*2305Sstevel 		err = CMD_REMOVE;
1117*2305Sstevel 	} else {
1118*2305Sstevel 		cfga_err(NULL, errstring, ERR_CMD_INVAL, (char *)function, 0);
1119*2305Sstevel 		return (rc);
1120*2305Sstevel 	}
1121*2305Sstevel 
1122*2305Sstevel 	sysc_cmd_init(sc, outputstr, 0);
1123*2305Sstevel 
1124*2305Sstevel 	if ((idx = ap_idx(ap_id)) == -1)
1125*2305Sstevel 		cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
1126*2305Sstevel 	else if (((fd = open(ap_id, O_RDWR, 0)) == -1) ||
1127*2305Sstevel 		(ioctl(fd, cmd, sc) == -1))
1128*2305Sstevel 		cfga_err(NULL, errstring, err, 0);
1129*2305Sstevel 	else
1130*2305Sstevel 		rc = CFGA_OK;
1131*2305Sstevel 
1132*2305Sstevel 	if (options) {
1133*2305Sstevel 		opterr = (dlist_find(idx, &dlist, &disabled) ||
1134*2305Sstevel 			dlist_update(idx, disable, dlist, msgp, verbose));
1135*2305Sstevel 		if (opterr) {
1136*2305Sstevel 			err = disable ? OPT_DISABLE : OPT_ENABLE;
1137*2305Sstevel 			if (verbose)
1138*2305Sstevel 				cfga_msg(msgp, err, opterr, 0);
1139*2305Sstevel 		}
1140*2305Sstevel 	}
1141*2305Sstevel 
1142*2305Sstevel 	(void) close(fd);
1143*2305Sstevel 	return (rc);
1144*2305Sstevel }
1145*2305Sstevel 
1146*2305Sstevel 
1147*2305Sstevel /*ARGSUSED*/
1148*2305Sstevel cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)1149*2305Sstevel cfga_test(
1150*2305Sstevel 	const char *ap_id,
1151*2305Sstevel 	const char *options,
1152*2305Sstevel 	struct cfga_msg *msgp,
1153*2305Sstevel 	char **errstring,
1154*2305Sstevel 	cfga_flags_t flags)
1155*2305Sstevel {
1156*2305Sstevel 	if (errstring != NULL)
1157*2305Sstevel 		*errstring = NULL;
1158*2305Sstevel 
1159*2305Sstevel 	return (CFGA_OPNOTSUPP);
1160*2305Sstevel }
1161*2305Sstevel 
1162*2305Sstevel static cfga_stat_t
rstate_cvt(sysc_cfga_rstate_t rs)1163*2305Sstevel rstate_cvt(sysc_cfga_rstate_t rs)
1164*2305Sstevel {
1165*2305Sstevel 	cfga_stat_t cs;
1166*2305Sstevel 
1167*2305Sstevel 	switch (rs) {
1168*2305Sstevel 	case SYSC_CFGA_RSTATE_EMPTY:
1169*2305Sstevel 		cs = CFGA_STAT_EMPTY;
1170*2305Sstevel 		break;
1171*2305Sstevel 	case SYSC_CFGA_RSTATE_DISCONNECTED:
1172*2305Sstevel 		cs = CFGA_STAT_DISCONNECTED;
1173*2305Sstevel 		break;
1174*2305Sstevel 	case SYSC_CFGA_RSTATE_CONNECTED:
1175*2305Sstevel 		cs = CFGA_STAT_CONNECTED;
1176*2305Sstevel 		break;
1177*2305Sstevel 	default:
1178*2305Sstevel 		cs = CFGA_STAT_NONE;
1179*2305Sstevel 		break;
1180*2305Sstevel 	}
1181*2305Sstevel 
1182*2305Sstevel 	return (cs);
1183*2305Sstevel }
1184*2305Sstevel 
1185*2305Sstevel static cfga_stat_t
ostate_cvt(sysc_cfga_ostate_t os)1186*2305Sstevel ostate_cvt(sysc_cfga_ostate_t os)
1187*2305Sstevel {
1188*2305Sstevel 	cfga_stat_t cs;
1189*2305Sstevel 
1190*2305Sstevel 	switch (os) {
1191*2305Sstevel 	case SYSC_CFGA_OSTATE_UNCONFIGURED:
1192*2305Sstevel 		cs = CFGA_STAT_UNCONFIGURED;
1193*2305Sstevel 		break;
1194*2305Sstevel 	case SYSC_CFGA_OSTATE_CONFIGURED:
1195*2305Sstevel 		cs = CFGA_STAT_CONFIGURED;
1196*2305Sstevel 		break;
1197*2305Sstevel 	default:
1198*2305Sstevel 		cs = CFGA_STAT_NONE;
1199*2305Sstevel 		break;
1200*2305Sstevel 	}
1201*2305Sstevel 
1202*2305Sstevel 	return (cs);
1203*2305Sstevel }
1204*2305Sstevel 
1205*2305Sstevel static cfga_cond_t
cond_cvt(sysc_cfga_cond_t sc)1206*2305Sstevel cond_cvt(sysc_cfga_cond_t sc)
1207*2305Sstevel {
1208*2305Sstevel 	cfga_cond_t cc;
1209*2305Sstevel 
1210*2305Sstevel 	switch (sc) {
1211*2305Sstevel 	case SYSC_CFGA_COND_OK:
1212*2305Sstevel 		cc = CFGA_COND_OK;
1213*2305Sstevel 		break;
1214*2305Sstevel 	case SYSC_CFGA_COND_FAILING:
1215*2305Sstevel 		cc = CFGA_COND_FAILING;
1216*2305Sstevel 		break;
1217*2305Sstevel 	case SYSC_CFGA_COND_FAILED:
1218*2305Sstevel 		cc = CFGA_COND_FAILED;
1219*2305Sstevel 		break;
1220*2305Sstevel 	case SYSC_CFGA_COND_UNUSABLE:
1221*2305Sstevel 		cc = CFGA_COND_UNUSABLE;
1222*2305Sstevel 		break;
1223*2305Sstevel 	case SYSC_CFGA_COND_UNKNOWN:
1224*2305Sstevel 	default:
1225*2305Sstevel 		cc = CFGA_COND_UNKNOWN;
1226*2305Sstevel 		break;
1227*2305Sstevel 	}
1228*2305Sstevel 
1229*2305Sstevel 	return (cc);
1230*2305Sstevel }
1231*2305Sstevel 
1232*2305Sstevel static char *
type_str(enum board_type type)1233*2305Sstevel type_str(enum board_type type)
1234*2305Sstevel {
1235*2305Sstevel 	char *type_str;
1236*2305Sstevel 
1237*2305Sstevel 	switch (type) {
1238*2305Sstevel 	case MEM_BOARD:
1239*2305Sstevel 		type_str = cfga_str(BD_MEM);
1240*2305Sstevel 		break;
1241*2305Sstevel 	case CPU_BOARD:
1242*2305Sstevel 		type_str = cfga_str(BD_CPU);
1243*2305Sstevel 		break;
1244*2305Sstevel 	case IO_2SBUS_BOARD:
1245*2305Sstevel 		type_str = cfga_str(BD_IO_2SBUS);
1246*2305Sstevel 		break;
1247*2305Sstevel 	case IO_SBUS_FFB_BOARD:
1248*2305Sstevel 		type_str = cfga_str(BD_IO_SBUS_FFB);
1249*2305Sstevel 		break;
1250*2305Sstevel 	case IO_PCI_BOARD:
1251*2305Sstevel 		type_str = cfga_str(BD_IO_PCI);
1252*2305Sstevel 		break;
1253*2305Sstevel 	case DISK_BOARD:
1254*2305Sstevel 		type_str = cfga_str(BD_DISK);
1255*2305Sstevel 		break;
1256*2305Sstevel 	case IO_2SBUS_SOCPLUS_BOARD:
1257*2305Sstevel 		type_str = cfga_str(BD_IO_2SBUS_SOCPLUS);
1258*2305Sstevel 		break;
1259*2305Sstevel 	case IO_SBUS_FFB_SOCPLUS_BOARD:
1260*2305Sstevel 		type_str = cfga_str(BD_IO_SBUS_FFB_SOCPLUS);
1261*2305Sstevel 		break;
1262*2305Sstevel 	case UNKNOWN_BOARD:
1263*2305Sstevel 	default:
1264*2305Sstevel 		type_str = cfga_str(BD_UNKNOWN);
1265*2305Sstevel 		break;
1266*2305Sstevel 	}
1267*2305Sstevel 	return (type_str);
1268*2305Sstevel }
1269*2305Sstevel 
1270*2305Sstevel static void
info_set(sysc_cfga_stat_t * sc,cfga_info_t info,int disabled)1271*2305Sstevel info_set(sysc_cfga_stat_t *sc, cfga_info_t info, int disabled)
1272*2305Sstevel {
1273*2305Sstevel 	int i;
1274*2305Sstevel 	struct cpu_info *cpu;
1275*2305Sstevel 	union bd_un *bd = &sc->bd;
1276*2305Sstevel 
1277*2305Sstevel 	*info = NULL;
1278*2305Sstevel 
1279*2305Sstevel 	switch (sc->type) {
1280*2305Sstevel 	case CPU_BOARD:
1281*2305Sstevel 		for (i = 0, cpu = bd->cpu; i < 2; i++, cpu++) {
1282*2305Sstevel 			if (cpu->cpu_speed > 1) {
1283*2305Sstevel 				info += sprintf(info, "cpu %d: ", i);
1284*2305Sstevel 				info += sprintf(info, "%3d MHz ",
1285*2305Sstevel 						cpu->cpu_speed);
1286*2305Sstevel 				if (cpu->cache_size)
1287*2305Sstevel 					info += sprintf(info, "%0.1fM ",
1288*2305Sstevel 						(float)cpu->cache_size /
1289*2305Sstevel 						(float)(1024 * 1024));
1290*2305Sstevel 			}
1291*2305Sstevel 		}
1292*2305Sstevel 		break;
1293*2305Sstevel 	case IO_SBUS_FFB_BOARD:
1294*2305Sstevel 		switch (bd->io2.ffb_size) {
1295*2305Sstevel 		case FFB_SINGLE:
1296*2305Sstevel 			info += sprintf(info, "single buffered ffb   ");
1297*2305Sstevel 			break;
1298*2305Sstevel 		case FFB_DOUBLE:
1299*2305Sstevel 			info += sprintf(info, "double buffered ffb   ");
1300*2305Sstevel 			break;
1301*2305Sstevel 		case FFB_NOT_FOUND:
1302*2305Sstevel #ifdef FFB_DR_SUPPORT
1303*2305Sstevel 			info += sprintf(info, "no ffb installed   ");
1304*2305Sstevel #endif
1305*2305Sstevel 			break;
1306*2305Sstevel 		default:
1307*2305Sstevel 			info += sprintf(info, "illegal ffb size   ");
1308*2305Sstevel 			break;
1309*2305Sstevel 		}
1310*2305Sstevel 		break;
1311*2305Sstevel 	case DISK_BOARD:
1312*2305Sstevel 		for (i = 0; i < 2; i++)
1313*2305Sstevel 			if (bd->dsk.disk_pres[i])
1314*2305Sstevel 				info += sprintf(info, "target: %2d ",
1315*2305Sstevel 						bd->dsk.disk_id[i]);
1316*2305Sstevel 			else
1317*2305Sstevel 				info += sprintf(info, "no disk   ");
1318*2305Sstevel 		break;
1319*2305Sstevel 	}
1320*2305Sstevel 
1321*2305Sstevel 	if (disabled)
1322*2305Sstevel 		info += sprintf(info, "disabled at boot   ");
1323*2305Sstevel 
1324*2305Sstevel 	if (sc->no_detach)
1325*2305Sstevel 		info += sprintf(info, "non-detachable   ");
1326*2305Sstevel 
1327*2305Sstevel 	if (sc->plus_board)
1328*2305Sstevel 		info += sprintf(info, "100 MHz capable   ");
1329*2305Sstevel }
1330*2305Sstevel 
1331*2305Sstevel static void
sysc_cvt(sysc_cfga_stat_t * sc,cfga_stat_data_t * cs,int disabled)1332*2305Sstevel sysc_cvt(sysc_cfga_stat_t *sc, cfga_stat_data_t *cs, int disabled)
1333*2305Sstevel {
1334*2305Sstevel 	(void) strcpy(cs->ap_type, type_str(sc->type));
1335*2305Sstevel 	cs->ap_r_state = rstate_cvt(sc->rstate);
1336*2305Sstevel 	cs->ap_o_state = ostate_cvt(sc->ostate);
1337*2305Sstevel 	cs->ap_cond = cond_cvt(sc->condition);
1338*2305Sstevel 	cs->ap_busy = (cfga_busy_t)sc->in_transition;
1339*2305Sstevel 	cs->ap_status_time = sc->last_change;
1340*2305Sstevel 	info_set(sc, cs->ap_info, disabled);
1341*2305Sstevel 	cs->ap_log_id[0] = NULL;
1342*2305Sstevel 	cs->ap_phys_id[0] = NULL;
1343*2305Sstevel }
1344*2305Sstevel 
1345*2305Sstevel /*ARGSUSED*/
1346*2305Sstevel cfga_err_t
cfga_list(const char * ap_id,cfga_stat_data_t ** ap_list,int * nlist,const char * options,char ** errstring)1347*2305Sstevel cfga_list(
1348*2305Sstevel 	const char *ap_id,
1349*2305Sstevel 	cfga_stat_data_t **ap_list,
1350*2305Sstevel 	int *nlist,
1351*2305Sstevel 	const char *options,
1352*2305Sstevel 	char **errstring)
1353*2305Sstevel {
1354*2305Sstevel 	int i;
1355*2305Sstevel 	cfga_err_t rc;
1356*2305Sstevel 	sysc_cfga_stat_t *sc;
1357*2305Sstevel 	cfga_stat_data_t *cs;
1358*2305Sstevel 
1359*2305Sstevel 	if (errstring != NULL)
1360*2305Sstevel 		*errstring = NULL;
1361*2305Sstevel 
1362*2305Sstevel 	rc = CFGA_ERROR;
1363*2305Sstevel 
1364*2305Sstevel 	if (ap_idx(ap_id) == -1)
1365*2305Sstevel 		cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
1366*2305Sstevel 	else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
1367*2305Sstevel 		cfga_err(NULL, errstring, CMD_LIST, 0);
1368*2305Sstevel 	else if (!(cs = (cfga_stat_data_t *)malloc(MAX_BOARDS * sizeof (*cs))))
1369*2305Sstevel 		cfga_err(NULL, errstring, CMD_LIST, 0);
1370*2305Sstevel 	else {
1371*2305Sstevel 		*ap_list = cs;
1372*2305Sstevel 
1373*2305Sstevel 		for (*nlist = 0, i = 0; i < MAX_BOARDS; i++, sc++) {
1374*2305Sstevel 			if (sc->board == -1)
1375*2305Sstevel 				continue;
1376*2305Sstevel 			sysc_cvt(sc, cs++, 0); /* XXX - disable */
1377*2305Sstevel 			(*nlist)++;
1378*2305Sstevel 		}
1379*2305Sstevel 
1380*2305Sstevel 		rc = CFGA_OK;
1381*2305Sstevel 	}
1382*2305Sstevel 
1383*2305Sstevel 	return (rc);
1384*2305Sstevel }
1385*2305Sstevel 
1386*2305Sstevel /*ARGSUSED*/
1387*2305Sstevel cfga_err_t
cfga_stat(const char * ap_id,struct cfga_stat_data * cs,const char * options,char ** errstring)1388*2305Sstevel cfga_stat(
1389*2305Sstevel 	const char *ap_id,
1390*2305Sstevel 	struct cfga_stat_data *cs,
1391*2305Sstevel 	const char *options,
1392*2305Sstevel 	char **errstring)
1393*2305Sstevel {
1394*2305Sstevel 	cfga_err_t rc;
1395*2305Sstevel 	int idx;
1396*2305Sstevel 	int err;
1397*2305Sstevel 	int opterr;
1398*2305Sstevel 	int disable;
1399*2305Sstevel 	int disabled;
1400*2305Sstevel 	char *dlist;
1401*2305Sstevel 	sysc_cfga_stat_t *sc;
1402*2305Sstevel 
1403*2305Sstevel 	if (errstring != NULL)
1404*2305Sstevel 		*errstring = NULL;
1405*2305Sstevel 
1406*2305Sstevel 	rc = CFGA_ERROR;
1407*2305Sstevel 
1408*2305Sstevel 	if (options && options[0]) {
1409*2305Sstevel 		disable = 0;
1410*2305Sstevel 		if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
1411*2305Sstevel 			disable++;
1412*2305Sstevel 		else if (strcmp(options, cfga_str(OPT_ENABLE))) {
1413*2305Sstevel 			cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
1414*2305Sstevel 			return (rc);
1415*2305Sstevel 		}
1416*2305Sstevel 	}
1417*2305Sstevel 
1418*2305Sstevel 	if ((idx = ap_idx(ap_id)) == -1)
1419*2305Sstevel 		cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
1420*2305Sstevel 	else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
1421*2305Sstevel 		cfga_err(NULL, errstring, CMD_GETSTAT, 0);
1422*2305Sstevel 	else {
1423*2305Sstevel 		opterr = dlist_find(idx, &dlist, &disabled);
1424*2305Sstevel 		sysc_cvt(sc + idx, cs, disabled);
1425*2305Sstevel 
1426*2305Sstevel 		rc = CFGA_OK;
1427*2305Sstevel 
1428*2305Sstevel 		if (options && options[0] && ((opterr != 0) ||
1429*2305Sstevel 			((opterr = dlist_update(idx, disable, dlist, NULL, 0))
1430*2305Sstevel 			!= 0))) {
1431*2305Sstevel 				err = disable ? OPT_DISABLE : OPT_ENABLE;
1432*2305Sstevel 				cfga_err(NULL, errstring, err, opterr, 0);
1433*2305Sstevel 		}
1434*2305Sstevel 	}
1435*2305Sstevel 
1436*2305Sstevel 	return (rc);
1437*2305Sstevel }
1438*2305Sstevel 
1439*2305Sstevel /*ARGSUSED*/
1440*2305Sstevel cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)1441*2305Sstevel cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1442*2305Sstevel {
1443*2305Sstevel 	int help = 0;
1444*2305Sstevel 
1445*2305Sstevel 	if (options) {
1446*2305Sstevel 		if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
1447*2305Sstevel 			help = HELP_DISABLE;
1448*2305Sstevel 		else if (strcmp(options, cfga_str(OPT_ENABLE)) == 0)
1449*2305Sstevel 			help = HELP_ENABLE;
1450*2305Sstevel 		else if (strcmp(options, cfga_str(CMD_INSERT)) == 0)
1451*2305Sstevel 			help = HELP_INSERT;
1452*2305Sstevel 		else if (strcmp(options, cfga_str(CMD_REMOVE)) == 0)
1453*2305Sstevel 			help = HELP_REMOVE;
1454*2305Sstevel 		else if (strcmp(options, cfga_str(CMD_QUIESCE)) == 0)
1455*2305Sstevel 			help = HELP_QUIESCE;
1456*2305Sstevel 		else
1457*2305Sstevel 			help = HELP_UNKNOWN;
1458*2305Sstevel 	}
1459*2305Sstevel 
1460*2305Sstevel 	if (help)  {
1461*2305Sstevel 		if (help == HELP_UNKNOWN)
1462*2305Sstevel 			cfga_msg(msgp, help, options, 0);
1463*2305Sstevel 		else
1464*2305Sstevel 			cfga_msg(msgp, help, 0);
1465*2305Sstevel 	} else {
1466*2305Sstevel 		cfga_msg(msgp, HELP_HEADER, 0);
1467*2305Sstevel 		cfga_msg(msgp, HELP_DISABLE, 0);
1468*2305Sstevel 		cfga_msg(msgp, HELP_ENABLE, 0);
1469*2305Sstevel 		cfga_msg(msgp, HELP_INSERT, 0);
1470*2305Sstevel 		cfga_msg(msgp, HELP_REMOVE, 0);
1471*2305Sstevel 		cfga_msg(msgp, HELP_QUIESCE, 0);
1472*2305Sstevel 		cfga_msg(msgp, HELP_SET_COND, 0);
1473*2305Sstevel 	}
1474*2305Sstevel 
1475*2305Sstevel 	return (CFGA_OK);
1476*2305Sstevel }
1477*2305Sstevel 
1478*2305Sstevel /*
1479*2305Sstevel  * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
1480*2305Sstevel  */
1481