summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-01-17 18:30:09 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-01-17 18:30:09 +0000
commite916ce54b942cbe7e945c96363d09a8d0d8abd4a (patch)
tree6887c6985c71b478a654a386b38f9f799f920e29
parent8ea9d93b0d532cb29503c3854978ab85fd316951 (diff)
Recognize environmental change machine checks on ES40, and report what
happens instead of panicing; while there, start providing more details for ev6 processor machine checks as well. This allows power supplies to be unplugged and exchanged while the system is running, without causing the kernel to crash.
-rw-r--r--sys/arch/alpha/alpha/dec_6600.c279
-rw-r--r--sys/arch/alpha/include/alpha_cpu.h3
-rw-r--r--sys/arch/alpha/include/logout.h217
3 files changed, 493 insertions, 6 deletions
diff --git a/sys/arch/alpha/alpha/dec_6600.c b/sys/arch/alpha/alpha/dec_6600.c
index 458e0dc19ef..9a3a9fc9af6 100644
--- a/sys/arch/alpha/alpha/dec_6600.c
+++ b/sys/arch/alpha/alpha/dec_6600.c
@@ -1,7 +1,22 @@
-/* $OpenBSD: dec_6600.c,v 1.10 2008/07/16 20:03:20 miod Exp $ */
+/* $OpenBSD: dec_6600.c,v 1.11 2009/01/17 18:30:05 miod Exp $ */
/* $NetBSD: dec_6600.c,v 1.7 2000/06/20 03:48:54 matt Exp $ */
/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 1995, 1996, 1997 Carnegie-Mellon University.
* All rights reserved.
*
@@ -38,6 +53,7 @@
#include <machine/autoconf.h>
#include <machine/cpuconf.h>
#include <machine/bus.h>
+#include <machine/logout.h>
#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>
@@ -69,6 +85,15 @@ static int comcnrate __attribute__((unused)) = CONSPEED;
void dec_6600_init(void);
static void dec_6600_cons_init(void);
static void dec_6600_device_register(struct device *, void *);
+static void dec_6600_mcheck_handler(unsigned long, struct trapframe *,
+ unsigned long, unsigned long);
+#ifndef SMALL_KERNEL
+static void dec_6600_environmental_mcheck(unsigned long, struct trapframe *,
+ unsigned long, unsigned long);
+static void dec_6600_mcheck(unsigned long, struct trapframe *, unsigned long,
+ unsigned long);
+static void dec_6600_print_syndrome(int, unsigned long);
+#endif
void
dec_6600_init()
@@ -84,6 +109,7 @@ dec_6600_init()
platform.iobus = "tsc";
platform.cons_init = dec_6600_cons_init;
platform.device_register = dec_6600_device_register;
+ platform.mcheck_handler = dec_6600_mcheck_handler;
STQP(TS_C_DIM0) = 0UL;
STQP(TS_C_DIM1) = 0UL;
}
@@ -295,3 +321,254 @@ dec_6600_device_register(dev, aux)
found = 1;
}
}
+
+#ifndef SMALL_KERNEL
+static void
+dec_6600_environmental_mcheck(unsigned long mces, struct trapframe *framep,
+ unsigned long vector, unsigned long logout)
+{
+ mc_hdr_ev6 *hdr = (mc_hdr_ev6 *)logout;
+ mc_env_ev6 *env = (mc_env_ev6 *)(logout + hdr->la_system_offset);
+ int silent = 0;
+ int itemno;
+
+ /*
+ * Note that we do not check for an expected machine check,
+ * since software is not supposed to trigger an environmental
+ * machine check, and there might be an environmental change
+ * just before our expected machine check occurs.
+ */
+
+ /*
+ * Most environmental changes are handled at the RMC level,
+ * and we are either not notified (e.g. PCI door open) or
+ * drastic action is taken (e.g. the RMC will power down the
+ * system immediately if the CPU door is open).
+ *
+ * The only events we seem to be notified of are power supply
+ * failures.
+ */
+
+ /* display CPU failures */
+ for (itemno = 0; itemno < 4; itemno++) {
+ if ((env->cpuir & EV6_ENV_CPUIR_CPU_ENABLE(itemno)) != 0 &&
+ (env->cpuir & EV6_ENV_CPUIR_CPU_FAIL(itemno)) != 0) {
+ printf("CPU%d FAILURE\n", itemno);
+ silent = 1;
+ }
+ }
+
+ /* display PSU failures */
+ if (env->smir & EV6_ENV_SMIR_PSU_FAILURE) {
+ for (itemno = 0; itemno < 3; itemno++) {
+ if ((env->psir & EV6_ENV_PSIR_PSU_FAIL(itemno)) != 0) {
+ if ((env->psir &
+ EV6_ENV_PSIR_PSU_ENABLE(itemno)) != 0)
+ printf("PSU%d FAILURE\n", itemno);
+ else
+ printf("PSU%d DISABLED\n", itemno);
+ } else {
+ if ((env->psir &
+ EV6_ENV_PSIR_PSU_ENABLE(itemno)) != 0)
+ printf("PSU%d ENABLED\n", itemno);
+ }
+ }
+ silent = 1;
+ }
+
+ /* if we could not print a summary, display everything */
+ if (silent == 0) {
+ printf(" Processor Environmental Machine Check, "
+ "Code 0x%x\n", hdr->mcheck_code);
+
+ printf("Flags\t%016x\n", env->flags);
+ printf("DIR\t%016x\n", env->c_dir);
+ printf("SMIR\t%016x\n", env->smir);
+ printf("CPUIR\t%016x\n", env->cpuir);
+ printf("PSIR\t%016x\n", env->psir);
+ printf("LM78_ISR\t%016x\n", env->lm78_isr);
+ printf("Doors\t%016x\n", env->doors);
+ printf("Temp Warning\t%016x\n", env->temp_warning);
+ printf("Fan Control\t%016x\n", env->fan_control);
+ printf("Fatal Power Down\t%016x\n", env->fatal_power_down);
+ }
+
+ /*
+ * Apparently, these checks occur with MCES == 0, which
+ * is supposed to be an uncorrectable machine check.
+ *
+ * Until I know of a better way to tell recoverable and
+ * unrecoverable environmental checks apart, I'll use
+ * the fatal power down code to discriminate.
+ */
+ if (mces == 0 && env->fatal_power_down == 0)
+ return;
+ else
+ machine_check(mces, framep, vector, logout);
+}
+
+/*
+ * Expected syndrome values per faulting bit
+ */
+static const uint8_t ev6_syndrome[64 + 8] = {
+ 0xce, 0xcb, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc,
+ 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,
+ 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
+ 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xf1, 0xf4,
+ 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,
+ 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xb0, 0xb5,
+ 0x8f, 0x8a, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d,
+ 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+static void
+dec_6600_print_syndrome(int sno, unsigned long syndrome)
+{
+ unsigned int bitno;
+
+ syndrome &= 0xff;
+ printf("Syndrome bits %d\t%02x ", sno, syndrome);
+ for (bitno = 0; bitno < nitems(ev6_syndrome); bitno++)
+ if (syndrome == ev6_syndrome[bitno])
+ break;
+
+ if (bitno < 64)
+ printf("(%d)\n", bitno);
+ else if (bitno < nitems(ev6_syndrome))
+ printf("(CB%d)\n", bitno - 64);
+ else
+ printf("(unknown)\n");
+}
+
+static void
+dec_6600_mcheck(unsigned long mces, struct trapframe *framep,
+ unsigned long vector, unsigned long logout)
+{
+ mc_hdr_ev6 *hdr = (mc_hdr_ev6 *)logout;
+ struct mchkinfo *mcp;
+
+ /*
+ * If we expected a machine check, don't decode it.
+ */
+ mcp = &curcpu()->ci_mcinfo;
+ if (mcp->mc_expected) {
+ machine_check(mces, framep, vector, logout);
+ return;
+ }
+
+ printf(" Processor Machine Check (%lx), Code 0x%x\n",
+ vector, hdr->mcheck_code);
+
+ if (vector == ALPHA_SYS_MCHECK) {
+#ifdef notyet
+ mc_sys_ev6 *sys = (mc_sys_ev6 *)(logout + hdr->la_system_offset);
+#endif
+ /* XXX Decode and report P-Chip errors */
+ } else /* ALPHA_PROC_MCHECK */ {
+ mc_cpu_ev6 *cpu = (mc_cpu_ev6 *)(logout + hdr->la_cpu_offset);
+ size_t cpu_size = hdr->la_system_offset - hdr->la_cpu_offset;
+
+ printf("Dcache status\t0x%05x\n",
+ cpu->dc_stat & EV6_DC_STAT_MASK);
+ dec_6600_print_syndrome(0, cpu->c_syndrome_0);
+ dec_6600_print_syndrome(1, cpu->c_syndrome_1);
+ /* C_STAT */
+ printf("C_STAT\t");
+ switch (cpu->c_stat & EV6_C_STAT_MASK) {
+ case EV6_C_STAT_DBL_ISTREAM_BC_ECC_ERR:
+ printf("Bcache instruction stream double ECC error\n");
+ break;
+ case EV6_C_STAT_DBL_ISTREAM_MEM_ECC_ERR:
+ printf("Memory instruction stream double ECC error\n");
+ break;
+ case EV6_C_STAT_DBL_DSTREAM_BC_ECC_ERR:
+ printf("Bcache data stream double ECC error\n");
+ break;
+ case EV6_C_STAT_DBL_DSTREAM_MEM_ECC_ERR:
+ printf("Memory data stream double ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_ISTREAM_BC_ECC_ERR:
+ printf("Bcache instruction stream single ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_ISTREAM_MEM_ECC_ERR:
+ printf("Memory instruction stream single ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_BC_PROBE_HIT_ERR:
+ case EV6_C_STAT_SNGL_BC_PROBE_HIT_ERR2:
+ printf("Bcache probe hit error\n");
+ break;
+ case EV6_C_STAT_SNGL_DSTREAM_DC_ECC_ERR:
+ printf("Dcache data stream single ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_DSTREAM_BC_ECC_ERR:
+ printf("Bcache data stream single ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_DSTREAM_MEM_ECC_ERR:
+ printf("Memory data stream single ECC error\n");
+ break;
+ case EV6_C_STAT_SNGL_DC_DUPLICATE_TAG_PERR:
+ printf("Dcache duplicate tag error\n");
+ break;
+ case EV6_C_STAT_SNGL_BC_TAG_PERR:
+ printf("Bcache tag error\n");
+ break;
+ case EV6_C_STAT_NO_ERROR:
+ if (cpu->dc_stat & EV6_DC_STAT_STORE_DATA_ECC_ERROR) {
+ printf("Bcache/Dcache victim read ECC error\n");
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ printf("%02x\n", cpu->c_stat);
+ break;
+ }
+ /* C_ADDR */
+ printf("Error address\t");
+ if ((cpu->c_stat & EV6_C_STAT_MASK) ==
+ EV6_C_STAT_SNGL_DSTREAM_DC_ECC_ERR)
+ printf("0xXXXXXXXXXXX%05x\n", cpu->c_addr & 0xfffc0);
+ else
+ printf("0x%016x\n", cpu->c_addr & 0xffffffffffffffc0);
+
+ if (cpu_size > offsetof(mc_cpu_ev6, exc_addr)) {
+ printf("Exception address\t0x%016x%s\n",
+ cpu->exc_addr & 0xfffffffffffffffc,
+ cpu->exc_addr & 1 ? " in PAL mode" : "");
+ /* other fields are not really informative */
+ }
+ }
+
+ machine_check(mces, framep, vector, logout);
+}
+#endif
+
+static void
+dec_6600_mcheck_handler(unsigned long mces, struct trapframe *framep,
+ unsigned long vector, unsigned long param)
+{
+#ifdef SMALL_KERNEL
+ /*
+ * Even though we can not afford the machine check
+ * analysis code, we need to ignore environmental
+ * changes.
+ */
+ if (vector == ALPHA_ENV_MCHECK)
+ return;
+
+ machine_check(mces, framep, vector, param);
+#else
+ switch (vector) {
+ case ALPHA_ENV_MCHECK:
+ dec_6600_environmental_mcheck(mces, framep, vector, param);
+ break;
+ case ALPHA_PROC_MCHECK:
+ case ALPHA_SYS_MCHECK:
+ dec_6600_mcheck(mces, framep, vector, param);
+ break;
+ default:
+ machine_check(mces, framep, vector, param);
+ break;
+ }
+#endif
+}
diff --git a/sys/arch/alpha/include/alpha_cpu.h b/sys/arch/alpha/include/alpha_cpu.h
index bb3a6fa3f54..2d33fcf9636 100644
--- a/sys/arch/alpha/include/alpha_cpu.h
+++ b/sys/arch/alpha/include/alpha_cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: alpha_cpu.h,v 1.8 2002/11/26 01:35:23 art Exp $ */
+/* $OpenBSD: alpha_cpu.h,v 1.9 2009/01/17 18:30:08 miod Exp $ */
/* $NetBSD: alpha_cpu.h,v 1.43 2001/12/18 04:18:22 thorpej Exp $ */
/*
@@ -184,6 +184,7 @@ struct alpha_logout_area {
#define ALPHA_PROC_ERROR 0x630 /* Processor correctable error */
#define ALPHA_SYS_MCHECK 0x660 /* System machine check */
#define ALPHA_PROC_MCHECK 0x670 /* Processor machine check */
+#define ALPHA_ENV_MCHECK 0x680 /* Environmental machine check */
/*
* Virtual Memory Management definitions [OSF/1 PALcode Specific]
diff --git a/sys/arch/alpha/include/logout.h b/sys/arch/alpha/include/logout.h
index e3c0a17cca2..0baa6e42e85 100644
--- a/sys/arch/alpha/include/logout.h
+++ b/sys/arch/alpha/include/logout.h
@@ -1,7 +1,22 @@
-/* $OpenBSD: logout.h,v 1.1 2008/07/24 16:34:25 miod Exp $ */
+/* $OpenBSD: logout.h,v 1.2 2009/01/17 18:30:08 miod Exp $ */
/* $NetBSD: logout.h,v 1.6 2005/12/11 12:16:16 christos Exp $ */
/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 1998 by Matthew Jacob
* NASA AMES Research Center.
* All rights reserved.
@@ -260,7 +275,201 @@ typedef struct {
u_int64_t isr; /* Interrupt Status Reg. */
} mc_cc_ev5;
+/*
+ * Information gathered from: AlphaServer ES40 Service Guide
+ */
+
+/*
+ * EV6 Specific OSF/1 Pal Code Exception Logout Area Definitions
+ */
+
+/*
+ * EV6 Specific common logout frame header.
+ * *Almost* identical to the generic logout header listed in alpha_cpu.h.
+ */
+
+typedef struct {
+ unsigned int la_frame_size; /* frame size */
+ unsigned int la_flags; /* flags; see alpha_cpu.h */
+ unsigned int la_cpu_offset; /* offset to CPU area */
+ unsigned int la_system_offset; /* offset to system area */
+ unsigned int mcheck_code; /* machine check code */
+ unsigned int mcheck_rev; /* frame revision */
+#define MC_EV6_FRAME_REVISION 1
+} mc_hdr_ev6;
+
+/*
+ * EV6 Specific Machine Check processor area.
+ */
+
+typedef struct {
+ uint64_t i_stat;
+ uint64_t dc_stat;
+ uint64_t c_addr;
+ uint64_t c_syndrome_0;
+ uint64_t c_syndrome_1;
+ uint64_t c_stat;
+ uint64_t c_sts;
+ uint64_t mm_stat;
+ /* the following fields only exist for uncorrectable errors */
+ uint64_t exc_addr;
+ uint64_t ier_cm;
+ uint64_t isum;
+ uint64_t reserved0;
+ uint64_t pal_base;
+ uint64_t i_ctl;
+ uint64_t pctx;
+ uint64_t reserved1;
+ uint64_t reserved2;
+} mc_cpu_ev6;
+
+/* C_STAT bits */
+#define EV6_C_STAT_MASK 0x1f
+#define EV6_C_STAT_NO_ERROR 0x00
+#define EV6_C_STAT_SNGL_BC_TAG_PERR 0x01
+#define EV6_C_STAT_SNGL_DC_DUPLICATE_TAG_PERR 0x02
+#define EV6_C_STAT_SNGL_DSTREAM_MEM_ECC_ERR 0x03
+#define EV6_C_STAT_SNGL_DSTREAM_BC_ECC_ERR 0x04
+#define EV6_C_STAT_SNGL_DSTREAM_DC_ECC_ERR 0x05
+#define EV6_C_STAT_SNGL_BC_PROBE_HIT_ERR 0x06
+#define EV6_C_STAT_SNGL_BC_PROBE_HIT_ERR2 0x07
+#define EV6_C_STAT_SNGL_ISTREAM_MEM_ECC_ERR 0x0b
+#define EV6_C_STAT_SNGL_ISTREAM_BC_ECC_ERR 0x0c
+#define EV6_C_STAT_DBL_DSTREAM_MEM_ECC_ERR 0x13
+#define EV6_C_STAT_DBL_DSTREAM_BC_ECC_ERR 0x14
+#define EV6_C_STAT_DBL_ISTREAM_MEM_ECC_ERR 0x1b
+#define EV6_C_STAT_DBL_ISTREAM_BC_ECC_ERR 0x1c
+
+/* C_STS bits */
+#define EV6_C_STS_MASK 0x0f
+#define EV6_C_STS_PARITY 0x08
+#define EV6_C_STS_VALID 0x04
+#define EV6_C_STS_DIRTY 0x02
+#define EV6_C_STS_SHARED 0x01
+
+/* DC_STAT */
+#define EV6_DC_STAT_MASK 0x1f
+#define EV6_DC_STAT_PIPELINE_0_ERROR 0x01
+#define EV6_DC_STAT_PIPELINE_1_ERROR 0x02
+#define EV6_DC_STAT_STORE_DATA_ECC_ERROR 0x04
+#define EV6_DC_STAT_LOAD_DATA_ECC_ERROR 0x08
+#define EV6_DC_STAT_STORE_DATA_ECC_ERROR_REPEATED 0x10
+
+/* MM_STAT */
+#define EV6_MM_STAT_MASK 0x03ff
+#define EV6_MM_STAT_WRITE 0x0001
+#define EV6_MM_STAT_ACCESS_VIOLATION 0x0002
+#define EV6_MM_STAT_FOR_SET 0x0004
+#define EV6_MM_STAT_FOW_SET 0x0008
+#define EV6_MM_STAT_OPCODE_MASK 0x02f0
+#define EV6_MM_STAT_DCACHE_CORRECTABLE_ERROR 0x0300
+
+/*
+ * EV6 Specific Machine Check system area.
+ */
+
+typedef struct {
+ uint64_t flags;
+ uint64_t c_dir;
+ uint64_t c_misc;
+ uint64_t p0_perror;
+ uint64_t p1_perror;
+} mc_sys_ev6;
+
+/*
+ * EV6 Environmental Error logout frame.
+ */
+
+typedef struct {
+ uint64_t flags;
+ uint64_t c_dir;
+ uint64_t smir;
+ uint64_t cpuir;
+ uint64_t psir;
+ uint64_t lm78_isr;
+ uint64_t doors;
+ uint64_t temp_warning;
+ uint64_t fan_control;
+ uint64_t fatal_power_down;
+ uint64_t reserved;
+} mc_env_ev6;
+
+/* SMIR */
+#define EV6_ENV_SMIR_RESET 0x80
+#define EV6_ENV_SMIR_PCI1_RESET 0x40
+#define EV6_ENV_SMIR_PCI0_RESET 0x20
+#define EV6_ENV_SMIR_OVERTEMP 0x10
+#define EV6_ENV_SMIR_DC_FAILURE 0x04
+#define EV6_ENV_SMIR_RMC_HALT 0x02
+#define EV6_ENV_SMIR_PSU_FAILURE 0x01
+
+/* CPUIR */
+#define EV6_ENV_CPUIR_CPU_FAIL(cpuno) ((cpuno) << 4)
+#define EV6_ENV_CPUIR_CPU_ENABLE(cpuno) ((cpuno) << 0)
+
+/* PSIR */
+#define EV6_ENV_PSIR_PSU_FAIL(psuno) ((psuno) << 4)
+#define EV6_ENV_PSIR_PSU_ENABLE(psuno) ((psuno) << 0)
+
+/* LM78_ISR */
+#define EV6_ENV_LM78_PSU_AC_HIGH_LIMIT 0x0000800000000000
+#define EV6_ENV_LM78_PSU_AC_LOW_LIMIT 0x0000400000000000
+#define EV6_ENV_LM78_PSU_OVERTEMP 0x0000200000000000
+#define EV6_ENV_LM78_PSU_12V_OVERAMP 0x0000100000000000
+#define EV6_ENV_LM78_PSU_5V_OVERAMP 0x0000080000000000
+#define EV6_ENV_LM78_PSU_3_3V_OVERAMP 0x0000040000000000
+#define EV6_ENV_LM78_PSU_NUMBER_MASK 0x0000030000000000
+#define EV6_ENV_LM78_PSU_NUMBER_SHIFT 40
+#define EV6_ENV_LM78_FAN6_FAILURE 0x0000008000000000
+#define EV6_ENV_LM78_FAN3_FAILURE 0x0000004000000000
+#define EV6_ENV_LM78_ZONE2_OVERTEMP 0x0000001000000000
+#define EV6_ENV_LM78_CPU3_VIO_OOT 0x0000000800000000
+#define EV6_ENV_LM78_CPU3_VCORE_OOT 0x0000000400000000
+#define EV6_ENV_LM78_CPU2_VIO_OOT 0x0000000200000000
+#define EV6_ENV_LM78_CPU2_VCORE_OOT 0x0000000100000000
+#define EV6_ENV_LM78_FAN5_FAILURE 0x0000000000800000
+#define EV6_ENV_LM78_FAN4_FAILURE 0x0000000000400000
+#define EV6_ENV_LM78_ZONE1_OVERTEMP 0x0000000000100000
+#define EV6_ENV_LM78_CPU1_VIO_OOT 0x0000000000080000
+#define EV6_ENV_LM78_CPU1_VCORE_OOT 0x0000000000040000
+#define EV6_ENV_LM78_CPU0_VIO_OOT 0x0000000000020000
+#define EV6_ENV_LM78_CPU0_VCORE_OOT 0x0000000000010000
+#define EV6_ENV_LM78_PSU_MINUS12V_OOT 0x0000000000000800
+#define EV6_ENV_LM78_CTERM_OOT 0x0000000000000100
+#define EV6_ENV_LM78_FAN2_FAILURE 0x0000000000000080
+#define EV6_ENV_LM78_FAN1_FAILURE 0x0000000000000040
+#define EV6_ENV_LM78_CPU_OVERTEMP 0x0000000000000020
+#define EV6_ENV_LM78_ZONA0_OVERTEMP 0x0000000000000010
+#define EV6_ENV_LM78_VTERM_OOT 0x0000000000000008
+#define EV6_ENV_LM78_PSU_12V_OOT 0x0000000000000004
+#define EV6_ENV_LM78_PSU_5V_OOT 0x0000000000000002
+#define EV6_ENV_LM78_PSU_3_3V_OOT 0x0000000000000001
+
+/* Doors */
+#define EV6_ENV_DOORS_PCI_CLOSED 0x80
+#define EV6_ENV_DOORS_FAN_CLOSED 0x40
+#define EV6_ENV_DOORS_CPU_CLOSED 0x20
+#define EV6_ENV_DOORS_PCI_OPEN 0x08
+#define EV6_ENV_DOORS_FAN_OPEN 0x04
+#define EV6_ENV_DOORS_CPU_OPEN 0x02
+
+/* System Temperature Warning (sticky?) */
+#define EV6_ENV_STW_ZONE2 0x40
+#define EV6_ENV_STW_ZONE1 0x20
+#define EV6_ENV_STW_ZONE0 0x10
+#define EV6_ENV_STW_CPU3 0x08
+#define EV6_ENV_STW_CPU2 0x04
+#define EV6_ENV_STW_CPU1 0x02
+#define EV6_ENV_STW_CPU0 0x01
-#ifdef _KERNEL
-extern void ev5_logout_print(mc_hdr_ev5 *, mc_uc_ev5 *);
-#endif
+/* System Fan Control Fault */
+#define EV6_ENV_SFCF_FAN1234_LOW_SPEED 0x0800
+#define EV6_ENV_SFCF_FAN1234_HIGH_SPEED 0x0400
+#define EV6_ENV_SFCF_FAN56_LOW_SPEED 0x0200
+#define EV6_ENV_SFCF_FAN56_HIGH_SPEED 0x0100
+#define EV6_ENV_SFCF_FAN6_NONRESPONSIVE 0x0020
+#define EV6_ENV_SFCF_FAN5_NONRESPONSIVE 0x0010
+#define EV6_ENV_SFCF_FAN4_NONRESPONSIVE 0x0008
+#define EV6_ENV_SFCF_FAN3_NONRESPONSIVE 0x0004
+#define EV6_ENV_SFCF_FAN2_NONRESPONSIVE 0x0002
+#define EV6_ENV_SFCF_FAN1_NONRESPONSIVE 0x0001