.\" $NetBSD: sysmon_envsys.9,v 1.46 2017/07/03 21:28:48 wiz Exp $
.\"
.\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Juan Romero Pardines.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd July 13, 2012
.Dt SYSMON_ENVSYS 9
.Os
.Sh NAME
.Nm sysmon_envsys
.Nd kernel part of the envsys 2 framework
.Sh SYNOPSIS
.In dev/sysmon/sysmonvar.h
.Ft struct sysmon_envsys *
.Fn sysmon_envsys_create "void"
.Ft void
.Fn sysmon_envsys_destroy "struct sysmon_envsys *"
.Ft int
.Fn sysmon_envsys_register "struct sysmon_envsys *"
.Ft void
.Fn sysmon_envsys_unregister "struct sysmon_envsys *"
.Ft int
.Fn sysmon_envsys_sensor_attach "struct sysmon_envsys *" "envsys_data_t *"
.Ft int
.Fn sysmon_envsys_sensor_detach "struct sysmon_envsys *" "envsys_data_t *"
.Ft void
.Fn sysmon_envsys_sensor_event "struct sysmon_envsys *" "envsys_data_t *" "int"
.Ft void
.Fn sysmon_envsys_foreach_sensor "sysmon_envsys_callback_t" "void *" "bool"
.Ft int
.Fn sysmon_envsys_update_limits "struct sysmon_envsys *" "envsys_data_t *"
.Sh DESCRIPTION
.Pp
.Nm
is the kernel part of the
.Xr envsys 4
framework.
With this framework you are able to register and unregister a
.Nm
device, attach or detach sensors into a device, and enable or disable
automatic monitoring for some sensors without any user interactivity,
among other things.
.Ss HOW TO USE THE FRAMEWORK
To register a new driver to the
.Nm
framework, a
.Em sysmon_envsys
object must be allocated and initialized; the
.Fn sysmon_envsys_create
function is used for this.
This returns a zero'ed pointer to a
.Em sysmon_envsys
structure.
.Pp
Once the object has been initialized,
actual sensors may be initialized and attached (see the
.Sx SENSOR DETAILS
section for more information).
This is accomplished by the
.Fn sysmon_envsys_sensor_attach
function, which will attach the
.Em envsys_data_t
(a sensor) specified as second argument into the
.Em sysmon_envsys
object specified in the first argument.
.Pp
Finally, after all sensors have been attached,
the device needs to set some required (and optional) members of the
.Em sysmon_envsys
structure before calling the
.Fn sysmon_envsys_register
function to register the device.
.Pp
In case of errors during the initialization, the
.Fn sysmon_envsys_destroy
function should be used.
This detaches all previously attached sensors and deallocates the
.Em sysmon_envsys
object.
.Pp
Some sensors can be monitored, and when the sensor value changes an event
can be delivered to the
.Xr powerd 8
daemon.
Sensor monitoring can be performed by the
.Nm
framework on a polled basis.
Alternatively, the sensor's device driver can call the
.Fn sysmon_envsys_sensor_event
function to deliver the event without waiting for the device to be polled.
.Pp
The
.Fn sysmon_envsys_foreach_sensor
function can be used by other parts of the kernel to iterate over all
registered sensors.
This capability is used by the
.Xr i386/apm 4
driver to summarize the state of all battery sensors.
.Pp
Drivers can also call the
.Fn sysmon_envsys_update_limits
function when it is necessary to reinitialize a sensor's threshold values.
This is used by the
.Xr acpibat 4
driver when a new battery is inserted.
.Pp
The
.Em sysmon_envsys
structure is defined as follows
(only the public members are shown):
.Bd -literal
struct sysmon_envsys {
const char *sme_name;
int sme_flags;
int sme_class;
uint64_t sme_events_timeout;
void *sme_cookie;
void (*sme_refresh)(struct sysmon_envsys *, envsys_data_t *);
void (*sme_set_limits)(struct sysmon_envsys *, envsys_data_t *,
sysmon_envsys_lim_t *, uint32_t *);
void (*sme_get_limits)(struct sysmon_envsys *, envsys_data_t *,
sysmon_envsys_lim_t *, uint32_t *);
};
.Ed
.Pp
The members have the following meaning:
.Pp
.Bl -tag -width "sme_events_timeout"
.It Fa sme_class
This specifies the class of the sysmon envsys device.
See the
.Sy DEVICE CLASSES
section for more information (OPTIONAL).
.It Fa sme_name
The name that will be used in the driver (REQUIRED).
.It Fa sme_flags
Additional flags for the
.Nm
device.
Currently supporting
.Ar SME_DISABLE_REFRESH .
If enabled, the
.Ar sme_refresh
function callback won't be used
to refresh sensor data and the driver will use its own method (OPTIONAL).
.It Fa sme_events_timeout
This is used to specify the default timeout value (in seconds) that will be
used to check for critical events if any monitoring flag was set (OPTIONAL).
.El
.Pp
If the driver wants to refresh sensors data via the
.Nm
framework, the following members may be specified:
.Pp
.Bl -tag -width "sme_events_timeout"
.It Fa sme_cookie
Typically a pointer to the device struct (also called
.Dq softc ) .
This may be used in the
.Sy sme_refresh ,
.Sy sme_get_limits ,
or
.Sy sme_set_limits
function callbacks.
.It Fa sme_refresh
Pointer to a function that will be used to refresh sensor data in
the device.
This can be used to set the state and other properties of the
sensor depending on the data returned by the driver.
.Em NOTE :
.Em You don't have to refresh all sensors, only the sensor specified by the
.Sy edata->sensor
.Em index .
If this member is not specified, the device driver will be totally
responsible for all updates of this sensor; the
.Nm
framework will not be able to update the sensor value.
.It Fa sme_get_limits
Pointer to a function that will be used to obtain from the driver the
initial limits (or thresholds) used when monitoring a sensor's value.
(See the
.Sx SENSOR DETAILS
section for more information.)
If this member is not specified, the
.Dv ENVSYS_FMONLIMITS
flag will be ignored, and limit monitoring will not occur until
appropriate limits are enabled from userland via
.Xr envstat 8 .
.It Fa sme_set_limits
Pointer to a function that alerts the device driver whenever monitoring
limits (or thresholds) are updated by the user.
Setting this function allows the device driver to reprogram hardware
limits (if provided by the device) when the user-specificied limits are
updated, and gives the driver direct control over setting the sensor's
state based on hardware status.
.Pp
The
.Fa sme_set_limits
callback can be invoked with the third argument (a pointer to the new
limits) set to a
.Dv NULL
pointer.
Device drivers must recognize this as a request to restore the sensor
limits to their original, boot-time values.
.Pp
If the
.Fa sme_set_limits
member is not specified, the device driver is not informed of changes to
the sensor's limit values, and the
.Nm
framework performs all limit checks in software.
.El
.Pp
Note that it's not necessary to refresh the sensors data before the
driver is registered, only do it if you need the data in your driver
to check for a specific condition.
.Pp
The timeout value for the monitoring events on a device may be changed via the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2
or the
.Xr envstat 8
command.
.Pp
To unregister a driver previously registered with the
.Nm
framework, the
.Fn sysmon_envsys_unregister
function must be used.
If there were monitoring events registered for the
driver, they all will be destroyed before the device is unregistered and
its sensors are detached.
Finally the
.Em sysmon_envsys
object will be freed, so there's no need to call
.Fn sysmon_envsys_destroy .
.Ss DEVICE CLASSES
The
.Fa sme_class
member of the
.Fa sysmon_envsys
structure is an optional flag that specifies the class of the
sysmon envsys device.
Currently there are two classes:
.Pp
.Bl -tag -width ident
.It SME_CLASS_ACADAPTER
.Pp
This class is for devices that want to act as an
.Em AC adapter .
The device writer must ensure that at least there is a
sensor with
.Em units
of
.Dv ENVSYS_INDICATOR .
This will be used to report its current state (on/off).
.It SME_CLASS_BATTERY
.Pp
This class is for devices that want to act as a
.Em Battery .
The device writer must ensure that at least there are two sensors with
units of
.Dv ENVSYS_BATTERY_CAPACITY
and
.Dv ENVSYS_BATTERY_CHARGE .
.Pp
These two sensors are used to ensure that the battery device can
send a
.Em low-power
event to the
.Xr powerd 8
daemon (if running) when all battery devices are in a critical state.
(The critical state occurs when a battery is not currently charging
and its charge state is low or critical.)
When the
.Em low-power
condition is met, an event is sent to the
.Xr powerd 8
daemon (if running), which will shutdown the system gracefully
by executing the
.Pa /etc/powerd/scripts/sensor_battery
script.
.Pp
If
.Xr powerd 8
is not running, the system will be powered off via the
.Xr cpu_reboot 9
call with the
.Dv RB_POWERDOWN
flag.
.Pp
.El
.Em NOTE :
If a
.Dv SME_CLASS_ACADAPTER
or
.Dv SME_CLASS_BATTERY
class device doesn't have the sensors required, the
.Em low-power
event will never be sent, and the graceful shutdown won't be possible.
.Ss SENSOR DETAILS
Each sensor uses a
.Sy envsys_data_t
structure, it's defined as follows (only the public members are shown);
.Bd -literal
typedef struct envsys_data {
uint32_t units;
uint32_t state;
uint32_t flags;
uint32_t rpms;
int32_t rfact;
int32_t value_cur;
int32_t value_max;
int32_t value_min;
int32_t value_avg;
sysmon_envsys_lim_t limits;
int upropset;
char desc[ENVSYS_DESCLEN];
} envsys_data_t;
.Ed
.Pp
The members for the
.Sy envsys_data_t
structure have the following meaning:
.Pp
.Bl -tag -width cdoscdosrunru
.It Fa units
Used to set the units type.
.It Fa state
Used to set the current state.
.It Fa flags
Used to set additional flags.
Among other uses, if one or more of the
.Dv ENVSYS_FMONxxx
flags are set, automatic sensor monitoring will be enabled.
Periodically, the sensor's value will be checked and if certain
conditions are met, an event will be sent to the
.Xr powerd 8
daemon.
.Em NOTE
.Em that limits (or thresholds) can be set at any time to enable
.Em monitoring that the sensor's value remains within those limits .
.It Fa rpms
Used to set the nominal RPM value for
.Sy fan
sensors.
.It Fa rfact
Used to set the rfact value for
.Sy voltage
sensors.
.It Fa value_cur
Used to set the current value.
.It Fa value_max
Used to set the maximum value.
.It Fa value_min
Used to set the minimum value.
.It Fa value_avg
Used to set the average value.
.It Fa limits
Structure used to contain the sensor's alarm thresholds.
.It Fa upropset
Used to keep track of which sensor properties are set.
.It Fa desc
Used to set the description string.
.Em NOTE
.Em that the description string must be unique in a device, and sensors with
.Em duplicate or empty description will simply be ignored .
.El
.Pp
Users of this framework must take care about the following points:
.Bl -bullet
.It
The
.Ar desc
member needs to have a valid description, unique in a device and non empty
to be valid.
.It
The
.Ar units
type must be valid.
The following units are defined:
.Pp
.Bl -tag -width "ENVSYS_BATTERY_CAPACITY" -compact
.It Dv ENVSYS_STEMP
For temperature sensors, in microkelvins.
.It Dv ENVSYS_SFANRPM
For fan sensors.
.It Dv ENVSYS_SVOLTS_AC
For AC Voltage.
.It Dv ENVSYS_SVOLTS_DC
For DC Voltage.
.It Dv ENVSYS_SOHMS
For Ohms.
.It Dv ENVSYS_SWATTS
For Watts.
.It Dv ENVSYS_SAMPS
For Ampere.
.It Dv ENVSYS_SWATTHOUR
For Watts hour.
.It Dv ENVSYS_SAMPHOUR
For Ampere hour.
.It Dv ENVSYS_INDICATOR
For sensors that only want a boolean type.
.It Dv ENVSYS_INTEGER
For sensors that only want an integer type.
.It Dv ENVSYS_DRIVE
For drive sensors.
.It Dv ENVSYS_BATTERY_CAPACITY
For Battery device classes.
This sensor unit uses the
.Dv ENVSYS_BATTERY_CAPACITY_*
values in
.Ar value_cur
to report its current capacity to userland.
Mandatory if
.Fa sme_class
is set to
.Dv SME_CLASS_BATTERY .
.It Dv ENVSYS_BATTERY_CHARGE
For Battery device classes.
This sensor is equivalent to the Indicator type, it's a boolean.
Use it to specify in what state is the Battery state:
.Sy true
if the battery is currently charging or
.Sy false
otherwise.
Mandatory if
.Fa sme_class
is set to
.Dv SME_CLASS_BATTERY .
.El
.It
When initializing or refreshing the sensor, the
.Ar state
member should be set to a known state (otherwise it will be in
unknown state).
Possible values:
.Pp
.Bl -tag -width "ENVSYS_SCRITUNDERXX" -compact
.It Dv ENVSYS_SVALID
Sets the sensor to a valid state.
.It Dv ENVSYS_SINVALID
Sets the sensor to an invalid state.
.It Dv ENVSYS_SCRITICAL
Sets the sensor to a critical state.
.It Dv ENVSYS_SCRITUNDER
Sets the sensor to a critical under state.
.It Dv ENVSYS_SCRITOVER
Sets the sensor to a critical over state.
.It Dv ENVSYS_SWARNUNDER
Sets the sensor to a warning under state.
.It Dv ENVSYS_SWARNOVER
Sets the sensor to a warning over state.
.El
.Pp
.It
The
.Ar flags
member accepts one or more of the following flags:
.Pp
.Bl -tag -width "ENVSYS_FCHANGERFACTXX"
.It Dv ENVSYS_FCHANGERFACT
Marks the sensor with ability to change the
.Ar rfact
value on the fly (in voltage sensors).
The
.Ar rfact
member must be used in the correct place of the code
that retrieves and converts the value of the sensor.
.It Dv ENVSYS_FPERCENT
This uses the
.Ar value_cur
and
.Ar value_max
members to make a percentage.
Both values must be enabled and have data.
.It Dv ENVSYS_FVALID_MAX
Marks the
.Ar value_max
value as valid.
.It Dv ENVSYS_FVALID_MIN
Marks the
.Ar value_min
value as valid.
.It Dv ENVSYS_FVALID_AVG
Marks the
.Ar value_avg
value as valid.
.It Dv ENVSYS_FMONCRITICAL
Enables and registers a new event to monitor a critical state.
.It Dv ENVSYS_FMONLIMITS
Enables and registers a new event to monitor a sensor's value crossing
limits or thresholds.
.It Dv ENVSYS_FMONSTCHANGED
Enables and registers a new event to monitor battery capacity or drive state
sensors.
The flag is not effective if the
.Ar units
member is not
.Dv ENVSYS_DRIVE
or
.Dv ENVSYS_BATTERY_CAPACITY .
.It Dv ENVSYS_FMONNOTSUPP
Disallows setting of limits (or thresholds) via the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
This flag only disables setting the limits from userland.
It has no effect on monitoring flags set by the driver.
.It Dv ENVSYS_FHAS_ENTROPY
Allows this sensor to provide entropy for
.Xr rnd 4 .
.El
.Pp
.Em If the driver has to use any of the
.Ar value_max ,
.Ar value_min ,
.Em or
.Ar value_avg
.Em members, they should be marked as valid with the appropriate flag .
.Pp
.It
If
.Ar units
is set to
.Dv ENVSYS_DRIVE ,
the
.Ar value_cur
member must be set to one of the following predefined states:
.Pp
.Bl -tag -width "ENVSYS_DRIVE_POWERDOWNXX" -compact
.It Dv ENVSYS_DRIVE_EMPTY
Drive state is unknown.
.It Dv ENVSYS_DRIVE_READY
Drive is ready.
.It Dv ENVSYS_DRIVE_POWERUP
Drive is powering up.
.It Dv ENVSYS_DRIVE_ONLINE
Drive is online.
.It Dv ENVSYS_DRIVE_OFFLINE
Drive is offline.
.It Dv ENVSYS_DRIVE_IDLE
Drive is idle.
.It Dv ENVSYS_DRIVE_ACTIVE
Drive is active.
.It Dv ENVSYS_DRIVE_BUILD
Drive is building.
.It Dv ENVSYS_DRIVE_REBUILD
Drive is rebuilding.
.It Dv ENVSYS_DRIVE_POWERDOWN
Drive is powering down.
.It Dv ENVSYS_DRIVE_FAIL
Drive has failed.
.It Dv ENVSYS_DRIVE_PFAIL
Drive has been degraded.
.It Dv ENVSYS_DRIVE_MIGRATING
Drive is migrating.
.It Dv ENVSYS_DRIVE_CHECK
Drive is checking its state.
.El
.Pp
.It
If
.Ar units
is set to
.Dv ENVSYS_BATTERY_CAPACITY ,
the
.Ar value_cur
member must be set to one of the following predefined capacity states:
.Pp
.Bl -tag -width "ENVSYS_BATTERY_CAPACITY_CRITICAL" -compact
.It Dv ENVSYS_BATTERY_CAPACITY_NORMAL
Battery charge is normal.
.It Dv ENVSYS_BATTERY_CAPACITY_CRITICAL
Battery charge is critical.
.It Dv ENVSYS_BATTERY_CAPACITY_LOW
Battery charge is low.
.It Dv ENVSYS_BATTERY_CAPACITY_WARNING
Battery charge is on or below the warning capacity.
.El
.It
The
.Xr envsys 4
framework expects to have the values converted to
a unit that can be converted to another one easily.
That means the user
should convert the value returned by the driver to the appropriate unit.
For example voltage sensors to
.Sy mV ,
temperature sensors to
.Sy uK ,
Watts to
.Sy mW ,
Ampere to
.Sy mA ,
etc.
.Pp
The following types shouldn't need any conversion:
.Dv ENVSYS_BATTERY_CAPACITY ,
.Dv ENVSYS_BATTERY_CHARGE ,
.Dv ENVSYS_INDICATOR ,
.Dv ENVSYS_INTEGER ,
and
.Dv ENVSYS_DRIVE .
.Pp
.Em PLEASE NOTE THAT YOU MUST AVOID USING FLOATING POINT OPERATIONS
.Em IN KERNEL WHEN CONVERTING THE DATA RETURNED BY THE DRIVER TO THE
.Em APPROPRIATE UNIT, IT'S NOT ALLOWED .
.Pp
.El
.Ss HOW TO ENABLE AUTOMATIC MONITORING IN SENSORS
The following example illustrates how to enable automatic monitoring
in a virtual driver for a
.Em critical
state in the first sensor
.Fa ( sc_sensor[0] ) :
.Pp
.Bd -literal
int
mydriver_initialize_sensors(struct mysoftc *sc)
{
...
/* sensor is initialized with a valid state */
sc->sc_sensor[0].state = ENVSYS_SVALID;
/*
* the monitor member must be true to enable
* automatic monitoring.
*/
sc->sc_sensor[0].monitor = true;
/* and now we specify the type of the monitoring event */
sc->sc_sensor[0].flags |= ENVSYS_FMONCRITICAL;
...
}
int
mydriver_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct mysoftc *sc = sme->sme_cookie;
/* we get current data from the driver */
edata->value_cur = sc->sc_getdata();
/*
* if value is too high, mark the sensor in
* critical state.
*/
if (edata->value_cur > MYDRIVER_SENSOR0_HIWAT) {
edata->state = ENVSYS_SCRITICAL;
/* a critical event will be sent now automatically */
} else {
/*
* if value is within the limits, and we came from
* a critical state make sure to change sensor's state
* to valid.
*/
edata->state = ENVSYS_SVALID;
}
...
}
.Ed
.Sh CODE REFERENCES
The
.Sy envsys 2
framework is implemented within the files:
.Pp
.Pa sys/dev/sysmon/sysmon_envsys.c
.Pp
.Pa sys/dev/sysmon/sysmon_envsys_events.c
.Pp
.Pa sys/dev/sysmon/sysmon_envsys_tables.c
.Pp
.Pa sys/dev/sysmon/sysmon_envsys_util.c
.Sh SEE ALSO
.Xr envsys 4 ,
.Xr envstat 8
.Sh HISTORY
The first
.Em envsys
framework first appeared in
.Nx 1.5 .
The
.Em envsys 2
framework first appeared in
.Nx 5.0 .
.Sh AUTHORS
The (current)
.Em envsys 2
framework was implemented by
.An Juan Romero Pardines .
Additional input on the design was provided by many
.Nx
developers around the world.
.Pp
The first
.Em envsys
framework was implemented by
Jason R. Thorpe, Tim Rightnour, and Bill Squier.