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);
548