piclsensors.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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Routines in this file are used to manage CPU temperature sensor
*/
#include <stdio.h>
#include <unistd.h>
#include <smclib.h>
#include <libintl.h>
#include <syslog.h>
#include <pthread.h>
#include <string.h>
#include <strings.h>
#include <picl.h>
#include <picltree.h>
#include <picldefs.h>
#include <pthread.h>
#include <errno.h>
#include <stropts.h>
#include "piclenvmond.h"
#include "piclsensors.h"
#define NULLREAD (int (*)(ptree_rarg_t *, void *))0
#define NULLWRITE (int (*)(ptree_warg_t *, const void *))0
#define POLL_TIMEOUT 5000
#define BUF_SIZE 50
/* packet lengths */
#define ENV_GET_THRESHOLD_PKT_LEN 1
#define ENV_SET_THRESHOLD_PKT_LEN 8
#define ENV_READ_SENSOR_PKT_LEN 1
#define ENV_SENSOR_EVENT_ENABLE_PKT_LEN 2
/* req pkt data */
#define ENV_SENSOR_EVENT_ENABLE_MASK 0x80
/* ptree wrapper to create property */
int (*writefn)(ptree_warg_t *, const void *),
extern int env_open_smc(void);
extern int env_debug;
/* globals */
int sensor_fd = -1;
picl_nodehdl_t sensorh = 0;
/* local vars */
static env_temp_sensor_t temp_sensor;
static char *env_thresholds[] = {
};
static int cpu_sensor_geo_addr = 0;
/* local func prototypes */
static void *env_temp_monitor(void *args);
/*
* Reads the threshold value from hardware
*/
static picl_errno_t
{
return (PICL_INVALIDARG);
}
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT)) != SMC_SUCCESS) {
return (PICL_FAILURE);
}
switch (threshold_no) {
case LOW_WARNING_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
case LOW_SHUTDOWN_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
case LOW_POWEROFF_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
case HIGH_WARNING_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
case HIGH_SHUTDOWN_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
case HIGH_POWEROFF_THRESHOLD:
} else {
return (PICL_PERMDENIED);
}
break;
default:
return (PICL_INVALIDARG);
}
return (PICL_SUCCESS);
}
/*
* Sets the threshold temperature specified in given sensor number
*/
static picl_errno_t
{
return (PICL_INVALIDARG);
}
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT)) != SMC_SUCCESS) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
/*
* returns the sensor reading of the SMC sensor specified in sensor_no
*/
static picl_errno_t
{
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT)) != SMC_SUCCESS) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
/*
* volatile call back function to read the current temparature
*/
static int
{
PICL_SUCCESS) {
return (rc);
}
/* read the temp from SMC f/w */
PICL_SUCCESS) {
return (rc);
}
/* update the internal cache */
(void) pthread_mutex_lock(&sensor_mutex);
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_SUCCESS);
}
/*
* volatile function that returns the state of sensor
*/
static int
{
PICL_SUCCESS) {
return (rc);
}
/* read the curr temp from SMC f/w */
PICL_SUCCESS) {
(void) pthread_mutex_lock(&sensor_mutex);
sizeof (temp_sensor.state));
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_SUCCESS);
}
(void) pthread_mutex_lock(&sensor_mutex);
sizeof (temp_sensor.state));
sizeof (temp_sensor.state));
else
sizeof (temp_sensor.state));
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_SUCCESS);
}
/*
* volatile property to read sensor thresholds
*/
static int
{
char prop_name[PICL_PROPNAMELEN_MAX];
return (rc);
}
(void) pthread_mutex_lock(&sensor_mutex);
} else {
}
(void) pthread_mutex_unlock(&sensor_mutex);
return (rc);
}
/*
* volatile callback function to set the temp thresholds
*/
static int
{
int threshold_no = 0;
char prop_name[PICL_PROPNAMELEN_MAX];
return (rc);
}
cmd[0] = '\0';
(void) pthread_mutex_lock(&sensor_mutex);
/* warning cannot be less than shutdown threshold */
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
/* shutdown cannot be greater than warning threshold */
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_PERMDENIED);
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
/* change the OBP nvram property */
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
/* change the OBP nvram property */
if (temp > MAX_POWEROFF_TEMP ||
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
/* change the OBP nvram property */
} else {
(void) pthread_mutex_unlock(&sensor_mutex);
return (PICL_INVALIDARG);
}
(void) pthread_mutex_unlock(&sensor_mutex);
return (rc);
}
(void) pthread_mutex_lock(&sensor_mutex);
switch (threshold_no) {
case LOW_WARNING_THRESHOLD:
break;
case LOW_SHUTDOWN_THRESHOLD:
break;
case LOW_POWEROFF_THRESHOLD:
break;
case HIGH_WARNING_THRESHOLD:
break;
case HIGH_SHUTDOWN_THRESHOLD:
break;
case HIGH_POWEROFF_THRESHOLD:
break;
}
(void) pthread_mutex_unlock(&sensor_mutex);
/* execute the cmd to change OBP nvram property */
if (cmd[0]) {
}
return (PICL_SUCCESS);
}
/*
* this routine reads the hardware state and initialises the internal
* cache for temperature thresholds
*/
static picl_errno_t
{
PICL_SUCCESS) {
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
} else {
}
return (PICL_SUCCESS);
}
/*
* sensor_event_enable_set: enables or disables Event Message generation
* from a sensor specified by sensor_no
*/
static int
{
if (enable) {
}
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT)) != SMC_SUCCESS) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
/*
* creates temperature sensor node and all of its properties
*/
{
int i = 0;
int8_t sensor_reading = 0;
sensor_fd = env_open_smc();
if (sensor_fd < 0) {
"opening SMC(failed to create sensor nodes)"));
return (PICL_FAILURE);
}
/* grab exclusive access to set the thresholds */
return (PICL_FAILURE);
}
/* create temperature sensor node */
PICL_SUCCESS) {
return (rc);
}
/* create Label prop. */
(char *)PICL_PROPVAL_LABEL_AMBIENT)) != PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (rc);
}
/* create the geo-addr property */
&sensor_no)) != PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (rc);
}
/* read the current temp from hardware */
PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (PICL_FAILURE);
}
/* create temperature prop. */
&sensor_reading)) != PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (rc);
}
/* create the threshold properties */
for (i = 0; i < NUM_OF_THRESHOLDS; i++) {
sizeof (uint8_t), env_thresholds[i],
(void *)NULL)) != PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (rc);
}
}
/* intialise the internal cache */
&temp_sensor) != PICL_SUCCESS) {
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (PICL_FAILURE);
}
/* create STATE prop. */
(void) ptree_delete_node(sensorh);
(void) ptree_destroy_node(sensorh);
return (rc);
}
/* start temperature monitoring thread */
&env_temp_monitor, NULL) != 0) {
"creating temperature monitor thread"));
}
/* enable sensor-event */
return (PICL_SUCCESS);
}
/*
* handles the sensor events (post corresponding Condition picl event)
*/
void
env_handle_sensor_event(void *res_datap)
{
char sensor_cond[BUF_SIZE];
return;
}
return;
}
}
/* Threshold event */
switch (offset) {
case 0:
(void) pthread_mutex_lock(&env_temp_monitor_mutex);
if (env_curr_state == LOW_WARNING_THRESHOLD) {
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
return;
}
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
(void) strncpy(sensor_cond,
sizeof (sensor_cond));
" is below lower warning temperature (%d).\n"),
break;
case 2:
(void) pthread_mutex_lock(&env_temp_monitor_mutex);
if (env_curr_state == LOW_SHUTDOWN_THRESHOLD) {
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
return;
}
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
(void) strncpy(sensor_cond,
sizeof (sensor_cond));
" is below lower critical temperature (%d).\n"),
break;
case 7:
(void) pthread_mutex_lock(&env_temp_monitor_mutex);
if (env_curr_state == HIGH_WARNING_THRESHOLD) {
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
return;
}
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
(void) strncpy(sensor_cond,
sizeof (sensor_cond));
" exceeds upper warning temperature (%d).\n"),
break;
case 9:
(void) pthread_mutex_lock(&env_temp_monitor_mutex);
if (env_curr_state == HIGH_SHUTDOWN_THRESHOLD) {
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
return;
}
(void) pthread_cond_signal(&env_temp_monitor_cv);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
(void) strncpy(sensor_cond,
sizeof (sensor_cond));
" exceeds upper critical temperature (%d).\n"),
break;
default:
sizeof (sensor_cond));
break;
}
!= PICL_SUCCESS) {
"%s event"), PICLEVENT_CONDITION_CHANGE);
}
}
/*
* this thread monitors the temperature when the current temperature
* raises above high warning threshold
*/
/*ARGSUSED*/
static void *
env_temp_monitor(void *args)
{
int ret;
char sensor_cond[BUF_SIZE];
for (;;) {
(void) pthread_mutex_lock(&env_temp_monitor_mutex);
if (env_curr_state == NORMAL_THRESHOLD) {
}
/* check until temp drops below warning threshold */
&env_temp_monitor_mutex, &to);
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
continue;
}
/* read the present temperature */
&sensor_reading) != PICL_SUCCESS) {
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
continue;
}
(void) pthread_mutex_lock(&sensor_mutex);
/* temperature is ok now */
sizeof (sensor_cond));
}
(void) pthread_mutex_unlock(&sensor_mutex);
if (env_curr_state == NORMAL_THRESHOLD) {
"temperature is ok now"));
NO_COND_TIMEDWAIT) != PICL_SUCCESS) {
" posting %s event"),
}
}
(void) pthread_mutex_unlock(&env_temp_monitor_mutex);
}
/*NOTREACHED*/
return (NULL);
}