69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * CDDL HEADER START
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
69cd775ffd53de411433f1f43de2b4f644793528schwartz * or http://www.opensolaris.org/os/licensing.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * See the License for the specific language governing permissions
69cd775ffd53de411433f1f43de2b4f644793528schwartz * and limitations under the License.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * When distributing Covered Code, include this CDDL HEADER in each
69cd775ffd53de411433f1f43de2b4f644793528schwartz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * If applicable, add the following below this CDDL HEADER, with the
69cd775ffd53de411433f1f43de2b4f644793528schwartz * fields enclosed by brackets "[]" replaced with your own identifying
69cd775ffd53de411433f1f43de2b4f644793528schwartz * information: Portions Copyright [yyyy] [name of copyright owner]
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * CDDL HEADER END
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Use is subject to license terms.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/types.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/stat.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/cpuvar.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/kmem.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/sunddi.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include "px_obj.h"
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/pci_tools.h>
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz#include "px_tools_ext.h"
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include "px_tools_var.h"
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * PCI Space definitions.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define PCI_CONFIG_SPACE (PCI_REG_ADDR_G(PCI_ADDR_CONFIG))
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define PCI_IO_SPACE (PCI_REG_ADDR_G(PCI_ADDR_IO))
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define PCI_MEM32_SPACE (PCI_REG_ADDR_G(PCI_ADDR_MEM32))
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define PCI_MEM64_SPACE (PCI_REG_ADDR_G(PCI_ADDR_MEM64))
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Config space range for a device. IEEE 1275 spec defines for PCI.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Space for PCI-express is multiplied by PX_PCI_BDF_OFFSET_DELTA
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define DEV_CFG_SPACE_SIZE \
69cd775ffd53de411433f1f43de2b4f644793528schwartz (1 << (PCI_REG_FUNC_SHIFT + PX_PCI_BDF_OFFSET_DELTA))
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Offsets of BARS in config space. First entry of 0 means config space.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Entries here correlate to pcitool_bars_t enumerated type.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartzuint8_t pci_bars[] = {
69cd775ffd53de411433f1f43de2b4f644793528schwartz 0x0,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE0,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE1,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE2,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE3,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE4,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_BASE5,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCI_CONF_ROM
69cd775ffd53de411433f1f43de2b4f644793528schwartz};
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzint pci_num_bars = sizeof (pci_bars) / sizeof (pci_bars[0]);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz/*ARGSUSED*/
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartzpxtool_intr_info(dev_info_t *dip, void *arg, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan px_t *px_p = DIP_TO_STATE(dip);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan px_msi_state_t *msi_state_p = &px_p->px_ib_p->ib_msi_state;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz pcitool_intr_info_t intr_info;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz int rval = SUCCESS;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz /* If we need user_version, and to ret same user version as passed in */
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz if (ddi_copyin(arg, &intr_info, sizeof (pcitool_intr_info_t), mode) !=
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz }
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz intr_info.ctlr_version = 0; /* XXX how to get real version? */
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz intr_info.ctlr_type = PCITOOL_CTLR_TYPE_RISC;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (intr_info.flags & PCITOOL_INTR_FLAG_GET_MSI)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_info.num_intr = msi_state_p->msi_cnt;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan else
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_info.num_intr = pxtool_num_inos;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz intr_info.drvr_version = PCITOOL_VERSION;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz if (ddi_copyout(&intr_info, arg, sizeof (pcitool_intr_info_t), mode) !=
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz DDI_SUCCESS) {
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz rval = EFAULT;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz }
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Get interrupt information for a given ino.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Returns info only for inos mapped to devices.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Returned info is valid only when iget.num_devs is returned > 0.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * If ino is not enabled or is not mapped to a device,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * iget.num_devs will be returned as = 0.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*ARGSUSED*/
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_get_intr(dev_info_t *dip, void *arg, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Array part isn't used here, but oh well... */
69cd775ffd53de411433f1f43de2b4f644793528schwartz pcitool_intr_get_t partial_iget;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan pcitool_intr_get_t *iget = &partial_iget;
69cd775ffd53de411433f1f43de2b4f644793528schwartz int copyout_rval;
69cd775ffd53de411433f1f43de2b4f644793528schwartz sysino_t sysino;
69cd775ffd53de411433f1f43de2b4f644793528schwartz intr_valid_state_t intr_valid_state;
69cd775ffd53de411433f1f43de2b4f644793528schwartz cpuid_t old_cpu_id;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_t *px_p = DIP_TO_STATE(dip);
69cd775ffd53de411433f1f43de2b4f644793528schwartz size_t iget_kmem_alloc_size = 0;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan int rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Read in just the header part, no array section. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_copyin(arg, &partial_iget, PCITOOL_IGET_SIZE(0), mode) !=
69cd775ffd53de411433f1f43de2b4f644793528schwartz DDI_SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->status = PCITOOL_IO_ERROR;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iget->flags & PCITOOL_INTR_FLAG_GET_MSI) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan px_msi_state_t *msi_state_p = &px_p->px_ib_p->ib_msi_state;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan pci_msi_valid_state_t msi_state;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan msiqid_t msiq_id;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((iget->msi < msi_state_p->msi_1st_msinum) ||
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (iget->msi >= (msi_state_p->msi_1st_msinum +
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan msi_state_p->msi_cnt))) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->status = PCITOOL_INVALID_MSI;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EINVAL;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_get_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((px_lib_msi_getvalid(dip, iget->msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &msi_state) != DDI_SUCCESS) ||
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (msi_state != PCI_MSI_VALID))
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_get_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_msi_getmsiq(dip, iget->msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &msiq_id) != DDI_SUCCESS)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_get_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->ino = px_msiqid_to_devino(px_p, msiq_id);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->msi = (uint32_t)-1;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Validate argument. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iget->ino > pxtool_num_inos) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->status = PCITOOL_INVALID_INO;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_get_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Caller wants device information returned. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iget->num_devs_ret > 0) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Allocate room.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Note if num_devs == 0 iget remains pointing to
69cd775ffd53de411433f1f43de2b4f644793528schwartz * partial_iget.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_kmem_alloc_size = PCITOOL_IGET_SIZE(iget->num_devs_ret);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget = kmem_zalloc(iget_kmem_alloc_size, KM_SLEEP);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Read in whole structure to verify there's room. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_copyin(arg, iget, iget_kmem_alloc_size, mode) !=
69cd775ffd53de411433f1f43de2b4f644793528schwartz SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Be consistent and just return EFAULT here. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz kmem_free(iget, iget_kmem_alloc_size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Convert leaf-wide intr to system-wide intr */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_intr_devino_to_sysino(dip, iget->ino, &sysino) !=
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz iget->status = PCITOOL_IO_ERROR;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_get_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Operate only on inos which are already enabled. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_intr_getvalid(dip, sysino, &intr_valid_state) !=
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz iget->status = PCITOOL_IO_ERROR;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_get_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Consider all valid inos: those mapped to the root complex itself
69cd775ffd53de411433f1f43de2b4f644793528schwartz * as well as those mapped to devices.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (intr_valid_state == INTR_VALID) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1govinda * The following looks up the px_ino and returns
69cd775ffd53de411433f1f43de2b4f644793528schwartz * info of devices mapped to this ino.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->num_devs = pxtool_ib_get_ino_devs(px_p, iget->ino,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget->msi, &iget->num_devs_ret, iget->dev);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_ib_get_intr_target(px_p, iget->ino,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &old_cpu_id) != DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz iget->status = PCITOOL_IO_ERROR;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_get_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
69cd775ffd53de411433f1f43de2b4f644793528schwartz iget->cpu_id = old_cpu_id;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz iget->status = PCITOOL_SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzdone_get_intr:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz iget->drvr_version = PCITOOL_VERSION;
69cd775ffd53de411433f1f43de2b4f644793528schwartz copyout_rval =
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan ddi_copyout(iget, arg, PCITOOL_IGET_SIZE(iget->num_devs_ret), mode);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (iget_kmem_alloc_size > 0)
69cd775ffd53de411433f1f43de2b4f644793528schwartz kmem_free(iget, iget_kmem_alloc_size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (copyout_rval != DDI_SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EFAULT;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Associate a new CPU with a given ino.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Operate only on inos which are already mapped to devices.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_set_intr(dev_info_t *dip, void *arg, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz pcitool_intr_set_t iset;
69cd775ffd53de411433f1f43de2b4f644793528schwartz cpuid_t old_cpu_id;
69cd775ffd53de411433f1f43de2b4f644793528schwartz sysino_t sysino;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_valid_state_t intr_valid_state;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_t *px_p = DIP_TO_STATE(dip);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan msiqid_t msiq_id;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan int rval = EIO;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan int ret = DDI_SUCCESS;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz size_t copyinout_size;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz bzero(&iset, sizeof (pcitool_intr_set_t));
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz /* Version 1 of pcitool_intr_set_t doesn't have flags. */
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz copyinout_size = (size_t)&iset.flags - (size_t)&iset;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz if (ddi_copyin(arg, &iset, copyinout_size, mode) != DDI_SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz switch (iset.user_version) {
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz case PCITOOL_V1:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz break;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz case PCITOOL_V2:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz copyinout_size = sizeof (pcitool_intr_set_t);
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz if (ddi_copyin(arg, &iset, copyinout_size, mode) != DDI_SUCCESS)
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz return (EFAULT);
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz break;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz default:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz iset.status = PCITOOL_OUT_OF_RANGE;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz rval = ENOTSUP;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz goto done_set_intr;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz }
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iset.flags & PCITOOL_INTR_FLAG_SET_GROUP) {
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz iset.status = PCITOOL_IO_ERROR;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz rval = ENOTSUP;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz goto done_set_intr;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz }
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_IO_ERROR;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iset.flags & PCITOOL_INTR_FLAG_SET_MSI) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan px_msi_state_t *msi_state_p = &px_p->px_ib_p->ib_msi_state;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan pci_msi_valid_state_t msi_state;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((iset.msi < msi_state_p->msi_1st_msinum) ||
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (iset.msi >= (msi_state_p->msi_1st_msinum +
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan msi_state_p->msi_cnt))) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_INVALID_MSI;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EINVAL;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((px_lib_msi_getvalid(dip, iset.msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &msi_state) != DDI_SUCCESS) ||
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (msi_state != PCI_MSI_VALID))
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_msi_getmsiq(dip, iset.msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &msiq_id) != DDI_SUCCESS)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.ino = px_msiqid_to_devino(px_p, msiq_id);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.msi = (uint32_t)-1;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Validate input argument. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iset.ino > pxtool_num_inos) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_INVALID_INO;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Convert leaf-wide intr to system-wide intr */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_intr_devino_to_sysino(dip, iset.ino, &sysino) !=
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_SUCCESS)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Operate only on inos which are already enabled. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((px_lib_intr_getvalid(dip, sysino, &intr_valid_state) !=
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan DDI_SUCCESS) || (intr_valid_state == INTR_NOTVALID))
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_set_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * Consider all valid inos: those mapped to the root complex itself
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * as well as those mapped to devices.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (px_lib_intr_gettarget(dip, sysino, &old_cpu_id) != DDI_SUCCESS)
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (iset.flags & PCITOOL_INTR_FLAG_SET_MSI) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan ddi_intr_handle_impl_t hdle;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan bzero(&hdle, sizeof (ddi_intr_handle_impl_t));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (pxtool_ib_get_msi_info(px_p, iset.ino, iset.msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan &hdle) != DDI_SUCCESS) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_INVALID_MSI;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((ret = px_ib_set_msix_target(px_p, &hdle, iset.msi,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.cpu_id)) == DDI_SUCCESS) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (void) px_lib_msi_getmsiq(dip, iset.msi, &msiq_id);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.ino = px_msiqid_to_devino(px_p, msiq_id);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.cpu_id = old_cpu_id;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_SUCCESS;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if ((ret = px_ib_set_intr_target(px_p, iset.ino,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.cpu_id)) == DDI_SUCCESS) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.cpu_id = old_cpu_id;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_SUCCESS;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = SUCCESS;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan goto done_set_intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan switch (ret) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan case DDI_EPENDING:
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_PENDING_INTRTIMEOUT;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = ETIME;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan break;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan case DDI_EINVAL:
69cd775ffd53de411433f1f43de2b4f644793528schwartz iset.status = PCITOOL_INVALID_CPUID;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan break;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan default:
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.status = PCITOOL_IO_ERROR;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = EIO;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzdone_set_intr:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz iset.drvr_version = PCITOOL_VERSION;
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz if (ddi_copyout(&iset, arg, copyinout_size, mode) != DDI_SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EFAULT;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/* Main function for handling interrupt CPU binding requests and queries. */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_intr(dev_info_t *dip, void *arg, int cmd, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval = SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz switch (cmd) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz /* Get system interrupt information. */
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz case PCITOOL_SYSTEM_INTR_INFO:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz rval = pxtool_intr_info(dip, arg, mode);
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Get interrupt information for a given ino. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz case PCITOOL_DEVICE_GET_INTR:
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = pxtool_get_intr(dip, arg, mode);
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Associate a new CPU with a given ino. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz case PCITOOL_DEVICE_SET_INTR:
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = pxtool_set_intr(dip, arg, mode);
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz default:
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = ENOTTY;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_validate_barnum_bdf(pcitool_reg_t *prg)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval = SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (prg->barnum >= (sizeof (pci_bars) / sizeof (pci_bars[0]))) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg->status = PCITOOL_OUT_OF_RANGE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Validate address arguments of bus / dev / func */
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else if (((prg->bus_no &
69cd775ffd53de411433f1f43de2b4f644793528schwartz (PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT)) != prg->bus_no) ||
69cd775ffd53de411433f1f43de2b4f644793528schwartz ((prg->dev_no &
69cd775ffd53de411433f1f43de2b4f644793528schwartz (PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT)) != prg->dev_no) ||
69cd775ffd53de411433f1f43de2b4f644793528schwartz ((prg->func_no &
69cd775ffd53de411433f1f43de2b4f644793528schwartz (PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT)) != prg->func_no)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg->status = PCITOOL_INVALID_ADDRESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz/*
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * px_p defines which leaf, space defines which space in that leaf, offset
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * defines the offset within the specified space.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * This returns the physical address of the corresponding location.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzstatic uintptr_t
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_get_phys_addr(px_t *px_p, int space, uint64_t offset)
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz{
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t range_base;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz int rval;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz pci_regspec_t dev_regspec;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz struct regspec xlated_regspec;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz dev_info_t *dip = px_p->px_dip;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz /*
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Assume that requested entity is small enough to be on the same page.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * PCItool checks alignment so that this will be true for single
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * accesses.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_phys_hi = space << PCI_REG_ADDR_SHIFT;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz if (space == PCI_CONFIG_SPACE) {
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_phys_hi +=
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz (offset & (PCI_REG_BDFR_M ^ PCI_REG_REG_M));
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_phys_low = offset & PCI_REG_REG_M;
d84bdf751decaa46a5b040101685eb133fe6b04degillett dev_regspec.pci_phys_mid = 0; /* Not used */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz } else {
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_phys_mid = offset >> 32;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_phys_low = offset & 0xffffffff;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz }
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_size_hi = 0; /* Not used. */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz /* Note: object is guaranteed to be within a page. */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz dev_regspec.pci_size_low = 4;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz rval = px_xlate_reg(px_p, &dev_regspec, &xlated_regspec);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip,
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz "space:0x%d, offset:0x%" PRIx64 "\n", space, offset);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (rval != DDI_SUCCESS)
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz return (NULL);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz /* Bustype here returns the high order address bits. */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz xlated_regspec.regspec_bustype &= px_get_rng_parent_hi_mask(px_p);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz range_base = (((uint64_t)xlated_regspec.regspec_bustype) << 32) +
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz xlated_regspec.regspec_addr;
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz DBG(DBG_TOOLS, dip,
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz "regspec: hi:0x%x, lo:0x%x, sz:0x%x, range base:0x%" PRIx64 "\n",
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz xlated_regspec.regspec_bustype, xlated_regspec.regspec_addr,
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz xlated_regspec.regspec_size, range_base);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz return ((uintptr_t)range_base);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz}
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_get_bar(px_t *px_p, pcitool_reg_t *prg_p, uint64_t *bar_p,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint32_t *space_p)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t off_in_space;
69cd775ffd53de411433f1f43de2b4f644793528schwartz pcitool_reg_t cfg_prg = *prg_p; /* Make local copy. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz dev_info_t *dip = px_p->px_dip;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz *space_p = PCI_MEM32_SPACE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz *bar_p = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Translate BAR number into offset of the BAR in
69cd775ffd53de411433f1f43de2b4f644793528schwartz * the device's config space.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz cfg_prg.acc_attr =
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCITOOL_ACC_ATTR_SIZE_4 | PCITOOL_ACC_ATTR_ENDN_LTL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz /*
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Note: sun4u acc function uses phys_addr which includes offset.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * sun4v acc function doesn't use phys_addr but uses cfg_prg.offset.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz cfg_prg.offset = PCI_BAR_OFFSET((*prg_p));
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz off_in_space = PX_GET_BDF(prg_p) + cfg_prg.offset;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz cfg_prg.phys_addr = pxtool_get_phys_addr(px_p, PCI_CONFIG_SPACE,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz off_in_space);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "off_in_space:0x%" PRIx64 ", phys_addr:0x%" PRIx64 ", barnum:%d\n",
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz off_in_space, cfg_prg.phys_addr, cfg_prg.barnum);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Get Bus Address Register (BAR) from config space.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * cfg_prg.offset is the offset into config space of the
69cd775ffd53de411433f1f43de2b4f644793528schwartz * BAR desired. prg_p->status is modified on error.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = pxtool_pcicfg_access(px_p, &cfg_prg, bar_p, PX_ISREAD);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (rval != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = cfg_prg.status;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "bar returned is 0x%" PRIx64 "\n", *bar_p);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * BAR has bits saying this space is IO space, unless
69cd775ffd53de411433f1f43de2b4f644793528schwartz * this is the ROM address register.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (((PCI_BASE_SPACE_M & *bar_p) == PCI_BASE_SPACE_IO) &&
69cd775ffd53de411433f1f43de2b4f644793528schwartz (cfg_prg.offset != PCI_CONF_ROM)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz *space_p = PCI_IO_SPACE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz *bar_p &= PCI_BASE_IO_ADDR_M;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * BAR has bits saying this space is 64 bit memory
69cd775ffd53de411433f1f43de2b4f644793528schwartz * space, unless this is the ROM address register.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * The 64 bit address stored in two BAR cells is not
69cd775ffd53de411433f1f43de2b4f644793528schwartz * necessarily aligned on an 8-byte boundary.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Need to keep the first 4 bytes read,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * and do a separate read of the high 4 bytes.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else if ((PCI_BASE_TYPE_ALL & *bar_p) &&
69cd775ffd53de411433f1f43de2b4f644793528schwartz (cfg_prg.offset != PCI_CONF_ROM)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint32_t low_bytes = (uint32_t)(*bar_p & ~PCI_BASE_TYPE_ALL);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Don't try to read the next 4 bytes past the end of BARs. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (cfg_prg.offset >= PCI_CONF_BASE5) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_OUT_OF_RANGE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Access device. prg_p->status is modified on error. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz cfg_prg.phys_addr += sizeof (uint32_t);
69cd775ffd53de411433f1f43de2b4f644793528schwartz cfg_prg.offset += sizeof (uint32_t);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = pxtool_pcicfg_access(px_p, &cfg_prg, bar_p, PX_ISREAD);
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (rval != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = cfg_prg.status;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Honor the 64 bit BAR as such, only when the upper 32 bits
69cd775ffd53de411433f1f43de2b4f644793528schwartz * store a non-zero value.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (*bar_p) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz *space_p = PCI_MEM64_SPACE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz *bar_p = (*bar_p << 32) | low_bytes;
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz *bar_p = low_bytes;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else if (cfg_prg.offset == PCI_CONF_ROM) { /* ROM requested */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * ROM enabled. Filter ROM enable bit from the BAR.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Treat as Mem32 henceforth.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!(*bar_p & PCI_BASE_ROM_ENABLE))
69cd775ffd53de411433f1f43de2b4f644793528schwartz *bar_p ^= PCI_BASE_ROM_ENABLE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz else { /* ROM disabled. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_ROM_DISABLED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Accept a bar of 0 only for IO space. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((*space_p != PCI_IO_SPACE) && (!(*bar_p))) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_INVALID_ADDRESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EINVAL);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (SUCCESS);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/* Perform register accesses on PCI leaf devices. */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_dev_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz pcitool_reg_t prg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint64_t bar;
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint32_t space;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t off_in_space;
69cd775ffd53de411433f1f43de2b4f644793528schwartz boolean_t write_flag = B_FALSE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_t *px_p = DIP_TO_STATE(dip);
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (cmd == PCITOOL_DEVICE_SET_REG)
69cd775ffd53de411433f1f43de2b4f644793528schwartz write_flag = B_TRUE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "pxtool_dev_reg_ops set/get reg\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_copyin(arg, &prg, sizeof (pcitool_reg_t),
69cd775ffd53de411433f1f43de2b4f644793528schwartz mode) != DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error reading arguments\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((rval = pxtool_dev_reg_ops_platchk(dip, &prg)) != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_reg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "raw bus:0x%x, dev:0x%x, func:0x%x\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.bus_no, prg.dev_no, prg.func_no);
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "barnum:0x%x, offset:0x%" PRIx64 ", acc:0x%x\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.barnum, prg.offset, prg.acc_attr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((rval = pxtool_validate_barnum_bdf(&prg)) != SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_reg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (prg.barnum == 0) { /* Proper config space desired. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz /* Enforce offset limits. */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (prg.offset >= DEV_CFG_SPACE_SIZE) {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "Config space offset 0x%" PRIx64 " out of range\n",
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz prg.offset);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz prg.status = PCITOOL_OUT_OF_RANGE;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = EINVAL;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz goto done_reg;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz /*
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * For sun4v, config space base won't be known.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * pxtool_get_phys_addr will return zero.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Note that for sun4v, phys_addr isn't
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * used for making config space accesses.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * For sun4u, assume that phys_addr will come back valid.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz /*
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * Accessed entity is assumed small enough to be on one page.
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz *
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * Since config space is less than a page and is aligned to
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * 0x1000, a device's entire config space will be on a single
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * page. Pass the device's base config space address here,
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * then add the offset within that space later. This works
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * around an issue in px_xlate_reg (called by
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * pxtool_get_phys_addr) which accepts only a 256 byte
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz * range within a device.
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz */
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz off_in_space = PX_GET_BDF(&prg);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz prg.phys_addr =
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz pxtool_get_phys_addr(px_p, PCI_CONFIG_SPACE, off_in_space);
d35337857fbb8d6fbd34c00f1f1a30eacb0a8dd1schwartz prg.phys_addr += prg.offset;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "off_in_space:0x%" PRIx64 ", phys_addr:0x%" PRIx64 ", "
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "end:%s\n", off_in_space, prg.phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCITOOL_ACC_IS_BIG_ENDIAN(prg.acc_attr) ? "big":"ltl");
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Access device. pr.status is modified.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * BDF is assumed valid at this point.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = pxtool_pcicfg_access(px_p, &prg, &prg.data, write_flag);
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_reg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* IO/ MEM/ MEM64 space. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if ((rval = pxtool_get_bar(px_p, &prg, &bar, &space)) != SUCCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_reg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz switch (space) {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz case PCI_MEM32_SPACE:
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "32 bit mem space\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Can't write to ROM */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((PCI_BAR_OFFSET(prg) == PCI_CONF_ROM) && (write_flag)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.status = PCITOOL_ROM_WRITE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done_reg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz case PCI_IO_SPACE:
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip, "IO space\n");
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz case PCI_MEM64_SPACE:
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "64 bit mem space. 64-bit bar is 0x%" PRIx64 "\n", bar);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz default:
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip, "Unknown space!\n");
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz prg.status = PCITOOL_IO_ERROR;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = EIO;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz goto done_reg;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Common code for all IO/MEM range spaces.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Use offset provided by caller to index into desired space.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Note that prg.status is modified on error.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz off_in_space = bar + prg.offset;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz prg.phys_addr = pxtool_get_phys_addr(px_p, space, off_in_space);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz DBG(DBG_TOOLS, dip,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "addr in bar:0x%" PRIx64 ", offset:0x%" PRIx64 ", "
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "phys_addr:0x%" PRIx64 "\n", bar, prg.offset, prg.phys_addr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = pxtool_pciiomem_access(px_p, &prg, &prg.data, write_flag);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzdone_reg:
2917a9c9c3eee6fcaedb239f5f68da01f4ed0da9schwartz prg.drvr_version = PCITOOL_VERSION;
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_copyout(&prg, arg, sizeof (pcitool_reg_t),
69cd775ffd53de411433f1f43de2b4f644793528schwartz mode) != DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error returning arguments.\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EFAULT;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_init(dev_info_t *dip)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz int instance = ddi_get_instance(dip);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_create_minor_node(dip, PCI_MINOR_REG, S_IFCHR,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PCI_MINOR_NUM(instance, PCI_TOOL_REG_MINOR_NUM),
69cd775ffd53de411433f1f43de2b4f644793528schwartz DDI_NT_REGACC, 0) != DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (DDI_FAILURE);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_create_minor_node(dip, PCI_MINOR_INTR, S_IFCHR,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PCI_MINOR_NUM(instance, PCI_TOOL_INTR_MINOR_NUM),
69cd775ffd53de411433f1f43de2b4f644793528schwartz DDI_NT_INTRCTL, 0) != DDI_SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz ddi_remove_minor_node(dip, PCI_MINOR_REG);
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (DDI_FAILURE);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (DDI_SUCCESS);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzvoid
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_uninit(dev_info_t *dip)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz ddi_remove_minor_node(dip, PCI_MINOR_REG);
69cd775ffd53de411433f1f43de2b4f644793528schwartz ddi_remove_minor_node(dip, PCI_MINOR_INTR);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}