xref: /onnv-gate/usr/src/uts/sun4u/io/px/px_err.c (revision 27:c1f182000c0a)
1*27Sjchu /*
2*27Sjchu  * CDDL HEADER START
3*27Sjchu  *
4*27Sjchu  * The contents of this file are subject to the terms of the
5*27Sjchu  * Common Development and Distribution License, Version 1.0 only
6*27Sjchu  * (the "License").  You may not use this file except in compliance
7*27Sjchu  * with the License.
8*27Sjchu  *
9*27Sjchu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*27Sjchu  * or http://www.opensolaris.org/os/licensing.
11*27Sjchu  * See the License for the specific language governing permissions
12*27Sjchu  * and limitations under the License.
13*27Sjchu  *
14*27Sjchu  * When distributing Covered Code, include this CDDL HEADER in each
15*27Sjchu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*27Sjchu  * If applicable, add the following below this CDDL HEADER, with the
17*27Sjchu  * fields enclosed by brackets "[]" replaced with your own identifying
18*27Sjchu  * information: Portions Copyright [yyyy] [name of copyright owner]
19*27Sjchu  *
20*27Sjchu  * CDDL HEADER END
21*27Sjchu  */
22*27Sjchu /*
23*27Sjchu  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*27Sjchu  * Use is subject to license terms.
25*27Sjchu  */
26*27Sjchu 
27*27Sjchu #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*27Sjchu 
29*27Sjchu /*
30*27Sjchu  * sun4u Fire Error Handling
31*27Sjchu  */
32*27Sjchu 
33*27Sjchu #include <sys/types.h>
34*27Sjchu #include <sys/ddi.h>
35*27Sjchu #include <sys/sunddi.h>
36*27Sjchu #include <sys/fm/protocol.h>
37*27Sjchu #include <sys/fm/util.h>
38*27Sjchu #include <sys/pcie.h>
39*27Sjchu #include <sys/pcie_impl.h>
40*27Sjchu #include "px_obj.h"
41*27Sjchu #include <px_regs.h>
42*27Sjchu #include <px_csr.h>
43*27Sjchu #include <sys/membar.h>
44*27Sjchu #include "px_lib4u.h"
45*27Sjchu #include "px_err.h"
46*27Sjchu #include "px_err_impl.h"
47*27Sjchu 
48*27Sjchu /*
49*27Sjchu  * JBC error bit table
50*27Sjchu  */
51*27Sjchu #define	JBC_BIT_DESC(bit, hdl, erpt) \
52*27Sjchu 	JBC_INTERRUPT_STATUS_ ## bit ## _P, \
53*27Sjchu 	0, \
54*27Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
55*27Sjchu 	PX_ERPT_SEND(erpt), \
56*27Sjchu 	PX_ERR_JBC_CLASS(bit)
57*27Sjchu px_err_bit_desc_t px_err_cb_tbl[] = {
58*27Sjchu 	/* JBC FATAL - see io erpt doc, section 1.1 */
59*27Sjchu 	{ JBC_BIT_DESC(MB_PEA,	fatal_hw,	jbc_fatal) },
60*27Sjchu 	{ JBC_BIT_DESC(CPE,	fatal_hw,	jbc_fatal) },
61*27Sjchu 	{ JBC_BIT_DESC(APE,	fatal_hw,	jbc_fatal) },
62*27Sjchu 	{ JBC_BIT_DESC(PIO_CPE,	fatal_hw,	jbc_fatal) },
63*27Sjchu 	{ JBC_BIT_DESC(JTCEEW,	fatal_hw,	jbc_fatal) },
64*27Sjchu 	{ JBC_BIT_DESC(JTCEEI,	fatal_hw,	jbc_fatal) },
65*27Sjchu 	{ JBC_BIT_DESC(JTCEER,	fatal_hw,	jbc_fatal) },
66*27Sjchu 
67*27Sjchu 	/* JBC MERGE - see io erpt doc, section 1.2 */
68*27Sjchu 	{ JBC_BIT_DESC(MB_PER,	jbc_merge,	jbc_merge) },
69*27Sjchu 	{ JBC_BIT_DESC(MB_PEW,	jbc_merge,	jbc_merge) },
70*27Sjchu 
71*27Sjchu 	/* JBC Jbusint IN - see io erpt doc, section 1.3 */
72*27Sjchu 	{ JBC_BIT_DESC(UE_ASYN,	fatal_gos,	jbc_in) },
73*27Sjchu 	{ JBC_BIT_DESC(CE_ASYN,	jbc_jbusint_in,	jbc_in) },
74*27Sjchu 	{ JBC_BIT_DESC(JTE,	fatal_gos,	jbc_in) },
75*27Sjchu 	{ JBC_BIT_DESC(JBE,	jbc_jbusint_in,	jbc_in) },
76*27Sjchu 	{ JBC_BIT_DESC(JUE,	jbc_jbusint_in,	jbc_in) },
77*27Sjchu 	{ JBC_BIT_DESC(ICISE,	fatal_gos,	jbc_in) },
78*27Sjchu 	{ JBC_BIT_DESC(WR_DPE,	jbc_jbusint_in,	jbc_in) },
79*27Sjchu 	{ JBC_BIT_DESC(RD_DPE,	jbc_jbusint_in,	jbc_in) },
80*27Sjchu 	{ JBC_BIT_DESC(ILL_BMW,	jbc_jbusint_in,	jbc_in) },
81*27Sjchu 	{ JBC_BIT_DESC(ILL_BMR,	jbc_jbusint_in,	jbc_in) },
82*27Sjchu 	{ JBC_BIT_DESC(BJC,	jbc_jbusint_in,	jbc_in) },
83*27Sjchu 
84*27Sjchu 	/* JBC Jbusint Out - see io erpt doc, section 1.4 */
85*27Sjchu 	{ JBC_BIT_DESC(IJP,	fatal_gos,	jbc_out) },
86*27Sjchu 
87*27Sjchu 	/* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
88*27Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP_RD,	jbc_dmcint_odcd,	jbc_odcd) },
89*27Sjchu 	{ JBC_BIT_DESC(ILL_ACC_RD,	jbc_dmcint_odcd,	jbc_odcd) },
90*27Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP,	jbc_dmcint_odcd,	jbc_odcd) },
91*27Sjchu 	{ JBC_BIT_DESC(PIO_DPE,		jbc_dmcint_odcd,	jbc_odcd) },
92*27Sjchu 	{ JBC_BIT_DESC(PIO_CPE,		non_fatal,		jbc_odcd) },
93*27Sjchu 	{ JBC_BIT_DESC(ILL_ACC,		jbc_dmcint_odcd,	jbc_odcd) },
94*27Sjchu 
95*27Sjchu 	/* JBC Dmcint IDC - see io erpt doc, section 1.6 */
96*27Sjchu 	{ JBC_BIT_DESC(UNSOL_RD,	non_fatal,	jbc_idc) },
97*27Sjchu 	{ JBC_BIT_DESC(UNSOL_INTR,	non_fatal,	jbc_idc) },
98*27Sjchu 
99*27Sjchu 	/* JBC CSR - see io erpt doc, section 1.7 */
100*27Sjchu 	{ JBC_BIT_DESC(EBUS_TO,	jbc_csr,	jbc_csr) }
101*27Sjchu };
102*27Sjchu 
103*27Sjchu #define	px_err_cb_keys \
104*27Sjchu 	(sizeof (px_err_cb_tbl)) / (sizeof (px_err_bit_desc_t))
105*27Sjchu 
106*27Sjchu /*
107*27Sjchu  * DMC error bit tables
108*27Sjchu  */
109*27Sjchu #define	IMU_BIT_DESC(bit, hdl, erpt) \
110*27Sjchu 	IMU_INTERRUPT_STATUS_ ## bit ## _P, \
111*27Sjchu 	0, \
112*27Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
113*27Sjchu 	PX_ERPT_SEND(erpt), \
114*27Sjchu 	PX_ERR_DMC_CLASS(bit)
115*27Sjchu px_err_bit_desc_t px_err_imu_tbl[] = {
116*27Sjchu 	/* DMC IMU RDS - see io erpt doc, section 2.1 */
117*27Sjchu 	{ IMU_BIT_DESC(MSI_MAL_ERR,		non_fatal,	imu_rds) },
118*27Sjchu 	{ IMU_BIT_DESC(MSI_PAR_ERR,		fatal_stuck,	imu_rds) },
119*27Sjchu 	{ IMU_BIT_DESC(PMEACK_MES_NOT_EN,	imu_rbne,	imu_rds) },
120*27Sjchu 	{ IMU_BIT_DESC(PMPME_MES_NOT_EN,	imu_rbne,	imu_rds) },
121*27Sjchu 	{ IMU_BIT_DESC(FATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
122*27Sjchu 	{ IMU_BIT_DESC(NONFATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
123*27Sjchu 	{ IMU_BIT_DESC(COR_MES_NOT_EN,		imu_rbne,	imu_rds) },
124*27Sjchu 	{ IMU_BIT_DESC(MSI_NOT_EN,		imu_rbne,	imu_rds) },
125*27Sjchu 
126*27Sjchu 	/* DMC IMU SCS - see io erpt doc, section 2.2 */
127*27Sjchu 	{ IMU_BIT_DESC(EQ_NOT_EN,		imu_rbne,	imu_rds) },
128*27Sjchu 
129*27Sjchu 	/* DMC IMU - see io erpt doc, section 2.3 */
130*27Sjchu 	{ IMU_BIT_DESC(EQ_OVER,			imu_eq_ovfl,	imu) }
131*27Sjchu };
132*27Sjchu 
133*27Sjchu #define	px_err_imu_keys (sizeof (px_err_imu_tbl)) / (sizeof (px_err_bit_desc_t))
134*27Sjchu 
135*27Sjchu /* mmu errors */
136*27Sjchu #define	MMU_BIT_DESC(bit, hdl, erpt) \
137*27Sjchu 	MMU_INTERRUPT_STATUS_ ## bit ## _P, \
138*27Sjchu 	0, \
139*27Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
140*27Sjchu 	PX_ERPT_SEND(erpt), \
141*27Sjchu 	PX_ERR_DMC_CLASS(bit)
142*27Sjchu px_err_bit_desc_t px_err_mmu_tbl[] = {
143*27Sjchu 	/* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
144*27Sjchu 	{ MMU_BIT_DESC(BYP_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
145*27Sjchu 	{ MMU_BIT_DESC(BYP_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
146*27Sjchu 	{ MMU_BIT_DESC(TRN_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
147*27Sjchu 	{ MMU_BIT_DESC(TRN_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
148*27Sjchu 	{ MMU_BIT_DESC(TTE_INV,		mmu_tfa,	mmu_tfar_tfsr) },
149*27Sjchu 	{ MMU_BIT_DESC(TTE_PRT,		mmu_tfa,	mmu_tfar_tfsr) },
150*27Sjchu 	{ MMU_BIT_DESC(TTC_DPE,		mmu_tfa,	mmu_tfar_tfsr) },
151*27Sjchu 	{ MMU_BIT_DESC(TBW_DME,		mmu_tblwlk,	mmu_tfar_tfsr) },
152*27Sjchu 	{ MMU_BIT_DESC(TBW_UDE,		mmu_tblwlk,	mmu_tfar_tfsr) },
153*27Sjchu 	{ MMU_BIT_DESC(TBW_ERR,		mmu_tblwlk,	mmu_tfar_tfsr) },
154*27Sjchu 	{ MMU_BIT_DESC(TBW_DPE,		mmu_tblwlk,	mmu_tfar_tfsr) },
155*27Sjchu 
156*27Sjchu 	/* DMC MMU - see io erpt doc, section 2.5 */
157*27Sjchu 	{ MMU_BIT_DESC(TTC_CAE,		non_fatal,	mmu) }
158*27Sjchu };
159*27Sjchu #define	px_err_mmu_keys (sizeof (px_err_mmu_tbl)) / (sizeof (px_err_bit_desc_t))
160*27Sjchu 
161*27Sjchu /*
162*27Sjchu  * PEC error bit tables
163*27Sjchu  */
164*27Sjchu #define	ILU_BIT_DESC(bit, hdl, erpt) \
165*27Sjchu 	ILU_INTERRUPT_STATUS_ ## bit ## _P, \
166*27Sjchu 	0, \
167*27Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
168*27Sjchu 	PX_ERPT_SEND(erpt), \
169*27Sjchu 	PX_ERR_PEC_CLASS(bit)
170*27Sjchu px_err_bit_desc_t px_err_ilu_tbl[] = {
171*27Sjchu 	/* PEC ILU none - see io erpt doc, section 3.1 */
172*27Sjchu 	{ ILU_BIT_DESC(IHB_PE,		fatal_gos,	pec_ilu) }
173*27Sjchu };
174*27Sjchu #define	px_err_ilu_keys \
175*27Sjchu 	(sizeof (px_err_ilu_tbl)) / (sizeof (px_err_bit_desc_t))
176*27Sjchu 
177*27Sjchu /*
178*27Sjchu  * PEC UE errors implementation is incomplete pending PCIE generic
179*27Sjchu  * fabric rules.
180*27Sjchu  */
181*27Sjchu /* pec ue errors */
182*27Sjchu #define	TLU_UC_BIT_DESC(bit, hdl, erpt) \
183*27Sjchu 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
184*27Sjchu 	0, \
185*27Sjchu 	NULL, \
186*27Sjchu 	NULL, \
187*27Sjchu 	""
188*27Sjchu px_err_bit_desc_t px_err_tlu_ue_tbl[] = {
189*27Sjchu 	/* PCI-E Receive Uncorrectable Errors - see io erpt doc, section 3.2 */
190*27Sjchu 	{ TLU_UC_BIT_DESC(UR,		NULL,		NULL) },
191*27Sjchu 	{ TLU_UC_BIT_DESC(ROF,		NULL,		NULL) },
192*27Sjchu 	{ TLU_UC_BIT_DESC(UC,		NULL,		NULL) },
193*27Sjchu 
194*27Sjchu 	/* PCI-E Transmit Uncorrectable Errors - see io erpt doc, section 3.3 */
195*27Sjchu 	{ TLU_UC_BIT_DESC(CTO,		NULL,		NULL) },
196*27Sjchu 
197*27Sjchu 	/* PCI-E Rx/Tx Uncorrectable Errors - see io erpt doc, section 3.4 */
198*27Sjchu 	{ TLU_UC_BIT_DESC(MFP,		NULL,		NULL) },
199*27Sjchu 	{ TLU_UC_BIT_DESC(PP,		NULL,		NULL) },
200*27Sjchu 
201*27Sjchu 	/* Other PCI-E Uncorrectable Errors - see io erpt doc, section 3.5 */
202*27Sjchu 	{ TLU_UC_BIT_DESC(FCP,		NULL,		NULL) },
203*27Sjchu 	{ TLU_UC_BIT_DESC(DLP,		NULL,		NULL) },
204*27Sjchu 	{ TLU_UC_BIT_DESC(TE,		NULL,		NULL) },
205*27Sjchu 	{ TLU_UC_BIT_DESC(CA,		NULL,		NULL) }
206*27Sjchu };
207*27Sjchu #define	px_err_tlu_ue_keys \
208*27Sjchu 	(sizeof (px_err_tlu_ue_tbl)) / (sizeof (px_err_bit_desc_t))
209*27Sjchu 
210*27Sjchu /*
211*27Sjchu  * PEC CE errors implementation is incomplete pending PCIE generic
212*27Sjchu  * fabric rules.
213*27Sjchu  */
214*27Sjchu /* pec ce errors */
215*27Sjchu #define	TLU_CE_BIT_DESC(bit, hdl, erpt) \
216*27Sjchu 	TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
217*27Sjchu 	0, \
218*27Sjchu 	NULL, \
219*27Sjchu 	NULL, \
220*27Sjchu 	""
221*27Sjchu px_err_bit_desc_t px_err_tlu_ce_tbl[] = {
222*27Sjchu 	/* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
223*27Sjchu 	{ TLU_CE_BIT_DESC(RTO,		NULL,		NULL) },
224*27Sjchu 	{ TLU_CE_BIT_DESC(RNR,		NULL,		NULL) },
225*27Sjchu 	{ TLU_CE_BIT_DESC(BDP,		NULL,		NULL) },
226*27Sjchu 	{ TLU_CE_BIT_DESC(BTP,		NULL,		NULL) },
227*27Sjchu 	{ TLU_CE_BIT_DESC(RE,		NULL,		NULL) }
228*27Sjchu };
229*27Sjchu #define	px_err_tlu_ce_keys \
230*27Sjchu 	(sizeof (px_err_tlu_ce_tbl)) / (sizeof (px_err_bit_desc_t))
231*27Sjchu 
232*27Sjchu /* pec oe errors */
233*27Sjchu #define	TLU_OE_BIT_DESC(bit, hdl, erpt) \
234*27Sjchu 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
235*27Sjchu 	0, \
236*27Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
237*27Sjchu 	PX_ERPT_SEND(erpt), \
238*27Sjchu 	PX_ERR_PEC_CLASS(bit)
239*27Sjchu px_err_bit_desc_t px_err_tlu_oe_tbl[] = {
240*27Sjchu 	/*
241*27Sjchu 	 * TLU Other Event Status (receive only) - see io erpt doc, section 3.7
242*27Sjchu 	 */
243*27Sjchu 	{ TLU_OE_BIT_DESC(MRC,		fatal_hw,	pciex_rx_oe) },
244*27Sjchu 
245*27Sjchu 	/* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
246*27Sjchu 	{ TLU_OE_BIT_DESC(WUC,		fatal_stuck,	pciex_rx_tx_oe) },
247*27Sjchu 	{ TLU_OE_BIT_DESC(RUC,		fatal_stuck,	pciex_rx_tx_oe) },
248*27Sjchu 	{ TLU_OE_BIT_DESC(CRS,		non_fatal,	pciex_rx_tx_oe) },
249*27Sjchu 
250*27Sjchu 	/* TLU Other Event - see io erpt doc, section 3.9 */
251*27Sjchu 	{ TLU_OE_BIT_DESC(IIP,		fatal_gos,	pciex_oe) },
252*27Sjchu 	{ TLU_OE_BIT_DESC(EDP,		fatal_gos,	pciex_oe) },
253*27Sjchu 	{ TLU_OE_BIT_DESC(EHP,		fatal_gos,	pciex_oe) },
254*27Sjchu 	{ TLU_OE_BIT_DESC(LIN,		non_fatal,	pciex_oe) },
255*27Sjchu 	{ TLU_OE_BIT_DESC(LRS,		non_fatal,	pciex_oe) },
256*27Sjchu 	{ TLU_OE_BIT_DESC(LDN,		non_fatal,	pciex_oe) },
257*27Sjchu 	{ TLU_OE_BIT_DESC(LUP,		non_fatal,	pciex_oe) },
258*27Sjchu 	{ TLU_OE_BIT_DESC(ERU,		fatal_gos,	pciex_oe) },
259*27Sjchu 	{ TLU_OE_BIT_DESC(ERO,		fatal_gos,	pciex_oe) },
260*27Sjchu 	{ TLU_OE_BIT_DESC(EMP,		fatal_gos,	pciex_oe) },
261*27Sjchu 	{ TLU_OE_BIT_DESC(EPE,		fatal_gos,	pciex_oe) },
262*27Sjchu 	{ TLU_OE_BIT_DESC(ERP,		fatal_gos,	pciex_oe) },
263*27Sjchu 	{ TLU_OE_BIT_DESC(EIP,		fatal_gos,	pciex_oe) }
264*27Sjchu };
265*27Sjchu 
266*27Sjchu #define	px_err_tlu_oe_keys \
267*27Sjchu 	(sizeof (px_err_tlu_oe_tbl)) / (sizeof (px_err_bit_desc_t))
268*27Sjchu 
269*27Sjchu /*
270*27Sjchu  * All the following tables below are for LPU Interrupts.  These interrupts
271*27Sjchu  * are *NOT* error interrupts, but event status interrupts.
272*27Sjchu  *
273*27Sjchu  * These events are probably of most interest to:
274*27Sjchu  * o Hotplug
275*27Sjchu  * o Power Management
276*27Sjchu  * o etc...
277*27Sjchu  *
278*27Sjchu  * There are also a few events that would be interresting for FMA.
279*27Sjchu  * Again none of the regiseters below state that an error has occured
280*27Sjchu  * or that data has been lost.  If anything, they give status that an
281*27Sjchu  * error is *about* to occur.  examples
282*27Sjchu  * o INT_SKP_ERR - indicates clock between fire and child is too far
283*27Sjchu  *		   off and is most unlikely able to compensate
284*27Sjchu  * o INT_TX_PAR_ERR - A parity error occured in ONE lane.  This is
285*27Sjchu  *		      HW recoverable, but will like end up as a future
286*27Sjchu  *		      fabric error as well.
287*27Sjchu  *
288*27Sjchu  * For now, we don't care about any of these errors and should be ignore,
289*27Sjchu  * but cleared.
290*27Sjchu  */
291*27Sjchu 
292*27Sjchu /* LPU Link Interrupt Table */
293*27Sjchu #define	LPUL_BIT_DESC(bit, hdl, erpt) \
294*27Sjchu 	LPU_LINK_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
295*27Sjchu 	0, \
296*27Sjchu 	NULL, \
297*27Sjchu 	NULL, \
298*27Sjchu 	""
299*27Sjchu px_err_bit_desc_t px_err_lpul_tbl[] = {
300*27Sjchu 	{ LPUL_BIT_DESC(LINK_ERR_ACT,	NULL,		NULL) }
301*27Sjchu };
302*27Sjchu #define	px_err_lpul_keys \
303*27Sjchu 	(sizeof (px_err_lpul_tbl)) / (sizeof (px_err_bit_desc_t))
304*27Sjchu 
305*27Sjchu /* LPU Physical Interrupt Table */
306*27Sjchu #define	LPUP_BIT_DESC(bit, hdl, erpt) \
307*27Sjchu 	LPU_PHY_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
308*27Sjchu 	0, \
309*27Sjchu 	NULL, \
310*27Sjchu 	NULL, \
311*27Sjchu 	""
312*27Sjchu px_err_bit_desc_t px_err_lpup_tbl[] = {
313*27Sjchu 	{ LPUP_BIT_DESC(PHY_LAYER_ERR,	NULL,		NULL) }
314*27Sjchu };
315*27Sjchu #define	px_err_lpup_keys \
316*27Sjchu 	(sizeof (px_err_lpup_tbl)) / (sizeof (px_err_bit_desc_t))
317*27Sjchu 
318*27Sjchu /* LPU Receive Interrupt Table */
319*27Sjchu #define	LPUR_BIT_DESC(bit, hdl, erpt) \
320*27Sjchu 	LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
321*27Sjchu 	0, \
322*27Sjchu 	NULL, \
323*27Sjchu 	NULL, \
324*27Sjchu 	""
325*27Sjchu px_err_bit_desc_t px_err_lpur_tbl[] = {
326*27Sjchu 	{ LPUR_BIT_DESC(RCV_PHY,	NULL,		NULL) }
327*27Sjchu };
328*27Sjchu #define	px_err_lpur_keys \
329*27Sjchu 	(sizeof (px_err_lpur_tbl)) / (sizeof (px_err_bit_desc_t))
330*27Sjchu 
331*27Sjchu /* LPU Transmit Interrupt Table */
332*27Sjchu #define	LPUX_BIT_DESC(bit, hdl, erpt) \
333*27Sjchu 	LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
334*27Sjchu 	0, \
335*27Sjchu 	NULL, \
336*27Sjchu 	NULL, \
337*27Sjchu 	""
338*27Sjchu px_err_bit_desc_t px_err_lpux_tbl[] = {
339*27Sjchu 	{ LPUX_BIT_DESC(UNMSK,		NULL,		NULL) }
340*27Sjchu };
341*27Sjchu #define	px_err_lpux_keys \
342*27Sjchu 	(sizeof (px_err_lpux_tbl)) / (sizeof (px_err_bit_desc_t))
343*27Sjchu 
344*27Sjchu /* LPU LTSSM Interrupt Table */
345*27Sjchu #define	LPUS_BIT_DESC(bit, hdl, erpt) \
346*27Sjchu 	LPU_LTSSM_INTERRUPT_AND_STATUS_INT_ ## bit, \
347*27Sjchu 	0, \
348*27Sjchu 	NULL, \
349*27Sjchu 	NULL, \
350*27Sjchu 	""
351*27Sjchu px_err_bit_desc_t px_err_lpus_tbl[] = {
352*27Sjchu 	{ LPUS_BIT_DESC(ANY,		NULL,		NULL) }
353*27Sjchu };
354*27Sjchu #define	px_err_lpus_keys \
355*27Sjchu 	(sizeof (px_err_lpus_tbl)) / (sizeof (px_err_bit_desc_t))
356*27Sjchu 
357*27Sjchu /* LPU Gigablaze Glue Interrupt Table */
358*27Sjchu #define	LPUG_BIT_DESC(bit, hdl, erpt) \
359*27Sjchu 	LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_INT_ ## bit, \
360*27Sjchu 	0, \
361*27Sjchu 	NULL, \
362*27Sjchu 	NULL, \
363*27Sjchu 	""
364*27Sjchu px_err_bit_desc_t px_err_lpug_tbl[] = {
365*27Sjchu 	{ LPUG_BIT_DESC(GLOBL_UNMSK,	NULL,		NULL) }
366*27Sjchu };
367*27Sjchu #define	px_err_lpug_keys \
368*27Sjchu 	(sizeof (px_err_lpug_tbl)) / (sizeof (px_err_bit_desc_t))
369*27Sjchu 
370*27Sjchu 
371*27Sjchu /* Mask and Tables */
372*27Sjchu #define	MnT6(pre) \
373*27Sjchu 	B_FALSE, \
374*27Sjchu 	&px_ ## pre ## _intr_mask, \
375*27Sjchu 	&px_ ## pre ## _log_mask, \
376*27Sjchu 	&px_ ## pre ## _count_mask, \
377*27Sjchu 	px_err_ ## pre ## _tbl, \
378*27Sjchu 	px_err_ ## pre ## _keys, \
379*27Sjchu 	0
380*27Sjchu 
381*27Sjchu /* LPU Registers Addresses */
382*27Sjchu #define	LR4(pre) \
383*27Sjchu 	NULL, \
384*27Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
385*27Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS, \
386*27Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS
387*27Sjchu 
388*27Sjchu /* LPU Registers Addresses with Irregularities */
389*27Sjchu #define	LR4_FIXME(pre) \
390*27Sjchu 	NULL, \
391*27Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
392*27Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS, \
393*27Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS
394*27Sjchu 
395*27Sjchu /* TLU Registers Addresses */
396*27Sjchu #define	TR4(pre) \
397*27Sjchu 	TLU_ ## pre ## _LOG_ENABLE, \
398*27Sjchu 	TLU_ ## pre ## _INTERRUPT_ENABLE, \
399*27Sjchu 	TLU_ ## pre ## _INTERRUPT_STATUS, \
400*27Sjchu 	TLU_ ## pre ## _STATUS_CLEAR
401*27Sjchu 
402*27Sjchu /* Registers Addresses for JBC, MMU, IMU and ILU */
403*27Sjchu #define	R4(pre) \
404*27Sjchu 	pre ## _ERROR_LOG_ENABLE, \
405*27Sjchu 	pre ## _INTERRUPT_ENABLE, \
406*27Sjchu 	pre ## _INTERRUPT_STATUS, \
407*27Sjchu 	pre ## _ERROR_STATUS_CLEAR
408*27Sjchu 
409*27Sjchu /*
410*27Sjchu  * Register error handling tables.
411*27Sjchu  * The ID Field (first field) is identified by an enum px_err_id_t.
412*27Sjchu  * It is located in px_err.h
413*27Sjchu  */
414*27Sjchu px_err_reg_desc_t px_err_reg_tbl[] = {
415*27Sjchu 	{ MnT6(cb),	R4(JBC),		  "JBC Error"},
416*27Sjchu 	{ MnT6(mmu),	R4(MMU),		  "IMU Error"},
417*27Sjchu 	{ MnT6(imu),	R4(IMU),		  "ILU Error"},
418*27Sjchu 	{ MnT6(tlu_ue),	TR4(UNCORRECTABLE_ERROR), "TLU UE"},
419*27Sjchu 	{ MnT6(tlu_ce), TR4(CORRECTABLE_ERROR),	  "TLU CE"},
420*27Sjchu 	{ MnT6(tlu_oe), TR4(OTHER_EVENT),	  "TLU OE"},
421*27Sjchu 	{ MnT6(ilu),	R4(ILU),		  "MMU Error"},
422*27Sjchu 	{ MnT6(lpul),	LR4(LINK_LAYER),	  "LPU Link Layer"},
423*27Sjchu 	{ MnT6(lpup),	LR4_FIXME(PHY),		  "LPU Phy Layer"},
424*27Sjchu 	{ MnT6(lpur),	LR4(RECEIVE_PHY),	  "LPU RX Phy Layer"},
425*27Sjchu 	{ MnT6(lpux),	LR4(TRANSMIT_PHY),	  "LPU TX Phy Layer"},
426*27Sjchu 	{ MnT6(lpus),	LR4(LTSSM),		  "LPU LTSSM"},
427*27Sjchu 	{ MnT6(lpug),	LR4(GIGABLAZE_GLUE),	  "LPU GigaBlaze Glue"}
428*27Sjchu };
429*27Sjchu #define	PX_ERR_REG_KEYS (sizeof (px_err_reg_tbl)) / (sizeof (px_err_reg_tbl[0]))
430*27Sjchu 
431*27Sjchu typedef struct px_err_ss {
432*27Sjchu 	uint64_t err_status[PX_ERR_REG_KEYS];
433*27Sjchu } px_err_ss_t;
434*27Sjchu 
435*27Sjchu static void px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chkjbc);
436*27Sjchu static int  px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr,
437*27Sjchu     px_err_ss_t *ss);
438*27Sjchu static int  px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr,
439*27Sjchu     int err, int caller);
440*27Sjchu 
441*27Sjchu /*
442*27Sjchu  * px_err_cb_intr:
443*27Sjchu  * Interrupt handler for the JBC block.
444*27Sjchu  * o lock
445*27Sjchu  * o create derr
446*27Sjchu  * o px_err_handle(leaf1, with jbc)
447*27Sjchu  * o px_err_handle(leaf2, without jbc)
448*27Sjchu  * o dispatch (leaf1)
449*27Sjchu  * o dispatch (leaf2)
450*27Sjchu  * o unlock
451*27Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
452*27Sjchu  */
453*27Sjchu uint_t
454*27Sjchu px_err_cb_intr(caddr_t arg)
455*27Sjchu {
456*27Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
457*27Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
458*27Sjchu 	dev_info_t	*leafdip;
459*27Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
460*27Sjchu 	px_cb_t		*cb_p = px_p->px_cb_p;
461*27Sjchu 	int		err = PX_OK, ret;
462*27Sjchu 	int		fatal = 0;
463*27Sjchu 	int		nonfatal = 0;
464*27Sjchu 	int		unknown = 0;
465*27Sjchu 	int		i;
466*27Sjchu 	boolean_t	chkjbc = B_TRUE;
467*27Sjchu 	ddi_fm_error_t	derr;
468*27Sjchu 
469*27Sjchu 	/* Create the derr */
470*27Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
471*27Sjchu 	derr.fme_version = DDI_FME_VERSION;
472*27Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
473*27Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
474*27Sjchu 
475*27Sjchu 	mutex_enter(&cb_p->xbc_fm_mutex);
476*27Sjchu 
477*27Sjchu 	/* send ereport/handle/clear for ALL fire leaves */
478*27Sjchu 	for (i = 0; i < PX_CB_MAX_LEAF; i++) {
479*27Sjchu 		if ((px_p = cb_p->xbc_px_list[i]) == NULL)
480*27Sjchu 			continue;
481*27Sjchu 
482*27Sjchu 		err |= px_err_handle(px_p, &derr, PX_INTR_CALL, chkjbc);
483*27Sjchu 		chkjbc = B_FALSE;
484*27Sjchu 	}
485*27Sjchu 
486*27Sjchu 	/* Check all child devices for errors on ALL fire leaves */
487*27Sjchu 	for (i = 0; i < PX_CB_MAX_LEAF; i++) {
488*27Sjchu 		if ((px_p = cb_p->xbc_px_list[i]) != NULL) {
489*27Sjchu 			leafdip = px_p->px_dip;
490*27Sjchu 			ret = ndi_fm_handler_dispatch(leafdip, NULL, &derr);
491*27Sjchu 			switch (ret) {
492*27Sjchu 			case DDI_FM_FATAL:
493*27Sjchu 				fatal++;
494*27Sjchu 				break;
495*27Sjchu 			case DDI_FM_NONFATAL:
496*27Sjchu 				nonfatal++;
497*27Sjchu 				break;
498*27Sjchu 			case DDI_FM_UNKNOWN:
499*27Sjchu 				unknown++;
500*27Sjchu 				break;
501*27Sjchu 			default:
502*27Sjchu 				break;
503*27Sjchu 			}
504*27Sjchu 		}
505*27Sjchu 	}
506*27Sjchu 
507*27Sjchu 	/* Set the intr state to idle for the leaf that received the mondo */
508*27Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
509*27Sjchu 	    INTR_IDLE_STATE);
510*27Sjchu 
511*27Sjchu 	mutex_exit(&cb_p->xbc_fm_mutex);
512*27Sjchu 
513*27Sjchu 	/*
514*27Sjchu 	 * PX_FATAL_HW error is diagnosed after system recovered from
515*27Sjchu 	 * HW initiated reset, therefore no furthur handling is required.
516*27Sjchu 	 */
517*27Sjchu 	if (fatal || err & (PX_FATAL_GOS | PX_FATAL_SW))
518*27Sjchu 		fm_panic("Fatal System Bus Error has occurred\n");
519*27Sjchu 
520*27Sjchu 	return (DDI_INTR_CLAIMED);
521*27Sjchu }
522*27Sjchu 
523*27Sjchu /*
524*27Sjchu  * px_err_dmc_pec_intr:
525*27Sjchu  * Interrupt handler for the DMC/PEC block.
526*27Sjchu  * o lock
527*27Sjchu  * o create derr
528*27Sjchu  * o px_err_handle(leaf, with jbc)
529*27Sjchu  * o dispatch (leaf)
530*27Sjchu  * o unlock
531*27Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
532*27Sjchu  */
533*27Sjchu uint_t
534*27Sjchu px_err_dmc_pec_intr(caddr_t arg)
535*27Sjchu {
536*27Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
537*27Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
538*27Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
539*27Sjchu 	px_cb_t		*cb_p = px_p->px_cb_p;
540*27Sjchu 	int		err = PX_OK, ret;
541*27Sjchu 	ddi_fm_error_t	derr;
542*27Sjchu 
543*27Sjchu 	/* Create the derr */
544*27Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
545*27Sjchu 	derr.fme_version = DDI_FME_VERSION;
546*27Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
547*27Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
548*27Sjchu 
549*27Sjchu 	mutex_enter(&cb_p->xbc_fm_mutex);
550*27Sjchu 
551*27Sjchu 	/* send ereport/handle/clear fire registers */
552*27Sjchu 	err |= px_err_handle(px_p, &derr, PX_INTR_CALL, B_TRUE);
553*27Sjchu 
554*27Sjchu 	/* Check all child devices for errors */
555*27Sjchu 	ret = ndi_fm_handler_dispatch(rpdip, NULL, &derr);
556*27Sjchu 
557*27Sjchu 	/* Set the interrupt state to idle */
558*27Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
559*27Sjchu 	    INTR_IDLE_STATE);
560*27Sjchu 
561*27Sjchu 	mutex_exit(&cb_p->xbc_fm_mutex);
562*27Sjchu 
563*27Sjchu 	/*
564*27Sjchu 	 * PX_FATAL_HW indicates a condition recovered from Fatal-Reset,
565*27Sjchu 	 * therefore it does not cause panic.
566*27Sjchu 	 */
567*27Sjchu 	if ((err & (PX_FATAL_GOS | PX_FATAL_SW)) || (ret == DDI_FM_FATAL))
568*27Sjchu 		fm_panic("Fatal System Port Error has occurred\n");
569*27Sjchu 
570*27Sjchu 	return (DDI_INTR_CLAIMED);
571*27Sjchu }
572*27Sjchu 
573*27Sjchu /*
574*27Sjchu  * Error register are being handled by px_hlib xxx_init functions.
575*27Sjchu  * They are also called again by px_err_add_intr for mondo62 and 63
576*27Sjchu  * from px_cb_attach and px_attach
577*27Sjchu  */
578*27Sjchu void
579*27Sjchu px_err_reg_enable(px_t *px_p, px_err_id_t id)
580*27Sjchu {
581*27Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
582*27Sjchu 	uint64_t 		intr_mask = *reg_desc->intr_mask_p;
583*27Sjchu 	uint64_t 		log_mask = *reg_desc->log_mask_p;
584*27Sjchu 	caddr_t			csr_base;
585*27Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
586*27Sjchu 
587*27Sjchu 	if (id == PX_ERR_JBC)
588*27Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
589*27Sjchu 	else
590*27Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
591*27Sjchu 
592*27Sjchu 	reg_desc->enabled = B_TRUE;
593*27Sjchu 
594*27Sjchu 	/* Enable logs if it exists */
595*27Sjchu 	if (reg_desc->log_addr != NULL)
596*27Sjchu 		CSR_XS(csr_base, reg_desc->log_addr, log_mask);
597*27Sjchu 
598*27Sjchu 	/*
599*27Sjchu 	 * For readability you in code you set 1 to enable an interrupt.
600*27Sjchu 	 * But in Fire it's backwards.  You set 1 to *disable* an intr.
601*27Sjchu 	 * Reverse the user tunable intr mask field.
602*27Sjchu 	 *
603*27Sjchu 	 * Disable All Errors
604*27Sjchu 	 * Clear All Errors
605*27Sjchu 	 * Enable Errors
606*27Sjchu 	 */
607*27Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, 0);
608*27Sjchu 	CSR_XS(csr_base, reg_desc->clear_addr, -1);
609*27Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, intr_mask);
610*27Sjchu 	DBG(DBG_ATTACH, NULL, "%s Mask: 0x%llx\n",
611*27Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->enable_addr));
612*27Sjchu 	DBG(DBG_ATTACH, NULL, "%s Status: 0x%llx\n",
613*27Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->status_addr));
614*27Sjchu 	DBG(DBG_ATTACH, NULL, "%s Clear: 0x%llx\n",
615*27Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->clear_addr));
616*27Sjchu 	if (reg_desc->log_addr != NULL) {
617*27Sjchu 		DBG(DBG_ATTACH, NULL, "%s Log: 0x%llx\n",
618*27Sjchu 		    reg_desc->msg, CSR_XR(csr_base, reg_desc->log_addr));
619*27Sjchu 	}
620*27Sjchu }
621*27Sjchu 
622*27Sjchu void
623*27Sjchu px_err_reg_disable(px_t *px_p, px_err_id_t id)
624*27Sjchu {
625*27Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
626*27Sjchu 	caddr_t			csr_base;
627*27Sjchu 
628*27Sjchu 	if (id == PX_ERR_JBC)
629*27Sjchu 		csr_base = (caddr_t)px_p->px_inos[PX_INTR_XBC];
630*27Sjchu 	else
631*27Sjchu 		csr_base = (caddr_t)px_p->px_inos[PX_INTR_PEC];
632*27Sjchu 
633*27Sjchu 	reg_desc->enabled = B_FALSE;
634*27Sjchu 
635*27Sjchu 	switch (id) {
636*27Sjchu 	case PX_ERR_JBC:
637*27Sjchu 	case PX_ERR_MMU:
638*27Sjchu 	case PX_ERR_IMU:
639*27Sjchu 	case PX_ERR_TLU_UE:
640*27Sjchu 	case PX_ERR_TLU_CE:
641*27Sjchu 	case PX_ERR_TLU_OE:
642*27Sjchu 	case PX_ERR_ILU:
643*27Sjchu 		if (reg_desc->log_addr != NULL) {
644*27Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, 0);
645*27Sjchu 		}
646*27Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, 0);
647*27Sjchu 		break;
648*27Sjchu 	case PX_ERR_LPU_LINK:
649*27Sjchu 	case PX_ERR_LPU_PHY:
650*27Sjchu 	case PX_ERR_LPU_RX:
651*27Sjchu 	case PX_ERR_LPU_TX:
652*27Sjchu 	case PX_ERR_LPU_LTSSM:
653*27Sjchu 	case PX_ERR_LPU_GIGABLZ:
654*27Sjchu 		if (reg_desc->log_addr != NULL) {
655*27Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, -1);
656*27Sjchu 		}
657*27Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, -1);
658*27Sjchu 		break;
659*27Sjchu 	}
660*27Sjchu }
661*27Sjchu 
662*27Sjchu /*
663*27Sjchu  * px_err_handle:
664*27Sjchu  * Common function called by trap, mondo and fabric intr.
665*27Sjchu  * o Snap shot current fire registers
666*27Sjchu  * o check for safe access
667*27Sjchu  * o send ereport and clear snap shot registers
668*27Sjchu  * o check severity of snap shot registers
669*27Sjchu  *
670*27Sjchu  * @param px_p		leaf in which to check access
671*27Sjchu  * @param derr		fm err data structure to be updated
672*27Sjchu  * @param caller	PX_TRAP_CALL | PX_INTR_CALL
673*27Sjchu  * @param chkjbc	whether to handle jbc registers
674*27Sjchu  * @return err		PX_OK | PX_NONFATAL |
675*27Sjchu  *                      PX_FATAL_GOS | PX_FATAL_HW | PX_STUCK_FATAL
676*27Sjchu  */
677*27Sjchu int
678*27Sjchu px_err_handle(px_t *px_p, ddi_fm_error_t *derr, int caller,
679*27Sjchu     boolean_t chkjbc)
680*27Sjchu {
681*27Sjchu 	px_cb_t			*cb_p = px_p->px_cb_p; /* for fm_mutex */
682*27Sjchu 	px_err_ss_t		ss;
683*27Sjchu 	int			err;
684*27Sjchu 
685*27Sjchu 	ASSERT(MUTEX_HELD(&cb_p->xbc_fm_mutex));
686*27Sjchu 
687*27Sjchu 	/* snap shot the current fire registers */
688*27Sjchu 	px_err_snapshot(px_p, &ss, chkjbc);
689*27Sjchu 
690*27Sjchu 	/* check for safe access */
691*27Sjchu 	px_err_safeacc_check(px_p, derr);
692*27Sjchu 
693*27Sjchu 	/* send ereports/handle/clear registers */
694*27Sjchu 	err = px_err_erpt_and_clr(px_p, derr, &ss);
695*27Sjchu 
696*27Sjchu 	/* check for error severity */
697*27Sjchu 	err = px_err_check_severity(px_p, derr, err, caller);
698*27Sjchu 
699*27Sjchu 	/* Mark the On Trap Handle if an error occured */
700*27Sjchu 	if (err != PX_OK) {
701*27Sjchu 		px_pec_t	*pec_p = px_p->px_pec_p;
702*27Sjchu 		on_trap_data_t	*otd = pec_p->pec_ontrap_data;
703*27Sjchu 
704*27Sjchu 		if ((otd != NULL) && (otd->ot_prot & OT_DATA_ACCESS)) {
705*27Sjchu 			otd->ot_trap |= OT_DATA_ACCESS;
706*27Sjchu 		}
707*27Sjchu 	}
708*27Sjchu 
709*27Sjchu 	return (err);
710*27Sjchu }
711*27Sjchu 
712*27Sjchu /*
713*27Sjchu  * Static function
714*27Sjchu  */
715*27Sjchu 
716*27Sjchu /*
717*27Sjchu  * px_err_snapshot:
718*27Sjchu  * Take a current snap shot of all the fire error registers.  This includes
719*27Sjchu  * JBC, DMC, and PEC, unless chkjbc == false;
720*27Sjchu  *
721*27Sjchu  * @param px_p		leaf in which to take the snap shot.
722*27Sjchu  * @param ss		pre-allocated memory to store the snap shot.
723*27Sjchu  * @param chkjbc	boolean on whether to store jbc register.
724*27Sjchu  */
725*27Sjchu static void
726*27Sjchu px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chkjbc)
727*27Sjchu {
728*27Sjchu 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
729*27Sjchu 	caddr_t	xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
730*27Sjchu 	caddr_t	pec_csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
731*27Sjchu 	px_err_reg_desc_t *reg_desc;
732*27Sjchu 	int reg_id;
733*27Sjchu 
734*27Sjchu 	/* snapshot JBC interrupt status */
735*27Sjchu 	reg_id = PX_ERR_JBC;
736*27Sjchu 	if (chkjbc == B_TRUE) {
737*27Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
738*27Sjchu 		ss->err_status[reg_id] = CSR_XR(xbc_csr_base,
739*27Sjchu 		    reg_desc->status_addr);
740*27Sjchu 	} else {
741*27Sjchu 		ss->err_status[reg_id] = 0;
742*27Sjchu 	}
743*27Sjchu 
744*27Sjchu 	/* snapshot DMC/PEC interrupt status */
745*27Sjchu 	for (reg_id = 1; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
746*27Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
747*27Sjchu 		ss->err_status[reg_id] = CSR_XR(pec_csr_base,
748*27Sjchu 		    reg_desc->status_addr);
749*27Sjchu 	}
750*27Sjchu }
751*27Sjchu 
752*27Sjchu /*
753*27Sjchu  * px_err_erpt_and_clr:
754*27Sjchu  * This function does the following thing to all the fire registers based
755*27Sjchu  * on an earlier snap shot.
756*27Sjchu  * o Send ereport
757*27Sjchu  * o Handle the error
758*27Sjchu  * o Clear the error
759*27Sjchu  *
760*27Sjchu  * @param px_p		leaf in which to take the snap shot.
761*27Sjchu  * @param derr		fm err in which the ereport is to be based on
762*27Sjchu  * @param ss		pre-allocated memory to store the snap shot.
763*27Sjchu  */
764*27Sjchu static int
765*27Sjchu px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr, px_err_ss_t *ss)
766*27Sjchu {
767*27Sjchu 	dev_info_t		*rpdip = px_p->px_dip;
768*27Sjchu 	px_cb_t			*cb_p = px_p->px_cb_p; /* for fm_mutex */
769*27Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
770*27Sjchu 	caddr_t			csr_base;
771*27Sjchu 	px_err_reg_desc_t	*err_reg_tbl;
772*27Sjchu 	px_err_bit_desc_t	*err_bit_tbl;
773*27Sjchu 	px_err_bit_desc_t	*err_bit_desc;
774*27Sjchu 
775*27Sjchu 	uint64_t		*log_mask, *count_mask;
776*27Sjchu 	uint64_t		status_addr, clear_addr;
777*27Sjchu 	uint64_t		ss_reg;
778*27Sjchu 
779*27Sjchu 	int			(*err_handler)();
780*27Sjchu 	int			(*erpt_handler)();
781*27Sjchu 	int			reg_id, key;
782*27Sjchu 	int			err = PX_OK;
783*27Sjchu 
784*27Sjchu 	ASSERT(MUTEX_HELD(&cb_p->xbc_fm_mutex));
785*27Sjchu 
786*27Sjchu 	/* send erport/handle/clear JBC errors */
787*27Sjchu 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
788*27Sjchu 		/* Get the correct register description table */
789*27Sjchu 		err_reg_tbl = &px_err_reg_tbl[reg_id];
790*27Sjchu 
791*27Sjchu 		/* Get the correct CSR BASE */
792*27Sjchu 		if (reg_id == PX_ERR_JBC) {
793*27Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
794*27Sjchu 		} else {
795*27Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
796*27Sjchu 		}
797*27Sjchu 
798*27Sjchu 		/* Get pointers to masks and register addresses */
799*27Sjchu 		log_mask = err_reg_tbl->log_mask_p;
800*27Sjchu 		count_mask = err_reg_tbl->count_mask_p;
801*27Sjchu 		status_addr = err_reg_tbl->status_addr;
802*27Sjchu 		clear_addr = err_reg_tbl->clear_addr;
803*27Sjchu 		ss_reg = ss->err_status[reg_id];
804*27Sjchu 
805*27Sjchu 		/* Get the register BIT description table */
806*27Sjchu 		err_bit_tbl = err_reg_tbl->err_bit_tbl;
807*27Sjchu 
808*27Sjchu 		/* For each known bit in the register send erpt and handle */
809*27Sjchu 		for (key = 0; key < err_reg_tbl->err_bit_keys; key += 1) {
810*27Sjchu 			/* Get the bit description table for this register */
811*27Sjchu 			err_bit_desc = &err_bit_tbl[key];
812*27Sjchu 
813*27Sjchu 			/*
814*27Sjchu 			 * If the ss_reg is set for this bit,
815*27Sjchu 			 * send ereport and handle
816*27Sjchu 			 */
817*27Sjchu 			if (BIT_TST(ss_reg, err_bit_desc->bit)) {
818*27Sjchu 				/* Increment the counter if necessary */
819*27Sjchu 				if (BIT_TST(*count_mask, err_bit_desc->bit)) {
820*27Sjchu 					err_bit_desc->counter++;
821*27Sjchu 				}
822*27Sjchu 
823*27Sjchu 				/* Error Handle for this bit */
824*27Sjchu 				err_handler = err_bit_desc->err_handler;
825*27Sjchu 				if (err_handler)
826*27Sjchu 					err |= err_handler(rpdip,
827*27Sjchu 					    csr_base,
828*27Sjchu 					    derr,
829*27Sjchu 					    err_reg_tbl,
830*27Sjchu 					    err_bit_desc);
831*27Sjchu 
832*27Sjchu 				/* Send the ereport for this bit */
833*27Sjchu 				erpt_handler = err_bit_desc->erpt_handler;
834*27Sjchu 				if (erpt_handler)
835*27Sjchu 					(void) erpt_handler(rpdip,
836*27Sjchu 					    csr_base,
837*27Sjchu 					    ss_reg,
838*27Sjchu 					    derr,
839*27Sjchu 					    err_bit_desc->class_name);
840*27Sjchu 			}
841*27Sjchu 		}
842*27Sjchu 		/* Log register status */
843*27Sjchu 		if ((px_err_log_all) || (ss_reg & *log_mask))
844*27Sjchu 			LOG(DBG_ERR_INTR, rpdip, "<%x>=%16llx %s\n",
845*27Sjchu 			    status_addr, ss_reg, err_reg_tbl->msg);
846*27Sjchu 
847*27Sjchu 		/* Clear the register and error */
848*27Sjchu 		CSR_XS(csr_base, clear_addr, ss_reg);
849*27Sjchu 	}
850*27Sjchu 
851*27Sjchu 	return (err);
852*27Sjchu }
853*27Sjchu 
854*27Sjchu /*
855*27Sjchu  * px_err_check_severity:
856*27Sjchu  * Check the severity of the fire error based on an earlier snapshot
857*27Sjchu  *
858*27Sjchu  * @param px_p		leaf in which to take the snap shot.
859*27Sjchu  * @param derr		fm err in which the ereport is to be based on
860*27Sjchu  * @param ss		pre-allocated memory to store the snap shot.
861*27Sjchu  */
862*27Sjchu static int
863*27Sjchu px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr, int err, int caller)
864*27Sjchu {
865*27Sjchu 	px_pec_t 	*pec_p = px_p->px_pec_p;
866*27Sjchu 	boolean_t	is_safeacc = B_FALSE;
867*27Sjchu 	int		ret = err;
868*27Sjchu 
869*27Sjchu 	/* Cautious access error handling  */
870*27Sjchu 	switch (derr->fme_flag) {
871*27Sjchu 	case DDI_FM_ERR_EXPECTED:
872*27Sjchu 		if (caller == PX_TRAP_CALL) {
873*27Sjchu 			/*
874*27Sjchu 			 * for ddi_caut_get treat all events as nonfatal
875*27Sjchu 			 * The trampoline will set err_ena = 0,
876*27Sjchu 			 * err_status = NONFATAL.
877*27Sjchu 			 */
878*27Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
879*27Sjchu 			is_safeacc = B_TRUE;
880*27Sjchu 		} else {
881*27Sjchu 			/*
882*27Sjchu 			 * For ddi_caut_put treat all events as nonfatal. Here
883*27Sjchu 			 * we have the handle and can call ndi_fm_acc_err_set().
884*27Sjchu 			 */
885*27Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
886*27Sjchu 			ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr);
887*27Sjchu 			is_safeacc = B_TRUE;
888*27Sjchu 		}
889*27Sjchu 		break;
890*27Sjchu 	case DDI_FM_ERR_PEEK:
891*27Sjchu 	case DDI_FM_ERR_POKE:
892*27Sjchu 		/*
893*27Sjchu 		 * For ddi_peek/poke treat all events as nonfatal.
894*27Sjchu 		 */
895*27Sjchu 		is_safeacc = B_TRUE;
896*27Sjchu 		break;
897*27Sjchu 	default:
898*27Sjchu 		is_safeacc = B_FALSE;
899*27Sjchu 	}
900*27Sjchu 
901*27Sjchu 	/*
902*27Sjchu 	 * The third argument "err" is passed in as error status from checking
903*27Sjchu 	 * Fire register, re-adjust error status from safe access.
904*27Sjchu 	 */
905*27Sjchu 	if (is_safeacc && !(err & PX_FATAL_GOS))
906*27Sjchu 		ret = PX_NONFATAL;
907*27Sjchu 
908*27Sjchu 	if (err & PX_FATAL_GOS)
909*27Sjchu 		ret = PX_FATAL_GOS;
910*27Sjchu 	else if (err & (PX_STUCK_FATAL | PX_FATAL_SW))
911*27Sjchu 		err &= (PX_STUCK_FATAL | PX_FATAL_SW);
912*27Sjchu 	else if (err & (PX_NONFATAL | PX_FATAL_HW))
913*27Sjchu 		ret = PX_NONFATAL;
914*27Sjchu 	else
915*27Sjchu 		ret = PX_OK;
916*27Sjchu 
917*27Sjchu 	return (ret);
918*27Sjchu }
919*27Sjchu 
920*27Sjchu /* predefined convenience functions */
921*27Sjchu /* ARGSUSED */
922*27Sjchu int
923*27Sjchu px_err_fatal_hw_handle(dev_info_t *rpdip, caddr_t csr_base,
924*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
925*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
926*27Sjchu {
927*27Sjchu 	return (PX_FATAL_HW);
928*27Sjchu }
929*27Sjchu 
930*27Sjchu /* ARGSUSED */
931*27Sjchu int
932*27Sjchu px_err_fatal_gos_handle(dev_info_t *rpdip, caddr_t csr_base,
933*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
934*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
935*27Sjchu {
936*27Sjchu 	return (PX_FATAL_GOS);
937*27Sjchu }
938*27Sjchu 
939*27Sjchu /* ARGSUSED */
940*27Sjchu int
941*27Sjchu px_err_fatal_stuck_handle(dev_info_t *rpdip, caddr_t csr_base,
942*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
943*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
944*27Sjchu {
945*27Sjchu 	return (PX_STUCK_FATAL);
946*27Sjchu }
947*27Sjchu 
948*27Sjchu /* ARGSUSED */
949*27Sjchu int
950*27Sjchu px_err_fatal_sw_handle(dev_info_t *rpdip, caddr_t csr_base,
951*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
952*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
953*27Sjchu {
954*27Sjchu 	return (PX_FATAL_SW);
955*27Sjchu }
956*27Sjchu 
957*27Sjchu /* ARGSUSED */
958*27Sjchu int
959*27Sjchu px_err_non_fatal_handle(dev_info_t *rpdip, caddr_t csr_base,
960*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
961*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
962*27Sjchu {
963*27Sjchu 	return (PX_NONFATAL);
964*27Sjchu }
965*27Sjchu 
966*27Sjchu /* ARGSUSED */
967*27Sjchu int
968*27Sjchu px_err_ok_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
969*27Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
970*27Sjchu {
971*27Sjchu 	return (PX_OK);
972*27Sjchu }
973*27Sjchu 
974*27Sjchu /* ARGSUSED */
975*27Sjchu int
976*27Sjchu px_err_unknown_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
977*27Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
978*27Sjchu {
979*27Sjchu 	return (PX_ERR_UNKNOWN);
980*27Sjchu }
981*27Sjchu 
982*27Sjchu /* JBC FATAL - see io erpt doc, section 1.1 */
983*27Sjchu PX_ERPT_SEND_DEC(jbc_fatal)
984*27Sjchu {
985*27Sjchu 	char		buf[FM_MAX_CLASS];
986*27Sjchu 
987*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
988*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
989*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
990*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
991*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
992*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
993*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
994*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
995*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
996*27Sjchu 	    ss_reg,
997*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
998*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
999*27Sjchu 	    FIRE_JBC_FEL1, DATA_TYPE_UINT64,
1000*27Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_1),
1001*27Sjchu 	    FIRE_JBC_FEL2, DATA_TYPE_UINT64,
1002*27Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_2),
1003*27Sjchu 	    NULL);
1004*27Sjchu 
1005*27Sjchu 	return (PX_OK);
1006*27Sjchu }
1007*27Sjchu 
1008*27Sjchu /* JBC MERGE - see io erpt doc, section 1.2 */
1009*27Sjchu PX_ERPT_SEND_DEC(jbc_merge)
1010*27Sjchu {
1011*27Sjchu 	char		buf[FM_MAX_CLASS];
1012*27Sjchu 
1013*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1014*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1015*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1016*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1017*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1018*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1019*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1020*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1021*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1022*27Sjchu 	    ss_reg,
1023*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1024*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1025*27Sjchu 	    FIRE_JBC_MTEL, DATA_TYPE_UINT64,
1026*27Sjchu 	    CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG),
1027*27Sjchu 	    NULL);
1028*27Sjchu 
1029*27Sjchu 	return (PX_OK);
1030*27Sjchu }
1031*27Sjchu 
1032*27Sjchu /*
1033*27Sjchu  * JBC Merge buffer nonfatal errors:
1034*27Sjchu  *    Merge buffer parity error (rd_buf): dma:read:M:nonfatal
1035*27Sjchu  *    Merge buffer parity error (wr_buf): dma:write:M:nonfatal
1036*27Sjchu  */
1037*27Sjchu /* ARGSUSED */
1038*27Sjchu int
1039*27Sjchu px_err_jbc_merge_handle(dev_info_t *rpdip, caddr_t csr_base,
1040*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1041*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1042*27Sjchu {
1043*27Sjchu 	uint64_t	paddr;
1044*27Sjchu 	int		ret;
1045*27Sjchu 
1046*27Sjchu 	paddr = CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG);
1047*27Sjchu 	paddr &= MERGE_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
1048*27Sjchu 
1049*27Sjchu 	ret = px_handle_lookup(
1050*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
1051*27Sjchu 
1052*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1053*27Sjchu }
1054*27Sjchu 
1055*27Sjchu /* JBC Jbusint IN - see io erpt doc, section 1.3 */
1056*27Sjchu PX_ERPT_SEND_DEC(jbc_in)
1057*27Sjchu {
1058*27Sjchu 	char		buf[FM_MAX_CLASS];
1059*27Sjchu 
1060*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1061*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1062*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1063*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1064*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1065*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1066*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1067*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1068*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1069*27Sjchu 	    ss_reg,
1070*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1071*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1072*27Sjchu 	    FIRE_JBC_JITEL1, DATA_TYPE_UINT64,
1073*27Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG),
1074*27Sjchu 	    FIRE_JBC_JITEL2, DATA_TYPE_UINT64,
1075*27Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG_2),
1076*27Sjchu 	    NULL);
1077*27Sjchu 
1078*27Sjchu 	return (PX_OK);
1079*27Sjchu }
1080*27Sjchu 
1081*27Sjchu /*
1082*27Sjchu  * JBC Jbusint IN nonfatal errors: PA logged in Jbusint In Transaction Error
1083*27Sjchu  * Log Reg[42:0].
1084*27Sjchu  *     CE async fault error: nonfatal
1085*27Sjchu  *     Jbus bus error: dma::nonfatal
1086*27Sjchu  *     Jbus unmapped error: pio|dma:rdwr:M:nonfatal
1087*27Sjchu  *     Write data parity error: pio/write:M:nonfatal
1088*27Sjchu  *     Read data parity error: pio/read:M:nonfatal
1089*27Sjchu  *     Illegal NCWR bytemask: pio:write:M:nonfatal
1090*27Sjchu  *     Illegal NCRD bytemask: pio:write:M:nonfatal
1091*27Sjchu  *     Invalid jbus transaction: nonfatal
1092*27Sjchu  */
1093*27Sjchu /* ARGSUSED */
1094*27Sjchu int
1095*27Sjchu px_err_jbc_jbusint_in_handle(dev_info_t *rpdip, caddr_t csr_base,
1096*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1097*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1098*27Sjchu {
1099*27Sjchu 	uint64_t	paddr;
1100*27Sjchu 	int		ret;
1101*27Sjchu 
1102*27Sjchu 	paddr = CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG);
1103*27Sjchu 	paddr &= JBCINT_IN_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
1104*27Sjchu 
1105*27Sjchu 	ret = px_handle_lookup(
1106*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
1107*27Sjchu 
1108*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1109*27Sjchu }
1110*27Sjchu 
1111*27Sjchu 
1112*27Sjchu /* JBC Jbusint Out - see io erpt doc, section 1.4 */
1113*27Sjchu PX_ERPT_SEND_DEC(jbc_out)
1114*27Sjchu {
1115*27Sjchu 	char		buf[FM_MAX_CLASS];
1116*27Sjchu 
1117*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1118*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1119*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1120*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1121*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1122*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1123*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1124*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1125*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1126*27Sjchu 	    ss_reg,
1127*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1128*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1129*27Sjchu 	    FIRE_JBC_JOTEL1, DATA_TYPE_UINT64,
1130*27Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG),
1131*27Sjchu 	    FIRE_JBC_JOTEL2, DATA_TYPE_UINT64,
1132*27Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG_2),
1133*27Sjchu 	    NULL);
1134*27Sjchu 
1135*27Sjchu 	return (PX_OK);
1136*27Sjchu }
1137*27Sjchu 
1138*27Sjchu /* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
1139*27Sjchu PX_ERPT_SEND_DEC(jbc_odcd)
1140*27Sjchu {
1141*27Sjchu 	char		buf[FM_MAX_CLASS];
1142*27Sjchu 
1143*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1144*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1145*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1146*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1147*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1148*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1149*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1150*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1151*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1152*27Sjchu 	    ss_reg,
1153*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1154*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1155*27Sjchu 	    FIRE_JBC_DMC_ODCD, DATA_TYPE_UINT64,
1156*27Sjchu 	    CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG),
1157*27Sjchu 	    NULL);
1158*27Sjchu 
1159*27Sjchu 	return (PX_OK);
1160*27Sjchu }
1161*27Sjchu 
1162*27Sjchu /*
1163*27Sjchu  * JBC Dmcint ODCO nonfatal errer handling -
1164*27Sjchu  *    Unmapped PIO read error: pio:read:M:nonfatal
1165*27Sjchu  *    Unmapped PIO write error: pio:write:M:nonfatal
1166*27Sjchu  *    PIO data parity error: pio:write:M:nonfatal
1167*27Sjchu  *    Invalid PIO write to PCIe cfg/io, csr, ebus or i2c bus: pio:write:nonfatal
1168*27Sjchu  *    Invalid PIO read to PCIe cfg/io, csr, ebus or i2c bus: pio:read:nonfatal
1169*27Sjchu  */
1170*27Sjchu /* ARGSUSED */
1171*27Sjchu int
1172*27Sjchu px_err_jbc_dmcint_odcd_handle(dev_info_t *rpdip, caddr_t csr_base,
1173*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1174*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1175*27Sjchu {
1176*27Sjchu 	uint64_t	paddr;
1177*27Sjchu 	int		ret;
1178*27Sjchu 
1179*27Sjchu 	paddr = CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG);
1180*27Sjchu 	paddr &= DMCINT_ODCD_ERROR_LOG_ADDRESS_MASK;
1181*27Sjchu 
1182*27Sjchu 	ret = px_handle_lookup(
1183*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
1184*27Sjchu 
1185*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1186*27Sjchu }
1187*27Sjchu 
1188*27Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
1189*27Sjchu PX_ERPT_SEND_DEC(jbc_idc)
1190*27Sjchu {
1191*27Sjchu 	char		buf[FM_MAX_CLASS];
1192*27Sjchu 
1193*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1194*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1195*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1196*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1197*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1198*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1199*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1200*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1201*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1202*27Sjchu 	    ss_reg,
1203*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1204*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1205*27Sjchu 	    FIRE_JBC_DMC_IDC, DATA_TYPE_UINT64,
1206*27Sjchu 	    CSR_XR(csr_base, DMCINT_IDC_ERROR_LOG),
1207*27Sjchu 	    NULL);
1208*27Sjchu 
1209*27Sjchu 	return (PX_OK);
1210*27Sjchu }
1211*27Sjchu 
1212*27Sjchu /* JBC CSR - see io erpt doc, section 1.7 */
1213*27Sjchu PX_ERPT_SEND_DEC(jbc_csr)
1214*27Sjchu {
1215*27Sjchu 	char		buf[FM_MAX_CLASS];
1216*27Sjchu 
1217*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1218*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1219*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1220*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1221*27Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
1222*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
1223*27Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
1224*27Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
1225*27Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
1226*27Sjchu 	    ss_reg,
1227*27Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
1228*27Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
1229*27Sjchu 	    "jbc-error-reg", DATA_TYPE_UINT64,
1230*27Sjchu 	    CSR_XR(csr_base, CSR_ERROR_LOG),
1231*27Sjchu 	    NULL);
1232*27Sjchu 
1233*27Sjchu 	return (PX_OK);
1234*27Sjchu }
1235*27Sjchu 
1236*27Sjchu /*
1237*27Sjchu  * JBC CSR errer handling -
1238*27Sjchu  * Ebus ready timeout error: pio:rdwr:M:nonfatal
1239*27Sjchu  */
1240*27Sjchu /* ARGSUSED */
1241*27Sjchu int
1242*27Sjchu px_err_jbc_csr_handle(dev_info_t *rpdip, caddr_t csr_base,
1243*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1244*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1245*27Sjchu {
1246*27Sjchu 	uint64_t	paddr;
1247*27Sjchu 	int		ret;
1248*27Sjchu 
1249*27Sjchu 	paddr = CSR_XR(csr_base, CSR_ERROR_LOG);
1250*27Sjchu 	paddr &= CSR_ERROR_LOG_ADDRESS_MASK;
1251*27Sjchu 
1252*27Sjchu 	ret = px_handle_lookup(
1253*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
1254*27Sjchu 
1255*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1256*27Sjchu }
1257*27Sjchu 
1258*27Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
1259*27Sjchu 
1260*27Sjchu /* DMC IMU RDS - see io erpt doc, section 2.1 */
1261*27Sjchu PX_ERPT_SEND_DEC(imu_rds)
1262*27Sjchu {
1263*27Sjchu 	char		buf[FM_MAX_CLASS];
1264*27Sjchu 
1265*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1266*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1267*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1268*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1269*27Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
1270*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
1271*27Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
1272*27Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
1273*27Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
1274*27Sjchu 	    ss_reg,
1275*27Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
1276*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
1277*27Sjchu 	    FIRE_IMU_RDS, DATA_TYPE_UINT64,
1278*27Sjchu 	    CSR_XR(csr_base, IMU_RDS_ERROR_LOG),
1279*27Sjchu 	    NULL);
1280*27Sjchu 
1281*27Sjchu 	return (PX_OK);
1282*27Sjchu }
1283*27Sjchu 
1284*27Sjchu /* imu function to handle all Received but Not Enabled errors */
1285*27Sjchu /* ARGSUSED */
1286*27Sjchu int
1287*27Sjchu px_err_imu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
1288*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1289*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1290*27Sjchu {
1291*27Sjchu 	uint64_t	imu_log_enable, imu_intr_enable;
1292*27Sjchu 	int		mask = BITMASK(err_bit_descr->bit);
1293*27Sjchu 	int		err = PX_NONFATAL;
1294*27Sjchu 
1295*27Sjchu 	imu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
1296*27Sjchu 	imu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
1297*27Sjchu 
1298*27Sjchu 	if (imu_log_enable & imu_intr_enable & mask) {
1299*27Sjchu 		err = PX_FATAL_SW;
1300*27Sjchu 	} else {
1301*27Sjchu 		/*
1302*27Sjchu 		 * S/W bug - this error should always be enabled
1303*27Sjchu 		 */
1304*27Sjchu 
1305*27Sjchu 		/* enable error & intr reporting for this bit */
1306*27Sjchu 		CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE, imu_log_enable | mask);
1307*27Sjchu 		CSR_XS(csr_base, IMU_INTERRUPT_ENABLE, imu_intr_enable | mask);
1308*27Sjchu 		err = PX_NONFATAL;
1309*27Sjchu 	}
1310*27Sjchu 
1311*27Sjchu 	return (err);
1312*27Sjchu }
1313*27Sjchu 
1314*27Sjchu /* handle EQ overflow */
1315*27Sjchu /* ARGSUSED */
1316*27Sjchu int
1317*27Sjchu px_err_imu_eq_ovfl_handle(dev_info_t *rpdip, caddr_t csr_base,
1318*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1319*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1320*27Sjchu {
1321*27Sjchu 	px_t			*px_p = DIP_TO_STATE(rpdip);
1322*27Sjchu 	px_msiq_state_t 	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1323*27Sjchu 	msiqid_t		eqno;
1324*27Sjchu 	pci_msiq_state_t	msiq_state;
1325*27Sjchu 	int			err = PX_NONFATAL;
1326*27Sjchu 	int			i;
1327*27Sjchu 
1328*27Sjchu 	eqno = msiq_state_p->msiq_1st_msiq_id;
1329*27Sjchu 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
1330*27Sjchu 		if (px_lib_msiq_getstate(rpdip, eqno, &msiq_state) ==
1331*27Sjchu 			DDI_SUCCESS) {
1332*27Sjchu 			if (msiq_state == PCI_MSIQ_STATE_ERROR) {
1333*27Sjchu 				err = PX_FATAL_SW;
1334*27Sjchu 			}
1335*27Sjchu 		}
1336*27Sjchu 	}
1337*27Sjchu 
1338*27Sjchu 	return (err);
1339*27Sjchu }
1340*27Sjchu 
1341*27Sjchu /* DMC IMU SCS - see io erpt doc, section 2.2 */
1342*27Sjchu PX_ERPT_SEND_DEC(imu_scs)
1343*27Sjchu {
1344*27Sjchu 	char		buf[FM_MAX_CLASS];
1345*27Sjchu 
1346*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1347*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1348*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1349*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1350*27Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
1351*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
1352*27Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
1353*27Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
1354*27Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
1355*27Sjchu 	    ss_reg,
1356*27Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
1357*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
1358*27Sjchu 	    FIRE_IMU_SCS, DATA_TYPE_UINT64,
1359*27Sjchu 	    CSR_XR(csr_base, IMU_SCS_ERROR_LOG),
1360*27Sjchu 	    NULL);
1361*27Sjchu 
1362*27Sjchu 	return (PX_OK);
1363*27Sjchu }
1364*27Sjchu 
1365*27Sjchu /* DMC IMU - see io erpt doc, section 2.3 */
1366*27Sjchu PX_ERPT_SEND_DEC(imu)
1367*27Sjchu {
1368*27Sjchu 	char		buf[FM_MAX_CLASS];
1369*27Sjchu 
1370*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1371*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1372*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1373*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1374*27Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
1375*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
1376*27Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
1377*27Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
1378*27Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
1379*27Sjchu 	    ss_reg,
1380*27Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
1381*27Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
1382*27Sjchu 	    NULL);
1383*27Sjchu 
1384*27Sjchu 	return (PX_OK);
1385*27Sjchu }
1386*27Sjchu 
1387*27Sjchu /* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
1388*27Sjchu PX_ERPT_SEND_DEC(mmu_tfar_tfsr)
1389*27Sjchu {
1390*27Sjchu 	char		buf[FM_MAX_CLASS];
1391*27Sjchu 
1392*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1393*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1394*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1395*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1396*27Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
1397*27Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
1398*27Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
1399*27Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
1400*27Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
1401*27Sjchu 	    ss_reg,
1402*27Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
1403*27Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
1404*27Sjchu 	    FIRE_MMU_TFAR, DATA_TYPE_UINT64,
1405*27Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS),
1406*27Sjchu 	    FIRE_MMU_TFSR, DATA_TYPE_UINT64,
1407*27Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS),
1408*27Sjchu 	    NULL);
1409*27Sjchu 
1410*27Sjchu 	return (PX_OK);
1411*27Sjchu }
1412*27Sjchu 
1413*27Sjchu /* DMC MMU - see io erpt doc, section 2.5 */
1414*27Sjchu PX_ERPT_SEND_DEC(mmu)
1415*27Sjchu {
1416*27Sjchu 	char		buf[FM_MAX_CLASS];
1417*27Sjchu 
1418*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1419*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1420*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1421*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1422*27Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
1423*27Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
1424*27Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
1425*27Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
1426*27Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
1427*27Sjchu 	    ss_reg,
1428*27Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
1429*27Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
1430*27Sjchu 	    NULL);
1431*27Sjchu 
1432*27Sjchu 	return (PX_OK);
1433*27Sjchu }
1434*27Sjchu 
1435*27Sjchu /* imu function to handle all Received but Not Enabled errors */
1436*27Sjchu int
1437*27Sjchu px_err_mmu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
1438*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1439*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1440*27Sjchu {
1441*27Sjchu 	uint64_t	mmu_log_enable, mmu_intr_enable, mmu_tfa;
1442*27Sjchu 	uint64_t	mask = BITMASK(err_bit_descr->bit);
1443*27Sjchu 	int		err = PX_NONFATAL;
1444*27Sjchu 	int		ret;
1445*27Sjchu 
1446*27Sjchu 	mmu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
1447*27Sjchu 	mmu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
1448*27Sjchu 
1449*27Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1450*27Sjchu 
1451*27Sjchu 	if (mmu_log_enable & mmu_intr_enable & mask) {
1452*27Sjchu 		err = PX_FATAL_SW;
1453*27Sjchu 	} else {
1454*27Sjchu 		ret = px_handle_lookup(
1455*27Sjchu 			rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
1456*27Sjchu 		err = (ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL;
1457*27Sjchu 
1458*27Sjchu 		/*
1459*27Sjchu 		 * S/W bug - this error should always be enabled
1460*27Sjchu 		 */
1461*27Sjchu 
1462*27Sjchu 		/* enable error & intr reporting for this bit */
1463*27Sjchu 		CSR_XS(csr_base, MMU_ERROR_LOG_ENABLE, mmu_log_enable | mask);
1464*27Sjchu 		CSR_XS(csr_base, MMU_INTERRUPT_ENABLE, mmu_intr_enable | mask);
1465*27Sjchu 	}
1466*27Sjchu 
1467*27Sjchu 	return (err);
1468*27Sjchu }
1469*27Sjchu 
1470*27Sjchu /* Generic error handling functions that involve MMU Translation Fault Addr */
1471*27Sjchu /* ARGSUSED */
1472*27Sjchu int
1473*27Sjchu px_err_mmu_tfa_handle(dev_info_t *rpdip, caddr_t csr_base,
1474*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1475*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1476*27Sjchu {
1477*27Sjchu 	uint64_t	mmu_tfa;
1478*27Sjchu 	uint_t		ret;
1479*27Sjchu 
1480*27Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1481*27Sjchu 	ret = px_handle_lookup(
1482*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
1483*27Sjchu 
1484*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1485*27Sjchu }
1486*27Sjchu 
1487*27Sjchu /* MMU Table walk errors */
1488*27Sjchu /* ARGSUSED */
1489*27Sjchu int
1490*27Sjchu px_err_mmu_tblwlk_handle(dev_info_t *rpdip, caddr_t csr_base,
1491*27Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1492*27Sjchu 	px_err_bit_desc_t *err_bit_descr)
1493*27Sjchu {
1494*27Sjchu 	uint64_t	mmu_tfa;
1495*27Sjchu 	uint_t		ret;
1496*27Sjchu 
1497*27Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1498*27Sjchu 	ret = px_handle_lookup(
1499*27Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
1500*27Sjchu 
1501*27Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
1502*27Sjchu }
1503*27Sjchu 
1504*27Sjchu /* PEC ILU none - see io erpt doc, section 3.1 */
1505*27Sjchu PX_ERPT_SEND_DEC(pec_ilu)
1506*27Sjchu {
1507*27Sjchu 	char		buf[FM_MAX_CLASS];
1508*27Sjchu 
1509*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1510*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1511*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1512*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1513*27Sjchu 	    FIRE_ILU_ELE, DATA_TYPE_UINT64,
1514*27Sjchu 	    CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE),
1515*27Sjchu 	    FIRE_ILU_IE, DATA_TYPE_UINT64,
1516*27Sjchu 	    CSR_XR(csr_base, ILU_INTERRUPT_ENABLE),
1517*27Sjchu 	    FIRE_ILU_IS, DATA_TYPE_UINT64,
1518*27Sjchu 	    ss_reg,
1519*27Sjchu 	    FIRE_ILU_ESS, DATA_TYPE_UINT64,
1520*27Sjchu 	    CSR_XR(csr_base, ILU_ERROR_STATUS_SET),
1521*27Sjchu 	    NULL);
1522*27Sjchu 
1523*27Sjchu 	return (PX_OK);
1524*27Sjchu }
1525*27Sjchu 
1526*27Sjchu /* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
1527*27Sjchu PX_ERPT_SEND_DEC(pciex_ce)
1528*27Sjchu {
1529*27Sjchu 	char		buf[FM_MAX_CLASS];
1530*27Sjchu 
1531*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1532*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1533*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1534*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1535*27Sjchu 	    FIRE_TLU_CELE, DATA_TYPE_UINT64,
1536*27Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE),
1537*27Sjchu 	    FIRE_TLU_CIE, DATA_TYPE_UINT64,
1538*27Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE),
1539*27Sjchu 	    FIRE_TLU_CIS, DATA_TYPE_UINT64,
1540*27Sjchu 	    ss_reg,
1541*27Sjchu 	    FIRE_TLU_CESS, DATA_TYPE_UINT64,
1542*27Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_SET),
1543*27Sjchu 	    NULL);
1544*27Sjchu 
1545*27Sjchu 	return (PX_OK);
1546*27Sjchu }
1547*27Sjchu 
1548*27Sjchu /* TLU Other Event Status (receive only) - see io erpt doc, section 3.7 */
1549*27Sjchu PX_ERPT_SEND_DEC(pciex_rx_oe)
1550*27Sjchu {
1551*27Sjchu 	char		buf[FM_MAX_CLASS];
1552*27Sjchu 
1553*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1554*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1555*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1556*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1557*27Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
1558*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
1559*27Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
1560*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
1561*27Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
1562*27Sjchu 	    ss_reg,
1563*27Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
1564*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
1565*27Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
1566*27Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
1567*27Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
1568*27Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
1569*27Sjchu 	    NULL);
1570*27Sjchu 
1571*27Sjchu 	return (PX_OK);
1572*27Sjchu }
1573*27Sjchu 
1574*27Sjchu /* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
1575*27Sjchu PX_ERPT_SEND_DEC(pciex_rx_tx_oe)
1576*27Sjchu {
1577*27Sjchu 	char		buf[FM_MAX_CLASS];
1578*27Sjchu 
1579*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1580*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1581*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1582*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1583*27Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
1584*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
1585*27Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
1586*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
1587*27Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
1588*27Sjchu 	    ss_reg,
1589*27Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
1590*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
1591*27Sjchu 	    FIRE_TLU_ROEEH1L, DATA_TYPE_UINT64,
1592*27Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
1593*27Sjchu 	    FIRE_TLU_ROEEH2L, DATA_TYPE_UINT64,
1594*27Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
1595*27Sjchu 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64,
1596*27Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG),
1597*27Sjchu 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64,
1598*27Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG),
1599*27Sjchu 	    NULL);
1600*27Sjchu 
1601*27Sjchu 	return (PX_OK);
1602*27Sjchu }
1603*27Sjchu 
1604*27Sjchu /* TLU Other Event - see io erpt doc, section 3.9 */
1605*27Sjchu PX_ERPT_SEND_DEC(pciex_oe)
1606*27Sjchu {
1607*27Sjchu 	char		buf[FM_MAX_CLASS];
1608*27Sjchu 
1609*27Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1610*27Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1611*27Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1612*27Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1613*27Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
1614*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
1615*27Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
1616*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
1617*27Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
1618*27Sjchu 	    ss_reg,
1619*27Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
1620*27Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
1621*27Sjchu 	    NULL);
1622*27Sjchu 
1623*27Sjchu 	return (PX_OK);
1624*27Sjchu }
1625