picllom.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
*/
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This plugin creates PICL nodes and properties for objects handled through
* the blade support chip (BSC). The BSC Solaris land device driver exposes
* information to the plugin and other clients through an existing LOM
* (Lights Out Management) ioctl interface. The plugin only exercises
* a subset of the interface which is known to be supported by the bsc.
*
* All the nodes which may be accessible through the BSC are included below
* the SUNW,bscv node (class system-controller) in the /platform tree.
* This plugin interrogates the BSC to determine which of
* those nodes are actually available. Properties are added to such nodes and
* in the case of volatile properties like temperature, a call-back function
* is established for on-demand access to the current value.
*
* NOTE:
* Depends on PICL devtree plugin.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <alloca.h>
#include <syslog.h>
#include <string.h>
#include <libintl.h>
#include <picl.h>
#include <picltree.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <sys/systeminfo.h>
#include <time.h>
#include <picldefs.h>
#include <picld_pluginutil.h>
#include "picllom.h"
static void picllom_register(void);
static void picllom_init(void);
static void picllom_fini(void);
static node_list_t *create_node_list();
node_list_t *listp);
static int open_lom_rd(int *lom_fd);
static int update_voltage_stats();
static int update_fan_stats();
static void convert_node_name(char *ptr);
static int add_voltage_monitors(int lom_fd,
static int get_config_file(char *outfilename);
#pragma init(picllom_register)
static picld_plugin_reg_t my_reg_info = {
"SUNW_picllom",
};
static const char str_OK[] = "OK";
static const char str_FAIL[] = "FAIL";
static const char str_On[] = "on";
static const char str_Off[] = "off";
static const char str_Enabled[] = "Enabled";
static const char str_Disabled[] = "Disabled";
static char lom_device_path[PATH_MAX];
static lom_fandata_t fandata;
static lom_volts_t voltsdata;
static int n_leds = 0;
static int max_state_size = 0;
static char **led_labels = NULL;
static lom2_info_t info2data;
static struct {
int size;
char *str_colour;
static struct {
char *str_ledstate;
} ledstate_lkup[] = {
{ LOM_LED_OFF },
{ LOM_LED_ON },
{ LOM_LED_BLINKING },
};
static node_el_t *
{
}
return (ptr);
}
static void
{
}
static node_list_t *
{
}
return (ptr);
}
static void
{
return;
}
}
static void
{
}
/*
* Get a linking element and add handle to end of chain
*/
static void
{
else
}
}
/*
* Get a list of nodes of the specified classname under nodeh.
* Once a node of the specified class is found, its children are not
* searched.
*/
static void
{
int err;
/*
* go through the children
*/
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
else
sizeof (picl_nodehdl_t));
}
}
static int
{
int err = PICL_SUCCESS;
listp = create_node_list();
lominfh)) != PICL_SUCCESS) {
return (err); /* no /platform ! */
}
*lominfh = 0;
} else {
}
return (err);
}
static int
{
int err = PICL_SUCCESS;
char devfs_path[PATH_MAX];
char devices_path[PATH_MAX];
devfs_path, sizeof (devfs_path));
/* Build up the full device path and set the global */
return (err);
}
/*
* Look for a node of specified name and class
* Confine search to nodes one level below that of supplied handle
*/
static int
{
int err;
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
sizeof (namebuf));
if (err != PICL_SUCCESS)
break;
if ((err == PICL_SUCCESS) &&
return (PICL_SUCCESS);
}
sizeof (picl_nodehdl_t));
}
return (err);
}
/*
* Create and add the specified regular property
*/
static int
{
int err;
if (err != PICL_SUCCESS)
return (err);
&proph);
return (err);
}
/*
* Create and add the specified volatile property
*/
static int
{
int err;
if (err != PICL_SUCCESS)
return (err);
return (err);
}
/*
* open LOM device to read
*/
static int
open_lom_rd(int *lom_fd)
{
if (*lom_fd < 0)
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* Function to open LOM and read temperature sensor values.
* The index to a specific sensor is supplied and that value returned.
*/
static int
{
int lom_fd;
int err;
int res;
if (err == PICL_SUCCESS) {
if (res == 0) {
} else {
err = PICL_FAILURE;
}
}
return (err);
}
/*
* Function to open LOM and read voltage monitor values.
* Called for each property, so only perform update if time has changed
*/
static int
{
int lom_fd;
int err;
int res;
return (PICL_SUCCESS);
if (err == PICL_SUCCESS) {
if (res < 0) {
err = PICL_FAILURE;
}
}
return (err);
}
/*
* Function to open LOM and read voltage monitor values.
* The index to a specific voltage status is supplied and that value returned.
*/
static int
{
int res;
return (res);
return (PICL_SUCCESS);
}
/*
* Function to open LOM and read voltage monitor values.
* The index to a specific shutdown flag is supplied and that value returned.
*/
static int
{
int res;
return (res);
return (PICL_SUCCESS);
}
/*
* Function to open LOM and read fan values.
* Called for each property, so only perform update if time has changed
*/
static int
{
int lom_fd;
int err;
int res;
return (PICL_SUCCESS);
if (err == PICL_SUCCESS) {
if (res < 0) {
err = PICL_FAILURE;
}
}
return (err);
}
/*
* The index to a specific fan is supplied and its speed value returned.
*/
static int
{
int res;
return (res);
return (PICL_SUCCESS);
}
/*
* Read function for volatile "Temperature" property via LOM
*/
static int
{
int index;
/*
* get the sensor index from the displacement of the
* property handle and get its temperature.
*/
break;
}
/*
* Handle not found. As this is a plugin, stale handles
* cannot occur, so just fail.
*/
return (PICL_FAILURE);
}
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* Read function for volatile "VoltageStatus" property via LOM
*/
static int
{
int voltsStatus;
int index;
/*
* get the voltage monitor index from the displacement of the
* status property handle and get its status.
*/
break;
}
return (PICL_FAILURE);
return (PICL_FAILURE);
sizeof (str_FAIL));
return (PICL_SUCCESS);
}
/*
* Read function for volatile "VoltageShutdown" property via LOM
*/
static int
{
int voltsShutdown;
int index;
/*
* get the voltage monitor index from the displacement of the
* shutdown property handle and get its value.
*/
break;
}
return (PICL_FAILURE);
return (PICL_FAILURE);
sizeof (str_Disabled));
return (PICL_SUCCESS);
}
/*
* Read function for volatile fan speed property via LOM
*/
static int
{
int fan_speed;
int index;
/*
* get the relevant fan from the displacement of its property handle
*/
break;
}
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* look up function to convert led status into string
*/
static int
{
int i;
for (i = 0; i < lim; i++) {
return (PICL_SUCCESS);
}
}
*string = "";
switch (state) {
case LOM_LED_ACCESS_ERROR:
return (PICL_PROPVALUNAVAILABLE);
case LOM_LED_NOT_IMPLEMENTED:
/*FALLTHROUGH*/
case LOM_LED_OUTOFRANGE:
/*FALLTHROUGH*/
default:
return (PICL_FAILURE);
}
}
/*
* Read function for volatile led status property.
*/
static int
{
int index;
int lom_fd;
int res;
const char *string;
/*
* get the relevant led from the displacement of its property handle
*/
break;
}
return (PICL_FAILURE);
if (res != PICL_SUCCESS)
return (res);
/*
* The interface for reading LED status doesn't promise to maintain
* a constant mapping between LED index number and LED identity
* (as defined by its label). On the other hand, PICL does promise
* that whilst a handle remains valid the object it represents will
* remain constant. To reconcile these positions, we maintain
* tables of labels and handles linked by index value. We search
* for the handle with which we are presented and then locate its
* label. Then we request LED entries from the LOM and compare their
* labels with the one we seek. As an optimisation, we try the original
* index value first and then revert to a full search.
*/
/*
* full scan required (bet it doesn't work!)
* first re-establish the range to scan
*/
int i;
int n;
if (res != 0) {
return (PICL_PROPVALUNAVAILABLE);
}
for (i = 0; i < n; i++) {
if (res == 0 &&
0) {
break;
}
}
if (i == n) {
return (PICL_PROPVALUNAVAILABLE);
}
}
}
/*
* if we get here, then we found the right LED.
*/
return (res);
}
/*
* Read function for volatile fan status property.
* This is a synthesized property using speed and min speed properties
*/
static int
{
int fan_speed;
int index;
/*
* get the relevant fan from the displacement of its property handle
*/
break;
}
return (PICL_FAILURE);
return (PICL_FAILURE);
sizeof (str_FAIL));
return (PICL_SUCCESS);
}
/*
* change to lower case and convert any spaces into hyphens
*/
static void
convert_node_name(char *ptr)
{
char ch;
*ptr = '-';
}
}
}
/*
* find first occurrence of string s2 within string s1 (ignoring case)
*/
static const char *
{
int i;
return (s1 + i);
}
return (NULL);
}
static int
{
int res;
int i;
int err = PICL_SUCCESS;
const char *cptr;
/*
* for each temperature location add a sensor node
*/
if (err != PICL_SUCCESS)
break;
&temp_handles[i]);
if (err != PICL_SUCCESS)
break;
if (high_warnings[i] != 0) {
sizeof (tempr_t), &high_warnings[i],
&proph);
if (err != PICL_SUCCESS)
break;
}
if (high_shutdowns[i] != 0) {
sizeof (tempr_t), &high_shutdowns[i],
&proph);
if (err != PICL_SUCCESS)
break;
}
/*
* for the benefit of prtdiag, add a label of
* either enclosure or die where appropriate
*/
NULL) ||
NULL)) {
cptr = CPU_AMBIENT;
}
if (err != PICL_SUCCESS) {
break;
}
}
if (err != PICL_SUCCESS)
break;
}
if (err != PICL_SUCCESS) {
}
}
return (err);
}
static int
{
int res;
int i;
int err = PICL_SUCCESS;
/*
* for each voltage monitor add a monitor node
*/
if (err != PICL_SUCCESS)
break;
if (err != PICL_SUCCESS)
break;
sizeof (str_Disabled), read_vol_volts_shutdown,
NULL, &volts_shutdown_handles[i]);
if (err != PICL_SUCCESS)
break;
&volts_status_handles[i]);
if (err != PICL_SUCCESS)
break;
if (err != PICL_SUCCESS)
break;
}
if (err != PICL_SUCCESS) {
}
}
return (err);
}
static void
{
int err;
return;
}
/*
* the led may exist already, e.g. Fault
*/
if (err != PICL_SUCCESS)
return;
/*
* Unlike LEDs derived from other interfaces, these are not
* writable. Establish a read-only volatile property.
*/
if (err != PICL_SUCCESS)
return;
/*
* if colour was defined for this LED, add a colour property
*/
}
if (err != PICL_SUCCESS)
return;
if (err != PICL_SUCCESS)
return;
if (err != PICL_SUCCESS) {
}
}
static void
{
int i;
int len;
for (i = 0; i < (sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]));
i++) {
break;
}
}
}
static void
{
int res;
int i;
/*
* If the led state enquiry ioctl is supported, an enquiry on
* index -1 will return the state of the highest supported index
* value.
*/
if (res != 0)
return;
if (led_labels != NULL) {
for (i = 0; i < n_leds; i++) {
if (led_labels[i] != NULL) {
free(led_labels[i]);
}
}
led_labels = NULL;
}
if (led_handles != NULL) {
}
n_leds = 0;
if (led_labels != NULL)
if (led_handles != NULL)
led_labels = NULL;
led_handles = NULL;
return;
}
/*
* For each LED with a valid state, add a node
* and because of the ludicrous API, stache a copy of its label too
*/
for (i = 0; i < n_leds; i++) {
if (res != 0)
continue;
continue;
/*
* only add a new led node,
* if it's not already in place
*/
}
}
}
static int
{
int res;
int i;
int err = PICL_SUCCESS;
if (res == 0) {
/*
* fan data available through lom, remove any placeholder
* fan-unit nodes, they will be superseded via lom.conf
*/
char path[80];
int slot;
continue;
continue;
(void) ptree_destroy_node(fan_unit_h);
}
/*
* see if fan names can be obtained
*/
/*
* if LOMIOCINFO2 not supported, names area
* will remain empty
*/
/*
* for each fan which is present, add a fan node
*/
for (i = 0; i < MAX_FANS; i++) {
char fanname[80];
continue;
"fan%d", i + 1);
} else {
sizeof (fanname));
}
if (err != PICL_SUCCESS)
break;
PICL_PTYPE_INT, PICL_READ, sizeof (int),
if (err != PICL_SUCCESS)
break;
PICL_PTYPE_INT, PICL_READ, sizeof (int),
if (err != PICL_SUCCESS)
break;
"%", &proph);
if (err != PICL_SUCCESS)
break;
&fan_status_handles[i]);
if (err != PICL_SUCCESS)
break;
/*
* add a label for prtdiag
*/
if (err != PICL_SUCCESS)
break;
if (err != PICL_SUCCESS)
break;
}
if (err != PICL_SUCCESS) {
}
}
return (err);
}
static void
{
/*
* initialise led colours lookup
*/
int i;
for (i = 0; i < lim; i++) {
}
for (i = 0; i < lim; i++) {
colour_lkup[i].size =
}
/*
* initialise led state lookup strings
*/
}
/*
* The size of outfilename must be PATH_MAX
*/
static int
get_config_file(char *outfilename)
{
return (0);
}
}
return (0);
}
}
return (0);
}
return (-1);
}
/*
* executed as part of .init when the plugin is dlopen()ed
*/
static void
picllom_register(void)
{
(void) picld_plugin_register(&my_reg_info);
}
/*
* Init entry point of the plugin
* Creates the PICL nodes and properties in the physical and logical aspects.
*/
static void
picllom_init(void)
{
int lom_fd;
char fullfilename[PATH_MAX];
/*
* Get platform node
*/
!= PICL_SUCCESS) {
return;
}
/*
* Get lom node
*/
return;
}
/*
* Retrive the device path to open
*/
if (get_lom_device_path(&lominfh) < 0) {
return;
}
/*
* Open LOM device and interrogate for devices it monitors
*/
return;
}
if (get_config_file(fullfilename) < 0) {
return;
}
return;
}
}
/*
* fini entry point of the plugin
*/
static void
picllom_fini(void)
{
}