14df55fdeSJanie Lu /*
24df55fdeSJanie Lu  * CDDL HEADER START
34df55fdeSJanie Lu  *
44df55fdeSJanie Lu  * The contents of this file are subject to the terms of the
54df55fdeSJanie Lu  * Common Development and Distribution License (the "License").
64df55fdeSJanie Lu  * You may not use this file except in compliance with the License.
74df55fdeSJanie Lu  *
84df55fdeSJanie Lu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94df55fdeSJanie Lu  * or http://www.opensolaris.org/os/licensing.
104df55fdeSJanie Lu  * See the License for the specific language governing permissions
114df55fdeSJanie Lu  * and limitations under the License.
124df55fdeSJanie Lu  *
134df55fdeSJanie Lu  * When distributing Covered Code, include this CDDL HEADER in each
144df55fdeSJanie Lu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154df55fdeSJanie Lu  * If applicable, add the following below this CDDL HEADER, with the
164df55fdeSJanie Lu  * fields enclosed by brackets "[]" replaced with your own identifying
174df55fdeSJanie Lu  * information: Portions Copyright [yyyy] [name of copyright owner]
184df55fdeSJanie Lu  *
194df55fdeSJanie Lu  * CDDL HEADER END
204df55fdeSJanie Lu  */
214df55fdeSJanie Lu 
224df55fdeSJanie Lu /*
23b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
244df55fdeSJanie Lu  * Use is subject to license terms.
25*ffb64830SJordan Paige Hendricks  *
26*ffb64830SJordan Paige Hendricks  * Copyright 2019 Joyent, Inc.
274df55fdeSJanie Lu  */
284df55fdeSJanie Lu #include <stddef.h>
294df55fdeSJanie Lu #include <strings.h>
304df55fdeSJanie Lu #include <sys/fm/util.h>
31*ffb64830SJordan Paige Hendricks #include <sys/pcie.h>
324df55fdeSJanie Lu 
334df55fdeSJanie Lu #include "fabric-xlate.h"
344df55fdeSJanie Lu 
354df55fdeSJanie Lu #define	FAB_LOOKUP(sz, name, field) \
364df55fdeSJanie Lu 	(void) nvlist_lookup_uint ## sz(nvl, name, field)
374df55fdeSJanie Lu 
384df55fdeSJanie Lu static boolean_t fab_xlate_fake_rp = B_TRUE;
394df55fdeSJanie Lu static fab_err_tbl_t *fab_master_err_tbl;
404df55fdeSJanie Lu 
414df55fdeSJanie Lu /*
424df55fdeSJanie Lu  * Translation tables for converting "fabric" error bits into "pci" ereports.
434df55fdeSJanie Lu  * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function>
444df55fdeSJanie Lu  */
454df55fdeSJanie Lu 
464df55fdeSJanie Lu /* MACRO for table entries with no TGT ereports */
474df55fdeSJanie Lu #define	NT(class, bit, prep) class, bit, prep, NULL
484df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.* */
494df55fdeSJanie Lu fab_erpt_tbl_t fab_pci_erpt_tbl[] = {
504df55fdeSJanie Lu 	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
514df55fdeSJanie Lu 	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
524df55fdeSJanie Lu 	PCI_SIG_SERR,		PCI_STAT_S_SYSERR,	NULL,
534df55fdeSJanie Lu 	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
544df55fdeSJanie Lu 	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
554df55fdeSJanie Lu 	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
56940f2f58SToomas Soome 	NULL, 0, NULL
574df55fdeSJanie Lu };
584df55fdeSJanie Lu 
594df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.sec-* */
604df55fdeSJanie Lu static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = {
614df55fdeSJanie Lu 	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
624df55fdeSJanie Lu 	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
634df55fdeSJanie Lu 	PCI_REC_SERR,		PCI_STAT_S_SYSERR,	NULL,
644df55fdeSJanie Lu #ifdef sparc
654df55fdeSJanie Lu 	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
664df55fdeSJanie Lu #endif
674df55fdeSJanie Lu 	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
684df55fdeSJanie Lu 	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
69940f2f58SToomas Soome 	NULL, 0, NULL,
704df55fdeSJanie Lu };
714df55fdeSJanie Lu 
724df55fdeSJanie Lu 
734df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.dto */
744df55fdeSJanie Lu static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
754df55fdeSJanie Lu 	PCI_DTO,	PCI_BCNF_BCNTRL_DTO_STAT,	NULL,
76940f2f58SToomas Soome 	NULL, 0, NULL
774df55fdeSJanie Lu };
784df55fdeSJanie Lu 
794df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */
804df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = {
814df55fdeSJanie Lu 	PCIEX_RE,	PCIE_AER_CE_RECEIVER_ERR,	NULL,
824df55fdeSJanie Lu 	PCIEX_RNR,	PCIE_AER_CE_REPLAY_ROLLOVER,	NULL,
834df55fdeSJanie Lu 	PCIEX_RTO,	PCIE_AER_CE_REPLAY_TO,		NULL,
844df55fdeSJanie Lu 	PCIEX_BDP,	PCIE_AER_CE_BAD_DLLP,		NULL,
854df55fdeSJanie Lu 	PCIEX_BTP,	PCIE_AER_CE_BAD_TLP,		NULL,
864df55fdeSJanie Lu 	PCIEX_ANFE,	PCIE_AER_CE_AD_NFE,		NULL,
87940f2f58SToomas Soome 	NULL, 0, NULL
884df55fdeSJanie Lu };
894df55fdeSJanie Lu 
904df55fdeSJanie Lu /*
914df55fdeSJanie Lu  * Translate Fabric ereports to ereport.io.pciex.*
924df55fdeSJanie Lu  * The Target Ereports for this section is only used on leaf devices, with the
934df55fdeSJanie Lu  * exception of TO
944df55fdeSJanie Lu  */
954df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = {
964df55fdeSJanie Lu 	PCIEX_TE,	PCIE_AER_UCE_TRAINING,		NULL,
974df55fdeSJanie Lu 	PCIEX_DLP,	PCIE_AER_UCE_DLP,		NULL,
984df55fdeSJanie Lu 	PCIEX_SD,	PCIE_AER_UCE_SD,		NULL,
994df55fdeSJanie Lu 	PCIEX_ROF,	PCIE_AER_UCE_RO,		NULL,
1004df55fdeSJanie Lu 	PCIEX_FCP,	PCIE_AER_UCE_FCP,		NULL,
1014df55fdeSJanie Lu 	PCIEX_MFP,	PCIE_AER_UCE_MTLP,		NULL,
1024df55fdeSJanie Lu 	PCIEX_CTO,	PCIE_AER_UCE_TO,		PCI_TARG_MA,
1034df55fdeSJanie Lu 	PCIEX_UC,	PCIE_AER_UCE_UC,		NULL,
1044df55fdeSJanie Lu 	PCIEX_ECRC,	PCIE_AER_UCE_ECRC,		NULL,
1054df55fdeSJanie Lu 	PCIEX_CA,	PCIE_AER_UCE_CA,		PCI_TARG_REC_TA,
1064df55fdeSJanie Lu #ifdef sparc
1074df55fdeSJanie Lu 	PCIEX_UR,	PCIE_AER_UCE_UR,		PCI_TARG_MA,
1084df55fdeSJanie Lu #endif
1094df55fdeSJanie Lu 	PCIEX_POIS,	PCIE_AER_UCE_PTLP,		PCI_TARG_MDPE,
110940f2f58SToomas Soome 	NULL, 0, NULL
1114df55fdeSJanie Lu };
1124df55fdeSJanie Lu 
1134df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */
1144df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = {
1154df55fdeSJanie Lu 	PCIEX_S_TA_SC,	PCIE_AER_SUCE_TA_ON_SC,		PCI_TARG_REC_TA,
1164df55fdeSJanie Lu 	PCIEX_S_MA_SC,	PCIE_AER_SUCE_MA_ON_SC,		PCI_TARG_MA,
1174df55fdeSJanie Lu 	PCIEX_S_RTA,	PCIE_AER_SUCE_RCVD_TA,		PCI_TARG_REC_TA,
1184df55fdeSJanie Lu #ifdef sparc
1194df55fdeSJanie Lu 	PCIEX_S_RMA,	PCIE_AER_SUCE_RCVD_MA,		PCI_TARG_MA,
1204df55fdeSJanie Lu #endif
1214df55fdeSJanie Lu 	PCIEX_S_USC,	PCIE_AER_SUCE_USC_ERR,		NULL,
1224df55fdeSJanie Lu 	PCIEX_S_USCMD,	PCIE_AER_SUCE_USC_MSG_DATA_ERR,	PCI_TARG_REC_TA,
1234df55fdeSJanie Lu 	PCIEX_S_UDE,	PCIE_AER_SUCE_UC_DATA_ERR,	PCI_TARG_MDPE,
1244df55fdeSJanie Lu 	PCIEX_S_UAT,	PCIE_AER_SUCE_UC_ATTR_ERR,	PCI_TARG_MDPE,
1254df55fdeSJanie Lu 	PCIEX_S_UADR,	PCIE_AER_SUCE_UC_ADDR_ERR,	PCI_TARG_MDPE,
1264df55fdeSJanie Lu 	PCIEX_S_TEX,	PCIE_AER_SUCE_TIMER_EXPIRED,	NULL,
1274df55fdeSJanie Lu 	PCIEX_S_PERR,	PCIE_AER_SUCE_PERR_ASSERT,	PCI_TARG_MDPE,
1284df55fdeSJanie Lu 	PCIEX_S_SERR,	PCIE_AER_SUCE_SERR_ASSERT,	NULL,
1294df55fdeSJanie Lu 	PCIEX_INTERR,	PCIE_AER_SUCE_INTERNAL_ERR,	NULL,
130940f2f58SToomas Soome 	NULL, 0, NULL
1314df55fdeSJanie Lu };
1324df55fdeSJanie Lu 
1334df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pcix.* */
1344df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = {
1354df55fdeSJanie Lu 	PCIX_SPL_DIS,		PCI_PCIX_SPL_DSCD,	NULL,
1364df55fdeSJanie Lu 	PCIX_UNEX_SPL,		PCI_PCIX_UNEX_SPL,	NULL,
1374df55fdeSJanie Lu 	PCIX_RX_SPL_MSG,	PCI_PCIX_RX_SPL_MSG,	NULL,
138940f2f58SToomas Soome 	NULL, 0, NULL
1394df55fdeSJanie Lu };
1404df55fdeSJanie Lu static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
1414df55fdeSJanie Lu 
1424df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pcix.sec-* */
1434df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = {
1444df55fdeSJanie Lu 	PCIX_SPL_DIS,		PCI_PCIX_BSS_SPL_DSCD,	NULL,
1454df55fdeSJanie Lu 	PCIX_UNEX_SPL,		PCI_PCIX_BSS_UNEX_SPL,	NULL,
1464df55fdeSJanie Lu 	PCIX_BSS_SPL_OR,	PCI_PCIX_BSS_SPL_OR,	NULL,
1474df55fdeSJanie Lu 	PCIX_BSS_SPL_DLY,	PCI_PCIX_BSS_SPL_DLY,	NULL,
148940f2f58SToomas Soome 	NULL, 0, NULL
1494df55fdeSJanie Lu };
1504df55fdeSJanie Lu 
1514df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */
1524df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = {
1534df55fdeSJanie Lu #ifdef sparc
1544df55fdeSJanie Lu 	PCIEX_UR,		PCIE_DEVSTS_UR_DETECTED,	NULL,
1554df55fdeSJanie Lu #endif
1564df55fdeSJanie Lu 	PCIEX_FAT,		PCIE_DEVSTS_FE_DETECTED,	NULL,
1574df55fdeSJanie Lu 	PCIEX_NONFAT,		PCIE_DEVSTS_NFE_DETECTED,	NULL,
1584df55fdeSJanie Lu 	PCIEX_CORR,		PCIE_DEVSTS_CE_DETECTED,	NULL,
159940f2f58SToomas Soome 	NULL, 0, NULL
1604df55fdeSJanie Lu };
1614df55fdeSJanie Lu 
1624df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */
1634df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = {
1644df55fdeSJanie Lu 	PCIEX_RC_FE_MSG,	PCIE_AER_RE_STS_FE_MSGS_RCVD,	NULL,
1654df55fdeSJanie Lu 	PCIEX_RC_NFE_MSG,	PCIE_AER_RE_STS_NFE_MSGS_RCVD,	NULL,
1664df55fdeSJanie Lu 	PCIEX_RC_CE_MSG,	PCIE_AER_RE_STS_CE_RCVD,	NULL,
1674df55fdeSJanie Lu 	PCIEX_RC_MCE_MSG,	PCIE_AER_RE_STS_MUL_CE_RCVD,	NULL,
1684df55fdeSJanie Lu 	PCIEX_RC_MUE_MSG,	PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL,
169940f2f58SToomas Soome 	NULL, 0, NULL
1704df55fdeSJanie Lu };
1714df55fdeSJanie Lu 
1724df55fdeSJanie Lu /*
1734df55fdeSJanie Lu  * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages.
1744df55fdeSJanie Lu  * If the RP is not a PCIe compliant RP or does not support AER, rely on the
1754df55fdeSJanie Lu  * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC.
1764df55fdeSJanie Lu  */
1774df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = {
1784df55fdeSJanie Lu 	PCIEX_RC_FE_MSG,	PCIE_DEVSTS_FE_DETECTED,	NULL,
1794df55fdeSJanie Lu 	PCIEX_RC_NFE_MSG,	PCIE_DEVSTS_NFE_DETECTED,	NULL,
1804df55fdeSJanie Lu 	PCIEX_RC_CE_MSG,	PCIE_DEVSTS_CE_DETECTED,	NULL,
181940f2f58SToomas Soome 	NULL, 0, NULL,
1824df55fdeSJanie Lu };
1834df55fdeSJanie Lu 
1844df55fdeSJanie Lu /* ARGSUSED */
1854df55fdeSJanie Lu void
fab_pci_fabric_to_data(fmd_hdl_t * hdl,nvlist_t * nvl,fab_data_t * data)1864df55fdeSJanie Lu fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data)
1874df55fdeSJanie Lu {
1884df55fdeSJanie Lu 	data->nvl = nvl;
1894df55fdeSJanie Lu 
1904df55fdeSJanie Lu 	/* Generic PCI device information */
1914df55fdeSJanie Lu 	FAB_LOOKUP(16,	"bdf",			&data->bdf);
1924df55fdeSJanie Lu 	FAB_LOOKUP(16,	"device_id",		&data->device_id);
1934df55fdeSJanie Lu 	FAB_LOOKUP(16,	"vendor_id",		&data->vendor_id);
1944df55fdeSJanie Lu 	FAB_LOOKUP(8,	"rev_id",		&data->rev_id);
1954df55fdeSJanie Lu 	FAB_LOOKUP(16,	"dev_type",		&data->dev_type);
1964df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_off",		&data->pcie_off);
1974df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_off",		&data->pcix_off);
1984df55fdeSJanie Lu 	FAB_LOOKUP(16,	"aer_off",		&data->aer_off);
1994df55fdeSJanie Lu 	FAB_LOOKUP(16,	"ecc_ver",		&data->ecc_ver);
2004df55fdeSJanie Lu 
2014df55fdeSJanie Lu 	/* Misc ereport information */
2024df55fdeSJanie Lu 	FAB_LOOKUP(32,	"remainder",		&data->remainder);
2034df55fdeSJanie Lu 	FAB_LOOKUP(32,	"severity",		&data->severity);
2044df55fdeSJanie Lu 
2054df55fdeSJanie Lu 	/* PCI registers */
2064df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pci_status",		&data->pci_err_status);
2074df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pci_command",		&data->pci_cfg_comm);
2084df55fdeSJanie Lu 
2094df55fdeSJanie Lu 	/* PCI bridge registers */
2104df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pci_bdg_sec_status",	&data->pci_bdg_sec_stat);
2114df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pci_bdg_ctrl",		&data->pci_bdg_ctrl);
2124df55fdeSJanie Lu 
2134df55fdeSJanie Lu 	/* PCIx registers */
2144df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_status",		&data->pcix_status);
2154df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_command",		&data->pcix_command);
2164df55fdeSJanie Lu 
2174df55fdeSJanie Lu 	/* PCIx ECC Registers */
2184df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_ecc_control_0",	&data->pcix_ecc_control_0);
2194df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_ecc_status_0",	&data->pcix_ecc_status_0);
2204df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_0",	&data->pcix_ecc_fst_addr_0);
2214df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_0",	&data->pcix_ecc_sec_addr_0);
2224df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_attr_0",	&data->pcix_ecc_attr_0);
2234df55fdeSJanie Lu 
2244df55fdeSJanie Lu 	/* PCIx ECC Bridge Registers */
2254df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_ecc_control_1",	&data->pcix_ecc_control_1);
2264df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_ecc_status_1",	&data->pcix_ecc_status_1);
2274df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_1",	&data->pcix_ecc_fst_addr_1);
2284df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_1",	&data->pcix_ecc_sec_addr_1);
2294df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_ecc_attr_1",	&data->pcix_ecc_attr_1);
2304df55fdeSJanie Lu 
2314df55fdeSJanie Lu 	/* PCIx Bridge */
2324df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcix_bdg_status",	&data->pcix_bdg_stat);
2334df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcix_bdg_sec_status",	&data->pcix_bdg_sec_stat);
2344df55fdeSJanie Lu 
2354df55fdeSJanie Lu 	/* PCIe registers */
2364df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_status",		&data->pcie_err_status);
2374df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_command",		&data->pcie_err_ctl);
2384df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_dev_cap",		&data->pcie_dev_cap);
2394df55fdeSJanie Lu 
2404df55fdeSJanie Lu 	/* PCIe AER registers */
2414df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_adv_ctl",		&data->pcie_adv_ctl);
2424df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_status",	&data->pcie_ue_status);
2434df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_mask",		&data->pcie_ue_mask);
2444df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_sev",		&data->pcie_ue_sev);
2454df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_hdr0",		&data->pcie_ue_hdr[0]);
2464df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_hdr1",		&data->pcie_ue_hdr[1]);
2474df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_hdr2",		&data->pcie_ue_hdr[2]);
2484df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_hdr3",		&data->pcie_ue_hdr[3]);
2494df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ce_status",	&data->pcie_ce_status);
2504df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ce_mask",		&data->pcie_ce_mask);
2514df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_ue_tgt_trans",	&data->pcie_ue_tgt_trans);
2524df55fdeSJanie Lu 	FAB_LOOKUP(64,	"pcie_ue_tgt_addr",	&data->pcie_ue_tgt_addr);
2534df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_ue_tgt_bdf",	&data->pcie_ue_tgt_bdf);
2544df55fdeSJanie Lu 
2554df55fdeSJanie Lu 	/* PCIe BDG AER registers */
2564df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_adv_ctl",	&data->pcie_sue_ctl);
2574df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_status",	&data->pcie_sue_status);
2584df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_mask",	&data->pcie_sue_mask);
2594df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_sev",		&data->pcie_sue_sev);
2604df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_hdr0",	&data->pcie_sue_hdr[0]);
2614df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_hdr1",	&data->pcie_sue_hdr[1]);
2624df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_hdr2",	&data->pcie_sue_hdr[2]);
2634df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_hdr3",	&data->pcie_sue_hdr[3]);
2644df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_sue_tgt_trans",	&data->pcie_sue_tgt_trans);
2654df55fdeSJanie Lu 	FAB_LOOKUP(64,	"pcie_sue_tgt_addr",	&data->pcie_sue_tgt_addr);
2664df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_sue_tgt_bdf",	&data->pcie_sue_tgt_bdf);
2674df55fdeSJanie Lu 
2684df55fdeSJanie Lu 	/* PCIe RP registers */
2694df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_rp_status",	&data->pcie_rp_status);
2704df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_rp_control",	&data->pcie_rp_ctl);
2714df55fdeSJanie Lu 
2724df55fdeSJanie Lu 	/* PCIe RP AER registers */
2734df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_adv_rp_status",	&data->pcie_rp_err_status);
2744df55fdeSJanie Lu 	FAB_LOOKUP(32,	"pcie_adv_rp_command",	&data->pcie_rp_err_cmd);
2754df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id);
2764df55fdeSJanie Lu 	FAB_LOOKUP(16,	"pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id);
277*ffb64830SJordan Paige Hendricks 
278*ffb64830SJordan Paige Hendricks 	/*
279*ffb64830SJordan Paige Hendricks 	 * PCIe Parent Slot Registers
280*ffb64830SJordan Paige Hendricks 	 *
281*ffb64830SJordan Paige Hendricks 	 * These are only passed in the ereport if the parent PCIe component
282*ffb64830SJordan Paige Hendricks 	 * supports the registers and the registers have valid data. As such, we
283*ffb64830SJordan Paige Hendricks 	 * look up one slot register value first: If that value is present in
284*ffb64830SJordan Paige Hendricks 	 * the input ereport data, then we know the others should be there as
285*ffb64830SJordan Paige Hendricks 	 * well. We also set the pcie_slot_data_valid flag to ensure we know
286*ffb64830SJordan Paige Hendricks 	 * the slot register data is safe to use in the module.
287*ffb64830SJordan Paige Hendricks 	 */
288*ffb64830SJordan Paige Hendricks 	data->pcie_slot_data_valid = B_FALSE;
289*ffb64830SJordan Paige Hendricks 	if (nvlist_lookup_uint32(nvl, "pcie_slot_cap", &data->pcie_slot_cap) ==
290*ffb64830SJordan Paige Hendricks 	    0) {
291*ffb64830SJordan Paige Hendricks 		FAB_LOOKUP(16,	"pcie_slot_control", &data->pcie_slot_control);
292*ffb64830SJordan Paige Hendricks 		FAB_LOOKUP(16,	"pcie_slot_status", &data->pcie_slot_status);
293*ffb64830SJordan Paige Hendricks 		data->pcie_slot_data_valid = B_TRUE;
294*ffb64830SJordan Paige Hendricks 	}
2954df55fdeSJanie Lu }
2964df55fdeSJanie Lu 
2974df55fdeSJanie Lu static int
fab_prep_pci_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)2984df55fdeSJanie Lu fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
2994df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
3004df55fdeSJanie Lu {
3014df55fdeSJanie Lu 	const char *class = tbl->err_class;
3024df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
3034df55fdeSJanie Lu 
3044df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
3054df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
3064df55fdeSJanie Lu 	    PCI_ERROR_SUBCLASS, class);
3074df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
3084df55fdeSJanie Lu 
3094df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status);
3104df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm);
3114df55fdeSJanie Lu 
3124df55fdeSJanie Lu 	return (err);
3134df55fdeSJanie Lu }
3144df55fdeSJanie Lu 
3154df55fdeSJanie Lu static int
fab_prep_pci_bdg_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)3164df55fdeSJanie Lu fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
3174df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
3184df55fdeSJanie Lu {
3194df55fdeSJanie Lu 	const char *class = tbl->err_class;
3204df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
3214df55fdeSJanie Lu 
3224df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
3234df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s",
3244df55fdeSJanie Lu 	    PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class);
3254df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
3264df55fdeSJanie Lu 
3274df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
3284df55fdeSJanie Lu 	    data->pci_bdg_sec_stat);
3294df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
3304df55fdeSJanie Lu 
3314df55fdeSJanie Lu 	return (err);
3324df55fdeSJanie Lu }
3334df55fdeSJanie Lu 
3344df55fdeSJanie Lu static int
fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)3354df55fdeSJanie Lu fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
3364df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
3374df55fdeSJanie Lu {
3384df55fdeSJanie Lu 	const char *class = tbl->err_class;
3394df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
3404df55fdeSJanie Lu 
3414df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
3424df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
3434df55fdeSJanie Lu 	    PCI_ERROR_SUBCLASS, class);
3444df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
3454df55fdeSJanie Lu 
3464df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
3474df55fdeSJanie Lu 	    data->pci_bdg_sec_stat);
3484df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
3494df55fdeSJanie Lu 
3504df55fdeSJanie Lu 	return (err);
3514df55fdeSJanie Lu }
3524df55fdeSJanie Lu 
3534df55fdeSJanie Lu 
3544df55fdeSJanie Lu static int
fab_prep_pcie_ce_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)3554df55fdeSJanie Lu fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
3564df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
3574df55fdeSJanie Lu {
3584df55fdeSJanie Lu 	const char *class = tbl->err_class;
3594df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
3604df55fdeSJanie Lu 
3614df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
3624df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
3634df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
3644df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
3654df55fdeSJanie Lu 
3664df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
3674df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG,
3684df55fdeSJanie Lu 	    data->pcie_ce_status);
3694df55fdeSJanie Lu 
3704df55fdeSJanie Lu 	return (err);
3714df55fdeSJanie Lu }
3724df55fdeSJanie Lu 
3734df55fdeSJanie Lu static int
fab_prep_pcie_ue_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)3744df55fdeSJanie Lu fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
3754df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
3764df55fdeSJanie Lu {
3774df55fdeSJanie Lu 	const char *class = tbl->err_class;
3784df55fdeSJanie Lu 	uint32_t first_err = 1 << (data->pcie_adv_ctl &
3794df55fdeSJanie Lu 	    PCIE_AER_CTL_FST_ERR_PTR_MASK);
3804df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
3814df55fdeSJanie Lu 
382*ffb64830SJordan Paige Hendricks 	if (data->pcie_slot_data_valid) {
383*ffb64830SJordan Paige Hendricks 		(void) nvlist_add_uint32(erpt, "pcie_slot_cap",
384*ffb64830SJordan Paige Hendricks 		    data->pcie_slot_cap);
385*ffb64830SJordan Paige Hendricks 		(void) nvlist_add_uint16(erpt, "pcie_slot_control",
386*ffb64830SJordan Paige Hendricks 		    data->pcie_slot_control);
387*ffb64830SJordan Paige Hendricks 		(void) nvlist_add_uint16(erpt, "pcie_slot_status",
388*ffb64830SJordan Paige Hendricks 		    data->pcie_slot_status);
389*ffb64830SJordan Paige Hendricks 
390*ffb64830SJordan Paige Hendricks 		/*
391*ffb64830SJordan Paige Hendricks 		 * It is possible to see uncorrectable errors for a slot that
392*ffb64830SJordan Paige Hendricks 		 * are related to the slot's child device being physically
393*ffb64830SJordan Paige Hendricks 		 * removed from the slot. As such, in the case that the slot
394*ffb64830SJordan Paige Hendricks 		 * reports that it is empty, we do not want to generate an
395*ffb64830SJordan Paige Hendricks 		 * ereport for all errors. Generating an ereport here will cause
396*ffb64830SJordan Paige Hendricks 		 * the eft module to fault the device and io-retire to
397*ffb64830SJordan Paige Hendricks 		 * subsequently retire the device. Retiring the device makes
398*ffb64830SJordan Paige Hendricks 		 * little sense given that the device is physically gone; more
399*ffb64830SJordan Paige Hendricks 		 * confusingly, if plugged back into the slot, it would be
400*ffb64830SJordan Paige Hendricks 		 * marked retired already.
401*ffb64830SJordan Paige Hendricks 		 *
402*ffb64830SJordan Paige Hendricks 		 * The only error ignored for this case is Completion Timeout.
403*ffb64830SJordan Paige Hendricks 		 * It is possible more errors should be ignored, and if they
404*ffb64830SJordan Paige Hendricks 		 * are seen in the field it might be worth broadening the set
405*ffb64830SJordan Paige Hendricks 		 * of ignored errors.
406*ffb64830SJordan Paige Hendricks 		 */
407*ffb64830SJordan Paige Hendricks 		if (tbl->reg_bit == PCIE_AER_UCE_TO &&
408*ffb64830SJordan Paige Hendricks 		    ((data->pcie_slot_status &
409*ffb64830SJordan Paige Hendricks 		    PCIE_SLOTSTS_PRESENCE_DETECTED) == 0x0)) {
410*ffb64830SJordan Paige Hendricks 			return (PF_EREPORT_IGNORE);
411*ffb64830SJordan Paige Hendricks 		}
412*ffb64830SJordan Paige Hendricks 	}
413*ffb64830SJordan Paige Hendricks 
4144df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
4154df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
4164df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
4174df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
4184df55fdeSJanie Lu 
4194df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
4204df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG,
4214df55fdeSJanie Lu 	    data->pcie_ue_status);
4224df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev);
4234df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl);
4244df55fdeSJanie Lu 
4254df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
4264df55fdeSJanie Lu 
4274df55fdeSJanie Lu 	if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) {
4284df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
4294df55fdeSJanie Lu 		    data->pcie_ue_tgt_bdf);
4304df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
4314df55fdeSJanie Lu 	} else {
4324df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
4334df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
4344df55fdeSJanie Lu 	}
4354df55fdeSJanie Lu 
4364df55fdeSJanie Lu 	if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
4374df55fdeSJanie Lu 	    data->pcie_ue_tgt_trans) {
4384df55fdeSJanie Lu 		if (tbl->tgt_class)
4394df55fdeSJanie Lu 			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE);
4404df55fdeSJanie Lu 	}
4414df55fdeSJanie Lu 
4424df55fdeSJanie Lu 	return (err);
4434df55fdeSJanie Lu }
4444df55fdeSJanie Lu 
4454df55fdeSJanie Lu static int
fab_prep_pcie_sue_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)4464df55fdeSJanie Lu fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
4474df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
4484df55fdeSJanie Lu {
4494df55fdeSJanie Lu 	const char *class = tbl->err_class;
4504df55fdeSJanie Lu 	uint32_t first_err = 1 << (data->pcie_sue_ctl &
4514df55fdeSJanie Lu 	    PCIE_AER_SCTL_FST_ERR_PTR_MASK);
4524df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
4534df55fdeSJanie Lu 
4544df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
4554df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
4564df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
4574df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
4584df55fdeSJanie Lu 
4594df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS,
4604df55fdeSJanie Lu 	    data->pcie_sue_status);
4614df55fdeSJanie Lu 
4624df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
4634df55fdeSJanie Lu 
4644df55fdeSJanie Lu 	if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) {
4654df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
4664df55fdeSJanie Lu 		    data->pcie_sue_tgt_bdf);
4674df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
4684df55fdeSJanie Lu 	} else {
4694df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
4704df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
4714df55fdeSJanie Lu 	}
4724df55fdeSJanie Lu 
4734df55fdeSJanie Lu 	if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
4744df55fdeSJanie Lu 	    data->pcie_sue_tgt_trans) {
4754df55fdeSJanie Lu 		if (tbl->tgt_class)
4764df55fdeSJanie Lu 			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE);
4774df55fdeSJanie Lu 	}
4784df55fdeSJanie Lu 
4794df55fdeSJanie Lu 	return (err);
4804df55fdeSJanie Lu }
4814df55fdeSJanie Lu 
4824df55fdeSJanie Lu static int
fab_prep_pcix_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)4834df55fdeSJanie Lu fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
4844df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
4854df55fdeSJanie Lu {
4864df55fdeSJanie Lu 	const char *class = tbl->err_class;
4874df55fdeSJanie Lu 	int err = 0;
4884df55fdeSJanie Lu 
4894df55fdeSJanie Lu 	/* Only send if this is not a bridge */
4904df55fdeSJanie Lu 	if (!data->pcix_status || data->pcix_bdg_sec_stat)
4914df55fdeSJanie Lu 		return (1);
4924df55fdeSJanie Lu 
4934df55fdeSJanie Lu 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
4944df55fdeSJanie Lu 
4954df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
4964df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
4974df55fdeSJanie Lu 	    PCIX_ERROR_SUBCLASS, class);
4984df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
4994df55fdeSJanie Lu 
5004df55fdeSJanie Lu 	(void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command);
5014df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
5024df55fdeSJanie Lu 
5034df55fdeSJanie Lu 	return (err);
5044df55fdeSJanie Lu }
5054df55fdeSJanie Lu 
5064df55fdeSJanie Lu static void
fab_send_pcix_ecc_erpt(fmd_hdl_t * hdl,fab_data_t * data)5074df55fdeSJanie Lu fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
5084df55fdeSJanie Lu {
5094df55fdeSJanie Lu 	nvlist_t *erpt;
5104df55fdeSJanie Lu 	int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4;
5114df55fdeSJanie Lu 	int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR;
5124df55fdeSJanie Lu 	int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE;
5134df55fdeSJanie Lu 	int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE;
5144df55fdeSJanie Lu 	uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) |
5154df55fdeSJanie Lu 	    data->pcix_ecc_status_0;
5164df55fdeSJanie Lu 
5174df55fdeSJanie Lu 	switch (ecc_phase) {
5184df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_NOERR:
5194df55fdeSJanie Lu 		break;
5204df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_FADDR:
5214df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_SADDR:
5224df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
5234df55fdeSJanie Lu 		    "%s.%s", PCIX_ERROR_SUBCLASS,
5244df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
5254df55fdeSJanie Lu 		break;
5264df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_ATTR:
5274df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
5284df55fdeSJanie Lu 		    "%s.%s", PCIX_ERROR_SUBCLASS,
5294df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
5304df55fdeSJanie Lu 		break;
5314df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_DATA32:
5324df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_DATA64:
5334df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
5344df55fdeSJanie Lu 		    "%s.%s", PCIX_ERROR_SUBCLASS,
5354df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
5364df55fdeSJanie Lu 		break;
5374df55fdeSJanie Lu 	}
5384df55fdeSJanie Lu 
5394df55fdeSJanie Lu 	if (ecc_phase) {
5404df55fdeSJanie Lu 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
5414df55fdeSJanie Lu 			goto done;
5424df55fdeSJanie Lu 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
5434df55fdeSJanie Lu 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
5444df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
5454df55fdeSJanie Lu 		    data->pcix_command);
5464df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
5474df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
5484df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
5494df55fdeSJanie Lu 		    data->pcix_ecc_attr_0);
5504df55fdeSJanie Lu 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
5514df55fdeSJanie Lu 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
5524df55fdeSJanie Lu 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
5534df55fdeSJanie Lu 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
5544df55fdeSJanie Lu 	}
5554df55fdeSJanie Lu 
5564df55fdeSJanie Lu 	if (sec_ce || sec_ue) {
5574df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
5584df55fdeSJanie Lu 		    "%s.%s", PCIX_ERROR_SUBCLASS,
5594df55fdeSJanie Lu 		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
5604df55fdeSJanie Lu 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
5614df55fdeSJanie Lu 			goto done;
5624df55fdeSJanie Lu 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
5634df55fdeSJanie Lu 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
5644df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
5654df55fdeSJanie Lu 		    data->pcix_command);
5664df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
5674df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
5684df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
5694df55fdeSJanie Lu 		    data->pcix_ecc_attr_0);
5704df55fdeSJanie Lu 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
5714df55fdeSJanie Lu 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
5724df55fdeSJanie Lu 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
5734df55fdeSJanie Lu 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
5744df55fdeSJanie Lu 	}
5754df55fdeSJanie Lu 
5764df55fdeSJanie Lu 	return;
5774df55fdeSJanie Lu done:
5784df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
5794df55fdeSJanie Lu }
5804df55fdeSJanie Lu 
5814df55fdeSJanie Lu static int
fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)5824df55fdeSJanie Lu fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
5834df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
5844df55fdeSJanie Lu {
5854df55fdeSJanie Lu 	const char *class = tbl->err_class;
5864df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
5874df55fdeSJanie Lu 
5884df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
5894df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s",
5904df55fdeSJanie Lu 	    PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class);
5914df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
5924df55fdeSJanie Lu 
5934df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
5944df55fdeSJanie Lu 	    data->pcix_bdg_sec_stat);
5954df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
5964df55fdeSJanie Lu 
5974df55fdeSJanie Lu 	return (err);
5984df55fdeSJanie Lu }
5994df55fdeSJanie Lu 
6004df55fdeSJanie Lu static int
fab_prep_pcix_bdg_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)6014df55fdeSJanie Lu fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
6024df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
6034df55fdeSJanie Lu {
6044df55fdeSJanie Lu 	const char *class = tbl->err_class;
6054df55fdeSJanie Lu 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
6064df55fdeSJanie Lu 
6074df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
6084df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
6094df55fdeSJanie Lu 	    PCIX_ERROR_SUBCLASS, class);
6104df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
6114df55fdeSJanie Lu 
6124df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
6134df55fdeSJanie Lu 	    data->pcix_bdg_sec_stat);
6144df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
6154df55fdeSJanie Lu 
6164df55fdeSJanie Lu 	return (err);
6174df55fdeSJanie Lu }
6184df55fdeSJanie Lu 
6194df55fdeSJanie Lu static void
fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t * hdl,fab_data_t * data)6204df55fdeSJanie Lu fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
6214df55fdeSJanie Lu {
6224df55fdeSJanie Lu 	nvlist_t *erpt;
6234df55fdeSJanie Lu 	int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4;
6244df55fdeSJanie Lu 	int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR;
6254df55fdeSJanie Lu 	int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE;
6264df55fdeSJanie Lu 	int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE;
6274df55fdeSJanie Lu 	uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) |
6284df55fdeSJanie Lu 	    data->pcix_ecc_status_1;
6294df55fdeSJanie Lu 
6304df55fdeSJanie Lu 	switch (ecc_phase) {
6314df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_NOERR:
6324df55fdeSJanie Lu 		break;
6334df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_FADDR:
6344df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_SADDR:
6354df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
6364df55fdeSJanie Lu 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
6374df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
6384df55fdeSJanie Lu 		break;
6394df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_ATTR:
6404df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
6414df55fdeSJanie Lu 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
6424df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
6434df55fdeSJanie Lu 		break;
6444df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_DATA32:
6454df55fdeSJanie Lu 	case PCI_PCIX_ECC_PHASE_DATA64:
6464df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
6474df55fdeSJanie Lu 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
6484df55fdeSJanie Lu 		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
6494df55fdeSJanie Lu 		break;
6504df55fdeSJanie Lu 	}
6514df55fdeSJanie Lu 	if (ecc_phase) {
6524df55fdeSJanie Lu 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
6534df55fdeSJanie Lu 			goto done;
6544df55fdeSJanie Lu 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
6554df55fdeSJanie Lu 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
6564df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
6574df55fdeSJanie Lu 		    data->pcix_bdg_sec_stat);
6584df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
6594df55fdeSJanie Lu 		    data->pcix_bdg_stat);
6604df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
6614df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
6624df55fdeSJanie Lu 		    data->pcix_ecc_attr_1);
6634df55fdeSJanie Lu 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
6644df55fdeSJanie Lu 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
6654df55fdeSJanie Lu 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
6664df55fdeSJanie Lu 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
6674df55fdeSJanie Lu 	}
6684df55fdeSJanie Lu 
6694df55fdeSJanie Lu 	if (sec_ce || sec_ue) {
6704df55fdeSJanie Lu 		(void) snprintf(fab_buf, FM_MAX_CLASS,
6714df55fdeSJanie Lu 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
6724df55fdeSJanie Lu 		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
6734df55fdeSJanie Lu 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
6744df55fdeSJanie Lu 			goto done;
6754df55fdeSJanie Lu 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
6764df55fdeSJanie Lu 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
6774df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
6784df55fdeSJanie Lu 		    data->pcix_bdg_sec_stat);
6794df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
6804df55fdeSJanie Lu 		    data->pcix_bdg_stat);
6814df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
6824df55fdeSJanie Lu 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
6834df55fdeSJanie Lu 		    data->pcix_ecc_attr_1);
6844df55fdeSJanie Lu 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
6854df55fdeSJanie Lu 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
6864df55fdeSJanie Lu 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
6874df55fdeSJanie Lu 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
6884df55fdeSJanie Lu 	}
6894df55fdeSJanie Lu 	return;
6904df55fdeSJanie Lu done:
6914df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
6924df55fdeSJanie Lu }
6934df55fdeSJanie Lu 
6944df55fdeSJanie Lu static int
fab_prep_pcie_nadv_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)6954df55fdeSJanie Lu fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
6964df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
6974df55fdeSJanie Lu {
6984df55fdeSJanie Lu 	const char *class = tbl->err_class;
6994df55fdeSJanie Lu 	int err = 0;
7004df55fdeSJanie Lu 
7014df55fdeSJanie Lu 	/* Don't send this for PCI device, Root Ports, or PCIe with AER */
7024df55fdeSJanie Lu 	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
7034df55fdeSJanie Lu 	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
7044df55fdeSJanie Lu 	    data->aer_off)
7054df55fdeSJanie Lu 		return (1);
7064df55fdeSJanie Lu 
7074df55fdeSJanie Lu 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
7084df55fdeSJanie Lu 
7094df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
7104df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
7114df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
7124df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
7134df55fdeSJanie Lu 
7144df55fdeSJanie Lu 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
7154df55fdeSJanie Lu 
7164df55fdeSJanie Lu 	return (err);
7174df55fdeSJanie Lu }
7184df55fdeSJanie Lu 
7194df55fdeSJanie Lu static int
fab_prep_pcie_rc_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)7204df55fdeSJanie Lu fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
7214df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
7224df55fdeSJanie Lu {
7234df55fdeSJanie Lu 	const char *class = tbl->err_class;
7244df55fdeSJanie Lu 	uint32_t status = data->pcie_rp_err_status;
7254df55fdeSJanie Lu 	int err = 0;
7264df55fdeSJanie Lu 	int isFE = 0, isNFE = 0;
7274df55fdeSJanie Lu 
7284df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class);
7294df55fdeSJanie Lu 
7304df55fdeSJanie Lu 	if (!data->aer_off)
7314df55fdeSJanie Lu 		return (-1);
7324df55fdeSJanie Lu 
7334df55fdeSJanie Lu 	/* Only send a FE Msg if the 1st UE error is FE */
7344df55fdeSJanie Lu 	if (STRCMP(class, PCIEX_RC_FE_MSG))
7354df55fdeSJanie Lu 		if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL))
7364df55fdeSJanie Lu 			return (-1);
7374df55fdeSJanie Lu 		else
7384df55fdeSJanie Lu 			isFE = 1;
7394df55fdeSJanie Lu 
7404df55fdeSJanie Lu 	/* Only send a NFE Msg is the 1st UE error is NFE */
7414df55fdeSJanie Lu 	if (STRCMP(class, PCIEX_RC_NFE_MSG))
7424df55fdeSJanie Lu 		if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL)
7434df55fdeSJanie Lu 			return (-1);
7444df55fdeSJanie Lu 		else
7454df55fdeSJanie Lu 			isNFE = 1;
7464df55fdeSJanie Lu 
7474df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "XLATE RP Error");
7484df55fdeSJanie Lu 
7494df55fdeSJanie Lu 	err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
7504df55fdeSJanie Lu 
7514df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
7524df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
7534df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
7544df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
7554df55fdeSJanie Lu 
7564df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status);
7574df55fdeSJanie Lu 	if ((isFE || isNFE) && data->pcie_rp_ue_src_id) {
7584df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
7594df55fdeSJanie Lu 		    data->pcie_rp_ue_src_id);
7604df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
7614df55fdeSJanie Lu 	}
7624df55fdeSJanie Lu 	if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) {
7634df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
7644df55fdeSJanie Lu 		    data->pcie_rp_ce_src_id);
7654df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
7664df55fdeSJanie Lu 	}
7674df55fdeSJanie Lu 
7684df55fdeSJanie Lu 	return (err);
7694df55fdeSJanie Lu }
7704df55fdeSJanie Lu 
7714df55fdeSJanie Lu static int
fab_prep_pcie_fake_rc_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)7724df55fdeSJanie Lu fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
7734df55fdeSJanie Lu     fab_erpt_tbl_t *tbl)
7744df55fdeSJanie Lu {
7754df55fdeSJanie Lu 	const char *class = tbl->err_class;
7764df55fdeSJanie Lu 	uint32_t rc_err_sts = 0;
7774df55fdeSJanie Lu 	int err = 0;
7784df55fdeSJanie Lu 
7794df55fdeSJanie Lu 	/*
7804df55fdeSJanie Lu 	 * Don't send this for PCI device or Root Ports.  Only send it on
7814df55fdeSJanie Lu 	 * systems with non-compliant RPs.
7824df55fdeSJanie Lu 	 */
7834df55fdeSJanie Lu 	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
7844df55fdeSJanie Lu 	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
7854df55fdeSJanie Lu 	    (!fab_xlate_fake_rp))
7864df55fdeSJanie Lu 		return (-1);
7874df55fdeSJanie Lu 
7884df55fdeSJanie Lu 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE);
7894df55fdeSJanie Lu 
7904df55fdeSJanie Lu 	/* Generate an ereport for this error bit. */
7914df55fdeSJanie Lu 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
7924df55fdeSJanie Lu 	    PCIEX_ERROR_SUBCLASS, class);
7934df55fdeSJanie Lu 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
7944df55fdeSJanie Lu 
7954df55fdeSJanie Lu 	/* Send PCIe RC Ereports */
7964df55fdeSJanie Lu 	if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) {
7974df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD;
7984df55fdeSJanie Lu 	}
7994df55fdeSJanie Lu 
8004df55fdeSJanie Lu 	/* NFE/FE src id takes precedence over CE src id */
8014df55fdeSJanie Lu 	if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) {
8024df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
8034df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
8044df55fdeSJanie Lu 	}
8054df55fdeSJanie Lu 	if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) {
8064df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
8074df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
8084df55fdeSJanie Lu 	}
8094df55fdeSJanie Lu 	if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) &&
8104df55fdeSJanie Lu 	    (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) {
8114df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
8124df55fdeSJanie Lu 		rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD;
8134df55fdeSJanie Lu 	}
8144df55fdeSJanie Lu 
8154df55fdeSJanie Lu 	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts);
8164df55fdeSJanie Lu 
8174df55fdeSJanie Lu 	if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) {
8184df55fdeSJanie Lu 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf);
8194df55fdeSJanie Lu 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
8204df55fdeSJanie Lu 	}
8214df55fdeSJanie Lu 
8224df55fdeSJanie Lu 	return (err);
8234df55fdeSJanie Lu }
8244df55fdeSJanie Lu 
8254df55fdeSJanie Lu void
fab_xlate_pcie_erpts(fmd_hdl_t * hdl,fab_data_t * data)8264df55fdeSJanie Lu fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data)
8274df55fdeSJanie Lu {
8284df55fdeSJanie Lu 	fab_err_tbl_t *tbl;
8294df55fdeSJanie Lu 
8304df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "Sending Ereports Now");
8314df55fdeSJanie Lu 
832*ffb64830SJordan Paige Hendricks 	/* Go through the error logs and send the relevant reports */
8334df55fdeSJanie Lu 	for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) {
8344df55fdeSJanie Lu 		fab_send_erpt(hdl, data, tbl);
8354df55fdeSJanie Lu 	}
8364df55fdeSJanie Lu 
8374df55fdeSJanie Lu 	/* Send PCI-X ECC Ereports */
8384df55fdeSJanie Lu 	fab_send_pcix_ecc_erpt(hdl, data);
8394df55fdeSJanie Lu 	fab_send_pcix_bdg_ecc_erpt(hdl, data);
8404df55fdeSJanie Lu }
8414df55fdeSJanie Lu 
8424df55fdeSJanie Lu void
fab_xlate_fabric_erpts(fmd_hdl_t * hdl,nvlist_t * nvl,const char * class)8434df55fdeSJanie Lu fab_xlate_fabric_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class)
8444df55fdeSJanie Lu {
8454df55fdeSJanie Lu 	fab_data_t data = {0};
8464df55fdeSJanie Lu 
8474df55fdeSJanie Lu 	fmd_hdl_debug(hdl, "fabric ereport received: %s\n", class);
8484df55fdeSJanie Lu 
8494df55fdeSJanie Lu 	fab_pci_fabric_to_data(hdl, nvl, &data);
8504df55fdeSJanie Lu 	fab_xlate_pcie_erpts(hdl, &data);
8514df55fdeSJanie Lu }
8524df55fdeSJanie Lu 
853b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China void
fab_set_fake_rp(fmd_hdl_t * hdl)854b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fab_set_fake_rp(fmd_hdl_t *hdl)
855b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China {
856b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	char *rppath = fab_get_rpdev(hdl), *str = NULL;
857b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	int count = 0;
858b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 
859b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	if (!rppath) {
860b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		fmd_hdl_debug(hdl, "Can't find root port dev path");
861b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		return;
862b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	}
863b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 
864b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	/*
865b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	 * For the path '/pci@xxx' is fake root port,
866b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	 * and  '/pci@xxx/pci@y' is real root port.
867b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	 */
868b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	str = rppath;
869b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	while (*str) {
870b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		if (*str == '/')
871b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 			count++;
872b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		str++;
873b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	}
874b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 
875b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	if (count == 1)
876b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		fab_xlate_fake_rp = B_TRUE;
877b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	else
878b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		/*
879b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		 * If count is 0, then it should still be B_FALSE
880b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		 */
881b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 		fab_xlate_fake_rp = B_FALSE;
882b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 
883b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	fmd_hdl_strfree(hdl, rppath);
884b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China }
885b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 
8864df55fdeSJanie Lu #define	SET_TBL(n, err, reg, sz) \
8874df55fdeSJanie Lu 	fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \
8884df55fdeSJanie Lu 	fab_master_err_tbl[n].reg_offset = offsetof(fab_data_t, reg); \
8894df55fdeSJanie Lu 	fab_master_err_tbl[n].reg_size = sz; \
8904df55fdeSJanie Lu 	fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt;
8914df55fdeSJanie Lu 
8924df55fdeSJanie Lu void
fab_setup_master_table()8934df55fdeSJanie Lu fab_setup_master_table()
8944df55fdeSJanie Lu {
8954df55fdeSJanie Lu 	/* Setup the master error table */
8964df55fdeSJanie Lu 	fab_master_err_tbl = (fab_err_tbl_t *)calloc(13,
8974df55fdeSJanie Lu 	    sizeof (fab_err_tbl_t));
8984df55fdeSJanie Lu 
8994df55fdeSJanie Lu 	SET_TBL(0, pci,			pci_err_status,	    16);
9004df55fdeSJanie Lu 	SET_TBL(1, pci_bdg,		pci_bdg_sec_stat,   16);
9014df55fdeSJanie Lu 	SET_TBL(2, pci_bdg_ctl,		pci_bdg_ctrl,	    16);
9024df55fdeSJanie Lu 	SET_TBL(3, pcie_ce,		pcie_ce_status,	    32);
9034df55fdeSJanie Lu 	SET_TBL(4, pcie_ue,		pcie_ue_status,	    32);
9044df55fdeSJanie Lu 	SET_TBL(5, pcie_sue,		pcie_sue_status,    32);
9054df55fdeSJanie Lu 	SET_TBL(6, pcix,		pcix_status,	    32);
9064df55fdeSJanie Lu 	SET_TBL(7, pcix_bdg_sec,	pcix_bdg_sec_stat,  16);
9074df55fdeSJanie Lu 	SET_TBL(8, pcix_bdg,		pcix_bdg_stat,	    32);
9084df55fdeSJanie Lu 	SET_TBL(9, pcie_nadv,		pcie_err_status,    16);
9094df55fdeSJanie Lu 	SET_TBL(10, pcie_rc,		pcie_rp_err_status, 32);
9104df55fdeSJanie Lu 	SET_TBL(11, pcie_fake_rc,	pcie_err_status,    16);
9114df55fdeSJanie Lu }
912