xref: /onnv-gate/usr/src/lib/cfgadm_plugins/ac/common/mema.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 <stdlib.h>
31*2305Sstevel #include <unistd.h>
32*2305Sstevel #include <ctype.h>
33*2305Sstevel #include <fcntl.h>
34*2305Sstevel #include <signal.h>
35*2305Sstevel #include <string.h>
36*2305Sstevel #include <locale.h>
37*2305Sstevel #include <errno.h>
38*2305Sstevel #include <assert.h>
39*2305Sstevel #include <sys/dditypes.h>
40*2305Sstevel #include <sys/param.h>
41*2305Sstevel #include <sys/obpdefs.h>
42*2305Sstevel #include <sys/fhc.h>
43*2305Sstevel #include <sys/sysctrl.h>
44*2305Sstevel #include <sys/ac.h>
45*2305Sstevel #include <sys/spitregs.h>
46*2305Sstevel #include <config_admin.h>
47*2305Sstevel #include "mema_util.h"
48*2305Sstevel #include "mema_test.h"
49*2305Sstevel #include "mema_prom.h"
50*2305Sstevel 
51*2305Sstevel #ifdef	DEBUG
52*2305Sstevel #define	DBG	(void) printf
53*2305Sstevel #define	DBG1	(void) printf
54*2305Sstevel #define	DBG3	(void) printf
55*2305Sstevel #define	DBG4	(void) printf
56*2305Sstevel #else
57*2305Sstevel #define	DBG(a, b)
58*2305Sstevel #define	DBG1(a)
59*2305Sstevel #define	DBG3(a, b, c)
60*2305Sstevel #define	DBG4(a, b, c, d)
61*2305Sstevel #endif
62*2305Sstevel 
63*2305Sstevel #ifndef P_DER_UE
64*2305Sstevel /*
65*2305Sstevel  * <sys/spitregs.h> has these defines inside 'ifdef _KERNEL' at the
66*2305Sstevel  * time of writing.  Re-define here if that is still the case.
67*2305Sstevel  */
68*2305Sstevel 
69*2305Sstevel #define	P_DER_UE	0x00000000000000200ULL	/* UE has occurred */
70*2305Sstevel #define	P_DER_CE	0x00000000000000100ULL	/* CE has occurred */
71*2305Sstevel #define	P_DER_E_SYND	0x000000000000000FFULL	/* SYND<7:0>: ECC syndrome */
72*2305Sstevel #endif /* ! P_DER_UE */
73*2305Sstevel 
74*2305Sstevel #define	DEV_DEBUG
75*2305Sstevel #ifdef DEV_DEBUG
76*2305Sstevel #include <stdio.h>
77*2305Sstevel #include <stdlib.h>
78*2305Sstevel 
79*2305Sstevel static FILE *debug_fp;
80*2305Sstevel static int debugging(void);
81*2305Sstevel static void dump_ioctl(int, void *);
82*2305Sstevel static void dump_ioctl_res(int, void *, int, int);
83*2305Sstevel #else /* DEV_DEBUG */
84*2305Sstevel #define	dump_ioctl(CMD, ARG)
85*2305Sstevel #define	dump_ioctl_res(CMD, ARG, RET, ERRNO)
86*2305Sstevel #endif /* DEV_DEBUG */
87*2305Sstevel 
88*2305Sstevel typedef struct {
89*2305Sstevel 	uint_t   board;
90*2305Sstevel 	uint_t   bank;
91*2305Sstevel } mema_bank_t;
92*2305Sstevel 
93*2305Sstevel static char *mema_opts[] = {
94*2305Sstevel #define	OPT_BOOT_DISABLE	0
95*2305Sstevel 	"disable-at-boot",
96*2305Sstevel #define	OPT_BOOT_ENABLE		1
97*2305Sstevel 	"enable-at-boot",
98*2305Sstevel #define	OPT_TIMEOUT		2
99*2305Sstevel 	"timeout",
100*2305Sstevel 	NULL
101*2305Sstevel };
102*2305Sstevel 
103*2305Sstevel #define	OPT_NEEDS_VALUE(O)	((O) == OPT_TIMEOUT)
104*2305Sstevel 
105*2305Sstevel #define	MAX_OPT_LENGTH		(sizeof ("disable-at-boot"))
106*2305Sstevel 
107*2305Sstevel /*
108*2305Sstevel  * For each function there is an array of opt_control structures giving
109*2305Sstevel  * the valid options.  The array is terminated by an element with the
110*2305Sstevel  * subopt field set to -1.  The group field is used to identify
111*2305Sstevel  * mutually exclusive options, with zero meaning no grouping.
112*2305Sstevel  */
113*2305Sstevel struct opt_control {
114*2305Sstevel 	int		subopt;
115*2305Sstevel 	int		group;
116*2305Sstevel };
117*2305Sstevel 
118*2305Sstevel /*
119*2305Sstevel  * Returned set of options.
120*2305Sstevel  * If the option takes a value, it will be set in 'val'
121*2305Sstevel  * if the corresponding bit is set in 'bits' is set,
122*2305Sstevel  * otherwise the pointer in 'val' is undefined.
123*2305Sstevel  */
124*2305Sstevel #define	OPT_VAL_ARRAY_SIZE	32	/* # bits in 'bits' */
125*2305Sstevel typedef struct {
126*2305Sstevel 	unsigned int	bits;
127*2305Sstevel 	char		*val[OPT_VAL_ARRAY_SIZE];
128*2305Sstevel } option_set_t;
129*2305Sstevel 
130*2305Sstevel #define	OPTSET_INIT(S)		((S).bits = 0)
131*2305Sstevel #define	_OPT_TO_BIT(O)		(1 << (O))
132*2305Sstevel #define	OPTSET_SET_VAL(S, O, V)	((S).bits |= _OPT_TO_BIT(O), \
133*2305Sstevel 				(S).val[(O)] = (V))
134*2305Sstevel #define	OPTSET_TEST(S, O)	(((S).bits & _OPT_TO_BIT(O)) != 0)
135*2305Sstevel #define	OPTSET_VAL(S, O)	((S).val[(O)])
136*2305Sstevel #define	OPTSET_IS_EMPTY(S)	((S).bits == 0)
137*2305Sstevel 
138*2305Sstevel static option_set_t process_options(const char *, struct opt_control *,
139*2305Sstevel 	int *, char **);
140*2305Sstevel 
141*2305Sstevel static struct opt_control add_opts[] = {
142*2305Sstevel 	{OPT_BOOT_ENABLE, 1},
143*2305Sstevel 	{OPT_BOOT_DISABLE, 1},
144*2305Sstevel 	{-1, 0}
145*2305Sstevel };
146*2305Sstevel 
147*2305Sstevel static struct opt_control del_opts[] = {
148*2305Sstevel 	{OPT_BOOT_ENABLE, 1},
149*2305Sstevel 	{OPT_BOOT_DISABLE, 1},
150*2305Sstevel 	{OPT_TIMEOUT, 2},
151*2305Sstevel 	{-1, 0}
152*2305Sstevel };
153*2305Sstevel 
154*2305Sstevel static struct opt_control stat_opts[] = {
155*2305Sstevel 	{OPT_BOOT_ENABLE, 1},
156*2305Sstevel 	{OPT_BOOT_DISABLE, 1},
157*2305Sstevel 	{-1, 0}
158*2305Sstevel };
159*2305Sstevel 
160*2305Sstevel #if !defined(TEXT_DOMAIN)
161*2305Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
162*2305Sstevel #endif
163*2305Sstevel 
164*2305Sstevel static const char still_testing[] = "bank %s being tested by process %d";
165*2305Sstevel static const char no_value[] = "sub-option \"%s\" does not take a value";
166*2305Sstevel static const char missing_value[] = "sub-option \"%s\" needs a value";
167*2305Sstevel static const char conflict_opt[] = "sub-option \"%s\" conflicts with \"%s\"";
168*2305Sstevel static const char unk_subopt[] = "sub-option \"%s\" unknown\n"
169*2305Sstevel 	"choose from: %s";
170*2305Sstevel static const char not_valid[] =
171*2305Sstevel 	"sub-option \"%s\" not valid for this operation\n"
172*2305Sstevel 	"choose from: %s";
173*2305Sstevel static const char timeout_notnum[] =
174*2305Sstevel 	"timeout value not a positive integer \"%s\"";
175*2305Sstevel static const char calloc_fail[] = "memory allocation failed (%d*%d bytes)";
176*2305Sstevel static const char unk_test[] = "test \"%s\" unknown\n"
177*2305Sstevel 	"choose from: %s";
178*2305Sstevel static const char dup_test[] = "more than one test type specified (\"%s\")";
179*2305Sstevel static const char dup_num[] = "option specified more than once (\"%s\")";
180*2305Sstevel static const char no_num[] = "invalid number specified for max_errors(\"%s\")";
181*2305Sstevel static const char mtest_rw_error[] = "memory test read/write error";
182*2305Sstevel static const char mtest_lib_error[] = "memory test library error";
183*2305Sstevel static const char dlist_invalid[] = "invalid disabled-memory-list";
184*2305Sstevel static const char dlist_write_failed[] = "disabled-memory-list write failed";
185*2305Sstevel static const char mtest_unknown_error[] = "unknown memory test error";
186*2305Sstevel static const char ap_invalid[] = "invalid attachment point: %s";
187*2305Sstevel static const char trans_illegal[] = "illegal transition";
188*2305Sstevel static const char open_failed[] = "open failed: %s: %s";
189*2305Sstevel static const char mema_help[] =	"\nAc specific options:\n";
190*2305Sstevel static const char disable_opts[] = "\t-o disable-at-boot\n";
191*2305Sstevel static const char enable_opts[] = "\t-o enable-at-boot\n";
192*2305Sstevel static const char timeout_opts[] = "\t-o timeout=# (seconds)\n";
193*2305Sstevel static const char test_opts[] =
194*2305Sstevel 	"\t-o {quick, normal, extended},[max_errors=#] -t ap_id [ap_id...]\n";
195*2305Sstevel static const char private_funcs[] = "\t-x relocate-test ap_id [ap_id...]\n";
196*2305Sstevel static const char add_is_disabled[] = "memory is disabled at boot";
197*2305Sstevel static const char add_willbe_disabled[] =
198*2305Sstevel 	"memory will be disabled at boot";
199*2305Sstevel static const char add_disab_err[] = "cannot get memory disabled status";
200*2305Sstevel static const char pfunc_unknown[] = "private function \"%s\" unknown";
201*2305Sstevel 
202*2305Sstevel 
203*2305Sstevel #define	mema_eid(a, b)		(((a) << 8) + (b))
204*2305Sstevel #define	mema_str(i)		mema_strs[(i)]
205*2305Sstevel 
206*2305Sstevel #define	AC_BK_BUSY		0
207*2305Sstevel #define	AC_BK_ID		1
208*2305Sstevel #define	AC_BD_ID		2
209*2305Sstevel #define	AC_BD_TYPE		3
210*2305Sstevel #define	AC_BD_STATE		4
211*2305Sstevel #define	AC_MEM_TEST_ID		5
212*2305Sstevel #define	AC_MEM_TEST_PAR		6
213*2305Sstevel #define	AC_MEM_PERM		7
214*2305Sstevel #define	AC_KPM_CANCELLED	8
215*2305Sstevel #define	AC_KPM_REFUSED		9
216*2305Sstevel #define	AC_KPM_SPAN		10
217*2305Sstevel #define	AC_KPM_DUP		11
218*2305Sstevel #define	AC_KPM_FAULT		12
219*2305Sstevel #define	AC_KPM_RESOURCE		13
220*2305Sstevel #define	AC_KPM_NOTSUP		14
221*2305Sstevel #define	AC_KPM_NOHANDLES	15
222*2305Sstevel #define	AC_KPM_NONRELOC		16
223*2305Sstevel #define	AC_KPM_HANDLE		17
224*2305Sstevel #define	AC_KPM_BUSY		18
225*2305Sstevel #define	AC_KPM_NOTVIABLE	19
226*2305Sstevel #define	AC_KPM_SEQUENCE		20
227*2305Sstevel #define	AC_KPM_NOWORK		21
228*2305Sstevel #define	AC_KPM_NOTFINISHED	22
229*2305Sstevel #define	AC_KPM_NOTRUNNING	23
230*2305Sstevel #define	AC_VMEM			24
231*2305Sstevel #define	CMD_MEM_STAT		25
232*2305Sstevel #define	CMD_MEM_ADD		26
233*2305Sstevel #define	CMD_MEM_DEL		27
234*2305Sstevel #define	CMD_MEM_TEST_START	28
235*2305Sstevel #define	CMD_MEM_TEST_STOP	29
236*2305Sstevel #define	AC_UNKNOWN		30
237*2305Sstevel #define	AC_INTR			31
238*2305Sstevel #define	AC_TIMEOUT		32
239*2305Sstevel #define	CMD_MEM_RELOCTEST	33
240*2305Sstevel #define	AC_DEINTLV		34
241*2305Sstevel 
242*2305Sstevel static char *
243*2305Sstevel mema_strs[] = {
244*2305Sstevel 	"memory bank busy",
245*2305Sstevel 	"invalid memory bank",
246*2305Sstevel 	"invalid board id",
247*2305Sstevel 	"invalid board type",
248*2305Sstevel 	"invalid board state",
249*2305Sstevel 	"invalid memory test id",
250*2305Sstevel 	"invalid memory test parameter(s)",
251*2305Sstevel 	"no write permission",
252*2305Sstevel 	"memory operation cancelled",
253*2305Sstevel 	"memory operation refused",
254*2305Sstevel 	"memory already in use (add)",
255*2305Sstevel 	"memory span duplicate (delete)",
256*2305Sstevel 	"memory access test failed (add)",
257*2305Sstevel 	"some resource was not available",
258*2305Sstevel 	"operation not supported",
259*2305Sstevel 	"cannot allocate any more handles",
260*2305Sstevel 	"non-relocatable pages in span",
261*2305Sstevel 	"bad handle supplied",
262*2305Sstevel 	"memory in span is being deleted",
263*2305Sstevel 	"VM viability test failed",
264*2305Sstevel 	"function called out of sequence",
265*2305Sstevel 	"no memory to delete",
266*2305Sstevel 	"delete processing not finished",
267*2305Sstevel 	"delete processing not running",
268*2305Sstevel 	"insufficient virtual memory",
269*2305Sstevel 	"memory stat failed: %s",
270*2305Sstevel 	"memory add failed: %s",
271*2305Sstevel 	"memory delete failed: %s",
272*2305Sstevel 	"memory test start failed: %s",
273*2305Sstevel 	"memory test stop failed: %s",
274*2305Sstevel 	"unknown error",
275*2305Sstevel 	"memory delete killed",
276*2305Sstevel 	"memory delete timeout",
277*2305Sstevel 	"memory relocate-test failed: %s",
278*2305Sstevel 	"memory cannot be de-interleaved"
279*2305Sstevel };
280*2305Sstevel 
281*2305Sstevel /*
282*2305Sstevel  *	AC_MEM_PERM,		EBADF,   AC_ERR_MEM_PERM
283*2305Sstevel  *	AC_BK_BUSY,		EBUSY,   AC_ERR_MEM_BK
284*2305Sstevel  *	AC_KPM_CANCELLED,	EINTR,   AC_ERR_KPM_CANCELLED
285*2305Sstevel  *	AC_KPM_REFUSED,		EINTR,   AC_ERR_KPM_REFUSED
286*2305Sstevel  *	AC_BK_ID,		EINVAL,  AC_ERR_MEM_BK
287*2305Sstevel  *	AC_BD_ID,		EINVAL,  AC_ERR_BD
288*2305Sstevel  *	AC_BD_TYPE,		EINVAL,  AC_ERR_BD_TYPE
289*2305Sstevel  *	AC_BD_STATE,		EINVAL,  AC_ERR_BD_STATE
290*2305Sstevel  *	AC_MEM_TEST_ID,		EINVAL,  AC_ERR_MEM_TEST
291*2305Sstevel  *	AC_MEM_TEST_PAR,	EINVAL,  AC_ERR_MEM_TEST_PAR
292*2305Sstevel  *	AC_KPM_SPAN,		EINVAL,  AC_ERR_KPM_SPAN
293*2305Sstevel  *	AC_KPM_DUP,		EINVAL,  AC_ERR_KPM_DUP?
294*2305Sstevel  *	AC_KPM_FAULT,		EINVAL,  AC_ERR_KPM_FAULT
295*2305Sstevel  *	AC_KPM_RESOURCE,	EINVAL,  AC_ERR_KPM_RESOURCE
296*2305Sstevel  *	AC_KPM_NOTSUP,		EINVAL,  AC_ERR_KPM_NOTSUP
297*2305Sstevel  *	AC_KPM_NOHANDLES,	EINVAL,  AC_ERR_KPM_NOHANDLES
298*2305Sstevel  *	AC_KPM_NONRELOC,	EINVAL,  AC_ERR_KPM_NONRELOC
299*2305Sstevel  *	AC_KPM_HANDLE,		EINVAL,  AC_ERR_KPM_HANDLE
300*2305Sstevel  *	AC_KPM_BUSY,		EINVAL,  AC_ERR_KPM_BUSY
301*2305Sstevel  *	AC_KPM_NOTVIABLE,	EINVAL,  AC_ERR_KPM_NOTVIABLE
302*2305Sstevel  *	AC_KPM_SEQUENCE,	EINVAL,  AC_ERR_KPM_SEQUENCE
303*2305Sstevel  *	AC_KPM_NOWORK,		EINVAL,  AC_ERR_KPM_NOWORK
304*2305Sstevel  *	AC_KPM_NOTFINISHED,	EINVAL,  AC_ERR_KPM_NOTFINISHED
305*2305Sstevel  *	AC_KPM_NOTRUNNING,	EINVAL,  AC_ERR_KPM_NOTRUNNING
306*2305Sstevel  *	AC_VMEM,		ENOMEM,  AC_ERR_VMEM
307*2305Sstevel  *	AC_INTR,		EINTR,   AC_ERR_INTR
308*2305Sstevel  *	AC_TIMEOUT,		EINTR,   AC_ERR_TIMEOUT
309*2305Sstevel  *	AC_DEINTLV,		EINVAL,  AC_ERR_MEM_DEINTLV
310*2305Sstevel  */
311*2305Sstevel static int
mema_sid(int err,int acerr)312*2305Sstevel mema_sid(int err, int acerr)
313*2305Sstevel {
314*2305Sstevel 	if (acerr == AC_ERR_DEFAULT)
315*2305Sstevel 		return (AC_UNKNOWN);
316*2305Sstevel 
317*2305Sstevel 	switch (mema_eid(err, acerr)) {
318*2305Sstevel 	case mema_eid(EBADF, AC_ERR_MEM_PERM):
319*2305Sstevel 		return (AC_MEM_PERM);
320*2305Sstevel 	case mema_eid(EBUSY, AC_ERR_MEM_BK):
321*2305Sstevel 		return (AC_BK_BUSY);
322*2305Sstevel 	case mema_eid(EINTR, AC_ERR_KPM_CANCELLED):
323*2305Sstevel 		return (AC_KPM_CANCELLED);
324*2305Sstevel 	case mema_eid(EINTR, AC_ERR_KPM_REFUSED):
325*2305Sstevel 		return (AC_KPM_REFUSED);
326*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_MEM_BK):
327*2305Sstevel 		return (AC_BK_ID);
328*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_BD):
329*2305Sstevel 		return (AC_BD_ID);
330*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_BD_TYPE):
331*2305Sstevel 		return (AC_BD_TYPE);
332*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_BD_STATE):
333*2305Sstevel 		return (AC_BD_STATE);
334*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_MEM_TEST):
335*2305Sstevel 		return (AC_MEM_TEST_ID);
336*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_MEM_TEST_PAR):
337*2305Sstevel 		return (AC_MEM_TEST_PAR);
338*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_SPAN):
339*2305Sstevel 		return (AC_KPM_SPAN);
340*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_DUP):
341*2305Sstevel 		return (AC_KPM_DUP);
342*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_FAULT):
343*2305Sstevel 		return (AC_KPM_FAULT);
344*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_RESOURCE):
345*2305Sstevel 		return (AC_KPM_RESOURCE);
346*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTSUP):
347*2305Sstevel 		return (AC_KPM_NOTSUP);
348*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOHANDLES):
349*2305Sstevel 		return (AC_KPM_NOHANDLES);
350*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NONRELOC):
351*2305Sstevel 		return (AC_KPM_NONRELOC);
352*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_HANDLE):
353*2305Sstevel 		return (AC_KPM_HANDLE);
354*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_BUSY):
355*2305Sstevel 		return (AC_KPM_BUSY);
356*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTVIABLE):
357*2305Sstevel 		return (AC_KPM_NOTVIABLE);
358*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_SEQUENCE):
359*2305Sstevel 		return (AC_KPM_SEQUENCE);
360*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOWORK):
361*2305Sstevel 		return (AC_KPM_NOWORK);
362*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTFINISHED):
363*2305Sstevel 		return (AC_KPM_NOTFINISHED);
364*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTRUNNING):
365*2305Sstevel 		return (AC_KPM_NOTRUNNING);
366*2305Sstevel 	case mema_eid(ENOMEM, AC_ERR_VMEM):
367*2305Sstevel 		return (AC_VMEM);
368*2305Sstevel 	case mema_eid(EINTR, AC_ERR_INTR):
369*2305Sstevel 		return (AC_INTR);
370*2305Sstevel 	case mema_eid(EINTR, AC_ERR_TIMEOUT):
371*2305Sstevel 		return (AC_TIMEOUT);
372*2305Sstevel 	case mema_eid(EINVAL, AC_ERR_MEM_DEINTLV):
373*2305Sstevel 		return (AC_DEINTLV);
374*2305Sstevel 	default:
375*2305Sstevel 		break;
376*2305Sstevel 	}
377*2305Sstevel 
378*2305Sstevel 	return (AC_UNKNOWN);
379*2305Sstevel }
380*2305Sstevel 
381*2305Sstevel static void
mema_err(ac_cfga_cmd_t * ac,int ret_errno,char ** errstring,int cmd)382*2305Sstevel mema_err(ac_cfga_cmd_t *ac, int ret_errno, char **errstring, int cmd)
383*2305Sstevel {
384*2305Sstevel 	char *cname = mema_str(cmd);
385*2305Sstevel 	char *syserr;
386*2305Sstevel 	char syserr_num[20];
387*2305Sstevel 
388*2305Sstevel 	if (ac) {
389*2305Sstevel 		syserr = mema_str(mema_sid(ret_errno, ac->errtype));
390*2305Sstevel 		syserr = dgettext(TEXT_DOMAIN, syserr);
391*2305Sstevel 	} else {
392*2305Sstevel 		syserr = strerror(ret_errno);
393*2305Sstevel 		/* strerror() does its own gettext(). */
394*2305Sstevel 		if (syserr == NULL) {
395*2305Sstevel 			(void) sprintf(syserr_num, "errno=%d", errno);
396*2305Sstevel 			syserr = syserr_num;
397*2305Sstevel 		}
398*2305Sstevel 	}
399*2305Sstevel 
400*2305Sstevel 	__fmt_errstring(errstring, strlen(syserr),
401*2305Sstevel 	    dgettext(TEXT_DOMAIN, cname), syserr);
402*2305Sstevel }
403*2305Sstevel 
404*2305Sstevel static void
mema_cmd_init(ac_cfga_cmd_t * ac,void * cmd,char * outputstr,int force)405*2305Sstevel mema_cmd_init(ac_cfga_cmd_t *ac, void *cmd, char *outputstr, int force)
406*2305Sstevel {
407*2305Sstevel 	(void) memset((void *)ac, 0, sizeof (*ac));
408*2305Sstevel 
409*2305Sstevel 	ac->errtype = AC_ERR_DEFAULT;
410*2305Sstevel 	ac->private = cmd;
411*2305Sstevel 	ac->force = force;
412*2305Sstevel 	ac->outputstr = outputstr;
413*2305Sstevel 
414*2305Sstevel 	(void) memset((void *)outputstr, 0, AC_OUTPUT_LEN);
415*2305Sstevel }
416*2305Sstevel 
417*2305Sstevel static int
ap_bk_idx(const char * ap_id)418*2305Sstevel ap_bk_idx(const char *ap_id)
419*2305Sstevel {
420*2305Sstevel 	int id;
421*2305Sstevel 	char *s;
422*2305Sstevel 	static char *bank = "bank";
423*2305Sstevel 
424*2305Sstevel 	DBG("ap_bk_idx(%s)\n", ap_id);
425*2305Sstevel 
426*2305Sstevel 	if ((s = strstr(ap_id, bank)) == NULL)
427*2305Sstevel 		return (-1);
428*2305Sstevel 	else {
429*2305Sstevel 		int n;
430*2305Sstevel 
431*2305Sstevel 		s += strlen(bank);
432*2305Sstevel 		n = strlen(s);
433*2305Sstevel 
434*2305Sstevel 		DBG3("ap_bk_idx: s=%s, n=%d\n", s, n);
435*2305Sstevel 
436*2305Sstevel 		if ((n != 1) || !isdigit(s[0]))
437*2305Sstevel 			return (-1);
438*2305Sstevel 	}
439*2305Sstevel 
440*2305Sstevel 	id = atoi(s);
441*2305Sstevel 
442*2305Sstevel 	if (id < 0 || id > 1)
443*2305Sstevel 		return (-1);
444*2305Sstevel 
445*2305Sstevel 	DBG3("ap_bk_idx(%s)=%d\n", s, id);
446*2305Sstevel 
447*2305Sstevel 	return (id);
448*2305Sstevel }
449*2305Sstevel 
450*2305Sstevel static cfga_err_t
ap_stat(const char * bank_spec,int * fdp,mema_bank_t * bkp,ac_stat_t * stp,char ** errstring)451*2305Sstevel ap_stat(
452*2305Sstevel 	const char *bank_spec,
453*2305Sstevel 	int *fdp,
454*2305Sstevel 	mema_bank_t *bkp,
455*2305Sstevel 	ac_stat_t *stp,
456*2305Sstevel 	char **errstring)
457*2305Sstevel {
458*2305Sstevel 	int fd;
459*2305Sstevel 	int ret, ret_errno;
460*2305Sstevel 	int bank;
461*2305Sstevel 	mema_bank_t bk;
462*2305Sstevel 	ac_stat_t stat;
463*2305Sstevel 	ac_cfga_cmd_t cmd;
464*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
465*2305Sstevel 
466*2305Sstevel 	if ((bank = ap_bk_idx(bank_spec)) == -1) {
467*2305Sstevel 		__fmt_errstring(errstring, strlen(bank_spec),
468*2305Sstevel 			dgettext(TEXT_DOMAIN, ap_invalid), bank_spec);
469*2305Sstevel 		return (CFGA_ERROR);
470*2305Sstevel 	}
471*2305Sstevel 
472*2305Sstevel 	bk.bank = bank;
473*2305Sstevel 
474*2305Sstevel 	if ((fd = open(bank_spec, ((fdp != NULL) ? O_RDWR : O_RDONLY), 0)) ==
475*2305Sstevel 	    -1) {
476*2305Sstevel 		char *syserr;
477*2305Sstevel 		char syserr_num[20];
478*2305Sstevel 
479*2305Sstevel 		syserr = strerror(errno);
480*2305Sstevel 		if (syserr == NULL) {
481*2305Sstevel 			(void) sprintf(syserr_num, "errno=%d", errno);
482*2305Sstevel 			syserr = syserr_num;
483*2305Sstevel 		}
484*2305Sstevel 		__fmt_errstring(errstring, strlen(syserr) +
485*2305Sstevel 		    strlen(bank_spec),
486*2305Sstevel 		    dgettext(TEXT_DOMAIN, open_failed), bank_spec, syserr);
487*2305Sstevel 		return (CFGA_ERROR);
488*2305Sstevel 	}
489*2305Sstevel 
490*2305Sstevel 	mema_cmd_init(&cmd, &stat, outputstr, 0);
491*2305Sstevel 	dump_ioctl(AC_MEM_STAT, NULL);
492*2305Sstevel 	ret = ioctl(fd, AC_MEM_STAT, &cmd);
493*2305Sstevel 	ret_errno = errno;
494*2305Sstevel 	dump_ioctl_res(AC_MEM_STAT, &stat, ret, ret_errno);
495*2305Sstevel 
496*2305Sstevel 	if (ret == -1) {
497*2305Sstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_STAT);
498*2305Sstevel 		(void) close(fd);
499*2305Sstevel 		return (CFGA_ERROR);
500*2305Sstevel 	}
501*2305Sstevel 
502*2305Sstevel 	if (fdp)
503*2305Sstevel 		*fdp = fd;
504*2305Sstevel 	else
505*2305Sstevel 		(void) close(fd);
506*2305Sstevel 
507*2305Sstevel 	if (stp)
508*2305Sstevel 		*stp = stat;
509*2305Sstevel 
510*2305Sstevel 	if (bkp) {
511*2305Sstevel 		bkp->bank = bk.bank;
512*2305Sstevel 		bkp->board = stat.board;
513*2305Sstevel 	}
514*2305Sstevel 
515*2305Sstevel 	return (CFGA_OK);
516*2305Sstevel }
517*2305Sstevel 
518*2305Sstevel static void
set_disabled_bits(mema_disabled_t * dp,int value)519*2305Sstevel set_disabled_bits(mema_disabled_t *dp, int value)
520*2305Sstevel {
521*2305Sstevel 	if (value == 0)
522*2305Sstevel 		*dp &= ~PROM_MEMORY_DISABLED;
523*2305Sstevel 	else
524*2305Sstevel 		*dp |= PROM_MEMORY_DISABLED;
525*2305Sstevel }
526*2305Sstevel 
527*2305Sstevel static void
set_present_bits(mema_disabled_t * dp,ac_stat_t * asp)528*2305Sstevel set_present_bits(mema_disabled_t *dp, ac_stat_t *asp)
529*2305Sstevel {
530*2305Sstevel 	if (asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED)
531*2305Sstevel 		*dp |= PROM_MEMORY_PRESENT;
532*2305Sstevel 	else
533*2305Sstevel 		*dp &= ~PROM_MEMORY_DISABLED;
534*2305Sstevel }
535*2305Sstevel 
536*2305Sstevel static cfga_err_t
prom_do_options(option_set_t do_option,int board,ac_stat_t * asp,char ** errstring)537*2305Sstevel prom_do_options(
538*2305Sstevel 	option_set_t do_option,
539*2305Sstevel 	int board,
540*2305Sstevel 	ac_stat_t *asp,
541*2305Sstevel 	char **errstring)
542*2305Sstevel {
543*2305Sstevel 	cfga_err_t ret;
544*2305Sstevel 	mema_disabled_t disab;
545*2305Sstevel 
546*2305Sstevel 	if (!prom_read_disabled_list(&disab, board))
547*2305Sstevel 		return (CFGA_ERROR);
548*2305Sstevel 
549*2305Sstevel 	set_present_bits(&disab, asp);
550*2305Sstevel 
551*2305Sstevel 	ret = CFGA_OK;
552*2305Sstevel 
553*2305Sstevel 	if (OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
554*2305Sstevel 		set_disabled_bits(&disab, 0);
555*2305Sstevel 		if (!prom_viable_disabled_list(&disab)) {
556*2305Sstevel 			__fmt_errstring(errstring, 0,
557*2305Sstevel 			    dgettext(TEXT_DOMAIN, dlist_invalid));
558*2305Sstevel 			ret = CFGA_ERROR;
559*2305Sstevel 		} else if (!prom_write_disabled_list(&disab, board)) {
560*2305Sstevel 			__fmt_errstring(errstring, 0,
561*2305Sstevel 			    dgettext(TEXT_DOMAIN, dlist_write_failed));
562*2305Sstevel 			ret = CFGA_ERROR;
563*2305Sstevel 		}
564*2305Sstevel 	} else if (OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
565*2305Sstevel 		set_disabled_bits(&disab, 1);
566*2305Sstevel 		if (!prom_viable_disabled_list(&disab)) {
567*2305Sstevel 			__fmt_errstring(errstring, 0,
568*2305Sstevel 			    dgettext(TEXT_DOMAIN, dlist_invalid));
569*2305Sstevel 			ret = CFGA_ERROR;
570*2305Sstevel 		} else if (!prom_write_disabled_list(&disab, board)) {
571*2305Sstevel 			__fmt_errstring(errstring, 0,
572*2305Sstevel 			    dgettext(TEXT_DOMAIN, dlist_write_failed));
573*2305Sstevel 			ret = CFGA_ERROR;
574*2305Sstevel 		}
575*2305Sstevel 	}
576*2305Sstevel 
577*2305Sstevel 	return (ret);
578*2305Sstevel }
579*2305Sstevel 
580*2305Sstevel static cfga_err_t
mema_add(const char * bank_spec,const char * options,char ** errstring,int force)581*2305Sstevel mema_add(
582*2305Sstevel 	const char *bank_spec,
583*2305Sstevel 	const char *options,
584*2305Sstevel 	char **errstring,
585*2305Sstevel 	int force)
586*2305Sstevel {
587*2305Sstevel 	mema_bank_t bk;
588*2305Sstevel 	int fd, ret, ret_errno;
589*2305Sstevel 	option_set_t do_option;
590*2305Sstevel 	ac_cfga_cmd_t cmd;
591*2305Sstevel 	ac_stat_t stat;
592*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
593*2305Sstevel 
594*2305Sstevel 	ret = 0;
595*2305Sstevel 	do_option = process_options(options, add_opts, &ret, errstring);
596*2305Sstevel 	if (ret != 0) {
597*2305Sstevel 		return (ret);
598*2305Sstevel 	}
599*2305Sstevel 
600*2305Sstevel 	ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
601*2305Sstevel 	if (ret != CFGA_OK)
602*2305Sstevel 		return (ret);
603*2305Sstevel 
604*2305Sstevel 
605*2305Sstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
606*2305Sstevel 	    stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
607*2305Sstevel 		__fmt_errstring(errstring, 0,
608*2305Sstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
609*2305Sstevel 		(void) close(fd);
610*2305Sstevel 		return (CFGA_ERROR);
611*2305Sstevel 	}
612*2305Sstevel 
613*2305Sstevel 	if (!force) {
614*2305Sstevel 		mema_disabled_t disab;
615*2305Sstevel 
616*2305Sstevel 		if (prom_read_disabled_list(&disab, bk.board)) {
617*2305Sstevel 			if (disab != 0 &&
618*2305Sstevel 			    !OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
619*2305Sstevel 				__fmt_errstring(errstring, 0,
620*2305Sstevel 				    dgettext(TEXT_DOMAIN, add_is_disabled));
621*2305Sstevel 				(void) close(fd);
622*2305Sstevel 				return (CFGA_ERROR);
623*2305Sstevel 			}
624*2305Sstevel 			if (disab == 0 &&
625*2305Sstevel 			    OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
626*2305Sstevel 				__fmt_errstring(errstring, 0,
627*2305Sstevel 				    dgettext(TEXT_DOMAIN, add_willbe_disabled));
628*2305Sstevel 				(void) close(fd);
629*2305Sstevel 				return (CFGA_ERROR);
630*2305Sstevel 			}
631*2305Sstevel 		} else {
632*2305Sstevel 			__fmt_errstring(errstring, 0,
633*2305Sstevel 			    dgettext(TEXT_DOMAIN, add_disab_err));
634*2305Sstevel 			(void) close(fd);
635*2305Sstevel 			return (CFGA_ERROR);
636*2305Sstevel 		}
637*2305Sstevel 	}
638*2305Sstevel 
639*2305Sstevel 	mema_cmd_init(&cmd, NULL, outputstr, force);
640*2305Sstevel 	dump_ioctl(AC_MEM_CONFIGURE, NULL);
641*2305Sstevel 	ret = ioctl(fd, AC_MEM_CONFIGURE, &cmd);
642*2305Sstevel 	ret_errno = errno;
643*2305Sstevel 	dump_ioctl_res(AC_MEM_CONFIGURE, NULL, ret, ret_errno);
644*2305Sstevel 	(void) close(fd);
645*2305Sstevel 
646*2305Sstevel 	if (ret == -1) {
647*2305Sstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_ADD);
648*2305Sstevel 		return (CFGA_ERROR);
649*2305Sstevel 	}
650*2305Sstevel 
651*2305Sstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
652*2305Sstevel 
653*2305Sstevel 	return (ret);
654*2305Sstevel }
655*2305Sstevel 
656*2305Sstevel static cfga_err_t
mema_delete(const char * bank_spec,const char * options,char ** errstring,int force)657*2305Sstevel mema_delete(
658*2305Sstevel 	const char *bank_spec,
659*2305Sstevel 	const char *options,
660*2305Sstevel 	char **errstring,
661*2305Sstevel 	int force)
662*2305Sstevel {
663*2305Sstevel 	mema_bank_t bk;
664*2305Sstevel 	int fd, ret, ret_errno;
665*2305Sstevel 	option_set_t do_option;
666*2305Sstevel 	ac_cfga_cmd_t cmd;
667*2305Sstevel 	ac_stat_t stat;
668*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
669*2305Sstevel 	int timeout_secs = -1;	/* Init to 'use default'. */
670*2305Sstevel 
671*2305Sstevel 	ret = 0;
672*2305Sstevel 	do_option = process_options(options, del_opts, &ret, errstring);
673*2305Sstevel 	if (ret != 0) {
674*2305Sstevel 		return (ret);
675*2305Sstevel 	}
676*2305Sstevel 
677*2305Sstevel 	if (OPTSET_TEST(do_option, OPT_TIMEOUT)) {
678*2305Sstevel 		char *to_val;
679*2305Sstevel 		char *ep;
680*2305Sstevel 
681*2305Sstevel 		to_val = OPTSET_VAL(do_option, OPT_TIMEOUT);
682*2305Sstevel 		timeout_secs = (int)strtol(to_val, &ep, 10);
683*2305Sstevel 		if (*ep != '\0' || ep == to_val || timeout_secs < 0) {
684*2305Sstevel 			__fmt_errstring(errstring, strlen(to_val),
685*2305Sstevel 			    dgettext(TEXT_DOMAIN, timeout_notnum), to_val);
686*2305Sstevel 			return (CFGA_ERROR);
687*2305Sstevel 		}
688*2305Sstevel 	}
689*2305Sstevel 
690*2305Sstevel 	ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
691*2305Sstevel 	if (ret != CFGA_OK)
692*2305Sstevel 		return (ret);
693*2305Sstevel 
694*2305Sstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
695*2305Sstevel 	    stat.ostate != SYSC_CFGA_OSTATE_CONFIGURED) {
696*2305Sstevel 		__fmt_errstring(errstring, 0,
697*2305Sstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
698*2305Sstevel 		(void) close(fd);
699*2305Sstevel 		return (CFGA_ERROR);
700*2305Sstevel 	}
701*2305Sstevel 
702*2305Sstevel 	mema_cmd_init(&cmd, NULL, outputstr, force);
703*2305Sstevel 	cmd.arg = timeout_secs;
704*2305Sstevel 	dump_ioctl(AC_MEM_UNCONFIGURE, NULL);
705*2305Sstevel 	ret = ioctl(fd, AC_MEM_UNCONFIGURE, &cmd);
706*2305Sstevel 	ret_errno = errno;
707*2305Sstevel 	dump_ioctl_res(AC_MEM_UNCONFIGURE, NULL, ret, ret_errno);
708*2305Sstevel 	(void) close(fd);
709*2305Sstevel 
710*2305Sstevel 	if (ret == -1) {
711*2305Sstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_DEL);
712*2305Sstevel 		return (CFGA_ERROR);
713*2305Sstevel 	}
714*2305Sstevel 
715*2305Sstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
716*2305Sstevel 
717*2305Sstevel 	return (ret);
718*2305Sstevel }
719*2305Sstevel 
720*2305Sstevel /*ARGSUSED*/
721*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)722*2305Sstevel cfga_change_state(
723*2305Sstevel 	cfga_cmd_t state_change_cmd,
724*2305Sstevel 	const char *ap_id,
725*2305Sstevel 	const char *options,
726*2305Sstevel 	struct cfga_confirm *confp,
727*2305Sstevel 	struct cfga_msg *msgp,
728*2305Sstevel 	char **errstring,
729*2305Sstevel 	cfga_flags_t flags)
730*2305Sstevel {
731*2305Sstevel 	int force;
732*2305Sstevel 	cfga_err_t rc;
733*2305Sstevel 
734*2305Sstevel 	if (errstring != NULL)
735*2305Sstevel 		*errstring = NULL;
736*2305Sstevel 
737*2305Sstevel 	force = flags & CFGA_FLAG_FORCE;
738*2305Sstevel 
739*2305Sstevel 	switch (state_change_cmd) {
740*2305Sstevel 	case CFGA_CMD_CONFIGURE:
741*2305Sstevel 		rc =  mema_add(ap_id, options, errstring, force);
742*2305Sstevel 		break;
743*2305Sstevel 
744*2305Sstevel 	case CFGA_CMD_UNCONFIGURE:
745*2305Sstevel 		rc =  mema_delete(ap_id, options, errstring, force);
746*2305Sstevel 		break;
747*2305Sstevel 
748*2305Sstevel 	default:
749*2305Sstevel 		rc = CFGA_OPNOTSUPP;
750*2305Sstevel 		break;
751*2305Sstevel 	}
752*2305Sstevel 
753*2305Sstevel 	return (rc);
754*2305Sstevel }
755*2305Sstevel 
756*2305Sstevel /*ARGSUSED*/
757*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)758*2305Sstevel cfga_private_func(
759*2305Sstevel 	const char *function,
760*2305Sstevel 	const char *ap_id,
761*2305Sstevel 	const char *options,
762*2305Sstevel 	struct cfga_confirm *confp,
763*2305Sstevel 	struct cfga_msg *msgp,
764*2305Sstevel 	char **errstring,
765*2305Sstevel 	cfga_flags_t flags)
766*2305Sstevel {
767*2305Sstevel 	mema_bank_t bk;
768*2305Sstevel 	ac_stat_t stat;
769*2305Sstevel 	int fd, ret, ret_errno;
770*2305Sstevel 	ac_cfga_cmd_t cmd;
771*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
772*2305Sstevel 
773*2305Sstevel 	if (errstring != NULL)
774*2305Sstevel 		*errstring = NULL;
775*2305Sstevel 
776*2305Sstevel 	ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
777*2305Sstevel 	if (ret != CFGA_OK)
778*2305Sstevel 		return (ret);
779*2305Sstevel 
780*2305Sstevel 	if (strcmp(function, "relocate-test") == 0) {
781*2305Sstevel 		struct ac_memx_relocate_stats rstat;
782*2305Sstevel 
783*2305Sstevel 		mema_cmd_init(&cmd, NULL, outputstr,
784*2305Sstevel 		    (flags & CFGA_FLAG_FORCE));
785*2305Sstevel 		cmd.arg = AC_MEMX_RELOCATE_ALL;
786*2305Sstevel 		cmd.private = &rstat;
787*2305Sstevel 		(void) memset((void *)&rstat, 0, sizeof (rstat));
788*2305Sstevel 		dump_ioctl(AC_MEM_EXERCISE, &cmd);
789*2305Sstevel 		ret = ioctl(fd, AC_MEM_EXERCISE, &cmd);
790*2305Sstevel 		ret_errno = errno;
791*2305Sstevel 		dump_ioctl_res(AC_MEM_EXERCISE, &cmd, ret, ret_errno);
792*2305Sstevel 		(void) close(fd);
793*2305Sstevel 
794*2305Sstevel 		if (ret == -1) {
795*2305Sstevel 			mema_err(&cmd, ret_errno, errstring, CMD_MEM_RELOCTEST);
796*2305Sstevel 			return (CFGA_ERROR);
797*2305Sstevel 		}
798*2305Sstevel 		return (CFGA_OK);
799*2305Sstevel 	}
800*2305Sstevel 
801*2305Sstevel 	__fmt_errstring(errstring, strlen(function),
802*2305Sstevel 	    dgettext(TEXT_DOMAIN, pfunc_unknown), function);
803*2305Sstevel 
804*2305Sstevel 	return (CFGA_ERROR);
805*2305Sstevel }
806*2305Sstevel 
807*2305Sstevel static int
mtest_run(int fd,int test_fun,mema_bank_t * abkp,struct cfga_msg * msgp,char ** errstring,ulong_t max_errors)808*2305Sstevel mtest_run(
809*2305Sstevel 	int fd,
810*2305Sstevel 	int test_fun,
811*2305Sstevel 	mema_bank_t *abkp,
812*2305Sstevel 	struct cfga_msg *msgp,
813*2305Sstevel 	char **errstring,
814*2305Sstevel 	ulong_t max_errors)
815*2305Sstevel {
816*2305Sstevel 	ac_mem_test_start_t test_start;
817*2305Sstevel 	ac_mem_test_stop_t test_stop;
818*2305Sstevel 	struct mtest_handle handle;
819*2305Sstevel 	int ret, ret_errno;
820*2305Sstevel 	int res;
821*2305Sstevel 	ac_cfga_cmd_t cmd;
822*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
823*2305Sstevel 
824*2305Sstevel 	(void) memset((void *)&test_start, 0, sizeof (test_start));
825*2305Sstevel 	mema_cmd_init(&cmd, &test_start, outputstr, 0);
826*2305Sstevel 	dump_ioctl(AC_MEM_TEST_START, &test_start);
827*2305Sstevel 	ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
828*2305Sstevel 	ret_errno = errno;
829*2305Sstevel 	dump_ioctl_res(AC_MEM_TEST_START, &test_start, ret, ret_errno);
830*2305Sstevel 
831*2305Sstevel 	if (ret == -1) {
832*2305Sstevel 		if (ret_errno == ENOTSUP) {
833*2305Sstevel 			mema_err(&cmd, ret_errno, errstring,
834*2305Sstevel 				CMD_MEM_TEST_START);
835*2305Sstevel 			return (CFGA_OPNOTSUPP);
836*2305Sstevel 		}
837*2305Sstevel 		if (ret_errno == EBUSY && test_start.tester_pid > 0) {
838*2305Sstevel 			/*
839*2305Sstevel 			 * Bank appears to be being tested.  Check that
840*2305Sstevel 			 * process 'tester_pid' is still running.
841*2305Sstevel 			 */
842*2305Sstevel 			if (kill(test_start.tester_pid, 0) != -1 ||
843*2305Sstevel 			    errno != ESRCH) {
844*2305Sstevel 				cfga_ap_log_id_t bname;
845*2305Sstevel 
846*2305Sstevel 				/* Process still exists. */
847*2305Sstevel 				(void) sprintf(bname, "board %d bank%d",
848*2305Sstevel 				    abkp->board, abkp->bank);
849*2305Sstevel 				__fmt_errstring(errstring, strlen(bname),
850*2305Sstevel 				    dgettext(TEXT_DOMAIN, still_testing),
851*2305Sstevel 				    bname, test_start.tester_pid);
852*2305Sstevel 				return (CFGA_ERROR);
853*2305Sstevel 			}
854*2305Sstevel 			/*
855*2305Sstevel 			 * Do a test stop and re-try the start.
856*2305Sstevel 			 */
857*2305Sstevel 			(void) memset((void *)&test_stop, 0,
858*2305Sstevel 			    sizeof (test_stop));
859*2305Sstevel 			test_stop.handle = test_start.handle;
860*2305Sstevel 			test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
861*2305Sstevel 			mema_cmd_init(&cmd, &test_stop, outputstr, 0);
862*2305Sstevel 			dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
863*2305Sstevel 			ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
864*2305Sstevel 			ret_errno = errno;
865*2305Sstevel 			dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop,
866*2305Sstevel 			    ret, ret_errno);
867*2305Sstevel 			/*
868*2305Sstevel 			 * Ignore test stop error processing and re-try the
869*2305Sstevel 			 * start.  The error return will be derived from the
870*2305Sstevel 			 * result of start.
871*2305Sstevel 			 */
872*2305Sstevel 			(void) memset((void *)&test_start, 0,
873*2305Sstevel 			    sizeof (test_start));
874*2305Sstevel 			mema_cmd_init(&cmd, &test_start, outputstr, 0);
875*2305Sstevel 			dump_ioctl(AC_MEM_TEST_START, &test_start);
876*2305Sstevel 			ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
877*2305Sstevel 			ret_errno = errno;
878*2305Sstevel 			dump_ioctl_res(AC_MEM_TEST_START, &test_start,
879*2305Sstevel 			    ret, ret_errno);
880*2305Sstevel 		}
881*2305Sstevel 		/* Test return code again to cover the case of a re-try. */
882*2305Sstevel 		if (ret == -1) {
883*2305Sstevel 			mema_err(&cmd, ret_errno, errstring,
884*2305Sstevel 			    CMD_MEM_TEST_START);
885*2305Sstevel 			return (CFGA_ERROR);
886*2305Sstevel 		}
887*2305Sstevel 	}
888*2305Sstevel 	(void) memset((void *)&handle, 0, sizeof (handle));
889*2305Sstevel 	handle.fd = fd;
890*2305Sstevel 	handle.drvhandle = (void *)&test_start;
891*2305Sstevel 	handle.msgp = msgp;
892*2305Sstevel 	handle.bank_size = test_start.bank_size;
893*2305Sstevel 	handle.page_size = test_start.page_size;
894*2305Sstevel 	handle.line_size = test_start.line_size;
895*2305Sstevel 	handle.lines_per_page = test_start.page_size / test_start.line_size;
896*2305Sstevel 	handle.condition = CFGA_COND_UNKNOWN;
897*2305Sstevel 	handle.max_errors = max_errors;
898*2305Sstevel 
899*2305Sstevel 	res = (*mtest_table[test_fun].test_func)(&handle);
900*2305Sstevel 
901*2305Sstevel 	mtest_deallocate_buf_all(&handle);
902*2305Sstevel 
903*2305Sstevel 	/*
904*2305Sstevel 	 * Convert memory test code to MEMA_ code.
905*2305Sstevel 	 */
906*2305Sstevel 	switch (res) {
907*2305Sstevel 	case MTEST_DONE:
908*2305Sstevel 		res = CFGA_OK;
909*2305Sstevel 		break;
910*2305Sstevel 	case MTEST_LIB_ERROR:
911*2305Sstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
912*2305Sstevel 		    mtest_lib_error));
913*2305Sstevel 		res = CFGA_ERROR;
914*2305Sstevel 		break;
915*2305Sstevel 	case MTEST_DEV_ERROR:
916*2305Sstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
917*2305Sstevel 		    mtest_rw_error));
918*2305Sstevel 		res = CFGA_ERROR;
919*2305Sstevel 		break;
920*2305Sstevel 	default:
921*2305Sstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
922*2305Sstevel 		    mtest_unknown_error));
923*2305Sstevel 		res = CFGA_ERROR;
924*2305Sstevel 		assert(0);
925*2305Sstevel 		break;
926*2305Sstevel 	}
927*2305Sstevel 
928*2305Sstevel 	(void) memset((void *)&test_stop, 0, sizeof (test_stop));
929*2305Sstevel 	test_stop.handle = test_start.handle;
930*2305Sstevel 	switch (handle.condition) {
931*2305Sstevel 	case CFGA_COND_OK:
932*2305Sstevel 		test_stop.condition = SYSC_CFGA_COND_OK;
933*2305Sstevel 		break;
934*2305Sstevel 	case CFGA_COND_FAILING:
935*2305Sstevel 		test_stop.condition = SYSC_CFGA_COND_FAILING;
936*2305Sstevel 		break;
937*2305Sstevel 	case CFGA_COND_FAILED:
938*2305Sstevel 		test_stop.condition = SYSC_CFGA_COND_FAILED;
939*2305Sstevel 		break;
940*2305Sstevel 	case CFGA_COND_UNKNOWN:
941*2305Sstevel 		test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
942*2305Sstevel 		break;
943*2305Sstevel 	default:
944*2305Sstevel 		test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
945*2305Sstevel 		assert(0);
946*2305Sstevel 		break;
947*2305Sstevel 	}
948*2305Sstevel 
949*2305Sstevel 	mema_cmd_init(&cmd, &test_stop, outputstr, 0);
950*2305Sstevel 	dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
951*2305Sstevel 	ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
952*2305Sstevel 	ret_errno = errno;
953*2305Sstevel 	dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop, ret, ret_errno);
954*2305Sstevel 	if (ret == -1) {
955*2305Sstevel 		mema_err(&cmd, ret_errno, errstring,
956*2305Sstevel 		    CMD_MEM_TEST_STOP);
957*2305Sstevel 		return (CFGA_ERROR);
958*2305Sstevel 	}
959*2305Sstevel 	return (res);
960*2305Sstevel }
961*2305Sstevel 
962*2305Sstevel #define	DRVHANDLE(H)	(((ac_mem_test_start_t *)(H)->drvhandle)->handle)
963*2305Sstevel 
964*2305Sstevel int
mtest_write(mtest_handle_t handle,void * page_buf,u_longlong_t page_no,uint_t line_offset,uint_t line_count)965*2305Sstevel mtest_write(
966*2305Sstevel 	mtest_handle_t handle,
967*2305Sstevel 	void *page_buf,
968*2305Sstevel 	u_longlong_t page_no,
969*2305Sstevel 	uint_t line_offset,
970*2305Sstevel 	uint_t line_count)
971*2305Sstevel {
972*2305Sstevel 	ac_mem_test_write_t test_write;
973*2305Sstevel 	int fd, ret, ret_errno;
974*2305Sstevel 	ac_cfga_cmd_t cmd;
975*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
976*2305Sstevel 
977*2305Sstevel 	(void) memset((void *)&test_write, 0, sizeof (test_write));
978*2305Sstevel 	fd = handle->fd;
979*2305Sstevel 	test_write.handle = DRVHANDLE(handle);
980*2305Sstevel 	test_write.page_buf = page_buf;
981*2305Sstevel 	test_write.address.page_num = page_no;
982*2305Sstevel 	test_write.address.line_offset = line_offset;
983*2305Sstevel 	if (line_count == 0)
984*2305Sstevel 		test_write.address.line_count = handle->lines_per_page;
985*2305Sstevel 	else
986*2305Sstevel 		test_write.address.line_count = line_count;
987*2305Sstevel 
988*2305Sstevel 	mema_cmd_init(&cmd, &test_write, outputstr, 0);
989*2305Sstevel 	dump_ioctl(AC_MEM_TEST_WRITE, &test_write);
990*2305Sstevel 	ret = ioctl(fd, AC_MEM_TEST_WRITE, &cmd);
991*2305Sstevel 	ret_errno = errno;
992*2305Sstevel 	dump_ioctl_res(AC_MEM_TEST_WRITE, &test_write, ret, ret_errno);
993*2305Sstevel 
994*2305Sstevel 	if (ret == -1)
995*2305Sstevel 		return (-1);
996*2305Sstevel 	return (0);
997*2305Sstevel }
998*2305Sstevel 
999*2305Sstevel int
mtest_read(mtest_handle_t handle,void * page_buf,u_longlong_t page_no,uint_t line_offset,uint_t line_count,struct mtest_error * errp)1000*2305Sstevel mtest_read(
1001*2305Sstevel 	mtest_handle_t handle,
1002*2305Sstevel 	void *page_buf,
1003*2305Sstevel 	u_longlong_t page_no,
1004*2305Sstevel 	uint_t line_offset,
1005*2305Sstevel 	uint_t line_count,
1006*2305Sstevel 	struct mtest_error *errp)
1007*2305Sstevel {
1008*2305Sstevel 	ac_mem_test_read_t test_read;
1009*2305Sstevel 	sunfire_processor_error_regs_t errbuf;
1010*2305Sstevel 	int fd, ret, ret_errno;
1011*2305Sstevel 	ac_cfga_cmd_t cmd;
1012*2305Sstevel 	char outputstr[AC_OUTPUT_LEN];
1013*2305Sstevel 
1014*2305Sstevel 	(void) memset((void *)&test_read, 0, sizeof (test_read));
1015*2305Sstevel 	(void) memset((void *)&errbuf, 0, sizeof (errbuf));
1016*2305Sstevel 	fd = handle->fd;
1017*2305Sstevel 	test_read.handle = DRVHANDLE(handle);
1018*2305Sstevel 	test_read.page_buf = page_buf;
1019*2305Sstevel 	test_read.address.page_num = page_no;
1020*2305Sstevel 	test_read.address.line_offset = line_offset;
1021*2305Sstevel 	test_read.error_buf =  &errbuf;
1022*2305Sstevel 	if (line_count == 0)
1023*2305Sstevel 		test_read.address.line_count = handle->lines_per_page;
1024*2305Sstevel 	else
1025*2305Sstevel 		test_read.address.line_count = line_count;
1026*2305Sstevel 
1027*2305Sstevel 	mema_cmd_init(&cmd, &test_read, outputstr, 0);
1028*2305Sstevel 	dump_ioctl(AC_MEM_TEST_READ, &test_read);
1029*2305Sstevel 	ret = ioctl(fd, AC_MEM_TEST_READ, &cmd);
1030*2305Sstevel 	ret_errno = errno;
1031*2305Sstevel 	dump_ioctl_res(AC_MEM_TEST_READ, &test_read, ret, ret_errno);
1032*2305Sstevel 
1033*2305Sstevel 	if (ret == -1) {
1034*2305Sstevel 		if (ret_errno == EIO) {
1035*2305Sstevel 			/*
1036*2305Sstevel 			 * Special case indicating CE or UE.
1037*2305Sstevel 			 */
1038*2305Sstevel 			if (((errbuf.udbh_error_reg | errbuf.udbl_error_reg) &
1039*2305Sstevel 			    P_DER_UE) != 0)
1040*2305Sstevel 				errp->error_type = MTEST_ERR_UE;
1041*2305Sstevel 			else
1042*2305Sstevel 				errp->error_type = MTEST_ERR_CE;
1043*2305Sstevel 		} else {
1044*2305Sstevel 			return (-1);
1045*2305Sstevel 		}
1046*2305Sstevel 	} else {
1047*2305Sstevel 		errp->error_type = MTEST_ERR_NONE;
1048*2305Sstevel 	}
1049*2305Sstevel 	return (0);
1050*2305Sstevel }
1051*2305Sstevel 
1052*2305Sstevel static char *
subopt_help_str(char * opts[])1053*2305Sstevel subopt_help_str(char *opts[])
1054*2305Sstevel {
1055*2305Sstevel 	char *str;
1056*2305Sstevel 	const char *sep;
1057*2305Sstevel 	int len;
1058*2305Sstevel 	int i, n;
1059*2305Sstevel 	static const char help_sep[] = ", ";
1060*2305Sstevel 	static const char help_nil[] = "???";
1061*2305Sstevel 
1062*2305Sstevel 	len = 0;
1063*2305Sstevel 	n = 0;
1064*2305Sstevel 	for (i = 0; opts[i] != NULL; i++) {
1065*2305Sstevel 		n++;
1066*2305Sstevel 		len += strlen(opts[i]);
1067*2305Sstevel 	}
1068*2305Sstevel 	if (n == 0)
1069*2305Sstevel 		return (strdup(help_nil));
1070*2305Sstevel 	len += (n - 1) * strlen(help_sep);
1071*2305Sstevel 	len++;
1072*2305Sstevel 	str = (char *)malloc(len);
1073*2305Sstevel 	if (str == NULL)
1074*2305Sstevel 		return (NULL);
1075*2305Sstevel 	*str = '\0';
1076*2305Sstevel 	sep = "";
1077*2305Sstevel 	for (i = 0; opts[i] != NULL; i++) {
1078*2305Sstevel 		(void) strcat(str, sep);
1079*2305Sstevel 		(void) strcat(str, opts[i]);
1080*2305Sstevel 		sep = help_sep;
1081*2305Sstevel 	}
1082*2305Sstevel 	return (str);
1083*2305Sstevel }
1084*2305Sstevel 
1085*2305Sstevel /*ARGSUSED*/
1086*2305Sstevel cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)1087*2305Sstevel cfga_test(
1088*2305Sstevel 	const char *ap_id,
1089*2305Sstevel 	const char *options,
1090*2305Sstevel 	struct cfga_msg *msgp,
1091*2305Sstevel 	char **errstring,
1092*2305Sstevel 	cfga_flags_t flags)
1093*2305Sstevel {
1094*2305Sstevel 	mema_bank_t bk;
1095*2305Sstevel 	ac_stat_t stat;
1096*2305Sstevel 	int test_fun = -1;
1097*2305Sstevel 	int fd, ret;
1098*2305Sstevel 	int maxerr_idx;
1099*2305Sstevel 	long max_errors = -1;
1100*2305Sstevel 	char *ret_p;
1101*2305Sstevel 
1102*2305Sstevel 	if (errstring != NULL)
1103*2305Sstevel 		*errstring = NULL;
1104*2305Sstevel 
1105*2305Sstevel 	/*
1106*2305Sstevel 	 * Decode test level and max error number.
1107*2305Sstevel 	 */
1108*2305Sstevel 	if (options != NULL && *options != '\0') {
1109*2305Sstevel 		char **opts;
1110*2305Sstevel 		char *value;
1111*2305Sstevel 		char *cp, *free_cp;
1112*2305Sstevel 		int subopt;
1113*2305Sstevel 
1114*2305Sstevel 		/* getsubopt() modifies the input string, so copy it. */
1115*2305Sstevel 		cp = strdup(options);
1116*2305Sstevel 		if (cp == NULL) {
1117*2305Sstevel 			return (CFGA_LIB_ERROR);
1118*2305Sstevel 		}
1119*2305Sstevel 		free_cp = cp;
1120*2305Sstevel 		opts = mtest_build_opts(&maxerr_idx);
1121*2305Sstevel 		if (opts == NULL) {
1122*2305Sstevel 			free((void *)free_cp);
1123*2305Sstevel 			return (CFGA_LIB_ERROR);
1124*2305Sstevel 		}
1125*2305Sstevel 
1126*2305Sstevel 		while (*cp != '\0') {
1127*2305Sstevel 			subopt = getsubopt(&cp, opts, &value);
1128*2305Sstevel 			if (subopt == -1) {
1129*2305Sstevel 				char *hlp;
1130*2305Sstevel 
1131*2305Sstevel 				hlp = subopt_help_str(opts);
1132*2305Sstevel 				if (hlp != NULL) {
1133*2305Sstevel 					__fmt_errstring(errstring,
1134*2305Sstevel 					strlen(value) + strlen(hlp),
1135*2305Sstevel 					dgettext(TEXT_DOMAIN, unk_test),
1136*2305Sstevel 					value, hlp);
1137*2305Sstevel 					free((void *)hlp);
1138*2305Sstevel 				} else {
1139*2305Sstevel 					__fmt_errstring(errstring, 20,
1140*2305Sstevel 					dgettext(TEXT_DOMAIN, calloc_fail),
1141*2305Sstevel 						strlen(options) + 1, 1);
1142*2305Sstevel 				}
1143*2305Sstevel 				/* Free after printing value. */
1144*2305Sstevel 				free((void *)free_cp);
1145*2305Sstevel 				return (CFGA_ERROR);
1146*2305Sstevel 			}
1147*2305Sstevel 
1148*2305Sstevel 			if (test_fun != -1 && subopt != test_fun &&
1149*2305Sstevel 			    subopt != maxerr_idx) {
1150*2305Sstevel 				__fmt_errstring(errstring,
1151*2305Sstevel 				    strlen(opts[subopt]),
1152*2305Sstevel 				    dgettext(TEXT_DOMAIN, dup_test),
1153*2305Sstevel 				    opts[subopt]);
1154*2305Sstevel 				free((void *)free_cp);
1155*2305Sstevel 				return (CFGA_ERROR);
1156*2305Sstevel 			}
1157*2305Sstevel 
1158*2305Sstevel 			if (subopt < maxerr_idx)
1159*2305Sstevel 				test_fun = subopt;
1160*2305Sstevel 			else {
1161*2305Sstevel 
1162*2305Sstevel 				if (max_errors != -1 && subopt == maxerr_idx) {
1163*2305Sstevel 					__fmt_errstring(errstring,
1164*2305Sstevel 					strlen(opts[subopt]),
1165*2305Sstevel 					dgettext(TEXT_DOMAIN, dup_num),
1166*2305Sstevel 					opts[subopt]);
1167*2305Sstevel 					free((void *)free_cp);
1168*2305Sstevel 					return (CFGA_ERROR);
1169*2305Sstevel 				}
1170*2305Sstevel 
1171*2305Sstevel 				if (value == NULL) {
1172*2305Sstevel 					__fmt_errstring(errstring,
1173*2305Sstevel 					0,
1174*2305Sstevel 					dgettext(TEXT_DOMAIN, no_num),
1175*2305Sstevel 					"");
1176*2305Sstevel 					free((void *)free_cp);
1177*2305Sstevel 					return (CFGA_ERROR);
1178*2305Sstevel 				}
1179*2305Sstevel 
1180*2305Sstevel 				max_errors = strtol(value, &ret_p, 10);
1181*2305Sstevel 				if ((ret_p == value) || (*ret_p != '\0') ||
1182*2305Sstevel 				    (max_errors < 0)) {
1183*2305Sstevel 					__fmt_errstring(errstring,
1184*2305Sstevel 					strlen(value),
1185*2305Sstevel 					dgettext(TEXT_DOMAIN, no_num),
1186*2305Sstevel 					value);
1187*2305Sstevel 					free((void *)free_cp);
1188*2305Sstevel 					return (CFGA_ERROR);
1189*2305Sstevel 				}
1190*2305Sstevel 			}
1191*2305Sstevel 		}
1192*2305Sstevel 		free((void *)free_cp);
1193*2305Sstevel 	}
1194*2305Sstevel 
1195*2305Sstevel 	if (test_fun == -1)
1196*2305Sstevel 		test_fun = MTEST_DEFAULT_TEST;
1197*2305Sstevel 	if (max_errors == -1)
1198*2305Sstevel 		max_errors = MAX_ERRORS;
1199*2305Sstevel 
1200*2305Sstevel 	ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
1201*2305Sstevel 	if (ret != CFGA_OK)
1202*2305Sstevel 		return (ret);
1203*2305Sstevel 
1204*2305Sstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
1205*2305Sstevel 	    stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
1206*2305Sstevel 		__fmt_errstring(errstring, 0,
1207*2305Sstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
1208*2305Sstevel 		(void) close(fd);
1209*2305Sstevel 		return (CFGA_ERROR);
1210*2305Sstevel 	}
1211*2305Sstevel 
1212*2305Sstevel 	ret = mtest_run(fd, test_fun, &bk,
1213*2305Sstevel 	    ((flags & CFGA_FLAG_VERBOSE) != 0) ? msgp : NULL, errstring,
1214*2305Sstevel 	    (ulong_t)max_errors);
1215*2305Sstevel 
1216*2305Sstevel 	(void) close(fd);
1217*2305Sstevel 
1218*2305Sstevel 	return (ret);
1219*2305Sstevel }
1220*2305Sstevel 
1221*2305Sstevel static cfga_stat_t
rstate_cvt(sysc_cfga_rstate_t rs)1222*2305Sstevel rstate_cvt(sysc_cfga_rstate_t rs)
1223*2305Sstevel {
1224*2305Sstevel 	cfga_stat_t cs;
1225*2305Sstevel 
1226*2305Sstevel 	switch (rs) {
1227*2305Sstevel 	case SYSC_CFGA_RSTATE_EMPTY:
1228*2305Sstevel 		cs = CFGA_STAT_EMPTY;
1229*2305Sstevel 		break;
1230*2305Sstevel 	case SYSC_CFGA_RSTATE_DISCONNECTED:
1231*2305Sstevel 		cs = CFGA_STAT_DISCONNECTED;
1232*2305Sstevel 		break;
1233*2305Sstevel 	case SYSC_CFGA_RSTATE_CONNECTED:
1234*2305Sstevel 		cs = CFGA_STAT_CONNECTED;
1235*2305Sstevel 		break;
1236*2305Sstevel 	default:
1237*2305Sstevel 		cs = CFGA_STAT_NONE;
1238*2305Sstevel 		break;
1239*2305Sstevel 	}
1240*2305Sstevel 
1241*2305Sstevel 	return (cs);
1242*2305Sstevel }
1243*2305Sstevel 
1244*2305Sstevel static cfga_stat_t
ostate_cvt(sysc_cfga_ostate_t os)1245*2305Sstevel ostate_cvt(sysc_cfga_ostate_t os)
1246*2305Sstevel {
1247*2305Sstevel 	cfga_stat_t cs;
1248*2305Sstevel 
1249*2305Sstevel 	switch (os) {
1250*2305Sstevel 	case SYSC_CFGA_OSTATE_UNCONFIGURED:
1251*2305Sstevel 		cs = CFGA_STAT_UNCONFIGURED;
1252*2305Sstevel 		break;
1253*2305Sstevel 	case SYSC_CFGA_OSTATE_CONFIGURED:
1254*2305Sstevel 		cs = CFGA_STAT_CONFIGURED;
1255*2305Sstevel 		break;
1256*2305Sstevel 	default:
1257*2305Sstevel 		cs = CFGA_STAT_NONE;
1258*2305Sstevel 		break;
1259*2305Sstevel 	}
1260*2305Sstevel 
1261*2305Sstevel 	return (cs);
1262*2305Sstevel }
1263*2305Sstevel 
1264*2305Sstevel static cfga_cond_t
cond_cvt(sysc_cfga_cond_t sc)1265*2305Sstevel cond_cvt(sysc_cfga_cond_t sc)
1266*2305Sstevel {
1267*2305Sstevel 	cfga_cond_t cc;
1268*2305Sstevel 
1269*2305Sstevel 	switch (sc) {
1270*2305Sstevel 	case SYSC_CFGA_COND_OK:
1271*2305Sstevel 		cc = CFGA_COND_OK;
1272*2305Sstevel 		break;
1273*2305Sstevel 	case SYSC_CFGA_COND_FAILING:
1274*2305Sstevel 		cc = CFGA_COND_FAILING;
1275*2305Sstevel 		break;
1276*2305Sstevel 	case SYSC_CFGA_COND_FAILED:
1277*2305Sstevel 		cc = CFGA_COND_FAILED;
1278*2305Sstevel 		break;
1279*2305Sstevel 	case SYSC_CFGA_COND_UNUSABLE:
1280*2305Sstevel 		cc = CFGA_COND_UNUSABLE;
1281*2305Sstevel 		break;
1282*2305Sstevel 	case SYSC_CFGA_COND_UNKNOWN:
1283*2305Sstevel 	default:
1284*2305Sstevel 		cc = CFGA_COND_UNKNOWN;
1285*2305Sstevel 		break;
1286*2305Sstevel 	}
1287*2305Sstevel 
1288*2305Sstevel 	return (cc);
1289*2305Sstevel }
1290*2305Sstevel 
1291*2305Sstevel static void
info_set(ac_stat_t * asp,mema_bank_t * bkp,cfga_info_t info)1292*2305Sstevel info_set(ac_stat_t *asp, mema_bank_t *bkp, cfga_info_t info)
1293*2305Sstevel {
1294*2305Sstevel 	mema_disabled_t disab;
1295*2305Sstevel 	uint_t board;
1296*2305Sstevel 	uint_t n;
1297*2305Sstevel 	u_longlong_t decode;
1298*2305Sstevel 	uint_t intlv;
1299*2305Sstevel 	char *f;
1300*2305Sstevel 	char *end;
1301*2305Sstevel 
1302*2305Sstevel 	end = &info[sizeof (cfga_info_t)];
1303*2305Sstevel 	*info = NULL;
1304*2305Sstevel 
1305*2305Sstevel 	board = bkp->board;
1306*2305Sstevel 
1307*2305Sstevel 	/* Print the board number in a way that matches the sysctrl AP. */
1308*2305Sstevel 	info += snprintf(info, end - info, "slot%d", board);
1309*2305Sstevel 
1310*2305Sstevel 	if (asp->real_size == 0) {
1311*2305Sstevel 		info += snprintf(info, end - info, " empty");
1312*2305Sstevel 		return;
1313*2305Sstevel 	}
1314*2305Sstevel 
1315*2305Sstevel 	if ((n = asp->real_size) >= 1024) {
1316*2305Sstevel 		n /= 1024;
1317*2305Sstevel 		f = "Gb";
1318*2305Sstevel 	} else
1319*2305Sstevel 		f = "Mb";
1320*2305Sstevel 	info += snprintf(info, end - info, " %d%s", n, f);
1321*2305Sstevel 
1322*2305Sstevel 	if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
1323*2305Sstevel 	    asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
1324*2305Sstevel 	    asp->use_size != asp->real_size) {
1325*2305Sstevel 		if ((n = asp->use_size) >= 1024) {
1326*2305Sstevel 			n /= 1024;
1327*2305Sstevel 			f = "Gb";
1328*2305Sstevel 		} else
1329*2305Sstevel 			f = "Mb";
1330*2305Sstevel 		info += snprintf(info, end - info, " (%d%s used)", n, f);
1331*2305Sstevel 	}
1332*2305Sstevel 
1333*2305Sstevel 	if (bkp->bank == 0)
1334*2305Sstevel 		decode = asp->ac_decode0;
1335*2305Sstevel 	else
1336*2305Sstevel 		decode = asp->ac_decode1;
1337*2305Sstevel 
1338*2305Sstevel 	info += snprintf(info, end - info, " base 0x%llx",
1339*2305Sstevel 	    GRP_REALBASE(decode));
1340*2305Sstevel 
1341*2305Sstevel 	if (bkp->bank == 0)
1342*2305Sstevel 		intlv = INTLV0(asp->ac_memctl);
1343*2305Sstevel 	else
1344*2305Sstevel 		intlv = INTLV1(asp->ac_memctl);
1345*2305Sstevel 
1346*2305Sstevel 	if (intlv != 1)
1347*2305Sstevel 		info += snprintf(info, end - info, " interleaved %u-way",
1348*2305Sstevel 		    intlv);
1349*2305Sstevel 
1350*2305Sstevel 	if (prom_read_disabled_list(&disab, board)) {
1351*2305Sstevel 		if (disab != 0) {
1352*2305Sstevel 			info += snprintf(info, end - info, " disabled at boot");
1353*2305Sstevel 		}
1354*2305Sstevel 
1355*2305Sstevel 	}
1356*2305Sstevel 
1357*2305Sstevel 	if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
1358*2305Sstevel 	    asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
1359*2305Sstevel 	    asp->nonrelocatable)
1360*2305Sstevel 		info += snprintf(info, end - info, " permanent");
1361*2305Sstevel }
1362*2305Sstevel 
1363*2305Sstevel static void
mema_cvt(ac_stat_t * ac,mema_bank_t * bkp,cfga_stat_data_t * cs)1364*2305Sstevel mema_cvt(ac_stat_t *ac, mema_bank_t *bkp, cfga_stat_data_t *cs)
1365*2305Sstevel {
1366*2305Sstevel 	(void) strcpy(cs->ap_type, "memory");
1367*2305Sstevel 	cs->ap_r_state = rstate_cvt(ac->rstate);
1368*2305Sstevel 	cs->ap_o_state = ostate_cvt(ac->ostate);
1369*2305Sstevel 	cs->ap_cond = cond_cvt(ac->condition);
1370*2305Sstevel 	cs->ap_busy = (cfga_busy_t)ac->busy;
1371*2305Sstevel 	cs->ap_status_time = ac->status_time;
1372*2305Sstevel 	info_set(ac, bkp, cs->ap_info);
1373*2305Sstevel 	cs->ap_log_id[0] = NULL;
1374*2305Sstevel 	cs->ap_phys_id[0] = NULL;
1375*2305Sstevel }
1376*2305Sstevel 
1377*2305Sstevel /*ARGSUSED*/
1378*2305Sstevel cfga_err_t
cfga_stat(const char * ap_id,struct cfga_stat_data * cs,const char * options,char ** errstring)1379*2305Sstevel cfga_stat(
1380*2305Sstevel 	const char *ap_id,
1381*2305Sstevel 	struct cfga_stat_data *cs,
1382*2305Sstevel 	const char *options,
1383*2305Sstevel 	char **errstring)
1384*2305Sstevel {
1385*2305Sstevel 	int ret;
1386*2305Sstevel 	mema_bank_t bk;
1387*2305Sstevel 	ac_stat_t stat;
1388*2305Sstevel 	option_set_t do_option;
1389*2305Sstevel 
1390*2305Sstevel 	if (errstring != NULL)
1391*2305Sstevel 		*errstring = NULL;
1392*2305Sstevel 
1393*2305Sstevel 	ret = 0;
1394*2305Sstevel 	do_option = process_options(options, stat_opts, &ret, errstring);
1395*2305Sstevel 	if (ret != 0)
1396*2305Sstevel 		return (ret);
1397*2305Sstevel 
1398*2305Sstevel 	ret = ap_stat(ap_id, NULL, &bk, &stat, errstring);
1399*2305Sstevel 	if (ret != CFGA_OK)
1400*2305Sstevel 		return (ret);
1401*2305Sstevel 
1402*2305Sstevel 	mema_cvt(&stat, &bk, cs);
1403*2305Sstevel 
1404*2305Sstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
1405*2305Sstevel 
1406*2305Sstevel 	return (ret);
1407*2305Sstevel }
1408*2305Sstevel 
1409*2305Sstevel /*ARGSUSED*/
1410*2305Sstevel cfga_err_t
cfga_list(const char * ap_id,cfga_stat_data_t ** ap_list,int * nlist,const char * options,char ** errstring)1411*2305Sstevel cfga_list(
1412*2305Sstevel 	const char *ap_id,
1413*2305Sstevel 	cfga_stat_data_t **ap_list,
1414*2305Sstevel 	int *nlist,
1415*2305Sstevel 	const char *options,
1416*2305Sstevel 	char **errstring)
1417*2305Sstevel {
1418*2305Sstevel 	if (errstring != NULL)
1419*2305Sstevel 		*errstring = NULL;
1420*2305Sstevel 
1421*2305Sstevel 	return (CFGA_NOTSUPP);
1422*2305Sstevel }
1423*2305Sstevel 
1424*2305Sstevel /*
1425*2305Sstevel  * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
1426*2305Sstevel  */
1427*2305Sstevel 
1428*2305Sstevel /*ARGSUSED*/
1429*2305Sstevel cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)1430*2305Sstevel cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1431*2305Sstevel {
1432*2305Sstevel 
1433*2305Sstevel 
1434*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, mema_help);
1435*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, disable_opts);
1436*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, enable_opts);
1437*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, timeout_opts);
1438*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, test_opts);
1439*2305Sstevel 	(*msgp->message_routine)(msgp->appdata_ptr, private_funcs);
1440*2305Sstevel 
1441*2305Sstevel 	return (CFGA_OK);
1442*2305Sstevel }
1443*2305Sstevel 
1444*2305Sstevel #if 0
1445*2305Sstevel static ac_mem_version_t
1446*2305Sstevel get_version(int fd)
1447*2305Sstevel {
1448*2305Sstevel 	ac_mem_version_t ver;
1449*2305Sstevel 	int ret, ret_errno;
1450*2305Sstevel 
1451*2305Sstevel 	ver = 0;
1452*2305Sstevel 	dump_ioctl(AC_MEM_ADMIN_VER, &ver);
1453*2305Sstevel 	ret = ioctl(fd, AC_MEM_ADMIN_VER, &ver);
1454*2305Sstevel 	ret_errno = errno;
1455*2305Sstevel 	dump_ioctl_res(AC_MEM_ADMIN_VER, &ver, ret, ret_errno);
1456*2305Sstevel 	return (ver);
1457*2305Sstevel }
1458*2305Sstevel #endif
1459*2305Sstevel 
1460*2305Sstevel static char *
opt_help_str(struct opt_control * opts)1461*2305Sstevel opt_help_str(struct opt_control *opts)
1462*2305Sstevel {
1463*2305Sstevel 	char *str;
1464*2305Sstevel 	const char *sep;
1465*2305Sstevel 	int len;
1466*2305Sstevel 	int i, n;
1467*2305Sstevel 	static const char help_sep[] = ", ";
1468*2305Sstevel 	static const char help_nil[] = "???";
1469*2305Sstevel 
1470*2305Sstevel 	len = 0;
1471*2305Sstevel 	n = 0;
1472*2305Sstevel 	for (i = 0; opts[i].subopt != -1; i++) {
1473*2305Sstevel 		n++;
1474*2305Sstevel 		len += strlen(mema_opts[opts[i].subopt]);
1475*2305Sstevel 	}
1476*2305Sstevel 	if (n == 0)
1477*2305Sstevel 		return (strdup(help_nil));
1478*2305Sstevel 	len += (n - 1) * strlen(help_sep);
1479*2305Sstevel 	len++;
1480*2305Sstevel 	str = (char *)malloc(len);
1481*2305Sstevel 	if (str == NULL)
1482*2305Sstevel 		return (NULL);
1483*2305Sstevel 	*str = '\0';
1484*2305Sstevel 	sep = "";
1485*2305Sstevel 	for (i = 0; opts[i].subopt != -1; i++) {
1486*2305Sstevel 		(void) strcat(str, sep);
1487*2305Sstevel 		(void) strcat(str, mema_opts[opts[i].subopt]);
1488*2305Sstevel 		sep = help_sep;
1489*2305Sstevel 	}
1490*2305Sstevel 	return (str);
1491*2305Sstevel }
1492*2305Sstevel 
1493*2305Sstevel static option_set_t
process_options(const char * options,struct opt_control * opts,int * retp,char ** errstring)1494*2305Sstevel process_options(
1495*2305Sstevel 	const char *options,
1496*2305Sstevel 	struct opt_control *opts,
1497*2305Sstevel 	int *retp,
1498*2305Sstevel 	char **errstring)
1499*2305Sstevel {
1500*2305Sstevel 	option_set_t opt_set;
1501*2305Sstevel 	char *optcopy, *optcopy_alloc;
1502*2305Sstevel 	char *value;
1503*2305Sstevel 	int subopt;
1504*2305Sstevel 	int subopt_err;
1505*2305Sstevel 	int i;
1506*2305Sstevel 	int group;
1507*2305Sstevel 	int need_value;
1508*2305Sstevel 
1509*2305Sstevel 	OPTSET_INIT(opt_set);
1510*2305Sstevel 
1511*2305Sstevel 	if (options == NULL || *options == '\0') {
1512*2305Sstevel 		return (opt_set);
1513*2305Sstevel 	}
1514*2305Sstevel 
1515*2305Sstevel 	optcopy = optcopy_alloc = strdup(options);
1516*2305Sstevel 	if (optcopy_alloc == NULL) {
1517*2305Sstevel 		__fmt_errstring(errstring, 20,
1518*2305Sstevel 		    dgettext(TEXT_DOMAIN, calloc_fail), strlen(options) + 1, 1);
1519*2305Sstevel 		*retp = CFGA_LIB_ERROR;
1520*2305Sstevel 		return (opt_set);
1521*2305Sstevel 	}
1522*2305Sstevel 
1523*2305Sstevel 	subopt_err = 0;
1524*2305Sstevel 	while (*optcopy != '\0' && subopt_err == 0) {
1525*2305Sstevel 		subopt = getsubopt(&optcopy, mema_opts, &value);
1526*2305Sstevel 		if (subopt == -1) {
1527*2305Sstevel 			char *hlp;
1528*2305Sstevel 
1529*2305Sstevel 			hlp = opt_help_str(opts);
1530*2305Sstevel 			__fmt_errstring(errstring, strlen(value) + strlen(hlp),
1531*2305Sstevel 			    dgettext(TEXT_DOMAIN, unk_subopt), value, hlp);
1532*2305Sstevel 			free((void *)hlp);
1533*2305Sstevel 			subopt_err = 1;
1534*2305Sstevel 			break;
1535*2305Sstevel 		}
1536*2305Sstevel 		for (i = 0; opts[i].subopt != -1; i++) {
1537*2305Sstevel 			if (opts[i].subopt == subopt) {
1538*2305Sstevel 				group = opts[i].group;
1539*2305Sstevel 				break;
1540*2305Sstevel 			}
1541*2305Sstevel 		}
1542*2305Sstevel 		if (opts[i].subopt == -1) {
1543*2305Sstevel 			char *hlp;
1544*2305Sstevel 
1545*2305Sstevel 			hlp = opt_help_str(opts);
1546*2305Sstevel 			__fmt_errstring(errstring,
1547*2305Sstevel 			    MAX_OPT_LENGTH + strlen(hlp),
1548*2305Sstevel 			    dgettext(TEXT_DOMAIN, not_valid),
1549*2305Sstevel 			    mema_opts[subopt], hlp);
1550*2305Sstevel 			free((void *)hlp);
1551*2305Sstevel 			subopt_err = 1;
1552*2305Sstevel 			break;
1553*2305Sstevel 		}
1554*2305Sstevel 		need_value = OPT_NEEDS_VALUE(subopt);
1555*2305Sstevel 		if (!need_value && value != NULL) {
1556*2305Sstevel 			__fmt_errstring(errstring, MAX_OPT_LENGTH,
1557*2305Sstevel 			    dgettext(TEXT_DOMAIN, no_value),
1558*2305Sstevel 			    mema_opts[subopt]);
1559*2305Sstevel 			subopt_err = 1;
1560*2305Sstevel 			break;
1561*2305Sstevel 		}
1562*2305Sstevel 		if (need_value && value == NULL) {
1563*2305Sstevel 			__fmt_errstring(errstring, MAX_OPT_LENGTH,
1564*2305Sstevel 			    dgettext(TEXT_DOMAIN, missing_value),
1565*2305Sstevel 			    mema_opts[subopt]);
1566*2305Sstevel 			subopt_err = 1;
1567*2305Sstevel 			break;
1568*2305Sstevel 		}
1569*2305Sstevel 		if (OPTSET_TEST(opt_set, subopt)) {
1570*2305Sstevel 			/* Ignore repeated options. */
1571*2305Sstevel 			continue;
1572*2305Sstevel 		}
1573*2305Sstevel 		if (group != 0 && !OPTSET_IS_EMPTY(opt_set)) {
1574*2305Sstevel 			for (i = 0; opts[i].subopt != -1; i++) {
1575*2305Sstevel 				if (i == subopt)
1576*2305Sstevel 					continue;
1577*2305Sstevel 				if (opts[i].group == group &&
1578*2305Sstevel 				    OPTSET_TEST(opt_set, opts[i].subopt))
1579*2305Sstevel 					break;
1580*2305Sstevel 			}
1581*2305Sstevel 			if (opts[i].subopt != -1) {
1582*2305Sstevel 				__fmt_errstring(errstring, MAX_OPT_LENGTH * 2,
1583*2305Sstevel 				    dgettext(TEXT_DOMAIN, conflict_opt),
1584*2305Sstevel 				    mema_opts[subopt],
1585*2305Sstevel 				    mema_opts[opts[i].subopt]);
1586*2305Sstevel 				subopt_err = 1;
1587*2305Sstevel 				break;
1588*2305Sstevel 			}
1589*2305Sstevel 		}
1590*2305Sstevel 		OPTSET_SET_VAL(opt_set, subopt, value);
1591*2305Sstevel 	}
1592*2305Sstevel 	free((void *)optcopy_alloc);
1593*2305Sstevel 	if (subopt_err) {
1594*2305Sstevel 		*retp = CFGA_ERROR;
1595*2305Sstevel 	}
1596*2305Sstevel 
1597*2305Sstevel 	return (opt_set);
1598*2305Sstevel }
1599*2305Sstevel 
1600*2305Sstevel #ifdef DEV_DEBUG
1601*2305Sstevel 
1602*2305Sstevel static int
debugging(void)1603*2305Sstevel debugging(void)
1604*2305Sstevel {
1605*2305Sstevel 	char *ep;
1606*2305Sstevel 	static int inited;
1607*2305Sstevel 
1608*2305Sstevel 	if (inited)
1609*2305Sstevel 		return (debug_fp != NULL);
1610*2305Sstevel 	inited = 1;
1611*2305Sstevel 
1612*2305Sstevel 	if ((ep = getenv("MEMADM_DEBUG")) == NULL) {
1613*2305Sstevel 		return (0);
1614*2305Sstevel 	}
1615*2305Sstevel 	if (*ep == '\0')
1616*2305Sstevel 		debug_fp = stderr;
1617*2305Sstevel 	else {
1618*2305Sstevel 		if ((debug_fp = fopen(ep, "a")) == NULL)
1619*2305Sstevel 			return (0);
1620*2305Sstevel 	}
1621*2305Sstevel 	(void) fprintf(debug_fp, "\nDebug started, pid=%d\n", (int)getpid());
1622*2305Sstevel 	return (1);
1623*2305Sstevel }
1624*2305Sstevel 
1625*2305Sstevel static void
dump_ioctl(int cmd,void * arg)1626*2305Sstevel dump_ioctl(
1627*2305Sstevel 	int cmd,
1628*2305Sstevel 	void *arg)
1629*2305Sstevel {
1630*2305Sstevel 	if (!debugging())
1631*2305Sstevel 		return;
1632*2305Sstevel 
1633*2305Sstevel 	switch (cmd) {
1634*2305Sstevel 	case AC_MEM_CONFIGURE:
1635*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_CONFIGURE\n");
1636*2305Sstevel 		break;
1637*2305Sstevel 
1638*2305Sstevel 	case AC_MEM_UNCONFIGURE:
1639*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_UNCONFIGURE\n");
1640*2305Sstevel 		break;
1641*2305Sstevel 
1642*2305Sstevel 	case AC_MEM_TEST_START:
1643*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_START\n");
1644*2305Sstevel 		break;
1645*2305Sstevel 
1646*2305Sstevel 	case AC_MEM_TEST_STOP: {
1647*2305Sstevel 		ac_mem_test_stop_t *tstop;
1648*2305Sstevel 
1649*2305Sstevel 		tstop = (ac_mem_test_stop_t *)arg;
1650*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_STOP handle=%#x "
1651*2305Sstevel 		    "condition=%d\n", tstop->handle, tstop->condition);
1652*2305Sstevel 	}
1653*2305Sstevel 		break;
1654*2305Sstevel 	case AC_MEM_TEST_READ: {
1655*2305Sstevel 		ac_mem_test_read_t *tread;
1656*2305Sstevel 
1657*2305Sstevel 		tread = (ac_mem_test_read_t *)arg;
1658*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_READ handle=%#x "
1659*2305Sstevel 		    "buf=%#p page=%#llx off=%#x count=%#x\n",
1660*2305Sstevel 		    tread->handle, tread->page_buf,
1661*2305Sstevel 		    tread->address.page_num,
1662*2305Sstevel 		    tread->address.line_offset, tread->address.line_count);
1663*2305Sstevel 	}
1664*2305Sstevel 		break;
1665*2305Sstevel 	case AC_MEM_TEST_WRITE: {
1666*2305Sstevel 		ac_mem_test_write_t *twrite;
1667*2305Sstevel 
1668*2305Sstevel 		twrite = (ac_mem_test_write_t *)arg;
1669*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_WRITE handle=%#x "
1670*2305Sstevel 		    "buf=%#p page=%#llx off=%#x count=%#x\n",
1671*2305Sstevel 		    twrite->handle, twrite->page_buf,
1672*2305Sstevel 		    twrite->address.page_num,
1673*2305Sstevel 		    twrite->address.line_offset, twrite->address.line_count);
1674*2305Sstevel 	}
1675*2305Sstevel 		break;
1676*2305Sstevel 	case AC_MEM_ADMIN_VER:
1677*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_ADMIN_VER:\n");
1678*2305Sstevel 		break;
1679*2305Sstevel 	case AC_MEM_STAT:
1680*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_STAT\n");
1681*2305Sstevel 		break;
1682*2305Sstevel 	case AC_MEM_EXERCISE: {
1683*2305Sstevel 		ac_cfga_cmd_t *cmdp;
1684*2305Sstevel 
1685*2305Sstevel 		cmdp = arg;
1686*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_EXERCISE arg=%d\n",
1687*2305Sstevel 		    cmdp->arg);
1688*2305Sstevel 		break;
1689*2305Sstevel 	}
1690*2305Sstevel 	default:
1691*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL: unknown (%#x)\n", cmd);
1692*2305Sstevel 		break;
1693*2305Sstevel 	}
1694*2305Sstevel 	(void) fflush(debug_fp);
1695*2305Sstevel }
1696*2305Sstevel 
1697*2305Sstevel static void
dump_ioctl_res(int cmd,void * arg,int ret,int ret_errno)1698*2305Sstevel dump_ioctl_res(
1699*2305Sstevel 	int cmd,
1700*2305Sstevel 	void *arg,
1701*2305Sstevel 	int ret,
1702*2305Sstevel 	int ret_errno)
1703*2305Sstevel {
1704*2305Sstevel 	if (!debugging())
1705*2305Sstevel 		return;
1706*2305Sstevel 
1707*2305Sstevel 	if (ret == -1) {
1708*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL failed, \"%s\" (errno=%d)\n",
1709*2305Sstevel 		    strerror(ret_errno), ret_errno);
1710*2305Sstevel 		(void) fflush(debug_fp);
1711*2305Sstevel 		return;
1712*2305Sstevel 	} else {
1713*2305Sstevel 		(void) fprintf(debug_fp, "IOCTL succeeded, ret=%d\n", ret);
1714*2305Sstevel 	}
1715*2305Sstevel 
1716*2305Sstevel 	switch (cmd) {
1717*2305Sstevel 	case AC_MEM_CONFIGURE:
1718*2305Sstevel 	case AC_MEM_UNCONFIGURE:
1719*2305Sstevel 		break;
1720*2305Sstevel 	case AC_MEM_TEST_START: {
1721*2305Sstevel 		ac_mem_test_start_t *tstart;
1722*2305Sstevel 
1723*2305Sstevel 		tstart = (ac_mem_test_start_t *)arg;
1724*2305Sstevel 		(void) fprintf(debug_fp, "    handle=%#x tester_pid=%d "
1725*2305Sstevel 		    "prev_condition=%d bank_size=%#llx "
1726*2305Sstevel 		    "page_size=%#x line_size=%#x afar_base=%#llx\n",
1727*2305Sstevel 		    tstart->handle, (int)tstart->tester_pid,
1728*2305Sstevel 		    tstart->prev_condition,
1729*2305Sstevel 		    tstart->bank_size, tstart->page_size,
1730*2305Sstevel 		    tstart->line_size, tstart->afar_base);
1731*2305Sstevel 	}
1732*2305Sstevel 		break;
1733*2305Sstevel 	case AC_MEM_TEST_STOP:
1734*2305Sstevel 		break;
1735*2305Sstevel 	case AC_MEM_TEST_READ: {
1736*2305Sstevel 		ac_mem_test_read_t *tread;
1737*2305Sstevel 		sunfire_processor_error_regs_t *err;
1738*2305Sstevel 
1739*2305Sstevel 		tread = (ac_mem_test_read_t *)arg;
1740*2305Sstevel 		err = tread->error_buf;
1741*2305Sstevel 		if (ret_errno == EIO) {
1742*2305Sstevel 			(void) fprintf(debug_fp, "module_id=%#llx afsr=%#llx "
1743*2305Sstevel 			    "afar=%#llx udbh_error_reg=%#llx "
1744*2305Sstevel 			    "udbl_error_reg=%#llx\n",
1745*2305Sstevel 			    (longlong_t)err->module_id, (longlong_t)err->afsr,
1746*2305Sstevel 			    (longlong_t)err->afar,
1747*2305Sstevel 			    (longlong_t)err->udbh_error_reg,
1748*2305Sstevel 			    (longlong_t)err->udbl_error_reg);
1749*2305Sstevel 		} else {
1750*2305Sstevel 			(void) fprintf(debug_fp, "\n");
1751*2305Sstevel 		}
1752*2305Sstevel 	}
1753*2305Sstevel 		break;
1754*2305Sstevel 	case AC_MEM_TEST_WRITE:
1755*2305Sstevel 		break;
1756*2305Sstevel 	case AC_MEM_ADMIN_VER: {
1757*2305Sstevel 		ac_mem_version_t *ver;
1758*2305Sstevel 
1759*2305Sstevel 		ver = (ac_mem_version_t *)arg;
1760*2305Sstevel 		(void) fprintf(debug_fp, "    version %d\n", *ver);
1761*2305Sstevel 	}
1762*2305Sstevel 		break;
1763*2305Sstevel 	case AC_MEM_STAT: {
1764*2305Sstevel 		ac_stat_t *tstat;
1765*2305Sstevel 
1766*2305Sstevel 		tstat = (ac_stat_t *)arg;
1767*2305Sstevel 		(void) fprintf(debug_fp, "    rstate=%u ostate=%u "
1768*2305Sstevel 		    "condition=%u status_time=%#lx board=%u\n",
1769*2305Sstevel 		    (uint_t)tstat->rstate, (uint_t)tstat->ostate,
1770*2305Sstevel 		    (uint_t)tstat->condition, (ulong_t)tstat->status_time,
1771*2305Sstevel 		    tstat->board);
1772*2305Sstevel 		(void) fprintf(debug_fp, "    real_size=%u use_size=%u "
1773*2305Sstevel 		    "busy=%u\n",
1774*2305Sstevel 		    tstat->real_size, tstat->use_size, tstat->busy);
1775*2305Sstevel 		(void) fprintf(debug_fp, "    page_size=%#x "
1776*2305Sstevel 		    "phys_pages=%#llx managed=%#llx nonrelocatable=%#llx\n",
1777*2305Sstevel 		    tstat->page_size, (longlong_t)tstat->phys_pages,
1778*2305Sstevel 		    (longlong_t)tstat->managed,
1779*2305Sstevel 		    (longlong_t)tstat->nonrelocatable);
1780*2305Sstevel 		(void) fprintf(debug_fp, "    memctl=%#llx "
1781*2305Sstevel 		    "decode0=%#llx decode1=%#llx\n",
1782*2305Sstevel 		    (longlong_t)tstat->ac_memctl, (longlong_t)tstat->ac_decode0,
1783*2305Sstevel 		    (longlong_t)tstat->ac_decode1);
1784*2305Sstevel 	}
1785*2305Sstevel 		break;
1786*2305Sstevel 	case AC_MEM_EXERCISE: {
1787*2305Sstevel 		ac_cfga_cmd_t *cmdp;
1788*2305Sstevel 
1789*2305Sstevel 		cmdp = arg;
1790*2305Sstevel 		switch (cmdp->arg) {
1791*2305Sstevel 		case AC_MEMX_RELOCATE_ALL: {
1792*2305Sstevel 			struct ac_memx_relocate_stats *stp;
1793*2305Sstevel 
1794*2305Sstevel 			if ((stp = cmdp->private) != NULL) {
1795*2305Sstevel 				(void) fprintf(debug_fp, "    base=%u npgs=%u"
1796*2305Sstevel 				    " nopaget=%u nolock=%u isfree=%u reloc=%u"
1797*2305Sstevel 				    " noreloc=%u\n",
1798*2305Sstevel 				    stp->base, stp->npgs, stp->nopaget,
1799*2305Sstevel 				    stp->nolock, stp->isfree, stp->reloc,
1800*2305Sstevel 				    stp->noreloc);
1801*2305Sstevel 			}
1802*2305Sstevel 			break;
1803*2305Sstevel 		}
1804*2305Sstevel 		default:
1805*2305Sstevel 			break;
1806*2305Sstevel 		}
1807*2305Sstevel 		break;
1808*2305Sstevel 	}
1809*2305Sstevel 	default:
1810*2305Sstevel 		break;
1811*2305Sstevel 	}
1812*2305Sstevel 	(void) fflush(debug_fp);
1813*2305Sstevel }
1814*2305Sstevel #endif /* DEV_DEBUG */
1815