xref: /titanic_51/usr/src/uts/sun4u/io/sysioerr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1990-2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/async.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/sysiosbus.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/sysioerr.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * Set the following variable in /etc/system to tell the kernel
46*7c478bd9Sstevel@tonic-gate  * not to shutdown the machine if the temperature reaches
47*7c478bd9Sstevel@tonic-gate  * the Thermal Warning limit.
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate int oven_test = 0;
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  * To indicate if the prom has the property of "thermal-interrupt".
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate static int thermal_interrupt_enabled = 0;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
57*7c478bd9Sstevel@tonic-gate #include <sys/starfire.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate int
60*7c478bd9Sstevel@tonic-gate pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate void
63*7c478bd9Sstevel@tonic-gate pc_ittrans_cleanup(caddr_t, volatile uint64_t *);
64*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /*
67*7c478bd9Sstevel@tonic-gate  * adb debug_sysio_errs to 1 if you don't want your system to panic on
68*7c478bd9Sstevel@tonic-gate  * sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
69*7c478bd9Sstevel@tonic-gate  * to check for sysio errors at all.
70*7c478bd9Sstevel@tonic-gate  */
71*7c478bd9Sstevel@tonic-gate int sysio_err_flag = 1;
72*7c478bd9Sstevel@tonic-gate uint_t debug_sysio_errs = 0;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  * bto_cnt = number of bus errors and timeouts allowed within bto_secs
76*7c478bd9Sstevel@tonic-gate  * use /etc/system to change the bto_cnt to a very large number if
77*7c478bd9Sstevel@tonic-gate  * it's a problem!
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate int bto_secs = 10;
80*7c478bd9Sstevel@tonic-gate int bto_cnt = 10;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate static uint_t
83*7c478bd9Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp);
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate static uint_t
86*7c478bd9Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp);
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static uint_t
89*7c478bd9Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp);
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate static void
92*7c478bd9Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum);
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate static void
95*7c478bd9Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum);
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate static void
98*7c478bd9Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate static void
101*7c478bd9Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
102*7c478bd9Sstevel@tonic-gate     ushort_t id, ushort_t inst, int cleared,
103*7c478bd9Sstevel@tonic-gate     on_trap_data_t *ontrap_data);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate static int
106*7c478bd9Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp);
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate static void
109*7c478bd9Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate static uint_t
112*7c478bd9Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp);
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate static uint_t
115*7c478bd9Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static uint_t
118*7c478bd9Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp);
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate static uint_t
121*7c478bd9Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp);
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate static int sbus_pil[] = {SBUS_UE_PIL, SBUS_CE_PIL, SBUS_ERR_PIL, SBUS_PF_PIL,
124*7c478bd9Sstevel@tonic-gate 	SBUS_THERMAL_PIL, SBUS_PM_PIL};
125*7c478bd9Sstevel@tonic-gate int
126*7c478bd9Sstevel@tonic-gate sysio_err_init(struct sbus_soft_state *softsp, caddr_t address)
127*7c478bd9Sstevel@tonic-gate {
128*7c478bd9Sstevel@tonic-gate 	if (sysio_err_flag == 0) {
129*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Warning: sysio errors not initialized\n");
130*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	/*
134*7c478bd9Sstevel@tonic-gate 	 * Get the address of the already mapped-in sysio/sbus error registers.
135*7c478bd9Sstevel@tonic-gate 	 * Simply add each registers offset to the already mapped in address
136*7c478bd9Sstevel@tonic-gate 	 * that was retrieved from the device node's "address" property,
137*7c478bd9Sstevel@tonic-gate 	 * and passed as an argument to this function.
138*7c478bd9Sstevel@tonic-gate 	 *
139*7c478bd9Sstevel@tonic-gate 	 * Define a macro for the pointer arithmetic ...
140*7c478bd9Sstevel@tonic-gate 	 */
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate #define	REG_ADDR(b, o)	(uint64_t *)((caddr_t)(b) + (o))
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	softsp->sysio_ecc_reg = REG_ADDR(address, OFF_SYSIO_ECC_REGS);
145*7c478bd9Sstevel@tonic-gate 	softsp->sysio_ue_reg = REG_ADDR(address, OFF_SYSIO_UE_REGS);
146*7c478bd9Sstevel@tonic-gate 	softsp->sysio_ce_reg = REG_ADDR(address, OFF_SYSIO_CE_REGS);
147*7c478bd9Sstevel@tonic-gate 	softsp->sbus_err_reg = REG_ADDR(address, OFF_SBUS_ERR_REGS);
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate #undef	REG_ADDR
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	/*
152*7c478bd9Sstevel@tonic-gate 	 * create the interrupt-priorities property if it doesn't
153*7c478bd9Sstevel@tonic-gate 	 * already exist to provide a hint as to the PIL level for
154*7c478bd9Sstevel@tonic-gate 	 * our interrupt.
155*7c478bd9Sstevel@tonic-gate 	 */
156*7c478bd9Sstevel@tonic-gate 	{
157*7c478bd9Sstevel@tonic-gate 		int len;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 		if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
160*7c478bd9Sstevel@tonic-gate 		    DDI_PROP_DONTPASS, "interrupt-priorities",
161*7c478bd9Sstevel@tonic-gate 		    &len) != DDI_PROP_SUCCESS) {
162*7c478bd9Sstevel@tonic-gate 				/* Create the interrupt-priorities property. */
163*7c478bd9Sstevel@tonic-gate 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
164*7c478bd9Sstevel@tonic-gate 			    softsp->dip, "interrupt-priorities",
165*7c478bd9Sstevel@tonic-gate 			    (int *)sbus_pil, sizeof (sbus_pil) / sizeof (int));
166*7c478bd9Sstevel@tonic-gate 		}
167*7c478bd9Sstevel@tonic-gate 	}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 0, NULL, NULL,
170*7c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sysio_ue_intr, (caddr_t)softsp);
171*7c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 1, NULL, NULL,
172*7c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sysio_ce_intr, (caddr_t)softsp);
173*7c478bd9Sstevel@tonic-gate 	(void) ddi_add_intr(softsp->dip, 2, NULL, NULL,
174*7c478bd9Sstevel@tonic-gate 	    (uint_t (*)())sbus_err_intr, (caddr_t)softsp);
175*7c478bd9Sstevel@tonic-gate 	/*
176*7c478bd9Sstevel@tonic-gate 	 * If the thermal-interrupt property is in place,
177*7c478bd9Sstevel@tonic-gate 	 * then register the thermal warning interrupt handler and
178*7c478bd9Sstevel@tonic-gate 	 * program its mapping register
179*7c478bd9Sstevel@tonic-gate 	 */
180*7c478bd9Sstevel@tonic-gate 	thermal_interrupt_enabled = ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
181*7c478bd9Sstevel@tonic-gate 		DDI_PROP_DONTPASS, "thermal-interrupt", -1);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
184*7c478bd9Sstevel@tonic-gate 		(void) ddi_add_intr(softsp->dip, 4, NULL, NULL,
185*7c478bd9Sstevel@tonic-gate 		    (uint_t (*)())sysio_thermal_warn_intr, (caddr_t)softsp);
186*7c478bd9Sstevel@tonic-gate 	}
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 	bus_func_register(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
189*7c478bd9Sstevel@tonic-gate 	bus_func_register(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	(void) sysio_init_err(softsp);
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate int
197*7c478bd9Sstevel@tonic-gate sysio_err_resume_init(struct sbus_soft_state *softsp)
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate 	(void) sysio_init_err(softsp);
200*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
201*7c478bd9Sstevel@tonic-gate }
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate int
204*7c478bd9Sstevel@tonic-gate sysio_err_uninit(struct sbus_soft_state *softsp)
205*7c478bd9Sstevel@tonic-gate {
206*7c478bd9Sstevel@tonic-gate 	/* remove the interrupts from the interrupt list */
207*7c478bd9Sstevel@tonic-gate 	(void) sysio_dis_err(softsp);
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 0, NULL);
210*7c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 1, NULL);
211*7c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 2, NULL);
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
214*7c478bd9Sstevel@tonic-gate 		ddi_remove_intr(softsp->dip, 4, NULL);
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	bus_func_unregister(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
218*7c478bd9Sstevel@tonic-gate 	bus_func_unregister(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate static uint_t
224*7c478bd9Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp)
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp_mondo_vec, tmpreg;
227*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg;
228*7c478bd9Sstevel@tonic-gate 	uint_t cpu_id, acpu_id;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	acpu_id = intr_dist_cpuid();
231*7c478bd9Sstevel@tonic-gate 	/*
232*7c478bd9Sstevel@tonic-gate 	 * Program the mondo vector accordingly.  This MUST be the
233*7c478bd9Sstevel@tonic-gate 	 * last thing we do.  Once we program the mondo, the device
234*7c478bd9Sstevel@tonic-gate 	 * may begin to interrupt. Store it in the hardware reg.
235*7c478bd9Sstevel@tonic-gate 	 */
236*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + UE_ECC_MAPREG);
237*7c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
238*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
239*7c478bd9Sstevel@tonic-gate 	cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
240*7c478bd9Sstevel@tonic-gate 				mondo_vec_reg);
241*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
242*7c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
243*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + CE_ECC_MAPREG);
246*7c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
247*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
248*7c478bd9Sstevel@tonic-gate 	cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
249*7c478bd9Sstevel@tonic-gate 				mondo_vec_reg);
250*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
251*7c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
252*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg =
255*7c478bd9Sstevel@tonic-gate 	    (uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
256*7c478bd9Sstevel@tonic-gate 	cpu_id = acpu_id;
257*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
258*7c478bd9Sstevel@tonic-gate 	cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
259*7c478bd9Sstevel@tonic-gate 				mondo_vec_reg);
260*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
263*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	if (thermal_interrupt_enabled == 1) {
266*7c478bd9Sstevel@tonic-gate 		mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
267*7c478bd9Sstevel@tonic-gate 		cpu_id = acpu_id;
268*7c478bd9Sstevel@tonic-gate 		tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) |
269*7c478bd9Sstevel@tonic-gate 			INTERRUPT_VALID;
270*7c478bd9Sstevel@tonic-gate 		*mondo_vec_reg = tmp_mondo_vec;
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
274*7c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	/*
277*7c478bd9Sstevel@tonic-gate 	 * XXX - This may already be set by the OBP.
278*7c478bd9Sstevel@tonic-gate 	 */
279*7c478bd9Sstevel@tonic-gate 	tmpreg = SYSIO_APCKEN;
280*7c478bd9Sstevel@tonic-gate 	*softsp->sysio_ctrl_reg |= tmpreg;
281*7c478bd9Sstevel@tonic-gate 	tmpreg = (SECR_ECC_EN | SECR_UE_INTEN | SECR_CE_INTEN);
282*7c478bd9Sstevel@tonic-gate 	*softsp->sysio_ecc_reg = tmpreg;
283*7c478bd9Sstevel@tonic-gate 	tmpreg = SB_CSR_ERRINT_EN;
284*7c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg |= tmpreg;
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	/* Initialize timeout/bus error counter */
287*7c478bd9Sstevel@tonic-gate 	softsp->bto_timestamp = 0;
288*7c478bd9Sstevel@tonic-gate 	softsp->bto_ctr = 0;
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	return (0);
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate static uint_t
294*7c478bd9Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp)
295*7c478bd9Sstevel@tonic-gate {
296*7c478bd9Sstevel@tonic-gate 	volatile uint64_t tmpreg;
297*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg, *clear_vec_reg;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	*softsp->sysio_ctrl_reg &= ~SYSIO_APCKEN;
300*7c478bd9Sstevel@tonic-gate 	*softsp->sysio_ecc_reg = 0;
301*7c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg &= ~SB_CSR_ERRINT_EN;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
304*7c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
305*7c478bd9Sstevel@tonic-gate #ifdef lint
306*7c478bd9Sstevel@tonic-gate 	tmpreg = tmpreg;
307*7c478bd9Sstevel@tonic-gate #endif
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	/* Unmap mapping registers */
310*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + UE_ECC_MAPREG);
311*7c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
316*7c478bd9Sstevel@tonic-gate 	/* do cleanup for starfire interrupt target translation */
317*7c478bd9Sstevel@tonic-gate 	pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
318*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG);
323*7c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
328*7c478bd9Sstevel@tonic-gate 	/* Do cleanup for starfire interrupt target translation */
329*7c478bd9Sstevel@tonic-gate 	pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
330*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
335*7c478bd9Sstevel@tonic-gate 	clear_vec_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = 0;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate #ifdef	_STARFIRE
340*7c478bd9Sstevel@tonic-gate 	/* Do cleanup for starfire interrupt target translation */
341*7c478bd9Sstevel@tonic-gate 	pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
342*7c478bd9Sstevel@tonic-gate #endif	/* _STARFIRE */
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	*clear_vec_reg = 0;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
347*7c478bd9Sstevel@tonic-gate 	tmpreg = *softsp->sbus_ctrl_reg;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	return (BF_NONE);
350*7c478bd9Sstevel@tonic-gate }
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate /*
353*7c478bd9Sstevel@tonic-gate  * Gather information about the error into an async_flt structure, and then
354*7c478bd9Sstevel@tonic-gate  * enqueue the error for reporting and processing and panic.
355*7c478bd9Sstevel@tonic-gate  */
356*7c478bd9Sstevel@tonic-gate static uint_t
357*7c478bd9Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp)
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
360*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
361*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *ue_reg, *afar_reg, *clear_reg;
362*7c478bd9Sstevel@tonic-gate 	struct async_flt ecc;
363*7c478bd9Sstevel@tonic-gate 	uint64_t offset;
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	/*
366*7c478bd9Sstevel@tonic-gate 	 * Disable all further sbus errors, for this sbus instance, for
367*7c478bd9Sstevel@tonic-gate 	 * what is guaranteed to be a fatal error. And grab any other cpus.
368*7c478bd9Sstevel@tonic-gate 	 */
369*7c478bd9Sstevel@tonic-gate 	(void) sysio_dis_err(softsp);		/* disabled sysio errors */
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	/*
372*7c478bd9Sstevel@tonic-gate 	 * Then read and clear the afsr/afar and clear interrupt regs.
373*7c478bd9Sstevel@tonic-gate 	 */
374*7c478bd9Sstevel@tonic-gate 	ue_reg = (uint64_t *)softsp->sysio_ue_reg;
375*7c478bd9Sstevel@tonic-gate 	t_afsr = *ue_reg;
376*7c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)ue_reg + 1;
377*7c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
378*7c478bd9Sstevel@tonic-gate 	*ue_reg = t_afsr;
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
381*7c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	/*
384*7c478bd9Sstevel@tonic-gate 	 * The AFSR DW_OFFSET field contains the offset of the doubleword with
385*7c478bd9Sstevel@tonic-gate 	 * the ECC error relative to the 64-byte aligned PA.  We multiply by 8
386*7c478bd9Sstevel@tonic-gate 	 * to convert to a byte offset, and then add this to flt_addr.
387*7c478bd9Sstevel@tonic-gate 	 */
388*7c478bd9Sstevel@tonic-gate 	offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	bzero(&ecc, sizeof (ecc));
391*7c478bd9Sstevel@tonic-gate 	ecc.flt_id = gethrtime();
392*7c478bd9Sstevel@tonic-gate 	ecc.flt_stat = t_afsr;
393*7c478bd9Sstevel@tonic-gate 	ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
394*7c478bd9Sstevel@tonic-gate 	ecc.flt_func = sysio_log_ue_err;
395*7c478bd9Sstevel@tonic-gate 	ecc.flt_bus_id = softsp->upa_id;
396*7c478bd9Sstevel@tonic-gate 	ecc.flt_inst = ddi_get_instance(softsp->dip);
397*7c478bd9Sstevel@tonic-gate 	ecc.flt_status = ECC_IOBUS;
398*7c478bd9Sstevel@tonic-gate 	ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
399*7c478bd9Sstevel@tonic-gate 	ecc.flt_class = BUS_FAULT;
400*7c478bd9Sstevel@tonic-gate 	ecc.flt_panic = (debug_sysio_errs == 0);
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	errorq_dispatch(ue_queue, &ecc, sizeof (ecc), ecc.flt_panic);
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 	/*
405*7c478bd9Sstevel@tonic-gate 	 * If the UE is in memory and fatal, save the fault info so the
406*7c478bd9Sstevel@tonic-gate 	 * panic code will know to check for copyback errors.
407*7c478bd9Sstevel@tonic-gate 	 */
408*7c478bd9Sstevel@tonic-gate 	if (ecc.flt_panic && ecc.flt_in_memory)
409*7c478bd9Sstevel@tonic-gate 		panic_aflt = ecc;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	/*
412*7c478bd9Sstevel@tonic-gate 	 * We must also check for other bus UE errors, and panic if
413*7c478bd9Sstevel@tonic-gate 	 * any fatal ones are detected at this point.
414*7c478bd9Sstevel@tonic-gate 	 */
415*7c478bd9Sstevel@tonic-gate 	if (bus_func_invoke(BF_TYPE_UE) == BF_FATAL)
416*7c478bd9Sstevel@tonic-gate 		ecc.flt_panic = 1;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	if (ecc.flt_panic)
419*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "Fatal Sbus%d UE Error", ecc.flt_inst);
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate /*
425*7c478bd9Sstevel@tonic-gate  * callback logging function from the common error handling code
426*7c478bd9Sstevel@tonic-gate  */
427*7c478bd9Sstevel@tonic-gate static void
428*7c478bd9Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum)
429*7c478bd9Sstevel@tonic-gate {
430*7c478bd9Sstevel@tonic-gate 	uint64_t t_afsr = ecc->flt_stat;
431*7c478bd9Sstevel@tonic-gate 	uint64_t t_afar = ecc->flt_addr;
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	ushort_t id = ecc->flt_bus_id;
434*7c478bd9Sstevel@tonic-gate 	ushort_t inst = ecc->flt_inst;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_PIO) {
437*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error from PIO: "
438*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
439*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
440*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
441*7c478bd9Sstevel@tonic-gate 	}
442*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_DRD) {
443*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error DMA read: "
444*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
445*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
446*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_P_DWR) {
449*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Primary Error DVMA write: "
450*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
451*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
452*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
453*7c478bd9Sstevel@tonic-gate 	}
454*7c478bd9Sstevel@tonic-gate 	/*
455*7c478bd9Sstevel@tonic-gate 	 * We should never hit the secondary error panics.
456*7c478bd9Sstevel@tonic-gate 	 */
457*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_PIO) {
458*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary Error from PIO: "
459*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
460*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
461*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_DRD) {
464*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary Error DMA read: "
465*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
466*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
467*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_UE_AFSR_S_DWR) {
470*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "SBus%d UE Secondary  Error DMA write: "
471*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
472*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
473*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
474*7c478bd9Sstevel@tonic-gate 	}
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	if ((debug_sysio_errs) || (aft_verbose)) {
477*7c478bd9Sstevel@tonic-gate 		(void) read_ecc_data(ecc, 1, 0);
478*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "\tOffset 0x%x, Size %d, UPA MID 0x%x\n",
479*7c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT),
480*7c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_SIZE) >> SB_UE_SIZE_SHIFT),
481*7c478bd9Sstevel@tonic-gate 		    (uint32_t)((t_afsr & SB_UE_AFSR_MID) >> SB_UE_MID_SHIFT));
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate /*
486*7c478bd9Sstevel@tonic-gate  * gather the information about the error, plus a pointer to
487*7c478bd9Sstevel@tonic-gate  * the callback logging function, and call the generic ce_error handler.
488*7c478bd9Sstevel@tonic-gate  */
489*7c478bd9Sstevel@tonic-gate static uint_t
490*7c478bd9Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp)
491*7c478bd9Sstevel@tonic-gate {
492*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
493*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
494*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *afar_reg, *clear_reg, *ce_reg;
495*7c478bd9Sstevel@tonic-gate 	struct async_flt ecc;
496*7c478bd9Sstevel@tonic-gate 	uint64_t offset;
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 	ce_reg = (uint64_t *)softsp->sysio_ce_reg;
499*7c478bd9Sstevel@tonic-gate 	t_afsr = *ce_reg;
500*7c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)ce_reg + 1;
501*7c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
502*7c478bd9Sstevel@tonic-gate 	*ce_reg = t_afsr;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
505*7c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	/*
508*7c478bd9Sstevel@tonic-gate 	 * The AFSR DW_OFFSET field contains the offset of the doubleword with
509*7c478bd9Sstevel@tonic-gate 	 * the ECC error relative to the 64-byte aligned PA.  We multiply by 8
510*7c478bd9Sstevel@tonic-gate 	 * to convert to a byte offset, and then add this to flt_addr.
511*7c478bd9Sstevel@tonic-gate 	 */
512*7c478bd9Sstevel@tonic-gate 	offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	bzero(&ecc, sizeof (ecc));
515*7c478bd9Sstevel@tonic-gate 	ecc.flt_id = gethrtime();
516*7c478bd9Sstevel@tonic-gate 	ecc.flt_stat = t_afsr;
517*7c478bd9Sstevel@tonic-gate 	ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
518*7c478bd9Sstevel@tonic-gate 	ecc.flt_func = sysio_log_ce_err;
519*7c478bd9Sstevel@tonic-gate 	ecc.flt_bus_id = softsp->upa_id;
520*7c478bd9Sstevel@tonic-gate 	ecc.flt_inst = ddi_get_instance(softsp->dip);
521*7c478bd9Sstevel@tonic-gate 	ecc.flt_status = ECC_IOBUS;
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	ecc.flt_synd = (ushort_t)((t_afsr & SB_CE_AFSR_SYND) >>
524*7c478bd9Sstevel@tonic-gate 	    SB_CE_SYND_SHIFT);
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
527*7c478bd9Sstevel@tonic-gate 	ecc.flt_class = BUS_FAULT;
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	ce_scrub(&ecc);
530*7c478bd9Sstevel@tonic-gate 	errorq_dispatch(ce_queue, &ecc, sizeof (ecc), ERRORQ_ASYNC);
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
533*7c478bd9Sstevel@tonic-gate }
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate /*
536*7c478bd9Sstevel@tonic-gate  * callback logging function from the common error handling code
537*7c478bd9Sstevel@tonic-gate  */
538*7c478bd9Sstevel@tonic-gate static void
539*7c478bd9Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	uint64_t t_afsr = ecc->flt_stat;
542*7c478bd9Sstevel@tonic-gate 	uint64_t t_afar = ecc->flt_addr;
543*7c478bd9Sstevel@tonic-gate 	ushort_t id = ecc->flt_bus_id;
544*7c478bd9Sstevel@tonic-gate 	ushort_t inst = ecc->flt_inst;
545*7c478bd9Sstevel@tonic-gate 	int ce_verbose = ce_verbose_memory;
546*7c478bd9Sstevel@tonic-gate 	char *syndrome_str = "!\tSyndrome 0x%x, Offset 0x%x, Size %d, "
547*7c478bd9Sstevel@tonic-gate 	    "UPA MID 0x%x\n";
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	if ((!ce_verbose_memory) && (!debug_sysio_errs))
550*7c478bd9Sstevel@tonic-gate 		return;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_PIO) {
553*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error from PIO: "
554*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
557*7c478bd9Sstevel@tonic-gate 			fmtstr++;
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
560*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32),
561*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afar, id);
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_DRD) {
564*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error DMA read: "
565*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
566*7c478bd9Sstevel@tonic-gate 		    "Id %d\n";
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
569*7c478bd9Sstevel@tonic-gate 			fmtstr++;
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
572*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
573*7c478bd9Sstevel@tonic-gate 		    unum, id);
574*7c478bd9Sstevel@tonic-gate 	}
575*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_P_DWR) {
576*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Primary Error DMA write: "
577*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d\n";
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
580*7c478bd9Sstevel@tonic-gate 			fmtstr++;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
583*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
584*7c478bd9Sstevel@tonic-gate 		    unum, id);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_PIO) {
588*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error from PIO: "
589*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
592*7c478bd9Sstevel@tonic-gate 			fmtstr++;
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
595*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
596*7c478bd9Sstevel@tonic-gate 		    id);
597*7c478bd9Sstevel@tonic-gate 	}
598*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_DRD) {
599*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error DMA read: "
600*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
601*7c478bd9Sstevel@tonic-gate 		    "Id %d\n";
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
604*7c478bd9Sstevel@tonic-gate 			fmtstr++;
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
607*7c478bd9Sstevel@tonic-gate 		    (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
608*7c478bd9Sstevel@tonic-gate 		    unum, id);
609*7c478bd9Sstevel@tonic-gate 	}
610*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_CE_AFSR_S_DWR) {
611*7c478bd9Sstevel@tonic-gate 		char *fmtstr = "!SBus%d CE Secondary Error DMA write: "
612*7c478bd9Sstevel@tonic-gate 		    "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
613*7c478bd9Sstevel@tonic-gate 		    "Id %d\n";
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 		if ((debug_sysio_errs) || (ce_verbose > 1))
616*7c478bd9Sstevel@tonic-gate 			fmtstr++;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, fmtstr,
619*7c478bd9Sstevel@tonic-gate 		    inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
620*7c478bd9Sstevel@tonic-gate 		    (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	if ((debug_sysio_errs) || (ce_verbose > 1))
624*7c478bd9Sstevel@tonic-gate 		syndrome_str++;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, syndrome_str,
627*7c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_SYND) >> SB_CE_SYND_SHIFT),
628*7c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_OFF) >> SB_CE_OFFSET_SHIFT),
629*7c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_SIZE) >> SB_CE_SIZE_SHIFT),
630*7c478bd9Sstevel@tonic-gate 	    (uint32_t)((t_afsr & SB_CE_AFSR_MID) >> SB_CE_MID_SHIFT));
631*7c478bd9Sstevel@tonic-gate }
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate static uint_t
634*7c478bd9Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp)
635*7c478bd9Sstevel@tonic-gate {
636*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afsr;
637*7c478bd9Sstevel@tonic-gate 	volatile uint64_t t_afar;
638*7c478bd9Sstevel@tonic-gate 	ushort_t id, inst;
639*7c478bd9Sstevel@tonic-gate 	int cleared = 0;
640*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *afar_reg;
641*7c478bd9Sstevel@tonic-gate 	on_trap_data_t *otp = softsp->ontrap_data;
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	t_afsr = *softsp->sbus_err_reg;
644*7c478bd9Sstevel@tonic-gate 	afar_reg = (uint64_t *)softsp->sbus_err_reg + 1;
645*7c478bd9Sstevel@tonic-gate 	t_afar = *afar_reg;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	if (otp == NULL || !(otp->ot_prot & OT_DATA_ACCESS)) {
648*7c478bd9Sstevel@tonic-gate 		sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
649*7c478bd9Sstevel@tonic-gate 		cleared = 1;
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	id = (ushort_t)softsp->upa_id;
653*7c478bd9Sstevel@tonic-gate 	inst = (ushort_t)ddi_get_instance(softsp->dip);
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	if (debug_sysio_errs) {
656*7c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS))
657*7c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
658*7c478bd9Sstevel@tonic-gate 		if (!cleared)
659*7c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "SBus%d Error: AFSR 0x%08x.%08x "
662*7c478bd9Sstevel@tonic-gate 			"AFAR 0x%08x.%08x Id %d\n",
663*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
664*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 		debug_enter("sbus_err_intr");
667*7c478bd9Sstevel@tonic-gate 	} else {
668*7c478bd9Sstevel@tonic-gate 		sbus_log_error(softsp, (uint64_t *)&t_afsr,
669*7c478bd9Sstevel@tonic-gate 		    (uint64_t *)&t_afar, id, inst, cleared, otp);
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 	if (!cleared) {
672*7c478bd9Sstevel@tonic-gate 		sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
673*7c478bd9Sstevel@tonic-gate 	}
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
676*7c478bd9Sstevel@tonic-gate }
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate static void
679*7c478bd9Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr)
680*7c478bd9Sstevel@tonic-gate {
681*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *clear_reg;
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	*softsp->sbus_err_reg = *pafsr;
684*7c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
685*7c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate static void
689*7c478bd9Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
690*7c478bd9Sstevel@tonic-gate     ushort_t id, ushort_t inst, int cleared, on_trap_data_t *otp)
691*7c478bd9Sstevel@tonic-gate {
692*7c478bd9Sstevel@tonic-gate 	uint64_t t_afsr;
693*7c478bd9Sstevel@tonic-gate 	uint64_t t_afar;
694*7c478bd9Sstevel@tonic-gate 	int level = CE_WARN;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	t_afsr = *pafsr;
697*7c478bd9Sstevel@tonic-gate 	t_afar = *pafar;
698*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_LE) {
699*7c478bd9Sstevel@tonic-gate 		if (!cleared)
700*7c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
701*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "SBus%d Primary Error Late PIO: "
702*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
703*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
704*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
705*7c478bd9Sstevel@tonic-gate 	}
706*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_TO) {
707*7c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
708*7c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
709*7c478bd9Sstevel@tonic-gate 			return;
710*7c478bd9Sstevel@tonic-gate 		}
711*7c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
712*7c478bd9Sstevel@tonic-gate 			if (!cleared)
713*7c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
714*7c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
715*7c478bd9Sstevel@tonic-gate 		}
716*7c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Primary Error Timeout: "
717*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
718*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
719*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
720*7c478bd9Sstevel@tonic-gate 	}
721*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_P_BERR) {
722*7c478bd9Sstevel@tonic-gate 		if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
723*7c478bd9Sstevel@tonic-gate 			otp->ot_trap |= OT_DATA_ACCESS;
724*7c478bd9Sstevel@tonic-gate 			return;
725*7c478bd9Sstevel@tonic-gate 		}
726*7c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
727*7c478bd9Sstevel@tonic-gate 			if (!cleared)
728*7c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
729*7c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
730*7c478bd9Sstevel@tonic-gate 		}
731*7c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Primary Error Bus Error: "
732*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n",
733*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
734*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_LE) {
738*7c478bd9Sstevel@tonic-gate 		if (!cleared)
739*7c478bd9Sstevel@tonic-gate 			sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
740*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "SBus%d Secondary Late PIO Error: "
741*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
742*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
743*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
744*7c478bd9Sstevel@tonic-gate 	}
745*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_TO) {
746*7c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
747*7c478bd9Sstevel@tonic-gate 			if (!cleared)
748*7c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
749*7c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
750*7c478bd9Sstevel@tonic-gate 		}
751*7c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Secondary Timeout Error: "
752*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
753*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
754*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
755*7c478bd9Sstevel@tonic-gate 	}
756*7c478bd9Sstevel@tonic-gate 	if (t_afsr & SB_AFSR_S_BERR) {
757*7c478bd9Sstevel@tonic-gate 		if (sbus_check_bto(softsp)) {
758*7c478bd9Sstevel@tonic-gate 			if (!cleared)
759*7c478bd9Sstevel@tonic-gate 				sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
760*7c478bd9Sstevel@tonic-gate 			level = CE_PANIC;
761*7c478bd9Sstevel@tonic-gate 		}
762*7c478bd9Sstevel@tonic-gate 		cmn_err(level, "SBus%d Secondary Bus Error: "
763*7c478bd9Sstevel@tonic-gate 			"AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
764*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
765*7c478bd9Sstevel@tonic-gate 			(uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate }
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate static int
771*7c478bd9Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp)
772*7c478bd9Sstevel@tonic-gate {
773*7c478bd9Sstevel@tonic-gate 	hrtime_t now = gethrtime();		/* high PIL safe */
774*7c478bd9Sstevel@tonic-gate 	hrtime_t diff = now - softsp->bto_timestamp;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	if (diff > ((hrtime_t)bto_secs * NANOSEC) || diff < 0LL) {
777*7c478bd9Sstevel@tonic-gate 		/*
778*7c478bd9Sstevel@tonic-gate 		 * Reset error counter as this bus error has occurred
779*7c478bd9Sstevel@tonic-gate 		 * after more than bto_secs duration.
780*7c478bd9Sstevel@tonic-gate 		 */
781*7c478bd9Sstevel@tonic-gate 		softsp->bto_timestamp = now;
782*7c478bd9Sstevel@tonic-gate 		softsp->bto_ctr = 0;
783*7c478bd9Sstevel@tonic-gate 	}
784*7c478bd9Sstevel@tonic-gate 	if (softsp->bto_ctr++ >= bto_cnt)
785*7c478bd9Sstevel@tonic-gate 		return (1);
786*7c478bd9Sstevel@tonic-gate 	return (0);
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate static uint_t
790*7c478bd9Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp)
791*7c478bd9Sstevel@tonic-gate {
792*7c478bd9Sstevel@tonic-gate 	uint64_t t_sb_csr;
793*7c478bd9Sstevel@tonic-gate 	ushort_t id, inst;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	t_sb_csr = *softsp->sbus_ctrl_reg;
796*7c478bd9Sstevel@tonic-gate 	id = (ushort_t)softsp->upa_id;
797*7c478bd9Sstevel@tonic-gate 	inst = (ushort_t)ddi_get_instance(softsp->dip);
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 	if (debug_sysio_errs) {
800*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "sbus_ctrl_ecc_error: SBus%d Control Reg "
801*7c478bd9Sstevel@tonic-gate 		    "0x%016llx Id %d\n", inst, (u_longlong_t)t_sb_csr, id);
802*7c478bd9Sstevel@tonic-gate 	}
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & (SB_CSR_DPERR_S14|SB_CSR_DPERR_S13|SB_CSR_DPERR_S3|
805*7c478bd9Sstevel@tonic-gate 	    SB_CSR_DPERR_S2|SB_CSR_DPERR_S1|SB_CSR_DPERR_S0|SB_CSR_PIO_PERRS)) {
806*7c478bd9Sstevel@tonic-gate 		struct async_flt aflt;
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 		*softsp->sbus_ctrl_reg = t_sb_csr; /* clear error bits */
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 		bzero(&aflt, sizeof (aflt));
811*7c478bd9Sstevel@tonic-gate 		aflt.flt_id = gethrtime();
812*7c478bd9Sstevel@tonic-gate 		aflt.flt_stat = t_sb_csr;
813*7c478bd9Sstevel@tonic-gate 		aflt.flt_func = sbus_log_csr_error;
814*7c478bd9Sstevel@tonic-gate 		aflt.flt_bus_id = id;
815*7c478bd9Sstevel@tonic-gate 		aflt.flt_inst = inst;
816*7c478bd9Sstevel@tonic-gate 		aflt.flt_status = ECC_IOBUS;
817*7c478bd9Sstevel@tonic-gate 		aflt.flt_class = BUS_FAULT;
818*7c478bd9Sstevel@tonic-gate 		aflt.flt_panic = 1;
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 		errorq_dispatch(ue_queue, &aflt, sizeof (aflt), aflt.flt_panic);
821*7c478bd9Sstevel@tonic-gate 		return (BF_FATAL);
822*7c478bd9Sstevel@tonic-gate 	}
823*7c478bd9Sstevel@tonic-gate 
824*7c478bd9Sstevel@tonic-gate 	return (BF_NONE);
825*7c478bd9Sstevel@tonic-gate }
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
828*7c478bd9Sstevel@tonic-gate static void
829*7c478bd9Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum)
830*7c478bd9Sstevel@tonic-gate {
831*7c478bd9Sstevel@tonic-gate 	uint64_t t_sb_csr = aflt->flt_stat;
832*7c478bd9Sstevel@tonic-gate 	uint_t id = aflt->flt_bus_id;
833*7c478bd9Sstevel@tonic-gate 	uint_t inst = aflt->flt_inst;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 	/*
836*7c478bd9Sstevel@tonic-gate 	 * Print out SBus error information.
837*7c478bd9Sstevel@tonic-gate 	 */
838*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S14) {
839*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
840*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 14 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
841*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
842*7c478bd9Sstevel@tonic-gate 	}
843*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S13) {
844*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
845*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 13 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
846*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
847*7c478bd9Sstevel@tonic-gate 	}
848*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S3) {
849*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
850*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 3 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
851*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
852*7c478bd9Sstevel@tonic-gate 	}
853*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S2) {
854*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
855*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 2 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
856*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
857*7c478bd9Sstevel@tonic-gate 	}
858*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S1) {
859*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
860*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 1 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
861*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
862*7c478bd9Sstevel@tonic-gate 	}
863*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_DPERR_S0) {
864*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
865*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 0 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
866*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
867*7c478bd9Sstevel@tonic-gate 	}
868*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S15) {
869*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
870*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 15 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
871*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
872*7c478bd9Sstevel@tonic-gate 	}
873*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S14) {
874*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
875*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 14 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
876*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
877*7c478bd9Sstevel@tonic-gate 	}
878*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S13) {
879*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
880*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 13 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
881*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
882*7c478bd9Sstevel@tonic-gate 	}
883*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S3) {
884*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
885*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 3 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
886*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
887*7c478bd9Sstevel@tonic-gate 	}
888*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S2) {
889*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
890*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 2 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
891*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
892*7c478bd9Sstevel@tonic-gate 	}
893*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S1) {
894*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
895*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 1 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
896*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
897*7c478bd9Sstevel@tonic-gate 	}
898*7c478bd9Sstevel@tonic-gate 	if (t_sb_csr & SB_CSR_PPERR_S0) {
899*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
900*7c478bd9Sstevel@tonic-gate 		"SBus%d Slot 0 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
901*7c478bd9Sstevel@tonic-gate 			inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
902*7c478bd9Sstevel@tonic-gate 	}
903*7c478bd9Sstevel@tonic-gate }
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate /*
906*7c478bd9Sstevel@tonic-gate  * Sysio Thermal Warning interrupt handler
907*7c478bd9Sstevel@tonic-gate  */
908*7c478bd9Sstevel@tonic-gate static uint_t
909*7c478bd9Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp)
910*7c478bd9Sstevel@tonic-gate {
911*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *clear_reg;
912*7c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp_mondo_vec;
913*7c478bd9Sstevel@tonic-gate 	volatile uint64_t *mondo_vec_reg;
914*7c478bd9Sstevel@tonic-gate 	const char thermal_warn_msg[] =
915*7c478bd9Sstevel@tonic-gate 	    "Severe over-temperature condition detected!";
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate 	/*
918*7c478bd9Sstevel@tonic-gate 	 * Take off the Thermal Warning interrupt and
919*7c478bd9Sstevel@tonic-gate 	 * remove its interrupt handler.
920*7c478bd9Sstevel@tonic-gate 	 */
921*7c478bd9Sstevel@tonic-gate 	mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
922*7c478bd9Sstevel@tonic-gate 	tmp_mondo_vec = *mondo_vec_reg;
923*7c478bd9Sstevel@tonic-gate 	tmp_mondo_vec &= ~INTERRUPT_VALID;
924*7c478bd9Sstevel@tonic-gate 	*mondo_vec_reg = tmp_mondo_vec;
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	ddi_remove_intr(softsp->dip, 4, NULL);
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	clear_reg = (softsp->clr_intr_reg + THERMAL_CLEAR);
929*7c478bd9Sstevel@tonic-gate 	*clear_reg = 0;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	if (oven_test) {
932*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "OVEN TEST: %s", thermal_warn_msg);
933*7c478bd9Sstevel@tonic-gate 		return (DDI_INTR_CLAIMED);
934*7c478bd9Sstevel@tonic-gate 	}
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_WARN, "%s", thermal_warn_msg);
937*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_WARN, "Powering down...");
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate 	do_shutdown();
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 	/*
942*7c478bd9Sstevel@tonic-gate 	 * just in case do_shutdown() fails
943*7c478bd9Sstevel@tonic-gate 	 */
944*7c478bd9Sstevel@tonic-gate 	(void) timeout((void(*)(void *))power_down, NULL,
945*7c478bd9Sstevel@tonic-gate 	    thermal_powerdown_delay * hz);
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
948*7c478bd9Sstevel@tonic-gate }
949