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