13db86aabSstevel /*
23db86aabSstevel  * CDDL HEADER START
33db86aabSstevel  *
43db86aabSstevel  * The contents of this file are subject to the terms of the
53db86aabSstevel  * Common Development and Distribution License, Version 1.0 only
63db86aabSstevel  * (the "License").  You may not use this file except in compliance
73db86aabSstevel  * with the License.
83db86aabSstevel  *
93db86aabSstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
103db86aabSstevel  * or http://www.opensolaris.org/os/licensing.
113db86aabSstevel  * See the License for the specific language governing permissions
123db86aabSstevel  * and limitations under the License.
133db86aabSstevel  *
143db86aabSstevel  * When distributing Covered Code, include this CDDL HEADER in each
153db86aabSstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
163db86aabSstevel  * If applicable, add the following below this CDDL HEADER, with the
173db86aabSstevel  * fields enclosed by brackets "[]" replaced with your own identifying
183db86aabSstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
193db86aabSstevel  *
203db86aabSstevel  * CDDL HEADER END
213db86aabSstevel  */
223db86aabSstevel /*
233db86aabSstevel  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
243db86aabSstevel  * Use is subject to license terms.
253db86aabSstevel  */
263db86aabSstevel 
273db86aabSstevel #include <stddef.h>
283db86aabSstevel #include <stdlib.h>
293db86aabSstevel #include <unistd.h>
303db86aabSstevel #include <ctype.h>
313db86aabSstevel #include <fcntl.h>
323db86aabSstevel #include <signal.h>
333db86aabSstevel #include <string.h>
343db86aabSstevel #include <locale.h>
353db86aabSstevel #include <errno.h>
363db86aabSstevel #include <assert.h>
373db86aabSstevel #include <sys/dditypes.h>
383db86aabSstevel #include <sys/param.h>
393db86aabSstevel #include <sys/obpdefs.h>
403db86aabSstevel #include <sys/fhc.h>
413db86aabSstevel #include <sys/sysctrl.h>
423db86aabSstevel #include <sys/ac.h>
433db86aabSstevel #include <sys/spitregs.h>
443db86aabSstevel #include <config_admin.h>
453db86aabSstevel #include "mema_util.h"
463db86aabSstevel #include "mema_test.h"
473db86aabSstevel #include "mema_prom.h"
483db86aabSstevel 
493db86aabSstevel #ifdef	DEBUG
503db86aabSstevel #define	DBG	(void) printf
513db86aabSstevel #define	DBG1	(void) printf
523db86aabSstevel #define	DBG3	(void) printf
533db86aabSstevel #define	DBG4	(void) printf
543db86aabSstevel #else
553db86aabSstevel #define	DBG(a, b)
563db86aabSstevel #define	DBG1(a)
573db86aabSstevel #define	DBG3(a, b, c)
583db86aabSstevel #define	DBG4(a, b, c, d)
593db86aabSstevel #endif
603db86aabSstevel 
613db86aabSstevel #ifndef P_DER_UE
623db86aabSstevel /*
633db86aabSstevel  * <sys/spitregs.h> has these defines inside 'ifdef _KERNEL' at the
643db86aabSstevel  * time of writing.  Re-define here if that is still the case.
653db86aabSstevel  */
663db86aabSstevel 
673db86aabSstevel #define	P_DER_UE	0x00000000000000200ULL	/* UE has occurred */
683db86aabSstevel #define	P_DER_CE	0x00000000000000100ULL	/* CE has occurred */
693db86aabSstevel #define	P_DER_E_SYND	0x000000000000000FFULL	/* SYND<7:0>: ECC syndrome */
703db86aabSstevel #endif /* ! P_DER_UE */
713db86aabSstevel 
723db86aabSstevel #define	DEV_DEBUG
733db86aabSstevel #ifdef DEV_DEBUG
743db86aabSstevel #include <stdio.h>
753db86aabSstevel #include <stdlib.h>
763db86aabSstevel 
773db86aabSstevel static FILE *debug_fp;
783db86aabSstevel static int debugging(void);
793db86aabSstevel static void dump_ioctl(int, void *);
803db86aabSstevel static void dump_ioctl_res(int, void *, int, int);
813db86aabSstevel #else /* DEV_DEBUG */
823db86aabSstevel #define	dump_ioctl(CMD, ARG)
833db86aabSstevel #define	dump_ioctl_res(CMD, ARG, RET, ERRNO)
843db86aabSstevel #endif /* DEV_DEBUG */
853db86aabSstevel 
863db86aabSstevel typedef struct {
873db86aabSstevel 	uint_t   board;
883db86aabSstevel 	uint_t   bank;
893db86aabSstevel } mema_bank_t;
903db86aabSstevel 
913db86aabSstevel static char *mema_opts[] = {
923db86aabSstevel #define	OPT_BOOT_DISABLE	0
933db86aabSstevel 	"disable-at-boot",
943db86aabSstevel #define	OPT_BOOT_ENABLE		1
953db86aabSstevel 	"enable-at-boot",
963db86aabSstevel #define	OPT_TIMEOUT		2
973db86aabSstevel 	"timeout",
983db86aabSstevel 	NULL
993db86aabSstevel };
1003db86aabSstevel 
1013db86aabSstevel #define	OPT_NEEDS_VALUE(O)	((O) == OPT_TIMEOUT)
1023db86aabSstevel 
1033db86aabSstevel #define	MAX_OPT_LENGTH		(sizeof ("disable-at-boot"))
1043db86aabSstevel 
1053db86aabSstevel /*
1063db86aabSstevel  * For each function there is an array of opt_control structures giving
1073db86aabSstevel  * the valid options.  The array is terminated by an element with the
1083db86aabSstevel  * subopt field set to -1.  The group field is used to identify
1093db86aabSstevel  * mutually exclusive options, with zero meaning no grouping.
1103db86aabSstevel  */
1113db86aabSstevel struct opt_control {
1123db86aabSstevel 	int		subopt;
1133db86aabSstevel 	int		group;
1143db86aabSstevel };
1153db86aabSstevel 
1163db86aabSstevel /*
1173db86aabSstevel  * Returned set of options.
1183db86aabSstevel  * If the option takes a value, it will be set in 'val'
1193db86aabSstevel  * if the corresponding bit is set in 'bits' is set,
1203db86aabSstevel  * otherwise the pointer in 'val' is undefined.
1213db86aabSstevel  */
1223db86aabSstevel #define	OPT_VAL_ARRAY_SIZE	32	/* # bits in 'bits' */
1233db86aabSstevel typedef struct {
1243db86aabSstevel 	unsigned int	bits;
1253db86aabSstevel 	char		*val[OPT_VAL_ARRAY_SIZE];
1263db86aabSstevel } option_set_t;
1273db86aabSstevel 
1283db86aabSstevel #define	OPTSET_INIT(S)		((S).bits = 0)
1293db86aabSstevel #define	_OPT_TO_BIT(O)		(1 << (O))
1303db86aabSstevel #define	OPTSET_SET_VAL(S, O, V)	((S).bits |= _OPT_TO_BIT(O), \
1313db86aabSstevel 				(S).val[(O)] = (V))
1323db86aabSstevel #define	OPTSET_TEST(S, O)	(((S).bits & _OPT_TO_BIT(O)) != 0)
1333db86aabSstevel #define	OPTSET_VAL(S, O)	((S).val[(O)])
1343db86aabSstevel #define	OPTSET_IS_EMPTY(S)	((S).bits == 0)
1353db86aabSstevel 
1363db86aabSstevel static option_set_t process_options(const char *, struct opt_control *,
1373db86aabSstevel 	int *, char **);
1383db86aabSstevel 
1393db86aabSstevel static struct opt_control add_opts[] = {
1403db86aabSstevel 	{OPT_BOOT_ENABLE, 1},
1413db86aabSstevel 	{OPT_BOOT_DISABLE, 1},
1423db86aabSstevel 	{-1, 0}
1433db86aabSstevel };
1443db86aabSstevel 
1453db86aabSstevel static struct opt_control del_opts[] = {
1463db86aabSstevel 	{OPT_BOOT_ENABLE, 1},
1473db86aabSstevel 	{OPT_BOOT_DISABLE, 1},
1483db86aabSstevel 	{OPT_TIMEOUT, 2},
1493db86aabSstevel 	{-1, 0}
1503db86aabSstevel };
1513db86aabSstevel 
1523db86aabSstevel static struct opt_control stat_opts[] = {
1533db86aabSstevel 	{OPT_BOOT_ENABLE, 1},
1543db86aabSstevel 	{OPT_BOOT_DISABLE, 1},
1553db86aabSstevel 	{-1, 0}
1563db86aabSstevel };
1573db86aabSstevel 
1583db86aabSstevel #if !defined(TEXT_DOMAIN)
1593db86aabSstevel #define	TEXT_DOMAIN	"SYS_TEST"
1603db86aabSstevel #endif
1613db86aabSstevel 
1623db86aabSstevel static const char still_testing[] = "bank %s being tested by process %d";
1633db86aabSstevel static const char no_value[] = "sub-option \"%s\" does not take a value";
1643db86aabSstevel static const char missing_value[] = "sub-option \"%s\" needs a value";
1653db86aabSstevel static const char conflict_opt[] = "sub-option \"%s\" conflicts with \"%s\"";
1663db86aabSstevel static const char unk_subopt[] = "sub-option \"%s\" unknown\n"
1673db86aabSstevel 	"choose from: %s";
1683db86aabSstevel static const char not_valid[] =
1693db86aabSstevel 	"sub-option \"%s\" not valid for this operation\n"
1703db86aabSstevel 	"choose from: %s";
1713db86aabSstevel static const char timeout_notnum[] =
1723db86aabSstevel 	"timeout value not a positive integer \"%s\"";
1733db86aabSstevel static const char calloc_fail[] = "memory allocation failed (%d*%d bytes)";
1743db86aabSstevel static const char unk_test[] = "test \"%s\" unknown\n"
1753db86aabSstevel 	"choose from: %s";
1763db86aabSstevel static const char dup_test[] = "more than one test type specified (\"%s\")";
1773db86aabSstevel static const char dup_num[] = "option specified more than once (\"%s\")";
1783db86aabSstevel static const char no_num[] = "invalid number specified for max_errors(\"%s\")";
1793db86aabSstevel static const char mtest_rw_error[] = "memory test read/write error";
1803db86aabSstevel static const char mtest_lib_error[] = "memory test library error";
1813db86aabSstevel static const char dlist_invalid[] = "invalid disabled-memory-list";
1823db86aabSstevel static const char dlist_write_failed[] = "disabled-memory-list write failed";
1833db86aabSstevel static const char mtest_unknown_error[] = "unknown memory test error";
1843db86aabSstevel static const char ap_invalid[] = "invalid attachment point: %s";
1853db86aabSstevel static const char trans_illegal[] = "illegal transition";
1863db86aabSstevel static const char open_failed[] = "open failed: %s: %s";
1873db86aabSstevel static const char mema_help[] =	"\nAc specific options:\n";
1883db86aabSstevel static const char disable_opts[] = "\t-o disable-at-boot\n";
1893db86aabSstevel static const char enable_opts[] = "\t-o enable-at-boot\n";
1903db86aabSstevel static const char timeout_opts[] = "\t-o timeout=# (seconds)\n";
1913db86aabSstevel static const char test_opts[] =
1923db86aabSstevel 	"\t-o {quick, normal, extended},[max_errors=#] -t ap_id [ap_id...]\n";
1933db86aabSstevel static const char private_funcs[] = "\t-x relocate-test ap_id [ap_id...]\n";
1943db86aabSstevel static const char add_is_disabled[] = "memory is disabled at boot";
1953db86aabSstevel static const char add_willbe_disabled[] =
1963db86aabSstevel 	"memory will be disabled at boot";
1973db86aabSstevel static const char add_disab_err[] = "cannot get memory disabled status";
1983db86aabSstevel static const char pfunc_unknown[] = "private function \"%s\" unknown";
1993db86aabSstevel 
2003db86aabSstevel 
2013db86aabSstevel #define	mema_eid(a, b)		(((a) << 8) + (b))
2023db86aabSstevel #define	mema_str(i)		mema_strs[(i)]
2033db86aabSstevel 
2043db86aabSstevel #define	AC_BK_BUSY		0
2053db86aabSstevel #define	AC_BK_ID		1
2063db86aabSstevel #define	AC_BD_ID		2
2073db86aabSstevel #define	AC_BD_TYPE		3
2083db86aabSstevel #define	AC_BD_STATE		4
2093db86aabSstevel #define	AC_MEM_TEST_ID		5
2103db86aabSstevel #define	AC_MEM_TEST_PAR		6
2113db86aabSstevel #define	AC_MEM_PERM		7
2123db86aabSstevel #define	AC_KPM_CANCELLED	8
2133db86aabSstevel #define	AC_KPM_REFUSED		9
2143db86aabSstevel #define	AC_KPM_SPAN		10
2153db86aabSstevel #define	AC_KPM_DUP		11
2163db86aabSstevel #define	AC_KPM_FAULT		12
2173db86aabSstevel #define	AC_KPM_RESOURCE		13
2183db86aabSstevel #define	AC_KPM_NOTSUP		14
2193db86aabSstevel #define	AC_KPM_NOHANDLES	15
2203db86aabSstevel #define	AC_KPM_NONRELOC		16
2213db86aabSstevel #define	AC_KPM_HANDLE		17
2223db86aabSstevel #define	AC_KPM_BUSY		18
2233db86aabSstevel #define	AC_KPM_NOTVIABLE	19
2243db86aabSstevel #define	AC_KPM_SEQUENCE		20
2253db86aabSstevel #define	AC_KPM_NOWORK		21
2263db86aabSstevel #define	AC_KPM_NOTFINISHED	22
2273db86aabSstevel #define	AC_KPM_NOTRUNNING	23
2283db86aabSstevel #define	AC_VMEM			24
2293db86aabSstevel #define	CMD_MEM_STAT		25
2303db86aabSstevel #define	CMD_MEM_ADD		26
2313db86aabSstevel #define	CMD_MEM_DEL		27
2323db86aabSstevel #define	CMD_MEM_TEST_START	28
2333db86aabSstevel #define	CMD_MEM_TEST_STOP	29
2343db86aabSstevel #define	AC_UNKNOWN		30
2353db86aabSstevel #define	AC_INTR			31
2363db86aabSstevel #define	AC_TIMEOUT		32
2373db86aabSstevel #define	CMD_MEM_RELOCTEST	33
2383db86aabSstevel #define	AC_DEINTLV		34
2393db86aabSstevel 
2403db86aabSstevel static char *
2413db86aabSstevel mema_strs[] = {
2423db86aabSstevel 	"memory bank busy",
2433db86aabSstevel 	"invalid memory bank",
2443db86aabSstevel 	"invalid board id",
2453db86aabSstevel 	"invalid board type",
2463db86aabSstevel 	"invalid board state",
2473db86aabSstevel 	"invalid memory test id",
2483db86aabSstevel 	"invalid memory test parameter(s)",
2493db86aabSstevel 	"no write permission",
2503db86aabSstevel 	"memory operation cancelled",
2513db86aabSstevel 	"memory operation refused",
2523db86aabSstevel 	"memory already in use (add)",
2533db86aabSstevel 	"memory span duplicate (delete)",
2543db86aabSstevel 	"memory access test failed (add)",
2553db86aabSstevel 	"some resource was not available",
2563db86aabSstevel 	"operation not supported",
2573db86aabSstevel 	"cannot allocate any more handles",
2583db86aabSstevel 	"non-relocatable pages in span",
2593db86aabSstevel 	"bad handle supplied",
2603db86aabSstevel 	"memory in span is being deleted",
2613db86aabSstevel 	"VM viability test failed",
2623db86aabSstevel 	"function called out of sequence",
2633db86aabSstevel 	"no memory to delete",
2643db86aabSstevel 	"delete processing not finished",
2653db86aabSstevel 	"delete processing not running",
2663db86aabSstevel 	"insufficient virtual memory",
2673db86aabSstevel 	"memory stat failed: %s",
2683db86aabSstevel 	"memory add failed: %s",
2693db86aabSstevel 	"memory delete failed: %s",
2703db86aabSstevel 	"memory test start failed: %s",
2713db86aabSstevel 	"memory test stop failed: %s",
2723db86aabSstevel 	"unknown error",
2733db86aabSstevel 	"memory delete killed",
2743db86aabSstevel 	"memory delete timeout",
2753db86aabSstevel 	"memory relocate-test failed: %s",
2763db86aabSstevel 	"memory cannot be de-interleaved"
2773db86aabSstevel };
2783db86aabSstevel 
2793db86aabSstevel /*
2803db86aabSstevel  *	AC_MEM_PERM,		EBADF,   AC_ERR_MEM_PERM
2813db86aabSstevel  *	AC_BK_BUSY,		EBUSY,   AC_ERR_MEM_BK
2823db86aabSstevel  *	AC_KPM_CANCELLED,	EINTR,   AC_ERR_KPM_CANCELLED
2833db86aabSstevel  *	AC_KPM_REFUSED,		EINTR,   AC_ERR_KPM_REFUSED
2843db86aabSstevel  *	AC_BK_ID,		EINVAL,  AC_ERR_MEM_BK
2853db86aabSstevel  *	AC_BD_ID,		EINVAL,  AC_ERR_BD
2863db86aabSstevel  *	AC_BD_TYPE,		EINVAL,  AC_ERR_BD_TYPE
2873db86aabSstevel  *	AC_BD_STATE,		EINVAL,  AC_ERR_BD_STATE
2883db86aabSstevel  *	AC_MEM_TEST_ID,		EINVAL,  AC_ERR_MEM_TEST
2893db86aabSstevel  *	AC_MEM_TEST_PAR,	EINVAL,  AC_ERR_MEM_TEST_PAR
2903db86aabSstevel  *	AC_KPM_SPAN,		EINVAL,  AC_ERR_KPM_SPAN
2913db86aabSstevel  *	AC_KPM_DUP,		EINVAL,  AC_ERR_KPM_DUP?
2923db86aabSstevel  *	AC_KPM_FAULT,		EINVAL,  AC_ERR_KPM_FAULT
2933db86aabSstevel  *	AC_KPM_RESOURCE,	EINVAL,  AC_ERR_KPM_RESOURCE
2943db86aabSstevel  *	AC_KPM_NOTSUP,		EINVAL,  AC_ERR_KPM_NOTSUP
2953db86aabSstevel  *	AC_KPM_NOHANDLES,	EINVAL,  AC_ERR_KPM_NOHANDLES
2963db86aabSstevel  *	AC_KPM_NONRELOC,	EINVAL,  AC_ERR_KPM_NONRELOC
2973db86aabSstevel  *	AC_KPM_HANDLE,		EINVAL,  AC_ERR_KPM_HANDLE
2983db86aabSstevel  *	AC_KPM_BUSY,		EINVAL,  AC_ERR_KPM_BUSY
2993db86aabSstevel  *	AC_KPM_NOTVIABLE,	EINVAL,  AC_ERR_KPM_NOTVIABLE
3003db86aabSstevel  *	AC_KPM_SEQUENCE,	EINVAL,  AC_ERR_KPM_SEQUENCE
3013db86aabSstevel  *	AC_KPM_NOWORK,		EINVAL,  AC_ERR_KPM_NOWORK
3023db86aabSstevel  *	AC_KPM_NOTFINISHED,	EINVAL,  AC_ERR_KPM_NOTFINISHED
3033db86aabSstevel  *	AC_KPM_NOTRUNNING,	EINVAL,  AC_ERR_KPM_NOTRUNNING
3043db86aabSstevel  *	AC_VMEM,		ENOMEM,  AC_ERR_VMEM
3053db86aabSstevel  *	AC_INTR,		EINTR,   AC_ERR_INTR
3063db86aabSstevel  *	AC_TIMEOUT,		EINTR,   AC_ERR_TIMEOUT
3073db86aabSstevel  *	AC_DEINTLV,		EINVAL,  AC_ERR_MEM_DEINTLV
3083db86aabSstevel  */
3093db86aabSstevel static int
mema_sid(int err,int acerr)3103db86aabSstevel mema_sid(int err, int acerr)
3113db86aabSstevel {
3123db86aabSstevel 	if (acerr == AC_ERR_DEFAULT)
3133db86aabSstevel 		return (AC_UNKNOWN);
3143db86aabSstevel 
3153db86aabSstevel 	switch (mema_eid(err, acerr)) {
3163db86aabSstevel 	case mema_eid(EBADF, AC_ERR_MEM_PERM):
3173db86aabSstevel 		return (AC_MEM_PERM);
3183db86aabSstevel 	case mema_eid(EBUSY, AC_ERR_MEM_BK):
3193db86aabSstevel 		return (AC_BK_BUSY);
3203db86aabSstevel 	case mema_eid(EINTR, AC_ERR_KPM_CANCELLED):
3213db86aabSstevel 		return (AC_KPM_CANCELLED);
3223db86aabSstevel 	case mema_eid(EINTR, AC_ERR_KPM_REFUSED):
3233db86aabSstevel 		return (AC_KPM_REFUSED);
3243db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_MEM_BK):
3253db86aabSstevel 		return (AC_BK_ID);
3263db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_BD):
3273db86aabSstevel 		return (AC_BD_ID);
3283db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_BD_TYPE):
3293db86aabSstevel 		return (AC_BD_TYPE);
3303db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_BD_STATE):
3313db86aabSstevel 		return (AC_BD_STATE);
3323db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_MEM_TEST):
3333db86aabSstevel 		return (AC_MEM_TEST_ID);
3343db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_MEM_TEST_PAR):
3353db86aabSstevel 		return (AC_MEM_TEST_PAR);
3363db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_SPAN):
3373db86aabSstevel 		return (AC_KPM_SPAN);
3383db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_DUP):
3393db86aabSstevel 		return (AC_KPM_DUP);
3403db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_FAULT):
3413db86aabSstevel 		return (AC_KPM_FAULT);
3423db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_RESOURCE):
3433db86aabSstevel 		return (AC_KPM_RESOURCE);
3443db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTSUP):
3453db86aabSstevel 		return (AC_KPM_NOTSUP);
3463db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOHANDLES):
3473db86aabSstevel 		return (AC_KPM_NOHANDLES);
3483db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NONRELOC):
3493db86aabSstevel 		return (AC_KPM_NONRELOC);
3503db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_HANDLE):
3513db86aabSstevel 		return (AC_KPM_HANDLE);
3523db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_BUSY):
3533db86aabSstevel 		return (AC_KPM_BUSY);
3543db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTVIABLE):
3553db86aabSstevel 		return (AC_KPM_NOTVIABLE);
3563db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_SEQUENCE):
3573db86aabSstevel 		return (AC_KPM_SEQUENCE);
3583db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOWORK):
3593db86aabSstevel 		return (AC_KPM_NOWORK);
3603db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTFINISHED):
3613db86aabSstevel 		return (AC_KPM_NOTFINISHED);
3623db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_KPM_NOTRUNNING):
3633db86aabSstevel 		return (AC_KPM_NOTRUNNING);
3643db86aabSstevel 	case mema_eid(ENOMEM, AC_ERR_VMEM):
3653db86aabSstevel 		return (AC_VMEM);
3663db86aabSstevel 	case mema_eid(EINTR, AC_ERR_INTR):
3673db86aabSstevel 		return (AC_INTR);
3683db86aabSstevel 	case mema_eid(EINTR, AC_ERR_TIMEOUT):
3693db86aabSstevel 		return (AC_TIMEOUT);
3703db86aabSstevel 	case mema_eid(EINVAL, AC_ERR_MEM_DEINTLV):
3713db86aabSstevel 		return (AC_DEINTLV);
3723db86aabSstevel 	default:
3733db86aabSstevel 		break;
3743db86aabSstevel 	}
3753db86aabSstevel 
3763db86aabSstevel 	return (AC_UNKNOWN);
3773db86aabSstevel }
3783db86aabSstevel 
3793db86aabSstevel static void
mema_err(ac_cfga_cmd_t * ac,int ret_errno,char ** errstring,int cmd)3803db86aabSstevel mema_err(ac_cfga_cmd_t *ac, int ret_errno, char **errstring, int cmd)
3813db86aabSstevel {
3823db86aabSstevel 	char *cname = mema_str(cmd);
3833db86aabSstevel 	char *syserr;
3843db86aabSstevel 	char syserr_num[20];
3853db86aabSstevel 
3863db86aabSstevel 	if (ac) {
3873db86aabSstevel 		syserr = mema_str(mema_sid(ret_errno, ac->errtype));
3883db86aabSstevel 		syserr = dgettext(TEXT_DOMAIN, syserr);
3893db86aabSstevel 	} else {
3903db86aabSstevel 		syserr = strerror(ret_errno);
3913db86aabSstevel 		/* strerror() does its own gettext(). */
3923db86aabSstevel 		if (syserr == NULL) {
3933db86aabSstevel 			(void) sprintf(syserr_num, "errno=%d", errno);
3943db86aabSstevel 			syserr = syserr_num;
3953db86aabSstevel 		}
3963db86aabSstevel 	}
3973db86aabSstevel 
3983db86aabSstevel 	__fmt_errstring(errstring, strlen(syserr),
3993db86aabSstevel 	    dgettext(TEXT_DOMAIN, cname), syserr);
4003db86aabSstevel }
4013db86aabSstevel 
4023db86aabSstevel static void
mema_cmd_init(ac_cfga_cmd_t * ac,void * cmd,char * outputstr,int force)4033db86aabSstevel mema_cmd_init(ac_cfga_cmd_t *ac, void *cmd, char *outputstr, int force)
4043db86aabSstevel {
4053db86aabSstevel 	(void) memset((void *)ac, 0, sizeof (*ac));
4063db86aabSstevel 
4073db86aabSstevel 	ac->errtype = AC_ERR_DEFAULT;
4083db86aabSstevel 	ac->private = cmd;
4093db86aabSstevel 	ac->force = force;
4103db86aabSstevel 	ac->outputstr = outputstr;
4113db86aabSstevel 
4123db86aabSstevel 	(void) memset((void *)outputstr, 0, AC_OUTPUT_LEN);
4133db86aabSstevel }
4143db86aabSstevel 
4153db86aabSstevel static int
ap_bk_idx(const char * ap_id)4163db86aabSstevel ap_bk_idx(const char *ap_id)
4173db86aabSstevel {
4183db86aabSstevel 	int id;
4193db86aabSstevel 	char *s;
4203db86aabSstevel 	static char *bank = "bank";
4213db86aabSstevel 
4223db86aabSstevel 	DBG("ap_bk_idx(%s)\n", ap_id);
4233db86aabSstevel 
4243db86aabSstevel 	if ((s = strstr(ap_id, bank)) == NULL)
4253db86aabSstevel 		return (-1);
4263db86aabSstevel 	else {
4273db86aabSstevel 		int n;
4283db86aabSstevel 
4293db86aabSstevel 		s += strlen(bank);
4303db86aabSstevel 		n = strlen(s);
4313db86aabSstevel 
4323db86aabSstevel 		DBG3("ap_bk_idx: s=%s, n=%d\n", s, n);
4333db86aabSstevel 
4343db86aabSstevel 		if ((n != 1) || !isdigit(s[0]))
4353db86aabSstevel 			return (-1);
4363db86aabSstevel 	}
4373db86aabSstevel 
4383db86aabSstevel 	id = atoi(s);
4393db86aabSstevel 
4403db86aabSstevel 	if (id < 0 || id > 1)
4413db86aabSstevel 		return (-1);
4423db86aabSstevel 
4433db86aabSstevel 	DBG3("ap_bk_idx(%s)=%d\n", s, id);
4443db86aabSstevel 
4453db86aabSstevel 	return (id);
4463db86aabSstevel }
4473db86aabSstevel 
4483db86aabSstevel static cfga_err_t
ap_stat(const char * bank_spec,int * fdp,mema_bank_t * bkp,ac_stat_t * stp,char ** errstring)4493db86aabSstevel ap_stat(
4503db86aabSstevel 	const char *bank_spec,
4513db86aabSstevel 	int *fdp,
4523db86aabSstevel 	mema_bank_t *bkp,
4533db86aabSstevel 	ac_stat_t *stp,
4543db86aabSstevel 	char **errstring)
4553db86aabSstevel {
4563db86aabSstevel 	int fd;
4573db86aabSstevel 	int ret, ret_errno;
4583db86aabSstevel 	int bank;
4593db86aabSstevel 	mema_bank_t bk;
4603db86aabSstevel 	ac_stat_t stat;
4613db86aabSstevel 	ac_cfga_cmd_t cmd;
4623db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
4633db86aabSstevel 
4643db86aabSstevel 	if ((bank = ap_bk_idx(bank_spec)) == -1) {
4653db86aabSstevel 		__fmt_errstring(errstring, strlen(bank_spec),
466*13c31a0eSToomas Soome 		    dgettext(TEXT_DOMAIN, ap_invalid), bank_spec);
4673db86aabSstevel 		return (CFGA_ERROR);
4683db86aabSstevel 	}
4693db86aabSstevel 
4703db86aabSstevel 	bk.bank = bank;
4713db86aabSstevel 
4723db86aabSstevel 	if ((fd = open(bank_spec, ((fdp != NULL) ? O_RDWR : O_RDONLY), 0)) ==
4733db86aabSstevel 	    -1) {
4743db86aabSstevel 		char *syserr;
4753db86aabSstevel 		char syserr_num[20];
4763db86aabSstevel 
4773db86aabSstevel 		syserr = strerror(errno);
4783db86aabSstevel 		if (syserr == NULL) {
4793db86aabSstevel 			(void) sprintf(syserr_num, "errno=%d", errno);
4803db86aabSstevel 			syserr = syserr_num;
4813db86aabSstevel 		}
4823db86aabSstevel 		__fmt_errstring(errstring, strlen(syserr) +
4833db86aabSstevel 		    strlen(bank_spec),
4843db86aabSstevel 		    dgettext(TEXT_DOMAIN, open_failed), bank_spec, syserr);
4853db86aabSstevel 		return (CFGA_ERROR);
4863db86aabSstevel 	}
4873db86aabSstevel 
4883db86aabSstevel 	mema_cmd_init(&cmd, &stat, outputstr, 0);
4893db86aabSstevel 	dump_ioctl(AC_MEM_STAT, NULL);
4903db86aabSstevel 	ret = ioctl(fd, AC_MEM_STAT, &cmd);
4913db86aabSstevel 	ret_errno = errno;
4923db86aabSstevel 	dump_ioctl_res(AC_MEM_STAT, &stat, ret, ret_errno);
4933db86aabSstevel 
4943db86aabSstevel 	if (ret == -1) {
4953db86aabSstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_STAT);
4963db86aabSstevel 		(void) close(fd);
4973db86aabSstevel 		return (CFGA_ERROR);
4983db86aabSstevel 	}
4993db86aabSstevel 
5003db86aabSstevel 	if (fdp)
5013db86aabSstevel 		*fdp = fd;
5023db86aabSstevel 	else
5033db86aabSstevel 		(void) close(fd);
5043db86aabSstevel 
5053db86aabSstevel 	if (stp)
5063db86aabSstevel 		*stp = stat;
5073db86aabSstevel 
5083db86aabSstevel 	if (bkp) {
5093db86aabSstevel 		bkp->bank = bk.bank;
5103db86aabSstevel 		bkp->board = stat.board;
5113db86aabSstevel 	}
5123db86aabSstevel 
5133db86aabSstevel 	return (CFGA_OK);
5143db86aabSstevel }
5153db86aabSstevel 
5163db86aabSstevel static void
set_disabled_bits(mema_disabled_t * dp,int value)5173db86aabSstevel set_disabled_bits(mema_disabled_t *dp, int value)
5183db86aabSstevel {
5193db86aabSstevel 	if (value == 0)
5203db86aabSstevel 		*dp &= ~PROM_MEMORY_DISABLED;
5213db86aabSstevel 	else
5223db86aabSstevel 		*dp |= PROM_MEMORY_DISABLED;
5233db86aabSstevel }
5243db86aabSstevel 
5253db86aabSstevel static void
set_present_bits(mema_disabled_t * dp,ac_stat_t * asp)5263db86aabSstevel set_present_bits(mema_disabled_t *dp, ac_stat_t *asp)
5273db86aabSstevel {
5283db86aabSstevel 	if (asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED)
5293db86aabSstevel 		*dp |= PROM_MEMORY_PRESENT;
5303db86aabSstevel 	else
5313db86aabSstevel 		*dp &= ~PROM_MEMORY_DISABLED;
5323db86aabSstevel }
5333db86aabSstevel 
5343db86aabSstevel static cfga_err_t
prom_do_options(option_set_t do_option,int board,ac_stat_t * asp,char ** errstring)5353db86aabSstevel prom_do_options(
5363db86aabSstevel 	option_set_t do_option,
5373db86aabSstevel 	int board,
5383db86aabSstevel 	ac_stat_t *asp,
5393db86aabSstevel 	char **errstring)
5403db86aabSstevel {
5413db86aabSstevel 	cfga_err_t ret;
5423db86aabSstevel 	mema_disabled_t disab;
5433db86aabSstevel 
5443db86aabSstevel 	if (!prom_read_disabled_list(&disab, board))
5453db86aabSstevel 		return (CFGA_ERROR);
5463db86aabSstevel 
5473db86aabSstevel 	set_present_bits(&disab, asp);
5483db86aabSstevel 
5493db86aabSstevel 	ret = CFGA_OK;
5503db86aabSstevel 
5513db86aabSstevel 	if (OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
5523db86aabSstevel 		set_disabled_bits(&disab, 0);
5533db86aabSstevel 		if (!prom_viable_disabled_list(&disab)) {
5543db86aabSstevel 			__fmt_errstring(errstring, 0,
5553db86aabSstevel 			    dgettext(TEXT_DOMAIN, dlist_invalid));
5563db86aabSstevel 			ret = CFGA_ERROR;
5573db86aabSstevel 		} else if (!prom_write_disabled_list(&disab, board)) {
5583db86aabSstevel 			__fmt_errstring(errstring, 0,
5593db86aabSstevel 			    dgettext(TEXT_DOMAIN, dlist_write_failed));
5603db86aabSstevel 			ret = CFGA_ERROR;
5613db86aabSstevel 		}
5623db86aabSstevel 	} else if (OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
5633db86aabSstevel 		set_disabled_bits(&disab, 1);
5643db86aabSstevel 		if (!prom_viable_disabled_list(&disab)) {
5653db86aabSstevel 			__fmt_errstring(errstring, 0,
5663db86aabSstevel 			    dgettext(TEXT_DOMAIN, dlist_invalid));
5673db86aabSstevel 			ret = CFGA_ERROR;
5683db86aabSstevel 		} else if (!prom_write_disabled_list(&disab, board)) {
5693db86aabSstevel 			__fmt_errstring(errstring, 0,
5703db86aabSstevel 			    dgettext(TEXT_DOMAIN, dlist_write_failed));
5713db86aabSstevel 			ret = CFGA_ERROR;
5723db86aabSstevel 		}
5733db86aabSstevel 	}
5743db86aabSstevel 
5753db86aabSstevel 	return (ret);
5763db86aabSstevel }
5773db86aabSstevel 
5783db86aabSstevel static cfga_err_t
mema_add(const char * bank_spec,const char * options,char ** errstring,int force)5793db86aabSstevel mema_add(
5803db86aabSstevel 	const char *bank_spec,
5813db86aabSstevel 	const char *options,
5823db86aabSstevel 	char **errstring,
5833db86aabSstevel 	int force)
5843db86aabSstevel {
5853db86aabSstevel 	mema_bank_t bk;
5863db86aabSstevel 	int fd, ret, ret_errno;
5873db86aabSstevel 	option_set_t do_option;
5883db86aabSstevel 	ac_cfga_cmd_t cmd;
5893db86aabSstevel 	ac_stat_t stat;
5903db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
5913db86aabSstevel 
5923db86aabSstevel 	ret = 0;
5933db86aabSstevel 	do_option = process_options(options, add_opts, &ret, errstring);
5943db86aabSstevel 	if (ret != 0) {
5953db86aabSstevel 		return (ret);
5963db86aabSstevel 	}
5973db86aabSstevel 
5983db86aabSstevel 	ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
5993db86aabSstevel 	if (ret != CFGA_OK)
6003db86aabSstevel 		return (ret);
6013db86aabSstevel 
6023db86aabSstevel 
6033db86aabSstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
6043db86aabSstevel 	    stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
6053db86aabSstevel 		__fmt_errstring(errstring, 0,
6063db86aabSstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
6073db86aabSstevel 		(void) close(fd);
6083db86aabSstevel 		return (CFGA_ERROR);
6093db86aabSstevel 	}
6103db86aabSstevel 
6113db86aabSstevel 	if (!force) {
6123db86aabSstevel 		mema_disabled_t disab;
6133db86aabSstevel 
6143db86aabSstevel 		if (prom_read_disabled_list(&disab, bk.board)) {
6153db86aabSstevel 			if (disab != 0 &&
6163db86aabSstevel 			    !OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
6173db86aabSstevel 				__fmt_errstring(errstring, 0,
6183db86aabSstevel 				    dgettext(TEXT_DOMAIN, add_is_disabled));
6193db86aabSstevel 				(void) close(fd);
6203db86aabSstevel 				return (CFGA_ERROR);
6213db86aabSstevel 			}
6223db86aabSstevel 			if (disab == 0 &&
6233db86aabSstevel 			    OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
6243db86aabSstevel 				__fmt_errstring(errstring, 0,
6253db86aabSstevel 				    dgettext(TEXT_DOMAIN, add_willbe_disabled));
6263db86aabSstevel 				(void) close(fd);
6273db86aabSstevel 				return (CFGA_ERROR);
6283db86aabSstevel 			}
6293db86aabSstevel 		} else {
6303db86aabSstevel 			__fmt_errstring(errstring, 0,
6313db86aabSstevel 			    dgettext(TEXT_DOMAIN, add_disab_err));
6323db86aabSstevel 			(void) close(fd);
6333db86aabSstevel 			return (CFGA_ERROR);
6343db86aabSstevel 		}
6353db86aabSstevel 	}
6363db86aabSstevel 
6373db86aabSstevel 	mema_cmd_init(&cmd, NULL, outputstr, force);
6383db86aabSstevel 	dump_ioctl(AC_MEM_CONFIGURE, NULL);
6393db86aabSstevel 	ret = ioctl(fd, AC_MEM_CONFIGURE, &cmd);
6403db86aabSstevel 	ret_errno = errno;
6413db86aabSstevel 	dump_ioctl_res(AC_MEM_CONFIGURE, NULL, ret, ret_errno);
6423db86aabSstevel 	(void) close(fd);
6433db86aabSstevel 
6443db86aabSstevel 	if (ret == -1) {
6453db86aabSstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_ADD);
6463db86aabSstevel 		return (CFGA_ERROR);
6473db86aabSstevel 	}
6483db86aabSstevel 
6493db86aabSstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
6503db86aabSstevel 
6513db86aabSstevel 	return (ret);
6523db86aabSstevel }
6533db86aabSstevel 
6543db86aabSstevel static cfga_err_t
mema_delete(const char * bank_spec,const char * options,char ** errstring,int force)6553db86aabSstevel mema_delete(
6563db86aabSstevel 	const char *bank_spec,
6573db86aabSstevel 	const char *options,
6583db86aabSstevel 	char **errstring,
6593db86aabSstevel 	int force)
6603db86aabSstevel {
6613db86aabSstevel 	mema_bank_t bk;
6623db86aabSstevel 	int fd, ret, ret_errno;
6633db86aabSstevel 	option_set_t do_option;
6643db86aabSstevel 	ac_cfga_cmd_t cmd;
6653db86aabSstevel 	ac_stat_t stat;
6663db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
6673db86aabSstevel 	int timeout_secs = -1;	/* Init to 'use default'. */
6683db86aabSstevel 
6693db86aabSstevel 	ret = 0;
6703db86aabSstevel 	do_option = process_options(options, del_opts, &ret, errstring);
6713db86aabSstevel 	if (ret != 0) {
6723db86aabSstevel 		return (ret);
6733db86aabSstevel 	}
6743db86aabSstevel 
6753db86aabSstevel 	if (OPTSET_TEST(do_option, OPT_TIMEOUT)) {
6763db86aabSstevel 		char *to_val;
6773db86aabSstevel 		char *ep;
6783db86aabSstevel 
6793db86aabSstevel 		to_val = OPTSET_VAL(do_option, OPT_TIMEOUT);
6803db86aabSstevel 		timeout_secs = (int)strtol(to_val, &ep, 10);
6813db86aabSstevel 		if (*ep != '\0' || ep == to_val || timeout_secs < 0) {
6823db86aabSstevel 			__fmt_errstring(errstring, strlen(to_val),
6833db86aabSstevel 			    dgettext(TEXT_DOMAIN, timeout_notnum), to_val);
6843db86aabSstevel 			return (CFGA_ERROR);
6853db86aabSstevel 		}
6863db86aabSstevel 	}
6873db86aabSstevel 
6883db86aabSstevel 	ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
6893db86aabSstevel 	if (ret != CFGA_OK)
6903db86aabSstevel 		return (ret);
6913db86aabSstevel 
6923db86aabSstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
6933db86aabSstevel 	    stat.ostate != SYSC_CFGA_OSTATE_CONFIGURED) {
6943db86aabSstevel 		__fmt_errstring(errstring, 0,
6953db86aabSstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
6963db86aabSstevel 		(void) close(fd);
6973db86aabSstevel 		return (CFGA_ERROR);
6983db86aabSstevel 	}
6993db86aabSstevel 
7003db86aabSstevel 	mema_cmd_init(&cmd, NULL, outputstr, force);
7013db86aabSstevel 	cmd.arg = timeout_secs;
7023db86aabSstevel 	dump_ioctl(AC_MEM_UNCONFIGURE, NULL);
7033db86aabSstevel 	ret = ioctl(fd, AC_MEM_UNCONFIGURE, &cmd);
7043db86aabSstevel 	ret_errno = errno;
7053db86aabSstevel 	dump_ioctl_res(AC_MEM_UNCONFIGURE, NULL, ret, ret_errno);
7063db86aabSstevel 	(void) close(fd);
7073db86aabSstevel 
7083db86aabSstevel 	if (ret == -1) {
7093db86aabSstevel 		mema_err(&cmd, ret_errno, errstring, CMD_MEM_DEL);
7103db86aabSstevel 		return (CFGA_ERROR);
7113db86aabSstevel 	}
7123db86aabSstevel 
7133db86aabSstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
7143db86aabSstevel 
7153db86aabSstevel 	return (ret);
7163db86aabSstevel }
7173db86aabSstevel 
7183db86aabSstevel /*ARGSUSED*/
7193db86aabSstevel 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)7203db86aabSstevel cfga_change_state(
7213db86aabSstevel 	cfga_cmd_t state_change_cmd,
7223db86aabSstevel 	const char *ap_id,
7233db86aabSstevel 	const char *options,
7243db86aabSstevel 	struct cfga_confirm *confp,
7253db86aabSstevel 	struct cfga_msg *msgp,
7263db86aabSstevel 	char **errstring,
7273db86aabSstevel 	cfga_flags_t flags)
7283db86aabSstevel {
7293db86aabSstevel 	int force;
7303db86aabSstevel 	cfga_err_t rc;
7313db86aabSstevel 
7323db86aabSstevel 	if (errstring != NULL)
7333db86aabSstevel 		*errstring = NULL;
7343db86aabSstevel 
7353db86aabSstevel 	force = flags & CFGA_FLAG_FORCE;
7363db86aabSstevel 
7373db86aabSstevel 	switch (state_change_cmd) {
7383db86aabSstevel 	case CFGA_CMD_CONFIGURE:
7393db86aabSstevel 		rc =  mema_add(ap_id, options, errstring, force);
7403db86aabSstevel 		break;
7413db86aabSstevel 
7423db86aabSstevel 	case CFGA_CMD_UNCONFIGURE:
7433db86aabSstevel 		rc =  mema_delete(ap_id, options, errstring, force);
7443db86aabSstevel 		break;
7453db86aabSstevel 
7463db86aabSstevel 	default:
7473db86aabSstevel 		rc = CFGA_OPNOTSUPP;
7483db86aabSstevel 		break;
7493db86aabSstevel 	}
7503db86aabSstevel 
7513db86aabSstevel 	return (rc);
7523db86aabSstevel }
7533db86aabSstevel 
7543db86aabSstevel /*ARGSUSED*/
7553db86aabSstevel 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)7563db86aabSstevel cfga_private_func(
7573db86aabSstevel 	const char *function,
7583db86aabSstevel 	const char *ap_id,
7593db86aabSstevel 	const char *options,
7603db86aabSstevel 	struct cfga_confirm *confp,
7613db86aabSstevel 	struct cfga_msg *msgp,
7623db86aabSstevel 	char **errstring,
7633db86aabSstevel 	cfga_flags_t flags)
7643db86aabSstevel {
7653db86aabSstevel 	mema_bank_t bk;
7663db86aabSstevel 	ac_stat_t stat;
7673db86aabSstevel 	int fd, ret, ret_errno;
7683db86aabSstevel 	ac_cfga_cmd_t cmd;
7693db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
7703db86aabSstevel 
7713db86aabSstevel 	if (errstring != NULL)
7723db86aabSstevel 		*errstring = NULL;
7733db86aabSstevel 
7743db86aabSstevel 	ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
7753db86aabSstevel 	if (ret != CFGA_OK)
7763db86aabSstevel 		return (ret);
7773db86aabSstevel 
7783db86aabSstevel 	if (strcmp(function, "relocate-test") == 0) {
7793db86aabSstevel 		struct ac_memx_relocate_stats rstat;
7803db86aabSstevel 
7813db86aabSstevel 		mema_cmd_init(&cmd, NULL, outputstr,
7823db86aabSstevel 		    (flags & CFGA_FLAG_FORCE));
7833db86aabSstevel 		cmd.arg = AC_MEMX_RELOCATE_ALL;
7843db86aabSstevel 		cmd.private = &rstat;
7853db86aabSstevel 		(void) memset((void *)&rstat, 0, sizeof (rstat));
7863db86aabSstevel 		dump_ioctl(AC_MEM_EXERCISE, &cmd);
7873db86aabSstevel 		ret = ioctl(fd, AC_MEM_EXERCISE, &cmd);
7883db86aabSstevel 		ret_errno = errno;
7893db86aabSstevel 		dump_ioctl_res(AC_MEM_EXERCISE, &cmd, ret, ret_errno);
7903db86aabSstevel 		(void) close(fd);
7913db86aabSstevel 
7923db86aabSstevel 		if (ret == -1) {
7933db86aabSstevel 			mema_err(&cmd, ret_errno, errstring, CMD_MEM_RELOCTEST);
7943db86aabSstevel 			return (CFGA_ERROR);
7953db86aabSstevel 		}
7963db86aabSstevel 		return (CFGA_OK);
7973db86aabSstevel 	}
7983db86aabSstevel 
7993db86aabSstevel 	__fmt_errstring(errstring, strlen(function),
8003db86aabSstevel 	    dgettext(TEXT_DOMAIN, pfunc_unknown), function);
8013db86aabSstevel 
8023db86aabSstevel 	return (CFGA_ERROR);
8033db86aabSstevel }
8043db86aabSstevel 
8053db86aabSstevel static int
mtest_run(int fd,int test_fun,mema_bank_t * abkp,struct cfga_msg * msgp,char ** errstring,ulong_t max_errors)8063db86aabSstevel mtest_run(
8073db86aabSstevel 	int fd,
8083db86aabSstevel 	int test_fun,
8093db86aabSstevel 	mema_bank_t *abkp,
8103db86aabSstevel 	struct cfga_msg *msgp,
8113db86aabSstevel 	char **errstring,
8123db86aabSstevel 	ulong_t max_errors)
8133db86aabSstevel {
8143db86aabSstevel 	ac_mem_test_start_t test_start;
8153db86aabSstevel 	ac_mem_test_stop_t test_stop;
8163db86aabSstevel 	struct mtest_handle handle;
8173db86aabSstevel 	int ret, ret_errno;
8183db86aabSstevel 	int res;
8193db86aabSstevel 	ac_cfga_cmd_t cmd;
8203db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
8213db86aabSstevel 
8223db86aabSstevel 	(void) memset((void *)&test_start, 0, sizeof (test_start));
8233db86aabSstevel 	mema_cmd_init(&cmd, &test_start, outputstr, 0);
8243db86aabSstevel 	dump_ioctl(AC_MEM_TEST_START, &test_start);
8253db86aabSstevel 	ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
8263db86aabSstevel 	ret_errno = errno;
8273db86aabSstevel 	dump_ioctl_res(AC_MEM_TEST_START, &test_start, ret, ret_errno);
8283db86aabSstevel 
8293db86aabSstevel 	if (ret == -1) {
8303db86aabSstevel 		if (ret_errno == ENOTSUP) {
8313db86aabSstevel 			mema_err(&cmd, ret_errno, errstring,
832*13c31a0eSToomas Soome 			    CMD_MEM_TEST_START);
8333db86aabSstevel 			return (CFGA_OPNOTSUPP);
8343db86aabSstevel 		}
8353db86aabSstevel 		if (ret_errno == EBUSY && test_start.tester_pid > 0) {
8363db86aabSstevel 			/*
8373db86aabSstevel 			 * Bank appears to be being tested.  Check that
8383db86aabSstevel 			 * process 'tester_pid' is still running.
8393db86aabSstevel 			 */
8403db86aabSstevel 			if (kill(test_start.tester_pid, 0) != -1 ||
8413db86aabSstevel 			    errno != ESRCH) {
8423db86aabSstevel 				cfga_ap_log_id_t bname;
8433db86aabSstevel 
8443db86aabSstevel 				/* Process still exists. */
8453db86aabSstevel 				(void) sprintf(bname, "board %d bank%d",
8463db86aabSstevel 				    abkp->board, abkp->bank);
8473db86aabSstevel 				__fmt_errstring(errstring, strlen(bname),
8483db86aabSstevel 				    dgettext(TEXT_DOMAIN, still_testing),
8493db86aabSstevel 				    bname, test_start.tester_pid);
8503db86aabSstevel 				return (CFGA_ERROR);
8513db86aabSstevel 			}
8523db86aabSstevel 			/*
8533db86aabSstevel 			 * Do a test stop and re-try the start.
8543db86aabSstevel 			 */
8553db86aabSstevel 			(void) memset((void *)&test_stop, 0,
8563db86aabSstevel 			    sizeof (test_stop));
8573db86aabSstevel 			test_stop.handle = test_start.handle;
8583db86aabSstevel 			test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
8593db86aabSstevel 			mema_cmd_init(&cmd, &test_stop, outputstr, 0);
8603db86aabSstevel 			dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
8613db86aabSstevel 			ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
8623db86aabSstevel 			ret_errno = errno;
8633db86aabSstevel 			dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop,
8643db86aabSstevel 			    ret, ret_errno);
8653db86aabSstevel 			/*
8663db86aabSstevel 			 * Ignore test stop error processing and re-try the
8673db86aabSstevel 			 * start.  The error return will be derived from the
8683db86aabSstevel 			 * result of start.
8693db86aabSstevel 			 */
8703db86aabSstevel 			(void) memset((void *)&test_start, 0,
8713db86aabSstevel 			    sizeof (test_start));
8723db86aabSstevel 			mema_cmd_init(&cmd, &test_start, outputstr, 0);
8733db86aabSstevel 			dump_ioctl(AC_MEM_TEST_START, &test_start);
8743db86aabSstevel 			ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
8753db86aabSstevel 			ret_errno = errno;
8763db86aabSstevel 			dump_ioctl_res(AC_MEM_TEST_START, &test_start,
8773db86aabSstevel 			    ret, ret_errno);
8783db86aabSstevel 		}
8793db86aabSstevel 		/* Test return code again to cover the case of a re-try. */
8803db86aabSstevel 		if (ret == -1) {
8813db86aabSstevel 			mema_err(&cmd, ret_errno, errstring,
8823db86aabSstevel 			    CMD_MEM_TEST_START);
8833db86aabSstevel 			return (CFGA_ERROR);
8843db86aabSstevel 		}
8853db86aabSstevel 	}
8863db86aabSstevel 	(void) memset((void *)&handle, 0, sizeof (handle));
8873db86aabSstevel 	handle.fd = fd;
8883db86aabSstevel 	handle.drvhandle = (void *)&test_start;
8893db86aabSstevel 	handle.msgp = msgp;
8903db86aabSstevel 	handle.bank_size = test_start.bank_size;
8913db86aabSstevel 	handle.page_size = test_start.page_size;
8923db86aabSstevel 	handle.line_size = test_start.line_size;
8933db86aabSstevel 	handle.lines_per_page = test_start.page_size / test_start.line_size;
8943db86aabSstevel 	handle.condition = CFGA_COND_UNKNOWN;
8953db86aabSstevel 	handle.max_errors = max_errors;
8963db86aabSstevel 
8973db86aabSstevel 	res = (*mtest_table[test_fun].test_func)(&handle);
8983db86aabSstevel 
8993db86aabSstevel 	mtest_deallocate_buf_all(&handle);
9003db86aabSstevel 
9013db86aabSstevel 	/*
9023db86aabSstevel 	 * Convert memory test code to MEMA_ code.
9033db86aabSstevel 	 */
9043db86aabSstevel 	switch (res) {
9053db86aabSstevel 	case MTEST_DONE:
9063db86aabSstevel 		res = CFGA_OK;
9073db86aabSstevel 		break;
9083db86aabSstevel 	case MTEST_LIB_ERROR:
9093db86aabSstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
9103db86aabSstevel 		    mtest_lib_error));
9113db86aabSstevel 		res = CFGA_ERROR;
9123db86aabSstevel 		break;
9133db86aabSstevel 	case MTEST_DEV_ERROR:
9143db86aabSstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
9153db86aabSstevel 		    mtest_rw_error));
9163db86aabSstevel 		res = CFGA_ERROR;
9173db86aabSstevel 		break;
9183db86aabSstevel 	default:
9193db86aabSstevel 		__fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
9203db86aabSstevel 		    mtest_unknown_error));
9213db86aabSstevel 		res = CFGA_ERROR;
9223db86aabSstevel 		assert(0);
9233db86aabSstevel 		break;
9243db86aabSstevel 	}
9253db86aabSstevel 
9263db86aabSstevel 	(void) memset((void *)&test_stop, 0, sizeof (test_stop));
9273db86aabSstevel 	test_stop.handle = test_start.handle;
9283db86aabSstevel 	switch (handle.condition) {
9293db86aabSstevel 	case CFGA_COND_OK:
9303db86aabSstevel 		test_stop.condition = SYSC_CFGA_COND_OK;
9313db86aabSstevel 		break;
9323db86aabSstevel 	case CFGA_COND_FAILING:
9333db86aabSstevel 		test_stop.condition = SYSC_CFGA_COND_FAILING;
9343db86aabSstevel 		break;
9353db86aabSstevel 	case CFGA_COND_FAILED:
9363db86aabSstevel 		test_stop.condition = SYSC_CFGA_COND_FAILED;
9373db86aabSstevel 		break;
9383db86aabSstevel 	case CFGA_COND_UNKNOWN:
9393db86aabSstevel 		test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
9403db86aabSstevel 		break;
9413db86aabSstevel 	default:
9423db86aabSstevel 		test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
9433db86aabSstevel 		assert(0);
9443db86aabSstevel 		break;
9453db86aabSstevel 	}
9463db86aabSstevel 
9473db86aabSstevel 	mema_cmd_init(&cmd, &test_stop, outputstr, 0);
9483db86aabSstevel 	dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
9493db86aabSstevel 	ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
9503db86aabSstevel 	ret_errno = errno;
9513db86aabSstevel 	dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop, ret, ret_errno);
9523db86aabSstevel 	if (ret == -1) {
9533db86aabSstevel 		mema_err(&cmd, ret_errno, errstring,
9543db86aabSstevel 		    CMD_MEM_TEST_STOP);
9553db86aabSstevel 		return (CFGA_ERROR);
9563db86aabSstevel 	}
9573db86aabSstevel 	return (res);
9583db86aabSstevel }
9593db86aabSstevel 
9603db86aabSstevel #define	DRVHANDLE(H)	(((ac_mem_test_start_t *)(H)->drvhandle)->handle)
9613db86aabSstevel 
9623db86aabSstevel int
mtest_write(mtest_handle_t handle,void * page_buf,u_longlong_t page_no,uint_t line_offset,uint_t line_count)9633db86aabSstevel mtest_write(
9643db86aabSstevel 	mtest_handle_t handle,
9653db86aabSstevel 	void *page_buf,
9663db86aabSstevel 	u_longlong_t page_no,
9673db86aabSstevel 	uint_t line_offset,
9683db86aabSstevel 	uint_t line_count)
9693db86aabSstevel {
9703db86aabSstevel 	ac_mem_test_write_t test_write;
9713db86aabSstevel 	int fd, ret, ret_errno;
9723db86aabSstevel 	ac_cfga_cmd_t cmd;
9733db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
9743db86aabSstevel 
9753db86aabSstevel 	(void) memset((void *)&test_write, 0, sizeof (test_write));
9763db86aabSstevel 	fd = handle->fd;
9773db86aabSstevel 	test_write.handle = DRVHANDLE(handle);
9783db86aabSstevel 	test_write.page_buf = page_buf;
9793db86aabSstevel 	test_write.address.page_num = page_no;
9803db86aabSstevel 	test_write.address.line_offset = line_offset;
9813db86aabSstevel 	if (line_count == 0)
9823db86aabSstevel 		test_write.address.line_count = handle->lines_per_page;
9833db86aabSstevel 	else
9843db86aabSstevel 		test_write.address.line_count = line_count;
9853db86aabSstevel 
9863db86aabSstevel 	mema_cmd_init(&cmd, &test_write, outputstr, 0);
9873db86aabSstevel 	dump_ioctl(AC_MEM_TEST_WRITE, &test_write);
9883db86aabSstevel 	ret = ioctl(fd, AC_MEM_TEST_WRITE, &cmd);
9893db86aabSstevel 	ret_errno = errno;
9903db86aabSstevel 	dump_ioctl_res(AC_MEM_TEST_WRITE, &test_write, ret, ret_errno);
9913db86aabSstevel 
9923db86aabSstevel 	if (ret == -1)
9933db86aabSstevel 		return (-1);
9943db86aabSstevel 	return (0);
9953db86aabSstevel }
9963db86aabSstevel 
9973db86aabSstevel 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)9983db86aabSstevel mtest_read(
9993db86aabSstevel 	mtest_handle_t handle,
10003db86aabSstevel 	void *page_buf,
10013db86aabSstevel 	u_longlong_t page_no,
10023db86aabSstevel 	uint_t line_offset,
10033db86aabSstevel 	uint_t line_count,
10043db86aabSstevel 	struct mtest_error *errp)
10053db86aabSstevel {
10063db86aabSstevel 	ac_mem_test_read_t test_read;
10073db86aabSstevel 	sunfire_processor_error_regs_t errbuf;
10083db86aabSstevel 	int fd, ret, ret_errno;
10093db86aabSstevel 	ac_cfga_cmd_t cmd;
10103db86aabSstevel 	char outputstr[AC_OUTPUT_LEN];
10113db86aabSstevel 
10123db86aabSstevel 	(void) memset((void *)&test_read, 0, sizeof (test_read));
10133db86aabSstevel 	(void) memset((void *)&errbuf, 0, sizeof (errbuf));
10143db86aabSstevel 	fd = handle->fd;
10153db86aabSstevel 	test_read.handle = DRVHANDLE(handle);
10163db86aabSstevel 	test_read.page_buf = page_buf;
10173db86aabSstevel 	test_read.address.page_num = page_no;
10183db86aabSstevel 	test_read.address.line_offset = line_offset;
10193db86aabSstevel 	test_read.error_buf =  &errbuf;
10203db86aabSstevel 	if (line_count == 0)
10213db86aabSstevel 		test_read.address.line_count = handle->lines_per_page;
10223db86aabSstevel 	else
10233db86aabSstevel 		test_read.address.line_count = line_count;
10243db86aabSstevel 
10253db86aabSstevel 	mema_cmd_init(&cmd, &test_read, outputstr, 0);
10263db86aabSstevel 	dump_ioctl(AC_MEM_TEST_READ, &test_read);
10273db86aabSstevel 	ret = ioctl(fd, AC_MEM_TEST_READ, &cmd);
10283db86aabSstevel 	ret_errno = errno;
10293db86aabSstevel 	dump_ioctl_res(AC_MEM_TEST_READ, &test_read, ret, ret_errno);
10303db86aabSstevel 
10313db86aabSstevel 	if (ret == -1) {
10323db86aabSstevel 		if (ret_errno == EIO) {
10333db86aabSstevel 			/*
10343db86aabSstevel 			 * Special case indicating CE or UE.
10353db86aabSstevel 			 */
10363db86aabSstevel 			if (((errbuf.udbh_error_reg | errbuf.udbl_error_reg) &
10373db86aabSstevel 			    P_DER_UE) != 0)
10383db86aabSstevel 				errp->error_type = MTEST_ERR_UE;
10393db86aabSstevel 			else
10403db86aabSstevel 				errp->error_type = MTEST_ERR_CE;
10413db86aabSstevel 		} else {
10423db86aabSstevel 			return (-1);
10433db86aabSstevel 		}
10443db86aabSstevel 	} else {
10453db86aabSstevel 		errp->error_type = MTEST_ERR_NONE;
10463db86aabSstevel 	}
10473db86aabSstevel 	return (0);
10483db86aabSstevel }
10493db86aabSstevel 
10503db86aabSstevel static char *
subopt_help_str(char * opts[])10513db86aabSstevel subopt_help_str(char *opts[])
10523db86aabSstevel {
10533db86aabSstevel 	char *str;
10543db86aabSstevel 	const char *sep;
10553db86aabSstevel 	int len;
10563db86aabSstevel 	int i, n;
10573db86aabSstevel 	static const char help_sep[] = ", ";
10583db86aabSstevel 	static const char help_nil[] = "???";
10593db86aabSstevel 
10603db86aabSstevel 	len = 0;
10613db86aabSstevel 	n = 0;
10623db86aabSstevel 	for (i = 0; opts[i] != NULL; i++) {
10633db86aabSstevel 		n++;
10643db86aabSstevel 		len += strlen(opts[i]);
10653db86aabSstevel 	}
10663db86aabSstevel 	if (n == 0)
10673db86aabSstevel 		return (strdup(help_nil));
10683db86aabSstevel 	len += (n - 1) * strlen(help_sep);
10693db86aabSstevel 	len++;
10703db86aabSstevel 	str = (char *)malloc(len);
10713db86aabSstevel 	if (str == NULL)
10723db86aabSstevel 		return (NULL);
10733db86aabSstevel 	*str = '\0';
10743db86aabSstevel 	sep = "";
10753db86aabSstevel 	for (i = 0; opts[i] != NULL; i++) {
10763db86aabSstevel 		(void) strcat(str, sep);
10773db86aabSstevel 		(void) strcat(str, opts[i]);
10783db86aabSstevel 		sep = help_sep;
10793db86aabSstevel 	}
10803db86aabSstevel 	return (str);
10813db86aabSstevel }
10823db86aabSstevel 
10833db86aabSstevel /*ARGSUSED*/
10843db86aabSstevel cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)10853db86aabSstevel cfga_test(
10863db86aabSstevel 	const char *ap_id,
10873db86aabSstevel 	const char *options,
10883db86aabSstevel 	struct cfga_msg *msgp,
10893db86aabSstevel 	char **errstring,
10903db86aabSstevel 	cfga_flags_t flags)
10913db86aabSstevel {
10923db86aabSstevel 	mema_bank_t bk;
10933db86aabSstevel 	ac_stat_t stat;
10943db86aabSstevel 	int test_fun = -1;
10953db86aabSstevel 	int fd, ret;
10963db86aabSstevel 	int maxerr_idx;
10973db86aabSstevel 	long max_errors = -1;
10983db86aabSstevel 	char *ret_p;
10993db86aabSstevel 
11003db86aabSstevel 	if (errstring != NULL)
11013db86aabSstevel 		*errstring = NULL;
11023db86aabSstevel 
11033db86aabSstevel 	/*
11043db86aabSstevel 	 * Decode test level and max error number.
11053db86aabSstevel 	 */
11063db86aabSstevel 	if (options != NULL && *options != '\0') {
11073db86aabSstevel 		char **opts;
11083db86aabSstevel 		char *value;
11093db86aabSstevel 		char *cp, *free_cp;
11103db86aabSstevel 		int subopt;
11113db86aabSstevel 
11123db86aabSstevel 		/* getsubopt() modifies the input string, so copy it. */
11133db86aabSstevel 		cp = strdup(options);
11143db86aabSstevel 		if (cp == NULL) {
11153db86aabSstevel 			return (CFGA_LIB_ERROR);
11163db86aabSstevel 		}
11173db86aabSstevel 		free_cp = cp;
11183db86aabSstevel 		opts = mtest_build_opts(&maxerr_idx);
11193db86aabSstevel 		if (opts == NULL) {
11203db86aabSstevel 			free((void *)free_cp);
11213db86aabSstevel 			return (CFGA_LIB_ERROR);
11223db86aabSstevel 		}
11233db86aabSstevel 
11243db86aabSstevel 		while (*cp != '\0') {
11253db86aabSstevel 			subopt = getsubopt(&cp, opts, &value);
11263db86aabSstevel 			if (subopt == -1) {
11273db86aabSstevel 				char *hlp;
11283db86aabSstevel 
11293db86aabSstevel 				hlp = subopt_help_str(opts);
11303db86aabSstevel 				if (hlp != NULL) {
11313db86aabSstevel 					__fmt_errstring(errstring,
1132*13c31a0eSToomas Soome 					    strlen(value) + strlen(hlp),
1133*13c31a0eSToomas Soome 					    dgettext(TEXT_DOMAIN, unk_test),
1134*13c31a0eSToomas Soome 					    value, hlp);
11353db86aabSstevel 					free((void *)hlp);
11363db86aabSstevel 				} else {
11373db86aabSstevel 					__fmt_errstring(errstring, 20,
1138*13c31a0eSToomas Soome 					    dgettext(TEXT_DOMAIN, calloc_fail),
1139*13c31a0eSToomas Soome 					    strlen(options) + 1, 1);
11403db86aabSstevel 				}
11413db86aabSstevel 				/* Free after printing value. */
11423db86aabSstevel 				free((void *)free_cp);
11433db86aabSstevel 				return (CFGA_ERROR);
11443db86aabSstevel 			}
11453db86aabSstevel 
11463db86aabSstevel 			if (test_fun != -1 && subopt != test_fun &&
11473db86aabSstevel 			    subopt != maxerr_idx) {
11483db86aabSstevel 				__fmt_errstring(errstring,
11493db86aabSstevel 				    strlen(opts[subopt]),
11503db86aabSstevel 				    dgettext(TEXT_DOMAIN, dup_test),
11513db86aabSstevel 				    opts[subopt]);
11523db86aabSstevel 				free((void *)free_cp);
11533db86aabSstevel 				return (CFGA_ERROR);
11543db86aabSstevel 			}
11553db86aabSstevel 
11563db86aabSstevel 			if (subopt < maxerr_idx)
11573db86aabSstevel 				test_fun = subopt;
11583db86aabSstevel 			else {
11593db86aabSstevel 
11603db86aabSstevel 				if (max_errors != -1 && subopt == maxerr_idx) {
11613db86aabSstevel 					__fmt_errstring(errstring,
1162*13c31a0eSToomas Soome 					    strlen(opts[subopt]),
1163*13c31a0eSToomas Soome 					    dgettext(TEXT_DOMAIN, dup_num),
1164*13c31a0eSToomas Soome 					    opts[subopt]);
11653db86aabSstevel 					free((void *)free_cp);
11663db86aabSstevel 					return (CFGA_ERROR);
11673db86aabSstevel 				}
11683db86aabSstevel 
11693db86aabSstevel 				if (value == NULL) {
11703db86aabSstevel 					__fmt_errstring(errstring,
1171*13c31a0eSToomas Soome 					    0,
1172*13c31a0eSToomas Soome 					    dgettext(TEXT_DOMAIN, no_num),
1173*13c31a0eSToomas Soome 					    "");
11743db86aabSstevel 					free((void *)free_cp);
11753db86aabSstevel 					return (CFGA_ERROR);
11763db86aabSstevel 				}
11773db86aabSstevel 
11783db86aabSstevel 				max_errors = strtol(value, &ret_p, 10);
11793db86aabSstevel 				if ((ret_p == value) || (*ret_p != '\0') ||
11803db86aabSstevel 				    (max_errors < 0)) {
11813db86aabSstevel 					__fmt_errstring(errstring,
1182*13c31a0eSToomas Soome 					    strlen(value),
1183*13c31a0eSToomas Soome 					    dgettext(TEXT_DOMAIN, no_num),
1184*13c31a0eSToomas Soome 					    value);
11853db86aabSstevel 					free((void *)free_cp);
11863db86aabSstevel 					return (CFGA_ERROR);
11873db86aabSstevel 				}
11883db86aabSstevel 			}
11893db86aabSstevel 		}
11903db86aabSstevel 		free((void *)free_cp);
11913db86aabSstevel 	}
11923db86aabSstevel 
11933db86aabSstevel 	if (test_fun == -1)
11943db86aabSstevel 		test_fun = MTEST_DEFAULT_TEST;
11953db86aabSstevel 	if (max_errors == -1)
11963db86aabSstevel 		max_errors = MAX_ERRORS;
11973db86aabSstevel 
11983db86aabSstevel 	ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
11993db86aabSstevel 	if (ret != CFGA_OK)
12003db86aabSstevel 		return (ret);
12013db86aabSstevel 
12023db86aabSstevel 	if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
12033db86aabSstevel 	    stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
12043db86aabSstevel 		__fmt_errstring(errstring, 0,
12053db86aabSstevel 		    dgettext(TEXT_DOMAIN, trans_illegal));
12063db86aabSstevel 		(void) close(fd);
12073db86aabSstevel 		return (CFGA_ERROR);
12083db86aabSstevel 	}
12093db86aabSstevel 
12103db86aabSstevel 	ret = mtest_run(fd, test_fun, &bk,
12113db86aabSstevel 	    ((flags & CFGA_FLAG_VERBOSE) != 0) ? msgp : NULL, errstring,
12123db86aabSstevel 	    (ulong_t)max_errors);
12133db86aabSstevel 
12143db86aabSstevel 	(void) close(fd);
12153db86aabSstevel 
12163db86aabSstevel 	return (ret);
12173db86aabSstevel }
12183db86aabSstevel 
12193db86aabSstevel static cfga_stat_t
rstate_cvt(sysc_cfga_rstate_t rs)12203db86aabSstevel rstate_cvt(sysc_cfga_rstate_t rs)
12213db86aabSstevel {
12223db86aabSstevel 	cfga_stat_t cs;
12233db86aabSstevel 
12243db86aabSstevel 	switch (rs) {
12253db86aabSstevel 	case SYSC_CFGA_RSTATE_EMPTY:
12263db86aabSstevel 		cs = CFGA_STAT_EMPTY;
12273db86aabSstevel 		break;
12283db86aabSstevel 	case SYSC_CFGA_RSTATE_DISCONNECTED:
12293db86aabSstevel 		cs = CFGA_STAT_DISCONNECTED;
12303db86aabSstevel 		break;
12313db86aabSstevel 	case SYSC_CFGA_RSTATE_CONNECTED:
12323db86aabSstevel 		cs = CFGA_STAT_CONNECTED;
12333db86aabSstevel 		break;
12343db86aabSstevel 	default:
12353db86aabSstevel 		cs = CFGA_STAT_NONE;
12363db86aabSstevel 		break;
12373db86aabSstevel 	}
12383db86aabSstevel 
12393db86aabSstevel 	return (cs);
12403db86aabSstevel }
12413db86aabSstevel 
12423db86aabSstevel static cfga_stat_t
ostate_cvt(sysc_cfga_ostate_t os)12433db86aabSstevel ostate_cvt(sysc_cfga_ostate_t os)
12443db86aabSstevel {
12453db86aabSstevel 	cfga_stat_t cs;
12463db86aabSstevel 
12473db86aabSstevel 	switch (os) {
12483db86aabSstevel 	case SYSC_CFGA_OSTATE_UNCONFIGURED:
12493db86aabSstevel 		cs = CFGA_STAT_UNCONFIGURED;
12503db86aabSstevel 		break;
12513db86aabSstevel 	case SYSC_CFGA_OSTATE_CONFIGURED:
12523db86aabSstevel 		cs = CFGA_STAT_CONFIGURED;
12533db86aabSstevel 		break;
12543db86aabSstevel 	default:
12553db86aabSstevel 		cs = CFGA_STAT_NONE;
12563db86aabSstevel 		break;
12573db86aabSstevel 	}
12583db86aabSstevel 
12593db86aabSstevel 	return (cs);
12603db86aabSstevel }
12613db86aabSstevel 
12623db86aabSstevel static cfga_cond_t
cond_cvt(sysc_cfga_cond_t sc)12633db86aabSstevel cond_cvt(sysc_cfga_cond_t sc)
12643db86aabSstevel {
12653db86aabSstevel 	cfga_cond_t cc;
12663db86aabSstevel 
12673db86aabSstevel 	switch (sc) {
12683db86aabSstevel 	case SYSC_CFGA_COND_OK:
12693db86aabSstevel 		cc = CFGA_COND_OK;
12703db86aabSstevel 		break;
12713db86aabSstevel 	case SYSC_CFGA_COND_FAILING:
12723db86aabSstevel 		cc = CFGA_COND_FAILING;
12733db86aabSstevel 		break;
12743db86aabSstevel 	case SYSC_CFGA_COND_FAILED:
12753db86aabSstevel 		cc = CFGA_COND_FAILED;
12763db86aabSstevel 		break;
12773db86aabSstevel 	case SYSC_CFGA_COND_UNUSABLE:
12783db86aabSstevel 		cc = CFGA_COND_UNUSABLE;
12793db86aabSstevel 		break;
12803db86aabSstevel 	case SYSC_CFGA_COND_UNKNOWN:
12813db86aabSstevel 	default:
12823db86aabSstevel 		cc = CFGA_COND_UNKNOWN;
12833db86aabSstevel 		break;
12843db86aabSstevel 	}
12853db86aabSstevel 
12863db86aabSstevel 	return (cc);
12873db86aabSstevel }
12883db86aabSstevel 
12893db86aabSstevel static void
info_set(ac_stat_t * asp,mema_bank_t * bkp,cfga_info_t info)12903db86aabSstevel info_set(ac_stat_t *asp, mema_bank_t *bkp, cfga_info_t info)
12913db86aabSstevel {
12923db86aabSstevel 	mema_disabled_t disab;
12933db86aabSstevel 	uint_t board;
12943db86aabSstevel 	uint_t n;
12953db86aabSstevel 	u_longlong_t decode;
12963db86aabSstevel 	uint_t intlv;
12973db86aabSstevel 	char *f;
12983db86aabSstevel 	char *end;
12993db86aabSstevel 
13003db86aabSstevel 	end = &info[sizeof (cfga_info_t)];
1301*13c31a0eSToomas Soome 	*info = '\0';
13023db86aabSstevel 
13033db86aabSstevel 	board = bkp->board;
13043db86aabSstevel 
13053db86aabSstevel 	/* Print the board number in a way that matches the sysctrl AP. */
13063db86aabSstevel 	info += snprintf(info, end - info, "slot%d", board);
13073db86aabSstevel 
13083db86aabSstevel 	if (asp->real_size == 0) {
13093db86aabSstevel 		info += snprintf(info, end - info, " empty");
13103db86aabSstevel 		return;
13113db86aabSstevel 	}
13123db86aabSstevel 
13133db86aabSstevel 	if ((n = asp->real_size) >= 1024) {
13143db86aabSstevel 		n /= 1024;
13153db86aabSstevel 		f = "Gb";
13163db86aabSstevel 	} else
13173db86aabSstevel 		f = "Mb";
13183db86aabSstevel 	info += snprintf(info, end - info, " %d%s", n, f);
13193db86aabSstevel 
13203db86aabSstevel 	if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
13213db86aabSstevel 	    asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
13223db86aabSstevel 	    asp->use_size != asp->real_size) {
13233db86aabSstevel 		if ((n = asp->use_size) >= 1024) {
13243db86aabSstevel 			n /= 1024;
13253db86aabSstevel 			f = "Gb";
13263db86aabSstevel 		} else
13273db86aabSstevel 			f = "Mb";
13283db86aabSstevel 		info += snprintf(info, end - info, " (%d%s used)", n, f);
13293db86aabSstevel 	}
13303db86aabSstevel 
13313db86aabSstevel 	if (bkp->bank == 0)
13323db86aabSstevel 		decode = asp->ac_decode0;
13333db86aabSstevel 	else
13343db86aabSstevel 		decode = asp->ac_decode1;
13353db86aabSstevel 
13363db86aabSstevel 	info += snprintf(info, end - info, " base 0x%llx",
13373db86aabSstevel 	    GRP_REALBASE(decode));
13383db86aabSstevel 
13393db86aabSstevel 	if (bkp->bank == 0)
13403db86aabSstevel 		intlv = INTLV0(asp->ac_memctl);
13413db86aabSstevel 	else
13423db86aabSstevel 		intlv = INTLV1(asp->ac_memctl);
13433db86aabSstevel 
13443db86aabSstevel 	if (intlv != 1)
13453db86aabSstevel 		info += snprintf(info, end - info, " interleaved %u-way",
13463db86aabSstevel 		    intlv);
13473db86aabSstevel 
13483db86aabSstevel 	if (prom_read_disabled_list(&disab, board)) {
13493db86aabSstevel 		if (disab != 0) {
13503db86aabSstevel 			info += snprintf(info, end - info, " disabled at boot");
13513db86aabSstevel 		}
13523db86aabSstevel 
13533db86aabSstevel 	}
13543db86aabSstevel 
13553db86aabSstevel 	if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
13563db86aabSstevel 	    asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
13573db86aabSstevel 	    asp->nonrelocatable)
13583db86aabSstevel 		info += snprintf(info, end - info, " permanent");
13593db86aabSstevel }
13603db86aabSstevel 
13613db86aabSstevel static void
mema_cvt(ac_stat_t * ac,mema_bank_t * bkp,cfga_stat_data_t * cs)13623db86aabSstevel mema_cvt(ac_stat_t *ac, mema_bank_t *bkp, cfga_stat_data_t *cs)
13633db86aabSstevel {
13643db86aabSstevel 	(void) strcpy(cs->ap_type, "memory");
13653db86aabSstevel 	cs->ap_r_state = rstate_cvt(ac->rstate);
13663db86aabSstevel 	cs->ap_o_state = ostate_cvt(ac->ostate);
13673db86aabSstevel 	cs->ap_cond = cond_cvt(ac->condition);
13683db86aabSstevel 	cs->ap_busy = (cfga_busy_t)ac->busy;
13693db86aabSstevel 	cs->ap_status_time = ac->status_time;
13703db86aabSstevel 	info_set(ac, bkp, cs->ap_info);
1371*13c31a0eSToomas Soome 	cs->ap_log_id[0] = '\0';
1372*13c31a0eSToomas Soome 	cs->ap_phys_id[0] = '\0';
13733db86aabSstevel }
13743db86aabSstevel 
13753db86aabSstevel /*ARGSUSED*/
13763db86aabSstevel cfga_err_t
cfga_stat(const char * ap_id,struct cfga_stat_data * cs,const char * options,char ** errstring)13773db86aabSstevel cfga_stat(
13783db86aabSstevel 	const char *ap_id,
13793db86aabSstevel 	struct cfga_stat_data *cs,
13803db86aabSstevel 	const char *options,
13813db86aabSstevel 	char **errstring)
13823db86aabSstevel {
13833db86aabSstevel 	int ret;
13843db86aabSstevel 	mema_bank_t bk;
13853db86aabSstevel 	ac_stat_t stat;
13863db86aabSstevel 	option_set_t do_option;
13873db86aabSstevel 
13883db86aabSstevel 	if (errstring != NULL)
13893db86aabSstevel 		*errstring = NULL;
13903db86aabSstevel 
13913db86aabSstevel 	ret = 0;
13923db86aabSstevel 	do_option = process_options(options, stat_opts, &ret, errstring);
13933db86aabSstevel 	if (ret != 0)
13943db86aabSstevel 		return (ret);
13953db86aabSstevel 
13963db86aabSstevel 	ret = ap_stat(ap_id, NULL, &bk, &stat, errstring);
13973db86aabSstevel 	if (ret != CFGA_OK)
13983db86aabSstevel 		return (ret);
13993db86aabSstevel 
14003db86aabSstevel 	mema_cvt(&stat, &bk, cs);
14013db86aabSstevel 
14023db86aabSstevel 	ret = prom_do_options(do_option, bk.board, &stat, errstring);
14033db86aabSstevel 
14043db86aabSstevel 	return (ret);
14053db86aabSstevel }
14063db86aabSstevel 
14073db86aabSstevel /*ARGSUSED*/
14083db86aabSstevel cfga_err_t
cfga_list(const char * ap_id,cfga_stat_data_t ** ap_list,int * nlist,const char * options,char ** errstring)14093db86aabSstevel cfga_list(
14103db86aabSstevel 	const char *ap_id,
14113db86aabSstevel 	cfga_stat_data_t **ap_list,
14123db86aabSstevel 	int *nlist,
14133db86aabSstevel 	const char *options,
14143db86aabSstevel 	char **errstring)
14153db86aabSstevel {
14163db86aabSstevel 	if (errstring != NULL)
14173db86aabSstevel 		*errstring = NULL;
14183db86aabSstevel 
14193db86aabSstevel 	return (CFGA_NOTSUPP);
14203db86aabSstevel }
14213db86aabSstevel 
14223db86aabSstevel /*
14233db86aabSstevel  * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
14243db86aabSstevel  */
14253db86aabSstevel 
14263db86aabSstevel /*ARGSUSED*/
14273db86aabSstevel cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)14283db86aabSstevel cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
14293db86aabSstevel {
14303db86aabSstevel 
14313db86aabSstevel 
14323db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, mema_help);
14333db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, disable_opts);
14343db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, enable_opts);
14353db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, timeout_opts);
14363db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, test_opts);
14373db86aabSstevel 	(*msgp->message_routine)(msgp->appdata_ptr, private_funcs);
14383db86aabSstevel 
14393db86aabSstevel 	return (CFGA_OK);
14403db86aabSstevel }
14413db86aabSstevel 
14423db86aabSstevel #if 0
14433db86aabSstevel static ac_mem_version_t
14443db86aabSstevel get_version(int fd)
14453db86aabSstevel {
14463db86aabSstevel 	ac_mem_version_t ver;
14473db86aabSstevel 	int ret, ret_errno;
14483db86aabSstevel 
14493db86aabSstevel 	ver = 0;
14503db86aabSstevel 	dump_ioctl(AC_MEM_ADMIN_VER, &ver);
14513db86aabSstevel 	ret = ioctl(fd, AC_MEM_ADMIN_VER, &ver);
14523db86aabSstevel 	ret_errno = errno;
14533db86aabSstevel 	dump_ioctl_res(AC_MEM_ADMIN_VER, &ver, ret, ret_errno);
14543db86aabSstevel 	return (ver);
14553db86aabSstevel }
14563db86aabSstevel #endif
14573db86aabSstevel 
14583db86aabSstevel static char *
opt_help_str(struct opt_control * opts)14593db86aabSstevel opt_help_str(struct opt_control *opts)
14603db86aabSstevel {
14613db86aabSstevel 	char *str;
14623db86aabSstevel 	const char *sep;
14633db86aabSstevel 	int len;
14643db86aabSstevel 	int i, n;
14653db86aabSstevel 	static const char help_sep[] = ", ";
14663db86aabSstevel 	static const char help_nil[] = "???";
14673db86aabSstevel 
14683db86aabSstevel 	len = 0;
14693db86aabSstevel 	n = 0;
14703db86aabSstevel 	for (i = 0; opts[i].subopt != -1; i++) {
14713db86aabSstevel 		n++;
14723db86aabSstevel 		len += strlen(mema_opts[opts[i].subopt]);
14733db86aabSstevel 	}
14743db86aabSstevel 	if (n == 0)
14753db86aabSstevel 		return (strdup(help_nil));
14763db86aabSstevel 	len += (n - 1) * strlen(help_sep);
14773db86aabSstevel 	len++;
14783db86aabSstevel 	str = (char *)malloc(len);
14793db86aabSstevel 	if (str == NULL)
14803db86aabSstevel 		return (NULL);
14813db86aabSstevel 	*str = '\0';
14823db86aabSstevel 	sep = "";
14833db86aabSstevel 	for (i = 0; opts[i].subopt != -1; i++) {
14843db86aabSstevel 		(void) strcat(str, sep);
14853db86aabSstevel 		(void) strcat(str, mema_opts[opts[i].subopt]);
14863db86aabSstevel 		sep = help_sep;
14873db86aabSstevel 	}
14883db86aabSstevel 	return (str);
14893db86aabSstevel }
14903db86aabSstevel 
14913db86aabSstevel static option_set_t
process_options(const char * options,struct opt_control * opts,int * retp,char ** errstring)14923db86aabSstevel process_options(
14933db86aabSstevel 	const char *options,
14943db86aabSstevel 	struct opt_control *opts,
14953db86aabSstevel 	int *retp,
14963db86aabSstevel 	char **errstring)
14973db86aabSstevel {
14983db86aabSstevel 	option_set_t opt_set;
14993db86aabSstevel 	char *optcopy, *optcopy_alloc;
15003db86aabSstevel 	char *value;
15013db86aabSstevel 	int subopt;
15023db86aabSstevel 	int subopt_err;
15033db86aabSstevel 	int i;
15043db86aabSstevel 	int group;
15053db86aabSstevel 	int need_value;
15063db86aabSstevel 
15073db86aabSstevel 	OPTSET_INIT(opt_set);
15083db86aabSstevel 
15093db86aabSstevel 	if (options == NULL || *options == '\0') {
15103db86aabSstevel 		return (opt_set);
15113db86aabSstevel 	}
15123db86aabSstevel 
15133db86aabSstevel 	optcopy = optcopy_alloc = strdup(options);
15143db86aabSstevel 	if (optcopy_alloc == NULL) {
15153db86aabSstevel 		__fmt_errstring(errstring, 20,
15163db86aabSstevel 		    dgettext(TEXT_DOMAIN, calloc_fail), strlen(options) + 1, 1);
15173db86aabSstevel 		*retp = CFGA_LIB_ERROR;
15183db86aabSstevel 		return (opt_set);
15193db86aabSstevel 	}
15203db86aabSstevel 
15213db86aabSstevel 	subopt_err = 0;
15223db86aabSstevel 	while (*optcopy != '\0' && subopt_err == 0) {
15233db86aabSstevel 		subopt = getsubopt(&optcopy, mema_opts, &value);
15243db86aabSstevel 		if (subopt == -1) {
15253db86aabSstevel 			char *hlp;
15263db86aabSstevel 
15273db86aabSstevel 			hlp = opt_help_str(opts);
15283db86aabSstevel 			__fmt_errstring(errstring, strlen(value) + strlen(hlp),
15293db86aabSstevel 			    dgettext(TEXT_DOMAIN, unk_subopt), value, hlp);
15303db86aabSstevel 			free((void *)hlp);
15313db86aabSstevel 			subopt_err = 1;
15323db86aabSstevel 			break;
15333db86aabSstevel 		}
15343db86aabSstevel 		for (i = 0; opts[i].subopt != -1; i++) {
15353db86aabSstevel 			if (opts[i].subopt == subopt) {
15363db86aabSstevel 				group = opts[i].group;
15373db86aabSstevel 				break;
15383db86aabSstevel 			}
15393db86aabSstevel 		}
15403db86aabSstevel 		if (opts[i].subopt == -1) {
15413db86aabSstevel 			char *hlp;
15423db86aabSstevel 
15433db86aabSstevel 			hlp = opt_help_str(opts);
15443db86aabSstevel 			__fmt_errstring(errstring,
15453db86aabSstevel 			    MAX_OPT_LENGTH + strlen(hlp),
15463db86aabSstevel 			    dgettext(TEXT_DOMAIN, not_valid),
15473db86aabSstevel 			    mema_opts[subopt], hlp);
15483db86aabSstevel 			free((void *)hlp);
15493db86aabSstevel 			subopt_err = 1;
15503db86aabSstevel 			break;
15513db86aabSstevel 		}
15523db86aabSstevel 		need_value = OPT_NEEDS_VALUE(subopt);
15533db86aabSstevel 		if (!need_value && value != NULL) {
15543db86aabSstevel 			__fmt_errstring(errstring, MAX_OPT_LENGTH,
15553db86aabSstevel 			    dgettext(TEXT_DOMAIN, no_value),
15563db86aabSstevel 			    mema_opts[subopt]);
15573db86aabSstevel 			subopt_err = 1;
15583db86aabSstevel 			break;
15593db86aabSstevel 		}
15603db86aabSstevel 		if (need_value && value == NULL) {
15613db86aabSstevel 			__fmt_errstring(errstring, MAX_OPT_LENGTH,
15623db86aabSstevel 			    dgettext(TEXT_DOMAIN, missing_value),
15633db86aabSstevel 			    mema_opts[subopt]);
15643db86aabSstevel 			subopt_err = 1;
15653db86aabSstevel 			break;
15663db86aabSstevel 		}
15673db86aabSstevel 		if (OPTSET_TEST(opt_set, subopt)) {
15683db86aabSstevel 			/* Ignore repeated options. */
15693db86aabSstevel 			continue;
15703db86aabSstevel 		}
15713db86aabSstevel 		if (group != 0 && !OPTSET_IS_EMPTY(opt_set)) {
15723db86aabSstevel 			for (i = 0; opts[i].subopt != -1; i++) {
15733db86aabSstevel 				if (i == subopt)
15743db86aabSstevel 					continue;
15753db86aabSstevel 				if (opts[i].group == group &&
15763db86aabSstevel 				    OPTSET_TEST(opt_set, opts[i].subopt))
15773db86aabSstevel 					break;
15783db86aabSstevel 			}
15793db86aabSstevel 			if (opts[i].subopt != -1) {
15803db86aabSstevel 				__fmt_errstring(errstring, MAX_OPT_LENGTH * 2,
15813db86aabSstevel 				    dgettext(TEXT_DOMAIN, conflict_opt),
15823db86aabSstevel 				    mema_opts[subopt],
15833db86aabSstevel 				    mema_opts[opts[i].subopt]);
15843db86aabSstevel 				subopt_err = 1;
15853db86aabSstevel 				break;
15863db86aabSstevel 			}
15873db86aabSstevel 		}
15883db86aabSstevel 		OPTSET_SET_VAL(opt_set, subopt, value);
15893db86aabSstevel 	}
15903db86aabSstevel 	free((void *)optcopy_alloc);
15913db86aabSstevel 	if (subopt_err) {
15923db86aabSstevel 		*retp = CFGA_ERROR;
15933db86aabSstevel 	}
15943db86aabSstevel 
15953db86aabSstevel 	return (opt_set);
15963db86aabSstevel }
15973db86aabSstevel 
15983db86aabSstevel #ifdef DEV_DEBUG
15993db86aabSstevel 
16003db86aabSstevel static int
debugging(void)16013db86aabSstevel debugging(void)
16023db86aabSstevel {
16033db86aabSstevel 	char *ep;
16043db86aabSstevel 	static int inited;
16053db86aabSstevel 
16063db86aabSstevel 	if (inited)
16073db86aabSstevel 		return (debug_fp != NULL);
16083db86aabSstevel 	inited = 1;
16093db86aabSstevel 
16103db86aabSstevel 	if ((ep = getenv("MEMADM_DEBUG")) == NULL) {
16113db86aabSstevel 		return (0);
16123db86aabSstevel 	}
16133db86aabSstevel 	if (*ep == '\0')
16143db86aabSstevel 		debug_fp = stderr;
16153db86aabSstevel 	else {
16163db86aabSstevel 		if ((debug_fp = fopen(ep, "a")) == NULL)
16173db86aabSstevel 			return (0);
16183db86aabSstevel 	}
16193db86aabSstevel 	(void) fprintf(debug_fp, "\nDebug started, pid=%d\n", (int)getpid());
16203db86aabSstevel 	return (1);
16213db86aabSstevel }
16223db86aabSstevel 
16233db86aabSstevel static void
dump_ioctl(int cmd,void * arg)16243db86aabSstevel dump_ioctl(
16253db86aabSstevel 	int cmd,
16263db86aabSstevel 	void *arg)
16273db86aabSstevel {
16283db86aabSstevel 	if (!debugging())
16293db86aabSstevel 		return;
16303db86aabSstevel 
16313db86aabSstevel 	switch (cmd) {
16323db86aabSstevel 	case AC_MEM_CONFIGURE:
16333db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_CONFIGURE\n");
16343db86aabSstevel 		break;
16353db86aabSstevel 
16363db86aabSstevel 	case AC_MEM_UNCONFIGURE:
16373db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_UNCONFIGURE\n");
16383db86aabSstevel 		break;
16393db86aabSstevel 
16403db86aabSstevel 	case AC_MEM_TEST_START:
16413db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_START\n");
16423db86aabSstevel 		break;
16433db86aabSstevel 
16443db86aabSstevel 	case AC_MEM_TEST_STOP: {
16453db86aabSstevel 		ac_mem_test_stop_t *tstop;
16463db86aabSstevel 
16473db86aabSstevel 		tstop = (ac_mem_test_stop_t *)arg;
16483db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_STOP handle=%#x "
16493db86aabSstevel 		    "condition=%d\n", tstop->handle, tstop->condition);
16503db86aabSstevel 	}
16513db86aabSstevel 		break;
16523db86aabSstevel 	case AC_MEM_TEST_READ: {
16533db86aabSstevel 		ac_mem_test_read_t *tread;
16543db86aabSstevel 
16553db86aabSstevel 		tread = (ac_mem_test_read_t *)arg;
16563db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_READ handle=%#x "
16573db86aabSstevel 		    "buf=%#p page=%#llx off=%#x count=%#x\n",
16583db86aabSstevel 		    tread->handle, tread->page_buf,
16593db86aabSstevel 		    tread->address.page_num,
16603db86aabSstevel 		    tread->address.line_offset, tread->address.line_count);
16613db86aabSstevel 	}
16623db86aabSstevel 		break;
16633db86aabSstevel 	case AC_MEM_TEST_WRITE: {
16643db86aabSstevel 		ac_mem_test_write_t *twrite;
16653db86aabSstevel 
16663db86aabSstevel 		twrite = (ac_mem_test_write_t *)arg;
16673db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_WRITE handle=%#x "
16683db86aabSstevel 		    "buf=%#p page=%#llx off=%#x count=%#x\n",
16693db86aabSstevel 		    twrite->handle, twrite->page_buf,
16703db86aabSstevel 		    twrite->address.page_num,
16713db86aabSstevel 		    twrite->address.line_offset, twrite->address.line_count);
16723db86aabSstevel 	}
16733db86aabSstevel 		break;
16743db86aabSstevel 	case AC_MEM_ADMIN_VER:
16753db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_ADMIN_VER:\n");
16763db86aabSstevel 		break;
16773db86aabSstevel 	case AC_MEM_STAT:
16783db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_STAT\n");
16793db86aabSstevel 		break;
16803db86aabSstevel 	case AC_MEM_EXERCISE: {
16813db86aabSstevel 		ac_cfga_cmd_t *cmdp;
16823db86aabSstevel 
16833db86aabSstevel 		cmdp = arg;
16843db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: AC_MEM_EXERCISE arg=%d\n",
16853db86aabSstevel 		    cmdp->arg);
16863db86aabSstevel 		break;
16873db86aabSstevel 	}
16883db86aabSstevel 	default:
16893db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL: unknown (%#x)\n", cmd);
16903db86aabSstevel 		break;
16913db86aabSstevel 	}
16923db86aabSstevel 	(void) fflush(debug_fp);
16933db86aabSstevel }
16943db86aabSstevel 
16953db86aabSstevel static void
dump_ioctl_res(int cmd,void * arg,int ret,int ret_errno)16963db86aabSstevel dump_ioctl_res(
16973db86aabSstevel 	int cmd,
16983db86aabSstevel 	void *arg,
16993db86aabSstevel 	int ret,
17003db86aabSstevel 	int ret_errno)
17013db86aabSstevel {
17023db86aabSstevel 	if (!debugging())
17033db86aabSstevel 		return;
17043db86aabSstevel 
17053db86aabSstevel 	if (ret == -1) {
17063db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL failed, \"%s\" (errno=%d)\n",
17073db86aabSstevel 		    strerror(ret_errno), ret_errno);
17083db86aabSstevel 		(void) fflush(debug_fp);
17093db86aabSstevel 		return;
17103db86aabSstevel 	} else {
17113db86aabSstevel 		(void) fprintf(debug_fp, "IOCTL succeeded, ret=%d\n", ret);
17123db86aabSstevel 	}
17133db86aabSstevel 
17143db86aabSstevel 	switch (cmd) {
17153db86aabSstevel 	case AC_MEM_CONFIGURE:
17163db86aabSstevel 	case AC_MEM_UNCONFIGURE:
17173db86aabSstevel 		break;
17183db86aabSstevel 	case AC_MEM_TEST_START: {
17193db86aabSstevel 		ac_mem_test_start_t *tstart;
17203db86aabSstevel 
17213db86aabSstevel 		tstart = (ac_mem_test_start_t *)arg;
17223db86aabSstevel 		(void) fprintf(debug_fp, "    handle=%#x tester_pid=%d "
17233db86aabSstevel 		    "prev_condition=%d bank_size=%#llx "
17243db86aabSstevel 		    "page_size=%#x line_size=%#x afar_base=%#llx\n",
17253db86aabSstevel 		    tstart->handle, (int)tstart->tester_pid,
17263db86aabSstevel 		    tstart->prev_condition,
17273db86aabSstevel 		    tstart->bank_size, tstart->page_size,
17283db86aabSstevel 		    tstart->line_size, tstart->afar_base);
17293db86aabSstevel 	}
17303db86aabSstevel 		break;
17313db86aabSstevel 	case AC_MEM_TEST_STOP:
17323db86aabSstevel 		break;
17333db86aabSstevel 	case AC_MEM_TEST_READ: {
17343db86aabSstevel 		ac_mem_test_read_t *tread;
17353db86aabSstevel 		sunfire_processor_error_regs_t *err;
17363db86aabSstevel 
17373db86aabSstevel 		tread = (ac_mem_test_read_t *)arg;
17383db86aabSstevel 		err = tread->error_buf;
17393db86aabSstevel 		if (ret_errno == EIO) {
17403db86aabSstevel 			(void) fprintf(debug_fp, "module_id=%#llx afsr=%#llx "
17413db86aabSstevel 			    "afar=%#llx udbh_error_reg=%#llx "
17423db86aabSstevel 			    "udbl_error_reg=%#llx\n",
17433db86aabSstevel 			    (longlong_t)err->module_id, (longlong_t)err->afsr,
17443db86aabSstevel 			    (longlong_t)err->afar,
17453db86aabSstevel 			    (longlong_t)err->udbh_error_reg,
17463db86aabSstevel 			    (longlong_t)err->udbl_error_reg);
17473db86aabSstevel 		} else {
17483db86aabSstevel 			(void) fprintf(debug_fp, "\n");
17493db86aabSstevel 		}
17503db86aabSstevel 	}
17513db86aabSstevel 		break;
17523db86aabSstevel 	case AC_MEM_TEST_WRITE:
17533db86aabSstevel 		break;
17543db86aabSstevel 	case AC_MEM_ADMIN_VER: {
17553db86aabSstevel 		ac_mem_version_t *ver;
17563db86aabSstevel 
17573db86aabSstevel 		ver = (ac_mem_version_t *)arg;
17583db86aabSstevel 		(void) fprintf(debug_fp, "    version %d\n", *ver);
17593db86aabSstevel 	}
17603db86aabSstevel 		break;
17613db86aabSstevel 	case AC_MEM_STAT: {
17623db86aabSstevel 		ac_stat_t *tstat;
17633db86aabSstevel 
17643db86aabSstevel 		tstat = (ac_stat_t *)arg;
17653db86aabSstevel 		(void) fprintf(debug_fp, "    rstate=%u ostate=%u "
17663db86aabSstevel 		    "condition=%u status_time=%#lx board=%u\n",
17673db86aabSstevel 		    (uint_t)tstat->rstate, (uint_t)tstat->ostate,
17683db86aabSstevel 		    (uint_t)tstat->condition, (ulong_t)tstat->status_time,
17693db86aabSstevel 		    tstat->board);
17703db86aabSstevel 		(void) fprintf(debug_fp, "    real_size=%u use_size=%u "
17713db86aabSstevel 		    "busy=%u\n",
17723db86aabSstevel 		    tstat->real_size, tstat->use_size, tstat->busy);
17733db86aabSstevel 		(void) fprintf(debug_fp, "    page_size=%#x "
17743db86aabSstevel 		    "phys_pages=%#llx managed=%#llx nonrelocatable=%#llx\n",
17753db86aabSstevel 		    tstat->page_size, (longlong_t)tstat->phys_pages,
17763db86aabSstevel 		    (longlong_t)tstat->managed,
17773db86aabSstevel 		    (longlong_t)tstat->nonrelocatable);
17783db86aabSstevel 		(void) fprintf(debug_fp, "    memctl=%#llx "
17793db86aabSstevel 		    "decode0=%#llx decode1=%#llx\n",
17803db86aabSstevel 		    (longlong_t)tstat->ac_memctl, (longlong_t)tstat->ac_decode0,
17813db86aabSstevel 		    (longlong_t)tstat->ac_decode1);
17823db86aabSstevel 	}
17833db86aabSstevel 		break;
17843db86aabSstevel 	case AC_MEM_EXERCISE: {
17853db86aabSstevel 		ac_cfga_cmd_t *cmdp;
17863db86aabSstevel 
17873db86aabSstevel 		cmdp = arg;
17883db86aabSstevel 		switch (cmdp->arg) {
17893db86aabSstevel 		case AC_MEMX_RELOCATE_ALL: {
17903db86aabSstevel 			struct ac_memx_relocate_stats *stp;
17913db86aabSstevel 
17923db86aabSstevel 			if ((stp = cmdp->private) != NULL) {
17933db86aabSstevel 				(void) fprintf(debug_fp, "    base=%u npgs=%u"
17943db86aabSstevel 				    " nopaget=%u nolock=%u isfree=%u reloc=%u"
17953db86aabSstevel 				    " noreloc=%u\n",
17963db86aabSstevel 				    stp->base, stp->npgs, stp->nopaget,
17973db86aabSstevel 				    stp->nolock, stp->isfree, stp->reloc,
17983db86aabSstevel 				    stp->noreloc);
17993db86aabSstevel 			}
18003db86aabSstevel 			break;
18013db86aabSstevel 		}
18023db86aabSstevel 		default:
18033db86aabSstevel 			break;
18043db86aabSstevel 		}
18053db86aabSstevel 		break;
18063db86aabSstevel 	}
18073db86aabSstevel 	default:
18083db86aabSstevel 		break;
18093db86aabSstevel 	}
18103db86aabSstevel 	(void) fflush(debug_fp);
18113db86aabSstevel }
18123db86aabSstevel #endif /* DEV_DEBUG */
1813