Home | History | Annotate | Download | only in os
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <sys/types.h>
     28 #include <sys/sunndi.h>
     29 #include <sys/sysmacros.h>
     30 #include <sys/ddifm_impl.h>
     31 #include <sys/fm/util.h>
     32 #include <sys/fm/protocol.h>
     33 #include <sys/fm/io/pci.h>
     34 #include <sys/fm/io/ddi.h>
     35 #include <sys/pci.h>
     36 #include <sys/pci_cap.h>
     37 #include <sys/pci_impl.h>
     38 #include <sys/epm.h>
     39 #include <sys/pcifm.h>
     40 
     41 #define	PCIX_ECC_VER_CHECK(x)	(((x) == PCI_PCIX_VER_1) ||\
     42 				((x) == PCI_PCIX_VER_2))
     43 
     44 errorq_t *pci_target_queue = NULL;
     45 
     46 pci_fm_err_t pci_err_tbl[] = {
     47 	PCI_DET_PERR,	PCI_STAT_PERROR,	NULL,		DDI_FM_UNKNOWN,
     48 	PCI_MDPE,	PCI_STAT_S_PERROR,	PCI_TARG_MDPE,	DDI_FM_UNKNOWN,
     49 	PCI_SIG_SERR,	PCI_STAT_S_SYSERR,	NULL,		DDI_FM_FATAL,
     50 	PCI_MA,		PCI_STAT_R_MAST_AB,	PCI_TARG_MA,	DDI_FM_UNKNOWN,
     51 	PCI_REC_TA,	PCI_STAT_R_TARG_AB,	PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
     52 	PCI_SIG_TA,	PCI_STAT_S_TARG_AB,	NULL,		DDI_FM_UNKNOWN,
     53 	NULL, NULL, NULL, NULL,
     54 };
     55 
     56 pci_fm_err_t pci_bdg_err_tbl[] = {
     57 	PCI_DET_PERR,	PCI_STAT_PERROR,	NULL,		DDI_FM_UNKNOWN,
     58 	PCI_MDPE,	PCI_STAT_S_PERROR,	PCI_TARG_MDPE,	DDI_FM_UNKNOWN,
     59 	PCI_REC_SERR,	PCI_STAT_S_SYSERR,	NULL,		DDI_FM_UNKNOWN,
     60 #if defined(__sparc)
     61 	PCI_MA,		PCI_STAT_R_MAST_AB,	PCI_TARG_MA,	DDI_FM_UNKNOWN,
     62 #endif
     63 	PCI_REC_TA,	PCI_STAT_R_TARG_AB,	PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
     64 	PCI_SIG_TA,	PCI_STAT_S_TARG_AB,	NULL,		DDI_FM_UNKNOWN,
     65 	NULL, NULL, NULL, NULL,
     66 };
     67 
     68 static pci_fm_err_t pcix_err_tbl[] = {
     69 	PCIX_SPL_DIS,		PCI_PCIX_SPL_DSCD,	NULL,	DDI_FM_UNKNOWN,
     70 	PCIX_UNEX_SPL,		PCI_PCIX_UNEX_SPL,	NULL,	DDI_FM_UNKNOWN,
     71 	PCIX_RX_SPL_MSG,	PCI_PCIX_RX_SPL_MSG,	NULL,   DDI_FM_UNKNOWN,
     72 	NULL, NULL, NULL, NULL,
     73 };
     74 
     75 static pci_fm_err_t pcix_sec_err_tbl[] = {
     76 	PCIX_SPL_DIS,		PCI_PCIX_BSS_SPL_DSCD,	NULL,	DDI_FM_UNKNOWN,
     77 	PCIX_UNEX_SPL,		PCI_PCIX_BSS_UNEX_SPL,	NULL,	DDI_FM_UNKNOWN,
     78 	PCIX_BSS_SPL_OR,	PCI_PCIX_BSS_SPL_OR,	NULL,	DDI_FM_OK,
     79 	PCIX_BSS_SPL_DLY,	PCI_PCIX_BSS_SPL_DLY,	NULL,	DDI_FM_OK,
     80 	NULL, NULL, NULL, NULL,
     81 };
     82 
     83 static int
     84 pci_config_check(ddi_acc_handle_t handle, int fme_flag)
     85 {
     86 	ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle);
     87 	ddi_fm_error_t de;
     88 
     89 	if (!(DDI_FM_ACC_ERR_CAP(ddi_fm_capable(hp->ah_dip))))
     90 		return (DDI_FM_OK);
     91 
     92 	de.fme_version = DDI_FME_VERSION;
     93 
     94 	ddi_fm_acc_err_get(handle, &de, de.fme_version);
     95 	if (de.fme_status != DDI_FM_OK) {
     96 		if (fme_flag == DDI_FM_ERR_UNEXPECTED) {
     97 			char buf[FM_MAX_CLASS];
     98 
     99 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
    100 			    PCI_ERROR_SUBCLASS, PCI_NR);
    101 			ddi_fm_ereport_post(hp->ah_dip, buf, de.fme_ena,
    102 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, NULL);
    103 		}
    104 		ddi_fm_acc_err_clear(handle, de.fme_version);
    105 	}
    106 	return (de.fme_status);
    107 }
    108 
    109 static void
    110 pcix_ecc_regs_gather(pci_erpt_t *erpt_p, pcix_ecc_regs_t *pcix_ecc_regs,
    111     uint8_t pcix_cap_ptr, int fme_flag)
    112 {
    113 	int bdg = erpt_p->pe_dflags & PCI_BRIDGE_DEV;
    114 
    115 	pcix_ecc_regs->pcix_ecc_ctlstat = pci_config_get32(erpt_p->pe_hdl,
    116 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_STATUS :
    117 	    PCI_PCIX_ECC_STATUS)));
    118 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    119 		pcix_ecc_regs->pcix_ecc_vflags |= PCIX_ERR_ECC_STS_VALID;
    120 	else
    121 		return;
    122 	pcix_ecc_regs->pcix_ecc_fstaddr = pci_config_get32(erpt_p->pe_hdl,
    123 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_FST_AD :
    124 	    PCI_PCIX_ECC_FST_AD)));
    125 	pcix_ecc_regs->pcix_ecc_secaddr = pci_config_get32(erpt_p->pe_hdl,
    126 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_SEC_AD :
    127 	    PCI_PCIX_ECC_SEC_AD)));
    128 	pcix_ecc_regs->pcix_ecc_attr = pci_config_get32((
    129 	    ddi_acc_handle_t)erpt_p->pe_hdl,
    130 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_ATTR : PCI_PCIX_ECC_ATTR)));
    131 }
    132 
    133 static void
    134 pcix_regs_gather(pci_erpt_t *erpt_p, void *pe_regs, int fme_flag)
    135 {
    136 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    137 		pcix_bdg_error_regs_t *pcix_bdg_regs =
    138 		    (pcix_bdg_error_regs_t *)pe_regs;
    139 		uint8_t pcix_bdg_cap_ptr;
    140 		int i;
    141 
    142 		pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
    143 		pcix_bdg_regs->pcix_bdg_sec_stat = pci_config_get16(
    144 		    erpt_p->pe_hdl, (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS));
    145 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    146 			pcix_bdg_regs->pcix_bdg_vflags |=
    147 			    PCIX_BDG_SEC_STATUS_VALID;
    148 		else
    149 			return;
    150 		pcix_bdg_regs->pcix_bdg_stat = pci_config_get32(erpt_p->pe_hdl,
    151 		    (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS));
    152 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    153 			pcix_bdg_regs->pcix_bdg_vflags |= PCIX_BDG_STATUS_VALID;
    154 		else
    155 			return;
    156 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
    157 			pcix_ecc_regs_t *pcix_bdg_ecc_regs;
    158 
    159 			for (i = 0; i < 2; i++) {
    160 				pcix_bdg_ecc_regs =
    161 				    pcix_bdg_regs->pcix_bdg_ecc_regs[i];
    162 				pci_config_put32(erpt_p->pe_hdl,
    163 				    (pcix_bdg_cap_ptr +
    164 				    PCI_PCIX_BDG_ECC_STATUS), i);
    165 				pcix_ecc_regs_gather(erpt_p,
    166 				    pcix_bdg_ecc_regs,
    167 				    pcix_bdg_cap_ptr, fme_flag);
    168 			}
    169 		}
    170 	} else {
    171 		pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
    172 		uint8_t pcix_cap_ptr;
    173 
    174 		pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
    175 
    176 		pcix_regs->pcix_command = pci_config_get16(erpt_p->pe_hdl,
    177 		    (pcix_cap_ptr + PCI_PCIX_COMMAND));
    178 		pcix_regs->pcix_status = pci_config_get32(erpt_p->pe_hdl,
    179 		    (pcix_cap_ptr + PCI_PCIX_STATUS));
    180 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    181 			pcix_regs->pcix_vflags |= PCIX_ERR_STATUS_VALID;
    182 		else
    183 			return;
    184 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
    185 			pcix_ecc_regs_t *pcix_ecc_regs =
    186 			    pcix_regs->pcix_ecc_regs;
    187 
    188 			pcix_ecc_regs_gather(erpt_p, pcix_ecc_regs,
    189 			    pcix_cap_ptr, fme_flag);
    190 		}
    191 	}
    192 }
    193 
    194 /*ARGSUSED*/
    195 static void
    196 pci_regs_gather(dev_info_t *dip, pci_erpt_t *erpt_p, int fme_flag)
    197 {
    198 	pci_error_regs_t *pci_regs = erpt_p->pe_pci_regs;
    199 
    200 	/*
    201 	 * Start by reading all the error registers that are available for
    202 	 * pci and pci express and for leaf devices and bridges/switches
    203 	 */
    204 	pci_regs->pci_err_status = pci_config_get16(erpt_p->pe_hdl,
    205 	    PCI_CONF_STAT);
    206 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
    207 		return;
    208 	pci_regs->pci_vflags |= PCI_ERR_STATUS_VALID;
    209 	pci_regs->pci_cfg_comm = pci_config_get16(erpt_p->pe_hdl,
    210 	    PCI_CONF_COMM);
    211 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
    212 		return;
    213 
    214 	/*
    215 	 * If pci-pci bridge grab PCI bridge specific error registers.
    216 	 */
    217 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    218 		pci_regs->pci_bdg_regs->pci_bdg_sec_stat =
    219 		    pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS);
    220 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    221 			pci_regs->pci_bdg_regs->pci_bdg_vflags |=
    222 			    PCI_BDG_SEC_STAT_VALID;
    223 		pci_regs->pci_bdg_regs->pci_bdg_ctrl =
    224 		    pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL);
    225 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
    226 			pci_regs->pci_bdg_regs->pci_bdg_vflags |=
    227 			    PCI_BDG_CTRL_VALID;
    228 	}
    229 
    230 	/* If pci-x device grab error registers */
    231 	if (erpt_p->pe_dflags & PCIX_DEV)
    232 		pcix_regs_gather(erpt_p, erpt_p->pe_regs, fme_flag);
    233 
    234 }
    235 
    236 static void
    237 pcix_regs_clear(pci_erpt_t *erpt_p, void *pe_regs)
    238 {
    239 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    240 		pcix_bdg_error_regs_t *pcix_bdg_regs =
    241 		    (pcix_bdg_error_regs_t *)pe_regs;
    242 		uint8_t pcix_bdg_cap_ptr;
    243 		int i;
    244 
    245 		pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
    246 
    247 		if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID)
    248 			pci_config_put16(erpt_p->pe_hdl,
    249 			    (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS),
    250 			    pcix_bdg_regs->pcix_bdg_sec_stat);
    251 
    252 		if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID)
    253 			pci_config_put32(erpt_p->pe_hdl,
    254 			    (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS),
    255 			    pcix_bdg_regs->pcix_bdg_stat);
    256 
    257 		pcix_bdg_regs->pcix_bdg_vflags = 0x0;
    258 
    259 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
    260 			pcix_ecc_regs_t *pcix_bdg_ecc_regs;
    261 			for (i = 0; i < 2; i++) {
    262 				pcix_bdg_ecc_regs =
    263 				    pcix_bdg_regs->pcix_bdg_ecc_regs[i];
    264 
    265 				if (pcix_bdg_ecc_regs->pcix_ecc_vflags &
    266 				    PCIX_ERR_ECC_STS_VALID) {
    267 					pci_config_put32(erpt_p->pe_hdl,
    268 					    (pcix_bdg_cap_ptr +
    269 					    PCI_PCIX_BDG_ECC_STATUS),
    270 					    i);
    271 
    272 					pci_config_put32(erpt_p->pe_hdl,
    273 					    (pcix_bdg_cap_ptr +
    274 					    PCI_PCIX_BDG_ECC_STATUS),
    275 					    pcix_bdg_ecc_regs->
    276 					    pcix_ecc_ctlstat);
    277 				}
    278 				pcix_bdg_ecc_regs->pcix_ecc_vflags =
    279 				    0x0;
    280 			}
    281 		}
    282 	} else {
    283 		pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
    284 		uint8_t pcix_cap_ptr;
    285 
    286 		pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
    287 
    288 		if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID)
    289 			pci_config_put32(erpt_p->pe_hdl,
    290 			    (pcix_cap_ptr + PCI_PCIX_STATUS),
    291 			    pcix_regs->pcix_status);
    292 
    293 		pcix_regs->pcix_vflags = 0x0;
    294 
    295 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
    296 			pcix_ecc_regs_t *pcix_ecc_regs =
    297 			    pcix_regs->pcix_ecc_regs;
    298 
    299 			if (pcix_ecc_regs->pcix_ecc_vflags &
    300 			    PCIX_ERR_ECC_STS_VALID)
    301 				pci_config_put32(erpt_p->pe_hdl,
    302 				    (pcix_cap_ptr + PCI_PCIX_ECC_STATUS),
    303 				    pcix_ecc_regs->pcix_ecc_ctlstat);
    304 
    305 			pcix_ecc_regs->pcix_ecc_vflags = 0x0;
    306 		}
    307 	}
    308 }
    309 
    310 static void
    311 pci_regs_clear(pci_erpt_t *erpt_p)
    312 {
    313 	/*
    314 	 * Finally clear the error bits
    315 	 */
    316 	if (erpt_p->pe_dflags & PCIX_DEV)
    317 		pcix_regs_clear(erpt_p, erpt_p->pe_regs);
    318 
    319 	if (erpt_p->pe_pci_regs->pci_vflags & PCI_ERR_STATUS_VALID)
    320 		pci_config_put16(erpt_p->pe_hdl, PCI_CONF_STAT,
    321 		    erpt_p->pe_pci_regs->pci_err_status);
    322 
    323 	erpt_p->pe_pci_regs->pci_vflags = 0x0;
    324 
    325 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    326 		if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
    327 		    PCI_BDG_SEC_STAT_VALID)
    328 			pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS,
    329 			    erpt_p->pe_pci_regs->pci_bdg_regs->
    330 			    pci_bdg_sec_stat);
    331 		if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
    332 		    PCI_BDG_CTRL_VALID)
    333 			pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL,
    334 			    erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_ctrl);
    335 
    336 		erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags = 0x0;
    337 	}
    338 }
    339 
    340 /*
    341  * pcix_ereport_setup: Allocate structures for PCI-X error handling and ereport
    342  * generation.
    343  */
    344 /* ARGSUSED */
    345 static void
    346 pcix_ereport_setup(dev_info_t *dip, pci_erpt_t *erpt_p)
    347 {
    348 	uint16_t pcix_cap_ptr = PCI_CAP_NEXT_PTR_NULL;
    349 	ddi_acc_handle_t eh;
    350 	int i;
    351 
    352 	if (pci_config_setup(dip, &eh) == DDI_SUCCESS) {
    353 		(void) PCI_CAP_LOCATE(eh, PCI_CAP_ID_PCIX, &pcix_cap_ptr);
    354 		pci_config_teardown(&eh);
    355 	}
    356 
    357 	if (pcix_cap_ptr != PCI_CAP_NEXT_PTR_NULL)
    358 		erpt_p->pe_dflags |= PCIX_DEV;
    359 	else
    360 		return;
    361 
    362 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    363 		pcix_bdg_error_regs_t *pcix_bdg_regs;
    364 
    365 		erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_bdg_error_regs_t),
    366 		    KM_SLEEP);
    367 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
    368 		pcix_bdg_regs->pcix_bdg_cap_ptr = pcix_cap_ptr;
    369 		pcix_bdg_regs->pcix_bdg_ver = pci_config_get16(erpt_p->pe_hdl,
    370 		    pcix_cap_ptr + PCI_PCIX_SEC_STATUS) & PCI_PCIX_VER_MASK;
    371 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
    372 			for (i = 0; i < 2; i++) {
    373 				pcix_bdg_regs->pcix_bdg_ecc_regs[i] =
    374 				    kmem_zalloc(sizeof (pcix_ecc_regs_t),
    375 				    KM_SLEEP);
    376 			}
    377 		}
    378 	} else {
    379 		pcix_error_regs_t *pcix_regs;
    380 
    381 		erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_error_regs_t),
    382 		    KM_SLEEP);
    383 		pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
    384 		pcix_regs->pcix_cap_ptr = pcix_cap_ptr;
    385 		pcix_regs->pcix_ver = pci_config_get16(erpt_p->pe_hdl,
    386 		    pcix_cap_ptr + PCI_PCIX_COMMAND) & PCI_PCIX_VER_MASK;
    387 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
    388 			pcix_regs->pcix_ecc_regs = kmem_zalloc(
    389 			    sizeof (pcix_ecc_regs_t), KM_SLEEP);
    390 		}
    391 	}
    392 }
    393 
    394 /*
    395  * pci_ereport_setup: Detect PCI device type and initialize structures to be
    396  * used to generate ereports based on detected generic device errors.
    397  */
    398 void
    399 pci_ereport_setup(dev_info_t *dip)
    400 {
    401 	struct dev_info *devi = DEVI(dip);
    402 	struct i_ddi_fmhdl *fmhdl = devi->devi_fmhdl;
    403 	pci_erpt_t *erpt_p;
    404 	uint8_t pci_hdr_type;
    405 	uint16_t pci_status;
    406 	pci_regspec_t *pci_rp;
    407 	int32_t len;
    408 	uint32_t phys_hi;
    409 
    410 	/*
    411 	 * If device is not ereport capbable then report an error against the
    412 	 * driver for using this interface,
    413 	 */
    414 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
    415 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
    416 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
    417 		return;
    418 	}
    419 
    420 	/*
    421 	 * ASSERT fmhdl exists and fh_bus_specific is NULL.
    422 	 */
    423 	ASSERT(fmhdl && (fmhdl->fh_bus_specific == NULL));
    424 
    425 	erpt_p = kmem_zalloc(sizeof (pci_erpt_t), KM_SLEEP);
    426 
    427 	if (pci_config_setup(dip, &erpt_p->pe_hdl) != DDI_SUCCESS)
    428 		goto error;
    429 
    430 	erpt_p->pe_pci_regs = kmem_zalloc(sizeof (pci_error_regs_t), KM_SLEEP);
    431 
    432 	pci_status = pci_config_get16(erpt_p->pe_hdl, PCI_CONF_STAT);
    433 	if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
    434 	    DDI_FM_OK)
    435 		goto error;
    436 
    437 	/*
    438 	 * Get header type and record if device is a bridge.
    439 	 */
    440 	pci_hdr_type = pci_config_get8(erpt_p->pe_hdl, PCI_CONF_HEADER);
    441 	if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
    442 	    DDI_FM_OK)
    443 		goto error;
    444 
    445 	/*
    446 	 * Check to see if PCI device is a bridge, if so allocate pci bridge
    447 	 * error register structure.
    448 	 */
    449 	if ((pci_hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
    450 		erpt_p->pe_dflags |= PCI_BRIDGE_DEV;
    451 		erpt_p->pe_pci_regs->pci_bdg_regs = kmem_zalloc(
    452 		    sizeof (pci_bdg_error_regs_t), KM_SLEEP);
    453 	}
    454 
    455 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
    456 	    (caddr_t)&pci_rp, &len) == DDI_SUCCESS) {
    457 		phys_hi = pci_rp->pci_phys_hi;
    458 		kmem_free(pci_rp, len);
    459 
    460 		erpt_p->pe_bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >>
    461 		    PCI_REG_FUNC_SHIFT);
    462 	}
    463 
    464 	if (!(pci_status & PCI_STAT_CAP)) {
    465 		goto done;
    466 	}
    467 
    468 	/* Initialize structures for PCI-X devices. */
    469 	pcix_ereport_setup(dip, erpt_p);
    470 
    471 done:
    472 	pci_regs_gather(dip, erpt_p, DDI_FM_ERR_UNEXPECTED);
    473 	pci_regs_clear(erpt_p);
    474 
    475 	/*
    476 	 * Before returning set fh_bus_specific to completed pci_erpt_t
    477 	 * structure
    478 	 */
    479 	fmhdl->fh_bus_specific = (void *)erpt_p;
    480 
    481 	return;
    482 error:
    483 	if (erpt_p->pe_pci_regs)
    484 		kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
    485 	kmem_free(erpt_p, sizeof (pci_erpt_t));
    486 	erpt_p = NULL;
    487 }
    488 
    489 static void
    490 pcix_ereport_teardown(pci_erpt_t *erpt_p)
    491 {
    492 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    493 		pcix_bdg_error_regs_t *pcix_bdg_regs;
    494 		uint16_t pcix_ver;
    495 
    496 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
    497 		pcix_ver = pcix_bdg_regs->pcix_bdg_ver;
    498 		if (PCIX_ECC_VER_CHECK(pcix_ver)) {
    499 			int i;
    500 			for (i = 0; i < 2; i++)
    501 				kmem_free(pcix_bdg_regs->pcix_bdg_ecc_regs[i],
    502 				    sizeof (pcix_ecc_regs_t));
    503 		}
    504 		kmem_free(erpt_p->pe_regs, sizeof (pcix_bdg_error_regs_t));
    505 	} else {
    506 		pcix_error_regs_t *pcix_regs;
    507 		uint16_t pcix_ver;
    508 
    509 		pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
    510 		pcix_ver = pcix_regs->pcix_ver;
    511 		if (PCIX_ECC_VER_CHECK(pcix_ver)) {
    512 			kmem_free(pcix_regs->pcix_ecc_regs,
    513 			    sizeof (pcix_ecc_regs_t));
    514 		}
    515 		kmem_free(erpt_p->pe_regs, sizeof (pcix_error_regs_t));
    516 	}
    517 }
    518 
    519 void
    520 pci_ereport_teardown(dev_info_t *dip)
    521 {
    522 	struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl;
    523 	pci_erpt_t *erpt_p;
    524 
    525 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
    526 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
    527 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
    528 	}
    529 
    530 	ASSERT(fmhdl);
    531 
    532 	erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
    533 	if (erpt_p == NULL)
    534 		return;
    535 
    536 	if (erpt_p->pe_dflags & PCIX_DEV)
    537 		pcix_ereport_teardown(erpt_p);
    538 	pci_config_teardown((ddi_acc_handle_t *)&erpt_p->pe_hdl);
    539 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV)
    540 		kmem_free(erpt_p->pe_pci_regs->pci_bdg_regs,
    541 		    sizeof (pci_bdg_error_regs_t));
    542 	kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
    543 	kmem_free(erpt_p, sizeof (pci_erpt_t));
    544 	fmhdl->fh_bus_specific = NULL;
    545 
    546 	/*
    547 	 * The following sparc specific code should be removed once the pci_cap
    548 	 * interfaces create the necessary properties for us.
    549 	 */
    550 }
    551 
    552 /*ARGSUSED*/
    553 static int
    554 pcix_check_addr(dev_info_t *dip, ddi_fm_error_t *derr,
    555     pcix_ecc_regs_t *pcix_ecc_regs, int type)
    556 {
    557 	int cmd = (pcix_ecc_regs->pcix_ecc_ctlstat >> 16) & 0xf;
    558 	uint64_t addr;
    559 	pci_fme_bus_specific_t *pci_fme_bsp =
    560 	    (pci_fme_bus_specific_t *)derr->fme_bus_specific;
    561 
    562 	addr = pcix_ecc_regs->pcix_ecc_secaddr;
    563 	addr = addr << 32;
    564 	addr |= pcix_ecc_regs->pcix_ecc_fstaddr;
    565 
    566 	switch (cmd) {
    567 	case PCI_PCIX_CMD_INTR:
    568 	case PCI_PCIX_CMD_SPEC:
    569 		return (DDI_FM_FATAL);
    570 	case PCI_PCIX_CMD_IORD:
    571 	case PCI_PCIX_CMD_IOWR:
    572 		pci_fme_bsp->pci_bs_addr = addr;
    573 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
    574 		pci_fme_bsp->pci_bs_type = type;
    575 		return (DDI_FM_UNKNOWN);
    576 	case PCI_PCIX_CMD_DEVID:
    577 		return (DDI_FM_FATAL);
    578 	case PCI_PCIX_CMD_MEMRD_DW:
    579 	case PCI_PCIX_CMD_MEMWR:
    580 	case PCI_PCIX_CMD_MEMRD_BL:
    581 	case PCI_PCIX_CMD_MEMWR_BL:
    582 		pci_fme_bsp->pci_bs_addr = addr;
    583 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
    584 		pci_fme_bsp->pci_bs_type = type;
    585 		return (DDI_FM_UNKNOWN);
    586 	case PCI_PCIX_CMD_CFRD:
    587 	case PCI_PCIX_CMD_CFWR:
    588 		/*
    589 		 * for type 1 config transaction we can find bdf from address
    590 		 */
    591 		if ((addr & 3) == 1) {
    592 			pci_fme_bsp->pci_bs_bdf = (addr >> 8) & 0xffffffff;
    593 			pci_fme_bsp->pci_bs_flags |= PCI_BS_BDF_VALID;
    594 			pci_fme_bsp->pci_bs_type = type;
    595 		}
    596 		return (DDI_FM_UNKNOWN);
    597 	case PCI_PCIX_CMD_SPL:
    598 	case PCI_PCIX_CMD_DADR:
    599 		return (DDI_FM_UNKNOWN);
    600 	case PCI_PCIX_CMD_MEMRDBL:
    601 	case PCI_PCIX_CMD_MEMWRBL:
    602 		pci_fme_bsp->pci_bs_addr = addr;
    603 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
    604 		pci_fme_bsp->pci_bs_type = type;
    605 		return (DDI_FM_UNKNOWN);
    606 	default:
    607 		return (DDI_FM_FATAL);
    608 	}
    609 }
    610 
    611 /*ARGSUSED*/
    612 static int
    613 pci_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
    614 {
    615 	pci_bdg_error_regs_t *pci_bdg_regs = erpt_p->pe_pci_regs->pci_bdg_regs;
    616 	int fatal = 0;
    617 	int nonfatal = 0;
    618 	int unknown = 0;
    619 	int ok = 0;
    620 	int ret = DDI_FM_OK;
    621 	char buf[FM_MAX_CLASS];
    622 	int i;
    623 	pci_fme_bus_specific_t *pci_fme_bsp =
    624 	    (pci_fme_bus_specific_t *)derr->fme_bus_specific;
    625 
    626 	if (derr->fme_flag != DDI_FM_ERR_UNEXPECTED)
    627 		goto done;
    628 
    629 	if ((pci_bdg_regs->pci_bdg_vflags & PCI_BDG_CTRL_VALID) &&
    630 	    (pci_bdg_regs->pci_bdg_ctrl & PCI_BCNF_BCNTRL_DTO_STAT)) {
    631 		(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
    632 		    PCI_ERROR_SUBCLASS, PCI_DTO);
    633 		ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    634 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    635 		    PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
    636 		    pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
    637 		    DATA_TYPE_UINT16, pci_bdg_regs->pci_bdg_ctrl, NULL);
    638 		unknown++;
    639 	}
    640 
    641 	if (pci_bdg_regs->pci_bdg_vflags & PCI_BDG_SEC_STAT_VALID) {
    642 		for (i = 0; pci_bdg_err_tbl[i].err_class != NULL; i++) {
    643 			if (pci_bdg_regs->pci_bdg_sec_stat &
    644 			    pci_bdg_err_tbl[i].reg_bit) {
    645 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
    646 				    PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS,
    647 				    pci_bdg_err_tbl[i].err_class);
    648 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    649 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    650 				    PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
    651 				    pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
    652 				    DATA_TYPE_UINT16,
    653 				    pci_bdg_regs->pci_bdg_ctrl, NULL);
    654 				PCI_FM_SEV_INC(pci_bdg_err_tbl[i].flags);
    655 				if (pci_fme_bsp && (pci_fme_bsp->pci_bs_flags &
    656 				    PCI_BS_ADDR_VALID) &&
    657 				    pci_fme_bsp->pci_bs_type == ACC_HANDLE &&
    658 				    pci_bdg_err_tbl[i].terr_class)
    659 					pci_target_enqueue(derr->fme_ena,
    660 					    pci_bdg_err_tbl[i].terr_class,
    661 					    PCI_ERROR_SUBCLASS,
    662 					    pci_fme_bsp->pci_bs_addr);
    663 			}
    664 		}
    665 	}
    666 
    667 done:
    668 	/*
    669 	 * Need to check for poke and cautious put. We already know peek
    670 	 * and cautious get errors occurred (as we got a trap) and we know
    671 	 * they are nonfatal.
    672 	 */
    673 	if (derr->fme_flag == DDI_FM_ERR_EXPECTED) {
    674 		/*
    675 		 * for cautious puts we treat all errors as nonfatal. Actually
    676 		 * we set nonfatal for cautious gets as well - doesn't do any
    677 		 * harm
    678 		 */
    679 		if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
    680 		    PCI_STAT_R_MAST_AB | PCI_STAT_S_PERROR | PCI_STAT_S_SYSERR))
    681 			nonfatal++;
    682 	}
    683 	if (derr->fme_flag == DDI_FM_ERR_POKE) {
    684 		/*
    685 		 * special case for pokes - we only consider master abort
    686 		 * and target abort as nonfatal. Sserr with no master abort is
    687 		 * fatal, but master/target abort can come in on separate
    688 		 * instance, so return unknown and parent will determine if
    689 		 * nonfatal (if another child returned nonfatal - ie master
    690 		 * or target abort) or fatal otherwise
    691 		 */
    692 		if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
    693 		    PCI_STAT_R_MAST_AB))
    694 			nonfatal++;
    695 		if (erpt_p->pe_pci_regs->pci_err_status & PCI_STAT_S_SYSERR)
    696 			unknown++;
    697 	}
    698 
    699 	/*
    700 	 * now check children below the bridge
    701 	 */
    702 	ret = ndi_fm_handler_dispatch(dip, NULL, derr);
    703 	PCI_FM_SEV_INC(ret);
    704 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
    705 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
    706 }
    707 
    708 static int
    709 pcix_ecc_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
    710     void *pe_regs)
    711 {
    712 	pcix_error_regs_t *pcix_regs;
    713 	pcix_bdg_error_regs_t *pcix_bdg_regs;
    714 	pcix_ecc_regs_t *pcix_ecc_regs;
    715 	int bridge;
    716 	int i;
    717 	int ecc_phase;
    718 	int ecc_corr;
    719 	int sec_ue;
    720 	int sec_ce;
    721 	int fatal = 0;
    722 	int nonfatal = 0;
    723 	int unknown = 0;
    724 	int ok = 0;
    725 	char buf[FM_MAX_CLASS];
    726 
    727 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
    728 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
    729 		bridge = 1;
    730 	} else {
    731 		pcix_regs = (pcix_error_regs_t *)pe_regs;
    732 		bridge = 0;
    733 	}
    734 
    735 	for (i = 0; i < (bridge ? 2 : 1); i++) {
    736 		int ret = DDI_FM_OK;
    737 		pcix_ecc_regs = bridge ? pcix_bdg_regs->pcix_bdg_ecc_regs[i] :
    738 		    pcix_regs->pcix_ecc_regs;
    739 		if (pcix_ecc_regs->pcix_ecc_vflags & PCIX_ERR_ECC_STS_VALID) {
    740 			ecc_phase = (pcix_ecc_regs->pcix_ecc_ctlstat &
    741 			    PCI_PCIX_ECC_PHASE) >> 0x4;
    742 			ecc_corr = (pcix_ecc_regs->pcix_ecc_ctlstat &
    743 			    PCI_PCIX_ECC_CORR);
    744 			sec_ue = (pcix_ecc_regs->pcix_ecc_ctlstat &
    745 			    PCI_PCIX_ECC_S_UE);
    746 			sec_ce = (pcix_ecc_regs->pcix_ecc_ctlstat &
    747 			    PCI_PCIX_ECC_S_CE);
    748 
    749 			switch (ecc_phase) {
    750 			case PCI_PCIX_ECC_PHASE_NOERR:
    751 				break;
    752 			case PCI_PCIX_ECC_PHASE_FADDR:
    753 			case PCI_PCIX_ECC_PHASE_SADDR:
    754 				PCI_FM_SEV_INC(ecc_corr ?  DDI_FM_OK :
    755 				    DDI_FM_FATAL);
    756 				(void) snprintf(buf, FM_MAX_CLASS,
    757 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
    758 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
    759 				    ecc_corr ? PCIX_ECC_CE_ADDR :
    760 				    PCIX_ECC_UE_ADDR);
    761 				break;
    762 			case PCI_PCIX_ECC_PHASE_ATTR:
    763 				PCI_FM_SEV_INC(ecc_corr ?
    764 				    DDI_FM_OK : DDI_FM_FATAL);
    765 				(void) snprintf(buf, FM_MAX_CLASS,
    766 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
    767 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
    768 				    ecc_corr ? PCIX_ECC_CE_ATTR :
    769 				    PCIX_ECC_UE_ATTR);
    770 				break;
    771 			case PCI_PCIX_ECC_PHASE_DATA32:
    772 			case PCI_PCIX_ECC_PHASE_DATA64:
    773 				if (ecc_corr)
    774 					ret = DDI_FM_OK;
    775 				else {
    776 					int type;
    777 					pci_error_regs_t *pci_regs =
    778 					    erpt_p->pe_pci_regs;
    779 
    780 					if (i) {
    781 						if (pci_regs->pci_bdg_regs->
    782 						    pci_bdg_sec_stat &
    783 						    PCI_STAT_S_PERROR)
    784 							type = ACC_HANDLE;
    785 						else
    786 							type = DMA_HANDLE;
    787 					} else {
    788 						if (pci_regs->pci_err_status &
    789 						    PCI_STAT_S_PERROR)
    790 							type = DMA_HANDLE;
    791 						else
    792 							type = ACC_HANDLE;
    793 					}
    794 					ret = pcix_check_addr(dip, derr,
    795 					    pcix_ecc_regs, type);
    796 				}
    797 				PCI_FM_SEV_INC(ret);
    798 
    799 				(void) snprintf(buf, FM_MAX_CLASS,
    800 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
    801 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
    802 				    ecc_corr ? PCIX_ECC_CE_DATA :
    803 				    PCIX_ECC_UE_DATA);
    804 				break;
    805 			}
    806 			if (ecc_phase)
    807 				if (bridge)
    808 					ddi_fm_ereport_post(dip, buf,
    809 					    derr->fme_ena,
    810 					    DDI_NOSLEEP, FM_VERSION,
    811 					    DATA_TYPE_UINT8, 0,
    812 					    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
    813 					    pcix_bdg_regs->pcix_bdg_sec_stat,
    814 					    PCIX_BDG_STAT, DATA_TYPE_UINT32,
    815 					    pcix_bdg_regs->pcix_bdg_stat,
    816 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
    817 					    pcix_ecc_regs->pcix_ecc_ctlstat,
    818 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
    819 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
    820 				else
    821 					ddi_fm_ereport_post(dip, buf,
    822 					    derr->fme_ena,
    823 					    DDI_NOSLEEP, FM_VERSION,
    824 					    DATA_TYPE_UINT8, 0,
    825 					    PCIX_COMMAND, DATA_TYPE_UINT16,
    826 					    pcix_regs->pcix_command,
    827 					    PCIX_STATUS, DATA_TYPE_UINT32,
    828 					    pcix_regs->pcix_status,
    829 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
    830 					    pcix_ecc_regs->pcix_ecc_ctlstat,
    831 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
    832 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
    833 			if (sec_ce || sec_ue) {
    834 				(void) snprintf(buf, FM_MAX_CLASS,
    835 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
    836 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
    837 				    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
    838 				if (bridge)
    839 					ddi_fm_ereport_post(dip, buf,
    840 					    derr->fme_ena,
    841 					    DDI_NOSLEEP, FM_VERSION,
    842 					    DATA_TYPE_UINT8, 0,
    843 					    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
    844 					    pcix_bdg_regs->pcix_bdg_sec_stat,
    845 					    PCIX_BDG_STAT, DATA_TYPE_UINT32,
    846 					    pcix_bdg_regs->pcix_bdg_stat,
    847 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
    848 					    pcix_ecc_regs->pcix_ecc_ctlstat,
    849 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
    850 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
    851 				else
    852 					ddi_fm_ereport_post(dip, buf,
    853 					    derr->fme_ena,
    854 					    DDI_NOSLEEP, FM_VERSION,
    855 					    DATA_TYPE_UINT8, 0,
    856 					    PCIX_COMMAND, DATA_TYPE_UINT16,
    857 					    pcix_regs->pcix_command,
    858 					    PCIX_STATUS, DATA_TYPE_UINT32,
    859 					    pcix_regs->pcix_status,
    860 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
    861 					    pcix_ecc_regs->pcix_ecc_ctlstat,
    862 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
    863 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
    864 				PCI_FM_SEV_INC(sec_ue ? DDI_FM_FATAL :
    865 				    DDI_FM_OK);
    866 			}
    867 		}
    868 	}
    869 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
    870 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
    871 }
    872 
    873 static int
    874 pcix_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
    875     void *pe_regs)
    876 {
    877 	pcix_bdg_error_regs_t *pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
    878 	int fatal = 0;
    879 	int nonfatal = 0;
    880 	int unknown = 0;
    881 	int ok = 0;
    882 	char buf[FM_MAX_CLASS];
    883 	int i;
    884 
    885 	if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID) {
    886 		for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
    887 			if ((pcix_bdg_regs->pcix_bdg_stat &
    888 			    pcix_err_tbl[i].reg_bit)) {
    889 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
    890 				    PCIX_ERROR_SUBCLASS,
    891 				    pcix_err_tbl[i].err_class);
    892 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    893 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    894 				    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
    895 				    pcix_bdg_regs->pcix_bdg_sec_stat,
    896 				    PCIX_BDG_STAT, DATA_TYPE_UINT32,
    897 				    pcix_bdg_regs->pcix_bdg_stat, NULL);
    898 				PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
    899 			}
    900 		}
    901 	}
    902 
    903 	if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID) {
    904 		for (i = 0; pcix_sec_err_tbl[i].err_class != NULL; i++) {
    905 			if ((pcix_bdg_regs->pcix_bdg_sec_stat &
    906 			    pcix_sec_err_tbl[i].reg_bit)) {
    907 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s%s",
    908 				    PCIX_ERROR_SUBCLASS,
    909 				    PCIX_SEC_ERROR_SUBCLASS,
    910 				    pcix_sec_err_tbl[i].err_class);
    911 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    912 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    913 				    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
    914 				    pcix_bdg_regs->pcix_bdg_sec_stat,
    915 				    PCIX_BDG_STAT, DATA_TYPE_UINT32,
    916 				    pcix_bdg_regs->pcix_bdg_stat, NULL);
    917 				PCI_FM_SEV_INC(pcix_sec_err_tbl[i].flags);
    918 			}
    919 		}
    920 	}
    921 
    922 	/* Log/Handle ECC errors */
    923 	if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
    924 		int ret;
    925 
    926 		ret = pcix_ecc_error_report(dip, derr, erpt_p,
    927 		    (void *)pcix_bdg_regs);
    928 		PCI_FM_SEV_INC(ret);
    929 	}
    930 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
    931 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
    932 }
    933 
    934 static int
    935 pcix_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
    936 {
    937 	pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
    938 	int fatal = 0;
    939 	int nonfatal = 0;
    940 	int unknown = 0;
    941 	int ok = 0;
    942 	char buf[FM_MAX_CLASS];
    943 	int i;
    944 
    945 	if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID) {
    946 		for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
    947 			if (!(pcix_regs->pcix_status & pcix_err_tbl[i].reg_bit))
    948 				continue;
    949 
    950 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
    951 			    PCIX_ERROR_SUBCLASS, pcix_err_tbl[i].err_class);
    952 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    953 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    954 			    PCIX_COMMAND, DATA_TYPE_UINT16,
    955 			    pcix_regs->pcix_command, PCIX_STATUS,
    956 			    DATA_TYPE_UINT32, pcix_regs->pcix_status,
    957 			    NULL);
    958 			PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
    959 		}
    960 	}
    961 	/* Log/Handle ECC errors */
    962 	if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
    963 		int ret = pcix_ecc_error_report(dip, derr, erpt_p,
    964 		    (void *)pcix_regs);
    965 		PCI_FM_SEV_INC(ret);
    966 	}
    967 
    968 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
    969 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
    970 }
    971 
    972 static void
    973 pci_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
    974 {
    975 	int fatal = 0;
    976 	int nonfatal = 0;
    977 	int unknown = 0;
    978 	int ok = 0;
    979 	char buf[FM_MAX_CLASS];
    980 	int i;
    981 
    982 	if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
    983 		/*
    984 		 * Log generic PCI errors.
    985 		 */
    986 		for (i = 0; pci_err_tbl[i].err_class != NULL; i++) {
    987 			if (!(erpt_p->pe_pci_regs->pci_err_status &
    988 			    pci_err_tbl[i].reg_bit) ||
    989 			    !(erpt_p->pe_pci_regs->pci_vflags &
    990 			    PCI_ERR_STATUS_VALID))
    991 				continue;
    992 			/*
    993 			 * Generate an ereport for this error bit.
    994 			 */
    995 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
    996 			    PCI_ERROR_SUBCLASS, pci_err_tbl[i].err_class);
    997 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
    998 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
    999 			    PCI_CONFIG_STATUS, DATA_TYPE_UINT16,
   1000 			    erpt_p->pe_pci_regs->pci_err_status,
   1001 			    PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
   1002 			    erpt_p->pe_pci_regs->pci_cfg_comm, NULL);
   1003 
   1004 			PCI_FM_SEV_INC(pci_err_tbl[i].flags);
   1005 		}
   1006 		if (erpt_p->pe_dflags & PCIX_DEV) {
   1007 			if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
   1008 				int ret = pcix_bdg_error_report(dip, derr,
   1009 				    erpt_p, erpt_p->pe_regs);
   1010 				PCI_FM_SEV_INC(ret);
   1011 			} else {
   1012 				int ret = pcix_error_report(dip, derr, erpt_p);
   1013 				PCI_FM_SEV_INC(ret);
   1014 			}
   1015 		}
   1016 	}
   1017 
   1018 	if ((erpt_p->pe_dflags & PCI_BRIDGE_DEV)) {
   1019 		int ret = pci_bdg_error_report(dip, derr, erpt_p);
   1020 		PCI_FM_SEV_INC(ret);
   1021 	}
   1022 
   1023 	if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
   1024 		pci_fme_bus_specific_t *pci_fme_bsp;
   1025 		int ret = DDI_FM_UNKNOWN;
   1026 
   1027 		pci_fme_bsp = (pci_fme_bus_specific_t *)derr->fme_bus_specific;
   1028 		if (pci_fme_bsp->pci_bs_flags & PCI_BS_ADDR_VALID) {
   1029 			ret = ndi_fmc_entry_error(dip,
   1030 			    pci_fme_bsp->pci_bs_type, derr,
   1031 			    (void *)&pci_fme_bsp->pci_bs_addr);
   1032 			PCI_FM_SEV_INC(ret);
   1033 		}
   1034 		/*
   1035 		 * If we didn't find the handle using an addr, try using bdf.
   1036 		 * Note we don't do this where the bdf is for a
   1037 		 * device behind a pciex/pci bridge as the bridge may have
   1038 		 * fabricated the bdf.
   1039 		 */
   1040 		if (ret == DDI_FM_UNKNOWN &&
   1041 		    (pci_fme_bsp->pci_bs_flags & PCI_BS_BDF_VALID) &&
   1042 		    pci_fme_bsp->pci_bs_bdf == erpt_p->pe_bdf) {
   1043 			ret = ndi_fmc_entry_error_all(dip,
   1044 			    pci_fme_bsp->pci_bs_type, derr);
   1045 			PCI_FM_SEV_INC(ret);
   1046 		}
   1047 	}
   1048 
   1049 	derr->fme_status = (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
   1050 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
   1051 }
   1052 
   1053 void
   1054 pci_ereport_post(dev_info_t *dip, ddi_fm_error_t *derr, uint16_t *xx_status)
   1055 {
   1056 	struct i_ddi_fmhdl *fmhdl;
   1057 	pci_erpt_t *erpt_p;
   1058 	ddi_fm_error_t de;
   1059 	pci_fme_bus_specific_t pci_fme_bs;
   1060 
   1061 	/*
   1062 	 * On PCI Express systems, all error handling and ereport are done via
   1063 	 * the PCIe misc module.  This function is a no-op for PCIe Systems.  In
   1064 	 * order to tell if a system is a PCI or PCIe system, check that the
   1065 	 * bus_private_data exists.  If it exists, this is a PCIe system.
   1066 	 */
   1067 	if (ndi_get_bus_private(dip, B_TRUE)) {
   1068 		derr->fme_status = DDI_FM_OK;
   1069 		if (xx_status != NULL)
   1070 			*xx_status = 0x0;
   1071 
   1072 		return;
   1073 	}
   1074 
   1075 	fmhdl = DEVI(dip)->devi_fmhdl;
   1076 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
   1077 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
   1078 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_NOSLEEP);
   1079 		return;
   1080 	}
   1081 
   1082 	/*
   1083 	 * copy in the ddi_fm_error_t structure in case it's VER0
   1084 	 */
   1085 	de.fme_version = derr->fme_version;
   1086 	de.fme_status = derr->fme_status;
   1087 	de.fme_flag = derr->fme_flag;
   1088 	de.fme_ena = derr->fme_ena;
   1089 	de.fme_acc_handle = derr->fme_acc_handle;
   1090 	de.fme_dma_handle = derr->fme_dma_handle;
   1091 	de.fme_bus_specific = derr->fme_bus_specific;
   1092 	if (derr->fme_version >= DDI_FME_VER1)
   1093 		de.fme_bus_type = derr->fme_bus_type;
   1094 	else
   1095 		de.fme_bus_type = DDI_FME_BUS_TYPE_DFLT;
   1096 	if (de.fme_bus_type == DDI_FME_BUS_TYPE_DFLT) {
   1097 		/*
   1098 		 * if this is the first pci device we've found convert
   1099 		 * fme_bus_specific to DDI_FME_BUS_TYPE_PCI
   1100 		 */
   1101 		bzero(&pci_fme_bs, sizeof (pci_fme_bs));
   1102 		if (de.fme_bus_specific) {
   1103 			/*
   1104 			 * the cpu passed us an addr - this can be used to look
   1105 			 * up an access handle
   1106 			 */
   1107 			pci_fme_bs.pci_bs_addr = (uintptr_t)de.fme_bus_specific;
   1108 			pci_fme_bs.pci_bs_type = ACC_HANDLE;
   1109 			pci_fme_bs.pci_bs_flags |= PCI_BS_ADDR_VALID;
   1110 		}
   1111 		de.fme_bus_specific = (void *)&pci_fme_bs;
   1112 		de.fme_bus_type = DDI_FME_BUS_TYPE_PCI;
   1113 	}
   1114 
   1115 	ASSERT(fmhdl);
   1116 
   1117 	if (de.fme_ena == NULL)
   1118 		de.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
   1119 
   1120 	erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
   1121 	if (erpt_p == NULL)
   1122 		return;
   1123 
   1124 	pci_regs_gather(dip, erpt_p, de.fme_flag);
   1125 	pci_error_report(dip, &de, erpt_p);
   1126 	pci_regs_clear(erpt_p);
   1127 
   1128 	derr->fme_status = de.fme_status;
   1129 	derr->fme_ena = de.fme_ena;
   1130 	derr->fme_acc_handle = de.fme_acc_handle;
   1131 	derr->fme_dma_handle = de.fme_dma_handle;
   1132 	if (xx_status != NULL)
   1133 		*xx_status = erpt_p->pe_pci_regs->pci_err_status;
   1134 }
   1135 
   1136 /*
   1137  * private version of walk_devs() that can be used during panic. No
   1138  * sleeping or locking required.
   1139  */
   1140 static int
   1141 pci_fm_walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg)
   1142 {
   1143 	while (dip) {
   1144 		switch ((*f)(dip, arg)) {
   1145 		case DDI_WALK_TERMINATE:
   1146 			return (DDI_WALK_TERMINATE);
   1147 		case DDI_WALK_CONTINUE:
   1148 			if (pci_fm_walk_devs(ddi_get_child(dip), f,
   1149 			    arg) == DDI_WALK_TERMINATE)
   1150 				return (DDI_WALK_TERMINATE);
   1151 			break;
   1152 		case DDI_WALK_PRUNECHILD:
   1153 			break;
   1154 		}
   1155 		dip = ddi_get_next_sibling(dip);
   1156 	}
   1157 	return (DDI_WALK_CONTINUE);
   1158 }
   1159 
   1160 /*
   1161  * need special version of ddi_fm_ereport_post() as the leaf driver may
   1162  * not be hardened.
   1163  */
   1164 static void
   1165 pci_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena,
   1166     uint8_t version, ...)
   1167 {
   1168 	char *name;
   1169 	char device_path[MAXPATHLEN];
   1170 	char ddi_error_class[FM_MAX_CLASS];
   1171 	nvlist_t *ereport, *detector;
   1172 	nv_alloc_t *nva;
   1173 	errorq_elem_t *eqep;
   1174 	va_list ap;
   1175 
   1176 	if (panicstr) {
   1177 		eqep = errorq_reserve(ereport_errorq);
   1178 		if (eqep == NULL)
   1179 			return;
   1180 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
   1181 		nva = errorq_elem_nva(ereport_errorq, eqep);
   1182 		detector = fm_nvlist_create(nva);
   1183 	} else {
   1184 		ereport = fm_nvlist_create(NULL);
   1185 		detector = fm_nvlist_create(NULL);
   1186 	}
   1187 
   1188 	(void) ddi_pathname(dip, device_path);
   1189 	fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
   1190 	    device_path, NULL);
   1191 	(void) snprintf(ddi_error_class, FM_MAX_CLASS, "%s.%s",
   1192 	    DDI_IO_CLASS, error_class);
   1193 	fm_ereport_set(ereport, version, ddi_error_class, ena, detector, NULL);
   1194 
   1195 	va_start(ap, version);
   1196 	name = va_arg(ap, char *);
   1197 	(void) i_fm_payload_set(ereport, name, ap);
   1198 	va_end(ap);
   1199 
   1200 	if (panicstr) {
   1201 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
   1202 	} else {
   1203 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
   1204 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
   1205 		fm_nvlist_destroy(detector, FM_NVA_FREE);
   1206 	}
   1207 }
   1208 
   1209 static int
   1210 pci_check_regs(dev_info_t *dip, void *arg)
   1211 {
   1212 	int reglen;
   1213 	int rn;
   1214 	int totreg;
   1215 	pci_regspec_t *drv_regp;
   1216 	pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
   1217 
   1218 	if (tgt_err->tgt_pci_space == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
   1219 		/*
   1220 		 * for config space, we need to check if the given address
   1221 		 * is a valid config space address for this device - based
   1222 		 * on pci_phys_hi of the config space entry in reg property.
   1223 		 */
   1224 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
   1225 		    "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
   1226 			return (DDI_WALK_CONTINUE);
   1227 
   1228 		totreg = reglen / sizeof (pci_regspec_t);
   1229 		for (rn = 0; rn < totreg; rn++) {
   1230 			if (tgt_err->tgt_pci_space ==
   1231 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi) &&
   1232 			    (tgt_err->tgt_pci_addr & (PCI_REG_BUS_M |
   1233 			    PCI_REG_DEV_M | PCI_REG_FUNC_M)) ==
   1234 			    (drv_regp[rn].pci_phys_hi & (PCI_REG_BUS_M |
   1235 			    PCI_REG_DEV_M | PCI_REG_FUNC_M))) {
   1236 				tgt_err->tgt_dip = dip;
   1237 				kmem_free(drv_regp, reglen);
   1238 				return (DDI_WALK_TERMINATE);
   1239 			}
   1240 		}
   1241 		kmem_free(drv_regp, reglen);
   1242 	} else {
   1243 		/*
   1244 		 * for non config space, need to check reg to look
   1245 		 * for any non-relocable mapping, otherwise check
   1246 		 * assigned-addresses.
   1247 		 */
   1248 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
   1249 		    "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
   1250 			return (DDI_WALK_CONTINUE);
   1251 
   1252 		totreg = reglen / sizeof (pci_regspec_t);
   1253 		for (rn = 0; rn < totreg; rn++) {
   1254 			if ((drv_regp[rn].pci_phys_hi & PCI_RELOCAT_B) &&
   1255 			    (tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
   1256 			    tgt_err->tgt_pci_space ==
   1257 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
   1258 			    (tgt_err->tgt_pci_addr >=
   1259 			    (uint64_t)drv_regp[rn].pci_phys_low +
   1260 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
   1261 			    (tgt_err->tgt_pci_addr <
   1262 			    (uint64_t)drv_regp[rn].pci_phys_low +
   1263 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
   1264 			    (uint64_t)drv_regp[rn].pci_size_low +
   1265 			    ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
   1266 				tgt_err->tgt_dip = dip;
   1267 				kmem_free(drv_regp, reglen);
   1268 				return (DDI_WALK_TERMINATE);
   1269 			}
   1270 		}
   1271 		kmem_free(drv_regp, reglen);
   1272 
   1273 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
   1274 		    "assigned-addresses", (caddr_t)&drv_regp, &reglen) !=
   1275 		    DDI_SUCCESS)
   1276 			return (DDI_WALK_CONTINUE);
   1277 
   1278 		totreg = reglen / sizeof (pci_regspec_t);
   1279 		for (rn = 0; rn < totreg; rn++) {
   1280 			if ((tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
   1281 			    tgt_err->tgt_pci_space ==
   1282 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
   1283 			    (tgt_err->tgt_pci_addr >=
   1284 			    (uint64_t)drv_regp[rn].pci_phys_low +
   1285 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
   1286 			    (tgt_err->tgt_pci_addr <
   1287 			    (uint64_t)drv_regp[rn].pci_phys_low +
   1288 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
   1289 			    (uint64_t)drv_regp[rn].pci_size_low +
   1290 			    ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
   1291 				tgt_err->tgt_dip = dip;
   1292 				kmem_free(drv_regp, reglen);
   1293 				return (DDI_WALK_TERMINATE);
   1294 			}
   1295 		}
   1296 		kmem_free(drv_regp, reglen);
   1297 	}
   1298 	return (DDI_WALK_CONTINUE);
   1299 }
   1300 
   1301 /*
   1302  * impl_fix_ranges - fixes the config space entry of the "ranges"
   1303  * property on psycho+ platforms.  (if changing this function please make sure
   1304  * to change the pci_fix_ranges function in pcipsy.c)
   1305  */
   1306 /*ARGSUSED*/
   1307 static void
   1308 pci_fix_ranges(dev_info_t *dip, pci_ranges_t *pci_ranges, int nrange)
   1309 {
   1310 #if defined(__sparc)
   1311 	char *name = ddi_binding_name(dip);
   1312 
   1313 	if ((strcmp(name, "pci108e,8000") == 0) ||
   1314 	    (strcmp(name, "pci108e,a000") == 0) ||
   1315 	    (strcmp(name, "pci108e,a001") == 0)) {
   1316 		int i;
   1317 		for (i = 0; i < nrange; i++, pci_ranges++)
   1318 			if ((pci_ranges->child_high & PCI_REG_ADDR_M) ==
   1319 			    PCI_ADDR_CONFIG)
   1320 				pci_ranges->parent_low |=
   1321 				    pci_ranges->child_high;
   1322 	}
   1323 #endif
   1324 }
   1325 
   1326 static int
   1327 pci_check_ranges(dev_info_t *dip, void *arg)
   1328 {
   1329 	uint64_t range_parent_begin;
   1330 	uint64_t range_parent_size;
   1331 	uint64_t range_parent_end;
   1332 	uint32_t space_type;
   1333 	uint32_t bus_num;
   1334 	uint32_t range_offset;
   1335 	pci_ranges_t *pci_ranges, *rangep;
   1336 	pci_bus_range_t *pci_bus_rangep;
   1337 	int pci_ranges_length;
   1338 	int nrange;
   1339 	pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
   1340 	int i, size;
   1341 	if (strcmp(ddi_node_name(dip), "pci") != 0 &&
   1342 	    strcmp(ddi_node_name(dip), "pciex") != 0)
   1343 		return (DDI_WALK_CONTINUE);
   1344 
   1345 	/*
   1346 	 * Get the ranges property. Note we only look at the top level pci
   1347 	 * node (hostbridge) which has a ranges property of type pci_ranges_t
   1348 	 * not at pci-pci bridges.
   1349 	 */
   1350 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
   1351 	    (caddr_t)&pci_ranges, &pci_ranges_length) != DDI_SUCCESS) {
   1352 		/*
   1353 		 * no ranges property - no translation needed
   1354 		 */
   1355 		tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr;
   1356 		tgt_err->tgt_pci_space = TGT_PCI_SPACE_UNKNOWN;
   1357 		if (panicstr)
   1358 			(void) pci_fm_walk_devs(ddi_get_child(dip),
   1359 			    pci_check_regs, (void *)tgt_err);
   1360 		else {
   1361 			int circ = 0;
   1362 			ndi_devi_enter(dip, &circ);
   1363 			ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
   1364 			    (void *)tgt_err);
   1365 			ndi_devi_exit(dip, circ);
   1366 		}
   1367 		if (tgt_err->tgt_dip != NULL)
   1368 			return (DDI_WALK_TERMINATE);
   1369 		return (DDI_WALK_PRUNECHILD);
   1370 	}
   1371 	nrange = pci_ranges_length / sizeof (pci_ranges_t);
   1372 	rangep = pci_ranges;
   1373 
   1374 	/* Need to fix the pci ranges property for psycho based systems */
   1375 	pci_fix_ranges(dip, pci_ranges, nrange);
   1376 
   1377 	for (i = 0; i < nrange; i++, rangep++) {
   1378 		range_parent_begin = ((uint64_t)rangep->parent_high << 32) +
   1379 		    rangep->parent_low;
   1380 		range_parent_size = ((uint64_t)rangep->size_high << 32) +
   1381 		    rangep->size_low;
   1382 		range_parent_end = range_parent_begin + range_parent_size - 1;
   1383 
   1384 		if ((tgt_err->tgt_err_addr < range_parent_begin) ||
   1385 		    (tgt_err->tgt_err_addr > range_parent_end)) {
   1386 			/* Not in range */
   1387 			continue;
   1388 		}
   1389 		space_type = PCI_REG_ADDR_G(rangep->child_high);
   1390 		if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
   1391 			/* Config space address - check bus range */
   1392 			range_offset = tgt_err->tgt_err_addr -
   1393 			    range_parent_begin;
   1394 			bus_num = PCI_REG_BUS_G(range_offset);
   1395 			if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
   1396 			    DDI_PROP_DONTPASS, "bus-range",
   1397 			    (caddr_t)&pci_bus_rangep, &size) != DDI_SUCCESS) {
   1398 				continue;
   1399 			}
   1400 			if ((bus_num < pci_bus_rangep->lo) ||
   1401 			    (bus_num > pci_bus_rangep->hi)) {
   1402 				/*
   1403 				 * Bus number not appropriate for this
   1404 				 * pci nexus.
   1405 				 */
   1406 				kmem_free(pci_bus_rangep, size);
   1407 				continue;
   1408 			}
   1409 			kmem_free(pci_bus_rangep, size);
   1410 		}
   1411 
   1412 		/* We have a match if we get here - compute pci address */
   1413 		tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr -
   1414 		    range_parent_begin;
   1415 		tgt_err->tgt_pci_addr += (((uint64_t)rangep->child_mid << 32) +
   1416 		    rangep->child_low);
   1417 		tgt_err->tgt_pci_space = space_type;
   1418 		if (panicstr)
   1419 			(void) pci_fm_walk_devs(ddi_get_child(dip),
   1420 			    pci_check_regs, (void *)tgt_err);
   1421 		else {
   1422 			int circ = 0;
   1423 			ndi_devi_enter(dip, &circ);
   1424 			ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
   1425 			    (void *)tgt_err);
   1426 			ndi_devi_exit(dip, circ);
   1427 		}
   1428 		if (tgt_err->tgt_dip != NULL) {
   1429 			kmem_free(pci_ranges, pci_ranges_length);
   1430 			return (DDI_WALK_TERMINATE);
   1431 		}
   1432 	}
   1433 	kmem_free(pci_ranges, pci_ranges_length);
   1434 	return (DDI_WALK_PRUNECHILD);
   1435 }
   1436 
   1437 /*
   1438  * Function used to drain pci_target_queue, either during panic or after softint
   1439  * is generated, to generate target device ereports based on captured physical
   1440  * addresses
   1441  */
   1442 /*ARGSUSED*/
   1443 static void
   1444 pci_target_drain(void *private_p, pci_target_err_t *tgt_err)
   1445 {
   1446 	char buf[FM_MAX_CLASS];
   1447 
   1448 	/*
   1449 	 * The following assumes that all pci_pci bridge devices
   1450 	 * are configured as transparant. Find the top-level pci
   1451 	 * nexus which has tgt_err_addr in one of its ranges, converting this
   1452 	 * to a pci address in the process. Then starting at this node do
   1453 	 * another tree walk to find a device with the pci address we've
   1454 	 * found within range of one of it's assigned-addresses properties.
   1455 	 */
   1456 	tgt_err->tgt_dip = NULL;
   1457 	if (panicstr)
   1458 		(void) pci_fm_walk_devs(ddi_root_node(), pci_check_ranges,
   1459 		    (void *)tgt_err);
   1460 	else
   1461 		ddi_walk_devs(ddi_root_node(), pci_check_ranges,
   1462 		    (void *)tgt_err);
   1463 	if (tgt_err->tgt_dip == NULL)
   1464 		return;
   1465 
   1466 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", tgt_err->tgt_bridge_type,
   1467 	    tgt_err->tgt_err_class);
   1468 	pci_fm_ereport_post(tgt_err->tgt_dip, buf, tgt_err->tgt_err_ena, 0,
   1469 	    PCI_PA, DATA_TYPE_UINT64, tgt_err->tgt_err_addr, NULL);
   1470 }
   1471 
   1472 void
   1473 pci_target_enqueue(uint64_t ena, char *class, char *bridge_type, uint64_t addr)
   1474 {
   1475 	pci_target_err_t tgt_err;
   1476 
   1477 	tgt_err.tgt_err_ena = ena;
   1478 	tgt_err.tgt_err_class = class;
   1479 	tgt_err.tgt_bridge_type = bridge_type;
   1480 	tgt_err.tgt_err_addr = addr;
   1481 	errorq_dispatch(pci_target_queue, (void *)&tgt_err,
   1482 	    sizeof (pci_target_err_t), ERRORQ_ASYNC);
   1483 }
   1484 
   1485 void
   1486 pci_targetq_init(void)
   1487 {
   1488 	/*
   1489 	 * PCI target errorq, to schedule async handling of generation of
   1490 	 * target device ereports based on captured physical address.
   1491 	 * The errorq is created here but destroyed when _fini is called
   1492 	 * for the pci module.
   1493 	 */
   1494 	if (pci_target_queue == NULL) {
   1495 		pci_target_queue = errorq_create("pci_target_queue",
   1496 		    (errorq_func_t)pci_target_drain, (void *)NULL,
   1497 		    TARGET_MAX_ERRS, sizeof (pci_target_err_t), FM_ERR_PIL,
   1498 		    ERRORQ_VITAL);
   1499 		if (pci_target_queue == NULL)
   1500 			panic("failed to create required system error queue");
   1501 	}
   1502 }
   1503