70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * CDDL HEADER START
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * The contents of this file are subject to the terms of the
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny * Common Development and Distribution License (the "License").
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny * You may not use this file except in compliance with the License.
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
70025d765b044c6d8594bb965a2247a61e991a99johnny * or http://www.opensolaris.org/os/licensing.
70025d765b044c6d8594bb965a2247a61e991a99johnny * See the License for the specific language governing permissions
70025d765b044c6d8594bb965a2247a61e991a99johnny * and limitations under the License.
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * When distributing Covered Code, include this CDDL HEADER in each
70025d765b044c6d8594bb965a2247a61e991a99johnny * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
70025d765b044c6d8594bb965a2247a61e991a99johnny * If applicable, add the following below this CDDL HEADER, with the
70025d765b044c6d8594bb965a2247a61e991a99johnny * fields enclosed by brackets "[]" replaced with your own identifying
70025d765b044c6d8594bb965a2247a61e991a99johnny * information: Portions Copyright [yyyy] [name of copyright owner]
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * CDDL HEADER END
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
5cd376e8b7030707d78315f63adb4bb2b4d9963eJimmy Vetayases * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * File that has code which is common between pci(7d) and npe(7d)
70025d765b044c6d8594bb965a2247a61e991a99johnny * It shares the following:
70025d765b044c6d8594bb965a2247a61e991a99johnny * - interrupt code
70025d765b044c6d8594bb965a2247a61e991a99johnny * - pci_tools ioctl code
70025d765b044c6d8594bb965a2247a61e991a99johnny * - name_child code
70025d765b044c6d8594bb965a2247a61e991a99johnny * - set_parent_private_data code
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/conf.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/pci.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/sunndi.h>
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz#include <sys/mach_intr.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/pci_intr_lib.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/psm.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/policy.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/sysmacros.h>
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz#include <sys/clock.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/apic.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/pci_tools.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_var.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_tools_ext.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_common.h>
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish#include <sys/pci_cfgspace.h>
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish#include <sys/pci_impl.h>
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta#include <sys/pci_cap.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Function prototypes
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int pci_get_priority(dev_info_t *, ddi_intr_handle_impl_t *, int *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int pci_enable_intr(dev_info_t *, dev_info_t *,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *, uint32_t);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic void pci_disable_intr(dev_info_t *, dev_info_t *,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *, uint32_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int pci_alloc_intr_fixed(dev_info_t *, dev_info_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t *, void *);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int pci_free_intr_fixed(dev_info_t *, dev_info_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t *);
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Extern declarations for PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnnyextern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_intr_op_t, int *);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern ddi_irm_pool_t *apix_irm_pool_p;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_name_child:
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * Assign the address portion of the node name
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_name_child(dev_info_t *child, char *name, int namelen)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int dev, func, length;
70025d765b044c6d8594bb965a2247a61e991a99johnny char **unit_addr;
70025d765b044c6d8594bb965a2247a61e991a99johnny uint_t n;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_regspec_t *pci_rp;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ndi_dev_is_persistent_node(child) == 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * For .conf node, use "unit-address" property
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "cannot find unit-address in %s.conf",
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_get_name(child));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "unit-address property in %s.conf"
70025d765b044c6d8594bb965a2247a61e991a99johnny " not well-formed", ddi_get_name(child));
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(unit_addr);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) snprintf(name, namelen, "%s", *unit_addr);
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(unit_addr);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
70025d765b044c6d8594bb965a2247a61e991a99johnny "reg", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "cannot find reg property in %s",
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_get_name(child));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* copy the device identifications */
70025d765b044c6d8594bb965a2247a61e991a99johnny dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
70025d765b044c6d8594bb965a2247a61e991a99johnny func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * free the memory allocated by ddi_prop_lookup_int_array
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(pci_rp);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (func != 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) snprintf(name, namelen, "%x,%x", dev, func);
70025d765b044c6d8594bb965a2247a61e991a99johnny } else {
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) snprintf(name, namelen, "%x", dev);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Interrupt related code:
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * The following busop is common to npe and pci drivers
70025d765b044c6d8594bb965a2247a61e991a99johnny * bus_introp
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Create the ddi_parent_private_data for a pseudo child.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnyvoid
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_set_parent_private_data(dev_info_t *dip)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny struct ddi_parent_private_data *pdptr;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pdptr = (struct ddi_parent_private_data *)kmem_zalloc(
70025d765b044c6d8594bb965a2247a61e991a99johnny (sizeof (struct ddi_parent_private_data) +
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz sizeof (struct intrspec)), KM_SLEEP);
70025d765b044c6d8594bb965a2247a61e991a99johnny pdptr->par_intr = (struct intrspec *)(pdptr + 1);
70025d765b044c6d8594bb965a2247a61e991a99johnny pdptr->par_nintr = 1;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_parent_data(dip, pdptr);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_get_priority:
70025d765b044c6d8594bb965a2247a61e991a99johnny * Figure out the priority of the device
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_get_priority(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, int *pri)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny struct intrspec *ispec;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_get_priority: dip = 0x%p, hdlp = %p\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny (void *)dip, (void *)hdlp));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip,
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_inum)) == NULL) {
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
614edcae07b011d0a945698ea463995b233d17e8Evan Yan *pri = pci_class_to_pil(dip);
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_common_set_parent_private_data(hdlp->ih_dip);
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip,
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny *pri = ispec->intrspec_pri;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elangostatic int pcieb_intr_pri_counter = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_common_intr_ops: bus_intr_op() function for interrupt support
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *hdlp, void *result)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int priority = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny int psm_status = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny int pci_status = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny int pci_rval, psm_rval = PSM_FAILURE;
70025d765b044c6d8594bb965a2247a61e991a99johnny int types = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny int pciepci = 0;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny int i, j, count;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta int rv;
70025d765b044c6d8594bb965a2247a61e991a99johnny int behavior;
d12abe7ce2663ac39e686a14960eb4febf560195anish int cap_ptr;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta uint16_t msi_cap_base, msix_cap_base, cap_ctrl;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta char *prop;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intrspec_t isp;
70025d765b044c6d8594bb965a2247a61e991a99johnny struct intrspec *ispec;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t tmp_hdl;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_msix_t *msix_p;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz ihdl_plat_t *ihdl_plat_datap;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny ddi_intr_handle_t *h_array;
d12abe7ce2663ac39e686a14960eb4febf560195anish ddi_acc_handle_t handle;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_get_intr_t intrinfo;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT,
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_common_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Process the request */
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (intr_op) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_SUPPORTED_TYPES:
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /*
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * First we determine the interrupt types supported by the
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * device itself, then we filter them through what the OS
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * and system supports. We determine system-level
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * interrupt type support for anything other than fixed intrs
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * through the psm_intr_ops vector
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta rv = DDI_FAILURE;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Fixed supported by default */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta types = DDI_INTR_TYPE_FIXED;
70025d765b044c6d8594bb965a2247a61e991a99johnny
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (psm_intr_ops == NULL) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta *(int *)result = types;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (pci_config_setup(rdip, &handle) != DDI_SUCCESS)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /* Sanity test cap control values if found */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI, &msi_cap_base) ==
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_SUCCESS) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta cap_ctrl = PCI_CAP_GET16(handle, 0, msi_cap_base,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta PCI_MSI_CTRL);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (cap_ctrl == PCI_CAP_EINVAL16)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta goto SUPPORTED_TYPES_OUT;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta types |= DDI_INTR_TYPE_MSI;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI_X, &msix_cap_base) ==
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_SUCCESS) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta cap_ctrl = PCI_CAP_GET16(handle, 0, msix_cap_base,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta PCI_MSIX_CTRL);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (cap_ctrl == PCI_CAP_EINVAL16)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta goto SUPPORTED_TYPES_OUT;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta types |= DDI_INTR_TYPE_MSIX;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /*
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Filter device-level types through system-level support
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta tmp_hdl.ih_type = types;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_CHECK_MSI,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta &types) != PSM_SUCCESS)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta goto SUPPORTED_TYPES_OUT;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "rdip: 0x%p supported types: 0x%x\n", (void *)rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases types));
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /*
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Export any MSI/MSI-X cap locations via properties
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (types & DDI_INTR_TYPE_MSI) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (ndi_prop_update_int(DDI_DEV_T_NONE, rdip,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "pci-msi-capid-pointer", (int)msi_cap_base) !=
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_PROP_SUCCESS)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta goto SUPPORTED_TYPES_OUT;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (types & DDI_INTR_TYPE_MSIX) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (ndi_prop_update_int(DDI_DEV_T_NONE, rdip,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "pci-msix-capid-pointer", (int)msix_cap_base) !=
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_PROP_SUCCESS)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta goto SUPPORTED_TYPES_OUT;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta rv = DDI_SUCCESS;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
600d77457b335b6f448f13d5f33bf7e70dfbb39djvetaSUPPORTED_TYPES_OUT:
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta *(int *)result = types;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta pci_config_teardown(&handle);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta return (rv);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish case DDI_INTROP_NAVAIL:
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_NINTRS:
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish if (pci_msi_get_nintrs(hdlp->ih_dip, hdlp->ih_type,
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish result) != DDI_SUCCESS)
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish return (DDI_FAILURE);
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish } else {
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish *(int *)result = i_ddi_get_intx_nintrs(hdlp->ih_dip);
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish if (*(int *)result == 0)
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish return (DDI_FAILURE);
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_ALLOC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * FIXED type
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (pci_alloc_intr_fixed(pdip, rdip, hdlp, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI or MSIX (figure out number of vectors available)
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
70025d765b044c6d8594bb965a2247a61e991a99johnny (psm_intr_ops != NULL) &&
70025d765b044c6d8594bb965a2247a61e991a99johnny (pci_get_priority(rdip, hdlp, &priority) == DDI_SUCCESS)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango * Following check is a special case for 'pcieb'.
70025d765b044c6d8594bb965a2247a61e991a99johnny * This makes sure vectors with the right priority
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango * are allocated for pcieb during ALLOC time.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango if (strcmp(ddi_driver_name(rdip), "pcieb") == 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_pri =
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango (pcieb_intr_pri_counter % 2) ? 4 : 7;
70025d765b044c6d8594bb965a2247a61e991a99johnny pciepci = 1;
70025d765b044c6d8594bb965a2247a61e991a99johnny } else
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_pri = priority;
80ab886d233f514d54c2a6bdeb9fdfd951bd6881wesolows behavior = (int)(uintptr_t)hdlp->ih_scratch2;
d12abe7ce2663ac39e686a14960eb4febf560195anish
d12abe7ce2663ac39e686a14960eb4febf560195anish /*
d12abe7ce2663ac39e686a14960eb4febf560195anish * Cache in the config handle and cap_ptr
d12abe7ce2663ac39e686a14960eb4febf560195anish */
d12abe7ce2663ac39e686a14960eb4febf560195anish if (i_ddi_get_pci_config_handle(rdip) == NULL) {
d12abe7ce2663ac39e686a14960eb4febf560195anish if (pci_config_setup(rdip, &handle) !=
d12abe7ce2663ac39e686a14960eb4febf560195anish DDI_SUCCESS)
d12abe7ce2663ac39e686a14960eb4febf560195anish return (DDI_FAILURE);
d12abe7ce2663ac39e686a14960eb4febf560195anish i_ddi_set_pci_config_handle(rdip, handle);
d12abe7ce2663ac39e686a14960eb4febf560195anish }
d12abe7ce2663ac39e686a14960eb4febf560195anish
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta prop = NULL;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta cap_ptr = 0;
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (hdlp->ih_type == DDI_INTR_TYPE_MSI)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta prop = "pci-msi-capid-pointer";
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta else if (hdlp->ih_type == DDI_INTR_TYPE_MSIX)
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta prop = "pci-msix-capid-pointer";
d12abe7ce2663ac39e686a14960eb4febf560195anish
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /*
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Enforce the calling of DDI_INTROP_SUPPORTED_TYPES
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * for MSI(X) before allocation
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (prop != NULL) {
d12abe7ce2663ac39e686a14960eb4febf560195anish cap_ptr = ddi_prop_get_int(DDI_DEV_T_ANY, rdip,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_PROP_DONTPASS, prop, 0);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (cap_ptr == 0) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta DDI_INTR_NEXDBG((CE_CONT,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "pci_common_intr_ops: rdip: 0x%p "
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "attempted MSI(X) alloc without "
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "cap property\n", (void *)rdip));
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta return (DDI_FAILURE);
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta }
d12abe7ce2663ac39e686a14960eb4febf560195anish }
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr);
d12abe7ce2663ac39e686a14960eb4febf560195anish
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /*
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Allocate interrupt vectors
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta */
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_ALLOC_VECTORS, result);
70025d765b044c6d8594bb965a2247a61e991a99johnny
1ac1709f7b6fe803d662ea7ee6a6885182bfb2e1anish if (*(int *)result == 0)
1ac1709f7b6fe803d662ea7ee6a6885182bfb2e1anish return (DDI_INTR_NOTFOUND);
1ac1709f7b6fe803d662ea7ee6a6885182bfb2e1anish
70025d765b044c6d8594bb965a2247a61e991a99johnny /* verify behavior flag and take appropriate action */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((behavior == DDI_INTR_ALLOC_STRICT) &&
70025d765b044c6d8594bb965a2247a61e991a99johnny (*(int *)result < hdlp->ih_scratch1)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT,
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_common_intr_ops: behavior %x, "
70025d765b044c6d8594bb965a2247a61e991a99johnny "couldn't get enough intrs\n", behavior));
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_scratch1 = *(int *)result;
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_FREE_VECTORS, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_EAGAIN);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
70025d765b044c6d8594bb965a2247a61e991a99johnny if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) {
70025d765b044c6d8594bb965a2247a61e991a99johnny msix_p = pci_msix_init(hdlp->ih_dip);
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China if (msix_p) {
70025d765b044c6d8594bb965a2247a61e991a99johnny i_ddi_set_msix(hdlp->ih_dip,
70025d765b044c6d8594bb965a2247a61e991a99johnny msix_p);
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China } else {
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China DDI_INTR_NEXDBG((CE_CONT,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China "pci_common_intr_ops: MSI-X"
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China "table initilization failed"
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China ", rdip 0x%p inum 0x%x\n",
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China (void *)rdip,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China hdlp->ih_inum));
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China (void) (*psm_intr_ops)(rdip,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China hdlp,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China PSM_INTR_OP_FREE_VECTORS,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China NULL);
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China return (DDI_FAILURE);
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China }
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pciepci) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update priority in ispec */
70025d765b044c6d8594bb965a2247a61e991a99johnny isp = pci_intx_get_ispec(pdip, rdip,
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz (int)hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)isp;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ispec)
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec->intrspec_pri = hdlp->ih_pri;
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango ++pcieb_intr_pri_counter;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny } else
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_FREE:
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
70025d765b044c6d8594bb965a2247a61e991a99johnny (psm_intr_ops != NULL)) {
6856520054585a7305203963c518444732a57448anish if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1 ==
6856520054585a7305203963c518444732a57448anish 0) {
d12abe7ce2663ac39e686a14960eb4febf560195anish if (handle = i_ddi_get_pci_config_handle(
d12abe7ce2663ac39e686a14960eb4febf560195anish rdip)) {
d12abe7ce2663ac39e686a14960eb4febf560195anish (void) pci_config_teardown(&handle);
d12abe7ce2663ac39e686a14960eb4febf560195anish i_ddi_set_pci_config_handle(rdip, NULL);
d12abe7ce2663ac39e686a14960eb4febf560195anish }
d12abe7ce2663ac39e686a14960eb4febf560195anish if (cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip))
d12abe7ce2663ac39e686a14960eb4febf560195anish i_ddi_set_msi_msix_cap_ptr(rdip, 0);
d12abe7ce2663ac39e686a14960eb4febf560195anish }
d12abe7ce2663ac39e686a14960eb4febf560195anish
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_FREE_VECTORS, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
70025d765b044c6d8594bb965a2247a61e991a99johnny msix_p = i_ddi_get_msix(hdlp->ih_dip);
70025d765b044c6d8594bb965a2247a61e991a99johnny if (msix_p &&
6856520054585a7305203963c518444732a57448anish (i_ddi_intr_get_current_nintrs(
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz hdlp->ih_dip) - 1) == 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_msix_fini(msix_p);
70025d765b044c6d8594bb965a2247a61e991a99johnny i_ddi_set_msix(hdlp->ih_dip, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (pci_free_intr_fixed(pdip, rdip, hdlp));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_GETPRI:
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Get the priority */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_get_priority(rdip, hdlp, &priority) != DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
70025d765b044c6d8594bb965a2247a61e991a99johnny "priority = 0x%x\n", priority));
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = priority;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_SETPRI:
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Validate the interrupt priority passed */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (*(int *)result > LOCK_LEVEL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Ensure that PSM is all initialized */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ispec = (struct intrspec *)isp;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li if (ispec == NULL)
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li return (DDI_FAILURE);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li /* For fixed interrupts */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) {
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li /* if interrupt is shared, return failure */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li psm_rval = (*psm_intr_ops)(rdip, hdlp,
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li PSM_INTR_OP_GET_SHARED, &psm_status);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li /*
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li * For fixed interrupts, the irq may not have been
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li * allocated when SET_PRI is called, and the above
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li * GET_SHARED op may return PSM_FAILURE. This is not
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li * a real error and is ignored below.
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li if ((psm_rval != PSM_FAILURE) && (psm_status == 1)) {
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li DDI_INTR_NEXDBG((CE_CONT,
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li "pci_common_intr_ops: "
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li "dip 0x%p cannot setpri, psm_rval=%d,"
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li "psm_status=%d\n", (void *)rdip, psm_rval,
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li psm_status));
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li return (DDI_FAILURE);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li }
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li }
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Change the priority */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) ==
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_FAILURE)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update ispec */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ispec->intrspec_pri = *(int *)result;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_ADDISR:
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update ispec */
70025d765b044c6d8594bb965a2247a61e991a99johnny isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)isp;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz if (ispec) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec->intrspec_func = hdlp->ih_cb_func;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz pci_kstat_create(&ihdl_plat_datap->ip_ksp, pdip, hdlp);
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_REMISR:
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Get the interrupt structure pointer */
70025d765b044c6d8594bb965a2247a61e991a99johnny isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)isp;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz if (ispec) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec->intrspec_func = (uint_t (*)()) 0;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz if (ihdl_plat_datap->ip_ksp != NULL)
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz pci_kstat_delete(ihdl_plat_datap->ip_ksp);
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_GETCAP:
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * First check the config space and/or
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI capability register(s)
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rval = pci_msi_get_cap(rdip, hdlp->ih_type,
70025d765b044c6d8594bb965a2247a61e991a99johnny &pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rval = pci_intx_get_cap(rdip, &pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* next check with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops != NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval = (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_GET_CAP, &psm_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned psm_rval = %x, "
70025d765b044c6d8594bb965a2247a61e991a99johnny "psm_status = %x, pci_rval = %x, pci_status = %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval, psm_status, pci_rval, pci_status));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = psm_status;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_rval == DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result |= pci_status;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned = %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result));
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_SETCAP:
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
70025d765b044c6d8594bb965a2247a61e991a99johnny "SETCAP cap=0x%x\n", *(int *)result));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "GETCAP: psm_intr_ops"
70025d765b044c6d8594bb965a2247a61e991a99johnny " returned failure\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_ENABLE:
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: ENABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_enable_intr(pdip, rdip, hdlp, hdlp->ih_inum) !=
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: ENABLE "
70025d765b044c6d8594bb965a2247a61e991a99johnny "vector=0x%x\n", hdlp->ih_vector));
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_DISABLE:
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: DISABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: DISABLE "
70025d765b044c6d8594bb965a2247a61e991a99johnny "vector = %x\n", hdlp->ih_vector));
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_BLOCKENABLE:
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
70025d765b044c6d8594bb965a2247a61e991a99johnny "BLOCKENABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: not MSI\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Check if psm_intr_ops is NULL? */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny count = hdlp->ih_scratch1;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny h_array = (ddi_intr_handle_t *)hdlp->ih_scratch2;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (i = 0; i < count; i++) {
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny hdlp = (ddi_intr_handle_impl_t *)h_array[i];
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_enable_intr(pdip, rdip, hdlp,
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny hdlp->ih_inum) != DDI_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: "
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_enable_intr failed for %d\n", i));
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (j = 0; j < i; j++) {
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz hdlp = (ddi_intr_handle_impl_t *)
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz h_array[j];
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz pci_disable_intr(pdip, rdip, hdlp,
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny hdlp->ih_inum);
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny "BLOCKENABLE inum %x done\n", hdlp->ih_inum));
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_BLOCKDISABLE:
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
70025d765b044c6d8594bb965a2247a61e991a99johnny "BLOCKDISABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "BLOCKDISABLE: not MSI\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Check if psm_intr_ops is present */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny count = hdlp->ih_scratch1;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny h_array = (ddi_intr_handle_t *)hdlp->ih_scratch2;
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (i = 0; i < count; i++) {
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny hdlp = (ddi_intr_handle_impl_t *)h_array[i];
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny "BLOCKDISABLE inum %x done\n", hdlp->ih_inum));
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_SETMASK:
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_CLRMASK:
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * First handle in the config space
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (intr_op == DDI_INTROP_SETMASK) {
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status = pci_msi_set_mask(rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_type, hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status = pci_intx_set_mask(rdip);
70025d765b044c6d8594bb965a2247a61e991a99johnny } else {
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status = pci_msi_clr_mask(rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_type, hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status = pci_intx_clr_mask(rdip);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* For MSI/X; no need to check with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* For fixed interrupts only: handle config space first */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hdlp->ih_type == DDI_INTR_TYPE_FIXED &&
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status == DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* For fixed interrupts only: confer with PSM module next */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_intr_ops != NULL) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /* If interrupt is shared; do nothing */
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval = (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_GET_SHARED, &psm_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_FAILURE || psm_status == 1)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Now, PSM module should try to set/clear the mask */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (intr_op == DDI_INTROP_SETMASK)
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval = (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_SET_MASK, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny else
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval = (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_CLEAR_MASK, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny return ((psm_rval == PSM_FAILURE) ? DDI_FAILURE : DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_INTROP_GETPENDING:
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * First check the config space and/or
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI capability register(s)
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rval = pci_msi_get_pending(rdip, hdlp->ih_type,
70025d765b044c6d8594bb965a2247a61e991a99johnny hdlp->ih_inum, &pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rval = pci_intx_get_pending(rdip, &pci_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* On failure; next try with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_rval != DDI_SUCCESS && psm_intr_ops != NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny psm_rval = (*psm_intr_ops)(rdip, hdlp,
70025d765b044c6d8594bb965a2247a61e991a99johnny PSM_INTR_OP_GET_PENDING, &psm_status);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned "
70025d765b044c6d8594bb965a2247a61e991a99johnny "psm_rval = %x, psm_status = %x, pci_rval = %x, "
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_status = %x\n", psm_rval, psm_status, pci_rval,
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_status));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval != PSM_FAILURE)
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = psm_status;
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (pci_rval != DDI_FAILURE)
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = pci_status;
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned = %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result));
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan case DDI_INTROP_GETTARGET:
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: GETTARGET\n"));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bcopy(hdlp, &tmp_hdl, sizeof (ddi_intr_handle_impl_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tmp_hdl.ih_private = (void *)&intrinfo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrinfo.avgi_req_flags = PSMGI_INTRBY_DEFAULT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrinfo.avgi_req_flags |= PSMGI_REQ_CPUID;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_GET_INTR,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases NULL) == PSM_FAILURE)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *(int *)result = intrinfo.avgi_cpu_id;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: GETTARGET "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "vector = 0x%x, cpu = 0x%x\n", hdlp->ih_vector,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *(int *)result));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan break;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan case DDI_INTROP_SETTARGET:
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: SETTARGET\n"));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bcopy(hdlp, &tmp_hdl, sizeof (ddi_intr_handle_impl_t));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan tmp_hdl.ih_private = (void *)(uintptr_t)*(int *)result;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tmp_hdl.ih_flags = PSMGI_INTRBY_DEFAULT;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_SET_CPU,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases &psm_status) == PSM_FAILURE)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hdlp->ih_vector = tmp_hdl.ih_vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: SETTARGET "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "vector = 0x%x\n", hdlp->ih_vector));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case DDI_INTROP_GETPOOL:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * For MSI/X interrupts use global IRM pool if available.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_irm_pool_p && DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *(ddi_irm_pool_t **)result = apix_irm_pool_p;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_SUCCESS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_ENOTSUP);
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Allocate a vector for FIXED type interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasespci_alloc_intr_fixed(dev_info_t *pdip, dev_info_t *rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t *hdlp, void *result)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct intrspec *ispec;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t info_hdl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int free_phdl = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int pci_rval;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int pci_status = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_get_type_t type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (psm_intr_ops == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Figure out if this device supports MASKING */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_rval = pci_intx_get_cap(rdip, &pci_status);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (pci_rval == DDI_SUCCESS && pci_status)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hdlp->ih_cap |= pci_status;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If the PSM module is "APIX" then pass the request for
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * allocating the vector now.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases info_hdl.ih_private = &type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) ==
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (int)hdlp->ih_inum);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ispec == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (hdlp->ih_private == NULL) { /* allocate phdl structure */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases free_phdl = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i_ddi_alloc_intr_phdl(hdlp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = (*psm_intr_ops)(rdip, hdlp,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_ALLOC_VECTORS, result);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (free_phdl) { /* free up the phdl structure */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases free_phdl = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i_ddi_free_intr_phdl(hdlp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hdlp->ih_private = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * No APIX module; fall back to the old scheme where the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupt vector is allocated during ddi_enable_intr() call.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *(int *)result = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = DDI_SUCCESS;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ret);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Free up the vector for FIXED (legacy) type interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasespci_free_intr_fixed(dev_info_t *pdip, dev_info_t *rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t *hdlp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct intrspec *ispec;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_handle_impl_t info_hdl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_get_type_t type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (psm_intr_ops == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If the PSM module is "APIX" then pass the request to it
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to free up the vector now.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases info_hdl.ih_private = &type_info;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) ==
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (int)hdlp->ih_inum);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ispec == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = (*psm_intr_ops)(rdip, hdlp,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PSM_INTR_OP_FREE_VECTORS, NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * No APIX module; fall back to the old scheme where
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the interrupt vector was already freed during
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * ddi_disable_intr() call.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = DDI_SUCCESS;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ret);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzint
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzpci_get_intr_from_vecirq(apic_get_intr_t *intrinfo_p,
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz int vecirq, boolean_t is_irq)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz{
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ddi_intr_handle_impl_t get_info_ii_hdl;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz if (is_irq)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz intrinfo_p->avgi_req_flags |= PSMGI_INTRBY_IRQ;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz /*
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz * For this locally-declared and used handle, ih_private will contain a
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz * pointer to apic_get_intr_t, not an ihdl_plat_t as used for
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz * global interrupt handling.
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz */
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz get_info_ii_hdl.ih_private = intrinfo_p;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases get_info_ii_hdl.ih_vector = vecirq;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz if ((*psm_intr_ops)(NULL, &get_info_ii_hdl,
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz PSM_INTR_OP_GET_INTR, NULL) == PSM_FAILURE)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz return (DDI_FAILURE);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz return (DDI_SUCCESS);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz}
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzint
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzpci_get_cpu_from_vecirq(int vecirq, boolean_t is_irq)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz{
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz int rval;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz apic_get_intr_t intrinfo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz intrinfo.avgi_req_flags = PSMGI_REQ_CPUID;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz rval = pci_get_intr_from_vecirq(&intrinfo, vecirq, is_irq);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz if (rval == DDI_SUCCESS)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz return (intrinfo.avgi_cpu_id);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz else
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz return (-1);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz}
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_enable_intr(dev_info_t *pdip, dev_info_t *rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *hdlp, uint32_t inum)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny struct intrspec *ispec;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz int irq;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: hdlp %p inum %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny (void *)hdlp, inum));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Translate the interrupt if needed */
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
8d9a0e261bb03582e0aca67948093672188be6caanish if (ispec == NULL)
8d9a0e261bb03582e0aca67948093672188be6caanish return (DDI_FAILURE);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec->intrspec_vec = inum;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ispec->intrspec_pri = hdlp->ih_pri;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li }
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_datap->ip_ispecp = ispec;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* translate the interrupt if needed */
86a9c507121ec77a92601d8844a5ca82373cd4aaGuoli Shu if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq) ==
86a9c507121ec77a92601d8844a5ca82373cd4aaGuoli Shu PSM_FAILURE)
86a9c507121ec77a92601d8844a5ca82373cd4aaGuoli Shu return (DDI_FAILURE);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x irq=%x\n",
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz hdlp->ih_pri, irq));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Add the interrupt handler */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func,
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz DEVI(rdip)->devi_name, irq, hdlp->ih_cb_arg1,
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz hdlp->ih_cb_arg2, &ihdl_plat_datap->ip_ticks, rdip))
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hdlp->ih_vector = irq;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic void
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_disable_intr(dev_info_t *pdip, dev_info_t *rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *hdlp, uint32_t inum)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz int irq;
70025d765b044c6d8594bb965a2247a61e991a99johnny struct intrspec *ispec;
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_disable_intr: \n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
8d9a0e261bb03582e0aca67948093672188be6caanish if (ispec == NULL)
8d9a0e261bb03582e0aca67948093672188be6caanish return;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec->intrspec_vec = inum;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ispec->intrspec_pri = hdlp->ih_pri;
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li }
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_datap->ip_ispecp = ispec;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* translate the interrupt if needed */
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Disable the interrupt handler */
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, irq);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_datap->ip_ispecp = NULL;
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Miscellaneous library function
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int i;
70025d765b044c6d8594bb965a2247a61e991a99johnny int number;
70025d765b044c6d8594bb965a2247a61e991a99johnny int assigned_addr_len;
70025d765b044c6d8594bb965a2247a61e991a99johnny uint_t phys_hi = pci_rp->pci_phys_hi;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_regspec_t *assigned_addr;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (((phys_hi & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) ||
70025d765b044c6d8594bb965a2247a61e991a99johnny (phys_hi & PCI_RELOCAT_B))
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * the "reg" property specifies relocatable, get and interpret the
70025d765b044c6d8594bb965a2247a61e991a99johnny * "assigned-addresses" property.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
70025d765b044c6d8594bb965a2247a61e991a99johnny "assigned-addresses", (int **)&assigned_addr,
70025d765b044c6d8594bb965a2247a61e991a99johnny (uint_t *)&assigned_addr_len) != DDI_PROP_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Scan the "assigned-addresses" for one that matches the specified
70025d765b044c6d8594bb965a2247a61e991a99johnny * "reg" property entry.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny phys_hi &= PCI_CONF_ADDR_MASK;
70025d765b044c6d8594bb965a2247a61e991a99johnny number = assigned_addr_len / (sizeof (pci_regspec_t) / sizeof (int));
70025d765b044c6d8594bb965a2247a61e991a99johnny for (i = 0; i < number; i++) {
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((assigned_addr[i].pci_phys_hi & PCI_CONF_ADDR_MASK) ==
70025d765b044c6d8594bb965a2247a61e991a99johnny phys_hi) {
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(assigned_addr);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(assigned_addr);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * To handle PCI tool ioctls
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_ioctl(dev_info_t *dip, dev_t dev, int cmd, intptr_t arg,
70025d765b044c6d8594bb965a2247a61e991a99johnny int mode, cred_t *credp, int *rvalp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
269473047d747f7815af570197e4ef7322d3632cEvan Yan minor_t minor = getminor(dev);
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = ENOTTY;
70025d765b044c6d8594bb965a2247a61e991a99johnny
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_TOOL_REG_MINOR_NUM:
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (cmd) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_DEVICE_SET_REG:
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_DEVICE_GET_REG:
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require full privileges. */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (secpolicy_kmdb(credp))
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = EPERM;
70025d765b044c6d8594bb965a2247a61e991a99johnny else
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = pcitool_dev_reg_ops(dip, (void *)arg,
70025d765b044c6d8594bb965a2247a61e991a99johnny cmd, mode);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_NEXUS_SET_REG:
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_NEXUS_GET_REG:
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require full privileges. */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (secpolicy_kmdb(credp))
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = EPERM;
70025d765b044c6d8594bb965a2247a61e991a99johnny else
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = pcitool_bus_reg_ops(dip, (void *)arg,
70025d765b044c6d8594bb965a2247a61e991a99johnny cmd, mode);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_TOOL_INTR_MINOR_NUM:
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (cmd) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_DEVICE_SET_INTR:
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require PRIV_SYS_RES_CONFIG, same as psradm */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (secpolicy_ponline(credp)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = EPERM;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*FALLTHRU*/
70025d765b044c6d8594bb965a2247a61e991a99johnny /* These require no special privileges. */
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCITOOL_DEVICE_GET_INTR:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz case PCITOOL_SYSTEM_INTR_INFO:
70025d765b044c6d8594bb965a2247a61e991a99johnny rv = pcitool_intr_admn(dip, (void *)arg, cmd, mode);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (rv);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetint
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_common_ctlops_poke(peekpoke_ctlops_t *in_args)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t size = in_args->size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uintptr_t dev_addr = in_args->dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uintptr_t host_addr = in_args->host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_hdl_t *hdlp = (ddi_acc_hdl_t *)in_args->handle;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t repcount = in_args->repcount;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint_t flags = in_args->flags;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int err = DDI_SUCCESS;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * if no handle then this is a poke. We have to return failure here
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * as we have no way of knowing whether this is a MEM or IO space access
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (in_args->handle == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FAILURE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * rest of this function is actually for cautious puts
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (; repcount; repcount--) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ahi_acc_attr == DDI_ACCATTR_CONFIG_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_wr8(hp, (uint8_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_wr16(hp, (uint16_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_wr32(hp, (uint32_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pci_config_wr64(hp, (uint64_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hdlp->ah_acc.devacc_attr_endian_flags ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_STRUCTURE_BE_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put8(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint8_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_swap_put16(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint16_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_swap_put32(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint32_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * note the 64-bit case is a dummy
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * function - so no need to swap
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put64(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put8(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint8_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put16(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint16_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put32(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint32_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_put64(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t *)dev_addr,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hdlp->ah_acc.devacc_attr_endian_flags ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_STRUCTURE_BE_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap16(*(uint16_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap32(*(uint32_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap64(*(uint64_t *)host_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)dev_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet host_addr += size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (flags == DDI_DEV_AUTOINCR)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet dev_addr += size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetint
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_acc_setup(ddi_acc_hdl_t *hp, off_t offset, off_t len)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_impl_t *ap = (ddi_acc_impl_t *)hp->ah_platform_private;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* endian-ness check */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FAILURE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * range check
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if ((offset >= PCI_CONF_HDR_SIZE) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (len > PCI_CONF_HDR_SIZE) ||
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (offset + len > PCI_CONF_HDR_SIZE))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FAILURE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_acc_attr |= DDI_ACCATTR_CONFIG_SPACE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * always use cautious mechanism for config space gets
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_get8 = i_ddi_caut_get8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_get16 = i_ddi_caut_get16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_get32 = i_ddi_caut_get32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_get64 = i_ddi_caut_get64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_get8 = i_ddi_caut_rep_get8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_get16 = i_ddi_caut_rep_get16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_get32 = i_ddi_caut_rep_get32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_get64 = i_ddi_caut_rep_get64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ah_acc.devacc_attr_access == DDI_CAUTIOUS_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put8 = i_ddi_caut_put8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put16 = i_ddi_caut_put16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put32 = i_ddi_caut_put32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put64 = i_ddi_caut_put64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put8 = i_ddi_caut_rep_put8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put16 = i_ddi_caut_rep_put16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put32 = i_ddi_caut_rep_put32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put64 = i_ddi_caut_rep_put64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put8 = pci_config_wr8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put16 = pci_config_wr16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put32 = pci_config_wr32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_put64 = pci_config_wr64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put8 = pci_config_rep_wr8;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put16 = pci_config_rep_wr16;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put32 = pci_config_rep_wr32;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_rep_put64 = pci_config_rep_wr64;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Initialize to default check/notify functions */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_fault_check = i_ddi_acc_fault_check;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_fault_notify = i_ddi_acc_fault_notify;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ap->ahi_fault = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet impl_acc_err_init(hp);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_SUCCESS);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetint
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_common_ctlops_peek(peekpoke_ctlops_t *in_args)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t size = in_args->size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uintptr_t dev_addr = in_args->dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uintptr_t host_addr = in_args->host_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_hdl_t *hdlp = (ddi_acc_hdl_t *)in_args->handle;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t repcount = in_args->repcount;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint_t flags = in_args->flags;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int err = DDI_SUCCESS;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * if no handle then this is a peek. We have to return failure here
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * as we have no way of knowing whether this is a MEM or IO space access
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (in_args->handle == NULL)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (DDI_FAILURE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet for (; repcount; repcount--) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ahi_acc_attr == DDI_ACCATTR_CONFIG_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr = pci_config_rd8(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint8_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr = pci_config_rd16(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint16_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr = pci_config_rd32(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint32_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr = pci_config_rd64(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hdlp->ah_acc.devacc_attr_endian_flags ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_STRUCTURE_BE_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get8(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint8_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_swap_get16(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint16_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_swap_get32(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint32_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * note the 64-bit case is a dummy
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * function - so no need to swap
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get64(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get8(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint8_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get16(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint16_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get32(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint32_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet i_ddi_io_get64(hp,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (uint64_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hdlp->ah_acc.devacc_attr_endian_flags ==
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet DDI_STRUCTURE_BE_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (in_args->size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap16(*(uint16_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap32(*(uint32_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_swap64(*(uint64_t *)dev_addr);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (in_args->size) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint8_t *)dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint16_t *)dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint32_t *)dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)host_addr =
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *(uint64_t *)dev_addr;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet err = DDI_FAILURE;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet break;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet host_addr += size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (flags == DDI_DEV_AUTOINCR)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet dev_addr += size;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (err);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetint
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_common_peekpoke(dev_info_t *dip, dev_info_t *rdip,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_ctl_enum_t ctlop, void *arg, void *result)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (ctlop == DDI_CTLOPS_PEEK)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (pci_common_ctlops_peek((peekpoke_ctlops_t *)arg));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (pci_common_ctlops_poke((peekpoke_ctlops_t *)arg));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish/*
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * These are the get and put functions to be shared with drivers. The
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * mutex locking is done inside the functions referenced, rather than
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * here, and is thus shared across PCI child drivers and any other
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * consumers of PCI config space (such as the ACPI subsystem).
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * The configuration space addresses come in as pointers. This is fine on
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * a 32-bit system, where the VM space and configuration space are the same
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * size. It's not such a good idea on a 64-bit system, where memory
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * addresses are twice as large as configuration space addresses. At some
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * point in the call tree we need to take a stand and say "you are 32-bit
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish * from this time forth", and this seems like a nice self-contained place.
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish */
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishuint8_t
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint8_t rval;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish return (rval);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint8_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint8_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd8(hdlp, d++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd8(hdlp, d);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishuint16_t
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint16_t rval;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish return (rval);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint16_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint16_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd16(hdlp, d++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd16(hdlp, d);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishuint32_t
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t rval;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp->c_funcnum, reg);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish return (rval);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd32(hdlp, d++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *h++ = pci_config_rd32(hdlp, d);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish (*pci_putb_func)(cfp->c_busnum, cfp->c_devnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp->c_funcnum, reg, value);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint8_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint8_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr8(hdlp, d++, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr8(hdlp, d, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish (*pci_putw_func)(cfp->c_busnum, cfp->c_devnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp->c_funcnum, reg, value);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint16_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint16_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr16(hdlp, d++, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr16(hdlp, d, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_acc_cfblk_t *cfp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish int reg;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish ASSERT64(((uintptr_t)addr >> 32) == 0);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish reg = (int)(uintptr_t)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish (*pci_putl_func)(cfp->c_busnum, cfp->c_devnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp->c_funcnum, reg, value);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *h, *d;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish h = host_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish d = dev_addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr32(hdlp, d++, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish else
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr32(hdlp, d, *h++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishuint64_t
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t lw_val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t hi_val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *dp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint64_t val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish dp = (uint32_t *)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish lw_val = pci_config_rd32(hdlp, dp);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish dp++;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish hi_val = pci_config_rd32(hdlp, dp);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish val = ((uint64_t)hi_val << 32) | lw_val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish return (val);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t lw_val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t hi_val;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint32_t *dp;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish dp = (uint32_t *)addr;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish lw_val = (uint32_t)(value & 0xffffffff);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish hi_val = (uint32_t)(value >> 32);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr32(hdlp, dp, lw_val);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish dp++;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr32(hdlp, dp, hi_val);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint64_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR) {
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *host_addr++ = pci_config_rd64(hdlp, dev_addr++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish } else {
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish *host_addr++ = pci_config_rd64(hdlp, dev_addr);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish }
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishvoid
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish uint64_t *dev_addr, size_t repcount, uint_t flags)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish{
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish if (flags == DDI_DEV_AUTOINCR) {
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr64(hdlp, host_addr++, *dev_addr++);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish } else {
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish for (; repcount; repcount--)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish pci_config_wr64(hdlp, host_addr++, *dev_addr);
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish }
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish}