npe.c revision 70025d765b044c6d8594bb965a2247a61e991a99
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * CDDL HEADER START
70025d765b044c6d8594bb965a2247a61e991a99johnny *
70025d765b044c6d8594bb965a2247a61e991a99johnny * The contents of this file are subject to the terms of the
70025d765b044c6d8594bb965a2247a61e991a99johnny * Common Development and Distribution License, Version 1.0 only
70025d765b044c6d8594bb965a2247a61e991a99johnny * (the "License"). You may not use this file except in compliance
70025d765b044c6d8594bb965a2247a61e991a99johnny * 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/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
70025d765b044c6d8594bb965a2247a61e991a99johnny * Use is subject to license terms.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny#pragma ident "%Z%%M% %I% %E% SMI"
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Host to PCI-Express local bus driver
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/conf.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/modctl.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/pcie.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/pci_impl.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/sysmacros.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/ddi_intr.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/sunndi.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <sys/hotplug/pci/pcihp.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_common.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_tools_ext.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pci/pci_var.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <io/pciex/pcie_error.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Bus Operation functions
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
70025d765b044c6d8594bb965a2247a61e991a99johnny off_t, off_t, caddr_t *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
70025d765b044c6d8594bb965a2247a61e991a99johnny void *, void *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_intr_handle_impl_t *, void *);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystruct bus_ops npe_bus_ops = {
70025d765b044c6d8594bb965a2247a61e991a99johnny BUSO_REV,
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_bus_map,
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL,
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL,
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL,
70025d765b044c6d8594bb965a2247a61e991a99johnny i_ddi_map_fault,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_map,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_allochdl,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_freehdl,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_bindhdl,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_unbindhdl,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_flush,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_win,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_dma_mctl,
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_ctlops,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_bus_prop_op,
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_get_eventcookie)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_add_eventcall)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_remove_eventcall)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_post_event)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_intr_ctl)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_config)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* (*bus_unconfig)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* (*bus_fm_init)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* (*bus_fm_fini)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* (*bus_fm_access_enter)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* (*bus_fm_access_exit)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* (*bus_power)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_intr_ops /* (*bus_intr_op)(); */
70025d765b044c6d8594bb965a2247a61e991a99johnny};
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * One goal here is to leverage off of the pcihp.c source without making
70025d765b044c6d8594bb965a2247a61e991a99johnny * changes to it. Call into it's cb_ops directly if needed, piggybacking
70025d765b044c6d8594bb965a2247a61e991a99johnny * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
70025d765b044c6d8594bb965a2247a61e991a99johnny * will be using the PCI devctl node.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_open(dev_t *, int, int, cred_t *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_close(dev_t, int, int, cred_t *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
70025d765b044c6d8594bb965a2247a61e991a99johnny caddr_t, int *);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystruct cb_ops npe_cb_ops = {
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_open, /* open */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_close, /* close */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* strategy */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* print */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* dump */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* read */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* write */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_ioctl, /* ioctl */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* devmap */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* mmap */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* segmap */
70025d765b044c6d8594bb965a2247a61e991a99johnny nochpoll, /* poll */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_prop_op, /* cb_prop_op */
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL, /* streamtab */
70025d765b044c6d8594bb965a2247a61e991a99johnny D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
70025d765b044c6d8594bb965a2247a61e991a99johnny CB_REV, /* rev */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev, /* int (*cb_aread)() */
70025d765b044c6d8594bb965a2247a61e991a99johnny nodev /* int (*cb_awrite)() */
70025d765b044c6d8594bb965a2247a61e991a99johnny};
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Device Node Operation functions
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystruct dev_ops npe_ops = {
70025d765b044c6d8594bb965a2247a61e991a99johnny DEVO_REV, /* devo_rev */
70025d765b044c6d8594bb965a2247a61e991a99johnny 0, /* refcnt */
70025d765b044c6d8594bb965a2247a61e991a99johnny pcihp_info, /* info */
70025d765b044c6d8594bb965a2247a61e991a99johnny nulldev, /* identify */
70025d765b044c6d8594bb965a2247a61e991a99johnny nulldev, /* probe */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_attach, /* attach */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_detach, /* detach */
70025d765b044c6d8594bb965a2247a61e991a99johnny nulldev, /* reset */
70025d765b044c6d8594bb965a2247a61e991a99johnny &npe_cb_ops, /* driver operations */
70025d765b044c6d8594bb965a2247a61e991a99johnny &npe_bus_ops /* bus operations */
70025d765b044c6d8594bb965a2247a61e991a99johnny};
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Internal routines in support of particular npe_ctlops.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_removechild(dev_info_t *child);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int npe_initchild(dev_info_t *child);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * External support routine
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnyextern void npe_query_acpi_mcfg(dev_info_t *dip);
70025d765b044c6d8594bb965a2247a61e991a99johnnyextern void npe_ck804_fix_aer_ptr(dev_info_t *child);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Module linkage information for the kernel.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic struct modldrv modldrv = {
70025d765b044c6d8594bb965a2247a61e991a99johnny &mod_driverops, /* Type of module */
70025d765b044c6d8594bb965a2247a61e991a99johnny "Host to PCIe nexus driver %I%",
70025d765b044c6d8594bb965a2247a61e991a99johnny &npe_ops, /* driver ops */
70025d765b044c6d8594bb965a2247a61e991a99johnny};
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic struct modlinkage modlinkage = {
70025d765b044c6d8594bb965a2247a61e991a99johnny MODREV_1,
70025d765b044c6d8594bb965a2247a61e991a99johnny (void *)&modldrv,
70025d765b044c6d8594bb965a2247a61e991a99johnny NULL
70025d765b044c6d8594bb965a2247a61e991a99johnny};
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/* Save minimal state. */
70025d765b044c6d8594bb965a2247a61e991a99johnnyvoid *npe_statep;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnny_init(void)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int e;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Initialize per-pci bus soft state pointer.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny e = ddi_soft_state_init(&npe_statep, sizeof (pci_state_t), 1);
70025d765b044c6d8594bb965a2247a61e991a99johnny if (e != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (e);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((e = mod_install(&modlinkage)) != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_soft_state_fini(&npe_statep);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (e);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnny_fini(void)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int rc;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = mod_remove(&modlinkage);
70025d765b044c6d8594bb965a2247a61e991a99johnny if (rc != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (rc);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_soft_state_fini(&npe_statep);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (rc);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnyint
70025d765b044c6d8594bb965a2247a61e991a99johnny_info(struct modinfo *modinfop)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny return (mod_info(&modlinkage, modinfop));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*ARGSUSED*/
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Use the minor number as constructed by pcihp, as the index value to
70025d765b044c6d8594bb965a2247a61e991a99johnny * ddi_soft_state_zalloc.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny int instance = ddi_get_instance(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_state_t *pcip = NULL;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type",
70025d765b044c6d8594bb965a2247a61e991a99johnny "pciex") != DDI_PROP_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "npe: 'device_type' prop create failed");
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_soft_state_zalloc(npe_statep, instance) == DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny pcip = ddi_get_soft_state(npe_statep, instance);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pcip == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pcip->pci_dip = devi;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Initialize hotplug support on this bus. At minimum
70025d765b044c6d8594bb965a2247a61e991a99johnny * (for non hotplug bus) this would create ":devctl" minor
70025d765b044c6d8594bb965a2247a61e991a99johnny * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
70025d765b044c6d8594bb965a2247a61e991a99johnny * to this bus.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pcihp_init(devi) != DDI_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "npe: Failed to setup hotplug framework");
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_soft_state_free(npe_statep, instance);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pcitool_init(devi, B_TRUE) != DDI_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) pcihp_uninit(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_soft_state_free(npe_statep, instance);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_query_acpi_mcfg(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_report_dev(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*ARGSUSED*/
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int instance = ddi_get_instance(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Uninitialize pcitool support. */
70025d765b044c6d8594bb965a2247a61e991a99johnny pcitool_uninit(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Uninitialize hotplug support on this bus.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) pcihp_uninit(devi);
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_soft_state_free(npe_statep, instance);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
70025d765b044c6d8594bb965a2247a61e991a99johnny off_t offset, off_t len, caddr_t *vaddrp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int rnumber;
70025d765b044c6d8594bb965a2247a61e991a99johnny int length;
70025d765b044c6d8594bb965a2247a61e991a99johnny int space;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_acc_hdl_t *hp;
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_map_req_t mr;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_regspec_t pci_reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_regspec_t *pci_rp;
70025d765b044c6d8594bb965a2247a61e991a99johnny struct regspec reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_acc_cfblk_t *cfp;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny mr = *mp; /* Get private copy of request */
70025d765b044c6d8594bb965a2247a61e991a99johnny mp = &mr;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * check for register number
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (mp->map_type) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_MT_REGSPEC:
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp = &pci_reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_MT_RNUMBER:
70025d765b044c6d8594bb965a2247a61e991a99johnny rnumber = mp->map_obj.rnumber;
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * get ALL "reg" properties for dip, select the one of
70025d765b044c6d8594bb965a2247a61e991a99johnny * of interest. In x86, "assigned-addresses" property
70025d765b044c6d8594bb965a2247a61e991a99johnny * is identical to the "reg" property, so there is no
70025d765b044c6d8594bb965a2247a61e991a99johnny * need to cross check the two to determine the physical
70025d765b044c6d8594bb965a2247a61e991a99johnny * address of the registers.
70025d765b044c6d8594bb965a2247a61e991a99johnny * This routine still performs some validity checks to
70025d765b044c6d8594bb965a2247a61e991a99johnny * make sure that everything is okay.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
70025d765b044c6d8594bb965a2247a61e991a99johnny (uint_t *)&length) != DDI_PROP_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * validate the register number.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny length /= (sizeof (pci_regspec_t) / sizeof (int));
70025d765b044c6d8594bb965a2247a61e991a99johnny if (rnumber >= length) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(pci_rp);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * copy the required entry.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_reg = pci_rp[rnumber];
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * free the memory allocated by ddi_prop_lookup_int_array
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(pci_rp);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp = &pci_reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny mp->map_type = DDI_MT_REGSPEC;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_ME_INVAL);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * check for unmap and unlock of address space
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Adjust offset and length
70025d765b044c6d8594bb965a2247a61e991a99johnny * A non-zero length means override the one in the regspec.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low += (uint_t)offset;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (len != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_size_low = len;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (space) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_IO:
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_bustype = 1;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_CONFIG:
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Just fall through */
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_MEM64:
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * MEM64 requires special treatment on map, to check
70025d765b044c6d8594bb965a2247a61e991a99johnny * that the device is below 4G. On unmap, however,
70025d765b044c6d8594bb965a2247a61e991a99johnny * we can assume that everything is OK... the map
70025d765b044c6d8594bb965a2247a61e991a99johnny * must have succeeded.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* FALLTHROUGH */
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_MEM32:
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_bustype = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_addr = pci_rp->pci_phys_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_size = pci_rp->pci_size_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny mp->map_obj.rp = &reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* check for user mapping request - not legal for Config */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_NOTE, "npe: Config mapping request from user\n");
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (space == PCI_ADDR_CONFIG) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /* Can't map config space without a handle */
70025d765b044c6d8594bb965a2247a61e991a99johnny hp = (ddi_acc_hdl_t *)mp->map_handlep;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (hp == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low = ddi_prop_get_int64(DDI_DEV_T_ANY,
70025d765b044c6d8594bb965a2247a61e991a99johnny rdip, 0, "ecfga-base-address", 0);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* record the device address for future reference */
70025d765b044c6d8594bb965a2247a61e991a99johnny cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
70025d765b044c6d8594bb965a2247a61e991a99johnny cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
70025d765b044c6d8594bb965a2247a61e991a99johnny cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
70025d765b044c6d8594bb965a2247a61e991a99johnny cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low += ((cfp->c_busnum << 20) |
70025d765b044c6d8594bb965a2247a61e991a99johnny (cfp->c_devnum) << 15 | (cfp->c_funcnum << 12));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_size_low = PCIE_CONF_HDR_SIZE;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny length = pci_rp->pci_size_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * range check
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((offset >= length) || (len > length) || (offset + len > length))
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Adjust offset and length
70025d765b044c6d8594bb965a2247a61e991a99johnny * A non-zero length means override the one in the regspec.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_phys_low += (uint_t)offset;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (len != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_rp->pci_size_low = len;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * convert the pci regsec into the generic regspec used by the
70025d765b044c6d8594bb965a2247a61e991a99johnny * parent root nexus driver.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (space) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_IO:
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_bustype = 1;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_CONFIG:
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_MEM64:
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * We can't handle 64-bit devices that are mapped above
70025d765b044c6d8594bb965a2247a61e991a99johnny * 4G or that are larger than 4G.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_rp->pci_phys_mid != 0 || pci_rp->pci_size_hi != 0)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Other than that, we can treat them as 32-bit mappings
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny /* FALLTHROUGH */
70025d765b044c6d8594bb965a2247a61e991a99johnny case PCI_ADDR_MEM32:
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_bustype = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_addr = pci_rp->pci_phys_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny reg.regspec_size = pci_rp->pci_size_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny mp->map_obj.rp = &reg;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*ARGSUSED*/
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_ctlops(dev_info_t *dip, dev_info_t *rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_ctl_enum_t ctlop, void *arg, void *result)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny int rn;
70025d765b044c6d8594bb965a2247a61e991a99johnny int totreg;
70025d765b044c6d8594bb965a2247a61e991a99johnny uint_t reglen;
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_regspec_t *drv_regp;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny switch (ctlop) {
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_REPORTDEV:
70025d765b044c6d8594bb965a2247a61e991a99johnny if (rdip == (dev_info_t *)0)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_CONT, "?PCI Express-device: %s@%s, %s%d\n",
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_node_name(rdip), ddi_get_name_addr(rdip),
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_driver_name(rdip), ddi_get_instance(rdip));
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_INITCHILD:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (npe_initchild((dev_info_t *)arg));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_UNINITCHILD:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (npe_removechild((dev_info_t *)arg));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_SIDDEV:
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_REGSIZE:
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_NREGS:
70025d765b044c6d8594bb965a2247a61e991a99johnny if (rdip == (dev_info_t *)0)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = 0;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
70025d765b044c6d8594bb965a2247a61e991a99johnny &reglen) != DDI_PROP_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ctlop == DDI_CTLOPS_NREGS)
70025d765b044c6d8594bb965a2247a61e991a99johnny *(int *)result = totreg;
70025d765b044c6d8594bb965a2247a61e991a99johnny else if (ctlop == DDI_CTLOPS_REGSIZE) {
70025d765b044c6d8594bb965a2247a61e991a99johnny rn = *(int *)arg;
70025d765b044c6d8594bb965a2247a61e991a99johnny if (rn >= totreg) {
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(drv_regp);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny *(off_t *)result = drv_regp[rn].pci_size_low;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_free(drv_regp);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny case DDI_CTLOPS_POWER:
70025d765b044c6d8594bb965a2247a61e991a99johnny {
70025d765b044c6d8594bb965a2247a61e991a99johnny power_req_t *reqp = (power_req_t *)arg;
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * We currently understand reporting of PCI_PM_IDLESPEED
70025d765b044c6d8594bb965a2247a61e991a99johnny * capability. Everything else is passed up.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((reqp->request_type == PMR_REPORT_PMCAP) &&
70025d765b044c6d8594bb965a2247a61e991a99johnny (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED))
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny default:
70025d765b044c6d8594bb965a2247a61e991a99johnny break;
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (ddi_ctlops(dip, rdip, ctlop, arg, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * npe_intr_ops
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_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 return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_initchild(dev_info_t *child)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny char name[80];
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_common_name_child(child, name, 80) != DDI_SUCCESS)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_name_addr(child, name);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Pseudo nodes indicate a prototype node with per-instance
70025d765b044c6d8594bb965a2247a61e991a99johnny * properties to be merged into the real h/w device node.
70025d765b044c6d8594bb965a2247a61e991a99johnny * The interpretation of the unit-address is DD[,F]
70025d765b044c6d8594bb965a2247a61e991a99johnny * where DD is the device id and F is the function.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ndi_dev_is_persistent_node(child) == 0) {
70025d765b044c6d8594bb965a2247a61e991a99johnny extern int pci_allow_pseudo_children;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_parent_data(child, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Try to merge the properties from this prototype
70025d765b044c6d8594bb965a2247a61e991a99johnny * node into real h/w nodes.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ndi_merge_node(child, pci_common_name_child) ==
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_SUCCESS) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Merged ok - return failure to remove the node.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_name_addr(child, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_FAILURE);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /* workaround for DDIVS to run under PCI Express */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_allow_pseudo_children) {
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * If the "interrupts" property doesn't exist,
70025d765b044c6d8594bb965a2247a61e991a99johnny * this must be the ddivs no-intr case, and it returns
70025d765b044c6d8594bb965a2247a61e991a99johnny * DDI_SUCCESS instead of DDI_FAILURE.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
70025d765b044c6d8594bb965a2247a61e991a99johnny DDI_PROP_DONTPASS, "interrupts", -1) == -1)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Create the ddi_parent_private_data for a pseudo
70025d765b044c6d8594bb965a2247a61e991a99johnny * child.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_common_set_parent_private_data(child);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * The child was not merged into a h/w node,
70025d765b044c6d8594bb965a2247a61e991a99johnny * but there's not much we can do with it other
70025d765b044c6d8594bb965a2247a61e991a99johnny * than return failure to cause the node to be removed.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_get_name(child), ddi_get_name_addr(child),
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_get_name(child));
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_name_addr(child, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_NOT_WELL_FORMED);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
70025d765b044c6d8594bb965a2247a61e991a99johnny "interrupts", -1) != -1)
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_common_set_parent_private_data(child);
70025d765b044c6d8594bb965a2247a61e991a99johnny else
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_parent_data(child, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Enable AER next pointer being displayed
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny npe_ck804_fix_aer_ptr(child);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny (void) pcie_error_init(child);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_removechild(dev_info_t *dip)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny struct ddi_parent_private_data *pdptr;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Do it way early.
70025d765b044c6d8594bb965a2247a61e991a99johnny * Otherwise ddi_map() call form pcie_error_fini crashes
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny pcie_error_fini(dip);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
70025d765b044c6d8594bb965a2247a61e991a99johnny kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_parent_data(dip, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_set_name_addr(dip, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny /*
70025d765b044c6d8594bb965a2247a61e991a99johnny * Strip the node to properly convert it back to prototype form
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_remove_minor_node(dip, NULL);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny ddi_prop_remove_all(dip);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return (DDI_SUCCESS);
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/*
70025d765b044c6d8594bb965a2247a61e991a99johnny * When retrofitting this module for pci_tools, functions such as open, close,
70025d765b044c6d8594bb965a2247a61e991a99johnny * and ioctl are now pulled into this module. Before this, the functions in
70025d765b044c6d8594bb965a2247a61e991a99johnny * the pcihp module were referenced directly. Now they are called or
70025d765b044c6d8594bb965a2247a61e991a99johnny * referenced through the pcihp cb_ops structure from functions in this module.
70025d765b044c6d8594bb965a2247a61e991a99johnny */
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_open(dev_t *devp, int flags, int otyp, cred_t *credp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_close(dev_t dev, int flags, int otyp, cred_t *credp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny minor_t minor = getminor(dev);
70025d765b044c6d8594bb965a2247a61e991a99johnny int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
70025d765b044c6d8594bb965a2247a61e991a99johnny pci_state_t *pci_p = ddi_get_soft_state(npe_statep, instance);
70025d765b044c6d8594bb965a2247a61e991a99johnny dev_info_t *dip;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pci_p == NULL)
70025d765b044c6d8594bb965a2247a61e991a99johnny return (ENXIO);
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny dip = pci_p->pci_dip;
70025d765b044c6d8594bb965a2247a61e991a99johnny return (pci_common_ioctl(dip, dev, cmd, arg, mode, credp, rvalp));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
70025d765b044c6d8594bb965a2247a61e991a99johnny int flags, char *name, caddr_t valuep, int *lengthp)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
70025d765b044c6d8594bb965a2247a61e991a99johnny name, valuep, lengthp));
70025d765b044c6d8594bb965a2247a61e991a99johnny}
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic int
70025d765b044c6d8594bb965a2247a61e991a99johnnynpe_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny return (pcihp_info(dip, cmd, arg, result));
70025d765b044c6d8594bb965a2247a61e991a99johnny}