summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorstevel <none@none>2006-06-29 14:43:12 -0700
committerstevel <none@none>2006-06-29 14:43:12 -0700
commit3db86aab554edbb4244c8d1a1c90f152eee768af (patch)
tree705cf08ad6c4913d9bf209e3b319816d99d03779 /usr/src/lib
parente34b029407ed5ec566196ede3f54256d7868dd10 (diff)
downloadillumos-joyent-3db86aab554edbb4244c8d1a1c90f152eee768af.tar.gz
6392835 move driver central to usr/src
6392843 move driver socal to usr/src 6393456 move driver pcic to usr/src 6393457 move driver pem to usr/src 6393459 move driver envctrltwo to usr/src 6393461 move driver lombus to usr/src 6393465 move driver rmclomv to usr/src 6393468 move driver wrsmd to usr/src 6438236 cfgadm plugins for ac & sysctrl want to be reunited with their drivers in usr/src 6443714 CardBus driver should be moved from usr/closed to usr/src
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/cfgadm_plugins/Makefile9
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/Makefile74
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/Makefile.com99
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/ac.xcl114
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mapfile-vers38
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema.c1814
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_prom.c270
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_prom.h49
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_test.c723
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_test.h127
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_test_config.c79
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_test_subr.c98
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_util.c81
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/common/mema_util.h42
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/sparc/Makefile34
-rw-r--r--usr/src/lib/cfgadm_plugins/ac/sparcv9/Makefile35
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/Makefile73
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/Makefile.com99
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/common/cfga.c1480
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/common/mapfile-vers38
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/sparc/Makefile34
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/sparcv9/Makefile35
-rw-r--r--usr/src/lib/cfgadm_plugins/sysctrl/sysctrl.xcl94
23 files changed, 5532 insertions, 7 deletions
diff --git a/usr/src/lib/cfgadm_plugins/Makefile b/usr/src/lib/cfgadm_plugins/Makefile
index a2afd72d10..399a8e3a8d 100644
--- a/usr/src/lib/cfgadm_plugins/Makefile
+++ b/usr/src/lib/cfgadm_plugins/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -29,16 +29,11 @@
include $(SRC)/Makefile.master
-CLOSED_PLUGIN = $(CLOSED)/lib/cfgadm_plugins/
-
COMMON_SUBDIRS= scsi pci usb ib
-sparc_SUBDIRS= sbd
+sparc_SUBDIRS= sbd ac sysctrl
i386_SUBDIRS= sata
-$(CLOSED_BUILD)sparc_SUBDIRS += $(CLOSED_PLUGIN)/ac
-$(CLOSED_BUILD)sparc_SUBDIRS += $(CLOSED_PLUGIN)/sysctrl
-
SUBDIRS= $(COMMON_SUBDIRS) $($(MACH)_SUBDIRS)
ALL_SUBDIRS= $(COMMON_SUBDIRS) $(sparc_SUBDIRS) $(i386_SUBDIRS)
diff --git a/usr/src/lib/cfgadm_plugins/ac/Makefile b/usr/src/lib/cfgadm_plugins/ac/Makefile
new file mode 100644
index 0000000000..09d804f547
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/Makefile
@@ -0,0 +1,74 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/cfgadm_plugins/ac/Makefile
+
+include $(SRC)/Makefile.master
+
+SUBDIRS= $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+catalog := TARGET= catalog
+package := TARGET= package
+
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a -x ac.xcl
+POFILE= ac.po
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber delete install lint catalog package: $(SUBDIRS)
+
+$(MACH) $(MACH64): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext */*.[ch]`
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+FRC:
diff --git a/usr/src/lib/cfgadm_plugins/ac/Makefile.com b/usr/src/lib/cfgadm_plugins/ac/Makefile.com
new file mode 100644
index 0000000000..c7aa48aadc
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/Makefile.com
@@ -0,0 +1,99 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/ac/Makefile.com
+
+include $(SRC)/lib/cfgadm_plugins/Makefile.com
+
+PLATFORM= sun4u
+LIBRARY= ac.a
+VERS= .1
+
+OBJECTS= mema.o mema_prom.o mema_test.o mema_test_config.o mema_test_subr.o \
+ mema_util.o
+
+# include library definitions
+include $(SRC)/lib/Makefile.lib
+
+INS.dir.root.sys= $(INS) -s -d -m $(DIRMODE) $@
+$(CH)INS.dir.root.sys= $(INS) -s -d -m $(DIRMODE) -u root -g sys $@
+INS.dir.root.bin= $(INS) -s -d -m $(DIRMODE) $@
+$(CH)INS.dir.root.bin= $(INS) -s -d -m $(DIRMODE) -u root -g bin $@
+
+USR_PLAT_DIR = $(ROOT)/usr/platform
+USR_PSM_DIR = $(USR_PLAT_DIR)/sun4u
+USR_PSM_LIB_DIR = $(USR_PSM_DIR)/lib
+USR_PSM_LIB_CFG_DIR = $(USR_PSM_LIB_DIR)/cfgadm
+USR_PSM_LIB_CFG_DIR_64 = $(USR_PSM_LIB_CFG_DIR)/$(MACH64)
+
+ROOTLIBDIR= $(USR_PSM_LIB_CFG_DIR)
+ROOTLIBDIR64= $(USR_PSM_LIB_CFG_DIR_64)
+
+MAPFILE= ../common/mapfile-vers
+SRCS= $(OBJECTS:%.o=../common/%.c)
+
+LIBS = $(DYNLIB)
+
+CFLAGS += $(CCVERBOSE)
+DYNFLAGS += -M $(MAPFILE)
+LDLIBS += -lc
+
+CPPFLAGS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(DYNLIB): $(MAPFILE)
+
+# Create target directories
+$(USR_PSM_DIR): $(LINKED_DIRS)
+ -$(INS.dir.root.sys)
+
+$(USR_PSM_LIB_DIR): $(USR_PSM_DIR) $(LINKED_LIB_DIRS)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR): $(USR_PSM_LIB_DIR) $(LINKED_CFG_DIRS)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR_64): $(USR_PSM_LIB_CFG_DIR)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR)/%: % $(USR_PSM_LIB_CFG_DIR)
+ -$(INS.file)
+
+$(USR_PSM_LIB_CFG_DIR_64)/%: % $(USR_PSM_LIB_CFG_DIR_64)
+ -$(INS.file)
+
+# include library targets
+include $(SRC)/lib/Makefile.targ
+
+pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/cfgadm_plugins/ac/ac.xcl b/usr/src/lib/cfgadm_plugins/ac/ac.xcl
new file mode 100644
index 0000000000..a42c3d6301
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/ac.xcl
@@ -0,0 +1,114 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+msgid "disable-at-boot"
+msgid "enable-at-boot"
+msgid "timeout"
+msgid "errno=%d"
+msgid "bank"
+msgid "ap_bk_idx(%s)\n"
+msgid "ap_bk_idx: s=%s, n=%d\n"
+msgid "ap_bk_idx(%s)=%d\n"
+msgid "relocate-test"
+msgid "board %d bank%d"
+msgid ", "
+msgid "???"
+msgid ""
+msgid "slot%d"
+msgid " empty"
+msgid "Gb"
+msgid "Mb"
+msgid " %d%s"
+msgid " (%d%s used)"
+msgid " base 0x%llx"
+msgid " interleaved %u-way"
+msgid " %s"
+msgid "disabled at boot"
+msgid " permanent"
+msgid "memory"
+msgid "ap_drv_idx(%s)\n"
+msgid "ac"
+msgid "ap_drv_idx(%s)=%d\n"
+msgid "MEMADM_DEBUG"
+msgid "a"
+msgid "\nDebug started, pid=%d\n"
+msgid "IOCTL: AC_MEM_CONFIGURE\n"
+msgid "IOCTL: AC_MEM_UNCONFIGURE\n"
+msgid "IOCTL: AC_MEM_TEST_START\n"
+msgid "IOCTL: AC_MEM_TEST_STOP handle=%#x "
+ "condition=%d\n"
+msgid "IOCTL: AC_MEM_TEST_READ handle=%#x "
+ "buf=%#x page=%#llx off=%#x count=%#x\n"
+msgid "IOCTL: AC_MEM_TEST_WRITE handle=%#x "
+ "buf=%#x page=%#llx off=%#x count=%#x\n"
+msgid "IOCTL: AC_MEM_ADMIN_VER:\n"
+msgid "IOCTL: AC_MEM_STAT\n"
+msgid "IOCTL: AC_MEM_EXERCISE arg=%d\n"
+msgid "IOCTL: unknown (%#x)\n"
+msgid "IOCTL failed, \"%s\" (errno=%d)\n"
+msgid "IOCTL succeeded, ret=%d\n"
+msgid " handle=%#x tester_pid=%d "
+ "prev_condition=%d bank_size=%#llx "
+ "page_size=%#x line_size=%#x afar_base=%#llx\n"
+msgid "module_id=%#llx afsr=%#llx "
+ "afar=%#llx udbh_error_reg=%#llx "
+ "udbl_error_reg=%#llx\n"
+msgid "\n"
+msgid " version %d\n"
+msgid " rstate=%u ostate=%u "
+ "condition=%u status_time=%#lx board=%u\n"
+msgid " real_size=%u use_size=%u "
+ "busy=%u\n"
+msgid " page_size=%#x "
+ "phys_pages=%#llx managed=%#llx nonrelocatable=%#llx\n"
+msgid " memctl=%#llx "
+ "decode0=%#llx decode1=%#llx\n"
+msgid " base=%u npgs=%u"
+ " nopaget=%u nolock=%u isfree=%u reloc=%u"
+ " noreloc=%u\n"
+msgid "total error %u\n"
+msgid "quick"
+msgid "normal"
+msgid "extended"
+msgid "max_errors"
+msgid "Normal test started\n"
+msgid "Normal test finished\n"
+msgid "Quick test started\n"
+msgid "Quick test finished\n"
+msgid "Extended test started\n"
+msgid "Extended test finished\n"
+msgid " March 1, "
+msgid " March 2, "
+msgid " March 3, "
+msgid " March 4, "
+msgid "read. "
+msgid "write. "
+msgid "compare. "
+msgid "read/compare. "
+msgid "repeated read/compare. "
+msgid "mixed line read/compare. "
+msgid "line read/compare. "
+msgid "%s%s%d%% complete.\n"
+msgid " Errors at page address: 0x%x.\n"
+msgid " Error reading page at address: 0x%x.\n"
+msgid " Error writing page at address: 0x%x.\n"
+msgid " Offset: 0x%x, data written/read: 0x%2x/0x%2x.\n"
+msgid "\t-o {quick, normal, extended},[max_errors=#] -t ap_id [ap_id...]\n"
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mapfile-vers b/usr/src/lib/cfgadm_plugins/ac/common/mapfile-vers
new file mode 100644
index 0000000000..b535a50cf7
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mapfile-vers
@@ -0,0 +1,38 @@
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+SUNWprivate_1.1 {
+ global:
+ cfga_change_state;
+ cfga_private_func;
+ cfga_test;
+ cfga_stat;
+ cfga_list;
+ cfga_help;
+ local:
+ *;
+};
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema.c b/usr/src/lib/cfgadm_plugins/ac/common/mema.c
new file mode 100644
index 0000000000..1b08d13f92
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema.c
@@ -0,0 +1,1814 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <locale.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/dditypes.h>
+#include <sys/param.h>
+#include <sys/obpdefs.h>
+#include <sys/fhc.h>
+#include <sys/sysctrl.h>
+#include <sys/ac.h>
+#include <sys/spitregs.h>
+#include <config_admin.h>
+#include "mema_util.h"
+#include "mema_test.h"
+#include "mema_prom.h"
+
+#ifdef DEBUG
+#define DBG (void) printf
+#define DBG1 (void) printf
+#define DBG3 (void) printf
+#define DBG4 (void) printf
+#else
+#define DBG(a, b)
+#define DBG1(a)
+#define DBG3(a, b, c)
+#define DBG4(a, b, c, d)
+#endif
+
+#ifndef P_DER_UE
+/*
+ * <sys/spitregs.h> has these defines inside 'ifdef _KERNEL' at the
+ * time of writing. Re-define here if that is still the case.
+ */
+
+#define P_DER_UE 0x00000000000000200ULL /* UE has occurred */
+#define P_DER_CE 0x00000000000000100ULL /* CE has occurred */
+#define P_DER_E_SYND 0x000000000000000FFULL /* SYND<7:0>: ECC syndrome */
+#endif /* ! P_DER_UE */
+
+#define DEV_DEBUG
+#ifdef DEV_DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+
+static FILE *debug_fp;
+static int debugging(void);
+static void dump_ioctl(int, void *);
+static void dump_ioctl_res(int, void *, int, int);
+#else /* DEV_DEBUG */
+#define dump_ioctl(CMD, ARG)
+#define dump_ioctl_res(CMD, ARG, RET, ERRNO)
+#endif /* DEV_DEBUG */
+
+typedef struct {
+ uint_t board;
+ uint_t bank;
+} mema_bank_t;
+
+static char *mema_opts[] = {
+#define OPT_BOOT_DISABLE 0
+ "disable-at-boot",
+#define OPT_BOOT_ENABLE 1
+ "enable-at-boot",
+#define OPT_TIMEOUT 2
+ "timeout",
+ NULL
+};
+
+#define OPT_NEEDS_VALUE(O) ((O) == OPT_TIMEOUT)
+
+#define MAX_OPT_LENGTH (sizeof ("disable-at-boot"))
+
+/*
+ * For each function there is an array of opt_control structures giving
+ * the valid options. The array is terminated by an element with the
+ * subopt field set to -1. The group field is used to identify
+ * mutually exclusive options, with zero meaning no grouping.
+ */
+struct opt_control {
+ int subopt;
+ int group;
+};
+
+/*
+ * Returned set of options.
+ * If the option takes a value, it will be set in 'val'
+ * if the corresponding bit is set in 'bits' is set,
+ * otherwise the pointer in 'val' is undefined.
+ */
+#define OPT_VAL_ARRAY_SIZE 32 /* # bits in 'bits' */
+typedef struct {
+ unsigned int bits;
+ char *val[OPT_VAL_ARRAY_SIZE];
+} option_set_t;
+
+#define OPTSET_INIT(S) ((S).bits = 0)
+#define _OPT_TO_BIT(O) (1 << (O))
+#define OPTSET_SET_VAL(S, O, V) ((S).bits |= _OPT_TO_BIT(O), \
+ (S).val[(O)] = (V))
+#define OPTSET_TEST(S, O) (((S).bits & _OPT_TO_BIT(O)) != 0)
+#define OPTSET_VAL(S, O) ((S).val[(O)])
+#define OPTSET_IS_EMPTY(S) ((S).bits == 0)
+
+static option_set_t process_options(const char *, struct opt_control *,
+ int *, char **);
+
+static struct opt_control add_opts[] = {
+ {OPT_BOOT_ENABLE, 1},
+ {OPT_BOOT_DISABLE, 1},
+ {-1, 0}
+};
+
+static struct opt_control del_opts[] = {
+ {OPT_BOOT_ENABLE, 1},
+ {OPT_BOOT_DISABLE, 1},
+ {OPT_TIMEOUT, 2},
+ {-1, 0}
+};
+
+static struct opt_control stat_opts[] = {
+ {OPT_BOOT_ENABLE, 1},
+ {OPT_BOOT_DISABLE, 1},
+ {-1, 0}
+};
+
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+
+static const char still_testing[] = "bank %s being tested by process %d";
+static const char no_value[] = "sub-option \"%s\" does not take a value";
+static const char missing_value[] = "sub-option \"%s\" needs a value";
+static const char conflict_opt[] = "sub-option \"%s\" conflicts with \"%s\"";
+static const char unk_subopt[] = "sub-option \"%s\" unknown\n"
+ "choose from: %s";
+static const char not_valid[] =
+ "sub-option \"%s\" not valid for this operation\n"
+ "choose from: %s";
+static const char timeout_notnum[] =
+ "timeout value not a positive integer \"%s\"";
+static const char calloc_fail[] = "memory allocation failed (%d*%d bytes)";
+static const char unk_test[] = "test \"%s\" unknown\n"
+ "choose from: %s";
+static const char dup_test[] = "more than one test type specified (\"%s\")";
+static const char dup_num[] = "option specified more than once (\"%s\")";
+static const char no_num[] = "invalid number specified for max_errors(\"%s\")";
+static const char mtest_rw_error[] = "memory test read/write error";
+static const char mtest_lib_error[] = "memory test library error";
+static const char dlist_invalid[] = "invalid disabled-memory-list";
+static const char dlist_write_failed[] = "disabled-memory-list write failed";
+static const char mtest_unknown_error[] = "unknown memory test error";
+static const char ap_invalid[] = "invalid attachment point: %s";
+static const char trans_illegal[] = "illegal transition";
+static const char open_failed[] = "open failed: %s: %s";
+static const char mema_help[] = "\nAc specific options:\n";
+static const char disable_opts[] = "\t-o disable-at-boot\n";
+static const char enable_opts[] = "\t-o enable-at-boot\n";
+static const char timeout_opts[] = "\t-o timeout=# (seconds)\n";
+static const char test_opts[] =
+ "\t-o {quick, normal, extended},[max_errors=#] -t ap_id [ap_id...]\n";
+static const char private_funcs[] = "\t-x relocate-test ap_id [ap_id...]\n";
+static const char add_is_disabled[] = "memory is disabled at boot";
+static const char add_willbe_disabled[] =
+ "memory will be disabled at boot";
+static const char add_disab_err[] = "cannot get memory disabled status";
+static const char pfunc_unknown[] = "private function \"%s\" unknown";
+
+
+#define mema_eid(a, b) (((a) << 8) + (b))
+#define mema_str(i) mema_strs[(i)]
+
+#define AC_BK_BUSY 0
+#define AC_BK_ID 1
+#define AC_BD_ID 2
+#define AC_BD_TYPE 3
+#define AC_BD_STATE 4
+#define AC_MEM_TEST_ID 5
+#define AC_MEM_TEST_PAR 6
+#define AC_MEM_PERM 7
+#define AC_KPM_CANCELLED 8
+#define AC_KPM_REFUSED 9
+#define AC_KPM_SPAN 10
+#define AC_KPM_DUP 11
+#define AC_KPM_FAULT 12
+#define AC_KPM_RESOURCE 13
+#define AC_KPM_NOTSUP 14
+#define AC_KPM_NOHANDLES 15
+#define AC_KPM_NONRELOC 16
+#define AC_KPM_HANDLE 17
+#define AC_KPM_BUSY 18
+#define AC_KPM_NOTVIABLE 19
+#define AC_KPM_SEQUENCE 20
+#define AC_KPM_NOWORK 21
+#define AC_KPM_NOTFINISHED 22
+#define AC_KPM_NOTRUNNING 23
+#define AC_VMEM 24
+#define CMD_MEM_STAT 25
+#define CMD_MEM_ADD 26
+#define CMD_MEM_DEL 27
+#define CMD_MEM_TEST_START 28
+#define CMD_MEM_TEST_STOP 29
+#define AC_UNKNOWN 30
+#define AC_INTR 31
+#define AC_TIMEOUT 32
+#define CMD_MEM_RELOCTEST 33
+#define AC_DEINTLV 34
+
+static char *
+mema_strs[] = {
+ "memory bank busy",
+ "invalid memory bank",
+ "invalid board id",
+ "invalid board type",
+ "invalid board state",
+ "invalid memory test id",
+ "invalid memory test parameter(s)",
+ "no write permission",
+ "memory operation cancelled",
+ "memory operation refused",
+ "memory already in use (add)",
+ "memory span duplicate (delete)",
+ "memory access test failed (add)",
+ "some resource was not available",
+ "operation not supported",
+ "cannot allocate any more handles",
+ "non-relocatable pages in span",
+ "bad handle supplied",
+ "memory in span is being deleted",
+ "VM viability test failed",
+ "function called out of sequence",
+ "no memory to delete",
+ "delete processing not finished",
+ "delete processing not running",
+ "insufficient virtual memory",
+ "memory stat failed: %s",
+ "memory add failed: %s",
+ "memory delete failed: %s",
+ "memory test start failed: %s",
+ "memory test stop failed: %s",
+ "unknown error",
+ "memory delete killed",
+ "memory delete timeout",
+ "memory relocate-test failed: %s",
+ "memory cannot be de-interleaved"
+};
+
+/*
+ * AC_MEM_PERM, EBADF, AC_ERR_MEM_PERM
+ * AC_BK_BUSY, EBUSY, AC_ERR_MEM_BK
+ * AC_KPM_CANCELLED, EINTR, AC_ERR_KPM_CANCELLED
+ * AC_KPM_REFUSED, EINTR, AC_ERR_KPM_REFUSED
+ * AC_BK_ID, EINVAL, AC_ERR_MEM_BK
+ * AC_BD_ID, EINVAL, AC_ERR_BD
+ * AC_BD_TYPE, EINVAL, AC_ERR_BD_TYPE
+ * AC_BD_STATE, EINVAL, AC_ERR_BD_STATE
+ * AC_MEM_TEST_ID, EINVAL, AC_ERR_MEM_TEST
+ * AC_MEM_TEST_PAR, EINVAL, AC_ERR_MEM_TEST_PAR
+ * AC_KPM_SPAN, EINVAL, AC_ERR_KPM_SPAN
+ * AC_KPM_DUP, EINVAL, AC_ERR_KPM_DUP?
+ * AC_KPM_FAULT, EINVAL, AC_ERR_KPM_FAULT
+ * AC_KPM_RESOURCE, EINVAL, AC_ERR_KPM_RESOURCE
+ * AC_KPM_NOTSUP, EINVAL, AC_ERR_KPM_NOTSUP
+ * AC_KPM_NOHANDLES, EINVAL, AC_ERR_KPM_NOHANDLES
+ * AC_KPM_NONRELOC, EINVAL, AC_ERR_KPM_NONRELOC
+ * AC_KPM_HANDLE, EINVAL, AC_ERR_KPM_HANDLE
+ * AC_KPM_BUSY, EINVAL, AC_ERR_KPM_BUSY
+ * AC_KPM_NOTVIABLE, EINVAL, AC_ERR_KPM_NOTVIABLE
+ * AC_KPM_SEQUENCE, EINVAL, AC_ERR_KPM_SEQUENCE
+ * AC_KPM_NOWORK, EINVAL, AC_ERR_KPM_NOWORK
+ * AC_KPM_NOTFINISHED, EINVAL, AC_ERR_KPM_NOTFINISHED
+ * AC_KPM_NOTRUNNING, EINVAL, AC_ERR_KPM_NOTRUNNING
+ * AC_VMEM, ENOMEM, AC_ERR_VMEM
+ * AC_INTR, EINTR, AC_ERR_INTR
+ * AC_TIMEOUT, EINTR, AC_ERR_TIMEOUT
+ * AC_DEINTLV, EINVAL, AC_ERR_MEM_DEINTLV
+ */
+static int
+mema_sid(int err, int acerr)
+{
+ if (acerr == AC_ERR_DEFAULT)
+ return (AC_UNKNOWN);
+
+ switch (mema_eid(err, acerr)) {
+ case mema_eid(EBADF, AC_ERR_MEM_PERM):
+ return (AC_MEM_PERM);
+ case mema_eid(EBUSY, AC_ERR_MEM_BK):
+ return (AC_BK_BUSY);
+ case mema_eid(EINTR, AC_ERR_KPM_CANCELLED):
+ return (AC_KPM_CANCELLED);
+ case mema_eid(EINTR, AC_ERR_KPM_REFUSED):
+ return (AC_KPM_REFUSED);
+ case mema_eid(EINVAL, AC_ERR_MEM_BK):
+ return (AC_BK_ID);
+ case mema_eid(EINVAL, AC_ERR_BD):
+ return (AC_BD_ID);
+ case mema_eid(EINVAL, AC_ERR_BD_TYPE):
+ return (AC_BD_TYPE);
+ case mema_eid(EINVAL, AC_ERR_BD_STATE):
+ return (AC_BD_STATE);
+ case mema_eid(EINVAL, AC_ERR_MEM_TEST):
+ return (AC_MEM_TEST_ID);
+ case mema_eid(EINVAL, AC_ERR_MEM_TEST_PAR):
+ return (AC_MEM_TEST_PAR);
+ case mema_eid(EINVAL, AC_ERR_KPM_SPAN):
+ return (AC_KPM_SPAN);
+ case mema_eid(EINVAL, AC_ERR_KPM_DUP):
+ return (AC_KPM_DUP);
+ case mema_eid(EINVAL, AC_ERR_KPM_FAULT):
+ return (AC_KPM_FAULT);
+ case mema_eid(EINVAL, AC_ERR_KPM_RESOURCE):
+ return (AC_KPM_RESOURCE);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOTSUP):
+ return (AC_KPM_NOTSUP);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOHANDLES):
+ return (AC_KPM_NOHANDLES);
+ case mema_eid(EINVAL, AC_ERR_KPM_NONRELOC):
+ return (AC_KPM_NONRELOC);
+ case mema_eid(EINVAL, AC_ERR_KPM_HANDLE):
+ return (AC_KPM_HANDLE);
+ case mema_eid(EINVAL, AC_ERR_KPM_BUSY):
+ return (AC_KPM_BUSY);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOTVIABLE):
+ return (AC_KPM_NOTVIABLE);
+ case mema_eid(EINVAL, AC_ERR_KPM_SEQUENCE):
+ return (AC_KPM_SEQUENCE);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOWORK):
+ return (AC_KPM_NOWORK);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOTFINISHED):
+ return (AC_KPM_NOTFINISHED);
+ case mema_eid(EINVAL, AC_ERR_KPM_NOTRUNNING):
+ return (AC_KPM_NOTRUNNING);
+ case mema_eid(ENOMEM, AC_ERR_VMEM):
+ return (AC_VMEM);
+ case mema_eid(EINTR, AC_ERR_INTR):
+ return (AC_INTR);
+ case mema_eid(EINTR, AC_ERR_TIMEOUT):
+ return (AC_TIMEOUT);
+ case mema_eid(EINVAL, AC_ERR_MEM_DEINTLV):
+ return (AC_DEINTLV);
+ default:
+ break;
+ }
+
+ return (AC_UNKNOWN);
+}
+
+static void
+mema_err(ac_cfga_cmd_t *ac, int ret_errno, char **errstring, int cmd)
+{
+ char *cname = mema_str(cmd);
+ char *syserr;
+ char syserr_num[20];
+
+ if (ac) {
+ syserr = mema_str(mema_sid(ret_errno, ac->errtype));
+ syserr = dgettext(TEXT_DOMAIN, syserr);
+ } else {
+ syserr = strerror(ret_errno);
+ /* strerror() does its own gettext(). */
+ if (syserr == NULL) {
+ (void) sprintf(syserr_num, "errno=%d", errno);
+ syserr = syserr_num;
+ }
+ }
+
+ __fmt_errstring(errstring, strlen(syserr),
+ dgettext(TEXT_DOMAIN, cname), syserr);
+}
+
+static void
+mema_cmd_init(ac_cfga_cmd_t *ac, void *cmd, char *outputstr, int force)
+{
+ (void) memset((void *)ac, 0, sizeof (*ac));
+
+ ac->errtype = AC_ERR_DEFAULT;
+ ac->private = cmd;
+ ac->force = force;
+ ac->outputstr = outputstr;
+
+ (void) memset((void *)outputstr, 0, AC_OUTPUT_LEN);
+}
+
+static int
+ap_bk_idx(const char *ap_id)
+{
+ int id;
+ char *s;
+ static char *bank = "bank";
+
+ DBG("ap_bk_idx(%s)\n", ap_id);
+
+ if ((s = strstr(ap_id, bank)) == NULL)
+ return (-1);
+ else {
+ int n;
+
+ s += strlen(bank);
+ n = strlen(s);
+
+ DBG3("ap_bk_idx: s=%s, n=%d\n", s, n);
+
+ if ((n != 1) || !isdigit(s[0]))
+ return (-1);
+ }
+
+ id = atoi(s);
+
+ if (id < 0 || id > 1)
+ return (-1);
+
+ DBG3("ap_bk_idx(%s)=%d\n", s, id);
+
+ return (id);
+}
+
+static cfga_err_t
+ap_stat(
+ const char *bank_spec,
+ int *fdp,
+ mema_bank_t *bkp,
+ ac_stat_t *stp,
+ char **errstring)
+{
+ int fd;
+ int ret, ret_errno;
+ int bank;
+ mema_bank_t bk;
+ ac_stat_t stat;
+ ac_cfga_cmd_t cmd;
+ char outputstr[AC_OUTPUT_LEN];
+
+ if ((bank = ap_bk_idx(bank_spec)) == -1) {
+ __fmt_errstring(errstring, strlen(bank_spec),
+ dgettext(TEXT_DOMAIN, ap_invalid), bank_spec);
+ return (CFGA_ERROR);
+ }
+
+ bk.bank = bank;
+
+ if ((fd = open(bank_spec, ((fdp != NULL) ? O_RDWR : O_RDONLY), 0)) ==
+ -1) {
+ char *syserr;
+ char syserr_num[20];
+
+ syserr = strerror(errno);
+ if (syserr == NULL) {
+ (void) sprintf(syserr_num, "errno=%d", errno);
+ syserr = syserr_num;
+ }
+ __fmt_errstring(errstring, strlen(syserr) +
+ strlen(bank_spec),
+ dgettext(TEXT_DOMAIN, open_failed), bank_spec, syserr);
+ return (CFGA_ERROR);
+ }
+
+ mema_cmd_init(&cmd, &stat, outputstr, 0);
+ dump_ioctl(AC_MEM_STAT, NULL);
+ ret = ioctl(fd, AC_MEM_STAT, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_STAT, &stat, ret, ret_errno);
+
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring, CMD_MEM_STAT);
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+
+ if (fdp)
+ *fdp = fd;
+ else
+ (void) close(fd);
+
+ if (stp)
+ *stp = stat;
+
+ if (bkp) {
+ bkp->bank = bk.bank;
+ bkp->board = stat.board;
+ }
+
+ return (CFGA_OK);
+}
+
+static void
+set_disabled_bits(mema_disabled_t *dp, int value)
+{
+ if (value == 0)
+ *dp &= ~PROM_MEMORY_DISABLED;
+ else
+ *dp |= PROM_MEMORY_DISABLED;
+}
+
+static void
+set_present_bits(mema_disabled_t *dp, ac_stat_t *asp)
+{
+ if (asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED)
+ *dp |= PROM_MEMORY_PRESENT;
+ else
+ *dp &= ~PROM_MEMORY_DISABLED;
+}
+
+static cfga_err_t
+prom_do_options(
+ option_set_t do_option,
+ int board,
+ ac_stat_t *asp,
+ char **errstring)
+{
+ cfga_err_t ret;
+ mema_disabled_t disab;
+
+ if (!prom_read_disabled_list(&disab, board))
+ return (CFGA_ERROR);
+
+ set_present_bits(&disab, asp);
+
+ ret = CFGA_OK;
+
+ if (OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
+ set_disabled_bits(&disab, 0);
+ if (!prom_viable_disabled_list(&disab)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, dlist_invalid));
+ ret = CFGA_ERROR;
+ } else if (!prom_write_disabled_list(&disab, board)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, dlist_write_failed));
+ ret = CFGA_ERROR;
+ }
+ } else if (OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
+ set_disabled_bits(&disab, 1);
+ if (!prom_viable_disabled_list(&disab)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, dlist_invalid));
+ ret = CFGA_ERROR;
+ } else if (!prom_write_disabled_list(&disab, board)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, dlist_write_failed));
+ ret = CFGA_ERROR;
+ }
+ }
+
+ return (ret);
+}
+
+static cfga_err_t
+mema_add(
+ const char *bank_spec,
+ const char *options,
+ char **errstring,
+ int force)
+{
+ mema_bank_t bk;
+ int fd, ret, ret_errno;
+ option_set_t do_option;
+ ac_cfga_cmd_t cmd;
+ ac_stat_t stat;
+ char outputstr[AC_OUTPUT_LEN];
+
+ ret = 0;
+ do_option = process_options(options, add_opts, &ret, errstring);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
+ if (ret != CFGA_OK)
+ return (ret);
+
+
+ if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
+ stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, trans_illegal));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+
+ if (!force) {
+ mema_disabled_t disab;
+
+ if (prom_read_disabled_list(&disab, bk.board)) {
+ if (disab != 0 &&
+ !OPTSET_TEST(do_option, OPT_BOOT_ENABLE)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, add_is_disabled));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+ if (disab == 0 &&
+ OPTSET_TEST(do_option, OPT_BOOT_DISABLE)) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, add_willbe_disabled));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+ } else {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, add_disab_err));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+ }
+
+ mema_cmd_init(&cmd, NULL, outputstr, force);
+ dump_ioctl(AC_MEM_CONFIGURE, NULL);
+ ret = ioctl(fd, AC_MEM_CONFIGURE, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_CONFIGURE, NULL, ret, ret_errno);
+ (void) close(fd);
+
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring, CMD_MEM_ADD);
+ return (CFGA_ERROR);
+ }
+
+ ret = prom_do_options(do_option, bk.board, &stat, errstring);
+
+ return (ret);
+}
+
+static cfga_err_t
+mema_delete(
+ const char *bank_spec,
+ const char *options,
+ char **errstring,
+ int force)
+{
+ mema_bank_t bk;
+ int fd, ret, ret_errno;
+ option_set_t do_option;
+ ac_cfga_cmd_t cmd;
+ ac_stat_t stat;
+ char outputstr[AC_OUTPUT_LEN];
+ int timeout_secs = -1; /* Init to 'use default'. */
+
+ ret = 0;
+ do_option = process_options(options, del_opts, &ret, errstring);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ if (OPTSET_TEST(do_option, OPT_TIMEOUT)) {
+ char *to_val;
+ char *ep;
+
+ to_val = OPTSET_VAL(do_option, OPT_TIMEOUT);
+ timeout_secs = (int)strtol(to_val, &ep, 10);
+ if (*ep != '\0' || ep == to_val || timeout_secs < 0) {
+ __fmt_errstring(errstring, strlen(to_val),
+ dgettext(TEXT_DOMAIN, timeout_notnum), to_val);
+ return (CFGA_ERROR);
+ }
+ }
+
+ ret = ap_stat(bank_spec, &fd, &bk, &stat, errstring);
+ if (ret != CFGA_OK)
+ return (ret);
+
+ if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
+ stat.ostate != SYSC_CFGA_OSTATE_CONFIGURED) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, trans_illegal));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+
+ mema_cmd_init(&cmd, NULL, outputstr, force);
+ cmd.arg = timeout_secs;
+ dump_ioctl(AC_MEM_UNCONFIGURE, NULL);
+ ret = ioctl(fd, AC_MEM_UNCONFIGURE, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_UNCONFIGURE, NULL, ret, ret_errno);
+ (void) close(fd);
+
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring, CMD_MEM_DEL);
+ return (CFGA_ERROR);
+ }
+
+ ret = prom_do_options(do_option, bk.board, &stat, errstring);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+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)
+{
+ int force;
+ cfga_err_t rc;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ force = flags & CFGA_FLAG_FORCE;
+
+ switch (state_change_cmd) {
+ case CFGA_CMD_CONFIGURE:
+ rc = mema_add(ap_id, options, errstring, force);
+ break;
+
+ case CFGA_CMD_UNCONFIGURE:
+ rc = mema_delete(ap_id, options, errstring, force);
+ break;
+
+ default:
+ rc = CFGA_OPNOTSUPP;
+ break;
+ }
+
+ return (rc);
+}
+
+/*ARGSUSED*/
+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)
+{
+ mema_bank_t bk;
+ ac_stat_t stat;
+ int fd, ret, ret_errno;
+ ac_cfga_cmd_t cmd;
+ char outputstr[AC_OUTPUT_LEN];
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
+ if (ret != CFGA_OK)
+ return (ret);
+
+ if (strcmp(function, "relocate-test") == 0) {
+ struct ac_memx_relocate_stats rstat;
+
+ mema_cmd_init(&cmd, NULL, outputstr,
+ (flags & CFGA_FLAG_FORCE));
+ cmd.arg = AC_MEMX_RELOCATE_ALL;
+ cmd.private = &rstat;
+ (void) memset((void *)&rstat, 0, sizeof (rstat));
+ dump_ioctl(AC_MEM_EXERCISE, &cmd);
+ ret = ioctl(fd, AC_MEM_EXERCISE, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_EXERCISE, &cmd, ret, ret_errno);
+ (void) close(fd);
+
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring, CMD_MEM_RELOCTEST);
+ return (CFGA_ERROR);
+ }
+ return (CFGA_OK);
+ }
+
+ __fmt_errstring(errstring, strlen(function),
+ dgettext(TEXT_DOMAIN, pfunc_unknown), function);
+
+ return (CFGA_ERROR);
+}
+
+static int
+mtest_run(
+ int fd,
+ int test_fun,
+ mema_bank_t *abkp,
+ struct cfga_msg *msgp,
+ char **errstring,
+ ulong_t max_errors)
+{
+ ac_mem_test_start_t test_start;
+ ac_mem_test_stop_t test_stop;
+ struct mtest_handle handle;
+ int ret, ret_errno;
+ int res;
+ ac_cfga_cmd_t cmd;
+ char outputstr[AC_OUTPUT_LEN];
+
+ (void) memset((void *)&test_start, 0, sizeof (test_start));
+ mema_cmd_init(&cmd, &test_start, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_START, &test_start);
+ ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_START, &test_start, ret, ret_errno);
+
+ if (ret == -1) {
+ if (ret_errno == ENOTSUP) {
+ mema_err(&cmd, ret_errno, errstring,
+ CMD_MEM_TEST_START);
+ return (CFGA_OPNOTSUPP);
+ }
+ if (ret_errno == EBUSY && test_start.tester_pid > 0) {
+ /*
+ * Bank appears to be being tested. Check that
+ * process 'tester_pid' is still running.
+ */
+ if (kill(test_start.tester_pid, 0) != -1 ||
+ errno != ESRCH) {
+ cfga_ap_log_id_t bname;
+
+ /* Process still exists. */
+ (void) sprintf(bname, "board %d bank%d",
+ abkp->board, abkp->bank);
+ __fmt_errstring(errstring, strlen(bname),
+ dgettext(TEXT_DOMAIN, still_testing),
+ bname, test_start.tester_pid);
+ return (CFGA_ERROR);
+ }
+ /*
+ * Do a test stop and re-try the start.
+ */
+ (void) memset((void *)&test_stop, 0,
+ sizeof (test_stop));
+ test_stop.handle = test_start.handle;
+ test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
+ mema_cmd_init(&cmd, &test_stop, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
+ ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop,
+ ret, ret_errno);
+ /*
+ * Ignore test stop error processing and re-try the
+ * start. The error return will be derived from the
+ * result of start.
+ */
+ (void) memset((void *)&test_start, 0,
+ sizeof (test_start));
+ mema_cmd_init(&cmd, &test_start, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_START, &test_start);
+ ret = ioctl(fd, AC_MEM_TEST_START, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_START, &test_start,
+ ret, ret_errno);
+ }
+ /* Test return code again to cover the case of a re-try. */
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring,
+ CMD_MEM_TEST_START);
+ return (CFGA_ERROR);
+ }
+ }
+ (void) memset((void *)&handle, 0, sizeof (handle));
+ handle.fd = fd;
+ handle.drvhandle = (void *)&test_start;
+ handle.msgp = msgp;
+ handle.bank_size = test_start.bank_size;
+ handle.page_size = test_start.page_size;
+ handle.line_size = test_start.line_size;
+ handle.lines_per_page = test_start.page_size / test_start.line_size;
+ handle.condition = CFGA_COND_UNKNOWN;
+ handle.max_errors = max_errors;
+
+ res = (*mtest_table[test_fun].test_func)(&handle);
+
+ mtest_deallocate_buf_all(&handle);
+
+ /*
+ * Convert memory test code to MEMA_ code.
+ */
+ switch (res) {
+ case MTEST_DONE:
+ res = CFGA_OK;
+ break;
+ case MTEST_LIB_ERROR:
+ __fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
+ mtest_lib_error));
+ res = CFGA_ERROR;
+ break;
+ case MTEST_DEV_ERROR:
+ __fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
+ mtest_rw_error));
+ res = CFGA_ERROR;
+ break;
+ default:
+ __fmt_errstring(errstring, 0, dgettext(TEXT_DOMAIN,
+ mtest_unknown_error));
+ res = CFGA_ERROR;
+ assert(0);
+ break;
+ }
+
+ (void) memset((void *)&test_stop, 0, sizeof (test_stop));
+ test_stop.handle = test_start.handle;
+ switch (handle.condition) {
+ case CFGA_COND_OK:
+ test_stop.condition = SYSC_CFGA_COND_OK;
+ break;
+ case CFGA_COND_FAILING:
+ test_stop.condition = SYSC_CFGA_COND_FAILING;
+ break;
+ case CFGA_COND_FAILED:
+ test_stop.condition = SYSC_CFGA_COND_FAILED;
+ break;
+ case CFGA_COND_UNKNOWN:
+ test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
+ break;
+ default:
+ test_stop.condition = SYSC_CFGA_COND_UNKNOWN;
+ assert(0);
+ break;
+ }
+
+ mema_cmd_init(&cmd, &test_stop, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_STOP, &test_stop);
+ ret = ioctl(fd, AC_MEM_TEST_STOP, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_STOP, &test_stop, ret, ret_errno);
+ if (ret == -1) {
+ mema_err(&cmd, ret_errno, errstring,
+ CMD_MEM_TEST_STOP);
+ return (CFGA_ERROR);
+ }
+ return (res);
+}
+
+#define DRVHANDLE(H) (((ac_mem_test_start_t *)(H)->drvhandle)->handle)
+
+int
+mtest_write(
+ mtest_handle_t handle,
+ void *page_buf,
+ u_longlong_t page_no,
+ uint_t line_offset,
+ uint_t line_count)
+{
+ ac_mem_test_write_t test_write;
+ int fd, ret, ret_errno;
+ ac_cfga_cmd_t cmd;
+ char outputstr[AC_OUTPUT_LEN];
+
+ (void) memset((void *)&test_write, 0, sizeof (test_write));
+ fd = handle->fd;
+ test_write.handle = DRVHANDLE(handle);
+ test_write.page_buf = page_buf;
+ test_write.address.page_num = page_no;
+ test_write.address.line_offset = line_offset;
+ if (line_count == 0)
+ test_write.address.line_count = handle->lines_per_page;
+ else
+ test_write.address.line_count = line_count;
+
+ mema_cmd_init(&cmd, &test_write, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_WRITE, &test_write);
+ ret = ioctl(fd, AC_MEM_TEST_WRITE, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_WRITE, &test_write, ret, ret_errno);
+
+ if (ret == -1)
+ return (-1);
+ return (0);
+}
+
+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)
+{
+ ac_mem_test_read_t test_read;
+ sunfire_processor_error_regs_t errbuf;
+ int fd, ret, ret_errno;
+ ac_cfga_cmd_t cmd;
+ char outputstr[AC_OUTPUT_LEN];
+
+ (void) memset((void *)&test_read, 0, sizeof (test_read));
+ (void) memset((void *)&errbuf, 0, sizeof (errbuf));
+ fd = handle->fd;
+ test_read.handle = DRVHANDLE(handle);
+ test_read.page_buf = page_buf;
+ test_read.address.page_num = page_no;
+ test_read.address.line_offset = line_offset;
+ test_read.error_buf = &errbuf;
+ if (line_count == 0)
+ test_read.address.line_count = handle->lines_per_page;
+ else
+ test_read.address.line_count = line_count;
+
+ mema_cmd_init(&cmd, &test_read, outputstr, 0);
+ dump_ioctl(AC_MEM_TEST_READ, &test_read);
+ ret = ioctl(fd, AC_MEM_TEST_READ, &cmd);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_TEST_READ, &test_read, ret, ret_errno);
+
+ if (ret == -1) {
+ if (ret_errno == EIO) {
+ /*
+ * Special case indicating CE or UE.
+ */
+ if (((errbuf.udbh_error_reg | errbuf.udbl_error_reg) &
+ P_DER_UE) != 0)
+ errp->error_type = MTEST_ERR_UE;
+ else
+ errp->error_type = MTEST_ERR_CE;
+ } else {
+ return (-1);
+ }
+ } else {
+ errp->error_type = MTEST_ERR_NONE;
+ }
+ return (0);
+}
+
+static char *
+subopt_help_str(char *opts[])
+{
+ char *str;
+ const char *sep;
+ int len;
+ int i, n;
+ static const char help_sep[] = ", ";
+ static const char help_nil[] = "???";
+
+ len = 0;
+ n = 0;
+ for (i = 0; opts[i] != NULL; i++) {
+ n++;
+ len += strlen(opts[i]);
+ }
+ if (n == 0)
+ return (strdup(help_nil));
+ len += (n - 1) * strlen(help_sep);
+ len++;
+ str = (char *)malloc(len);
+ if (str == NULL)
+ return (NULL);
+ *str = '\0';
+ sep = "";
+ for (i = 0; opts[i] != NULL; i++) {
+ (void) strcat(str, sep);
+ (void) strcat(str, opts[i]);
+ sep = help_sep;
+ }
+ return (str);
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_test(
+ const char *ap_id,
+ const char *options,
+ struct cfga_msg *msgp,
+ char **errstring,
+ cfga_flags_t flags)
+{
+ mema_bank_t bk;
+ ac_stat_t stat;
+ int test_fun = -1;
+ int fd, ret;
+ int maxerr_idx;
+ long max_errors = -1;
+ char *ret_p;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ /*
+ * Decode test level and max error number.
+ */
+ if (options != NULL && *options != '\0') {
+ char **opts;
+ char *value;
+ char *cp, *free_cp;
+ int subopt;
+
+ /* getsubopt() modifies the input string, so copy it. */
+ cp = strdup(options);
+ if (cp == NULL) {
+ return (CFGA_LIB_ERROR);
+ }
+ free_cp = cp;
+ opts = mtest_build_opts(&maxerr_idx);
+ if (opts == NULL) {
+ free((void *)free_cp);
+ return (CFGA_LIB_ERROR);
+ }
+
+ while (*cp != '\0') {
+ subopt = getsubopt(&cp, opts, &value);
+ if (subopt == -1) {
+ char *hlp;
+
+ hlp = subopt_help_str(opts);
+ if (hlp != NULL) {
+ __fmt_errstring(errstring,
+ strlen(value) + strlen(hlp),
+ dgettext(TEXT_DOMAIN, unk_test),
+ value, hlp);
+ free((void *)hlp);
+ } else {
+ __fmt_errstring(errstring, 20,
+ dgettext(TEXT_DOMAIN, calloc_fail),
+ strlen(options) + 1, 1);
+ }
+ /* Free after printing value. */
+ free((void *)free_cp);
+ return (CFGA_ERROR);
+ }
+
+ if (test_fun != -1 && subopt != test_fun &&
+ subopt != maxerr_idx) {
+ __fmt_errstring(errstring,
+ strlen(opts[subopt]),
+ dgettext(TEXT_DOMAIN, dup_test),
+ opts[subopt]);
+ free((void *)free_cp);
+ return (CFGA_ERROR);
+ }
+
+ if (subopt < maxerr_idx)
+ test_fun = subopt;
+ else {
+
+ if (max_errors != -1 && subopt == maxerr_idx) {
+ __fmt_errstring(errstring,
+ strlen(opts[subopt]),
+ dgettext(TEXT_DOMAIN, dup_num),
+ opts[subopt]);
+ free((void *)free_cp);
+ return (CFGA_ERROR);
+ }
+
+ if (value == NULL) {
+ __fmt_errstring(errstring,
+ 0,
+ dgettext(TEXT_DOMAIN, no_num),
+ "");
+ free((void *)free_cp);
+ return (CFGA_ERROR);
+ }
+
+ max_errors = strtol(value, &ret_p, 10);
+ if ((ret_p == value) || (*ret_p != '\0') ||
+ (max_errors < 0)) {
+ __fmt_errstring(errstring,
+ strlen(value),
+ dgettext(TEXT_DOMAIN, no_num),
+ value);
+ free((void *)free_cp);
+ return (CFGA_ERROR);
+ }
+ }
+ }
+ free((void *)free_cp);
+ }
+
+ if (test_fun == -1)
+ test_fun = MTEST_DEFAULT_TEST;
+ if (max_errors == -1)
+ max_errors = MAX_ERRORS;
+
+ ret = ap_stat(ap_id, &fd, &bk, &stat, errstring);
+ if (ret != CFGA_OK)
+ return (ret);
+
+ if (stat.rstate != SYSC_CFGA_RSTATE_CONNECTED ||
+ stat.ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
+ __fmt_errstring(errstring, 0,
+ dgettext(TEXT_DOMAIN, trans_illegal));
+ (void) close(fd);
+ return (CFGA_ERROR);
+ }
+
+ ret = mtest_run(fd, test_fun, &bk,
+ ((flags & CFGA_FLAG_VERBOSE) != 0) ? msgp : NULL, errstring,
+ (ulong_t)max_errors);
+
+ (void) close(fd);
+
+ return (ret);
+}
+
+static cfga_stat_t
+rstate_cvt(sysc_cfga_rstate_t rs)
+{
+ cfga_stat_t cs;
+
+ switch (rs) {
+ case SYSC_CFGA_RSTATE_EMPTY:
+ cs = CFGA_STAT_EMPTY;
+ break;
+ case SYSC_CFGA_RSTATE_DISCONNECTED:
+ cs = CFGA_STAT_DISCONNECTED;
+ break;
+ case SYSC_CFGA_RSTATE_CONNECTED:
+ cs = CFGA_STAT_CONNECTED;
+ break;
+ default:
+ cs = CFGA_STAT_NONE;
+ break;
+ }
+
+ return (cs);
+}
+
+static cfga_stat_t
+ostate_cvt(sysc_cfga_ostate_t os)
+{
+ cfga_stat_t cs;
+
+ switch (os) {
+ case SYSC_CFGA_OSTATE_UNCONFIGURED:
+ cs = CFGA_STAT_UNCONFIGURED;
+ break;
+ case SYSC_CFGA_OSTATE_CONFIGURED:
+ cs = CFGA_STAT_CONFIGURED;
+ break;
+ default:
+ cs = CFGA_STAT_NONE;
+ break;
+ }
+
+ return (cs);
+}
+
+static cfga_cond_t
+cond_cvt(sysc_cfga_cond_t sc)
+{
+ cfga_cond_t cc;
+
+ switch (sc) {
+ case SYSC_CFGA_COND_OK:
+ cc = CFGA_COND_OK;
+ break;
+ case SYSC_CFGA_COND_FAILING:
+ cc = CFGA_COND_FAILING;
+ break;
+ case SYSC_CFGA_COND_FAILED:
+ cc = CFGA_COND_FAILED;
+ break;
+ case SYSC_CFGA_COND_UNUSABLE:
+ cc = CFGA_COND_UNUSABLE;
+ break;
+ case SYSC_CFGA_COND_UNKNOWN:
+ default:
+ cc = CFGA_COND_UNKNOWN;
+ break;
+ }
+
+ return (cc);
+}
+
+static void
+info_set(ac_stat_t *asp, mema_bank_t *bkp, cfga_info_t info)
+{
+ mema_disabled_t disab;
+ uint_t board;
+ uint_t n;
+ u_longlong_t decode;
+ uint_t intlv;
+ char *f;
+ char *end;
+
+ end = &info[sizeof (cfga_info_t)];
+ *info = NULL;
+
+ board = bkp->board;
+
+ /* Print the board number in a way that matches the sysctrl AP. */
+ info += snprintf(info, end - info, "slot%d", board);
+
+ if (asp->real_size == 0) {
+ info += snprintf(info, end - info, " empty");
+ return;
+ }
+
+ if ((n = asp->real_size) >= 1024) {
+ n /= 1024;
+ f = "Gb";
+ } else
+ f = "Mb";
+ info += snprintf(info, end - info, " %d%s", n, f);
+
+ if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
+ asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
+ asp->use_size != asp->real_size) {
+ if ((n = asp->use_size) >= 1024) {
+ n /= 1024;
+ f = "Gb";
+ } else
+ f = "Mb";
+ info += snprintf(info, end - info, " (%d%s used)", n, f);
+ }
+
+ if (bkp->bank == 0)
+ decode = asp->ac_decode0;
+ else
+ decode = asp->ac_decode1;
+
+ info += snprintf(info, end - info, " base 0x%llx",
+ GRP_REALBASE(decode));
+
+ if (bkp->bank == 0)
+ intlv = INTLV0(asp->ac_memctl);
+ else
+ intlv = INTLV1(asp->ac_memctl);
+
+ if (intlv != 1)
+ info += snprintf(info, end - info, " interleaved %u-way",
+ intlv);
+
+ if (prom_read_disabled_list(&disab, board)) {
+ if (disab != 0) {
+ info += snprintf(info, end - info, " disabled at boot");
+ }
+
+ }
+
+ if (asp->rstate == SYSC_CFGA_RSTATE_CONNECTED &&
+ asp->ostate == SYSC_CFGA_OSTATE_CONFIGURED &&
+ asp->nonrelocatable)
+ info += snprintf(info, end - info, " permanent");
+}
+
+static void
+mema_cvt(ac_stat_t *ac, mema_bank_t *bkp, cfga_stat_data_t *cs)
+{
+ (void) strcpy(cs->ap_type, "memory");
+ cs->ap_r_state = rstate_cvt(ac->rstate);
+ cs->ap_o_state = ostate_cvt(ac->ostate);
+ cs->ap_cond = cond_cvt(ac->condition);
+ cs->ap_busy = (cfga_busy_t)ac->busy;
+ cs->ap_status_time = ac->status_time;
+ info_set(ac, bkp, cs->ap_info);
+ cs->ap_log_id[0] = NULL;
+ cs->ap_phys_id[0] = NULL;
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_stat(
+ const char *ap_id,
+ struct cfga_stat_data *cs,
+ const char *options,
+ char **errstring)
+{
+ int ret;
+ mema_bank_t bk;
+ ac_stat_t stat;
+ option_set_t do_option;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ ret = 0;
+ do_option = process_options(options, stat_opts, &ret, errstring);
+ if (ret != 0)
+ return (ret);
+
+ ret = ap_stat(ap_id, NULL, &bk, &stat, errstring);
+ if (ret != CFGA_OK)
+ return (ret);
+
+ mema_cvt(&stat, &bk, cs);
+
+ ret = prom_do_options(do_option, bk.board, &stat, errstring);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_list(
+ const char *ap_id,
+ cfga_stat_data_t **ap_list,
+ int *nlist,
+ const char *options,
+ char **errstring)
+{
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ return (CFGA_NOTSUPP);
+}
+
+/*
+ * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
+ */
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
+{
+
+
+ (*msgp->message_routine)(msgp->appdata_ptr, mema_help);
+ (*msgp->message_routine)(msgp->appdata_ptr, disable_opts);
+ (*msgp->message_routine)(msgp->appdata_ptr, enable_opts);
+ (*msgp->message_routine)(msgp->appdata_ptr, timeout_opts);
+ (*msgp->message_routine)(msgp->appdata_ptr, test_opts);
+ (*msgp->message_routine)(msgp->appdata_ptr, private_funcs);
+
+ return (CFGA_OK);
+}
+
+#if 0
+static ac_mem_version_t
+get_version(int fd)
+{
+ ac_mem_version_t ver;
+ int ret, ret_errno;
+
+ ver = 0;
+ dump_ioctl(AC_MEM_ADMIN_VER, &ver);
+ ret = ioctl(fd, AC_MEM_ADMIN_VER, &ver);
+ ret_errno = errno;
+ dump_ioctl_res(AC_MEM_ADMIN_VER, &ver, ret, ret_errno);
+ return (ver);
+}
+#endif
+
+static char *
+opt_help_str(struct opt_control *opts)
+{
+ char *str;
+ const char *sep;
+ int len;
+ int i, n;
+ static const char help_sep[] = ", ";
+ static const char help_nil[] = "???";
+
+ len = 0;
+ n = 0;
+ for (i = 0; opts[i].subopt != -1; i++) {
+ n++;
+ len += strlen(mema_opts[opts[i].subopt]);
+ }
+ if (n == 0)
+ return (strdup(help_nil));
+ len += (n - 1) * strlen(help_sep);
+ len++;
+ str = (char *)malloc(len);
+ if (str == NULL)
+ return (NULL);
+ *str = '\0';
+ sep = "";
+ for (i = 0; opts[i].subopt != -1; i++) {
+ (void) strcat(str, sep);
+ (void) strcat(str, mema_opts[opts[i].subopt]);
+ sep = help_sep;
+ }
+ return (str);
+}
+
+static option_set_t
+process_options(
+ const char *options,
+ struct opt_control *opts,
+ int *retp,
+ char **errstring)
+{
+ option_set_t opt_set;
+ char *optcopy, *optcopy_alloc;
+ char *value;
+ int subopt;
+ int subopt_err;
+ int i;
+ int group;
+ int need_value;
+
+ OPTSET_INIT(opt_set);
+
+ if (options == NULL || *options == '\0') {
+ return (opt_set);
+ }
+
+ optcopy = optcopy_alloc = strdup(options);
+ if (optcopy_alloc == NULL) {
+ __fmt_errstring(errstring, 20,
+ dgettext(TEXT_DOMAIN, calloc_fail), strlen(options) + 1, 1);
+ *retp = CFGA_LIB_ERROR;
+ return (opt_set);
+ }
+
+ subopt_err = 0;
+ while (*optcopy != '\0' && subopt_err == 0) {
+ subopt = getsubopt(&optcopy, mema_opts, &value);
+ if (subopt == -1) {
+ char *hlp;
+
+ hlp = opt_help_str(opts);
+ __fmt_errstring(errstring, strlen(value) + strlen(hlp),
+ dgettext(TEXT_DOMAIN, unk_subopt), value, hlp);
+ free((void *)hlp);
+ subopt_err = 1;
+ break;
+ }
+ for (i = 0; opts[i].subopt != -1; i++) {
+ if (opts[i].subopt == subopt) {
+ group = opts[i].group;
+ break;
+ }
+ }
+ if (opts[i].subopt == -1) {
+ char *hlp;
+
+ hlp = opt_help_str(opts);
+ __fmt_errstring(errstring,
+ MAX_OPT_LENGTH + strlen(hlp),
+ dgettext(TEXT_DOMAIN, not_valid),
+ mema_opts[subopt], hlp);
+ free((void *)hlp);
+ subopt_err = 1;
+ break;
+ }
+ need_value = OPT_NEEDS_VALUE(subopt);
+ if (!need_value && value != NULL) {
+ __fmt_errstring(errstring, MAX_OPT_LENGTH,
+ dgettext(TEXT_DOMAIN, no_value),
+ mema_opts[subopt]);
+ subopt_err = 1;
+ break;
+ }
+ if (need_value && value == NULL) {
+ __fmt_errstring(errstring, MAX_OPT_LENGTH,
+ dgettext(TEXT_DOMAIN, missing_value),
+ mema_opts[subopt]);
+ subopt_err = 1;
+ break;
+ }
+ if (OPTSET_TEST(opt_set, subopt)) {
+ /* Ignore repeated options. */
+ continue;
+ }
+ if (group != 0 && !OPTSET_IS_EMPTY(opt_set)) {
+ for (i = 0; opts[i].subopt != -1; i++) {
+ if (i == subopt)
+ continue;
+ if (opts[i].group == group &&
+ OPTSET_TEST(opt_set, opts[i].subopt))
+ break;
+ }
+ if (opts[i].subopt != -1) {
+ __fmt_errstring(errstring, MAX_OPT_LENGTH * 2,
+ dgettext(TEXT_DOMAIN, conflict_opt),
+ mema_opts[subopt],
+ mema_opts[opts[i].subopt]);
+ subopt_err = 1;
+ break;
+ }
+ }
+ OPTSET_SET_VAL(opt_set, subopt, value);
+ }
+ free((void *)optcopy_alloc);
+ if (subopt_err) {
+ *retp = CFGA_ERROR;
+ }
+
+ return (opt_set);
+}
+
+#ifdef DEV_DEBUG
+
+static int
+debugging(void)
+{
+ char *ep;
+ static int inited;
+
+ if (inited)
+ return (debug_fp != NULL);
+ inited = 1;
+
+ if ((ep = getenv("MEMADM_DEBUG")) == NULL) {
+ return (0);
+ }
+ if (*ep == '\0')
+ debug_fp = stderr;
+ else {
+ if ((debug_fp = fopen(ep, "a")) == NULL)
+ return (0);
+ }
+ (void) fprintf(debug_fp, "\nDebug started, pid=%d\n", (int)getpid());
+ return (1);
+}
+
+static void
+dump_ioctl(
+ int cmd,
+ void *arg)
+{
+ if (!debugging())
+ return;
+
+ switch (cmd) {
+ case AC_MEM_CONFIGURE:
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_CONFIGURE\n");
+ break;
+
+ case AC_MEM_UNCONFIGURE:
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_UNCONFIGURE\n");
+ break;
+
+ case AC_MEM_TEST_START:
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_START\n");
+ break;
+
+ case AC_MEM_TEST_STOP: {
+ ac_mem_test_stop_t *tstop;
+
+ tstop = (ac_mem_test_stop_t *)arg;
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_STOP handle=%#x "
+ "condition=%d\n", tstop->handle, tstop->condition);
+ }
+ break;
+ case AC_MEM_TEST_READ: {
+ ac_mem_test_read_t *tread;
+
+ tread = (ac_mem_test_read_t *)arg;
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_READ handle=%#x "
+ "buf=%#p page=%#llx off=%#x count=%#x\n",
+ tread->handle, tread->page_buf,
+ tread->address.page_num,
+ tread->address.line_offset, tread->address.line_count);
+ }
+ break;
+ case AC_MEM_TEST_WRITE: {
+ ac_mem_test_write_t *twrite;
+
+ twrite = (ac_mem_test_write_t *)arg;
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_TEST_WRITE handle=%#x "
+ "buf=%#p page=%#llx off=%#x count=%#x\n",
+ twrite->handle, twrite->page_buf,
+ twrite->address.page_num,
+ twrite->address.line_offset, twrite->address.line_count);
+ }
+ break;
+ case AC_MEM_ADMIN_VER:
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_ADMIN_VER:\n");
+ break;
+ case AC_MEM_STAT:
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_STAT\n");
+ break;
+ case AC_MEM_EXERCISE: {
+ ac_cfga_cmd_t *cmdp;
+
+ cmdp = arg;
+ (void) fprintf(debug_fp, "IOCTL: AC_MEM_EXERCISE arg=%d\n",
+ cmdp->arg);
+ break;
+ }
+ default:
+ (void) fprintf(debug_fp, "IOCTL: unknown (%#x)\n", cmd);
+ break;
+ }
+ (void) fflush(debug_fp);
+}
+
+static void
+dump_ioctl_res(
+ int cmd,
+ void *arg,
+ int ret,
+ int ret_errno)
+{
+ if (!debugging())
+ return;
+
+ if (ret == -1) {
+ (void) fprintf(debug_fp, "IOCTL failed, \"%s\" (errno=%d)\n",
+ strerror(ret_errno), ret_errno);
+ (void) fflush(debug_fp);
+ return;
+ } else {
+ (void) fprintf(debug_fp, "IOCTL succeeded, ret=%d\n", ret);
+ }
+
+ switch (cmd) {
+ case AC_MEM_CONFIGURE:
+ case AC_MEM_UNCONFIGURE:
+ break;
+ case AC_MEM_TEST_START: {
+ ac_mem_test_start_t *tstart;
+
+ tstart = (ac_mem_test_start_t *)arg;
+ (void) fprintf(debug_fp, " handle=%#x tester_pid=%d "
+ "prev_condition=%d bank_size=%#llx "
+ "page_size=%#x line_size=%#x afar_base=%#llx\n",
+ tstart->handle, (int)tstart->tester_pid,
+ tstart->prev_condition,
+ tstart->bank_size, tstart->page_size,
+ tstart->line_size, tstart->afar_base);
+ }
+ break;
+ case AC_MEM_TEST_STOP:
+ break;
+ case AC_MEM_TEST_READ: {
+ ac_mem_test_read_t *tread;
+ sunfire_processor_error_regs_t *err;
+
+ tread = (ac_mem_test_read_t *)arg;
+ err = tread->error_buf;
+ if (ret_errno == EIO) {
+ (void) fprintf(debug_fp, "module_id=%#llx afsr=%#llx "
+ "afar=%#llx udbh_error_reg=%#llx "
+ "udbl_error_reg=%#llx\n",
+ (longlong_t)err->module_id, (longlong_t)err->afsr,
+ (longlong_t)err->afar,
+ (longlong_t)err->udbh_error_reg,
+ (longlong_t)err->udbl_error_reg);
+ } else {
+ (void) fprintf(debug_fp, "\n");
+ }
+ }
+ break;
+ case AC_MEM_TEST_WRITE:
+ break;
+ case AC_MEM_ADMIN_VER: {
+ ac_mem_version_t *ver;
+
+ ver = (ac_mem_version_t *)arg;
+ (void) fprintf(debug_fp, " version %d\n", *ver);
+ }
+ break;
+ case AC_MEM_STAT: {
+ ac_stat_t *tstat;
+
+ tstat = (ac_stat_t *)arg;
+ (void) fprintf(debug_fp, " rstate=%u ostate=%u "
+ "condition=%u status_time=%#lx board=%u\n",
+ (uint_t)tstat->rstate, (uint_t)tstat->ostate,
+ (uint_t)tstat->condition, (ulong_t)tstat->status_time,
+ tstat->board);
+ (void) fprintf(debug_fp, " real_size=%u use_size=%u "
+ "busy=%u\n",
+ tstat->real_size, tstat->use_size, tstat->busy);
+ (void) fprintf(debug_fp, " page_size=%#x "
+ "phys_pages=%#llx managed=%#llx nonrelocatable=%#llx\n",
+ tstat->page_size, (longlong_t)tstat->phys_pages,
+ (longlong_t)tstat->managed,
+ (longlong_t)tstat->nonrelocatable);
+ (void) fprintf(debug_fp, " memctl=%#llx "
+ "decode0=%#llx decode1=%#llx\n",
+ (longlong_t)tstat->ac_memctl, (longlong_t)tstat->ac_decode0,
+ (longlong_t)tstat->ac_decode1);
+ }
+ break;
+ case AC_MEM_EXERCISE: {
+ ac_cfga_cmd_t *cmdp;
+
+ cmdp = arg;
+ switch (cmdp->arg) {
+ case AC_MEMX_RELOCATE_ALL: {
+ struct ac_memx_relocate_stats *stp;
+
+ if ((stp = cmdp->private) != NULL) {
+ (void) fprintf(debug_fp, " base=%u npgs=%u"
+ " nopaget=%u nolock=%u isfree=%u reloc=%u"
+ " noreloc=%u\n",
+ stp->base, stp->npgs, stp->nopaget,
+ stp->nolock, stp->isfree, stp->reloc,
+ stp->noreloc);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ (void) fflush(debug_fp);
+}
+#endif /* DEV_DEBUG */
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.c b/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.c
new file mode 100644
index 0000000000..6f44fbd37b
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.c
@@ -0,0 +1,270 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/param.h>
+#include <sys/obpdefs.h>
+#include <sys/fhc.h>
+#include <sys/ac.h>
+#include <sys/sysctrl.h>
+#include <sys/openpromio.h>
+#include "mema_prom.h"
+#include <config_admin.h>
+
+
+/*
+ * PROM access routines to get and set disabled lists
+ * Based on code in the usr/src/cmd/eeprom directory.
+ */
+#define PROMDEV "/dev/openprom"
+/*
+ * 128 is the size of the largest (currently) property name
+ * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
+ * (currently) property value, viz. nvramrc.
+ * the sizeof(u_int) is from struct openpromio
+ */
+
+#define MAXPROPSIZE 128
+#define MAXNAMESIZE MAXPROPSIZE
+#define MAXVALSIZE (8192 - MAXPROPSIZE - sizeof (u_int))
+#define BUFSIZE (MAXPROPSIZE + MAXVALSIZE + sizeof (u_int))
+typedef union {
+ char buf[BUFSIZE];
+ struct openpromio opp;
+} Oppbuf;
+#define PROP_MEMORY_LIST "disabled-memory-list"
+
+static int prom_read_one(mema_disabled_t *, int, int, char *, u_int);
+static int prom_write_one(mema_disabled_t *, int, int, char *, u_int);
+
+int
+prom_read_disabled_list(mema_disabled_t *dp, int bd)
+{
+ int prom_fd;
+ int ret;
+
+ (void) memset((void *)dp, 0, sizeof (*dp));
+ prom_fd = open(PROMDEV, O_RDONLY);
+ if (prom_fd == -1) {
+ return (0);
+ }
+ ret = prom_read_one(dp, bd, prom_fd,
+ PROP_MEMORY_LIST, PROM_MEMORY_DISABLED);
+ (void) close(prom_fd);
+ return (ret);
+}
+
+int
+prom_write_disabled_list(mema_disabled_t *dp, int bd)
+{
+ int prom_fd;
+ int ret;
+
+ prom_fd = open(PROMDEV, O_RDWR);
+ if (prom_fd == -1) {
+ return (0);
+ }
+ ret = prom_write_one(dp, bd, prom_fd,
+ PROP_MEMORY_LIST, PROM_MEMORY_DISABLED);
+ (void) close(prom_fd);
+ return (ret);
+}
+
+static int
+prom_read_one(
+ mema_disabled_t *dp,
+ int bd,
+ int prom_fd,
+ char *var,
+ u_int bit)
+{
+ Oppbuf oppbuf;
+ struct openpromio *opp = &oppbuf.opp;
+ int ret;
+
+ (void) memset((void *)&oppbuf, 0, sizeof (oppbuf));
+ (void) strncpy(opp->oprom_array, var, MAXNAMESIZE);
+ opp->oprom_size = MAXVALSIZE;
+ if (ioctl(prom_fd, OPROMGETOPT, opp) == -1) {
+ ret = 0;
+ } else
+ if (opp->oprom_size == 0) {
+ /* Not a failure - just not set to anything */
+ ret = 1;
+ } else {
+ char *cp;
+ int board;
+
+ ret = 1;
+ for (cp = opp->oprom_array; *cp != '\0'; cp++) {
+ switch (*cp) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ board = *cp - '0';
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ board = *cp - 'a' + 10;
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ board = *cp - 'A' + 10;
+ break;
+ default:
+ /* Ignore bad characters. */
+ /* TODO: maybe should set ret to 0? */
+ board = -1;
+ break;
+ }
+ if (board == bd)
+ *dp |= bit;
+ }
+ }
+ return (ret);
+}
+
+static int
+prom_write_one(
+ mema_disabled_t *dp,
+ int bd,
+ int prom_fd,
+ char *var,
+ u_int bit)
+{
+ Oppbuf in_oppbuf;
+ struct openpromio *in_opp = &in_oppbuf.opp;
+ Oppbuf oppbuf;
+ struct openpromio *opp = &oppbuf.opp;
+ int ret;
+ char *cp;
+
+ /* Setup output buffer. */
+ (void) memset((void *)&oppbuf, 0, sizeof (oppbuf));
+ (void) strncpy(opp->oprom_array, var, MAXNAMESIZE);
+ opp->oprom_size = strlen(var) + 1;
+ cp = opp->oprom_array + opp->oprom_size;
+
+ /*
+ * First read the existing list, filtering out 'bd' if 'bit'
+ * not set.
+ */
+ (void) memset((void *)&in_oppbuf, 0, sizeof (in_oppbuf));
+ (void) strncpy(in_opp->oprom_array, var, MAXNAMESIZE);
+ in_opp->oprom_size = MAXVALSIZE;
+ if (ioctl(prom_fd, OPROMGETOPT, in_opp) != -1 &&
+ in_opp->oprom_size != 0) {
+ char *icp;
+ int board;
+
+ for (icp = in_opp->oprom_array; *icp != '\0'; icp++) {
+ switch (*icp) {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ board = *icp - '0';
+ break;
+ case 'a': case 'b': case 'c':
+ case 'd': case 'e': case 'f':
+ board = *icp - 'a' + 10;
+ break;
+ case 'A': case 'B': case 'C':
+ case 'D': case 'E': case 'F':
+ board = *icp - 'A' + 10;
+ break;
+ default:
+ /* Ignore bad characters. */
+ continue;
+ }
+ /* If enabling this board ... */
+ if (board == bd && (*dp & bit) == 0)
+ continue;
+ *cp++ = "0123456789abcdef"[board];
+ opp->oprom_size++;
+ }
+ }
+
+ if ((*dp & bit) != 0) {
+ *cp++ = "0123456789abcdef"[bd];
+ opp->oprom_size++;
+ }
+ if (ioctl(prom_fd, OPROMSETOPT, opp) == -1) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+ return (ret);
+}
+
+/*
+ * The PROM only has board-level disable of memory. If two banks are present
+ * on the board, both are either enabled or disabled at boot.
+ * The caller of this routine must set the PROM_MEMORY_PRESENT bits
+ * before calling this function.
+ */
+
+/*ARGSUSED*/
+int
+prom_viable_disabled_list(mema_disabled_t *dp)
+{
+#ifdef XXX
+ int board;
+
+ for (board = 0; board < MAX_BOARDS; board++) {
+ if ((dp->bank_A[board] & PROM_MEMORY_PRESENT) != 0 &&
+ (dp->bank_B[board] & PROM_MEMORY_PRESENT) != 0 &&
+ (dp->bank_A[board] & PROM_MEMORY_DISABLED) !=
+ (dp->bank_B[board] & PROM_MEMORY_DISABLED)) {
+ return (0);
+ }
+ }
+#endif
+ return (1);
+}
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.h b/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.h
new file mode 100644
index 0000000000..445620be3e
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.h
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _MEMA_SF_PROM_H
+#define _MEMA_SF_PROM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char mema_disabled_t;
+
+extern int prom_read_disabled_list(mema_disabled_t *, int);
+extern int prom_write_disabled_list(mema_disabled_t *, int);
+extern int prom_viable_disabled_list(mema_disabled_t *);
+
+#define PROM_MEMORY_DISABLED 0x02
+#define PROM_MEMORY_PRESENT 0x04 /* for viable check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MEMA_SF_PROM_H */
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_test.c b/usr/src/lib/cfgadm_plugins/ac/common/mema_test.c
new file mode 100644
index 0000000000..ff2c78f287
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_test.c
@@ -0,0 +1,723 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998, 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <config_admin.h>
+#include <memory.h>
+#include <sys/types.h>
+#include <time.h>
+#include "mema_test.h"
+
+typedef u_longlong_t pbuf_t;
+
+/*
+ * Test for stuck-at fault and transitional faults
+ * Algorithm:
+ * for i = 0 to npages
+ * write(0x55)
+ * for npages to 0
+ * read_compare(0x55)
+ * write(0xaa)
+ * for 0 to number of pages
+ * read_compare(0xaa)
+ * write(0x55)
+ * read_compare(0x55)
+ *
+ * stuck-at fault is detected because each cell have a 1 and a 0 is read
+ * transitional fault is detected because after each 0 to 1 and 1 to 0
+ * transition the value is check to be sure that the cell is not frozen.
+ */
+
+/*
+ * The following strings are subject of stderr output and
+ * gettext() is not used for them.
+ */
+static const char err_sum[] = "total error %u\n";
+static const char nts_msg[] = "Normal test started\n";
+static const char ntf_msg[] = "Normal test finished\n";
+static const char qts_msg[] = "Quick test started\n";
+static const char qtf_msg[] = "Quick test finished\n";
+static const char ets_msg[] = "Extended test started\n";
+static const char etf_msg[] = "Extended test finished\n";
+static const char m1_msg[] = " March 1, ";
+static const char m2_msg[] = " March 2, ";
+static const char m3_msg[] = " March 3, ";
+static const char m4_msg[] = " March 4, ";
+static const char wr_msg[] = "write. ";
+static const char rd_cmp_msg[] = "read/compare. ";
+static const char rpt_rd_cmp_msg[] = "repeated read/compare. ";
+static const char ml_rd_cmp_msg[] = "mixed line read/compare. ";
+static const char ln_rd_cmp_msg[] = "line read/compare. ";
+static const char report_msg[] = "%s%s%d%% complete.\n";
+static const char pg_header_msg[] = " Errors at page address: 0x%x.\n";
+static const char rd_err_msg[] = " Error reading page at address: 0x%x.\n";
+static const char wr_err_msg[] = " Error writing page at address: 0x%x.\n";
+static const
+char mem_err_msg[] = " Offset: 0x%x, data written/read: 0x%2x/0x%2x.\n";
+
+/*
+ * Macros do deal with test conditions.
+ */
+#define TEST_END(END_MSG) \
+ if ((handle->max_errors != 0) &&\
+ (handle->max_errors == total_errors)) {\
+ mtest_message(handle, (END_MSG));\
+ error_summary(handle, total_errors);\
+ SET_CONDITION(handle, cond);\
+ return (MTEST_DONE);\
+ }
+
+static void
+error_summary(mtest_handle_t handle, uint_t total_errors)
+{
+ char msgbuf[100];
+
+ (void) sprintf(msgbuf, err_sum, total_errors);
+ mtest_message(handle, msgbuf);
+}
+
+
+static void
+error_print(char *writebuf, char *readbuf, mtest_handle_t handle, long pageno,
+ uint_t *total_errorsp)
+{
+ char msgbuf[100];
+ size_t offset;
+
+ (void) sprintf(msgbuf, pg_header_msg, PAGE_SIZE(handle) * pageno);
+ mtest_message(handle, msgbuf);
+
+ for (offset = 0; offset < PAGE_SIZE(handle); offset++) {
+ if ((handle->max_errors != 0) &&
+ (readbuf[offset] != writebuf[offset]) &&
+ (handle->max_errors == *total_errorsp))
+ return;
+ else {
+ (*total_errorsp)++;
+ (void) sprintf(msgbuf, mem_err_msg, offset,
+ writebuf[offset], readbuf[offset]);
+ mtest_message(handle, msgbuf);
+ }
+ }
+}
+
+int
+memory_test_normal(
+ mtest_handle_t handle)
+{
+ pbuf_t *patternbuf1;
+ pbuf_t *patternbuf2;
+ pbuf_t *readbuf;
+ long npages, pageno;
+ struct mtest_error errbuf;
+ uint_t total_errors;
+ cfga_cond_t cond;
+ time_t time_rep;
+ char msgbuf[100];
+
+ patternbuf1 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ patternbuf2 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ readbuf = (pbuf_t *)mtest_allocate_page_buf(handle);
+ if (patternbuf1 == NULL || patternbuf2 == NULL || readbuf == NULL) {
+ return (MTEST_LIB_ERROR);
+ }
+
+ mtest_message(handle, nts_msg);
+ npages = BANK_SIZE(handle) / PAGE_SIZE(handle);
+
+ total_errors = 0;
+ cond = CFGA_COND_OK;
+
+ (void) memset((void *)patternbuf1, 0x55, PAGE_SIZE(handle));
+ (void) memset((void *)patternbuf2, 0xaa, PAGE_SIZE(handle));
+
+ time_rep = time(NULL) + REPORT_SEC;
+
+ for (pageno = 0; pageno < npages; pageno++) {
+ if (mtest_write(handle, (void *)patternbuf1, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg, wr_msg,
+ ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+ for (pageno = npages-1; pageno >= 0; pageno--) {
+ if (mtest_read(handle, (void *)readbuf, pageno, 0, 0, &errbuf)
+ == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ /*
+ * Keep going if max errors is 0 or limit not
+ * reached.
+ */
+ TEST_END(ntf_msg);
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf1, (void *)readbuf,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void *)patternbuf2, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg, rd_cmp_msg,
+ ((npages - pageno) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+ /* March 2 (repeated) */
+ for (pageno = 0; pageno < npages; pageno++) {
+ if (mtest_read(handle, (void *)readbuf, pageno, 0, 0, &errbuf)
+ == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (memcmp((void *)patternbuf2, (void *)readbuf,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf2, (void *)readbuf,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void *)patternbuf1, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_read(handle, (void *)readbuf, pageno, 0, 0, &errbuf)
+ == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf1, (void *)readbuf,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m2_msg,
+ rpt_rd_cmp_msg, ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+ mtest_message(handle, ntf_msg);
+ error_summary(handle, total_errors);
+ SET_CONDITION(handle, cond);
+ return (MTEST_DONE);
+}
+
+/* this test look only for stuck-at fault */
+int
+memory_test_quick(
+ mtest_handle_t handle)
+{
+ pbuf_t *patternbuf1;
+ pbuf_t *patternbuf2;
+ pbuf_t *readbuf;
+ long npages, pageno;
+ struct mtest_error errbuf;
+ uint_t total_errors;
+ cfga_cond_t cond;
+ time_t time_rep;
+ char msgbuf[100];
+
+ patternbuf1 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ patternbuf2 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ readbuf = (pbuf_t *)mtest_allocate_page_buf(handle);
+ if (patternbuf1 == NULL || patternbuf2 == NULL || readbuf == NULL) {
+ return (MTEST_LIB_ERROR);
+ }
+
+ mtest_message(handle, qts_msg);
+ npages = BANK_SIZE(handle) / PAGE_SIZE(handle);
+
+ total_errors = 0;
+ cond = CFGA_COND_OK;
+
+ (void) memset((void *)patternbuf1, 0x55, PAGE_SIZE(handle));
+ (void) memset((void *)patternbuf2, 0xaa, PAGE_SIZE(handle));
+
+ time_rep = time(NULL) + REPORT_SEC;
+
+ for (pageno = 0; pageno < npages; pageno++) {
+ if (mtest_write(handle, (void *)patternbuf1, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg, wr_msg,
+ ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+
+ for (pageno = npages-1; pageno >= 0; pageno--) {
+ if (mtest_read(handle, (void *)readbuf, pageno, 0, 0, &errbuf)
+ == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ /*
+ * Keep going if max errors is 0 or limit not
+ * reached.
+ */
+ TEST_END(qtf_msg);
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf1, (void *)readbuf,
+ handle, pageno, &total_errors);
+ TEST_END(qtf_msg);
+ }
+ if (mtest_write(handle, (void *)patternbuf2, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg, rd_cmp_msg,
+ ((npages - pageno) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+ /* March 2 */
+ for (pageno = 0; pageno < npages; pageno++) {
+ if (mtest_read(handle, (void *)readbuf, pageno, 0, 0, &errbuf)
+ == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(qtf_msg);
+ }
+ if (memcmp((void *)patternbuf2, (void *)readbuf,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf2, (void *)readbuf,
+ handle, pageno, &total_errors);
+ TEST_END(qtf_msg);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m2_msg, rd_cmp_msg,
+ ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+ mtest_message(handle, qtf_msg);
+ error_summary(handle, total_errors);
+ SET_CONDITION(handle, cond);
+ return (MTEST_DONE);
+}
+
+
+/* look for stuck-at, transition, coupling fault: inversion, idempotent */
+int
+memory_test_extended(
+ mtest_handle_t handle)
+{
+ pbuf_t *patternbuf0, *patternbuf1;
+ pbuf_t *readbuf0, *readbuf1, *readbuf2;
+ long npages, pageno;
+ long line;
+ struct mtest_error errbuf;
+ uint_t total_errors;
+ cfga_cond_t cond;
+ time_t time_rep;
+ char msgbuf[100];
+
+ patternbuf0 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ patternbuf1 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ readbuf0 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ readbuf1 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ readbuf2 = (pbuf_t *)mtest_allocate_page_buf(handle);
+ if (patternbuf0 == NULL || patternbuf1 == NULL ||
+ readbuf0 == NULL || readbuf1 == NULL || readbuf2 == NULL) {
+ return (MTEST_LIB_ERROR);
+ }
+
+ mtest_message(handle, ets_msg);
+ npages = BANK_SIZE(handle) / PAGE_SIZE(handle);
+
+ total_errors = 0;
+ cond = CFGA_COND_OK;
+
+ (void) memset((void *)patternbuf0, 0x55, PAGE_SIZE(handle));
+ (void) memset((void *)patternbuf1, 0xaa, PAGE_SIZE(handle));
+
+ time_rep = time(NULL) + REPORT_SEC;
+
+ for (pageno = 0; pageno < npages; pageno++) {
+ if (mtest_write(handle, (void *)patternbuf0, pageno, 0, 0)
+ == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg, wr_msg,
+ ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC;
+ }
+ }
+
+ /*
+ * Line tests take 5-9 time longer and the reprting interval
+ * should be extended 3-5 times.
+ */
+
+ /* March 1 */
+ for (pageno = npages-1; pageno >= 0; pageno--) {
+ for (line = (LINES_PER_PAGE(handle) - 1); line >= 0; line--) {
+ if (mtest_read(handle, (void *)readbuf0, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ /*
+ * Keep going if max errors is 0 or limit not
+ * reached.
+ */
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf1, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_read(handle, (void *)readbuf1, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf0, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_read(handle, (void *)readbuf2, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf1, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ return (MTEST_DEV_ERROR);
+ }
+ } /* line */
+ if (memcmp((void *)patternbuf0, (void *)readbuf0,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf0, (void *)readbuf0,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf1,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf1, (void *)readbuf1,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if (memcmp((void *)patternbuf0, (void *)readbuf2,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf0, (void *)readbuf2,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m1_msg,
+ ml_rd_cmp_msg, ((npages - pageno) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC * 3;
+ }
+ } /* page */
+
+ /* March 2 */
+ for (pageno = npages-1; pageno >= 0; pageno--) {
+ for (line = (LINES_PER_PAGE(handle) - 1); line >= 0; line--) {
+ if (mtest_read(handle, (void *)readbuf0, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ /*
+ * Keep going if max errors is 0 or limit not
+ * reached.
+ */
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf0, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_write(handle, (void*)patternbuf1, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf0,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m2_msg,
+ ln_rd_cmp_msg, ((npages - pageno) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC * 3;
+ }
+ } /* page */
+
+ /* March 3 */
+ for (pageno = 0; pageno < npages; pageno++) {
+ for (line = 0; line < LINES_PER_PAGE(handle); line++) {
+ if (mtest_read(handle, (void *)readbuf0, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf0, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_write(handle, (void*)patternbuf1, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_write(handle, (void*)patternbuf0, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ }
+ if (memcmp((void *)patternbuf1, (void *)readbuf0,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf1, (void *)readbuf0,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m3_msg,
+ ml_rd_cmp_msg, ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC * 3;
+ }
+ } /* page */
+
+ /* March 4 */
+ for (pageno = 0; pageno < npages; pageno++) {
+ for (line = 0; line < LINES_PER_PAGE(handle); line++) {
+ if (mtest_read(handle, (void *)readbuf0, pageno,
+ line, 1, &errbuf) == -1) {
+ (void) sprintf(msgbuf, rd_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (errbuf.error_type != MTEST_ERR_NONE) {
+ if (errbuf.error_type == MTEST_ERR_CE &&
+ cond != CFGA_COND_FAILED)
+ cond = CFGA_COND_FAILING;
+ else
+ cond = CFGA_COND_FAILED;
+ total_errors++;
+ TEST_END(ntf_msg);
+ }
+ if (mtest_write(handle, (void*)patternbuf1, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ if (mtest_write(handle, (void*)patternbuf0, pageno,
+ line, 1) == -1) {
+ (void) sprintf(msgbuf, wr_err_msg, pageno);
+ mtest_message(handle, msgbuf);
+ return (MTEST_DEV_ERROR);
+ }
+ }
+ if (memcmp((void *)patternbuf0, (void *)readbuf0,
+ PAGE_SIZE(handle)) != 0) {
+ cond = CFGA_COND_FAILED;
+ error_print((void *)patternbuf0, (void *)readbuf0,
+ handle, pageno, &total_errors);
+ TEST_END(ntf_msg);
+ }
+ if ((time(NULL) >= time_rep) || (pageno == npages - 1) ||
+ (pageno == 0)) {
+ (void) sprintf(msgbuf, report_msg, m4_msg,
+ ln_rd_cmp_msg, ((pageno + 1) * 100) / npages);
+ mtest_message(handle, msgbuf);
+ time_rep = time(NULL) + REPORT_SEC * 3;
+ }
+ } /* page */
+ mtest_message(handle, etf_msg);
+ error_summary(handle, total_errors);
+ SET_CONDITION(handle, cond);
+ return (MTEST_DONE);
+}
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_test.h b/usr/src/lib/cfgadm_plugins/ac/common/mema_test.h
new file mode 100644
index 0000000000..929eebabca
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_test.h
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _MEMA_TEST_H
+#define _MEMA_TEST_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mtest_alloc_ent {
+ struct mtest_alloc_ent *next;
+ void *buf;
+};
+
+struct mtest_handle {
+ u_longlong_t bank_size;
+ ulong_t page_size;
+ ulong_t line_size;
+ ulong_t lines_per_page;
+ cfga_cond_t condition;
+ int fd;
+ ulong_t max_errors;
+ struct mtest_alloc_ent *alloc_list;
+ void *drvhandle;
+ struct cfga_msg *msgp;
+};
+
+typedef struct mtest_handle *mtest_handle_t;
+
+typedef int mtest_func_t(mtest_handle_t);
+
+struct mtest_table_ent {
+ const char *test_name;
+ mtest_func_t *test_func;
+};
+extern struct mtest_table_ent mtest_table[];
+#define MTEST_DEFAULT_TEST (0)
+extern char **mtest_build_opts(int *maxerr_idx);
+
+#define BANK_SIZE(H) ((H)->bank_size)
+#define PAGE_SIZE(H) ((H)->page_size)
+#define LINE_SIZE(H) ((H)->line_size)
+#define LINES_PER_PAGE(H) ((H)->lines_per_page)
+#define SET_CONDITION(H, C) ((H)->condition = (C))
+
+struct mtest_error {
+ int error_type;
+};
+
+/*
+ * Error types.
+ */
+#define MTEST_ERR_NONE 0
+#define MTEST_ERR_UE 1
+#define MTEST_ERR_CE 2
+
+/*
+ * Test routine return codes.
+ */
+#define MTEST_DONE 0
+#define MTEST_LIB_ERROR 1
+#define MTEST_DEV_ERROR 2
+
+/*
+ * Each test is allowed maximum number of errors and the index has
+ * to be coordinated with the token table size in mema_test_config.c
+ */
+#define MAX_ERRORS 32
+#define REPORT_SEC 5
+
+/*
+ * Test functions should use this buffer allocation interface.
+ * The test framework will deallocate them on return.
+ */
+extern void *mtest_allocate_buf(mtest_handle_t, size_t);
+#define mtest_allocate_page_buf(H) mtest_allocate_buf((H), \
+ (size_t)PAGE_SIZE(H))
+extern void mtest_deallocate_buf(mtest_handle_t, void *);
+extern void mtest_deallocate_buf_all(mtest_handle_t);
+
+/*
+ * Test write: mtest_write(handle, buffer, page_num, line_offset, line_count)
+ * A line count of 0 indicates the whole page.
+ * A return of 0 indicates success. A return of -1 indicates a failure of
+ * the device interface.
+ */
+extern int mtest_write(mtest_handle_t, void *, u_longlong_t, uint_t, uint_t);
+extern int mtest_read(mtest_handle_t, void *, u_longlong_t, uint_t, uint_t,
+ struct mtest_error *);
+
+/*
+ * Message interface. If the upper layer has verbose on, the
+ * message will be seen by the user.
+ */
+extern void mtest_message(mtest_handle_t, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MEMA_TEST_H */
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_test_config.c b/usr/src/lib/cfgadm_plugins/ac/common/mema_test_config.c
new file mode 100644
index 0000000000..8391b631d8
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_test_config.c
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <config_admin.h>
+#include <memory.h>
+#include "mema_test.h"
+
+extern mtest_func_t memory_test_normal;
+extern mtest_func_t memory_test_quick;
+extern mtest_func_t memory_test_extended;
+
+/*
+ * Default test is first entry in the table (MTEST_DEFAULT_TEST).
+ */
+struct mtest_table_ent mtest_table[] = {
+ {"normal", memory_test_normal},
+ {"quick", memory_test_quick},
+ {"extended", memory_test_extended},
+};
+
+static char **opt_array;
+
+char **
+mtest_build_opts(int *maxerr_idx)
+{
+ if (opt_array == NULL) {
+ int nopts;
+ /*
+ * Test "type" options here, max_errors should be the
+ * last one.
+ */
+ nopts = sizeof (mtest_table) / sizeof (mtest_table[0]);
+ *maxerr_idx = nopts;
+
+ /*
+ * One extra option for "max_errors"
+ */
+ opt_array = (char **)malloc((nopts + 2) * sizeof (*opt_array));
+ if (opt_array != NULL) {
+ int i;
+
+ for (i = 0; i < nopts; i++)
+ opt_array[i] = (char *)mtest_table[i].test_name;
+
+ opt_array[nopts] = "max_errors";
+ opt_array[nopts + 1] = NULL;
+ }
+ }
+ *maxerr_idx = sizeof (mtest_table) / sizeof (mtest_table[0]);
+ return (opt_array);
+}
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_test_subr.c b/usr/src/lib/cfgadm_plugins/ac/common/mema_test_subr.c
new file mode 100644
index 0000000000..90a2656358
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_test_subr.c
@@ -0,0 +1,98 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/param.h>
+#include <memory.h>
+#include <config_admin.h>
+#include "mema_test.h"
+
+void *
+mtest_allocate_buf(
+ mtest_handle_t handle,
+ size_t size)
+{
+ struct mtest_alloc_ent *new_ent;
+
+ new_ent =
+ (struct mtest_alloc_ent *)malloc(sizeof (struct mtest_alloc_ent));
+ if (new_ent == NULL)
+ return (NULL);
+
+ new_ent->buf = malloc(size);
+ if (new_ent->buf == NULL) {
+ free((void *)new_ent);
+ return (NULL);
+ }
+ /* TODO: probably not thread safe? */
+ new_ent->next = handle->alloc_list;
+ handle->alloc_list = new_ent;
+
+ return (new_ent->buf);
+}
+
+/* This routine dedicated to George Cameron */
+void
+mtest_deallocate_buf(
+ mtest_handle_t handle,
+ void *buf)
+{
+ struct mtest_alloc_ent **p, *p1;
+
+ p = &handle->alloc_list;
+ while ((*p) != NULL && (*p)->buf != buf)
+ p = &(*p)->next;
+ assert((*p) != NULL);
+ p1 = *p;
+ *p = (*p)->next;
+ free(p1->buf);
+ free((void *)p1);
+}
+
+void
+mtest_deallocate_buf_all(mtest_handle_t handle)
+{
+ struct mtest_alloc_ent *p1;
+
+ while ((p1 = handle->alloc_list) != NULL) {
+ handle->alloc_list = p1->next;
+ free(p1->buf);
+ free((void *)p1);
+ }
+}
+
+void
+mtest_message(mtest_handle_t handle, const char *msg)
+{
+ if (handle->msgp != NULL && handle->msgp->message_routine != NULL) {
+ (*handle->msgp->message_routine)(handle->msgp->appdata_ptr,
+ msg);
+ }
+}
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_util.c b/usr/src/lib/cfgadm_plugins/ac/common/mema_util.c
new file mode 100644
index 0000000000..944d1c569b
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_util.c
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <locale.h>
+#include <sys/param.h>
+#include <config_admin.h>
+#include "mema_util.h"
+
+/*
+ * The libmemadm routines can return arbitrary error strings. As the
+ * calling program does not know how long these errors might be,
+ * the library routines must allocate the required space and the
+ * calling program must deallocate it.
+ *
+ * This routine povides a printf-like interface for creating the
+ * error strings.
+ */
+
+#define FMT_STR_SLOP (16)
+
+void
+__fmt_errstring(
+ char **errstring,
+ size_t extra_length_hint,
+ const char *fmt,
+ ...)
+{
+ char *ebuf;
+ size_t elen;
+ va_list ap;
+
+ /*
+ * If no errors required or error already set, return.
+ */
+ if ((errstring == NULL) || (*errstring != NULL))
+ return;
+
+ elen = strlen(fmt) + extra_length_hint + FMT_STR_SLOP;
+
+ if ((ebuf = (char *)malloc(elen + 1)) == NULL)
+ return;
+
+ va_start(ap, fmt);
+ (void) vsprintf(ebuf, fmt, ap);
+ va_end(ap);
+
+ if (strlen(ebuf) > elen)
+ abort();
+
+ *errstring = ebuf;
+}
diff --git a/usr/src/lib/cfgadm_plugins/ac/common/mema_util.h b/usr/src/lib/cfgadm_plugins/ac/common/mema_util.h
new file mode 100644
index 0000000000..f4a3710682
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/common/mema_util.h
@@ -0,0 +1,42 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _MEMA_UTIL_H
+#define _MEMA_UTIL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void __fmt_errstring(char **, size_t, const char *, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MEMA_UTIL_H */
diff --git a/usr/src/lib/cfgadm_plugins/ac/sparc/Makefile b/usr/src/lib/cfgadm_plugins/ac/sparc/Makefile
new file mode 100644
index 0000000000..b5723eab97
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/sparc/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1998, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/ac/sparc/Makefile
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/cfgadm_plugins/ac/sparcv9/Makefile b/usr/src/lib/cfgadm_plugins/ac/sparcv9/Makefile
new file mode 100644
index 0000000000..7fff4f77de
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/ac/sparcv9/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/ac/sparcv9/Makefile
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+.KEEP_STATE:
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/Makefile b/usr/src/lib/cfgadm_plugins/sysctrl/Makefile
new file mode 100644
index 0000000000..9d582057e8
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/Makefile
@@ -0,0 +1,73 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/cfgadm_plugins/sysctrl/Makefile
+
+include $(SRC)/Makefile.master
+
+SUBDIRS= $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+package := TARGET= package
+
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a -x sysctrl.xcl
+POFILE= sysctrl.po
+POFILES= generic.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+.KEEP_STATE:
+
+all clean clobber delete install lint package: $(SUBDIRS)
+
+$(MACH) $(MACH64): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext */*.[ch]`
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+FRC:
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/Makefile.com b/usr/src/lib/cfgadm_plugins/sysctrl/Makefile.com
new file mode 100644
index 0000000000..f37a852473
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/Makefile.com
@@ -0,0 +1,99 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/sysctrl/Makefile.com
+#
+
+include $(SRC)/lib/cfgadm_plugins/Makefile.com
+
+PLATFORM= sun4u
+LIBRARY= sysctrl.a
+VERS= .1
+
+OBJECTS= cfga.o
+
+# include library definitions
+include $(SRC)/lib/Makefile.lib
+
+INS.dir.root.sys= $(INS) -s -d -m $(DIRMODE) $@
+$(CH)INS.dir.root.sys= $(INS) -s -d -m $(DIRMODE) -u root -g sys $@
+INS.dir.root.bin= $(INS) -s -d -m $(DIRMODE) $@
+$(CH)INS.dir.root.bin= $(INS) -s -d -m $(DIRMODE) -u root -g bin $@
+
+USR_PLAT_DIR = $(ROOT)/usr/platform
+USR_PSM_DIR = $(USR_PLAT_DIR)/sun4u
+USR_PSM_LIB_DIR = $(USR_PSM_DIR)/lib
+USR_PSM_LIB_CFG_DIR = $(USR_PSM_LIB_DIR)/cfgadm
+USR_PSM_LIB_CFG_DIR_64 = $(USR_PSM_LIB_CFG_DIR)/$(MACH64)
+
+ROOTLIBDIR= $(USR_PSM_LIB_CFG_DIR)
+ROOTLIBDIR64= $(USR_PSM_LIB_CFG_DIR_64)
+
+MAPFILE= ../common/mapfile-vers
+SRCS= $(OBJECTS:%.o=../common/%.c)
+
+LIBS = $(DYNLIB)
+
+CFLAGS += $(CCVERBOSE)
+DYNFLAGS += -M $(MAPFILE)
+LDLIBS += -lc
+
+CPPFLAGS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(DYNLIB): $(MAPFILE)
+
+# Create target directories
+$(USR_PSM_DIR): $(LINKED_DIRS)
+ -$(INS.dir.root.sys)
+
+$(USR_PSM_LIB_DIR): $(USR_PSM_DIR) $(LINKED_LIB_DIRS)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR): $(USR_PSM_LIB_DIR) $(LINKED_CFG_DIRS)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR_64): $(USR_PSM_LIB_CFG_DIR)
+ -$(INS.dir.root.bin)
+
+$(USR_PSM_LIB_CFG_DIR)/%: % $(USR_PSM_LIB_CFG_DIR)
+ -$(INS.file)
+
+$(USR_PSM_LIB_CFG_DIR_64)/%: % $(USR_PSM_LIB_CFG_DIR_64)
+ -$(INS.file)
+
+# include library targets
+include $(SRC)/lib/Makefile.targ
+
+pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/common/cfga.c b/usr/src/lib/cfgadm_plugins/sysctrl/common/cfga.c
new file mode 100644
index 0000000000..1dca716564
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/common/cfga.c
@@ -0,0 +1,1480 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stddef.h>
+#include <locale.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <time.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/dditypes.h>
+#include <sys/modctl.h>
+#include <sys/obpdefs.h>
+#include <sys/fhc.h>
+#include <sys/sysctrl.h>
+#include <sys/openpromio.h>
+#ifdef SIM
+#include <sys/stat.h>
+#endif
+#define CFGA_PLUGIN_LIB
+#include <config_admin.h>
+
+#ifdef DEBUG
+#define DBG printf
+#define DBG1 printf
+#define DBG3 printf
+#define DBG4 printf
+#else
+#define DBG(a, b)
+#define DBG1(a)
+#define DBG3(a, b, c)
+#define DBG4(a, b, c, d)
+#endif
+
+#define BD_CPU 1
+#define BD_MEM 2
+#define BD_IO_2SBUS 3
+#define BD_IO_SBUS_FFB 4
+#define BD_IO_PCI 5
+#define BD_DISK 6
+#define BD_IO_2SBUS_SOCPLUS 7
+#define BD_IO_SBUS_FFB_SOCPLUS 8
+#define BD_UNKNOWN 9
+#define CMD_GETSTAT 10
+#define CMD_LIST 11
+#define CMD_CONNECT 12
+#define CMD_DISCONNECT 13
+#define CMD_CONFIGURE 14
+#define CMD_UNCONFIGURE 15
+#define CMD_QUIESCE 16
+#define CMD_INSERT 17
+#define CMD_REMOVE 18
+#define CMD_SET_COND 19
+#define OPT_ENABLE 20
+#define OPT_DISABLE 21
+#define ERR_PROM_OPEN 22
+#define ERR_PROM_GETPROP 23
+#define ERR_PROM_SETPROP 24
+#define ERR_TRANS 25
+#define ERR_CMD_INVAL 26
+#define ERR_OPT_INVAL 27
+#define ERR_AP_INVAL 28
+#define ERR_DISABLED 29
+#define DIAG_FORCE 30
+#define DIAG_TRANS_OK 31
+#define DIAG_FAILED 32
+#define DIAG_WAS_ENABLED 33
+#define DIAG_WAS_DISABLED 34
+#define DIAG_WILL_ENABLE 35
+#define DIAG_WILL_DISABLE 36
+#define HELP_HEADER 37
+#define HELP_QUIESCE 38
+#define HELP_INSERT 39
+#define HELP_REMOVE 40
+#define HELP_SET_COND 41
+#define HELP_ENABLE 42
+#define HELP_DISABLE 43
+#define HELP_UNKNOWN 44
+#define ASK_CONNECT 45
+#define STR_BD 46
+#define STR_COL 47
+#define COND_UNKNOWN 48
+#define COND_OK 49
+#define COND_FAILING 50
+#define COND_FAILED 51
+#define COND_UNUSABLE 52
+#define SYSC_COOLING 53
+#define SYSC_POWER 54
+#define SYSC_PRECHARGE 55
+#define SYSC_INTRANS 56
+#define SYSC_UTHREAD 57
+#define SYSC_KTHREAD 58
+#define SYSC_DEV_ATTACH 59
+#define SYSC_DEV_DETACH 60
+#define SYSC_NDI_ATTACH 61
+#define SYSC_NDI_DETACH 62
+#define SYSC_CORE_RESOURCE 63
+#define SYSC_OSTATE 64
+#define SYSC_RSTATE 65
+#define SYSC_COND 66
+#define SYSC_PROM 67
+#define SYSC_NOMEM 68
+#define SYSC_HOTPLUG 69
+#define SYSC_HW_COMPAT 70
+#define SYSC_NON_DR_PROM 71
+#define SYSC_SUSPEND 72
+#define SYSC_RESUME 73
+#define SYSC_UNKNOWN 74
+#define SYSC_DEVSTR 75
+
+/*
+ * The string table contains all the strings used by the platform
+ * library. The comment next to each string specifies whether the
+ * string should be internationalized (y) or not (n).
+ * Note that there are calls to dgettext() with strings other than
+ * the ones below, they are marked by the li18 symbol.
+ */
+static char *
+cfga_strs[] = {
+ /* */ NULL,
+ /* n */ "cpu/mem ",
+ /* n */ "mem ",
+ /* n */ "dual-sbus ",
+ /* n */ "sbus-upa ",
+ /* n */ "dual-pci ",
+ /* n */ "disk ",
+ /* n */ "soc+sbus ",
+ /* n */ "soc+upa ",
+ /* n */ "unknown ",
+ /* n */ "get-status",
+ /* n */ "list",
+ /* n */ "connect",
+ /* n */ "disconnect",
+ /* n */ "configure",
+ /* n */ "unconfigure",
+ /* n */ "quiesce-test",
+ /* n */ "insert-test",
+ /* n */ "remove-test",
+ /* n */ "set-condition-test",
+ /* n */ "enable-at-boot",
+ /* n */ "disable-at-boot",
+ /* n */ "prom open",
+ /* n */ "prom getprop",
+ /* n */ "prom setprop",
+ /* y */ "invalid transition",
+ /* y */ "invalid command: ",
+ /* y */ "invalid option: ",
+ /* y */ "invalid attachment point: ",
+ /* y */ "board is disabled: must override with ",
+ /* n */ "[-f][-o enable-at-boot]",
+ /* y */ "transition succeeded but ",
+ /* y */ " failed: ",
+ /* y */ "was already enabled at boot time",
+ /* y */ "was already disabled at boot time",
+ /* y */ "will be enabled at boot time",
+ /* y */ "will be disabled at boot time",
+ /* y */ "\nSysctrl specific commands/options:",
+ /* n */ "\t-x quiesce-test ap_id [ap_id...]",
+ /* n */ "\t-x insert-test ap_id [ap_id...]",
+ /* n */ "\t-x remove-test ap_id [ap_id...]",
+ /* n */ "\t-x set-condition-test=<condition>",
+ /* n */ "\t-o enable-at-boot",
+ /* n */ "\t-o disable-at-boot",
+ /* y */ "\tunknown command or option: ",
+ /* y */
+ "system will be temporarily suspended to connect a board: proceed",
+ /* y */ "board ",
+ /* y */ ": ",
+ /* n */ "unknown",
+ /* n */ "ok",
+ /* n */ "failing",
+ /* n */ "failed",
+ /* n */ "unusable",
+ /* y */ "not enough cooling for a new board",
+ /* y */ "not enough power for a new board",
+ /* y */ "not enough precharge power for a new board",
+ /* y */ "configuration operation already in progress on this board",
+ /* y */ "could not suspend user process: ",
+ /* y */ "could not suspend system processes",
+ /* y */ "device did not attach",
+ /* y */ "device did not detach",
+ /* y */ "nexus error during attach",
+ /* y */ "nexus error during detach",
+ /* y */ "attempt to remove core system resource",
+ /* y */ "invalid occupant state",
+ /* y */ "invalid receptacle state",
+ /* y */ "insufficient condition",
+ /* y */ "firmware operation error",
+ /* y */ "not enough memory",
+ /* y */ "hotplug feature unavailable on this machine",
+ /* y */ "board does not support dynamic reconfiguration",
+ /* y */ "firmware does not support dynamic reconfiguration",
+ /* y */ "system suspend error",
+ /* y */ "system resume error",
+ /* y */ "unknown system error",
+ /* */ NULL
+};
+
+#define cfga_str(i) cfga_strs[(i)]
+
+#define cfga_eid(a, b) (((a) << 8) + (b))
+
+/*
+ *
+ * Translation table for mapping from an <errno,sysc_err>
+ * pair to an error string.
+ *
+ *
+ * SYSC_COOLING, EAGAIN, SYSC_ERR_COOLING
+ * SYSC_POWER, EAGAIN, SYSC_ERR_POWER
+ * SYSC_PRECHARGE, EAGAIN, SYSC_ERR_PRECHARGE
+ * SYSC_INTRANS, EBUSY, SYSC_ERR_INTRANS
+ * SYSC_KTHREAD, EBUSY, SYSC_ERR_KTHREAD
+ * SYSC_DEV_ATTACH, EBUSY, SYSC_ERR_NDI_ATTACH
+ * SYSC_DEV_DETACH, EBUSY, SYSC_ERR_NDI_DETACH
+ * SYSC_NDI_ATTACH, EFAULT, SYSC_ERR_NDI_ATTACH
+ * SYSC_NDI_DETACH, EFAULT, SYSC_ERR_NDI_DETACH
+ * SYSC_CORE_RESOURCE, EINVAL, SYSC_ERR_CORE_RESOURCE
+ * SYSC_OSTATE, EINVAL, SYSC_ERR_OSTATE
+ * SYSC_RSTATE, EINVAL, SYSC_ERR_RSTATE
+ * SYSC_COND, EINVAL, SYSC_ERR_COND
+ * SYSC_PROM, EIO, SYSC_ERR_PROM
+ * SYSC_NOMEM, ENOMEM, SYSC_ERR_DR_INIT
+ * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_ATTACH
+ * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_DETACH
+ * SYSC_HOTPLUG, ENOTSUP, SYSC_ERR_HOTPLUG
+ * SYSC_HW_COMPAT, ENOTSUP, SYSC_ERR_HW_COMPAT
+ * SYSC_NON_DR_PROM, ENOTSUP, SYSC_ERR_NON_DR_PROM
+ * SYSC_SUSPEND, ENXIO, SYSC_ERR_SUSPEND
+ * SYSC_RESUME, ENXIO, SYSC_ERR_RESUME
+ * SYSC_UTHREAD, ESRCH, SYSC_ERR_UTHREAD
+ */
+static int
+cfga_sid(int err, int scerr)
+{
+ if (scerr == SYSC_ERR_DEFAULT)
+ return (SYSC_UNKNOWN);
+
+ switch (cfga_eid(err, scerr)) {
+ case cfga_eid(EAGAIN, SYSC_ERR_COOLING):
+ return (SYSC_COOLING);
+ case cfga_eid(EAGAIN, SYSC_ERR_POWER):
+ return (SYSC_POWER);
+ case cfga_eid(EAGAIN, SYSC_ERR_PRECHARGE):
+ return (SYSC_PRECHARGE);
+ case cfga_eid(EBUSY, SYSC_ERR_INTRANS):
+ return (SYSC_INTRANS);
+ case cfga_eid(EBUSY, SYSC_ERR_KTHREAD):
+ return (SYSC_KTHREAD);
+ case cfga_eid(EBUSY, SYSC_ERR_NDI_ATTACH):
+ return (SYSC_DEV_ATTACH);
+ case cfga_eid(EBUSY, SYSC_ERR_NDI_DETACH):
+ return (SYSC_DEV_DETACH);
+ case cfga_eid(EFAULT, SYSC_ERR_NDI_ATTACH):
+ return (SYSC_NDI_ATTACH);
+ case cfga_eid(EFAULT, SYSC_ERR_NDI_DETACH):
+ return (SYSC_NDI_DETACH);
+ case cfga_eid(EINVAL, SYSC_ERR_CORE_RESOURCE):
+ return (SYSC_CORE_RESOURCE);
+ case cfga_eid(EINVAL, SYSC_ERR_OSTATE):
+ return (SYSC_OSTATE);
+ case cfga_eid(EINVAL, SYSC_ERR_RSTATE):
+ return (SYSC_RSTATE);
+ case cfga_eid(EINVAL, SYSC_ERR_COND):
+ return (SYSC_COND);
+ case cfga_eid(EIO, SYSC_ERR_PROM):
+ return (SYSC_PROM);
+ case cfga_eid(ENOMEM, SYSC_ERR_DR_INIT):
+ return (SYSC_NOMEM);
+ case cfga_eid(ENOMEM, SYSC_ERR_NDI_ATTACH):
+ return (SYSC_NOMEM);
+ case cfga_eid(ENOMEM, SYSC_ERR_NDI_DETACH):
+ return (SYSC_NOMEM);
+ case cfga_eid(ENOTSUP, SYSC_ERR_HOTPLUG):
+ return (SYSC_HOTPLUG);
+ case cfga_eid(ENOTSUP, SYSC_ERR_HW_COMPAT):
+ return (SYSC_HW_COMPAT);
+ case cfga_eid(ENOTSUP, SYSC_ERR_NON_DR_PROM):
+ return (SYSC_NON_DR_PROM);
+ case cfga_eid(ENXIO, SYSC_ERR_SUSPEND):
+ return (SYSC_SUSPEND);
+ case cfga_eid(ENXIO, SYSC_ERR_RESUME):
+ return (SYSC_RESUME);
+ case cfga_eid(ESRCH, SYSC_ERR_UTHREAD):
+ return (SYSC_UTHREAD);
+ default:
+ break;
+ }
+
+ return (SYSC_UNKNOWN);
+}
+
+static void
+sysc_cmd_init(sysc_cfga_cmd_t *sc, char *outputstr, int force)
+{
+ sc->force = force;
+ sc->outputstr = outputstr;
+ sc->errtype = SYSC_ERR_DEFAULT;
+
+ (void) memset((void *)outputstr, 0, sizeof (outputstr));
+
+ cfga_str(SYSC_DEVSTR) = outputstr;
+}
+
+/*
+ * cfga_err() accepts a variable number of message IDs and constructs
+ * a corresponding error string which is returned via the errstring argument.
+ * cfga_err() calls dgettext() to internationalize proper messages.
+ */
+static void
+cfga_err(sysc_cfga_cmd_t *sc, char **errstring, ...)
+{
+ int a;
+ int i;
+ int n;
+ int len;
+ int flen;
+ char *p;
+ char *q;
+ char *s[32];
+ char *failed;
+ va_list ap;
+ char syserr_num[20];
+
+ /*
+ * If errstring is null it means user in not interested in getting
+ * error status. So we don't do all the work
+ */
+ if (errstring == NULL) {
+ return;
+ }
+ va_start(ap, errstring);
+
+ failed = dgettext(TEXT_DOMAIN, cfga_str(DIAG_FAILED));
+ flen = strlen(failed);
+
+ for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
+
+ switch (a) {
+ case ERR_PROM_OPEN:
+ case ERR_PROM_GETPROP:
+ case ERR_PROM_SETPROP:
+ case CMD_GETSTAT:
+ case CMD_LIST:
+ case CMD_CONNECT:
+ case CMD_DISCONNECT:
+ case CMD_CONFIGURE:
+ case CMD_UNCONFIGURE:
+ case CMD_QUIESCE:
+ case CMD_INSERT:
+ case CMD_REMOVE:
+ case CMD_SET_COND:
+ p = cfga_str(a);
+ len += (strlen(p) + flen);
+ s[n] = p;
+ s[++n] = failed;
+
+ DBG("<%s>", p);
+ DBG("<%s>", failed);
+ break;
+
+ case OPT_ENABLE:
+ case OPT_DISABLE:
+ p = dgettext(TEXT_DOMAIN, cfga_str(DIAG_TRANS_OK));
+ q = cfga_str(a);
+ len += (strlen(p) + strlen(q) + flen);
+ s[n] = p;
+ s[++n] = q;
+ s[++n] = failed;
+
+ DBG("<%s>", p);
+ DBG("<%s>", q);
+ DBG("<%s>", failed);
+ break;
+
+ case ERR_CMD_INVAL:
+ case ERR_AP_INVAL:
+ case ERR_OPT_INVAL:
+ p = dgettext(TEXT_DOMAIN, cfga_str(a));
+ q = va_arg(ap, char *);
+ len += (strlen(p) + strlen(q));
+ s[n] = p;
+ s[++n] = q;
+
+ DBG("<%s>", p);
+ DBG("<%s>", q);
+ break;
+
+ case ERR_TRANS:
+ case ERR_DISABLED:
+ p = dgettext(TEXT_DOMAIN, cfga_str(a));
+ len += strlen(p);
+ s[n] = p;
+
+ DBG("<%s>", p);
+ break;
+
+ case DIAG_FORCE:
+ default:
+ p = cfga_str(a);
+ len += strlen(p);
+ s[n] = p;
+
+ DBG("<%s>", p);
+ break;
+ }
+ }
+
+ DBG1("\n");
+ va_end(ap);
+
+ if (errno) {
+ if (sc)
+ i = cfga_sid(errno, (int)sc->errtype);
+ else
+ i = SYSC_UNKNOWN;
+
+ DBG4("cfga_sid(%d,%d)=%d\n", errno, sc->errtype, i);
+
+ if (i == SYSC_UNKNOWN) {
+ p = strerror(errno);
+ if (p == NULL) {
+ (void) sprintf(syserr_num, "errno=%d", errno);
+ p = syserr_num;
+ }
+ } else
+ p = dgettext(TEXT_DOMAIN, cfga_str(i));
+
+ len += strlen(p);
+ s[n++] = p;
+ p = cfga_str(SYSC_DEVSTR);
+ if (p && p[0]) {
+ q = cfga_str(STR_COL);
+
+ len += strlen(q);
+ s[n++] = q;
+ len += strlen(p);
+ s[n++] = p;
+ }
+ }
+
+ if ((p = (char *)calloc(len, 1)) == NULL)
+ return;
+
+ for (i = 0; i < n; i++)
+ (void) strcat(p, s[i]);
+
+ *errstring = p;
+#ifdef SIM_MSG
+ printf("%s\n", *errstring);
+#endif
+}
+
+/*
+ * This routine accepts a variable number of message IDs and constructs
+ * a corresponding error string which is printed via the message print routine
+ * argument. The HELP_UNKNOWN message ID has an argument string (the unknown
+ * help topic) that follows.
+ */
+static void
+cfga_msg(struct cfga_msg *msgp, ...)
+{
+ int a;
+ int i;
+ int n;
+ int len;
+ char *p;
+ char *s[32];
+ va_list ap;
+
+ va_start(ap, msgp);
+
+ for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
+ DBG("<%d>", a);
+ p = dgettext(TEXT_DOMAIN, cfga_str(a));
+ len += strlen(p);
+ s[n] = p;
+ if (a == HELP_UNKNOWN) {
+ p = va_arg(ap, char *);
+ len += strlen(p);
+ s[++n] = p;
+ }
+ }
+
+ va_end(ap);
+
+ if ((p = (char *)calloc(len + 1, 1)) == NULL)
+ return;
+
+ for (i = 0; i < n; i++)
+ (void) strcat(p, s[i]);
+ (void) strcat(p, "\n");
+
+#ifdef SIM_MSG
+ printf("%s", p);
+#else
+ (*msgp->message_routine)(msgp->appdata_ptr, p);
+#endif
+ free(p);
+}
+
+static sysc_cfga_stat_t *
+sysc_stat(const char *ap_id, int *fdp)
+{
+ int fd;
+ static sysc_cfga_stat_t sc_list[MAX_BOARDS];
+
+
+ if ((fd = open(ap_id, O_RDWR, 0)) == -1)
+ return (NULL);
+ else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sc_list) == -1) {
+ (void) close(fd);
+ return (NULL);
+ } else if (fdp)
+ *fdp = fd;
+ else
+ (void) close(fd);
+
+ return (sc_list);
+}
+
+/*
+ * This code implementes the simulation of the ioctls that transition state.
+ * The GETSTAT ioctl is not simulated. In this way a snapshot of the system
+ * state is read and manipulated by the simulation routines. It is basically
+ * a useful debugging tool.
+ */
+#ifdef SIM
+static int sim_idx;
+static int sim_fd = -1;
+static int sim_size = MAX_BOARDS * sizeof (sysc_cfga_stat_t);
+static sysc_cfga_stat_t sim_sc_list[MAX_BOARDS];
+
+static sysc_cfga_stat_t *
+sim_sysc_stat(const char *ap_id, int *fdp)
+{
+ int fd;
+ struct stat buf;
+
+ if (sim_fd != -1)
+ return (sim_sc_list);
+
+ if ((sim_fd = open("/tmp/cfga_simdata", O_RDWR|O_CREAT)) == -1) {
+ perror("sim_open");
+ exit(1);
+ } else if (fstat(sim_fd, &buf) == -1) {
+ perror("sim_stat");
+ exit(1);
+ }
+
+ if (buf.st_size) {
+ if (buf.st_size != sim_size) {
+ perror("sim_size");
+ exit(1);
+ } else if (read(sim_fd, sim_sc_list, sim_size) == -1) {
+ perror("sim_read");
+ exit(1);
+ }
+ } else if ((fd = open(ap_id, O_RDWR, 0)) == -1)
+ return (NULL);
+ else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sim_sc_list) == -1) {
+ (void) close(fd);
+ return (NULL);
+ } else if (fdp)
+ *fdp = fd;
+
+ return (sim_sc_list);
+}
+
+static int
+sim_open(char *a, int b, int c)
+{
+ printf("sim_open(%s)\n", a);
+
+ if (strcmp(a, "/dev/openprom") == 0)
+ return (open(a, b, c));
+ return (0);
+}
+
+static int
+sim_close(int a) { return (0); }
+
+static int
+sim_ioctl(int fd, int cmd, void *a)
+{
+ printf("sim_ioctl(%d)\n", sim_idx);
+
+ switch (cmd) {
+ case SYSC_CFGA_CMD_CONNECT:
+ sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_CONNECTED;
+ break;
+ case SYSC_CFGA_CMD_CONFIGURE:
+ sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_CONFIGURED;
+ break;
+ case SYSC_CFGA_CMD_UNCONFIGURE:
+ sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
+ break;
+ case SYSC_CFGA_CMD_DISCONNECT:
+ sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
+ break;
+ case SYSC_CFGA_CMD_QUIESCE_TEST:
+ case SYSC_CFGA_CMD_TEST:
+ return (0);
+ case OPROMGETOPT:
+ return (ioctl(fd, OPROMGETOPT, a));
+ case OPROMSETOPT:
+ return (ioctl(fd, OPROMSETOPT, a));
+ }
+
+ if (lseek(sim_fd, SEEK_SET, 0) == -1) {
+ perror("sim_seek");
+ exit(1);
+ }
+ if (write(sim_fd, sim_sc_list, sim_size) == -1) {
+ perror("sim_write");
+ exit(1);
+ }
+
+ return (0);
+}
+
+#define open(a, b, c) sim_open((char *)(a), (int)(b), (int)(c))
+#define close(a) sim_close(a)
+#define ioctl(a, b, c) sim_ioctl((int)(a), (int)(b), (void *)(c))
+#define sysc_stat(a, b) sim_sysc_stat(a, b)
+#endif /* SIM */
+
+static char *promdev = "/dev/openprom";
+static char *dlprop = "disabled-board-list";
+
+#define BUFSIZE 128
+
+typedef union {
+ char buf[BUFSIZE];
+ struct openpromio opp;
+} oppbuf_t;
+
+static int
+prom_get_prop(int prom_fd, char *var, char **val)
+{
+ static oppbuf_t oppbuf;
+ struct openpromio *opp = &(oppbuf.opp);
+
+ (void) strncpy(opp->oprom_array, var, OBP_MAXPROPNAME);
+ opp->oprom_array[OBP_MAXPROPNAME + 1] = '\0';
+ opp->oprom_size = BUFSIZE;
+
+ DBG3("getprop(%s, %d)\n", opp->oprom_array, opp->oprom_size);
+
+ if (ioctl(prom_fd, OPROMGETOPT, opp) < 0)
+ return (ERR_PROM_GETPROP);
+ else if (opp->oprom_size > 0)
+ *val = opp->oprom_array;
+ else
+ *val = NULL;
+
+ return (0);
+}
+
+static cfga_err_t
+prom_set_prop(int prom_fd, char *var, char *val)
+{
+ oppbuf_t oppbuf;
+ struct openpromio *opp = &(oppbuf.opp);
+ int varlen = strlen(var) + 1;
+ int vallen = strlen(val);
+
+ DBG("prom_set_prop(%s)\n", val);
+
+ (void) strcpy(opp->oprom_array, var);
+ (void) strcpy(opp->oprom_array + varlen, val);
+ opp->oprom_size = varlen + vallen;
+
+ if (ioctl(prom_fd, OPROMSETOPT, opp) < 0)
+ return (ERR_PROM_SETPROP);
+
+ return (0);
+}
+
+static int
+dlist_find(int board, char **dlist, int *disabled)
+{
+ int i;
+ int err;
+ int prom_fd;
+ char *p;
+ char *dl;
+ char b[2];
+
+ if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
+ return (ERR_PROM_OPEN);
+ else if (err = prom_get_prop(prom_fd, dlprop, dlist)) {
+ (void) close(prom_fd);
+ return (err);
+ } else
+ (void) close(prom_fd);
+
+ b[1] = 0;
+ *disabled = 0;
+
+ if ((dl = *dlist) != NULL) {
+ int len = strlen(dl);
+
+ for (i = 0; i < len; i++) {
+ int bd;
+
+ b[0] = dl[i];
+ bd = strtol(b, &p, 16);
+
+ if (p != b && bd == board)
+ (*disabled)++;
+ }
+ }
+
+ return (0);
+}
+
+static int
+dlist_update(int board, int disable, char *dlist, struct cfga_msg *msgp,
+ int verbose)
+{
+ int i, j, n;
+ int err;
+ int found;
+ int update;
+ int prom_fd;
+ char *p;
+ char b[2];
+ char ndlist[64];
+
+ b[1] = 0;
+ ndlist[0] = 0;
+ j = 0;
+ found = 0;
+ update = 0;
+
+ if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
+ return (ERR_PROM_OPEN);
+
+ if (dlist) {
+ int len = strlen(dlist);
+
+ for (i = 0; i < len; i++) {
+ int bd;
+
+ b[0] = dlist[i];
+ bd = strtol(b, &p, 16);
+
+ if (p != b && bd == board) {
+
+ found++;
+ if (disable) {
+ if (verbose)
+ cfga_msg(msgp, STR_BD,
+ DIAG_WAS_DISABLED, 0);
+ } else {
+ if (verbose)
+ cfga_msg(msgp, STR_BD,
+ DIAG_WILL_ENABLE, 0);
+ update++;
+ continue;
+ }
+ }
+ ndlist[j++] = dlist[i];
+ }
+ ndlist[j] = 0;
+ }
+
+ if (!found)
+ if (disable) {
+ if (verbose)
+ cfga_msg(msgp, STR_BD, DIAG_WILL_DISABLE, 0);
+ p = &ndlist[j];
+ n = sprintf(p, "%x", board);
+ p[n] = 0;
+ update++;
+ } else {
+ if (verbose)
+ cfga_msg(msgp, STR_BD, DIAG_WAS_ENABLED, 0);
+ }
+
+ if (update)
+ err = prom_set_prop(prom_fd, dlprop, ndlist);
+ else
+ err = 0;
+
+ (void) close(prom_fd);
+
+ return (err);
+}
+
+static int
+ap_idx(const char *ap_id)
+{
+ int id;
+ char *s;
+ static char *slot = "slot";
+
+ DBG("ap_idx(%s)\n", ap_id);
+
+ if ((s = strstr(ap_id, slot)) == NULL)
+ return (-1);
+ else {
+ int n;
+
+ s += strlen(slot);
+ n = strlen(s);
+
+ DBG3("ap_idx: s=%s, n=%d\n", s, n);
+
+ switch (n) {
+ case 2:
+ if (!isdigit(s[1]))
+ return (-1);
+ /* FALLTHROUGH */
+ case 1:
+ if (!isdigit(s[0]))
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
+ }
+
+ if ((id = atoi(s)) > MAX_BOARDS)
+ return (-1);
+
+ DBG3("ap_idx(%s)=%d\n", s, id);
+
+ return (id);
+}
+
+/*ARGSUSED*/
+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)
+{
+ int fd;
+ int idx;
+ int err;
+ int force;
+ int verbose;
+ int opterr;
+ int disable;
+ int disabled;
+ cfga_err_t rc;
+ sysc_cfga_stat_t *ss;
+ sysc_cfga_cmd_t *sc, sysc_cmd;
+ sysc_cfga_rstate_t rs;
+ sysc_cfga_ostate_t os;
+ char *dlist;
+ char outputstr[SYSC_OUTPUT_LEN];
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ rc = CFGA_ERROR;
+
+ if (options) {
+ disable = 0;
+ if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
+ disable++;
+ else if (strcmp(options, cfga_str(OPT_ENABLE))) {
+ cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
+ return (rc);
+ }
+ }
+
+ if ((idx = ap_idx(ap_id)) == -1) {
+ cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
+ return (rc);
+ } else if ((ss = sysc_stat(ap_id, &fd)) == NULL) {
+ cfga_err(NULL, errstring, CMD_GETSTAT, 0);
+ return (rc);
+ }
+#ifdef SIM
+ sim_idx = idx;
+#endif
+ /*
+ * We disallow connecting on the disabled list unless
+ * either the FORCE flag or the enable-at-boot option
+ * is set. The check is made further below
+ */
+ if (opterr = dlist_find(idx, &dlist, &disabled)) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ (void) close(fd);
+ return (rc);
+ } else
+ force = flags & CFGA_FLAG_FORCE;
+
+ rs = ss[idx].rstate;
+ os = ss[idx].ostate;
+
+ sc = &sysc_cmd;
+ sysc_cmd_init(sc, outputstr, force);
+ verbose = flags & CFGA_FLAG_VERBOSE;
+
+ switch (state_change_cmd) {
+ case CFGA_CMD_CONNECT:
+ if (rs != SYSC_CFGA_RSTATE_DISCONNECTED)
+ cfga_err(NULL, errstring, ERR_TRANS, 0);
+ else if (disabled && !(force || (options && !disable)))
+ cfga_err(NULL, errstring, CMD_CONNECT,
+ ERR_DISABLED, DIAG_FORCE, 0);
+ else if (!(*confp->confirm)(confp->appdata_ptr,
+ cfga_str(ASK_CONNECT))) {
+ (void) close(fd);
+ return (CFGA_NACK);
+ } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1)
+ cfga_err(sc, errstring, CMD_CONNECT, 0);
+ else if (options && (opterr = dlist_update(idx, disable,
+ dlist, msgp, verbose))) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ } else
+ rc = CFGA_OK;
+ break;
+
+ case CFGA_CMD_DISCONNECT:
+ if ((os == SYSC_CFGA_OSTATE_CONFIGURED) &&
+ (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)) {
+ cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
+ (void) close(fd);
+ return (CFGA_ERROR);
+ } else
+ sysc_cmd_init(sc, outputstr, force);
+
+ if (rs == SYSC_CFGA_RSTATE_CONNECTED) {
+ if (ioctl(fd, SYSC_CFGA_CMD_DISCONNECT, sc) == -1)
+ cfga_err(sc, errstring, CMD_DISCONNECT, 0);
+ else if (options && (opterr = dlist_update(idx, disable,
+ dlist, msgp, verbose))) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ } else
+ rc = CFGA_OK;
+ } else
+ cfga_err(NULL, errstring, ERR_TRANS, 0);
+ break;
+
+ case CFGA_CMD_CONFIGURE:
+ if (rs == SYSC_CFGA_RSTATE_DISCONNECTED)
+ if (disabled && !(force || (options && !disable))) {
+ cfga_err(NULL, errstring, CMD_CONFIGURE,
+ ERR_DISABLED, DIAG_FORCE, 0);
+ (void) close(fd);
+ return (CFGA_ERROR);
+ } else if (!(*confp->confirm)(confp->appdata_ptr,
+ cfga_str(ASK_CONNECT))) {
+ (void) close(fd);
+ return (CFGA_NACK);
+ } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1) {
+ cfga_err(sc, errstring, CMD_CONNECT, 0);
+ (void) close(fd);
+ return (CFGA_ERROR);
+ } else
+ sysc_cmd_init(sc, outputstr, force);
+
+ if (os == SYSC_CFGA_OSTATE_UNCONFIGURED) {
+ if (ioctl(fd, SYSC_CFGA_CMD_CONFIGURE, sc) == -1)
+ cfga_err(sc, errstring, CMD_CONFIGURE, 0);
+ else if (options && (opterr = dlist_update(idx,
+ disable, dlist, msgp, verbose))) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ } else
+ rc = CFGA_OK;
+ } else
+ cfga_err(NULL, errstring, ERR_TRANS, 0);
+ break;
+
+ case CFGA_CMD_UNCONFIGURE:
+ if (os != SYSC_CFGA_OSTATE_CONFIGURED)
+ cfga_err(NULL, errstring, ERR_TRANS, 0);
+ else if (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)
+ cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
+ else if (options && (opterr = dlist_update(idx, disable,
+ dlist, msgp, verbose))) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ } else
+ rc = CFGA_OK;
+ break;
+
+ default:
+ rc = CFGA_OPNOTSUPP;
+ break;
+ }
+
+ (void) close(fd);
+ return (rc);
+}
+
+static int
+str2cond(const char *cond)
+{
+ int c;
+
+ if (strcmp(cond, cfga_str(COND_UNKNOWN)) == 0)
+ c = SYSC_CFGA_COND_UNKNOWN;
+ else if (strcmp(cond, cfga_str(COND_OK)) == 0)
+ c = SYSC_CFGA_COND_OK;
+ else if (strcmp(cond, cfga_str(COND_FAILING)) == 0)
+ c = SYSC_CFGA_COND_FAILING;
+ else if (strcmp(cond, cfga_str(COND_FAILED)) == 0)
+ c = SYSC_CFGA_COND_FAILED;
+ else if (strcmp(cond, cfga_str(COND_UNUSABLE)) == 0)
+ c = SYSC_CFGA_COND_UNUSABLE;
+ else
+ c = -1;
+
+ return (c);
+}
+
+/*ARGSUSED*/
+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)
+{
+ int fd;
+ int idx;
+ int len;
+ int cmd;
+ int cond;
+ int err;
+ int opterr;
+ int verbose;
+ int disable;
+ int disabled;
+ cfga_err_t rc;
+ char *str;
+ char *dlist;
+ char outputstr[SYSC_OUTPUT_LEN];
+ sysc_cfga_cmd_t *sc, sysc_cmd;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ verbose = flags & CFGA_FLAG_VERBOSE;
+
+ rc = CFGA_ERROR;
+
+ if (options) {
+ disable = 0;
+ if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
+ disable++;
+ else if (strcmp(options, cfga_str(OPT_ENABLE))) {
+ cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
+ return (rc);
+ }
+ }
+
+ sc = &sysc_cmd;
+ str = cfga_str(CMD_SET_COND);
+ len = strlen(str);
+
+ if ((strncmp(function, str, len) == 0) && (function[len++] == '=') &&
+ ((cond = (str2cond(&function[len]))) != -1)) {
+ cmd = SYSC_CFGA_CMD_TEST_SET_COND;
+ err = CMD_SET_COND;
+ sc->arg = cond;
+ } else if (strcmp(function, cfga_str(CMD_QUIESCE)) == 0) {
+ cmd = SYSC_CFGA_CMD_QUIESCE_TEST;
+ err = CMD_QUIESCE;
+ } else if (strcmp(function, cfga_str(CMD_INSERT)) == 0) {
+ cmd = SYSC_CFGA_CMD_TEST;
+ err = CMD_INSERT;
+ } else if (strcmp(function, cfga_str(CMD_REMOVE)) == 0) {
+ cmd = SYSC_CFGA_CMD_TEST;
+ err = CMD_REMOVE;
+ } else {
+ cfga_err(NULL, errstring, ERR_CMD_INVAL, (char *)function, 0);
+ return (rc);
+ }
+
+ sysc_cmd_init(sc, outputstr, 0);
+
+ if ((idx = ap_idx(ap_id)) == -1)
+ cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
+ else if (((fd = open(ap_id, O_RDWR, 0)) == -1) ||
+ (ioctl(fd, cmd, sc) == -1))
+ cfga_err(NULL, errstring, err, 0);
+ else
+ rc = CFGA_OK;
+
+ if (options) {
+ opterr = (dlist_find(idx, &dlist, &disabled) ||
+ dlist_update(idx, disable, dlist, msgp, verbose));
+ if (opterr) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ if (verbose)
+ cfga_msg(msgp, err, opterr, 0);
+ }
+ }
+
+ (void) close(fd);
+ return (rc);
+}
+
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_test(
+ const char *ap_id,
+ const char *options,
+ struct cfga_msg *msgp,
+ char **errstring,
+ cfga_flags_t flags)
+{
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ return (CFGA_OPNOTSUPP);
+}
+
+static cfga_stat_t
+rstate_cvt(sysc_cfga_rstate_t rs)
+{
+ cfga_stat_t cs;
+
+ switch (rs) {
+ case SYSC_CFGA_RSTATE_EMPTY:
+ cs = CFGA_STAT_EMPTY;
+ break;
+ case SYSC_CFGA_RSTATE_DISCONNECTED:
+ cs = CFGA_STAT_DISCONNECTED;
+ break;
+ case SYSC_CFGA_RSTATE_CONNECTED:
+ cs = CFGA_STAT_CONNECTED;
+ break;
+ default:
+ cs = CFGA_STAT_NONE;
+ break;
+ }
+
+ return (cs);
+}
+
+static cfga_stat_t
+ostate_cvt(sysc_cfga_ostate_t os)
+{
+ cfga_stat_t cs;
+
+ switch (os) {
+ case SYSC_CFGA_OSTATE_UNCONFIGURED:
+ cs = CFGA_STAT_UNCONFIGURED;
+ break;
+ case SYSC_CFGA_OSTATE_CONFIGURED:
+ cs = CFGA_STAT_CONFIGURED;
+ break;
+ default:
+ cs = CFGA_STAT_NONE;
+ break;
+ }
+
+ return (cs);
+}
+
+static cfga_cond_t
+cond_cvt(sysc_cfga_cond_t sc)
+{
+ cfga_cond_t cc;
+
+ switch (sc) {
+ case SYSC_CFGA_COND_OK:
+ cc = CFGA_COND_OK;
+ break;
+ case SYSC_CFGA_COND_FAILING:
+ cc = CFGA_COND_FAILING;
+ break;
+ case SYSC_CFGA_COND_FAILED:
+ cc = CFGA_COND_FAILED;
+ break;
+ case SYSC_CFGA_COND_UNUSABLE:
+ cc = CFGA_COND_UNUSABLE;
+ break;
+ case SYSC_CFGA_COND_UNKNOWN:
+ default:
+ cc = CFGA_COND_UNKNOWN;
+ break;
+ }
+
+ return (cc);
+}
+
+static char *
+type_str(enum board_type type)
+{
+ char *type_str;
+
+ switch (type) {
+ case MEM_BOARD:
+ type_str = cfga_str(BD_MEM);
+ break;
+ case CPU_BOARD:
+ type_str = cfga_str(BD_CPU);
+ break;
+ case IO_2SBUS_BOARD:
+ type_str = cfga_str(BD_IO_2SBUS);
+ break;
+ case IO_SBUS_FFB_BOARD:
+ type_str = cfga_str(BD_IO_SBUS_FFB);
+ break;
+ case IO_PCI_BOARD:
+ type_str = cfga_str(BD_IO_PCI);
+ break;
+ case DISK_BOARD:
+ type_str = cfga_str(BD_DISK);
+ break;
+ case IO_2SBUS_SOCPLUS_BOARD:
+ type_str = cfga_str(BD_IO_2SBUS_SOCPLUS);
+ break;
+ case IO_SBUS_FFB_SOCPLUS_BOARD:
+ type_str = cfga_str(BD_IO_SBUS_FFB_SOCPLUS);
+ break;
+ case UNKNOWN_BOARD:
+ default:
+ type_str = cfga_str(BD_UNKNOWN);
+ break;
+ }
+ return (type_str);
+}
+
+static void
+info_set(sysc_cfga_stat_t *sc, cfga_info_t info, int disabled)
+{
+ int i;
+ struct cpu_info *cpu;
+ union bd_un *bd = &sc->bd;
+
+ *info = NULL;
+
+ switch (sc->type) {
+ case CPU_BOARD:
+ for (i = 0, cpu = bd->cpu; i < 2; i++, cpu++) {
+ if (cpu->cpu_speed > 1) {
+ info += sprintf(info, "cpu %d: ", i);
+ info += sprintf(info, "%3d MHz ",
+ cpu->cpu_speed);
+ if (cpu->cache_size)
+ info += sprintf(info, "%0.1fM ",
+ (float)cpu->cache_size /
+ (float)(1024 * 1024));
+ }
+ }
+ break;
+ case IO_SBUS_FFB_BOARD:
+ switch (bd->io2.ffb_size) {
+ case FFB_SINGLE:
+ info += sprintf(info, "single buffered ffb ");
+ break;
+ case FFB_DOUBLE:
+ info += sprintf(info, "double buffered ffb ");
+ break;
+ case FFB_NOT_FOUND:
+#ifdef FFB_DR_SUPPORT
+ info += sprintf(info, "no ffb installed ");
+#endif
+ break;
+ default:
+ info += sprintf(info, "illegal ffb size ");
+ break;
+ }
+ break;
+ case DISK_BOARD:
+ for (i = 0; i < 2; i++)
+ if (bd->dsk.disk_pres[i])
+ info += sprintf(info, "target: %2d ",
+ bd->dsk.disk_id[i]);
+ else
+ info += sprintf(info, "no disk ");
+ break;
+ }
+
+ if (disabled)
+ info += sprintf(info, "disabled at boot ");
+
+ if (sc->no_detach)
+ info += sprintf(info, "non-detachable ");
+
+ if (sc->plus_board)
+ info += sprintf(info, "100 MHz capable ");
+}
+
+static void
+sysc_cvt(sysc_cfga_stat_t *sc, cfga_stat_data_t *cs, int disabled)
+{
+ (void) strcpy(cs->ap_type, type_str(sc->type));
+ cs->ap_r_state = rstate_cvt(sc->rstate);
+ cs->ap_o_state = ostate_cvt(sc->ostate);
+ cs->ap_cond = cond_cvt(sc->condition);
+ cs->ap_busy = (cfga_busy_t)sc->in_transition;
+ cs->ap_status_time = sc->last_change;
+ info_set(sc, cs->ap_info, disabled);
+ cs->ap_log_id[0] = NULL;
+ cs->ap_phys_id[0] = NULL;
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_list(
+ const char *ap_id,
+ cfga_stat_data_t **ap_list,
+ int *nlist,
+ const char *options,
+ char **errstring)
+{
+ int i;
+ cfga_err_t rc;
+ sysc_cfga_stat_t *sc;
+ cfga_stat_data_t *cs;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ rc = CFGA_ERROR;
+
+ if (ap_idx(ap_id) == -1)
+ cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
+ else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
+ cfga_err(NULL, errstring, CMD_LIST, 0);
+ else if (!(cs = (cfga_stat_data_t *)malloc(MAX_BOARDS * sizeof (*cs))))
+ cfga_err(NULL, errstring, CMD_LIST, 0);
+ else {
+ *ap_list = cs;
+
+ for (*nlist = 0, i = 0; i < MAX_BOARDS; i++, sc++) {
+ if (sc->board == -1)
+ continue;
+ sysc_cvt(sc, cs++, 0); /* XXX - disable */
+ (*nlist)++;
+ }
+
+ rc = CFGA_OK;
+ }
+
+ return (rc);
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_stat(
+ const char *ap_id,
+ struct cfga_stat_data *cs,
+ const char *options,
+ char **errstring)
+{
+ cfga_err_t rc;
+ int idx;
+ int err;
+ int opterr;
+ int disable;
+ int disabled;
+ char *dlist;
+ sysc_cfga_stat_t *sc;
+
+ if (errstring != NULL)
+ *errstring = NULL;
+
+ rc = CFGA_ERROR;
+
+ if (options && options[0]) {
+ disable = 0;
+ if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
+ disable++;
+ else if (strcmp(options, cfga_str(OPT_ENABLE))) {
+ cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
+ return (rc);
+ }
+ }
+
+ if ((idx = ap_idx(ap_id)) == -1)
+ cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
+ else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
+ cfga_err(NULL, errstring, CMD_GETSTAT, 0);
+ else {
+ opterr = dlist_find(idx, &dlist, &disabled);
+ sysc_cvt(sc + idx, cs, disabled);
+
+ rc = CFGA_OK;
+
+ if (options && options[0] && ((opterr != 0) ||
+ ((opterr = dlist_update(idx, disable, dlist, NULL, 0))
+ != 0))) {
+ err = disable ? OPT_DISABLE : OPT_ENABLE;
+ cfga_err(NULL, errstring, err, opterr, 0);
+ }
+ }
+
+ return (rc);
+}
+
+/*ARGSUSED*/
+cfga_err_t
+cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
+{
+ int help = 0;
+
+ if (options) {
+ if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
+ help = HELP_DISABLE;
+ else if (strcmp(options, cfga_str(OPT_ENABLE)) == 0)
+ help = HELP_ENABLE;
+ else if (strcmp(options, cfga_str(CMD_INSERT)) == 0)
+ help = HELP_INSERT;
+ else if (strcmp(options, cfga_str(CMD_REMOVE)) == 0)
+ help = HELP_REMOVE;
+ else if (strcmp(options, cfga_str(CMD_QUIESCE)) == 0)
+ help = HELP_QUIESCE;
+ else
+ help = HELP_UNKNOWN;
+ }
+
+ if (help) {
+ if (help == HELP_UNKNOWN)
+ cfga_msg(msgp, help, options, 0);
+ else
+ cfga_msg(msgp, help, 0);
+ } else {
+ cfga_msg(msgp, HELP_HEADER, 0);
+ cfga_msg(msgp, HELP_DISABLE, 0);
+ cfga_msg(msgp, HELP_ENABLE, 0);
+ cfga_msg(msgp, HELP_INSERT, 0);
+ cfga_msg(msgp, HELP_REMOVE, 0);
+ cfga_msg(msgp, HELP_QUIESCE, 0);
+ cfga_msg(msgp, HELP_SET_COND, 0);
+ }
+
+ return (CFGA_OK);
+}
+
+/*
+ * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
+ */
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/common/mapfile-vers b/usr/src/lib/cfgadm_plugins/sysctrl/common/mapfile-vers
new file mode 100644
index 0000000000..6d56c4331a
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/common/mapfile-vers
@@ -0,0 +1,38 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+SUNWprivate_1.1 {
+ global:
+ cfga_change_state;
+ cfga_private_func;
+ cfga_test;
+ cfga_stat;
+ cfga_list;
+ cfga_help;
+ local:
+ *;
+};
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/sparc/Makefile b/usr/src/lib/cfgadm_plugins/sysctrl/sparc/Makefile
new file mode 100644
index 0000000000..2be38997cb
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/sparc/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1998, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/sysctrl/sparc/Makefile
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/sparcv9/Makefile b/usr/src/lib/cfgadm_plugins/sysctrl/sparcv9/Makefile
new file mode 100644
index 0000000000..53a2dc875c
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/sparcv9/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/sysctrl/sparcv9/Makefile
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+.KEEP_STATE:
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/cfgadm_plugins/sysctrl/sysctrl.xcl b/usr/src/lib/cfgadm_plugins/sysctrl/sysctrl.xcl
new file mode 100644
index 0000000000..852c813749
--- /dev/null
+++ b/usr/src/lib/cfgadm_plugins/sysctrl/sysctrl.xcl
@@ -0,0 +1,94 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+msgid "cpu/mem "
+msgid "mem "
+msgid "dual-sbus "
+msgid "sbus-upa "
+msgid "dual-pci "
+msgid "disk "
+msgid "soc+sbus "
+msgid "soc+upa "
+msgid "unknown "
+msgid "get-status"
+msgid "list"
+msgid "connect"
+msgid "disconnect"
+msgid "configure"
+msgid "unconfigure"
+msgid "quiesce-test"
+msgid "insert-test"
+msgid "remove-test"
+msgid "set-condition-test"
+msgid "enable-at-boot"
+msgid "disable-at-boot"
+msgid "prom open"
+msgid "prom getprop"
+msgid "prom setprop"
+msgid "[-f][-o enable-at-boot]"
+msgid "\t-x quiesce-test ap_id [ap_id...]"
+msgid "\t-x insert-test ap_id [ap_id...]"
+msgid "\t-x remove-test ap_id [ap_id...]"
+msgid "\t-x set-condition-test=<condition>"
+msgid "\t-o enable-at-boot"
+msgid "\t-o disable-at-boot"
+msgid "unknown"
+msgid "ok"
+msgid "failing"
+msgid "failed"
+msgid "unusable"
+msgid "<%s>"
+msgid "\n"
+msgid "cfga_sid(%d,%d)=%d\n"
+msgid "errno=%d"
+msgid "%s\n"
+msgid "<%d>"
+msgid "%s"
+msgid "/tmp/cfga_simdata"
+msgid "sim_open"
+msgid "sim_stat"
+msgid "sim_size"
+msgid "sim_read"
+msgid "sim_open(%s)\n"
+msgid "/dev/openprom"
+msgid "sim_ioctl(%d)\n"
+msgid "sim_seek"
+msgid "sim_write"
+msgid "disabled-board-list"
+msgid "getprop(%s, %d)\n"
+msgid "prom_set_prop(%s)\n"
+msgid "%x"
+msgid "slot"
+msgid "ap_idx(%s)\n"
+msgid "ap_idx: s=%s, n=%d\n"
+msgid "ap_idx(%s)=%d\n"
+msgid "cpu %d: "
+msgid "%3d MHz "
+msgid "%0.1fM "
+msgid "single buffered ffb "
+msgid "double buffered ffb "
+msgid "no ffb installed "
+msgid "illegal ffb size "
+msgid "target: %2d "
+msgid "no disk "
+msgid "disabled at boot "
+msgid "non-detachable "
+msgid "100 MHz capable "