SYSMON_ENVSYS(9) | Kernel Developer's Manual | SYSMON_ENVSYS(9) |
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 *);
void
sysmon_envsys_sensor_event(struct sysmon_envsys *, envsys_data_t *, int);
void
sysmon_envsys_foreach_sensor(sysmon_envsys_callback_t, void *, bool);
int
sysmon_envsys_update_limits(struct sysmon_envsys *, envsys_data_t *);
Once the object has been initialized, actual sensors may be initialized and attached (see the SENSOR DETAILS section for more information). This is accomplished by the sysmon_envsys_sensor_attach() function, which will attach the envsys_data_t (a sensor) specified as second argument into the sysmon_envsys object specified in the first argument.
Finally, after all sensors have been attached, the device needs to set some required (and optional) members of the sysmon_envsys structure before calling the sysmon_envsys_register() function to register the device.
In case of errors during the initialization, the sysmon_envsys_destroy() function should be used. This detachs all previously attached sensors and deallocates the sysmon_envsys object.
Some sensors can be monitored, and when the sensor value changes an event can be delivered to the powerd(8) daemon. Sensor monitoring can be performed by the sysmon_envsys framework on a polled basis. Alternatively, the sensor's device driver can call the sysmon_envsys_sensor_event() function to deliver the event without waiting for the device to be polled.
The 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 i386/apm(4) driver to summarize the state of all battery sensors.
Drivers can also call the sysmon_envsys_update_limits() function when it is necessary to reinitialize a sensor's threshhold values. This is used by the acpibat(4) driver when a new battery is inserted.
The sysmon_envsys structure is defined as follows (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 *); 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 *); };
The members have the following meaning:
If the driver wants to refresh sensors data via the sysmon_envsys framework, the following members may be specified:
The sme_set_limits callback can be invoked with the third argument (a pointer to the new limits) set to a NULL pointer. Device drivers must recognize this as a request to restore the sensor limits to their original, boot-time values.
If the sme_set_limits member is not specified, the device driver is not informed of changes to the sensor's limit values, and the sysmon_envsys framework performs all limit checks in software.
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 are detached. Finally the sysmon_envsys object will be freed, so there's no need to call sysmon_envsys_destroy().
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).
This class is for devices that want to act as a 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 can send a low-power event to the 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 low-power condition is met, an event is sent to the powerd(8) daemon (if running), which will shutdown the system gracefully by executing 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.
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;
The members for the envsys_data_t structure have the following meaning:
Users of this framework must take care about the following points:
If the driver has to use any of the value_max, value_min, or value_avg members, they should be marked as valid with the appropriate flag.
The following types shouldn't need any conversion: ENVSYS_BATTERY_CAPACITY, ENVSYS_BATTERY_CHARGE, ENVSYS_INDICATOR, ENVSYS_INTEGER, and ENVSYS_DRIVE.
PLEASE NOTE THAT YOU MUST AVOID USING FLOATING POINT OPERATIONS IN KERNEL WHEN CONVERTING THE DATA RETURNED BY THE DRIVER TO THE APPROPRIATE UNIT, IT'S NOT ALLOWED.
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; } ... }
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
The first envsys framework was implemented by Jason R. Thorpe, Tim Rightnour, and Bill Squier.
April 10, 2010 | NetBSD 6.1 |