pcipsy.c revision 9129170ada39d6c7a0cf249048ae65df8f924524
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Psycho+ specifics implementation:
* interrupt mapping register
* PBM configuration
* ECC and PBM error handling
* Iommu mapping handling
* Streaming Cache flushing
*/
#include <sys/sysmacros.h>
#include <sys/machsystm.h>
#include <sys/ddi_impldefs.h>
#include <sys/iommutsb.h>
#ifdef _STARFIRE
#include <sys/starfire.h>
#endif /* _STARFIRE */
static pci_ksinfo_t *pci_name_kstat;
/*LINTLIBRARY*/
/* called by pci_attach() DDI_ATTACH to initialize pci objects */
int
{
int ret;
return (DDI_FAILURE);
}
}
/* second side attach */
}
if (cmn_p->pci_common_refcnt == 0) {
/* Perform allocation first to avoid delicate unwinding. */
return (DDI_FAILURE);
}
} else {
}
goto done;
done:
if (ret != DDI_SUCCESS)
ret);
return (ret);
}
/* called by pci_detach() DDI_DETACH to destroy pci objects */
void
{
if (cmn_p->pci_common_refcnt != 0) {
return;
}
}
/* called by pci_attach() DDI_RESUME to (re)initialize pci objects */
void
{
if (cmn_p->pci_common_attachcnt == 0) {
}
if (cmn_p->pci_common_attachcnt == 0)
}
/* called by pci_detach() DDI_SUSPEND to suspend pci objects */
void
{
}
}
static int
{
extern char *platform;
int i, no_of_intrs;
/*
* This is a hack to fix a broken imap entry in the javelin PROM.
* see bugid 4226603
*/
sizeof (javelin_prom_fix));
/*
* Get the interrupts property.
*/
/*
* figure out number of interrupts in the "interrupts" property
* and convert them all into ino.
*/
i = CELLS_1275_TO_BYTES(i);
for (i = 0; i < no_of_intrs; i++)
if (i = cb_register_intr(pci_p))
goto teardown;
if (i = ecc_register_intr(pci_p))
goto teardown;
}
if (i = pbm_register_intr(pbm_p)) {
goto teardown;
}
return (DDI_SUCCESS);
return (i);
}
/*
* pci_fix_ranges - fixes the config space entry of the "ranges"
* property on psycho+ platforms
*/
void
{
int i;
for (i = 0; i < rng_entries; i++, rng_p++)
}
/*
* map_pci_registers
*
* This function is called from the attach routine to map the registers
* accessed by this driver.
*
* used by: pci_attach()
*
* return value: DDI_FAILURE on failure
*/
int
{
return (DDI_FAILURE);
}
/*
* if we don't have streaming buffer, then we don't have
* pci_address[2].
*/
if (pci_stream_buf_exists &&
return (DDI_FAILURE);
}
/*
* The second register set contains the bridge's configuration
* header. This header is at the very beginning of the bridge's
* configuration space. This space has litte-endian byte order.
*/
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* unmap_pci_registers:
*
* This routine unmap the registers mapped by map_pci_registers.
*
* used by: pci_detach()
*
* return value: none
*/
void
{
}
/*
* These convenience wrappers relies on map_pci_registers() to setup
* pci_address[0-2] correctly at first.
*/
/* The psycho+ reg base is at 1fe.0000.0000 */
static uintptr_t
{
}
/* The psycho+ config reg base is always the 2nd reg entry */
static uintptr_t
{
}
{
}
{
return ((reg & COMMON_INTR_MAP_REG_TID) >>
}
uint64_t *
{
if (ino & 0x20)
else
return (addr);
}
uint64_t *
{
if (ino & 0x20)
else
return (addr);
}
/*
* psycho have one mapping register per slot
*/
void
{
if (!IB_IS_OBIO_INO(ino)) {
}
}
/*
* return true if the ino shares mapping register with other interrupts
* of the same slot, or is still shared by other On-board devices.
*/
int
{
if (IB_IS_OBIO_INO(ino))
return (ino_p->ino_ih_size);
else
}
/*ARGSUSED*/
void
{
}
{
return (a);
}
{
goto done;
goto done;
/*
* Hack for pre 1275 imap machines e.g. quark & tazmo
* We need to turn any PCI interrupts into ino interrupts. machines
* supporting imap will have this done in the map.
*/
return (0);
/*
* The ino for a given device id is derived as 0BSSNN where
*
* B = 0 for bus A, 1 for bus B
* SS = dev - 1 for bus A, dev - 2 for bus B
* NN = 00 for INTA#, 01 for INTB#, 10 for INTC#, 11 for INTD#
*
* if pci bus number > 0x80, then devices are located on the A side(66)
*/
intr--;
done:
}
/*
* Return the cpuid to to be used for an ino. Psycho has special slot-cpu
* constraints on cpu assignment:
*
* On multi-function pci cards, functions have separate devinfo nodes and
* control interrupt-to-cpu binding on a per pci-slot basis instead of per
* function. For hardware like this, if an interrupt for one function has
* already been directed to a particular cpu, we can't choose a different
* cpu for another function implemented in the same pci-slot - if we did
* we would be redirecting the first function too (which causes problems
* for consistent interrupt distribution).
*
* This function determines if there is already an established slot-oriented
* interrupt-to-cpu binding established, if there is then it returns that
* cpu. Otherwise a new cpu is selected by intr_dist_cpuid().
*
* The devinfo node we are trying to associate a cpu with is
* ino_p->ino_ih_head->ih_dip.
*/
{
int l2;
int cpu_id;
/* must be psycho driver parent (not ebus) */
goto newcpu;
/*
* From PCI 1275 binding: 2.2.1.3 Unit Address representation:
* Since the "unit-number" is the address that appears in on Open
* Firmware 'device path', it follows that only the DD and DD,FF
* forms of the text representation can appear in a 'device path'.
*
* The rdip unit address is of the form "DD[,FF]". Define two
* unit address strings that represent same-slot use: "DD" and "DD,".
* The first compare uses strcmp, the second uses strncmp.
*/
goto newcpu;
if (s1) {
} else {
}
/*
* Search the established ino list for devinfo nodes bound
* to an ino that matches one of the slot use strings.
*/
/* skip self and non-established */
continue;
/* skip non-siblings */
continue;
/* must be psycho driver parent (not ebus) */
continue;
extern int intr_dist_debug;
if (intr_dist_debug)
"pcipsy`pci_intr_dist_cpuid "
"%s#%d %s: cpu %d established "
break;
}
}
/* If a slot use match is found then use established cpu */
if (sino_p) {
goto out;
}
if (buf2)
return (cpu_id);
}
/*ARGSUSED*/
static void
cb_thermal_timeout(void *arg)
{
do_shutdown();
/*
* In case do_shutdown() fails to halt the system.
*/
}
/*
* High-level handler for psycho's CBNINTR_THERMAL interrupt.
*
* Use timeout(9f) to implement the core functionality so that the
* timeout(9f) function can sleep, if needed.
*/
/*ARGSUSED*/
{
if (pci_thermal_intr_fatal) {
}
return (DDI_INTR_CLAIMED);
}
void
{
}
#ifdef _STARFIRE
#endif /* _STARFIRE */
}
int
{
return (DDI_SUCCESS);
}
void
{
}
{
}
{
}
/*
*/
int
{
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
int
{
}
void
{
}
void
{
uint64_t l;
uint16_t s = 0;
/*
* Workarounds for hardware bugs:
*
* bus parking
*
* Pass 2 psycho parts have a bug that requires bus
* parking to be disabled.
*
* Pass 1 cheerio parts have a bug which prevents them
* from working on a PBM with bus parking enabled.
*
* rerun disable
*
* Pass 1 and 2 psycho's require that the rerun's be
* enabled.
*
* retry limit
*
* For pass 1 and pass 2 psycho parts we disable the
* retry limit. This is because the limit of 16 seems
* too restrictive for devices that are children of pci
* to pci bridges. For pass 3 this limit will be 64.
*
*
* For pass 2 psycho, the disable this feature.
*/
switch (l) {
case 0:
if (!pci_disable_pass1_workarounds) {
if (pbm_has_pass_1_cheerio(pci_p))
pci_rerun_disable &= ~mask;
}
break;
case 1:
if (!pci_disable_pass2_workarounds) {
pci_rerun_disable &= ~mask;
}
break;
case 2:
if (!pci_disable_pass3_workarounds) {
if (pbm_has_pass_1_cheerio(pci_p))
}
break;
case 3:
if (!pci_disable_plus_workarounds) {
if (pbm_has_pass_1_cheerio(pci_p))
}
break;
default:
if (!pci_disable_default_workarounds) {
if (pbm_has_pass_1_cheerio(pci_p))
}
break;
}
/*
* Clear any PBM errors.
*/
l = (PSYCHO_PCI_AFSR_E_MASK << PSYCHO_PCI_AFSR_PE_SHIFT) |
*pbm_p->pbm_async_flt_status_reg = l;
/*
* Clear error bits in configuration status register.
*/
s = PCI_STAT_PERROR | PCI_STAT_S_PERROR |
/*
* See if any SERR# signals are asserted. We'll clear them later.
*/
if (l & COMMON_PCI_CTRL_SERR)
/*
* Determine if PCI bus is running at 33 or 66 mhz.
*/
if (l & COMMON_PCI_CTRL_SPEED)
else
/*
* Enable error interrupts.
*/
if (pci_error_intr_enable & mask)
else
l &= ~PSYCHO_PCI_CTRL_ERR_INT_EN;
/*
* Disable pci streaming byte errors and error interrupts.
*/
l &= ~PSYCHO_PCI_CTRL_SBH_INT_EN;
/*
*/
if ((pci_bus_parking_enable & mask) &&
"no-bus-parking"))
l |= PSYCHO_PCI_CTRL_ARB_PARK;
else
l &= ~PSYCHO_PCI_CTRL_ARB_PARK;
/*
* Enable arbitration.
*/
l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_b_arb_enable;
else
l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_a_arb_enable;
/*
* Make sure SERR is clear
*/
l |= COMMON_PCI_CTRL_SERR;
/*
* Make sure power management interrupt is disabled.
*/
l &= ~PSYCHO_PCI_CTRL_WAKEUP_EN;
#ifdef _STARFIRE
/*
* Hack to determine whether we do Starfire special handling
* For starfire, we simply program a constant odd-value
* (0x1D) in the MID field.
*
* Zero out the MID field before ORing. We leave the LSB of
* the MID field intact since we cannot have a zero (even)
* MID value.
*/
l &= 0xFF0FFFFFFFFFFFFFULL;
l |= 0x1DULL << 51;
/*
* Program in the Interrupt Group Number. Here we have to
* convert the starfire 7bit upaid into a 5bit value.
*/
#endif /* _STARFIRE */
/*
* Now finally write the control register with the appropriate value.
*/
*pbm_p->pbm_ctrl_reg = l;
/*
* Allow the diag register to be set based upon variable that
*/
l = *pbm_p->pbm_diag_reg;
if (pci_retry_disable & mask)
if (pci_retry_enable & mask)
l &= ~COMMON_PCI_DIAG_DIS_RETRY;
if (pci_intsync_disable & mask)
else
l &= ~COMMON_PCI_DIAG_DIS_INTSYNC;
if (pci_dwsync_disable & mask)
else
l &= ~PSYCHO_PCI_DIAG_DIS_DWSYNC;
*pbm_p->pbm_diag_reg = l;
/*
* Enable SERR# and parity reporting via command register.
*/
/*
* The current versions of the obp are suppose to set the latency
* timer register but do not. Bug 1234181 is open against this
* problem. Until this bug is fixed we check to see if the obp
* has attempted to set the latency timer register by checking
* for the existence of a "latency-timer" property.
*/
"pbm_configure: set psycho latency timer to %x\n",
}
}
{
/*
* Disable error and streaming byte hole interrupts via the
* PBM control register.
*/
*pbm_p->pbm_ctrl_reg &=
/*
* Disable error interrupts via the interrupt mapping register.
*/
return (BF_NONE);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
void
{
if (pa)
}
/*ARGSUSED*/
{
ASSERT(0);
return (0);
}
/*ARGSUSED*/
void
{
ASSERT(0);
}
void
{
"\npci_iommu_config: pbm_csr_p=%016llx pbm_ctl=%016llx",
"\n\tiommu_ctl_p=%016llx iommu_ctl=%016llx",
if (!cfgpa)
goto reprog;
/* disable PBM arbiters - turn off bits 0-7 */
/* make sure we own the bus by reading any child device config space */
*tsb_bar_p = tsb_bar_val;
*iommu_ctl_p = iommu_ctl;
}
int
{
ASSERT(0);
return (DDI_FAILURE);
}
void
{
/* cb_p->cb_node_id = 0; */
/*
* Clear any pending address parity errors.
*/
if (csr & COMMON_CB_CONTROL_STATUS_APERR) {
}
#ifdef _STARFIRE
/* Setup Starfire interrupt target translation */
#endif /* _STARFIRE */
}
void
{
}
/*
* overwrite dvma end address (only on virtual-dma systems)
* initialize tsb size
* reset context bits
* return: IOMMU CSR bank base address (VA)
*/
{
int dvma_prop_len;
goto tsb_done;
if (dvma_prop_len != sizeof (pci_dvma_range_prop_t)) {
goto tsb_end;
}
/*
* Psycho has no context support.
*/
pci_use_contexts = 0;
pci_sc_use_contexts = 0;
/*
* Determine the virtual address of the register block
* containing the iommu control registers.
*/
return (get_reg_base(pci_p));
}
/*ARGSUSED*/
void
{
}
/* The psycho+ PBM reg base is at 1fe.0000.2000 */
{
(pci_stream_buf_exists ? 0 : PSYCHO_PCI_PBM_REG_BASE)));
}
void
{
}
void
{
/*
* Get the base virtual address for the PBM control block.
*/
/*
* Get the virtual address of the PCI configuration header.
* This should be mapped little-endian.
*/
/*
* Get the virtual addresses for control, error and diag
* registers.
*/
(uint64_t *)(a + PSYCHO_PCI_ASYNC_FLT_ADDR_REG_OFFSET);
}
/*ARGSUSED*/
void
{
}
void
{
/*
* Determine the virtual addresses of the streaming cache
*/
/*
* Determine the virtual addresses of the streaming cache
* diagnostic access registers.
*/
a = get_reg_base(pci_p);
(a + PSYCHO_SC_A_DATA_DIAG_OFFSET);
(a + PSYCHO_SC_A_TAG_DIAG_OFFSET);
(a + PSYCHO_SC_A_LTAG_DIAG_OFFSET);
} else {
(a + PSYCHO_SC_B_DATA_DIAG_OFFSET);
(a + PSYCHO_SC_B_TAG_DIAG_OFFSET);
(a + PSYCHO_SC_B_LTAG_DIAG_OFFSET);
}
}
int
{
"#upa-interrupt-proxies", 1));
}
int
{
"upa-portid", -1));
}
/*
* pbm_has_pass_1_cheerio
*
*
* Given a PBM soft state pointer, this routine scans it child nodes
* to see if one is a pass 1 cheerio.
*
* return value: 1 if pass 1 cheerio is found, 0 otherwise
*/
static int
{
int found = 0;
char *s;
int rev;
s = ddi_get_name(cdip);
rev =
"revision-id", 0);
if (rev == 0)
found = 1;
}
}
return (found);
}
/*
* Psycho Performance Events.
*/
psycho_pci_events[] = {
{"dvma_stream_rd_a", 0x0}, {"dvma_stream_wr_a", 0x1},
{"dvma_const_rd_a", 0x2}, {"dvma_const_wr_a", 0x3},
{"dvma_stream_buf_mis_a", 0x4}, {"dvma_cycles_a", 0x5},
{"dvma_wd_xfr_a", 0x6}, {"pio_cycles_a", 0x7},
{"dvma_stream_rd_b", 0x8}, {"dvma_stream_wr_b", 0x9},
{"dvma_const_rd_b", 0xa}, {"dvma_const_wr_b", 0xb},
{"dvma_stream_buf_mis_b", 0xc}, {"dvma_cycles_b", 0xd},
{"dvma_wd_xfr_b", 0xe}, {"pio_cycles_b", 0xf},
{"dvma_tlb_misses", 0x10}, {"interrupts", 0x11},
{"upa_inter_nack", 0x12}, {"pio_reads", 0x13},
{"pio_writes", 0x14}, {"merge_buffer", 0x15},
{"dma_tbwalk_a", 0x16}, {"dma_stc_a", 0x17},
{"dma_tbwalk_b", 0x18}, {"dma_stc_b", 0x19},
{"clear_pic", 0x1f}
};
/*
* Create the picN kstat's.
*/
void
{
if (pci_name_kstat == NULL) {
} else {
sizeof (psycho_pci_events) / sizeof (pci_kev_mask_t);
pci_create_name_kstat("pcip",
}
}
/*
* Called from _fini()
*/
void
{
if (pci_name_kstat != NULL) {
}
}
/* ARGSUSED */
void
{
}
/* ARGSUSED */
void
{
}
/*
* Create the performance 'counters' kstat.
*/
void
{
}
/*
* Extract the drivers binding name to identify which chip
* we're binding to. Whenever a new bus bridge is created, the driver alias
* entry should be added here to identify the device if needed. If a device
* isn't added, the identity defaults to PCI_CHIP_UNIDENTIFIED.
*/
static uint32_t
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
int
{
return (DDI_SUCCESS);
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*
* pcipsy error handling 101:
*
* The various functions below are responsible for error handling. Given
* a particular error, they must gather the appropriate state, report all
* errors with correct payload, and attempt recovery where ever possible.
*
* Recovery in the context of this driver is being able notify a leaf device
* of the failed transaction. This leaf device may either be the master or
* target for this transaction and may have already received an error
* notification via a PCI interrupt. Notification is done via DMA and access
* handles. If we capture an address for the transaction then we can map it
* to a handle(if the leaf device is fma-compliant) and fault the handle as
* well as call the device driver registered callback.
*
* The hardware can either interrupt or trap upon detection of an error, in
* some rare cases it also causes a fatal reset.
*
* pbm_error_intr() and ecc_intr() are responsible for PCI Block Module
* errors(generic PCI + bridge specific) and ECC errors, respectively. They
* are common between pcisch and pcipsy and therefore exist in pci_pbm.c and
* pci_ecc.c. To support error handling certain chip specific handlers
* must exist and they are defined below.
*
* cpu_deferred_error() and cpu_async_error(), handle the traps that may
* have originated from IO space. They call into the registered IO callbacks
* to report and handle errors that may have caused the trap.
*
* pci_pbm_err_handler() is called by pbm_error_intr() or pci_err_callback()
* related errors which are detected by the chip.
*
* pci_pbm_err_handler() calls a generic interface pbm_afsr_report()(pci_pbm.c)
* to report the pbm specific errors and attempt to map the failed address
* (if captured) to a device instance. pbm_afsr_report() calls a chip specific
*
* ecc_err_handler()(pci_ecc.c) also calls a chip specific interface to
* interpret the afsr, pci_ecc_classify(). ecc_err_handler() also calls
* pci_pbm_err_handler() and ndi_fm_handler_dispatch() to log any related
* errors.
*
* To make sure that the trap code and the interrupt code are not going
* to step on each others toes we have a per chip pci_fm_mutex. This also
* makes it necessary for us to be cautious while we are at a high PIL, so
* that we do not cause a subsequent trap that causes us to hang.
*
* The attempt to commonize code was meant to keep in line with the current
* pci driver implementation and it was not meant to confuse. If you are
* confused then don't worry, I was too.
*/
/*
* For Psycho, a UE is always fatal, except if it is a translation error on a
* Darwin platform. We ignore these because they do not cause data corruption.
*/
int
{
SABRE_UE_AFSR_E_PDTE) == 0);
}
/*
* pci_ecc_classify, called by ecc_handler to classify ecc errors
* and determine if we should panic or not.
*
* Note that it is possible yet extremely rare for more than one
* primary error bit to be set. We classify the ecc error based
* on the first set bit that is found.
*/
void
{
/*
* Get the parent bus id that caused the error.
*/
/*
* Determine the doubleword offset of the error.
*/
/*
* Determine the primary error type.
*/
if (err & COMMON_ECC_UE_AFSR_E_PIO) {
} else {
}
} else {
return;
}
} else if (err & COMMON_ECC_UE_AFSR_E_DRD) {
} else {
}
} else {
return;
}
} else if (err & COMMON_ECC_UE_AFSR_E_DWR) {
} else {
}
} else {
return;
}
}
}
{
}
/*
* pci_pbm_classify, called by pbm_afsr_report to classify piow afsr.
*/
int
{
uint32_t e;
int nerr = 0;
char **tmp_class;
} else {
}
if (e & PSYCHO_PCI_AFSR_E_MA) {
nerr++;
}
if (e & PSYCHO_PCI_AFSR_E_TA) {
nerr++;
}
if (e & PSYCHO_PCI_AFSR_E_RTRY) {
nerr++;
}
if (e & PSYCHO_PCI_AFSR_E_PERR) {
nerr++;
}
return (nerr);
}
/*
* is complete. Only clearing error bits which have been logged. Called by
* pci_pbm_err_handler and pci_bus_exit.
*/
static void
{
}
/*ARGSUSED*/
int
{
int fatal = 0;
int nonfatal = 0;
int unknown = 0;
char buf[FM_MAX_CLASS];
int ret = 0;
if (caller == PCI_TRAP_CALL) {
/*
* For ddi_caut_get treat all events as
* nonfatal. The trampoline will set
* err_ena = 0, err_status = NONFATAL. We only
* really call this function so that pci_clear_error()
* and ndi_fm_handler_dispatch() will get called.
*/
nonfatal++;
goto done;
} else {
/*
* For ddi_caut_put treat all events as nonfatal. Here
* we have the handle and can call ndi_fm_acc_err_set().
*/
nonfatal++;
goto done;
}
/*
* For ddi_peek treat all events as nonfatal. We only
* really call this function so that pci_clear_error()
* and ndi_fm_handler_dispatch() will get called.
*/
nonfatal++;
goto done;
/*
* For ddi_poke we can treat as nonfatal if the
* following conditions are met :
* 2. Make sure no secondary error
* since it gets much more complicated when a
* PCI-to-PCI bridge is present.
*/
nonfatal++;
goto done;
}
nonfatal++;
goto done;
}
}
if (ret == DDI_FM_FATAL)
fatal++;
else
nonfatal++;
}
if (ret == DDI_FM_FATAL)
fatal++;
else if (ret == DDI_FM_NONFATAL)
nonfatal++;
/*
* PBM Received System Error - During any transaction, or
* at any point on the bus, some device may detect a critical
* error and signal a system error to the system.
*/
if (pbm_ctl_stat & COMMON_PCI_CTRL_SERR) {
/*
* may be expected (master abort from pci-pci bridge during
* poke will generate SERR)
*/
}
unknown++;
}
/* Streaming Byte Hole Error */
if (pbm_ctl_stat & COMMON_PCI_CTRL_SBH_ERR) {
fatal++;
else
nonfatal++;
}
done:
if (ret == DDI_FM_FATAL) {
fatal++;
} else if (ret == DDI_FM_NONFATAL) {
nonfatal++;
} else if (ret == DDI_FM_UNKNOWN) {
unknown++;
}
/*
* rserr not claimed as nonfatal by a child is treated as fatal
*/
fatal++;
/* Cleanup and reset error bits */
}
int
{
PCI_STAT_S_SYSERR | PCI_STAT_PERROR)) ||
COMMON_PCI_CTRL_SERR)) ||
return (1);
return (0);
}
/*
* pci_pbm_err_handler. This function must be called while pci_fm_mutex
* is held.
*/
static void
{
/*
* Capture all pbm error state for later logging
*/
}
void
{
/*
* for poke() support - called from POKE_FLUSH. Spin waiting
* for MA, TA or SERR to be cleared by a pbm_error_intr().
* We have to wait for SERR too in case the device is beyond
* a pci-pci bridge.
*/
while (((pbm_afsr >> PSYCHO_PCI_AFSR_PE_SHIFT) &
(pbm_ctl_stat & COMMON_PCI_CTRL_SERR)) {
}
}
/*ARGSUSED*/
void
{
/*
* For Psycho the full address is stored in hardware. So
* there is no need to format it.
*/
}
/*ARGSUSED*/
int
{
return (DDI_FAILURE);
}
/*ARGSUSED*/
int
{
return (DDI_FAILURE);
}
void
{
}
/*
* NOTE: This call is only used by legacy systems (eg. E250 and E450) that
* require unregistering the pci driver's thermal intrerrupt handler before
* they can register their own.
*/
void
{
int instance;
break;
}
if (!pdip) {
return;
}
/* Calculate the requesting device's mondo */
/* get pci's thermal mondo */
}
}