7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Common Development and Distribution License (the "License").
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#pragma ident "%Z%%M% %I% %E% SMI"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Given a unum including an offset calculate the associated system
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * address. This may be different to when the original PA to unum
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * calculation took place if interleave etc has changed.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/errno.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/types.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/mc.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <mcamd_api.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <mcamd_err.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The submitted unum must have the MC and DIMM numbers and an offset.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Any cs info it has will not be used - we will reconstruct cs info.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * This is because cs is not in the topology used for diagnosis.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
8a40a695ee676a322b094e9afe5375567bfb51e3gavinmmcamd_unumtopa(struct mcamd_hdl *hdl, mcamd_node_t *root, mc_unum_t *unump,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint64_t *pa)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_node_t *mc, *dimm;
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm uint64_t num, holesz;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa: chip %d "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "mc %d dimm %d offset 0x%llx\n", unump->unum_chip, unump->unum_mc,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi unump->unum_dimms[0], unump->unum_offset);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!MCAMD_RC_OFFSET_VALID(unump->unum_offset)) {
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa: offset "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "invalid\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Search current config for a MC number matching the chip in the
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * unum.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (mc = mcamd_mc_next(hdl, root, NULL); mc != NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mc = mcamd_mc_next(hdl, root, mc)) {
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (!mcamd_get_numprops(hdl,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mc, MCAMD_PROP_NUM, &num,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mc, MCAMD_PROP_DRAMHOLE_SIZE, &holesz,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm NULL)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mcamd_unumtopa: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "failed to lookup num, dramhole for MC 0x%p\n", mc);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (num == unump->unum_chip)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (mc == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa; "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "no match for MC %d\n", unump->unum_chip);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Search DIMMs of this MC. We can match against the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * first dimm in the unum - if there is more than one they all
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * share the same chip-selects anyway and the pa we will resolve
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * to is not finer grained than the 128-bits of a dimm pair.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (dimm = mcamd_dimm_next(hdl, mc, NULL); dimm != NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dimm = mcamd_dimm_next(hdl, mc, dimm)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!mcamd_get_numprop(hdl, dimm, MCAMD_PROP_NUM, &num)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mcamd_unumtopa: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "failed to lookup num for dimm 0xx%p\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dimm);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (num == unump->unum_dimms[0])
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dimm == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa; "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "no match for dimm %d cs %d on MC %d\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi unump->unum_dimms[0], unump->unum_cs, unump->unum_chip);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa: matched "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "mc 0x%p dimm 0x%p; resolving offset 0x%llx\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mc, dimm, unump->unum_offset);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (mc_offset_to_pa(hdl, mc, dimm, unump->unum_offset, pa) < 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "mc_offset_to_pa failed: %s\n", mcamd_errmsg(hdl));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1); /* errno already set */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_unumtopa: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "mc_offset_to_pa succeeded and returned pa=0x%llx: %\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *pa);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If this MC has a dram address hole just below 4GB then we must
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * hoist all address from the hole start upwards by the hole size
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (holesz != 0) {
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (*pa >= 0x100000000 - holesz)
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm *pa += holesz;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_untopa: hoist "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "above dram hole of size 0x%llx to get pa=0x%llx",
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm holesz, *pa);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}