1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/nxge/nxge_impl.h>
27#include <sys/nxge/nxge_hio.h>
28#include <sys/ddifm.h>
29#include <sys/fm/protocol.h>
30#include <sys/fm/util.h>
31#include <sys/fm/io/ddi.h>
32
33static nxge_fm_ereport_attr_t
34*nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t);
35
36static int
37nxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data);
38
39nxge_fm_ereport_attr_t	nxge_fm_ereport_pcs[] = {
40	{NXGE_FM_EREPORT_XPCS_LINK_DOWN,	"10g_link_down",
41						DDI_FM_DEVICE_INVAL_STATE,
42						DDI_SERVICE_LOST},
43	{NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT,	"10g_tx_link_fault",
44						DDI_FM_DEVICE_INVAL_STATE,
45						DDI_SERVICE_DEGRADED},
46	{NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT,	"10g_rx_link_fault",
47						DDI_FM_DEVICE_INVAL_STATE,
48						DDI_SERVICE_DEGRADED},
49	{NXGE_FM_EREPORT_PCS_LINK_DOWN,		"1g_link_down",
50						DDI_FM_DEVICE_INVAL_STATE,
51						DDI_SERVICE_LOST},
52	{NXGE_FM_EREPORT_PCS_REMOTE_FAULT,	"1g_remote_fault",
53						DDI_FM_DEVICE_INVAL_STATE,
54						DDI_SERVICE_DEGRADED},
55};
56
57nxge_fm_ereport_attr_t	nxge_fm_ereport_mif[] = {
58	{NXGE_FM_EREPORT_MIF_ACCESS_FAIL,	"transceiver_access_fail"}
59};
60
61nxge_fm_ereport_attr_t nxge_fm_ereport_fflp[] = {
62	{NXGE_FM_EREPORT_FFLP_TCAM_ERR,		"classifier_tcam_err",
63						DDI_FM_DEVICE_INTERN_UNCORR,
64						DDI_SERVICE_UNAFFECTED},
65	{NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR,	"classifier_vlan_par_err",
66						DDI_FM_DEVICE_INTERN_UNCORR,
67						DDI_SERVICE_UNAFFECTED},
68	{NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR,	"classifier_hasht_data_err",
69						DDI_FM_DEVICE_INTERN_UNCORR,
70						DDI_SERVICE_UNAFFECTED},
71	{NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR,	"classifier_hasht_lookup_err",
72						DDI_FM_DEVICE_INTERN_UNCORR,
73						DDI_SERVICE_UNAFFECTED},
74	{NXGE_FM_EREPORT_FFLP_ACCESS_FAIL,	"classifier_access_fail",
75						DDI_FM_DEVICE_NO_RESPONSE,
76						DDI_SERVICE_DEGRADED}
77};
78
79nxge_fm_ereport_attr_t nxge_fm_ereport_ipp[] = {
80	{NXGE_FM_EREPORT_IPP_EOP_MISS,		"rx_eop_miss",
81						DDI_FM_DEVICE_INVAL_STATE,
82						DDI_SERVICE_LOST},
83	{NXGE_FM_EREPORT_IPP_SOP_MISS,		"rx_sop_miss",
84						DDI_FM_DEVICE_INVAL_STATE,
85						DDI_SERVICE_LOST},
86	{NXGE_FM_EREPORT_IPP_DFIFO_UE,		"rx_dfifo_ucorr_err",
87						DDI_FM_DEVICE_INTERN_UNCORR,
88						DDI_SERVICE_LOST},
89	{NXGE_FM_EREPORT_IPP_DFIFO_CE,		"rx_dfifo_corr_err",
90						DDI_FM_DEVICE_INTERN_CORR,
91						DDI_SERVICE_UNAFFECTED},
92	{NXGE_FM_EREPORT_IPP_PFIFO_PERR,	"rx_dfifo_parity_err",
93						DDI_FM_DEVICE_INTERN_UNCORR,
94						DDI_SERVICE_LOST},
95	{NXGE_FM_EREPORT_IPP_ECC_ERR_MAX,	"rx_ecc_err_max",
96						DDI_FM_DEVICE_INTERN_UNCORR,
97						DDI_SERVICE_UNAFFECTED},
98	{NXGE_FM_EREPORT_IPP_PFIFO_OVER,	"rx_pfifo_overflow",
99						DDI_FM_DEVICE_INVAL_STATE,
100						DDI_SERVICE_LOST},
101	{NXGE_FM_EREPORT_IPP_PFIFO_UND,		"rx_pfifo_underrun",
102						DDI_FM_DEVICE_INVAL_STATE,
103						DDI_SERVICE_LOST},
104	{NXGE_FM_EREPORT_IPP_BAD_CS_MX,		"rx_bad_cksum_max",
105						DDI_FM_DEVICE_INTERN_UNCORR,
106						DDI_SERVICE_UNAFFECTED},
107	{NXGE_FM_EREPORT_IPP_PKT_DIS_MX,	"rx_pkt_discard_max",
108						DDI_FM_DEVICE_INTERN_UNCORR,
109						DDI_SERVICE_UNAFFECTED},
110	{NXGE_FM_EREPORT_IPP_RESET_FAIL,	"rx_reset_fail",
111						DDI_FM_DEVICE_NO_RESPONSE,
112						DDI_SERVICE_LOST}
113};
114
115nxge_fm_ereport_attr_t nxge_fm_ereport_rdmc[] = {
116	{NXGE_FM_EREPORT_RDMC_DCF_ERR,		"rxdma_dcf_err",
117						DDI_FM_DEVICE_INTERN_UNCORR,
118						DDI_SERVICE_LOST},
119	{NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR,	"rxdma_rcr_ack_err",
120						DDI_FM_DEVICE_INTERN_UNCORR,
121						DDI_SERVICE_DEGRADED},
122	{NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR,	"rxdma_dc_fifo_err",
123						DDI_FM_DEVICE_INTERN_UNCORR,
124						DDI_SERVICE_LOST},
125	{NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR,	"rxdma_rcr_sha_par_err",
126						DDI_FM_DEVICE_INTERN_UNCORR,
127						DDI_SERVICE_DEGRADED},
128	{NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR,	"rxdma_rbr_pre_par_err",
129						DDI_FM_DEVICE_INTERN_UNCORR,
130						DDI_SERVICE_DEGRADED},
131	{NXGE_FM_EREPORT_RDMC_RBR_TMOUT,	"rxdma_rbr_tmout",
132						DDI_FM_DEVICE_NO_RESPONSE,
133						DDI_SERVICE_DEGRADED},
134	{NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR,	"rxdma_rsp_cnt_err",
135						DDI_FM_DEVICE_INVAL_STATE,
136						DDI_SERVICE_DEGRADED},
137	{NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS,	"rxdma_byte_en_bus",
138						DDI_FM_DEVICE_INVAL_STATE,
139						DDI_SERVICE_DEGRADED},
140	{NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR,	"rxdma_rsp_dat_err",
141						DDI_FM_DEVICE_INTERN_UNCORR,
142						DDI_SERVICE_DEGRADED},
143	{NXGE_FM_EREPORT_RDMC_ID_MISMATCH,	"rxdma_id_mismatch",
144						DDI_FM_DEVICE_INVAL_STATE,
145						DDI_SERVICE_LOST},
146	{NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR,	"rxdma_zcp_eop_err",
147						DDI_FM_DEVICE_INVAL_STATE,
148						DDI_SERVICE_LOST},
149	{NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR,	"rxdma_ipp_eop_err",
150						DDI_FM_DEVICE_INVAL_STATE,
151						DDI_SERVICE_LOST},
152	{NXGE_FM_EREPORT_RDMC_RCR_ERR,		"rxdma_completion_err",
153						DDI_FM_DEVICE_INTERN_UNCORR,
154						DDI_SERVICE_UNAFFECTED},
155	{NXGE_FM_EREPORT_RDMC_CONFIG_ERR,	"rxdma_config_err",
156						DDI_FM_DEVICE_INVAL_STATE,
157						DDI_SERVICE_DEGRADED},
158	{NXGE_FM_EREPORT_RDMC_RCRINCON,		"rxdma_rcrincon",
159						DDI_FM_DEVICE_INVAL_STATE,
160						DDI_SERVICE_DEGRADED},
161	{NXGE_FM_EREPORT_RDMC_RCRFULL,		"rxdma_rcrfull",
162						DDI_FM_DEVICE_INVAL_STATE,
163						DDI_SERVICE_DEGRADED},
164	{NXGE_FM_EREPORT_RDMC_RBRFULL,		"rxdma_rbrfull",
165						DDI_FM_DEVICE_INVAL_STATE,
166						DDI_SERVICE_DEGRADED},
167	{NXGE_FM_EREPORT_RDMC_RBRLOGPAGE,	"rxdma_rbrlogpage",
168						DDI_FM_DEVICE_INVAL_STATE,
169						DDI_SERVICE_DEGRADED},
170	{NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE,	"rxdma_cfiglogpage",
171						DDI_FM_DEVICE_INVAL_STATE,
172						DDI_SERVICE_DEGRADED}
173};
174
175nxge_fm_ereport_attr_t nxge_fm_ereport_zcp[] = {
176	{NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN,	"rxzcopy_rrfifo_underrun",
177						DDI_FM_DEVICE_INVAL_STATE,
178						DDI_SERVICE_UNAFFECTED},
179	{NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR,
180						"rxzcopy_rspfifo_uncorr_err",
181						DDI_FM_DEVICE_INTERN_UNCORR,
182						DDI_SERVICE_UNAFFECTED},
183	{NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR,	"rxzcopy_stat_tbl_perr",
184						DDI_FM_DEVICE_INTERN_UNCORR,
185						DDI_SERVICE_UNAFFECTED},
186	{NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR,	"rxzcopy_dyn_tbl_perr",
187						DDI_FM_DEVICE_INTERN_UNCORR,
188						DDI_SERVICE_UNAFFECTED},
189	{NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR,	"rxzcopy_buf_tbl_perr",
190						DDI_FM_DEVICE_INTERN_UNCORR,
191						DDI_SERVICE_UNAFFECTED},
192	{NXGE_FM_EREPORT_ZCP_CFIFO_ECC,		"rxzcopy_cfifo_ecc",
193						DDI_FM_DEVICE_INTERN_CORR,
194						DDI_SERVICE_UNAFFECTED},
195	{NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN,	"rxzcopy_rrfifo_overrun",
196						DDI_FM_DEVICE_INVAL_STATE,
197						DDI_SERVICE_UNAFFECTED},
198	{NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW,	"rxzcopy_buffer_overflow",
199						DDI_FM_DEVICE_INVAL_STATE,
200						DDI_SERVICE_LOST},
201	{NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR,	"rxzcopy_tt_program_err",
202						DDI_FM_DEVICE_INVAL_STATE,
203						DDI_SERVICE_UNAFFECTED},
204	{NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR,	"rxzcopy_rsp_tt_index_err",
205						DDI_FM_DEVICE_INVAL_STATE,
206						DDI_SERVICE_UNAFFECTED},
207	{NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR,	"rxzcopy_slv_tt_index_err",
208						DDI_FM_DEVICE_INVAL_STATE,
209						DDI_SERVICE_UNAFFECTED},
210	{NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR,	"rxzcopy_tt_index_err",
211						DDI_FM_DEVICE_INVAL_STATE,
212						DDI_SERVICE_UNAFFECTED},
213	{NXGE_FM_EREPORT_ZCP_ACCESS_FAIL,	"rxzcopy_access_fail",
214						DDI_FM_DEVICE_NO_RESPONSE,
215						DDI_SERVICE_LOST},
216};
217
218nxge_fm_ereport_attr_t nxge_fm_ereport_rxmac[] = {
219	{NXGE_FM_EREPORT_RXMAC_UNDERFLOW,	"rxmac_underflow",
220						DDI_FM_DEVICE_INVAL_STATE,
221						DDI_SERVICE_UNAFFECTED},
222	{NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP,	"rxmac_crc_errcnt_exp",
223						DDI_FM_DEVICE_INTERN_UNCORR,
224						DDI_SERVICE_UNAFFECTED},
225	{NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP,
226						"rxmac_length_errcnt_exp",
227						DDI_FM_DEVICE_INTERN_UNCORR,
228						DDI_SERVICE_UNAFFECTED},
229	{NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP,	"rxmac_viol_errcnt_exp",
230						DDI_FM_DEVICE_INTERN_UNCORR,
231						DDI_SERVICE_UNAFFECTED},
232	{NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP,	"rxmac_rxfrag_cnt_exp",
233						DDI_FM_DEVICE_INTERN_UNCORR,
234						DDI_SERVICE_UNAFFECTED},
235	{NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP,	"rxmac_align_ecnt_exp",
236						DDI_FM_DEVICE_INTERN_UNCORR,
237						DDI_SERVICE_UNAFFECTED},
238	{NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP,
239						"rxmac_linkfault_cnt_exp",
240						DDI_FM_DEVICE_INTERN_UNCORR,
241						DDI_SERVICE_UNAFFECTED},
242	{NXGE_FM_EREPORT_RXMAC_RESET_FAIL,	"rxmac_reset_fail",
243						DDI_FM_DEVICE_NO_RESPONSE,
244						DDI_SERVICE_UNAFFECTED},
245};
246
247nxge_fm_ereport_attr_t nxge_fm_ereport_tdmc[] = {
248	{NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR,	"txdma_pref_buf_par_err",
249						DDI_FM_DEVICE_INTERN_UNCORR,
250						DDI_SERVICE_DEGRADED},
251	{NXGE_FM_EREPORT_TDMC_MBOX_ERR,		"txdma_mbox_err",
252						DDI_FM_DEVICE_NO_RESPONSE,
253						DDI_SERVICE_DEGRADED},
254	{NXGE_FM_EREPORT_TDMC_NACK_PREF,	"txdma_nack_pref",
255						DDI_FM_DEVICE_NO_RESPONSE,
256						DDI_SERVICE_DEGRADED},
257	{NXGE_FM_EREPORT_TDMC_NACK_PKT_RD,	"txdma_nack_pkt_rd",
258						DDI_FM_DEVICE_NO_RESPONSE,
259						DDI_SERVICE_DEGRADED},
260	{NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR,	"txdma_pkt_size_err",
261						DDI_FM_DEVICE_INVAL_STATE,
262						DDI_SERVICE_DEGRADED},
263	{NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW,	"txdma_tx_ring_oflow",
264						DDI_FM_DEVICE_INVAL_STATE,
265						DDI_SERVICE_DEGRADED},
266	{NXGE_FM_EREPORT_TDMC_CONF_PART_ERR,	"txdma_conf_part_err",
267						DDI_FM_DEVICE_INVAL_STATE,
268						DDI_SERVICE_DEGRADED},
269	{NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR,	"txdma_pkt_prt_err",
270						DDI_FM_DEVICE_INTERN_UNCORR,
271						DDI_SERVICE_DEGRADED},
272	{NXGE_FM_EREPORT_TDMC_RESET_FAIL,	"txdma_reset_fail",
273						DDI_FM_DEVICE_NO_RESPONSE,
274						DDI_SERVICE_LOST},
275};
276
277nxge_fm_ereport_attr_t nxge_fm_ereport_txc[] = {
278	{NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR,	"tx_ro_correct_err",
279						DDI_FM_DEVICE_INTERN_CORR,
280						DDI_SERVICE_UNAFFECTED},
281	{NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR,	"tx_ro_uncorrect_err",
282						DDI_FM_DEVICE_INTERN_UNCORR,
283						DDI_SERVICE_UNAFFECTED},
284	{NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR,	"tx_sf_correct_err",
285						DDI_FM_DEVICE_INTERN_CORR,
286						DDI_SERVICE_UNAFFECTED},
287	{NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR,	"tx_sf_uncorrect_err",
288						DDI_FM_DEVICE_INTERN_UNCORR,
289						DDI_SERVICE_UNAFFECTED},
290	{NXGE_FM_EREPORT_TXC_ASSY_DEAD,		"tx_assembly_uncorrect_err",
291						DDI_FM_DEVICE_INTERN_UNCORR,
292						DDI_SERVICE_UNAFFECTED},
293	{NXGE_FM_EREPORT_TXC_REORDER_ERR,	"tx_reorder_err",
294						DDI_FM_DEVICE_INVAL_STATE,
295						DDI_SERVICE_LOST},
296};
297
298nxge_fm_ereport_attr_t nxge_fm_ereport_txmac[] = {
299	{NXGE_FM_EREPORT_TXMAC_UNDERFLOW,	"txmac_underflow",
300						DDI_FM_DEVICE_INVAL_STATE,
301						DDI_SERVICE_UNAFFECTED},
302	{NXGE_FM_EREPORT_TXMAC_OVERFLOW,	"txmac_overflow",
303						DDI_FM_DEVICE_INVAL_STATE,
304						DDI_SERVICE_UNAFFECTED},
305	{NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR,	"txmac_txfifo_xfr_err",
306						DDI_FM_DEVICE_INVAL_STATE,
307						DDI_SERVICE_UNAFFECTED},
308	{NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR,	"txmac_max_pkt_err",
309						DDI_FM_DEVICE_INTERN_UNCORR,
310						DDI_SERVICE_UNAFFECTED},
311	{NXGE_FM_EREPORT_TXMAC_RESET_FAIL,	"txmac_reset_fail",
312						DDI_FM_DEVICE_NO_RESPONSE,
313						DDI_SERVICE_UNAFFECTED},
314};
315
316nxge_fm_ereport_attr_t nxge_fm_ereport_espc[] = {
317	{NXGE_FM_EREPORT_ESPC_ACCESS_FAIL,	"eprom_access_fail",
318						DDI_FM_DEVICE_NO_RESPONSE,
319						DDI_SERVICE_LOST},
320};
321
322nxge_fm_ereport_attr_t nxge_fm_ereport_xaui[] = {
323	{NXGE_FM_EREPORT_XAUI_ERR,		"xaui_bad_or_missing",
324						NXGE_FM_DEVICE_XAUI_ERR,
325						DDI_SERVICE_LOST},
326};
327
328nxge_fm_ereport_attr_t nxge_fm_ereport_xfp[] = {
329	{NXGE_FM_EREPORT_XFP_ERR,		"xfp_bad_or_missing",
330						NXGE_FM_DEVICE_XFP_ERR,
331						DDI_SERVICE_LOST},
332};
333
334nxge_fm_ereport_attr_t nxge_fm_ereport_sw[] = {
335	{NXGE_FM_EREPORT_SW_INVALID_PORT_NUM,	"invalid_port_num",
336						DDI_FM_DEVICE_INVAL_STATE,
337						DDI_SERVICE_LOST},
338	{NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM,	"invalid_chan_num",
339						DDI_FM_DEVICE_INVAL_STATE,
340						DDI_SERVICE_LOST},
341	{NXGE_FM_EREPORT_SW_INVALID_PARAM,	"invalid_param",
342						DDI_FM_DEVICE_INVAL_STATE,
343						DDI_SERVICE_LOST},
344};
345
346void
347nxge_fm_init(p_nxge_t nxgep, ddi_device_acc_attr_t *reg_attr,
348	ddi_dma_attr_t *dma_attr)
349{
350	ddi_iblock_cookie_t iblk;
351
352	/*
353	 * fm-capable in nxge.conf can be used to set fm_capabilities.
354	 * If fm-capable is not defined, then the last argument passed to
355	 * ddi_prop_get_int will be returned as the capabilities.
356	 */
357	nxgep->fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, nxgep->dip,
358	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "fm-capable",
359	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE);
360
361	NXGE_ERROR_MSG((nxgep, DDI_CTL,
362	    "FM capable = %d\n", nxgep->fm_capabilities));
363
364	if (isLDOMguest(nxgep)) {
365		nxgep->fm_capabilities = DDI_FM_NOT_CAPABLE;
366		return;
367	}
368
369	/*
370	 * Register capabilities with IO Fault Services. The capabilities
371	 * set above may not be supported by the parent nexus, in that case
372	 * some capability bits may be cleared.
373	 */
374	if (nxgep->fm_capabilities)
375		ddi_fm_init(nxgep->dip, &nxgep->fm_capabilities, &iblk);
376
377	/*
378	 * Initialize pci ereport capabilities if ereport capable
379	 */
380	if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
381	    DDI_FM_ERRCB_CAP(nxgep->fm_capabilities)) {
382		pci_ereport_setup(nxgep->dip);
383	}
384
385	/* Register error callback if error callback capable */
386	if (DDI_FM_ERRCB_CAP(nxgep->fm_capabilities)) {
387		ddi_fm_handler_register(nxgep->dip,
388		    nxge_fm_error_cb, (void*) nxgep);
389	}
390
391	/*
392	 * DDI_FLGERR_ACC indicates:
393	 * o Driver will check its access handle(s) for faults on
394	 *   a regular basis by calling ddi_fm_acc_err_get
395	 * o Driver is able to cope with incorrect results of I/O
396	 *   operations resulted from an I/O fault
397	 */
398	if (DDI_FM_ACC_ERR_CAP(nxgep->fm_capabilities)) {
399		reg_attr->devacc_attr_access  = DDI_FLAGERR_ACC;
400	} else {
401		reg_attr->devacc_attr_access  = DDI_DEFAULT_ACC;
402	}
403
404	/*
405	 * DDI_DMA_FLAGERR indicates:
406	 * o Driver will check its DMA handle(s) for faults on a
407	 *   regular basis using ddi_fm_dma_err_get
408	 * o Driver is able to cope with incorrect results of DMA
409	 *   operations resulted from an I/O fault
410	 */
411	if (DDI_FM_DMA_ERR_CAP(nxgep->fm_capabilities))
412		dma_attr->dma_attr_flags |= DDI_DMA_FLAGERR;
413	else
414		dma_attr->dma_attr_flags &= ~DDI_DMA_FLAGERR;
415
416}
417
418void
419nxge_fm_fini(p_nxge_t nxgep)
420{
421	/* Only unregister FMA capabilities if we registered some */
422	if (nxgep->fm_capabilities) {
423
424		/*
425		 * Release any resources allocated by pci_ereport_setup()
426		 */
427		if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
428		    DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
429			pci_ereport_teardown(nxgep->dip);
430
431		/*
432		 * Un-register error callback if error callback capable
433		 */
434		if (DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
435			ddi_fm_handler_unregister(nxgep->dip);
436
437		/* Unregister from IO Fault Services */
438		ddi_fm_fini(nxgep->dip);
439	}
440}
441
442/*ARGSUSED*/
443/*
444 * Simply call pci_ereport_post which generates ereports for errors
445 * that occur in the PCI local bus configuration status registers.
446 */
447static int
448nxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
449	const void *impl_data)
450{
451	pci_ereport_post(dip, err, NULL);
452	return (err->fme_status);
453}
454
455
456static nxge_fm_ereport_attr_t *
457nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t ereport_id)
458{
459	nxge_fm_ereport_attr_t *attr;
460	uint8_t	blk_id = (ereport_id >> EREPORT_FM_ID_SHIFT) &
461	    EREPORT_FM_ID_MASK;
462	uint8_t index = ereport_id & EREPORT_INDEX_MASK;
463
464	switch (blk_id) {
465	case FM_SW_ID:
466		attr = &nxge_fm_ereport_sw[index];
467		break;
468	case FM_PCS_ID:
469		attr = &nxge_fm_ereport_pcs[index];
470		break;
471	case FM_TXMAC_ID:
472		attr = &nxge_fm_ereport_txmac[index];
473		break;
474	case FM_RXMAC_ID:
475		attr = &nxge_fm_ereport_rxmac[index];
476		break;
477	case FM_MIF_ID:
478		attr = &nxge_fm_ereport_mif[index];
479		break;
480	case FM_FFLP_ID:
481		attr = &nxge_fm_ereport_fflp[index];
482		break;
483	case FM_ZCP_ID:
484		attr = &nxge_fm_ereport_zcp[index];
485		break;
486	case FM_RXDMA_ID:
487		attr = &nxge_fm_ereport_rdmc[index];
488		break;
489	case FM_TXDMA_ID:
490		attr = &nxge_fm_ereport_tdmc[index];
491		break;
492	case FM_IPP_ID:
493		attr = &nxge_fm_ereport_ipp[index];
494		break;
495	case FM_TXC_ID:
496		attr = &nxge_fm_ereport_txc[index];
497		break;
498	case FM_ESPC_ID:
499		attr = &nxge_fm_ereport_espc[index];
500		break;
501	case FM_XAUI_ID:
502		attr = &nxge_fm_ereport_xaui[index];
503		break;
504	case FM_XFP_ID:
505		attr = &nxge_fm_ereport_xfp[index];
506		break;
507	default:
508		attr = NULL;
509	}
510
511	return (attr);
512}
513
514static void
515nxge_fm_ereport(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
516					nxge_fm_ereport_attr_t *ereport)
517{
518	uint64_t		ena;
519	char			eclass[FM_MAX_CLASS];
520	char			*err_str;
521	p_nxge_stats_t		statsp;
522
523	(void) snprintf(eclass, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE,
524	    ereport->eclass);
525	err_str = ereport->str;
526	ena = fm_ena_generate(0, FM_ENA_FMT1);
527	statsp = nxgep->statsp;
528
529	switch (ereport->index) {
530		case NXGE_FM_EREPORT_XPCS_LINK_DOWN:
531		case NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT:
532		case NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT:
533		case NXGE_FM_EREPORT_PCS_LINK_DOWN:
534		case NXGE_FM_EREPORT_PCS_REMOTE_FAULT:
535			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
536			    DDI_NOSLEEP,
537			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
538			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
539			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
540			    NULL);
541			break;
542		case NXGE_FM_EREPORT_IPP_EOP_MISS:
543		case NXGE_FM_EREPORT_IPP_SOP_MISS:
544			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
545			    DDI_NOSLEEP,
546			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
547			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
548			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
549			    ERNAME_DFIFO_RD_PTR, DATA_TYPE_UINT16,
550			    statsp->ipp_stats.errlog.dfifo_rd_ptr,
551			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
552			    statsp->ipp_stats.errlog.state_mach,
553			    NULL);
554			break;
555		case NXGE_FM_EREPORT_IPP_DFIFO_UE:
556			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
557			    DDI_NOSLEEP,
558			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
559			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
560			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
561			    ERNAME_DFIFO_ENTRY, DATA_TYPE_UINT16,
562			    nxgep->ipp.status.bits.w0.dfifo_ecc_err_idx,
563			    ERNAME_DFIFO_SYNDROME, DATA_TYPE_UINT16,
564			    statsp->ipp_stats.errlog.ecc_syndrome,
565			    NULL);
566			break;
567		case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
568			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
569			    DDI_NOSLEEP,
570			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
571			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
572			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
573			    ERNAME_PFIFO_ENTRY, DATA_TYPE_UINT8,
574			    nxgep->ipp.status.bits.w0.pre_fifo_perr_idx,
575			    NULL);
576			break;
577		case NXGE_FM_EREPORT_IPP_DFIFO_CE:
578		case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
579			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
580			    DDI_NOSLEEP,
581			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
582			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
583			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
584			    NULL);
585			break;
586		case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
587		case NXGE_FM_EREPORT_IPP_PFIFO_UND:
588			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
589			    DDI_NOSLEEP,
590			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
591			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
592			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
593			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
594			    statsp->ipp_stats.errlog.state_mach,
595			    NULL);
596			break;
597		case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
598		case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
599			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
600			    DDI_NOSLEEP,
601			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
602			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
603			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
604			    NULL);
605			break;
606		case NXGE_FM_EREPORT_FFLP_TCAM_ERR:
607			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
608			    DDI_NOSLEEP,
609			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
610			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
611			    ERNAME_TCAM_ERR_LOG, DATA_TYPE_UINT32,
612			    statsp->fflp_stats.errlog.tcam,
613			    NULL);
614			break;
615		case NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR:
616			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
617			    DDI_NOSLEEP,
618			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
619			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
620			    ERNAME_VLANTAB_ERR_LOG, DATA_TYPE_UINT32,
621			    statsp->fflp_stats.errlog.vlan,
622			    NULL);
623			break;
624		case NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR:
625		{
626			int rdc_grp;
627			hash_tbl_data_log_t hash_log;
628
629			for (rdc_grp = 0; rdc_grp < MAX_PARTITION; rdc_grp++) {
630				hash_log.value = nxgep->classifier.fflp_stats->
631				    errlog.hash_pio[rdc_grp];
632				if (hash_log.bits.ldw.pio_err) {
633					ddi_fm_ereport_post(nxgep->dip, eclass,
634					    ena, DDI_NOSLEEP,
635					    FM_VERSION, DATA_TYPE_UINT8,
636					    FM_EREPORT_VERS0,
637					    ERNAME_DETAILED_ERR_TYPE,
638					    DATA_TYPE_STRING, err_str,
639					    ERNAME_HASHTAB_ERR_LOG,
640					    DATA_TYPE_UINT32,
641					    nxgep->classifier.fflp_stats->
642					    errlog.hash_pio[rdc_grp], NULL);
643				}
644			}
645		}
646			break;
647		case NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR:
648			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
649			    DDI_NOSLEEP,
650			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
651			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
652			    ERNAME_HASHT_LOOKUP_ERR_LOG0, DATA_TYPE_UINT32,
653			    statsp->fflp_stats.errlog. hash_lookup1,
654			    ERNAME_HASHT_LOOKUP_ERR_LOG1, DATA_TYPE_UINT32,
655			    statsp->fflp_stats.errlog.hash_lookup2,
656			    NULL);
657			break;
658		case NXGE_FM_EREPORT_RDMC_DCF_ERR:
659		case NXGE_FM_EREPORT_RDMC_RBR_TMOUT:
660		case NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR:
661		case NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS:
662		case NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR:
663		case NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR:
664		case NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR:
665		case NXGE_FM_EREPORT_RDMC_CONFIG_ERR:
666		case NXGE_FM_EREPORT_RDMC_RCRINCON:
667		case NXGE_FM_EREPORT_RDMC_RCRFULL:
668		case NXGE_FM_EREPORT_RDMC_RBRFULL:
669		case NXGE_FM_EREPORT_RDMC_RBRLOGPAGE:
670		case NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE:
671		case NXGE_FM_EREPORT_RDMC_ID_MISMATCH:
672		case NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR:
673		case NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR:
674			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
675			    DDI_NOSLEEP,
676			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
677			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
678			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
679			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
680			    NULL);
681			break;
682		case NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
683		case NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR:
684			{
685			uint32_t err_log;
686			if (ereport->index == NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
687				err_log = (uint32_t)statsp->
688				    rdc_stats[err_chan].errlog.pre_par.value;
689			else
690				err_log = (uint32_t)statsp->
691				    rdc_stats[err_chan].errlog.sha_par.value;
692			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
693			    DDI_NOSLEEP,
694			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
695			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
696			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
697			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
698			    ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8, err_log,
699			    NULL);
700			}
701			break;
702		case NXGE_FM_EREPORT_RDMC_RCR_ERR:
703			{
704			uint8_t err_type;
705			err_type = statsp->
706			    rdc_stats[err_chan].errlog.compl_err_type;
707			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
708			    DDI_NOSLEEP,
709			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
710			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
711			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
712			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
713			    ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8, err_type,
714			    NULL);
715			}
716			break;
717
718		case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
719		case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
720		case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
721			{
722			uint32_t sm;
723			sm = statsp->
724			    zcp_stats.errlog.state_mach.bits.ldw.state;
725			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
726			    DDI_NOSLEEP,
727			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
728			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
729			    sm, DATA_TYPE_UINT32,
730			    NULL);
731			break;
732			}
733		case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
734			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
735			    DDI_NOSLEEP,
736			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
737			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
738			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
739			    NULL);
740			break;
741		case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
742		case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
743		case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
744		case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
745		case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
746		case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
747		case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
748		case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
749		case NXGE_FM_EREPORT_RXMAC_UNDERFLOW:
750		case NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP:
751		case NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP:
752		case NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP:
753		case NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP:
754		case NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP:
755		case NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP:
756			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
757			    DDI_NOSLEEP,
758			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
759			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
760			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
761			    NULL);
762			break;
763		case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
764		case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
765			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
766			    DDI_NOSLEEP,
767			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
768			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
769			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
770			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
771			    NULL);
772			break;
773		case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
774		case NXGE_FM_EREPORT_TDMC_NACK_PREF:
775		case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
776		case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
777		case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
778		case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
779			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
780			    DDI_NOSLEEP,
781			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
782			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
783			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
784			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
785			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
786			    statsp->tdc_stats[err_chan].errlog.logl.value,
787			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
788			    statsp->tdc_stats[err_chan].errlog.logh.value,
789			    DATA_TYPE_UINT32,
790			    NULL);
791			break;
792		case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
793		case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
794			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
795			    DDI_NOSLEEP,
796			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
797			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
798			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
799			    ERNAME_TXC_ROECC_ADDR, DATA_TYPE_UINT16,
800			    statsp->txc_stats.errlog.ro_st.roecc.
801			    bits.ldw.ecc_address,
802			    ERNAME_TXC_ROECC_DATA0, DATA_TYPE_UINT32,
803			    statsp->txc_stats.errlog.ro_st.d0.
804			    bits.ldw.ro_ecc_data0,
805			    ERNAME_TXC_ROECC_DATA1, DATA_TYPE_UINT32,
806			    statsp->txc_stats.errlog.ro_st.d1.
807			    bits.ldw.ro_ecc_data1,
808			    ERNAME_TXC_ROECC_DATA2, DATA_TYPE_UINT32,
809			    statsp->txc_stats.errlog.ro_st.d2.
810			    bits.ldw.ro_ecc_data2,
811			    ERNAME_TXC_ROECC_DATA3, DATA_TYPE_UINT32,
812			    statsp->txc_stats.errlog.ro_st.d3.
813			    bits.ldw.ro_ecc_data3,
814			    ERNAME_TXC_ROECC_DATA4, DATA_TYPE_UINT32,
815			    statsp->txc_stats.errlog.ro_st.d4.
816			    bits.ldw.ro_ecc_data4,
817			    NULL);
818			break;
819		case NXGE_FM_EREPORT_TXC_REORDER_ERR:
820			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
821			    DDI_NOSLEEP,
822			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
823			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
824			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
825			    ERNAME_TXC_RO_STATE0, DATA_TYPE_UINT32,
826			    (uint32_t)statsp->txc_stats.errlog.ro_st.st0.value,
827			    ERNAME_TXC_RO_STATE1, DATA_TYPE_UINT32,
828			    (uint32_t)statsp->txc_stats.errlog.ro_st.st1.value,
829			    ERNAME_TXC_RO_STATE2, DATA_TYPE_UINT32,
830			    (uint32_t)statsp->txc_stats.errlog.ro_st.st2.value,
831			    ERNAME_TXC_RO_STATE3, DATA_TYPE_UINT32,
832			    (uint32_t)statsp->txc_stats.errlog.ro_st.st3.value,
833			    ERNAME_TXC_RO_STATE_CTL, DATA_TYPE_UINT32,
834			    (uint32_t)statsp->txc_stats.errlog.ro_st.ctl.value,
835			    ERNAME_TXC_RO_TIDS, DATA_TYPE_UINT32,
836			    (uint32_t)statsp->txc_stats.errlog.ro_st.tids.value,
837			    NULL);
838			break;
839		case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
840		case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
841			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
842			    DDI_NOSLEEP,
843			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
844			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
845			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
846			    ERNAME_TXC_SFECC_ADDR, DATA_TYPE_UINT32,
847			    statsp->txc_stats.errlog.sf_st.sfecc.
848			    bits.ldw.ecc_address,
849			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
850			    statsp->txc_stats.errlog.sf_st.d0.
851			    bits.ldw.sf_ecc_data0,
852			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
853			    statsp->txc_stats.errlog.sf_st.d1.
854			    bits.ldw.sf_ecc_data1,
855			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
856			    statsp->txc_stats.errlog.sf_st.d2.
857			    bits.ldw.sf_ecc_data2,
858			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
859			    statsp->txc_stats.errlog.sf_st.d3.
860			    bits.ldw.sf_ecc_data3,
861			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
862			    statsp->txc_stats.errlog.sf_st.d4.
863			    bits.ldw.sf_ecc_data4,
864			    NULL);
865			break;
866		case NXGE_FM_EREPORT_TXMAC_UNDERFLOW:
867		case NXGE_FM_EREPORT_TXMAC_OVERFLOW:
868		case NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR:
869		case NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR:
870		case NXGE_FM_EREPORT_XAUI_ERR:
871		case NXGE_FM_EREPORT_XFP_ERR:
872		case NXGE_FM_EREPORT_SW_INVALID_PORT_NUM:
873		case NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
874		case NXGE_FM_EREPORT_SW_INVALID_PARAM:
875			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
876			    DDI_NOSLEEP,
877			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
878			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
879			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
880			    NULL);
881			break;
882	}
883}
884
885void
886nxge_fm_report_error(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
887					nxge_fm_ereport_id_t fm_ereport_id)
888{
889	nxge_fm_ereport_attr_t		*fm_ereport_attr;
890
891	fm_ereport_attr = nxge_fm_get_ereport_attr(fm_ereport_id);
892	if (fm_ereport_attr != NULL &&
893	    (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities))) {
894		nxge_fm_ereport(nxgep, err_portn, err_chan, fm_ereport_attr);
895		ddi_fm_service_impact(nxgep->dip, fm_ereport_attr->impact);
896	}
897}
898
899int
900fm_check_acc_handle(ddi_acc_handle_t handle)
901{
902	ddi_fm_error_t err;
903
904	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
905#ifndef	NXGE_FM_S10
906	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
907#endif
908	return (err.fme_status);
909}
910
911int
912fm_check_dma_handle(ddi_dma_handle_t handle)
913{
914	ddi_fm_error_t err;
915
916	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
917	return (err.fme_status);
918}
919