xref: /illumos-gate/usr/src/uts/sun4u/io/sysioerr.c (revision 2a1fd0ff)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 1990-2002 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*2a1fd0ffSPeter Tribble /*
27*2a1fd0ffSPeter Tribble  * Copyright 2019 Peter Tribble.
28*2a1fd0ffSPeter Tribble  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/conf.h>
327c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
367c478bd9Sstevel@tonic-gate #include <sys/async.h>
377c478bd9Sstevel@tonic-gate #include <sys/sysiosbus.h>
387c478bd9Sstevel@tonic-gate #include <sys/sysioerr.h>
397c478bd9Sstevel@tonic-gate #include <sys/x_call.h>
407c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
427c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
437c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * Set the following variable in /etc/system to tell the kernel
477c478bd9Sstevel@tonic-gate  * not to shutdown the machine if the temperature reaches
487c478bd9Sstevel@tonic-gate  * the Thermal Warning limit.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate int oven_test = 0;
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * To indicate if the prom has the property of "thermal-interrupt".
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate static int thermal_interrupt_enabled = 0;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * adb debug_sysio_errs to 1 if you don't want your system to panic on
597c478bd9Sstevel@tonic-gate  * sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
607c478bd9Sstevel@tonic-gate  * to check for sysio errors at all.
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate int sysio_err_flag = 1;
637c478bd9Sstevel@tonic-gate uint_t debug_sysio_errs = 0;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * bto_cnt = number of bus errors and timeouts allowed within bto_secs
677c478bd9Sstevel@tonic-gate  * use /etc/system to change the bto_cnt to a very large number if
687c478bd9Sstevel@tonic-gate  * it's a problem!
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate int bto_secs = 10;
717c478bd9Sstevel@tonic-gate int bto_cnt = 10;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static uint_t
747c478bd9Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static uint_t
777c478bd9Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static uint_t
807c478bd9Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate static void
837c478bd9Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static void
867c478bd9Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static void
897c478bd9Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate static void
927c478bd9Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
937c478bd9Sstevel@tonic-gate     ushort_t id, ushort_t inst, int cleared,
947c478bd9Sstevel@tonic-gate     on_trap_data_t *ontrap_data);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static int
977c478bd9Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp);
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static void
1007c478bd9Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static uint_t
1037c478bd9Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp);
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static uint_t
1067c478bd9Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate static uint_t
1097c478bd9Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp);
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate static uint_t
1127c478bd9Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp);
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate static int sbus_pil[] = {SBUS_UE_PIL, SBUS_CE_PIL, SBUS_ERR_PIL, SBUS_PF_PIL,
1157c478bd9Sstevel@tonic-gate 	SBUS_THERMAL_PIL, SBUS_PM_PIL};
1167c478bd9Sstevel@tonic-gate int
sysio_err_init(struct sbus_soft_state * softsp,caddr_t address)1177c478bd9Sstevel@tonic-gate sysio_err_init(struct sbus_soft_state *softsp, caddr_t address)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	if (sysio_err_flag == 0) {
1207c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Warning: sysio errors not initialized\n");
1217c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/*
1257c478bd9Sstevel@tonic-gate 	 * Get the address of the already mapped-in sysio/sbus error registers.
1267c478bd9Sstevel@tonic-gate 	 * Simply add each registers offset to the already mapped in address
1277c478bd9Sstevel@tonic-gate 	 * that was retrieved from the device node's "address" property,
1287c478bd9Sstevel@tonic-gate 	 * and passed as an argument to this function.
1297c478bd9Sstevel@tonic-gate 	 *
1307c478bd9Sstevel@tonic-gate 	 * Define a macro for the pointer arithmetic ...
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate #define	REG_ADDR(b, o)	(uint64_t *)((caddr_t)(b) + (o))
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	softsp->sysio_ecc_reg = REG_ADDR(address, OFF_SYSIO_ECC_REGS);
1367c478bd9Sstevel@tonic-gate 	softsp->sysio_ue_reg = REG_ADDR(address, OFF_SYSIO_UE_REGS);
1377c478bd9Sstevel@tonic-gate 	softsp->sysio_ce_reg = REG_ADDR(address, OFF_SYSIO_CE_REGS);
1387c478bd9Sstevel@tonic-gate 	softsp->sbus_err_reg = REG_ADDR(address, OFF_SBUS_ERR_REGS);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate #undef	REG_ADDR
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	/*
1437c478bd9Sstevel@tonic-gate 	 * create the interrupt-priorities property if it doesn't
1447c478bd9Sstevel@tonic-gate 	 * already exist to provide a hint as to the PIL level for
1457c478bd9Sstevel@tonic-gate 	 * our interrupt.
1467c478bd9Sstevel@tonic-gate 	 */
1477c478bd9Sstevel@tonic-gate 	{
1487c478bd9Sstevel@tonic-gate 		int len;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
1517c478bd9Sstevel@tonic-gate 		    DDI_PROP_DONTPASS, "interrupt-priorities",
1527c478bd9Sstevel@tonic-gate 		    &len) != DDI_PROP_SUCCESS) {
1537c478bd9Sstevel@tonic-gate 				/* Create the interrupt-priorities property. */
1547c478bd9Sstevel@tonic-gate 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
1557c478bd9Sstevel@tonic-gate 			    softsp->dip, "interrupt-priorities",
1567c478bd9Sstevel@tonic-gate 			    (int *)sbus_pil, sizeof (sbus_pil) / sizeof (int));
1577c478bd9Sstevel@tonic-gate 		}
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 0, NULL, NULL,
1617c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sysio_ue_intr, (caddr_t)softsp);
1627c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 1, NULL, NULL,
1637c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sysio_ce_intr, (caddr_t)softsp);
1647c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 2, NULL, NULL,
1657c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sbus_err_intr, (caddr_t)softsp);
1667c478bd9Sstevel@tonic-gate 	/*
1677c478bd9Sstevel@tonic-gate 	 * If the thermal-interrupt property is in place,
1687c478bd9Sstevel@tonic-gate 	 * then register the thermal warning interrupt handler and
1697c478bd9Sstevel@tonic-gate 	 * program its mapping register
1707c478bd9Sstevel@tonic-gate 	 */
1717c478bd9Sstevel@tonic-gate 	thermal_interrupt_enabled = ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
1727c478bd9Sstevel@tonic-gate 		DDI_PROP_DONTPASS, "thermal-interrupt", -1);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
1757c478bd9Sstevel@tonic-gate 		(void) ddi_add_intr(softsp->dip, 4, NULL, NULL,
1767c478bd9Sstevel@tonic-gate 		    (uint_t (*)())sysio_thermal_warn_intr, (caddr_t)softsp);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	bus_func_register(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
1807c478bd9Sstevel@tonic-gate 	bus_func_register(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	(void) sysio_init_err(softsp);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate int
sysio_err_resume_init(struct sbus_soft_state * softsp)1887c478bd9Sstevel@tonic-gate sysio_err_resume_init(struct sbus_soft_state *softsp)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	(void) sysio_init_err(softsp);
1917c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate int
sysio_err_uninit(struct sbus_soft_state * softsp)1957c478bd9Sstevel@tonic-gate sysio_err_uninit(struct sbus_soft_state *softsp)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	/* remove the interrupts from the interrupt list */
1987c478bd9Sstevel@tonic-gate 	(void) sysio_dis_err(softsp);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 0, NULL);
2017c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 1, NULL);
2027c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 2, NULL);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
2057c478bd9Sstevel@tonic-gate 		ddi_remove_intr(softsp->dip, 4, NULL);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	bus_func_unregister(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
2097c478bd9Sstevel@tonic-gate 	bus_func_unregister(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate static uint_t
sysio_init_err(struct sbus_soft_state * softsp)2157c478bd9Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp_mondo_vec, tmpreg;
2187c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg;
2197c478bd9Sstevel@tonic-gate 	uint_t cpu_id, acpu_id;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	acpu_id = intr_dist_cpuid();
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * Program the mondo vector accordingly.  This MUST be the
2247c478bd9Sstevel@tonic-gate 	 * last thing we do.  Once we program the mondo, the device
2257c478bd9Sstevel@tonic-gate 	 * may begin to interrupt. Store it in the hardware reg.
2267c478bd9Sstevel@tonic-gate 	 */
2277c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + UE_ECC_MAPREG);
2287c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
2297c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
2307c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + CE_ECC_MAPREG);
2337c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
2347c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
2357c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	mondo_vec_reg =
2387c478bd9Sstevel@tonic-gate 	    (uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
2397c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
2427c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
2457c478bd9Sstevel@tonic-gate 		mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
2467c478bd9Sstevel@tonic-gate 		cpu_id = acpu_id;
2477c478bd9Sstevel@tonic-gate 		tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) |
2487c478bd9Sstevel@tonic-gate 			INTERRUPT_VALID;
2497c478bd9Sstevel@tonic-gate 		*mondo_vec_reg = tmp_mondo_vec;
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
2537c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/*
2567c478bd9Sstevel@tonic-gate 	 * XXX - This may already be set by the OBP.
2577c478bd9Sstevel@tonic-gate 	 */
2587c478bd9Sstevel@tonic-gate 	tmpreg = SYSIO_APCKEN;
2597c478bd9Sstevel@tonic-gate 	*softsp->sysio_ctrl_reg |= tmpreg;
2607c478bd9Sstevel@tonic-gate 	tmpreg = (SECR_ECC_EN | SECR_UE_INTEN | SECR_CE_INTEN);
2617c478bd9Sstevel@tonic-gate 	*softsp->sysio_ecc_reg = tmpreg;
2627c478bd9Sstevel@tonic-gate 	tmpreg = SB_CSR_ERRINT_EN;
2637c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg |= tmpreg;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	/* Initialize timeout/bus error counter */
2667c478bd9Sstevel@tonic-gate 	softsp->bto_timestamp = 0;
2677c478bd9Sstevel@tonic-gate 	softsp->bto_ctr = 0;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	return (0);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate static uint_t
sysio_dis_err(struct sbus_soft_state * softsp)2737c478bd9Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	volatile uint64_t tmpreg;
2767c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg, *clear_vec_reg;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	*softsp->sysio_ctrl_reg &= ~SYSIO_APCKEN;
2797c478bd9Sstevel@tonic-gate 	*softsp->sysio_ecc_reg = 0;
2807c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg &= ~SB_CSR_ERRINT_EN;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
2837c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
2847c478bd9Sstevel@tonic-gate #ifdef lint
2857c478bd9Sstevel@tonic-gate 	tmpreg = tmpreg;
2867c478bd9Sstevel@tonic-gate #endif
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	/* Unmap mapping registers */
2897c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + UE_ECC_MAPREG);
2907c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG);
2977c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
3047c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
3117c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	return (BF_NONE);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate  * Gather information about the error into an async_flt structure, and then
3187c478bd9Sstevel@tonic-gate  * enqueue the error for reporting and processing and panic.
3197c478bd9Sstevel@tonic-gate  */
3207c478bd9Sstevel@tonic-gate static uint_t
sysio_ue_intr(struct sbus_soft_state * softsp)3217c478bd9Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
3247c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
3257c478bd9Sstevel@tonic-gate 	volatile uint64_t *ue_reg, *afar_reg, *clear_reg;
3267c478bd9Sstevel@tonic-gate 	struct async_flt ecc;
3277c478bd9Sstevel@tonic-gate 	uint64_t offset;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/*
3307c478bd9Sstevel@tonic-gate 	 * Disable all further sbus errors, for this sbus instance, for
3317c478bd9Sstevel@tonic-gate 	 * what is guaranteed to be a fatal error. And grab any other cpus.
3327c478bd9Sstevel@tonic-gate 	 */
3337c478bd9Sstevel@tonic-gate 	(void) sysio_dis_err(softsp);		/* disabled sysio errors */
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * Then read and clear the afsr/afar and clear interrupt regs.
3377c478bd9Sstevel@tonic-gate 	 */
3387c478bd9Sstevel@tonic-gate 	ue_reg = (uint64_t *)softsp->sysio_ue_reg;
3397c478bd9Sstevel@tonic-gate 	t_afsr = *ue_reg;
3407c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)ue_reg + 1;
3417c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
3427c478bd9Sstevel@tonic-gate 	*ue_reg = t_afsr;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
3457c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/*
3487c478bd9Sstevel@tonic-gate 	 * The AFSR DW_OFFSET field contains the offset of the doubleword with
3497c478bd9Sstevel@tonic-gate 	 * the ECC error relative to the 64-byte aligned PA.  We multiply by 8
3507c478bd9Sstevel@tonic-gate 	 * to convert to a byte offset, and then add this to flt_addr.
3517c478bd9Sstevel@tonic-gate 	 */
3527c478bd9Sstevel@tonic-gate 	offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	bzero(&ecc, sizeof (ecc));
3557c478bd9Sstevel@tonic-gate 	ecc.flt_id = gethrtime();
3567c478bd9Sstevel@tonic-gate 	ecc.flt_stat = t_afsr;
3577c478bd9Sstevel@tonic-gate 	ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
3587c478bd9Sstevel@tonic-gate 	ecc.flt_func = sysio_log_ue_err;
3597c478bd9Sstevel@tonic-gate 	ecc.flt_bus_id = softsp->upa_id;
3607c478bd9Sstevel@tonic-gate 	ecc.flt_inst = ddi_get_instance(softsp->dip);
3617c478bd9Sstevel@tonic-gate 	ecc.flt_status = ECC_IOBUS;
3627c478bd9Sstevel@tonic-gate 	ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
3637c478bd9Sstevel@tonic-gate 	ecc.flt_class = BUS_FAULT;
3647c478bd9Sstevel@tonic-gate 	ecc.flt_panic = (debug_sysio_errs == 0);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	errorq_dispatch(ue_queue, &ecc, sizeof (ecc), ecc.flt_panic);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	/*
3697c478bd9Sstevel@tonic-gate 	 * If the UE is in memory and fatal, save the fault info so the
3707c478bd9Sstevel@tonic-gate 	 * panic code will know to check for copyback errors.
3717c478bd9Sstevel@tonic-gate 	 */
3727c478bd9Sstevel@tonic-gate 	if (ecc.flt_panic && ecc.flt_in_memory)
3737c478bd9Sstevel@tonic-gate 		panic_aflt = ecc;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	/*
3767c478bd9Sstevel@tonic-gate 	 * We must also check for other bus UE errors, and panic if
3777c478bd9Sstevel@tonic-gate 	 * any fatal ones are detected at this point.
3787c478bd9Sstevel@tonic-gate 	 */
3797c478bd9Sstevel@tonic-gate 	if (bus_func_invoke(BF_TYPE_UE) == BF_FATAL)
3807c478bd9Sstevel@tonic-gate 		ecc.flt_panic = 1;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	if (ecc.flt_panic)
3837c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "Fatal Sbus%d UE Error", ecc.flt_inst);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate  * callback logging function from the common error handling code
3907c478bd9Sstevel@tonic-gate  */
3917c478bd9Sstevel@tonic-gate static void
sysio_log_ue_err(struct async_flt * ecc,char * unum)3927c478bd9Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate 	uint64_t t_afsr = ecc->flt_stat;
3957c478bd9Sstevel@tonic-gate 	uint64_t t_afar = ecc->flt_addr;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	ushort_t id = ecc->flt_bus_id;
3987c478bd9Sstevel@tonic-gate 	ushort_t inst = ecc->flt_inst;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_PIO) {
4017c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error from PIO: "
4027c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
4037c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4047c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_DRD) {
4077c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error DMA read: "
4087c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
4097c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4107c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_DWR) {
4137c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error DVMA write: "
4147c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
4157c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4167c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 	/*
4197c478bd9Sstevel@tonic-gate 	 * We should never hit the secondary error panics.
4207c478bd9Sstevel@tonic-gate 	 */
4217c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_PIO) {
4227c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary Error from PIO: "
4237c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
4247c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4257c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_DRD) {
4287c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary Error DMA read: "
4297c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
4307c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4317c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_DWR) {
4347c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary  Error DMA write: "
4357c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
4367c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
4377c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if ((debug_sysio_errs) || (aft_verbose)) {
4417c478bd9Sstevel@tonic-gate 		(void) read_ecc_data(ecc, 1, 0);
4427c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "\tOffset 0x%x, Size %d, UPA MID 0x%x\n",
4437c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT),
4447c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_SIZE) >> SB_UE_SIZE_SHIFT),
4457c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_MID) >> SB_UE_MID_SHIFT));
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate  * gather the information about the error, plus a pointer to
4517c478bd9Sstevel@tonic-gate  * the callback logging function, and call the generic ce_error handler.
4527c478bd9Sstevel@tonic-gate  */
4537c478bd9Sstevel@tonic-gate static uint_t
sysio_ce_intr(struct sbus_soft_state * softsp)4547c478bd9Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
4577c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
4587c478bd9Sstevel@tonic-gate 	volatile uint64_t *afar_reg, *clear_reg, *ce_reg;
4597c478bd9Sstevel@tonic-gate 	struct async_flt ecc;
4607c478bd9Sstevel@tonic-gate 	uint64_t offset;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	ce_reg = (uint64_t *)softsp->sysio_ce_reg;
4637c478bd9Sstevel@tonic-gate 	t_afsr = *ce_reg;
4647c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)ce_reg + 1;
4657c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
4667c478bd9Sstevel@tonic-gate 	*ce_reg = t_afsr;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
4697c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	/*
4727c478bd9Sstevel@tonic-gate 	 * The AFSR DW_OFFSET field contains the offset of the doubleword with
4737c478bd9Sstevel@tonic-gate 	 * the ECC error relative to the 64-byte aligned PA.  We multiply by 8
4747c478bd9Sstevel@tonic-gate 	 * to convert to a byte offset, and then add this to flt_addr.
4757c478bd9Sstevel@tonic-gate 	 */
4767c478bd9Sstevel@tonic-gate 	offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	bzero(&ecc, sizeof (ecc));
4797c478bd9Sstevel@tonic-gate 	ecc.flt_id = gethrtime();
4807c478bd9Sstevel@tonic-gate 	ecc.flt_stat = t_afsr;
4817c478bd9Sstevel@tonic-gate 	ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
4827c478bd9Sstevel@tonic-gate 	ecc.flt_func = sysio_log_ce_err;
4837c478bd9Sstevel@tonic-gate 	ecc.flt_bus_id = softsp->upa_id;
4847c478bd9Sstevel@tonic-gate 	ecc.flt_inst = ddi_get_instance(softsp->dip);
4857c478bd9Sstevel@tonic-gate 	ecc.flt_status = ECC_IOBUS;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	ecc.flt_synd = (ushort_t)((t_afsr & SB_CE_AFSR_SYND) >>
4887c478bd9Sstevel@tonic-gate 	    SB_CE_SYND_SHIFT);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
4917c478bd9Sstevel@tonic-gate 	ecc.flt_class = BUS_FAULT;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	ce_scrub(&ecc);
4947c478bd9Sstevel@tonic-gate 	errorq_dispatch(ce_queue, &ecc, sizeof (ecc), ERRORQ_ASYNC);
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate  * callback logging function from the common error handling code
5017c478bd9Sstevel@tonic-gate  */
5027c478bd9Sstevel@tonic-gate static void
sysio_log_ce_err(struct async_flt * ecc,char * unum)5037c478bd9Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate 	uint64_t t_afsr = ecc->flt_stat;
5067c478bd9Sstevel@tonic-gate 	uint64_t t_afar = ecc->flt_addr;
5077c478bd9Sstevel@tonic-gate 	ushort_t id = ecc->flt_bus_id;
5087c478bd9Sstevel@tonic-gate 	ushort_t inst = ecc->flt_inst;
5097c478bd9Sstevel@tonic-gate 	int ce_verbose = ce_verbose_memory;
5107c478bd9Sstevel@tonic-gate 	char *syndrome_str = "!\tSyndrome 0x%x, Offset 0x%x, Size %d, "
5117c478bd9Sstevel@tonic-gate 	    "UPA MID 0x%x\n";
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if ((!ce_verbose_memory) && (!debug_sysio_errs))
5147c478bd9Sstevel@tonic-gate 		return;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_PIO) {
5177c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error from PIO: "
5187c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5217c478bd9Sstevel@tonic-gate 			fmtstr++;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
5247c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32),
5257c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afar, id);
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_DRD) {
5287c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error DMA read: "
5297c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
5307c478bd9Sstevel@tonic-gate 		    "Id %d\n";
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5337c478bd9Sstevel@tonic-gate 			fmtstr++;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
5367c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
5377c478bd9Sstevel@tonic-gate 		    unum, id);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_DWR) {
5407c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error DMA write: "
5417c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d\n";
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5447c478bd9Sstevel@tonic-gate 			fmtstr++;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
5477c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
5487c478bd9Sstevel@tonic-gate 		    unum, id);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_PIO) {
5527c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error from PIO: "
5537c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5567c478bd9Sstevel@tonic-gate 			fmtstr++;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
5597c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
5607c478bd9Sstevel@tonic-gate 		    id);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_DRD) {
5637c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error DMA read: "
5647c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
5657c478bd9Sstevel@tonic-gate 		    "Id %d\n";
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5687c478bd9Sstevel@tonic-gate 			fmtstr++;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
5717c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
5727c478bd9Sstevel@tonic-gate 		    unum, id);
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_DWR) {
5757c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error DMA write: "
5767c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
5777c478bd9Sstevel@tonic-gate 		    "Id %d\n";
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
5807c478bd9Sstevel@tonic-gate 			fmtstr++;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr,
5837c478bd9Sstevel@tonic-gate 		    inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
5847c478bd9Sstevel@tonic-gate 		    (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	if ((debug_sysio_errs) || (ce_verbose > 1))
5887c478bd9Sstevel@tonic-gate 		syndrome_str++;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, syndrome_str,
5917c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_SYND) >> SB_CE_SYND_SHIFT),
5927c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_OFF) >> SB_CE_OFFSET_SHIFT),
5937c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_SIZE) >> SB_CE_SIZE_SHIFT),
5947c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_MID) >> SB_CE_MID_SHIFT));
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate static uint_t
sbus_err_intr(struct sbus_soft_state * softsp)5987c478bd9Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
6017c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
6027c478bd9Sstevel@tonic-gate 	ushort_t id, inst;
6037c478bd9Sstevel@tonic-gate 	int cleared = 0;
6047c478bd9Sstevel@tonic-gate 	volatile uint64_t *afar_reg;
6057c478bd9Sstevel@tonic-gate 	on_trap_data_t *otp = softsp->ontrap_data;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	t_afsr = *softsp->sbus_err_reg;
6087c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)softsp->sbus_err_reg + 1;
6097c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	if (otp == NULL || !(otp->ot_prot & OT_DATA_ACCESS)) {
6127c478bd9Sstevel@tonic-gate 		sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6137c478bd9Sstevel@tonic-gate 		cleared = 1;
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	id = (ushort_t)softsp->upa_id;
6177c478bd9Sstevel@tonic-gate 	inst = (ushort_t)ddi_get_instance(softsp->dip);
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	if (debug_sysio_errs) {
6207c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS))
6217c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
6227c478bd9Sstevel@tonic-gate 		if (!cleared)
6237c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "SBus%d Error: AFSR 0x%08x.%08x "
6267c478bd9Sstevel@tonic-gate 			"AFAR 0x%08x.%08x Id %d\n",
6277c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
6287c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 		debug_enter("sbus_err_intr");
6317c478bd9Sstevel@tonic-gate 	} else {
6327c478bd9Sstevel@tonic-gate 		sbus_log_error(softsp, (uint64_t *)&t_afsr,
6337c478bd9Sstevel@tonic-gate 		    (uint64_t *)&t_afar, id, inst, cleared, otp);
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 	if (!cleared) {
6367c478bd9Sstevel@tonic-gate 		sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate static void
sbus_clear_intr(struct sbus_soft_state * softsp,uint64_t * pafsr)6437c478bd9Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr)
6447c478bd9Sstevel@tonic-gate {
6457c478bd9Sstevel@tonic-gate 	volatile uint64_t *clear_reg;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg = *pafsr;
6487c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
6497c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate static void
sbus_log_error(struct sbus_soft_state * softsp,uint64_t * pafsr,uint64_t * pafar,ushort_t id,ushort_t inst,int cleared,on_trap_data_t * otp)6537c478bd9Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
6547c478bd9Sstevel@tonic-gate     ushort_t id, ushort_t inst, int cleared, on_trap_data_t *otp)
6557c478bd9Sstevel@tonic-gate {
6567c478bd9Sstevel@tonic-gate 	uint64_t t_afsr;
6577c478bd9Sstevel@tonic-gate 	uint64_t t_afar;
6587c478bd9Sstevel@tonic-gate 	int level = CE_WARN;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	t_afsr = *pafsr;
6617c478bd9Sstevel@tonic-gate 	t_afar = *pafar;
6627c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_LE) {
6637c478bd9Sstevel@tonic-gate 		if (!cleared)
6647c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6657c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "SBus%d Primary Error Late PIO: "
6667c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
6677c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
6687c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_TO) {
6717c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
6727c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
6737c478bd9Sstevel@tonic-gate 			return;
6747c478bd9Sstevel@tonic-gate 		}
6757c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
6767c478bd9Sstevel@tonic-gate 			if (!cleared)
6777c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6787c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
6797c478bd9Sstevel@tonic-gate 		}
6807c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Primary Error Timeout: "
6817c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
6827c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
6837c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_BERR) {
6867c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
6877c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
6887c478bd9Sstevel@tonic-gate 			return;
6897c478bd9Sstevel@tonic-gate 		}
6907c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
6917c478bd9Sstevel@tonic-gate 			if (!cleared)
6927c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
6937c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
6947c478bd9Sstevel@tonic-gate 		}
6957c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Primary Error Bus Error: "
6967c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n",
6977c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
6987c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
6997c478bd9Sstevel@tonic-gate 	}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_LE) {
7027c478bd9Sstevel@tonic-gate 		if (!cleared)
7037c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
7047c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "SBus%d Secondary Late PIO Error: "
7057c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
7067c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
7077c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_TO) {
7107c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
7117c478bd9Sstevel@tonic-gate 			if (!cleared)
7127c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
7137c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
7147c478bd9Sstevel@tonic-gate 		}
7157c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Secondary Timeout Error: "
7167c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
7177c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
7187c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_BERR) {
7217c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
7227c478bd9Sstevel@tonic-gate 			if (!cleared)
7237c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
7247c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
7257c478bd9Sstevel@tonic-gate 		}
7267c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Secondary Bus Error: "
7277c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
7287c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
7297c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
7307c478bd9Sstevel@tonic-gate 	}
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate static int
sbus_check_bto(struct sbus_soft_state * softsp)7357c478bd9Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 	hrtime_t now = gethrtime();		/* high PIL safe */
7387c478bd9Sstevel@tonic-gate 	hrtime_t diff = now - softsp->bto_timestamp;
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	if (diff > ((hrtime_t)bto_secs * NANOSEC) || diff < 0LL) {
7417c478bd9Sstevel@tonic-gate 		/*
7427c478bd9Sstevel@tonic-gate 		 * Reset error counter as this bus error has occurred
7437c478bd9Sstevel@tonic-gate 		 * after more than bto_secs duration.
7447c478bd9Sstevel@tonic-gate 		 */
7457c478bd9Sstevel@tonic-gate 		softsp->bto_timestamp = now;
7467c478bd9Sstevel@tonic-gate 		softsp->bto_ctr = 0;
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 	if (softsp->bto_ctr++ >= bto_cnt)
7497c478bd9Sstevel@tonic-gate 		return (1);
7507c478bd9Sstevel@tonic-gate 	return (0);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate static uint_t
sbus_ctrl_ecc_err(struct sbus_soft_state * softsp)7547c478bd9Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp)
7557c478bd9Sstevel@tonic-gate {
7567c478bd9Sstevel@tonic-gate 	uint64_t t_sb_csr;
7577c478bd9Sstevel@tonic-gate 	ushort_t id, inst;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	t_sb_csr = *softsp->sbus_ctrl_reg;
7607c478bd9Sstevel@tonic-gate 	id = (ushort_t)softsp->upa_id;
7617c478bd9Sstevel@tonic-gate 	inst = (ushort_t)ddi_get_instance(softsp->dip);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	if (debug_sysio_errs) {
7647c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "sbus_ctrl_ecc_error: SBus%d Control Reg "
7657c478bd9Sstevel@tonic-gate 		    "0x%016llx Id %d\n", inst, (u_longlong_t)t_sb_csr, id);
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (t_sb_csr & (SB_CSR_DPERR_S14|SB_CSR_DPERR_S13|SB_CSR_DPERR_S3|
7697c478bd9Sstevel@tonic-gate 	    SB_CSR_DPERR_S2|SB_CSR_DPERR_S1|SB_CSR_DPERR_S0|SB_CSR_PIO_PERRS)) {
7707c478bd9Sstevel@tonic-gate 		struct async_flt aflt;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 		*softsp->sbus_ctrl_reg = t_sb_csr; /* clear error bits */
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		bzero(&aflt, sizeof (aflt));
7757c478bd9Sstevel@tonic-gate 		aflt.flt_id = gethrtime();
7767c478bd9Sstevel@tonic-gate 		aflt.flt_stat = t_sb_csr;
7777c478bd9Sstevel@tonic-gate 		aflt.flt_func = sbus_log_csr_error;
7787c478bd9Sstevel@tonic-gate 		aflt.flt_bus_id = id;
7797c478bd9Sstevel@tonic-gate 		aflt.flt_inst = inst;
7807c478bd9Sstevel@tonic-gate 		aflt.flt_status = ECC_IOBUS;
7817c478bd9Sstevel@tonic-gate 		aflt.flt_class = BUS_FAULT;
7827c478bd9Sstevel@tonic-gate 		aflt.flt_panic = 1;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		errorq_dispatch(ue_queue, &aflt, sizeof (aflt), aflt.flt_panic);
7857c478bd9Sstevel@tonic-gate 		return (BF_FATAL);
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	return (BF_NONE);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7927c478bd9Sstevel@tonic-gate static void
sbus_log_csr_error(struct async_flt * aflt,char * unum)7937c478bd9Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	uint64_t t_sb_csr = aflt->flt_stat;
7967c478bd9Sstevel@tonic-gate 	uint_t id = aflt->flt_bus_id;
7977c478bd9Sstevel@tonic-gate 	uint_t inst = aflt->flt_inst;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	/*
8007c478bd9Sstevel@tonic-gate 	 * Print out SBus error information.
8017c478bd9Sstevel@tonic-gate 	 */
8027c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S14) {
8037c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8047c478bd9Sstevel@tonic-gate 		"SBus%d Slot 14 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8057c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8067c478bd9Sstevel@tonic-gate 	}
8077c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S13) {
8087c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8097c478bd9Sstevel@tonic-gate 		"SBus%d Slot 13 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8107c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S3) {
8137c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8147c478bd9Sstevel@tonic-gate 		"SBus%d Slot 3 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8157c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S2) {
8187c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8197c478bd9Sstevel@tonic-gate 		"SBus%d Slot 2 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8207c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S1) {
8237c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8247c478bd9Sstevel@tonic-gate 		"SBus%d Slot 1 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8257c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S0) {
8287c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8297c478bd9Sstevel@tonic-gate 		"SBus%d Slot 0 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
8307c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S15) {
8337c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8347c478bd9Sstevel@tonic-gate 		"SBus%d Slot 15 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8357c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S14) {
8387c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8397c478bd9Sstevel@tonic-gate 		"SBus%d Slot 14 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8407c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S13) {
8437c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8447c478bd9Sstevel@tonic-gate 		"SBus%d Slot 13 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8457c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S3) {
8487c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8497c478bd9Sstevel@tonic-gate 		"SBus%d Slot 3 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8507c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S2) {
8537c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8547c478bd9Sstevel@tonic-gate 		"SBus%d Slot 2 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8557c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S1) {
8587c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8597c478bd9Sstevel@tonic-gate 		"SBus%d Slot 1 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8607c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8617c478bd9Sstevel@tonic-gate 	}
8627c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S0) {
8637c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8647c478bd9Sstevel@tonic-gate 		"SBus%d Slot 0 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
8657c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
8667c478bd9Sstevel@tonic-gate 	}
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate  * Sysio Thermal Warning interrupt handler
8717c478bd9Sstevel@tonic-gate  */
8727c478bd9Sstevel@tonic-gate static uint_t
sysio_thermal_warn_intr(struct sbus_soft_state * softsp)8737c478bd9Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp)
8747c478bd9Sstevel@tonic-gate {
8757c478bd9Sstevel@tonic-gate 	volatile uint64_t *clear_reg;
8767c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp_mondo_vec;
8777c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg;
8787c478bd9Sstevel@tonic-gate 	const char thermal_warn_msg[] =
8797c478bd9Sstevel@tonic-gate 	    "Severe over-temperature condition detected!";
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	/*
8827c478bd9Sstevel@tonic-gate 	 * Take off the Thermal Warning interrupt and
8837c478bd9Sstevel@tonic-gate 	 * remove its interrupt handler.
8847c478bd9Sstevel@tonic-gate 	 */
8857c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
8867c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = *mondo_vec_reg;
8877c478bd9Sstevel@tonic-gate 	tmp_mondo_vec &= ~INTERRUPT_VALID;
8887c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 4, NULL);
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + THERMAL_CLEAR);
8937c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	if (oven_test) {
8967c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "OVEN TEST: %s", thermal_warn_msg);
8977c478bd9Sstevel@tonic-gate 		return (DDI_INTR_CLAIMED);
8987c478bd9Sstevel@tonic-gate 	}
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	cmn_err(CE_WARN, "%s", thermal_warn_msg);
9017c478bd9Sstevel@tonic-gate 	cmn_err(CE_WARN, "Powering down...");
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	do_shutdown();
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	/*
9067c478bd9Sstevel@tonic-gate 	 * just in case do_shutdown() fails
9077c478bd9Sstevel@tonic-gate 	 */
9087c478bd9Sstevel@tonic-gate 	(void) timeout((void(*)(void *))power_down, NULL,
9097c478bd9Sstevel@tonic-gate 	    thermal_powerdown_delay * hz);
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
9127c478bd9Sstevel@tonic-gate }
913