0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * CDDL HEADER START
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * The contents of this file are subject to the terms of the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Common Development and Distribution License (the "License").
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * You may not use this file except in compliance with the License.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * or http://www.opensolaris.org/os/licensing.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * See the License for the specific language governing permissions
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * and limitations under the License.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * When distributing Covered Code, include this CDDL HEADER in each
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * If applicable, add the following below this CDDL HEADER, with the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * fields enclosed by brackets "[]" replaced with your own identifying
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * information: Portions Copyright [yyyy] [name of copyright owner]
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * CDDL HEADER END
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Use is subject to license terms.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * SUNW,OPL-Enterprise platform ioboard topology enumerator
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <string.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <strings.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <libdevinfo.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <fm/topo_mod.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <fm/topo_hc.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <sys/fm/protocol.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include "opl_topo.h"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#define IOB_ENUMR_VERS 1
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#define FRUNAME "iou"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#define LABEL FRUNAME "#%d"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#define IOBDFRU "hc:///component=" LABEL
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl#define IKKAKU_FRUNAME "MBU_A"
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl#define IKKAKU_LABEL IKKAKU_FRUNAME
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl#define IKKAKU_IOBDFRU "hc:///component=" IKKAKU_LABEL
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic int opl_iob_enum(topo_mod_t *hdl, tnode_t *parent, const char *name,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t imin, topo_instance_t imax, void *notused1, void *notused2);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic const topo_modops_t Iobops =
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { opl_iob_enum, NULL };
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic const topo_modinfo_t IobInfo = {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston IOBOARD,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi FM_FMRI_SCHEME_HC,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston IOB_ENUMR_VERS,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi &Iobops};
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl/* OPL model type */
78ed97a7b79b59ef2ef41f190c9be35c54d90119jltypedef enum {
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl MODEL_FF,
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl MODEL_DC,
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl MODEL_IKKAKU
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl} opl_model_t;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonvoid
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston_topo_init(topo_mod_t *modhdl)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Turn on module debugging output
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (getenv("TOPOIOBDBG") != NULL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_mod_setdebug(modhdl);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(modhdl, "initializing ioboard enumerator\n");
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_register(modhdl, &IobInfo, TOPO_VERSION);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonvoid
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston_topo_fini(topo_mod_t *modhdl)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_unregister(modhdl);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Checks to see if there's a physical board number property on this
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * device node.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic int
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiopl_get_physical_board(topo_mod_t *mod, di_node_t n)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_prom_prop_t pp = DI_PROM_PROP_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston uchar_t *buf;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int val;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (-1);
23a276b1252962c987a613be470dde26561247b8hueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi for (pp = di_prom_prop_next(ptp, n, pp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pp != DI_PROM_PROP_NIL;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi pp = di_prom_prop_next(ptp, n, pp)) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (strcmp(di_prom_prop_name(pp), OPL_PHYSICAL_BD) == 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (di_prom_prop_data(pp, &buf) < sizeof (val))
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston continue;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston bcopy(buf, &val, sizeof (val));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (val);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Creates a map of logical boards to physical location.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic void
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiopl_map_boards(topo_mod_t *mod, di_node_t opl_devtree,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi int lsb_to_psb[OPL_IOB_MAX])
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_node_t n;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int i;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Initialize all entries to no mapping */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (i = 0; i < OPL_IOB_MAX; i++) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston lsb_to_psb[i] = i;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Get LSB-to-PSB (logical-to-physical board) mapping by finding the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * memory controller driver per LSB. The MC driver will have a
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * physical-board# property.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (n = di_drv_first_node(OPL_MC_DRV, opl_devtree);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston n != DI_NODE_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston n = di_drv_next_node(n)) {
23a276b1252962c987a613be470dde26561247b8hueston int a, lsb, psb;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char *ba = di_bus_addr(n);
23a276b1252962c987a613be470dde26561247b8hueston if (ba == NULL) {
23a276b1252962c987a613be470dde26561247b8hueston /*
23a276b1252962c987a613be470dde26561247b8hueston * di_bus_addr returned NULL. This can happen during
23a276b1252962c987a613be470dde26561247b8hueston * DR attach/detach of the mc driver. Just skip this
23a276b1252962c987a613be470dde26561247b8hueston * node for now.
23a276b1252962c987a613be470dde26561247b8hueston */
23a276b1252962c987a613be470dde26561247b8hueston continue;
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston a = OPL_MC_STR2BA(ba);
23a276b1252962c987a613be470dde26561247b8hueston lsb = OPL_MC_LSB(a);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi psb = opl_get_physical_board(mod, n);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (psb < 0 || psb >= OPL_IOB_MAX) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* psb mapping is out of range, skip */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston continue;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston lsb_to_psb[lsb] = psb;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Create the ioboard node. Add fru and label properties, and create room
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * for child hostbridge nodes.
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl *
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl * Only IKKAKU model has different IO topology.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic tnode_t *
78ed97a7b79b59ef2ef41f190c9be35c54d90119jlopl_iob_node_create(topo_mod_t *mp, tnode_t *parent, int inst,
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl opl_model_t opl_model)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int err;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *ion;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *fmri;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char label[8];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char fmri_str[32];
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_t *auth = topo_mod_auth(mp, parent);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (parent == NULL || inst < 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create ioboard FMRI */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, IOBOARD,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_free(auth);
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "create of tnode for ioboard failed: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_free(auth);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create node for this ioboard */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi ion = topo_node_bind(mp, parent, IOBOARD, inst, fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (ion == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "unable to bind ioboard: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL); /* mod_errno already set */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create and add FRU fmri for this ioboard */
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (opl_model == MODEL_IKKAKU)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (void) snprintf(fmri_str, sizeof (fmri_str), IKKAKU_IOBDFRU);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl else
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (void) snprintf(fmri_str, sizeof (fmri_str), IOBDFRU, inst);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_mod_str2nvl(mp, fmri_str, &fmri) == 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_fru_set(ion, fmri, 0, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Add label for this ioboard */
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (opl_model == MODEL_IKKAKU)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (void) snprintf(label, sizeof (label), IKKAKU_LABEL);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl else
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (void) snprintf(label, sizeof (label), LABEL, inst);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_label_set(ion, label, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create range of hostbridges on this ioboard */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (topo_node_range_create(mp, ion, HOSTBRIDGE, 0, OPL_HB_MAX) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "topo_node_range_create failed: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (ion);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl/*
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl * get the OPL model name from rootnode property "model"
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl */
78ed97a7b79b59ef2ef41f190c9be35c54d90119jlstatic int
78ed97a7b79b59ef2ef41f190c9be35c54d90119jlopl_get_model(topo_mod_t *mp, di_node_t opl_devtree, char *model)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl{
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl char *bufp;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl di_prom_handle_t promh = DI_PROM_HANDLE_NIL;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (opl_devtree == DI_NODE_NIL ||
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (promh = topo_mod_prominfo(mp)) == DI_PROM_HANDLE_NIL)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl return (-1);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (di_prom_prop_lookup_bytes(promh, opl_devtree, "model",
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (unsigned char **)&bufp) != -1) {
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl (void) strlcpy(model, bufp, MAXNAMELEN);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl return (0);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl } else {
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl return (-1);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl }
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl}
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*ARGSUSED*/
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic int
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_iob_enum(topo_mod_t *mp, tnode_t *parent, const char *name,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t imin, topo_instance_t imax, void *notused1, void *notused2)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi di_node_t opl_devtree;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_node_t pnode;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *ion;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_instance_t inst;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int lsb_to_psb[OPL_IOB_MAX];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston ioboard_contents_t ioboard_list[OPL_IOB_MAX];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int retval = 0;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl char model[MAXNAMELEN];
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl opl_model_t opl_model = MODEL_FF;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Validate the name is correct */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (strcmp(name, "ioboard") != 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Make sure we don't exceed OPL_IOB_MAX */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (imax >= OPL_IOB_MAX) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston imax = OPL_IOB_MAX;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston bzero(ioboard_list, sizeof (ioboard_list));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi opl_devtree = topo_mod_devinfo(mp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (opl_devtree == DI_NODE_NIL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_mod_seterrno(mp, errno);
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "devinfo init failed.\n");
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (opl_get_model(mp, opl_devtree, model) == -1) {
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl topo_mod_dprintf(mp, "opl_get_model failed.\n");
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl } else {
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl if (strncmp(model, "FF", 2) == 0)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl opl_model = MODEL_FF;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl else if (strncmp(model, "DC", 2) == 0)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl opl_model = MODEL_DC;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl else if (strcmp(model, "IKKAKU") == 0)
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl opl_model = MODEL_IKKAKU;
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl topo_mod_dprintf(mp, "opl_get_model %s found.\n", model);
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl }
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Create a mapping from logical board numbers (which are part of
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * the device node bus address) to physical board numbers, so we
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * can create meaningful fru labels.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi opl_map_boards(mp, opl_devtree, lsb_to_psb);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Figure out which boards are installed by finding hostbridges
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * with matching bus addresses.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (pnode = di_drv_first_node(OPL_PX_DRV, opl_devtree);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pnode != DI_NODE_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pnode = di_drv_next_node(pnode)) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int psb = -1;
864221ad7169608e293fbeaa9df563afc9f345a0kd int a, lsb, hb, rc;
864221ad7169608e293fbeaa9df563afc9f345a0kd
864221ad7169608e293fbeaa9df563afc9f345a0kd /* Get the bus address */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char *ba = di_bus_addr(pnode);
864221ad7169608e293fbeaa9df563afc9f345a0kd if (ba == NULL || (*ba == '\0')) {
864221ad7169608e293fbeaa9df563afc9f345a0kd return (-1); /* Return if it's not assigned */
864221ad7169608e293fbeaa9df563afc9f345a0kd }
864221ad7169608e293fbeaa9df563afc9f345a0kd
864221ad7169608e293fbeaa9df563afc9f345a0kd a = OPL_PX_STR2BA(ba);
864221ad7169608e293fbeaa9df563afc9f345a0kd lsb = OPL_PX_LSB(a);
864221ad7169608e293fbeaa9df563afc9f345a0kd hb = OPL_PX_HB(a);
864221ad7169608e293fbeaa9df563afc9f345a0kd rc = OPL_PX_RC(a);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Map logical system board to physical system board */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (lsb >= 0 && lsb <= OPL_IOB_MAX) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston psb = lsb_to_psb[lsb];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* If valid psb, note that this board exists */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (psb >= 0 && psb < OPL_IOB_MAX) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston ioboard_list[psb].count++;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston ioboard_list[psb].rcs[hb][rc] = pnode;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Now enumerate each existing board Exit loop if retval is
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * ever set to non-zero.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (inst = imin; inst <= imax && retval == 0; inst++) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* If this board doesn't contain any hostbridges, skip it */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (ioboard_list[inst].count == 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston continue;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create node for this ioboard */
78ed97a7b79b59ef2ef41f190c9be35c54d90119jl ion = opl_iob_node_create(mp, parent, inst, opl_model);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (ion == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
23a276b1252962c987a613be470dde26561247b8hueston "enumeration of ioboard failed: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston retval = -1;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston break;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Enumerate hostbridges on this ioboard, sets errno */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi retval = opl_hb_enum(mp, &ioboard_list[inst], ion, inst);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (retval);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}