#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <alloca.h>
#include <syslog.h>
#include <string.h>
#include <libintl.h>
#include <picl.h>
#include <picltree.h>
#include <sys/types.h>
#include <sys/obpdefs.h>
#include "piclmemcfg.h"
#include "memcfg_impl.h"
static void piclmemcfg_register(void);
static void piclmemcfg_init(void);
static void piclmemcfg_fini(void);
#pragma init(piclmemcfg_register)
static picld_plugin_reg_t my_reg_info = {
PICLD_PLUGIN_VERSION_1,
PICLD_PLUGIN_NON_CRITICAL,
"SUNW_piclmemcfg",
piclmemcfg_init,
piclmemcfg_fini
};
static int
create_logical_tree(picl_nodehdl_t memh, mmodinfo_t *mmodinfo)
{
picl_nodehdl_t msegh;
picl_nodehdl_t *memsegh;
ptree_propinfo_t propinfo;
uint32_t ifactor = INTERLEAVEFACTOR;
int i;
int err = PICL_SUCCESS;
if ((memsegh = alloca(sizeof (picl_nodehdl_t) * TOTAL_MEM_SLOTS)) ==
NULL)
return (PICL_FAILURE);
for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
if (mmodinfo[i].size == 0) {
memsegh[i] = 0;
continue;
}
err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT,
PICL_CLASS_MEMORY_SEGMENT, &msegh);
if (err != PICL_SUCCESS)
break;
memsegh[i] = msegh;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_UNSIGNED_INT, PICL_READ,
sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_create_and_add_prop(msegh, &propinfo,
&mmodinfo[i].size, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_UNSIGNED_INT, PICL_READ,
sizeof (mmodinfo[i].base), PICL_PROP_BASEADDRESS, NULL,
NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_create_and_add_prop(msegh, &propinfo,
&mmodinfo[i].base, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (ifactor),
PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_create_and_add_prop(msegh, &propinfo, &ifactor,
NULL);
if (err != PICL_SUCCESS)
break;
if (mmodinfo[i].memmodh == 0)
continue;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
PICL_REFPROP_MEMORY_MODULE, NULL, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_create_and_add_prop(msegh, &propinfo,
&mmodinfo[i].memmodh, NULL);
if (err != PICL_SUCCESS)
break;
}
if (err != PICL_SUCCESS) {
for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
if (memsegh[i] == 0)
continue;
(void) ptree_delete_node(memsegh[i]);
(void) ptree_destroy_node(memsegh[i]);
}
}
return (err);
}
static int
create_physical_tree(picl_nodehdl_t plfh, mmodinfo_t *mmodinfo)
{
picl_nodehdl_t mch, memmodh;
ptree_propinfo_t propinfo;
int i;
int err = PICL_SUCCESS;
uint32_t id;
err = ptree_create_and_add_node(plfh, PICL_NAME_MEMORY_CONTROLLER,
PICL_CLASS_MEMORY_CONTROLLER, &mch);
if (err != PICL_SUCCESS)
return (err);
for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
if (mmodinfo[i].size == 0)
continue;
err = ptree_create_and_add_node(mch, PICL_NAME_MEMORY_MODULE,
PICL_CLASS_MEMORY_MODULE, &memmodh);
if (err != PICL_SUCCESS)
break;
mmodinfo[i].memmodh = memmodh;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_UNSIGNED_INT, PICL_READ,
sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_create_and_add_prop(memmodh, &propinfo,
&mmodinfo[i].size, NULL);
if (err != PICL_SUCCESS)
break;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_INT, PICL_READ, sizeof (id), PICL_PROP_ID,
NULL, NULL);
if (err != PICL_SUCCESS)
break;
id = i;
err = ptree_create_and_add_prop(memmodh, &propinfo, &id, NULL);
if (err != PICL_SUCCESS)
break;
}
if (err != PICL_SUCCESS) {
for (i = 0; i < TOTAL_MEM_SLOTS; i++)
mmodinfo[i].memmodh = 0;
(void) ptree_delete_node(mch);
(void) ptree_destroy_node(mch);
}
return (err);
}
static int
get_reg_info(picl_nodehdl_t plfh, picl_nodehdl_t memh,
mmodinfo_t *mmodinfo)
{
picl_prophdl_t proph;
ptree_propinfo_t pinfo;
regspec_t *memspec;
int i, err;
int pval;
int nregspec;
err = ptree_get_propval_by_name(plfh, OBP_PROP_SIZE_CELLS, &pval,
sizeof (pval));
if (err == PICL_PROPNOTFOUND)
pval = SUPPORTED_NUM_CELL_SIZE;
else if (err != PICL_SUCCESS)
return (err);
if (pval != SUPPORTED_NUM_CELL_SIZE)
return (PICL_FAILURE);
err = ptree_get_prop_by_name(memh, OBP_REG, &proph);
if (err != PICL_SUCCESS)
return (err);
err = ptree_get_propinfo(proph, &pinfo);
if (err != PICL_SUCCESS)
return (err);
if ((memspec = alloca(pinfo.piclinfo.size)) == NULL)
return (PICL_FAILURE);
nregspec = pinfo.piclinfo.size / sizeof (*memspec);
if ((nregspec == 0) || (nregspec > TOTAL_MEM_SLOTS))
return (PICL_FAILURE);
err = ptree_get_propval(proph, memspec, pinfo.piclinfo.size);
if (err != PICL_SUCCESS)
return (err);
for (i = 0; i < nregspec; i++) {
mmodinfo[i].base = memspec[i].physaddr;
mmodinfo[i].size = memspec[i].size;
}
return (PICL_SUCCESS);
}
static void
piclmemcfg_register(void)
{
(void) picld_plugin_register(&my_reg_info);
}
static void
piclmemcfg_init(void)
{
picl_nodehdl_t plfh, memh;
mmodinfo_t mmodinfo[TOTAL_MEM_SLOTS];
if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) {
syslog(LOG_ERR, EM_INIT_FAILED);
return;
}
if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) {
syslog(LOG_ERR, EM_INIT_FAILED);
return;
}
(void) memset(mmodinfo, 0, sizeof (mmodinfo));
if ((get_reg_info(plfh, memh, mmodinfo)) != PICL_SUCCESS) {
syslog(LOG_ERR, EM_INIT_FAILED);
return;
}
if ((create_physical_tree(plfh, mmodinfo)) != PICL_SUCCESS)
syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED);
if ((create_logical_tree(memh, mmodinfo)) != PICL_SUCCESS)
syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED);
}
static void
piclmemcfg_fini(void)
{
}