/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <fm/topo_mod.h>
#include <unistd.h>
#include <fcntl.h>
#include <umem.h>
#include <mem_mdesc.h>
/*
* Enumerates the DIMMS in a system. For each DIMM found, the necessary nodes
* are also constructed.
*/
extern topo_method_t pi_mem_methods[];
/* Forward declaration */
topo_instance_t, void *, void *);
{ dimm_enum, dimm_release };
1
};
int
{
if (getenv("TOPOMEMDBG"))
return (-1);
return (-1);
}
return (-1);
}
return (0);
}
void
{
}
static tnode_t *
{
int err;
"Unable to make nvlist for %s bind: %s.\n",
return (NULL);
}
"topo_node_bind (%s%d/%s%d) failed: %s\n",
name, i,
return (NULL);
}
/* chassis */
}
return (ntn);
}
typedef struct {
const char *nh_name;
const char *nh_sscan;
} nac_hc_t;
{"branch", "BR%d" },
{"dram-channel", "CH%d" },
{"rank", "R%d" },
{"dimm", "D%d" },
{"memboard", "MR%d" },
{"memboard", "MEM%d" },
{"chip", "CMP%d" }
};
static const char *
{
int i;
if (s == NULL)
return (NULL);
for (i = 0; i < sizeof (nac_mem_tbl) / sizeof (nac_hc_t); i++) {
return (nac_mem_tbl[i].nh_name);
}
return (NULL);
}
static int
{
/*
* Because mem_tnode_create will fill in a "FRU" value by default,
* but not an "ASRU" value, we have to compute the desired "FRU"
* value -before- calling mem_tnode_create, but it's ok to
* topo_mod_asru_set() the ASRU value after the topo_node is
* created.
*/
nerr++;
return (++nerr);
/* ASRU will be computed by topo method */
nerr++;
return (nerr);
}
int
{
const char *t = s + start;
return (strlen(s)); /* end */
else
return (t - s); /* next slash */
}
/*
* mem_range_create and mem_inst_create are mutually recursive routines which
* together create the node hierarchy for one dimm and its siblings.
* mem_range_create is called when creating the first instance of a given node
* type as child of a parent instance, because it is then, and only then,
* that a topo range must be created. It calls mem_inst_create for its first
* and subsequent instances. The recursion always starts with
* mem_range_create, so it performs the up-front sanity checks.
*
* Note: the list of mem_dimm_map_t's pointed at by dp must be sorted
* alphabetically by *dm_label.
*/
static int
{
const char *nodename;
mem_dimm_map_t *d;
int nerr = 0;
d = dp;
} else {
}
if ((d != NULL) &&
return (nerr);
}
int
{
const char *nodename;
mem_dimm_map_t *d;
int nerr = 0;
return (1); /* definitely an error */
return (1); /* recursed too far */
MEM_DIMM_MAX) < 0) {
"DIMM range %s error %s\n", nodename,
return (-1);
}
} else {
/*
* Skip over NAC elements other than those listed
* above. These elements will appear
* in the DIMM's unum, but not in hc: scheme hierarchy.
*/
}
continue; /* child of 1st instance -- already done */
pflen) == 0) { /* child of same parent */
/*
* Same nodename as sibling. Don't create
* new range, or the enumeration will die.
*/
dp = d;
} else {
dp = d;
}
}
else
return (nerr); /* finished all children of my parent */
}
return (nerr); /* reached end of mem_dimm_map_t list */
}
static int
{
int l, nerrs;
char *p;
break;
}
}
if (p != NULL) {
l = 3; /* start with MEM */
break;
}
}
} else {
return (1);
}
else
nerrs = 1;
return (nerrs);
}
/*
* The hc-scheme memory enumerator is invoked from within a platform
* toplogy file. Make sure that the invocation is either
* 1) a child of the chip enumerator, which will cause the argument "rnode"
* below to be a chip node, and the dimm structures specific for that chip can
* then be built from its specific node, or
* 2) a child of the motherboard enumerator -- for Batoka and similar machines
* with cpu-boards.
*/
/*ARGSUSED*/
static int
{
return (-1);
}
/*ARGSUSED*/
static void
{
}