pcicmu.c revision a54f81fbf66e3e4c14a94d571c0fe241e4cf2394
/*
* 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"
/*
* OPL CMU-CH PCI nexus driver.
*
*/
#include <sys/sysmacros.h>
#include <sys/machsystm.h>
#include <sys/ddi_impldefs.h>
#include <sys/ddi_subrdefs.h>
/*
* The variable controls the default setting of the command register
* for pci devices. See pcmu_init_child() for details.
*
* This flags also controls the setting of bits in the bridge control
* register pci to pci bridges. See pcmu_init_child() for details.
*/
/*
* The following driver parameters are defined as variables to allow
* patching for debugging and tuning. Flags that can be set on a per
* PBM basis are bit fields where the PBM device instance number maps
* to the bit position.
*/
#ifdef DEBUG
uint64_t pcmu_debug_flags = 0;
#endif
/*
* The following value is the number of consecutive unclaimed interrupts that
* will be tolerated for a particular ino_p before the interrupt is deemed to
* be jabbering and is blocked.
*/
/*
* function prototypes for dev ops routines:
*/
void *result);
static void unmap_pcmu_registers(pcmu_t *);
static void pcmu_pbm_clear_error(pcmu_pbm_t *);
void *, void *);
ddi_intr_handle_impl_t *, void *);
static void u2u_ittrans_resume(u2u_ittrans_data_t **);
static void u2u_ittrans_uninit(u2u_ittrans_data_t *);
static pcmu_ksinfo_t *pcmu_name_kstat;
/*
* bus ops and dev ops structures:
*/
static struct bus_ops pcmu_bus_ops = {
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
ndi_busop_get_eventcookie, /* (*bus_get_eventcookie)(); */
ndi_busop_add_eventcall, /* (*bus_add_eventcall)(); */
ndi_busop_remove_eventcall, /* (*bus_remove_eventcall)(); */
ndi_post_event, /* (*bus_post_event)(); */
NULL, /* (*bus_intr_ctl)(); */
NULL, /* (*bus_config)(); */
NULL, /* (*bus_unconfig)(); */
NULL, /* (*bus_fm_init)(); */
NULL, /* (*bus_fm_fini)(); */
NULL, /* (*bus_fm_access_enter)(); */
NULL, /* (*bus_fm_access_fini)(); */
NULL, /* (*bus_power)(); */
pcmu_intr_ops /* (*bus_intr_op)(); */
};
struct cb_ops pcmu_cb_ops = {
pcmu_open, /* open */
pcmu_close, /* close */
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
pcmu_ioctl, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
pcmu_prop_op, /* cb_prop_op */
NULL, /* streamtab */
CB_REV, /* rev */
nodev, /* int (*cb_aread)() */
nodev /* int (*cb_awrite)() */
};
0,
0,
0
};
/*
* module definitions:
*/
extern struct mod_ops mod_driverops;
&mod_driverops, /* Type of module - driver */
"OPL CMU-CH PCI Nexus driver %I%", /* Name of module. */
&pcmu_ops, /* driver ops */
};
static struct modlinkage modlinkage = {
};
/*
* driver global data:
*/
void *per_pcmu_state; /* per-pbm soft state pointer */
int
_init(void)
{
int e;
/*
* Initialize per-pci bus soft state pointer.
*/
if (e != 0)
return (e);
/*
* Initialize global mutexes.
*/
/*
* Create the performance kstats.
*/
/*
* Install the module.
*/
e = mod_install(&modlinkage);
if (e != 0) {
}
return (e);
}
int
_fini(void)
{
int e;
/*
* Remove the module.
*/
e = mod_remove(&modlinkage);
if (e != 0) {
return (e);
}
/*
* Destroy pcmu_ecc_queue, and set it to NULL.
*/
if (pcmu_ecc_queue) {
}
/*
* Destroy the performance kstats.
*/
/*
* Free the per-pci and per-CMU-CH soft state info and destroy
* mutex for per-CMU-CH soft state.
*/
return (e);
}
int
{
}
/*ARGSUSED*/
static int
{
switch (infocmd) {
case DDI_INFO_DEVT2INSTANCE:
return (DDI_SUCCESS);
case DDI_INFO_DEVT2DEVINFO:
return (DDI_FAILURE);
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
/* device driver entry points */
/*
* attach entry point:
*/
static int
{
switch (cmd) {
case DDI_ATTACH:
/*
* Allocate and get the per-pci soft state structure.
*/
goto err_bad_pcmu_softstate;
}
pcmu_p->pcmu_open_count = 0;
/*
* Get key properties of the pci bridge node.
*/
goto err_bad_pcmu_prop;
}
/*
* Map in the registers.
*/
goto err_bad_reg_prop;
}
goto err_bad_objs;
}
DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
goto err_bad_devctl_node;
}
/*
* Due to unresolved hardware issues, disable PCIPM until
* the problem is fully understood.
*
* pcmu_pwr_setup(pcmu_p, dip);
*/
break;
return (DDI_FAILURE);
case DDI_RESUME:
/*
* Make sure the CMU-CH control registers
* are configured properly.
*/
/*
* Make sure this instance has been suspended.
*/
"instance NOT suspended\n");
return (DDI_FAILURE);
}
break;
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* detach entry point:
*/
static int
{
int len;
/*
* Make sure we are currently attached
*/
"failed - instance not attached\n");
return (DDI_FAILURE);
}
switch (cmd) {
case DDI_DETACH:
/*
* Free the pci soft state structure and the rest of the
* resources it's using.
*/
/* Free the interrupt-priorities prop if we created it. */
"interrupt-priorities");
}
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
/*LINTLIBRARY*/
/* ARGSUSED3 */
static int
{
return (EINVAL);
}
/*
* Get the soft state structure for the device.
*/
return (ENXIO);
}
/*
* Handle the open by tracking the device state.
*/
return (EBUSY);
}
} else {
return (EBUSY);
}
}
return (0);
}
/* ARGSUSED */
static int
{
return (EINVAL);
}
return (ENXIO);
}
pcmu_p->pcmu_open_count = 0;
return (0);
}
/* ARGSUSED */
static int
{
struct devctl_iocdata *dcp;
int rv = 0;
return (ENXIO);
}
/*
* We can use the generic implementation for these ioctls
*/
switch (cmd) {
case DEVCTL_DEVICE_GETSTATE:
case DEVCTL_DEVICE_ONLINE:
case DEVCTL_DEVICE_OFFLINE:
case DEVCTL_BUS_GETSTATE:
}
/*
* read devctl ioctl data
*/
return (EFAULT);
switch (cmd) {
case DEVCTL_DEVICE_RESET:
break;
case DEVCTL_BUS_QUIESCE:
if (bus_state == BUS_QUIESCED) {
break;
}
}
break;
case DEVCTL_BUS_UNQUIESCE:
if (bus_state == BUS_ACTIVE) {
break;
}
}
break;
case DEVCTL_BUS_RESET:
break;
case DEVCTL_BUS_RESETALL:
break;
default:
}
return (rv);
}
{
}
/* bus driver entry points */
/*
* bus map entry point:
*
* if map request is for an rnumber
* get the corresponding regspec from device node
* build a new regspec in our parent's format
* build a new map_req with the new regspec
* call up the tree to complete the mapping
*/
static int
{
return (DDI_ME_UNIMPLEMENTED);
}
case DDI_MT_REGSPEC:
break;
case DDI_MT_RNUMBER:
return (DDI_ME_RNUMBER_RANGE);
}
return (DDI_ME_RNUMBER_RANGE);
}
break;
default:
return (DDI_ME_INVAL);
}
/* use "assigned-addresses" to relocate regspec within pci space */
goto done;
}
/* adjust regspec according to mapping request */
if (len) {
}
/* use "ranges" to translate relocated pci regspec into parent space */
goto done;
}
done:
}
return (rval);
}
#ifdef DEBUG
int pcmu_peekfault_cnt = 0;
int pcmu_pokefault_cnt = 0;
#endif /* DEBUG */
static int
{
int err = DDI_SUCCESS;
/* Set up protected environment. */
} else {
err = DDI_FAILURE;
}
/*
* Read the async fault register for the PBM to see it sees
* a master-abort.
*/
err = DDI_FAILURE;
}
/* Take down protected environment. */
no_trap();
#ifdef DEBUG
if (err == DDI_FAILURE)
#endif
return (err);
}
static int
{
}
/* ARGSUSED */
static int
{
int err = DDI_SUCCESS;
} else
err = DDI_FAILURE;
no_trap();
#ifdef DEBUG
if (err == DDI_FAILURE)
#endif
return (err);
}
static int
{
}
/*
* control ops entry point:
*
* Requests handled completely:
* DDI_CTLOPS_INITCHILD see pcmu_init_child() for details
* DDI_CTLOPS_UNINITCHILD
* DDI_CTLOPS_REPORTDEV see report_dev() for details
* DDI_CTLOPS_XLATE_INTRS nothing to do
* DDI_CTLOPS_IOMIN cache line size if streaming otherwise 1
* DDI_CTLOPS_REGSIZE
* DDI_CTLOPS_NREGS
* DDI_CTLOPS_NINTRS
* DDI_CTLOPS_DVMAPAGESIZE
* DDI_CTLOPS_POKE
* DDI_CTLOPS_PEEK
* DDI_CTLOPS_QUIESCE
* DDI_CTLOPS_UNQUIESCE
*
* All others passed to parent.
*/
static int
{
switch (op) {
case DDI_CTLOPS_INITCHILD:
case DDI_CTLOPS_UNINITCHILD:
case DDI_CTLOPS_REPORTDEV:
return (pcmu_report_dev(rdip));
case DDI_CTLOPS_IOMIN:
/*
* If we are using the streaming cache, align at
* least on a cache line boundary. Otherwise use
* whatever alignment is passed in.
*/
return (DDI_SUCCESS);
case DDI_CTLOPS_REGSIZE:
return (DDI_SUCCESS);
case DDI_CTLOPS_NREGS:
return (DDI_SUCCESS);
case DDI_CTLOPS_DVMAPAGESIZE:
return (DDI_SUCCESS);
case DDI_CTLOPS_POKE:
case DDI_CTLOPS_PEEK:
result));
case DDI_CTLOPS_AFFINITY:
break;
case DDI_CTLOPS_QUIESCE:
return (DDI_FAILURE);
case DDI_CTLOPS_UNQUIESCE:
return (DDI_FAILURE);
default:
break;
}
/*
* Now pass the request up to our parent.
*/
"passing request to parent: rdip=%s%d\n",
}
/* ARGSUSED */
static int
{
int ret = DDI_SUCCESS;
switch (intr_op) {
case DDI_INTROP_GETCAP:
/* GetCap will always fail for all non PCI devices */
break;
case DDI_INTROP_SETCAP:
ret = DDI_ENOTSUP;
break;
case DDI_INTROP_ALLOC:
break;
case DDI_INTROP_FREE:
break;
case DDI_INTROP_GETPRI:
break;
case DDI_INTROP_SETPRI:
break;
case DDI_INTROP_ADDISR:
break;
case DDI_INTROP_REMISR:
break;
case DDI_INTROP_ENABLE:
break;
case DDI_INTROP_DISABLE:
break;
case DDI_INTROP_SETMASK:
break;
case DDI_INTROP_CLRMASK:
break;
case DDI_INTROP_GETPENDING:
break;
case DDI_INTROP_NINTRS:
case DDI_INTROP_NAVAIL:
break;
/* PCI nexus driver supports only fixed interrupts */
DDI_INTR_TYPE_FIXED : 0;
break;
default:
ret = DDI_ENOTSUP;
break;
}
return (ret);
}
/*
* CMU-CH specifics implementation:
* interrupt mapping register
* PBM configuration
* ECC and PBM error handling
*/
/* called by pcmu_attach() DDI_ATTACH to initialize pci objects */
static int
{
int ret;
DDI_PROP_DONTPASS, "module-revision#", 0);
goto done;
done:
if (ret != DDI_SUCCESS) {
ret);
}
return (ret);
}
/* called by pcmu_detach() DDI_DETACH to destroy pci objects */
static void
{
}
/* called by pcmu_attach() DDI_RESUME to (re)initialize pci objects */
static void
{
}
/* called by pcmu_detach() DDI_SUSPEND to suspend pci objects */
static void
{
}
static int
{
int i, no_of_intrs;
/*
* 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 = pcmu_ecc_register_intr(pcmu_p)) {
goto teardown;
}
if (i = pcmu_pbm_register_intr(pcbm_p)) {
goto teardown;
}
return (DDI_SUCCESS);
return (i);
}
/*
* pcmu_fix_ranges - fixes the config space entry of the "ranges"
* property on CMU-CH platforms
*/
void
{
int i;
for (i = 0; i < rng_entries; i++, rng_p++) {
}
}
/*
* map_pcmu_registers
*
* This function is called from the attach routine to map the registers
* accessed by this driver.
*
* used by: pcmu_attach()
*
* return value: DDI_FAILURE on failure
*/
static int
{
return (DDI_FAILURE);
}
/*
* We still use pcmu_address[2]
*/
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_pcmu_registers:
*
* This routine unmap the registers mapped by map_pcmu_registers.
*
* used by: pcmu_detach()
*
* return value: none
*/
static void
{
}
/*
* These convenience wrappers relies on map_pcmu_registers() to setup
* pcmu_address[0-2] correctly at first.
*/
static uintptr_t
{
}
/* The CMU-CH config reg base is always the 2nd reg entry */
static uintptr_t
{
}
{
}
{
return ((reg & PCMU_INTR_MAP_REG_TID) >>
}
uint64_t *
{
return (addr);
}
uint64_t *
{
return (addr);
}
{
return (a);
}
/*
* Return the cpuid to to be used for an ino.
*
* On multi-function pci devices, functions have separate devinfo nodes and
* interrupts.
*
* 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->pino_ih_head->ih_dip.
*/
{
int l2;
int cpu_id;
/* must be CMU-CH 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 CMU-CH driver parent (not ebus) */
continue;
extern int intr_dist_debug;
if (intr_dist_debug) {
"pcicmu`pcmu_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);
}
void
{
}
int
{
return (PCMU_ATTACH_RETCODE(PCMU_ECC_OBJ,
}
/* ARGSUSED */
void
{
}
void
{
/*
* Clear any PBM errors.
*/
/*
* Clear error bits in configuration status register.
*/
"pcmu_pbm_configure: conf status reg=%x\n", csr_err);
"pcmu_pbm_configure: conf status reg==%x\n",
}
{
/*
* Disable error and streaming byte hole interrupts via the
* PBM control register.
*/
/*
* Disable error interrupts via the interrupt mapping register.
*/
return (BF_NONE);
}
void
{
/*
* Clear any pending address parity errors.
*/
if (csr & PCMU_CB_CONTROL_STATUS_APERR) {
}
}
void
{
}
static uintptr_t
{
}
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 + PCMU_PCI_ASYNC_FLT_STATUS_REG_OFFSET);
(uint64_t *)(a + PCMU_PCI_ASYNC_FLT_ADDR_REG_OFFSET);
}
/*ARGSUSED*/
void
{
}
int
{
"#upa-interrupt-proxies", 1));
}
int
{
"portid", -1));
}
/*
* CMU-CH Performance Events.
*/
static pcmu_kev_mask_t
pcicmu_pcmu_events[] = {
{"pio_cycles_b", 0xf}, {"interrupts", 0x11},
{"upa_inter_nack", 0x12}, {"pio_reads", 0x13},
{"pio_writes", 0x14},
{"clear_pic", 0x1f}
};
/*
* Create the picN kstat's.
*/
void
{
if (pcmu_name_kstat == NULL) {
} else {
sizeof (pcicmu_pcmu_events) / sizeof (pcmu_kev_mask_t);
pcmu_create_name_kstat("pcmup",
}
}
/*
* Called from _fini()
*/
void
{
if (pcmu_name_kstat != NULL) {
}
}
/*
* Create the performance 'counters' kstat.
*/
void
{
}
/*
* u2u_ittrans_init() is caled from in pci.c's pcmu_cb_setup() per CMU.
* Second argument "ittrans_cookie" is address of pcb_ittrans_cookie in
* pcb_p member. allocated interrupt block is returned in it.
*/
static void
{
int ret;
int board;
/*
* Allocate the data structure to support U2U's
* interrupt target translations.
*/
/*
* Get other properties, "board#"
*/
if (board == -1) {
/* this cannot happen on production systems */
}
/*
* Initialize interrupt target translations mutex.
*/
/*
* Get U2U's registers space by ddi_regs_map_setup(9F)
*/
/*
* check result of ddi_regs_map_setup().
*/
if (ret != DDI_SUCCESS) {
}
/*
* Read Port-id(1 byte) in u2u
*/
}
}
/*
* u2u_ittras_resume() is called from pcmu_obj_resume() at DDI_RESUME entry.
*/
static void
{
int ix;
/*
* Set U2U Data Register
*/
/* This index was not set */
continue;
}
*(volatile uint32_t *) (data_reg_addr) =
}
}
/*
* u2u_ittras_uninit() is called from ib_destroy() at detach,
* or occuring error in attach.
*/
static void
{
if (ittrans_cookie == NULL) {
return; /* not support */
}
return; /* illeagal case */
}
}
/*
* This routine,u2u_translate_tgtid(, , cpu_id, pino_map_reg),
* searches index having same value of pino_map_reg, or empty.
* Then, stores cpu_id in a U2U Data Register as this index,
* and return this index.
*/
int
volatile uint64_t *pino_map_reg)
{
int index = -1;
int ix;
int err_level; /* severity level for cmn_err */
if (ittrans_cookie == NULL) {
return (cpu_id);
}
return (-1); /* illeagal case */
}
/*
* Decide index No. of U2U Data registers in either
* already used by same pino_map_reg, or empty.
*/
/* already used this pino_map_reg */
break;
}
if (index == -1 &&
}
}
if (index == -1) {
if (panicstr) {
} else {
}
return (cpu_id);
}
/*
* For U2U
* set cpu_id into u2u_data_reg by index.
* ((uint64_t)(u2u_regs_base
* + U2U_DATA_REGISTER_OFFSET))[index] = cpu_id;
*/
/*
* Set cpu_id into U2U Data register[index]
*/
/*
* Setup for software, excepting at panicing.
* and rebooting, etc...?
*/
if (!panicstr) {
}
return (index);
}
/*
* u2u_ittrans_cleanup() is called from common_pcmu_ib_intr_disable()
* after called intr_rem_cpu(mondo).
*/
void
volatile uint64_t *pino_map_reg)
{
int ix;
if (ittrans_cookie == NULL) {
return;
}
return; /* illeagal case */
}
break;
}
}
}
/*
* pcmu_ecc_classify, called by ecc_handler to classify ecc errors
* and determine if we should panic or not.
*/
void
{
/* LINTED */
/*
* Get the parent bus id that caused the error.
*/
/*
* Determine the doubleword offset of the error.
*/
/*
* Determine the primary error type.
*/
switch (err) {
case PCMU_ECC_UE_AFSR_E_PIO:
} else {
}
/* For CMU-CH, a UE is always fatal. */
break;
default:
return;
}
}
/*
* pcmu_pbm_classify, called by pcmu_pbm_afsr_report to classify piow afsr.
*/
int
{
uint32_t e;
int nerr = 0;
char **tmp_class;
} else {
}
if (e & PCMU_PCI_AFSR_E_MA) {
nerr++;
}
return (nerr);
}
/*
* is complete. Only clearing error bits which have been logged. Called by
* pcmu_pbm_err_handler and pcmu_bus_exit.
*/
static void
{
}
/*ARGSUSED*/
int
{
int fatal = 0;
int nonfatal = 0;
int unknown = 0;
int ret = 0;
/*
* For ddi_peek treat all events as nonfatal. We only
* really call this function so that pcmu_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;
}
}
if (ret == DDI_FM_FATAL) {
fatal++;
} else {
nonfatal++;
}
}
if (ret == DDI_FM_FATAL) {
fatal++;
} else if (ret == DDI_FM_NONFATAL) {
nonfatal++;
}
done:
if (ret == DDI_FM_FATAL) {
fatal++;
} else if (ret == DDI_FM_NONFATAL) {
nonfatal++;
} else if (ret == DDI_FM_UNKNOWN) {
unknown++;
}
/* Cleanup and reset error bits */
}
int
{
PCI_STAT_S_SYSERR | PCI_STAT_PERROR)) ||
(PBM_AFSR_TO_PRIERR(pbm_afsr))) {
return (1);
}
return (0);
}
/*
* pcmu_pbm_err_handler. This function must be called while pcmu_err_mutex
* is held.
*/
static void
{
/*
* Capture all pbm error state for later logging
*/
}
static void
{
/*
* for poke() support - called from POKE_FLUSH. Spin waiting
* for MA, TA or SERR to be cleared by a pcmu_pbm_error_intr().
* We have to wait for SERR too in case the device is beyond
* a pci-pci bridge.
*/
while (((pbm_afsr >> PCMU_PCI_AFSR_PE_SHIFT) &
(PCMU_PCI_AFSR_E_MA | PCMU_PCI_AFSR_E_TA))) {
}
}
void
{
/*
* PCI detected ECC errorq, to schedule async handling
* of ECC errors and logging.
* The errorq is created here but destroyed when _fini is called
* for the pci module.
*/
if (pcmu_ecc_queue == NULL) {
(void *)NULL,
ECC_MAX_ERRS, sizeof (pcmu_ecc_errstate_t),
if (pcmu_ecc_queue == NULL)
panic("failed to create required system error queue");
}
/*
* Initialize error handling mutex.
*/
(void *)pcmu_p->pcmu_fm_ibc);
}
void
{
}
/*
* Function used to post PCI block module specific ereports.
*/
void
{
char *aux_msg;
if (prierr)
aux_msg = "PCI primary error: Master Abort";
else if (secerr)
aux_msg = "PCI secondary error: Master Abort";
else
aux_msg = "";
}