70025d765b044c6d8594bb965a2247a61e991a99johnny * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
70025d765b044c6d8594bb965a2247a61e991a99johnny * See the License for the specific language governing permissions
70025d765b044c6d8594bb965a2247a61e991a99johnny * and limitations under the License.
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 * CDDL HEADER END
5cd376e8b7030707d78315f63adb4bb2b4d9963eJimmy Vetayases * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
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 * Function prototypes
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 *,
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic void pci_disable_intr(dev_info_t *, dev_info_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int pci_alloc_intr_fixed(dev_info_t *, dev_info_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int pci_free_intr_fixed(dev_info_t *, dev_info_t *,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Extern declarations for PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnnyextern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_name_child:
70025d765b044c6d8594bb965a2247a61e991a99johnny * Assign the address portion of the node name
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_name_child(dev_info_t *child, char *name, int namelen)
70025d765b044c6d8594bb965a2247a61e991a99johnny * For .conf node, use "unit-address" property
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "cannot find unit-address in %s.conf",
70025d765b044c6d8594bb965a2247a61e991a99johnny if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
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 /* copy the device identifications */
70025d765b044c6d8594bb965a2247a61e991a99johnny * free the memory allocated by ddi_prop_lookup_int_array
70025d765b044c6d8594bb965a2247a61e991a99johnny if (func != 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny * Interrupt related code:
70025d765b044c6d8594bb965a2247a61e991a99johnny * The following busop is common to npe and pci drivers
70025d765b044c6d8594bb965a2247a61e991a99johnny * bus_introp
70025d765b044c6d8594bb965a2247a61e991a99johnny * Create the ddi_parent_private_data for a pseudo child.
70025d765b044c6d8594bb965a2247a61e991a99johnny pdptr = (struct ddi_parent_private_data *)kmem_zalloc(
70025d765b044c6d8594bb965a2247a61e991a99johnny (sizeof (struct ddi_parent_private_data) +
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_get_priority:
70025d765b044c6d8594bb965a2247a61e991a99johnny * Figure out the priority of the device
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_get_priority(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, int *pri)
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_get_priority: dip = 0x%p, hdlp = %p\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip,
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip,
70025d765b044c6d8594bb965a2247a61e991a99johnny * pci_common_intr_ops: bus_intr_op() function for interrupt support
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_common_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Process the request */
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
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Fixed supported by default */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta /* Sanity test cap control values if found */
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI, &msi_cap_base) ==
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI_X, &msix_cap_base) ==
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Filter device-level types through system-level support
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_CHECK_MSI,
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Export any MSI/MSI-X cap locations via properties
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish if (*(int *)result == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (pci_alloc_intr_fixed(pdip, rdip, hdlp, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI or MSIX (figure out number of vectors available)
70025d765b044c6d8594bb965a2247a61e991a99johnny (pci_get_priority(rdip, hdlp, &priority) == DDI_SUCCESS)) {
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.
d4bc0535efa2c2219e9f83246a5f371dc7f94273Krishna Elango if (strcmp(ddi_driver_name(rdip), "pcieb") == 0) {
d12abe7ce2663ac39e686a14960eb4febf560195anish * Cache in the config handle and cap_ptr
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Enforce the calling of DDI_INTROP_SUPPORTED_TYPES
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * for MSI(X) before allocation
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta if (cap_ptr == 0) {
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "pci_common_intr_ops: rdip: 0x%p "
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta "attempted MSI(X) alloc without "
600d77457b335b6f448f13d5f33bf7e70dfbb39djveta * Allocate interrupt vectors
1ac1709f7b6fe803d662ea7ee6a6885182bfb2e1anish if (*(int *)result == 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny /* verify behavior flag and take appropriate action */
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_common_intr_ops: behavior %x, "
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China if (msix_p) {
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 (void) (*psm_intr_ops)(rdip,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China PSM_INTR_OP_FREE_VECTORS,
fbb8dc2c3d5adc161fd7801c9c61776528ca600blipeng sang - Sun Microsystems - Beijing China return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update priority in ispec */
6856520054585a7305203963c518444732a57448anish if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1 ==
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (pci_free_intr_fixed(pdip, rdip, hdlp));
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Get the priority */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_get_priority(rdip, hdlp, &priority) != DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Validate the interrupt priority passed */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Ensure that PSM is all initialized */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li /* For fixed interrupts */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li /* if interrupt is shared, return failure */
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
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 if ((psm_rval != PSM_FAILURE) && (psm_status == 1)) {
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li "pci_common_intr_ops: "
96f82fef09bdebba70a409640c49772b1cdf1a2aSophia Li "dip 0x%p cannot setpri, psm_rval=%d,"
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Change the priority */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) ==
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update ispec */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* update ispec */
70025d765b044c6d8594bb965a2247a61e991a99johnny isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
e1d9f4e6832768425b218c917c09c9afaed8ae36schwartz pci_kstat_create(&ihdl_plat_datap->ip_ksp, pdip, hdlp);
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Get the interrupt structure pointer */
70025d765b044c6d8594bb965a2247a61e991a99johnny isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny * First check the config space and/or
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI capability register(s)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* next check with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned psm_rval = %x, "
70025d765b044c6d8594bb965a2247a61e991a99johnny "psm_status = %x, pci_rval = %x, pci_status = %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned = %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny " returned failure\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: ENABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_enable_intr(pdip, rdip, hdlp, hdlp->ih_inum) !=
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: ENABLE "
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: DISABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: DISABLE "
70025d765b044c6d8594bb965a2247a61e991a99johnny "BLOCKENABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: not MSI\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Check if psm_intr_ops is NULL? */
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (i = 0; i < count; i++) {
70025d765b044c6d8594bb965a2247a61e991a99johnny "pci_enable_intr failed for %d\n", i));
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (j = 0; j < i; j++) {
70025d765b044c6d8594bb965a2247a61e991a99johnny "BLOCKDISABLE\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "BLOCKDISABLE: not MSI\n"));
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Check if psm_intr_ops is present */
102cb92e8d0279f358afd8cc24b05e4032ac0644johnny for (i = 0; i < count; i++) {
70025d765b044c6d8594bb965a2247a61e991a99johnny * First handle in the config space
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* For MSI/X; no need to check with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* For fixed interrupts only: handle config space first */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* For fixed interrupts only: confer with PSM module next */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* If interrupt is shared; do nothing */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Now, PSM module should try to set/clear the mask */
70025d765b044c6d8594bb965a2247a61e991a99johnny return ((psm_rval == PSM_FAILURE) ? DDI_FAILURE : DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny * First check the config space and/or
70025d765b044c6d8594bb965a2247a61e991a99johnny * MSI capability register(s)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* On failure; next try with PSM module */
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned "
70025d765b044c6d8594bb965a2247a61e991a99johnny "psm_rval = %x, psm_status = %x, pci_rval = %x, "
70025d765b044c6d8594bb965a2247a61e991a99johnny if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned = %x\n",
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: GETTARGET\n"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bcopy(hdlp, &tmp_hdl, sizeof (ddi_intr_handle_impl_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrinfo.avgi_req_flags = PSMGI_INTRBY_DEFAULT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_GET_INTR,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: GETTARGET "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "vector = 0x%x, cpu = 0x%x\n", hdlp->ih_vector,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: SETTARGET\n"));
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 if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_SET_CPU,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: SETTARGET "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * For MSI/X interrupts use global IRM pool if available.
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;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Allocate a vector for FIXED type interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasespci_alloc_intr_fixed(dev_info_t *pdip, dev_info_t *rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Figure out if this device supports MASKING */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_rval = pci_intx_get_cap(rdip, &pci_status);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If the PSM module is "APIX" then pass the request for
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * allocating the vector now.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
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 if (hdlp->ih_private == NULL) { /* allocate phdl structure */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (free_phdl) { /* free up the phdl structure */
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 * Free up the vector for FIXED (legacy) type interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasespci_free_intr_fixed(dev_info_t *pdip, dev_info_t *rdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If the PSM module is "APIX" then pass the request to it
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to free up the vector now.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
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 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
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.
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzpci_get_intr_from_vecirq(apic_get_intr_t *intrinfo_p,
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.
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartzpci_get_cpu_from_vecirq(int vecirq, boolean_t is_irq)
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz rval = pci_get_intr_from_vecirq(&intrinfo, vecirq, is_irq);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz return (-1);
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: hdlp %p inum %x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Translate the interrupt if needed */
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny /* translate the interrupt if needed */
86a9c507121ec77a92601d8844a5ca82373cd4aaGuoli Shu if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq) ==
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x irq=%x\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Add the interrupt handler */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func,
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz hdlp->ih_cb_arg2, &ihdl_plat_datap->ip_ticks, rdip))
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private;
70025d765b044c6d8594bb965a2247a61e991a99johnny ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
70025d765b044c6d8594bb965a2247a61e991a99johnny /* translate the interrupt if needed */
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq);
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Disable the interrupt handler */
7a364d25fde47aa82704b12b5251bf7fac37f02eschwartz rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, irq);
70025d765b044c6d8594bb965a2247a61e991a99johnny * Miscellaneous library function
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp)
70025d765b044c6d8594bb965a2247a61e991a99johnny if (((phys_hi & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) ||
70025d765b044c6d8594bb965a2247a61e991a99johnny * the "reg" property specifies relocatable, get and interpret the
70025d765b044c6d8594bb965a2247a61e991a99johnny * "assigned-addresses" property.
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
70025d765b044c6d8594bb965a2247a61e991a99johnny * Scan the "assigned-addresses" for one that matches the specified
70025d765b044c6d8594bb965a2247a61e991a99johnny * "reg" property entry.
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 pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low;
269473047d747f7815af570197e4ef7322d3632cEvan Yan * To handle PCI tool ioctls
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
70025d765b044c6d8594bb965a2247a61e991a99johnnypci_common_ioctl(dev_info_t *dip, dev_t dev, int cmd, intptr_t arg,
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require full privileges. */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require full privileges. */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Require PRIV_SYS_RES_CONFIG, same as psradm */
70025d765b044c6d8594bb965a2247a61e991a99johnny /*FALLTHRU*/
70025d765b044c6d8594bb965a2247a61e991a99johnny /* These require no special privileges. */
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 * 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 * rest of this function is actually for cautious puts
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ahi_acc_attr == DDI_ACCATTR_CONFIG_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * note the 64-bit case is a dummy
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * function - so no need to swap
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_fm_acc_setup(ddi_acc_hdl_t *hp, off_t offset, off_t len)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet ddi_acc_impl_t *ap = (ddi_acc_impl_t *)hp->ah_platform_private;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* endian-ness check */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * range check
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * always use cautious mechanism for config space gets
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (hp->ah_acc.devacc_attr_access == DDI_CAUTIOUS_ACC) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* Initialize to default check/notify functions */
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 * 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 if (hp->ahi_acc_attr == DDI_ACCATTR_CONFIG_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } else if (hp->ahi_acc_attr & DDI_ACCATTR_IO_SPACE) {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * note the 64-bit case is a dummy
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * function - so no need to swap
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint8_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint16_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint32_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case sizeof (uint64_t):
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*ARGSUSED*/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetpci_common_peekpoke(dev_info_t *dip, dev_info_t *rdip,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (pci_common_ctlops_peek((peekpoke_ctlops_t *)arg));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return (pci_common_ctlops_poke((peekpoke_ctlops_t *)arg));
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 * 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 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anish cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
649d4cce0c8ba57f2c399df82be95a0395cfeef2anishpci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,