fac_prov_ipmi.c revision 825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77
/*
* 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
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <alloca.h>
#include <errno.h>
#include <libnvpair.h>
#include <fm/topo_mod.h>
#include <libipmi.h>
#define BUFSZ 128
#define TOPO_PGROUP_IPMI "ipmi"
#define THUMPER_PRESENT_LED_MASK 0x01
#define THUMPER_SERVICE_LED_MASK 0x02
#define THUMPER_OK2RM_LED_MASK 0x08
/*
* The largest possible SDR ID length is 2^5+1
*/
#define MAX_ID_LEN 33
#define TOPO_METH_IPMI_READING_VERSION 0
#define TOPO_METH_IPMI_STATE_VERSION 0
#define TOPO_METH_IPMI_MODE_VERSION 0
#define TOPO_METH_THUMPER_LOCATE_VERSION 0
#define TOPO_METH_THUMPER_MODE_VERSION 0
#define TOPO_METH_IPMI_ENTITY_VERSION 0
#define TOPO_METH_DIMM_IPMI_ENTITY_VERSION 0
topo_instance_t, topo_instance_t, void *, void *);
/*
* IPMI facility provider methods
*/
nvlist_t **);
nvlist_t **);
const topo_modinfo_t ipmi_info =
&ipmi_ops };
static const topo_method_t ipmi_node_methods[] = {
{ "dimm_ipmi_entity", TOPO_PROP_METH_DESC,
{ NULL }
};
static const topo_method_t ipmi_fac_methods[] = {
{ "ipmi_sensor_reading", TOPO_PROP_METH_DESC,
{ "ipmi_sensor_state", TOPO_PROP_METH_DESC,
{ "ipmi_indicator_mode", TOPO_PROP_METH_DESC,
{ "thumper_locate_mode", TOPO_PROP_METH_DESC,
{ "thumper_indicator_mode", TOPO_PROP_METH_DESC,
{ "dimm_ipmi_entity", TOPO_PROP_METH_DESC,
{ NULL }
};
struct entity_info {
};
struct sensor_data {
char sd_entity_ref[MAX_ID_LEN];
char *sd_class;
};
/*ARGSUSED*/
int
{
}
void
{
}
static char *
{
char *fmtstr;
return (NULL);
}
return (NULL);
}
return (fmtstr);
}
/*ARGSUSED*/
static int
{
char *entity_ref;
int err;
if (vers > TOPO_METH_IPMI_STATE_VERSION)
&entity_ref, &err) != 0) {
}
return (-1);
}
return (-1);
}
break;
break;
default:
"compact SDR\n", entity_ref);
return (-1);
}
== NULL) {
ipmi_errmsg(hdl));
return (-1);
}
TOPO_SENSOR_STATE) != 0 ||
!= 0) {
}
return (0);
}
/*ARGSUSED*/
static int
{
int err = 0;
double conv_reading;
&entity_ref, &err) != 0) {
}
return (-1);
}
== NULL) {
return (-1);
}
== NULL) {
"%s, sensor_num=%d (%s)\n", entity_ref,
return (-1);
}
!= 0) {
return (-1);
}
TOPO_SENSOR_READING) != 0 ||
}
return (0);
}
static int
{
char *entity_ref;
if (vers > TOPO_METH_IPMI_MODE_VERSION)
/*
* Get an IPMI handle and then lookup the generic device locator sensor
* data record referenced by the entity_ref prop val
*/
return (-1);
}
&entity_ref, &err) != 0) {
}
== NULL) {
return (-1);
}
/*
* Now look for a private argument list to figure out whether we're
* doing a get or a set operation, and then do it.
*/
/*
* Set the LED mode
*/
&mode_in)) != 0) {
}
if (mode_in != TOPO_LED_STATE_OFF &&
mode_in != TOPO_LED_STATE_ON) {
mode_in);
}
return (-1);
}
} else {
/*
* Get the LED mode
*/
return (-1);
}
}
}
return (0);
}
/*
* On thumper platforms these is no seperate locate LED for the drive bays.
* Therefore we simulate a locate LED by blinking the ok2rm LED.
*/
static int
{
char *entity_ref;
/*
* Get an IPMI handle and then lookup the generic device locator sensor
* data record referenced by the entity_ref prop val
*/
return (-1);
}
&entity_ref, &err) != 0) {
}
== NULL) {
return (-1);
}
/*
* Now look for a private argument list to figure out whether we're
* doing a get or a set operation, and then do it.
*/
/*
* Set the LED mode
*/
&mode_in)) != 0) {
}
if (mode_in != TOPO_LED_STATE_OFF &&
mode_in != TOPO_LED_STATE_ON) {
mode_in);
}
if (mode_in == TOPO_LED_STATE_ON)
else
return (-1);
}
} else {
/*
* Get the LED mode
*/
return (-1);
}
}
if (ledmode == IPMI_SUNOEM_LED_MODE_FAST)
else
}
return (0);
}
/*
* This is a method for the "mode" property that is specific for the drive bay
* LED's on thumper platforms. On thumper, the drive bay LED's are manipulated
* by asserting the right state bits in the hdd#.state compact SDR.
*/
static int
{
char *entity_ref;
/*
* Figure out which sensor state mask to use based on the indicator
* node's type prop val
*/
}
switch (type) {
case (TOPO_LED_TYPE_SERVICE):
break;
case (TOPO_LED_TYPE_PRESENT):
break;
case (TOPO_LED_TYPE_OK2RM):
break;
default:
}
/*
* Get an IPMI handle and then lookup the compact sensor data record
* referenced by the entity_ref prop val
*/
return (-1);
}
&entity_ref, &err) != 0) {
}
== NULL) {
return (-1);
}
/*
* Now lookup the propmethod argument list and figure out whether we're
* doing a get or a set operation, and then do it.
*/
/*
* Set the LED mode
*/
&ledmode)) != 0) {
}
if (ledmode == TOPO_LED_STATE_OFF) {
} else if (ledmode == TOPO_LED_STATE_ON) {
} else {
ledmode);
return (-1);
}
"for sensor %s (%s)\n", entity_ref,
ipmi_errmsg(hdl));
return (-1);
}
} else {
/*
* Get the LED mode
*/
== NULL) {
"for sensor %s (sensor num: %d) (error: %s)\n",
return (-1);
}
else
}
}
return (0);
}
static int
{
char *ftype = "sensor";
sd->sd_entity_ref);
/* topo errno set */
return (-1);
}
if (err != ETOPO_PROP_DEFD) {
topo_strerror(err));
return (-1);
}
}
"failed to register facility methods");
return (-1);
}
/*
* For both threshold and discrete sensors we set up a propmethod for
* getting the sensor state and properties to hold the entity ref,
* sensor class and sensor type.
*
* Additionally, for analog sensors we set up a property method for
* getting the converted sensor reading and property for the base
* unit type
*/
return (-1);
}
return (-1);
}
return (-1);
}
}
!= 0) {
return (-1);
}
&err) != 0) {
topo_strerror(err));
return (-1);
}
"on fac node %s (%s)\n", TOPO_SENSOR_READING,
return (-1);
}
!= 0) {
topo_strerror(err));
return (-1);
}
}
return (0);
}
/* ARGSUSED */
static int
{
int sensor_idlen;
struct sensor_data sd;
f_sensor =
break;
c_sensor =
break;
default:
return (0);
}
/*
* We offset the threshold and generic sensor reading types by 0x100
*/
return (-1);
}
return (0);
}
/* ARGSUSED */
static int
{
char *entity_ref;
int err;
struct entity_info ei;
return (-1);
}
/*
* Use the entity ref to lookup the SDR, which will have the entity ID
* and instance.
*/
}
ipmi_errmsg(hdl));
}
break;
break;
break;
break;
default:
}
/*
* Now iterate through all of the full and compact sensor data records
* and create a sensor facility node for each record that matches our
* entity ID and instance
*/
return (-1);
}
return (0);
}
static int
{
}
}
}
/* topo errno already set */
return (-1);
}
else
switch (nparams) {
case 1:
/* LINTED: E_SEC_PRINTF_VAR_FMT */
break;
case 2:
/* LINTED: E_SEC_PRINTF_VAR_FMT */
break;
default:
nparams);
}
}
return (0);
}
/* ARGSUSED */
static int
{
int ret;
}
}
/* topo errno already set */
return (-1);
}
else
/* LINTED: E_SEC_PRINTF_VAR_FMT */
}
return (0);
}
/*ARGSUSED*/
static int
{
int err;
if (err != ETOPO_PROP_DEFD) {
"pgroups create failure: %s\n",
topo_strerror(err));
return (-1);
}
}
"topo_method_register() failed: %s",
return (-1);
}
} else {
"topo_method_register() failed: %s",
return (-1);
}
}
return (0);
}