d4476ccb08e9498c2013971c4212dc6362fcec46schwartz/*
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * CDDL HEADER START
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz *
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * The contents of this file are subject to the terms of the
44bb982b3dceb1fe23d61ef29b896b40508e2a5agovinda * Common Development and Distribution License (the "License").
44bb982b3dceb1fe23d61ef29b896b40508e2a5agovinda * You may not use this file except in compliance with the License.
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz *
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * or http://www.opensolaris.org/os/licensing.
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * See the License for the specific language governing permissions
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * and limitations under the License.
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz *
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * When distributing Covered Code, include this CDDL HEADER in each
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * If applicable, add the following below this CDDL HEADER, with the
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * fields enclosed by brackets "[]" replaced with your own identifying
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * information: Portions Copyright [yyyy] [name of copyright owner]
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz *
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz * CDDL HEADER END
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
abdf5d9abf528d6c318fd8533e09bc3cac1f228bShesha Sreenivasamurthy * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Use is subject to license terms.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/sysmacros.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/machsystm.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/cpuvar.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/ddi_implfuncs.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/hypervisor_api.h>
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz#include <sys/hsvc.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <px_obj.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <sys/pci_tools.h>
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu#include <sys/pci_cfgacc.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include <px_tools_var.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz#include "px_lib4v.h"
d4476ccb08e9498c2013971c4212dc6362fcec46schwartz#include <px_tools_ext.h>
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Delay needed to have a safe environment envelop any error which could
69cd775ffd53de411433f1f43de2b4f644793528schwartz * surface. The larger the number of bridges and switches, the larger the
69cd775ffd53de411433f1f43de2b4f644793528schwartz * number needed here.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Note: this is a workaround until a better solution is found. While this
69cd775ffd53de411433f1f43de2b4f644793528schwartz * number is high, given enough bridges and switches in the device path, this
69cd775ffd53de411433f1f43de2b4f644793528schwartz * workaround can break. Also, other PIL 15 interrupts besides the ones we are
69cd775ffd53de411433f1f43de2b4f644793528schwartz * enveloping could delay processing of the interrupt we are trying to protect.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint pxtool_cfg_delay_usec = 2500;
69cd775ffd53de411433f1f43de2b4f644793528schwartzint pxtool_iomem_delay_usec = 25000;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/* Currently there is no way of getting this info from hypervisor. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz#define INTERRUPT_MAPPING_ENTRIES 64
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/* Number of inos per root complex. */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint pxtool_num_inos = INTERRUPT_MAPPING_ENTRIES;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz/* Verify hypervisor version for DIAG functions ra2pa and hpriv. */
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz#define PXTOOL_HYP_VER_UNINIT 0
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz#define PXTOOL_HYP_VER_BAD 1
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz#define PXTOOL_HYP_VER_OK 2
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartzstatic int pxtool_hyp_version = PXTOOL_HYP_VER_UNINIT;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz/* Swap endianness. */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzstatic uint64_t
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_swap_endian(uint64_t data, int size)
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz{
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz typedef union {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t data64;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint8_t data8[8];
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz } data_split_t;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz data_split_t orig_data;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz data_split_t returned_data;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz int i;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz orig_data.data64 = data;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz returned_data.data64 = 0;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz for (i = 0; i < size; i++) {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz returned_data.data8[7 - i] = orig_data.data8[8 - size + i];
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz }
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz return (returned_data.data64);
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz}
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartzstatic void
0ad689d678ef901f32945172f48ddc7b16dde50dschwartzpxtool_validate_diag_hyp_svc(dev_info_t *dip, int *diag_svc_status_p)
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz{
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz uint64_t pxtool_diag_maj_ver;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz uint64_t pxtool_diag_min_ver;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz int ret;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz if (*diag_svc_status_p == PXTOOL_HYP_VER_UNINIT) {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz *diag_svc_status_p = PXTOOL_HYP_VER_BAD;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz /*
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * Verify that hypervisor DIAG API has been
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * negotiated (by unix).
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz */
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz if ((ret = hsvc_version(HSVC_GROUP_DIAG,
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz &pxtool_diag_maj_ver, &pxtool_diag_min_ver)) != 0) {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz DBG(DBG_TOOLS, dip,
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz "diag hypervisor svc not negotiated: "
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz "grp:0x%lx, errno:%d\n", HSVC_GROUP_DIAG, ret);
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz } else if (pxtool_diag_maj_ver == 1) {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz /*
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * Major version 1 is OK.
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz *
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * Code maintainers: if the version changes, check for
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * API changes in hv_ra2pa() and hv_hpriv() before
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz * accepting the new version.
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz */
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz *diag_svc_status_p = PXTOOL_HYP_VER_OK;
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz } else {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz DBG(DBG_TOOLS, dip,
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz "diag hypervisor svc: bad major number: "
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz "grp:0x%lx, maj:0x%lx, min:0x%lx\n",
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz HSVC_GROUP_DIAG, pxtool_diag_maj_ver,
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz pxtool_diag_min_ver);
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz }
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz }
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz}
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzstatic int
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_phys_access(px_t *px_p, uintptr_t dev_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint64_t *data_p, boolean_t is_big_endian, boolean_t is_write)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t rfunc, pfunc;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t rdata_addr, pdata_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t to_addr, from_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t local_data;
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval;
69cd775ffd53de411433f1f43de2b4f644793528schwartz dev_info_t *dip = px_p->px_dip;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip,
69cd775ffd53de411433f1f43de2b4f644793528schwartz "pxtool_phys_access: dev_addr:0x%" PRIx64 "\n", dev_addr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, " data_addr:0x%" PRIx64 ", is_write:%s\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz data_p, (is_write ? "yes" : "no"));
69cd775ffd53de411433f1f43de2b4f644793528schwartz
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz if (pxtool_hyp_version != PXTOOL_HYP_VER_OK) {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz pxtool_validate_diag_hyp_svc(dip, &pxtool_hyp_version);
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz if (pxtool_hyp_version != PXTOOL_HYP_VER_OK) {
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz DBG(DBG_TOOLS, dip, "Couldn't validate diag hyp svc\n");
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz return (EPERM);
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz }
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz }
0ad689d678ef901f32945172f48ddc7b16dde50dschwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if ((rfunc = va_to_pa((void *)px_phys_acc_4v)) == (uint64_t)-1) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error getting real addr for function\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((pfunc = hv_ra2pa(rfunc)) == -1) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error getting phys addr for function\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if ((rdata_addr = va_to_pa((void *)&local_data)) == (uint64_t)-1) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error getting real addr for data_p\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if ((pdata_addr = hv_ra2pa(rdata_addr)) == -1) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "Error getting phys addr for data ptr\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EIO);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (is_write) {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz to_addr = dev_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz from_addr = pdata_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (is_big_endian)
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz local_data = *data_p;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz else
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz local_data =
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz pxtool_swap_endian(*data_p, sizeof (uint64_t));
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz } else {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz to_addr = pdata_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz from_addr = dev_addr;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz }
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz rval = hv_hpriv((void *)pfunc, from_addr, to_addr, NULL);
69cd775ffd53de411433f1f43de2b4f644793528schwartz switch (rval) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz case H_ENOACCESS: /* Returned by non-debug hypervisor. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = ENOTSUP;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz case H_EOK:
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz default:
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if ((rval == SUCCESS) && (!is_write)) {
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz if (is_big_endian)
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *data_p = local_data;
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz else
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *data_p =
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz pxtool_swap_endian(local_data, sizeof (uint64_t));
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * This function is for PCI config space access.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * It assumes that offset, bdf, acc_attr are valid in prg_p.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * This function modifies prg_p status and data.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz *
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * prg_p->phys_addr isn't used.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_pcicfg_access(px_t *px_p, pcitool_reg_t *prg_p,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz uint64_t *data_p, boolean_t is_write)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz pci_cfg_data_t data;
69cd775ffd53de411433f1f43de2b4f644793528schwartz on_trap_data_t otd;
69cd775ffd53de411433f1f43de2b4f644793528schwartz dev_info_t *dip = px_p->px_dip;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_pec_t *pec_p = px_p->px_pec_p;
69cd775ffd53de411433f1f43de2b4f644793528schwartz size_t size = PCITOOL_ACC_ATTR_SIZE(prg_p->acc_attr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval = 0;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu pci_cfgacc_req_t req;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu if ((size <= 0) || (size > 8)) {
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu DBG(DBG_TOOLS, dip, "not supported size.\n");
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu prg_p->status = PCITOOL_INVALID_SIZE;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu return (ENOTSUP);
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Alignment checking. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!IS_P2ALIGNED(prg_p->offset, size)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "not aligned.\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_NOT_ALIGNED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EINVAL);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz mutex_enter(&pec_p->pec_pokefault_mutex);
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_ontrap_data = &otd;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu req.rcdip = dip;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu req.bdf = PCI_GETBDF(prg_p->bus_no, prg_p->dev_no, prg_p->func_no);
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu req.offset = prg_p->offset;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu req.size = size;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu req.write = is_write;
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (is_write) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (PCITOOL_ACC_IS_BIG_ENDIAN(prg_p->acc_attr))
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.qw = pxtool_swap_endian(*data_p, size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz else
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.qw = *data_p;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz switch (size) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz case sizeof (uint8_t):
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.b = (uint8_t)data.qw;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz case sizeof (uint16_t):
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.w = (uint16_t)data.qw;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz case sizeof (uint32_t):
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.dw = (uint32_t)data.qw;
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz case sizeof (uint64_t):
69cd775ffd53de411433f1f43de2b4f644793528schwartz break;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu DBG(DBG_TOOLS, dip, "put: bdf:%d,%d,%d, off:0x%"PRIx64", size:"
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu "0x%"PRIx64", data:0x%"PRIx64"\n",
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu prg_p->bus_no, prg_p->dev_no, prg_p->func_no,
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu prg_p->offset, size, data.qw);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!on_trap(&otd, OT_DATA_ACCESS)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz otd.ot_trampoline = (uintptr_t)&poke_fault;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu VAL64(&req) = data.qw;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu pci_cfgacc_acc(&req);
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (otd.ot_trap & OT_DATA_ACCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz data.qw = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!on_trap(&otd, OT_DATA_ACCESS)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz otd.ot_trampoline = (uintptr_t)&peek_fault;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu pci_cfgacc_acc(&req);
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu data.qw = VAL64(&req);
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu switch (size) {
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu case sizeof (uint8_t):
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu data.qw = (uint64_t)data.b;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu break;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu case sizeof (uint16_t):
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu data.qw = (uint64_t)data.w;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu break;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu case sizeof (uint32_t):
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu data.qw = (uint64_t)data.dw;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu break;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu case sizeof (uint64_t):
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu break;
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu }
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu DBG(DBG_TOOLS, dip, "get: bdf:%d,%d,%d, off:0x%"PRIx64", size:"
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu "0x%"PRIx64", data:0x%"PRIx64"\n",
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu prg_p->bus_no, prg_p->dev_no, prg_p->func_no,
c0da627439dfb642fb41ab7d78406fc69d2c64b2Zhi-Jun Robin Fu prg_p->offset, size, data.qw);
abdf5d9abf528d6c318fd8533e09bc3cac1f228bShesha Sreenivasamurthy *data_p = data.qw;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (PCITOOL_ACC_IS_BIG_ENDIAN(prg_p->acc_attr))
69cd775ffd53de411433f1f43de2b4f644793528schwartz *data_p = pxtool_swap_endian(*data_p, size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Workaround: delay taking down safe access env.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * For more info, see comments where pxtool_cfg_delay_usec is declared.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (pxtool_cfg_delay_usec > 0)
69cd775ffd53de411433f1f43de2b4f644793528schwartz drv_usecwait(pxtool_cfg_delay_usec);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz no_trap();
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_ontrap_data = NULL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz mutex_exit(&pec_p->pec_pokefault_mutex);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (rval != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_INVALID_ADDRESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * This function is for PCI IO space and memory space access.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * It assumes that offset, bdf, acc_attr are current in prg_p.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * It assumes that prg_p->phys_addr is the final phys addr (including offset).
69cd775ffd53de411433f1f43de2b4f644793528schwartz * This function modifies prg_p status and data.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_pciiomem_access(px_t *px_p, pcitool_reg_t *prg_p,
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint64_t *data_p, boolean_t is_write)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz on_trap_data_t otd;
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint32_t io_stat = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz dev_info_t *dip = px_p->px_dip;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_pec_t *pec_p = px_p->px_pec_p;
69cd775ffd53de411433f1f43de2b4f644793528schwartz size_t size = PCITOOL_ACC_ATTR_SIZE(prg_p->acc_attr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz int rval = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Alignment checking. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!IS_P2ALIGNED(prg_p->offset, size)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "not aligned.\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_NOT_ALIGNED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EINVAL);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz mutex_enter(&pec_p->pec_pokefault_mutex);
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_ontrap_data = &otd;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (is_write) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz pci_device_t bdf = PX_GET_BDF(prg_p);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (PCITOOL_ACC_IS_BIG_ENDIAN(prg_p->acc_attr))
69cd775ffd53de411433f1f43de2b4f644793528schwartz *data_p = pxtool_swap_endian(*data_p, size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!on_trap(&otd, OT_DATA_ACCESS)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz otd.ot_trampoline = (uintptr_t)&poke_fault;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = hvio_poke(px_p->px_dev_hdl, prg_p->phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz size, *data_p, bdf, &io_stat);
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (otd.ot_trap & OT_DATA_ACCESS)
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "iomem:phys_addr:0x%" PRIx64 ", bdf:0x%x, "
69cd775ffd53de411433f1f43de2b4f644793528schwartz "rval:%d, io_stat:%d\n", prg_p->phys_addr, bdf,
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval, io_stat);
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else {
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz *data_p = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!on_trap(&otd, OT_DATA_ACCESS)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz otd.ot_trampoline = (uintptr_t)&peek_fault;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = hvio_peek(px_p->px_dev_hdl, prg_p->phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz size, &io_stat, data_p);
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = H_EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "iomem:phys_addr:0x%" PRIx64 ", "
69cd775ffd53de411433f1f43de2b4f644793528schwartz "size:0x%" PRIx64 ", hdl:0x%" PRIx64 ", "
69cd775ffd53de411433f1f43de2b4f644793528schwartz "rval:%d, io_stat:%d\n", prg_p->phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz size, px_p->px_dev_hdl, rval, io_stat);
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "read data:0x%" PRIx64 "\n", *data_p);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (PCITOOL_ACC_IS_BIG_ENDIAN(prg_p->acc_attr))
69cd775ffd53de411433f1f43de2b4f644793528schwartz *data_p = pxtool_swap_endian(*data_p, size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Workaround: delay taking down safe access env.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * For more info, see comment where pxtool_iomem_delay_usec is declared.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (pxtool_iomem_delay_usec > 0)
69cd775ffd53de411433f1f43de2b4f644793528schwartz delay(drv_usectohz(pxtool_iomem_delay_usec));
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz no_trap();
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_ontrap_data = NULL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz mutex_exit(&pec_p->pec_pokefault_mutex);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (rval != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_INVALID_ADDRESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else if (io_stat != SUCCESS) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_IO_ERROR;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EIO;
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg_p->status = PCITOOL_SUCCESS;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*ARGSUSED*/
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_dev_reg_ops_platchk(dev_info_t *dip, pcitool_reg_t *prg_p)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (SUCCESS);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Perform register accesses on the nexus device itself.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartzint
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_bus_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz{
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz pcitool_reg_t prg;
69cd775ffd53de411433f1f43de2b4f644793528schwartz size_t size;
69cd775ffd53de411433f1f43de2b4f644793528schwartz px_t *px_p = DIP_TO_STATE(dip);
69cd775ffd53de411433f1f43de2b4f644793528schwartz boolean_t is_write = B_FALSE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz uint32_t rval = 0;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (cmd == PCITOOL_NEXUS_SET_REG)
69cd775ffd53de411433f1f43de2b4f644793528schwartz is_write = B_TRUE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "pxtool_bus_reg_ops set/get reg\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Read data from userland. */
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 size = PCITOOL_ACC_ATTR_SIZE(prg.acc_attr);
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 DBG(DBG_TOOLS, dip, "data:0x%" PRIx64 ", phys_addr:0x%" PRIx64 "\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.data, prg.phys_addr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /*
69cd775ffd53de411433f1f43de2b4f644793528schwartz * If bank num == ff, base phys addr passed in from userland.
69cd775ffd53de411433f1f43de2b4f644793528schwartz *
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Normal bank specification is invalid, as there is no OBP property to
69cd775ffd53de411433f1f43de2b4f644793528schwartz * back it up.
69cd775ffd53de411433f1f43de2b4f644793528schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (prg.barnum != PCITOOL_BASE) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.status = PCITOOL_OUT_OF_RANGE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Allow only size of 8-bytes. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (size != sizeof (uint64_t)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.status = PCITOOL_INVALID_SIZE;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Alignment checking. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (!IS_P2ALIGNED(prg.offset, size)) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "not aligned.\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.status = PCITOOL_NOT_ALIGNED;
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = EINVAL;
69cd775ffd53de411433f1f43de2b4f644793528schwartz goto done;
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz prg.phys_addr += prg.offset;
69cd775ffd53de411433f1f43de2b4f644793528schwartz
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz /*
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz * Only the hypervisor can access nexus registers. As a result, there
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz * can be no error recovery in the OS. If there is an error, the
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz * system will go down, but with a trap type 7f. The OS cannot
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz * intervene with this kind of trap.
f0a73f0415a4150b270534bc7ed2cbb77d87c5a2schwartz */
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Access device. prg.status is modified. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz rval = pxtool_phys_access(px_p, prg.phys_addr, &prg.data,
69cd775ffd53de411433f1f43de2b4f644793528schwartz PCITOOL_ACC_IS_BIG_ENDIAN(prg.acc_attr), is_write);
69cd775ffd53de411433f1f43de2b4f644793528schwartzdone:
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, "Copyout failed.\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (EFAULT);
69cd775ffd53de411433f1f43de2b4f644793528schwartz }
69cd775ffd53de411433f1f43de2b4f644793528schwartz
69cd775ffd53de411433f1f43de2b4f644793528schwartz return (rval);
69cd775ffd53de411433f1f43de2b4f644793528schwartz}