#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include <libnvpair.h>
#include <syslog.h>
#include <picl.h>
#include <picltree.h>
#include <picldefs.h>
static void picl_frutree_register(void);
static void picl_frutree_init(void);
static void picl_frutree_fini(void);
static void picl_frutree_evhandler(const char *ename, const void *earg,
size_t size, void *cookie);
#pragma init(picl_frutree_register)
#define CREATE_FRUTREE_FAIL gettext("Failed to create frutree node\n")
#define CREATE_CHASSIS_FAIL gettext("Failed to create chassis node\n")
#define IOBRD_INIT_FAIL gettext("do_ioboard_init() failed\n")
#define RSCBRD_INIT_FAIL gettext("do_rscboard_init() failed\n")
#define FCAL_INIT_FAIL gettext("do_fcal_init() failed\n")
#define PS_INIT_FAIL gettext("do_power_supplies_init() failed\n")
#define SYSBOARD_INIT_FAIL gettext("do_motherboard_init() failed\n")
#define CHASSIS_VIEWPOINTS gettext("front left right rear")
#define SEEPROM_SOURCE "_seeprom_source"
#define FRU_PARENT "_fru_parent"
#define IOBRD 0
#define RSC 1
#define FCAL0 2
#define FCAL1 3
#define FCALGBIC 4
#define PDB 5
#define PS0 6
#define PS1 7
#define PS2 8
#define SYSBRD 9
#define CPUMOD0 10
#define CPUMOD1 11
#define CPUMOD2 12
#define CPUMOD3 13
#define CPU0_DIMM0 14
#define DIMMS_PER_MOD 8
#define DIMMS_PER_SLOT 16
static picld_plugin_reg_t my_reg_info = {
PICLD_PLUGIN_VERSION_1,
PICLD_PLUGIN_NON_CRITICAL,
"SUNW_Sun-Fire-880_frutree",
picl_frutree_init,
picl_frutree_fini
};
static char *platform_frupath[] = {
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ae",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a0",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a2",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a4",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a6",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a8",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,aa",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ac",
"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ae",
NULL};
static char *location_label[] = {
NULL,
NULL,
"0",
"1",
NULL,
NULL,
"0",
"1",
"2",
NULL,
"A",
"B",
"C",
"D",
"J2900",
"J3100",
"J2901",
"J3101",
"J3000",
"J3200",
"J3001",
"J3201",
"J7900",
"J8100",
"J7901",
"J8101",
"J8000",
"J8200",
"J8001",
"J8201",
"0",
"1",
NULL};
static char *frutree_power_supply[] = {
"/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
"/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
"/frutree/chassis/power-dist-board/power-supply-slot?Slot=2",
NULL};
static char *frutree_cpu_module[] = {
"/frutree/chassis/system-board/cpu-mem-slot?Slot=0",
"/frutree/chassis/system-board/cpu-mem-slot?Slot=1",
"/frutree/chassis/system-board/cpu-mem-slot?Slot=2",
"/frutree/chassis/system-board/cpu-mem-slot?Slot=3",
NULL};
static picl_nodehdl_t frutreeh;
static int do_ioboard_init(picl_nodehdl_t);
static int do_rscboard_init(picl_nodehdl_t);
static int do_fcal_init(picl_nodehdl_t);
static int do_power_supplies_init(picl_nodehdl_t);
static int do_motherboard_init(picl_nodehdl_t);
static int do_cpu_module_init(picl_nodehdl_t, int);
static int do_dimms_init(picl_nodehdl_t, int, int);
static int add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
static int add_slot_prop(picl_nodehdl_t, int);
static int add_label_prop(picl_nodehdl_t, char *);
static int add_void_fda_prop(picl_nodehdl_t);
static int add_viewpoints_prop(picl_nodehdl_t, char *);
static int add_all_nodes();
static int remove_all_nodes(picl_nodehdl_t);
static int add_hotplug_fru_device(void);
static int rem_hotplug_fru_device(void);
static int is_added_device(char *, char *);
static int is_removed_device(char *, char *);
static int add_power_supply(int);
static int remove_power_supply(int);
static int add_cpu_module(int);
static int remove_cpu_module(int);
static void
picl_frutree_register()
{
(void) picld_plugin_register(&my_reg_info);
}
static void
picl_frutree_init()
{
int err;
err = add_all_nodes();
if (err != PICL_SUCCESS) {
(void) remove_all_nodes(frutreeh);
return;
}
(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
picl_frutree_evhandler, NULL);
(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
picl_frutree_evhandler, NULL);
}
static void
picl_frutree_fini(void)
{
(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
picl_frutree_evhandler, NULL);
(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
picl_frutree_evhandler, NULL);
(void) remove_all_nodes(frutreeh);
}
static void
picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
void *cookie)
{
if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
(void) add_hotplug_fru_device();
} else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
(void) rem_hotplug_fru_device();
}
}
static int
do_ioboard_init(picl_nodehdl_t rooth)
{
picl_nodehdl_t iobrdh;
picl_nodehdl_t tmph;
int err;
if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("io-board", "fru", &iobrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(iobrdh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, iobrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_SUCCESS);
}
static int
do_rscboard_init(picl_nodehdl_t rooth)
{
picl_nodehdl_t rscbrdh;
picl_nodehdl_t tmph;
int err;
if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("rsc-board", "fru", &rscbrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(rscbrdh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, rscbrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_SUCCESS);
}
static int
do_fcal_init(picl_nodehdl_t rooth)
{
picl_nodehdl_t fcalsloth;
picl_nodehdl_t fcalmodh;
picl_nodehdl_t fcalgbich;
picl_nodehdl_t tmph;
int i, err, slotnum;
for (i = FCAL0; i <= FCAL1; i++) {
err = ptree_create_node("fcal-backplane-slot",
"location", &fcalsloth);
if (err != PICL_SUCCESS)
return (err);
slotnum = i - FCAL0;
err = add_slot_prop(fcalsloth, slotnum);
if (err != PICL_SUCCESS)
return (err);
err = add_label_prop(fcalsloth, location_label[i]);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, fcalsloth);
if (err != PICL_SUCCESS)
return (err);
if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("fcal-backplane", "fru",
&fcalmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(fcalmodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(fcalsloth, fcalmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, fcalmodh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
}
if (ptree_get_node_by_path(platform_frupath[FCALGBIC], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("fcal-gbic-board", "fru",
&fcalgbich);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(fcalgbich);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, fcalgbich);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, fcalgbich, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_SUCCESS);
}
static int
do_power_supplies_init(picl_nodehdl_t rooth)
{
picl_nodehdl_t powerbrdh;
picl_nodehdl_t powersloth;
picl_nodehdl_t powermodh;
picl_nodehdl_t tmph;
int i, err, slotnum;
if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(powerbrdh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, powerbrdh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
for (i = PS0; i <= PS2; i++) {
err = ptree_create_node("power-supply-slot",
"location", &powersloth);
if (err != PICL_SUCCESS)
return (err);
slotnum = i - PS0;
err = add_slot_prop(powersloth, slotnum);
if (err != PICL_SUCCESS)
return (err);
err = add_label_prop(powersloth, location_label[i]);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(powerbrdh, powersloth);
if (err != PICL_SUCCESS)
return (err);
if (ptree_get_node_by_path(platform_frupath[i],
&tmph) == PICL_SUCCESS) {
err = ptree_create_node("power-supply",
"fru", &powermodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(powermodh, tmph,
SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(powermodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(powersloth, powermodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, powermodh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
}
}
return (PICL_SUCCESS);
}
static int
do_motherboard_init(picl_nodehdl_t rooth)
{
picl_nodehdl_t sysboardh;
picl_nodehdl_t cpumemsloth;
picl_nodehdl_t cpumemmodh;
picl_nodehdl_t tmph;
int i, err, slotnum;
if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("system-board", "fru",
&sysboardh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(sysboardh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, sysboardh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
for (i = CPUMOD0; i <= CPUMOD3; i++) {
err = ptree_create_node("cpu-mem-slot", "location",
&cpumemsloth);
if (err != PICL_SUCCESS)
return (err);
slotnum = i - CPUMOD0;
err = add_slot_prop(cpumemsloth, slotnum);
if (err != PICL_SUCCESS)
return (err);
err = add_label_prop(cpumemsloth, location_label[i]);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(sysboardh, cpumemsloth);
if (err != PICL_SUCCESS)
return (err);
if (ptree_get_node_by_path(platform_frupath[i],
&tmph) == PICL_SUCCESS) {
err = ptree_create_node("cpu-mem-module",
"fru", &cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(cpumemmodh, tmph,
SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(cpumemsloth, cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, cpumemmodh,
FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
err = do_cpu_module_init(cpumemmodh, slotnum);
if (err != PICL_SUCCESS)
return (err);
}
}
}
return (PICL_SUCCESS);
}
static int
do_cpu_module_init(picl_nodehdl_t rooth, int slot)
{
picl_nodehdl_t cpumodh;
int i, c, err;
for (i = 0; i <= 1; i++) {
err = ptree_create_node("cpu-module", "location",
&cpumodh);
if (err != PICL_SUCCESS)
return (err);
err = add_slot_prop(cpumodh, i);
if (err != PICL_SUCCESS)
return (err);
c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
err = add_label_prop(cpumodh, location_label[c]);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, cpumodh);
if (err != PICL_SUCCESS)
return (err);
err = do_dimms_init(cpumodh, slot, i);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_SUCCESS);
}
static int
do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
{
picl_nodehdl_t dimmsloth;
picl_nodehdl_t dimmmodh;
picl_nodehdl_t tmph;
int i, c, l, err;
for (i = 0; i < DIMMS_PER_MOD; i++) {
err = ptree_create_node("dimm-slot", "location",
&dimmsloth);
if (err != PICL_SUCCESS)
return (err);
err = add_slot_prop(dimmsloth, i);
if (err != PICL_SUCCESS)
return (err);
c = ((slot * DIMMS_PER_SLOT) +
(module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
l = c - (DIMMS_PER_SLOT * slot);
err = add_label_prop(dimmsloth, location_label[l]);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(rooth, dimmsloth);
if (err != PICL_SUCCESS)
return (err);
if (ptree_get_node_by_path(platform_frupath[c], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("dimm-module", "fru",
&dimmmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(dimmmodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(dimmsloth, dimmmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
}
return (PICL_SUCCESS);
}
static int
add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
{
picl_prophdl_t proph;
ptree_propinfo_t propinfo;
int err;
if (str == NULL)
return (PICL_FAILURE);
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
str, NULL, NULL);
if (err != PICL_SUCCESS)
return (err);
err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
{
picl_prophdl_t proph;
ptree_propinfo_t propinfo;
int err;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
if (err != PICL_SUCCESS)
return (err);
err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
add_label_prop(picl_nodehdl_t nodeh, char *label)
{
picl_prophdl_t proph;
ptree_propinfo_t propinfo;
int err;
if (label == NULL)
return (PICL_FAILURE);
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
NULL, NULL);
if (err != PICL_SUCCESS)
return (err);
err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
add_void_fda_prop(picl_nodehdl_t nodeh)
{
picl_prophdl_t proph;
ptree_propinfo_t propinfo;
int err;
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
if (err != PICL_SUCCESS)
return (err);
err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
{
picl_prophdl_t proph;
ptree_propinfo_t propinfo;
int err;
if (string == NULL)
return (PICL_FAILURE);
err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
NULL, NULL);
if (err != PICL_SUCCESS)
return (err);
err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
add_all_nodes()
{
picl_nodehdl_t rooth;
picl_nodehdl_t chassish;
int err;
err = ptree_get_root(&rooth);
if (err != PICL_SUCCESS) {
return (err);
}
err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
return (err);
}
err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
return (err);
}
err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
if (err != PICL_SUCCESS)
return (err);
err = do_ioboard_init(chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, IOBRD_INIT_FAIL);
return (err);
}
err = do_rscboard_init(chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, RSCBRD_INIT_FAIL);
return (err);
}
err = do_fcal_init(chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, FCAL_INIT_FAIL);
return (err);
}
err = do_power_supplies_init(chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, PS_INIT_FAIL);
return (err);
}
err = do_motherboard_init(chassish);
if (err != PICL_SUCCESS) {
syslog(LOG_ERR, SYSBOARD_INIT_FAIL);
return (err);
}
return (PICL_SUCCESS);
}
static int
remove_all_nodes(picl_nodehdl_t rooth)
{
picl_nodehdl_t chdh;
int err, done = 0;
while (!done) {
err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
sizeof (picl_nodehdl_t));
if (err != PICL_PROPNOTFOUND) {
(void) remove_all_nodes(chdh);
} else {
err = ptree_delete_node(rooth);
if (err != PICL_SUCCESS) {
return (err);
} else {
(void) ptree_destroy_node(rooth);
}
done = 1;
}
}
return (PICL_SUCCESS);
}
static int
add_hotplug_fru_device()
{
int i, err, slotnum;
for (i = PS0; i <= PS2; i++) {
slotnum = i - PS0;
err = is_added_device(platform_frupath[i],
frutree_power_supply[slotnum]);
if (err != PICL_SUCCESS)
continue;
err = add_power_supply(slotnum);
if (err != PICL_SUCCESS)
continue;
}
for (i = CPUMOD0; i <= CPUMOD3; i++) {
slotnum = i - CPUMOD0;
err = is_added_device(platform_frupath[i],
frutree_cpu_module[slotnum]);
if (err != PICL_SUCCESS)
continue;
err = add_cpu_module(slotnum);
if (err != PICL_SUCCESS)
continue;
}
return (PICL_SUCCESS);
}
static int
rem_hotplug_fru_device()
{
int i, err, slotnum;
for (i = PS0; i <= PS2; i++) {
slotnum = i - PS0;
err = is_removed_device(platform_frupath[i],
frutree_power_supply[slotnum]);
if (err != PICL_SUCCESS)
continue;
err = remove_power_supply(slotnum);
if (err != PICL_SUCCESS)
continue;
}
for (i = CPUMOD0; i <= CPUMOD3; i++) {
slotnum = i - CPUMOD0;
err = is_removed_device(platform_frupath[i],
frutree_cpu_module[slotnum]);
if (err != PICL_SUCCESS)
continue;
err = remove_cpu_module(slotnum);
if (err != PICL_SUCCESS)
continue;
}
return (PICL_SUCCESS);
}
static int
is_added_device(char *plat, char *fru)
{
int err;
picl_nodehdl_t plath, frusloth, frumodh;
err = ptree_get_node_by_path(plat, &plath);
if (err != PICL_SUCCESS)
return (err);
err = ptree_get_node_by_path(fru, &frusloth);
if (err != PICL_SUCCESS)
return (err);
err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
&frumodh, sizeof (picl_nodehdl_t));
if (err == PICL_SUCCESS)
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
static int
is_removed_device(char *plat, char *fru)
{
int err;
picl_nodehdl_t plath, frusloth, frumodh;
err = ptree_get_node_by_path(plat, &plath);
if (err == PICL_SUCCESS)
return (PICL_FAILURE);
err = ptree_get_node_by_path(fru, &frusloth);
if (err != PICL_SUCCESS)
return (err);
err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
&frumodh, sizeof (picl_nodehdl_t));
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static int
remove_picl_node(picl_nodehdl_t nodeh)
{
int err;
err = ptree_delete_node(nodeh);
if (err != PICL_SUCCESS)
return (err);
(void) ptree_destroy_node(nodeh);
return (PICL_SUCCESS);
}
static void
frudr_completion_handler(char *ename, void *earg, size_t size)
{
picl_nodehdl_t fruh;
if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
fruh = 0;
(void) nvlist_lookup_uint64(earg,
PICLEVENTARG_FRUHANDLE, &fruh);
if (fruh != 0) {
(void) remove_picl_node(fruh);
}
}
nvlist_free(earg);
free(earg);
free(ename);
}
static void
post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
{
nvlist_t *nvl;
char *ev_name;
ev_name = strdup(ename);
if (ev_name == NULL)
return;
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) {
free(ev_name);
return;
}
if (parenth != 0L &&
nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
free(ev_name);
nvlist_free(nvl);
return;
}
if (fruh != 0L &&
nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
free(ev_name);
nvlist_free(nvl);
return;
}
if (ptree_post_event(ev_name, nvl, sizeof (nvl),
frudr_completion_handler) != 0) {
free(ev_name);
nvlist_free(nvl);
}
}
static int
add_power_supply(int slotnum)
{
picl_nodehdl_t powersloth;
picl_nodehdl_t powermodh;
picl_nodehdl_t tmph;
int i, err;
if (ptree_get_node_by_path(frutree_power_supply[slotnum],
&powersloth) == PICL_SUCCESS) {
i = slotnum + PS0;
if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("power-supply", "fru",
&powermodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(powermodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(powersloth, powermodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, powermodh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
post_frudr_event(PICL_FRU_ADDED, 0, powermodh);
}
}
return (PICL_SUCCESS);
}
static int
remove_power_supply(int slotnum)
{
picl_nodehdl_t powersloth;
picl_nodehdl_t powermodh;
int err;
if (ptree_get_node_by_path(frutree_power_supply[slotnum],
&powersloth) == PICL_SUCCESS) {
err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
&powermodh, sizeof (picl_nodehdl_t));
if (err != PICL_SUCCESS) {
return (err);
}
err = ptree_delete_node(powermodh);
if (err != PICL_SUCCESS) {
return (err);
} else {
(void) ptree_destroy_node(powermodh);
}
post_frudr_event(PICL_FRU_REMOVED, 0, powermodh);
}
return (PICL_SUCCESS);
}
static int
add_cpu_module(int slotnum)
{
picl_nodehdl_t cpumemsloth;
picl_nodehdl_t cpumemmodh;
picl_nodehdl_t tmph;
int i, err;
if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
&cpumemsloth) == PICL_SUCCESS) {
i = slotnum + CPUMOD0;
if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
PICL_SUCCESS) {
err = ptree_create_node("cpu-mem-module", "fru",
&cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE);
if (err != PICL_SUCCESS)
return (err);
err = add_void_fda_prop(cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = ptree_add_node(cpumemsloth, cpumemmodh);
if (err != PICL_SUCCESS)
return (err);
err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT);
if (err != PICL_SUCCESS)
return (err);
}
err = do_cpu_module_init(cpumemmodh, slotnum);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_SUCCESS);
}
static int
remove_cpu_module(int slotnum)
{
picl_nodehdl_t cpumemsloth;
picl_nodehdl_t cpumemmodh;
int err;
if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
&cpumemsloth) == PICL_SUCCESS) {
err = ptree_get_propval_by_name(cpumemsloth, PICL_PROP_CHILD,
&cpumemmodh, sizeof (picl_nodehdl_t));
if (err != PICL_SUCCESS) {
return (err);
}
err = remove_all_nodes(cpumemmodh);
if (err != PICL_SUCCESS) {
return (err);
}
}
return (PICL_SUCCESS);
}