fabric-xlate.c revision 6392:f12303b590d6
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/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <assert.h>
29#include <stddef.h>
30#include <strings.h>
31#include <fm/fmd_api.h>
32#include <fm/libtopo.h>
33#include <sys/fm/util.h>
34#include <sys/fm/protocol.h>
35#include <sys/fm/io/pci.h>
36#include <sys/fm/io/sun4_fire.h>
37#include <sys/pci.h>
38#include <sys/pcie.h>
39#include <sys/nvpair.h>
40#include <sys/nvpair_impl.h>
41
42#include <libxml/xpath.h>
43#include <libxml/parser.h>
44#include <libxml/xpathInternals.h>
45#include <libxml/tree.h>
46
47/* PCI-E config space data for error handling and fabric ereports */
48typedef struct fab_data {
49	/* Original ereport NVL */
50	nvlist_t	*nvl;
51
52	/* Device Information */
53	uint16_t bdf;
54	uint16_t device_id;
55	uint16_t vendor_id;
56	uint8_t rev_id;
57	uint16_t dev_type;
58	uint16_t pcie_off;
59	uint16_t pcix_off;
60	uint16_t aer_off;
61	uint16_t ecc_ver;
62
63	/* Ereport Information */
64	uint32_t remainder;
65	uint32_t severity;
66
67	/* Error Registers */
68	uint16_t pci_err_status;	/* pci status register */
69	uint16_t pci_cfg_comm;		/* pci command register */
70
71	uint16_t pci_bdg_sec_stat;	/* PCI secondary status reg */
72	uint16_t pci_bdg_ctrl;		/* PCI bridge control reg */
73
74	uint16_t pcix_command;		/* pcix command register */
75	uint32_t pcix_status;		/* pcix status register */
76
77	uint16_t pcix_bdg_sec_stat;	/* pcix bridge secondary status reg */
78	uint32_t pcix_bdg_stat;		/* pcix bridge status reg */
79
80	uint16_t pcix_ecc_control_0;	/* pcix ecc control status reg */
81	uint16_t pcix_ecc_status_0;	/* pcix ecc control status reg */
82	uint32_t pcix_ecc_fst_addr_0;	/* pcix ecc first address reg */
83	uint32_t pcix_ecc_sec_addr_0;	/* pcix ecc second address reg */
84	uint32_t pcix_ecc_attr_0;	/* pcix ecc attributes reg */
85	uint16_t pcix_ecc_control_1;	/* pcix ecc control status reg */
86	uint16_t pcix_ecc_status_1;	/* pcix ecc control status reg */
87	uint32_t pcix_ecc_fst_addr_1;	/* pcix ecc first address reg */
88	uint32_t pcix_ecc_sec_addr_1;	/* pcix ecc second address reg */
89	uint32_t pcix_ecc_attr_1;	/* pcix ecc attributes reg */
90
91	uint16_t pcie_err_status;	/* pcie device status register */
92	uint16_t pcie_err_ctl;		/* pcie error control register */
93	uint32_t pcie_dev_cap;		/* pcie device capabilities register */
94
95	uint32_t pcie_adv_ctl;		/* pcie advanced control reg */
96	uint32_t pcie_ue_status;	/* pcie ue error status reg */
97	uint32_t pcie_ue_mask;		/* pcie ue error mask reg */
98	uint32_t pcie_ue_sev;		/* pcie ue error severity reg */
99	uint32_t pcie_ue_hdr[4];	/* pcie ue header log */
100	uint32_t pcie_ce_status;	/* pcie ce error status reg */
101	uint32_t pcie_ce_mask;		/* pcie ce error mask reg */
102	uint32_t pcie_ue_tgt_trans;	/* Fault trans type from AER Logs */
103	uint64_t pcie_ue_tgt_addr;	/* Fault addr from AER Logs */
104	pcie_req_id_t pcie_ue_tgt_bdf;	/* Fault bdf from SAER Logs */
105
106	uint32_t pcie_sue_ctl;		/* pcie bridge secondary ue control */
107	uint32_t pcie_sue_status;	/* pcie bridge secondary ue status */
108	uint32_t pcie_sue_mask;		/* pcie bridge secondary ue mask */
109	uint32_t pcie_sue_sev;		/* pcie bridge secondary ue severity */
110	uint32_t pcie_sue_hdr[4];	/* pcie bridge secondary ue hdr log */
111	uint32_t pcie_sue_tgt_trans;	/* Fault trans type from AER Logs */
112	uint64_t pcie_sue_tgt_addr;	/* Fault addr from AER Logs */
113	pcie_req_id_t pcie_sue_tgt_bdf;	/* Fault bdf from SAER Logs */
114
115	uint32_t pcie_rp_status;	/* root complex status register */
116	uint16_t pcie_rp_ctl;		/* root complex control register */
117	uint32_t pcie_rp_err_status;	/* pcie root complex error status reg */
118	uint32_t pcie_rp_err_cmd;	/* pcie root complex error cmd reg */
119	uint16_t pcie_rp_ce_src_id;	/* pcie root complex ce sourpe id */
120	uint16_t pcie_rp_ue_src_id;	/* pcie root complex ue sourpe id */
121} fab_data_t;
122
123/*
124 * These values are used for the xxx_tgt_trans value in fab_data_t.  They are
125 * originally set in pcie_fault.c and originally defined in pcie_impl.h.
126 */
127#define	PF_ADDR_DMA		(1 << 0)
128#define	PF_ADDR_PIO		(1 << 1)
129#define	PF_ADDR_CFG		(1 << 2)
130
131typedef struct fab_erpt_tbl {
132	const char	*err_class;	/* Final Ereport Class */
133	uint32_t	reg_bit;	/* Error Bit Mask */
134	/* Pointer to function that prepares the ereport body */
135	const char	*tgt_class;	/* Target Ereport Class */
136} fab_erpt_tbl_t;
137
138typedef struct fab_err_tbl {
139	fab_erpt_tbl_t	*erpt_tbl;	/* ereport table */
140	uint32_t	reg_offset;	/* sts reg for ereport table offset */
141	uint32_t	reg_size;	/* size of the status register */
142	/* Pointer to function that prepares the ereport body */
143	int		(*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *,
144	    fab_erpt_tbl_t *);
145} fab_err_tbl_t;
146
147typedef struct fab_fire_tbl {
148	const char	*err_class;
149	uint32_t	fire_bit;	/* Fire error bit */
150	uint16_t	pci_err_sts;	/* Equivalent PCI Error Status */
151	uint16_t	pci_bdg_sts;	/* Equivalent PCI Bridge Status */
152} fab_fire_tbl_t;
153
154/* Static FM Topo XML Format and XML XPath Context  */
155static xmlDocPtr		fab_doc = NULL;
156static xmlXPathContextPtr	fab_xpathCtx = NULL;
157static int			fab_valid_topo = 0;
158#define	XMLTOPOFILE "/tmp/fab-xlate-topo.xml"
159
160/* Functions that convert ereports to a common C data structure */
161static void fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl,
162    fab_data_t *data);
163static void fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data);
164
165/* Common functions for sending translated ereports */
166static int fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
167    boolean_t isRC);
168static void fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath);
169static char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr);
170static char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf);
171static void fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data,
172    const char *class, boolean_t isPrimary);
173static void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl);
174
175/*
176 * Common functions for converting  pci.fabric classes of
177 * ereports
178 */
179static int fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data,
180    nvlist_t *erpt, fab_erpt_tbl_t *table);
181static int fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data,
182    nvlist_t *erpt, fab_erpt_tbl_t *table);
183static int fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data,
184    nvlist_t *erpt, fab_erpt_tbl_t *table);
185static int fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data,
186    nvlist_t *erpt, fab_erpt_tbl_t *table);
187static int fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data,
188    nvlist_t *erpt, fab_erpt_tbl_t *table);
189static int fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data,
190    nvlist_t *erpt, fab_erpt_tbl_t *table);
191static int fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data,
192    nvlist_t *erpt, fab_erpt_tbl_t *table);
193static int fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data,
194    nvlist_t *erpt, fab_erpt_tbl_t *table);
195static void fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data);
196static int fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data,
197    nvlist_t *erpt, fab_erpt_tbl_t *table);
198static void fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data);
199static int fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data,
200    nvlist_t *erpt, fab_erpt_tbl_t *table);
201static int fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data,
202    nvlist_t *erpt, fab_erpt_tbl_t *table);
203
204/* Functions for converting fire specific error registers */
205static int fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
206    const char *class);
207static int fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
208    const char *class);
209static int fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
210    const char *class);
211static int fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
212    const char *class);
213
214/* Main functions for converting "fabric" ereports */
215static void fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data);
216static void fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data,
217    nvlist_t *nvl, const char *class);
218
219/*
220 * Translation tables for converting "fabric" error bits into "pci" ereports.
221 * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function>
222 */
223
224/* MACRO for table entries with no TGT ereports */
225#define	NT(class, bit, prep) class, bit, prep, NULL
226/* Translate Fabric ereports to ereport.io.pci.* */
227static fab_erpt_tbl_t fab_pci_erpt_tbl[] = {
228	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
229	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
230	PCI_SIG_SERR,		PCI_STAT_S_SYSERR,	NULL,
231	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
232	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
233	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
234	NULL, NULL, NULL
235};
236
237/* Translate Fabric ereports to ereport.io.pci.sec-* */
238static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = {
239	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
240	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
241	PCI_REC_SERR,		PCI_STAT_S_SYSERR,	NULL,
242#ifdef sparc
243	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
244#endif
245	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
246	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
247	NULL, NULL, NULL, NULL,
248};
249
250
251/* Translate Fabric ereports to ereport.io.pci.dto */
252static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
253	PCI_DTO,	PCI_BCNF_BCNTRL_DTO_STAT,	NULL,
254	NULL, NULL, NULL
255};
256
257/* Translate Fabric ereports to ereport.io.pciex.* */
258static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = {
259	PCIEX_RE,	PCIE_AER_CE_RECEIVER_ERR,	NULL,
260	PCIEX_RNR,	PCIE_AER_CE_REPLAY_ROLLOVER,	NULL,
261	PCIEX_RTO,	PCIE_AER_CE_REPLAY_TO,		NULL,
262	PCIEX_BDP,	PCIE_AER_CE_BAD_DLLP,		NULL,
263	PCIEX_BTP,	PCIE_AER_CE_BAD_TLP,		NULL,
264	PCIEX_ANFE,	PCIE_AER_CE_AD_NFE,		NULL,
265	NULL, NULL, NULL
266};
267
268/* Translate Fabric ereports to ereport.io.pciex.* */
269static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = {
270	PCIEX_TE,	PCIE_AER_UCE_TRAINING,		NULL,
271	PCIEX_DLP,	PCIE_AER_UCE_DLP,		NULL,
272	PCIEX_SD,	PCIE_AER_UCE_SD,		NULL,
273	PCIEX_ROF,	PCIE_AER_UCE_RO,		NULL,
274	PCIEX_FCP,	PCIE_AER_UCE_FCP,		NULL,
275	PCIEX_MFP,	PCIE_AER_UCE_MTLP,		NULL,
276	PCIEX_CTO,	PCIE_AER_UCE_TO,		PCI_TARG_MA,
277	PCIEX_UC,	PCIE_AER_UCE_UC,		NULL,
278	PCIEX_ECRC,	PCIE_AER_UCE_ECRC,		NULL,
279	PCIEX_CA,	PCIE_AER_UCE_CA,		PCI_TARG_REC_TA,
280#ifdef sparc
281	PCIEX_UR,	PCIE_AER_UCE_UR,		PCI_TARG_MA,
282#endif
283	PCIEX_POIS,	PCIE_AER_UCE_PTLP,		PCI_TARG_MDPE,
284	NULL, NULL, NULL
285};
286
287/* Translate Fabric ereports to ereport.io.pciex.* */
288static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = {
289	PCIEX_S_TA_SC,	PCIE_AER_SUCE_TA_ON_SC,		PCI_TARG_REC_TA,
290	PCIEX_S_MA_SC,	PCIE_AER_SUCE_MA_ON_SC,		PCI_TARG_MA,
291	PCIEX_S_RTA,	PCIE_AER_SUCE_RCVD_TA,		PCI_TARG_REC_TA,
292#ifdef sparc
293	PCIEX_S_RMA,	PCIE_AER_SUCE_RCVD_MA,		PCI_TARG_MA,
294#endif
295	PCIEX_S_USC,	PCIE_AER_SUCE_USC_ERR,		NULL,
296	PCIEX_S_USCMD,	PCIE_AER_SUCE_USC_MSG_DATA_ERR,	PCI_TARG_REC_TA,
297	PCIEX_S_UDE,	PCIE_AER_SUCE_UC_DATA_ERR,	PCI_TARG_MDPE,
298	PCIEX_S_UAT,	PCIE_AER_SUCE_UC_ATTR_ERR,	PCI_TARG_MDPE,
299	PCIEX_S_UADR,	PCIE_AER_SUCE_UC_ADDR_ERR,	PCI_TARG_MDPE,
300	PCIEX_S_TEX,	PCIE_AER_SUCE_TIMER_EXPIRED,	NULL,
301	PCIEX_S_PERR,	PCIE_AER_SUCE_PERR_ASSERT,	PCI_TARG_MDPE,
302	PCIEX_S_SERR,	PCIE_AER_SUCE_SERR_ASSERT,	NULL,
303	PCIEX_INTERR,	PCIE_AER_SUCE_INTERNAL_ERR,	NULL,
304	NULL, NULL, NULL
305};
306
307/* Translate Fabric ereports to ereport.io.pcix.* */
308static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = {
309	PCIX_SPL_DIS,		PCI_PCIX_SPL_DSCD,	NULL,
310	PCIX_UNEX_SPL,		PCI_PCIX_UNEX_SPL,	NULL,
311	PCIX_RX_SPL_MSG,	PCI_PCIX_RX_SPL_MSG,	NULL,
312	NULL, NULL, NULL
313};
314static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
315
316/* Translate Fabric ereports to ereport.io.pcix.sec-* */
317static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = {
318	PCIX_SPL_DIS,		PCI_PCIX_BSS_SPL_DSCD,	NULL,
319	PCIX_UNEX_SPL,		PCI_PCIX_BSS_UNEX_SPL,	NULL,
320	PCIX_BSS_SPL_OR,	PCI_PCIX_BSS_SPL_OR,	NULL,
321	PCIX_BSS_SPL_DLY,	PCI_PCIX_BSS_SPL_DLY,	NULL,
322	NULL, NULL, NULL
323};
324
325/* Translate Fabric ereports to ereport.io.pciex.* */
326static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = {
327#ifdef sparc
328	PCIEX_UR,		PCIE_DEVSTS_UR_DETECTED,	NULL,
329#endif
330	PCIEX_FAT,		PCIE_DEVSTS_FE_DETECTED,	NULL,
331	PCIEX_NONFAT,		PCIE_DEVSTS_NFE_DETECTED,	NULL,
332	PCIEX_CORR,		PCIE_DEVSTS_CE_DETECTED,	NULL,
333	NULL, NULL, NULL
334};
335
336/* Translate Fabric ereports to ereport.io.pciex.* */
337static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = {
338	PCIEX_RC_FE_MSG,	PCIE_AER_RE_STS_FE_MSGS_RCVD,	NULL,
339	PCIEX_RC_NFE_MSG,	PCIE_AER_RE_STS_NFE_MSGS_RCVD,	NULL,
340	PCIEX_RC_CE_MSG,	PCIE_AER_RE_STS_CE_RCVD,	NULL,
341	PCIEX_RC_MCE_MSG,	PCIE_AER_RE_STS_MUL_CE_RCVD,	NULL,
342	PCIEX_RC_MUE_MSG,	PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL,
343	NULL, NULL, NULL
344};
345
346/*
347 * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages.
348 * If the RP is not a PCIe compliant RP or does not support AER, rely on the
349 * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC.
350 */
351static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = {
352	PCIEX_RC_FE_MSG,	PCIE_DEVSTS_FE_DETECTED,	NULL,
353	PCIEX_RC_NFE_MSG,	PCIE_DEVSTS_NFE_DETECTED,	NULL,
354	PCIEX_RC_CE_MSG,	PCIE_DEVSTS_CE_DETECTED,	NULL,
355	NULL, NULL, NULL,
356};
357
358static fab_err_tbl_t *fab_master_err_tbl;
359
360/*
361 * Translation tables for converting fire error bits into "pci" ereports.
362 * <Fire Bit>
363 * <pci ereport Class>
364 * <pci error status reg>
365 * <pci bridge status reg>
366 * <pci target class>
367 */
368#define	FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb
369#define	FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb
370#define	FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb
371#define	FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb
372
373#define	FAB_FIRE_UE(fb, bit, sts, bdg) \
374	FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
375#define	FAB_OB_UE(fb, bit, sts, bdg) \
376	FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
377static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = {
378	FAB_FIRE_UE(UR,	 UR,	   PCI_STAT_S_SYSERR,	0),
379	FAB_FIRE_UE(UC,	 UC,	   PCI_STAT_S_SYSERR,	0),
380	FAB_OB_UE(ECRC,	 ECRC,	   PCI_STAT_S_SYSERR,	0),
381	FAB_FIRE_UE(CTO, TO,	   PCI_STAT_S_SYSERR,	0),
382	FAB_FIRE_UE(ROF, RO,	   PCI_STAT_S_SYSERR,	0),
383	FAB_FIRE_UE(MFP, MTLP,	   PCI_STAT_S_SYSERR,	0),
384	FAB_FIRE_UE(PP,	 PTLP,	   PCI_STAT_S_PERROR,
385	    (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)),
386	FAB_FIRE_UE(FCP, FCP,	   PCI_STAT_S_SYSERR,	0),
387	FAB_FIRE_UE(DLP, DLP,	   PCI_STAT_S_SYSERR,	0),
388	FAB_FIRE_UE(TE,	 TRAINING, PCI_STAT_S_SYSERR,	0),
389	FAB_FIRE_UE(CA,	 CA,	   PCI_STAT_S_TARG_AB,
390	    PCI_STAT_S_TARG_AB),
391	NULL, NULL, NULL,
392};
393
394#define	FAB_FIRE_CE(fb, bit) \
395	FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0
396static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = {
397	FAB_FIRE_CE(RTO,	REPLAY_TO),
398	FAB_FIRE_CE(RNR,	REPLAY_ROLLOVER),
399	FAB_FIRE_CE(BDP,	BAD_DLLP),
400	FAB_FIRE_CE(BTP,	BAD_TLP),
401	FAB_FIRE_CE(RE,		RECEIVER_ERR),
402	NULL, NULL, NULL,
403};
404
405/*
406 * WUC/RUC will need to be special cased for the target ereports, because you
407 * need to decode the tlp log.
408 */
409#define	FAB_FIRE_WUCRUC(fb) \
410	FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR)
411#define	FAB_FIRE_OE(fb, bit) \
412	FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
413#define	FAB_OB_OE(fb, bit) \
414	FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
415static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = {
416	FAB_FIRE_WUCRUC(WUC),
417	FAB_FIRE_WUCRUC(RUC),
418	FAB_FIRE_OE(ERU, DLP),
419	FAB_FIRE_OE(ERO, DLP),
420	FAB_FIRE_OE(EMP, DLP),
421	FAB_FIRE_OE(EPE, DLP),
422	NULL, NULL, NULL,
423};
424
425#define	FAB_FIRE_DMC(fb) \
426	FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
427#define	FAB_N2_DMU(fb) \
428	FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
429static fab_fire_tbl_t fab_fire_dmc_tbl[] = {
430	FAB_FIRE_DMC(BYP_ERR),
431	FAB_FIRE_DMC(BYP_OOR),
432	FAB_FIRE_DMC(TRN_OOR),
433	FAB_FIRE_DMC(TTE_INV),
434	FAB_FIRE_DMC(TTE_PRT),
435	FAB_N2_DMU("iotsbdesc_inv"),
436	FAB_N2_DMU("sun4v_adj_va_uf"),
437	FAB_N2_DMU("sun4v_inv_pg_sz"),
438	FAB_N2_DMU("sun4v_key_err"),
439	FAB_N2_DMU("sun4v_va_oor"),
440	NULL, NULL, NULL
441};
442
443static fmd_xprt_t *fab_fmd_xprt = NULL;	/* FMD transport layer handle */
444static char fab_buf[FM_MAX_CLASS];
445static boolean_t fab_xlate_fake_rp = B_TRUE;
446
447#define	HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
448#define	GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
449#define	STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0)
450
451#define	FAB_LOOKUP(sz, name, field) \
452	(void) nvlist_lookup_uint ## sz(nvl, name, field)
453/* ARGSUSED */
454static void
455fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) {
456	data->nvl = nvl;
457
458	/* Generic PCI device information */
459	FAB_LOOKUP(16,	"bdf",			&data->bdf);
460	FAB_LOOKUP(16,	"device_id",		&data->device_id);
461	FAB_LOOKUP(16,	"vendor_id",		&data->vendor_id);
462	FAB_LOOKUP(8,	"rev_id",		&data->rev_id);
463	FAB_LOOKUP(16,	"dev_type",		&data->dev_type);
464	FAB_LOOKUP(16,	"pcie_off",		&data->pcie_off);
465	FAB_LOOKUP(16,	"pcix_off",		&data->pcix_off);
466	FAB_LOOKUP(16,	"aer_off",		&data->aer_off);
467	FAB_LOOKUP(16,	"ecc_ver",		&data->ecc_ver);
468
469	/* Misc ereport information */
470	FAB_LOOKUP(32,	"remainder",		&data->remainder);
471	FAB_LOOKUP(32,	"severity",		&data->severity);
472
473	/* PCI registers */
474	FAB_LOOKUP(16,	"pci_status",		&data->pci_err_status);
475	FAB_LOOKUP(16,	"pci_command",		&data->pci_cfg_comm);
476
477	/* PCI bridge registers */
478	FAB_LOOKUP(16,	"pci_bdg_sec_status",	&data->pci_bdg_sec_stat);
479	FAB_LOOKUP(16,	"pci_bdg_ctrl",		&data->pci_bdg_ctrl);
480
481	/* PCIx registers */
482	FAB_LOOKUP(32,	"pcix_status",		&data->pcix_status);
483	FAB_LOOKUP(16,	"pcix_command",		&data->pcix_command);
484
485	/* PCIx ECC Registers */
486	FAB_LOOKUP(16,	"pcix_ecc_control_0",	&data->pcix_ecc_control_0);
487	FAB_LOOKUP(16,	"pcix_ecc_status_0",	&data->pcix_ecc_status_0);
488	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_0",	&data->pcix_ecc_fst_addr_0);
489	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_0",	&data->pcix_ecc_sec_addr_0);
490	FAB_LOOKUP(32,	"pcix_ecc_attr_0",	&data->pcix_ecc_attr_0);
491
492	/* PCIx ECC Bridge Registers */
493	FAB_LOOKUP(16,	"pcix_ecc_control_1",	&data->pcix_ecc_control_1);
494	FAB_LOOKUP(16,	"pcix_ecc_status_1",	&data->pcix_ecc_status_1);
495	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_1",	&data->pcix_ecc_fst_addr_1);
496	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_1",	&data->pcix_ecc_sec_addr_1);
497	FAB_LOOKUP(32,	"pcix_ecc_attr_1",	&data->pcix_ecc_attr_1);
498
499	/* PCIx Bridge */
500	FAB_LOOKUP(32,	"pcix_bdg_status",	&data->pcix_bdg_stat);
501	FAB_LOOKUP(16,	"pcix_bdg_sec_status",	&data->pcix_bdg_sec_stat);
502
503	/* PCIe registers */
504	FAB_LOOKUP(16,	"pcie_status",		&data->pcie_err_status);
505	FAB_LOOKUP(16,	"pcie_command",		&data->pcie_err_ctl);
506	FAB_LOOKUP(32,	"pcie_dev_cap",		&data->pcie_dev_cap);
507
508	/* PCIe AER registers */
509	FAB_LOOKUP(32,	"pcie_adv_ctl",		&data->pcie_adv_ctl);
510	FAB_LOOKUP(32,	"pcie_ue_status",	&data->pcie_ue_status);
511	FAB_LOOKUP(32,	"pcie_ue_mask",		&data->pcie_ue_mask);
512	FAB_LOOKUP(32,	"pcie_ue_sev",		&data->pcie_ue_sev);
513	FAB_LOOKUP(32,	"pcie_ue_hdr0",		&data->pcie_ue_hdr[0]);
514	FAB_LOOKUP(32,	"pcie_ue_hdr1",		&data->pcie_ue_hdr[1]);
515	FAB_LOOKUP(32,	"pcie_ue_hdr2",		&data->pcie_ue_hdr[2]);
516	FAB_LOOKUP(32,	"pcie_ue_hdr3",		&data->pcie_ue_hdr[3]);
517	FAB_LOOKUP(32,	"pcie_ce_status",	&data->pcie_ce_status);
518	FAB_LOOKUP(32,	"pcie_ce_mask",		&data->pcie_ce_mask);
519	FAB_LOOKUP(32,	"pcie_ue_tgt_trans",	&data->pcie_ue_tgt_trans);
520	FAB_LOOKUP(64,	"pcie_ue_tgt_addr",	&data->pcie_ue_tgt_addr);
521	FAB_LOOKUP(16,	"pcie_ue_tgt_bdf",	&data->pcie_ue_tgt_bdf);
522
523	/* PCIe BDG AER registers */
524	FAB_LOOKUP(32,	"pcie_sue_adv_ctl",	&data->pcie_sue_ctl);
525	FAB_LOOKUP(32,	"pcie_sue_status",	&data->pcie_sue_status);
526	FAB_LOOKUP(32,	"pcie_sue_mask",	&data->pcie_sue_mask);
527	FAB_LOOKUP(32,	"pcie_sue_sev",		&data->pcie_sue_sev);
528	FAB_LOOKUP(32,	"pcie_sue_hdr0",	&data->pcie_sue_hdr[0]);
529	FAB_LOOKUP(32,	"pcie_sue_hdr1",	&data->pcie_sue_hdr[1]);
530	FAB_LOOKUP(32,	"pcie_sue_hdr2",	&data->pcie_sue_hdr[2]);
531	FAB_LOOKUP(32,	"pcie_sue_hdr3",	&data->pcie_sue_hdr[3]);
532	FAB_LOOKUP(32,	"pcie_sue_tgt_trans",	&data->pcie_sue_tgt_trans);
533	FAB_LOOKUP(64,	"pcie_sue_tgt_addr",	&data->pcie_sue_tgt_addr);
534	FAB_LOOKUP(16,	"pcie_sue_tgt_bdf",	&data->pcie_sue_tgt_bdf);
535
536	/* PCIe RP registers */
537	FAB_LOOKUP(32,	"pcie_rp_status",	&data->pcie_rp_status);
538	FAB_LOOKUP(16,	"pcie_rp_control",	&data->pcie_rp_ctl);
539
540	/* PCIe RP AER registers */
541	FAB_LOOKUP(32,	"pcie_adv_rp_status",	&data->pcie_rp_err_status);
542	FAB_LOOKUP(32,	"pcie_adv_rp_command",	&data->pcie_rp_err_cmd);
543	FAB_LOOKUP(16,	"pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id);
544	FAB_LOOKUP(16,	"pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id);
545
546	/*
547	 * If the system has a PCIe complaint RP with AER, turn off translating
548	 * fake RP ereports.
549	 */
550	if (fab_xlate_fake_rp &&
551	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) &&
552	    data->aer_off)
553		fab_xlate_fake_rp = B_FALSE;
554}
555
556/* ARGSUSED */
557static void
558fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) {
559	data->nvl = nvl;
560
561	/* Always Root Complex */
562	data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT;
563
564	data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD |
565	    PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP);
566}
567
568/* ARGSUSED */
569static int
570fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
571    boolean_t isRC) {
572	uint64_t	*now;
573	uint64_t	ena;
574	uint_t		nelem;
575	nvlist_t	*detector, *new_detector;
576	char		rcpath[255];
577	int		err = 0;
578
579	/* Grab the tod, ena and detector(FMRI) */
580	err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
581	err |= nvlist_lookup_uint64(nvl, "ena", &ena);
582	err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
583	if (err)
584		return (err);
585
586	/* Make a copy of the detector */
587	err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME);
588	if (err)
589		return (err);
590
591	/* Copy the tod and ena to erpt */
592	(void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
593	(void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
594
595	/*
596	 * Create the correct ROOT FMRI from PCIe leaf fabric ereports.	 Used
597	 * only by fab_prep_fake_rc_erpt.  See the fab_pciex_fake_rc_erpt_tbl
598	 * comments for more information.
599	 */
600	if (isRC) {
601		fab_get_rcpath(hdl, nvl, rcpath);
602
603		/* Create the correct PCIe RC new_detector aka FMRI */
604		(void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH,
605		    DATA_TYPE_STRING);
606		(void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH,
607		    rcpath);
608	}
609
610	/* Copy the FMRI to erpt */
611	(void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector);
612
613	nvlist_free(new_detector);
614	return (err);
615}
616
617static void
618fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class,
619    boolean_t isPrimary)
620{
621	nvlist_t	*nvl = data->nvl;
622	nvlist_t	*erpt;
623	char		*fmri = NULL;
624	uint32_t	tgt_trans;
625	uint64_t	tgt_addr;
626	uint16_t	tgt_bdf;
627
628	if (isPrimary) {
629		tgt_trans = data->pcie_ue_tgt_trans;
630		tgt_addr = data->pcie_ue_tgt_addr;
631		tgt_bdf = data->pcie_ue_tgt_bdf;
632	} else {
633		tgt_trans = data->pcie_sue_tgt_trans;
634		tgt_addr = data->pcie_sue_tgt_addr;
635		tgt_bdf = data->pcie_sue_tgt_bdf;
636	}
637
638	fmd_hdl_debug(hdl, "Sending Target Ereport: "
639	    "type 0x%x addr 0x%llx fltbdf 0x%x\n",
640	    tgt_trans, tgt_addr, tgt_bdf);
641
642	if (!tgt_trans)
643		return;
644
645	if ((tgt_trans == PF_ADDR_PIO) && tgt_addr)
646		fmri = fab_find_addr(hdl, nvl, tgt_addr);
647	else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf)
648		fmri = fab_find_bdf(hdl, nvl, tgt_bdf);
649
650	if (fmri) {
651		uint64_t	*now;
652		uint64_t	ena;
653		uint_t		nelem;
654		nvlist_t	*detector;
655		int		err = 0;
656
657		/* Allocate space for new erpt */
658		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
659			goto done;
660
661		/* Generate the target ereport class */
662		(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
663		    PCI_ERROR_SUBCLASS, class);
664		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
665
666		/* Grab the tod, ena and detector(FMRI) */
667		err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
668		err |= nvlist_lookup_uint64(nvl, "ena", &ena);
669
670		/* Copy the tod and ena to erpt */
671		(void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
672		(void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
673
674		/* Create the correct FMRI */
675		if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
676			nvlist_free(erpt);
677			goto done;
678		}
679		(void) nvlist_add_string(detector, FM_VERSION,
680		    FM_DEV_SCHEME_VERSION);
681		(void) nvlist_add_string(detector, FM_FMRI_SCHEME,
682		    FM_FMRI_SCHEME_DEV);
683		(void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri);
684		(void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector);
685
686		/* Add the address payload */
687		(void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr);
688
689		fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n",
690		    fab_buf, tgt_addr);
691		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
692		if (fmd_xprt_error(hdl, fab_fmd_xprt))
693			fmd_hdl_debug(hdl, "Failed to send Target PCI ereport");
694	} else {
695		fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx",
696		    tgt_addr);
697	}
698
699	return;
700done:
701	fmd_hdl_debug(hdl, "Failed  to send Target PCI ereport\n");
702}
703
704static void
705fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl)
706{
707	fab_erpt_tbl_t	*erpt_tbl, *entry;
708	nvlist_t	*erpt;
709	uint32_t	reg;
710
711	erpt_tbl = tbl->erpt_tbl;
712	if (tbl->reg_size == 16) {
713		reg = (uint32_t)*((uint16_t *)
714		    ((uint32_t)data + tbl->reg_offset));
715	} else {
716		reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset));
717	}
718
719	for (entry = erpt_tbl; entry->err_class; entry++) {
720		if (!(reg & entry->reg_bit))
721			continue;
722
723		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
724			goto done;
725		if (tbl->fab_prep(hdl, data, erpt, entry) != 0) {
726			fmd_hdl_debug(hdl, "Prepping ereport failed\n");
727			nvlist_free(erpt);
728			continue;
729		}
730
731		fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg);
732		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
733		if (fmd_xprt_error(hdl, fab_fmd_xprt)) {
734			fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
735			return;
736		}
737	}
738
739	return;
740done:
741	fmd_hdl_debug(hdl, "Failed  to send PCI ereport\n");
742}
743
744static int
745fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
746    fab_erpt_tbl_t *tbl)
747{
748	const char *class = tbl->err_class;
749	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
750
751	/* Generate an ereport for this error bit. */
752	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
753	    PCI_ERROR_SUBCLASS, class);
754	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
755
756	(void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status);
757	(void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm);
758
759	return (err);
760}
761
762static int
763fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
764    fab_erpt_tbl_t *tbl)
765{
766	const char *class = tbl->err_class;
767	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
768
769	/* Generate an ereport for this error bit. */
770	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s",
771	    PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class);
772	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
773
774	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
775	    data->pci_bdg_sec_stat);
776	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
777
778	return (err);
779}
780
781static int
782fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
783    fab_erpt_tbl_t *tbl)
784{
785	const char *class = tbl->err_class;
786	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
787
788	/* Generate an ereport for this error bit. */
789	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
790	    PCI_ERROR_SUBCLASS, class);
791	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
792
793	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
794	    data->pci_bdg_sec_stat);
795	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
796
797	return (err);
798}
799
800
801static int
802fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
803    fab_erpt_tbl_t *tbl)
804{
805	const char *class = tbl->err_class;
806	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
807
808	/* Generate an ereport for this error bit. */
809	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
810	    PCIEX_ERROR_SUBCLASS, class);
811	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
812
813	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
814	(void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG,
815	    data->pcie_ce_status);
816
817	return (err);
818}
819
820static int
821fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
822    fab_erpt_tbl_t *tbl)
823{
824	const char *class = tbl->err_class;
825	uint32_t first_err = 1 << (data->pcie_adv_ctl &
826	    PCIE_AER_CTL_FST_ERR_PTR_MASK);
827	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
828
829	/* Generate an ereport for this error bit. */
830	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
831	    PCIEX_ERROR_SUBCLASS, class);
832	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
833
834	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
835	(void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG,
836	    data->pcie_ue_status);
837	(void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev);
838	(void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl);
839
840	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
841
842	if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) {
843		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
844		    data->pcie_ue_tgt_bdf);
845		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
846	} else {
847		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
848		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
849	}
850
851	if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) {
852		if (tbl->tgt_class)
853			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE);
854	}
855
856	return (err);
857}
858
859static int
860fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
861    fab_erpt_tbl_t *tbl)
862{
863	const char *class = tbl->err_class;
864	uint32_t first_err = 1 << (data->pcie_sue_ctl &
865	    PCIE_AER_SCTL_FST_ERR_PTR_MASK);
866	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
867
868	/* Generate an ereport for this error bit. */
869	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
870	    PCIEX_ERROR_SUBCLASS, class);
871	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
872
873	(void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS,
874	    data->pcie_sue_status);
875
876	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
877
878	if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) {
879		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
880		    data->pcie_sue_tgt_bdf);
881		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
882	} else {
883		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
884		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
885	}
886
887	if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) {
888		if (tbl->tgt_class)
889			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE);
890	}
891
892	return (err);
893}
894
895static int
896fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
897    fab_erpt_tbl_t *tbl)
898{
899	const char *class = tbl->err_class;
900	int err = 0;
901
902	/* Only send if this is not a bridge */
903	if (!data->pcix_status || data->pcix_bdg_sec_stat)
904		return (1);
905
906	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
907
908	/* Generate an ereport for this error bit. */
909	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
910	    PCIX_ERROR_SUBCLASS, class);
911	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
912
913	(void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command);
914	(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
915
916	return (err);
917}
918
919static void
920fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
921{
922	nvlist_t *erpt;
923	int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4;
924	int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR;
925	int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE;
926	int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE;
927	uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) |
928	    data->pcix_ecc_status_0;
929
930	switch (ecc_phase) {
931	case PCI_PCIX_ECC_PHASE_NOERR:
932		break;
933	case PCI_PCIX_ECC_PHASE_FADDR:
934	case PCI_PCIX_ECC_PHASE_SADDR:
935		(void) snprintf(fab_buf, FM_MAX_CLASS,
936		    "%s.%s", PCIX_ERROR_SUBCLASS,
937		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
938		break;
939	case PCI_PCIX_ECC_PHASE_ATTR:
940		(void) snprintf(fab_buf, FM_MAX_CLASS,
941		    "%s.%s", PCIX_ERROR_SUBCLASS,
942		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
943		break;
944	case PCI_PCIX_ECC_PHASE_DATA32:
945	case PCI_PCIX_ECC_PHASE_DATA64:
946		(void) snprintf(fab_buf, FM_MAX_CLASS,
947		    "%s.%s", PCIX_ERROR_SUBCLASS,
948		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
949		break;
950	}
951
952	if (ecc_phase) {
953		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
954			goto done;
955		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
956		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
957		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
958		    data->pcix_command);
959		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
960		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
961		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
962		    data->pcix_ecc_attr_0);
963		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
964		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
965		if (fmd_xprt_error(hdl, fab_fmd_xprt))
966			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
967	}
968
969	if (sec_ce || sec_ue) {
970		(void) snprintf(fab_buf, FM_MAX_CLASS,
971		    "%s.%s", PCIX_ERROR_SUBCLASS,
972		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
973		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
974			goto done;
975		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
976		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
977		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
978		    data->pcix_command);
979		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
980		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
981		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
982		    data->pcix_ecc_attr_0);
983		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
984		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
985		if (fmd_xprt_error(hdl, fab_fmd_xprt))
986			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
987	}
988
989	return;
990done:
991	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
992}
993
994static int
995fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
996    fab_erpt_tbl_t *tbl)
997{
998	const char *class = tbl->err_class;
999	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1000
1001	/* Generate an ereport for this error bit. */
1002	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s",
1003	    PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class);
1004	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1005
1006	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
1007	    data->pcix_bdg_sec_stat);
1008	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
1009
1010	return (err);
1011}
1012
1013static int
1014fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1015    fab_erpt_tbl_t *tbl)
1016{
1017	const char *class = tbl->err_class;
1018	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1019
1020	/* Generate an ereport for this error bit. */
1021	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
1022	    PCIX_ERROR_SUBCLASS, class);
1023	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1024
1025	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
1026	    data->pcix_bdg_sec_stat);
1027	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
1028
1029	return (err);
1030}
1031
1032static void
1033fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
1034{
1035	nvlist_t *erpt;
1036	int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4;
1037	int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR;
1038	int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE;
1039	int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE;
1040	uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) |
1041	    data->pcix_ecc_status_1;
1042
1043	switch (ecc_phase) {
1044	case PCI_PCIX_ECC_PHASE_NOERR:
1045		break;
1046	case PCI_PCIX_ECC_PHASE_FADDR:
1047	case PCI_PCIX_ECC_PHASE_SADDR:
1048		(void) snprintf(fab_buf, FM_MAX_CLASS,
1049		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
1050		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
1051		break;
1052	case PCI_PCIX_ECC_PHASE_ATTR:
1053		(void) snprintf(fab_buf, FM_MAX_CLASS,
1054		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
1055		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
1056		break;
1057	case PCI_PCIX_ECC_PHASE_DATA32:
1058	case PCI_PCIX_ECC_PHASE_DATA64:
1059		(void) snprintf(fab_buf, FM_MAX_CLASS,
1060		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
1061		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
1062		break;
1063	}
1064	if (ecc_phase) {
1065		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
1066			goto done;
1067		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1068		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1069		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
1070		    data->pcix_bdg_sec_stat);
1071		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
1072		    data->pcix_bdg_stat);
1073		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
1074		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
1075		    data->pcix_ecc_attr_1);
1076		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
1077		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
1078		if (fmd_xprt_error(hdl, fab_fmd_xprt))
1079			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
1080	}
1081
1082	if (sec_ce || sec_ue) {
1083		(void) snprintf(fab_buf, FM_MAX_CLASS,
1084		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
1085		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
1086		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
1087			goto done;
1088		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1089		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1090		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
1091		    data->pcix_bdg_sec_stat);
1092		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
1093		    data->pcix_bdg_stat);
1094		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
1095		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
1096		    data->pcix_ecc_attr_1);
1097		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
1098		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
1099		if (fmd_xprt_error(hdl, fab_fmd_xprt))
1100			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
1101	}
1102	return;
1103done:
1104	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
1105}
1106
1107static int
1108fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1109    fab_erpt_tbl_t *tbl)
1110{
1111	const char *class = tbl->err_class;
1112	int err = 0;
1113
1114	/* Don't send this for PCI device, Root Ports, or PCIe with AER */
1115	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
1116	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
1117	    data->aer_off)
1118		return (1);
1119
1120	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1121
1122	/* Generate an ereport for this error bit. */
1123	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
1124	    PCIEX_ERROR_SUBCLASS, class);
1125	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1126
1127	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
1128
1129	return (err);
1130}
1131
1132static int
1133fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1134    fab_erpt_tbl_t *tbl)
1135{
1136	const char *class = tbl->err_class;
1137	uint32_t status = data->pcie_rp_err_status;
1138	int err = 0;
1139	int isFE = 0, isNFE = 0;
1140
1141	fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class);
1142
1143	if (!data->aer_off)
1144		return (-1);
1145
1146	/* Only send a FE Msg if the 1st UE error is FE */
1147	if (strcmp(class, PCIEX_RC_FE_MSG) == 0)
1148		if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL))
1149			return (-1);
1150		else
1151			isFE = 1;
1152
1153	/* Only send a NFE Msg is the 1st UE error is NFE */
1154	if (strcmp(class, PCIEX_RC_NFE_MSG) == 0)
1155		if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL)
1156			return (-1);
1157		else
1158			isNFE = 1;
1159
1160	fmd_hdl_debug(hdl, "XLATE RP Error");
1161
1162	err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
1163
1164	/* Generate an ereport for this error bit. */
1165	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
1166	    PCIEX_ERROR_SUBCLASS, class);
1167	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1168
1169	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status);
1170	if ((isFE || isNFE) && data->pcie_rp_ue_src_id) {
1171		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
1172		    data->pcie_rp_ue_src_id);
1173		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
1174	}
1175	if ((strcmp(class, PCIEX_RC_CE_MSG) == 0) && data->pcie_rp_ce_src_id) {
1176		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
1177		    data->pcie_rp_ce_src_id);
1178		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
1179	}
1180
1181	return (err);
1182}
1183
1184static int
1185fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1186    fab_erpt_tbl_t *tbl)
1187{
1188	const char *class = tbl->err_class;
1189	uint32_t rc_err_sts = 0;
1190	int err = 0;
1191
1192	/*
1193	 * Don't send this for PCI device or Root Ports.  Only send it on
1194	 * systems with non-compliant RPs.
1195	 */
1196	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
1197	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
1198	    (!fab_xlate_fake_rp))
1199		return (-1);
1200
1201	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE);
1202
1203	/* Generate an ereport for this error bit. */
1204	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
1205	    PCIEX_ERROR_SUBCLASS, class);
1206	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1207
1208	/* Send PCIe RC Ereports */
1209	if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) {
1210		rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD;
1211	}
1212
1213	/* NFE/FE src id takes precedence over CE src id */
1214	if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) {
1215		rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
1216		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
1217	}
1218	if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) {
1219		rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
1220		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
1221	}
1222	if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) &&
1223	    (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) {
1224		rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
1225		rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD;
1226	}
1227
1228	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts);
1229
1230	if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) {
1231		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf);
1232		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
1233	}
1234
1235	return (err);
1236}
1237
1238static int
1239fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1240    const char *class)
1241{
1242	fab_fire_tbl_t	*entry;
1243	uint64_t	reg;
1244
1245	for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) {
1246		if (strcmp(class, entry->err_class) == 0)
1247			goto send;
1248	}
1249
1250	return (0);
1251
1252send:
1253	fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class);
1254
1255	/* Fill in the device status register */
1256	data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED;
1257
1258	/* Fill in the AER CE register */
1259	if (nvlist_lookup_uint64(erpt, "tlu-cess", &reg) == 0) {
1260		data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32);
1261	}
1262
1263	return (1);
1264}
1265
1266static int
1267fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1268    const char *class)
1269{
1270	fab_fire_tbl_t	*entry;
1271	uint64_t	reg;
1272	uint32_t	temp;
1273	pcie_tlp_hdr_t	*hdr;
1274
1275	for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) {
1276		if (strcmp(class, entry->err_class) == 0)
1277			goto send;
1278	}
1279
1280	return (0);
1281
1282send:
1283	fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class);
1284
1285	/* Fill in PCI Status Register */
1286	data->pci_err_status = entry->pci_err_sts;
1287	data->pci_bdg_sec_stat = entry->pci_bdg_sts;
1288
1289	/* Fill in the device status register */
1290	if (entry->fire_bit & data->pcie_ue_sev)
1291		data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
1292	else
1293		data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
1294
1295	if (entry->fire_bit == PCIE_AER_UCE_UR)
1296		data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED;
1297
1298	/* Fill in the AER UE register */
1299	if (nvlist_lookup_uint64(erpt, "tlu-uess", &reg) == 0) {
1300		data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32);
1301	}
1302
1303	/* Fill in the AER Control register */
1304	if ((reg & (uint64_t)entry->fire_bit) &&
1305	    nvlist_lookup_boolean(erpt, "primary")) {
1306		temp = entry->fire_bit;
1307		for (data->pcie_adv_ctl = (uint32_t)-1; temp;
1308		    data->pcie_adv_ctl++)
1309			temp = temp >> 1;
1310	}
1311
1312	/* If CTO create target information */
1313	if (entry->fire_bit == PCIE_AER_UCE_TO &&
1314	    nvlist_lookup_boolean(erpt, "primary")) {
1315		if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", &reg) == 0) {
1316			data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
1317			data->pcie_ue_hdr[1] = (uint32_t)(reg);
1318		}
1319		if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", &reg) == 0) {
1320			data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
1321			data->pcie_ue_hdr[3] = (uint32_t)(reg);
1322		}
1323
1324		hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]);
1325		switch (hdr->type) {
1326		case PCIE_TLP_TYPE_IO:
1327		case PCIE_TLP_TYPE_MEM:
1328		case PCIE_TLP_TYPE_MEMLK:
1329			data->pcie_ue_tgt_trans = PF_ADDR_PIO;
1330			if (hdr->fmt & 0x1) {
1331				data->pcie_ue_tgt_addr = reg;
1332			} else {
1333				data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2];
1334			}
1335			break;
1336		case PCIE_TLP_TYPE_CFG0:
1337		case PCIE_TLP_TYPE_CFG1:
1338			data->pcie_ue_tgt_trans = PF_ADDR_CFG;
1339			data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16;
1340			break;
1341		}
1342	}
1343
1344	/* Fill in the AER Header registers */
1345	if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", &reg) == 0) {
1346		data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
1347		data->pcie_ue_hdr[1] = (uint32_t)(reg);
1348	}
1349	if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", &reg) == 0) {
1350		data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
1351		data->pcie_ue_hdr[3] = (uint32_t)(reg);
1352	}
1353
1354	return (1);
1355}
1356
1357static int
1358fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1359    const char *class)
1360{
1361	fab_fire_tbl_t	*entry;
1362	uint64_t	reg;
1363
1364	for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) {
1365		if (strcmp(class, entry->err_class) == 0)
1366			goto send;
1367	}
1368
1369	return (0);
1370
1371send:
1372	fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class);
1373
1374	/* Fill in PCI Status Register */
1375	if (entry->fire_bit) {
1376		data->pci_err_status = entry->pci_err_sts;
1377		data->pci_bdg_sec_stat = entry->pci_bdg_sts;
1378	} else {
1379		if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", &reg) == 0) {
1380			data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
1381			data->pcie_ue_hdr[1] = (uint32_t)(reg);
1382		}
1383		if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", &reg) == 0) {
1384			data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
1385			data->pcie_ue_hdr[3] = (uint32_t)(reg);
1386		}
1387
1388		if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type ==
1389		    PCIE_TLP_TYPE_CPL) {
1390			pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1];
1391			switch (cpl->status) {
1392			case PCIE_CPL_STS_UR:
1393				data->pci_err_status = 0;
1394				data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB |
1395				    PCI_STAT_S_SYSERR;
1396				break;
1397			case PCIE_CPL_STS_CA:
1398				data->pci_err_status = 0;
1399				data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB |
1400				    PCI_STAT_S_SYSERR;
1401				break;
1402			}
1403		}
1404	}
1405
1406	/* Fill in the device status register */
1407	if (entry->fire_bit & data->pcie_ue_sev)
1408		data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
1409	else
1410		data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
1411
1412	/* Fill in the AER UE register */
1413	data->pcie_ue_status = entry->fire_bit;
1414
1415	return (1);
1416}
1417
1418static int
1419fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
1420    const char *class)
1421{
1422	fab_fire_tbl_t	*entry;
1423	uint64_t	reg;
1424	uint32_t	temp;
1425
1426	for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) {
1427		fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class);
1428		if ((strcmp(class, entry->err_class) == 0) &&
1429		    nvlist_lookup_boolean(erpt, "primary"))
1430				goto send;
1431	}
1432
1433	return (0);
1434
1435send:
1436	fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class);
1437
1438	/* Fill in PCI Status Register */
1439	data->pci_err_status = entry->pci_err_sts;
1440	data->pci_bdg_sec_stat = entry->pci_bdg_sts;
1441
1442	/* Fill in the device status register */
1443	data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
1444
1445	/* Fill in the AER UE register */
1446	data->pcie_ue_status = entry->fire_bit;
1447
1448	/* Fill in the AER Control register */
1449	temp = entry->fire_bit;
1450	for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++)
1451		temp = temp >> 1;
1452
1453	/* Fill in the AER Header registers */
1454	if (nvlist_lookup_uint64(erpt, "mmu-tfsr", &reg) == 0) {
1455		fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg);
1456		/* Get the trans type */
1457		temp = (reg & 0x3F0000) >> 16;
1458		data->pcie_ue_hdr[0] = (uint32_t)(temp << 24);
1459		data->pcie_ue_tgt_trans = PF_ADDR_DMA;
1460		/* Get the req id */
1461		temp = (reg & 0xFFFF);
1462		data->pcie_ue_hdr[1] = (uint32_t)(temp << 16);
1463		data->pcie_ue_tgt_bdf = temp;
1464	}
1465
1466	if (nvlist_lookup_uint64(erpt, "mmu-tfar", &reg) == 0) {
1467		fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg);
1468		/* Get the address */
1469		data->pcie_ue_hdr[2] = reg;
1470		data->pcie_ue_hdr[3] = 0;
1471		data->pcie_ue_tgt_addr = reg;
1472	}
1473
1474	fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]);
1475	fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]);
1476	fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]);
1477	fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]);
1478
1479	return (1);
1480}
1481
1482static void
1483fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data)
1484{
1485	fab_err_tbl_t *tbl;
1486
1487	fmd_hdl_debug(hdl, "Sending Ereports Now");
1488
1489	/* Go through the error logs and send the relavant reports */
1490	for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) {
1491		fab_send_erpt(hdl, data, tbl);
1492	}
1493
1494	/* Send PCI-X ECC Ereports */
1495	fab_send_pcix_ecc_erpt(hdl, data);
1496	fab_send_pcix_bdg_ecc_erpt(hdl, data);
1497}
1498
1499static void
1500fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl,
1501    const char *class)
1502{
1503	if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) {
1504		if (fab_xlate_fire_ce(hdl, data, nvl, class))
1505			return;
1506
1507		if (fab_xlate_fire_ue(hdl, data, nvl, class))
1508			return;
1509
1510		if (fab_xlate_fire_oe(hdl, data, nvl, class))
1511			return;
1512	} else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") ||
1513	    fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) {
1514		if (fab_xlate_fire_dmc(hdl, data, nvl, class))
1515			return;
1516	}
1517}
1518
1519static void
1520fab_update_topo(fmd_hdl_t *hdl)
1521{
1522	topo_hdl_t	*thp = NULL;
1523	FILE		*fp;
1524	int		err = 0;
1525
1526	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) {
1527		fmd_hdl_debug(hdl, "Failed to hold topo\n");
1528	}
1529
1530	fp = fopen(XMLTOPOFILE, "w");
1531
1532	if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) {
1533		fmd_hdl_debug(hdl, "Failed to get XML topo\n");
1534	}
1535
1536	(void) fclose(fp);
1537
1538	fmd_hdl_topo_rele(hdl, thp);
1539
1540	if (fab_xpathCtx)
1541		xmlXPathFreeContext(fab_xpathCtx);
1542	if (fab_doc)
1543		xmlFreeDoc(fab_doc);
1544
1545	/* Load xml document */
1546	fab_doc = xmlParseFile(XMLTOPOFILE);
1547
1548	/* Init xpath */
1549	fab_xpathCtx = xmlXPathNewContext(fab_doc);
1550
1551	fab_valid_topo = 1;
1552}
1553
1554/* ARGSUSED */
1555static void
1556fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) {
1557	nvlist_t	*detector;
1558	char		*path;
1559	int		i;
1560
1561	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
1562	(void) nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, &path);
1563	(void) strncpy(rcpath, path, FM_MAX_CLASS);
1564	for (i = 1; (i < FM_MAX_CLASS) && (rcpath[i] != '/') &&
1565	    (rcpath[i] != '\0'); i++);
1566	rcpath[i] = '\0';
1567}
1568
1569static char *
1570fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) {
1571	xmlXPathObjectPtr xpathObj;
1572	xmlNodeSetPtr	nodes;
1573	char		query[500];
1574	int		bus, dev, fn;
1575	char		rcpath[255];
1576
1577	if (bdf != (uint16_t)-1) {
1578		bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
1579		dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
1580		fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
1581	}
1582
1583	fab_get_rcpath(hdl, nvl, rcpath);
1584
1585	/*
1586	 * Explanation of the XSL XPATH Query
1587	 * Line 1: Look at all nodes with the node name "propval"
1588	 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
1589	 * Line 4-5: See if the "value" of the node ends with correct PCI BDF
1590	 * Line 6: Go up one level to the parent of the current node
1591	 * Line 7: See if child node contains "ASRU" with the same PCIe Root
1592	 * Line 8: Traverse up the parent and the other siblings and look for
1593	 *	   the io "propgroup" and get the value of the dev "propval"
1594	 */
1595	(void) snprintf(query, sizeof (query), "//propval["
1596	    "contains(substring(@value, string-length(@value) - 34), "
1597	    "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
1598	    "contains(substring(@value, string-length(@value) - 28), "
1599	    "'pcibus=%d/pcidev=%d/pcifn=%d')"
1600	    "]/parent::"
1601	    "*/propval[@name='ASRU' and contains(@value, '%s')]"
1602	    "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
1603	    "@value", bus, dev, fn, bus, dev, fn, rcpath);
1604
1605	xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
1606
1607	fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
1608	fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
1609	nodes = xpathObj->nodesetval;
1610	if (nodes) {
1611		fmd_hdl_debug(hdl, "BDF Dev Path: %s\n",
1612		    xmlNodeGetContent(nodes->nodeTab[0]));
1613		return ((char *)xmlNodeGetContent(nodes->nodeTab[0]));
1614	}
1615	return (NULL);
1616}
1617
1618static char *
1619fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) {
1620	xmlXPathObjectPtr xpathObj;
1621	xmlNodeSetPtr nodes;
1622	xmlNodePtr devNode;
1623	char query[500];
1624	int size, i, j;
1625	uint32_t prop[50];
1626	char *token;
1627	pci_regspec_t *assign_p;
1628	uint64_t low, hi;
1629	char rcpath[255];
1630
1631	fab_get_rcpath(hdl, nvl, rcpath);
1632
1633	(void) snprintf(query, sizeof (query), "//propval["
1634	    "@name='ASRU' and contains(@value, '%s')]/"
1635	    "parent::*/following-sibling::*[@name='pci']/"
1636	    "propval[@name='assigned-addresses']", rcpath);
1637
1638	xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
1639
1640	fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
1641	fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
1642	nodes = xpathObj->nodesetval;
1643	size = (nodes) ? nodes->nodeNr : 0;
1644
1645	/* Decode the list of assigned addresses xml nodes for each device */
1646	for (i = 0; i < size; i++) {
1647		devNode = nodes->nodeTab[i];
1648		if (!HAS_PROP(devNode, "value"))
1649			continue;
1650
1651		/* Convert "string" assigned-addresses to pci_regspec_t */
1652		j = 0;
1653		for (token = strtok(GET_PROP(devNode, "value"), " "); token;
1654		    token = strtok(NULL, " ")) {
1655			prop[j++] = strtoul(token, (char **)NULL, 16);
1656		}
1657		prop[j] = (uint32_t)-1;
1658
1659		/* Check if address belongs to this device */
1660		for (assign_p = (pci_regspec_t *)prop;
1661		    assign_p->pci_phys_hi != (uint_t)-1; assign_p++) {
1662			low = assign_p->pci_phys_low;
1663			hi = low + assign_p->pci_size_low;
1664			if ((addr < hi) && (addr >= low)) {
1665				fmd_hdl_debug(hdl, "Found Address\n");
1666				goto found;
1667			}
1668		}
1669	}
1670	return (NULL);
1671
1672found:
1673	/* Traverse up the xml tree and back down to find the right propgroup */
1674	for (devNode = devNode->parent->parent->children;
1675	    devNode; devNode = devNode->next) {
1676		if (STRCMP(devNode->name, "propgroup") &&
1677		    STRCMP(GET_PROP(devNode, "name"), "io"))
1678			goto propgroup;
1679	}
1680	return (NULL);
1681
1682propgroup:
1683	/* Retrive the "dev" propval and return */
1684	for (devNode = devNode->children; devNode; devNode = devNode->next) {
1685		if (STRCMP(devNode->name, "propval") &&
1686		    STRCMP(GET_PROP(devNode, "name"), "dev")) {
1687			fmd_hdl_debug(hdl, "Addr Dev Path: %s\n",
1688			    GET_PROP(devNode, "value"));
1689			return (GET_PROP(devNode, "value"));
1690		}
1691	}
1692	return (NULL);
1693}
1694
1695static void
1696fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) {
1697	nvpair_t *nvp;
1698
1699	for (nvp = nvlist_next_nvpair(nvl, NULL);
1700	    nvp != NULL;
1701	    nvp = nvlist_next_nvpair(nvl, nvp)) {
1702
1703		data_type_t type = nvpair_type(nvp);
1704		const char *name = nvpair_name(nvp);
1705
1706		boolean_t b;
1707		uint8_t i8;
1708		uint16_t i16;
1709		uint32_t i32;
1710		uint64_t i64;
1711		char *str;
1712		nvlist_t *cnv;
1713
1714		nvlist_t **nvlarr;
1715		uint_t arrsize;
1716		int arri;
1717
1718
1719		if (strcmp(name, FM_CLASS) == 0)
1720			continue; /* already printed by caller */
1721
1722		fmd_hdl_debug(hdl, " %s=", name);
1723
1724		switch (type) {
1725		case DATA_TYPE_BOOLEAN:
1726			fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1");
1727			break;
1728
1729		case DATA_TYPE_BOOLEAN_VALUE:
1730			(void) nvpair_value_boolean_value(nvp, &b);
1731			fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d",
1732			    b ? "1" : "0");
1733			break;
1734
1735		case DATA_TYPE_BYTE:
1736			(void) nvpair_value_byte(nvp, &i8);
1737			fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8);
1738			break;
1739
1740		case DATA_TYPE_INT8:
1741			(void) nvpair_value_int8(nvp, (void *)&i8);
1742			fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8);
1743			break;
1744
1745		case DATA_TYPE_UINT8:
1746			(void) nvpair_value_uint8(nvp, &i8);
1747			fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8);
1748			break;
1749
1750		case DATA_TYPE_INT16:
1751			(void) nvpair_value_int16(nvp, (void *)&i16);
1752			fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16);
1753			break;
1754
1755		case DATA_TYPE_UINT16:
1756			(void) nvpair_value_uint16(nvp, &i16);
1757			fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16);
1758			break;
1759
1760		case DATA_TYPE_INT32:
1761			(void) nvpair_value_int32(nvp, (void *)&i32);
1762			fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32);
1763			break;
1764
1765		case DATA_TYPE_UINT32:
1766			(void) nvpair_value_uint32(nvp, &i32);
1767			fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32);
1768			break;
1769
1770		case DATA_TYPE_INT64:
1771			(void) nvpair_value_int64(nvp, (void *)&i64);
1772			fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx",
1773			    (u_longlong_t)i64);
1774			break;
1775
1776		case DATA_TYPE_UINT64:
1777			(void) nvpair_value_uint64(nvp, &i64);
1778			fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx",
1779			    (u_longlong_t)i64);
1780			break;
1781
1782		case DATA_TYPE_HRTIME:
1783			(void) nvpair_value_hrtime(nvp, (void *)&i64);
1784			fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx",
1785			    (u_longlong_t)i64);
1786			break;
1787
1788		case DATA_TYPE_STRING:
1789			(void) nvpair_value_string(nvp, &str);
1790			fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"",
1791			    str ? str : "<NULL>");
1792			break;
1793
1794		case DATA_TYPE_NVLIST:
1795			fmd_hdl_debug(hdl, "[");
1796			(void) nvpair_value_nvlist(nvp, &cnv);
1797			fab_pr(hdl, NULL, cnv);
1798			fmd_hdl_debug(hdl, " ]");
1799			break;
1800
1801		case DATA_TYPE_BOOLEAN_ARRAY:
1802		case DATA_TYPE_BYTE_ARRAY:
1803		case DATA_TYPE_INT8_ARRAY:
1804		case DATA_TYPE_UINT8_ARRAY:
1805		case DATA_TYPE_INT16_ARRAY:
1806		case DATA_TYPE_UINT16_ARRAY:
1807		case DATA_TYPE_INT32_ARRAY:
1808		case DATA_TYPE_UINT32_ARRAY:
1809		case DATA_TYPE_INT64_ARRAY:
1810		case DATA_TYPE_UINT64_ARRAY:
1811		case DATA_TYPE_STRING_ARRAY:
1812			fmd_hdl_debug(hdl, "[...]");
1813			break;
1814		case DATA_TYPE_NVLIST_ARRAY:
1815			arrsize = 0;
1816			(void) nvpair_value_nvlist_array(nvp, &nvlarr,
1817			    &arrsize);
1818
1819			for (arri = 0; arri < arrsize; arri++) {
1820				fab_pr(hdl, ep, nvlarr[arri]);
1821			}
1822
1823			break;
1824		case DATA_TYPE_UNKNOWN:
1825			fmd_hdl_debug(hdl, "<unknown>");
1826			break;
1827		}
1828	}
1829}
1830
1831/*ARGSUSED*/
1832static void
1833fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
1834{
1835	fab_data_t fab_data = {0};
1836
1837	if (!fab_valid_topo)
1838		fab_update_topo(hdl);
1839
1840	if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) {
1841		fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class);
1842		fab_pci_fabric_to_data(hdl, nvl, &fab_data);
1843		fab_xlate_pcie_erpts(hdl, &fab_data);
1844	} else {
1845		fab_pr(hdl, ep, nvl);
1846		fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class);
1847		fab_fire_to_data(hdl, nvl, &fab_data);
1848		fab_xlate_fire_erpts(hdl, &fab_data, nvl, class);
1849		fab_xlate_pcie_erpts(hdl, &fab_data);
1850	}
1851}
1852
1853/* ARGSUSED */
1854static void
1855fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo)
1856{
1857	fab_valid_topo = 0;
1858}
1859
1860static const fmd_hdl_ops_t fmd_ops = {
1861	fab_recv,	/* fmdo_recv */
1862	NULL,		/* fmdo_timeout */
1863	NULL,		/* fmdo_close */
1864	NULL,		/* fmdo_stats */
1865	NULL,		/* fmdo_gc */
1866	NULL,		/* fmdo_send */
1867	fab_topo,	/* fmdo_topo */
1868};
1869
1870static const fmd_hdl_info_t fmd_info = {
1871	"Fabric Ereport Translater", "1.0", &fmd_ops, NULL
1872};
1873
1874#define	REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data)
1875#define	SET_TBL(n, err, reg, sz) \
1876	fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \
1877	fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \
1878	fab_master_err_tbl[n].reg_size = sz; \
1879	fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt;
1880
1881void
1882_fmd_init(fmd_hdl_t *hdl)
1883{
1884	fab_data_t fab_data;
1885
1886	if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0)
1887		return;
1888
1889	/* Init libxml */
1890	xmlInitParser();
1891
1892	fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL);
1893	fmd_hdl_debug(hdl, "Fabric Translater Started\n");
1894
1895	/* Setup the master error table */
1896	fab_master_err_tbl = (fab_err_tbl_t *)calloc(13,
1897	    sizeof (fab_err_tbl_t));
1898
1899	SET_TBL(0, pci,			pci_err_status,	    16);
1900	SET_TBL(1, pci_bdg,		pci_bdg_sec_stat,   16);
1901	SET_TBL(2, pci_bdg_ctl,		pci_bdg_ctrl,	    16);
1902	SET_TBL(3, pcie_ce,		pcie_ce_status,	    32);
1903	SET_TBL(4, pcie_ue,		pcie_ue_status,	    32);
1904	SET_TBL(5, pcie_sue,		pcie_sue_status,    32);
1905	SET_TBL(6, pcix,		pcix_status,	    32);
1906	SET_TBL(7, pcix_bdg_sec,	pcix_bdg_sec_stat,  16);
1907	SET_TBL(8, pcix_bdg,		pcix_bdg_stat,	    32);
1908	SET_TBL(9, pcie_nadv,		pcie_err_status,    16);
1909	SET_TBL(10, pcie_rc,		pcie_rp_err_status, 32);
1910	SET_TBL(11, pcie_fake_rc,	pcie_err_status,    16);
1911}
1912
1913void
1914_fmd_fini(fmd_hdl_t *hdl)
1915{
1916	/* Fini xpath */
1917	if (fab_xpathCtx)
1918		xmlXPathFreeContext(fab_xpathCtx);
1919	/* Free xml document */
1920	if (fab_doc)
1921		xmlFreeDoc(fab_doc);
1922	/* Fini libxml */
1923	xmlCleanupParser();
1924
1925	fmd_xprt_close(hdl, fab_fmd_xprt);
1926}
1927