px_tools_4u.c revision dabea0db6f27d1bf410afbc09b7dcec947a03164
69cd775ffd53de411433f1f43de2b4f644793528schwartz * CDDL HEADER START
69cd775ffd53de411433f1f43de2b4f644793528schwartz * The contents of this file are subject to the terms of the
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Common Development and Distribution License, Version 1.0 only
69cd775ffd53de411433f1f43de2b4f644793528schwartz * (the "License"). You may not use this file except in compliance
69cd775ffd53de411433f1f43de2b4f644793528schwartz * with the License.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
69cd775ffd53de411433f1f43de2b4f644793528schwartz * See the License for the specific language governing permissions
69cd775ffd53de411433f1f43de2b4f644793528schwartz * and limitations under the License.
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 * CDDL HEADER END
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Use is subject to license terms.
69cd775ffd53de411433f1f43de2b4f644793528schwartz#pragma ident "%Z%%M% %I% %E% SMI"
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.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * The way it works is as follows:
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * An access is done which causes an error. Fire errors are handled with
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * ontrap protection and usually come in first. Fabric errors can come in
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * px_phys_peek_4u() disables interrupts. Interrupts are reenabled at the end
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * of that function if no errors have been caught by the trap handler, or by
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * peek_fault() which executes when a fire error occurs.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Fabric error messages get put on an event queue but are not processed until
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * interrupts are reenabled.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * The delay gives time for the fabric errors to be processed by FMA before
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * changing the fm error flag back to DDI_FM_ERR_UNEXPECTED. If this isn't
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * done, then the fabric error which should be safe can panic the system.
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/* Number of inos per root complex. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz/* Mechanism for getting offsets of smaller datatypes aligned in 64 bit long */
69cd775ffd53de411433f1f43de2b4f644793528schwartztypedef union {
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Safe C wrapper around assy language routine px_phys_peek_4u
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Type is TRUE for big endian, FALSE for little endian.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Size is 1, 2, 4 or 8 bytes.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * paddr is the physical address in IO space to access read.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * value_p is where the value is returned.
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_safe_phys_peek(px_t *px_p, boolean_t type, size_t size, uint64_t paddr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Set up trap handling to make the access safe.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * on_trap works like setjmp.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Set it up to not panic on data access error,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * but to call peek_fault instead.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Call px_phys_peek_4u after trap handling is setup.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * When on_trap returns FALSE, it has been setup.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * When it returns TRUE, an it has caught an error.
69cd775ffd53de411433f1f43de2b4f644793528schwartz err = px_phys_peek_4u(size, paddr, &peek_value.u64, type);
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Workaround: delay taking down safe access env.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * For more info, see comments where pxtool_delay_ticks is declared.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Safe C wrapper around assy language routine px_phys_poke_4u
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Type is TRUE for big endian, FALSE for little endian.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Size is 1,2,4 or 8 bytes.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * paddr is the physical address in IO space to access read.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * value contains the value to be written.
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_safe_phys_poke(px_t *px_p, boolean_t type, size_t size, uint64_t paddr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * on_trap works like setjmp.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Set it up to not panic on data access error,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * but to call poke_fault instead.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Call px_phys_poke_4u after trap handling is setup.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * When on_trap returns FALSE, it has been setup.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * When it returns TRUE, an it has caught an error.
69cd775ffd53de411433f1f43de2b4f644793528schwartz err = px_phys_poke_4u(size, paddr, &poke_value.u64, type);
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Take down protected environment. */
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * Workaround: delay taking down safe access env.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * For more info, see comments where pxtool_delay_ticks is declared.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Wrapper around pxtool_safe_phys_peek/poke.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Validates arguments and calls pxtool_safe_phys_peek/poke appropriately.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Dip is of the nexus,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * phys_addr is the address to write in physical space.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * pcitool_status returns more detailed status in addition to a more generic
69cd775ffd53de411433f1f43de2b4f644793528schwartz * errno-style function return value.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * other args are self-explanatory.
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz * This function assumes that offset, bdf, and acc_attr are current in
69cd775ffd53de411433f1f43de2b4f644793528schwartz * prg_p. It also assumes that prg_p->phys_addr is the final phys addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz * including offset.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * This function modifies prg_p status and data.
69cd775ffd53de411433f1f43de2b4f644793528schwartz/*ARGSUSED*/
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_access(px_t *px_p, pcitool_reg_t *prg_p, uint64_t *data_p,
69cd775ffd53de411433f1f43de2b4f644793528schwartz boolean_t endian = PCITOOL_ACC_IS_BIG_ENDIAN(prg_p->acc_attr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz size_t size = PCITOOL_ACC_ATTR_SIZE(prg_p->acc_attr);
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Alignment checking. Assumes base address is 8-byte aligned. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else if (is_write) { /* Made it through checks. Do the access. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz "%d byte %s pxtool_safe_phys_poke at addr 0x%" PRIx64 "\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (pxtool_safe_phys_poke(px_p, endian, size, phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz "%d byte %s pxtool_safe_phys_poke at addr "
69cd775ffd53de411433f1f43de2b4f644793528schwartz } else { /* Read */
69cd775ffd53de411433f1f43de2b4f644793528schwartz "%d byte %s pxtool_safe_phys_peek at addr 0x%" PRIx64 "\n",
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (pxtool_safe_phys_peek(px_p, endian, size, phys_addr,
69cd775ffd53de411433f1f43de2b4f644793528schwartz "%d byte %s pxtool_safe_phys_peek at addr "
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_pcicfg_access(px_t *px_p, pcitool_reg_t *prg_p,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz return (pxtool_access(px_p, prg_p, data_p, is_write));
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartzpxtool_pciiomem_access(px_t *px_p, pcitool_reg_t *prg_p,
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz return (pxtool_access(px_p, prg_p, data_p, is_write));
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_dev_reg_ops_platchk(dev_info_t *dip, pcitool_reg_t *prg_p)
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Guard against checking a root nexus which is empty.
69cd775ffd53de411433f1f43de2b4f644793528schwartz * On some systems this will result in a Fatal Reset.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((int)prom_childnode((pnode_t)devi_nodeid) == OBP_NONODE) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz "pxtool_dev_reg_ops set/get reg: nexus has no devs!\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz * Perform register accesses on the nexus device itself.
69cd775ffd53de411433f1f43de2b4f644793528schwartzpxtool_bus_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode)
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "pxtool_bus_reg_ops set/get reg\n");
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Read data from userland. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_copyin(arg, &prg, sizeof (pcitool_reg_t), mode) !=
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Read reg property which contains starting addr and size of banks. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
69cd775ffd53de411433f1f43de2b4f644793528schwartz if (((reglen * sizeof (int)) %
69cd775ffd53de411433f1f43de2b4f644793528schwartz sizeof (px_nexus_regspec_t)) != 0) {
69cd775ffd53de411433f1f43de2b4f644793528schwartz numbanks = (reglen * sizeof (int)) / sizeof (px_nexus_regspec_t);
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Bounds check the bank number. */
69cd775ffd53de411433f1f43de2b4f644793528schwartz DBG(DBG_TOOLS, dip, "pxtool_bus_reg_ops: nexus: base:0x%" PRIx64 ", "
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz "offset:0x%" PRIx64 ", addr:0x%" PRIx64 ", max_offset:"
dabea0db6f27d1bf410afbc09b7dcec947a03164schwartz base_addr, prg.offset, prg.phys_addr, px_rp[prg.barnum].size);
69cd775ffd53de411433f1f43de2b4f644793528schwartz /* Access device. prg.status is modified. */