NAME

sysmon_envsys - kernel part of the envsys 2 framework

SYNOPSIS



struct sysmon_envsys * sysmon_envsys_create(void)

void sysmon_envsys_destroy(struct sysmon_envsys *)

int sysmon_envsys_register(struct sysmon_envsys *)

void sysmon_envsys_unregister(struct sysmon_envsys *)

int sysmon_envsys_sensor_attach(struct sysmon_envsys *, envsys_data_t *)

int sysmon_envsys_sensor_detach(struct sysmon_envsys *, envsys_data_t *)

DESCRIPTION

sysmon_envsys is the kernel part of the envsys(4) framework. With this framework you are able to register and unregister a sysmon_envsys device, attach or detach sensors into a device and enable or disable automatic monitoring for some sensors without any user interactivity, among other things.

HOW TO USE THE FRAMEWORK

To register a new driver to the sysmon_envsys framework, a sysmon_envsys object must be allocated and initialized; the sysmon_envsys_create() function is used for this. This returns a zero'ed pointer to a sysmon_envsys structure and takes care of initialization of some private features.

Once we have the object we could start initializing sensors (see the SENSOR DETAILS section for more information) and attaching them to the device, this is acomplished by the sysmon_envsys_sensor_attach() function. This function attachs the envsys_data_t (sensor) specified as second argument into the sysmon_envsys object specified in the first argument.

Finally when the sensors are already attached, the device needs to set some required (and optional) members of the sysmon_envsys struct before calling the sysmon_envsys_register() function to register the device.

If there's some error before registering the device, the sysmon_envsys_destroy() function must be used to detach the sensors previously attached and free the sysmon_envsys object allocated by the sysmon_envsys_create() function.

The sysmon_envsys structure is defined as follow (only the public members are shown):

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 *);
};

The members have the following meaning:

sme_class
This specifies the class of the sysmon envsys device. See the DEVICE CLASSES section for more information (OPTIONAL).

sme_name
The name that will be used in the driver (REQUIRED).

sme_flags
Additional flags for the sysmon_envsys device. Currently supporting SME_DISABLE_REFRESH. If enabled, the sme_refresh function callback won't be used to refresh sensors data and the driver will use its own method. Hence sme_cookie won't be necessary either (OPTIONAL).

sme_events_timeout
This is used to specify the default timeout value that will be used to check for critical events if any monitoring flag was set. The value is used as seconds (OPTIONAL).

If the driver wants to refresh sensors data via the sysmon_envsys framework, the following members must be specified:

sme_cookie
Pointer to the device struct (also called ``softc'' ). This may be used in the sme_refresh function callback.

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 of the returned data by the driver. NOTE: You don't have to refresh all sensors, only the sensor specified by the edata->sensor index.

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.

The timeout value for the monitoring events on a device may be changed via the ENVSYS_SETDICTIONARY ioctl(2) or the envstat(8) command.

To unregister a driver previously registered with the sysmon_envsys framework, the 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 will be detached; finally the sysmon_envsys object will be freed, so there's no need to call sysmon_envsys_destroy() if we are going to unregister a device.

DEVICE CLASSES

The sme_class member of the sysmon_envsys structure is an optional flag that specifies the class of the sysmon envsys device. Currently there are two classes:

SME_CLASS_ACADAPTER

This class is for devices that want to act as an AC adapter. The device writer must ensure that at least there is a sensor with units of ENVSYS_INDICATOR. This will be used to report its current state (on/off).

SME_CLASS_BATTERY

This class is for devices that want to act as an Battery. The device writer must ensure that at least there are two sensors with units of ENVSYS_BATTERY_CAPACITY and ENVSYS_BATTERY_CHARGE.

These two sensors are used to ensure that the battery device won't never send a low-power event to the powerd(8) daemon (if running) when all battery devices are in a critical state. The critical state means that a battery is not currently charging and its charge state is low or critical. When the low-power condition is met, an event is sent to the powerd(8) daemon (if running) and will shutdown the system gracefully via the /etc/powerd/scripts/sensor_battery script.

If powerd(8) is not running, the system will be powered off via the cpu_reboot(9) call with the RB_POWERDOWN flag.

NOTE: If a SME_CLASS_ACADAPTER or SME_CLASS_BATTERY class don't have the sensors required, the low-power event will never be sent, and the graceful shutdown won't be possible.

SENSOR DETAILS

Each sensor uses a envsys_data_t structure, it's defined as follow (only the public members are shown);

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;
        bool            monitor;
        char            desc[ENVSYS_DESCLEN];
} envsys_data_t;

The members for the envsys_data_t structure have the following meaning:

units
Used to set the units type.

state
Used to set the current state.

flags
Used to set additional flags.

rpms
Used to set the nominal RPM value for fan sensors.

rfact
Used to set the rfact value for voltage sensors.

value_cur
Used to set the current value.

value_max
Used to set the maximum value.

value_min
Used to set the minimum value.

value_avg
Used to set the average value.

monitor
Used to enable automatic sensor monitoring (by default it's disabled). The automatic sensor monitoring will check if a condition is met periodically and will send an event to the powerd(8) daemon (if running). The monitoring event will be registered when this flag is true and one or more of the ENVSYS_FMONFOO flags were set in the flags member.

desc
Used to set the description string. NOTE that the description string must be unique in a device, and sensors with duplicate or empty description will simply be ignored.

Users of this framework must take care about the following points:

HOW TO ENABLE AUTOMATIC MONITORING IN SENSORS

The following example illustrates how to enable automatic monitoring in a virtual driver for a critical state in the first sensor (sc_sensor[0]):

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; } ... }

CODE REFERENCES

This section describes places within the NetBSD source tree where actual code implementing the envsys 2 framework can be found. All pathnames are relative to /usr/src.

The envsys 2 framework is implemented within the files:

sys/dev/sysmon/sysmon_envsys.c

sys/dev/sysmon/sysmon_envsys_events.c

sys/dev/sysmon/sysmon_envsys_tables.c

sys/dev/sysmon/sysmon_envsys_util.c

There's an example LKM driver that shows how the framework works in: sys/lkm/misc/envsys2/lkminit_envsys2.c.

SEE ALSO

envsys(4), envstat(8)

HISTORY

The first envsys framework first appeared in NetBSD1.5. The envsys 2 framework first appeared in NetBSD5.0.

AUTHORS

The (current) envsys 2 framework was implemented by Juan Romero Pardines
. Additional input on the design was provided by many NetBSD developers around the world.

The first envsys framework was implemented by Jason R. Thorpe, Tim Rightnour and Bill Squier.