/*
* 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
* 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 1990-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ddi_impldefs.h>
#include <sys/sysiosbus.h>
#include <sys/sysioerr.h>
#include <sys/machsystm.h>
#include <sys/sysmacros.h>
#include <sys/cpu_module.h>
/*
* not to shutdown the machine if the temperature reaches
* the Thermal Warning limit.
*/
int oven_test = 0;
/*
* To indicate if the prom has the property of "thermal-interrupt".
*/
static int thermal_interrupt_enabled = 0;
#ifdef _STARFIRE
#include <sys/starfire.h>
int
void
#endif /* _STARFIRE */
/*
* adb debug_sysio_errs to 1 if you don't want your system to panic on
* sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
* to check for sysio errors at all.
*/
/*
* bto_cnt = number of bus errors and timeouts allowed within bto_secs
* it's a problem!
*/
static uint_t
static uint_t
static uint_t
static void
static void
static void
static void
static int
static void
static uint_t
static uint_t
static uint_t
static uint_t
int
{
if (sysio_err_flag == 0) {
return (DDI_SUCCESS);
}
/*
* Simply add each registers offset to the already mapped in address
* that was retrieved from the device node's "address" property,
* and passed as an argument to this function.
*
* Define a macro for the pointer arithmetic ...
*/
/*
* create the interrupt-priorities property if it doesn't
* already exist to provide a hint as to the PIL level for
* our interrupt.
*/
{
int len;
DDI_PROP_DONTPASS, "interrupt-priorities",
&len) != DDI_PROP_SUCCESS) {
/* Create the interrupt-priorities property. */
}
}
/*
* If the thermal-interrupt property is in place,
* then register the thermal warning interrupt handler and
* program its mapping register
*/
if (thermal_interrupt_enabled == 1) {
}
(void) sysio_init_err(softsp);
return (DDI_SUCCESS);
}
int
{
(void) sysio_init_err(softsp);
return (DDI_SUCCESS);
}
int
{
/* remove the interrupts from the interrupt list */
(void) sysio_dis_err(softsp);
if (thermal_interrupt_enabled == 1) {
}
return (DDI_SUCCESS);
}
static uint_t
{
acpu_id = intr_dist_cpuid();
/*
* Program the mondo vector accordingly. This MUST be the
* last thing we do. Once we program the mondo, the device
* may begin to interrupt. Store it in the hardware reg.
*/
#ifdef _STARFIRE
#endif /* _STARFIRE */
#ifdef _STARFIRE
#endif /* _STARFIRE */
#ifdef _STARFIRE
#endif /* _STARFIRE */
if (thermal_interrupt_enabled == 1) {
}
/* Flush store buffers */
/*
* XXX - This may already be set by the OBP.
*/
softsp->bto_timestamp = 0;
return (0);
}
static uint_t
{
*softsp->sysio_ecc_reg = 0;
/* Flush store buffers */
#ifdef lint
#endif
/* Unmap mapping registers */
*mondo_vec_reg = 0;
#ifdef _STARFIRE
/* do cleanup for starfire interrupt target translation */
#endif /* _STARFIRE */
*clear_vec_reg = 0;
*mondo_vec_reg = 0;
#ifdef _STARFIRE
/* Do cleanup for starfire interrupt target translation */
#endif /* _STARFIRE */
*clear_vec_reg = 0;
*mondo_vec_reg = 0;
#ifdef _STARFIRE
/* Do cleanup for starfire interrupt target translation */
#endif /* _STARFIRE */
*clear_vec_reg = 0;
/* Flush store buffers */
return (BF_NONE);
}
/*
* Gather information about the error into an async_flt structure, and then
* enqueue the error for reporting and processing and panic.
*/
static uint_t
{
/*
* Disable all further sbus errors, for this sbus instance, for
* what is guaranteed to be a fatal error. And grab any other cpus.
*/
/*
*/
*clear_reg = 0;
/*
* The AFSR DW_OFFSET field contains the offset of the doubleword with
* the ECC error relative to the 64-byte aligned PA. We multiply by 8
* to convert to a byte offset, and then add this to flt_addr.
*/
/*
* If the UE is in memory and fatal, save the fault info so the
* panic code will know to check for copyback errors.
*/
panic_aflt = ecc;
/*
* We must also check for other bus UE errors, and panic if
* any fatal ones are detected at this point.
*/
return (DDI_INTR_CLAIMED);
}
/*
* callback logging function from the common error handling code
*/
static void
{
if (t_afsr & SB_UE_AFSR_P_PIO) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_UE_AFSR_P_DRD) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
}
if (t_afsr & SB_UE_AFSR_P_DWR) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
}
/*
* We should never hit the secondary error panics.
*/
if (t_afsr & SB_UE_AFSR_S_PIO) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_UE_AFSR_S_DRD) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
}
if (t_afsr & SB_UE_AFSR_S_DWR) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
}
if ((debug_sysio_errs) || (aft_verbose)) {
}
}
/*
* gather the information about the error, plus a pointer to
* the callback logging function, and call the generic ce_error handler.
*/
static uint_t
{
*clear_reg = 0;
/*
* The AFSR DW_OFFSET field contains the offset of the doubleword with
* the ECC error relative to the 64-byte aligned PA. We multiply by 8
* to convert to a byte offset, and then add this to flt_addr.
*/
return (DDI_INTR_CLAIMED);
}
/*
* callback logging function from the common error handling code
*/
static void
{
"UPA MID 0x%x\n";
if ((!ce_verbose_memory) && (!debug_sysio_errs))
return;
if (t_afsr & SB_CE_AFSR_P_PIO) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
fmtstr++;
}
if (t_afsr & SB_CE_AFSR_P_DRD) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
"Id %d\n";
fmtstr++;
}
if (t_afsr & SB_CE_AFSR_P_DWR) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d\n";
fmtstr++;
}
if (t_afsr & SB_CE_AFSR_S_PIO) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
fmtstr++;
id);
}
if (t_afsr & SB_CE_AFSR_S_DRD) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
"Id %d\n";
fmtstr++;
}
if (t_afsr & SB_CE_AFSR_S_DWR) {
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
"Id %d\n";
fmtstr++;
}
syndrome_str++;
}
static uint_t
{
int cleared = 0;
cleared = 1;
}
if (debug_sysio_errs) {
if (!cleared)
"AFAR 0x%08x.%08x Id %d\n",
debug_enter("sbus_err_intr");
} else {
}
if (!cleared) {
}
return (DDI_INTR_CLAIMED);
}
static void
{
*clear_reg = 0;
}
static void
{
if (t_afsr & SB_AFSR_P_LE) {
if (!cleared)
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_AFSR_P_TO) {
return;
}
if (sbus_check_bto(softsp)) {
if (!cleared)
}
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_AFSR_P_BERR) {
return;
}
if (sbus_check_bto(softsp)) {
if (!cleared)
}
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n",
}
if (t_afsr & SB_AFSR_S_LE) {
if (!cleared)
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_AFSR_S_TO) {
if (sbus_check_bto(softsp)) {
if (!cleared)
}
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
if (t_afsr & SB_AFSR_S_BERR) {
if (sbus_check_bto(softsp)) {
if (!cleared)
}
"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
}
}
static int
{
/*
* Reset error counter as this bus error has occurred
* after more than bto_secs duration.
*/
}
return (1);
return (0);
}
static uint_t
{
if (debug_sysio_errs) {
}
return (BF_FATAL);
}
return (BF_NONE);
}
/*ARGSUSED*/
static void
{
/*
* Print out SBus error information.
*/
if (t_sb_csr & SB_CSR_DPERR_S14) {
"SBus%d Slot 14 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_DPERR_S13) {
"SBus%d Slot 13 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_DPERR_S3) {
"SBus%d Slot 3 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_DPERR_S2) {
"SBus%d Slot 2 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_DPERR_S1) {
"SBus%d Slot 1 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_DPERR_S0) {
"SBus%d Slot 0 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S15) {
"SBus%d Slot 15 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S14) {
"SBus%d Slot 14 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S13) {
"SBus%d Slot 13 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S3) {
"SBus%d Slot 3 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S2) {
"SBus%d Slot 2 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S1) {
"SBus%d Slot 1 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
if (t_sb_csr & SB_CSR_PPERR_S0) {
"SBus%d Slot 0 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
}
}
/*
* Sysio Thermal Warning interrupt handler
*/
static uint_t
{
const char thermal_warn_msg[] =
"Severe over-temperature condition detected!";
/*
* Take off the Thermal Warning interrupt and
* remove its interrupt handler.
*/
*clear_reg = 0;
if (oven_test) {
return (DDI_INTR_CLAIMED);
}
do_shutdown();
/*
* just in case do_shutdown() fails
*/
return (DDI_INTR_CLAIMED);
}