00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * CDDL HEADER START
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * The contents of this file are subject to the terms of the
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Common Development and Distribution License (the "License").
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * You may not use this file except in compliance with the License.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * or http://www.opensolaris.org/os/licensing.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * See the License for the specific language governing permissions
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * and limitations under the License.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * When distributing Covered Code, include this CDDL HEADER in each
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * If applicable, add the following below this CDDL HEADER, with the
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * fields enclosed by brackets "[]" replaced with your own identifying
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * information: Portions Copyright [yyyy] [name of copyright owner]
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * CDDL HEADER END
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
392e836b07e8da771953e4d64233b2abe4393efeGavin Maltby * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/types.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/sunndi.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/sysmacros.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/ddifm_impl.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/fm/util.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/fm/protocol.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/fm/io/pci.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/fm/io/ddi.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/pci.h>
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur#include <sys/pci_cap.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/pci_impl.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/epm.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#include <sys/pcifm.h>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#define PCIX_ECC_VER_CHECK(x) (((x) == PCI_PCIX_VER_1) ||\
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((x) == PCI_PCIX_VER_2))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreeterrorq_t *pci_target_queue = NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_err_t pci_err_tbl[] = {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_DET_PERR, PCI_STAT_PERROR, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_MDPE, PCI_STAT_S_PERROR, PCI_TARG_MDPE, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, DDI_FM_FATAL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_MA, PCI_STAT_R_MAST_AB, PCI_TARG_MA, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REC_TA, PCI_STAT_R_TARG_AB, PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet NULL, NULL, NULL, NULL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet};
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_err_t pci_bdg_err_tbl[] = {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_DET_PERR, PCI_STAT_PERROR, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_MDPE, PCI_STAT_S_PERROR, PCI_TARG_MDPE, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, DDI_FM_UNKNOWN,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh#if defined(__sparc)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_MA, PCI_STAT_R_MAST_AB, PCI_TARG_MA, DDI_FM_UNKNOWN,
0c64a9b435314788e185507d40ef9fae71507f5aanish#endif
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REC_TA, PCI_STAT_R_TARG_AB, PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet NULL, NULL, NULL, NULL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet};
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic pci_fm_err_t pcix_err_tbl[] = {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet NULL, NULL, NULL, NULL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet};
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic pci_fm_err_t pcix_sec_err_tbl[] = {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, DDI_FM_UNKNOWN,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, DDI_FM_UNKNOWN,
ac4d633f367252125bb35e97c5725d2aa68c1291stephh PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, DDI_FM_OK,
ac4d633f367252125bb35e97c5725d2aa68c1291stephh PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, DDI_FM_OK,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet NULL, NULL, NULL, NULL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet};
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephhpci_config_check(ddi_acc_handle_t handle, int fme_flag)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_error_t de;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!(DDI_FM_ACC_ERR_CAP(ddi_fm_capable(hp->ah_dip))))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FM_OK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet de.fme_version = DDI_FME_VERSION;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_acc_err_get(handle, &de, de.fme_version);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (de.fme_status != DDI_FM_OK) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (fme_flag == DDI_FM_ERR_UNEXPECTED) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_ERROR_SUBCLASS, PCI_NR);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh ddi_fm_ereport_post(hp->ah_dip, buf, de.fme_ena,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, NULL);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_acc_err_clear(handle, de.fme_version);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (de.fme_status);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_ecc_regs_gather(pci_erpt_t *erpt_p, pcix_ecc_regs_t *pcix_ecc_regs,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh uint8_t pcix_cap_ptr, int fme_flag)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int bdg = erpt_p->pe_dflags & PCI_BRIDGE_DEV;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat = pci_config_get32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_STATUS :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_STATUS)));
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_vflags |= PCIX_ERR_ECC_STS_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_fstaddr = pci_config_get32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_FST_AD :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_FST_AD)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_secaddr = pci_config_get32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_SEC_AD :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_SEC_AD)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_attr = pci_config_get32((
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_handle_t)erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_ATTR : PCI_PCIX_ECC_ATTR)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephhpcix_regs_gather(pci_erpt_t *erpt_p, void *pe_regs, int fme_flag)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t pcix_bdg_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat = pci_config_get16(
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_hdl, (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS));
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_vflags |=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_BDG_SEC_STATUS_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat = pci_config_get32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS));
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_vflags |= PCIX_BDG_STATUS_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_t *pcix_bdg_ecc_regs;
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur for (i = 0; i < 2; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_ecc_regs =
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_bdg_regs->pcix_bdg_ecc_regs[i];
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pci_config_put32(erpt_p->pe_hdl,
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur (pcix_bdg_cap_ptr +
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur PCI_PCIX_BDG_ECC_STATUS), i);
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_ecc_regs_gather(erpt_p,
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_bdg_ecc_regs,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pcix_bdg_cap_ptr, fme_flag);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_command = pci_config_get16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + PCI_PCIX_COMMAND));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_status = pci_config_get32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + PCI_PCIX_STATUS));
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_vflags |= PCIX_ERR_STATUS_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_t *pcix_ecc_regs =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_ecc_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_gather(erpt_p, pcix_ecc_regs,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pcix_cap_ptr, fme_flag);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephhpci_regs_gather(dev_info_t *dip, pci_erpt_t *erpt_p, int fme_flag)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_error_regs_t *pci_regs = erpt_p->pe_pci_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Start by reading all the error registers that are available for
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * pci and pci express and for leaf devices and bridges/switches
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_err_status = pci_config_get16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_CONF_STAT);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_vflags |= PCI_ERR_STATUS_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_cfg_comm = pci_config_get16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_CONF_COMM);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * If pci-pci bridge grab PCI bridge specific error registers.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_bdg_regs->pci_bdg_sec_stat =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_bdg_regs->pci_bdg_vflags |=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_BDG_SEC_STAT_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_bdg_regs->pci_bdg_ctrl =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs->pci_bdg_regs->pci_bdg_vflags |=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_BDG_CTRL_VALID;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur /* If pci-x device grab error registers */
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur if (erpt_p->pe_dflags & PCIX_DEV)
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pcix_regs_gather(erpt_p, erpt_p->pe_regs, fme_flag);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_regs_clear(pci_erpt_t *erpt_p, void *pe_regs)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t pcix_bdg_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_vflags = 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_t *pcix_bdg_ecc_regs;
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur for (i = 0; i < 2; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_ecc_regs =
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_bdg_regs->pcix_bdg_ecc_regs[i];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_bdg_ecc_regs->pcix_ecc_vflags &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ERR_ECC_STS_VALID) {
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pci_config_put32(erpt_p->pe_hdl,
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur (pcix_bdg_cap_ptr +
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur PCI_PCIX_BDG_ECC_STATUS),
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur i);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_bdg_cap_ptr +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_BDG_ECC_STATUS),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_ecc_regs->
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_ctlstat);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_bdg_ecc_regs->pcix_ecc_vflags =
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + PCI_PCIX_STATUS),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_status);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_vflags = 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_t *pcix_ecc_regs =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_ecc_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_ecc_regs->pcix_ecc_vflags &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ERR_ECC_STS_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put32(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pcix_cap_ptr + PCI_PCIX_ECC_STATUS),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_vflags = 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_regs_clear(pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Finally clear the error bits
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur if (erpt_p->pe_dflags & PCIX_DEV)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs_clear(erpt_p, erpt_p->pe_regs);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_pci_regs->pci_vflags & PCI_ERR_STATUS_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put16(erpt_p->pe_hdl, PCI_CONF_STAT,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_err_status);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_vflags = 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_BDG_SEC_STAT_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_bdg_regs->
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_sec_stat);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_BDG_CTRL_VALID)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_ctrl);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags = 0x0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * pcix_ereport_setup: Allocate structures for PCI-X error handling and ereport
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * generation.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/* ARGSUSED */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_ereport_setup(dev_info_t *dip, pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur uint16_t pcix_cap_ptr = PCI_CAP_NEXT_PTR_NULL;
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur ddi_acc_handle_t eh;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
be84494cdccacd78ec75f82fb1d837585975ffd2Krishna Elango if (pci_config_setup(dip, &eh) == DDI_SUCCESS) {
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur (void) PCI_CAP_LOCATE(eh, PCI_CAP_ID_PCIX, &pcix_cap_ptr);
be84494cdccacd78ec75f82fb1d837585975ffd2Krishna Elango pci_config_teardown(&eh);
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_cap_ptr != PCI_CAP_NEXT_PTR_NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_dflags |= PCIX_DEV;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_bdg_error_regs_t),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_cap_ptr = pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_ver = pci_config_get16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_cap_ptr + PCI_PCIX_SEC_STATUS) & PCI_PCIX_VER_MASK;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; i < 2; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_ecc_regs[i] =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_zalloc(sizeof (pcix_ecc_regs_t),
2901c7f30f3d151027f01874d586b2872497b3b6stephh KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_error_regs_t),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_cap_ptr = pcix_cap_ptr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_ver = pci_config_get16(erpt_p->pe_hdl,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_cap_ptr + PCI_PCIX_COMMAND) & PCI_PCIX_VER_MASK;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_ecc_regs = kmem_zalloc(
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pcix_ecc_regs_t), KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * pci_ereport_setup: Detect PCI device type and initialize structures to be
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * used to generate ereports based on detected generic device errors.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetvoid
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_ereport_setup(dev_info_t *dip)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet struct dev_info *devi = DEVI(dip);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet struct i_ddi_fmhdl *fmhdl = devi->devi_fmhdl;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_erpt_t *erpt_p;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t pci_hdr_type;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint16_t pci_status;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regspec_t *pci_rp;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int32_t len;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint32_t phys_hi;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * If device is not ereport capbable then report an error against the
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * driver for using this interface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * ASSERT fmhdl exists and fh_bus_specific is NULL.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ASSERT(fmhdl && (fmhdl->fh_bus_specific == NULL));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p = kmem_zalloc(sizeof (pci_erpt_t), KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_config_setup(dip, &erpt_p->pe_hdl) != DDI_SUCCESS)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet goto error;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs = kmem_zalloc(sizeof (pci_error_regs_t), KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_status = pci_config_get16(erpt_p->pe_hdl, PCI_CONF_STAT);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet goto error;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Get header type and record if device is a bridge.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_hdr_type = pci_config_get8(erpt_p->pe_hdl, PCI_CONF_HEADER);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh DDI_FM_OK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet goto error;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Check to see if PCI device is a bridge, if so allocate pci bridge
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * error register structure.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((pci_hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_dflags |= PCI_BRIDGE_DEV;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_bdg_regs = kmem_zalloc(
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pci_bdg_error_regs_t), KM_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (caddr_t)&pci_rp, &len) == DDI_SUCCESS) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet phys_hi = pci_rp->pci_phys_hi;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pci_rp, len);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >>
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_FUNC_SHIFT);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!(pci_status & PCI_STAT_CAP)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet goto done;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur /* Initialize structures for PCI-X devices. */
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pcix_ereport_setup(dip, erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetdone:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_regs_gather(dip, erpt_p, DDI_FM_ERR_UNEXPECTED);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs_clear(erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Before returning set fh_bus_specific to completed pci_erpt_t
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * structure
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fmhdl->fh_bus_specific = (void *)erpt_p;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreeterror:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_pci_regs)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p, sizeof (pci_erpt_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p = NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_ereport_teardown(pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint16_t pcix_ver;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ver = pcix_bdg_regs->pcix_bdg_ver;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; i < 2; i++)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pcix_bdg_regs->pcix_bdg_ecc_regs[i],
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pcix_ecc_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p->pe_regs, sizeof (pcix_bdg_error_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint16_t pcix_ver;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ver = pcix_regs->pcix_ver;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pcix_regs->pcix_ecc_regs,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pcix_ecc_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p->pe_regs, sizeof (pcix_error_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetvoid
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_ereport_teardown(dev_info_t *dip)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_erpt_t *erpt_p;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ASSERT(fmhdl);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur if (erpt_p->pe_dflags & PCIX_DEV)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ereport_teardown(erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_teardown((ddi_acc_handle_t *)&erpt_p->pe_hdl);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p->pe_pci_regs->pci_bdg_regs,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pci_bdg_error_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(erpt_p, sizeof (pci_erpt_t));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fmhdl->fh_bus_specific = NULL;
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * The following sparc specific code should be removed once the pci_cap
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * interfaces create the necessary properties for us.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_check_addr(dev_info_t *dip, ddi_fm_error_t *derr,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pcix_ecc_regs_t *pcix_ecc_regs, int type)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int cmd = (pcix_ecc_regs->pcix_ecc_ctlstat >> 16) & 0xf;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint64_t addr;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bus_specific_t *pci_fme_bsp =
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh (pci_fme_bus_specific_t *)derr->fme_bus_specific;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet addr = pcix_ecc_regs->pcix_ecc_secaddr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet addr = addr << 32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet addr |= pcix_ecc_regs->pcix_ecc_fstaddr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (cmd) {
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_INTR:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_SPEC:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FM_FATAL);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_IORD:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_IOWR:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_addr = addr;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type = type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh return (DDI_FM_UNKNOWN);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_DEVID:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FM_FATAL);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMRD_DW:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMWR:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMRD_BL:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMWR_BL:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_addr = addr;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type = type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh return (DDI_FM_UNKNOWN);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_CFRD:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_CFWR:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * for type 1 config transaction we can find bdf from address
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if ((addr & 3) == 1) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_bdf = (addr >> 8) & 0xffffffff;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_flags |= PCI_BS_BDF_VALID;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type = type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh return (DDI_FM_UNKNOWN);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_SPL:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_DADR:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh return (DDI_FM_UNKNOWN);
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMRDBL:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_CMD_MEMWRBL:
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_addr = addr;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type = type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh return (DDI_FM_UNKNOWN);
2901c7f30f3d151027f01874d586b2872497b3b6stephh default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FM_FATAL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_error_regs_t *pci_bdg_regs = erpt_p->pe_pci_regs->pci_bdg_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nonfatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int unknown = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ok = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = DDI_FM_OK;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bus_specific_t *pci_fme_bsp =
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh (pci_fme_bus_specific_t *)derr->fme_bus_specific;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (derr->fme_flag != DDI_FM_ERR_UNEXPECTED)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet goto done;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((pci_bdg_regs->pci_bdg_vflags & PCI_BDG_CTRL_VALID) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (pci_bdg_regs->pci_bdg_ctrl & PCI_BCNF_BCNTRL_DTO_STAT)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ERROR_SUBCLASS, PCI_DTO);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT16, pci_bdg_regs->pci_bdg_ctrl, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet unknown++;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_bdg_regs->pci_bdg_vflags & PCI_BDG_SEC_STAT_VALID) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; pci_bdg_err_tbl[i].err_class != NULL; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_bdg_regs->pci_bdg_sec_stat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_err_tbl[i].reg_bit) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_err_tbl[i].err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_regs->pci_bdg_ctrl, NULL);
ac4d633f367252125bb35e97c5725d2aa68c1291stephh PCI_FM_SEV_INC(pci_bdg_err_tbl[i].flags);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_fme_bsp && (pci_fme_bsp->pci_bs_flags &
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_BS_ADDR_VALID) &&
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type == ACC_HANDLE &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_err_tbl[i].terr_class)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_target_enqueue(derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bdg_err_tbl[i].terr_class,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ERROR_SUBCLASS,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetdone:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Need to check for poke and cautious put. We already know peek
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * and cautious get errors occurred (as we got a trap) and we know
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * they are nonfatal.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (derr->fme_flag == DDI_FM_ERR_EXPECTED) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * for cautious puts we treat all errors as nonfatal. Actually
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * we set nonfatal for cautious gets as well - doesn't do any
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * harm
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_STAT_R_MAST_AB | PCI_STAT_S_PERROR | PCI_STAT_S_SYSERR))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nonfatal++;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (derr->fme_flag == DDI_FM_ERR_POKE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * special case for pokes - we only consider master abort
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * and target abort as nonfatal. Sserr with no master abort is
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * fatal, but master/target abort can come in on separate
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * instance, so return unknown and parent will determine if
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * nonfatal (if another child returned nonfatal - ie master
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * or target abort) or fatal otherwise
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_STAT_R_MAST_AB))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nonfatal++;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_pci_regs->pci_err_status & PCI_STAT_S_SYSERR)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet unknown++;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * now check children below the bridge
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh ret = ndi_fm_handler_dispatch(dip, NULL, derr);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_ecc_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet void *pe_regs)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs_t *pcix_ecc_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int bridge;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ecc_phase;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ecc_corr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int sec_ue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int sec_ce;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nonfatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int unknown = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ok = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bridge = 1;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs = (pcix_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bridge = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; i < (bridge ? 2 : 1); i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = DDI_FM_OK;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs = bridge ? pcix_bdg_regs->pcix_bdg_ecc_regs[i] :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_ecc_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_ecc_regs->pcix_ecc_vflags & PCIX_ERR_ECC_STS_VALID) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ecc_phase = (pcix_ecc_regs->pcix_ecc_ctlstat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_PHASE) >> 0x4;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ecc_corr = (pcix_ecc_regs->pcix_ecc_ctlstat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_CORR);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sec_ue = (pcix_ecc_regs->pcix_ecc_ctlstat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_S_UE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sec_ce = (pcix_ecc_regs->pcix_ecc_ctlstat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PCIX_ECC_S_CE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (ecc_phase) {
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_NOERR:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_FADDR:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_SADDR:
ac4d633f367252125bb35e97c5725d2aa68c1291stephh PCI_FM_SEV_INC(ecc_corr ? DDI_FM_OK :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_FM_FATAL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "%s.%s%s", PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i ? PCIX_SEC_ERROR_SUBCLASS : "",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ecc_corr ? PCIX_ECC_CE_ADDR :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_UE_ADDR);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_ATTR:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ecc_corr ?
ac4d633f367252125bb35e97c5725d2aa68c1291stephh DDI_FM_OK : DDI_FM_FATAL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "%s.%s%s", PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i ? PCIX_SEC_ERROR_SUBCLASS : "",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ecc_corr ? PCIX_ECC_CE_ATTR :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_UE_ATTR);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_DATA32:
2901c7f30f3d151027f01874d586b2872497b3b6stephh case PCI_PCIX_ECC_PHASE_DATA64:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ecc_corr)
ac4d633f367252125bb35e97c5725d2aa68c1291stephh ret = DDI_FM_OK;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh else {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh int type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_error_regs_t *pci_regs =
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh erpt_p->pe_pci_regs;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (i) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_regs->pci_bdg_regs->
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_bdg_sec_stat &
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_STAT_S_PERROR)
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh type = ACC_HANDLE;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh else
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh type = DMA_HANDLE;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh } else {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_regs->pci_err_status &
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_STAT_S_PERROR)
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh type = DMA_HANDLE;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh else
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh type = ACC_HANDLE;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ret = pcix_check_addr(dip, derr,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pcix_ecc_regs, type);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "%s.%s%s", PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i ? PCIX_SEC_ERROR_SUBCLASS : "",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ecc_corr ? PCIX_ECC_CE_DATA :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_UE_DATA);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ecc_phase)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (bridge)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SEC_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_BDG_STAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_ATTR, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_attr, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_COMMAND, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_command,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_STATUS, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_status,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_ATTR, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_attr, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (sec_ce || sec_ue) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "%s.%s%s", PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i ? PCIX_SEC_ERROR_SUBCLASS : "",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (bridge)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SEC_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_BDG_STAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_ATTR, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_attr, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_COMMAND, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_command,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_STATUS, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_status,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_ctlstat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ECC_ATTR, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_ecc_regs->pcix_ecc_attr, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(sec_ue ? DDI_FM_FATAL :
ac4d633f367252125bb35e97c5725d2aa68c1291stephh DDI_FM_OK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet void *pe_regs)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_error_regs_t *pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nonfatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int unknown = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ok = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((pcix_bdg_regs->pcix_bdg_stat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_err_tbl[i].reg_bit)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_err_tbl[i].err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SEC_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_BDG_STAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; pcix_sec_err_tbl[i].err_class != NULL; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((pcix_bdg_regs->pcix_bdg_sec_stat &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_sec_err_tbl[i].reg_bit)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SEC_ERROR_SUBCLASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_sec_err_tbl[i].err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_SEC_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_sec_stat,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_BDG_STAT, DATA_TYPE_UINT32,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_bdg_regs->pcix_bdg_stat, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(pcix_sec_err_tbl[i].flags);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Log/Handle ECC errors */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ret = pcix_ecc_error_report(dip, derr, erpt_p,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)pcix_bdg_regs);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpcix_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nonfatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int unknown = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ok = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!(pcix_regs->pcix_status & pcix_err_tbl[i].reg_bit))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet continue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_ERROR_SUBCLASS, pcix_err_tbl[i].err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCIX_COMMAND, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pcix_regs->pcix_command, PCIX_STATUS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DATA_TYPE_UINT32, pcix_regs->pcix_status,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Log/Handle ECC errors */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = pcix_ecc_error_report(dip, derr, erpt_p,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)pcix_regs);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nonfatal = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int unknown = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ok = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Log generic PCI errors.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; pci_err_tbl[i].err_class != NULL; i++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!(erpt_p->pe_pci_regs->pci_err_status &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_err_tbl[i].reg_bit) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet !(erpt_p->pe_pci_regs->pci_vflags &
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ERR_STATUS_VALID))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet continue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Generate an ereport for this error bit.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ERROR_SUBCLASS, pci_err_tbl[i].err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_fm_ereport_post(dip, buf, derr->fme_ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_CONFIG_STATUS, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_err_status,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p->pe_pci_regs->pci_cfg_comm, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur PCI_FM_SEV_INC(pci_err_tbl[i].flags);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur if (erpt_p->pe_dflags & PCIX_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = pcix_bdg_error_report(dip, derr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p, erpt_p->pe_regs);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = pcix_error_report(dip, derr, erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((erpt_p->pe_dflags & PCI_BRIDGE_DEV)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int ret = pci_bdg_error_report(dip, derr, erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_FM_SEV_INC(ret);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bus_specific_t *pci_fme_bsp;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh int ret = DDI_FM_UNKNOWN;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp = (pci_fme_bus_specific_t *)derr->fme_bus_specific;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (pci_fme_bsp->pci_bs_flags & PCI_BS_ADDR_VALID) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh ret = ndi_fmc_entry_error(dip,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type, derr,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh (void *)&pci_fme_bsp->pci_bs_addr);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_FM_SEV_INC(ret);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * If we didn't find the handle using an addr, try using bdf.
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * Note we don't do this where the bdf is for a
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * device behind a pciex/pci bridge as the bridge may have
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * fabricated the bdf.
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (ret == DDI_FM_UNKNOWN &&
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh (pci_fme_bsp->pci_bs_flags & PCI_BS_BDF_VALID) &&
49fbdd30212f016ddd49c4b5c997b0b827ff0962Erwin T Tsaur pci_fme_bsp->pci_bs_bdf == erpt_p->pe_bdf) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh ret = ndi_fmc_entry_error_all(dip,
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bsp->pci_bs_type, derr);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh PCI_FM_SEV_INC(ret);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet derr->fme_status = (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetvoid
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_ereport_post(dev_info_t *dip, ddi_fm_error_t *derr, uint16_t *xx_status)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet struct i_ddi_fmhdl *fmhdl;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_erpt_t *erpt_p;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh ddi_fm_error_t de;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bus_specific_t pci_fme_bs;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae /*
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae * On PCI Express systems, all error handling and ereport are done via
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae * the PCIe misc module. This function is a no-op for PCIe Systems. In
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae * order to tell if a system is a PCI or PCIe system, check that the
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae * bus_private_data exists. If it exists, this is a PCIe system.
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae */
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae if (ndi_get_bus_private(dip, B_TRUE)) {
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae derr->fme_status = DDI_FM_OK;
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae if (xx_status != NULL)
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae *xx_status = 0x0;
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae return;
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae }
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fmhdl = DEVI(dip)->devi_fmhdl;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_NOSLEEP);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * copy in the ddi_fm_error_t structure in case it's VER0
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_version = derr->fme_version;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_status = derr->fme_status;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_flag = derr->fme_flag;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_ena = derr->fme_ena;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_acc_handle = derr->fme_acc_handle;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_dma_handle = derr->fme_dma_handle;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_bus_specific = derr->fme_bus_specific;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (derr->fme_version >= DDI_FME_VER1)
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_bus_type = derr->fme_bus_type;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh else
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_bus_type = DDI_FME_BUS_TYPE_DFLT;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (de.fme_bus_type == DDI_FME_BUS_TYPE_DFLT) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * if this is the first pci device we've found convert
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * fme_bus_specific to DDI_FME_BUS_TYPE_PCI
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh bzero(&pci_fme_bs, sizeof (pci_fme_bs));
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (de.fme_bus_specific) {
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh /*
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * the cpu passed us an addr - this can be used to look
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh * up an access handle
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh */
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bs.pci_bs_addr = (uintptr_t)de.fme_bus_specific;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bs.pci_bs_type = ACC_HANDLE;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_fme_bs.pci_bs_flags |= PCI_BS_ADDR_VALID;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_bus_specific = (void *)&pci_fme_bs;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_bus_type = DDI_FME_BUS_TYPE_PCI;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh }
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ASSERT(fmhdl);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh if (de.fme_ena == NULL)
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh de.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
ac4d633f367252125bb35e97c5725d2aa68c1291stephh if (erpt_p == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_regs_gather(dip, erpt_p, de.fme_flag);
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh pci_error_report(dip, &de, erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regs_clear(erpt_p);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh derr->fme_status = de.fme_status;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh derr->fme_ena = de.fme_ena;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh derr->fme_acc_handle = de.fme_acc_handle;
8aec91825357bbeaf2ab5d30fc97fe5051a6b8ddstephh derr->fme_dma_handle = de.fme_dma_handle;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (xx_status != NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *xx_status = erpt_p->pe_pci_regs->pci_err_status;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * private version of walk_devs() that can be used during panic. No
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * sleeping or locking required.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet while (dip) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch ((*f)(dip, arg)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case DDI_WALK_TERMINATE:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case DDI_WALK_CONTINUE:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_fm_walk_devs(ddi_get_child(dip), f,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet arg) == DDI_WALK_TERMINATE)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case DDI_WALK_PRUNECHILD:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet dip = ddi_get_next_sibling(dip);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * need special version of ddi_fm_ereport_post() as the leaf driver may
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * not be hardened.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint8_t version, ...)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *name;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char device_path[MAXPATHLEN];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char ddi_error_class[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nvlist_t *ereport, *detector;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nv_alloc_t *nva;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet errorq_elem_t *eqep;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet va_list ap;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (panicstr) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet eqep = errorq_reserve(ereport_errorq);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (eqep == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ereport = errorq_elem_nvl(ereport_errorq, eqep);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nva = errorq_elem_nva(ereport_errorq, eqep);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet detector = fm_nvlist_create(nva);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ereport = fm_nvlist_create(NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet detector = fm_nvlist_create(NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) ddi_pathname(dip, device_path);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
392e836b07e8da771953e4d64233b2abe4393efeGavin Maltby device_path, NULL, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(ddi_error_class, FM_MAX_CLASS, "%s.%s",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_IO_CLASS, error_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fm_ereport_set(ereport, version, ddi_error_class, ena, detector, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet va_start(ap, version);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet name = va_arg(ap, char *);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) i_fm_payload_set(ereport, name, ap);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet va_end(ap);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (panicstr) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) fm_ereport_post(ereport, EVCH_TRYHARD);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fm_nvlist_destroy(ereport, FM_NVA_FREE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fm_nvlist_destroy(detector, FM_NVA_FREE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_check_regs(dev_info_t *dip, void *arg)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int reglen;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rn;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int totreg;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_regspec_t *drv_regp;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (tgt_err->tgt_pci_space == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * for config space, we need to check if the given address
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * is a valid config space address for this device - based
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * on pci_phys_hi of the config space entry in reg property.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet totreg = reglen / sizeof (pci_regspec_t);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (rn = 0; rn < totreg; rn++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (tgt_err->tgt_pci_space ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_addr & (PCI_REG_BUS_M |
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_DEV_M | PCI_REG_FUNC_M)) ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (drv_regp[rn].pci_phys_hi & (PCI_REG_BUS_M |
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_DEV_M | PCI_REG_FUNC_M))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_dip = dip;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * for non config space, need to check reg to look
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * for any non-relocable mapping, otherwise check
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * assigned-addresses.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet totreg = reglen / sizeof (pci_regspec_t);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (rn = 0; rn < totreg; rn++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((drv_regp[rn].pci_phys_hi & PCI_RELOCAT_B) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_space ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_addr >=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_phys_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_addr <
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_phys_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_size_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_dip = dip;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet "assigned-addresses", (caddr_t)&drv_regp, &reglen) !=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_SUCCESS)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet totreg = reglen / sizeof (pci_regspec_t);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (rn = 0; rn < totreg; rn++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_space ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_addr >=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_phys_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_pci_addr <
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_phys_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t)drv_regp[rn].pci_size_low +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_dip = dip;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(drv_regp, reglen);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * impl_fix_ranges - fixes the config space entry of the "ranges"
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * property on psycho+ platforms. (if changing this function please make sure
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * to change the pci_fix_ranges function in pcipsy.c)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fix_ranges(dev_info_t *dip, pci_ranges_t *pci_ranges, int nrange)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#if defined(__sparc)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *name = ddi_binding_name(dip);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((strcmp(name, "pci108e,8000") == 0) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (strcmp(name, "pci108e,a000") == 0) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (strcmp(name, "pci108e,a001") == 0)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; i < nrange; i++, pci_ranges++)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((pci_ranges->child_high & PCI_REG_ADDR_M) ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_ADDR_CONFIG)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_ranges->parent_low |=
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_ranges->child_high;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet#endif
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic int
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_check_ranges(dev_info_t *dip, void *arg)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint64_t range_parent_begin;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint64_t range_parent_size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint64_t range_parent_end;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint32_t space_type;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint32_t bus_num;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint32_t range_offset;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_ranges_t *pci_ranges, *rangep;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_bus_range_t *pci_bus_rangep;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int pci_ranges_length;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int nrange;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int i, size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (strcmp(ddi_node_name(dip), "pci") != 0 &&
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet strcmp(ddi_node_name(dip), "pciex") != 0)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_CONTINUE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Get the ranges property. Note we only look at the top level pci
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * node (hostbridge) which has a ranges property of type pci_ranges_t
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * not at pci-pci bridges.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (caddr_t)&pci_ranges, &pci_ranges_length) != DDI_SUCCESS) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * no ranges property - no translation needed
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_space = TGT_PCI_SPACE_UNKNOWN;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (panicstr)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) pci_fm_walk_devs(ddi_get_child(dip),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_check_regs, (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int circ = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ndi_devi_enter(dip, &circ);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ndi_devi_exit(dip, circ);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (tgt_err->tgt_dip != NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_PRUNECHILD);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet nrange = pci_ranges_length / sizeof (pci_ranges_t);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rangep = pci_ranges;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Need to fix the pci ranges property for psycho based systems */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_fix_ranges(dip, pci_ranges, nrange);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (i = 0; i < nrange; i++, rangep++) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_parent_begin = ((uint64_t)rangep->parent_high << 32) +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rangep->parent_low;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_parent_size = ((uint64_t)rangep->size_high << 32) +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rangep->size_low;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_parent_end = range_parent_begin + range_parent_size - 1;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((tgt_err->tgt_err_addr < range_parent_begin) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (tgt_err->tgt_err_addr > range_parent_end)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Not in range */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet continue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet space_type = PCI_REG_ADDR_G(rangep->child_high);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Config space address - check bus range */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_offset = tgt_err->tgt_err_addr -
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_parent_begin;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bus_num = PCI_REG_BUS_G(range_offset);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_PROP_DONTPASS, "bus-range",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (caddr_t)&pci_bus_rangep, &size) != DDI_SUCCESS) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet continue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((bus_num < pci_bus_rangep->lo) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (bus_num > pci_bus_rangep->hi)) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Bus number not appropriate for this
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * pci nexus.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pci_bus_rangep, size);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet continue;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pci_bus_rangep, size);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* We have a match if we get here - compute pci address */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr -
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet range_parent_begin;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_addr += (((uint64_t)rangep->child_mid << 32) +
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rangep->child_low);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_pci_space = space_type;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (panicstr)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) pci_fm_walk_devs(ddi_get_child(dip),
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_check_regs, (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int circ = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ndi_devi_enter(dip, &circ);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ndi_devi_exit(dip, circ);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (tgt_err->tgt_dip != NULL) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pci_ranges, pci_ranges_length);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_TERMINATE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet kmem_free(pci_ranges, pci_ranges_length);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_WALK_PRUNECHILD);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Function used to drain pci_target_queue, either during panic or after softint
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * is generated, to generate target device ereports based on captured physical
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * addresses
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic void
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_target_drain(void *private_p, pci_target_err_t *tgt_err)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char buf[FM_MAX_CLASS];
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * The following assumes that all pci_pci bridge devices
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * are configured as transparant. Find the top-level pci
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * nexus which has tgt_err_addr in one of its ranges, converting this
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * to a pci address in the process. Then starting at this node do
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * another tree walk to find a device with the pci address we've
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * found within range of one of it's assigned-addresses properties.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_dip = NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (panicstr)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) pci_fm_walk_devs(ddi_root_node(), pci_check_ranges,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_walk_devs(ddi_root_node(), pci_check_ranges,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void *)tgt_err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (tgt_err->tgt_dip == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", tgt_err->tgt_bridge_type,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err->tgt_err_class);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_fm_ereport_post(tgt_err->tgt_dip, buf, tgt_err->tgt_err_ena, 0,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCI_PA, DATA_TYPE_UINT64, tgt_err->tgt_err_addr, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetvoid
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_target_enqueue(uint64_t ena, char *class, char *bridge_type, uint64_t addr)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_target_err_t tgt_err;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err.tgt_err_ena = ena;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err.tgt_err_class = class;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err.tgt_bridge_type = bridge_type;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet tgt_err.tgt_err_addr = addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet errorq_dispatch(pci_target_queue, (void *)&tgt_err,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet sizeof (pci_target_err_t), ERRORQ_ASYNC);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetvoid
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_targetq_init(void)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * PCI target errorq, to schedule async handling of generation of
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * target device ereports based on captured physical address.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * The errorq is created here but destroyed when _fini is called
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * for the pci module.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_target_queue == NULL) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_target_queue = errorq_create("pci_target_queue",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (errorq_func_t)pci_target_drain, (void *)NULL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet TARGET_MAX_ERRS, sizeof (pci_target_err_t), FM_ERR_PIL,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ERRORQ_VITAL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (pci_target_queue == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet panic("failed to create required system error queue");
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}