25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER START
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * or http://www.opensolaris.org/os/licensing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * See the License for the specific language governing permissions
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and limitations under the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When distributing Covered Code, include this CDDL HEADER in each
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If applicable, add the following below this CDDL HEADER, with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fields enclosed by brackets "[]" replaced with your own identifying
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information: Portions Copyright [yyyy] [name of copyright owner]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER END
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
193974072f41a843678abf5f61979c748687e66bSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Use is subject to license terms.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * OPL CMU-CH PCI nexus driver.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/types.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sysmacros.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/systm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/intreg.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/intr.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/machsystm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/conf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/stat.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/kmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/async.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ivintr.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunddi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunndi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ndifm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ontrap.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi_impldefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi_subrdefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/epm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/spl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fm/util.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fm/util.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fm/protocol.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fm/io/pci.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fm/io/sun4upci.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/pcicmu/pcicmu.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cmn_err.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/time.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/pci.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/modctl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/open.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/errno.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/file.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint32_t pcmu_spurintr_duration = 60000000; /* One minute */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The variable controls the default setting of the command register
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for pci devices. See pcmu_init_child() for details.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This flags also controls the setting of bits in the bridge control
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * register pci to pci bridges. See pcmu_init_child() for details.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlushort_t pcmu_command_default = PCI_COMM_SERR_ENABLE |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_COMM_WAIT_CYC_ENAB |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_COMM_PARITY_DETECT |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_COMM_ME |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_COMM_MAE |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_COMM_IO;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The following driver parameters are defined as variables to allow
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * patching for debugging and tuning. Flags that can be set on a per
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * PBM basis are bit fields where the PBM device instance number maps
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to the bit position.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint64_t pcmu_debug_flags = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t ecc_error_intr_enable = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t pcmu_ecc_afsr_retries = 100; /* XXX - what's a good value? */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t pcmu_intr_retry_intv = 5; /* for interrupt retry reg */
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t pcmu_panic_on_fatal_errors = 1; /* should be 1 at beta */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlhrtime_t pcmu_intrpend_timeout = 5ll * NANOSEC; /* 5 seconds in nanoseconds */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint64_t pcmu_errtrig_pa = 0x0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The following value is the number of consecutive unclaimed interrupts that
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * will be tolerated for a particular ino_p before the interrupt is deemed to
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * be jabbering and is blocked.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t pcmu_unclaimed_intr_max = 20;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * function prototypes for dev ops routines:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *arg, void **result);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_open(dev_t *devp, int flags, int otyp, cred_t *credp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_close(dev_t dev, int flags, int otyp, cred_t *credp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cred_t *credp, int *rvalp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int flags, char *name, caddr_t valuep, int *lengthp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_ctlops_poke(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_ctlops_peek(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *result);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int map_pcmu_registers(pcmu_t *, dev_info_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void unmap_pcmu_registers(pcmu_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void pcmu_pbm_clear_error(pcmu_pbm_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *, void *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl off_t, off_t, caddr_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_intr_handle_impl_t *, void *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic uint32_t pcmu_identity_init(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_intr_setup(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void pcmu_pbm_errstate_get(pcmu_t *pcmu_p,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_errstate_t *pbm_err_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_obj_setup(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void pcmu_obj_destroy(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void pcmu_obj_resume(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void pcmu_obj_suspend(pcmu_t *pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void u2u_ittrans_init(pcmu_t *, u2u_ittrans_data_t **);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void u2u_ittrans_resume(u2u_ittrans_data_t **);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void u2u_ittrans_uninit(u2u_ittrans_data_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pcmu_ksinfo_t *pcmu_name_kstat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bus ops and dev ops structures:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct bus_ops pcmu_bus_ops = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl BUSO_REV,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_map,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i_ddi_map_fault,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ctlops,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_bus_prop_op,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_busop_get_eventcookie, /* (*bus_get_eventcookie)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_busop_add_eventcall, /* (*bus_add_eventcall)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_busop_remove_eventcall, /* (*bus_remove_eventcall)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_post_event, /* (*bus_post_event)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_intr_ctl)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_config)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_unconfig)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_fm_init)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_fm_fini)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_fm_access_enter)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_fm_access_fini)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* (*bus_power)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_intr_ops /* (*bus_intr_op)(); */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct cb_ops pcmu_cb_ops = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_open, /* open */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_close, /* close */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* strategy */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* print */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* dump */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* read */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* write */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ioctl, /* ioctl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* devmap */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* mmap */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* segmap */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nochpoll, /* poll */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_prop_op, /* cb_prop_op */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, /* streamtab */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl CB_REV, /* rev */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev, /* int (*cb_aread)() */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev /* int (*cb_awrite)() */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct dev_ops pcmu_ops = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DEVO_REV,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_info,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nulldev,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_attach,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_detach,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nodev,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &pcmu_cb_ops,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &pcmu_bus_ops,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
193974072f41a843678abf5f61979c748687e66bSherry Moore
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * module definitions:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern struct mod_ops mod_driverops;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modldrv modldrv = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &mod_driverops, /* Type of module - driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "OPL CMU-CH PCI Nexus driver", /* Name of module. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &pcmu_ops, /* driver ops */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modlinkage modlinkage = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl MODREV_1, (void *)&modldrv, NULL
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * driver global data:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid *per_pcmu_state; /* per-pbm soft state pointer */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlkmutex_t pcmu_global_mutex; /* attach/detach common struct lock */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerrorq_t *pcmu_ecc_queue = NULL; /* per-system ecc handling queue */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern void pcmu_child_cfg_save(dev_info_t *dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern void pcmu_child_cfg_restore(dev_info_t *dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_init(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int e;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize per-pci bus soft state pointer.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e = ddi_soft_state_init(&per_pcmu_state, sizeof (pcmu_t), 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (e);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize global mutexes.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&pcmu_global_mutex, NULL, MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create the performance kstats.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_kstat_init();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Install the module.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e = mod_install(&modlinkage);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_soft_state_fini(&per_pcmu_state);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (e);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_fini(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int e;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Remove the module.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e = mod_remove(&modlinkage);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (e);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Destroy pcmu_ecc_queue, and set it to NULL.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_ecc_queue) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl errorq_destroy(pcmu_ecc_queue);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_queue = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Destroy the performance kstats.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_kstat_fini();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Free the per-pci and per-CMU-CH soft state info and destroy
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * mutex for per-CMU-CH soft state.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_soft_state_fini(&per_pcmu_state);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (e);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_info(struct modinfo *modinfop)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (mod_info(&modlinkage, modinfop));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int instance = getminor((dev_t)arg) >> 8;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = get_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (infocmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INFO_DEVT2INSTANCE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *result = (void *)(uintptr_t)instance;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INFO_DEVT2DEVINFO:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *result = (void *)pcmu_p->pcmu_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* device driver entry points */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * attach entry point:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int instance = ddi_get_instance(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_ATTACH:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip, "DDI_ATTACH\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Allocate and get the per-pci soft state structure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (alloc_pcmu_soft_state(instance) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s%d: can't allocate pci state",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(dip), instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto err_bad_pcmu_softstate;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = get_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_dip = dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&pcmu_p->pcmu_mutex, NULL, MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_soft_state = PCMU_SOFT_STATE_CLOSED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_open_count = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get key properties of the pci bridge node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (get_pcmu_properties(pcmu_p, dip) == DDI_FAILURE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto err_bad_pcmu_prop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Map in the registers.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (map_pcmu_registers(pcmu_p, dip) == DDI_FAILURE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto err_bad_reg_prop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_obj_setup(pcmu_p) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto err_bad_objs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (uint_t)instance<<8 | 0xff,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto err_bad_devctl_node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Due to unresolved hardware issues, disable PCIPM until
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the problem is fully understood.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_pwr_setup(pcmu_p, dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_report_dev(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_state = PCMU_ATTACHED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip, "attach success\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerr_bad_objs:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_remove_minor_node(dip, "devctl");
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerr_bad_devctl_node:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl unmap_pcmu_registers(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerr_bad_reg_prop:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl free_pcmu_properties(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerr_bad_pcmu_prop:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl free_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerr_bad_pcmu_softstate:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_RESUME:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip, "DDI_RESUME\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Make sure the CMU-CH control registers
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * are configured properly.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = get_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Make sure this instance has been suspended.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p->pcmu_state != PCMU_SUSPENDED) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "instance NOT suspended\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_obj_resume(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_state = PCMU_ATTACHED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_child_cfg_restore(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip, "unsupported attach op\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * detach entry point:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int instance = ddi_get_instance(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = get_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Make sure we are currently attached
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p->pcmu_state != PCMU_ATTACHED) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_ATTACH, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "failed - instance not attached\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_DETACH:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_DETACH, dip, "DDI_DETACH\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_obj_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Free the pci soft state structure and the rest of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * resources it's using.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl free_pcmu_properties(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl unmap_pcmu_registers(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl free_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Free the interrupt-priorities prop if we created it. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getproplen(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "interrupt-priorities", &len) == DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "interrupt-priorities");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_SUSPEND:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_child_cfg_save(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_obj_suspend(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_state = PCMU_SUSPENDED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_DETACH, dip, "unsupported detach op\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED3 */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_open(dev_t *devp, int flags, int otyp, cred_t *credp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (otyp != OTYP_CHR) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EINVAL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the soft state structure for the device.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = DEV_TO_SOFTSTATE(*devp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ENXIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Handle the open by tracking the device state.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_OPEN, pcmu_p->pcmu_dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "devp=%x: flags=%x\n", devp, flags);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (flags & FEXCL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p->pcmu_soft_state != PCMU_SOFT_STATE_CLOSED) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_OPEN, pcmu_p->pcmu_dip, "busy\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EBUSY);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_soft_state = PCMU_SOFT_STATE_OPEN_EXCL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p->pcmu_soft_state == PCMU_SOFT_STATE_OPEN_EXCL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_OPEN, pcmu_p->pcmu_dip, "busy\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EBUSY);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_soft_state = PCMU_SOFT_STATE_OPEN;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_open_count++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_close(dev_t dev, int flags, int otyp, cred_t *credp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (otyp != OTYP_CHR) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EINVAL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = DEV_TO_SOFTSTATE(dev);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ENXIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_CLOSE, pcmu_p->pcmu_dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "dev=%x: flags=%x\n", dev, flags);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_soft_state = PCMU_SOFT_STATE_CLOSED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_open_count = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_p->pcmu_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cred_t *credp, int *rvalp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct devctl_iocdata *dcp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint_t bus_state;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = DEV_TO_SOFTSTATE(dev);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ENXIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = pcmu_p->pcmu_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_IOCTL, dip, "dev=%x: cmd=%x\n", dev, cmd);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We can use the generic implementation for these ioctls
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_DEVICE_GETSTATE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_DEVICE_ONLINE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_DEVICE_OFFLINE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_BUS_GETSTATE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ndi_devctl_ioctl(dip, cmd, arg, mode, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * read devctl ioctl data
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EFAULT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_DEVICE_RESET:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_IOCTL, dip, "DEVCTL_DEVICE_RESET\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = ENOTSUP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_BUS_QUIESCE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_IOCTL, dip, "DEVCTL_BUS_QUIESCE\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndi_get_bus_state(dip, &bus_state) == NDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bus_state == BUS_QUIESCED) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_set_bus_state(dip, BUS_QUIESCED);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_BUS_UNQUIESCE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_IOCTL, dip, "DEVCTL_BUS_UNQUIESCE\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndi_get_bus_state(dip, &bus_state) == NDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bus_state == BUS_ACTIVE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_set_bus_state(dip, BUS_ACTIVE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_BUS_RESET:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_IOCTL, dip, "DEVCTL_BUS_RESET\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = ENOTSUP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DEVCTL_BUS_RESETALL:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_IOCTL, dip, "DEVCTL_BUS_RESETALL\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = ENOTSUP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = ENOTTY;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_dc_freehdl(dcp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int pcmu_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int flags, char *name, caddr_t valuep, int *lengthp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* bus driver entry points */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bus map entry point:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * if map request is for an rnumber
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * get the corresponding regspec from device node
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * build a new regspec in our parent's format
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * build a new map_req with the new regspec
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * call up the tree to complete the mapping
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl off_t off, off_t len, caddr_t *addrp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = get_pcmu_soft_state(ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct regspec p_regspec;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_map_req_t p_mapreq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int reglen, rval, r_no;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pci_regspec_t reloc_reg, *rp = &reloc_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_MAP, dip, "rdip=%s%d:",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(rdip), ddi_get_instance(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mp->map_flags & DDI_MF_USER_MAPPING) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_ME_UNIMPLEMENTED);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (mp->map_type) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_MT_REGSPEC:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl reloc_reg = *(pci_regspec_t *)mp->map_obj.rp; /* dup whole */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_MT_RNUMBER:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl r_no = mp->map_obj.rnumber;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG1(PCMU_DBG_MAP | PCMU_DBG_CONT, dip, " r#=%x", r_no);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "reg", (caddr_t)&rp, &reglen) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_ME_RNUMBER_RANGE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (r_no < 0 || r_no >= reglen / sizeof (pci_regspec_t)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(rp, reglen);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_ME_RNUMBER_RANGE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp += r_no;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_ME_INVAL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG0(PCMU_DBG_MAP | PCMU_DBG_CONT, dip, "\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* use "assigned-addresses" to relocate regspec within pci space */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval = pcmu_reloc_reg(dip, rdip, pcmu_p, rp)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* adjust regspec according to mapping request */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (len) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->pci_size_low = (uint_t)len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->pci_phys_low += off;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* use "ranges" to translate relocated pci regspec into parent space */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval = pcmu_xlate_reg(pcmu_p, rp, &p_regspec)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p_mapreq = *mp; /* dup the whole structure */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p_mapreq.map_type = DDI_MT_REGSPEC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p_mapreq.map_obj.rp = &p_regspec;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ddi_map(dip, &p_mapreq, 0, 0, addrp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jldone:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mp->map_type == DDI_MT_RNUMBER) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(rp - r_no, reglen);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rval);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint pcmu_peekfault_cnt = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint pcmu_pokefault_cnt = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif /* DEBUG */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_do_poke(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err = DDI_SUCCESS;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl on_trap_data_t otd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcbm_p->pcbm_pokeflt_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_ontrap_data = &otd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set up protected environment. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!on_trap(&otd, OT_DATA_ACCESS)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t tramp = otd.ot_trampoline;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl otd.ot_trampoline = (uintptr_t)&poke_fault;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = do_poke(in_args->size, (void *)in_args->dev_addr,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void *)in_args->host_addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl otd.ot_trampoline = tramp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = DDI_FAILURE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Read the async fault register for the PBM to see it sees
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * a master-abort.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_clear_error(pcbm_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (otd.ot_trap & OT_DATA_ACCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = DDI_FAILURE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Take down protected environment. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_trap();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_ontrap_data = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcbm_p->pcbm_pokeflt_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err == DDI_FAILURE)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pokefault_cnt++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ctlops_poke(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_do_poke(pcmu_p, in_args));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_do_peek(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err = DDI_SUCCESS;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl on_trap_data_t otd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!on_trap(&otd, OT_DATA_ACCESS)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t tramp = otd.ot_trampoline;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl otd.ot_trampoline = (uintptr_t)&peek_fault;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = do_peek(in_args->size, (void *)in_args->dev_addr,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void *)in_args->host_addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl otd.ot_trampoline = tramp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = DDI_FAILURE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_trap();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err == DDI_FAILURE)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_peekfault_cnt++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ctlops_peek(pcmu_t *pcmu_p, peekpoke_ctlops_t *in_args, void *result)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl result = (void *)in_args->host_addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_do_peek(pcmu_p, in_args));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * control ops entry point:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Requests handled completely:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_INITCHILD see pcmu_init_child() for details
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_UNINITCHILD
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_REPORTDEV see report_dev() for details
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_XLATE_INTRS nothing to do
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_IOMIN cache line size if streaming otherwise 1
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_REGSIZE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_NREGS
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_NINTRS
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_DVMAPAGESIZE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_POKE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_PEEK
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_QUIESCE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DDI_CTLOPS_UNQUIESCE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * All others passed to parent.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ctlops(dev_info_t *dip, dev_info_t *rdip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_ctl_enum_t op, void *arg, void *result)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = get_pcmu_soft_state(ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (op) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_INITCHILD:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_init_child(pcmu_p, (dev_info_t *)arg));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_UNINITCHILD:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_uninit_child(pcmu_p, (dev_info_t *)arg));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_REPORTDEV:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_report_dev(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_IOMIN:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If we are using the streaming cache, align at
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * least on a cache line boundary. Otherwise use
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * whatever alignment is passed in.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_REGSIZE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *((off_t *)result) = pcmu_get_reg_set_size(rdip, *((int *)arg));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_NREGS:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *((uint_t *)result) = pcmu_get_nreg_set(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_DVMAPAGESIZE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *((ulong_t *)result) = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_POKE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_ctlops_poke(pcmu_p, (peekpoke_ctlops_t *)arg));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_PEEK:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (pcmu_ctlops_peek(pcmu_p, (peekpoke_ctlops_t *)arg,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl result));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_AFFINITY:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_QUIESCE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_CTLOPS_UNQUIESCE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Now pass the request up to our parent.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_CTLOPS, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "passing request to parent: rdip=%s%d\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(rdip), ddi_get_instance(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ddi_ctlops(dip, rdip, op, arg, result));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_intr_handle_impl_t *hdlp, void *result)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = get_pcmu_soft_state(ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret = DDI_SUCCESS;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (intr_op) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_GETCAP:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* GetCap will always fail for all non PCI devices */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) pci_intx_get_cap(rdip, (int *)result);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_SETCAP:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = DDI_ENOTSUP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_ALLOC:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(int *)result = hdlp->ih_scratch1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_FREE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_GETPRI:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(int *)result = hdlp->ih_pri ? hdlp->ih_pri : 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_SETPRI:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_ADDISR:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_add_intr(dip, rdip, hdlp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_REMISR:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_remove_intr(dip, rdip, hdlp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_ENABLE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_ib_update_intr_state(pcmu_p, rdip, hdlp,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_INTR_STATE_ENABLE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_DISABLE:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_ib_update_intr_state(pcmu_p, rdip, hdlp,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_INTR_STATE_DISABLE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_SETMASK:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pci_intx_set_mask(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_CLRMASK:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pci_intx_clr_mask(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_GETPENDING:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pci_intx_get_pending(rdip, (int *)result);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_NINTRS:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_NAVAIL:
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish *(int *)result = i_ddi_get_intx_nintrs(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case DDI_INTROP_SUPPORTED_TYPES:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* PCI nexus driver supports only fixed interrupts */
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish *(int *)result = i_ddi_get_intx_nintrs(rdip) ?
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_INTR_TYPE_FIXED : 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = DDI_ENOTSUP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CMU-CH specifics implementation:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interrupt mapping register
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * PBM configuration
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ECC and PBM error handling
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* called by pcmu_attach() DDI_ATTACH to initialize pci objects */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_obj_setup(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_rev = ddi_prop_get_int(DDI_DEV_T_ANY, pcmu_p->pcmu_dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "module-revision#", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_create(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_create(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_create(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_create(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_err_create(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((ret = pcmu_intr_setup(pcmu_p)) != DDI_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
c9b6d37c673213b7ad91d849a105790cb469f95bfherard /*
c9b6d37c673213b7ad91d849a105790cb469f95bfherard * Due to a hardware bug, do not create kstat for DC systems
c9b6d37c673213b7ad91d849a105790cb469f95bfherard * with PCI hw revision less than 5.
c9b6d37c673213b7ad91d849a105790cb469f95bfherard */
c9b6d37c673213b7ad91d849a105790cb469f95bfherard if ((strncmp(ddi_binding_name(pcmu_p->pcmu_dip),
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCICMU_OPL_DC_BINDING_NAME, strlen(PCICMU_OPL_DC_BINDING_NAME))
c9b6d37c673213b7ad91d849a105790cb469f95bfherard != 0) || (pcmu_p->pcmu_rev > 4)) {
c9b6d37c673213b7ad91d849a105790cb469f95bfherard pcmu_kstat_create(pcmu_p);
c9b6d37c673213b7ad91d849a105790cb469f95bfherard }
25cf1a301a396c38e8adf52c15f537b80d2483f7jldone:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_NOTE, "Interrupt register failure, returning 0x%x\n",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* called by pcmu_detach() DDI_DETACH to destroy pci objects */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_obj_destroy(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_kstat_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_err_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_destroy(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_intr_teardown(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* called by pcmu_attach() DDI_RESUME to (re)initialize pci objects */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_obj_resume(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_configure(pcmu_p->pcmu_ib_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_configure(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_resume(pcmu_p->pcmu_ib_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_resume((u2u_ittrans_data_t **)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &(pcmu_p->pcmu_cb_p->pcb_ittrans_cookie));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_configure(pcmu_p->pcmu_pcbm_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_resume(pcmu_p->pcmu_cb_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_resume(pcmu_p->pcmu_pcbm_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* called by pcmu_detach() DDI_SUSPEND to suspend pci objects */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_obj_suspend(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_suspend(pcmu_p->pcmu_pcbm_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_suspend(pcmu_p->pcmu_ib_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_suspend(pcmu_p->pcmu_cb_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&pcmu_global_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_intr_setup(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip = pcmu_p->pcmu_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_t *pcb_p = pcmu_p->pcmu_cb_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, no_of_intrs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the interrupts property.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "interrupts", (caddr_t)&pcmu_p->pcmu_inos,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &pcmu_p->pcmu_inos_len) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "%s%d: no interrupts property\n",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard ddi_driver_name(dip), ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * figure out number of interrupts in the "interrupts" property
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and convert them all into ino.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "#interrupt-cells", 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i = CELLS_1275_TO_BYTES(i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_of_intrs = pcmu_p->pcmu_inos_len / i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < no_of_intrs; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_inos[i] =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_IB_MONDO_TO_INO(pcmu_p->pcmu_inos[i]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_no_of_inos = no_of_intrs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (i = pcmu_ecc_register_intr(pcmu_p)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto teardown;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl intr_dist_add(pcmu_cb_intr_dist, pcb_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_enable_intr(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (i = pcmu_pbm_register_intr(pcbm_p)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl intr_dist_rem(pcmu_cb_intr_dist, pcb_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto teardown;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl intr_dist_add(pcmu_pbm_intr_dist, pcbm_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_intr_enable(pcmu_p, pcmu_p->pcmu_inos[CBNINTR_PBM]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl intr_dist_add_weighted(pcmu_ib_intr_dist_all, pcmu_p->pcmu_ib_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlteardown:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_intr_teardown(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_fix_ranges - fixes the config space entry of the "ranges"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * property on CMU-CH platforms
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_fix_ranges(pcmu_ranges_t *rng_p, int rng_entries)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < rng_entries; i++, rng_p++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((rng_p->child_high & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rng_p->parent_low |= rng_p->child_high;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * map_pcmu_registers
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This function is called from the attach routine to map the registers
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * accessed by this driver.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * used by: pcmu_attach()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * return value: DDI_FAILURE on failure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlmap_pcmu_registers(pcmu_t *pcmu_p, dev_info_t *dip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_device_acc_attr_t attr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_regs_map_setup(dip, 0, &pcmu_p->pcmu_address[0], 0, 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &attr, &pcmu_p->pcmu_ac[0]) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s%d: unable to map reg entry 0\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(dip), ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We still use pcmu_address[2]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_regs_map_setup(dip, 2, &pcmu_p->pcmu_address[2], 0, 0,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard &attr, &pcmu_p->pcmu_ac[2]) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s%d: unable to map reg entry 2\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(dip), ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&pcmu_p->pcmu_ac[0]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The second register set contains the bridge's configuration
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * header. This header is at the very beginning of the bridge's
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * configuration space. This space has litte-endian byte order.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_regs_map_setup(dip, 1, &pcmu_p->pcmu_address[1], 0,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_CONF_HDR_SIZE, &attr, &pcmu_p->pcmu_ac[1]) != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s%d: unable to map reg entry 1\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(dip), ddi_get_instance(dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&pcmu_p->pcmu_ac[0]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_FAILURE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG2(PCMU_DBG_ATTACH, dip, "address (%p,%p)\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_address[0], pcmu_p->pcmu_address[1]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_SUCCESS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * unmap_pcmu_registers:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This routine unmap the registers mapped by map_pcmu_registers.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * used by: pcmu_detach()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * return value: none
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlunmap_pcmu_registers(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&pcmu_p->pcmu_ac[0]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&pcmu_p->pcmu_ac[1]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&pcmu_p->pcmu_ac[2]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * These convenience wrappers relies on map_pcmu_registers() to setup
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_address[0-2] correctly at first.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic uintptr_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlget_reg_base(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((uintptr_t)pcmu_p->pcmu_address[2]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* The CMU-CH config reg base is always the 2nd reg entry */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic uintptr_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlget_config_reg_base(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((uintptr_t)(pcmu_p->pcmu_address[1]));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint64_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlib_get_map_reg(pcmu_ib_mondo_t mondo, uint32_t cpu_id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((mondo) | (cpu_id << PCMU_INTR_MAP_REG_TID_SHIFT) |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_INTR_MAP_REG_VALID);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint32_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlib_map_reg_get_cpu(volatile uint64_t reg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((reg & PCMU_INTR_MAP_REG_TID) >>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_INTR_MAP_REG_TID_SHIFT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint64_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jlib_intr_map_reg_addr(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t *addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(ino & 0x20);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl addr = (uint64_t *)(pib_p->pib_obio_intr_map_regs +
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (((uint_t)ino & 0x1f) << 3));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint64_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jlib_clear_intr_reg_addr(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t *addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(ino & 0x20);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl addr = (uint64_t *)(pib_p->pib_obio_clear_intr_regs +
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (((uint_t)ino & 0x1f) << 3));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluintptr_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ib_setup(pcmu_ib_t *pib_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = pib_p->pib_pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t a = get_reg_base(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pib_p->pib_ign = PCMU_ID_TO_IGN(pcmu_p->pcmu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pib_p->pib_max_ino = PCMU_MAX_INO;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pib_p->pib_obio_intr_map_regs = a + PCMU_IB_OBIO_INTR_MAP_REG_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pib_p->pib_obio_clear_intr_regs =
c9b6d37c673213b7ad91d849a105790cb469f95bfherard a + PCMU_IB_OBIO_CLEAR_INTR_REG_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (a);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return the cpuid to to be used for an ino.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * On multi-function pci devices, functions have separate devinfo nodes and
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interrupts.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This function determines if there is already an established slot-oriented
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interrupt-to-cpu binding established, if there is then it returns that
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * cpu. Otherwise a new cpu is selected by intr_dist_cpuid().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The devinfo node we are trying to associate a cpu with is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ino_p->pino_ih_head->ih_dip.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint32_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_intr_dist_cpuid(pcmu_ib_t *pib_p, pcmu_ib_ino_info_t *ino_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *rdip = ino_p->pino_ih_head->ih_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *prdip = ddi_get_parent(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_ino_info_t *sino_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *sdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *psdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *buf1 = NULL, *buf2 = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *s1, *s2, *s3;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int l2;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* must be CMU-CH driver parent (not ebus) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(ddi_driver_name(prdip), "pcicmu") != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto newcpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * From PCI 1275 binding: 2.2.1.3 Unit Address representation:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Since the "unit-number" is the address that appears in on Open
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Firmware 'device path', it follows that only the DD and DD,FF
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * forms of the text representation can appear in a 'device path'.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The rdip unit address is of the form "DD[,FF]". Define two
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * unit address strings that represent same-slot use: "DD" and "DD,".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The first compare uses strcmp, the second uses strncmp.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s1 = ddi_get_name_addr(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (s1 == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto newcpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl buf1 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strcmp */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl buf2 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strncmp */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s1 = strcpy(buf1, s1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s2 = strcpy(buf2, s1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s1 = strrchr(s1, ',');
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (s1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *s1 = '\0'; /* have "DD,FF" */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s1 = buf1; /* search via strcmp "DD" */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s2 = strrchr(s2, ',');
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(s2 + 1) = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s2 = buf2;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl l2 = strlen(s2); /* search via strncmp "DD," */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) strcat(s2, ","); /* have "DD" */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl l2 = strlen(s2); /* search via strncmp "DD," */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Search the established ino list for devinfo nodes bound
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to an ino that matches one of the slot use strings.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pib_p->pib_ino_lst_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (sino_p = pib_p->pib_ino_lst; sino_p; sino_p = sino_p->pino_next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* skip self and non-established */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((sino_p == ino_p) || (sino_p->pino_established == 0))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* skip non-siblings */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sdip = sino_p->pino_ih_head->ih_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl psdip = ddi_get_parent(sdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (psdip != prdip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* must be CMU-CH driver parent (not ebus) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(ddi_driver_name(psdip), "pcicmu") != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s3 = ddi_get_name_addr(sdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((s1 && (strcmp(s1, s3) == 0)) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (strncmp(s2, s3, l2) == 0)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern int intr_dist_debug;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (intr_dist_debug) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_CONT, "intr_dist: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "pcicmu`pcmu_intr_dist_cpuid "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "%s#%d %s: cpu %d established "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "by %s#%d %s\n", ddi_driver_name(rdip),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_get_instance(rdip),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_deviname(rdip, buf1),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sino_p->pino_cpuid,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_driver_name(sdip),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_get_instance(sdip),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_deviname(sdip, buf2));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* If a slot use match is found then use established cpu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (sino_p) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu_id = sino_p->pino_cpuid; /* target established cpu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto out;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlnewcpu: cpu_id = intr_dist_cpuid(); /* target new cpu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlout: if (buf1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(buf1, MAXNAMELEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (buf2)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(buf2, MAXNAMELEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (cpu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_cb_teardown(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_t *pcb_p = pcmu_p->pcmu_cb_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_uninit((u2u_ittrans_data_t *)pcb_p->pcb_ittrans_cookie);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ecc_add_intr(pcmu_t *pcmu_p, int inum, pcmu_ecc_intr_info_t *eii_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t mondo;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mondo = ((pcmu_p->pcmu_cb_p->pcb_ign << PCMU_INO_BITS) |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_inos[inum]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda VERIFY(add_ivintr(mondo, pcmu_pil[inum], (intrfunc)pcmu_ecc_intr,
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda (caddr_t)eii_p, NULL, NULL) == 0);
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (PCMU_ATTACH_RETCODE(PCMU_ECC_OBJ,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_OBJ_INTR_ADD, DDI_SUCCESS));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ecc_rem_intr(pcmu_t *pcmu_p, int inum, pcmu_ecc_intr_info_t *eii_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t mondo;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mondo = ((pcmu_p->pcmu_cb_p->pcb_ign << PCMU_INO_BITS) |
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_inos[inum]);
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda VERIFY(rem_ivintr(mondo, pcmu_pil[inum]) == 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_configure(pcmu_pbm_t *pcbm_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = pcbm_p->pcbm_pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip = pcmu_p->pcmu_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define pbm_err ((PCMU_PCI_AFSR_E_MASK << PCMU_PCI_AFSR_PE_SHIFT) | \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (PCMU_PCI_AFSR_E_MASK << PCMU_PCI_AFSR_SE_SHIFT))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define csr_err (PCI_STAT_PERROR | PCI_STAT_S_PERROR | \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB | \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCI_STAT_S_TARG_AB | PCI_STAT_S_PERROR)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Clear any PBM errors.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *pcbm_p->pcbm_async_flt_status_reg = pbm_err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Clear error bits in configuration status register.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG1(PCMU_DBG_ATTACH, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "pcmu_pbm_configure: conf status reg=%x\n", csr_err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header->ch_status_reg = csr_err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_DBG1(PCMU_DBG_ATTACH, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "pcmu_pbm_configure: conf status reg==%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header->ch_status_reg);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_prop_update_int(DDI_DEV_T_ANY, dip, "latency-timer",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (int)pcbm_p->pcbm_config_header->ch_latency_timer_reg);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#undef pbm_err
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#undef csr_err
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jluint_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_disable_errors(pcmu_pbm_t *pcbm_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = pcbm_p->pcbm_pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_t *pib_p = pcmu_p->pcmu_ib_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Disable error and streaming byte hole interrupts via the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * PBM control register.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *pcbm_p->pcbm_ctrl_reg &= ~PCMU_PCI_CTRL_ERR_INT_EN;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Disable error interrupts via the interrupt mapping register.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ib_intr_disable(pib_p,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_inos[CBNINTR_PBM], PCMU_IB_INTR_NOWAIT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (BF_NONE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_cb_setup(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t csr, csr_pa, pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cb_t *pcb_p = pcmu_p->pcmu_cb_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_ign = PCMU_ID_TO_IGN(pcmu_p->pcmu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pa = (uint64_t)hat_getpfnum(kas.a_hat, pcmu_p->pcmu_address[0]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_base_pa = pa = pa >> (32 - MMU_PAGESHIFT) << 32;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_map_pa = pa + PCMU_IB_OBIO_INTR_MAP_REG_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_clr_pa = pa + PCMU_IB_OBIO_CLEAR_INTR_REG_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcb_p->pcb_obsta_pa = pa + PCMU_IB_OBIO_INTR_STATE_DIAG_REG;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl csr_pa = pa + PCMU_CB_CONTROL_STATUS_REG_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl csr = lddphysio(csr_pa);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Clear any pending address parity errors.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (csr & PCMU_CB_CONTROL_STATUS_APERR) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl csr |= PCMU_CB_CONTROL_STATUS_APERR;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "clearing UPA address parity error\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl csr |= PCMU_CB_CONTROL_STATUS_APCKEN;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl csr &= ~PCMU_CB_CONTROL_STATUS_IAP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stdphysio(csr_pa, csr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_init(pcmu_p,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (u2u_ittrans_data_t **)&pcb_p->pcb_ittrans_cookie);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ecc_setup(pcmu_ecc_t *pecc_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pecc_p->pecc_ue.pecc_errpndg_mask = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pecc_p->pecc_ue.pecc_offset_mask = PCMU_ECC_UE_AFSR_DW_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pecc_p->pecc_ue.pecc_offset_shift = PCMU_ECC_UE_AFSR_DW_OFFSET_SHIFT;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pecc_p->pecc_ue.pecc_size_log2 = 3;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic uintptr_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlget_pbm_reg_base(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((uintptr_t)(pcmu_p->pcmu_address[0]));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_setup(pcmu_pbm_t *pcbm_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = pcbm_p->pcbm_pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the base virtual address for the PBM control block.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t a = get_pbm_reg_base(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the virtual address of the PCI configuration header.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This should be mapped little-endian.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header =
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (config_header_t *)get_config_reg_base(pcmu_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the virtual addresses for control, error and diag
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * registers.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_ctrl_reg = (uint64_t *)(a + PCMU_PCI_CTRL_REG_OFFSET);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_diag_reg = (uint64_t *)(a + PCMU_PCI_DIAG_REG_OFFSET);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_async_flt_status_reg =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (uint64_t *)(a + PCMU_PCI_ASYNC_FLT_STATUS_REG_OFFSET);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_async_flt_addr_reg =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (uint64_t *)(a + PCMU_PCI_ASYNC_FLT_ADDR_REG_OFFSET);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_teardown(pcmu_pbm_t *pcbm_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_get_numproxy(dev_info_t *dip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard "#upa-interrupt-proxies", 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_get_portid(dev_info_t *dip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "portid", -1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CMU-CH Performance Events.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pcmu_kev_mask_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcicmu_pcmu_events[] = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl {"pio_cycles_b", 0xf}, {"interrupts", 0x11},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl {"upa_inter_nack", 0x12}, {"pio_reads", 0x13},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl {"pio_writes", 0x14},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl {"clear_pic", 0x1f}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create the picN kstat's.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_kstat_init()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_name_kstat = (pcmu_ksinfo_t *)kmem_alloc(sizeof (pcmu_ksinfo_t),
c9b6d37c673213b7ad91d849a105790cb469f95bfherard KM_NOSLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_name_kstat == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "pcicmu : no space for kstat\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_name_kstat->pic_no_evs =
c9b6d37c673213b7ad91d849a105790cb469f95bfherard sizeof (pcicmu_pcmu_events) / sizeof (pcmu_kev_mask_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_name_kstat->pic_shift[0] = PCMU_SHIFT_PIC0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_name_kstat->pic_shift[1] = PCMU_SHIFT_PIC1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_create_name_kstat("pcmup",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard pcmu_name_kstat, pcicmu_pcmu_events);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Called from _fini()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_kstat_fini()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_name_kstat != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_delete_name_kstat(pcmu_name_kstat);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(pcmu_name_kstat, sizeof (pcmu_ksinfo_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_name_kstat = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create the performance 'counters' kstat.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_add_upstream_kstat(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cntr_pa_t *cntr_pa_p = &pcmu_p->pcmu_uks_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t regbase = va_to_pa((void *)get_reg_base(pcmu_p));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cntr_pa_p->pcr_pa = regbase + PCMU_PERF_PCR_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cntr_pa_p->pic_pa = regbase + PCMU_PERF_PIC_OFFSET;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p->pcmu_uksp = pcmu_create_cntr_kstat(pcmu_p, "pcmup",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard NUM_OF_PICS, pcmu_cntr_kstat_pa_update, cntr_pa_p);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * u2u_ittrans_init() is caled from in pci.c's pcmu_cb_setup() per CMU.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Second argument "ittrans_cookie" is address of pcb_ittrans_cookie in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcb_p member. allocated interrupt block is returned in it.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlu2u_ittrans_init(pcmu_t *pcmu_p, u2u_ittrans_data_t **ittrans_cookie)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_data_t *u2u_trans_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_device_acc_attr_t attr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Allocate the data structure to support U2U's
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interrupt target translations.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_trans_p = (u2u_ittrans_data_t *)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_zalloc(sizeof (u2u_ittrans_data_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get other properties, "board#"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = ddi_getprop(DDI_DEV_T_ANY, pcmu_p->pcmu_dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "board#", -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_trans_p->u2u_board = board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (board == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* this cannot happen on production systems */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "u2u:Invalid property;board = %d", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize interrupt target translations mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&(u2u_trans_p->u2u_ittrans_lock), "u2u_ittrans_lock",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl MUTEX_DEFAULT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get U2U's registers space by ddi_regs_map_setup(9F)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = ddi_regs_map_setup(pcmu_p->pcmu_dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl REGS_INDEX_OF_U2U, (caddr_t *)(&(u2u_trans_p->u2u_regs_base)),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0, 0, &attr, &(u2u_trans_p->u2u_acc));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * check result of ddi_regs_map_setup().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "u2u%d: registers map setup failed", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Read Port-id(1 byte) in u2u
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_trans_p->u2u_port_id = *(volatile int32_t *)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (u2u_trans_p->u2u_regs_base + U2U_PID_REGISTER_OFFSET);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_p->pcmu_id != u2u_trans_p->u2u_port_id) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "u2u%d: Invalid Port-ID", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *ittrans_cookie = u2u_trans_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * u2u_ittras_resume() is called from pcmu_obj_resume() at DDI_RESUME entry.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlu2u_ittrans_resume(u2u_ittrans_data_t **ittrans_cookie)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_data_t *u2u_trans_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_id_t *ittrans_id_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t data_reg_addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ix;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_trans_p = *ittrans_cookie;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set U2U Data Register
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (ix = 0; ix < U2U_DATA_NUM; ix++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p = &(u2u_trans_p->u2u_ittrans_id[ix]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data_reg_addr = u2u_trans_p->u2u_regs_base +
25cf1a301a396c38e8adf52c15f537b80d2483f7jl U2U_DATA_REGISTER_OFFSET + (ix * sizeof (uint64_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_id_p->u2u_ino_map_reg == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* This index was not set */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(volatile uint32_t *) (data_reg_addr) =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (uint32_t)ittrans_id_p->u2u_tgt_cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * u2u_ittras_uninit() is called from ib_destroy() at detach,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * or occuring error in attach.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlu2u_ittrans_uninit(u2u_ittrans_data_t *ittrans_cookie)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return; /* not support */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == (u2u_ittrans_data_t *)(-1)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return; /* illeagal case */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_regs_map_free(&(ittrans_cookie->u2u_acc));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&(ittrans_cookie->u2u_ittrans_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free((void *)ittrans_cookie, sizeof (u2u_ittrans_data_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This routine,u2u_translate_tgtid(, , cpu_id, pino_map_reg),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * searches index having same value of pino_map_reg, or empty.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Then, stores cpu_id in a U2U Data Register as this index,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and return this index.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlu2u_translate_tgtid(pcmu_t *pcmu_p, uint_t cpu_id,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl volatile uint64_t *pino_map_reg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int index = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ix;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err_level; /* severity level for cmn_err */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_id_t *ittrans_id_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uintptr_t data_reg_addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_data_t *ittrans_cookie;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_cookie =
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (u2u_ittrans_data_t *)(pcmu_p->pcmu_cb_p->pcb_ittrans_cookie);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (cpu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == (u2u_ittrans_data_t *)(-1)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1); /* illeagal case */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&(ittrans_cookie->u2u_ittrans_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Decide index No. of U2U Data registers in either
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * already used by same pino_map_reg, or empty.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (ix = 0; ix < U2U_DATA_NUM; ix++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p = &(ittrans_cookie->u2u_ittrans_id[ix]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_id_p->u2u_ino_map_reg == pino_map_reg) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* already used this pino_map_reg */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl index = ix;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (index == -1 &&
c9b6d37c673213b7ad91d849a105790cb469f95bfherard ittrans_id_p->u2u_ino_map_reg == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl index = ix;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (index == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (panicstr) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err_level = CE_WARN;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err_level = CE_PANIC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(err_level, "u2u%d:No more U2U-Data regs!!",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard ittrans_cookie->u2u_board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (cpu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For U2U
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * set cpu_id into u2u_data_reg by index.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ((uint64_t)(u2u_regs_base
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * + U2U_DATA_REGISTER_OFFSET))[index] = cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data_reg_addr = ittrans_cookie->u2u_regs_base
c9b6d37c673213b7ad91d849a105790cb469f95bfherard + U2U_DATA_REGISTER_OFFSET
c9b6d37c673213b7ad91d849a105790cb469f95bfherard + (index * sizeof (uint64_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set cpu_id into U2U Data register[index]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(volatile uint32_t *) (data_reg_addr) = (uint32_t)cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Setup for software, excepting at panicing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and rebooting, etc...?
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!panicstr) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p = &(ittrans_cookie->u2u_ittrans_id[index]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p->u2u_tgt_cpu_id = cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p->u2u_ino_map_reg = pino_map_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&(ittrans_cookie->u2u_ittrans_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (index);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * u2u_ittrans_cleanup() is called from common_pcmu_ib_intr_disable()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * after called intr_rem_cpu(mondo).
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlu2u_ittrans_cleanup(u2u_ittrans_data_t *ittrans_cookie,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl volatile uint64_t *pino_map_reg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ix;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl u2u_ittrans_id_t *ittrans_id_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_cookie == (u2u_ittrans_data_t *)(-1)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return; /* illeagal case */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&(ittrans_cookie->u2u_ittrans_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (ix = 0; ix < U2U_DATA_NUM; ix++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p = &(ittrans_cookie->u2u_ittrans_id[ix]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ittrans_id_p->u2u_ino_map_reg == pino_map_reg) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ittrans_id_p->u2u_ino_map_reg = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&(ittrans_cookie->u2u_ittrans_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_ecc_classify, called by ecc_handler to classify ecc errors
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and determine if we should panic or not.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_ecc_classify(uint64_t err, pcmu_ecc_errstate_t *ecc_err_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct async_flt *ecc = &ecc_err_p->ecc_aflt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* LINTED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = ecc_err_p->ecc_ii_p.pecc_p->pecc_pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pcmu_p->pcmu_err_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc_err_p->ecc_bridge_type = PCI_OPLCMU; /* RAGS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the parent bus id that caused the error.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc_err_p->ecc_dev_id = (ecc_err_p->ecc_afsr & PCMU_ECC_UE_AFSR_ID)
c9b6d37c673213b7ad91d849a105790cb469f95bfherard >> PCMU_ECC_UE_AFSR_ID_SHIFT;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Determine the doubleword offset of the error.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc_err_p->ecc_dw_offset = (ecc_err_p->ecc_afsr &
25cf1a301a396c38e8adf52c15f537b80d2483f7jl PCMU_ECC_UE_AFSR_DW_OFFSET) >> PCMU_ECC_UE_AFSR_DW_OFFSET_SHIFT;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Determine the primary error type.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (err) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case PCMU_ECC_UE_AFSR_E_PIO:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ecc_err_p->pecc_pri) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc->flt_erpt_class = PCI_ECC_PIO_UE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc->flt_erpt_class = PCI_ECC_SEC_PIO_UE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* For CMU-CH, a UE is always fatal. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ecc->flt_panic = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_pbm_classify, called by pcmu_pbm_afsr_report to classify piow afsr.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_classify(pcmu_pbm_errstate_t *pbm_err_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t e;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int nerr = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char **tmp_class;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pbm_err_p->pcbm_pri) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl tmp_class = &pbm_err_p->pcbm_pci.pcmu_err_class;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e = PBM_AFSR_TO_PRIERR(pbm_err_p->pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_log = FM_LOG_PCI;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl tmp_class = &pbm_err_p->pbm_err_class;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e = PBM_AFSR_TO_SECERR(pbm_err_p->pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_log = FM_LOG_PBM;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e & PCMU_PCI_AFSR_E_MA) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *tmp_class = pbm_err_p->pcbm_pri ? PCI_MA : PCI_SEC_MA;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nerr++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (nerr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Function used to clear PBM/PCI/IOMMU error state after error handling
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is complete. Only clearing error bits which have been logged. Called by
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_pbm_err_handler and pcmu_bus_exit.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_clear_error(pcmu_t *pcmu_p, pcmu_pbm_errstate_t *pbm_err_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pcbm_p->pcbm_pcmu_p->pcmu_err_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *pcbm_p->pcbm_ctrl_reg = pbm_err_p->pbm_ctl_stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *pcbm_p->pcbm_async_flt_status_reg = pbm_err_p->pbm_afsr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header->ch_status_reg =
c9b6d37c673213b7ad91d849a105790cb469f95bfherard pbm_err_p->pcbm_pci.pcmu_cfg_stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_err_handler(dev_info_t *dip, ddi_fm_error_t *derr,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl const void *impl_data, int caller)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int fatal = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int nonfatal = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int unknown = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t prierr, secerr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_errstate_t pbm_err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p = (pcmu_t *)impl_data;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pcmu_p->pcmu_err_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_errstate_get(pcmu_p, &pbm_err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl derr->fme_ena = derr->fme_ena ? derr->fme_ena :
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fm_ena_generate(0, FM_ENA_FMT1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prierr = PBM_AFSR_TO_PRIERR(pbm_err.pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl secerr = PBM_AFSR_TO_SECERR(pbm_err.pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (derr->fme_flag == DDI_FM_ERR_PEEK) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For ddi_peek treat all events as nonfatal. We only
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * really call this function so that pcmu_clear_error()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and ndi_fm_handler_dispatch() will get called.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nonfatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (derr->fme_flag == DDI_FM_ERR_POKE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For ddi_poke we can treat as nonfatal if the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * following conditions are met :
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 1. Make sure only primary error is MA/TA
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 2. Make sure no secondary error
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 3. check pci config header stat reg to see MA/TA is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * logged. We cannot verify only MA/TA is recorded
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * since it gets much more complicated when a
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * PCI-to-PCI bridge is present.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((prierr == PCMU_PCI_AFSR_E_MA) && !secerr &&
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (pbm_err.pcbm_pci.pcmu_cfg_stat & PCI_STAT_R_MAST_AB)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nonfatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prierr || secerr) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_pbm_afsr_report(dip, derr->fme_ena, &pbm_err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == DDI_FM_FATAL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nonfatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = pcmu_cfg_report(dip, derr, &pbm_err.pcbm_pci, caller, prierr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == DDI_FM_FATAL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (ret == DDI_FM_NONFATAL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nonfatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jldone:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == DDI_FM_FATAL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (ret == DDI_FM_NONFATAL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nonfatal++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (ret == DDI_FM_UNKNOWN) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl unknown++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Cleanup and reset error bits */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_clear_error(pcmu_p, &pbm_err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_check_error(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint16_t pcmu_cfg_stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t pbm_afsr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pcmu_p->pcmu_err_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_cfg_stat = pcbm_p->pcbm_config_header->ch_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_afsr = *pcbm_p->pcbm_async_flt_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((pcmu_cfg_stat & (PCI_STAT_S_PERROR | PCI_STAT_S_TARG_AB |
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB |
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCI_STAT_S_SYSERR | PCI_STAT_PERROR)) ||
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (PBM_AFSR_TO_PRIERR(pbm_afsr))) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Function used to gather PBM/PCI error state for the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pcmu_pbm_err_handler. This function must be called while pcmu_err_mutex
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is held.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_errstate_get(pcmu_t *pcmu_p, pcmu_pbm_errstate_t *pbm_err_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_t *pcbm_p = pcmu_p->pcmu_pcbm_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&pcmu_p->pcmu_err_mutex));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bzero(pbm_err_p, sizeof (pcmu_pbm_errstate_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Capture all pbm error state for later logging
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_bridge_type = PCI_OPLCMU; /* RAGS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pcbm_pci.pcmu_cfg_stat =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header->ch_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_ctl_stat = *pcbm_p->pcbm_ctrl_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pcbm_pci.pcmu_cfg_comm =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcbm_p->pcbm_config_header->ch_command_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_afsr = *pcbm_p->pcbm_async_flt_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pbm_afar = *pcbm_p->pcbm_async_flt_addr_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_err_p->pcbm_pci.pcmu_pa = *pcbm_p->pcbm_async_flt_addr_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_clear_error(pcmu_pbm_t *pcbm_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t pbm_afsr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for poke() support - called from POKE_FLUSH. Spin waiting
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for MA, TA or SERR to be cleared by a pcmu_pbm_error_intr().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We have to wait for SERR too in case the device is beyond
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * a pci-pci bridge.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_afsr = *pcbm_p->pcbm_async_flt_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (((pbm_afsr >> PCMU_PCI_AFSR_PE_SHIFT) &
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (PCMU_PCI_AFSR_E_MA | PCMU_PCI_AFSR_E_TA))) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pbm_afsr = *pcbm_p->pcbm_async_flt_status_reg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_err_create(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * PCI detected ECC errorq, to schedule async handling
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * of ECC errors and logging.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The errorq is created here but destroyed when _fini is called
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for the pci module.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_ecc_queue == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_ecc_queue = errorq_create("pcmu_ecc_queue",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (errorq_func_t)pcmu_ecc_err_drain,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (void *)NULL,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard ECC_MAX_ERRS, sizeof (pcmu_ecc_errstate_t),
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PIL_2, ERRORQ_VITAL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pcmu_ecc_queue == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl panic("failed to create required system error queue");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize error handling mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&pcmu_p->pcmu_err_mutex, NULL, MUTEX_DRIVER,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (void *)pcmu_p->pcmu_fm_ibc);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_err_destroy(pcmu_t *pcmu_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_destroy(&pcmu_p->pcmu_err_mutex);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Function used to post PCI block module specific ereports.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlpcmu_pbm_ereport_post(dev_info_t *dip, uint64_t ena,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_pbm_errstate_t *pbm_err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *aux_msg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t prierr, secerr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_t *pcmu_p;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int instance = ddi_get_instance(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ena = ena ? ena : fm_ena_generate(0, FM_ENA_FMT1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pcmu_p = get_pcmu_soft_state(instance);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prierr = PBM_AFSR_TO_PRIERR(pbm_err->pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl secerr = PBM_AFSR_TO_SECERR(pbm_err->pbm_afsr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prierr)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl aux_msg = "PCI primary error: Master Abort";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (secerr)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl aux_msg = "PCI secondary error: Master Abort";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl aux_msg = "";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s %s: %s %s=0x%lx, %s=0x%lx, %s=0x%lx %s=0x%x",
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (pcmu_p->pcmu_pcbm_p)->pcbm_nameinst_str,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard (pcmu_p->pcmu_pcbm_p)->pcbm_nameaddr_str,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard aux_msg,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCI_PBM_AFAR, pbm_err->pbm_afar,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCI_PBM_AFSR, pbm_err->pbm_afsr,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard PCI_PBM_CSR, pbm_err->pbm_ctl_stat,
c9b6d37c673213b7ad91d849a105790cb469f95bfherard "portid", pcmu_p->pcmu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}